PageSourceSearch

https://lygia.xyz/js/glslEditor.js

js lygia.xyz collected 2026-10-03 23:02:45 UTC 2,305,045 bytes, 23,459 lines download raw bytes

1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GlslEditor = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
2module.exports = { "default": _dereq_("core-js/library/fn/get-iterator"), __esModule: true };
3},{"core-js/library/fn/get-iterator":32}],2:[function(_dereq_,module,exports){
4module.exports = { "default": _dereq_("core-js/library/fn/object/assign"), __esModule: true };
5},{"core-js/library/fn/object/assign":33}],3:[function(_dereq_,module,exports){
6module.exports = { "default": _dereq_("core-js/library/fn/object/create"), __esModule: true };
7},{"core-js/library/fn/object/create":34}],4:[function(_dereq_,module,exports){
8module.exports = { "default": _dereq_("core-js/library/fn/object/define-property"), __esModule: true };
9},{"core-js/library/fn/object/define-property":35}],5:[function(_dereq_,module,exports){
10module.exports = { "default": _dereq_("core-js/library/fn/object/get-own-property-descriptor"), __esModule: true };
11},{"core-js/library/fn/object/get-own-property-descriptor":36}],6:[function(_dereq_,module,exports){
12module.exports = { "default": _dereq_("core-js/library/fn/object/keys"), __esModule: true };
13},{"core-js/library/fn/object/keys":37}],7:[function(_dereq_,module,exports){
14module.exports = { "default": _dereq_("core-js/library/fn/object/set-prototype-of"), __esModule: true };
15},{"core-js/library/fn/object/set-prototype-of":38}],8:[function(_dereq_,module,exports){
16module.exports = { "default": _dereq_("core-js/library/fn/promise"), __esModule: true };
17},{"core-js/library/fn/promise":39}],9:[function(_dereq_,module,exports){
18module.exports = { "default": _dereq_("core-js/library/fn/set"), __esModule: true };
19},{"core-js/library/fn/set":40}],10:[function(_dereq_,module,exports){
20"use strict";
21
22exports["default"] = function (instance, Constructor) {
23  if (!(instance instanceof Constructor)) {
24    throw new TypeError("Cannot call a class as a function");
25  }
26};
27
28exports.__esModule = true;
29},{}],11:[function(_dereq_,module,exports){
30"use strict";
31
32var _Object$defineProperty = _dereq_("babel-runtime/core-js/object/define-property")["default"];
33
34exports["default"] = (function () {
35  function defineProperties(target, props) {
36    for (var i = 0; i < props.length; i++) {
37      var descriptor = props[i];
38      descriptor.enumerable = descriptor.enumerable || false;
39      descriptor.configurable = true;
40      if ("value" in descriptor) descriptor.writable = true;
41
42      _Object$defineProperty(target, descriptor.key, descriptor);
43    }
44  }
45
46  return function (Constructor, protoProps, staticProps) {
47    if (protoProps) defineProperties(Constructor.prototype, protoProps);
48    if (staticProps) defineProperties(Constructor, staticProps);
49    return Constructor;
50  };
51})();
52
53exports.__esModule = true;
54},{"babel-runtime/core-js/object/define-property":4}],12:[function(_dereq_,module,exports){
55"use strict";
56
57var _Object$getOwnPropertyDescriptor = _dereq_("babel-runtime/core-js/object/get-own-property-descriptor")["default"];
58
59exports["default"] = function get(_x, _x2, _x3) {
60  var _again = true;
61
62  _function: while (_again) {
63    var object = _x,
64        property = _x2,
65        receiver = _x3;
66    _again = false;
67    if (object === null) object = Function.prototype;
68
69    var desc = _Object$getOwnPropertyDescriptor(object, property);
70
71    if (desc === undefined) {
72      var parent = Object.getPrototypeOf(object);
73
74      if (parent === null) {
75        return undefined;
76      } else {
77        _x = parent;
78        _x2 = property;
79        _x3 = receiver;
80        _again = true;
81        desc = parent = undefined;
82        continue _function;
83      }
84    } else if ("value" in desc) {
85      return desc.value;
86    } else {
87      var getter = desc.get;
88
89      if (getter === undefined) {
90        return undefined;
91      }
92
93      return getter.call(receiver);
94    }
95  }
96};
97
98exports.__esModule = true;
99},{"babel-runtime/core-js/object/get-own-property-descriptor":5}],13:[function(_dereq_,module,exports){
100"use strict";
101
102var _Object$create = _dereq_("babel-runtime/core-js/object/create")["default"];
103
104var _Object$setPrototypeOf = _dereq_("babel-runtime/core-js/object/set-prototype-of")["default"];
105
106exports["default"] = function (subClass, superClass) {
107  if (typeof superClass !== "function" && superClass !== null) {
108    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
109  }
110
111  subClass.prototype = _Object$create(superClass && superClass.prototype, {
112    constructor: {
113      value: subClass,
114      enumerable: false,
115      writable: true,
116      configurable: true
117    }
118  });
119  if (superClass) _Object$setPrototypeOf ? _Object$setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
120};
121
122exports.__esModule = true;
123},{"babel-runtime/core-js/object/create":3,"babel-runtime/core-js/object/set-prototype-of":7}],14:[function(_dereq_,module,exports){
124"use strict";
125
126exports["default"] = function (obj) {
127  return obj && obj.__esModule ? obj : {
128    "default": obj
129  };
130};
131
132exports.__esModule = true;
133},{}],15:[function(_dereq_,module,exports){
134// CodeMirror, copyright (c) by Marijn Haverbeke and others
135// Distributed under an MIT license: http://codemirror.net/LICENSE
136
137(function(mod) {
138  if (typeof exports == "object" && typeof module == "object") // CommonJS
139    mod(_dereq_("../../lib/codemirror"));
140  else if (typeof define == "function" && define.amd) // AMD
141    define(["../../lib/codemirror"], mod);
142  else // Plain browser env
143    mod(CodeMirror);
144})(function(CodeMirror) {
145  "use strict";
146
147  var noOptions = {};
148  var nonWS = /[^\s\u00a0]/;
149  var Pos = CodeMirror.Pos;
150
151  function firstNonWS(str) {
152    var found = str.search(nonWS);
153    return found == -1 ? 0 : found;
154  }
155
156  CodeMirror.commands.toggleComment = function(cm) {
157    cm.toggleComment();
158  };
159
160  CodeMirror.defineExtension("toggleComment", function(options) {
161    if (!options) options = noOptions;
162    var cm = this;
163    var minLine = Infinity, ranges = this.listSelections(), mode = null;
164    for (var i = ranges.length - 1; i >= 0; i--) {
165      var from = ranges[i].from(), to = ranges[i].to();
166      if (from.line >= minLine) continue;
167      if (to.line >= minLine) to = Pos(minLine, 0);
168      minLine = from.line;
169      if (mode == null) {
170        if (cm.uncomment(from, to, options)) mode = "un";
171        else { cm.lineComment(from, to, options); mode = "line"; }
172      } else if (mode == "un") {
173        cm.uncomment(from, to, options);
174      } else {
175        cm.lineComment(from, to, options);
176      }
177    }
178  });
179
180  CodeMirror.defineExtension("lineComment", function(from, to, options) {
181    if (!options) options = noOptions;
182    var self = this, mode = self.getModeAt(from);
183    var commentString = options.lineComment || mode.lineComment;
184    if (!commentString) {
185      if (options.blockCommentStart || mode.blockCommentStart) {
186        options.fullLines = true;
187        self.blockComment(from, to, options);
188      }
189      return;
190    }
191    var firstLine = self.getLine(from.line);
192    if (firstLine == null) return;
193    var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
194    var pad = options.padding == null ? " " : options.padding;
195    var blankLines = options.commentBlankLines || from.line == to.line;
196
197    self.operation(function() {
198      if (options.indent) {
199        var baseString = null;
200        for (var i = from.line; i < end; ++i) {
201          var line = self.getLine(i);
202          var whitespace = line.slice(0, firstNonWS(line));
203          if (baseString == null || baseString.length > whitespace.length) {
204            baseString = whitespace;
205          }
206        }
207        for (var i = from.line; i < end; ++i) {
208          var line = self.getLine(i), cut = baseString.length;
209          if (!blankLines && !nonWS.test(line)) continue;
210          if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
211          self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
212        }
213      } else {
214        for (var i = from.line; i < end; ++i) {
215          if (blankLines || nonWS.test(self.getLine(i)))
216            self.replaceRange(commentString + pad, Pos(i, 0));
217        }
218      }
219    });
220  });
221
222  CodeMirror.defineExtension("blockComment", function(from, to, options) {
223    if (!options) options = noOptions;
224    var self = this, mode = self.getModeAt(from);
225    var startString = options.blockCommentStart || mode.blockCommentStart;
226    var endString = options.blockCommentEnd || mode.blockCommentEnd;
227    if (!startString || !endString) {
228      if ((options.lineComment || mode.lineComment) && options.fullLines != false)
229        self.lineComment(from, to, options);
230      return;
231    }
232
233    var end = Math.min(to.line, self.lastLine());
234    if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
235
236    var pad = options.padding == null ? " " : options.padding;
237    if (from.line > end) return;
238
239    self.operation(function() {
240      if (options.fullLines != false) {
241        var lastLineHasText = nonWS.test(self.getLine(end));
242        self.replaceRange(pad + endString, Pos(end));
243        self.replaceRange(startString + pad, Pos(from.line, 0));
244        var lead = options.blockCommentLead || mode.blockCommentLead;
245        if (lead != null) for (var i = from.line + 1; i <= end; ++i)
246          if (i != end || lastLineHasText)
247            self.replaceRange(lead + pad, Pos(i, 0));
248      } else {
249        self.replaceRange(endString, to);
250        self.replaceRange(startString, from);
251      }
252    });
253  });
254
255  CodeMirror.defineExtension("uncomment", function(from, to, options) {
256    if (!options) options = noOptions;
257    var self = this, mode = self.getModeAt(from);
258    var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
259
260    // Try finding line comments
261    var lineString = options.lineComment || mode.lineComment, lines = [];
262    var pad = options.padding == null ? " " : options.padding, didSomething;
263    lineComment: {
264      if (!lineString) break lineComment;
265      for (var i = start; i <= end; ++i) {
266        var line = self.getLine(i);
267        var found = line.indexOf(lineString);
268        if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
269        if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment;
270        if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
271        lines.push(line);
272      }
273      self.operation(function() {
274        for (var i = start; i <= end; ++i) {
275          var line = lines[i - start];
276          var pos = line.indexOf(lineString), endPos = pos + lineString.length;
277          if (pos < 0) continue;
278          if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
279          didSomething = true;
280          self.replaceRange("", Pos(i, pos), Pos(i, endPos));
281        }
282      });
283      if (didSomething) return true;
284    }
285
286    // Try block comments
287    var startString = options.blockCommentStart || mode.blockCommentStart;
288    var endString = options.blockCommentEnd || mode.blockCommentEnd;
289    if (!startString || !endString) return false;
290    var lead = options.blockCommentLead || mode.blockCommentLead;
291    var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end);
292    var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString);
293    if (close == -1 && start != end) {
294      endLine = self.getLine(--end);
295      close = endLine.lastIndexOf(endString);
296    }
297    if (open == -1 || close == -1 ||
298        !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
299        !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
300      return false;
301
302    // Avoid killing block comments completely outside the selection.
303    // Positions of the last startString before the start of the selection, and the first endString after it.
304    var lastStart = startLine.lastIndexOf(startString, from.ch);
305    var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
306    if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
307    // Positions of the first endString after the end of the selection, and the last startString before it.
308    firstEnd = endLine.indexOf(endString, to.ch);
309    var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
310    lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
311    if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
312
313    self.operation(function() {
314      self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
315                        Pos(end, close + endString.length));
316      var openEnd = open + startString.length;
317      if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
318      self.replaceRange("", Pos(start, open), Pos(start, openEnd));
319      if (lead) for (var i = start + 1; i <= end; ++i) {
320        var line = self.getLine(i), found = line.indexOf(lead);
321        if (found == -1 || nonWS.test(line.slice(0, found))) continue;
322        var foundEnd = found + lead.length;
323        if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
324        self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
325      }
326    });
327    return true;
328  });
329});
330
331},{"../../lib/codemirror":30}],16:[function(_dereq_,module,exports){
332// CodeMirror, copyright (c) by Marijn Haverbeke and others
333// Distributed under an MIT license: http://codemirror.net/LICENSE
334
335// Open simple dialogs on top of an editor. Relies on dialog.css.
336
337(function(mod) {
338  if (typeof exports == "object" && typeof module == "object") // CommonJS
339    mod(_dereq_("../../lib/codemirror"));
340  else if (typeof define == "function" && define.amd) // AMD
341    define(["../../lib/codemirror"], mod);
342  else // Plain browser env
343    mod(CodeMirror);
344})(function(CodeMirror) {
345  function dialogDiv(cm, template, bottom) {
346    var wrap = cm.getWrapperElement();
347    var dialog;
348    dialog = wrap.appendChild(document.createElement("div"));
349    if (bottom)
350      dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
351    else
352      dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
353
354    if (typeof template == "string") {
355      dialog.innerHTML = template;
356    } else { // Assuming it's a detached DOM element.
357      dialog.appendChild(template);
358    }
359    return dialog;
360  }
361
362  function closeNotification(cm, newVal) {
363    if (cm.state.currentNotificationClose)
364      cm.state.currentNotificationClose();
365    cm.state.currentNotificationClose = newVal;
366  }
367
368  CodeMirror.defineExtension("openDialog", function(template, callback, options) {
369    if (!options) options = {};
370
371    closeNotification(this, null);
372
373    var dialog = dialogDiv(this, template, options.bottom);
374    var closed = false, me = this;
375    function close(newVal) {
376      if (typeof newVal == 'string') {
377        inp.value = newVal;
378      } else {
379        if (closed) return;
380        closed = true;
381        dialog.parentNode.removeChild(dialog);
382        me.focus();
383
384        if (options.onClose) options.onClose(dialog);
385      }
386    }
387
388    var inp = dialog.getElementsByTagName("input")[0], button;
389    if (inp) {
390      if (options.value) {
391        inp.value = options.value;
392        if (options.selectValueOnOpen !== false) {
393          inp.select();
394        }
395      }
396
397      if (options.onInput)
398        CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
399      if (options.onKeyUp)
400        CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
401
402      CodeMirror.on(inp, "keydown", function(e) {
403        if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
404        if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
405          inp.blur();
406          CodeMirror.e_stop(e);
407          close();
408        }
409        if (e.keyCode == 13) callback(inp.value, e);
410      });
411
412      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
413
414      inp.focus();
415    } else if (button = dialog.getElementsByTagName("button")[0]) {
416      CodeMirror.on(button, "click", function() {
417        close();
418        me.focus();
419      });
420
421      if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
422
423      button.focus();
424    }
425    return close;
426  });
427
428  CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
429    closeNotification(this, null);
430    var dialog = dialogDiv(this, template, options && options.bottom);
431    var buttons = dialog.getElementsByTagName("button");
432    var closed = false, me = this, blurring = 1;
433    function close() {
434      if (closed) return;
435      closed = true;
436      dialog.parentNode.removeChild(dialog);
437      me.focus();
438    }
439    buttons[0].focus();
440    for (var i = 0; i < buttons.length; ++i) {
441      var b = buttons[i];
442      (function(callback) {
443        CodeMirror.on(b, "click", function(e) {
444          CodeMirror.e_preventDefault(e);
445          close();
446          if (callback) callback(me);
447        });
448      })(callbacks[i]);
449      CodeMirror.on(b, "blur", function() {
450        --blurring;
451        setTimeout(function() { if (blurring <= 0) close(); }, 200);
452      });
453      CodeMirror.on(b, "focus", function() { ++blurring; });
454    }
455  });
456
457  /*
458   * openNotification
459   * Opens a notification, that can be closed with an optional timer
460   * (default 5000ms timer) and always closes on click.
461   *
462   * If a notification is opened while another is opened, it will close the
463   * currently opened one and open the new one immediately.
464   */
465  CodeMirror.defineExtension("openNotification", function(template, options) {
466    closeNotification(this, close);
467    var dialog = dialogDiv(this, template, options && options.bottom);
468    var closed = false, doneTimer;
469    var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
470
471    function close() {
472      if (closed) return;
473      closed = true;
474      clearTimeout(doneTimer);
475      dialog.parentNode.removeChild(dialog);
476    }
477
478    CodeMirror.on(dialog, 'click', function(e) {
479      CodeMirror.e_preventDefault(e);
480      close();
481    });
482
483    if (duration)
484      doneTimer = setTimeout(close, duration);
485
486    return close;
487  });
488});
489
490},{"../../lib/codemirror":30}],17:[function(_dereq_,module,exports){
491// CodeMirror, copyright (c) by Marijn Haverbeke and others
492// Distributed under an MIT license: http://codemirror.net/LICENSE
493
494(function(mod) {
495  if (typeof exports == "object" && typeof module == "object") // CommonJS
496    mod(_dereq_("../../lib/codemirror"));
497  else if (typeof define == "function" && define.amd) // AMD
498    define(["../../lib/codemirror"], mod);
499  else // Plain browser env
500    mod(CodeMirror);
501})(function(CodeMirror) {
502  CodeMirror.defineExtension("addPanel", function(node, options) {
503    options = options || {};
504
505    if (!this.state.panels) initPanels(this);
506
507    var info = this.state.panels;
508    var wrapper = info.wrapper;
509    var cmWrapper = this.getWrapperElement();
510
511    if (options.after instanceof Panel && !options.after.cleared) {
512      wrapper.insertBefore(node, options.before.node.nextSibling);
513    } else if (options.before instanceof Panel && !options.before.cleared) {
514      wrapper.insertBefore(node, options.before.node);
515    } else if (options.replace instanceof Panel && !options.replace.cleared) {
516      wrapper.insertBefore(node, options.replace.node);
517      options.replace.clear();
518    } else if (options.position == "bottom") {
519      wrapper.appendChild(node);
520    } else if (options.position == "before-bottom") {
521      wrapper.insertBefore(node, cmWrapper.nextSibling);
522    } else if (options.position == "after-top") {
523      wrapper.insertBefore(node, cmWrapper);
524    } else {
525      wrapper.insertBefore(node, wrapper.firstChild);
526    }
527
528    var height = (options && options.height) || node.offsetHeight;
529    this._setSize(null, info.heightLeft -= height);
530    info.panels++;
531    return new Panel(this, node, options, height);
532  });
533
534  function Panel(cm, node, options, height) {
535    this.cm = cm;
536    this.node = node;
537    this.options = options;
538    this.height = height;
539    this.cleared = false;
540  }
541
542  Panel.prototype.clear = function() {
543    if (this.cleared) return;
544    this.cleared = true;
545    var info = this.cm.state.panels;
546    this.cm._setSize(null, info.heightLeft += this.height);
547    info.wrapper.removeChild(this.node);
548    if (--info.panels == 0) removePanels(this.cm);
549  };
550
551  Panel.prototype.changed = function(height) {
552    var newHeight = height == null ? this.node.offsetHeight : height;
553    var info = this.cm.state.panels;
554    this.cm._setSize(null, info.height += (newHeight - this.height));
555    this.height = newHeight;
556  };
557
558  function initPanels(cm) {
559    var wrap = cm.getWrapperElement();
560    var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
561    var height = parseInt(style.height);
562    var info = cm.state.panels = {
563      setHeight: wrap.style.height,
564      heightLeft: height,
565      panels: 0,
566      wrapper: document.createElement("div")
567    };
568    wrap.parentNode.insertBefore(info.wrapper, wrap);
569    var hasFocus = cm.hasFocus();
570    info.wrapper.appendChild(wrap);
571    if (hasFocus) cm.focus();
572
573    cm._setSize = cm.setSize;
574    if (height != null) cm.setSize = function(width, newHeight) {
575      if (newHeight == null) return this._setSize(width, newHeight);
576      info.setHeight = newHeight;
577      if (typeof newHeight != "number") {
578        var px = /^(\d+\.?\d*)px$/.exec(newHeight);
579        if (px) {
580          newHeight = Number(px[1]);
581        } else {
582          info.wrapper.style.height = newHeight;
583          newHeight = info.wrapper.offsetHeight;
584          info.wrapper.style.height = "";
585        }
586      }
587      cm._setSize(width, info.heightLeft += (newHeight - height));
588      height = newHeight;
589    };
590  }
591
592  function removePanels(cm) {
593    var info = cm.state.panels;
594    cm.state.panels = null;
595
596    var wrap = cm.getWrapperElement();
597    info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
598    wrap.style.height = info.setHeight;
599    cm.setSize = cm._setSize;
600    cm.setSize();
601  }
602});
603
604},{"../../lib/codemirror":30}],18:[function(_dereq_,module,exports){
605// CodeMirror, copyright (c) by Marijn Haverbeke and others
606// Distributed under an MIT license: http://codemirror.net/LICENSE
607
608(function(mod) {
609  if (typeof exports == "object" && typeof module == "object") // CommonJS
610    mod(_dereq_("../../lib/codemirror"));
611  else if (typeof define == "function" && define.amd) // AMD
612    define(["../../lib/codemirror"], mod);
613  else // Plain browser env
614    mod(CodeMirror);
615})(function(CodeMirror) {
616  "use strict";
617
618  CodeMirror.defineOption("rulers", false, function(cm, val, old) {
619    if (old && old != CodeMirror.Init) {
620      clearRulers(cm);
621      cm.off("refresh", refreshRulers);
622    }
623    if (val && val.length) {
624      setRulers(cm);
625      cm.on("refresh", refreshRulers);
626    }
627  });
628
629  function clearRulers(cm) {
630    for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) {
631      var node = cm.display.lineSpace.childNodes[i];
632      if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className))
633        node.parentNode.removeChild(node);
634    }
635  }
636
637  function setRulers(cm) {
638    var val = cm.getOption("rulers");
639    var cw = cm.defaultCharWidth();
640    var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
641    var minH = cm.display.scroller.offsetHeight + 30;
642    for (var i = 0; i < val.length; i++) {
643      var elt = document.createElement("div");
644      elt.className = "CodeMirror-ruler";
645      var col, conf = val[i];
646      if (typeof conf == "number") {
647        col = conf;
648      } else {
649        col = conf.column;
650        if (conf.className) elt.className += " " + conf.className;
651        if (conf.color) elt.style.borderColor = conf.color;
652        if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
653        if (conf.width) elt.style.borderLeftWidth = conf.width;
654      }
655      elt.style.left = (left + col * cw) + "px";
656      elt.style.top = "-50px";
657      elt.style.bottom = "-20px";
658      elt.style.minHeight = minH + "px";
659      cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);
660    }
661  }
662
663  function refreshRulers(cm) {
664    clearRulers(cm);
665    setRulers(cm);
666  }
667});
668
669},{"../../lib/codemirror":30}],19:[function(_dereq_,module,exports){
670// CodeMirror, copyright (c) by Marijn Haverbeke and others
671// Distributed under an MIT license: http://codemirror.net/LICENSE
672
673(function(mod) {
674  if (typeof exports == "object" && typeof module == "object") // CommonJS
675    mod(_dereq_("../../lib/codemirror"));
676  else if (typeof define == "function" && define.amd) // AMD
677    define(["../../lib/codemirror"], mod);
678  else // Plain browser env
679    mod(CodeMirror);
680})(function(CodeMirror) {
681  var defaults = {
682    pairs: "()[]{}''\"\"",
683    triples: "",
684    explode: "[]{}"
685  };
686
687  var Pos = CodeMirror.Pos;
688
689  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
690    if (old && old != CodeMirror.Init) {
691      cm.removeKeyMap(keyMap);
692      cm.state.closeBrackets = null;
693    }
694    if (val) {
695      cm.state.closeBrackets = val;
696      cm.addKeyMap(keyMap);
697    }
698  });
699
700  function getOption(conf, name) {
701    if (name == "pairs" && typeof conf == "string") return conf;
702    if (typeof conf == "object" && conf[name] != null) return conf[name];
703    return defaults[name];
704  }
705
706  var bind = defaults.pairs + "`";
707  var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
708  for (var i = 0; i < bind.length; i++)
709    keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
710
711  function handler(ch) {
712    return function(cm) { return handleChar(cm, ch); };
713  }
714
715  function getConfig(cm) {
716    var deflt = cm.state.closeBrackets;
717    if (!deflt) return null;
718    var mode = cm.getModeAt(cm.getCursor());
719    return mode.closeBrackets || deflt;
720  }
721
722  function handleBackspace(cm) {
723    var conf = getConfig(cm);
724    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
725
726    var pairs = getOption(conf, "pairs");
727    var ranges = cm.listSelections();
728    for (var i = 0; i < ranges.length; i++) {
729      if (!ranges[i].empty()) return CodeMirror.Pass;
730      var around = charsAround(cm, ranges[i].head);
731      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
732    }
733    for (var i = ranges.length - 1; i >= 0; i--) {
734      var cur = ranges[i].head;
735      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
736    }
737  }
738
739  function handleEnter(cm) {
740    var conf = getConfig(cm);
741    var explode = conf && getOption(conf, "explode");
742    if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
743
744    var ranges = cm.listSelections();
745    for (var i = 0; i < ranges.length; i++) {
746      if (!ranges[i].empty()) return CodeMirror.Pass;
747      var around = charsAround(cm, ranges[i].head);
748      if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
749    }
750    cm.operation(function() {
751      cm.replaceSelection("\n\n", null);
752      cm.execCommand("goCharLeft");
753      ranges = cm.listSelections();
754      for (var i = 0; i < ranges.length; i++) {
755        var line = ranges[i].head.line;
756        cm.indentLine(line, null, true);
757        cm.indentLine(line + 1, null, true);
758      }
759    });
760  }
761
762  function contractSelection(sel) {
763    var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
764    return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
765            head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
766  }
767
768  function handleChar(cm, ch) {
769    var conf = getConfig(cm);
770    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
771
772    var pairs = getOption(conf, "pairs");
773    var pos = pairs.indexOf(ch);
774    if (pos == -1) return CodeMirror.Pass;
775    var triples = getOption(conf, "triples");
776
777    var identical = pairs.charAt(pos + 1) == ch;
778    var ranges = cm.listSelections();
779    var opening = pos % 2 == 0;
780
781    var type, next;
782    for (var i = 0; i < ranges.length; i++) {
783      var range = ranges[i], cur = range.head, curType;
784      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
785      if (opening && !range.empty()) {
786        curType = "surround";
787      } else if ((identical || !opening) && next == ch) {
788        if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
789          curType = "skipThree";
790        else
791          curType = "skip";
792      } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
793                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
794                 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
795        curType = "addFour";
796      } else if (identical) {
797        if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
798        else return CodeMirror.Pass;
799      } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
800                             isClosingBracket(next, pairs) ||
801                             /\s/.test(next))) {
802        curType = "both";
803      } else {
804        return CodeMirror.Pass;
805      }
806      if (!type) type = curType;
807      else if (type != curType) return CodeMirror.Pass;
808    }
809
810    var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
811    var right = pos % 2 ? ch : pairs.charAt(pos + 1);
812    cm.operation(function() {
813      if (type == "skip") {
814        cm.execCommand("goCharRight");
815      } else if (type == "skipThree") {
816        for (var i = 0; i < 3; i++)
817          cm.execCommand("goCharRight");
818      } else if (type == "surround") {
819        var sels = cm.getSelections();
820        for (var i = 0; i < sels.length; i++)
821          sels[i] = left + sels[i] + right;
822        cm.replaceSelections(sels, "around");
823        sels = cm.listSelections().slice();
824        for (var i = 0; i < sels.length; i++)
825          sels[i] = contractSelection(sels[i]);
826        cm.setSelections(sels);
827      } else if (type == "both") {
828        cm.replaceSelection(left + right, null);
829        cm.triggerElectric(left + right);
830        cm.execCommand("goCharLeft");
831      } else if (type == "addFour") {
832        cm.replaceSelection(left + left + left + left, "before");
833        cm.execCommand("goCharRight");
834      }
835    });
836  }
837
838  function isClosingBracket(ch, pairs) {
839    var pos = pairs.lastIndexOf(ch);
840    return pos > -1 && pos % 2 == 1;
841  }
842
843  function charsAround(cm, pos) {
844    var str = cm.getRange(Pos(pos.line, pos.ch - 1),
vendor: 12,203 bytes, lines 845-1175
845                          Pos(pos.line, pos.ch + 1));
846    return str.length == 2 ? str : null;
847  }
848
849  // Project the token type that will exists after the given char is
850  // typed, and use it to determine whether it would cause the start
851  // of a string token.
852  function enteringString(cm, pos, ch) {
853    var line = cm.getLine(pos.line);
854    var token = cm.getTokenAt(pos);
855    if (/\bstring2?\b/.test(token.type)) return false;
856    var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
857    stream.pos = stream.start = token.start;
858    for (;;) {
859      var type1 = cm.getMode().token(stream, token.state);
860      if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
861      stream.start = stream.pos;
862    }
863  }
864});
865
866},{"../../lib/codemirror":30}],20:[function(_dereq_,module,exports){
867// CodeMirror, copyright (c) by Marijn Haverbeke and others
868// Distributed under an MIT license: http://codemirror.net/LICENSE
869
870(function(mod) {
871  if (typeof exports == "object" && typeof module == "object") // CommonJS
872    mod(_dereq_("../../lib/codemirror"));
873  else if (typeof define == "function" && define.amd) // AMD
874    define(["../../lib/codemirror"], mod);
875  else // Plain browser env
876    mod(CodeMirror);
877})(function(CodeMirror) {
878  var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
879    (document.documentMode == null || document.documentMode < 8);
880
881  var Pos = CodeMirror.Pos;
882
883  var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
884
885  function findMatchingBracket(cm, where, strict, config) {
886    var line = cm.getLineHandle(where.line), pos = where.ch - 1;
887    var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
888    if (!match) return null;
889    var dir = match.charAt(1) == ">" ? 1 : -1;
890    if (strict && (dir > 0) != (pos == where.ch)) return null;
891    var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
892
893    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
894    if (found == null) return null;
895    return {from: Pos(where.line, pos), to: found && found.pos,
896            match: found && found.ch == match.charAt(0), forward: dir > 0};
897  }
898
899  // bracketRegex is used to specify which type of bracket to scan
900  // should be a regexp, e.g. /[[\]]/
901  //
902  // Note: If "where" is on an open bracket, then this bracket is ignored.
903  //
904  // Returns false when no bracket was found, null when it reached
905  // maxScanLines and gave up
906  function scanForBracket(cm, where, dir, style, config) {
907    var maxScanLen = (config && config.maxScanLineLength) || 10000;
908    var maxScanLines = (config && config.maxScanLines) || 1000;
909
910    var stack = [];
911    var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
912    var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
913                          : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
914    for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
915      var line = cm.getLine(lineNo);
916      if (!line) continue;
917      var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
918      if (line.length > maxScanLen) continue;
919      if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
920      for (; pos != end; pos += dir) {
921        var ch = line.charAt(pos);
922        if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
923          var match = matching[ch];
924          if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
925          else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
926          else stack.pop();
927        }
928      }
929    }
930    return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
931  }
932
933  function matchBrackets(cm, autoclear, config) {
934    // Disable brace matching in long lines, since it'll cause hugely slow updates
935    var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
936    var marks = [], ranges = cm.listSelections();
937    for (var i = 0; i < ranges.length; i++) {
938      var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
939      if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
940        var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
941        marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
942        if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
943          marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
944      }
945    }
946
947    if (marks.length) {
948      // Kludge to work around the IE bug from issue #1193, where text
949      // input stops going to the textare whever this fires.
950      if (ie_lt8 && cm.state.focused) cm.focus();
951
952      var clear = function() {
953        cm.operation(function() {
954          for (var i = 0; i < marks.length; i++) marks[i].clear();
955        });
956      };
957      if (autoclear) setTimeout(clear, 800);
958      else return clear;
959    }
960  }
961
962  var currentlyHighlighted = null;
963  function doMatchBrackets(cm) {
964    cm.operation(function() {
965      if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
966      currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
967    });
968  }
969
970  CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
971    if (old && old != CodeMirror.Init)
972      cm.off("cursorActivity", doMatchBrackets);
973    if (val) {
974      cm.state.matchBrackets = typeof val == "object" ? val : {};
975      cm.on("cursorActivity", doMatchBrackets);
976    }
977  });
978
979  CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
980  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
981    return findMatchingBracket(this, pos, strict, config);
982  });
983  CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
984    return scanForBracket(this, pos, dir, style, config);
985  });
986});
987
988},{"../../lib/codemirror":30}],21:[function(_dereq_,module,exports){
989// CodeMirror, copyright (c) by Marijn Haverbeke and others
990// Distributed under an MIT license: http://codemirror.net/LICENSE
991
992(function(mod) {
993  if (typeof exports == "object" && typeof module == "object") // CommonJS
994    mod(_dereq_("../../lib/codemirror"));
995  else if (typeof define == "function" && define.amd) // AMD
996    define(["../../lib/codemirror"], mod);
997  else // Plain browser env
998    mod(CodeMirror);
999})(function(CodeMirror) {
1000  "use strict";
1001
1002  function doFold(cm, pos, options, force) {
1003    if (options && options.call) {
1004      var finder = options;
1005      options = null;
1006    } else {
1007      var finder = getOption(cm, options, "rangeFinder");
1008    }
1009    if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
1010    var minSize = getOption(cm, options, "minFoldSize");
1011
1012    function getRange(allowFolded) {
1013      var range = finder(cm, pos);
1014      if (!range || range.to.line - range.from.line < minSize) return null;
1015      var marks = cm.findMarksAt(range.from);
1016      for (var i = 0; i < marks.length; ++i) {
1017        if (marks[i].__isFold && force !== "fold") {
1018          if (!allowFolded) return null;
1019          range.cleared = true;
1020          marks[i].clear();
1021        }
1022      }
1023      return range;
1024    }
1025
1026    var range = getRange(true);
1027    if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
1028      pos = CodeMirror.Pos(pos.line - 1, 0);
1029      range = getRange(false);
1030    }
1031    if (!range || range.cleared || force === "unfold") return;
1032
1033    var myWidget = makeWidget(cm, options);
1034    CodeMirror.on(myWidget, "mousedown", function(e) {
1035      myRange.clear();
1036      CodeMirror.e_preventDefault(e);
1037    });
1038    var myRange = cm.markText(range.from, range.to, {
1039      replacedWith: myWidget,
1040      clearOnEnter: true,
1041      __isFold: true
1042    });
1043    myRange.on("clear", function(from, to) {
1044      CodeMirror.signal(cm, "unfold", cm, from, to);
1045    });
1046    CodeMirror.signal(cm, "fold", cm, range.from, range.to);
1047  }
1048
1049  function makeWidget(cm, options) {
1050    var widget = getOption(cm, options, "widget");
1051    if (typeof widget == "string") {
1052      var text = document.createTextNode(widget);
1053      widget = document.createElement("span");
1054      widget.appendChild(text);
1055      widget.className = "CodeMirror-foldmarker";
1056    }
1057    return widget;
1058  }
1059
1060  // Clumsy backwards-compatible interface
1061  CodeMirror.newFoldFunction = function(rangeFinder, widget) {
1062    return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
1063  };
1064
1065  // New-style interface
1066  CodeMirror.defineExtension("foldCode", function(pos, options, force) {
1067    doFold(this, pos, options, force);
1068  });
1069
1070  CodeMirror.defineExtension("isFolded", function(pos) {
1071    var marks = this.findMarksAt(pos);
1072    for (var i = 0; i < marks.length; ++i)
1073      if (marks[i].__isFold) return true;
1074  });
1075
1076  CodeMirror.commands.toggleFold = function(cm) {
1077    cm.foldCode(cm.getCursor());
1078  };
1079  CodeMirror.commands.fold = function(cm) {
1080    cm.foldCode(cm.getCursor(), null, "fold");
1081  };
1082  CodeMirror.commands.unfold = function(cm) {
1083    cm.foldCode(cm.getCursor(), null, "unfold");
1084  };
1085  CodeMirror.commands.foldAll = function(cm) {
1086    cm.operation(function() {
1087      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
1088        cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
1089    });
1090  };
1091  CodeMirror.commands.unfoldAll = function(cm) {
1092    cm.operation(function() {
1093      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
1094        cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
1095    });
1096  };
1097
1098  CodeMirror.registerHelper("fold", "combine", function() {
1099    var funcs = Array.prototype.slice.call(arguments, 0);
1100    return function(cm, start) {
1101      for (var i = 0; i < funcs.length; ++i) {
1102        var found = funcs[i](cm, start);
1103        if (found) return found;
1104      }
1105    };
1106  });
1107
1108  CodeMirror.registerHelper("fold", "auto", function(cm, start) {
1109    var helpers = cm.getHelpers(start, "fold");
1110    for (var i = 0; i < helpers.length; i++) {
1111      var cur = helpers[i](cm, start);
1112      if (cur) return cur;
1113    }
1114  });
1115
1116  var defaultOptions = {
1117    rangeFinder: CodeMirror.fold.auto,
1118    widget: "\u2194",
1119    minFoldSize: 0,
1120    scanUp: false
1121  };
1122
1123  CodeMirror.defineOption("foldOptions", null);
1124
1125  function getOption(cm, options, name) {
1126    if (options && options[name] !== undefined)
1127      return options[name];
1128    var editorOptions = cm.options.foldOptions;
1129    if (editorOptions && editorOptions[name] !== undefined)
1130      return editorOptions[name];
1131    return defaultOptions[name];
1132  }
1133
1134  CodeMirror.defineExtension("foldOption", function(options, name) {
1135    return getOption(this, options, name);
1136  });
1137});
1138
1139},{"../../lib/codemirror":30}],22:[function(_dereq_,module,exports){
1140// CodeMirror, copyright (c) by Marijn Haverbeke and others
1141// Distributed under an MIT license: http://codemirror.net/LICENSE
1142
1143(function(mod) {
1144  if (typeof exports == "object" && typeof module == "object") // CommonJS
1145    mod(_dereq_("../../lib/codemirror"), _dereq_("./foldcode"));
1146  else if (typeof define == "function" && define.amd) // AMD
1147    define(["../../lib/codemirror", "./foldcode"], mod);
1148  else // Plain browser env
1149    mod(CodeMirror);
1150})(function(CodeMirror) {
1151  "use strict";
1152
1153  CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
1154    if (old && old != CodeMirror.Init) {
1155      cm.clearGutter(cm.state.foldGutter.options.gutter);
1156      cm.state.foldGutter = null;
1157      cm.off("gutterClick", onGutterClick);
1158      cm.off("change", onChange);
1159      cm.off("viewportChange", onViewportChange);
1160      cm.off("fold", onFold);
1161      cm.off("unfold", onFold);
1162      cm.off("swapDoc", updateInViewport);
1163    }
1164    if (val) {
1165      cm.state.foldGutter = new State(parseOptions(val));
1166      updateInViewport(cm);
1167      cm.on("gutterClick", onGutterClick);
1168      cm.on("change", onChange);
1169      cm.on("viewportChange", onViewportChange);
1170      cm.on("fold", onFold);
1171      cm.on("unfold", onFold);
1172      cm.on("swapDoc", updateInViewport);
1173    }
1174  });
1175
1176  var Pos = CodeMirror.Pos;
1177
1178  function State(options) {
1179    this.options = options;
1180    this.from = this.to = 0;
1181  }
1182
1183  function parseOptions(opts) {
1184    if (opts === true) opts = {};
1185    if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
1186    if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
1187    if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
1188    return opts;
1189  }
1190
1191  function isFolded(cm, line) {
1192    var marks = cm.findMarksAt(Pos(line));
1193    for (var i = 0; i < marks.length; ++i)
1194      if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
1195  }
1196
1197  function marker(spec) {
1198    if (typeof spec == "string") {
1199      var elt = document.createElement("div");
1200      elt.className = spec + " CodeMirror-guttermarker-subtle";
1201      return elt;
1202    } else {
1203      return spec.cloneNode(true);
1204    }
1205  }
1206
1207  function updateFoldInfo(cm, from, to) {
1208    var opts = cm.state.foldGutter.options, cur = from;
1209    var minSize = cm.foldOption(opts, "minFoldSize");
1210    var func = cm.foldOption(opts, "rangeFinder");
1211    cm.eachLine(from, to, function(line) {
1212      var mark = null;
1213      if (isFolded(cm, cur)) {
1214        mark = marker(opts.indicatorFolded);
1215      } else {
1216        var pos = Pos(cur, 0);
1217        var range = func && func(cm, pos);
1218        if (range && range.to.line - range.from.line >= minSize)
1219          mark = marker(opts.indicatorOpen);
1220      }
1221      cm.setGutterMarker(line, opts.gutter, mark);
1222      ++cur;
1223    });
1224  }
1225
1226  function updateInViewport(cm) {
1227    var vp = cm.getViewport(), state = cm.state.foldGutter;
1228    if (!state) return;
1229    cm.operation(function() {
1230      updateFoldInfo(cm, vp.from, vp.to);
1231    });
1232    state.from = vp.from; state.to = vp.to;
1233  }
1234
1235  function onGutterClick(cm, line, gutter) {
1236    var state = cm.state.foldGutter;
1237    if (!state) return;
1238    var opts = state.options;
1239    if (gutter != opts.gutter) return;
1240    var folded = isFolded(cm, line);
1241    if (folded) folded.clear();
1242    else cm.foldCode(Pos(line, 0), opts.rangeFinder);
1243  }
1244
1245  function onChange(cm) {
1246    var state = cm.state.foldGutter;
1247    if (!state) return;
1248    var opts = state.options;
1249    state.from = state.to = 0;
1250    clearTimeout(state.changeUpdate);
1251    state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
1252  }
1253
1254  function onViewportChange(cm) {
1255    var state = cm.state.foldGutter;
1256    if (!state) return;
1257    var opts = state.options;
1258    clearTimeout(state.changeUpdate);
1259    state.changeUpdate = setTimeout(function() {
1260      var vp = cm.getViewport();
1261      if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
1262        updateInViewport(cm);
1263      } else {
1264        cm.operation(function() {
1265          if (vp.from < state.from) {
1266            updateFoldInfo(cm, vp.from, state.from);
1267            state.from = vp.from;
1268          }
1269          if (vp.to > state.to) {
1270            updateFoldInfo(cm, state.to, vp.to);
1271            state.to = vp.to;
1272          }
1273        });
1274      }
1275    }, opts.updateViewportTimeSpan || 400);
1276  }
1277
1278  function onFold(cm, from) {
1279    var state = cm.state.foldGutter;
1280    if (!state) return;
1281    var line = from.line;
1282    if (line >= state.from && line < state.to)
1283      updateFoldInfo(cm, line, line + 1);
1284  }
1285});
1286
1287},{"../../lib/codemirror":30,"./foldcode":21}],23:[function(_dereq_,module,exports){
1288// CodeMirror, copyright (c) by Marijn Haverbeke and others
1289// Distributed under an MIT license: http://codemirror.net/LICENSE
1290
1291(function(mod) {
1292  if (typeof exports == "object" && typeof module == "object") // CommonJS
1293    mod(_dereq_("../../lib/codemirror"));
1294  else if (typeof define == "function" && define.amd) // AMD
1295    define(["../../lib/codemirror"], mod);
1296  else // Plain browser env
1297    mod(CodeMirror);
1298})(function(CodeMirror) {
1299"use strict";
1300
1301CodeMirror.registerHelper("fold", "indent", function(cm, start) {
1302  var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
1303  if (!/\S/.test(firstLine)) return;
1304  var getIndent = function(line) {
1305    return CodeMirror.countColumn(line, null, tabSize);
1306  };
1307  var myIndent = getIndent(firstLine);
1308  var lastLineInFold = null;
1309  // Go through lines until we find a line that definitely doesn't belong in
1310  // the block we're folding, or to the end.
1311  for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
1312    var curLine = cm.getLine(i);
1313    var curIndent = getIndent(curLine);
1314    if (curIndent > myIndent) {
1315      // Lines with a greater indent are considered part of the block.
1316      lastLineInFold = i;
1317    } else if (!/\S/.test(curLine)) {
1318      // Empty lines might be breaks within the block we're trying to fold.
1319    } else {
1320      // A non-empty line at an indent equal to or less than ours marks the
1321      // start of another block.
1322      break;
1323    }
1324  }
1325  if (lastLineInFold) return {
1326    from: CodeMirror.Pos(start.line, firstLine.length),
1327    to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
1328  };
1329});
1330
1331});
1332
1333},{"../../lib/codemirror":30}],24:[function(_dereq_,module,exports){
1334// CodeMirror, copyright (c) by Marijn Haverbeke and others
1335// Distributed under an MIT license: http://codemirror.net/LICENSE
1336
1337(function(mod) {
1338  if (typeof exports == "object" && typeof module == "object") // CommonJS
1339    mod(_dereq_("../../lib/codemirror"));
1340  else if (typeof define == "function" && define.amd) // AMD
1341    define(["../../lib/codemirror"], mod);
1342  else // Plain browser env
1343    mod(CodeMirror);
1344})(function(CodeMirror) {
1345  var Pos = CodeMirror.Pos;
1346
1347  function forEach(arr, f) {
1348    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
1349  }
1350
1351  function arrayContains(arr, item) {
1352    if (!Array.prototype.indexOf) {
1353      var i = arr.length;
1354      while (i--) {
1355        if (arr[i] === item) {
1356          return true;
1357        }
1358      }
1359      return false;
1360    }
1361    return arr.indexOf(item) != -1;
1362  }
1363
1364  function scriptHint(editor, keywords, getToken, options) {
1365    // Find the token at the cursor
1366    var cur = editor.getCursor(), token = getToken(editor, cur);
1367    if (/\b(?:string|comment)\b/.test(token.type)) return;
1368    token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
1369
1370    // If it's not a 'word-style' token, ignore the token.
1371    if (!/^[\w$_]*$/.test(token.string)) {
1372      token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
1373               type: token.string == "." ? "property" : null};
1374    } else if (token.end > cur.ch) {
1375      token.end = cur.ch;
1376      token.string = token.string.slice(0, cur.ch - token.start);
1377    }
1378
1379    var tprop = token;
1380    // If it is a property, find out what it is a property of.
1381    while (tprop.type == "property") {
1382      tprop = getToken(editor, Pos(cur.line, tprop.start));
1383      if (tprop.string != ".") return;
1384      tprop = getToken(editor, Pos(cur.line, tprop.start));
1385      if (!context) var context = [];
1386      context.push(tprop);
1387    }
1388    return {list: getCompletions(token, context, keywords, options),
1389            from: Pos(cur.line, token.start),
1390            to: Pos(cur.line, token.end)};
1391  }
1392
1393  function javascriptHint(editor, options) {
1394    return scriptHint(editor, javascriptKeywords,
1395                      function (e, cur) {return e.getTokenAt(cur);},
1396                      options);
1397  };
1398  CodeMirror.registerHelper("hint", "javascript", javascriptHint);
1399
1400  function getCoffeeScriptToken(editor, cur) {
1401  // This getToken, it is for coffeescript, imitates the behavior of
1402  // getTokenAt method in javascript.js, that is, returning "property"
1403  // type and treat "." as indepenent token.
1404    var token = editor.getTokenAt(cur);
1405    if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
1406      token.end = token.start;
1407      token.string = '.';
1408      token.type = "property";
1409    }
1410    else if (/^\.[\w$_]*$/.test(token.string)) {
1411      token.type = "property";
1412      token.start++;
1413      token.string = token.string.replace(/\./, '');
1414    }
1415    return token;
1416  }
1417
1418  function coffeescriptHint(editor, options) {
1419    return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
1420  }
1421  CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
1422
1423  var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
1424                     "toUpperCase toLowerCase split concat match replace search").split(" ");
1425  var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
1426                    "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
1427  var funcProps = "prototype apply call bind".split(" ");
1428  var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
1429                  "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
1430  var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
1431                  "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
1432
1433  function getCompletions(token, context, keywords, options) {
1434    var found = [], start = token.string, global = options && options.globalScope || window;
1435    function maybeAdd(str) {
1436      if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
1437    }
1438    function gatherCompletions(obj) {
1439      if (typeof obj == "string") forEach(stringProps, maybeAdd);
1440      else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
1441      else if (obj instanceof Function) forEach(funcProps, maybeAdd);
1442      for (var name in obj) maybeAdd(name);
1443    }
1444
1445    if (context && context.length) {
1446      // If this is a property, see if it belongs to some object we can
1447      // find in the current environment.
1448      var obj = context.pop(), base;
1449      if (obj.type && obj.type.indexOf("variable") === 0) {
1450        if (options && options.additionalContext)
1451          base = options.additionalContext[obj.string];
1452        if (!options || options.useGlobalScope !== false)
1453          base = base || global[obj.string];
1454      } else if (obj.type == "string") {
1455        base = "";
1456      } else if (obj.type == "atom") {
1457        base = 1;
1458      } else if (obj.type == "function") {
1459        if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
1460            (typeof global.jQuery == 'function'))
1461          base = global.jQuery();
1462        else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
1463          base = global._();
1464      }
1465      while (base != null && context.length)
1466        base = base[context.pop().string];
1467      if (base != null) gatherCompletions(base);
1468    } else {
1469      // If not, just look in the global object and any local scope
1470      // (reading into JS mode internals to get at the local and global variables)
1471      for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
1472      for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
1473      if (!options || options.useGlobalScope !== false)
1474        gatherCompletions(global);
vendor: 4,113 bytes, lines 1475-1586
1475      forEach(keywords, maybeAdd);
1476    }
1477    return found;
1478  }
1479});
1480
1481},{"../../lib/codemirror":30}],25:[function(_dereq_,module,exports){
1482// CodeMirror, copyright (c) by Marijn Haverbeke and others
1483// Distributed under an MIT license: http://codemirror.net/LICENSE
1484
1485(function(mod) {
1486  if (typeof exports == "object" && typeof module == "object") // CommonJS
1487    mod(_dereq_("../../lib/codemirror"));
1488  else if (typeof define == "function" && define.amd) // AMD
1489    define(["../../lib/codemirror"], mod);
1490  else // Plain browser env
1491    mod(CodeMirror);
1492})(function(CodeMirror) {
1493  "use strict";
1494
1495  var HINT_ELEMENT_CLASS        = "CodeMirror-hint";
1496  var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
1497
1498  // This is the old interface, kept around for now to stay
1499  // backwards-compatible.
1500  CodeMirror.showHint = function(cm, getHints, options) {
1501    if (!getHints) return cm.showHint(options);
1502    if (options && options.async) getHints.async = true;
1503    var newOpts = {hint: getHints};
1504    if (options) for (var prop in options) newOpts[prop] = options[prop];
1505    return cm.showHint(newOpts);
1506  };
1507
1508  CodeMirror.defineExtension("showHint", function(options) {
1509    options = parseOptions(this, this.getCursor("start"), options);
1510    var selections = this.listSelections()
1511    if (selections.length > 1) return;
1512    // By default, don't allow completion when something is selected.
1513    // A hint function can have a `supportsSelection` property to
1514    // indicate that it can handle selections.
1515    if (this.somethingSelected()) {
1516      if (!options.hint.supportsSelection) return;
1517      // Don't try with cross-line selections
1518      for (var i = 0; i < selections.length; i++)
1519        if (selections[i].head.line != selections[i].anchor.line) return;
1520    }
1521
1522    if (this.state.completionActive) this.state.completionActive.close();
1523    var completion = this.state.completionActive = new Completion(this, options);
1524    if (!completion.options.hint) return;
1525
1526    CodeMirror.signal(this, "startCompletion", this);
1527    completion.update(true);
1528  });
1529
1530  function Completion(cm, options) {
1531    this.cm = cm;
1532    this.options = options;
1533    this.widget = null;
1534    this.debounce = 0;
1535    this.tick = 0;
1536    this.startPos = this.cm.getCursor("start");
1537    this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
1538
1539    var self = this;
1540    cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
1541  }
1542
1543  var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
1544    return setTimeout(fn, 1000/60);
1545  };
1546  var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
1547
1548  Completion.prototype = {
1549    close: function() {
1550      if (!this.active()) return;
1551      this.cm.state.completionActive = null;
1552      this.tick = null;
1553      this.cm.off("cursorActivity", this.activityFunc);
1554
1555      if (this.widget && this.data) CodeMirror.signal(this.data, "close");
1556      if (this.widget) this.widget.close();
1557      CodeMirror.signal(this.cm, "endCompletion", this.cm);
1558    },
1559
1560    active: function() {
1561      return this.cm.state.completionActive == this;
1562    },
1563
1564    pick: function(data, i) {
1565      var completion = data.list[i];
1566      if (completion.hint) completion.hint(this.cm, data, completion);
1567      else this.cm.replaceRange(getText(completion), completion.from || data.from,
1568                                completion.to || data.to, "complete");
1569      CodeMirror.signal(data, "pick", completion);
1570      this.close();
1571    },
1572
1573    cursorActivity: function() {
1574      if (this.debounce) {
1575        cancelAnimationFrame(this.debounce);
1576        this.debounce = 0;
1577      }
1578
1579      var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
1580      if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
1581          pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
1582          (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
1583        this.close();
1584      } else {
1585        var self = this;
1586        this.debounce = requestAnimationFrame(function() {self.update(
1586);});
1587        if (this.widget) this.widget.disable();
1588      }
1589    },
1590
1591    update: function(first) {
1592      if (this.tick == null) return;
1593      if (!this.options.hint.async) {
1594        this.finishUpdate(this.options.hint(this.cm, this.options), first);
1595      } else {
1596        var myTick = ++this.tick, self = this;
1597        this.options.hint(this.cm, function(data) {
1598          if (self.tick == myTick) self.finishUpdate(data, first);
1599        }, this.options);
1600      }
1601    },
1602
1603    finishUpdate: function(data, first) {
1604      if (this.data) CodeMirror.signal(this.data, "update");
1605      if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null;
1606      this.data = data;
1607
1608      var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
1609      if (this.widget) this.widget.close();
1610      if (data && data.list.length) {
1611        if (picked && data.list.length == 1) {
1612          this.pick(data, 0);
1613        } else {
1614          this.widget = new Widget(this, data);
1615          CodeMirror.signal(data, "shown");
1616        }
1617      }
1618    }
1619  };
1620
1621  function parseOptions(cm, pos, options) {
1622    var editor = cm.options.hintOptions;
1623    var out = {};
1624    for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
1625    if (editor) for (var prop in editor)
1626      if (editor[prop] !== undefined) out[prop] = editor[prop];
1627    if (options) for (var prop in options)
1628      if (options[prop] !== undefined) out[prop] = options[prop];
1629    if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
1630    return out;
1631  }
1632
1633  function getText(completion) {
1634    if (typeof completion == "string") return completion;
1635    else return completion.text;
1636  }
1637
1638  function buildKeyMap(completion, handle) {
1639    var baseMap = {
1640      Up: function() {handle.moveFocus(-1);},
1641      Down: function() {handle.moveFocus(1);},
1642      PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
1643      PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
1644      Home: function() {handle.setFocus(0);},
1645      End: function() {handle.setFocus(handle.length - 1);},
1646      Enter: handle.pick,
1647      Tab: handle.pick,
1648      Esc: handle.close
1649    };
1650    var custom = completion.options.customKeys;
1651    var ourMap = custom ? {} : baseMap;
1652    function addBinding(key, val) {
1653      var bound;
1654      if (typeof val != "string")
1655        bound = function(cm) { return val(cm, handle); };
1656      // This mechanism is deprecated
1657      else if (baseMap.hasOwnProperty(val))
1658        bound = baseMap[val];
1659      else
1660        bound = val;
1661      ourMap[key] = bound;
1662    }
1663    if (custom)
1664      for (var key in custom) if (custom.hasOwnProperty(key))
1665        addBinding(key, custom[key]);
1666    var extra = completion.options.extraKeys;
1667    if (extra)
1668      for (var key in extra) if (extra.hasOwnProperty(key))
1669        addBinding(key, extra[key]);
1670    return ourMap;
1671  }
1672
1673  function getHintElement(hintsElement, el) {
1674    while (el && el != hintsElement) {
1675      if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
1676      el = el.parentNode;
1677    }
1678  }
1679
1680  function Widget(completion, data) {
1681    this.completion = completion;
1682    this.data = data;
1683    this.picked = false;
1684    var widget = this, cm = completion.cm;
1685
1686    var hints = this.hints = document.createElement("ul");
1687    hints.className = "CodeMirror-hints";
1688    this.selectedHint = data.selectedHint || 0;
1689
1690    var completions = data.list;
1691    for (var i = 0; i < completions.length; ++i) {
1692      var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
1693      var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
1694      if (cur.className != null) className = cur.className + " " + className;
1695      elt.className = className;
1696      if (cur.render) cur.render(elt, data, cur);
1697      else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
1698      elt.hintId = i;
1699    }
1700
1701    var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
1702    var left = pos.left, top = pos.bottom, below = true;
1703    hints.style.left = left + "px";
1704    hints.style.top = top + "px";
1705    // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
1706    var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
1707    var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
1708    (completion.options.container || document.body).appendChild(hints);
1709    var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
1710    if (overlapY > 0) {
1711      var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
1712      if (curTop - height > 0) { // Fits above cursor
1713        hints.style.top = (top = pos.top - height) + "px";
1714        below = false;
1715      } else if (height > winH) {
1716        hints.style.height = (winH - 5) + "px";
1717        hints.style.top = (top = pos.bottom - box.top) + "px";
1718        var cursor = cm.getCursor();
1719        if (data.from.ch != cursor.ch) {
1720          pos = cm.cursorCoords(cursor);
1721          hints.style.left = (left = pos.left) + "px";
1722          box = hints.getBoundingClientRect();
1723        }
1724      }
1725    }
1726    var overlapX = box.right - winW;
1727    if (overlapX > 0) {
1728      if (box.right - box.left > winW) {
1729        hints.style.width = (winW - 5) + "px";
1730        overlapX -= (box.right - box.left) - winW;
1731      }
1732      hints.style.left = (left = pos.left - overlapX) + "px";
1733    }
1734
1735    cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
1736      moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
1737      setFocus: function(n) { widget.changeActive(n); },
1738      menuSize: function() { return widget.screenAmount(); },
1739      length: completions.length,
1740      close: function() { completion.close(); },
1741      pick: function() { widget.pick(); },
1742      data: data
1743    }));
1744
1745    if (completion.options.closeOnUnfocus) {
1746      var closingOnBlur;
1747      cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
1748      cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
1749    }
1750
1751    var startScroll = cm.getScrollInfo();
1752    cm.on("scroll", this.onScroll = function() {
1753      var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
1754      var newTop = top + startScroll.top - curScroll.top;
1755      var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
1756      if (!below) point += hints.offsetHeight;
1757      if (point <= editor.top || point >= editor.bottom) return completion.close();
1758      hints.style.top = newTop + "px";
1759      hints.style.left = (left + startScroll.left - curScroll.left) + "px";
1760    });
1761
1762    CodeMirror.on(hints, "dblclick", function(e) {
1763      var t = getHintElement(hints, e.target || e.srcElement);
1764      if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
1765    });
1766
1767    CodeMirror.on(hints, "click", function(e) {
1768      var t = getHintElement(hints, e.target || e.srcElement);
1769      if (t && t.hintId != null) {
1770        widget.changeActive(t.hintId);
1771        if (completion.options.completeOnSingleClick) widget.pick();
1772      }
1773    });
1774
1775    CodeMirror.on(hints, "mousedown", function() {
1776      setTimeout(function(){cm.focus();}, 20);
1777    });
1778
1779    CodeMirror.signal(data, "select", completions[0], hints.firstChild);
1780    return true;
1781  }
1782
1783  Widget.prototype = {
1784    close: function() {
1785      if (this.completion.widget != this) return;
1786      this.completion.widget = null;
1787      this.hints.parentNode.removeChild(this.hints);
1788      this.completion.cm.removeKeyMap(this.keyMap);
1789
1790      var cm = this.completion.cm;
1791      if (this.completion.options.closeOnUnfocus) {
1792        cm.off("blur", this.onBlur);
1793        cm.off("focus", this.onFocus);
1794      }
1795      cm.off("scroll", this.onScroll);
1796    },
1797
1798    disable: function() {
1799      this.completion.cm.removeKeyMap(this.keyMap);
1800      var widget = this;
1801      this.keyMap = {Enter: function() { widget.picked = true; }};
1802      this.completion.cm.addKeyMap(this.keyMap);
1803    },
1804
1805    pick: function() {
1806      this.completion.pick(this.data, this.selectedHint);
1807    },
1808
1809    changeActive: function(i, avoidWrap) {
1810      if (i >= this.data.list.length)
1811        i = avoidWrap ? this.data.list.length - 1 : 0;
1812      else if (i < 0)
1813        i = avoidWrap ? 0  : this.data.list.length - 1;
1814      if (this.selectedHint == i) return;
1815      var node = this.hints.childNodes[this.selectedHint];
1816      node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
1817      node = this.hints.childNodes[this.selectedHint = i];
1818      node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
1819      if (node.offsetTop < this.hints.scrollTop)
1820        this.hints.scrollTop = node.offsetTop - 3;
1821      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
1822        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
1823      CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
1824    },
1825
1826    screenAmount: function() {
1827      return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
1828    }
1829  };
1830
1831  function applicableHelpers(cm, helpers) {
1832    if (!cm.somethingSelected()) return helpers
1833    var result = []
1834    for (var i = 0; i < helpers.length; i++)
1835      if (helpers[i].supportsSelection) result.push(helpers[i])
1836    return result
1837  }
1838
1839  function resolveAutoHints(cm, pos) {
1840    var helpers = cm.getHelpers(pos, "hint"), words
1841    if (helpers.length) {
1842      var async = false, resolved
1843      for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true
1844      if (async) {
1845        resolved = function(cm, callback, options) {
1846          var app = applicableHelpers(cm, helpers)
1847          function run(i, result) {
1848            if (i == app.length) return callback(null)
1849            var helper = app[i]
1850            if (helper.async) {
1851              helper(cm, function(result) {
1852                if (result) callback(result)
1853                else run(i + 1)
1854              }, options)
1855            } else {
1856              var result = helper(cm, options)
1857              if (result) callback(result)
1858              else run(i + 1)
1859            }
1860          }
1861          run(0)
1862        }
1863        resolved.async = true
1864      } else {
1865        resolved = function(cm, options) {
1866          var app = applicableHelpers(cm, helpers)
1867          for (var i = 0; i < app.length; i++) {
1868            var cur = app[i](cm, options)
1869            if (cur && cur.list.length) return cur
1870          }
1871        }
1872      }
1873      resolved.supportsSelection = true
1874      return resolved
1875    } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
1876      return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
1877    } else if (CodeMirror.hint.anyword) {
1878      return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
1879    } else {
1880      return function() {}
1881    }
1882  }
1883
1884  CodeMirror.registerHelper("hint", "auto", {
1885    resolve: resolveAutoHints
1886  });
1887
1888  CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
1889    var cur = cm.getCursor(), token = cm.getTokenAt(cur);
1890    var to = CodeMirror.Pos(cur.line, token.end);
1891    if (token.string && /\w/.test(token.string[token.string.length - 1])) {
1892      var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
1893    } else {
1894      var term = "", from = to;
1895    }
1896    var found = [];
1897    for (var i = 0; i < options.words.length; i++) {
1898      var word = options.words[i];
1899      if (word.slice(0, term.length) == term)
1900        found.push(word);
1901    }
1902
1903    if (found.length) return {list: found, from: from, to: to};
1904  });
1905
1906  CodeMirror.commands.autocomplete = CodeMirror.showHint;
1907
1908  var defaultOptions = {
1909    hint: CodeMirror.hint.auto,
1910    completeSingle: true,
1911    alignWithWord: true,
1912    closeCharacters: /[\s()\[\]{};:>,]/,
1913    closeOnUnfocus: true,
1914    completeOnSingleClick: false,
1915    container: null,
1916    customKeys: null,
1917    extraKeys: null
1918  };
1919
1920  CodeMirror.defineOption("hintOptions", null);
1921});
1922
1923},{"../../lib/codemirror":30}],26:[function(_dereq_,module,exports){
1924// CodeMirror, copyright (c) by Marijn Haverbeke and others
1925// Distributed under an MIT license: http://codemirror.net/LICENSE
1926
1927// Define search commands. Depends on dialog.js or another
1928// implementation of the openDialog method.
1929
1930// Replace works a little oddly -- it will do the replace on the next
1931// Ctrl-G (or whatever is bound to findNext) press. You prevent a
1932// replace by making sure the match is no longer selected when hitting
1933// Ctrl-G.
1934
1935(function(mod) {
1936  if (typeof exports == "object" && typeof module == "object") // CommonJS
1937    mod(_dereq_("../../lib/codemirror"), _dereq_("./searchcursor"), _dereq_("../dialog/dialog"));
1938  else if (typeof define == "function" && define.amd) // AMD
1939    define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
1940  else // Plain browser env
1941    mod(CodeMirror);
1942})(function(CodeMirror) {
1943  "use strict";
1944
1945  function searchOverlay(query, caseInsensitive) {
1946    if (typeof query == "string")
1947      query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
1948    else if (!query.global)
1949      query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
1950
1951    return {token: function(stream) {
1952      query.lastIndex = stream.pos;
1953      var match = query.exec(stream.string);
1954      if (match && match.index == stream.pos) {
1955        stream.pos += match[0].length;
1956        return "searching";
1957      } else if (match) {
1958        stream.pos = match.index;
1959      } else {
1960        stream.skipToEnd();
1961      }
1962    }};
1963  }
1964
1965  function SearchState() {
1966    this.posFrom = this.posTo = this.lastQuery = this.query = null;
1967    this.overlay = null;
1968  }
1969
1970  function getSearchState(cm) {
1971    return cm.state.search || (cm.state.search = new SearchState());
1972  }
1973
1974  function queryCaseInsensitive(query) {
1975    return typeof query == "string" && query == query.toLowerCase();
1976  }
1977
1978  function getSearchCursor(cm, query, pos) {
1979    // Heuristic: if the query string is all lowercase, do a case insensitive search.
1980    return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
1981  }
1982
1983  function persistentDialog(cm, text, deflt, f) {
1984    cm.openDialog(text, f, {
1985      value: deflt,
1986      selectValueOnOpen: true,
1987      closeOnEnter: false,
1988      onClose: function() { clearSearch(cm); }
1989    });
1990  }
1991
1992  function dialog(cm, text, shortText, deflt, f) {
1993    if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
1994    else f(prompt(shortText, deflt));
1995  }
1996
1997  function confirmDialog(cm, text, shortText, fs) {
1998    if (cm.openConfirm) cm.openConfirm(text, fs);
1999    else if (confirm(shortText)) fs[0]();
2000  }
2001
2002  function parseString(string) {
2003    return string.replace(/\\(.)/g, function(_, ch) {
2004      if (ch == "n") return "\n"
2005      if (ch == "r") return "\r"
2006      return ch
2007    })
2008  }
2009
2010  function parseQuery(query) {
2011    var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
2012    if (isRE) {
2013      try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
2014      catch(e) {} // Not a regular expression after all, do a string search
2015    } else {
2016      query = parseString(query)
2017    }
2018    if (typeof query == "string" ? query == "" : query.test(""))
2019      query = /x^/;
2020    return query;
2021  }
2022
2023  var queryDialog =
2024    'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
2025
2026  function startSearch(cm, state, query) {
2027    state.queryText = query;
2028    state.query = parseQuery(query);
2029    cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
2030    state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
2031    cm.addOverlay(state.overlay);
2032    if (cm.showMatchesOnScrollbar) {
2033      if (state.annotate) { state.annotate.clear(); state.annotate = null; }
2034      state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
2035    }
2036  }
2037
2038  function doSearch(cm, rev, persistent) {
2039    var state = getSearchState(cm);
2040    if (state.query) return findNext(cm, rev);
2041    var q = cm.getSelection() || state.lastQuery;
2042    if (persistent && cm.openDialog) {
2043      var hiding = null
2044      persistentDialog(cm, queryDialog, q, function(query, event) {
2045        CodeMirror.e_stop(event);
2046        if (!query) return;
2047        if (query != state.queryText) startSearch(cm, state, query);
2048        if (hiding) hiding.style.opacity = 1
2049        findNext(cm, event.shiftKey, function(_, to) {
2050          var dialog
2051          if (to.line < 3 && document.querySelector &&
2052              (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
2053              dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
2054            (hiding = dialog).style.opacity = .4
2055        })
2056      });
2057    } else {
2058      dialog(cm, queryDialog, "Search for:", q, function(query) {
2059        if (query && !state.query) cm.operation(function() {
2060          startSearch(cm, state, query);
2061          state.posFrom = state.posTo = cm.getCursor();
2062          findNext(cm, rev);
2063        });
2064      });
2065    }
2066  }
2067
2068  function findNext(cm, rev, callback) {cm.operation(function() {
2069    var state = getSearchState(cm);
2070    var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
2071    if (!cursor.find(rev)) {
2072      cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
2073      if (!cursor.find(rev)) return;
2074    }
2075    cm.setSelection(cursor.from(), cursor.to());
2076    cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
2077    state.posFrom = cursor.from(); state.posTo = cursor.to();
2078    if (callback) callback(cursor.from(), cursor.to())
2079  });}
2080
2081  function clearSearch(cm) {cm.operation(function() {
2082    var state = getSearchState(cm);
2083    state.lastQuery = state.query;
2084    if (!state.query) return;
2085    state.query = state.queryText = null;
2086    cm.removeOverlay(state.overlay);
2087    if (state.annotate) { state.annotate.clear(); state.annotate = null; }
2088  });}
2089
2090  var replaceQueryDialog =
2091    ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
2092  var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
2093  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>";
2094
2095  function replaceAll(cm, query, text) {
2096    cm.operation(function() {
2097      for (var cursor = getSearchCursor(cm, query);
2097 cursor.findNext();) {
2098        if (typeof query != "string") {
2099          var match = cm.getRange(cursor.from(), cursor.to()).match(query);
2100          cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
2101        } else cursor.replace(text);
2102      }
2103    });
2104  }
2105
2106  function replace(cm, all) {
2107    if (cm.getOption("readOnly")) return;
2108    var query = cm.getSelection() || getSearchState(cm).lastQuery;
2109    var dialogText = all ? "Replace all:" : "Replace:"
2110    dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
2111      if (!query) return;
2112      query = parseQuery(query);
2113      dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
2114        text = parseString(text)
2115        if (all) {
2116          replaceAll(cm, query, text)
2117        } else {
2118          clearSearch(cm);
2119          var cursor = getSearchCursor(cm, query, cm.getCursor());
2120          var advance = function() {
2121            var start = cursor.from(), match;
2122            if (!(match = cursor.findNext())) {
2123              cursor = getSearchCursor(cm, query);
2124              if (!(match = cursor.findNext()) ||
2125                  (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
2126            }
2127            cm.setSelection(cursor.from(), cursor.to());
2128            cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
2129            confirmDialog(cm, doReplaceConfirm, "Replace?",
2130                          [function() {doReplace(match);}, advance,
2131                           function() {replaceAll(cm, query, text)}]);
2132          };
2133          var doReplace = function(match) {
2134            cursor.replace(typeof query == "string" ? text :
2135                           text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
2136            advance();
2137          };
2138          advance();
2139        }
2140      });
2141    });
2142  }
2143
2144  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
2145  CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
2146  CodeMirror.commands.findNext = doSearch;
2147  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
2148  CodeMirror.commands.clearSearch = clearSearch;
2149  CodeMirror.commands.replace = replace;
2150  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
2151});
2152
2153},{"../../lib/codemirror":30,"../dialog/dialog":16,"./searchcursor":27}],27:[function(_dereq_,module,exports){
2154// CodeMirror, copyright (c) by Marijn Haverbeke and others
2155// Distributed under an MIT license: http://codemirror.net/LICENSE
2156
2157(function(mod) {
2158  if (typeof exports == "object" && typeof module == "object") // CommonJS
2159    mod(_dereq_("../../lib/codemirror"));
2160  else if (typeof define == "function" && define.amd) // AMD
2161    define(["../../lib/codemirror"], mod);
2162  else // Plain browser env
2163    mod(CodeMirror);
2164})(function(CodeMirror) {
2165  "use strict";
2166  var Pos = CodeMirror.Pos;
2167
2168  function SearchCursor(doc, query, pos, caseFold) {
2169    this.atOccurrence = false; this.doc = doc;
2170    if (caseFold == null && typeof query == "string") caseFold = false;
2171
2172    pos = pos ? doc.clipPos(pos) : Pos(0, 0);
2173    this.pos = {from: pos, to: pos};
2174
2175    // The matches method is filled in based on the type of query.
2176    // It takes a position and a direction, and returns an object
2177    // describing the next occurrence of the query, or null if no
2178    // more matches were found.
2179    if (typeof query != "string") { // Regexp match
2180      if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
2181      this.matches = function(reverse, pos) {
2182        if (reverse) {
2183          query.lastIndex = 0;
2184          var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
2185          for (;;) {
2186            query.lastIndex = cutOff;
2187            var newMatch = query.exec(line);
2188            if (!newMatch) break;
2189            match = newMatch;
2190            start = match.index;
2191            cutOff = match.index + (match[0].length || 1);
2192            if (cutOff == line.length) break;
2193          }
2194          var matchLen = (match && match[0].length) || 0;
2195          if (!matchLen) {
2196            if (start == 0 && line.length == 0) {match = undefined;}
2197            else if (start != doc.getLine(pos.line).length) {
2198              matchLen++;
2199            }
2200          }
2201        } else {
2202          query.lastIndex = pos.ch;
2203          var line = doc.getLine(pos.line), match = query.exec(line);
2204          var matchLen = (match && match[0].length) || 0;
2205          var start = match && match.index;
2206          if (start + matchLen != line.length && !matchLen) matchLen = 1;
2207        }
2208        if (match && matchLen)
2209          return {from: Pos(pos.line, start),
2210                  to: Pos(pos.line, start + matchLen),
2211                  match: match};
2212      };
2213    } else { // String query
2214      var origQuery = query;
2215      if (caseFold) query = query.toLowerCase();
2216      var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
2217      var target = query.split("\n");
2218      // Different methods for single-line and multi-line queries
2219      if (target.length == 1) {
2220        if (!query.length) {
2221          // Empty string would match anything and never progress, so
2222          // we define it to match nothing instead.
2223          this.matches = function() {};
2224        } else {
2225          this.matches = function(reverse, pos) {
2226            if (reverse) {
2227              var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
2228              var match = line.lastIndexOf(query);
2229              if (match > -1) {
2230                match = adjustPos(orig, line, match);
2231                return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
2232              }
2233             } else {
2234               var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
2235               var match = line.indexOf(query);
2236               if (match > -1) {
2237                 match = adjustPos(orig, line, match) + pos.ch;
2238                 return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
2239               }
2240            }
2241          };
2242        }
2243      } else {
2244        var origTarget = origQuery.split("\n");
2245        this.matches = function(reverse, pos) {
2246          var last = target.length - 1;
2247          if (reverse) {
2248            if (pos.line - (target.length - 1) < doc.firstLine()) return;
2249            if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
2250            var to = Pos(pos.line, origTarget[last].length);
2251            for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
2252              if (target[i] != fold(doc.getLine(ln))) return;
2253            var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
2254            if (fold(line.slice(cut)) != target[0]) return;
2255            return {from: Pos(ln, cut), to: to};
2256          } else {
2257            if (pos.line + (target.length - 1) >
2257 doc.lastLine()) return;
2258            var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
2259            if (fold(line.slice(cut)) != target[0]) return;
2260            var from = Pos(pos.line, cut);
2261            for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
2262              if (target[i] != fold(doc.getLine(ln))) return;
2263            if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
2264            return {from: from, to: Pos(ln, origTarget[last].length)};
2265          }
2266        };
2267      }
2268    }
2269  }
2270
2271  SearchCursor.prototype = {
2272    findNext: function() {return this.find(false);},
2273    findPrevious: function() {return this.find(true);},
2274
2275    find: function(reverse) {
2276      var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
2277      function savePosAndFail(line) {
2278        var pos = Pos(line, 0);
2279        self.pos = {from: pos, to: pos};
2280        self.atOccurrence = false;
2281        return false;
2282      }
2283
2284      for (;;) {
2285        if (this.pos = this.matches(reverse, pos)) {
2286          this.atOccurrence = true;
2287          return this.pos.match || true;
2288        }
2289        if (reverse) {
2290          if (!pos.line) return savePosAndFail(0);
2291          pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
2292        }
2293        else {
2294          var maxLine = this.doc.lineCount();
2295          if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
2296          pos = Pos(pos.line + 1, 0);
2297        }
2298      }
2299    },
2300
2301    from: function() {if (this.atOccurrence) return this.pos.from;},
2302    to: function() {if (this.atOccurrence) return this.pos.to;},
2303
2304    replace: function(newText, origin) {
2305      if (!this.atOccurrence) return;
2306      var lines = CodeMirror.splitLines(newText);
2307      this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
2308      this.pos.to = Pos(this.pos.from.line + lines.length - 1,
2309                        lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
2310    }
2311  };
2312
2313  // Maps a position in a case-folded line back to a position in the original line
2314  // (compensating for codepoints increasing in number during folding)
2315  function adjustPos(orig, folded, pos) {
2316    if (orig.length == folded.length) return pos;
2317    for (var pos1 = Math.min(pos, orig.length);;) {
2318      var len1 = orig.slice(0, pos1).toLowerCase().length;
2319      if (len1 < pos) ++pos1;
2320      else if (len1 > pos) --pos1;
2321      else return pos1;
2322    }
2323  }
2324
2325  CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
2326    return new SearchCursor(this.doc, query, pos, caseFold);
2327  });
2328  CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
2329    return new SearchCursor(this, query, pos, caseFold);
2330  });
2331
2332  CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
2333    var ranges = [];
2334    var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
2335    while (cur.findNext()) {
2336      if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
2337      ranges.push({anchor: cur.from(), head: cur.to()});
2338    }
2339    if (ranges.length)
2340      this.setSelections(ranges, 0);
2341  });
2342});
2343
2344},{"../../lib/codemirror":30}],28:[function(_dereq_,module,exports){
2345// CodeMirror, copyright (c) by Marijn Haverbeke and others
2346// Distributed under an MIT license: http://codemirror.net/LICENSE
2347
2348(function(mod) {
2349  if (typeof exports == "object" && typeof module == "object") // CommonJS
2350    mod(_dereq_("../../lib/codemirror"));
2351  else if (typeof define == "function" && define.amd) // AMD
2352    define(["../../lib/codemirror"], mod);
2353  else // Plain browser env
2354    mod(CodeMirror);
2355})(function(CodeMirror) {
2356  "use strict";
2357
2358  var Pos = CodeMirror.Pos;
2359
2360  function findParagraph(cm, pos, options) {
2361    var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
2362    for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
2363      var line = cm.getLine(start);
2364      if (startRE && startRE.test(line)) break;
2365      if (!/\S/.test(line)) { ++start; break; }
2366    }
2367    var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
2368    for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
2369      var line = cm.getLine(end);
2370      if (endRE && endRE.test(line)) { ++end; break; }
2371      if (!/\S/.test(line)) break;
2372    }
2373    return {from: start, to: end};
2374  }
2375
2376  function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
2377    for (var at = column; at > 0; --at)
2378      if (wrapOn.test(text.slice(at - 1, at + 1))) break;
2379    for (var first = true;; first = false) {
2380      var endOfText = at;
2381      if (killTrailingSpace)
2382        while (text.charAt(endOfText - 1) == " ") --endOfText;
2383      if (endOfText == 0 && first) at = column;
2384      else return {from: endOfText, to: at};
2385    }
2386  }
2387
2388  function wrapRange(cm, from, to, options) {
2389    from = cm.clipPos(from); to = cm.clipPos(to);
2390    var column = options.column || 80;
2391    var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
2392    var killTrailing = options.killTrailingSpace !== false;
2393    var changes = [], curLine = "", curNo = from.line;
2394    var lines = cm.getRange(from, to, false);
2395    if (!lines.length) return null;
2396    var leadingSpace = lines[0].match(/^[ \t]*/)[0];
2397
2398    for (var i = 0; i < lines.length; ++i) {
2399      var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
2400      if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
2401        curLine += " ";
2402        spaceInserted = 1;
2403      }
2404      var spaceTrimmed = "";
2405      if (i) {
2406        spaceTrimmed = text.match(/^\s*/)[0];
2407        text = text.slice(spaceTrimmed.length);
2408      }
2409      curLine += text;
2410      if (i) {
2411        var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
2412          findBreakPoint(curLine, column, wrapOn, killTrailing);
2413        // If this isn't broken, or is broken at a different point, remove old break
2414        if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
2415          changes.push({text: [spaceInserted ? " " : ""],
2416                        from: Pos(curNo, oldLen),
2417                        to: Pos(curNo + 1, spaceTrimmed.length)});
2418        } else {
2419          curLine = leadingSpace + text;
2420          ++curNo;
2421        }
2422      }
2423      while (curLine.length > column) {
2424        var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
2425        changes.push({text: ["", leadingSpace],
2426                      from: Pos(curNo, bp.from),
2427                      to: Pos(curNo, bp.to)});
2428        curLine = leadingSpace + curLine.slice(bp.to);
2429        ++curNo;
2430      }
2431    }
2432    if (changes.length) cm.operation(function() {
2433      for (var i = 0; i < changes.length; ++i) {
2434        var change = changes[i];
2435        if (change.text || CodeMirror.cmpPos(change.from, change.to))
2436          cm.replaceRange(change.text, change.from, change.to);
2437      }
2438    });
2439    return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
2440  }
2441
2442  CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
2443    options = options || {};
2444    if (!pos) pos = this.getCursor();
2445    var para = findParagraph(this, pos, options);
2446    return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
2447  });
2448
2449  CodeMirror.commands.wrapLines = function(cm) {
2450    cm.operation(function() {
2451      var ranges = cm.listSelections(), at = cm.lastLine() + 1;
2452      for (var i = ranges.length - 1; i >= 0; i--) {
2453        var range = ranges[i], span;
2454        if (range.empty()) {
2455          var para = findParagraph(cm, range.head, {});
2456          span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
2457        } else {
2458          span = {from: range.from(), to: range.to()};
2459        }
2460        if (span.to.line >= at) continue;
2461        at = span.from.line;
2462        wrapRange(cm, span.from, span.to, {});
2463      }
2464    });
2465  };
2466
2467  CodeMirror.defineExtension("wrapRange", function(from, to, options) {
2468    return wrapRange(this, from, to, options || {});
2469  });
2470
2471  CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
2472    options = options || {};
2473    var cm = this, paras = [];
2474    for (var line = from.line; line <= to.line;) {
2475      var para = findParagraph(cm, Pos(line, 0), options);
2476      paras.push(para);
2477      line = para.to;
2478    }
2479    var madeChange = false;
2480    if (paras.length) cm.operation(function() {
2481      for (var i = paras.length - 1; i >= 0; --i)
2482        madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
2483    });
2484    return madeChange;
2485  });
2486});
2487
2488},{"../../lib/codemirror":30}],29:[function(_dereq_,module,exports){
2489// CodeMirror, copyright (c) by Marijn Haverbeke and others
2490// Distributed under an MIT license: http://codemirror.net/LICENSE
2491
2492// A rough approximation of Sublime Text's keybindings
2493// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js
2494
2495(function(mod) {
2496  if (typeof exports == "object" && typeof module == "object") // CommonJS
2497    mod(_dereq_("../lib/codemirror"), _dereq_("../addon/search/searchcursor"), _dereq_("../addon/edit/matchbrackets"));
2498  else if (typeof define == "function" && define.amd) // AMD
2499    define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);
2500  else // Plain browser env
2501    mod(CodeMirror);
2502})(function(CodeMirror) {
2503  "use strict";
2504
2505  var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};
2506  var cmds = CodeMirror.commands;
2507  var Pos = CodeMirror.Pos;
2508  var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
2509  var ctrl = mac ? "Cmd-" : "Ctrl-";
2510
2511  // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
2512  function findPosSubword(doc, start, dir) {
2513    if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
2514    var line = doc.getLine(start.line);
2515    if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
2516    var state = "start", type;
2517    for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {
2518      var next = line.charAt(dir < 0 ? pos - 1 : pos);
2519      var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
2520      if (cat == "w" && next.toUpperCase() == next) cat = "W";
2521      if (state == "start") {
2522        if (cat != "o") { state = "in"; type = cat; }
2523      } else if (state == "in") {
2524        if (type != cat) {
2525          if (type == "w" && cat == "W" && dir < 0) pos--;
2526          if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; }
2527          break;
2528        }
2529      }
2530    }
2531    return Pos(start.line, pos);
2532  }
2533
2534  function moveSubword(cm, dir) {
2535    cm.extendSelectionsBy(function(range) {
2536      if (cm.display.shift || cm.doc.extend || range.empty())
2537        return findPosSubword(cm.doc, range.head, dir);
2538      else
2539        return dir < 0 ? range.from() : range.to();
2540    });
2541  }
2542
2543  cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
2544  cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };
2545
2546  var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-";
2547
2548  cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) {
2549    var info = cm.getScrollInfo();
2550    if (!cm.somethingSelected()) {
2551      var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
2552      if (cm.getCursor().line >= visibleBottomLine)
2553        cm.execCommand("goLineUp");
2554    }
2555    cm.scrollTo(null, info.top - cm.defaultTextHeight());
2556  };
2557  cmds[map[scrollLineCombo + "Down"] = "scrollLineDown"] = function(cm) {
2558    var info = cm.getScrollInfo();
2559    if (!cm.somethingSelected()) {
2560      var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
2561      if (cm.getCursor().line <= visibleTopLine)
2562        cm.execCommand("goLineDown");
2563    }
2564    cm.scrollTo(null, info.top + cm.defaultTextHeight());
2565  };
2566
2567  cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) {
2568    var ranges = cm.listSelections(), lineRanges = [];
2569    for (var i = 0; i < ranges.length; i++) {
2570      var from = ranges[i].from(), to = ranges[i].to();
2571      for (var line = from.line; line <= to.line; ++line)
2572        if (!(to.line > from.line && line == to.line && to.ch == 0))
2573          lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),
2574                           head: line == to.line ? to : Pos(line)});
2575    }
2576    cm.setSelections(lineRanges, 0);
2577  };
2578
2579  map["Shift-Tab"] = "indentLess";
2580
2581  cmds[map["Esc"] = "singleSelectionTop"] = function(cm) {
2582    var range = cm.listSelections()[0];
2583    cm.setSelection(range.anchor, range.head, {scroll: false});
2584  };
2585
2586  cmds[map[ctrl + "L"] = "selectLine"] = function(cm) {
2587    var ranges = cm.listSelections(), extended = [];
2588    for (var i = 0; i < ranges.length; i++) {
2589      var range = ranges[i];
2590      extended.push({anchor: Pos(range.from().line, 0),
2591                     head: Pos(range.to().line + 1, 0)});
2592    }
2593    cm.setSelections(extended);
2594  };
2595
2596  map["Shift-" + ctrl + "K"] = "deleteLine";
2597
2598  function insertLine(cm, above) {
2599    cm.operation(function() {
2600      var len = cm.listSelections().length, newSelection = [], last = -1;
2601      for (var i = 0; i < len; i++) {
2602        var head = cm.listSelections()[i].head;
2603        if (head.line <= last) continue;
2604        var at = Pos(head.line + (above ? 0 : 1), 0);
2605        cm.replaceRange("\n", at, null, "+insertLine");
2606        cm.indentLine(at.line, null, true);
2607        newSelection.push({head: at, anchor: at});
2608        last = head.line + 1;
2609      }
2610      cm.setSelections(newSelection);
2611    });
2612  }
2613
2614  cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); };
2615
2616  cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); };
2617
2618  function wordAt(cm, pos) {
2619    var start = pos.ch, end = start, line = cm.getLine(pos.line);
2620    while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;
2621    while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;
2622    return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};
2623  }
2624
2625  cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) {
2626    var from = cm.getCursor("from"), to = cm.getCursor("to");
2627    var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;
2628    if (CodeMirror.cmpPos(from, to) == 0) {
2629      var word = wordAt(cm, from);
2630      if (!word.word) return;
2631      cm.setSelection(word.from, word.to);
2632      fullWord = true;
2633    } else {
2634      var text = cm.getRange(from, to);
2635      var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
2636      var cur = cm.getSearchCursor(query, to);
2637      if (cur.findNext()) {
2638        cm.addSelection(cur.from(), cur.to());
2639      } else {
2640        cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
2641        if (cur.findNext())
2642          cm.addSelection(cur.from(), cur.to());
2643      }
2644    }
2645    if (fullWord)
2646      cm.state.sublimeFindFullWord = cm.doc.sel;
2647  };
2648
2649  var mirror = "(){}[]";
2650  function selectBetweenBrackets(cm) {
2651    var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1);
2652    if (!opening) return;
2653    for (;;) {
2654      var closing = cm.scanForBracket(pos, 1);
2655      if (!closing) return;
2656      if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {
2657        cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false);
2658        return true;
2659      }
2660      pos = Pos(closing.pos.line, closing.pos.ch + 1);
2661    }
2662  }
2663
2664  cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) {
2665    selectBetweenBrackets(cm) || cm.execCommand("selectAll");
2666  };
2667  cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) {
2668    if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
2669  };
2670
2671  cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) {
2672    cm.extendSelectionsBy(function(range) {
2673      var next = cm.scanForBracket(range.head, 1);
2674      if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;
2675      var prev = cm.scanForBracket(range.head, -1);
2676      return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
2677    });
2678  };
2679
2680  var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";
2681
2682  cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {
2683    var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
2684    for (var i = 0; i < ranges.length; i++) {
2685      var range = ranges[i], from = range.from().line - 1, to = range.to().line;
2686      newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),
2687                    head: Pos(range.head.line - 1, range.head.ch)});
2688      if (range.to().ch == 0 && !range.empty()) --to;
2689      if (from > at) linesToMove.push(from, to);
2690      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
2691      at = to;
2692    }
2693    cm.operation(function() {
2694      for (var i = 0; i < linesToMove.length; i += 2) {
2695        var from = linesToMove[i], to = linesToMove[i + 1];
2696        var line = cm.getLine(from);
2697        cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
2698        if (to > cm.lastLine())
2699          cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine");
2700        else
2701          cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
2702      }
2703      cm.setSelections(newSels);
2704      cm.scrollIntoView();
2705    });
2706  };
2707
2708  cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {
2709    var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
2710    for (var i = ranges.length - 1; i >= 0; i--) {
2711      var range = ranges[i], from = range.to().line + 1, to = range.from().line;
2712      if (range.to().ch == 0 && !range.empty()) from--;
2713      if (from < at) linesToMove.push(from, to);
2714      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
2715      at = to;
2716    }
2717    cm.operation(function() {
2718      for (var i = linesToMove.length - 2; i >= 0; i -= 2) {
2719        var from = linesToMove[i], to = linesToMove[i + 1];
2720        var line = cm.getLine(from);
2721        if (from == cm.lastLine())
2722          cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");
2723        else
2724          cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
2725        cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
2726      }
2727      cm.scrollIntoView();
2728    });
2729  };
2730
2731  map[ctrl + "/"] = function(cm) {
2732    cm.toggleComment({ indent: true });
2733  }
2734
2735  cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {
2736    var ranges = cm.listSelections(), joined = [];
2737    for (var i = 0; i < ranges.length; i++) {
2738      var range = ranges[i], from = range.from();
2739      var start = from.line, end = range.to().line;
2740      while (i < ranges.length - 1 && ranges[i + 1].from().line == end)
2741        end = ranges[++i].to().line;
2742      joined.push({start: start, end: end, anchor: !range.empty() && from});
2743    }
2744    cm.operation(function() {
2745      var offset = 0, ranges = [];
2746      for (var i = 0; i < joined.length; i++) {
2747        var obj = joined[i];
2748        var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;
2749        for (var line = obj.start; line <= obj.end; line++) {
2750          var actual = line - offset;
2751          if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);
2752          if (actual < cm.lastLine()) {
2753            cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length));
2754            ++offset;
2755          }
2756        }
2757        ranges.push({anchor: anchor || head, head: head});
2758      }
2759      cm.setSelections(ranges, 0);
2760    });
2761  };
2762
2763  cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) {
2764    cm.operation(function() {
2765      var rangeCount = cm.listSelections().length;
2766      for (var i = 0; i < rangeCount; i++) {
2767        var range = cm.listSelections()[i];
2768        if (range.empty())
2769          cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0));
2770        else
2771          cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());
2772      }
2773      cm.scrollIntoView();
2774    });
2775  };
2776
2777  map[ctrl + "T"] = "transposeChars";
2778
2779  function sortLines(cm, caseSensitive) {
2780    var ranges = cm.listSelections(), toSort = [], selected;
2781    for (var i = 0; i < ranges.length; i++) {
2782      var range = ranges[i];
2783      if (range.empty()) continue;
2784      var from = range.from().line, to = range.to().line;
2785      while (i < ranges.length - 1 && ranges[i + 1].from().line == to)
2786        to = range[++i].to().line;
2787      toSort.push(from, to);
2788    }
2789    if (toSort.length) selected = true;
2790    else toSort.push(cm.firstLine(), cm.lastLine());
2791
2792    cm.operation(function() {
2793      var ranges = [];
2794      for (var i = 0; i < toSort.length; i += 2) {
2795        var from = toSort[i], to = toSort[i + 1];
2796        var start = Pos(from, 0), end = Pos(to);
2797        var lines = cm.getRange(start, end, false);
2798        if (caseSensitive)
2799          lines.sort();
2800        else
2801          lines.sort(function(a, b) {
2802            var au = a.toUpperCase(), bu = b.toUpperCase();
2803            if (au != bu) { a = au; b = bu; }
2804            return a < b ? -1 : a == b ? 0 : 1;
2805          });
2806        cm.replaceRange(lines, start, end);
2807        if (selected) ranges.push({anchor: start, head: end});
2808      }
2809      if (selected) cm.setSelections(ranges, 0);
2810    });
2811  }
2812
2813  cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); };
2814  cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); };
2815
2816  cmds[map["F2"] = "nextBookmark"] = function(cm) {
2817    var marks = cm.state.sublimeBookmarks;
2818    if (marks) while (marks.length) {
2819      var current = marks.shift();
2820      var found = current.find();
2821      if (found) {
2822        marks.push(current);
2823        return cm.setSelection(found.from, found.to);
2824      }
2825    }
2826  };
2827
2828  cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) {
2829    var marks = cm.state.sublimeBookmarks;
2830    if (marks) while (marks.length) {
2831      marks.unshift(marks.pop());
2832      var found = marks[marks.length - 1].find();
2833      if (!found)
2834        marks.pop();
2835      else
2836        return cm.setSelection(found.from, found.to);
2837    }
2838  };
2839
2840  cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) {
2841    var ranges = cm.listSelections();
2842    var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);
2843    for (var i = 0; i < ranges.length; i++) {
2844      var from = ranges[i].from(), to = ranges[i].to();
2845      var found = cm.findMarks(from, to);
2846      for (var j = 0; j < found.length; j++) {
2847        if (found[j].sublimeBookmark) {
2848          found[j].clear();
2849          for (var k = 0; k < marks.length; k++)
2850            if (marks[k] == found[j])
2851              marks.splice(k--, 1);
2852          break;
2853        }
2854      }
2855      if (j == found.length)
2856        marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));
2857    }
2858  };
2859
2860  cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) {
2861    var marks = cm.state.sublimeBookmarks;
2862    if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();
2863    marks.length = 0;
2864  };
2865
2866  cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) {
2867    var marks = cm.state.sublimeBookmarks, ranges = [];
2868    if (marks) for (var i = 0; i < marks.length; i++) {
2869      var found = marks[i].find();
2870      if (!found)
2871        marks.splice(i--, 0);
2872      else
2873        ranges.push({anchor: found.from, head: found.to});
2874    }
2875    if (ranges.length)
2876      cm.setSelections(ranges, 0);
2877  };
2878
2879  map["Alt-Q"] = "wrapLines";
2880
2881  var cK = ctrl + "K ";
2882
2883  function modifyWordOrSelection(cm, mod) {
2884    cm.operation(function() {
2885      var ranges = cm.listSelections(), indices = [], replacements = [];
2886      for (var i = 0; i < ranges.length; i++) {
2887        var range = ranges[i];
2888        if (range.empty()) { indices.push(i); replacements.push(""); }
2889        else replacements.push(mod(cm.getRange(range.from(), range.to())));
2890      }
2891      cm.replaceSelections(replacements, "around", "case");
2892      for (var i = indices.length - 1, at; i >= 0; i--) {
2893        var range = ranges[indices[i]];
2894        if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;
2895        var word = wordAt(cm, range.head);
2896        at = word.from;
2897        cm.replaceRange(mod(word.word), word.from, word.to);
2898      }
2899    });
2900  }
2901
2902  map[cK + ctrl + "Backspace"] = "delLineLeft";
2903
2904  cmds[map["Backspace"] = "smartBackspace"] = function(cm) {
2905    if (cm.somethingSelected()) return CodeMirror.Pass;
2906
2907    var cursor = cm.getCursor();
2908    var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
2909    var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
2910    var indentUnit = cm.getOption("indentUnit");
2911
2912    if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) {
2913      var prevIndent = new Pos(cursor.line,
2914        CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit));
2915
2916      // If no smart delete is happening (due to tab sizing) just do a regular delete
2917      if (prevIndent.ch == cursor.ch) return CodeMirror.Pass;
2918
2919      return cm.replaceRange("", prevIndent, cursor, "+delete");
2920    } else {
2921      return CodeMirror.Pass;
2922    }
2923  };
2924
2925  cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
2926    cm.operation(function() {
2927      var ranges = cm.listSelections();
2928      for (var i = ranges.length - 1; i >= 0; i--)
2929        cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");
2930      cm.scrollIntoView();
2931    });
2932  };
2933
2934  cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
2935    modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
2936  };
2937  cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
2938    modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
2939  };
2940
2941  cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {
2942    if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
2943    cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
2944  };
2945  cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
2946    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
2947    if (found) cm.setSelection(cm.getCursor(), found);
2948  };
2949  cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
2950    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
2951    if (found) {
2952      var from = cm.getCursor(), to = found;
2953      if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }
2954      cm.state.sublimeKilled = cm.getRange(from, to);
2955      cm.replaceRange("", from, to);
2956    }
2957  };
2958  cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
2959    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
2960    if (found) {
2961      cm.state.sublimeMark.clear();
2962      cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
2963      cm.setCursor(found);
2964    }
2965  };
2966  cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {
2967    if (cm.state.sublimeKilled != null)
2968      cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
2969  };
2970
2971  map[cK + ctrl + "G"] = "clearBookmarks";
2972  cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {
2973    var pos = cm.cursorCoords(null, "local");
2974    cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
2975  };
2976
2977  cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) {
2978    cm.operation(function() {
2979      var ranges = cm.listSelections();
2980      for (var i = 0; i < ranges.length; i++) {
2981        var range = ranges[i];
2982        if (range.head.line > cm.firstLine())
2983          cm.addSelection(Pos(range.head.line - 1, range.head.ch));
2984      }
2985    });
2986  };
2987  cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) {
2988    cm.operation(function() {
2989      var ranges = cm.listSelections();
2990      for (var i = 0; i < ranges.length; i++) {
2991        var range = ranges[i];
2992        if (range.head.line < cm.lastLine())
2993          cm.addSelection(Pos(range.head.line + 1, range.head.ch));
2994      }
2995    });
2996  };
2997
2998  function getTarget(cm) {
2999    var from = cm.getCursor("from"), to = cm.getCursor("to");
3000    if (CodeMirror.cmpPos(from, to) == 0) {
3001      var word = wordAt(cm, from);
3002      if (!word.word) return;
3003      from = word.from;
3004      to = word.to;
3005    }
3006    return {from: from, to: to, query: cm.getRange(from, to), word: word};
3007  }
3008
3009  function findAndGoTo(cm, forward) {
3010    var target = getTarget(cm);
3011    if (!target) return;
3012    var query = target.query;
3013    var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
3014
3015    if (forward ? cur.findNext() : cur.findPrevious()) {
3016      cm.setSelection(cur.from(), cur.to());
3017    } else {
3018      cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)
3019                                              : cm.clipPos(Pos(cm.lastLine())));
3020      if (forward ? cur.findNext() : cur.findPrevious())
3021        cm.setSelection(cur.from(), cur.to());
3022      else if (target.word)
3023        cm.setSelection(target.from, target.to);
3024    }
3025  };
3026  cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); };
3027  cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); };
3028  cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) {
3029    var target = getTarget(cm);
3030    if (!target) return;
3031    var cur = cm.getSearchCursor(target.query);
3032    var matches = [];
3033    var primaryIndex = -1;
3034    while (cur.findNext()) {
3035      matches.push({anchor: cur.from(), head: cur.to()});
3036      if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
3037        primaryIndex++;
3038    }
3039    cm.setSelections(matches, primaryIndex);
3040  };
3041
3042  map["Shift-" + ctrl + "["] = "fold";
3043  map["Shift-" + ctrl + "]"] = "unfold";
3044  map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";
3045
3046  map[ctrl + "I"] = "findIncremental";
3047  map["Shift-" + ctrl + "I"] = "findIncrementalReverse";
3048  map[ctrl + "H"] = "replace";
3049  map["F3"] = "findNext";
3050  map["Shift-F3"] = "findPrev";
3051
3052  CodeMirror.normalizeKeyMap(map);
3053});
3054
3055},{"../addon/edit/matchbrackets":20,"../addon/search/searchcursor":27,"../lib/codemirror":30}],30:[function(_dereq_,module,exports){
3056// CodeMirror, copyright (c) by Marijn Haverbeke and others
3057// Distributed under an MIT license: http://codemirror.net/LICENSE
3058
3059// This is CodeMirror (http://codemirror.net), a code editor
3060// implemented in JavaScript on top of the browser's DOM.
3061//
3062// You can find some technical background for some of the code below
3063// at http://marijnhaverbeke.nl/blog/#cm-internals .
3064
3065(function(mod) {
3066  if (typeof exports == "object" && typeof module == "object") // CommonJS
3067    module.exports = mod();
3068  else if (typeof define == "function" && define.amd) // AMD
3069    return define([], mod);
3070  else // Plain browser env
3071    this.CodeMirror = mod();
3072})(function() {
3073  "use strict";
3074
3075  // BROWSER SNIFFING
3076
3077  // Kludges for bugs and behavior differences that can't be feature
3078  // detected are enabled based on userAgent etc sniffing.
3079  var userAgent = navigator.userAgent;
3080  var platform = navigator.platform;
3081
3082  var gecko = /gecko\/\d/i.test(userAgent);
3083  var ie_upto10 = /MSIE \d/.test(userAgent);
3084  var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
3085  var ie = ie_upto10 || ie_11up;
3086  var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
3087  var webkit = /WebKit\//.test(userAgent);
3088  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
3089  var chrome = /Chrome\//.test(userAgent);
3090  var presto = /Opera\//.test(userAgent);
3091  var safari = /Apple Computer/.test(navigator.vendor);
3092  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
3093  var phantom = /PhantomJS/.test(userAgent);
3094
3095  var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
3096  // This is woefully incomplete. Suggestions for alternative methods welcome.
3097  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
3098  var mac = ios || /Mac/.test(platform
vendor: 14,033 bytes, lines 3098-3468
3098);
3099  var windows = /win/i.test(platform);
3100
3101  var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
3102  if (presto_version) presto_version = Number(presto_version[1]);
3103  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
3104  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
3105  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
3106  var captureRightClick = gecko || (ie && ie_version >= 9);
3107
3108  // Optimize some code when these features are not used.
3109  var sawReadOnlySpans = false, sawCollapsedSpans = false;
3110
3111  // EDITOR CONSTRUCTOR
3112
3113  // A CodeMirror instance represents an editor. This is the object
3114  // that user code is usually dealing with.
3115
3116  function CodeMirror(place, options) {
3117    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
3118
3119    this.options = options = options ? copyObj(options) : {};
3120    // Determine effective options based on given values and defaults.
3121    copyObj(defaults, options, false);
3122    setGuttersForLineNumbers(options);
3123
3124    var doc = options.value;
3125    if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator);
3126    this.doc = doc;
3127
3128    var input = new CodeMirror.inputStyles[options.inputStyle](this);
3129    var display = this.display = new Display(place, doc, input);
3130    display.wrapper.CodeMirror = this;
3131    updateGutters(this);
3132    themeChanged(this);
3133    if (options.lineWrapping)
3134      this.display.wrapper.className += " CodeMirror-wrap";
3135    if (options.autofocus && !mobile) display.input.focus();
3136    initScrollbars(this);
3137
3138    this.state = {
3139      keyMaps: [],  // stores maps added by addKeyMap
3140      overlays: [], // highlighting overlays, as added by addOverlay
3141      modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
3142      overwrite: false,
3143      delayingBlurEvent: false,
3144      focused: false,
3145      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
3146      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
3147      selectingText: false,
3148      draggingText: false,
3149      highlight: new Delayed(), // stores highlight worker timeout
3150      keySeq: null,  // Unfinished key sequence
3151      specialChars: null
3152    };
3153
3154    var cm = this;
3155
3156    // Override magic textarea content restore that IE sometimes does
3157    // on our hidden textarea on reload
3158    if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
3159
3160    registerEventHandlers(this);
3161    ensureGlobalHandlers();
3162
3163    startOperation(this);
3164    this.curOp.forceUpdate = true;
3165    attachDoc(this, doc);
3166
3167    if ((options.autofocus && !mobile) || cm.hasFocus())
3168      setTimeout(bind(onFocus, this), 20);
3169    else
3170      onBlur(this);
3171
3172    for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
3173      optionHandlers[opt](this, options[opt], Init);
3174    maybeUpdateLineNumberWidth(this);
3175    if (options.finishInit) options.finishInit(this);
3176    for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
3177    endOperation(this);
3178    // Suppress optimizelegibility in Webkit, since it breaks text
3179    // measuring on line wrapping boundaries.
3180    if (webkit && options.lineWrapping &&
3181        getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
3182      display.lineDiv.style.textRendering = "auto";
3183  }
3184
3185  // DISPLAY CONSTRUCTOR
3186
3187  // The display handles the DOM integration, both for input reading
3188  // and content drawing. It holds references to DOM nodes and
3189  // display-related state.
3190
3191  function Display(place, doc, input) {
3192    var d = this;
3193    this.input = input;
3194
3195    // Covers bottom-right square when both scrollbars are present.
3196    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
3197    d.scrollbarFiller.setAttribute("cm-not-content", "true");
3198    // Covers bottom of gutter when coverGutterNextToScrollbar is on
3199    // and h scrollbar is present.
3200    d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
3201    d.gutterFiller.setAttribute("cm-not-content", "true");
3202    // Will contain the actual code, positioned to cover the viewport.
3203    d.lineDiv = elt("div", null, "CodeMirror-code");
3204    // Elements are added to these to represent selection and cursors.
3205    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
3206    d.cursorDiv = elt("div", null, "CodeMirror-cursors");
3207    // A visibility: hidden element used to find the size of things.
3208    d.measure = elt("div", null, "CodeMirror-measure");
3209    // When lines outside of the viewport are measured, they are drawn in this.
3210    d.lineMeasure = elt("div", null, "CodeMirror-measure");
3211    // Wraps everything that needs to exist inside the vertically-padded coordinate system
3212    d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
3213                      null, "position: relative; outline: none");
3214    // Moved around its parent to cover visible view.
3215    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
3216    // Set to the height of the document, allowing scrolling.
3217    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
3218    d.sizerWidth = null;
3219    // Behavior of elts with overflow: auto and padding is
3220    // inconsistent across browsers. This is used to ensure the
3221    // scrollable area is big enough.
3222    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
3223    // Will contain the gutters, if any.
3224    d.gutters = elt("div", null, "CodeMirror-gutters");
3225    d.lineGutter = null;
3226    // Actual scrollable element.
3227    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
3228    d.scroller.setAttribute("tabIndex", "-1");
3229    // The element in which the editor lives.
3230    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
3231
3232    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
3233    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
3234    if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
3235
3236    if (place) {
3237      if (place.appendChild) place.appendChild(d.wrapper);
3238      else place(d.wrapper);
3239    }
3240
3241    // Current rendered range (may be bigger than the view window).
3242    d.viewFrom = d.viewTo = doc.first;
3243    d.reportedViewFrom = d.reportedViewTo = doc.first;
3244    // Information about the rendered lines.
3245    d.view = [];
3246    d.renderedView = null;
3247    // Holds info about a single rendered line when it was rendered
3248    // for measurement, while not in view.
3249    d.externalMeasured = null;
3250    // Empty space (in pixels) above the view
3251    d.viewOffset = 0;
3252    d.lastWrapHeight = d.lastWrapWidth = 0;
3253    d.updateLineNumbers = null;
3254
3255    d.nativeBarWidth = d.barHeight = d.barWidth = 0;
3256    d.scrollbarsClipped = false;
3257
3258    // Used to only resize the line number gutter when necessary (when
3259    // the amount of lines crosses a boundary that makes its width change)
3260    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
3261    // Set to true when a non-horizontal-scrolling line widget is
3262    // added. As an optimization, line widget aligning is skipped when
3263    // this is false.
3264    d.alignWidgets = false;
3265
3266    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
3267
3268    // Tracks the maximum line length so that the horizontal scrollbar
3269    // can be kept static when scrolling.
3270    d.maxLine = null;
3271    d.maxLineLength = 0;
3272    d.maxLineChanged = false;
3273
3274    // Used for measuring wheel scrolling granularity
3275    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
3276
3277    // True when shift is held down.
3278    d.shift = false;
3279
3280    // Used to track whether anything happened since the context menu
3281    // was opened.
3282    d.selForContextMenu = null;
3283
3284    d.activeTouch = null;
3285
3286    input.init(d);
3287  }
3288
3289  // STATE UPDATES
3290
3291  // Used to get the editor into a consistent state again when options change.
3292
3293  function loadMode(cm) {
3294    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
3295    resetModeState(cm);
3296  }
3297
3298  function resetModeState(cm) {
3299    cm.doc.iter(function(line) {
3300      if (line.stateAfter) line.stateAfter = null;
3301      if (line.styles) line.styles = null;
3302    });
3303    cm.doc.frontier = cm.doc.first;
3304    startWorker(cm, 100);
3305    cm.state.modeGen++;
3306    if (cm.curOp) regChange(cm);
3307  }
3308
3309  function wrappingChanged(cm) {
3310    if (cm.options.lineWrapping) {
3311      addClass(cm.display.wrapper, "CodeMirror-wrap");
3312      cm.display.sizer.style.minWidth = "";
3313      cm.display.sizerWidth = null;
3314    } else {
3315      rmClass(cm.display.wrapper, "CodeMirror-wrap");
3316      findMaxLine(cm);
3317    }
3318    estimateLineHeights(cm);
3319    regChange(cm);
3320    clearCaches(cm);
3321    setTimeout(function(){updateScrollbars(cm);}, 100);
3322  }
3323
3324  // Returns a function that estimates the height of a line, to use as
3325  // first approximation until the line becomes visible (and is thus
3326  // properly measurable).
3327  function estimateHeight(cm) {
3328    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
3329    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
3330    return function(line) {
3331      if (lineIsHidden(cm.doc, line)) return 0;
3332
3333      var widgetsHeight = 0;
3334      if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
3335        if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
3336      }
3337
3338      if (wrapping)
3339        return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
3340      else
3341        return widgetsHeight + th;
3342    };
3343  }
3344
3345  function estimateLineHeights(cm) {
3346    var doc = cm.doc, est = estimateHeight(cm);
3347    doc.iter(function(line) {
3348      var estHeight = est(line);
3349      if (estHeight != line.height) updateLineHeight(line, estHeight);
3350    });
3351  }
3352
3353  function themeChanged(cm) {
3354    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
3355      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
3356    clearCaches(cm);
3357  }
3358
3359  function guttersChanged(cm) {
3360    updateGutters(cm);
3361    regChange(cm);
3362    setTimeout(function(){alignHorizontally(cm);}, 20);
3363  }
3364
3365  // Rebuild the gutter elements, ensure the margin to the left of the
3366  // code matches their width.
3367  function updateGutters(cm) {
3368    var gutters = cm.display.gutters, specs = cm.options.gutters;
3369    removeChildren(gutters);
3370    for (var i = 0; i < specs.length; ++i) {
3371      var gutterClass = specs[i];
3372      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
3373      if (gutterClass == "CodeMirror-linenumbers") {
3374        cm.display.lineGutter = gElt;
3375        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
3376      }
3377    }
3378    gutters.style.display = i ? "" : "none";
3379    updateGutterSpace(cm);
3380  }
3381
3382  function updateGutterSpace(cm) {
3383    var width = cm.display.gutters.offsetWidth;
3384    cm.display.sizer.style.marginLeft = width + "px";
3385  }
3386
3387  // Compute the character length of a line, taking into account
3388  // collapsed ranges (see markText) that might hide parts, and join
3389  // other lines onto it.
3390  function lineLength(line) {
3391    if (line.height == 0) return 0;
3392    var len = line.text.length, merged, cur = line;
3393    while (merged = collapsedSpanAtStart(cur)) {
3394      var found = merged.find(0, true);
3395      cur = found.from.line;
3396      len += found.from.ch - found.to.ch;
3397    }
3398    cur = line;
3399    while (merged = collapsedSpanAtEnd(cur)) {
3400      var found = merged.find(0, true);
3401      len -= cur.text.length - found.from.ch;
3402      cur = found.to.line;
3403      len += cur.text.length - found.to.ch;
3404    }
3405    return len;
3406  }
3407
3408  // Find the longest line in the document.
3409  function findMaxLine(cm) {
3410    var d = cm.display, doc = cm.doc;
3411    d.maxLine = getLine(doc, doc.first);
3412    d.maxLineLength = lineLength(d.maxLine);
3413    d.maxLineChanged = true;
3414    doc.iter(function(line) {
3415      var len = lineLength(line);
3416      if (len > d.maxLineLength) {
3417        d.maxLineLength = len;
3418        d.maxLine = line;
3419      }
3420    });
3421  }
3422
3423  // Make sure the gutters options contains the element
3424  // "CodeMirror-linenumbers" when the lineNumbers option is true.
3425  function setGuttersForLineNumbers(options) {
3426    var found = indexOf(options.gutters, "CodeMirror-linenumbers");
3427    if (found == -1 && options.lineNumbers) {
3428      options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
3429    } else if (found > -1 && !options.lineNumbers) {
3430      options.gutters = options.gutters.slice(0);
3431      options.gutters.splice(found, 1);
3432    }
3433  }
3434
3435  // SCROLLBARS
3436
3437  // Prepare DOM reads needed to update the scrollbars. Done in one
3438  // shot to minimize update/measure roundtrips.
3439  function measureForScrollbars(cm) {
3440    var d = cm.display, gutterW = d.gutters.offsetWidth;
3441    var docH = Math.round(cm.doc.height + paddingVert(cm.display));
3442    return {
3443      clientHeight: d.scroller.clientHeight,
3444      viewHeight: d.wrapper.clientHeight,
3445      scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
3446      viewWidth: d.wrapper.clientWidth,
3447      barLeft: cm.options.fixedGutter ? gutterW : 0,
3448      docHeight: docH,
3449      scrollHeight: docH + scrollGap(cm) + d.barHeight,
3450      nativeBarWidth: d.nativeBarWidth,
3451      gutterWidth: gutterW
3452    };
3453  }
3454
3455  function NativeScrollbars(place, scroll, cm) {
3456    this.cm = cm;
3457    var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
3458    var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
3459    place(vert); place(horiz);
3460
3461    on(vert, "scroll", function() {
3462      if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
3463    });
3464    on(horiz, "scroll", function() {
3465      if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
3466    });
3467
3468    this.checked
3468Overlay = false;
3469    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
3470    if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
3471  }
3472
3473  NativeScrollbars.prototype = copyObj({
3474    update: function(measure) {
3475      var needsH = measure.scrollWidth > measure.clientWidth + 1;
3476      var needsV = measure.scrollHeight > measure.clientHeight + 1;
3477      var sWidth = measure.nativeBarWidth;
3478
3479      if (needsV) {
3480        this.vert.style.display = "block";
3481        this.vert.style.bottom = needsH ? sWidth + "px" : "0";
3482        var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
3483        // A bug in IE8 can cause this value to be negative, so guard it.
3484        this.vert.firstChild.style.height =
3485          Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
3486      } else {
3487        this.vert.style.display = "";
3488        this.vert.firstChild.style.height = "0";
3489      }
3490
3491      if (needsH) {
3492        this.horiz.style.display = "block";
3493        this.horiz.style.right = needsV ? sWidth + "px" : "0";
3494        this.horiz.style.left = measure.barLeft + "px";
3495        var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
3496        this.horiz.firstChild.style.width =
3497          (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
3498      } else {
3499        this.horiz.style.display = "";
3500        this.horiz.firstChild.style.width = "0";
3501      }
3502
3503      if (!this.checkedOverlay && measure.clientHeight > 0) {
3504        if (sWidth == 0) this.overlayHack();
3505        this.checkedOverlay = true;
3506      }
3507
3508      return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
3509    },
3510    setScrollLeft: function(pos) {
3511      if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
3512    },
3513    setScrollTop: function(pos) {
3514      if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
3515    },
3516    overlayHack: function() {
3517      var w = mac && !mac_geMountainLion ? "12px" : "18px";
3518      this.horiz.style.minHeight = this.vert.style.minWidth = w;
3519      var self = this;
3520      var barMouseDown = function(e) {
3521        if (e_target(e) != self.vert && e_target(e) != self.horiz)
3522          operation(self.cm, onMouseDown)(e);
3523      };
3524      on(this.vert, "mousedown", barMouseDown);
3525      on(this.horiz, "mousedown", barMouseDown);
3526    },
3527    clear: function() {
3528      var parent = this.horiz.parentNode;
3529      parent.removeChild(this.horiz);
3530      parent.removeChild(this.vert);
3531    }
3532  }, NativeScrollbars.prototype);
3533
3534  function NullScrollbars() {}
3535
3536  NullScrollbars.prototype = copyObj({
3537    update: function() { return {bottom: 0, right: 0}; },
3538    setScrollLeft: function() {},
3539    setScrollTop: function() {},
3540    clear: function() {}
3541  }, NullScrollbars.prototype);
3542
3543  CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
3544
3545  function initScrollbars(cm) {
3546    if (cm.display.scrollbars) {
3547      cm.display.scrollbars.clear();
3548      if (cm.display.scrollbars.addClass)
3549        rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
3550    }
3551
3552    cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
3553      cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
3554      // Prevent clicks in the scrollbars from killing focus
3555      on(node, "mousedown", function() {
3556        if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
3557      });
3558      node.setAttribute("cm-not-content", "true");
3559    }, function(pos, axis) {
3560      if (axis == "horizontal") setScrollLeft(cm, pos);
3561      else setScrollTop(cm, pos);
3562    }, cm);
3563    if (cm.display.scrollbars.addClass)
3564      addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
3565  }
3566
3567  function updateScrollbars(cm, measure) {
3568    if (!measure) measure = measureForScrollbars(cm);
3569    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
3570    updateScrollbarsInner(cm, measure);
3571    for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
3572      if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
3573        updateHeightsInViewport(cm);
3574      updateScrollbarsInner(cm, measureForScrollbars(cm));
3575      startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
3576    }
3577  }
3578
3579  // Re-synchronize the fake scrollbars with the actual size of the
3580  // content.
3581  function updateScrollbarsInner(cm, measure) {
3582    var d = cm.display;
3583    var sizes = d.scrollbars.update(measure);
3584
3585    d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
3586    d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
vendor: 8,669 bytes, lines 3586-3789
3586
3587
3588    if (sizes.right && sizes.bottom) {
3589      d.scrollbarFiller.style.display = "block";
3590      d.scrollbarFiller.style.height = sizes.bottom + "px";
3591      d.scrollbarFiller.style.width = sizes.right + "px";
3592    } else d.scrollbarFiller.style.display = "";
3593    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
3594      d.gutterFiller.style.display = "block";
3595      d.gutterFiller.style.height = sizes.bottom + "px";
3596      d.gutterFiller.style.width = measure.gutterWidth + "px";
3597    } else d.gutterFiller.style.display = "";
3598  }
3599
3600  // Compute the lines that are visible in a given viewport (defaults
3601  // the the current scroll position). viewport may contain top,
3602  // height, and ensure (see op.scrollToPos) properties.
3603  function visibleLines(display, doc, viewport) {
3604    var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
3605    top = Math.floor(top - paddingTop(display));
3606    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
3607
3608    var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
3609    // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
3610    // forces those lines into the viewport (if possible).
3611    if (viewport && viewport.ensure) {
3612      var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
3613      if (ensureFrom < from) {
3614        from = ensureFrom;
3615        to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
3616      } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
3617        from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
3618        to = ensureTo;
3619      }
3620    }
3621    return {from: from, to: Math.max(to, from + 1)};
3622  }
3623
3624  // LINE NUMBERS
3625
3626  // Re-align line numbers and gutter marks to compensate for
3627  // horizontal scrolling.
3628  function alignHorizontally(cm) {
3629    var display = cm.display, view = display.view;
3630    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
3631    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
3632    var gutterW = display.gutters.offsetWidth, left = comp + "px";
3633    for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
3634      if (cm.options.fixedGutter && view[i].gutter)
3635        view[i].gutter.style.left = left;
3636      var align = view[i].alignable;
3637      if (align) for (var j = 0; j < align.length; j++)
3638        align[j].style.left = left;
3639    }
3640    if (cm.options.fixedGutter)
3641      display.gutters.style.left = (comp + gutterW) + "px";
3642  }
3643
3644  // Used to ensure that the line number gutter is still the right
3645  // size for the current document size. Returns true when an update
3646  // is needed.
3647  function maybeUpdateLineNumberWidth(cm) {
3648    if (!cm.options.lineNumbers) return false;
3649    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
3650    if (last.length != display.lineNumChars) {
3651      var test = display.measure.appendChild(elt("div", [elt("div", last)],
3652                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
3653      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
3654      display.lineGutter.style.width = "";
3655      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
3656      display.lineNumWidth = display.lineNumInnerWidth + padding;
3657      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
3658      display.lineGutter.style.width = display.lineNumWidth + "px";
3659      updateGutterSpace(cm);
3660      return true;
3661    }
3662    return false;
3663  }
3664
3665  function lineNumberFor(options, i) {
3666    return String(options.lineNumberFormatter(i + options.firstLineNumber));
3667  }
3668
3669  // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
3670  // but using getBoundingClientRect to get a sub-pixel-accurate
3671  // result.
3672  function compensateForHScroll(display) {
3673    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
3674  }
3675
3676  // DISPLAY DRAWING
3677
3678  function DisplayUpdate(cm, viewport, force) {
3679    var display = cm.display;
3680
3681    this.viewport = viewport;
3682    // Store some values that we'll need later (but don't want to force a relayout for)
3683    this.visible = visibleLines(display, cm.doc, viewport);
3684    this.editorIsHidden = !display.wrapper.offsetWidth;
3685    this.wrapperHeight = display.wrapper.clientHeight;
3686    this.wrapperWidth = display.wrapper.clientWidth;
3687    this.oldDisplayWidth = displayWidth(cm);
3688    this.force = force;
3689    this.dims = getDimensions(cm);
3690    this.events = [];
3691  }
3692
3693  DisplayUpdate.prototype.signal = function(emitter, type) {
3694    if (hasHandler(emitter, type))
3695      this.events.push(arguments);
3696  };
3697  DisplayUpdate.prototype.finish = function() {
3698    for (var i = 0; i < this.events.length; i++)
3699      signal.apply(null, this.events[i]);
3700  };
3701
3702  function maybeClipScrollbars(cm) {
3703    var display = cm.display;
3704    if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
3705      display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
3706      display.heightForcer.style.height = scrollGap(cm) + "px";
3707      display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
3708      display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
3709      display.scrollbarsClipped = true;
3710    }
3711  }
3712
3713  // Does the actual updating of the line display. Bails out
3714  // (returning false) when there is nothing to be done and forced is
3715  // false.
3716  function updateDisplayIfNeeded(cm, update) {
3717    var display = cm.display, doc = cm.doc;
3718
3719    if (update.editorIsHidden) {
3720      resetView(cm);
3721      return false;
3722    }
3723
3724    // Bail out if the visible area is already rendered and nothing changed.
3725    if (!update.force &&
3726        update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
3727        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
3728        display.renderedView == display.view && countDirtyView(cm) == 0)
3729      return false;
3730
3731    if (maybeUpdateLineNumberWidth(cm)) {
3732      resetView(cm);
3733      update.dims = getDimensions(cm);
3734    }
3735
3736    // Compute a suitable new viewport (from & to)
3737    var end = doc.first + doc.size;
3738    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
3739    var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
3740    if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
3741    if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
3742    if (sawCollapsedSpans) {
3743      from = visualLineNo(cm.doc, from);
3744      to = visualLineEndNo(cm.doc, to);
3745    }
3746
3747    var different = from != display.viewFrom || to != display.viewTo ||
3748      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
3749    adjustView(cm, from, to);
3750
3751    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
3752    // Position the mover div to align with the current scroll position
3753    cm.display.mover.style.top = display.viewOffset + "px";
3754
3755    var toUpdate = countDirtyView(cm);
3756    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
3757        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
3758      return false;
3759
3760    // For big changes, we hide the enclosing element during the
3761    // update, since that speeds up the operations on most browsers.
3762    var focused = activeElt();
3763    if (toUpdate > 4) display.lineDiv.style.display = "none";
3764    patchDisplay(cm, display.updateLineNumbers, update.dims);
3765    if (toUpdate > 4) display.lineDiv.style.display = "";
3766    display.renderedView = display.view;
3767    // There might have been a widget with a focused element that got
3768    // hidden or updated, if so re-focus it.
3769    if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
3770
3771    // Prevent selection and cursors from interfering with the scroll
3772    // width and height.
3773    removeChildren(display.cursorDiv);
3774    removeChildren(display.selectionDiv);
3775    display.gutters.style.height = display.sizer.style.minHeight = 0;
3776
3777    if (different) {
3778      display.lastWrapHeight = update.wrapperHeight;
3779      display.lastWrapWidth = update.wrapperWidth;
3780      startWorker(cm, 400);
3781    }
3782
3783    display.updateLineNumbers = null;
3784
3785    return true;
3786  }
3787
3788  function postUpdateDisplay(cm, update) {
3789    var viewport = update.viewport;
3790    for (var first = true;; first = false) {
3791      if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
3792        // Clip forced viewport to actual scrollable area.
3793        if (viewport && viewport.top != null)
3794          viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
3795        // Updated line heights might result in the drawn area not
3796        // actually covering the viewport. Keep looping until it does.
3797        update.visible = visibleLines(cm.display, cm.doc, viewport);
3798        if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
3799          break;
3800      }
3801      if (!updateDisplayIfNeeded(cm, update)) break;
3802      updateHeightsInViewport(cm);
3803      var barMeasure = measureForScrollbars(cm);
3804      updateSelection(cm);
3805      setDocumentHeight(cm, barMeasure);
3806      updateScrollbars(cm, barMeasure);
3807    }
3808
3809    update.signal(cm, "update", cm);
3810    if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
3811      update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
3812      cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
3813    }
3814  }
3815
3816  function updateDisplaySimple(cm, viewport) {
3817    var update = new DisplayUpdate(cm, viewport);
3818    if (updateDisplayIfNeeded(cm, update)) {
3819      updateHeightsInViewport(cm);
3820      postUpdateDisplay(cm, update);
3821      var barMeasure = measureForScrollbars(cm);
3822      updateSelection(cm);
3823      setDocumentHeight(cm, barMeasure);
3824      updateScrollbars(cm, barMeasure);
3825      update.finish();
3826    }
3827  }
3828
3829  function setDocumentHeight(cm, measure) {
3830    cm.display.sizer.style.minHeight = measure.docHeight + "px";
3831    var total = measure.docHeight + cm.display.barHeight;
3832    cm.display.heightForcer.style.top = total + "px";
3833    cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
3834  }
3835
3836  // Read the actual heights of the rendered lines, and update their
3837  // stored heights to match.
3838  function updateHeightsInViewport(cm) {
3839    var display = cm.display;
3840    var prevBottom = display.lineDiv.offsetTop;
3841    for (var i = 0; i < display.view.length; i++) {
3842      var cur = display.view[i], height;
3843      if (cur.hidden) continue;
3844      if (ie && ie_version < 8) {
3845        var bot = cur.node.offsetTop + cur.node.offsetHeight;
3846        height = bot - prevBottom;
3847        prevBottom = bot;
3848      } else {
3849        var box = cur.node.getBoundingClientRect();
3850        height = box.bottom - box.top;
3851      }
3852      var diff = cur.line.height - height;
3853      if (height < 2) height = textHeight(display);
3854      if (diff > .001 || diff < -.001) {
3855        updateLineHeight(cur.line, height);
3856        updateWidgetHeight(cur.line);
3857        if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
3858          updateWidgetHeight(cur.rest[j]);
3859      }
3860    }
3861  }
3862
3863  // Read and store the height of line widgets associated with the
3864  // given line.
3865  function updateWidgetHeight(line) {
3866    if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
3867      line.widgets[i].height = line.widgets[i].n
vendor: 11,316 bytes, lines 3867-4138
3867ode.offsetHeight;
3868  }
3869
3870  // Do a bulk-read of the DOM positions and sizes needed to draw the
3871  // view, so that we don't interleave reading and writing to the DOM.
3872  function getDimensions(cm) {
3873    var d = cm.display, left = {}, width = {};
3874    var gutterLeft = d.gutters.clientLeft;
3875    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
3876      left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
3877      width[cm.options.gutters[i]] = n.clientWidth;
3878    }
3879    return {fixedPos: compensateForHScroll(d),
3880            gutterTotalWidth: d.gutters.offsetWidth,
3881            gutterLeft: left,
3882            gutterWidth: width,
3883            wrapperWidth: d.wrapper.clientWidth};
3884  }
3885
3886  // Sync the actual display DOM structure with display.view, removing
3887  // nodes for lines that are no longer in view, and creating the ones
3888  // that are not there yet, and updating the ones that are out of
3889  // date.
3890  function patchDisplay(cm, updateNumbersFrom, dims) {
3891    var display = cm.display, lineNumbers = cm.options.lineNumbers;
3892    var container = display.lineDiv, cur = container.firstChild;
3893
3894    function rm(node) {
3895      var next = node.nextSibling;
3896      // Works around a throw-scroll bug in OS X Webkit
3897      if (webkit && mac && cm.display.currentWheelTarget == node)
3898        node.style.display = "none";
3899      else
3900        node.parentNode.removeChild(node);
3901      return next;
3902    }
3903
3904    var view = display.view, lineN = display.viewFrom;
3905    // Loop over the elements in the view, syncing cur (the DOM nodes
3906    // in display.lineDiv) with the view as we go.
3907    for (var i = 0; i < view.length; i++) {
3908      var lineView = view[i];
3909      if (lineView.hidden) {
3910      } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
3911        var node = buildLineElement(cm, lineView, lineN, dims);
3912        container.insertBefore(node, cur);
3913      } else { // Already drawn
3914        while (cur != lineView.node) cur = rm(cur);
3915        var updateNumber = lineNumbers && updateNumbersFrom != null &&
3916          updateNumbersFrom <= lineN && lineView.lineNumber;
3917        if (lineView.changes) {
3918          if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
3919          updateLineForChanges(cm, lineView, lineN, dims);
3920        }
3921        if (updateNumber) {
3922          removeChildren(lineView.lineNumber);
3923          lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
3924        }
3925        cur = lineView.node.nextSibling;
3926      }
3927      lineN += lineView.size;
3928    }
3929    while (cur) cur = rm(cur);
3930  }
3931
3932  // When an aspect of a line changes, a string is added to
3933  // lineView.changes. This updates the relevant part of the line's
3934  // DOM structure.
3935  function updateLineForChanges(cm, lineView, lineN, dims) {
3936    for (var j = 0; j < lineView.changes.length; j++) {
3937      var type = lineView.changes[j];
3938      if (type == "text") updateLineText(cm, lineView);
3939      else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
3940      else if (type == "class") updateLineClasses(lineView);
3941      else if (type == "widget") updateLineWidgets(cm, lineView, dims);
3942    }
3943    lineView.changes = null;
3944  }
3945
3946  // Lines with gutter elements, widgets or a background class need to
3947  // be wrapped, and have the extra elements added to the wrapper div
3948  function ensureLineWrapped(lineView) {
3949    if (lineView.node == lineView.text) {
3950      lineView.node = elt("div", null, null, "position: relative");
3951      if (lineView.text.parentNode)
3952        lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
3953      lineView.node.appendChild(lineView.text);
3954      if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
3955    }
3956    return lineView.node;
3957  }
3958
3959  function updateLineBackground(lineView) {
3960    var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
3961    if (cls) cls += " CodeMirror-linebackground";
3962    if (lineView.background) {
3963      if (cls) lineView.background.className = cls;
3964      else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
3965    } else if (cls) {
3966      var wrap = ensureLineWrapped(lineView);
3967      lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
3968    }
3969  }
3970
3971  // Wrapper around buildLineContent which will reuse the structure
3972  // in display.externalMeasured when possible.
3973  function getLineContent(cm, lineView) {
3974    var ext = cm.display.externalMeasured;
3975    if (ext && ext.line == lineView.line) {
3976      cm.display.externalMeasured = null;
3977      lineView.measure = ext.measure;
3978      return ext.built;
3979    }
3980    return buildLineContent(cm, lineView);
3981  }
3982
3983  // Redraw the line's text. Interacts with the background and text
3984  // classes because the mode may output tokens that influence these
3985  // classes.
3986  function updateLineText(cm, lineView) {
3987    var cls = lineView.text.className;
3988    var built = getLineContent(cm, lineView);
3989    if (lineView.text == lineView.node) lineView.node = built.pre;
3990    lineView.text.parentNode.replaceChild(built.pre, lineView.text);
3991    lineView.text = built.pre;
3992    if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
3993      lineView.bgClass = built.bgClass;
3994      lineView.textClass = built.textClass;
3995      updateLineClasses(lineView);
3996    } else if (cls) {
3997      lineView.text.className = cls;
3998    }
3999  }
4000
4001  function updateLineClasses(lineView) {
4002    updateLineBackground(lineView);
4003    if (lineView.line.wrapClass)
4004      ensureLineWrapped(lineView).className = lineView.line.wrapClass;
4005    else if (lineView.node != lineView.text)
4006      lineView.node.className = "";
4007    var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
4008    lineView.text.className = textClass || "";
4009  }
4010
4011  function updateLineGutter(cm, lineView, lineN, dims) {
4012    if (lineView.gutter) {
4013      lineView.node.removeChild(lineView.gutter);
4014      lineView.gutter = null;
4015    }
4016    if (lineView.gutterBackground) {
4017      lineView.node.removeChild(lineView.gutterBackground);
4018      lineView.gutterBackground = null;
4019    }
4020    if (lineView.line.gutterClass) {
4021      var wrap = ensureLineWrapped(lineView);
4022      lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
4023                                      "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
4024                                      "px; width: " + dims.gutterTotalWidth + "px");
4025      wrap.insertBefore(lineView.gutterBackground, lineView.text);
4026    }
4027    var markers = lineView.line.gutterMarkers;
4028    if (cm.options.lineNumbers || markers) {
4029      var wrap = ensureLineWrapped(lineView);
4030      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
4031                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px");
4032      cm.display.input.setUneditable(gutterWrap);
4033      wrap.insertBefore(gutterWrap, lineView.text);
4034      if (lineView.line.gutterClass)
4035        gutterWrap.className += " " + lineView.line.gutterClass;
4036      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
4037        lineView.lineNumber = gutterWrap.appendChild(
4038          elt("div", lineNumberFor(cm.options, lineN),
4039              "CodeMirror-linenumber CodeMirror-gutter-elt",
4040              "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
4041              + cm.display.lineNumInnerWidth + "px"));
4042      if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
4043        var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
4044        if (found)
4045          gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
4046                                     dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
4047      }
4048    }
4049  }
4050
4051  function updateLineWidgets(cm, lineView, dims) {
4052    if (lineView.alignable) lineView.alignable = null;
4053    for (var node = lineView.node.firstChild, next; node; node = next) {
4054      var next = node.nextSibling;
4055      if (node.className == "CodeMirror-linewidget")
4056        lineView.node.removeChild(node);
4057    }
4058    insertLineWidgets(cm, lineView, dims);
4059  }
4060
4061  // Build a line's DOM representation from scratch
4062  function buildLineElement(cm, lineView, lineN, dims) {
4063    var built = getLineContent(cm, lineView);
4064    lineView.text = lineView.node = built.pre;
4065    if (built.bgClass) lineView.bgClass = built.bgClass;
4066    if (built.textClass) lineView.textClass = built.textClass;
4067
4068    updateLineClasses(lineView);
4069    updateLineGutter(cm, lineView, lineN, dims);
4070    insertLineWidgets(cm, lineView, dims);
4071    return lineView.node;
4072  }
4073
4074  // A lineView may contain multiple logical lines (when merged by
4075  // collapsed spans). The widgets for all of them need to be drawn.
4076  function insertLineWidgets(cm, lineView, dims) {
4077    insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
4078    if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
4079      insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
4080  }
4081
4082  function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
4083    if (!line.widgets) return;
4084    var wrap = ensureLineWrapped(lineView);
4085    for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
4086      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
4087      if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
4088      positionLineWidget(widget, node, lineView, dims);
4089      cm.display.input.setUneditable(node);
4090      if (allowAbove && widget.above)
4091        wrap.insertBefore(node, lineView.gutter || lineView.text);
4092      else
4093        wrap.appendChild(node);
4094      signalLater(widget, "redraw");
4095    }
4096  }
4097
4098  function positionLineWidget(widget, node, lineView, dims) {
4099    if (widget.noHScroll) {
4100      (lineView.alignable || (lineView.alignable = [])).push(node);
4101      var width = dims.wrapperWidth;
4102      node.style.left = dims.fixedPos + "px";
4103      if (!widget.coverGutter) {
4104        width -= dims.gutterTotalWidth;
4105        node.style.paddingLeft = dims.gutterTotalWidth + "px";
4106      }
4107      node.style.width = width + "px";
4108    }
4109    if (widget.coverGutter) {
4110      node.style.zIndex = 5;
4111      node.style.position = "relative";
4112      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
4113    }
4114  }
4115
4116  // POSITION OBJECT
4117
4118  // A Pos instance represents a position within the text.
4119  var Pos = CodeMirror.Pos = function(line, ch) {
4120    if (!(this instanceof Pos)) return new Pos(line, ch);
4121    this.line = line; this.ch = ch;
4122  };
4123
4124  // Compare two positions, return 0 if they are the same, a negative
4125  // number when a is less, and a positive number otherwise.
4126  var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
4127
4128  function copyPos(x) {return Pos(x.line, x.ch);}
4129  function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
4130  function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
4131
4132  // INPUT HANDLING
4133
4134  function ensureFocus(cm) {
4135    if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
4136  }
4137
4138  
4138function isReadOnly(cm) {
4139    return cm.options.readOnly || cm.doc.cantEdit;
4140  }
4141
4142  // This will be set to an array of strings when copying, so that,
4143  // when pasting, we know what kind of selections the copied text
4144  // was made out of.
4145  var lastCopied = null;
4146
4147  function applyTextInput(cm, inserted, deleted, sel, origin) {
4148    var doc = cm.doc;
4149    cm.display.shift = false;
4150    if (!sel) sel = doc.sel;
4151
4152    var paste = cm.state.pasteIncoming || origin == "paste";
4153    var textLines = doc.splitLines(inserted), multiPaste = null;
4154    // When pasing N lines into N selections, insert one line per selection
4155    if (paste && sel.ranges.length > 1) {
4156      if (lastCopied && lastCopied.join("\n") == inserted) {
4157        if (sel.ranges.length % lastCopied.length == 0) {
4158          multiPaste = [];
4159          for (var i = 0; i < lastCopied.length; i++)
4160            multiPaste.push(doc.splitLines(lastCopied[i]));
4161        }
4162      } else if (textLines.length == sel.ranges.length) {
4163        multiPaste = map(textLines, function(l) { return [l]; });
4164      }
4165    }
4166
4167    // Normal behavior is to insert the new text into every selection
4168    for (var i = sel.ranges.length - 1; i >= 0; i--) {
4169      var range = sel.ranges[i];
4170      var from = range.from(), to = range.to();
4171      if (range.empty()) {
4172        if (deleted && deleted > 0) // Handle deletion
4173          from = Pos(from.line, from.ch - deleted);
4174        else if (cm.state.overwrite && !paste) // Handle overwrite
4175          to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
4176      }
4177      var updateInput = cm.curOp.updateInput;
4178      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
4179                         origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
4180      makeChange(cm.doc, changeEvent);
4181      signalLater(cm, "inputRead", cm, changeEvent);
4182    }
4183    if (inserted && !paste)
4184      triggerElectric(cm, inserted);
4185
4186    ensureCursorVisible(cm);
4187    cm.curOp.updateInput = updateInput;
4188    cm.curOp.typing = true;
4189    cm.state.pasteIncoming = cm.state.cutIncoming = false;
vendor: 21,341 bytes, lines 4190-4737
4190  }
4191
4192  function handlePaste(e, cm) {
4193    var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
4194    if (pasted) {
4195      e.preventDefault();
4196      if (!isReadOnly(cm) && !cm.options.disableInput)
4197        runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
4198      return true;
4199    }
4200  }
4201
4202  function triggerElectric(cm, inserted) {
4203    // When an 'electric' character is inserted, immediately trigger a reindent
4204    if (!cm.options.electricChars || !cm.options.smartIndent) return;
4205    var sel = cm.doc.sel;
4206
4207    for (var i = sel.ranges.length - 1; i >= 0; i--) {
4208      var range = sel.ranges[i];
4209      if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
4210      var mode = cm.getModeAt(range.head);
4211      var indented = false;
4212      if (mode.electricChars) {
4213        for (var j = 0; j < mode.electricChars.length; j++)
4214          if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
4215            indented = indentLine(cm, range.head.line, "smart");
4216            break;
4217          }
4218      } else if (mode.electricInput) {
4219        if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
4220          indented = indentLine(cm, range.head.line, "smart");
4221      }
4222      if (indented) signalLater(cm, "electricInput", cm, range.head.line);
4223    }
4224  }
4225
4226  function copyableRanges(cm) {
4227    var text = [], ranges = [];
4228    for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
4229      var line = cm.doc.sel.ranges[i].head.line;
4230      var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
4231      ranges.push(lineRange);
4232      text.push(cm.getRange(lineRange.anchor, lineRange.head));
4233    }
4234    return {text: text, ranges: ranges};
4235  }
4236
4237  function disableBrowserMagic(field) {
4238    field.setAttribute("autocorrect", "off");
4239    field.setAttribute("autocapitalize", "off");
4240    field.setAttribute("spellcheck", "false");
4241  }
4242
4243  // TEXTAREA INPUT STYLE
4244
4245  function TextareaInput(cm) {
4246    this.cm = cm;
4247    // See input.poll and input.reset
4248    this.prevInput = "";
4249
4250    // Flag that indicates whether we expect input to appear real soon
4251    // now (after some event like 'keypress' or 'input') and are
4252    // polling intensively.
4253    this.pollingFast = false;
4254    // Self-resetting timeout for the poller
4255    this.polling = new Delayed();
4256    // Tracks when input.reset has punted to just putting a short
4257    // string into the textarea instead of the full selection.
4258    this.inaccurateSelection = false;
4259    // Used to work around IE issue with selection being forgotten when focus moves away from textarea
4260    this.hasSelection = false;
4261    this.composing = null;
4262  };
4263
4264  function hiddenTextarea() {
4265    var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
4266    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
4267    // The textarea is kept positioned near the cursor to prevent the
4268    // fact that it'll be scrolled into view on input from scrolling
4269    // our fake cursor out of view. On webkit, when wrap=off, paste is
4270    // very slow. So make the area wide instead.
4271    if (webkit) te.style.width = "1000px";
4272    else te.setAttribute("wrap", "off");
4273    // If border: 0; -- iOS fails to open keyboard (issue #1287)
4274    if (ios) te.style.border = "1px solid black";
4275    disableBrowserMagic(te);
4276    return div;
4277  }
4278
4279  TextareaInput.prototype = copyObj({
4280    init: function(display) {
4281      var input = this, cm = this.cm;
4282
4283      // Wraps and hides input textarea
4284      var div = this.wrapper = hiddenTextarea();
4285      // The semihidden textarea that is focused when the editor is
4286      // focused, and receives input.
4287      var te = this.textarea = div.firstChild;
4288      display.wrapper.insertBefore(div, display.wrapper.firstChild);
4289
4290      // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
4291      if (ios) te.style.width = "0px";
4292
4293      on(te, "input", function() {
4294        if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
4295        input.poll();
4296      });
4297
4298      on(te, "paste", function(e) {
4299        if (handlePaste(e, cm)) return true;
4300
4301        cm.state.pasteIncoming = true;
4302        input.fastPoll();
4303      });
4304
4305      function prepareCopyCut(e) {
4306        if (cm.somethingSelected()) {
4307          lastCopied = cm.getSelections();
4308          if (input.inaccurateSelection) {
4309            input.prevInput = "";
4310            input.inaccurateSelection = false;
4311            te.value = lastCopied.join("\n");
4312            selectInput(te);
4313          }
4314        } else if (!cm.options.lineWiseCopyCut) {
4315          return;
4316        } else {
4317          var ranges = copyableRanges(cm);
4318          lastCopied = ranges.text;
4319          if (e.type == "cut") {
4320            cm.setSelections(ranges.ranges, null, sel_dontScroll);
4321          } else {
4322            input.prevInput = "";
4323            te.value = ranges.text.join("\n");
4324            selectInput(te);
4325          }
4326        }
4327        if (e.type == "cut") cm.state.cutIncoming = true;
4328      }
4329      on(te, "cut", prepareCopyCut);
4330      on(te, "copy", prepareCopyCut);
4331
4332      on(display.scroller, "paste", function(e) {
4333        if (eventInWidget(display, e)) return;
4334        cm.state.pasteIncoming = true;
4335        input.focus();
4336      });
4337
4338      // Prevent normal selection in the editor (we handle our own)
4339      on(display.lineSpace, "selectstart", function(e) {
4340        if (!eventInWidget(display, e)) e_preventDefault(e);
4341      });
4342
4343      on(te, "compositionstart", function() {
4344        var start = cm.getCursor("from");
4345        if (input.composing) input.composing.range.clear()
4346        input.composing = {
4347          start: start,
4348          range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
4349        };
4350      });
4351      on(te, "compositionend", function() {
4352        if (input.composing) {
4353          input.poll();
4354          input.composing.range.clear();
4355          input.composing = null;
4356        }
4357      });
4358    },
4359
4360    prepareSelection: function() {
4361      // Redraw the selection and/or cursor
4362      var cm = this.cm, display = cm.display, doc = cm.doc;
4363      var result = prepareSelection(cm);
4364
4365      // Move the hidden textarea near the cursor to prevent scrolling artifacts
4366      if (cm.options.moveInputWithCursor) {
4367        var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
4368        var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
4369        result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
4370                                            headPos.top + lineOff.top - wrapOff.top));
4371        result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
4372                                             headPos.left + lineOff.left - wrapOff.left));
4373      }
4374
4375      return result;
4376    },
4377
4378    showSelection: function(drawn) {
4379      var cm = this.cm, display = cm.display;
4380      removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
4381      removeChildrenAndAdd(display.selectionDiv, drawn.selection);
4382      if (drawn.teTop != null) {
4383        this.wrapper.style.top = drawn.teTop + "px";
4384        this.wrapper.style.left = drawn.teLeft + "px";
4385      }
4386    },
4387
4388    // Reset the input to correspond to the selection (or to be empty,
4389    // when not typing and nothing is selected)
4390    reset: function(typing) {
4391      if (this.contextMenuPending) return;
4392      var minimal, selected, cm = this.cm, doc = cm.doc;
4393      if (cm.somethingSelected()) {
4394        this.prevInput = "";
4395        var range = doc.sel.primary();
4396        minimal = hasCopyEvent &&
4397          (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
4398        var content = minimal ? "-" : selected || cm.getSelection();
4399        this.textarea.value = content;
4400        if (cm.state.focused) selectInput(this.textarea);
4401        if (ie && ie_version >= 9) this.hasSelection = content;
4402      } else if (!typing) {
4403        this.prevInput = this.textarea.value = "";
4404        if (ie && ie_version >= 9) this.hasSelection = null;
4405      }
4406      this.inaccurateSelection = minimal;
4407    },
4408
4409    getField: function() { return this.textarea; },
4410
4411    supportsTouch: function() { return false; },
4412
4413    focus: function() {
4414      if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
4415        try { this.textarea.focus(); }
4416        catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
4417      }
4418    },
4419
4420    blur: function() { this.textarea.blur(); },
4421
4422    resetPosition: function() {
4423      this.wrapper.style.top = this.wrapper.style.left = 0;
4424    },
4425
4426    receivedFocus: function() { this.slowPoll(); },
4427
4428    // Poll for input changes, using the normal rate of polling. This
4429    // runs as long as the editor is focused.
4430    slowPoll: function() {
4431      var input = this;
4432      if (input.pollingFast) return;
4433      input.polling.set(this.cm.options.pollInterval, function() {
4434        input.poll();
4435        if (input.cm.state.focused) input.slowPoll();
4436      });
4437    },
4438
4439    // When an event has just come in that is likely to add or change
4440    // something in the input textarea, we poll faster, to ensure that
4441    // the change appears on the screen quickly.
4442    fastPoll: function() {
4443      var missed = false, input = this;
4444      input.pollingFast = true;
4445      function p() {
4446        var changed = input.poll();
4447        if (!changed && !missed) {missed = true; input.polling.set(60, p);}
4448        else {input.pollingFast = false; input.slowPoll();}
4449      }
4450      input.polling.set(20, p);
4451    },
4452
4453    // Read input from the textarea, and update the document to match.
4454    // When something is selected, it is present in the textarea, and
4455    // selected (unless it is huge, in which case a placeholder is
4456    // used). When nothing is selected, the cursor sits after previously
4457    // seen text (can be empty), which is stored in prevInput (we must
4458    // not reset the textarea when typing, because that breaks IME).
4459    poll: function() {
4460      var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
4461      // Since this is called a *lot*, try to bail out as cheaply as
4462      // possible when it is clear that nothing happened. hasSelection
4463      // will be the case when there is a lot of text in the textarea,
4464      // in which case reading its value would be expensive.
4465      if (this.contextMenuPending || !cm.state.focused ||
4466          (hasSelection(input) && !prevInput && !this.composing) ||
4467          isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
4468        return false;
4469
4470      var text = input.value;
4471      // If nothing changed, bail.
4472      if (text == prevInput && !cm.somethingSelected()) return false;
4473      // Work around nonsensical selection resetting in IE9/10, and
4474      // inexplicable appearance of private area unicode characters on
4475      // some key combos in Mac (#2689).
4476      if (ie && ie_version >= 9 && this.hasSelection === text ||
4477          mac && /[\uf700-\uf7ff]/.test(text)) {
4478        cm.display.input.reset();
4479        return false;
4480      }
4481
4482      if (cm.doc.sel == cm.display.selForContextMenu) {
4483        var first = text.charCodeAt(0);
4484        if (first == 0x200b && !prevInput) prevInput = "\u200b";
4485        if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
4486      }
4487      // Find the part of the input that is actually new
4488      var same = 0, l = Math.min(prevInput.length, text.length);
4489      while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
4490
4491      var self = this;
4492      runInOp(cm, function() {
4493        applyTextInput(cm, text.slice(same), prevInput.length - same,
4494                       null, self.composing ? "*compose" : null);
4495
4496        // Don't leave long text in the textarea, since it makes further polling slow
4497        if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
4498        else self.prevInput = text;
4499
4500        if (self.composing) {
4501          self.composing.range.clear();
4502          self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
4503                                             {className: "CodeMirror-composing"});
4504        }
4505      });
4506      return true;
4507    },
4508
4509    ensurePolled: function() {
4510      if (this.pollingFast && this.poll()) this.pollingFast = false;
4511    },
4512
4513    onKeyPress: function() {
4514      if (ie && ie_version >= 9) this.hasSelection = null;
4515      this.fastPoll();
4516    },
4517
4518    onContextMenu: function(e) {
4519      var input = this, cm = input.cm, display = cm.display, te = input.textarea;
4520      var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
4521      if (!pos || presto) return; // Opera is difficult.
4522
4523      // Reset the current text selection only if the click is done outside of the selection
4524      // and 'resetSelectionOnContextMenu' option is true.
4525      var reset = cm.options.resetSelectionOnContextMenu;
4526      if (reset && cm.doc.sel.contains(pos) == -1)
4527        operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
4528
4529      var oldCSS = te.style.cssText;
4530      input.wrapper.style.position = "absolute";
4531      te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
4532        "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
4533        (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
4534        "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
4535      if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
4536      display.input.focus();
4537      if (webkit) window.scrollTo(null, oldScrollY);
4538      display.input.reset();
4539      // Adds "Select all" to context menu in FF
4540      if (!cm.somethingSelected()) te.value = input.prevInput = " ";
4541      input.contextMenuPending = true;
4542      display.selForContextMenu = cm.doc.sel;
4543      clearTimeout(display.detectingSelectAll);
4544
4545      // Select-all will be greyed out if there's nothing to select, so
4546      // this adds a zero-width space so that we can later check whether
4547      // it got selected.
4548      function prepareSelectAllHack() {
4549        if (te.selectionStart != null) {
4550          var selected = cm.somethingSelected();
4551          var extval = "\u200b" + (selected ? te.value : "");
4552          te.value = "\u21da"; // Used to catch context-menu undo
4553          te.value = extval;
4554          input.prevInput = selected ? "" : "\u200b";
4555          te.selectionStart = 1; te.selectionEnd = extval.length;
4556          // Re-set this, in case some other handler touched the
4557          // selection in the meantime.
4558          display.selForContextMenu = cm.doc.sel;
4559        }
4560      }
4561      function rehide() {
4562        input.contextMenuPending = false;
4563        input.wrapper.style.position = "relative";
4564        te.style.cssText = oldCSS;
4565        if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
4566
4567        // Try to detect the user choosing select-all
4568        if (te.selectionStart != null) {
4569          if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
4570          var i = 0, poll = function() {
4571            if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
4572                te.selectionEnd > 0 && input.prevInput == "\u200b")
4573              operation(cm, commands.selectAll)(cm);
4574            else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
4575            else display.input.reset();
4576          };
4577          display.detectingSelectAll = setTimeout(poll, 200);
4578        }
4579      }
4580
4581      if (ie && ie_version >= 9) prepareSelectAllHack();
4582      if (captureRightClick) {
4583        e_stop(e);
4584        var mouseup = function() {
4585          off(window, "mouseup", mouseup);
4586          setTimeout(rehide, 20);
4587        };
4588        on(window, "mouseup", mouseup);
4589      } else {
4590        setTimeout(rehide, 50);
4591      }
4592    },
4593
4594    readOnlyChanged: function(val) {
4595      if (!val) this.reset();
4596    },
4597
4598    setUneditable: nothing,
4599
4600    needsContentAttribute: false
4601  }, TextareaInput.prototype);
4602
4603  // CONTENTEDITABLE INPUT STYLE
4604
4605  function ContentEditableInput(cm) {
4606    this.cm = cm;
4607    this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
4608    this.polling = new Delayed();
4609    this.gracePeriod = false;
4610  }
4611
4612  ContentEditableInput.prototype = copyObj({
4613    init: function(display) {
4614      var input = this, cm = input.cm;
4615      var div = input.div = display.lineDiv;
4616      disableBrowserMagic(div);
4617
4618      on(div, "paste", function(e) { handlePaste(e, cm); })
4619
4620      on(div, "compositionstart", function(e) {
4621        var data = e.data;
4622        input.composing = {sel: cm.doc.sel, data: data, startData: data};
4623        if (!data) return;
4624        var prim = cm.doc.sel.primary();
4625        var line = cm.getLine(prim.head.line);
4626        var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
4627        if (found > -1 && found <= prim.head.ch)
4628          input.composing.sel = simpleSelection(Pos(prim.head.line, found),
4629                                                Pos(prim.head.line, found + data.length));
4630      });
4631      on(div, "compositionupdate", function(e) {
4632        input.composing.data = e.data;
4633      });
4634      on(div, "compositionend", function(e) {
4635        var ours = input.composing;
4636        if (!ours) return;
4637        if (e.data != ours.startData && !/\u200b/.test(e.data))
4638          ours.data = e.data;
4639        // Need a small delay to prevent other code (input event,
4640        // selection polling) from doing damage when fired right after
4641        // compositionend.
4642        setTimeout(function() {
4643          if (!ours.handled)
4644            input.applyComposition(ours);
4645          if (input.composing == ours)
4646            input.composing = null;
4647        }, 50);
4648      });
4649
4650      on(div, "touchstart", function() {
4651        input.forceCompositionEnd();
4652      });
4653
4654      on(div, "input", function() {
4655        if (input.composing) return;
4656        if (isReadOnly(cm) || !input.pollContent())
4657          runInOp(input.cm, function() {regChange(cm);});
4658      });
4659
4660      function onCopyCut(e) {
4661        if (cm.somethingSelected()) {
4662          lastCopied = cm.getSelections();
4663          if (e.type == "cut") cm.replaceSelection("", null, "cut");
4664        } else if (!cm.options.lineWiseCopyCut) {
4665          return;
4666        } else {
4667          var ranges = copyableRanges(cm);
4668          lastCopied = ranges.text;
4669          if (e.type == "cut") {
4670            cm.operation(function() {
4671              cm.setSelections(ranges.ranges, 0, sel_dontScroll);
4672              cm.replaceSelection("", null, "cut");
4673            });
4674          }
4675        }
4676        // iOS exposes the clipboard API, but seems to discard content inserted into it
4677        if (e.clipboardData && !ios) {
4678          e.preventDefault();
4679          e.clipboardData.clearData();
4680          e.clipboardData.setData("text/plain", lastCopied.join("\n"));
4681        } else {
4682          // Old-fashioned briefly-focus-a-textarea hack
4683          var kludge = hiddenTextarea(), te = kludge.firstChild;
4684          cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
4685          te.value = lastCopied.join("\n");
4686          var hadFocus = document.activeElement;
4687          selectInput(te);
4688          setTimeout(function() {
4689            cm.display.lineSpace.removeChild(kludge);
4690            hadFocus.focus();
4691          }, 50);
4692        }
4693      }
4694      on(div, "copy", onCopyCut);
4695      on(div, "cut", onCopyCut);
4696    },
4697
4698    prepareSelection: function() {
4699      var result = prepareSelection(this.cm, false);
4700      result.focus = this.cm.state.focused;
4701      return result;
4702    },
4703
4704    showSelection: function(info) {
4705      if (!info || !this.cm.display.view.length) return;
4706      if (info.focus) this.showPrimarySelection();
4707      this.showMultipleSelections(info);
4708    },
4709
4710    showPrimarySelection: function() {
4711      var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
4712      var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
4713      var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
4714      if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
4715          cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
4716          cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
4717        return;
4718
4719      var start = posToDOM(this.cm, prim.from());
4720      var end = posToDOM(this.cm, prim.to());
4721      if (!start && !end) return;
4722
4723      var view = this.cm.display.view;
4724      var old = sel.rangeCount && sel.getRangeAt(0);
4725      if (!start) {
4726        start = {node: view[0].measure.map[2], offset: 0};
4727      } else if (!end) { // FIXME dangerously hacky
4728        var measure = view[view.length - 1].measure;
4729        var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
4730        end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
4731      }
4732
4733      try { var rng = range(start.node, start.offset, end.offset, end.node); }
4734      catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
4735      if (rng) {
4736        sel.removeAllRanges();
4737        sel.addRange(rng);
vendor: 5,598 bytes, lines 4737-4881
4737
4738        if (old && sel.anchorNode == null) sel.addRange(old);
4739        else if (gecko) this.startGracePeriod();
4740      }
4741      this.rememberSelection();
4742    },
4743
4744    startGracePeriod: function() {
4745      var input = this;
4746      clearTimeout(this.gracePeriod);
4747      this.gracePeriod = setTimeout(function() {
4748        input.gracePeriod = false;
4749        if (input.selectionChanged())
4750          input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
4751      }, 20);
4752    },
4753
4754    showMultipleSelections: function(info) {
4755      removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
4756      removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
4757    },
4758
4759    rememberSelection: function() {
4760      var sel = window.getSelection();
4761      this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
4762      this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
4763    },
4764
4765    selectionInEditor: function() {
4766      var sel = window.getSelection();
4767      if (!sel.rangeCount) return false;
4768      var node = sel.getRangeAt(0).commonAncestorContainer;
4769      return contains(this.div, node);
4770    },
4771
4772    focus: function() {
4773      if (this.cm.options.readOnly != "nocursor") this.div.focus();
4774    },
4775    blur: function() { this.div.blur(); },
4776    getField: function() { return this.div; },
4777
4778    supportsTouch: function() { return true; },
4779
4780    receivedFocus: function() {
4781      var input = this;
4782      if (this.selectionInEditor())
4783        this.pollSelection();
4784      else
4785        runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
4786
4787      function poll() {
4788        if (input.cm.state.focused) {
4789          input.pollSelection();
4790          input.polling.set(input.cm.options.pollInterval, poll);
4791        }
4792      }
4793      this.polling.set(this.cm.options.pollInterval, poll);
4794    },
4795
4796    selectionChanged: function() {
4797      var sel = window.getSelection();
4798      return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
4799        sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
4800    },
4801
4802    pollSelection: function() {
4803      if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
4804        var sel = window.getSelection(), cm = this.cm;
4805        this.rememberSelection();
4806        var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
4807        var head = domToPos(cm, sel.focusNode, sel.focusOffset);
4808        if (anchor && head) runInOp(cm, function() {
4809          setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
4810          if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
4811        });
4812      }
4813    },
4814
4815    pollContent: function() {
4816      var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
4817      var from = sel.from(), to = sel.to();
4818      if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
4819
4820      var fromIndex;
4821      if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
4822        var fromLine = lineNo(display.view[0].line);
4823        var fromNode = display.view[0].node;
4824      } else {
4825        var fromLine = lineNo(display.view[fromIndex].line);
4826        var fromNode = display.view[fromIndex - 1].node.nextSibling;
4827      }
4828      var toIndex = findViewIndex(cm, to.line);
4829      if (toIndex == display.view.length - 1) {
4830        var toLine = display.viewTo - 1;
4831        var toNode = display.lineDiv.lastChild;
4832      } else {
4833        var toLine = lineNo(display.view[toIndex + 1].line) - 1;
4834        var toNode = display.view[toIndex + 1].node.previousSibling;
4835      }
4836
4837      var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
4838      var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
4839      while (newText.length > 1 && oldText.length > 1) {
4840        if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
4841        else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
4842        else break;
4843      }
4844
4845      var cutFront = 0, cutEnd = 0;
4846      var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
4847      while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
4848        ++cutFront;
4849      var newBot = lst(newText), oldBot = lst(oldText);
4850      var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
4851                               oldBot.length - (oldText.length == 1 ? cutFront : 0));
4852      while (cutEnd < maxCutEnd &&
4853             newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
4854        ++cutEnd;
4855
4856      newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
4857      newText[0] = newText[0].slice(cutFront);
4858
4859      var chFrom = Pos(fromLine, cutFront);
4860      var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
4861      if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
4862        replaceRange(cm.doc, newText, chFrom, chTo, "+input");
4863        return true;
4864      }
4865    },
4866
4867    ensurePolled: function() {
4868      this.forceCompositionEnd();
4869    },
4870    reset: function() {
4871      this.forceCompositionEnd();
4872    },
4873    forceCompositionEnd: function() {
4874      if (!this.composing || this.composing.handled) return;
4875      this.applyComposition(this.composing);
4876      this.composing.handled = true;
4877      this.div.blur();
4878      this.div.focus();
4879    },
4880    applyComposition: function(composing) {
4881      if (
4881isReadOnly(this.cm))
4882        operation(this.cm, regChange)(this.cm)
4883      else if (composing.data && composing.data != composing.startData)
4884        operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
4885    },
4886
4887    setUneditable: function(node) {
4888      node.contentEditable = "false"
4889    },
4890
4891    onKeyPress: function(e) {
4892      e.preventDefault();
4893      if (!isReadOnly(this.cm
vendor: 11,411 bytes, lines 4893-5198
4893))
4894        operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
4895    },
4896
4897    readOnlyChanged: function(val) {
4898      this.div.contentEditable = String(val != "nocursor")
4899    },
4900
4901    onContextMenu: nothing,
4902    resetPosition: nothing,
4903
4904    needsContentAttribute: true
4905  }, ContentEditableInput.prototype);
4906
4907  function posToDOM(cm, pos) {
4908    var view = findViewForLine(cm, pos.line);
4909    if (!view || view.hidden) return null;
4910    var line = getLine(cm.doc, pos.line);
4911    var info = mapFromLineView(view, line, pos.line);
4912
4913    var order = getOrder(line), side = "left";
4914    if (order) {
4915      var partPos = getBidiPartAt(order, pos.ch);
4916      side = partPos % 2 ? "right" : "left";
4917    }
4918    var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
4919    result.offset = result.collapse == "right" ? result.end : result.start;
4920    return result;
4921  }
4922
4923  function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
4924
4925  function domToPos(cm, node, offset) {
4926    var lineNode;
4927    if (node == cm.display.lineDiv) {
4928      lineNode = cm.display.lineDiv.childNodes[offset];
4929      if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
4930      node = null; offset = 0;
4931    } else {
4932      for (lineNode = node;; lineNode = lineNode.parentNode) {
4933        if (!lineNode || lineNode == cm.display.lineDiv) return null;
4934        if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
4935      }
4936    }
4937    for (var i = 0; i < cm.display.view.length; i++) {
4938      var lineView = cm.display.view[i];
4939      if (lineView.node == lineNode)
4940        return locateNodeInLineView(lineView, node, offset);
4941    }
4942  }
4943
4944  function locateNodeInLineView(lineView, node, offset) {
4945    var wrapper = lineView.text.firstChild, bad = false;
4946    if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
4947    if (node == wrapper) {
4948      bad = true;
4949      node = wrapper.childNodes[offset];
4950      offset = 0;
4951      if (!node) {
4952        var line = lineView.rest ? lst(lineView.rest) : lineView.line;
4953        return badPos(Pos(lineNo(line), line.text.length), bad);
4954      }
4955    }
4956
4957    var textNode = node.nodeType == 3 ? node : null, topNode = node;
4958    if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
4959      textNode = node.firstChild;
4960      if (offset) offset = textNode.nodeValue.length;
4961    }
4962    while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
4963    var measure = lineView.measure, maps = measure.maps;
4964
4965    function find(textNode, topNode, offset) {
4966      for (var i = -1; i < (maps ? maps.length : 0); i++) {
4967        var map = i < 0 ? measure.map : maps[i];
4968        for (var j = 0; j < map.length; j += 3) {
4969          var curNode = map[j + 2];
4970          if (curNode == textNode || curNode == topNode) {
4971            var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
4972            var ch = map[j] + offset;
4973            if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
4974            return Pos(line, ch);
4975          }
4976        }
4977      }
4978    }
4979    var found = find(textNode, topNode, offset);
4980    if (found) return badPos(found, bad);
4981
4982    // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
4983    for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
4984      found = find(after, after.firstChild, 0);
4985      if (found)
4986        return badPos(Pos(found.line, found.ch - dist), bad);
4987      else
4988        dist += after.textContent.length;
4989    }
4990    for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
4991      found = find(before, before.firstChild, -1);
4992      if (found)
4993        return badPos(Pos(found.line, found.ch + dist), bad);
4994      else
4995        dist += after.textContent.length;
4996    }
4997  }
4998
4999  function domTextBetween(cm, from, to, fromLine, toLine) {
5000    var text = "", closing = false, lineSep = cm.doc.lineSeparator();
5001    function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
5002    function walk(node) {
5003      if (node.nodeType == 1) {
5004        var cmText = node.getAttribute("cm-text");
5005        if (cmText != null) {
5006          if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
5007          text += cmText;
5008          return;
5009        }
5010        var markerID = node.getAttribute("cm-marker"), range;
5011        if (markerID) {
5012          var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
5013          if (found.length && (range = found[0].find()))
5014            text += getBetween(cm.doc, range.from, range.to).join(lineSep);
5015          return;
5016        }
5017        if (node.getAttribute("contenteditable") == "false") return;
5018        for (var i = 0; i < node.childNodes.length; i++)
5019          walk(node.childNodes[i]);
5020        if (/^(pre|div|p)$/i.test(node.nodeName))
5021          closing = true;
5022      } else if (node.nodeType == 3) {
5023        var val = node.nodeValue;
5024        if (!val) return;
5025        if (closing) {
5026          text += lineSep;
5027          closing = false;
5028        }
5029        text += val;
5030      }
5031    }
5032    for (;;) {
5033      walk(from);
5034      if (from == to) break;
5035      from = from.nextSibling;
5036    }
5037    return text;
5038  }
5039
5040  CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
5041
5042  // SELECTION / CURSOR
5043
5044  // Selection objects are immutable. A new one is created every time
5045  // the selection changes. A selection is one or more non-overlapping
5046  // (and non-touching) ranges, sorted, and an integer that indicates
5047  // which one is the primary selection (the one that's scrolled into
5048  // view, that getCursor returns, etc).
5049  function Selection(ranges, primIndex) {
5050    this.ranges = ranges;
5051    this.primIndex = primIndex;
5052  }
5053
5054  Selection.prototype = {
5055    primary: function() { return this.ranges[this.primIndex]; },
5056    equals: function(other) {
5057      if (other == this) return true;
5058      if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
5059      for (var i = 0; i < this.ranges.length; i++) {
5060        var here = this.ranges[i], there = other.ranges[i];
5061        if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
5062      }
5063      return true;
5064    },
5065    deepCopy: function() {
5066      for (var out = [], i = 0; i < this.ranges.length; i++)
5067        out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
5068      return new Selection(out, this.primIndex);
5069    },
5070    somethingSelected: function() {
5071      for (var i = 0; i < this.ranges.length; i++)
5072        if (!this.ranges[i].empty()) return true;
5073      return false;
5074    },
5075    contains: function(pos, end) {
5076      if (!end) end = pos;
5077      for (var i = 0; i < this.ranges.length; i++) {
5078        var range = this.ranges[i];
5079        if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
5080          return i;
5081      }
5082      return -1;
5083    }
5084  };
5085
5086  function Range(anchor, head) {
5087    this.anchor = anchor; this.head = head;
5088  }
5089
5090  Range.prototype = {
5091    from: function() { return minPos(this.anchor, this.head); },
5092    to: function() { return maxPos(this.anchor, this.head); },
5093    empty: function() {
5094      return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
5095    }
5096  };
5097
5098  // Take an unsorted, potentially overlapping set of ranges, and
5099  // build a selection out of it. 'Consumes' ranges array (modifying
5100  // it).
5101  function normalizeSelection(ranges, primIndex) {
5102    var prim = ranges[primIndex];
5103    ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
5104    primIndex = indexOf(ranges, prim);
5105    for (var i = 1; i < ranges.length; i++) {
5106      var cur = ranges[i], prev = ranges[i - 1];
5107      if (cmp(prev.to(), cur.from()) >= 0) {
5108        var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
5109        var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
5110        if (i <= primIndex) --primIndex;
5111        ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
5112      }
5113    }
5114    return new Selection(ranges, primIndex);
5115  }
5116
5117  function simpleSelection(anchor, head) {
5118    return new Selection([new Range(anchor, head || anchor)], 0);
5119  }
5120
5121  // Most of the external API clips given positions to make sure they
5122  // actually exist within the document.
5123  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
5124  function clipPos(doc, pos) {
5125    if (pos.line < doc.first) return Pos(doc.first, 0);
5126    var last = doc.first + doc.size - 1;
5127    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
5128    return clipToLen(pos, getLine(doc, pos.line).text.length);
5129  }
5130  function clipToLen(pos, linelen) {
5131    var ch = pos.ch;
5132    if (ch == null || ch > linelen) return Pos(pos.line, linelen);
5133    else if (ch < 0) return Pos(pos.line, 0);
5134    else return pos;
5135  }
5136  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
5137  function clipPosArray(doc, array) {
5138    for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
5139    return out;
5140  }
5141
5142  // SELECTION UPDATES
5143
5144  // The 'scroll' parameter given to many of these indicated whether
5145  // the new cursor position should be scrolled into view after
5146  // modifying the selection.
5147
5148  // If shift is held or the extend flag is set, extends a range to
5149  // include a given position (and optionally a second position).
5150  // Otherwise, simply returns the range between the given positions.
5151  // Used for cursor motion and such.
5152  function extendRange(doc, range, head, other) {
5153    if (doc.cm && doc.cm.display.shift || doc.extend) {
5154      var anchor = range.anchor;
5155      if (other) {
5156        var posBefore = cmp(head, anchor) < 0;
5157        if (posBefore != (cmp(other, anchor) < 0)) {
5158          anchor = head;
5159          head = other;
5160        } else if (posBefore != (cmp(head, other) < 0)) {
5161          head = other;
5162        }
5163      }
5164      return new Range(anchor, head);
5165    } else {
5166      return new Range(other || head, head);
5167    }
5168  }
5169
5170  // Extend the primary selection range, discard the rest.
5171  function extendSelection(doc, head, other, options) {
5172    setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
5173  }
5174
5175  // Extend all selections (pos is an array of selections with length
5176  // equal the number of selections)
5177  function extendSelections(doc, heads, options) {
5178    for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
5179      out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
5180    var newSel = normalizeSelection(out, doc.sel.primIndex);
5181    setSelection(doc, newSel, options);
5182  }
5183
5184  // Updates a single range in the selection.
5185  function replaceOneSelection(doc, i, range, options) {
5186    var ranges = doc.sel.ranges.slice(0);
5187    ranges[i] = range;
5188    setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
5189  }
5190
5191  // Reset the selection to a single range.
5192  function setSimpleSelection(doc, anchor, head, options) {
5193    setSelection(doc, simpleSelection(anchor, head), options);
5194  }
5195
5196  // Give beforeSelectionChange handlers a change to influence a
5197  // selection update.
5198  function filterSelectionChange(doc, sel
5198) {
5199    var obj = {
5200      ranges: sel.ranges,
5201      update: function(ranges) {
5202        this.ranges = [];
5203        for (var i = 0; i < ranges.length; i++)
5204          this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
5205                                     clipPos(doc, ranges[i].head));
5206      }
5207    };
5208    signal(doc, "beforeSelectionChange", doc, obj);
5209    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
5210    if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
5211    else return sel;
5212  }
5213
5214  function setSelectionReplaceHistory(doc, sel, options) {
5215    var done = doc.history.done, last = lst(done);
5216    if (last && last.ranges) {
5217      done[done.length - 1] = sel;
5218      setSelectionNoUndo(doc, sel, options);
5219    } else {
5220      setSelection(doc, sel, options);
5221    }
5222  }
5223
5224  // Set a new selection.
5225  function setSelection(doc, sel, options) {
5226    setSelectionNoUndo(doc, sel, options);
5227    addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
5228  }
5229
5230  function setSelectionNoUndo(doc, sel, options) {
5231    if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
5232      sel = filterSelectionChange(doc, sel);
5233
5234    var bias = options && options.bias ||
5235      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
5236    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
5237
5238    if (!(options && options.scroll === false) && doc.cm)
5239      ensureCursorVisible(doc.cm);
5240  }
5241
5242  function setSelectionInner(doc, sel) {
5243    if (sel.equals(doc.sel)) return;
5244
5245    doc.sel = sel;
5246
5247    if (doc.cm) {
5248      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
5249      signalCursorActivity(doc.cm);
5250    }
5251    signalLater(doc, "cursorActivity", doc);
5252  }
5253
5254  // Verify that the selection does not partially select any atomic
5255  // marked ranges.
5256  function reCheckSelection(doc) {
5257    setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
5258  }
5259
5260  // Return a selection that does not partially select any atomic
5261  // ranges.
5262  function skipAtomicInSelection(doc, sel, bias, mayClear) {
5263    var out;
5264    for (var i = 0; i < sel.ranges.length; i++) {
5265      var range = sel.ranges[i];
5266      var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
5267      var newHead = skipAtomic(doc, range.head, bias, mayClear);
5268      if (out || newAnchor != range.anchor || newHead != range.head) {
5269        if (!out) out = sel.ranges.slice(0, i);
5270        out[i] = new Range(newAnchor, newHead);
5271      }
5272    }
5273    return out ? normalizeSelection(out, sel.primIndex) : sel;
5274  }
5275
5276  // Ensure a given position is not inside an atomic range.
5277  function skipAtomic(doc, pos, bias, mayClear) {
5278    var flipped = false, curPos = pos;
5279    var dir = bias || 1;
5280    doc.cantEdit = false;
5281    search: for (;;) {
5282      var line = getLine(doc, curPos.line);
5283      if (line.markedSpans) {
5284        for (var i = 0; i < line.markedSpans.length; ++i) {
5285          var sp = line.markedSpans[i], m = sp.marker;
5286          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
5287              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
5288            if (mayClear) {
5289              signal(m, "beforeCursorEnter");
5290              if (m.explicitlyCleared) {
5291                if (!line.markedSpans) break;
5292                else {--i; continue;}
5293              }
5294            }
5295            if (!m.atomic) continue;
5296            var newPos = m.find(dir < 0 ? -1 : 1);
5297            if (cmp(newPos, curPos) == 0) {
5298              newPos.ch += dir;
5299              if (newPos.ch < 0) {
5300                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
5301                else newPos = null;
5302              } else if (newPos.ch > line.text.length) {
5303                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
5304                else newPos = null;
5305              }
5306              if (!newPos) {
5307                if (flipped) {
5308                  // Driven in a corner -- no valid cursor position found at all
5309                  // -- try again *with* clearing, if we didn't already
5310                  if (!mayClear) return skipAtomic(doc, pos, bias, true);
5311                  // Otherwise, turn off editing until further notice, and return the start of the doc
5312                  doc.cantEdit = true;
5313                  return Pos(doc.first, 0);
5314                }
5315                flipped = true; newPos = pos; dir = -dir;
5316              }
5317            }
5318            curPos = newPos;
5319            continue search;
5320          }
5321        }
5322      }
5323      return curPos;
5324    }
5325  }
5326
5327  // SELECTION DRAWING
5328
5329  function updateSelection(cm) {
5330    cm.display.input.showSelection(cm.display.input.prepareSelection());
5331  }
5332
5333  function prepareSelection(cm, primary) {
5334    var doc = cm.doc, result = {};
5335    var curFragment = result.cursors = document.createDocumentFragment();
5336    var selFragment = result.selection = document.createDocumentFragment();
5337
5338    for (var i = 0; i < doc.sel.ranges.length; i++) {
5339      if (primary === false && i == doc.sel.primIndex) continue;
5340      var range = doc.sel.ranges[i]
vendor: 15,513 bytes, lines 5340-5712
5340;
5341      var collapsed = range.empty();
5342      if (collapsed || cm.options.showCursorWhenSelecting)
5343        drawSelectionCursor(cm, range.head, curFragment);
5344      if (!collapsed)
5345        drawSelectionRange(cm, range, selFragment);
5346    }
5347    return result;
5348  }
5349
5350  // Draws a cursor for the given range
5351  function drawSelectionCursor(cm, head, output) {
5352    var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
5353
5354    var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
5355    cursor.style.left = pos.left + "px";
5356    cursor.style.top = pos.top + "px";
5357    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
5358
5359    if (pos.other) {
5360      // Secondary cursor, shown when on a 'jump' in bi-directional text
5361      var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
5362      otherCursor.style.display = "";
5363      otherCursor.style.left = pos.other.left + "px";
5364      otherCursor.style.top = pos.other.top + "px";
5365      otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
5366    }
5367  }
5368
5369  // Draws the given range as a highlighted selection
5370  function drawSelectionRange(cm, range, output) {
5371    var display = cm.display, doc = cm.doc;
5372    var fragment = document.createDocumentFragment();
5373    var padding = paddingH(cm.display), leftSide = padding.left;
5374    var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
5375
5376    function add(left, top, width, bottom) {
5377      if (top < 0) top = 0;
5378      top = Math.round(top);
5379      bottom = Math.round(bottom);
5380      fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
5381                               "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
5382                               "px; height: " + (bottom - top) + "px"));
5383    }
5384
5385    function drawForLine(line, fromArg, toArg) {
5386      var lineObj = getLine(doc, line);
5387      var lineLen = lineObj.text.length;
5388      var start, end;
5389      function coords(ch, bias) {
5390        return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
5391      }
5392
5393      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
5394        var leftPos = coords(from, "left"), rightPos, left, right;
5395        if (from == to) {
5396          rightPos = leftPos;
5397          left = right = leftPos.left;
5398        } else {
5399          rightPos = coords(to - 1, "right");
5400          if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
5401          left = leftPos.left;
5402          right = rightPos.right;
5403        }
5404        if (fromArg == null && from == 0) left = leftSide;
5405        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
5406          add(left, leftPos.top, null, leftPos.bottom);
5407          left = leftSide;
5408          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
5409        }
5410        if (toArg == null && to == lineLen) right = rightSide;
5411        if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
5412          start = leftPos;
5413        if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
5414          end = rightPos;
5415        if (left < leftSide + 1) left = leftSide;
5416        add(left, rightPos.top, right - left, rightPos.bottom);
5417      });
5418      return {start: start, end: end};
5419    }
5420
5421    var sFrom = range.from(), sTo = range.to();
5422    if (sFrom.line == sTo.line) {
5423      drawForLine(sFrom.line, sFrom.ch, sTo.ch);
5424    } else {
5425      var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
5426      var singleVLine = visualLine(fromLine) == visualLine(toLine);
5427      var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
5428      var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
5429      if (singleVLine) {
5430        if (leftEnd.top < rightStart.top - 2) {
5431          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
5432          add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
5433        } else {
5434          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
5435        }
5436      }
5437      if (leftEnd.bottom < rightStart.top)
5438        add(leftSide, leftEnd.bottom, null, rightStart.top);
5439    }
5440
5441    output.appendChild(fragment);
5442  }
5443
5444  // Cursor-blinking
5445  function restartBlink(cm) {
5446    if (!cm.state.focused) return;
5447    var display = cm.display;
5448    clearInterval(display.blinker);
5449    var on = true;
5450    display.cursorDiv.style.visibility = "";
5451    if (cm.options.cursorBlinkRate > 0)
5452      display.blinker = setInterval(function() {
5453        display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
5454      }, cm.options.cursorBlinkRate);
5455    else if (cm.options.cursorBlinkRate < 0)
5456      display.cursorDiv.style.visibility = "hidden";
5457  }
5458
5459  // HIGHLIGHT WORKER
5460
5461  function startWorker(cm, time) {
5462    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
5463      cm.state.highlight.set(time, bind(highlightWorker, cm));
5464  }
5465
5466  function highlightWorker(cm) {
5467    var doc = cm.doc;
5468    if (doc.frontier < doc.first) doc.frontier = doc.first;
5469    if (doc.frontier >= cm.display.viewTo) return;
5470    var end = +new Date + cm.options.workTime;
5471    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
5472    var changedLines = [];
5473
5474    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
5475      if (doc.frontier >= cm.display.viewFrom) { // Visible
5476        var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;
5477        var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);
5478        line.styles = highlighted.styles;
5479        var oldCls = line.styleClasses, newCls = highlighted.classes;
5480        if (newCls) line.styleClasses = newCls;
5481        else if (oldCls) line.styleClasses = null;
5482        var ischange = !oldStyles || oldStyles.length != line.styles.length ||
5483          oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
5484        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
5485        if (ischange) changedLines.push(doc.frontier);
5486        line.stateAfter = tooLong ? state : copyState(doc.mode, state);
5487      } else {
5488        if (line.text.length <= cm.options.maxHighlightLength)
5489          processLine(cm, line.text, state);
5490        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
5491      }
5492      ++doc.frontier;
5493      if (+new Date > end) {
5494        startWorker(cm, cm.options.workDelay);
5495        return true;
5496      }
5497    });
5498    if (changedLines.length) runInOp(cm, function() {
5499      for (var i = 0; i < changedLines.length; i++)
5500        regLineChange(cm, changedLines[i], "text");
5501    });
5502  }
5503
5504  // Finds the line to start with when starting a parse. Tries to
5505  // find a line with a stateAfter, so that it can start with a
5506  // valid state. If that fails, it returns the line with the
5507  // smallest indentation, which tends to need the least context to
5508  // parse correctly.
5509  function findStartLine(cm, n, precise) {
5510    var minindent, minline, doc = cm.doc;
5511    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
5512    for (var search = n; search > lim; --search) {
5513      if (search <= doc.first) return doc.first;
5514      var line = getLine(doc, search - 1);
5515      if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
5516      var indented = countColumn(line.text, null, cm.options.tabSize);
5517      if (minline == null || minindent > indented) {
5518        minline = search - 1;
5519        minindent = indented;
5520      }
5521    }
5522    return minline;
5523  }
5524
5525  function getStateBefore(cm, n, precise) {
5526    var doc = cm.doc, display = cm.display;
5527    if (!doc.mode.startState) return true;
5528    var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
5529    if (!state) state = startState(doc.mode);
5530    else state = copyState(doc.mode, state);
5531    doc.iter(pos, n, function(line) {
5532      processLine(cm, line.text, state);
5533      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
5534      line.stateAfter = save ? copyState(doc.mode, state) : null;
5535      ++pos;
5536    });
5537    if (precise) doc.frontier = pos;
5538    return state;
5539  }
5540
5541  // POSITION MEASUREMENT
5542
5543  function paddingTop(display) {return display.lineSpace.offsetTop;}
5544  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
5545  function paddingH(display) {
5546    if (display.cachedPaddingH) return display.cachedPaddingH;
5547    var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
5548    var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
5549    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
5550    if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
5551    return data;
5552  }
5553
5554  function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
5555  function displayWidth(cm) {
5556    return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
5557  }
5558  function displayHeight(cm) {
5559    return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
5560  }
5561
5562  // Ensure the lineView.wrapping.heights array is populated. This is
5563  // an array of bottom offsets for the lines that make up a drawn
5564  // line. When lineWrapping is on, there might be more than one
5565  // height.
5566  function ensureLineHeights(cm, lineView, rect) {
5567    var wrapping = cm.options.lineWrapping;
5568    var curWidth = wrapping && displayWidth(cm);
5569    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
5570      var heights = lineView.measure.heights = [];
5571      if (wrapping) {
5572        lineView.measure.width = curWidth;
5573        var rects = lineView.text.firstChild.getClientRects();
5574        for (var i = 0; i < rects.length - 1; i++) {
5575          var cur = rects[i], next = rects[i + 1];
5576          if (Math.abs(cur.bottom - next.bottom) > 2)
5577            heights.push((cur.bottom + next.top) / 2 - rect.top);
5578        }
5579      }
5580      heights.push(rect.bottom - rect.top);
5581    }
5582  }
5583
5584  // Find a line map (mapping character offsets to text nodes) and a
5585  // measurement cache for the given line number. (A line view might
5586  // contain multiple lines when collapsed ranges are present.)
5587  function mapFromLineView(lineView, line, lineN) {
5588    if (lineView.line == line)
5589      return {map: lineView.measure.map, cache: lineView.measure.cache};
5590    for (var i = 0; i < lineView.rest.length; i++)
5591      if (lineView.rest[i] == line)
5592        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
5593    for (var i = 0; i < lineView.rest.length; i++)
5594      if (lineNo(lineView.rest[i]) > lineN)
5595        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
5596  }
5597
5598  // Render a line into the hidden node display.externalMeasured. Used
5599  // when measurement is needed for a line that's not in the viewport.
5600  function updateExternalMeasurement(cm, line) {
5601    line = visualLine(line);
5602    var lineN = lineNo(line);
5603    var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
5604    view.lineN = lineN;
5605    var built = view.built = buildLineContent(cm, view);
5606    view.text = built.pre;
5607    removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
5608    return view;
5609  }
5610
5611  // Get a {top, bottom, left, right} box (in line-local coordinates)
5612  // for a given character.
5613  function measureChar(cm, line, ch, bias) {
5614    return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
5615  }
5616
5617  // Find a line view that corresponds to the given line number.
5618  function findViewForLine(cm, lineN) {
5619    if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
5620      return cm.display.view[findViewIndex(cm, lineN)];
5621    var ext = cm.display.externalMeasured;
5622    if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
5623      return ext;
5624  }
5625
5626  // Measurement can be split in two steps, the set-up work that
5627  // applies to the whole line, and the measurement of the actual
5628  // character. Functions like coordsChar, that need to do a lot of
5629  // measurements in a row, can thus ensure that the set-up work is
5630  // only done once.
5631  function prepareMeasureForLine(cm, line) {
5632    var lineN = lineNo(line);
5633    var view = findViewForLine(cm, lineN);
5634    if (view && !view.text) {
5635      view = null;
5636    } else if (view && view.changes) {
5637      updateLineForChanges(cm, view, lineN, getDimensions(cm));
5638      cm.curOp.forceUpdate = true;
5639    }
5640    if (!view)
5641      view = updateExternalMeasurement(cm, line);
5642
5643    var info = mapFromLineView(view, line, lineN);
5644    return {
5645      line: line, view: view, rect: null,
5646      map: info.map, cache: info.cache, before: info.before,
5647      hasHeights: false
5648    };
5649  }
5650
5651  // Given a prepared measurement object, measures the position of an
5652  // actual character (or fetches it from the cache).
5653  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
5654    if (prepared.before) ch = -1;
5655    var key = ch + (bias || ""), found;
5656    if (prepared.cache.hasOwnProperty(key)) {
5657      found = prepared.cache[key];
5658    } else {
5659      if (!prepared.rect)
5660        prepared.rect = prepared.view.text.getBoundingClientRect();
5661      if (!prepared.hasHeights) {
5662        ensureLineHeights(cm, prepared.view, prepared.rect);
5663        prepared.hasHeights = true;
5664      }
5665      found = measureCharInner(cm, prepared, ch, bias);
5666      if (!found.bogus) prepared.cache[key] = found;
5667    }
5668    return {left: found.left, right: found.right,
5669            top: varHeight ? found.rtop : found.top,
5670            bottom: varHeight ? found.rbottom : found.bottom};
5671  }
5672
5673  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
5674
5675  function nodeAndOffsetInLineMap(map, ch, bias) {
5676    var node, start, end, collapse;
5677    // First, search the line map for the text node corresponding to,
5678    // or closest to, the target character.
5679    for (var i = 0; i < map.length; i += 3) {
5680      var mStart = map[i], mEnd = map[i + 1];
5681      if (ch < mStart) {
5682        start = 0; end = 1;
5683        collapse = "left";
5684      } else if (ch < mEnd) {
5685        start = ch - mStart;
5686        end = start + 1;
5687      } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
5688        end = mEnd - mStart;
5689        start = end - 1;
5690        if (ch >= mEnd) collapse = "right";
5691      }
5692      if (start != null) {
5693        node = map[i + 2];
5694        if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
5695          collapse = bias;
5696        if (bias == "left" && start == 0)
5697          while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
5698            node = map[(i -= 3) + 2];
5699            collapse = "left";
5700          }
5701        if (bias == "right" && start == mEnd - mStart)
5702          while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
5703            node = map[(i += 3) + 2];
5704            collapse = "right";
5705          }
5706        break;
5707      }
5708    }
5709    return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
5710  }
5711
5712  function 
5712measureCharInner(cm, prepared, ch, bias) {
5713    var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
5714    var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
5715
5716    var rect;
5717    if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
5718      for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
5719        while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
5720        while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
5721        if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
5722          rect = node.parentNode.getBoundingClientRect();
5723        } else if (ie && cm.options.lineWrapping) {
5724          var rects = range(node, start, end).getClientRects();
5725          if (rects.length)
5726            rect = rects[bias == "right" ? rects.length - 1 : 0];
5727          else
5728            rect = nullRect;
5729        } else {
5730          rect = range(node, start, end).getBoundingClientRect() || nullRect;
5731        }
vendor: 9,620 bytes, lines 5731-5957
5731
5732        if (rect.left || rect.right || start == 0) break;
5733        end = start;
5734        start = start - 1;
5735        collapse = "right";
5736      }
5737      if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
5738    } else { // If it is a widget, simply get the box for the whole widget.
5739      if (start > 0) collapse = bias = "right";
5740      var rects;
5741      if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
5742        rect = rects[bias == "right" ? rects.length - 1 : 0];
5743      else
5744        rect = node.getBoundingClientRect();
5745    }
5746    if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
5747      var rSpan = node.parentNode.getClientRects()[0];
5748      if (rSpan)
5749        rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
5750      else
5751        rect = nullRect;
5752    }
5753
5754    var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
5755    var mid = (rtop + rbot) / 2;
5756    var heights = prepared.view.measure.heights;
5757    for (var i = 0; i < heights.length - 1; i++)
5758      if (mid < heights[i]) break;
5759    var top = i ? heights[i - 1] : 0, bot = heights[i];
5760    var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
5761                  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
5762                  top: top, bottom: bot};
5763    if (!rect.left && !rect.right) result.bogus = true;
5764    if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
5765
5766    return result;
5767  }
5768
5769  // Work around problem with bounding client rects on ranges being
5770  // returned incorrectly when zoomed on IE10 and below.
5771  function maybeUpdateRectForZooming(measure, rect) {
5772    if (!window.screen || screen.logicalXDPI == null ||
5773        screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
5774      return rect;
5775    var scaleX = screen.logicalXDPI / screen.deviceXDPI;
5776    var scaleY = screen.logicalYDPI / screen.deviceYDPI;
5777    return {left: rect.left * scaleX, right: rect.right * scaleX,
5778            top: rect.top * scaleY, bottom: rect.bottom * scaleY};
5779  }
5780
5781  function clearLineMeasurementCacheFor(lineView) {
5782    if (lineView.measure) {
5783      lineView.measure.cache = {};
5784      lineView.measure.heights = null;
5785      if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
5786        lineView.measure.caches[i] = {};
5787    }
5788  }
5789
5790  function clearLineMeasurementCache(cm) {
5791    cm.display.externalMeasure = null;
5792    removeChildren(cm.display.lineMeasure);
5793    for (var i = 0; i < cm.display.view.length; i++)
5794      clearLineMeasurementCacheFor(cm.display.view[i]);
5795  }
5796
5797  function clearCaches(cm) {
5798    clearLineMeasurementCache(cm);
5799    cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
5800    if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
5801    cm.display.lineNumChars = null;
5802  }
5803
5804  function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
5805  function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
5806
5807  // Converts a {top, bottom, left, right} box from line-local
5808  // coordinates into another coordinate system. Context may be one of
5809  // "line", "div" (display.lineDiv), "local"/null (editor), "window",
5810  // or "page".
5811  function intoCoordSystem(cm, lineObj, rect, context) {
5812    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
5813      var size = widgetHeight(lineObj.widgets[i]);
5814      rect.top += size; rect.bottom += size;
5815    }
5816    if (context == "line") return rect;
5817    if (!context) context = "local";
5818    var yOff = heightAtLine(lineObj);
5819    if (context == "local") yOff += paddingTop(cm.display);
5820    else yOff -= cm.display.viewOffset;
5821    if (context == "page" || context == "window") {
5822      var lOff = cm.display.lineSpace.getBoundingClientRect();
5823      yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
5824      var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
5825      rect.left += xOff; rect.right += xOff;
5826    }
5827    rect.top += yOff; rect.bottom += yOff;
5828    return rect;
5829  }
5830
5831  // Coverts a box from "div" coords to another coordinate system.
5832  // Context may be "window", "page", "div", or "local"/null.
5833  function fromCoordSystem(cm, coords, context) {
5834    if (context == "div") return coords;
5835    var left = coords.left, top = coords.top;
5836    // First move into "page" coordinate system
5837    if (context == "page") {
5838      left -= pageScrollX();
5839      top -= pageScrollY();
5840    } else if (context == "local" || !context) {
5841      var localBox = cm.display.sizer.getBoundingClientRect();
5842      left += localBox.left;
5843      top += localBox.top;
5844    }
5845
5846    var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
5847    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
5848  }
5849
5850  function charCoords(cm, pos, context, lineObj, bias) {
5851    if (!lineObj) lineObj = getLine(cm.doc, pos.line);
5852    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
5853  }
5854
5855  // Returns a box for a given cursor position, which may have an
5856  // 'other' property containing the position of the secondary cursor
5857  // on a bidi boundary.
5858  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
5859    lineObj = lineObj || getLine(cm.doc, pos.line);
5860    if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
5861    function get(ch, right) {
5862      var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
5863      if (right) m.left = m.right; else m.right = m.left;
5864      return intoCoordSystem(cm, lineObj, m, context);
5865    }
5866    function getBidi(ch, partPos) {
5867      var part = order[partPos], right = part.level % 2;
5868      if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
5869        part = order[--partPos];
5870        ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
5871        right = true;
5872      } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
5873        part = order[++partPos];
5874        ch = bidiLeft(part) - part.level % 2;
5875        right = false;
5876      }
5877      if (right && ch == part.to && ch > part.from) return get(ch - 1);
5878      return get(ch, right);
5879    }
5880    var order = getOrder(lineObj), ch = pos.ch;
5881    if (!order) return get(ch);
5882    var partPos = getBidiPartAt(order, ch);
5883    var val = getBidi(ch, partPos);
5884    if (bidiOther != null) val.other = getBidi(ch, bidiOther);
5885    return val;
5886  }
5887
5888  // Used to cheaply estimate the coordinates for a position. Used for
5889  // intermediate scroll updates.
5890  function estimateCoords(cm, pos) {
5891    var left = 0, pos = clipPos(cm.doc, pos);
5892    if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
5893    var lineObj = getLine(cm.doc, pos.line);
5894    var top = heightAtLine(lineObj) + paddingTop(cm.display);
5895    return {left: left, right: left, top: top, bottom: top + lineObj.height};
5896  }
5897
5898  // Positions returned by coordsChar contain some extra information.
5899  // xRel is the relative x position of the input coordinates compared
5900  // to the found position (so xRel > 0 means the coordinates are to
5901  // the right of the character position, for example). When outside
5902  // is true, that means the coordinates lie outside the line's
5903  // vertical range.
5904  function PosWithInfo(line, ch, outside, xRel) {
5905    var pos = Pos(line, ch);
5906    pos.xRel = xRel;
5907    if (outside) pos.outside = true;
5908    return pos;
5909  }
5910
5911  // Compute the character position closest to the given coordinates.
5912  // Input must be lineSpace-local ("div" coordinate system).
5913  function coordsChar(cm, x, y) {
5914    var doc = cm.doc;
5915    y += cm.display.viewOffset;
5916    if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
5917    var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
5918    if (lineN > last)
5919      return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
5920    if (x < 0) x = 0;
5921
5922    var lineObj = getLine(doc, lineN);
5923    for (;;) {
5924      var found = coordsCharInner(cm, lineObj, lineN, x, y);
5925      var merged = collapsedSpanAtEnd(lineObj);
5926      var mergedPos = merged && merged.find(0, true);
5927      if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
5928        lineN = lineNo(lineObj = mergedPos.to.line);
5929      else
5930        return found;
5931    }
5932  }
5933
5934  function coordsCharInner(cm, lineObj, lineNo, x, y) {
5935    var innerOff = y - heightAtLine(lineObj);
5936    var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
5937    var preparedMeasure = prepareMeasureForLine(cm, lineObj);
5938
5939    function getX(ch) {
5940      var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
5941      wrongLine = true;
5942      if (innerOff > sp.bottom) return sp.left - adjust;
5943      else if (innerOff < sp.top) return sp.left + adjust;
5944      else wrongLine = false;
5945      return sp.left;
5946    }
5947
5948    var bidi = getOrder(lineObj), dist = lineObj.text.length;
5949    var from = lineLeft(lineObj), to = lineRight(lineObj);
5950    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
5951
5952    if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
5953    // Do a binary search between these bounds.
5954    for (;;) {
5955      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
5956        var ch = x < fromX || x - fromX <= toX - x ? from : to;
5957        var 
vendor: 45,424 bytes, lines 5957-7114
5957xDiff = x - (ch == from ? fromX : toX);
5958        while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
5959        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
5960                              xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
5961        return pos;
5962      }
5963      var step = Math.ceil(dist / 2), middle = from + step;
5964      if (bidi) {
5965        middle = from;
5966        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
5967      }
5968      var middleX = getX(middle);
5969      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
5970      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
5971    }
5972  }
5973
5974  var measureText;
5975  // Compute the default text height.
5976  function textHeight(display) {
5977    if (display.cachedTextHeight != null) return display.cachedTextHeight;
5978    if (measureText == null) {
5979      measureText = elt("pre");
5980      // Measure a bunch of lines, for browsers that compute
5981      // fractional heights.
5982      for (var i = 0; i < 49; ++i) {
5983        measureText.appendChild(document.createTextNode("x"));
5984        measureText.appendChild(elt("br"));
5985      }
5986      measureText.appendChild(document.createTextNode("x"));
5987    }
5988    removeChildrenAndAdd(display.measure, measureText);
5989    var height = measureText.offsetHeight / 50;
5990    if (height > 3) display.cachedTextHeight = height;
5991    removeChildren(display.measure);
5992    return height || 1;
5993  }
5994
5995  // Compute the default character width.
5996  function charWidth(display) {
5997    if (display.cachedCharWidth != null) return display.cachedCharWidth;
5998    var anchor = elt("span", "xxxxxxxxxx");
5999    var pre = elt("pre", [anchor]);
6000    removeChildrenAndAdd(display.measure, pre);
6001    var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
6002    if (width > 2) display.cachedCharWidth = width;
6003    return width || 10;
6004  }
6005
6006  // OPERATIONS
6007
6008  // Operations are used to wrap a series of changes to the editor
6009  // state in such a way that each change won't have to update the
6010  // cursor and display (which would be awkward, slow, and
6011  // error-prone). Instead, display updates are batched and then all
6012  // combined and executed at once.
6013
6014  var operationGroup = null;
6015
6016  var nextOpId = 0;
6017  // Start a new operation.
6018  function startOperation(cm) {
6019    cm.curOp = {
6020      cm: cm,
6021      viewChanged: false,      // Flag that indicates that lines might need to be redrawn
6022      startHeight: cm.doc.height, // Used to detect need to update scrollbar
6023      forceUpdate: false,      // Used to force a redraw
6024      updateInput: null,       // Whether to reset the input textarea
6025      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
6026      changeObjs: null,        // Accumulated changes, for firing change events
6027      cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
6028      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
6029      selectionChanged: false, // Whether the selection needs to be redrawn
6030      updateMaxLine: false,    // Set when the widest line needs to be determined anew
6031      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
6032      scrollToPos: null,       // Used to scroll to a specific position
6033      focus: false,
6034      id: ++nextOpId           // Unique ID
6035    };
6036    if (operationGroup) {
6037      operationGroup.ops.push(cm.curOp);
6038    } else {
6039      cm.curOp.ownsGroup = operationGroup = {
6040        ops: [cm.curOp],
6041        delayedCallbacks: []
6042      };
6043    }
6044  }
6045
6046  function fireCallbacksForOps(group) {
6047    // Calls delayed callbacks and cursorActivity handlers until no
6048    // new ones appear
6049    var callbacks = group.delayedCallbacks, i = 0;
6050    do {
6051      for (; i < callbacks.length; i++)
6052        callbacks[i].call(null);
6053      for (var j = 0; j < group.ops.length; j++) {
6054        var op = group.ops[j];
6055        if (op.cursorActivityHandlers)
6056          while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
6057            op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);
6058      }
6059    } while (i < callbacks.length);
6060  }
6061
6062  // Finish an operation, updating the display and signalling delayed events
6063  function endOperation(cm) {
6064    var op = cm.curOp, group = op.ownsGroup;
6065    if (!group) return;
6066
6067    try { fireCallbacksForOps(group); }
6068    finally {
6069      operationGroup = null;
6070      for (var i = 0; i < group.ops.length; i++)
6071        group.ops[i].cm.curOp = null;
6072      endOperations(group);
6073    }
6074  }
6075
6076  // The DOM updates done when an operation finishes are batched so
6077  // that the minimum number of relayouts are required.
6078  function endOperations(group) {
6079    var ops = group.ops;
6080    for (var i = 0; i < ops.length; i++) // Read DOM
6081      endOperation_R1(ops[i]);
6082    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
6083      endOperation_W1(ops[i]);
6084    for (var i = 0; i < ops.length; i++) // Read DOM
6085      endOperation_R2(ops[i]);
6086    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
6087      endOperation_W2(ops[i]);
6088    for (var i = 0; i < ops.length; i++) // Read DOM
6089      endOperation_finish(ops[i]);
6090  }
6091
6092  function endOperation_R1(op) {
6093    var cm = op.cm, display = cm.display;
6094    maybeClipScrollbars(cm);
6095    if (op.updateMaxLine) findMaxLine(cm);
6096
6097    op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
6098      op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
6099                         op.scrollToPos.to.line >= display.viewTo) ||
6100      display.maxLineChanged && cm.options.lineWrapping;
6101    op.update = op.mustUpdate &&
6102      new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
6103  }
6104
6105  function endOperation_W1(op) {
6106    op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
6107  }
6108
6109  function endOperation_R2(op) {
6110    var cm = op.cm, display = cm.display;
6111    if (op.updatedDisplay) updateHeightsInViewport(cm);
6112
6113    op.barMeasure = measureForScrollbars(cm);
6114
6115    // If the max line changed since it was last measured, measure it,
6116    // and ensure the document's width matches it.
6117    // updateDisplay_W2 will use these properties to do the actual resizing
6118    if (display.maxLineChanged && !cm.options.lineWrapping) {
6119      op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
6120      cm.display.sizerWidth = op.adjustWidthTo;
6121      op.barMeasure.scrollWidth =
6122        Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
6123      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
6124    }
6125
6126    if (op.updatedDisplay || op.selectionChanged)
6127      op.preparedSelection = display.input.prepareSelection();
6128  }
6129
6130  function endOperation_W2(op) {
6131    var cm = op.cm;
6132
6133    if (op.adjustWidthTo != null) {
6134      cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
6135      if (op.maxScrollLeft < cm.doc.scrollLeft)
6136        setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
6137      cm.display.maxLineChanged = false;
6138    }
6139
6140    if (op.preparedSelection)
6141      cm.display.input.showSelection(op.preparedSelection);
6142    if (op.updatedDisplay)
6143      setDocumentHeight(cm, op.barMeasure);
6144    if (op.updatedDisplay || op.startHeight != cm.doc.height)
6145      updateScrollbars(cm, op.barMeasure);
6146
6147    if (op.selectionChanged) restartBlink(cm);
6148
6149    if (cm.state.focused && op.updateInput)
6150      cm.display.input.reset(op.typing);
6151    if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
6152  }
6153
6154  function endOperation_finish(op) {
6155    var cm = op.cm, display = cm.display, doc = cm.doc;
6156
6157    if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
6158
6159    // Abort mouse wheel delta measurement, when scrolling explicitly
6160    if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
6161      display.wheelStartX = display.wheelStartY = null;
6162
6163    // Propagate the scroll position to the actual DOM scroller
6164    if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
6165      doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
6166      display.scrollbars.setScrollTop(doc.scrollTop);
6167      display.scroller.scrollTop = doc.scrollTop;
6168    }
6169    if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
6170      doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
6171      display.scrollbars.setScrollLeft(doc.scrollLeft);
6172      display.scroller.scrollLeft = doc.scrollLeft;
6173      alignHorizontally(cm);
6174    }
6175    // If we need to scroll a specific position into view, do so.
6176    if (op.scrollToPos) {
6177      var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
6178                                     clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
6179      if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
6180    }
6181
6182    // Fire events for markers that are hidden/unidden by editing or
6183    // undoing
6184    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
6185    if (hidden) for (var i = 0; i < hidden.length; ++i)
6186      if (!hidden[i].lines.length) signal(hidden[i], "hide");
6187    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
6188      if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
6189
6190    if (display.wrapper.offsetHeight)
6191      doc.scrollTop = cm.display.scroller.scrollTop;
6192
6193    // Fire change events, and delayed event handlers
6194    if (op.changeObjs)
6195      signal(cm, "changes", cm, op.changeObjs);
6196    if (op.update)
6197      op.update.finish();
6198  }
6199
6200  // Run the given function in an operation
6201  function runInOp(cm, f) {
6202    if (cm.curOp) return f();
6203    startOperation(cm);
6204    try { return f(); }
6205    finally { endOperation(cm); }
6206  }
6207  // Wraps a function in an operation. Returns the wrapped function.
6208  function operation(cm, f) {
6209    return function() {
6210      if (cm.curOp) return f.apply(cm, arguments);
6211      startOperation(cm);
6212      try { return f.apply(cm, arguments); }
6213      finally { endOperation(cm); }
6214    };
6215  }
6216  // Used to add methods to editor and doc instances, wrapping them in
6217  // operations.
6218  function methodOp(f) {
6219    return function() {
6220      if (this.curOp) return f.apply(this, arguments);
6221      startOperation(this);
6222      try { return f.apply(this, arguments); }
6223      finally { endOperation(this); }
6224    };
6225  }
6226  function docMethodOp(f) {
6227    return function() {
6228      var cm = this.cm;
6229      if (!cm || cm.curOp) return f.apply(this, arguments);
6230      startOperation(cm);
6231      try { return f.apply(this, arguments); }
6232      finally { endOperation(cm); }
6233    };
6234  }
6235
6236  // VIEW TRACKING
6237
6238  // These objects are used to represent the visible (currently drawn)
6239  // part of the document. A LineView may correspond to multiple
6240  // logical lines, if those are connected by collapsed ranges.
6241  function LineView(doc, line, lineN) {
6242    // The starting line
6243    this.line = line;
6244    // Continuing lines, if any
6245    this.rest = visualLineContinued(line);
6246    // Number of logical lines in this visual line
6247    this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
6248    this.node = this.text = null;
6249    this.hidden = lineIsHidden(doc, line);
6250  }
6251
6252  // Create a range of LineView objects for the given lines.
6253  function buildViewArray(cm, from, to) {
6254    var array = [], nextPos;
6255    for (var pos = from; pos < to; pos = nextPos) {
6256      var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
6257      nextPos = pos + view.size;
6258      array.push(view);
6259    }
6260    return array;
6261  }
6262
6263  // Updates the display.view data structure for a given change to the
6264  // document. From and to are in pre-change coordinates. Lendiff is
6265  // the amount of lines added or subtracted by the change. This is
6266  // used for changes that span multiple lines, or change the way
6267  // lines are divided into visual lines. regLineChange (below)
6268  // registers single-line changes.
6269  function regChange(cm, from, to, lendiff) {
6270    if (from == null) from = cm.doc.first;
6271    if (to == null) to = cm.doc.first + cm.doc.size;
6272    if (!lendiff) lendiff = 0;
6273
6274    var display = cm.display;
6275    if (lendiff && to < display.viewTo &&
6276        (display.updateLineNumbers == null || display.updateLineNumbers > from))
6277      display.updateLineNumbers = from;
6278
6279    cm.curOp.viewChanged = true;
6280
6281    if (from >= display.viewTo) { // Change after
6282      if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
6283        resetView(cm);
6284    } else if (to <= display.viewFrom) { // Change before
6285      if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
6286        resetView(cm);
6287      } else {
6288        display.viewFrom += lendiff;
6289        display.viewTo += lendiff;
6290      }
6291    } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
6292      resetView(cm);
6293    } else if (from <= display.viewFrom) { // Top overlap
6294      var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
6295      if (cut) {
6296        display.view = display.view.slice(cut.index);
6297        display.viewFrom = cut.lineN;
6298        display.viewTo += lendiff;
6299      } else {
6300        resetView(cm);
6301      }
6302    } else if (to >= display.viewTo) { // Bottom overlap
6303      var cut = viewCuttingPoint(cm, from, from, -1);
6304      if (cut) {
6305        display.view = display.view.slice(0, cut.index);
6306        display.viewTo = cut.lineN;
6307      } else {
6308        resetView(cm);
6309      }
6310    } else { // Gap in the middle
6311      var cutTop = viewCuttingPoint(cm, from, from, -1);
6312      var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
6313      if (cutTop && cutBot) {
6314        display.view = display.view.slice(0, cutTop.index)
6315          .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
6316          .concat(display.view.slice(cutBot.index));
6317        display.viewTo += lendiff;
6318      } else {
6319        resetView(cm);
6320      }
6321    }
6322
6323    var ext = display.externalMeasured;
6324    if (ext) {
6325      if (to < ext.lineN)
6326        ext.lineN += lendiff;
6327      else if (from < ext.lineN + ext.size)
6328        display.externalMeasured = null;
6329    }
6330  }
6331
6332  // Register a change to a single line. Type must be one of "text",
6333  // "gutter", "class", "widget"
6334  function regLineChange(cm, line, type) {
6335    cm.curOp.viewChanged = true;
6336    var display = cm.display, ext = cm.display.externalMeasured;
6337    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
6338      display.externalMeasured = null;
6339
6340    if (line < display.viewFrom || line >= display.viewTo) return;
6341    var lineView = display.view[findViewIndex(cm, line)];
6342    if (lineView.node == null) return;
6343    var arr = lineView.changes || (lineView.changes = []);
6344    if (indexOf(arr, type) == -1) arr.push(type);
6345  }
6346
6347  // Clear the view.
6348  function resetView(cm) {
6349    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
6350    cm.display.view = [];
6351    cm.display.viewOffset = 0;
6352  }
6353
6354  // Find the view element corresponding to a given line. Return null
6355  // when the line isn't visible.
6356  function findViewIndex(cm, n) {
6357    if (n >= cm.display.viewTo) return null;
6358    n -= cm.display.viewFrom;
6359    if (n < 0) return null;
6360    var view = cm.display.view;
6361    for (var i = 0; i < view.length; i++) {
6362      n -= view[i].size;
6363      if (n < 0) return i;
6364    }
6365  }
6366
6367  function viewCuttingPoint(cm, oldN, newN, dir) {
6368    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
6369    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
6370      return {index: index, lineN: newN};
6371    for (var i = 0, n = cm.display.viewFrom; i < index; i++)
6372      n += view[i].size;
6373    if (n != oldN) {
6374      if (dir > 0) {
6375        if (index == view.length - 1) return null;
6376        diff = (n + view[index].size) - oldN;
6377        index++;
6378      } else {
6379        diff = n - oldN;
6380      }
6381      oldN += diff; newN += diff;
6382    }
6383    while (visualLineNo(cm.doc, newN) != newN) {
6384      if (index == (dir < 0 ? 0 : view.length - 1)) return null;
6385      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
6386      index += dir;
6387    }
6388    return {index: index, lineN: newN};
6389  }
6390
6391  // Force the view to cover a given range, adding empty view element
6392  // or clipping off existing ones as needed.
6393  function adjustView(cm, from, to) {
6394    var display = cm.display, view = display.view;
6395    if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
6396      display.view = buildViewArray(cm, from, to);
6397      display.viewFrom = from;
6398    } else {
6399      if (display.viewFrom > from)
6400        display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
6401      else if (display.viewFrom < from)
6402        display.view = display.view.slice(findViewIndex(cm, from));
6403      display.viewFrom = from;
6404      if (display.viewTo < to)
6405        display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
6406      else if (display.viewTo > to)
6407        display.view = display.view.slice(0, findViewIndex(cm, to));
6408    }
6409    display.viewTo = to;
6410  }
6411
6412  // Count the number of lines in the view whose DOM representation is
6413  // out of date (or nonexistent).
6414  function countDirtyView(cm) {
6415    var view = cm.display.view, dirty = 0;
6416    for (var i = 0; i < view.length; i++) {
6417      var lineView = view[i];
6418      if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
6419    }
6420    return dirty;
6421  }
6422
6423  // EVENT HANDLERS
6424
6425  // Attach the necessary event handlers when initializing the editor
6426  function registerEventHandlers(cm) {
6427    var d = cm.display;
6428    on(d.scroller, "mousedown", operation(cm, onMouseDown));
6429    // Older IE's will not fire a second mousedown for a double click
6430    if (ie && ie_version < 11)
6431      on(d.scroller, "dblclick", operation(cm, function(e) {
6432        if (signalDOMEvent(cm, e)) return;
6433        var pos = posFromMouse(cm, e);
6434        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
6435        e_preventDefault(e);
6436        var word = cm.findWordAt(pos);
6437        extendSelection(cm.doc, word.anchor, word.head);
6438      }));
6439    else
6440      on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
6441    // Some browsers fire contextmenu *after* opening the menu, at
6442    // which point we can't mess with it anymore. Context menu is
6443    // handled in onMouseDown for these browsers.
6444    if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
6445
6446    // Used to suppress mouse event handling when a touch happens
6447    var touchFinished, prevTouch = {end: 0};
6448    function finishTouch() {
6449      if (d.activeTouch) {
6450        touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
6451        prevTouch = d.activeTouch;
6452        prevTouch.end = +new Date;
6453      }
6454    };
6455    function isMouseLikeTouchEvent(e) {
6456      if (e.touches.length != 1) return false;
6457      var touch = e.touches[0];
6458      return touch.radiusX <= 1 && touch.radiusY <= 1;
6459    }
6460    function farAway(touch, other) {
6461      if (other.left == null) return true;
6462      var dx = other.left - touch.left, dy = other.top - touch.top;
6463      return dx * dx + dy * dy > 20 * 20;
6464    }
6465    on(d.scroller, "touchstart", function(e) {
6466      if (!isMouseLikeTouchEvent(e)) {
6467        clearTimeout(touchFinished);
6468        var now = +new Date;
6469        d.activeTouch = {start: now, moved: false,
6470                         prev: now - prevTouch.end <= 300 ? prevTouch : null};
6471        if (e.touches.length == 1) {
6472          d.activeTouch.left = e.touches[0].pageX;
6473          d.activeTouch.top = e.touches[0].pageY;
6474        }
6475      }
6476    });
6477    on(d.scroller, "touchmove", function() {
6478      if (d.activeTouch) d.activeTouch.moved = true;
6479    });
6480    on(d.scroller, "touchend", function(e) {
6481      var touch = d.activeTouch;
6482      if (touch && !eventInWidget(d, e) && touch.left != null &&
6483          !touch.moved && new Date - touch.start < 300) {
6484        var pos = cm.coordsChar(d.activeTouch, "page"), range;
6485        if (!touch.prev || farAway(touch, touch.prev)) // Single tap
6486          range = new Range(pos, pos);
6487        else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
6488          range = cm.findWordAt(pos);
6489        else // Triple tap
6490          range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
6491        cm.setSelection(range.anchor, range.head);
6492        cm.focus();
6493        e_preventDefault(e);
6494      }
6495      finishTouch();
6496    });
6497    on(d.scroller, "touchcancel", finishTouch);
6498
6499    // Sync scrolling between fake scrollbars and real scrollable
6500    // area, ensure viewport is updated when scrolling.
6501    on(d.scroller, "scroll", function() {
6502      if (d.scroller.clientHeight) {
6503        setScrollTop(cm, d.scroller.scrollTop);
6504        setScrollLeft(cm, d.scroller.scrollLeft, true);
6505        signal(cm, "scroll", cm);
6506      }
6507    });
6508
6509    // Listen to wheel events in order to try and update the viewport on time.
6510    on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
6511    on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
6512
6513    // Prevent wrapper from ever scrolling
6514    on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
6515
6516    d.dragFunctions = {
6517      enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
6518      over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
6519      start: function(e){onDragStart(cm, e);},
6520      drop: operation(cm, onDrop),
6521      leave: function() {clearDragCursor(cm);}
6522    };
6523
6524    var inp = d.input.getField();
6525    on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
6526    on(inp, "keydown", operation(cm, onKeyDown));
6527    on(inp, "keypress", operation(cm, onKeyPress));
6528    on(inp, "focus", bind(onFocus, cm));
6529    on(inp, "blur", bind(onBlur, cm));
6530  }
6531
6532  function dragDropChanged(cm, value, old) {
6533    var wasOn = old && old != CodeMirror.Init;
6534    if (!value != !wasOn) {
6535      var funcs = cm.display.dragFunctions;
6536      var toggle = value ? on : off;
6537      toggle(cm.display.scroller, "dragstart", funcs.start);
6538      toggle(cm.display.scroller, "dragenter", funcs.enter);
6539      toggle(cm.display.scroller, "dragover", funcs.over);
6540      toggle(cm.display.scroller, "dragleave", funcs.leave);
6541      toggle(cm.display.scroller, "drop", funcs.drop);
6542    }
6543  }
6544
6545  // Called when the window resizes
6546  function onResize(cm) {
6547    var d = cm.display;
6548    if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
6549      return;
6550    // Might be a text scaling operation, clear size caches.
6551    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
6552    d.scrollbarsClipped = false;
6553    cm.setSize();
6554  }
6555
6556  // MOUSE EVENTS
6557
6558  // Return true when the given mouse event happened in a widget
6559  function eventInWidget(display, e) {
6560    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
6561      if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
6562          (n.parentNode == display.sizer && n != display.mover))
6563        return true;
6564    }
6565  }
6566
6567  // Given a mouse event, find the corresponding position. If liberal
6568  // is false, it checks whether a gutter or scrollbar was clicked,
6569  // and returns null if it was. forRect is used by rectangular
6570  // selections, and tries to estimate a character position even for
6571  // coordinates beyond the right of the text.
6572  function posFromMouse(cm, e, liberal, forRect) {
6573    var display = cm.display;
6574    if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
6575
6576    var x, y, space = display.lineSpace.getBoundingClientRect();
6577    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
6578    try { x = e.clientX - space.left; y = e.clientY - space.top; }
6579    catch (e) { return null; }
6580    var coords = coordsChar(cm, x, y), line;
6581    if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
6582      var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
6583      coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
6584    }
6585    return coords;
6586  }
6587
6588  // A mouse down can be a single click, double click, triple click,
6589  // start of selection drag, start of text drag, new cursor
6590  // (ctrl-click), rectangle drag (alt-drag), or xwin
6591  // middle-click-paste. Or it might be a click on something we should
6592  // not interfere with, such as a scrollbar or widget.
6593  function onMouseDown(e) {
6594    var cm = this, display = cm.display;
6595    if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
6596    display.shift = e.shiftKey;
6597
6598    if (eventInWidget(display, e)) {
6599      if (!webkit) {
6600        // Briefly turn off draggability, to allow widgets to do
6601        // normal dragging things.
6602        display.scroller.draggable = false;
6603        setTimeout(function(){display.scroller.draggable = true;}, 100);
6604      }
6605      return;
6606    }
6607    if (clickInGutter(cm, e)) return;
6608    var start = posFromMouse(cm, e);
6609    window.focus();
6610
6611    switch (e_button(e)) {
6612    case 1:
6613      // #3261: make sure, that we're not starting a second selection
6614      if (cm.state.selectingText)
6615        cm.state.selectingText(e);
6616      else if (start)
6617        leftButtonDown(cm, e, start);
6618      else if (e_target(e) == display.scroller)
6619        e_preventDefault(e);
6620      break;
6621    case 2:
6622      if (webkit) cm.state.lastMiddleDown = +new Date;
6623      if (start) extendSelection(cm.doc, start);
6624      setTimeout(function() {display.input.focus();}, 20);
6625      e_preventDefault(e);
6626      break;
6627    case 3:
6628      if (captureRightClick) onContextMenu(cm, e);
6629      else delayBlurEvent(cm);
6630      break;
6631    }
6632  }
6633
6634  var lastClick, lastDoubleClick;
6635  function leftButtonDown(cm, e, start) {
6636    if (ie) setTimeout(bind(ensureFocus, cm), 0);
6637    else cm.curOp.focus = activeElt();
6638
6639    var now = +new Date, type;
6640    if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
6641      type = "triple";
6642    } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
6643      type = "double";
6644      lastDoubleClick = {time: now, pos: start};
6645    } else {
6646      type = "single";
6647      lastClick = {time: now, pos: start};
6648    }
6649
6650    var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
6651    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
6652        type == "single" && (contained = sel.contains(start)) > -1 &&
6653        (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
6654        (cmp(contained.to(), start) > 0 || start.xRel < 0))
6655      leftButtonStartDrag(cm, e, start, modifier);
6656    else
6657      leftButtonSelect(cm, e, start, type, modifier);
6658  }
6659
6660  // Start a text drag. When it ends, see if any dragging actually
6661  // happen, and treat as a click if it didn't.
6662  function leftButtonStartDrag(cm, e, start, modifier) {
6663    var display = cm.display, startTime = +new Date;
6664    var dragEnd = operation(cm, function(e2) {
6665      if (webkit) display.scroller.draggable = false;
6666      cm.state.draggingText = false;
6667      off(document, "mouseup", dragEnd);
6668      off(display.scroller, "drop", dragEnd);
6669      if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
6670        e_preventDefault(e2);
6671        if (!modifier && +new Date - 200 < startTime)
6672          extendSelection(cm.doc, start);
6673        // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
6674        if (webkit || ie && ie_version == 9)
6675          setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
6676        else
6677          display.input.focus();
6678      }
6679    });
6680    // Let the drag handler handle this.
6681    if (webkit) display.scroller.draggable = true;
6682    cm.state.draggingText = dragEnd;
6683    // IE's approach to draggable
6684    if (display.scroller.dragDrop) display.scroller.dragDrop();
6685    on(document, "mouseup", dragEnd);
6686    on(display.scroller, "drop", dragEnd);
6687  }
6688
6689  // Normal selection, as opposed to text dragging.
6690  function leftButtonSelect(cm, e, start, type, addNew) {
6691    var display = cm.display, doc = cm.doc;
6692    e_preventDefault(e);
6693
6694    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
6695    if (addNew && !e.shiftKey) {
6696      ourIndex = doc.sel.contains(start);
6697      if (ourIndex > -1)
6698        ourRange = ranges[ourIndex];
6699      else
6700        ourRange = new Range(start, start);
6701    } else {
6702      ourRange = doc.sel.primary();
6703      ourIndex = doc.sel.primIndex;
6704    }
6705
6706    if (e.altKey) {
6707      type = "rect";
6708      if (!addNew) ourRange = new Range(start, start);
6709      start = posFromMouse(cm, e, true, true);
6710      ourIndex = -1;
6711    } else if (type == "double") {
6712      var word = cm.findWordAt(start);
6713      if (cm.display.shift || doc.extend)
6714        ourRange = extendRange(doc, ourRange, word.anchor, word.head);
6715      else
6716        ourRange = word;
6717    } else if (type == "triple") {
6718      var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
6719      if (cm.display.shift || doc.extend)
6720        ourRange = extendRange(doc, ourRange, line.anchor, line.head);
6721      else
6722        ourRange = line;
6723    } else {
6724      ourRange = extendRange(doc, ourRange, start);
6725    }
6726
6727    if (!addNew) {
6728      ourIndex = 0;
6729      setSelection(doc, new Selection([ourRange], 0), sel_mouse);
6730      startSel = doc.sel;
6731    } else if (ourIndex == -1) {
6732      ourIndex = ranges.length;
6733      setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
6734                   {scroll: false, origin: "*mouse"});
6735    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
6736      setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
6737                   {scroll: false, origin: "*mouse"});
6738      startSel = doc.sel;
6739    } else {
6740      replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
6741    }
6742
6743    var lastPos = start;
6744    function extendTo(pos) {
6745      if (cmp(lastPos, pos) == 0) return;
6746      lastPos = pos;
6747
6748      if (type == "rect") {
6749        var ranges = [], tabSize = cm.options.tabSize;
6750        var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
6751        var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
6752        var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
6753        for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
6754             line <= end; line++) {
6755          var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
6756          if (left == right)
6757            ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
6758          else if (text.length > leftPos)
6759            ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
6760        }
6761        if (!ranges.length) ranges.push(new Range(start, start));
6762        setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
6763                     {origin: "*mouse", scroll: false});
6764        cm.scrollIntoView(pos);
6765      } else {
6766        var oldRange = ourRange;
6767        var anchor = oldRange.anchor, head = pos;
6768        if (type != "single") {
6769          if (type == "double")
6770            var range = cm.findWordAt(pos);
6771          else
6772            var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
6773          if (cmp(range.anchor, anchor) > 0) {
6774            head = range.head;
6775            anchor = minPos(oldRange.from(), range.anchor);
6776          } else {
6777            head = range.anchor;
6778            anchor = maxPos(oldRange.to(), range.head);
6779          }
6780        }
6781        var ranges = startSel.ranges.slice(0);
6782        ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
6783        setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
6784      }
6785    }
6786
6787    var editorSize = display.wrapper.getBoundingClientRect();
6788    // Used to ensure timeout re-tries don't fire when another extend
6789    // happened in the meantime (clearTimeout isn't reliable -- at
6790    // least on Chrome, the timeouts still happen even when cleared,
6791    // if the clear happens after their scheduled firing time).
6792    var counter = 0;
6793
6794    function extend(e) {
6795      var curCount = ++counter;
6796      var cur = posFromMouse(cm, e, true, type == "rect");
6797      if (!cur) return;
6798      if (cmp(cur, lastPos) != 0) {
6799        cm.curOp.focus = activeElt();
6800        extendTo(cur);
6801        var visible = visibleLines(display, doc);
6802        if (cur.line >= visible.to || cur.line < visible.from)
6803          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
6804      } else {
6805        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
6806        if (outside) setTimeout(operation(cm, function() {
6807          if (counter != curCount) return;
6808          display.scroller.scrollTop += outside;
6809          extend(e);
6810        }), 50);
6811      }
6812    }
6813
6814    function done(e) {
6815      cm.state.selectingText = false;
6816      counter = Infinity;
6817      e_preventDefault(e);
6818      display.input.focus();
6819      off(document, "mousemove", move);
6820      off(document, "mouseup", up);
6821      doc.history.lastSelOrigin = null;
6822    }
6823
6824    var move = operation(cm, function(e) {
6825      if (!e_button(e)) done(e);
6826      else extend(e);
6827    });
6828    var up = operation(cm, done);
6829    cm.state.selectingText = up;
6830    on(document, "mousemove", move);
6831    on(document, "mouseup", up);
6832  }
6833
6834  // Determines whether an event happened in the gutter, and fires the
6835  // handlers for the corresponding event.
6836  function gutterEvent(cm, e, type, prevent, signalfn) {
6837    try { var mX = e.clientX, mY = e.clientY; }
6838    catch(e) { return false; }
6839    if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
6840    if (prevent) e_preventDefault(e);
6841
6842    var display = cm.display;
6843    var lineBox = display.lineDiv.getBoundingClientRect();
6844
6845    if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
6846    mY -= lineBox.top - display.viewOffset;
6847
6848    for (var i = 0; i < cm.options.gutters.length; ++i) {
6849      var g = display.gutters.childNodes[i];
6850      if (g && g.getBoundingClientRect().right >= mX) {
6851        var line = lineAtHeight(cm.doc, mY);
6852        var gutter = cm.options.gutters[i];
6853        signalfn(cm, type, cm, line, gutter, e);
6854        return e_defaultPrevented(e);
6855      }
6856    }
6857  }
6858
6859  function clickInGutter(cm, e) {
6860    return gutterEvent(cm, e, "gutterClick", true, signalLater);
6861  }
6862
6863  // Kludge to work around strange IE behavior where it'll sometimes
6864  // re-fire a series of drag-related events right after the drop (#1551)
6865  var lastDrop = 0;
6866
6867  function onDrop(e) {
6868    var cm = this;
6869    clearDragCursor(cm);
6870    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
6871      return;
6872    e_preventDefault(e);
6873    if (ie) lastDrop = +new Date;
6874    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
6875    if (!pos || isReadOnly(cm)) return;
6876    // Might be a file drop, in which case we simply extract the text
6877    // and insert it.
6878    if (files && files.length && window.FileReader && window.File) {
6879      var n = files.length, text = Array(n), read = 0;
6880      var loadFile = function(file, i) {
6881        if (cm.options.allowDropFileTypes &&
6882            indexOf(cm.options.allowDropFileTypes, file.type) == -1)
6883          return;
6884
6885        var reader = new FileReader;
6886        reader.onload = operation(cm, function() {
6887          var content = reader.result;
6888          if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
6889          text[i] = content;
6890          if (++read == n) {
6891            pos = clipPos(cm.doc, pos);
6892            var change = {from: pos, to: pos,
6893                          text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
6894                          origin: "paste"};
6895            makeChange(cm.doc, change);
6896            setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
6897          }
6898        });
6899        reader.readAsText(file);
6900      };
6901      for (var i = 0; i < n; ++i) loadFile(files[i], i);
6902    } else { // Normal drop
6903      // Don't do a replace if the drop happened inside of the selected text.
6904      if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
6905        cm.state.draggingText(e);
6906        // Ensure the editor is re-focused
6907        setTimeout(function() {cm.display.input.focus();}, 20);
6908        return;
6909      }
6910      try {
6911        var text = e.dataTransfer.getData("Text");
6912        if (text) {
6913          if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
6914            var selected = cm.listSelections();
6915          setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
6916          if (selected) for (var i = 0; i < selected.length; ++i)
6917            replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
6918          cm.replaceSelection(text, "around", "paste");
6919          cm.display.input.focus();
6920        }
6921      }
6922      catch(e){}
6923    }
6924  }
6925
6926  function onDragStart(cm, e) {
6927    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
6928    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
6929
6930    e.dataTransfer.setData("Text", cm.getSelection());
6931
6932    // Use dummy image instead of default browsers image.
6933    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
6934    if (e.dataTransfer.setDragImage && !safari) {
6935      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
6936      img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
6937      if (presto) {
6938        img.width = img.height = 1;
6939        cm.display.wrapper.appendChild(img);
6940        // Force a relayout, or Opera won't use our image for some obscure reason
6941        img._top = img.offsetTop;
6942      }
6943      e.dataTransfer.setDragImage(img, 0, 0);
6944      if (presto) img.parentNode.removeChild(img);
6945    }
6946  }
6947
6948  function onDragOver(cm, e) {
6949    var pos = posFromMouse(cm, e);
6950    if (!pos) return;
6951    var frag = document.createDocumentFragment();
6952    drawSelectionCursor(cm, pos, frag);
6953    if (!cm.display.dragCursor) {
6954      cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
6955      cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
6956    }
6957    removeChildrenAndAdd(cm.display.dragCursor, frag);
6958  }
6959
6960  function clearDragCursor(cm) {
6961    if (cm.display.dragCursor) {
6962      cm.display.lineSpace.removeChild(cm.display.dragCursor);
6963      cm.display.dragCursor = null;
6964    }
6965  }
6966
6967  // SCROLL EVENTS
6968
6969  // Sync the scrollable area and scrollbars, ensure the viewport
6970  // covers the visible area.
6971  function setScrollTop(cm, val) {
6972    if (Math.abs(cm.doc.scrollTop - val) < 2) return;
6973    cm.doc.scrollTop = val;
6974    if (!gecko) updateDisplaySimple(cm, {top: val});
6975    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
6976    cm.display.scrollbars.setScrollTop(val);
6977    if (gecko) updateDisplaySimple(cm);
6978    startWorker(cm, 100);
6979  }
6980  // Sync scroller and scrollbar, ensure the gutter elements are
6981  // aligned.
6982  function setScrollLeft(cm, val, isScroller) {
6983    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
6984    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
6985    cm.doc.scrollLeft = val;
6986    alignHorizontally(cm);
6987    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
6988    cm.display.scrollbars.setScrollLeft(val);
6989  }
6990
6991  // Since the delta values reported on mouse wheel events are
6992  // unstandardized between browsers and even browser versions, and
6993  // generally horribly unpredictable, this code starts by measuring
6994  // the scroll effect that the first few mouse wheel events have,
6995  // and, from that, detects the way it can convert deltas to pixel
6996  // offsets afterwards.
6997  //
6998  // The reason we want to know the amount a wheel event will scroll
6999  // is that it gives us a chance to update the display before the
7000  // actual scrolling happens, reducing flickering.
7001
7002  var wheelSamples = 0, wheelPixelsPerUnit = null;
7003  // Fill in a browser-detected starting value on browsers where we
7004  // know one. These don't have to be accurate -- the result of them
7005  // being wrong would just be a slight flicker on the first wheel
7006  // scroll (if it is large enough).
7007  if (ie) wheelPixelsPerUnit = -.53;
7008  else if (gecko) wheelPixelsPerUnit = 15;
7009  else if (chrome) wheelPixelsPerUnit = -.7;
7010  else if (safari) wheelPixelsPerUnit = -1/3;
7011
7012  var wheelEventDelta = function(e) {
7013    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
7014    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
7015    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
7016    else if (dy == null) dy = e.wheelDelta;
7017    return {x: dx, y: dy};
7018  };
7019  CodeMirror.wheelEventPixels = function(e) {
7020    var delta = wheelEventDelta(e);
7021    delta.x *= wheelPixelsPerUnit;
7022    delta.y *= wheelPixelsPerUnit;
7023    return delta;
7024  };
7025
7026  function onScrollWheel(cm, e) {
7027    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
7028
7029    var display = cm.display, scroll = display.scroller;
7030    // Quit if there's nothing to scroll here
7031    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
7032    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
7033    if (!(dx && canScrollX || dy && canScrollY)) return;
7034
7035    // Webkit browsers on OS X abort momentum scrolls when the target
7036    // of the scroll event is removed from the scrollable element.
7037    // This hack (see related code in patchDisplay) makes sure the
7038    // element is kept around.
7039    if (dy && mac && webkit) {
7040      outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
7041        for (var i = 0; i < view.length; i++) {
7042          if (view[i].node == cur) {
7043            cm.display.currentWheelTarget = cur;
7044            break outer;
7045          }
7046        }
7047      }
7048    }
7049
7050    // On some browsers, horizontal scrolling will cause redraws to
7051    // happen before the gutter has been realigned, causing it to
7052    // wriggle around in a most unseemly way. When we have an
7053    // estimated pixels/delta value, we just handle horizontal
7054    // scrolling entirely here. It'll be slightly off from native, but
7055    // better than glitching out.
7056    if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
7057      if (dy && canScrollY)
7058        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
7059      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
7060      // Only prevent default scrolling if vertical scrolling is
7061      // actually possible. Otherwise, it causes vertical scroll
7062      // jitter on OSX trackpads when deltaX is small and deltaY
7063      // is large (issue #3579)
7064      if (!dy || (dy && canScrollY))
7065        e_preventDefault(e);
7066      display.wheelStartX = null; // Abort measurement, if in progress
7067      return;
7068    }
7069
7070    // 'Project' the visible viewport to cover the area that is being
7071    // scrolled into view (if we know enough to estimate it).
7072    if (dy && wheelPixelsPerUnit != null) {
7073      var pixels = dy * wheelPixelsPerUnit;
7074      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
7075      if (pixels < 0) top = Math.max(0, top + pixels - 50);
7076      else bot = Math.min(cm.doc.height, bot + pixels + 50);
7077      updateDisplaySimple(cm, {top: top, bottom: bot});
7078    }
7079
7080    if (wheelSamples < 20) {
7081      if (display.wheelStartX == null) {
7082        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
7083        display.wheelDX = dx; display.wheelDY = dy;
7084        setTimeout(function() {
7085          if (display.wheelStartX == null) return;
7086          var movedX = scroll.scrollLeft - display.wheelStartX;
7087          var movedY = scroll.scrollTop - display.wheelStartY;
7088          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
7089            (movedX && display.wheelDX && movedX / display.wheelDX);
7090          display.wheelStartX = display.wheelStartY = null;
7091          if (!sample) return;
7092          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
7093          ++wheelSamples;
7094        }, 200);
7095      } else {
7096        display.wheelDX += dx; display.wheelDY += dy;
7097      }
7098    }
7099  }
7100
7101  // KEY EVENTS
7102
7103  // Run a handler that was bound to a key.
7104  function doHandleBinding(cm, bound, dropShift) {
7105    if (typeof bound == "string") {
7106      bound = commands[bound];
7107      if (!bound) return false;
7108    }
7109    // Ensure previous input has been read, so that the handler sees a
7110    // consistent view of the document
7111    cm.display.input.ensurePolled();
7112    var prevShift = cm.display.shift, done = false;
7113    try {
7114      if (isReadOnly(cm
vendor: 6,170 bytes, lines 7114-7299
7114)) cm.state.suppressEdits = true;
7115      if (dropShift) cm.display.shift = false;
7116      done = bound(cm) != Pass;
7117    } finally {
7118      cm.display.shift = prevShift;
7119      cm.state.suppressEdits = false;
7120    }
7121    return done;
7122  }
7123
7124  function lookupKeyForEditor(cm, name, handle) {
7125    for (var i = 0; i < cm.state.keyMaps.length; i++) {
7126      var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
7127      if (result) return result;
7128    }
7129    return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
7130      || lookupKey(name, cm.options.keyMap, handle, cm);
7131  }
7132
7133  var stopSeq = new Delayed;
7134  function dispatchKey(cm, name, e, handle) {
7135    var seq = cm.state.keySeq;
7136    if (seq) {
7137      if (isModifierKey(name)) return "handled";
7138      stopSeq.set(50, function() {
7139        if (cm.state.keySeq == seq) {
7140          cm.state.keySeq = null;
7141          cm.display.input.reset();
7142        }
7143      });
7144      name = seq + " " + name;
7145    }
7146    var result = lookupKeyForEditor(cm, name, handle);
7147
7148    if (result == "multi")
7149      cm.state.keySeq = name;
7150    if (result == "handled")
7151      signalLater(cm, "keyHandled", cm, name, e);
7152
7153    if (result == "handled" || result == "multi") {
7154      e_preventDefault(e);
7155      restartBlink(cm);
7156    }
7157
7158    if (seq && !result && /\'$/.test(name)) {
7159      e_preventDefault(e);
7160      return true;
7161    }
7162    return !!result;
7163  }
7164
7165  // Handle a key from the keydown event.
7166  function handleKeyBinding(cm, e) {
7167    var name = keyName(e, true);
7168    if (!name) return false;
7169
7170    if (e.shiftKey && !cm.state.keySeq) {
7171      // First try to resolve full name (including 'Shift-'). Failing
7172      // that, see if there is a cursor-motion command (starting with
7173      // 'go') bound to the keyname without 'Shift-'.
7174      return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
7175          || dispatchKey(cm, name, e, function(b) {
7176               if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
7177                 return doHandleBinding(cm, b);
7178             });
7179    } else {
7180      return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
7181    }
7182  }
7183
7184  // Handle a key from the keypress event
7185  function handleCharBinding(cm, e, ch) {
7186    return dispatchKey(cm, "'" + ch + "'", e,
7187                       function(b) { return doHandleBinding(cm, b, true); });
7188  }
7189
7190  var lastStoppedKey = null;
7191  function onKeyDown(e) {
7192    var cm = this;
7193    cm.curOp.focus = activeElt();
7194    if (signalDOMEvent(cm, e)) return;
7195    // IE does strange things with escape.
7196    if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
7197    var code = e.keyCode;
7198    cm.display.shift = code == 16 || e.shiftKey;
7199    var handled = handleKeyBinding(cm, e);
7200    if (presto) {
7201      lastStoppedKey = handled ? code : null;
7202      // Opera has no cut event... we try to at least catch the key combo
7203      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
7204        cm.replaceSelection("", null, "cut");
7205    }
7206
7207    // Turn mouse into crosshair when Alt is held on Mac.
7208    if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
7209      showCrossHair(cm);
7210  }
7211
7212  function showCrossHair(cm) {
7213    var lineDiv = cm.display.lineDiv;
7214    addClass(lineDiv, "CodeMirror-crosshair");
7215
7216    function up(e) {
7217      if (e.keyCode == 18 || !e.altKey) {
7218        rmClass(lineDiv, "CodeMirror-crosshair");
7219        off(document, "keyup", up);
7220        off(document, "mouseover", up);
7221      }
7222    }
7223    on(document, "keyup", up);
7224    on(document, "mouseover", up);
7225  }
7226
7227  function onKeyUp(e) {
7228    if (e.keyCode == 16) this.doc.sel.shift = false;
7229    signalDOMEvent(this, e);
7230  }
7231
7232  function onKeyPress(e) {
7233    var cm = this;
7234    if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
7235    var keyCode = e.keyCode, charCode = e.charCode;
7236    if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
7237    if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
7238    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
7239    if (handleCharBinding(cm, e, ch)) return;
7240    cm.display.input.onKeyPress(e);
7241  }
7242
7243  // FOCUS/BLUR EVENTS
7244
7245  function delayBlurEvent(cm) {
7246    cm.state.delayingBlurEvent = true;
7247    setTimeout(function() {
7248      if (cm.state.delayingBlurEvent) {
7249        cm.state.delayingBlurEvent = false;
7250        onBlur(cm);
7251      }
7252    }, 100);
7253  }
7254
7255  function onFocus(cm) {
7256    if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
7257
7258    if (cm.options.readOnly == "nocursor") return;
7259    if (!cm.state.focused) {
7260      signal(cm, "focus", cm);
7261      cm.state.focused = true;
7262      addClass(cm.display.wrapper, "CodeMirror-focused");
7263      // This test prevents this from firing when a context
7264      // menu is closed (since the input reset would kill the
7265      // select-all detection hack)
7266      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
7267        cm.display.input.reset();
7268        if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
7269      }
7270      cm.display.input.receivedFocus();
7271    }
7272    restartBlink(cm);
7273  }
7274  function onBlur(cm) {
7275    if (cm.state.delayingBlurEvent) return;
7276
7277    if (cm.state.focused) {
7278      signal(cm, "blur", cm);
7279      cm.state.focused = false;
7280      rmClass(cm.display.wrapper, "CodeMirror-focused");
7281    }
7282    clearInterval(cm.display.blinker);
7283    setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
7284  }
7285
7286  // CONTEXT MENU HANDLING
7287
7288  // To make the context menu work, we need to briefly unhide the
7289  // textarea (making it as unobtrusive as possible) to let the
7290  // right-click take effect on it.
7291  function onContextMenu(cm, e) {
7292    if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
7293    if (signalDOMEvent(cm, e, "contextmenu")) return;
7294    cm.display.input.onContextMenu(e);
7295  }
7296
7297  function contextMenuInGutter(cm, e) {
7298    if (!hasHandler(cm, "gutterContextMenu")) return false;
7299    return gutterEvent(cm, e, "gutterContextMenu", false
vendor: 4,806 bytes, lines 7299-7427
7299, signal);
7300  }
7301
7302  // UPDATING
7303
7304  // Compute the position of the end of a change (its 'to' property
7305  // refers to the pre-change end).
7306  var changeEnd = CodeMirror.changeEnd = function(change) {
7307    if (!change.text) return change.to;
7308    return Pos(change.from.line + change.text.length - 1,
7309               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
7310  };
7311
7312  // Adjust a position to refer to the post-change position of the
7313  // same text, or the end of the change if the change covers it.
7314  function adjustForChange(pos, change) {
7315    if (cmp(pos, change.from) < 0) return pos;
7316    if (cmp(pos, change.to) <= 0) return changeEnd(change);
7317
7318    var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
7319    if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
7320    return Pos(line, ch);
7321  }
7322
7323  function computeSelAfterChange(doc, change) {
7324    var out = [];
7325    for (var i = 0; i < doc.sel.ranges.length; i++) {
7326      var range = doc.sel.ranges[i];
7327      out.push(new Range(adjustForChange(range.anchor, change),
7328                         adjustForChange(range.head, change)));
7329    }
7330    return normalizeSelection(out, doc.sel.primIndex);
7331  }
7332
7333  function offsetPos(pos, old, nw) {
7334    if (pos.line == old.line)
7335      return Pos(nw.line, pos.ch - old.ch + nw.ch);
7336    else
7337      return Pos(nw.line + (pos.line - old.line), pos.ch);
7338  }
7339
7340  // Used by replaceSelections to allow moving the selection to the
7341  // start or around the replaced test. Hint may be "start" or "around".
7342  function computeReplacedSel(doc, changes, hint) {
7343    var out = [];
7344    var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
7345    for (var i = 0; i < changes.length; i++) {
7346      var change = changes[i];
7347      var from = offsetPos(change.from, oldPrev, newPrev);
7348      var to = offsetPos(changeEnd(change), oldPrev, newPrev);
7349      oldPrev = change.to;
7350      newPrev = to;
7351      if (hint == "around") {
7352        var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
7353        out[i] = new Range(inv ? to : from, inv ? from : to);
7354      } else {
7355        out[i] = new Range(from, from);
7356      }
7357    }
7358    return new Selection(out, doc.sel.primIndex);
7359  }
7360
7361  // Allow "beforeChange" event handlers to influence a change
7362  function filterChange(doc, change, update) {
7363    var obj = {
7364      canceled: false,
7365      from: change.from,
7366      to: change.to,
7367      text: change.text,
7368      origin: change.origin,
7369      cancel: function() { this.canceled = true; }
7370    };
7371    if (update) obj.update = function(from, to, text, origin) {
7372      if (from) this.from = clipPos(doc, from);
7373      if (to) this.to = clipPos(doc, to);
7374      if (text) this.text = text;
7375      if (origin !== undefined) this.origin = origin;
7376    };
7377    signal(doc, "beforeChange", doc, obj);
7378    if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
7379
7380    if (obj.canceled) return null;
7381    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
7382  }
7383
7384  // Apply a change to a document, and add it to the document's
7385  // history, and propagating it to all linked documents.
7386  function makeChange(doc, change, ignoreReadOnly) {
7387    if (doc.cm) {
7388      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
7389      if (doc.cm.state.suppressEdits) return;
7390    }
7391
7392    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
7393      change = filterChange(doc, change, true);
7394      if (!change) return;
7395    }
7396
7397    // Possibly split or suppress the update based on the presence
7398    // of read-only spans in its range.
7399    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
7400    if (split) {
7401      for (var i = split.length - 1; i >= 0; --i)
7402        makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
7403    } else {
7404      makeChangeInner(doc, change);
7405    }
7406  }
7407
7408  function makeChangeInner(doc, change) {
7409    if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
7410    var selAfter = computeSelAfterChange(doc, change);
7411    addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
7412
7413    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
7414    var rebased = [];
7415
7416    linkedDocs(doc, function(doc, sharedHist) {
7417      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
7418        rebaseHist(doc.history, change);
7419        rebased.push(doc.history);
7420      }
7421      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
7422    });
7423  }
7424
7425  // Revert a change stored in a document's history.
7426  function makeChangeFromHistory(doc, type, allowSelectionOnly) {
7427    if (doc.cm && doc.cm.state.suppressEdits
vendor: 17,279 bytes, lines 7427-7847
7427) return;
7428
7429    var hist = doc.history, event, selAfter = doc.sel;
7430    var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
7431
7432    // Verify that there is a useable event (so that ctrl-z won't
7433    // needlessly clear selection events)
7434    for (var i = 0; i < source.length; i++) {
7435      event = source[i];
7436      if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
7437        break;
7438    }
7439    if (i == source.length) return;
7440    hist.lastOrigin = hist.lastSelOrigin = null;
7441
7442    for (;;) {
7443      event = source.pop();
7444      if (event.ranges) {
7445        pushSelectionToHistory(event, dest);
7446        if (allowSelectionOnly && !event.equals(doc.sel)) {
7447          setSelection(doc, event, {clearRedo: false});
7448          return;
7449        }
7450        selAfter = event;
7451      }
7452      else break;
7453    }
7454
7455    // Build up a reverse change object to add to the opposite history
7456    // stack (redo when undoing, and vice versa).
7457    var antiChanges = [];
7458    pushSelectionToHistory(selAfter, dest);
7459    dest.push({changes: antiChanges, generation: hist.generation});
7460    hist.generation = event.generation || ++hist.maxGeneration;
7461
7462    var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
7463
7464    for (var i = event.changes.length - 1; i >= 0; --i) {
7465      var change = event.changes[i];
7466      change.origin = type;
7467      if (filter && !filterChange(doc, change, false)) {
7468        source.length = 0;
7469        return;
7470      }
7471
7472      antiChanges.push(historyChangeFromChange(doc, change));
7473
7474      var after = i ? computeSelAfterChange(doc, change) : lst(source);
7475      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
7476      if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
7477      var rebased = [];
7478
7479      // Propagate to the linked documents
7480      linkedDocs(doc, function(doc, sharedHist) {
7481        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
7482          rebaseHist(doc.history, change);
7483          rebased.push(doc.history);
7484        }
7485        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
7486      });
7487    }
7488  }
7489
7490  // Sub-views need their line numbers shifted when text is added
7491  // above or below them in the parent document.
7492  function shiftDoc(doc, distance) {
7493    if (distance == 0) return;
7494    doc.first += distance;
7495    doc.sel = new Selection(map(doc.sel.ranges, function(range) {
7496      return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
7497                       Pos(range.head.line + distance, range.head.ch));
7498    }), doc.sel.primIndex);
7499    if (doc.cm) {
7500      regChange(doc.cm, doc.first, doc.first - distance, distance);
7501      for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
7502        regLineChange(doc.cm, l, "gutter");
7503    }
7504  }
7505
7506  // More lower-level change function, handling only a single document
7507  // (not linked ones).
7508  function makeChangeSingleDoc(doc, change, selAfter, spans) {
7509    if (doc.cm && !doc.cm.curOp)
7510      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
7511
7512    if (change.to.line < doc.first) {
7513      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
7514      return;
7515    }
7516    if (change.from.line > doc.lastLine()) return;
7517
7518    // Clip the change to the size of this doc
7519    if (change.from.line < doc.first) {
7520      var shift = change.text.length - 1 - (doc.first - change.from.line);
7521      shiftDoc(doc, shift);
7522      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
7523                text: [lst(change.text)], origin: change.origin};
7524    }
7525    var last = doc.lastLine();
7526    if (change.to.line > last) {
7527      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
7528                text: [change.text[0]], origin: change.origin};
7529    }
7530
7531    change.removed = getBetween(doc, change.from, change.to);
7532
7533    if (!selAfter) selAfter = computeSelAfterChange(doc, change);
7534    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
7535    else updateDoc(doc, change, spans);
7536    setSelectionNoUndo(doc, selAfter, sel_dontScroll);
7537  }
7538
7539  // Handle the interaction of a change to a document with the editor
7540  // that this document is part of.
7541  function makeChangeSingleDocInEditor(cm, change, spans) {
7542    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
7543
7544    var recomputeMaxLength = false, checkWidthStart = from.line;
7545    if (!cm.options.lineWrapping) {
7546      checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
7547      doc.iter(checkWidthStart, to.line + 1, function(line) {
7548        if (line == display.maxLine) {
7549          recomputeMaxLength = true;
7550          return true;
7551        }
7552      });
7553    }
7554
7555    if (doc.sel.contains(change.from, change.to) > -1)
7556      signalCursorActivity(cm);
7557
7558    updateDoc(doc, change, spans, estimateHeight(cm));
7559
7560    if (!cm.options.lineWrapping) {
7561      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
7562        var len = lineLength(line);
7563        if (len > display.maxLineLength) {
7564          display.maxLine = line;
7565          display.maxLineLength = len;
7566          display.maxLineChanged = true;
7567          recomputeMaxLength = false;
7568        }
7569      });
7570      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
7571    }
7572
7573    // Adjust frontier, schedule worker
7574    doc.frontier = Math.min(doc.frontier, from.line);
7575    startWorker(cm, 400);
7576
7577    var lendiff = change.text.length - (to.line - from.line) - 1;
7578    // Remember that these lines changed, for updating the display
7579    if (change.full)
7580      regChange(cm);
7581    else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
7582      regLineChange(cm, from.line, "text");
7583    else
7584      regChange(cm, from.line, to.line + 1, lendiff);
7585
7586    var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
7587    if (changeHandler || changesHandler) {
7588      var obj = {
7589        from: from, to: to,
7590        text: change.text,
7591        removed: change.removed,
7592        origin: change.origin
7593      };
7594      if (changeHandler) signalLater(cm, "change", cm, obj);
7595      if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
7596    }
7597    cm.display.selForContextMenu = null;
7598  }
7599
7600  function replaceRange(doc, code, from, to, origin) {
7601    if (!to) to = from;
7602    if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
7603    if (typeof code == "string") code = doc.splitLines(code);
7604    makeChange(doc, {from: from, to: to, text: code, origin: origin});
7605  }
7606
7607  // SCROLLING THINGS INTO VIEW
7608
7609  // If an editor sits on the top or bottom of the window, partially
7610  // scrolled out of view, this ensures that the cursor is visible.
7611  function maybeScrollWindow(cm, coords) {
7612    if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
7613
7614    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
7615    if (coords.top + box.top < 0) doScroll = true;
7616    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
7617    if (doScroll != null && !phantom) {
7618      var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
7619                           (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
7620                           (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
7621                           coords.left + "px; width: 2px;");
7622      cm.display.lineSpace.appendChild(scrollNode);
7623      scrollNode.scrollIntoView(doScroll);
7624      cm.display.lineSpace.removeChild(scrollNode);
7625    }
7626  }
7627
7628  // Scroll a given position into view (immediately), verifying that
7629  // it actually became visible (as line heights are accurately
7630  // measured, the position of something may 'drift' during drawing).
7631  function scrollPosIntoView(cm, pos, end, margin) {
7632    if (margin == null) margin = 0;
7633    for (var limit = 0; limit < 5; limit++) {
7634      var changed = false, coords = cursorCoords(cm, pos);
7635      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
7636      var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
7637                                         Math.min(coords.top, endCoords.top) - margin,
7638                                         Math.max(coords.left, endCoords.left),
7639                                         Math.max(coords.bottom, endCoords.bottom) + margin);
7640      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
7641      if (scrollPos.scrollTop != null) {
7642        setScrollTop(cm, scrollPos.scrollTop);
7643        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
7644      }
7645      if (scrollPos.scrollLeft != null) {
7646        setScrollLeft(cm, scrollPos.scrollLeft);
7647        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
7648      }
7649      if (!changed) break;
7650    }
7651    return coords;
7652  }
7653
7654  // Scroll a given set of coordinates into view (immediately).
7655  function scrollIntoView(cm, x1, y1, x2, y2) {
7656    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
7657    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
7658    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
7659  }
7660
7661  // Calculate a new scroll position needed to scroll the given
7662  // rectangle into view. Returns an object with scrollTop and
7663  // scrollLeft properties. When these are undefined, the
7664  // vertical/horizontal position does not need to be adjusted.
7665  function calculateScrollPos(cm, x1, y1, x2, y2) {
7666    var display = cm.display, snapMargin = textHeight(cm.display);
7667    if (y1 < 0) y1 = 0;
7668    var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
7669    var screen = displayHeight(cm), result = {};
7670    if (y2 - y1 > screen) y2 = y1 + screen;
7671    var docBottom = cm.doc.height + paddingVert(display);
7672    var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
7673    if (y1 < screentop) {
7674      result.scrollTop = atTop ? 0 : y1;
7675    } else if (y2 > screentop + screen) {
7676      var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
7677      if (newTop != screentop) result.scrollTop = newTop;
7678    }
7679
7680    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
7681    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
7682    var tooWide = x2 - x1 > screenw;
7683    if (tooWide) x2 = x1 + screenw;
7684    if (x1 < 10)
7685      result.scrollLeft = 0;
7686    else if (x1 < screenleft)
7687      result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
7688    else if (x2 > screenw + screenleft - 3)
7689      result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
7690    return result;
7691  }
7692
7693  // Store a relative adjustment to the scroll position in the current
7694  // operation (to be applied when the operation finishes).
7695  function addToScrollPos(cm, left, top) {
7696    if (left != null || top != null) resolveScrollToPos(cm);
7697    if (left != null)
7698      cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
7699    if (top != null)
7700      cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
7701  }
7702
7703  // Make sure that at the end of the operation the current cursor is
7704  // shown.
7705  function ensureCursorVisible(cm) {
7706    resolveScrollToPos(cm);
7707    var cur = cm.getCursor(), from = cur, to = cur;
7708    if (!cm.options.lineWrapping) {
7709      from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
7710      to = Pos(cur.line, cur.ch + 1);
7711    }
7712    cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
7713  }
7714
7715  // When an operation has its scrollToPos property set, and another
7716  // scroll action is applied before the end of the operation, this
7717  // 'simulates' scrolling that position into view in a cheap way, so
7718  // that the effect of intermediate scroll commands is not ignored.
7719  function resolveScrollToPos(cm) {
7720    var range = cm.curOp.scrollToPos;
7721    if (range) {
7722      cm.curOp.scrollToPos = null;
7723      var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
7724      var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
7725                                    Math.min(from.top, to.top) - range.margin,
7726                                    Math.max(from.right, to.right),
7727                                    Math.max(from.bottom, to.bottom) + range.margin);
7728      cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
7729    }
7730  }
7731
7732  // API UTILITIES
7733
7734  // Indent the given line. The how parameter can be "smart",
7735  // "add"/null, "subtract", or "prev". When aggressive is false
7736  // (typically set to true for forced single-line indents), empty
7737  // lines are not indented, and places where the mode returns Pass
7738  // are left alone.
7739  function indentLine(cm, n, how, aggressive) {
7740    var doc = cm.doc, state;
7741    if (how == null) how = "add";
7742    if (how == "smart") {
7743      // Fall back to "prev" when the mode doesn't have an indentation
7744      // method.
7745      if (!doc.mode.indent) how = "prev";
7746      else state = getStateBefore(cm, n);
7747    }
7748
7749    var tabSize = cm.options.tabSize;
7750    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
7751    if (line.stateAfter) line.stateAfter = null;
7752    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
7753    if (!aggressive && !/\S/.test(line.text)) {
7754      indentation = 0;
7755      how = "not";
7756    } else if (how == "smart") {
7757      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
7758      if (indentation == Pass || indentation > 150) {
7759        if (!aggressive) return;
7760        how = "prev";
7761      }
7762    }
7763    if (how == "prev") {
7764      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
7765      else indentation = 0;
7766    } else if (how == "add") {
7767      indentation = curSpace + cm.options.indentUnit;
7768    } else if (how == "subtract") {
7769      indentation = curSpace - cm.options.indentUnit;
7770    } else if (typeof how == "number") {
7771      indentation = curSpace + how;
7772    }
7773    indentation = Math.max(0, indentation);
7774
7775    var indentString = "", pos = 0;
7776    if (cm.options.indentWithTabs)
7777      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
7778    if (pos < indentation) indentString += spaceStr(indentation - pos);
7779
7780    if (indentString != curSpaceString) {
7781      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
7782      line.stateAfter = null;
7783      return true;
7784    } else {
7785      // Ensure that, if the cursor was in the whitespace at the start
7786      // of the line, it is moved to the end of that space.
7787      for (var i = 0; i < doc.sel.ranges.length; i++) {
7788        var range = doc.sel.ranges[i];
7789        if (range.head.line == n && range.head.ch < curSpaceString.length) {
7790          var pos = Pos(n, curSpaceString.length);
7791          replaceOneSelection(doc, i, new Range(pos, pos));
7792          break;
7793        }
7794      }
7795    }
7796  }
7797
7798  // Utility for applying a change to a line by handle or number,
7799  // returning the number and optionally registering the line as
7800  // changed.
7801  function changeLine(doc, handle, changeType, op) {
7802    var no = handle, line = handle;
7803    if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
7804    else no = lineNo(handle);
7805    if (no == null) return null;
7806    if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
7807    return line;
7808  }
7809
7810  // Helper for deleting text near the selection(s), used to implement
7811  // backspace, delete, and similar functionality.
7812  function deleteNearSelection(cm, compute) {
7813    var ranges = cm.doc.sel.ranges, kill = [];
7814    // Build up a set of ranges to kill first, merging overlapping
7815    // ranges.
7816    for (var i = 0; i < ranges.length; i++) {
7817      var toKill = compute(ranges[i]);
7818      while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
7819        var replaced = kill.pop();
7820        if (cmp(replaced.from, toKill.from) < 0) {
7821          toKill.from = replaced.from;
7822          break;
7823        }
7824      }
7825      kill.push(toKill);
7826    }
7827    // Next, remove those actual ranges.
7828    runInOp(cm, function() {
7829      for (var i = kill.length - 1; i >= 0; i--)
7830        replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
7831      ensureCursorVisible(cm);
7832    });
7833  }
7834
7835  // Used for horizontal relative motion. Dir is -1 or 1 (left or
7836  // right), unit can be "char", "column" (like char, but doesn't
7837  // cross line boundaries), "word" (across next word), or "group" (to
7838  // the start of next group of word or non-word-non-whitespace
7839  // chars). The visually param controls whether, in right-to-left
7840  // text, direction 1 means to move towards the next index in the
7841  // string, or towards the character to the right of the current
7842  // position. The resulting position will have a hitSide=true
7843  // property if it reached the end of the document.
7844  function findPosH(doc, pos, dir, unit, visually) {
7845    var line = pos.line, ch = pos.ch, origDir = dir;
7846    var lineObj = getLine(doc, line);
7847    
7847var possible = true;
7848    function findNextLine() {
7849      var l = line + dir;
7850      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
7851      line = l;
7852      return lineObj = getLine(doc, l);
7853    }
7854    function moveOnce(boundToLine) {
7855      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
7856      if (next == null) {
7857        if (!boundToLine && findNextLine()) {
7858          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
7859          else ch = dir < 0 ? lineObj.text.length : 0;
7860        } else return (possible = false);
7861      } else ch = next;
7862      return true;
7863    }
7864
7865    if (unit == "char") moveOnce();
7866    else if (unit == "column") moveOnce(true);
7867    else if (unit == "word" || unit == "group") {
7868      var sawType = null, group = unit == "group";
7869      var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
7870      for (var first = true;; first = false) {
7871        if (dir < 0 && !moveOnce(!first)) break;
7872        var cur = lineObj.text.charAt(ch) || "\n";
7873        var type = isWordChar(cur, helper) ? "w"
7874          : group && cur == "\n" ? "n"
7875          : !group || /\s/.test(cur) ? null
7876          : "p";
7877        if (group && !first && !type) type = "s";
7878        if (sawType && sawType != type) {
7879          if (dir < 0) {dir = 1; moveOnce();}
7880          break;
7881        }
7882
7883        if (type) sawType = type;
7884        if (dir > 0 && !moveOnce(!first)) break;
7885      }
7886    }
7887    var result = skipAtomic(doc, Pos(line, ch), origDir, true);
7888    if (!possible
vendor: 14,934 bytes, lines 7888-8274
7888) result.hitSide = true;
7889    return result;
7890  }
7891
7892  // For relative vertical movement. Dir may be -1 or 1. Unit can be
7893  // "page" or "line". The resulting position will have a hitSide=true
7894  // property if it reached the end of the document.
7895  function findPosV(cm, pos, dir, unit) {
7896    var doc = cm.doc, x = pos.left, y;
7897    if (unit == "page") {
7898      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
7899      y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
7900    } else if (unit == "line") {
7901      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
7902    }
7903    for (;;) {
7904      var target = coordsChar(cm, x, y);
7905      if (!target.outside) break;
7906      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
7907      y += dir * 5;
7908    }
7909    return target;
7910  }
7911
7912  // EDITOR METHODS
7913
7914  // The publicly visible API. Note that methodOp(f) means
7915  // 'wrap f in an operation, performed on its `this` parameter'.
7916
7917  // This is not the complete set of editor methods. Most of the
7918  // methods defined on the Doc type are also injected into
7919  // CodeMirror.prototype, for backwards compatibility and
7920  // convenience.
7921
7922  CodeMirror.prototype = {
7923    constructor: CodeMirror,
7924    focus: function(){window.focus(); this.display.input.focus();},
7925
7926    setOption: function(option, value) {
7927      var options = this.options, old = options[option];
7928      if (options[option] == value && option != "mode") return;
7929      options[option] = value;
7930      if (optionHandlers.hasOwnProperty(option))
7931        operation(this, optionHandlers[option])(this, value, old);
7932    },
7933
7934    getOption: function(option) {return this.options[option];},
7935    getDoc: function() {return this.doc;},
7936
7937    addKeyMap: function(map, bottom) {
7938      this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
7939    },
7940    removeKeyMap: function(map) {
7941      var maps = this.state.keyMaps;
7942      for (var i = 0; i < maps.length; ++i)
7943        if (maps[i] == map || maps[i].name == map) {
7944          maps.splice(i, 1);
7945          return true;
7946        }
7947    },
7948
7949    addOverlay: methodOp(function(spec, options) {
7950      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
7951      if (mode.startState) throw new Error("Overlays may not be stateful.");
7952      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
7953      this.state.modeGen++;
7954      regChange(this);
7955    }),
7956    removeOverlay: methodOp(function(spec) {
7957      var overlays = this.state.overlays;
7958      for (var i = 0; i < overlays.length; ++i) {
7959        var cur = overlays[i].modeSpec;
7960        if (cur == spec || typeof spec == "string" && cur.name == spec) {
7961          overlays.splice(i, 1);
7962          this.state.modeGen++;
7963          regChange(this);
7964          return;
7965        }
7966      }
7967    }),
7968
7969    indentLine: methodOp(function(n, dir, aggressive) {
7970      if (typeof dir != "string" && typeof dir != "number") {
7971        if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
7972        else dir = dir ? "add" : "subtract";
7973      }
7974      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
7975    }),
7976    indentSelection: methodOp(function(how) {
7977      var ranges = this.doc.sel.ranges, end = -1;
7978      for (var i = 0; i < ranges.length; i++) {
7979        var range = ranges[i];
7980        if (!range.empty()) {
7981          var from = range.from(), to = range.to();
7982          var start = Math.max(end, from.line);
7983          end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
7984          for (var j = start; j < end; ++j)
7985            indentLine(this, j, how);
7986          var newRanges = this.doc.sel.ranges;
7987          if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
7988            replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
7989        } else if (range.head.line > end) {
7990          indentLine(this, range.head.line, how, true);
7991          end = range.head.line;
7992          if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
7993        }
7994      }
7995    }),
7996
7997    // Fetch the parser token for a given character. Useful for hacks
7998    // that want to inspect the mode state (say, for completion).
7999    getTokenAt: function(pos, precise) {
8000      return takeToken(this, pos, precise);
8001    },
8002
8003    getLineTokens: function(line, precise) {
8004      return takeToken(this, Pos(line), precise, true);
8005    },
8006
8007    getTokenTypeAt: function(pos) {
8008      pos = clipPos(this.doc, pos);
8009      var styles = getLineStyles(this, getLine(this.doc, pos.line));
8010      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
8011      var type;
8012      if (ch == 0) type = styles[2];
8013      else for (;;) {
8014        var mid = (before + after) >> 1;
8015        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
8016        else if (styles[mid * 2 + 1] < ch) before = mid + 1;
8017        else { type = styles[mid * 2 + 2]; break; }
8018      }
8019      var cut = type ? type.indexOf("cm-overlay ") : -1;
8020      return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
8021    },
8022
8023    getModeAt: function(pos) {
8024      var mode = this.doc.mode;
8025      if (!mode.innerMode) return mode;
8026      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
8027    },
8028
8029    getHelper: function(pos, type) {
8030      return this.getHelpers(pos, type)[0];
8031    },
8032
8033    getHelpers: function(pos, type) {
8034      var found = [];
8035      if (!helpers.hasOwnProperty(type)) return found;
8036      var help = helpers[type], mode = this.getModeAt(pos);
8037      if (typeof mode[type] == "string") {
8038        if (help[mode[type]]) found.push(help[mode[type]]);
8039      } else if (mode[type]) {
8040        for (var i = 0; i < mode[type].length; i++) {
8041          var val = help[mode[type][i]];
8042          if (val) found.push(val);
8043        }
8044      } else if (mode.helperType && help[mode.helperType]) {
8045        found.push(help[mode.helperType]);
8046      } else if (help[mode.name]) {
8047        found.push(help[mode.name]);
8048      }
8049      for (var i = 0; i < help._global.length; i++) {
8050        var cur = help._global[i];
8051        if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
8052          found.push(cur.val);
8053      }
8054      return found;
8055    },
8056
8057    getStateAfter: function(line, precise) {
8058      var doc = this.doc;
8059      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
8060      return getStateBefore(this, line + 1, precise);
8061    },
8062
8063    cursorCoords: function(start, mode) {
8064      var pos, range = this.doc.sel.primary();
8065      if (start == null) pos = range.head;
8066      else if (typeof start == "object") pos = clipPos(this.doc, start);
8067      else pos = start ? range.from() : range.to();
8068      return cursorCoords(this, pos, mode || "page");
8069    },
8070
8071    charCoords: function(pos, mode) {
8072      return charCoords(this, clipPos(this.doc, pos), mode || "page");
8073    },
8074
8075    coordsChar: function(coords, mode) {
8076      coords = fromCoordSystem(this, coords, mode || "page");
8077      return coordsChar(this, coords.left, coords.top);
8078    },
8079
8080    lineAtHeight: function(height, mode) {
8081      height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
8082      return lineAtHeight(this.doc, height + this.display.viewOffset);
8083    },
8084    heightAtLine: function(line, mode) {
8085      var end = false, lineObj;
8086      if (typeof line == "number") {
8087        var last = this.doc.first + this.doc.size - 1;
8088        if (line < this.doc.first) line = this.doc.first;
8089        else if (line > last) { line = last; end = true; }
8090        lineObj = getLine(this.doc, line);
8091      } else {
8092        lineObj = line;
8093      }
8094      return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
8095        (end ? this.doc.height - heightAtLine(lineObj) : 0);
8096    },
8097
8098    defaultTextHeight: function() { return textHeight(this.display); },
8099    defaultCharWidth: function() { return charWidth(this.display); },
8100
8101    setGutterMarker: methodOp(function(line, gutterID, value) {
8102      return changeLine(this.doc, line, "gutter", function(line) {
8103        var markers = line.gutterMarkers || (line.gutterMarkers = {});
8104        markers[gutterID] = value;
8105        if (!value && isEmpty(markers)) line.gutterMarkers = null;
8106        return true;
8107      });
8108    }),
8109
8110    clearGutter: methodOp(function(gutterID) {
8111      var cm = this, doc = cm.doc, i = doc.first;
8112      doc.iter(function(line) {
8113        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
8114          line.gutterMarkers[gutterID] = null;
8115          regLineChange(cm, i, "gutter");
8116          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
8117        }
8118        ++i;
8119      });
8120    }),
8121
8122    lineInfo: function(line) {
8123      if (typeof line == "number") {
8124        if (!isLine(this.doc, line)) return null;
8125        var n = line;
8126        line = getLine(this.doc, line);
8127        if (!line) return null;
8128      } else {
8129        var n = lineNo(line);
8130        if (n == null) return null;
8131      }
8132      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
8133              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
8134              widgets: line.widgets};
8135    },
8136
8137    getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
8138
8139    addWidget: function(pos, node, scroll, vert, horiz) {
8140      var display = this.display;
8141      pos = cursorCoords(this, clipPos(this.doc, pos));
8142      var top = pos.bottom, left = pos.left;
8143      node.style.position = "absolute";
8144      node.setAttribute("cm-ignore-events", "true");
8145      this.display.input.setUneditable(node);
8146      display.sizer.appendChild(node);
8147      if (vert == "over") {
8148        top = pos.top;
8149      } else if (vert == "above" || vert == "near") {
8150        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
8151        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
8152        // Default to positioning above (if specified and possible); otherwise default to positioning below
8153        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
8154          top = pos.top - node.offsetHeight;
8155        else if (pos.bottom + node.offsetHeight <= vspace)
8156          top = pos.bottom;
8157        if (left + node.offsetWidth > hspace)
8158          left = hspace - node.offsetWidth;
8159      }
8160      node.style.top = top + "px";
8161      node.style.left = node.style.right = "";
8162      if (horiz == "right") {
8163        left = display.sizer.clientWidth - node.offsetWidth;
8164        node.style.right = "0px";
8165      } else {
8166        if (horiz == "left") left = 0;
8167        else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
8168        node.style.left = left + "px";
8169      }
8170      if (scroll)
8171        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
8172    },
8173
8174    triggerOnKeyDown: methodOp(onKeyDown),
8175    triggerOnKeyPress: methodOp(onKeyPress),
8176    triggerOnKeyUp: onKeyUp,
8177
8178    execCommand: function(cmd) {
8179      if (commands.hasOwnProperty(cmd))
8180        return commands[cmd].call(null, this);
8181    },
8182
8183    triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
8184
8185    findPosH: function(from, amount, unit, visually) {
8186      var dir = 1;
8187      if (amount < 0) { dir = -1; amount = -amount; }
8188      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
8189        cur = findPosH(this.doc, cur, dir, unit, visually);
8190        if (cur.hitSide) break;
8191      }
8192      return cur;
8193    },
8194
8195    moveH: methodOp(function(dir, unit) {
8196      var cm = this;
8197      cm.extendSelectionsBy(function(range) {
8198        if (cm.display.shift || cm.doc.extend || range.empty())
8199          return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
8200        else
8201          return dir < 0 ? range.from() : range.to();
8202      }, sel_move);
8203    }),
8204
8205    deleteH: methodOp(function(dir, unit) {
8206      var sel = this.doc.sel, doc = this.doc;
8207      if (sel.somethingSelected())
8208        doc.replaceSelection("", null, "+delete");
8209      else
8210        deleteNearSelection(this, function(range) {
8211          var other = findPosH(doc, range.head, dir, unit, false);
8212          return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
8213        });
8214    }),
8215
8216    findPosV: function(from, amount, unit, goalColumn) {
8217      var dir = 1, x = goalColumn;
8218      if (amount < 0) { dir = -1; amount = -amount; }
8219      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
8220        var coords = cursorCoords(this, cur, "div");
8221        if (x == null) x = coords.left;
8222        else coords.left = x;
8223        cur = findPosV(this, coords, dir, unit);
8224        if (cur.hitSide) break;
8225      }
8226      return cur;
8227    },
8228
8229    moveV: methodOp(function(dir, unit) {
8230      var cm = this, doc = this.doc, goals = [];
8231      var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
8232      doc.extendSelectionsBy(function(range) {
8233        if (collapse)
8234          return dir < 0 ? range.from() : range.to();
8235        var headPos = cursorCoords(cm, range.head, "div");
8236        if (range.goalColumn != null) headPos.left = range.goalColumn;
8237        goals.push(headPos.left);
8238        var pos = findPosV(cm, headPos, dir, unit);
8239        if (unit == "page" && range == doc.sel.primary())
8240          addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
8241        return pos;
8242      }, sel_move);
8243      if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
8244        doc.sel.ranges[i].goalColumn = goals[i];
8245    }),
8246
8247    // Find the word at the given position (as returned by coordsChar).
8248    findWordAt: function(pos) {
8249      var doc = this.doc, line = getLine(doc, pos.line).text;
8250      var start = pos.ch, end = pos.ch;
8251      if (line) {
8252        var helper = this.getHelper(pos, "wordChars");
8253        if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
8254        var startChar = line.charAt(start);
8255        var check = isWordChar(startChar, helper)
8256          ? function(ch) { return isWordChar(ch, helper); }
8257          : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
8258          : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
8259        while (start > 0 && check(line.charAt(start - 1))) --start;
8260        while (end < line.length && check(line.charAt(end))) ++end;
8261      }
8262      return new Range(Pos(pos.line, start), Pos(pos.line, end));
8263    },
8264
8265    toggleOverwrite: function(value) {
8266      if (value != null && value == this.state.overwrite) return;
8267      if (this.state.overwrite = !this.state.overwrite)
8268        addClass(this.display.cursorDiv, "CodeMirror-overwrite");
8269      else
8270        rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
8271
8272      signal(this, "overwriteToggle", this, this.state.overwrite);
8273    },
8274    hasFocus: function() { return this.display.input.getField() == activeElt(); },
vendor: 5,266 bytes, lines 8275-8414
8275
8276    scrollTo: methodOp(function(x, y) {
8277      if (x != null || y != null) resolveScrollToPos(this);
8278      if (x != null) this.curOp.scrollLeft = x;
8279      if (y != null) this.curOp.scrollTop = y;
8280    }),
8281    getScrollInfo: function() {
8282      var scroller = this.display.scroller;
8283      return {left: scroller.scrollLeft, top: scroller.scrollTop,
8284              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
8285              width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
8286              clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
8287    },
8288
8289    scrollIntoView: methodOp(function(range, margin) {
8290      if (range == null) {
8291        range = {from: this.doc.sel.primary().head, to: null};
8292        if (margin == null) margin = this.options.cursorScrollMargin;
8293      } else if (typeof range == "number") {
8294        range = {from: Pos(range, 0), to: null};
8295      } else if (range.from == null) {
8296        range = {from: range, to: null};
8297      }
8298      if (!range.to) range.to = range.from;
8299      range.margin = margin || 0;
8300
8301      if (range.from.line != null) {
8302        resolveScrollToPos(this);
8303        this.curOp.scrollToPos = range;
8304      } else {
8305        var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
8306                                      Math.min(range.from.top, range.to.top) - range.margin,
8307                                      Math.max(range.from.right, range.to.right),
8308                                      Math.max(range.from.bottom, range.to.bottom) + range.margin);
8309        this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
8310      }
8311    }),
8312
8313    setSize: methodOp(function(width, height) {
8314      var cm = this;
8315      function interpret(val) {
8316        return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
8317      }
8318      if (width != null) cm.display.wrapper.style.width = interpret(width);
8319      if (height != null) cm.display.wrapper.style.height = interpret(height);
8320      if (cm.options.lineWrapping) clearLineMeasurementCache(this);
8321      var lineNo = cm.display.viewFrom;
8322      cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
8323        if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
8324          if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
8325        ++lineNo;
8326      });
8327      cm.curOp.forceUpdate = true;
8328      signal(cm, "refresh", this);
8329    }),
8330
8331    operation: function(f){return runInOp(this, f);},
8332
8333    refresh: methodOp(function() {
8334      var oldHeight = this.display.cachedTextHeight;
8335      regChange(this);
8336      this.curOp.forceUpdate = true;
8337      clearCaches(this);
8338      this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
8339      updateGutterSpace(this);
8340      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
8341        estimateLineHeights(this);
8342      signal(this, "refresh", this);
8343    }),
8344
8345    swapDoc: methodOp(function(doc) {
8346      var old = this.doc;
8347      old.cm = null;
8348      attachDoc(this, doc);
8349      clearCaches(this);
8350      this.display.input.reset();
8351      this.scrollTo(doc.scrollLeft, doc.scrollTop);
8352      this.curOp.forceScroll = true;
8353      signalLater(this, "swapDoc", this, old);
8354      return old;
8355    }),
8356
8357    getInputField: function(){return this.display.input.getField();},
8358    getWrapperElement: function(){return this.display.wrapper;},
8359    getScrollerElement: function(){return this.display.scroller;},
8360    getGutterElement: function(){return this.display.gutters;}
8361  };
8362  eventMixin(CodeMirror);
8363
8364  // OPTION DEFAULTS
8365
8366  // The default configuration options.
8367  var defaults = CodeMirror.defaults = {};
8368  // Functions to run when options are changed.
8369  var optionHandlers = CodeMirror.optionHandlers = {};
8370
8371  function option(name, deflt, handle, notOnInit) {
8372    CodeMirror.defaults[name] = deflt;
8373    if (handle) optionHandlers[name] =
8374      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
8375  }
8376
8377  // Passed to option handlers when there is no old value.
8378  var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
8379
8380  // These two are, on init, called from the constructor because they
8381  // have to be initialized before the editor can start at all.
8382  option("value", "", function(cm, val) {
8383    cm.setValue(val);
8384  }, true);
8385  option("mode", null, function(cm, val) {
8386    cm.doc.modeOption = val;
8387    loadMode(cm);
8388  }, true);
8389
8390  option("indentUnit", 2, loadMode, true);
8391  option("indentWithTabs", false);
8392  option("smartIndent", true);
8393  option("tabSize", 4, function(cm) {
8394    resetModeState(cm);
8395    clearCaches(cm);
8396    regChange(cm);
8397  }, true);
8398  option("lineSeparator", null, function(cm, val) {
8399    cm.doc.lineSep = val;
8400    if (!val) return;
8401    var newBreaks = [], lineNo = cm.doc.first;
8402    cm.doc.iter(function(line) {
8403      for (var pos = 0;;) {
8404        var found = line.text.indexOf(val, pos);
8405        if (found == -1) break;
8406        pos = found + val.length;
8407        newBreaks.push(Pos(lineNo, found));
8408      }
8409      lineNo++;
8410    });
8411    for (var i = newBreaks.length - 1; i >= 0; i--)
8412      replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
8413  });
8414  option("specialChars", /[\t\u0000-\u0019
vendor: 13,170 bytes, lines 8414-8743
8414\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
8415    cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
8416    if (old != CodeMirror.Init) cm.refresh();
8417  });
8418  option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
8419  option("electricChars", true);
8420  option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
8421    throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
8422  }, true);
8423  option("rtlMoveVisually", !windows);
8424  option("wholeLineUpdateBefore", true);
8425
8426  option("theme", "default", function(cm) {
8427    themeChanged(cm);
8428    guttersChanged(cm);
8429  }, true);
8430  option("keyMap", "default", function(cm, val, old) {
8431    var next = getKeyMap(val);
8432    var prev = old != CodeMirror.Init && getKeyMap(old);
8433    if (prev && prev.detach) prev.detach(cm, next);
8434    if (next.attach) next.attach(cm, prev || null);
8435  });
8436  option("extraKeys", null);
8437
8438  option("lineWrapping", false, wrappingChanged, true);
8439  option("gutters", [], function(cm) {
8440    setGuttersForLineNumbers(cm.options);
8441    guttersChanged(cm);
8442  }, true);
8443  option("fixedGutter", true, function(cm, val) {
8444    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
8445    cm.refresh();
8446  }, true);
8447  option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
8448  option("scrollbarStyle", "native", function(cm) {
8449    initScrollbars(cm);
8450    updateScrollbars(cm);
8451    cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
8452    cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
8453  }, true);
8454  option("lineNumbers", false, function(cm) {
8455    setGuttersForLineNumbers(cm.options);
8456    guttersChanged(cm);
8457  }, true);
8458  option("firstLineNumber", 1, guttersChanged, true);
8459  option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
8460  option("showCursorWhenSelecting", false, updateSelection, true);
8461
8462  option("resetSelectionOnContextMenu", true);
8463  option("lineWiseCopyCut", true);
8464
8465  option("readOnly", false, function(cm, val) {
8466    if (val == "nocursor") {
8467      onBlur(cm);
8468      cm.display.input.blur();
8469      cm.display.disabled = true;
8470    } else {
8471      cm.display.disabled = false;
8472    }
8473    cm.display.input.readOnlyChanged(val)
8474  });
8475  option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
8476  option("dragDrop", true, dragDropChanged);
8477  option("allowDropFileTypes", null);
8478
8479  option("cursorBlinkRate", 530);
8480  option("cursorScrollMargin", 0);
8481  option("cursorHeight", 1, updateSelection, true);
8482  option("singleCursorHeightPerLine", true, updateSelection, true);
8483  option("workTime", 100);
8484  option("workDelay", 100);
8485  option("flattenSpans", true, resetModeState, true);
8486  option("addModeClass", false, resetModeState, true);
8487  option("pollInterval", 100);
8488  option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
8489  option("historyEventDelay", 1250);
8490  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
8491  option("maxHighlightLength", 10000, resetModeState, true);
8492  option("moveInputWithCursor", true, function(cm, val) {
8493    if (!val) cm.display.input.resetPosition();
8494  });
8495
8496  option("tabindex", null, function(cm, val) {
8497    cm.display.input.getField().tabIndex = val || "";
8498  });
8499  option("autofocus", null);
8500
8501  // MODE DEFINITION AND QUERYING
8502
8503  // Known modes, by name and by MIME
8504  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
8505
8506  // Extra arguments are stored as the mode's dependencies, which is
8507  // used by (legacy) mechanisms like loadmode.js to automatically
8508  // load a mode. (Preferred mechanism is the require/define calls.)
8509  CodeMirror.defineMode = function(name, mode) {
8510    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
8511    if (arguments.length > 2)
8512      mode.dependencies = Array.prototype.slice.call(arguments, 2);
8513    modes[name] = mode;
8514  };
8515
8516  CodeMirror.defineMIME = function(mime, spec) {
8517    mimeModes[mime] = spec;
8518  };
8519
8520  // Given a MIME type, a {name, ...options} config object, or a name
8521  // string, return a mode config object.
8522  CodeMirror.resolveMode = function(spec) {
8523    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
8524      spec = mimeModes[spec];
8525    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
8526      var found = mimeModes[spec.name];
8527      if (typeof found == "string") found = {name: found};
8528      spec = createObj(found, spec);
8529      spec.name = found.name;
8530    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
8531      return CodeMirror.resolveMode("application/xml");
8532    }
8533    if (typeof spec == "string") return {name: spec};
8534    else return spec || {name: "null"};
8535  };
8536
8537  // Given a mode spec (anything that resolveMode accepts), find and
8538  // initialize an actual mode object.
8539  CodeMirror.getMode = function(options, spec) {
8540    var spec = CodeMirror.resolveMode(spec);
8541    var mfactory = modes[spec.name];
8542    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
8543    var modeObj = mfactory(options, spec);
8544    if (modeExtensions.hasOwnProperty(spec.name)) {
8545      var exts = modeExtensions[spec.name];
8546      for (var prop in exts) {
8547        if (!exts.hasOwnProperty(prop)) continue;
8548        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
8549        modeObj[prop] = exts[prop];
8550      }
8551    }
8552    modeObj.name = spec.name;
8553    if (spec.helperType) modeObj.helperType = spec.helperType;
8554    if (spec.modeProps) for (var prop in spec.modeProps)
8555      modeObj[prop] = spec.modeProps[prop];
8556
8557    return modeObj;
8558  };
8559
8560  // Minimal default mode.
8561  CodeMirror.defineMode("null", function() {
8562    return {token: function(stream) {stream.skipToEnd();}};
8563  });
8564  CodeMirror.defineMIME("text/plain", "null");
8565
8566  // This can be used to attach properties to mode objects from
8567  // outside the actual mode definition.
8568  var modeExtensions = CodeMirror.modeExtensions = {};
8569  CodeMirror.extendMode = function(mode, properties) {
8570    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
8571    copyObj(properties, exts);
8572  };
8573
8574  // EXTENSIONS
8575
8576  CodeMirror.defineExtension = function(name, func) {
8577    CodeMirror.prototype[name] = func;
8578  };
8579  CodeMirror.defineDocExtension = function(name, func) {
8580    Doc.prototype[name] = func;
8581  };
8582  CodeMirror.defineOption = option;
8583
8584  var initHooks = [];
8585  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
8586
8587  var helpers = CodeMirror.helpers = {};
8588  CodeMirror.registerHelper = function(type, name, value) {
8589    if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
8590    helpers[type][name] = value;
8591  };
8592  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
8593    CodeMirror.registerHelper(type, name, value);
8594    helpers[type]._global.push({pred: predicate, val: value});
8595  };
8596
8597  // MODE STATE HANDLING
8598
8599  // Utility functions for working with state. Exported because nested
8600  // modes need to do this for their inner modes.
8601
8602  var copyState = CodeMirror.copyState = function(mode, state) {
8603    if (state === true) return state;
8604    if (mode.copyState) return mode.copyState(state);
8605    var nstate = {};
8606    for (var n in state) {
8607      var val = state[n];
8608      if (val instanceof Array) val = val.concat([]);
8609      nstate[n] = val;
8610    }
8611    return nstate;
8612  };
8613
8614  var startState = CodeMirror.startState = function(mode, a1, a2) {
8615    return mode.startState ? mode.startState(a1, a2) : true;
8616  };
8617
8618  // Given a mode and a state (for that mode), find the inner mode and
8619  // state at the position that the state refers to.
8620  CodeMirror.innerMode = function(mode, state) {
8621    while (mode.innerMode) {
8622      var info = mode.innerMode(state);
8623      if (!info || info.mode == mode) break;
8624      state = info.state;
8625      mode = info.mode;
8626    }
8627    return info || {mode: mode, state: state};
8628  };
8629
8630  // STANDARD COMMANDS
8631
8632  // Commands are parameter-less actions that can be performed on an
8633  // editor, mostly used for keybindings.
8634  var commands = CodeMirror.commands = {
8635    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
8636    singleSelection: function(cm) {
8637      cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
8638    },
8639    killLine: function(cm) {
8640      deleteNearSelection(cm, function(range) {
8641        if (range.empty()) {
8642          var len = getLine(cm.doc, range.head.line).text.length;
8643          if (range.head.ch == len && range.head.line < cm.lastLine())
8644            return {from: range.head, to: Pos(range.head.line + 1, 0)};
8645          else
8646            return {from: range.head, to: Pos(range.head.line, len)};
8647        } else {
8648          return {from: range.from(), to: range.to()};
8649        }
8650      });
8651    },
8652    deleteLine: function(cm) {
8653      deleteNearSelection(cm, function(range) {
8654        return {from: Pos(range.from().line, 0),
8655                to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
8656      });
8657    },
8658    delLineLeft: function(cm) {
8659      deleteNearSelection(cm, function(range) {
8660        return {from: Pos(range.from().line, 0), to: range.from()};
8661      });
8662    },
8663    delWrappedLineLeft: function(cm) {
8664      deleteNearSelection(cm, function(range) {
8665        var top = cm.charCoords(range.head, "div").top + 5;
8666        var leftPos = cm.coordsChar({left: 0, top: top}, "div");
8667        return {from: leftPos, to: range.from()};
8668      });
8669    },
8670    delWrappedLineRight: function(cm) {
8671      deleteNearSelection(cm, function(range) {
8672        var top = cm.charCoords(range.head, "div").top + 5;
8673        var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
8674        return {from: range.from(), to: rightPos };
8675      });
8676    },
8677    undo: function(cm) {cm.undo();},
8678    redo: function(cm) {cm.redo();},
8679    undoSelection: function(cm) {cm.undoSelection();},
8680    redoSelection: function(cm) {cm.redoSelection();},
8681    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
8682    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
8683    goLineStart: function(cm) {
8684      cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
8685                            {origin: "+move", bias: 1});
8686    },
8687    goLineStartSmart: function(cm) {
8688      cm.extendSelectionsBy(function(range) {
8689        return lineStartSmart(cm, range.head);
8690      }, {origin: "+move", bias: 1});
8691    },
8692    goLineEnd: function(cm) {
8693      cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
8694                            {origin: "+move", bias: -1});
8695    },
8696    goLineRight: function(cm) {
8697      cm.extendSelectionsBy(function(range) {
8698        var top = cm.charCoords(range.head, "div").top + 5;
8699        return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
8700      }, sel_move);
8701    },
8702    goLineLeft: function(cm) {
8703      cm.extendSelectionsBy(function(range) {
8704        var top = cm.charCoords(range.head, "div").top + 5;
8705        return cm.coordsChar({left: 0, top: top}, "div");
8706      }, sel_move);
8707    },
8708    goLineLeftSmart: function(cm) {
8709      cm.extendSelectionsBy(function(range) {
8710        var top = cm.charCoords(range.head, "div").top + 5;
8711        var pos = cm.coordsChar({left: 0, top: top}, "div");
8712        if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
8713        return pos;
8714      }, sel_move);
8715    },
8716    goLineUp: function(cm) {cm.moveV(-1, "line");},
8717    goLineDown: function(cm) {cm.moveV(1, "line");},
8718    goPageUp: function(cm) {cm.moveV(-1, "page");},
8719    goPageDown: function(cm) {cm.moveV(1, "page");},
8720    goCharLeft: function(cm) {cm.moveH(-1, "char");},
8721    goCharRight: function(cm) {cm.moveH(1, "char");},
8722    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
8723    goColumnRight: function(cm) {cm.moveH(1, "column");},
8724    goWordLeft: function(cm) {cm.moveH(-1, "word");},
8725    goGroupRight: function(cm) {cm.moveH(1, "group");},
8726    goGroupLeft: function(cm) {cm.moveH(-1, "group");},
8727    goWordRight: function(cm) {cm.moveH(1, "word");},
8728    delCharBefore: function(cm) {cm.deleteH(-1, "char");},
8729    delCharAfter: function(cm) {cm.deleteH(1, "char");},
8730    delWordBefore: function(cm) {cm.deleteH(-1, "word");},
8731    delWordAfter: function(cm) {cm.deleteH(1, "word");},
8732    delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
8733    delGroupAfter: function(cm) {cm.deleteH(1, "group");},
8734    indentAuto: function(cm) {cm.indentSelection("smart");},
8735    indentMore: function(cm) {cm.indentSelection("add");},
8736    indentLess: function(cm) {cm.indentSelection("subtract");},
8737    insertTab: function(cm) {cm.replaceSelection("\t");},
8738    insertSoftTab: function(cm) {
8739      var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
8740      for (var i = 0; i < ranges.length; i++) {
8741        var pos = ranges[i].from();
8742        var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
8743        spaces.push(
vendor: 3,732 bytes, lines 8743-8820
8743new Array(tabSize - col % tabSize + 1).join(" "));
8744      }
8745      cm.replaceSelections(spaces);
8746    },
8747    defaultTab: function(cm) {
8748      if (cm.somethingSelected()) cm.indentSelection("add");
8749      else cm.execCommand("insertTab");
8750    },
8751    transposeChars: function(cm) {
8752      runInOp(cm, function() {
8753        var ranges = cm.listSelections(), newSel = [];
8754        for (var i = 0; i < ranges.length; i++) {
8755          var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
8756          if (line) {
8757            if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
8758            if (cur.ch > 0) {
8759              cur = new Pos(cur.line, cur.ch + 1);
8760              cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
8761                              Pos(cur.line, cur.ch - 2), cur, "+transpose");
8762            } else if (cur.line > cm.doc.first) {
8763              var prev = getLine(cm.doc, cur.line - 1).text;
8764              if (prev)
8765                cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
8766                                prev.charAt(prev.length - 1),
8767                                Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
8768            }
8769          }
8770          newSel.push(new Range(cur, cur));
8771        }
8772        cm.setSelections(newSel);
8773      });
8774    },
8775    newlineAndIndent: function(cm) {
8776      runInOp(cm, function() {
8777        var len = cm.listSelections().length;
8778        for (var i = 0; i < len; i++) {
8779          var range = cm.listSelections()[i];
8780          cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
8781          cm.indentLine(range.from().line + 1, null, true);
8782        }
8783        ensureCursorVisible(cm);
8784      });
8785    },
8786    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
8787  };
8788
8789
8790  // STANDARD KEYMAPS
8791
8792  var keyMap = CodeMirror.keyMap = {};
8793
8794  keyMap.basic = {
8795    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
8796    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
8797    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
8798    "Tab": "defaultTab", "Shift-Tab": "indentAuto",
8799    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
8800    "Esc": "singleSelection"
8801  };
8802  // Note that the save and find-related commands aren't defined by
8803  // default. User code or addons can define them. Unknown commands
8804  // are simply ignored.
8805  keyMap.pcDefault = {
8806    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
8807    "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
8808    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
8809    "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
8810    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
8811    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
8812    "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
8813    fallthrough: "basic"
8814  };
8815  // Very basic readline/emacs-style bindings, which are standard on Mac.
8816  keyMap.emacsy = {
8817    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
8818    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
8819    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
8820    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars
vendor: 30,541 bytes, lines 8820-9582
8820"
8821  };
8822  keyMap.macDefault = {
8823    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
8824    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
8825    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
8826    "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
8827    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
8828    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
8829    "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
8830    fallthrough: ["basic", "emacsy"]
8831  };
8832  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
8833
8834  // KEYMAP DISPATCH
8835
8836  function normalizeKeyName(name) {
8837    var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
8838    var alt, ctrl, shift, cmd;
8839    for (var i = 0; i < parts.length - 1; i++) {
8840      var mod = parts[i];
8841      if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
8842      else if (/^a(lt)?$/i.test(mod)) alt = true;
8843      else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
8844      else if (/^s(hift)$/i.test(mod)) shift = true;
8845      else throw new Error("Unrecognized modifier name: " + mod);
8846    }
8847    if (alt) name = "Alt-" + name;
8848    if (ctrl) name = "Ctrl-" + name;
8849    if (cmd) name = "Cmd-" + name;
8850    if (shift) name = "Shift-" + name;
8851    return name;
8852  }
8853
8854  // This is a kludge to keep keymaps mostly working as raw objects
8855  // (backwards compatibility) while at the same time support features
8856  // like normalization and multi-stroke key bindings. It compiles a
8857  // new normalized keymap, and then updates the old object to reflect
8858  // this.
8859  CodeMirror.normalizeKeyMap = function(keymap) {
8860    var copy = {};
8861    for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
8862      var value = keymap[keyname];
8863      if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
8864      if (value == "...") { delete keymap[keyname]; continue; }
8865
8866      var keys = map(keyname.split(" "), normalizeKeyName);
8867      for (var i = 0; i < keys.length; i++) {
8868        var val, name;
8869        if (i == keys.length - 1) {
8870          name = keys.join(" ");
8871          val = value;
8872        } else {
8873          name = keys.slice(0, i + 1).join(" ");
8874          val = "...";
8875        }
8876        var prev = copy[name];
8877        if (!prev) copy[name] = val;
8878        else if (prev != val) throw new Error("Inconsistent bindings for " + name);
8879      }
8880      delete keymap[keyname];
8881    }
8882    for (var prop in copy) keymap[prop] = copy[prop];
8883    return keymap;
8884  };
8885
8886  var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
8887    map = getKeyMap(map);
8888    var found = map.call ? map.call(key, context) : map[key];
8889    if (found === false) return "nothing";
8890    if (found === "...") return "multi";
8891    if (found != null && handle(found)) return "handled";
8892
8893    if (map.fallthrough) {
8894      if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
8895        return lookupKey(key, map.fallthrough, handle, context);
8896      for (var i = 0; i < map.fallthrough.length; i++) {
8897        var result = lookupKey(key, map.fallthrough[i], handle, context);
8898        if (result) return result;
8899      }
8900    }
8901  };
8902
8903  // Modifier key presses don't count as 'real' key presses for the
8904  // purpose of keymap fallthrough.
8905  var isModifierKey = CodeMirror.isModifierKey = function(value) {
8906    var name = typeof value == "string" ? value : keyNames[value.keyCode];
8907    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
8908  };
8909
8910  // Look up the name of a key as indicated by an event object.
8911  var keyName = CodeMirror.keyName = function(event, noShift) {
8912    if (presto && event.keyCode == 34 && event["char"]) return false;
8913    var base = keyNames[event.keyCode], name = base;
8914    if (name == null || event.altGraphKey) return false;
8915    if (event.altKey && base != "Alt") name = "Alt-" + name;
8916    if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
8917    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
8918    if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
8919    return name;
8920  };
8921
8922  function getKeyMap(val) {
8923    return typeof val == "string" ? keyMap[val] : val;
8924  }
8925
8926  // FROMTEXTAREA
8927
8928  CodeMirror.fromTextArea = function(textarea, options) {
8929    options = options ? copyObj(options) : {};
8930    options.value = textarea.value;
8931    if (!options.tabindex && textarea.tabIndex)
8932      options.tabindex = textarea.tabIndex;
8933    if (!options.placeholder && textarea.placeholder)
8934      options.placeholder = textarea.placeholder;
8935    // Set autofocus to true if this textarea is focused, or if it has
8936    // autofocus and no other element is focused.
8937    if (options.autofocus == null) {
8938      var hasFocus = activeElt();
8939      options.autofocus = hasFocus == textarea ||
8940        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
8941    }
8942
8943    function save() {textarea.value = cm.getValue();}
8944    if (textarea.form) {
8945      on(textarea.form, "submit", save);
8946      // Deplorable hack to make the submit method do the right thing.
8947      if (!options.leaveSubmitMethodAlone) {
8948        var form = textarea.form, realSubmit = form.submit;
8949        try {
8950          var wrappedSubmit = form.submit = function() {
8951            save();
8952            form.submit = realSubmit;
8953            form.submit();
8954            form.submit = wrappedSubmit;
8955          };
8956        } catch(e) {}
8957      }
8958    }
8959
8960    options.finishInit = function(cm) {
8961      cm.save = save;
8962      cm.getTextArea = function() { return textarea; };
8963      cm.toTextArea = function() {
8964        cm.toTextArea = isNaN; // Prevent this from being ran twice
8965        save();
8966        textarea.parentNode.removeChild(cm.getWrapperElement());
8967        textarea.style.display = "";
8968        if (textarea.form) {
8969          off(textarea.form, "submit", save);
8970          if (typeof textarea.form.submit == "function")
8971            textarea.form.submit = realSubmit;
8972        }
8973      };
8974    };
8975
8976    textarea.style.display = "none";
8977    var cm = CodeMirror(function(node) {
8978      textarea.parentNode.insertBefore(node, textarea.nextSibling);
8979    }, options);
8980    return cm;
8981  };
8982
8983  // STRING STREAM
8984
8985  // Fed to the mode parsers, provides helper functions to make
8986  // parsers more succinct.
8987
8988  var StringStream = CodeMirror.StringStream = function(string, tabSize) {
8989    this.pos = this.start = 0;
8990    this.string = string;
8991    this.tabSize = tabSize || 8;
8992    this.lastColumnPos = this.lastColumnValue = 0;
8993    this.lineStart = 0;
8994  };
8995
8996  StringStream.prototype = {
8997    eol: function() {return this.pos >= this.string.length;},
8998    sol: function() {return this.pos == this.lineStart;},
8999    peek: function() {return this.string.charAt(this.pos) || undefined;},
9000    next: function() {
9001      if (this.pos < this.string.length)
9002        return this.string.charAt(this.pos++);
9003    },
9004    eat: function(match) {
9005      var ch = this.string.charAt(this.pos);
9006      if (typeof match == "string") var ok = ch == match;
9007      else var ok = ch && (match.test ? match.test(ch) : match(ch));
9008      if (ok) {++this.pos; return ch;}
9009    },
9010    eatWhile: function(match) {
9011      var start = this.pos;
9012      while (this.eat(match)){}
9013      return this.pos > start;
9014    },
9015    eatSpace: function() {
9016      var start = this.pos;
9017      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
9018      return this.pos > start;
9019    },
9020    skipToEnd: function() {this.pos = this.string.length;},
9021    skipTo: function(ch) {
9022      var found = this.string.indexOf(ch, this.pos);
9023      if (found > -1) {this.pos = found; return true;}
9024    },
9025    backUp: function(n) {this.pos -= n;},
9026    column: function() {
9027      if (this.lastColumnPos < this.start) {
9028        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
9029        this.lastColumnPos = this.start;
9030      }
9031      return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
9032    },
9033    indentation: function() {
9034      return countColumn(this.string, null, this.tabSize) -
9035        (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
9036    },
9037    match: function(pattern, consume, caseInsensitive) {
9038      if (typeof pattern == "string") {
9039        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
9040        var substr = this.string.substr(this.pos, pattern.length);
9041        if (cased(substr) == cased(pattern)) {
9042          if (consume !== false) this.pos += pattern.length;
9043          return true;
9044        }
9045      } else {
9046        var match = this.string.slice(this.pos).match(pattern);
9047        if (match && match.index > 0) return null;
9048        if (match && consume !== false) this.pos += match[0].length;
9049        return match;
9050      }
9051    },
9052    current: function(){return this.string.slice(this.start, this.pos);},
9053    hideFirstChars: function(n, inner) {
9054      this.lineStart += n;
9055      try { return inner(); }
9056      finally { this.lineStart -= n; }
9057    }
9058  };
9059
9060  // TEXTMARKERS
9061
9062  // Created with markText and setBookmark methods. A TextMarker is a
9063  // handle that can be used to clear or find a marked position in the
9064  // document. Line objects hold arrays (markedSpans) containing
9065  // {from, to, marker} object pointing to such marker objects, and
9066  // indicating that such a marker is present on that line. Multiple
9067  // lines may point to the same marker when it spans across lines.
9068  // The spans will have null for their from/to properties when the
9069  // marker continues beyond the start/end of the line. Markers have
9070  // links back to the lines they currently touch.
9071
9072  var nextMarkerId = 0;
9073
9074  var TextMarker = CodeMirror.TextMarker = function(doc, type) {
9075    this.lines = [];
9076    this.type = type;
9077    this.doc = doc;
9078    this.id = ++nextMarkerId;
9079  };
9080  eventMixin(TextMarker);
9081
9082  // Clear the marker.
9083  TextMarker.prototype.clear = function() {
9084    if (this.explicitlyCleared) return;
9085    var cm = this.doc.cm, withOp = cm && !cm.curOp;
9086    if (withOp) startOperation(cm);
9087    if (hasHandler(this, "clear")) {
9088      var found = this.find();
9089      if (found) signalLater(this, "clear", found.from, found.to);
9090    }
9091    var min = null, max = null;
9092    for (var i = 0; i < this.lines.length; ++i) {
9093      var line = this.lines[i];
9094      var span = getMarkedSpanFor(line.markedSpans, this);
9095      if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
9096      else if (cm) {
9097        if (span.to != null) max = lineNo(line);
9098        if (span.from != null) min = lineNo(line);
9099      }
9100      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
9101      if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
9102        updateLineHeight(line, textHeight(cm.display));
9103    }
9104    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
9105      var visual = visualLine(this.lines[i]), len = lineLength(visual);
9106      if (len > cm.display.maxLineLength) {
9107        cm.display.maxLine = visual;
9108        cm.display.maxLineLength = len;
9109        cm.display.maxLineChanged = true;
9110      }
9111    }
9112
9113    if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
9114    this.lines.length = 0;
9115    this.explicitlyCleared = true;
9116    if (this.atomic && this.doc.cantEdit) {
9117      this.doc.cantEdit = false;
9118      if (cm) reCheckSelection(cm.doc);
9119    }
9120    if (cm) signalLater(cm, "markerCleared", cm, this);
9121    if (withOp) endOperation(cm);
9122    if (this.parent) this.parent.clear();
9123  };
9124
9125  // Find the position of the marker in the document. Returns a {from,
9126  // to} object by default. Side can be passed to get a specific side
9127  // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
9128  // Pos objects returned contain a line object, rather than a line
9129  // number (used to prevent looking up the same line twice).
9130  TextMarker.prototype.find = function(side, lineObj) {
9131    if (side == null && this.type == "bookmark") side = 1;
9132    var from, to;
9133    for (var i = 0; i < this.lines.length; ++i) {
9134      var line = this.lines[i];
9135      var span = getMarkedSpanFor(line.markedSpans, this);
9136      if (span.from != null) {
9137        from = Pos(lineObj ? line : lineNo(line), span.from);
9138        if (side == -1) return from;
9139      }
9140      if (span.to != null) {
9141        to = Pos(lineObj ? line : lineNo(line), span.to);
9142        if (side == 1) return to;
9143      }
9144    }
9145    return from && {from: from, to: to};
9146  };
9147
9148  // Signals that the marker's widget changed, and surrounding layout
9149  // should be recomputed.
9150  TextMarker.prototype.changed = function() {
9151    var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
9152    if (!pos || !cm) return;
9153    runInOp(cm, function() {
9154      var line = pos.line, lineN = lineNo(pos.line);
9155      var view = findViewForLine(cm, lineN);
9156      if (view) {
9157        clearLineMeasurementCacheFor(view);
9158        cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
9159      }
9160      cm.curOp.updateMaxLine = true;
9161      if (!lineIsHidden(widget.doc, line) && widget.height != null) {
9162        var oldHeight = widget.height;
9163        widget.height = null;
9164        var dHeight = widgetHeight(widget) - oldHeight;
9165        if (dHeight)
9166          updateLineHeight(line, line.height + dHeight);
9167      }
9168    });
9169  };
9170
9171  TextMarker.prototype.attachLine = function(line) {
9172    if (!this.lines.length && this.doc.cm) {
9173      var op = this.doc.cm.curOp;
9174      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
9175        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
9176    }
9177    this.lines.push(line);
9178  };
9179  TextMarker.prototype.detachLine = function(line) {
9180    this.lines.splice(indexOf(this.lines, line), 1);
9181    if (!this.lines.length && this.doc.cm) {
9182      var op = this.doc.cm.curOp;
9183      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
9184    }
9185  };
9186
9187  // Collapsed markers have unique ids, in order to be able to order
9188  // them, which is needed for uniquely determining an outer marker
9189  // when they overlap (they may nest, but not partially overlap).
9190  var nextMarkerId = 0;
9191
9192  // Create a marker, wire it up to the right lines, and
9193  function markText(doc, from, to, options, type) {
9194    // Shared markers (across linked documents) are handled separately
9195    // (markTextShared will call out to this again, once per
9196    // document).
9197    if (options && options.shared) return markTextShared(doc, from, to, options, type);
9198    // Ensure we are in an operation.
9199    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
9200
9201    var marker = new TextMarker(doc, type), diff = cmp(from, to);
9202    if (options) copyObj(options, marker, false);
9203    // Don't connect empty markers unless clearWhenEmpty is false
9204    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
9205      return marker;
9206    if (marker.replacedWith) {
9207      // Showing up as a widget implies collapsed (widget replaces text)
9208      marker.collapsed = true;
9209      marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
9210      if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
9211      if (options.insertLeft) marker.widgetNode.insertLeft = true;
9212    }
9213    if (marker.collapsed) {
9214      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
9215          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
9216        throw new Error("Inserting collapsed marker partially overlapping an existing one");
9217      sawCollapsedSpans = true;
9218    }
9219
9220    if (marker.addToHistory)
9221      addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
9222
9223    var curLine = from.line, cm = doc.cm, updateMaxLine;
9224    doc.iter(curLine, to.line + 1, function(line) {
9225      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
9226        updateMaxLine = true;
9227      if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
9228      addMarkedSpan(line, new MarkedSpan(marker,
9229                                         curLine == from.line ? from.ch : null,
9230                                         curLine == to.line ? to.ch : null));
9231      ++curLine;
9232    });
9233    // lineIsHidden depends on the presence of the spans, so needs a second pass
9234    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
9235      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
9236    });
9237
9238    if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
9239
9240    if (marker.readOnly) {
9241      sawReadOnlySpans = true;
9242      if (doc.history.done.length || doc.history.undone.length)
9243        doc.clearHistory();
9244    }
9245    if (marker.collapsed) {
9246      marker.id = ++nextMarkerId;
9247      marker.atomic = true;
9248    }
9249    if (cm) {
9250      // Sync editor state
9251      if (updateMaxLine) cm.curOp.updateMaxLine = true;
9252      if (marker.collapsed)
9253        regChange(cm, from.line, to.line + 1);
9254      else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
9255        for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
9256      if (marker.atomic) reCheckSelection(cm.doc);
9257      signalLater(cm, "markerAdded", cm, marker);
9258    }
9259    return marker;
9260  }
9261
9262  // SHARED TEXTMARKERS
9263
9264  // A shared marker spans multiple linked documents. It is
9265  // implemented as a meta-marker-object controlling multiple normal
9266  // markers.
9267  var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
9268    this.markers = markers;
9269    this.primary = primary;
9270    for (var i = 0; i < markers.length; ++i)
9271      markers[i].parent = this;
9272  };
9273  eventMixin(SharedTextMarker);
9274
9275  SharedTextMarker.prototype.clear = function() {
9276    if (this.explicitlyCleared) return;
9277    this.explicitlyCleared = true;
9278    for (var i = 0; i < this.markers.length; ++i)
9279      this.markers[i].clear();
9280    signalLater(this, "clear");
9281  };
9282  SharedTextMarker.prototype.find = function(side, lineObj) {
9283    return this.primary.find(side, lineObj);
9284  };
9285
9286  function markTextShared(doc, from, to, options, type) {
9287    options = copyObj(options);
9288    options.shared = false;
9289    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
9290    var widget = options.widgetNode;
9291    linkedDocs(doc, function(doc) {
9292      if (widget) options.widgetNode = widget.cloneNode(true);
9293      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
9294      for (var i = 0; i < doc.linked.length; ++i)
9295        if (doc.linked[i].isParent) return;
9296      primary = lst(markers);
9297    });
9298    return new SharedTextMarker(markers, primary);
9299  }
9300
9301  function findSharedMarkers(doc) {
9302    return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
9303                         function(m) { return m.parent; });
9304  }
9305
9306  function copySharedMarkers(doc, markers) {
9307    for (var i = 0; i < markers.length; i++) {
9308      var marker = markers[i], pos = marker.find();
9309      var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
9310      if (cmp(mFrom, mTo)) {
9311        var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
9312        marker.markers.push(subMark);
9313        subMark.parent = marker;
9314      }
9315    }
9316  }
9317
9318  function detachSharedMarkers(markers) {
9319    for (var i = 0; i < markers.length; i++) {
9320      var marker = markers[i], linked = [marker.primary.doc];;
9321      linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
9322      for (var j = 0; j < marker.markers.length; j++) {
9323        var subMarker = marker.markers[j];
9324        if (indexOf(linked, subMarker.doc) == -1) {
9325          subMarker.parent = null;
9326          marker.markers.splice(j--, 1);
9327        }
9328      }
9329    }
9330  }
9331
9332  // TEXTMARKER SPANS
9333
9334  function MarkedSpan(marker, from, to) {
9335    this.marker = marker;
9336    this.from = from; this.to = to;
9337  }
9338
9339  // Search an array of spans for a span matching the given marker.
9340  function getMarkedSpanFor(spans, marker) {
9341    if (spans) for (var i = 0; i < spans.length; ++i) {
9342      var span = spans[i];
9343      if (span.marker == marker) return span;
9344    }
9345  }
9346  // Remove a span from an array, returning undefined if no spans are
9347  // left (we don't store arrays for lines without spans).
9348  function removeMarkedSpan(spans, span) {
9349    for (var r, i = 0; i < spans.length; ++i)
9350      if (spans[i] != span) (r || (r = [])).push(spans[i]);
9351    return r;
9352  }
9353  // Add a span to a line.
9354  function addMarkedSpan(line, span) {
9355    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
9356    span.marker.attachLine(line);
9357  }
9358
9359  // Used for the algorithm that adjusts markers for a change in the
9360  // document. These functions cut an array of spans at a given
9361  // character position, returning an array of remaining chunks (or
9362  // undefined if nothing remains).
9363  function markedSpansBefore(old, startCh, isInsert) {
9364    if (old) for (var i = 0, nw; i < old.length; ++i) {
9365      var span = old[i], marker = span.marker;
9366      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
9367      if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
9368        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
9369        (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
9370      }
9371    }
9372    return nw;
9373  }
9374  function markedSpansAfter(old, endCh, isInsert) {
9375    if (old) for (var i = 0, nw; i < old.length; ++i) {
9376      var span = old[i], marker = span.marker;
9377      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
9378      if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
9379        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
9380        (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
9381                                              span.to == null ? null : span.to - endCh));
9382      }
9383    }
9384    return nw;
9385  }
9386
9387  // Given a change object, compute the new set of marker spans that
9388  // cover the line in which the change took place. Removes spans
9389  // entirely within the change, reconnects spans belonging to the
9390  // same marker that appear on both sides of the change, and cuts off
9391  // spans partially within the change. Returns an array of span
9392  // arrays with one element for each line in (after) the change.
9393  function stretchSpansOverChange(doc, change) {
9394    if (change.full) return null;
9395    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
9396    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
9397    if (!oldFirst && !oldLast) return null;
9398
9399    var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
9400    // Get the spans that 'stick out' on both sides
9401    var first = markedSpansBefore(oldFirst, startCh, isInsert);
9402    var last = markedSpansAfter(oldLast, endCh, isInsert);
9403
9404    // Next, merge those two ends
9405    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
9406    if (first) {
9407      // Fix up .to properties of first
9408      for (var i = 0; i < first.length; ++i) {
9409        var span = first[i];
9410        if (span.to == null) {
9411          var found = getMarkedSpanFor(last, span.marker);
9412          if (!found) span.to = startCh;
9413          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
9414        }
9415      }
9416    }
9417    if (last) {
9418      // Fix up .from in last (or move them into first in case of sameLine)
9419      for (var i = 0; i < last.length; ++i) {
9420        var span = last[i];
9421        if (span.to != null) span.to += offset;
9422        if (span.from == null) {
9423          var found = getMarkedSpanFor(first, span.marker);
9424          if (!found) {
9425            span.from = offset;
9426            if (sameLine) (first || (first = [])).push(span);
9427          }
9428        } else {
9429          span.from += offset;
9430          if (sameLine) (first || (first = [])).push(span);
9431        }
9432      }
9433    }
9434    // Make sure we didn't create any zero-length spans
9435    if (first) first = clearEmptySpans(first);
9436    if (last && last != first) last = clearEmptySpans(last);
9437
9438    var newMarkers = [first];
9439    if (!sameLine) {
9440      // Fill gap with whole-line-spans
9441      var gap = change.text.length - 2, gapMarkers;
9442      if (gap > 0 && first)
9443        for (var i = 0; i < first.length; ++i)
9444          if (first[i].to == null)
9445            (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
9446      for (var i = 0; i < gap; ++i)
9447        newMarkers.push(gapMarkers);
9448      newMarkers.push(last);
9449    }
9450    return newMarkers;
9451  }
9452
9453  // Remove spans that are empty and don't have a clearWhenEmpty
9454  // option of false.
9455  function clearEmptySpans(spans) {
9456    for (var i = 0; i < spans.length; ++i) {
9457      var span = spans[i];
9458      if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
9459        spans.splice(i--, 1);
9460    }
9461    if (!spans.length) return null;
9462    return spans;
9463  }
9464
9465  // Used for un/re-doing changes from the history. Combines the
9466  // result of computing the existing spans with the set of spans that
9467  // existed in the history (so that deleting around a span and then
9468  // undoing brings back the span).
9469  function mergeOldSpans(doc, change) {
9470    var old = getOldSpans(doc, change);
9471    var stretched = stretchSpansOverChange(doc, change);
9472    if (!old) return stretched;
9473    if (!stretched) return old;
9474
9475    for (var i = 0; i < old.length; ++i) {
9476      var oldCur = old[i], stretchCur = stretched[i];
9477      if (oldCur && stretchCur) {
9478        spans: for (var j = 0; j < stretchCur.length; ++j) {
9479          var span = stretchCur[j];
9480          for (var k = 0; k < oldCur.length; ++k)
9481            if (oldCur[k].marker == span.marker) continue spans;
9482          oldCur.push(span);
9483        }
9484      } else if (stretchCur) {
9485        old[i] = stretchCur;
9486      }
9487    }
9488    return old;
9489  }
9490
9491  // Used to 'clip' out readOnly ranges when making a change.
9492  function removeReadOnlyRanges(doc, from, to) {
9493    var markers = null;
9494    doc.iter(from.line, to.line + 1, function(line) {
9495      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
9496        var mark = line.markedSpans[i].marker;
9497        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
9498          (markers || (markers = [])).push(mark);
9499      }
9500    });
9501    if (!markers) return null;
9502    var parts = [{from: from, to: to}];
9503    for (var i = 0; i < markers.length; ++i) {
9504      var mk = markers[i], m = mk.find(0);
9505      for (var j = 0; j < parts.length; ++j) {
9506        var p = parts[j];
9507        if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
9508        var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
9509        if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
9510          newParts.push({from: p.from, to: m.from});
9511        if (dto > 0 || !mk.inclusiveRight && !dto)
9512          newParts.push({from: m.to, to: p.to});
9513        parts.splice.apply(parts, newParts);
9514        j += newParts.length - 1;
9515      }
9516    }
9517    return parts;
9518  }
9519
9520  // Connect or disconnect spans from a line.
9521  function detachMarkedSpans(line) {
9522    var spans = line.markedSpans;
9523    if (!spans) return;
9524    for (var i = 0; i < spans.length; ++i)
9525      spans[i].marker.detachLine(line);
9526    line.markedSpans = null;
9527  }
9528  function attachMarkedSpans(line, spans) {
9529    if (!spans) return;
9530    for (var i = 0; i < spans.length; ++i)
9531      spans[i].marker.attachLine(line);
9532    line.markedSpans = spans;
9533  }
9534
9535  // Helpers used when computing which overlapping collapsed span
9536  // counts as the larger one.
9537  function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
9538  function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
9539
9540  // Returns a number indicating which of two overlapping collapsed
9541  // spans is larger (and thus includes the other). Falls back to
9542  // comparing ids when the spans cover exactly the same range.
9543  function compareCollapsedMarkers(a, b) {
9544    var lenDiff = a.lines.length - b.lines.length;
9545    if (lenDiff != 0) return lenDiff;
9546    var aPos = a.find(), bPos = b.find();
9547    var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
9548    if (fromCmp) return -fromCmp;
9549    var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
9550    if (toCmp) return toCmp;
9551    return b.id - a.id;
9552  }
9553
9554  // Find out whether a line ends or starts in a collapsed span. If
9555  // so, return the marker for that span.
9556  function collapsedSpanAtSide(line, start) {
9557    var sps = sawCollapsedSpans && line.markedSpans, found;
9558    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
9559      sp = sps[i];
9560      if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
9561          (!found || compareCollapsedMarkers(found, sp.marker) < 0))
9562        found = sp.marker;
9563    }
9564    return found;
9565  }
9566  function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
9567  function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
9568
9569  // Test whether there exists a collapsed span that partially
9570  // overlaps (covers the start or end, but not both) of a new span.
9571  // Such overlap is not allowed.
9572  function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
9573    var line = getLine(doc, lineNo);
9574    var sps = sawCollapsedSpans && line.markedSpans;
9575    if (sps) for (var i = 0; i < sps.length; ++i) {
9576      var sp = sps[i];
9577      if (!sp.marker.collapsed) continue;
9578      var found = sp.marker.find(0);
9579      var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
9580      var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
9581      if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
9582      if (fromCmp <= 0 && (
vendor: 4,962 bytes, lines 9582-9711
9582cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
9583          fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
9584        return true;
9585    }
9586  }
9587
9588  // A visual line is a line as drawn on the screen. Folding, for
9589  // example, can cause multiple logical lines to appear on the same
9590  // visual line. This finds the start of the visual line that the
9591  // given line is part of (usually that is the line itself).
9592  function visualLine(line) {
9593    var merged;
9594    while (merged = collapsedSpanAtStart(line))
9595      line = merged.find(-1, true).line;
9596    return line;
9597  }
9598
9599  // Returns an array of logical lines that continue the visual line
9600  // started by the argument, or undefined if there are no such lines.
9601  function visualLineContinued(line) {
9602    var merged, lines;
9603    while (merged = collapsedSpanAtEnd(line)) {
9604      line = merged.find(1, true).line;
9605      (lines || (lines = [])).push(line);
9606    }
9607    return lines;
9608  }
9609
9610  // Get the line number of the start of the visual line that the
9611  // given line number is part of.
9612  function visualLineNo(doc, lineN) {
9613    var line = getLine(doc, lineN), vis = visualLine(line);
9614    if (line == vis) return lineN;
9615    return lineNo(vis);
9616  }
9617  // Get the line number of the start of the next visual line after
9618  // the given line.
9619  function visualLineEndNo(doc, lineN) {
9620    if (lineN > doc.lastLine()) return lineN;
9621    var line = getLine(doc, lineN), merged;
9622    if (!lineIsHidden(doc, line)) return lineN;
9623    while (merged = collapsedSpanAtEnd(line))
9624      line = merged.find(1, true).line;
9625    return lineNo(line) + 1;
9626  }
9627
9628  // Compute whether a line is hidden. Lines count as hidden when they
9629  // are part of a visual line that starts with another line, or when
9630  // they are entirely covered by collapsed, non-widget span.
9631  function lineIsHidden(doc, line) {
9632    var sps = sawCollapsedSpans && line.markedSpans;
9633    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
9634      sp = sps[i];
9635      if (!sp.marker.collapsed) continue;
9636      if (sp.from == null) return true;
9637      if (sp.marker.widgetNode) continue;
9638      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
9639        return true;
9640    }
9641  }
9642  function lineIsHiddenInner(doc, line, span) {
9643    if (span.to == null) {
9644      var end = span.marker.find(1, true);
9645      return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
9646    }
9647    if (span.marker.inclusiveRight && span.to == line.text.length)
9648      return true;
9649    for (var sp, i = 0; i < line.markedSpans.length; ++i) {
9650      sp = line.markedSpans[i];
9651      if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
9652          (sp.to == null || sp.to != span.from) &&
9653          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
9654          lineIsHiddenInner(doc, line, sp)) return true;
9655    }
9656  }
9657
9658  // LINE WIDGETS
9659
9660  // Line widgets are block elements displayed above or below a line.
9661
9662  var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
9663    if (options) for (var opt in options) if (options.hasOwnProperty(opt))
9664      this[opt] = options[opt];
9665    this.doc = doc;
9666    this.node = node;
9667  };
9668  eventMixin(LineWidget);
9669
9670  function adjustScrollWhenAboveVisible(cm, line, diff) {
9671    if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
9672      addToScrollPos(cm, null, diff);
9673  }
9674
9675  LineWidget.prototype.clear = function() {
9676    var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
9677    if (no == null || !ws) return;
9678    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
9679    if (!ws.length) line.widgets = null;
9680    var height = widgetHeight(this);
9681    updateLineHeight(line, Math.max(0, line.height - height));
9682    if (cm) runInOp(cm, function() {
9683      adjustScrollWhenAboveVisible(cm, line, -height);
9684      regLineChange(cm, no, "widget");
9685    });
9686  };
9687  LineWidget.prototype.changed = function() {
9688    var oldH = this.height, cm = this.doc.cm, line = this.line;
9689    this.height = null;
9690    var diff = widgetHeight(this) - oldH;
9691    if (!diff) return;
9692    updateLineHeight(line, line.height + diff);
9693    if (cm) runInOp(cm, function() {
9694      cm.curOp.forceUpdate = true;
9695      adjustScrollWhenAboveVisible(cm, line, diff);
9696    });
9697  };
9698
9699  function widgetHeight(widget) {
9700    if (widget.height != null) return widget.height;
9701    var cm = widget.doc.cm;
9702    if (!cm) return 0;
9703    if (!contains(document.body, widget.node)) {
9704      var parentStyle = "position: relative;";
9705      if (widget.coverGutter)
9706        parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
9707      if (widget.noHScroll)
9708        parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
9709      removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
9710    }
9711    return widget.height = widget.n
vendor: 9,482 bytes, lines 9711-9948
9711ode.offsetHeight;
9712  }
9713
9714  function addLineWidget(doc, handle, node, options) {
9715    var widget = new LineWidget(doc, node, options);
9716    var cm = doc.cm;
9717    if (cm && widget.noHScroll) cm.display.alignWidgets = true;
9718    changeLine(doc, handle, "widget", function(line) {
9719      var widgets = line.widgets || (line.widgets = []);
9720      if (widget.insertAt == null) widgets.push(widget);
9721      else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
9722      widget.line = line;
9723      if (cm && !lineIsHidden(doc, line)) {
9724        var aboveVisible = heightAtLine(line) < doc.scrollTop;
9725        updateLineHeight(line, line.height + widgetHeight(widget));
9726        if (aboveVisible) addToScrollPos(cm, null, widget.height);
9727        cm.curOp.forceUpdate = true;
9728      }
9729      return true;
9730    });
9731    return widget;
9732  }
9733
9734  // LINE DATA STRUCTURE
9735
9736  // Line objects. These hold state related to a line, including
9737  // highlighting info (the styles array).
9738  var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
9739    this.text = text;
9740    attachMarkedSpans(this, markedSpans);
9741    this.height = estimateHeight ? estimateHeight(this) : 1;
9742  };
9743  eventMixin(Line);
9744  Line.prototype.lineNo = function() { return lineNo(this); };
9745
9746  // Change the content (text, markers) of a line. Automatically
9747  // invalidates cached information and tries to re-estimate the
9748  // line's height.
9749  function updateLine(line, text, markedSpans, estimateHeight) {
9750    line.text = text;
9751    if (line.stateAfter) line.stateAfter = null;
9752    if (line.styles) line.styles = null;
9753    if (line.order != null) line.order = null;
9754    detachMarkedSpans(line);
9755    attachMarkedSpans(line, markedSpans);
9756    var estHeight = estimateHeight ? estimateHeight(line) : 1;
9757    if (estHeight != line.height) updateLineHeight(line, estHeight);
9758  }
9759
9760  // Detach a line from the document tree and its markers.
9761  function cleanUpLine(line) {
9762    line.parent = null;
9763    detachMarkedSpans(line);
9764  }
9765
9766  function extractLineClasses(type, output) {
9767    if (type) for (;;) {
9768      var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
9769      if (!lineClass) break;
9770      type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
9771      var prop = lineClass[1] ? "bgClass" : "textClass";
9772      if (output[prop] == null)
9773        output[prop] = lineClass[2];
9774      else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
9775        output[prop] += " " + lineClass[2];
9776    }
9777    return type;
9778  }
9779
9780  function callBlankLine(mode, state) {
9781    if (mode.blankLine) return mode.blankLine(state);
9782    if (!mode.innerMode) return;
9783    var inner = CodeMirror.innerMode(mode, state);
9784    if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
9785  }
9786
9787  function readToken(mode, stream, state, inner) {
9788    for (var i = 0; i < 10; i++) {
9789      if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
9790      var style = mode.token(stream, state);
9791      if (stream.pos > stream.start) return style;
9792    }
9793    throw new Error("Mode " + mode.name + " failed to advance stream.");
9794  }
9795
9796  // Utility for getTokenAt and getLineTokens
9797  function takeToken(cm, pos, precise, asArray) {
9798    function getObj(copy) {
9799      return {start: stream.start, end: stream.pos,
9800              string: stream.current(),
9801              type: style || null,
9802              state: copy ? copyState(doc.mode, state) : state};
9803    }
9804
9805    var doc = cm.doc, mode = doc.mode, style;
9806    pos = clipPos(doc, pos);
9807    var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
9808    var stream = new StringStream(line.text, cm.options.tabSize), tokens;
9809    if (asArray) tokens = [];
9810    while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
9811      stream.start = stream.pos;
9812      style = readToken(mode, stream, state);
9813      if (asArray) tokens.push(getObj(true));
9814    }
9815    return asArray ? tokens : getObj();
9816  }
9817
9818  // Run the given mode's parser over a line, calling f for each token.
9819  function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
9820    var flattenSpans = mode.flattenSpans;
9821    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
9822    var curStart = 0, curStyle = null;
9823    var stream = new StringStream(text, cm.options.tabSize), style;
9824    var inner = cm.options.addModeClass && [null];
9825    if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
9826    while (!stream.eol()) {
9827      if (stream.pos > cm.options.maxHighlightLength) {
9828        flattenSpans = false;
9829        if (forceToEnd) processLine(cm, text, state, stream.pos);
9830        stream.pos = text.length;
9831        style = null;
9832      } else {
9833        style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
9834      }
9835      if (inner) {
9836        var mName = inner[0].name;
9837        if (mName) style = "m-" + (style ? mName + " " + style : mName);
9838      }
9839      if (!flattenSpans || curStyle != style) {
9840        while (curStart < stream.start) {
9841          curStart = Math.min(stream.start, curStart + 50000);
9842          f(curStart, curStyle);
9843        }
9844        curStyle = style;
9845      }
9846      stream.start = stream.pos;
9847    }
9848    while (curStart < stream.pos) {
9849      // Webkit seems to refuse to render text nodes longer than 57444 characters
9850      var pos = Math.min(stream.pos, curStart + 50000);
9851      f(pos, curStyle);
9852      curStart = pos;
9853    }
9854  }
9855
9856  // Compute a style array (an array starting with a mode generation
9857  // -- for invalidation -- followed by pairs of end positions and
9858  // style strings), which is used to highlight the tokens on the
9859  // line.
9860  function highlightLine(cm, line, state, forceToEnd) {
9861    // A styles array always starts with a number identifying the
9862    // mode/overlays that it is based on (for easy invalidation).
9863    var st = [cm.state.modeGen], lineClasses = {};
9864    // Compute the base array of styles
9865    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
9866      st.push(end, style);
9867    }, lineClasses, forceToEnd);
9868
9869    // Run overlays, adjust style array.
9870    for (var o = 0; o < cm.state.overlays.length; ++o) {
9871      var overlay = cm.state.overlays[o], i = 1, at = 0;
9872      runMode(cm, line.text, overlay.mode, true, function(end, style) {
9873        var start = i;
9874        // Ensure there's a token end at the current position, and that i points at it
9875        while (at < end) {
9876          var i_end = st[i];
9877          if (i_end > end)
9878            st.splice(i, 1, end, st[i+1], i_end);
9879          i += 2;
9880          at = Math.min(end, i_end);
9881        }
9882        if (!style) return;
9883        if (overlay.opaque) {
9884          st.splice(start, i - start, end, "cm-overlay " + style);
9885          i = start + 2;
9886        } else {
9887          for (; start < i; start += 2) {
9888            var cur = st[start+1];
9889            st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
9890          }
9891        }
9892      }, lineClasses);
9893    }
9894
9895    return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
9896  }
9897
9898  function getLineStyles(cm, line, updateFrontier) {
9899    if (!line.styles || line.styles[0] != cm.state.modeGen) {
9900      var state = getStateBefore(cm, lineNo(line));
9901      var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);
9902      line.stateAfter = state;
9903      line.styles = result.styles;
9904      if (result.classes) line.styleClasses = result.classes;
9905      else if (line.styleClasses) line.styleClasses = null;
9906      if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
9907    }
9908    return line.styles;
9909  }
9910
9911  // Lightweight form of highlight -- proceed over this line and
9912  // update state, but don't save a style array. Used for lines that
9913  // aren't currently visible.
9914  function processLine(cm, text, state, startAt) {
9915    var mode = cm.doc.mode;
9916    var stream = new StringStream(text, cm.options.tabSize);
9917    stream.start = stream.pos = startAt || 0;
9918    if (text == "") callBlankLine(mode, state);
9919    while (!stream.eol()) {
9920      readToken(mode, stream, state);
9921      stream.start = stream.pos;
9922    }
9923  }
9924
9925  // Convert a style as returned by a mode (either null, or a string
9926  // containing one or more styles) to a CSS style. This is cached,
9927  // and also looks for line-wide styles.
9928  var styleToClassCache = {}, styleToClassCacheWithMode = {};
9929  function interpretTokenStyle(style, options) {
9930    if (!style || /^\s*$/.test(style)) return null;
9931    var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
9932    return cache[style] ||
9933      (cache[style] = style.replace(/\S+/g, "cm-$&"));
9934  }
9935
9936  // Render the DOM representation of the text of a line. Also builds
9937  // up a 'line map', which points at the DOM nodes that represent
9938  // specific stretches of text, and is used by the measuring code.
9939  // The returned object contains the DOM node, this map, and
9940  // information about line-wide styles that were set by the mode.
9941  function buildLineContent(cm, lineView) {
9942    // The padding-right forces the element to have a 'border', which
9943    // is needed on Webkit to be able to get line-level bounding
9944    // rectangles for it (in measureChar).
9945    var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
9946    var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
9947                   col: 0, pos: 0, cm: cm,
9948                   
vendor: 644 bytes, lines 9948-9960
9948splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
9949    lineView.measure = {};
9950
9951    // Iterate over the logical lines that make up this visual line.
9952    for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
9953      var line = i ? lineView.rest[i - 1] : lineView.line, order;
9954      builder.pos = 0;
9955      builder.addToken = buildToken;
9956      // Optionally wire in some hacks into the token-rendering
9957      // algorithm, to deal with browser quirks.
9958      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
9959        builder.addToken = buildTokenBadBidi(builder.addToken, order);
9960      builder.map = [];
9961      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
9962      insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
9963      if (line.styleClasses) {
9964        if (line.styleClasses.bgClass)
9965          builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
9966        if (line.styleClasses.textClass)
9967          builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
9968      }
9969
9970      // Ensure at least a single node is present, for measuring.
9971      if (builder.map.length == 0)
9972        builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
9973
9974      // Store the map and a cache object for the current logical line
9975      if (i == 0) {
9976        lineView.measure.map = builder.map;
9977        lineView.measure.cache = {};
9978      } else {
9979        (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
9980        (lineView.measure.caches || (lineView.measure.caches = [])).push({});
9981      }
9982    }
9983
9984    // See issue #2901
9985    if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
9986      builder.content.className = "cm-tab-wrap-hack";
9987
9988    signal(cm, "renderLine", cm, lineView.line, builder.pre);
9989    if (builder.pre.className)
vendor: 28,432 bytes, lines 9990-10679
9990      builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
9991
9992    return builder;
9993  }
9994
9995  function defaultSpecialCharPlaceholder(ch) {
9996    var token = elt("span", "\u2022", "cm-invalidchar");
9997    token.title = "\\u" + ch.charCodeAt(0).toString(16);
9998    token.setAttribute("aria-label", token.title);
9999    return token;
10000  }
10001
10002  // Build up the DOM representation for a single token, and add it to
10003  // the line map. Takes care to render special characters separately.
10004  function buildToken(builder, text, style, startStyle, endStyle, title, css) {
10005    if (!text) return;
10006    var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
10007    var special = builder.cm.state.specialChars, mustWrap = false;
10008    if (!special.test(text)) {
10009      builder.col += text.length;
10010      var content = document.createTextNode(displayText);
10011      builder.map.push(builder.pos, builder.pos + text.length, content);
10012      if (ie && ie_version < 9) mustWrap = true;
10013      builder.pos += text.length;
10014    } else {
10015      var content = document.createDocumentFragment(), pos = 0;
10016      while (true) {
10017        special.lastIndex = pos;
10018        var m = special.exec(text);
10019        var skipped = m ? m.index - pos : text.length - pos;
10020        if (skipped) {
10021          var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
10022          if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
10023          else content.appendChild(txt);
10024          builder.map.push(builder.pos, builder.pos + skipped, txt);
10025          builder.col += skipped;
10026          builder.pos += skipped;
10027        }
10028        if (!m) break;
10029        pos += skipped + 1;
10030        if (m[0] == "\t") {
10031          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
10032          var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
10033          txt.setAttribute("role", "presentation");
10034          txt.setAttribute("cm-text", "\t");
10035          builder.col += tabWidth;
10036        } else if (m[0] == "\r" || m[0] == "\n") {
10037          var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
10038          txt.setAttribute("cm-text", m[0]);
10039          builder.col += 1;
10040        } else {
10041          var txt = builder.cm.options.specialCharPlaceholder(m[0]);
10042          txt.setAttribute("cm-text", m[0]);
10043          if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
10044          else content.appendChild(txt);
10045          builder.col += 1;
10046        }
10047        builder.map.push(builder.pos, builder.pos + 1, txt);
10048        builder.pos++;
10049      }
10050    }
10051    if (style || startStyle || endStyle || mustWrap || css) {
10052      var fullStyle = style || "";
10053      if (startStyle) fullStyle += startStyle;
10054      if (endStyle) fullStyle += endStyle;
10055      var token = elt("span", [content], fullStyle, css);
10056      if (title) token.title = title;
10057      return builder.content.appendChild(token);
10058    }
10059    builder.content.appendChild(content);
10060  }
10061
10062  function splitSpaces(old) {
10063    var out = " ";
10064    for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
10065    out += " ";
10066    return out;
10067  }
10068
10069  // Work around nonsense dimensions being reported for stretches of
10070  // right-to-left text.
10071  function buildTokenBadBidi(inner, order) {
10072    return function(builder, text, style, startStyle, endStyle, title, css) {
10073      style = style ? style + " cm-force-border" : "cm-force-border";
10074      var start = builder.pos, end = start + text.length;
10075      for (;;) {
10076        // Find the part that overlaps with the start of this text
10077        for (var i = 0; i < order.length; i++) {
10078          var part = order[i];
10079          if (part.to > start && part.from <= start) break;
10080        }
10081        if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
10082        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
10083        startStyle = null;
10084        text = text.slice(part.to - start);
10085        start = part.to;
10086      }
10087    };
10088  }
10089
10090  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
10091    var widget = !ignoreWidget && marker.widgetNode;
10092    if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
10093    if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
10094      if (!widget)
10095        widget = builder.content.appendChild(document.createElement("span"));
10096      widget.setAttribute("cm-marker", marker.id);
10097    }
10098    if (widget) {
10099      builder.cm.display.input.setUneditable(widget);
10100      builder.content.appendChild(widget);
10101    }
10102    builder.pos += size;
10103  }
10104
10105  // Outputs a number of spans to make up a line, taking highlighting
10106  // and marked text into account.
10107  function insertLineContent(line, builder, styles) {
10108    var spans = line.markedSpans, allText = line.text, at = 0;
10109    if (!spans) {
10110      for (var i = 1; i < styles.length; i+=2)
10111        builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
10112      return;
10113    }
10114
10115    var len = allText.length, pos = 0, i = 1, text = "", style, css;
10116    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
10117    for (;;) {
10118      if (nextChange == pos) { // Update current marker set
10119        spanStyle = spanEndStyle = spanStartStyle = title = css = "";
10120        collapsed = null; nextChange = Infinity;
10121        var foundBookmarks = [];
10122        for (var j = 0; j < spans.length; ++j) {
10123          var sp = spans[j], m = sp.marker;
10124          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
10125            foundBookmarks.push(m);
10126          } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
10127            if (sp.to != null && sp.to != pos && nextChange > sp.to) {
10128              nextChange = sp.to;
10129              spanEndStyle = "";
10130            }
10131            if (m.className) spanStyle += " " + m.className;
10132            if (m.css) css = m.css;
10133            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
10134            if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
10135            if (m.title && !title) title = m.title;
10136            if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
10137              collapsed = sp;
10138          } else if (sp.from > pos && nextChange > sp.from) {
10139            nextChange = sp.from;
10140          }
10141        }
10142        if (collapsed && (collapsed.from || 0) == pos) {
10143          buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
10144                             collapsed.marker, collapsed.from == null);
10145          if (collapsed.to == null) return;
10146          if (collapsed.to == pos) collapsed = false;
10147        }
10148        if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
10149          buildCollapsedSpan(builder, 0, foundBookmarks[j]);
10150      }
10151      if (pos >= len) break;
10152
10153      var upto = Math.min(len, nextChange);
10154      while (true) {
10155        if (text) {
10156          var end = pos + text.length;
10157          if (!collapsed) {
10158            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
10159            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
10160                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
10161          }
10162          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
10163          pos = end;
10164          spanStartStyle = "";
10165        }
10166        text = allText.slice(at, at = styles[i++]);
10167        style = interpretTokenStyle(styles[i++], builder.cm.options);
10168      }
10169    }
10170  }
10171
10172  // DOCUMENT DATA STRUCTURE
10173
10174  // By default, updates that start and end at the beginning of a line
10175  // are treated specially, in order to make the association of line
10176  // widgets and marker elements with the text behave more intuitive.
10177  function isWholeLineUpdate(doc, change) {
10178    return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
10179      (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
10180  }
10181
10182  // Perform a change on the document data structure.
10183  function updateDoc(doc, change, markedSpans, estimateHeight) {
10184    function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
10185    function update(line, text, spans) {
10186      updateLine(line, text, spans, estimateHeight);
10187      signalLater(line, "change", line, change);
10188    }
10189    function linesFor(start, end) {
10190      for (var i = start, result = []; i < end; ++i)
10191        result.push(new Line(text[i], spansFor(i), estimateHeight));
10192      return result;
10193    }
10194
10195    var from = change.from, to = change.to, text = change.text;
10196    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
10197    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
10198
10199    // Adjust the line structure
10200    if (change.full) {
10201      doc.insert(0, linesFor(0, text.length));
10202      doc.remove(text.length, doc.size - text.length);
10203    } else if (isWholeLineUpdate(doc, change)) {
10204      // This is a whole-line replace. Treated specially to make
10205      // sure line objects move the way they are supposed to.
10206      var added = linesFor(0, text.length - 1);
10207      update(lastLine, lastLine.text, lastSpans);
10208      if (nlines) doc.remove(from.line, nlines);
10209      if (added.length) doc.insert(from.line, added);
10210    } else if (firstLine == lastLine) {
10211      if (text.length == 1) {
10212        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
10213      } else {
10214        var added = linesFor(1, text.length - 1);
10215        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
10216        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
10217        doc.insert(from.line + 1, added);
10218      }
10219    } else if (text.length == 1) {
10220      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
10221      doc.remove(from.line + 1, nlines);
10222    } else {
10223      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
10224      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
10225      var added = linesFor(1, text.length - 1);
10226      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
10227      doc.insert(from.line + 1, added);
10228    }
10229
10230    signalLater(doc, "change", doc, change);
10231  }
10232
10233  // The document is represented as a BTree consisting of leaves, with
10234  // chunk of lines in them, and branches, with up to ten leaves or
10235  // other branch nodes below them. The top node is always a branch
10236  // node, and is the document object itself (meaning it has
10237  // additional methods and properties).
10238  //
10239  // All nodes have parent links. The tree is used both to go from
10240  // line numbers to line objects, and to go from objects to numbers.
10241  // It also indexes by height, and is used to convert between height
10242  // and line object, and to find the total height of the document.
10243  //
10244  // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
10245
10246  function LeafChunk(lines) {
10247    this.lines = lines;
10248    this.parent = null;
10249    for (var i = 0, height = 0; i < lines.length; ++i) {
10250      lines[i].parent = this;
10251      height += lines[i].height;
10252    }
10253    this.height = height;
10254  }
10255
10256  LeafChunk.prototype = {
10257    chunkSize: function() { return this.lines.length; },
10258    // Remove the n lines at offset 'at'.
10259    removeInner: function(at, n) {
10260      for (var i = at, e = at + n; i < e; ++i) {
10261        var line = this.lines[i];
10262        this.height -= line.height;
10263        cleanUpLine(line);
10264        signalLater(line, "delete");
10265      }
10266      this.lines.splice(at, n);
10267    },
10268    // Helper used to collapse a small branch into a single leaf.
10269    collapse: function(lines) {
10270      lines.push.apply(lines, this.lines);
10271    },
10272    // Insert the given array of lines at offset 'at', count them as
10273    // having the given height.
10274    insertInner: function(at, lines, height) {
10275      this.height += height;
10276      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
10277      for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
10278    },
10279    // Used to iterate over a part of the tree.
10280    iterN: function(at, n, op) {
10281      for (var e = at + n; at < e; ++at)
10282        if (op(this.lines[at])) return true;
10283    }
10284  };
10285
10286  function BranchChunk(children) {
10287    this.children = children;
10288    var size = 0, height = 0;
10289    for (var i = 0; i < children.length; ++i) {
10290      var ch = children[i];
10291      size += ch.chunkSize(); height += ch.height;
10292      ch.parent = this;
10293    }
10294    this.size = size;
10295    this.height = height;
10296    this.parent = null;
10297  }
10298
10299  BranchChunk.prototype = {
10300    chunkSize: function() { return this.size; },
10301    removeInner: function(at, n) {
10302      this.size -= n;
10303      for (var i = 0; i < this.children.length; ++i) {
10304        var child = this.children[i], sz = child.chunkSize();
10305        if (at < sz) {
10306          var rm = Math.min(n, sz - at), oldHeight = child.height;
10307          child.removeInner(at, rm);
10308          this.height -= oldHeight - child.height;
10309          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
10310          if ((n -= rm) == 0) break;
10311          at = 0;
10312        } else at -= sz;
10313      }
10314      // If the result is smaller than 25 lines, ensure that it is a
10315      // single leaf node.
10316      if (this.size - n < 25 &&
10317          (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
10318        var lines = [];
10319        this.collapse(lines);
10320        this.children = [new LeafChunk(lines)];
10321        this.children[0].parent = this;
10322      }
10323    },
10324    collapse: function(lines) {
10325      for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
10326    },
10327    insertInner: function(at, lines, height) {
10328      this.size += lines.length;
10329      this.height += height;
10330      for (var i = 0; i < this.children.length; ++i) {
10331        var child = this.children[i], sz = child.chunkSize();
10332        if (at <= sz) {
10333          child.insertInner(at, lines, height);
10334          if (child.lines && child.lines.length > 50) {
10335            while (child.lines.length > 50) {
10336              var spilled = child.lines.splice(child.lines.length - 25, 25);
10337              var newleaf = new LeafChunk(spilled);
10338              child.height -= newleaf.height;
10339              this.children.splice(i + 1, 0, newleaf);
10340              newleaf.parent = this;
10341            }
10342            this.maybeSpill();
10343          }
10344          break;
10345        }
10346        at -= sz;
10347      }
10348    },
10349    // When a node has grown, check whether it should be split.
10350    maybeSpill: function() {
10351      if (this.children.length <= 10) return;
10352      var me = this;
10353      do {
10354        var spilled = me.children.splice(me.children.length - 5, 5);
10355        var sibling = new BranchChunk(spilled);
10356        if (!me.parent) { // Become the parent node
10357          var copy = new BranchChunk(me.children);
10358          copy.parent = me;
10359          me.children = [copy, sibling];
10360          me = copy;
10361        } else {
10362          me.size -= sibling.size;
10363          me.height -= sibling.height;
10364          var myIndex = indexOf(me.parent.children, me);
10365          me.parent.children.splice(myIndex + 1, 0, sibling);
10366        }
10367        sibling.parent = me.parent;
10368      } while (me.children.length > 10);
10369      me.parent.maybeSpill();
10370    },
10371    iterN: function(at, n, op) {
10372      for (var i = 0; i < this.children.length; ++i) {
10373        var child = this.children[i], sz = child.chunkSize();
10374        if (at < sz) {
10375          var used = Math.min(n, sz - at);
10376          if (child.iterN(at, used, op)) return true;
10377          if ((n -= used) == 0) break;
10378          at = 0;
10379        } else at -= sz;
10380      }
10381    }
10382  };
10383
10384  var nextDocId = 0;
10385  var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {
10386    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);
10387    if (firstLine == null) firstLine = 0;
10388
10389    BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
10390    this.first = firstLine;
10391    this.scrollTop = this.scrollLeft = 0;
10392    this.cantEdit = false;
10393    this.cleanGeneration = 1;
10394    this.frontier = firstLine;
10395    var start = Pos(firstLine, 0);
10396    this.sel = simpleSelection(start);
10397    this.history = new History(null);
10398    this.id = ++nextDocId;
10399    this.modeOption = mode;
10400    this.lineSep = lineSep;
10401
10402    if (typeof text == "string") text = this.splitLines(text);
10403    updateDoc(this, {from: start, to: start, text: text});
10404    setSelection(this, simpleSelection(start), sel_dontScroll);
10405  };
10406
10407  Doc.prototype = createObj(BranchChunk.prototype, {
10408    constructor: Doc,
10409    // Iterate over the document. Supports two forms -- with only one
10410    // argument, it calls that for each line in the document. With
10411    // three, it iterates over the range given by the first two (with
10412    // the second being non-inclusive).
10413    iter: function(from, to, op) {
10414      if (op) this.iterN(from - this.first, to - from, op);
10415      else this.iterN(this.first, this.first + this.size, from);
10416    },
10417
10418    // Non-public interface for adding and removing lines.
10419    insert: function(at, lines) {
10420      var height = 0;
10421      for (var i = 0; i < lines.length; ++i) height += lines[i].height;
10422      this.insertInner(at - this.first, lines, height);
10423    },
10424    remove: function(at, n) { this.removeInner(at - this.first, n); },
10425
10426    // From here, the methods are part of the public interface. Most
10427    // are also available from CodeMirror (editor) instances.
10428
10429    getValue: function(lineSep) {
10430      var lines = getLines(this, this.first, this.first + this.size);
10431      if (lineSep === false) return lines;
10432      return lines.join(lineSep || this.lineSeparator());
10433    },
10434    setValue: docMethodOp(function(code) {
10435      var top = Pos(this.first, 0), last = this.first + this.size - 1;
10436      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
10437                        text: this.splitLines(code), origin: "setValue", full: true}, true);
10438      setSelection(this, simpleSelection(top));
10439    }),
10440    replaceRange: function(code, from, to, origin) {
10441      from = clipPos(this, from);
10442      to = to ? clipPos(this, to) : from;
10443      replaceRange(this, code, from, to, origin);
10444    },
10445    getRange: function(from, to, lineSep) {
10446      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
10447      if (lineSep === false) return lines;
10448      return lines.join(lineSep || this.lineSeparator());
10449    },
10450
10451    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
10452
10453    getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
10454    getLineNumber: function(line) {return lineNo(line);},
10455
10456    getLineHandleVisualStart: function(line) {
10457      if (typeof line == "number") line = getLine(this, line);
10458      return visualLine(line);
10459    },
10460
10461    lineCount: function() {return this.size;},
10462    firstLine: function() {return this.first;},
10463    lastLine: function() {return this.first + this.size - 1;},
10464
10465    clipPos: function(pos) {return clipPos(this, pos);},
10466
10467    getCursor: function(start) {
10468      var range = this.sel.primary(), pos;
10469      if (start == null || start == "head") pos = range.head;
10470      else if (start == "anchor") pos = range.anchor;
10471      else if (start == "end" || start == "to" || start === false) pos = range.to();
10472      else pos = range.from();
10473      return pos;
10474    },
10475    listSelections: function() { return this.sel.ranges; },
10476    somethingSelected: function() {return this.sel.somethingSelected();},
10477
10478    setCursor: docMethodOp(function(line, ch, options) {
10479      setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
10480    }),
10481    setSelection: docMethodOp(function(anchor, head, options) {
10482      setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
10483    }),
10484    extendSelection: docMethodOp(function(head, other, options) {
10485      extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
10486    }),
10487    extendSelections: docMethodOp(function(heads, options) {
10488      extendSelections(this, clipPosArray(this, heads, options));
10489    }),
10490    extendSelectionsBy: docMethodOp(function(f, options) {
10491      extendSelections(this, map(this.sel.ranges, f), options);
10492    }),
10493    setSelections: docMethodOp(function(ranges, primary, options) {
10494      if (!ranges.length) return;
10495      for (var i = 0, out = []; i < ranges.length; i++)
10496        out[i] = new Range(clipPos(this, ranges[i].anchor),
10497                           clipPos(this, ranges[i].head));
10498      if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
10499      setSelection(this, normalizeSelection(out, primary), options);
10500    }),
10501    addSelection: docMethodOp(function(anchor, head, options) {
10502      var ranges = this.sel.ranges.slice(0);
10503      ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
10504      setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
10505    }),
10506
10507    getSelection: function(lineSep) {
10508      var ranges = this.sel.ranges, lines;
10509      for (var i = 0; i < ranges.length; i++) {
10510        var sel = getBetween(this, ranges[i].from(), ranges[i].to());
10511        lines = lines ? lines.concat(sel) : sel;
10512      }
10513      if (lineSep === false) return lines;
10514      else return lines.join(lineSep || this.lineSeparator());
10515    },
10516    getSelections: function(lineSep) {
10517      var parts = [], ranges = this.sel.ranges;
10518      for (var i = 0; i < ranges.length; i++) {
10519        var sel = getBetween(this, ranges[i].from(), ranges[i].to());
10520        if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());
10521        parts[i] = sel;
10522      }
10523      return parts;
10524    },
10525    replaceSelection: function(code, collapse, origin) {
10526      var dup = [];
10527      for (var i = 0; i < this.sel.ranges.length; i++)
10528        dup[i] = code;
10529      this.replaceSelections(dup, collapse, origin || "+input");
10530    },
10531    replaceSelections: docMethodOp(function(code, collapse, origin) {
10532      var changes = [], sel = this.sel;
10533      for (var i = 0; i < sel.ranges.length; i++) {
10534        var range = sel.ranges[i];
10535        changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
10536      }
10537      var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
10538      for (var i = changes.length - 1; i >= 0; i--)
10539        makeChange(this, changes[i]);
10540      if (newSel) setSelectionReplaceHistory(this, newSel);
10541      else if (this.cm) ensureCursorVisible(this.cm);
10542    }),
10543    undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
10544    redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
10545    undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
10546    redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
10547
10548    setExtending: function(val) {this.extend = val;},
10549    getExtending: function() {return this.extend;},
10550
10551    historySize: function() {
10552      var hist = this.history, done = 0, undone = 0;
10553      for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
10554      for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
10555      return {undo: done, redo: undone};
10556    },
10557    clearHistory: function() {this.history = new History(this.history.maxGeneration);},
10558
10559    markClean: function() {
10560      this.cleanGeneration = this.changeGeneration(true);
10561    },
10562    changeGeneration: function(forceSplit) {
10563      if (forceSplit)
10564        this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
10565      return this.history.generation;
10566    },
10567    isClean: function (gen) {
10568      return this.history.generation == (gen || this.cleanGeneration);
10569    },
10570
10571    getHistory: function() {
10572      return {done: copyHistoryArray(this.history.done),
10573              undone: copyHistoryArray(this.history.undone)};
10574    },
10575    setHistory: function(histData) {
10576      var hist = this.history = new History(this.history.maxGeneration);
10577      hist.done = copyHistoryArray(histData.done.slice(0), null, true);
10578      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
10579    },
10580
10581    addLineClass: docMethodOp(function(handle, where, cls) {
10582      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
10583        var prop = where == "text" ? "textClass"
10584                 : where == "background" ? "bgClass"
10585                 : where == "gutter" ? "gutterClass" : "wrapClass";
10586        if (!line[prop]) line[prop] = cls;
10587        else if (classTest(cls).test(line[prop])) return false;
10588        else line[prop] += " " + cls;
10589        return true;
10590      });
10591    }),
10592    removeLineClass: docMethodOp(function(handle, where, cls) {
10593      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
10594        var prop = where == "text" ? "textClass"
10595                 : where == "background" ? "bgClass"
10596                 : where == "gutter" ? "gutterClass" : "wrapClass";
10597        var cur = line[prop];
10598        if (!cur) return false;
10599        else if (cls == null) line[prop] = null;
10600        else {
10601          var found = cur.match(classTest(cls));
10602          if (!found) return false;
10603          var end = found.index + found[0].length;
10604          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
10605        }
10606        return true;
10607      });
10608    }),
10609
10610    addLineWidget: docMethodOp(function(handle, node, options) {
10611      return addLineWidget(this, handle, node, options);
10612    }),
10613    removeLineWidget: function(widget) { widget.clear(); },
10614
10615    markText: function(from, to, options) {
10616      return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
10617    },
10618    setBookmark: function(pos, options) {
10619      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
10620                      insertLeft: options && options.insertLeft,
10621                      clearWhenEmpty: false, shared: options && options.shared,
10622                      handleMouseEvents: options && options.handleMouseEvents};
10623      pos = clipPos(this, pos);
10624      return markText(this, pos, pos, realOpts, "bookmark");
10625    },
10626    findMarksAt: function(pos) {
10627      pos = clipPos(this, pos);
10628      var markers = [], spans = getLine(this, pos.line).markedSpans;
10629      if (spans) for (var i = 0; i < spans.length; ++i) {
10630        var span = spans[i];
10631        if ((span.from == null || span.from <= pos.ch) &&
10632            (span.to == null || span.to >= pos.ch))
10633          markers.push(span.marker.parent || span.marker);
10634      }
10635      return markers;
10636    },
10637    findMarks: function(from, to, filter) {
10638      from = clipPos(this, from); to = clipPos(this, to);
10639      var found = [], lineNo = from.line;
10640      this.iter(from.line, to.line + 1, function(line) {
10641        var spans = line.markedSpans;
10642        if (spans) for (var i = 0; i < spans.length; i++) {
10643          var span = spans[i];
10644          if (!(lineNo == from.line && from.ch > span.to ||
10645                span.from == null && lineNo != from.line||
10646                lineNo == to.line && span.from > to.ch) &&
10647              (!filter || filter(span.marker)))
10648            found.push(span.marker.parent || span.marker);
10649        }
10650        ++lineNo;
10651      });
10652      return found;
10653    },
10654    getAllMarks: function() {
10655      var markers = [];
10656      this.iter(function(line) {
10657        var sps = line.markedSpans;
10658        if (sps) for (var i = 0; i < sps.length; ++i)
10659          if (sps[i].from != null) markers.push(sps[i].marker);
10660      });
10661      return markers;
10662    },
10663
10664    posFromIndex: function(off) {
10665      var ch, lineNo = this.first;
10666      this.iter(function(line) {
10667        var sz = line.text.length + 1;
10668        if (sz > off) { ch = off; return true; }
10669        off -= sz;
10670        ++lineNo;
10671      });
10672      return clipPos(this, Pos(lineNo, ch));
10673    },
10674    indexFromPos: function (coords) {
10675      coords = clipPos(this, coords);
10676      var index = coords.ch;
10677      if (coords.line < this.first || coords.ch < 0) return 0;
10678      this.iter(this.first, coords.line, function (line) {
10679        index += line.text.length + 1
vendor: 32,457 bytes, lines 10679-11541
10679;
10680      });
10681      return index;
10682    },
10683
10684    copy: function(copyHistory) {
10685      var doc = new Doc(getLines(this, this.first, this.first + this.size),
10686                        this.modeOption, this.first, this.lineSep);
10687      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
10688      doc.sel = this.sel;
10689      doc.extend = false;
10690      if (copyHistory) {
10691        doc.history.undoDepth = this.history.undoDepth;
10692        doc.setHistory(this.getHistory());
10693      }
10694      return doc;
10695    },
10696
10697    linkedDoc: function(options) {
10698      if (!options) options = {};
10699      var from = this.first, to = this.first + this.size;
10700      if (options.from != null && options.from > from) from = options.from;
10701      if (options.to != null && options.to < to) to = options.to;
10702      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);
10703      if (options.sharedHist) copy.history = this.history;
10704      (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
10705      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
10706      copySharedMarkers(copy, findSharedMarkers(this));
10707      return copy;
10708    },
10709    unlinkDoc: function(other) {
10710      if (other instanceof CodeMirror) other = other.doc;
10711      if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
10712        var link = this.linked[i];
10713        if (link.doc != other) continue;
10714        this.linked.splice(i, 1);
10715        other.unlinkDoc(this);
10716        detachSharedMarkers(findSharedMarkers(this));
10717        break;
10718      }
10719      // If the histories were shared, split them again
10720      if (other.history == this.history) {
10721        var splitIds = [other.id];
10722        linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
10723        other.history = new History(null);
10724        other.history.done = copyHistoryArray(this.history.done, splitIds);
10725        other.history.undone = copyHistoryArray(this.history.undone, splitIds);
10726      }
10727    },
10728    iterLinkedDocs: function(f) {linkedDocs(this, f);},
10729
10730    getMode: function() {return this.mode;},
10731    getEditor: function() {return this.cm;},
10732
10733    splitLines: function(str) {
10734      if (this.lineSep) return str.split(this.lineSep);
10735      return splitLinesAuto(str);
10736    },
10737    lineSeparator: function() { return this.lineSep || "\n"; }
10738  });
10739
10740  // Public alias.
10741  Doc.prototype.eachLine = Doc.prototype.iter;
10742
10743  // Set up methods on CodeMirror's prototype to redirect to the editor's document.
10744  var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
10745  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
10746    CodeMirror.prototype[prop] = (function(method) {
10747      return function() {return method.apply(this.doc, arguments);};
10748    })(Doc.prototype[prop]);
10749
10750  eventMixin(Doc);
10751
10752  // Call f for all linked documents.
10753  function linkedDocs(doc, f, sharedHistOnly) {
10754    function propagate(doc, skip, sharedHist) {
10755      if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
10756        var rel = doc.linked[i];
10757        if (rel.doc == skip) continue;
10758        var shared = sharedHist && rel.sharedHist;
10759        if (sharedHistOnly && !shared) continue;
10760        f(rel.doc, shared);
10761        propagate(rel.doc, doc, shared);
10762      }
10763    }
10764    propagate(doc, null, true);
10765  }
10766
10767  // Attach a document to an editor.
10768  function attachDoc(cm, doc) {
10769    if (doc.cm) throw new Error("This document is already in use.");
10770    cm.doc = doc;
10771    doc.cm = cm;
10772    estimateLineHeights(cm);
10773    loadMode(cm);
10774    if (!cm.options.lineWrapping) findMaxLine(cm);
10775    cm.options.mode = doc.modeOption;
10776    regChange(cm);
10777  }
10778
10779  // LINE UTILITIES
10780
10781  // Find the line object corresponding to the given line number.
10782  function getLine(doc, n) {
10783    n -= doc.first;
10784    if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
10785    for (var chunk = doc; !chunk.lines;) {
10786      for (var i = 0;; ++i) {
10787        var child = chunk.children[i], sz = child.chunkSize();
10788        if (n < sz) { chunk = child; break; }
10789        n -= sz;
10790      }
10791    }
10792    return chunk.lines[n];
10793  }
10794
10795  // Get the part of a document between two positions, as an array of
10796  // strings.
10797  function getBetween(doc, start, end) {
10798    var out = [], n = start.line;
10799    doc.iter(start.line, end.line + 1, function(line) {
10800      var text = line.text;
10801      if (n == end.line) text = text.slice(0, end.ch);
10802      if (n == start.line) text = text.slice(start.ch);
10803      out.push(text);
10804      ++n;
10805    });
10806    return out;
10807  }
10808  // Get the lines between from and to, as array of strings.
10809  function getLines(doc, from, to) {
10810    var out = [];
10811    doc.iter(from, to, function(line) { out.push(line.text); });
10812    return out;
10813  }
10814
10815  // Update the height of a line, propagating the height change
10816  // upwards to parent nodes.
10817  function updateLineHeight(line, height) {
10818    var diff = height - line.height;
10819    if (diff) for (var n = line; n; n = n.parent) n.height += diff;
10820  }
10821
10822  // Given a line object, find its line number by walking up through
10823  // its parent links.
10824  function lineNo(line) {
10825    if (line.parent == null) return null;
10826    var cur = line.parent, no = indexOf(cur.lines, line);
10827    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
10828      for (var i = 0;; ++i) {
10829        if (chunk.children[i] == cur) break;
10830        no += chunk.children[i].chunkSize();
10831      }
10832    }
10833    return no + cur.first;
10834  }
10835
10836  // Find the line at the given vertical position, using the height
10837  // information in the document tree.
10838  function lineAtHeight(chunk, h) {
10839    var n = chunk.first;
10840    outer: do {
10841      for (var i = 0; i < chunk.children.length; ++i) {
10842        var child = chunk.children[i], ch = child.height;
10843        if (h < ch) { chunk = child; continue outer; }
10844        h -= ch;
10845        n += child.chunkSize();
10846      }
10847      return n;
10848    } while (!chunk.lines);
10849    for (var i = 0; i < chunk.lines.length; ++i) {
10850      var line = chunk.lines[i], lh = line.height;
10851      if (h < lh) break;
10852      h -= lh;
10853    }
10854    return n + i;
10855  }
10856
10857
10858  // Find the height above the given line.
10859  function heightAtLine(lineObj) {
10860    lineObj = visualLine(lineObj);
10861
10862    var h = 0, chunk = lineObj.parent;
10863    for (var i = 0; i < chunk.lines.length; ++i) {
10864      var line = chunk.lines[i];
10865      if (line == lineObj) break;
10866      else h += line.height;
10867    }
10868    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
10869      for (var i = 0; i < p.children.length; ++i) {
10870        var cur = p.children[i];
10871        if (cur == chunk) break;
10872        else h += cur.height;
10873      }
10874    }
10875    return h;
10876  }
10877
10878  // Get the bidi ordering for the given line (and cache it). Returns
10879  // false for lines that are fully left-to-right, and an array of
10880  // BidiSpan objects otherwise.
10881  function getOrder(line) {
10882    var order = line.order;
10883    if (order == null) order = line.order = bidiOrdering(line.text);
10884    return order;
10885  }
10886
10887  // HISTORY
10888
10889  function History(startGen) {
10890    // Arrays of change events and selections. Doing something adds an
10891    // event to done and clears undo. Undoing moves events from done
10892    // to undone, redoing moves them in the other direction.
10893    this.done = []; this.undone = [];
10894    this.undoDepth = Infinity;
10895    // Used to track when changes can be merged into a single undo
10896    // event
10897    this.lastModTime = this.lastSelTime = 0;
10898    this.lastOp = this.lastSelOp = null;
10899    this.lastOrigin = this.lastSelOrigin = null;
10900    // Used by the isClean() method
10901    this.generation = this.maxGeneration = startGen || 1;
10902  }
10903
10904  // Create a history change event from an updateDoc-style change
10905  // object.
10906  function historyChangeFromChange(doc, change) {
10907    var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
10908    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
10909    linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
10910    return histChange;
10911  }
10912
10913  // Pop all selection events off the end of a history array. Stop at
10914  // a change event.
10915  function clearSelectionEvents(array) {
10916    while (array.length) {
10917      var last = lst(array);
10918      if (last.ranges) array.pop();
10919      else break;
10920    }
10921  }
10922
10923  // Find the top change event in the history. Pop off selection
10924  // events that are in the way.
10925  function lastChangeEvent(hist, force) {
10926    if (force) {
10927      clearSelectionEvents(hist.done);
10928      return lst(hist.done);
10929    } else if (hist.done.length && !lst(hist.done).ranges) {
10930      return lst(hist.done);
10931    } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
10932      hist.done.pop();
10933      return lst(hist.done);
10934    }
10935  }
10936
10937  // Register a change in the history. Merges changes that are within
10938  // a single operation, ore are close together with an origin that
10939  // allows merging (starting with "+") into a single event.
10940  function addChangeToHistory(doc, change, selAfter, opId) {
10941    var hist = doc.history;
10942    hist.undone.length = 0;
10943    var time = +new Date, cur;
10944
10945    if ((hist.lastOp == opId ||
10946         hist.lastOrigin == change.origin && change.origin &&
10947         ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
10948          change.origin.charAt(0) == "*")) &&
10949        (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
10950      // Merge this change into the last event
10951      var last = lst(cur.changes);
10952      if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
10953        // Optimized case for simple insertion -- don't want to add
10954        // new changesets for every character typed
10955        last.to = changeEnd(change);
10956      } else {
10957        // Add new sub-event
10958        cur.changes.push(historyChangeFromChange(doc, change));
10959      }
10960    } else {
10961      // Can not be merged, start a new event.
10962      var before = lst(hist.done);
10963      if (!before || !before.ranges)
10964        pushSelectionToHistory(doc.sel, hist.done);
10965      cur = {changes: [historyChangeFromChange(doc, change)],
10966             generation: hist.generation};
10967      hist.done.push(cur);
10968      while (hist.done.length > hist.undoDepth) {
10969        hist.done.shift();
10970        if (!hist.done[0].ranges) hist.done.shift();
10971      }
10972    }
10973    hist.done.push(selAfter);
10974    hist.generation = ++hist.maxGeneration;
10975    hist.lastModTime = hist.lastSelTime = time;
10976    hist.lastOp = hist.lastSelOp = opId;
10977    hist.lastOrigin = hist.lastSelOrigin = change.origin;
10978
10979    if (!last) signal(doc, "historyAdded");
10980  }
10981
10982  function selectionEventCanBeMerged(doc, origin, prev, sel) {
10983    var ch = origin.charAt(0);
10984    return ch == "*" ||
10985      ch == "+" &&
10986      prev.ranges.length == sel.ranges.length &&
10987      prev.somethingSelected() == sel.somethingSelected() &&
10988      new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
10989  }
10990
10991  // Called whenever the selection changes, sets the new selection as
10992  // the pending selection in the history, and pushes the old pending
10993  // selection into the 'done' array when it was significantly
10994  // different (in number of selected ranges, emptiness, or time).
10995  function addSelectionToHistory(doc, sel, opId, options) {
10996    var hist = doc.history, origin = options && options.origin;
10997
10998    // A new event is started when the previous origin does not match
10999    // the current, or the origins don't allow matching. Origins
11000    // starting with * are always merged, those starting with + are
11001    // merged when similar and close together in time.
11002    if (opId == hist.lastSelOp ||
11003        (origin && hist.lastSelOrigin == origin &&
11004         (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
11005          selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
11006      hist.done[hist.done.length - 1] = sel;
11007    else
11008      pushSelectionToHistory(sel, hist.done);
11009
11010    hist.lastSelTime = +new Date;
11011    hist.lastSelOrigin = origin;
11012    hist.lastSelOp = opId;
11013    if (options && options.clearRedo !== false)
11014      clearSelectionEvents(hist.undone);
11015  }
11016
11017  function pushSelectionToHistory(sel, dest) {
11018    var top = lst(dest);
11019    if (!(top && top.ranges && top.equals(sel)))
11020      dest.push(sel);
11021  }
11022
11023  // Used to store marked span information in the history.
11024  function attachLocalSpans(doc, change, from, to) {
11025    var existing = change["spans_" + doc.id], n = 0;
11026    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
11027      if (line.markedSpans)
11028        (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
11029      ++n;
11030    });
11031  }
11032
11033  // When un/re-doing restores text containing marked spans, those
11034  // that have been explicitly cleared should not be restored.
11035  function removeClearedSpans(spans) {
11036    if (!spans) return null;
11037    for (var i = 0, out; i < spans.length; ++i) {
11038      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
11039      else if (out) out.push(spans[i]);
11040    }
11041    return !out ? spans : out.length ? out : null;
11042  }
11043
11044  // Retrieve and filter the old marked spans stored in a change event.
11045  function getOldSpans(doc, change) {
11046    var found = change["spans_" + doc.id];
11047    if (!found) return null;
11048    for (var i = 0, nw = []; i < change.text.length; ++i)
11049      nw.push(removeClearedSpans(found[i]));
11050    return nw;
11051  }
11052
11053  // Used both to provide a JSON-safe object in .getHistory, and, when
11054  // detaching a document, to split the history in two
11055  function copyHistoryArray(events, newGroup, instantiateSel) {
11056    for (var i = 0, copy = []; i < events.length; ++i) {
11057      var event = events[i];
11058      if (event.ranges) {
11059        copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
11060        continue;
11061      }
11062      var changes = event.changes, newChanges = [];
11063      copy.push({changes: newChanges});
11064      for (var j = 0; j < changes.length; ++j) {
11065        var change = changes[j], m;
11066        newChanges.push({from: change.from, to: change.to, text: change.text});
11067        if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
11068          if (indexOf(newGroup, Number(m[1])) > -1) {
11069            lst(newChanges)[prop] = change[prop];
11070            delete change[prop];
11071          }
11072        }
11073      }
11074    }
11075    return copy;
11076  }
11077
11078  // Rebasing/resetting history to deal with externally-sourced changes
11079
11080  function rebaseHistSelSingle(pos, from, to, diff) {
11081    if (to < pos.line) {
11082      pos.line += diff;
11083    } else if (from < pos.line) {
11084      pos.line = from;
11085      pos.ch = 0;
11086    }
11087  }
11088
11089  // Tries to rebase an array of history events given a change in the
11090  // document. If the change touches the same lines as the event, the
11091  // event, and everything 'behind' it, is discarded. If the change is
11092  // before the event, the event's positions are updated. Uses a
11093  // copy-on-write scheme for the positions, to avoid having to
11094  // reallocate them all on every rebase, but also avoid problems with
11095  // shared position objects being unsafely updated.
11096  function rebaseHistArray(array, from, to, diff) {
11097    for (var i = 0; i < array.length; ++i) {
11098      var sub = array[i], ok = true;
11099      if (sub.ranges) {
11100        if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
11101        for (var j = 0; j < sub.ranges.length; j++) {
11102          rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
11103          rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
11104        }
11105        continue;
11106      }
11107      for (var j = 0; j < sub.changes.length; ++j) {
11108        var cur = sub.changes[j];
11109        if (to < cur.from.line) {
11110          cur.from = Pos(cur.from.line + diff, cur.from.ch);
11111          cur.to = Pos(cur.to.line + diff, cur.to.ch);
11112        } else if (from <= cur.to.line) {
11113          ok = false;
11114          break;
11115        }
11116      }
11117      if (!ok) {
11118        array.splice(0, i + 1);
11119        i = 0;
11120      }
11121    }
11122  }
11123
11124  function rebaseHist(hist, change) {
11125    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
11126    rebaseHistArray(hist.done, from, to, diff);
11127    rebaseHistArray(hist.undone, from, to, diff);
11128  }
11129
11130  // EVENT UTILITIES
11131
11132  // Due to the fact that we still support jurassic IE versions, some
11133  // compatibility wrappers are needed.
11134
11135  var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
11136    if (e.preventDefault) e.preventDefault();
11137    else e.returnValue = false;
11138  };
11139  var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
11140    if (e.stopPropagation) e.stopPropagation();
11141    else e.cancelBubble = true;
11142  };
11143  function e_defaultPrevented(e) {
11144    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
11145  }
11146  var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
11147
11148  function e_target(e) {return e.target || e.srcElement;}
11149  function e_button(e) {
11150    var b = e.which;
11151    if (b == null) {
11152      if (e.button & 1) b = 1;
11153      else if (e.button & 2) b = 3;
11154      else if (e.button & 4) b = 2;
11155    }
11156    if (mac && e.ctrlKey && b == 1) b = 3;
11157    return b;
11158  }
11159
11160  // EVENT HANDLING
11161
11162  // Lightweight event framework. on/off also work on DOM nodes,
11163  // registering native DOM handlers.
11164
11165  var on = CodeMirror.on = function(emitter, type, f) {
11166    if (emitter.addEventListener)
11167      emitter.addEventListener(type, f, false);
11168    else if (emitter.attachEvent)
11169      emitter.attachEvent("on" + type, f);
11170    else {
11171      var map = emitter._handlers || (emitter._handlers = {});
11172      var arr = map[type] || (map[type] = []);
11173      arr.push(f);
11174    }
11175  };
11176
11177  var noHandlers = []
11178  function getHandlers(emitter, type, copy) {
11179    var arr = emitter._handlers && emitter._handlers[type]
11180    if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
11181    else return arr || noHandlers
11182  }
11183
11184  var off = CodeMirror.off = function(emitter, type, f) {
11185    if (emitter.removeEventListener)
11186      emitter.removeEventListener(type, f, false);
11187    else if (emitter.detachEvent)
11188      emitter.detachEvent("on" + type, f);
11189    else {
11190      var handlers = getHandlers(emitter, type, false)
11191      for (var i = 0; i < handlers.length; ++i)
11192        if (handlers[i] == f) { handlers.splice(i, 1); break; }
11193    }
11194  };
11195
11196  var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
11197    var handlers = getHandlers(emitter, type, true)
11198    if (!handlers.length) return;
11199    var args = Array.prototype.slice.call(arguments, 2);
11200    for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
11201  };
11202
11203  var orphanDelayedCallbacks = null;
11204
11205  // Often, we want to signal events at a point where we are in the
11206  // middle of some work, but don't want the handler to start calling
11207  // other methods on the editor, which might be in an inconsistent
11208  // state or simply not expect any other events to happen.
11209  // signalLater looks whether there are any handlers, and schedules
11210  // them to be executed when the last operation ends, or, if no
11211  // operation is active, when a timeout fires.
11212  function signalLater(emitter, type /*, values...*/) {
11213    var arr = getHandlers(emitter, type, false)
11214    if (!arr.length) return;
11215    var args = Array.prototype.slice.call(arguments, 2), list;
11216    if (operationGroup) {
11217      list = operationGroup.delayedCallbacks;
11218    } else if (orphanDelayedCallbacks) {
11219      list = orphanDelayedCallbacks;
11220    } else {
11221      list = orphanDelayedCallbacks = [];
11222      setTimeout(fireOrphanDelayed, 0);
11223    }
11224    function bnd(f) {return function(){f.apply(null, args);};};
11225    for (var i = 0; i < arr.length; ++i)
11226      list.push(bnd(arr[i]));
11227  }
11228
11229  function fireOrphanDelayed() {
11230    var delayed = orphanDelayedCallbacks;
11231    orphanDelayedCallbacks = null;
11232    for (var i = 0; i < delayed.length; ++i) delayed[i]();
11233  }
11234
11235  // The DOM events that CodeMirror handles can be overridden by
11236  // registering a (non-DOM) handler on the editor for the event name,
11237  // and preventDefault-ing the event in that handler.
11238  function signalDOMEvent(cm, e, override) {
11239    if (typeof e == "string")
11240      e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
11241    signal(cm, override || e.type, cm, e);
11242    return e_defaultPrevented(e) || e.codemirrorIgnore;
11243  }
11244
11245  function signalCursorActivity(cm) {
11246    var arr = cm._handlers && cm._handlers.cursorActivity;
11247    if (!arr) return;
11248    var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
11249    for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
11250      set.push(arr[i]);
11251  }
11252
11253  function hasHandler(emitter, type) {
11254    return getHandlers(emitter, type).length > 0
11255  }
11256
11257  // Add on and off methods to a constructor's prototype, to make
11258  // registering events on such objects more convenient.
11259  function eventMixin(ctor) {
11260    ctor.prototype.on = function(type, f) {on(this, type, f);};
11261    ctor.prototype.off = function(type, f) {off(this, type, f);};
11262  }
11263
11264  // MISC UTILITIES
11265
11266  // Number of pixels added to scroller and sizer to hide scrollbar
11267  var scrollerGap = 30;
11268
11269  // Returned or thrown by various protocols to signal 'I'm not
11270  // handling this'.
11271  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
11272
11273  // Reused option objects for setSelection & friends
11274  var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
11275
11276  function Delayed() {this.id = null;}
11277  Delayed.prototype.set = function(ms, f) {
11278    clearTimeout(this.id);
11279    this.id = setTimeout(f, ms);
11280  };
11281
11282  // Counts the column offset in a string, taking tabs into account.
11283  // Used mostly to find indentation.
11284  var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
11285    if (end == null) {
11286      end = string.search(/[^\s\u00a0]/);
11287      if (end == -1) end = string.length;
11288    }
11289    for (var i = startIndex || 0, n = startValue || 0;;) {
11290      var nextTab = string.indexOf("\t", i);
11291      if (nextTab < 0 || nextTab >= end)
11292        return n + (end - i);
11293      n += nextTab - i;
11294      n += tabSize - (n % tabSize);
11295      i = nextTab + 1;
11296    }
11297  };
11298
11299  // The inverse of countColumn -- find the offset that corresponds to
11300  // a particular column.
11301  var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
11302    for (var pos = 0, col = 0;;) {
11303      var nextTab = string.indexOf("\t", pos);
11304      if (nextTab == -1) nextTab = string.length;
11305      var skipped = nextTab - pos;
11306      if (nextTab == string.length || col + skipped >= goal)
11307        return pos + Math.min(skipped, goal - col);
11308      col += nextTab - pos;
11309      col += tabSize - (col % tabSize);
11310      pos = nextTab + 1;
11311      if (col >= goal) return pos;
11312    }
11313  }
11314
11315  var spaceStrs = [""];
11316  function spaceStr(n) {
11317    while (spaceStrs.length <= n)
11318      spaceStrs.push(lst(spaceStrs) + " ");
11319    return spaceStrs[n];
11320  }
11321
11322  function lst(arr) { return arr[arr.length-1]; }
11323
11324  var selectInput = function(node) { node.select(); };
11325  if (ios) // Mobile Safari apparently has a bug where select() is broken.
11326    selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
11327  else if (ie) // Suppress mysterious IE10 errors
11328    selectInput = function(node) { try { node.select(); } catch(_e) {} };
11329
11330  function indexOf(array, elt) {
11331    for (var i = 0; i < array.length; ++i)
11332      if (array[i] == elt) return i;
11333    return -1;
11334  }
11335  function map(array, f) {
11336    var out = [];
11337    for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
11338    return out;
11339  }
11340
11341  function nothing() {}
11342
11343  function createObj(base, props) {
11344    var inst;
11345    if (Object.create) {
11346      inst = Object.create(base);
11347    } else {
11348      nothing.prototype = base;
11349      inst = new nothing();
11350    }
11351    if (props) copyObj(props, inst);
11352    return inst;
11353  };
11354
11355  function copyObj(obj, target, overwrite) {
11356    if (!target) target = {};
11357    for (var prop in obj)
11358      if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
11359        target[prop] = obj[prop];
11360    return target;
11361  }
11362
11363  function bind(f) {
11364    var args = Array.prototype.slice.call(arguments, 1);
11365    return function(){return f.apply(null, args);};
11366  }
11367
11368  var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
11369  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
11370    return /\w/.test(ch) || ch > "\x80" &&
11371      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
11372  };
11373  function isWordChar(ch, helper) {
11374    if (!helper) return isWordCharBasic(ch);
11375    if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
11376    return helper.test(ch);
11377  }
11378
11379  function isEmpty(obj) {
11380    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
11381    return true;
11382  }
11383
11384  // Extending unicode characters. A series of a non-extending char +
11385  // any number of extending chars is treated as a single unit as far
11386  // as editing and measuring is concerned. This is not fully correct,
11387  // since some scripts/fonts/browsers also treat other configurations
11388  // of code points as a group.
11389  var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
11390  function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
11391
11392  // DOM UTILITIES
11393
11394  function elt(tag, content, className, style) {
11395    var e = document.createElement(tag);
11396    if (className) e.className = className;
11397    if (style) e.style.cssText = style;
11398    if (typeof content == "string") e.appendChild(document.createTextNode(content));
11399    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
11400    return e;
11401  }
11402
11403  var range;
11404  if (document.createRange) range = function(node, start, end, endNode) {
11405    var r = document.createRange();
11406    r.setEnd(endNode || node, end);
11407    r.setStart(node, start);
11408    return r;
11409  };
11410  else range = function(node, start, end) {
11411    var r = document.body.createTextRange();
11412    try { r.moveToElementText(node.parentNode); }
11413    catch(e) { return r; }
11414    r.collapse(true);
11415    r.moveEnd("character", end);
11416    r.moveStart("character", start);
11417    return r;
11418  };
11419
11420  function removeChildren(e) {
11421    for (var count = e.childNodes.length; count > 0; --count)
11422      e.removeChild(e.firstChild);
11423    return e;
11424  }
11425
11426  function removeChildrenAndAdd(parent, e) {
11427    return removeChildren(parent).appendChild(e);
11428  }
11429
11430  var contains = CodeMirror.contains = function(parent, child) {
11431    if (child.nodeType == 3) // Android browser always returns false when child is a textnode
11432      child = child.parentNode;
11433    if (parent.contains)
11434      return parent.contains(child);
11435    do {
11436      if (child.nodeType == 11) child = child.host;
11437      if (child == parent) return true;
11438    } while (child = child.parentNode);
11439  };
11440
11441  function activeElt() {
11442    var activeElement = document.activeElement;
11443    while (activeElement && activeElement.root && activeElement.root.activeElement)
11444      activeElement = activeElement.root.activeElement;
11445    return activeElement;
11446  }
11447  // Older versions of IE throws unspecified error when touching
11448  // document.activeElement in some cases (during loading, in iframe)
11449  if (ie && ie_version < 11) activeElt = function() {
11450    try { return document.activeElement; }
11451    catch(e) { return document.body; }
11452  };
11453
11454  function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
11455  var rmClass = CodeMirror.rmClass = function(node, cls) {
11456    var current = node.className;
11457    var match = classTest(cls).exec(current);
11458    if (match) {
11459      var after = current.slice(match.index + match[0].length);
11460      node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
11461    }
11462  };
11463  var addClass = CodeMirror.addClass = function(node, cls) {
11464    var current = node.className;
11465    if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
11466  };
11467  function joinClasses(a, b) {
11468    var as = a.split(" ");
11469    for (var i = 0; i < as.length; i++)
11470      if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
11471    return b;
11472  }
11473
11474  // WINDOW-WIDE EVENTS
11475
11476  // These must be handled carefully, because naively registering a
11477  // handler for each editor will cause the editors to never be
11478  // garbage collected.
11479
11480  function forEachCodeMirror(f) {
11481    if (!document.body.getElementsByClassName) return;
11482    var byClass = document.body.getElementsByClassName("CodeMirror");
11483    for (var i = 0; i < byClass.length; i++) {
11484      var cm = byClass[i].CodeMirror;
11485      if (cm) f(cm);
11486    }
11487  }
11488
11489  var globalsRegistered = false;
11490  function ensureGlobalHandlers() {
11491    if (globalsRegistered) return;
11492    registerGlobalHandlers();
11493    globalsRegistered = true;
11494  }
11495  function registerGlobalHandlers() {
11496    // When the window resizes, we need to refresh active editors.
11497    var resizeTimer;
11498    on(window, "resize", function() {
11499      if (resizeTimer == null) resizeTimer = setTimeout(function() {
11500        resizeTimer = null;
11501        forEachCodeMirror(onResize);
11502      }, 100);
11503    });
11504    // When the window loses focus, we want to show the editor as blurred
11505    on(window, "blur", function() {
11506      forEachCodeMirror(onBlur);
11507    });
11508  }
11509
11510  // FEATURE DETECTION
11511
11512  // Detect drag-and-drop
11513  var dragAndDrop = function() {
11514    // There is *some* kind of drag-and-drop support in IE6-8, but I
11515    // couldn't get it to work yet.
11516    if (ie && ie_version < 9) return false;
11517    var div = elt('div');
11518    return "draggable" in div || "dragDrop" in div;
11519  }();
11520
11521  var zwspSupported;
11522  function zeroWidthElement(measure) {
11523    if (zwspSupported == null) {
11524      var test = elt("span", "\u200b");
11525      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
11526      if (measure.firstChild.offsetHeight != 0)
11527        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
11528    }
11529    var node = zwspSupported ? elt("span", "\u200b") :
11530      elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
11531    node.setAttribute("cm-text", "");
11532    return node;
11533  }
11534
11535  // Feature-detect IE's crummy client rect reporting for bidi text
11536  var badBidiRects;
11537  function hasBadBidiRects(measure) {
11538    if (badBidiRects != null) return badBidiRects;
11539    var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
11540    var r0 = range(txt, 0, 1).getBoundingClientRect();
11541    
11541if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
11542    var r1 = range(txt, 1, 2).getBoundingClientRect();
vendor: 14,748 bytes, lines 11542-11908
11542
11543    return badBidiRects = (r1.right - r0.right < 3);
11544  }
11545
11546  // See if "".split is the broken IE version, if so, provide an
11547  // alternative way to split lines.
11548  var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
11549    var pos = 0, result = [], l = string.length;
11550    while (pos <= l) {
11551      var nl = string.indexOf("\n", pos);
11552      if (nl == -1) nl = string.length;
11553      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
11554      var rt = line.indexOf("\r");
11555      if (rt != -1) {
11556        result.push(line.slice(0, rt));
11557        pos += rt + 1;
11558      } else {
11559        result.push(line);
11560        pos = nl + 1;
11561      }
11562    }
11563    return result;
11564  } : function(string){return string.split(/\r\n?|\n/);};
11565
11566  var hasSelection = window.getSelection ? function(te) {
11567    try { return te.selectionStart != te.selectionEnd; }
11568    catch(e) { return false; }
11569  } : function(te) {
11570    try {var range = te.ownerDocument.selection.createRange();}
11571    catch(e) {}
11572    if (!range || range.parentElement() != te) return false;
11573    return range.compareEndPoints("StartToEnd", range) != 0;
11574  };
11575
11576  var hasCopyEvent = (function() {
11577    var e = elt("div");
11578    if ("oncopy" in e) return true;
11579    e.setAttribute("oncopy", "return;");
11580    return typeof e.oncopy == "function";
11581  })();
11582
11583  var badZoomedRects = null;
11584  function hasBadZoomedRects(measure) {
11585    if (badZoomedRects != null) return badZoomedRects;
11586    var node = removeChildrenAndAdd(measure, elt("span", "x"));
11587    var normal = node.getBoundingClientRect();
11588    var fromRange = range(node, 0, 1).getBoundingClientRect();
11589    return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
11590  }
11591
11592  // KEY NAMES
11593
11594  var keyNames = CodeMirror.keyNames = {
11595    3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
11596    19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
11597    36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
11598    46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
11599    106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
11600    173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
11601    221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
11602    63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
11603  };
11604  (function() {
11605    // Number keys
11606    for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
11607    // Alphabetic keys
11608    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
11609    // Function keys
11610    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
11611  })();
11612
11613  // BIDI HELPERS
11614
11615  function iterateBidiSections(order, from, to, f) {
11616    if (!order) return f(from, to, "ltr");
11617    var found = false;
11618    for (var i = 0; i < order.length; ++i) {
11619      var part = order[i];
11620      if (part.from < to && part.to > from || from == to && part.to == from) {
11621        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
11622        found = true;
11623      }
11624    }
11625    if (!found) f(from, to, "ltr");
11626  }
11627
11628  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
11629  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
11630
11631  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
11632  function lineRight(line) {
11633    var order = getOrder(line);
11634    if (!order) return line.text.length;
11635    return bidiRight(lst(order));
11636  }
11637
11638  function lineStart(cm, lineN) {
11639    var line = getLine(cm.doc, lineN);
11640    var visual = visualLine(line);
11641    if (visual != line) lineN = lineNo(visual);
11642    var order = getOrder(visual);
11643    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
11644    return Pos(lineN, ch);
11645  }
11646  function lineEnd(cm, lineN) {
11647    var merged, line = getLine(cm.doc, lineN);
11648    while (merged = collapsedSpanAtEnd(line)) {
11649      line = merged.find(1, true).line;
11650      lineN = null;
11651    }
11652    var order = getOrder(line);
11653    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
11654    return Pos(lineN == null ? lineNo(line) : lineN, ch);
11655  }
11656  function lineStartSmart(cm, pos) {
11657    var start = lineStart(cm, pos.line);
11658    var line = getLine(cm.doc, start.line);
11659    var order = getOrder(line);
11660    if (!order || order[0].level == 0) {
11661      var firstNonWS = Math.max(0, line.text.search(/\S/));
11662      var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
11663      return Pos(start.line, inWS ? 0 : firstNonWS);
11664    }
11665    return start;
11666  }
11667
11668  function compareBidiLevel(order, a, b) {
11669    var linedir = order[0].level;
11670    if (a == linedir) return true;
11671    if (b == linedir) return false;
11672    return a < b;
11673  }
11674  var bidiOther;
11675  function getBidiPartAt(order, pos) {
11676    bidiOther = null;
11677    for (var i = 0, found; i < order.length; ++i) {
11678      var cur = order[i];
11679      if (cur.from < pos && cur.to > pos) return i;
11680      if ((cur.from == pos || cur.to == pos)) {
11681        if (found == null) {
11682          found = i;
11683        } else if (compareBidiLevel(order, cur.level, order[found].level)) {
11684          if (cur.from != cur.to) bidiOther = found;
11685          return i;
11686        } else {
11687          if (cur.from != cur.to) bidiOther = i;
11688          return found;
11689        }
11690      }
11691    }
11692    return found;
11693  }
11694
11695  function moveInLine(line, pos, dir, byUnit) {
11696    if (!byUnit) return pos + dir;
11697    do pos += dir;
11698    while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
11699    return pos;
11700  }
11701
11702  // This is needed in order to move 'visually' through bi-directional
11703  // text -- i.e., pressing left should make the cursor go left, even
11704  // when in RTL text. The tricky part is the 'jumps', where RTL and
11705  // LTR text touch each other. This often requires the cursor offset
11706  // to move more than one unit, in order to visually move one unit.
11707  function moveVisually(line, start, dir, byUnit) {
11708    var bidi = getOrder(line);
11709    if (!bidi) return moveLogically(line, start, dir, byUnit);
11710    var pos = getBidiPartAt(bidi, start), part = bidi[pos];
11711    var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
11712
11713    for (;;) {
11714      if (target > part.from && target < part.to) return target;
11715      if (target == part.from || target == part.to) {
11716        if (getBidiPartAt(bidi, target) == pos) return target;
11717        part = bidi[pos += dir];
11718        return (dir > 0) == part.level % 2 ? part.to : part.from;
11719      } else {
11720        part = bidi[pos += dir];
11721        if (!part) return null;
11722        if ((dir > 0) == part.level % 2)
11723          target = moveInLine(line, part.to, -1, byUnit);
11724        else
11725          target = moveInLine(line, part.from, 1, byUnit);
11726      }
11727    }
11728  }
11729
11730  function moveLogically(line, start, dir, byUnit) {
11731    var target = start + dir;
11732    if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
11733    return target < 0 || target > line.text.length ? null : target;
11734  }
11735
11736  // Bidirectional ordering algorithm
11737  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
11738  // that this (partially) implements.
11739
11740  // One-char codes used for character types:
11741  // L (L):   Left-to-Right
11742  // R (R):   Right-to-Left
11743  // r (AL):  Right-to-Left Arabic
11744  // 1 (EN):  European Number
11745  // + (ES):  European Number Separator
11746  // % (ET):  European Number Terminator
11747  // n (AN):  Arabic Number
11748  // , (CS):  Common Number Separator
11749  // m (NSM): Non-Spacing Mark
11750  // b (BN):  Boundary Neutral
11751  // s (B):   Paragraph Separator
11752  // t (S):   Segment Separator
11753  // w (WS):  Whitespace
11754  // N (ON):  Other Neutrals
11755
11756  // Returns null if characters are ordered as they appear
11757  // (left-to-right), or an array of sections ({from, to, level}
11758  // objects) in the order in which they occur visually.
11759  var bidiOrdering = (function() {
11760    // Character types for codepoints 0 to 0xff
11761    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
11762    // Character types for codepoints 0x600 to 0x6ff
11763    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
11764    function charType(code) {
11765      if (code <= 0xf7) return lowTypes.charAt(code);
11766      else if (0x590 <= code && code <= 0x5f4) return "R";
11767      else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
11768      else if (0x6ee <= code && code <= 0x8ac) return "r";
11769      else if (0x2000 <= code && code <= 0x200b) return "w";
11770      else if (code == 0x200c) return "b";
11771      else return "L";
11772    }
11773
11774    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
11775    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
11776    // Browsers seem to always treat the boundaries of block elements as being L.
11777    var outerType = "L";
11778
11779    function BidiSpan(level, from, to) {
11780      this.level = level;
11781      this.from = from; this.to = to;
11782    }
11783
11784    return function(str) {
11785      if (!bidiRE.test(str)) return false;
11786      var len = str.length, types = [];
11787      for (var i = 0, type; i < len; ++i)
11788        types.push(type = charType(str.charCodeAt(i)));
11789
11790      // W1. Examine each non-spacing mark (NSM) in the level run, and
11791      // change the type of the NSM to the type of the previous
11792      // character. If the NSM is at the start of the level run, it will
11793      // get the type of sor.
11794      for (var i = 0, prev = outerType; i < len; ++i) {
11795        var type = types[i];
11796        if (type == "m") types[i] = prev;
11797        else prev = type;
11798      }
11799
11800      // W2. Search backwards from each instance of a European number
11801      // until the first strong type (R, L, AL, or sor) is found. If an
11802      // AL is found, change the type of the European number to Arabic
11803      // number.
11804      // W3. Change all ALs to R.
11805      for (var i = 0, cur = outerType; i < len; ++i) {
11806        var type = types[i];
11807        if (type == "1" && cur == "r") types[i] = "n";
11808        else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
11809      }
11810
11811      // W4. A single European separator between two European numbers
11812      // changes to a European number. A single common separator between
11813      // two numbers of the same type changes to that type.
11814      for (var i = 1, prev = types[0]; i < len - 1; ++i) {
11815        var type = types[i];
11816        if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
11817        else if (type == "," && prev == types[i+1] &&
11818                 (prev == "1" || prev == "n")) types[i] = prev;
11819        prev = type;
11820      }
11821
11822      // W5. A sequence of European terminators adjacent to European
11823      // numbers changes to all European numbers.
11824      // W6. Otherwise, separators and terminators change to Other
11825      // Neutral.
11826      for (var i = 0; i < len; ++i) {
11827        var type = types[i];
11828        if (type == ",") types[i] = "N";
11829        else if (type == "%") {
11830          for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
11831          var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
11832          for (var j = i; j < end; ++j) types[j] = replace;
11833          i = end - 1;
11834        }
11835      }
11836
11837      // W7. Search backwards from each instance of a European number
11838      // until the first strong type (R, L, or sor) is found. If an L is
11839      // found, then change the type of the European number to L.
11840      for (var i = 0, cur = outerType; i < len; ++i) {
11841        var type = types[i];
11842        if (cur == "L" && type == "1") types[i] = "L";
11843        else if (isStrong.test(type)) cur = type;
11844      }
11845
11846      // N1. A sequence of neutrals takes the direction of the
11847      // surrounding strong text if the text on both sides has the same
11848      // direction. European and Arabic numbers act as if they were R in
11849      // terms of their influence on neutrals. Start-of-level-run (sor)
11850      // and end-of-level-run (eor) are used at level run boundaries.
11851      // N2. Any remaining neutrals take the embedding direction.
11852      for (var i = 0; i < len; ++i) {
11853        if (isNeutral.test(types[i])) {
11854          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
11855          var before = (i ? types[i-1] : outerType) == "L";
11856          var after = (end < len ? types[end] : outerType) == "L";
11857          var replace = before || after ? "L" : "R";
11858          for (var j = i; j < end; ++j) types[j] = replace;
11859          i = end - 1;
11860        }
11861      }
11862
11863      // Here we depart from the documented algorithm, in order to avoid
11864      // building up an actual levels array. Since there are only three
11865      // levels (0, 1, 2) in an implementation that doesn't take
11866      // explicit embedding into account, we can build up the order on
11867      // the fly, without following the level-based algorithm.
11868      var order = [], m;
11869      for (var i = 0; i < len;) {
11870        if (countsAsLeft.test(types[i])) {
11871          var start = i;
11872          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
11873          order.push(new BidiSpan(0, start, i));
11874        } else {
11875          var pos = i, at = order.length;
11876          for (++i; i < len && types[i] != "L"; ++i) {}
11877          for (var j = pos; j < i;) {
11878            if (countsAsNum.test(types[j])) {
11879              if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
11880              var nstart = j;
11881              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
11882              order.splice(at, 0, new BidiSpan(2, nstart, j));
11883              pos = j;
11884            } else ++j;
11885          }
11886          if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
11887        }
11888      }
11889      if (order[0].level == 1 && (m = str.match(/^\s+/))) {
11890        order[0].from = m[0].length;
11891        order.unshift(new BidiSpan(0, 0, m[0].length));
11892      }
11893      if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
11894        lst(order).to -= m[0].length;
11895        order.push(new BidiSpan(0, len - m[0].length, len));
11896      }
11897      if (order[0].level == 2)
11898        order.unshift(new BidiSpan(1, order[0].to, order[0].to));
11899      if (order[0].level != lst(order).level)
11900        order.push(new BidiSpan(order[0].level, len, len));
11901
11902      return order;
11903    };
11904  })();
11905
11906  // THE END
11907
11908  CodeMirror.version = "5.
119088.0";
11909
11910  return CodeMirror;
11911});
11912
11913},{}],31:[function(_dereq_,module,exports){
11914// CodeMirror, copyright (c) by Marijn Haverbeke and others
11915// Distributed under an MIT license: http://codemirror.net/LICENSE
11916
11917(function(mod) {
11918  if (typeof exports == "object" && typeof module == "object") // CommonJS
11919    mod(_dereq_("../../lib/codemirror"));
11920  else if (typeof define == "function" && define.amd) // AMD
11921    define(["../../lib/codemirror"], mod);
11922  else // Plain browser env
11923    mod(CodeMirror);
11924})(function(CodeMirror) {
11925"use strict";
11926
11927CodeMirror.defineMode("clike", function(config, parserConfig) {
11928  var indentUnit = config.indentUnit,
11929      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
11930      dontAlignCalls = parserConfig.dontAlignCalls,
11931      keywords = parserConfig.keywords || {},
11932      types = parserConfig.types || {},
11933      builtin = parserConfig.builtin || {},
11934      blockKeywords = parserConfig.blockKeywords || {},
11935      defKeywords = parserConfig.defKeywords || {},
11936      atoms = parserConfig.atoms || {},
11937      hooks = parserConfig.hooks || {},
11938      multiLineStrings = parserConfig.multiLineStrings,
11939      indentStatements = parserConfig.indentStatements !== false,
11940      indentSwitch = parserConfig.indentSwitch !== false,
11941      namespaceSeparator = parserConfig.namespaceSeparator,
11942      isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
11943      isNumberChar = parserConfig.isNumberChar || /\d/,
11944      isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
11945      endStatement = parserConfig.endStatement || /^[;:,]$/;
11946
11947  var curPunc, isDefKeyword;
11948
11949  function tokenBase(stream, state) {
11950    var ch = stream.next();
11951    if (hooks[ch]) {
11952      var result = hooks[ch](stream, state);
11953      if (result !== false) return result;
11954    }
11955    if (ch == '"' || ch == "'") {
11956      state.tokenize = tokenString(ch);
11957      return state.tokenize(stream, state);
11958    }
11959    if (isPunctuationChar.test(ch)) {
11960      curPunc = ch;
11961      return null;
11962    }
11963    if (isNumberChar.test(ch)) {
11964      stream.eatWhile(/[\w\.]/);
11965      return "number";
11966    }
11967    if (ch == "/") {
11968      if (stream.eat("*")) {
11969        state.tokenize = tokenComment;
11970        return tokenComment(stream, state);
11971      }
11972      if (stream.eat("/")) {
11973        stream.skipToEnd();
11974        return "comment";
11975      }
11976    }
11977    if (isOperatorChar.test(ch)) {
11978      stream.eatWhile(isOperatorChar);
11979      return "operator";
11980    }
11981    stream.eatWhile(/[\w\$_\xa1-\uffff]/);
11982    if (namespaceSeparator) while (stream.match(namespaceSeparator))
11983      stream.eatWhile(/[\w\$_\xa1-\uffff]/);
11984
11985    var cur = stream.current();
11986    if (contains(keywords, cur)) {
11987      if (contains(blockKeywords, cur)) curPunc = "newstatement";
11988      if (contains(defKeywords, cur)) isDefKeyword = true;
11989      return "keyword";
11990    }
11991    if (contains(types, cur)) return "variable-3";
11992    if (contains(builtin, cur)) {
11993      if (contains(blockKeywords, cur)) curPunc = "newstatement";
11994      return "builtin";
11995    }
11996    if (contains(atoms, cur)) return "atom";
11997    return "variable";
11998  }
11999
12000  function tokenString(quote) {
12001    return function(stream, state) {
12002      var escaped = false, next, end = false;
12003      while ((next = stream.next()) != null) {
12004        if (next == quote && !escaped) {end = true; break;}
12005        escaped = !escaped && next == "\\";
12006      }
12007      if (end || !(escaped || multiLineStrings))
12008        state.tokenize = null;
12009      return "string";
12010    };
12011  }
12012
12013  function tokenComment(stream, state) {
12014    var maybeEnd = false, ch;
12015    while (ch = stream.next()) {
12016      if (ch == "/" && maybeEnd) {
12017        state.tokenize = null;
12018        break;
12019      }
12020      maybeEnd = (ch == "*");
12021    }
12022    return "comment";
12023  }
12024
12025  function Context(indented, column, type, align, prev) {
12026    this.indented = indented;
12027    this.column = column;
12028    this.type = type;
12029    this.align = align;
12030    this.prev = prev;
12031  }
12032  function isStatement(type) {
12033    return type == "statement" || type == "switchstatement" || type == "namespace";
12034  }
12035  function pushContext(state, col, type) {
12036    var indent = state.indented;
12037    if (state.context && isStatement(state.context.type) && !isStatement(type))
12038      indent = state.context.indented;
12039    return state.context = new Context(indent, col, type, null, state.context);
12040  }
12041  function popContext(state) {
12042    var t = state.context.type;
12043    if (t == ")" || t == "]" || t == "}")
12044      state.indented = state.context.indented;
12045    return state.context = state.context.prev;
12046  }
12047
12048  function typeBefore(stream, state) {
12049    if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
12050    if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true;
12051  }
12052
12053  function isTopScope(context) {
12054    for (;;) {
12055      if (!context || context.type == "top") return true;
12056      if (context.type == "}" && context.prev.type != "namespace") return false;
12057      context = context.prev;
12058    }
12059  }
12060
12061  // Interface
12062
12063  return {
12064    startState: function(basecolumn) {
12065      return {
12066        tokenize: null,
12067        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
12068        indented: 0,
12069        startOfLine: true,
12070        prevToken: null
12071      };
12072    },
12073
12074    token: function(stream, state) {
12075      var ctx = state.context;
12076      if (stream.sol()) {
12077        if (ctx.align == null) ctx.align = false;
12078        state.indented = stream.indentation();
12079        state.startOfLine = true;
12080      }
12081      if (stream.eatSpace()) return null;
12082      curPunc = isDefKeyword = null;
12083      var style = (state.tokenize || tokenBase)(stream, state);
12084      if (style == "comment" || style == "meta") return style;
12085      if (ctx.align == null) ctx.align = true;
12086
12087      if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);
12088      else if (curPunc == "{") pushContext(state, stream.column(), "}");
12089      else if (curPunc == "[") pushContext(state, stream.column(), "]");
12090      else if (curPunc == "(") pushContext(state, stream.column(), ")");
12091      else if (curPunc == "}") {
12092        while (isStatement(ctx.type)) ctx = popContext(state);
12093        if (ctx.type == "}") ctx = popContext(state);
12094        while (isStatement(ctx.type)) ctx = popContext(state);
12095      }
12096      else if (curPunc == ctx.type) popContext(state);
12097      else if (indentStatements &&
12098               (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
12099                (isStatement(ctx.type) && curPunc == "newstatement"))) {
12100        var type = "statement";
12101        if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
12102          type = "switchstatement";
12103        else if (style == "keyword" && stream.current() == "namespace")
12104          type = "namespace";
12105        pushContext(state, stream.column(), type);
12106      }
12107
12108      if (style == "variable" &&
12109          ((state.prevToken == "def" ||
12110            (parserConfig.typeFirstDefinitions && typeBefore(stream, state) &&
12111             isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
12112        style = "def";
12113
12114      if (hooks.token) {
12115        var result = hooks.token(stream, state, style);
12116        if (result !== undefined) style = result;
12117      }
12118
12119      if (style == "def" && parserConfig.styleDefs === false) style = "variable";
12120
12121      state.startOfLine = false;
12122      state.prevToken = isDefKeyword ? "def" : style || curPunc;
12123      return style;
12124    },
12125
12126    indent: function(state, textAfter) {
12127      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
12128      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
12129      if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
12130      if (hooks.indent) {
12131        var hook = hooks.indent(state, ctx, textAfter);
12132        if (typeof hook == "number") return hook
12133      }
12134      var closing = firstChar == ctx.type;
12135      var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
12136      if (isStatement(ctx.type))
12137        return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
12138      if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
12139        return ctx.column + (closing ? 0 : 1);
12140      if (ctx.type == ")" && !closing)
12141        return ctx.indented + statementIndentUnit;
12142
12143      return ctx.indented + (closing ? 0 : indentUnit) +
12144        (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
12145    },
12146
12147    electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
12148    blockCommentStart: "/*",
12149    blockCommentEnd: "*/",
12150    lineComment: "//",
12151    fold: "brace"
12152  };
12153});
12154
12155  function words(str) {
12156    var obj = {}, words = str.split(" ");
12157    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
12158    return obj;
12159  }
12160  function contains(words, word) {
12161    if (typeof words === "function") {
12162      return words(word);
12163    } else {
12164      return words.propertyIsEnumerable(word);
12165    }
12166  }
12167  var cKeywords = "auto if break case register continue return default do sizeof " +
12168    "static else struct switch extern typedef float union for " +
12169    "goto while enum const volatile";
12170  var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
12171
12172  function cppHook(stream, state) {
12173    if (!state.startOfLine) return false;
12174    for (;;) {
12175      if (stream.skipTo("\\")) {
12176        stream.next();
12177        if (stream.eol()) {
12178          state.tokenize = cppHook;
12179          break;
12180        }
12181      } else {
12182        stream.skipToEnd();
12183        state.tokenize = null;
12184        break;
12185      }
12186    }
12187    return "meta";
12188  }
12189
12190  function pointerHook(_stream, state) {
12191    if (state.prevToken == "variable-3") return "variable-3";
12192    return false;
12193  }
12194
12195  function cpp14Literal(stream) {
12196    stream.eatWhile(/[\w\.']/);
12197    return "number";
12198  }
12199
12200  function cpp11StringHook(stream, state) {
12201    stream.backUp(1);
12202    // Raw strings.
12203    if (stream.match(/(R|u8R|uR|UR|LR)/)) {
12204      var match = stream.match(/"([^\s\\()]{0,16})\(/);
12205      if (!match) {
12206        return false;
12207      }
12208      state.cpp11RawStringDelim = match[1];
12209      state.tokenize = tokenRawString;
12210      return tokenRawString(stream, state);
12211    }
12212    // Unicode strings/chars.
12213    if (stream.match(/(u8|u|U|L)/)) {
12214      if (stream.match(/["']/, /* eat */ false)) {
12215        return "string";
12216      }
12217      return false;
12218    }
12219    // Ignore this hook.
12220    stream.next();
12221    return false;
12222  }
12223
12224  function cppLooksLikeConstructor(word) {
12225    var lastTwo = /(\w+)::(\w+)$/.exec(word);
12226    return lastTwo && lastTwo[1] == lastTwo[2];
12227  }
12228
12229  // C#-style strings where "" escapes a quote.
12230  function tokenAtString(stream, state) {
12231    var next;
12232    while ((next = stream.next()) != null) {
12233      if (next == '"' && !stream.eat('"')) {
12234        state.tokenize = null;
12235        break;
12236      }
12237    }
12238    return "string";
12239  }
12240
12241  // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
12242  // <delim> can be a string up to 16 characters long.
12243  function tokenRawString(stream, state) {
12244    // Escape characters that have special regex meanings.
12245    var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
12246    var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
12247    if (match)
12248      state.tokenize = null;
12249    else
12250      stream.skipToEnd();
12251    return "string";
12252  }
12253
12254  function def(mimes, mode) {
12255    if (typeof mimes == "string") mimes = [mimes];
12256    var words = [];
12257    function add(obj) {
12258      if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
12259        words.push(prop);
12260    }
12261    add(mode.keywords);
12262    add(mode.types);
12263    add(mode.builtin);
12264    add(mode.atoms);
12265    if (words.length) {
12266      mode.helperType = mimes[0];
12267      CodeMirror.registerHelper("hintWords", mimes[0], words);
12268    }
12269
12270    for (var i = 0; i < mimes.length; ++i)
12271      CodeMirror.defineMIME(mimes[i], mode);
12272  }
12273
12274  def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
12275    name: "clike",
12276    keywords: words(cKeywords),
12277    types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
12278                 "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
12279                 "uint32_t uint64_t"),
12280    blockKeywords: words("case do else for if switch while struct"),
12281    defKeywords: words("struct"),
12282    typeFirstDefinitions: true,
12283    atoms: words("null true false"),
12284    hooks: {"#": cppHook, "*": pointerHook},
12285    modeProps: {fold: ["brace", "include"]}
12286  });
12287
12288  def(["text/x-c++src", "text/x-c++hdr"], {
12289    name: "clike",
12290    keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
12291                    "static_cast typeid catch operator template typename class friend private " +
12292                    "this using const_cast inline public throw virtual delete mutable protected " +
12293                    "alignas alignof constexpr decltype nullptr noexcept thread_local final " +
12294                    "static_assert override"),
12295    types: words(cTypes + " bool wchar_t"),
12296    blockKeywords: words("catch class do else finally for if struct switch try while"),
12297    defKeywords: words("class namespace struct enum union"),
12298    typeFirstDefinitions: true,
12299    atoms: words("true false null"),
12300    hooks: {
12301      "#": cppHook,
12302      "*": pointerHook,
12303      "u": cpp11StringHook,
12304      "U": cpp11StringHook,
12305      "L": cpp11StringHook,
12306      "R": cpp11StringHook,
12307      "0": cpp14Literal,
12308      "1": cpp14Literal,
12309      "2": cpp14Literal,
12310      "3": cpp14Literal,
12311      "4": cpp14Literal,
12312      "5": cpp14Literal,
12313      "6": cpp14Literal,
12314      "7": cpp14Literal,
12315      "8": cpp14Literal,
12316      "9": cpp14Literal,
12317      token: function(stream, state, style) {
12318        if (style == "variable" && stream.peek() == "(" &&
12319            (state.prevToken == ";" || state.prevToken == null ||
12320             state.prevToken == "}") &&
12321            cppLooksLikeConstructor(stream.current()))
12322          return "def";
12323      }
12324    },
12325    namespaceSeparator: "::",
12326    modeProps: {fold: ["brace", "include"]}
12327  });
12328
12329  def("text/x-java", {
12330    name: "clike",
12331    keywords: words("abstract assert break case catch class const continue default " +
12332                    "do else enum extends final finally float for goto if implements import " +
12333                    "instanceof interface native new package private protected public " +
12334                    "return static strictfp super switch synchronized this throw throws transient " +
12335                    "try volatile while"),
12336    types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
12337                 "Integer Long Number Object Short String StringBuffer StringBuilder Void"),
12338    blockKeywords: words("catch class do else finally for if switch try while"),
12339    defKeywords: words("class interface package enum"),
12340    typeFirstDefinitions: true,
12341    atoms: words("true false null"),
12342    endStatement: /^[;:]$/,
12343    hooks: {
12344      "@": function(stream) {
12345        stream.eatWhile(/[\w\$_]/);
12346        return "meta";
12347      }
12348    },
12349    modeProps: {fold: ["brace", "import"]}
12350  });
12351
12352  def("text/x-csharp", {
12353    name: "clike",
12354    keywords: words("abstract as async await base break case catch checked class const continue" +
12355                    " default delegate do else enum event explicit extern finally fixed for" +
12356                    " foreach goto if implicit in interface internal is lock namespace new" +
12357                    " operator out override params private protected public readonly ref return sealed" +
12358                    " sizeof stackalloc static struct switch this throw try typeof unchecked" +
12359                    " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
12360                    " global group into join let orderby partial remove select set value var yield"),
12361    types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
12362                 " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
12363                 " UInt64 bool byte char decimal double short int long object"  +
12364                 " sbyte float string ushort uint ulong"),
12365    blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
12366    defKeywords: words("class interface namespace struct var"),
12367    typeFirstDefinitions: true,
12368    atoms: words("true false null"),
12369    hooks: {
12370      "@": function(stream, state) {
12371        if (stream.eat('"')) {
12372          state.tokenize = tokenAtString;
12373          return tokenAtString(stream, state);
12374        }
12375        stream.eatWhile(/[\w\$_]/);
12376        return "meta";
12377      }
12378    }
12379  });
12380
12381  function tokenTripleString(stream, state) {
12382    var escaped = false;
12383    while (!stream.eol()) {
12384      if (!escaped && stream.match('"""')) {
12385        state.tokenize = null;
12386        break;
12387      }
12388      escaped = stream.next() == "\\" && !escaped;
12389    }
12390    return "string";
12391  }
12392
12393  def("text/x-scala", {
12394    name: "clike",
12395    keywords: words(
12396
12397      /* scala */
12398      "abstract case catch class def do else extends final finally for forSome if " +
12399      "implicit import lazy match new null object override package private protected return " +
12400      "sealed super this throw trait try type val var while with yield _ : = => <- <: " +
12401      "<% >: # @ " +
12402
12403      /* package scala */
12404      "assert assume require print println printf readLine readBoolean readByte readShort " +
12405      "readChar readInt readLong readFloat readDouble " +
12406
12407      ":: #:: "
12408    ),
12409    types: words(
12410      "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
12411      "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
12412      "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
12413      "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
12414      "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
12415
12416      /* package java.lang */
12417      "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
12418      "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
12419      "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
12420      "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
12421    ),
12422    multiLineStrings: true,
12423    blockKeywords: words("catch class do else finally for forSome if match switch try while"),
12424    defKeywords: words("class def object package trait type val var"),
12425    atoms: words("true false null"),
12426    indentStatements: false,
12427    indentSwitch: false,
12428    hooks: {
12429      "@": function(stream) {
12430        stream.eatWhile(/[\w\$_]/);
12431        return "meta";
12432      },
12433      '"': function(stream, state) {
12434        if (!stream.match('""')) return false;
12435        state.tokenize = tokenTripleString;
12436        return state.tokenize(stream, state);
12437      },
12438      "'": function(stream) {
12439        stream.eatWhile(/[\w\$_\xa1-\uffff]/);
12440        return "atom";
12441      }
12442    },
12443    modeProps: {closeBrackets: {triples: '"'}}
12444  });
12445
12446  def("text/x-kotlin", {
12447    name: "clike",
12448    keywords: words(
12449      /*keywords*/
12450      "package as typealias class interface this super val " +
12451      "var fun for is in This throw return " +
12452      "break continue object if else while do try when !in !is as?" +
12453
12454      /*soft keywords*/
12455      "file import where by get set abstract enum open inner override private public internal " +
12456      "protected catch finally out final vararg reified dynamic companion constructor init " +
12457      "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
12458      "external annotation crossinline"
12459    ),
12460    types: words(
12461      /* package java.lang */
12462      "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
12463      "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
12464      "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
12465      "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
12466    ),
12467    multiLineStrings: true,
12468    blockKeywords: words("catch class do else finally for if where try while enum"),
12469    defKeywords: words("class val var object package interface fun"),
12470    atoms: words("true false null this"),
12471    modeProps: {closeBrackets: {triples: '"'}}
12472  });
12473
12474  def(["x-shader/x-vertex", "x-shader/x-fragment"], {
12475    name: "clike",
12476    keywords: words("sampler1D sampler2D sampler3D samplerCube " +
12477                    "sampler1DShadow sampler2DShadow " +
12478                    "const attribute uniform varying " +
12479                    "break continue discard return " +
12480                    "for while do if else struct " +
12481                    "in out inout"),
12482    types: words("float int bool void " +
12483                 "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
12484                 "mat2 mat3 mat4"),
12485    blockKeywords: words("for while do if else struct"),
12486    builtin: words("radians degrees sin cos tan asin acos atan " +
12487                    "pow exp log exp2 sqrt inversesqrt " +
12488                    "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
12489                    "length distance dot cross normalize ftransform faceforward " +
12490                    "reflect refract matrixCompMult " +
12491                    "lessThan lessThanEqual greaterThan greaterThanEqual " +
12492                    "equal notEqual any all not " +
12493                    "texture1D texture1DProj texture1DLod texture1DProjLod " +
12494                    "texture2D texture2DProj texture2DLod texture2DProjLod " +
12495                    "texture3D texture3DProj texture3DLod texture3DProjLod " +
12496                    "textureCube textureCubeLod " +
12497                    "shadow1D shadow2D shadow1DProj shadow2DProj " +
12498                    "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
12499                    "dFdx dFdy fwidth " +
12500                    "noise1 noise2 noise3 noise4"),
12501    atoms: words("true false " +
12502                "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
12503                "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
12504                "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
12505                "gl_FogCoord gl_PointCoord " +
12506                "gl_Position gl_PointSize gl_ClipVertex " +
12507                "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
12508                "gl_TexCoord gl_FogFragCoord " +
12509                "gl_FragCoord gl_FrontFacing " +
12510                "gl_FragData gl_FragDepth " +
12511                "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
12512                "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
12513                "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
12514                "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
12515                "gl_ProjectionMatrixInverseTranspose " +
12516                "gl_ModelViewProjectionMatrixInverseTranspose " +
12517                "gl_TextureMatrixInverseTranspose " +
12518                "gl_NormalScale gl_DepthRange gl_ClipPlane " +
12519                "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
12520                "gl_FrontLightModelProduct gl_BackLightModelProduct " +
12521                "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
12522                "gl_FogParameters " +
12523                "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
12524                "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
12525                "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
12526                "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
12527                "gl_MaxDrawBuffers"),
12528    indentSwitch: false,
12529    hooks: {"#": cppHook},
12530    modeProps: {fold: ["brace", "include"]}
12531  });
12532
12533  def("text/x-nesc", {
12534    name: "clike",
12535    keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
12536                    "implementation includes interface module new norace nx_struct nx_union post provides " +
12537                    "signal task uses abstract extends"),
12538    types: words(cTypes),
12539    blockKeywords: words("case do else for if switch while struct"),
12540    atoms: words("null true false"),
12541    hooks: {"#": cppHook},
12542    modeProps: {fold: ["brace", "include"]}
12543  });
12544
12545  def("text/x-objectivec", {
12546    name: "clike",
12547    keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
12548                    "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
12549    types: words(cTypes),
12550    atoms: words("YES NO NULL NILL ON OFF true false"),
12551    hooks: {
12552      "@": function(stream) {
12553        stream.eatWhile(/[\w\$]/);
12554        return "keyword";
12555      },
12556      "#": cppHook,
12557      indent: function(_state, ctx, textAfter) {
12558        if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
12559      }
12560    },
12561    modeProps: {fold: "brace"}
12562  });
12563
12564  def("text/x-squirrel", {
12565    name: "clike",
12566    keywords: words("base break clone continue const default delete enum extends function in class" +
12567                    " foreach local resume return this throw typeof yield constructor instanceof static"),
12568    types: words(cTypes),
12569    blockKeywords: words("case catch class else for foreach if switch try while"),
12570    defKeywords: words("function local class"),
12571    typeFirstDefinitions: true,
12572    atoms: words("true false null"),
12573    hooks: {"#": cppHook},
12574    modeProps: {fold: ["brace", "include"]}
12575  });
12576
12577  // Ceylon Strings need to deal with interpolation
12578  var stringTokenizer = null;
12579  function tokenCeylonString(type) {
12580    return function(stream, state) {
12581      var escaped = false, next, end = false;
12582      while (!stream.eol()) {
12583        if (!escaped && stream.match('"') &&
12584              (type == "single" || stream.match('""'))) {
12585          end = true;
12586          break;
12587        }
12588        if (!escaped && stream.match('``')) {
12589          stringTokenizer = tokenCeylonString(type);
12590          end = true;
12591          break;
12592        }
12593        next = stream.next();
12594        escaped = type == "single" && !escaped && next == "\\";
12595      }
12596      if (end)
12597          state.tokenize = null;
12598      return "string";
12599    }
12600  }
12601
12602  def("text/x-ceylon", {
12603    name: "clike",
12604    keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
12605                    " exists extends finally for function given if import in interface is let module new" +
12606                    " nonempty object of out outer package return satisfies super switch then this throw" +
12607                    " try value void while"),
12608    types: function(word) {
12609        // In Ceylon all identifiers that start with an uppercase are types
12610        var first = word.charAt(0);
12611        return (first === first.toUpperCase() && first !== first.toLowerCase());
12612    },
12613    blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
12614    defKeywords: words("class dynamic function interface module object package value"),
12615    builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
12616                   " native optional sealed see serializable shared suppressWarnings tagged throws variable"),
12617    isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
12618    isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
12619    isNumberChar: /[\d#$]/,
12620    multiLineStrings: true,
12621    typeFirstDefinitions: true,
12622    atoms: words("true false null larger smaller equal empty finished"),
12623    indentSwitch: false,
12624    styleDefs: false,
12625    hooks: {
12626      "@": function(stream) {
12627        stream.eatWhile(/[\w\$_]/);
12628        return "meta";
12629      },
12630      '"': function(stream, state) {
12631          state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
12632          return state.tokenize(stream, state);
12633        },
12634      '`': function(stream, state) {
12635          if (!stringTokenizer || !stream.match('`')) return false;
12636          state.tokenize = stringTokenizer;
12637          stringTokenizer = null;
12638          return state.tokenize(stream, state);
12639        },
12640      "'": function(stream) {
12641        stream.eatWhile(/[\w\$_\xa1-\uffff]/);
12642        return "atom";
12643      },
12644      token: function(_stream, state, style) {
12645          if ((style == "variable" || style == "variable-3") &&
12646              state.prevToken == ".") {
12647            return "variable-2";
12648          }
12649        }
12650    },
12651    modeProps: {
12652        fold: ["brace", "import"],
12653        closeBrackets: {triples: '"'}
12654    }
12655  });
12656
12657});
12658
12659},{"../../lib/codemirror":30}],32:[function(_dereq_,module,exports){
12660_dereq_('../modules/web.dom.iterable');
12661_dereq_('../modules/es6.string.iterator');
12662module.exports = _dereq_('../modules/core.get-iterator');
12663},{"../modules/core.get-iterator":95,"../modules/es6.string.iterator":104,"../modules/web.dom.iterable":106}],33:[function(_dereq_,module,exports){
12664_dereq_('../../modules/es6.object.assign');
12665module.exports = _dereq_('../../modules/$.core').Object.assign;
12666},{"../../modules/$.core":49,"../../modules/es6.object.assign":97}],34:[function(_dereq_,module,exports){
12667var $ = _dereq_('../../modules/$');
12668module.exports = function create(P, D){
12669  return $.create(P, D);
12670};
12671},{"../../modules/$":71}],35:[function(_dereq_,module,exports){
12672var $ = _dereq_('../../modules/$');
12673module.exports = function defineProperty(it, key, desc){
12674  return $.setDesc(it, key, desc);
12675};
12676},{"../../modules/$":71}],36:[function(_dereq_,module,exports){
12677var $ = _dereq_('../../modules/$');
12678_dereq_('../../modules/es6.object.get-own-property-descriptor');
12679module.exports = function getOwnPropertyDescriptor(it, key){
12680  return $.getDesc(it, key);
12681};
12682},{"../../modules/$":71,"../../modules/es6.object.get-own-property-descriptor":98}],37:[function(_dereq_,module,exports){
12683_dereq_('../../modules/es6.object.keys');
12684module.exports = _dereq_('../../modules/$.core').Object.keys;
12685},{"../../modules/$.core":49,"../../modules/es6.object.keys":99}],38:[function(_dereq_,module,exports){
12686_dereq_('../../modules/es6.object.set-prototype-of');
12687module.exports = _dereq_('../../modules/$.core').Object.setPrototypeOf;
12688},{"../../modules/$.core":49,"../../modules/es6.object.set-prototype-of":100}],39:[function(_dereq_,module,exports){
12689_dereq_('../modules/es6.object.to-string');
12690_dereq_('../modules/es6.string.iterator');
12691_dereq_('../modules/web.dom.iterable');
12692_dereq_('../modules/es6.promise');
12693module.exports = _dereq_('../modules/$.core').Promise;
12694},{"../modules/$.core":49,"../modules/es6.object.to-string":101,"../modules/es6.promise":102,"../modules/es6.string.iterator":104,"../modules/web.dom.iterable":106}],40:[function(_dereq_,module,exports){
12695_dereq_('../modules/es6.object.to-string');
12696_dereq_('../modules/es6.string.iterator');
12697_dereq_('../modules/web.dom.iterable');
12698_dereq_('../modules/es6.set');
12699_dereq_('../modules/es7.set.to-json');
12700module.exports = _dereq_('../modules/$.core').Set;
12701},{"../modules/$.core":49,"../modules/es6.object.to-string":101,"../modules/es6.set":103,"../modules/es6.string.iterator":104,"../modules/es7.set.to-json":105,"../modules/web.dom.iterable":106}],41:[function(_dereq_,module,exports){
12702module.exports = function(it){
12703  if(typeof it != 'function')throw TypeError(it + ' is not a function!');
12704  return it;
12705};
12706},{}],42:[function(_dereq_,module,exports){
12707module.exports = function(){ /* empty */ };
12708},{}],43:[function(_dereq_,module,exports){
12709var isObject = _dereq_('./$.is-object');
12710module.exports = function(it){
12711  if(!isObject(it))throw TypeError(it + ' is not an object!');
12712  return it;
12713};
12714},{"./$.is-object":64}],44:[function(_dereq_,module,exports){
12715// getting tag from 19.1.3.6 Object.prototype.toString()
12716var cof = _dereq_('./$.cof')
12717  , TAG = _dereq_('./$.wks')('toStringTag')
12718  // ES3 wrong here
12719  , ARG = cof(function(){ return arguments; }()) == 'Arguments';
12720
12721module.exports = function(it){
12722  var O, T, B;
12723  return it === undefined ? 'Undefined' : it === null ? 'Null'
12724    // @@toStringTag case
12725    : typeof (T = (O = Object(it))[TAG]) == 'string' ? T
12726    // builtinTag case
12727    : ARG ? cof(O)
12728    // ES3 arguments fallback
12729    : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
12730};
12731},{"./$.cof":45,"./$.wks":93}],45:[function(_dereq_,module,exports){
12732var toString = {}.toString;
12733
12734module.exports = function(it){
12735  return toString.call(it).slice(8, -1);
12736};
12737},{}],46:[function(_dereq_,module,exports){
12738'use strict';
12739var $            = _dereq_('./$')
12740  , hide         = _dereq_('./$.hide')
12741  , redefineAll  = _dereq_('./$.redefine-all')
12742  , ctx          = _dereq_('./$.ctx')
12743  , strictNew    = _dereq_('./$.strict-new')
12744  , defined      = _dereq_('./$.defined')
12745  , forOf        = _dereq_('./$.for-of')
12746  , $iterDefine  = _dereq_('./$.iter-define')
12747  , step         = _dereq_('./$.iter-step')
12748  , ID           = _dereq_('./$.uid')('id')
12749  , $has         = _dereq_('./$.has')
12750  , isObject     = _dereq_('./$.is-object')
12751  , setSpecies   = _dereq_('./$.set-species')
12752  , DESCRIPTORS  = _dereq_('./$.descriptors')
12753  , isExtensible = Object.isExtensible || isObject
12754  , SIZE         = DESCRIPTORS ? '_s' : 'size'
12755  , id           = 0;
12756
12757var fastKey = function(it, create){
12758  // return primitive with prefix
12759  if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
12760  if(!$has(it, ID)){
12761    // can't set id to frozen object
12762    if(!isExtensible(it))return 'F';
12763    // not necessary to add id
12764    if(!create)return 'E';
12765    // add missing object id
12766    hide(it, ID, ++id);
12767  // return object id with prefix
12768  } return 'O' + it[ID];
12769};
12770
12771var getEntry = function(that, key){
12772  // fast case
12773  var index = fastKey(key), entry;
12774  if(index !== 'F')return that._i[index];
12775  // frozen object case
12776  for(entry = that._f; entry; entry = entry.n){
12777    if(entry.k == key)return entry;
12778  }
12779};
12780
12781module.exports = {
12782  getConstructor: function(wrapper, NAME, IS_MAP, ADDER){
12783    var C = wrapper(function(that, iterable){
12784      strictNew(that, C, NAME);
12785      that._i = $.create(null); // index
12786      that._f = undefined;      // first entry
12787      that._l = undefined;      // last entry
12788      that[SIZE] = 0;           // size
12789      if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
12790    });
12791    redefineAll(C.prototype, {
12792      // 23.1.3.1 Map.prototype.clear()
12793      // 23.2.3.2 Set.prototype.clear()
12794      clear: function clear(){
12795        for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){
12796          entry.r = true;
12797          if(entry.p)entry.p = entry.p.n = undefined;
12798          delete data[entry.i];
12799        }
12800        that._f = that._l = undefined;
12801        that[SIZE] = 0;
12802      },
12803      // 23.1.3.3 Map.prototype.delete(key)
12804      // 23.2.3.4 Set.prototype.delete(value)
12805      'delete': function(key){
12806        var that  = this
12807          , entry = getEntry(that, key);
12808        if(entry){
12809          var next = entry.n
12810            , prev = entry.p;
12811          delete that._i[entry.i];
12812          entry.r = true;
12813          if(prev)prev.n = next;
12814          if(next)next.p = prev;
12815          if(that._f == entry)that._f = next;
12816          if(that._l == entry)that._l = prev;
12817          that[SIZE]--;
12818        } return !!entry;
12819      },
12820      // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
12821      // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
12822      forEach: function forEach(callbackfn /*, that = undefined */){
12823        var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3)
12824          , entry;
12825        while(entry = entry ? entry.n : this._f){
12826          f(entry.v, entry.k, this);
12827          // revert to the last existing entry
12828          while(entry && entry.r)entry = entry.p;
12829        }
12830      },
12831      // 23.1.3.7 Map.prototype.has(key)
12832      // 23.2.3.7 Set.prototype.has(value)
12833      has: function has(key){
12834        return !!getEntry(this, key);
12835      }
12836    });
12837    if(DESCRIPTORS)$.setDesc(C.prototype, 'size', {
12838      get: function(){
12839        return defined(this[SIZE]);
12840      }
12841    });
12842    return C;
12843  },
12844  def: function(that, key, value){
12845    var entry = getEntry(that, key)
12846      , prev, index;
12847    // change existing entry
12848    if(entry){
12849      entry.v = value;
12850    // create new entry
12851    } else {
12852      that._l = entry = {
12853        i: index = fastKey(key, true), // <- index
12854        k: key,                        // <- key
12855        v: value,                      // <- value
12856        p: prev = that._l,             // <- previous entry
12857        n: undefined,                  // <- next entry
12858        r: false                       // <- removed
12859      };
12860      if(!that._f)that._f = entry;
12861      if(prev)prev.n = entry;
12862      that[SIZE]++;
12863      // add to index
12864      if(index !== 'F')that._i[index] = entry;
12865    } return that;
12866  },
12867  getEntry: getEntry,
12868  setStrong: function(C, NAME, IS_MAP){
12869    // add .keys, .values, .entries, [@@iterator]
12870    // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
12871    $iterDefine(C, NAME, function(iterated, kind){
12872      this._t = iterated;  // target
12873      this._k = kind;      // kind
12874      this._l = undefined; // previous
12875    }, function(){
12876      var that  = this
12877        , kind  = that._k
12878        , entry = that._l;
12879      // revert to the last existing entry
12880      while(entry && entry.r)entry = entry.p;
12881      // get next entry
12882      if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){
12883        // or finish the iteration
12884        that._t = undefined;
12885        return step(1);
12886      }
12887      // return step by kind
12888      if(kind == 'keys'  )return step(0, entry.k);
12889      if(kind == 'values')return step(0, entry.v);
12890      return step(0, [entry.k, entry.v]);
12891    }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true);
12892
12893    // add [@@species], 23.1.2.2, 23.2.2.2
12894    setSpecies(NAME);
12895  }
12896};
12897},{"./$":71,"./$.ctx":50,"./$.defined":51,"./$.descriptors":52,"./$.for-of":56,"./$.has":58,"./$.hide":59,"./$.is-object":64,"./$.iter-define":67,"./$.iter-step":69,"./$.redefine-all":77,"./$.set-species":81,"./$.strict-new":85,"./$.uid":92}],47:[function(_dereq_,module,exports){
12898// https://github.com/DavidBruant/Map-Set.prototype.toJSON
12899var forOf   = _dereq_('./$.for-of')
12900  , classof = _dereq_('./$.classof');
12901module.exports = function(NAME){
12902  return function toJSON(){
12903    if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic");
12904    var arr = [];
12905    forOf(this, false, arr.push, arr);
12906    return arr;
12907  };
12908};
12909},{"./$.classof":44,"./$.for-of":56}],48:[function(_dereq_,module,exports){
12910'use strict';
12911var $              = _dereq_('./$')
12912  , global         = _dereq_('./$.global')
12913  , $export        = _dereq_('./$.export')
12914  , fails          = _dereq_('./$.fails')
12915  , hide           = _dereq_('./$.hide')
12916  , redefineAll    = _dereq_('./$.redefine-all')
12917  , forOf          = _dereq_('./$.for-of')
12918  , strictNew      = _dereq_('./$.strict-new')
12919  , isObject       = _dereq_('./$.is-object')
12920  , setToStringTag = _dereq_('./$.set-to-string-tag')
12921  , DESCRIPTORS    = _dereq_('./$.descriptors');
12922
12923module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){
12924  var Base  = global[NAME]
12925    , C     = Base
12926    , ADDER = IS_MAP ? 'set' : 'add'
12927    , proto = C && C.prototype
12928    , O     = {};
12929  if(!DESCRIPTORS || typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){
12930    new C().entries().next();
12931  }))){
12932    // create collection constructor
12933    C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
12934    redefineAll(C.prototype, methods);
12935  } else {
12936    C = wrapper(function(target, iterable){
12937      strictNew(target, C, NAME);
12938      target._c = new Base;
12939      if(iterable != undefined)forOf(iterable, IS_MAP, target[ADDER], target);
12940    });
12941    $.each.call('add,clear,delete,forEach,get,has,set,keys,values,entries'.split(','),function(KEY){
12942      var IS_ADDER = KEY == 'add' || KEY == 'set';
12943      if(KEY in proto && !(IS_WEAK && KEY == 'clear'))hide(C.prototype, KEY, function(a, b){
12944        if(!IS_ADDER && IS_WEAK && !isObject(a))return KEY == 'get' ? undefined : false;
12945        var result = this._c[KEY](a === 0 ? 0 : a, b);
12946        return IS_ADDER ? this : result;
12947      });
12948    });
12949    if('size' in proto)$.setDesc(C.prototype, 'size', {
12950      get: function(){
12951        return this._c.size;
12952      }
12953    });
12954  }
12955
12956  setToStringTag(C, NAME);
12957
12958  O[NAME] = C;
12959  $export($export.G + $export.W + $export.F, O);
12960
12961  if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP);
12962
12963  return C;
12964};
12965},{"./$":71,"./$.descriptors":52,"./$.export":54,"./$.fails":55,"./$.for-of":56,"./$.global":57,"./$.hide":59,"./$.is-object":64,"./$.redefine-all":77,"./$.set-to-string-tag":82,"./$.strict-new":85}],49:[function(_dereq_,module,exports){
12966var core = module.exports = {version: '1.2.6'};
12967if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
12968},{}],50:[function(_dereq_,module,exports){
12969// optional / simple context binding
12970var aFunction = _dereq_('./$.a-function');
12971module.exports = function(fn, that, length){
12972  aFunction(fn);
12973  if(that === undefined)return fn;
12974  switch(length){
12975    case 1: return function(a){
12976      return fn.call(that, a);
12977    };
12978    case 2: return function(a, b){
12979      return fn.call(that, a, b);
12980    };
12981    case 3: return function(a, b, c){
12982      return fn.call(that, a, b, c);
12983    };
12984  }
12985  return function(/* ...args */){
12986    return fn.apply(that, arguments);
12987  };
12988};
12989},{"./$.a-function":41}],51:[function(_dereq_,module,exports){
12990// 7.2.1 RequireObjectCoercible(argument)
12991module.exports = function(it){
12992  if(it == undefined)throw TypeError("Can't call method on  " + it);
12993  return it;
12994};
12995},{}],52:[function(_dereq_,module,exports){
12996// Thank's IE8 for his funny defineProperty
12997module.exports = !_dereq_('./$.fails')(function(){
12998  return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;
12999});
13000},{"./$.fails":55}],53:[function(_dereq_,module,exports){
13001var isObject = _dereq_('./$.is-object')
13002  , document = _dereq_('./$.global').document
13003  // in old IE typeof document.createElement is 'object'
13004  , is = isObject(document) && isObject(document.createElement);
13005module.exports = function(it){
13006  return is ? document.createElement(it) : {};
13007};
13008},{"./$.global":57,"./$.is-object":64}],54:[function(_dereq_,module,exports){
13009var global    = _dereq_('./$.global')
13010  , core      = _dereq_('./$.core')
13011  , ctx       = _dereq_('./$.ctx')
13012  , PROTOTYPE = 'prototype';
13013
13014var $export = function(type, name, source){
13015  var IS_FORCED = type & $export.F
13016    , IS_GLOBAL = type & $export.G
13017    , IS_STATIC = type & $export.S
13018    , IS_PROTO  = type & $export.P
13019    , IS_BIND   = type & $export.B
13020    , IS_WRAP   = type & $export.W
13021    , exports   = IS_GLOBAL ? core : core[name] || (core[name] = {})
13022    , target    = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]
13023    , key, own, out;
13024  if(IS_GLOBAL)source = name;
13025  for(key in source){
13026    // contains in native
13027    own = !IS_FORCED && target && key in target;
13028    if(own && key in exports)continue;
13029    // export native or passed
13030    out = own ? target[key] : source[key];
13031    // prevent global pollution for namespaces
13032    exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
13033    // bind timers to global for call from export context
13034    : IS_BIND && own ? ctx(out, global)
13035    // wrap global constructors for prevent change them in library
13036    : IS_WRAP && target[key] == out ? (function(C){
13037      var F = function(param){
13038        return this instanceof C ? new C(param) : C(param);
13039      };
13040      F[PROTOTYPE] = C[PROTOTYPE];
13041      return F;
13042    // make static versions for prototype methods
13043    })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
13044    if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
13045  }
13046};
13047// type bitmap
13048$export.F = 1;  // forced
13049$export.G = 2;  // global
13050$export.S = 4;  // static
13051$export.P = 8;  // proto
13052$export.B = 16; // bind
13053$export.W = 32; // wrap
13054module.exports = $export;
13055},{"./$.core":49,"./$.ctx":50,"./$.global":57}],55:[function(_dereq_,module,exports){
13056module.exports = function(exec){
13057  try {
13058    return !!exec();
13059  } catch(e){
13060    return true;
13061  }
13062};
13063},{}],56:[function(_dereq_,module,exports){
13064var ctx         = _dereq_('./$.ctx')
13065  , call        = _dereq_('./$.iter-call')
13066  , isArrayIter = _dereq_('./$.is-array-iter')
13067  , anObject    = _dereq_('./$.an-object')
13068  , toLength    = _dereq_('./$.to-length')
13069  , getIterFn   = _dereq_('./core.get-iterator-method');
13070module.exports = function(iterable, entries, fn, that){
13071  var iterFn = getIterFn(iterable)
13072    , f      = ctx(fn, that, entries ? 2 : 1)
13073    , index  = 0
13074    , length, step, iterator;
13075  if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!');
13076  // fast case for arrays with default iterator
13077  if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){
13078    entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
13079  } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){
13080    call(iterator, f, step.value, entries);
13081  }
13082};
13083},{"./$.an-object":43,"./$.ctx":50,"./$.is-array-iter":63,"./$.iter-call":65,"./$.to-length":90,"./core.get-iterator-method":94}],57:[function(_dereq_,module,exports){
13084// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
13085var global = module.exports = typeof window != 'undefined' && window.Math == Math
13086  ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
13087if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
13088},{}],58:[function(_dereq_,module,exports){
13089var hasOwnProperty = {}.hasOwnProperty;
13090module.exports = function(it, key){
13091  return hasOwnProperty.call(it, key);
13092};
13093},{}],59:[function(_dereq_,module,exports){
13094var $          = _dereq_('./$')
13095  , createDesc = _dereq_('./$.property-desc');
13096module.exports = _dereq_('./$.descriptors') ? function(object, key, value){
13097  return $.setDesc(object, key, createDesc(1, value));
13098} : function(object, key, value){
13099  object[key] = value;
13100  return object;
13101};
13102},{"./$":71,"./$.descriptors":52,"./$.property-desc":76}],60:[function(_dereq_,module,exports){
13103module.exports = _dereq_('./$.global').document && document.documentElement;
13104},{"./$.global":57}],61:[function(_dereq_,module,exports){
13105// fast apply, http://jsperf.lnkit.com/fast-apply/5
13106module.exports = function(fn, args, that){
13107  var un = that === undefined;
13108  switch(args.length){
13109    case 0: return un ? fn()
13110                      : fn.call(that);
13111    case 1: return un ? fn(args[0])
13112                      : fn.call(that, args[0]);
13113    case 2: return un ? fn(args[0], args[1])
13114                      : fn.call(that, args[0], args[1]);
13115    case 3: return un ? fn(args[0], args[1], args[2])
13116                      : fn.call(that, args[0], args[1], args[2]);
13117    case 4: return un ? fn(args[0], args[1], args[2], args[3])
13118                      : fn.call(that, args[0], args[1], args[2], args[3]);
13119  } return              fn.apply(that, args);
13120};
13121},{}],62:[function(_dereq_,module,exports){
13122// fallback for non-array-like ES3 and non-enumerable old V8 strings
13123var cof = _dereq_('./$.cof');
13124module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){
13125  return cof(it) == 'String' ? it.split('') : Object(it);
13126};
13127},{"./$.cof":45}],63:[function(_dereq_,module,exports){
13128// check on default Array iterator
13129var Iterators  = _dereq_('./$.iterators')
13130  , ITERATOR   = _dereq_('./$.wks')('iterator')
13131  , ArrayProto = Array.prototype;
13132
13133module.exports = function(it){
13134  return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
13135};
13136},{"./$.iterators":70,"./$.wks":93}],64:[function(_dereq_,module,exports){
13137module.exports = function(it){
13138  return typeof it === 'object' ? it !== null : typeof it === 'function';
13139};
13140},{}],65:[function(_dereq_,module,exports){
13141// call something on iterator step with safe closing on error
13142var anObject = _dereq_('./$.an-object');
13143module.exports = function(iterator, fn, value, entries){
13144  try {
13145    return entries ? fn(anObject(value)[0], value[1]) : fn(value);
13146  // 7.4.6 IteratorClose(iterator, completion)
13147  } catch(e){
13148    var ret = iterator['return'];
13149    if(ret !== undefined)anObject(ret.call(iterator));
13150    throw e;
13151  }
13152};
13153},{"./$.an-object":43}],66:[function(_dereq_,module,exports){
13154'use strict';
13155var $              = _dereq_('./$')
13156  , descriptor     = _dereq_('./$.property-desc')
13157  , setToStringTag = _dereq_('./$.set-to-string-tag')
13158  , IteratorPrototype = {};
13159
13160// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
13161_dereq_('./$.hide')(IteratorPrototype, _dereq_('./$.wks')('iterator'), function(){ return this; });
13162
13163module.exports = function(Constructor, NAME, next){
13164  Constructor.prototype = $.create(IteratorPrototype, {next: descriptor(1, next)});
13165  setToStringTag(Constructor, NAME + ' Iterator');
13166};
13167},{"./$":71,"./$.hide":59,"./$.property-desc":76,"./$.set-to-string-tag":82,"./$.wks":93}],67:[function(_dereq_,module,exports){
13168'use strict';
13169var LIBRARY        = _dereq_('./$.library')
13170  , $export        = _dereq_('./$.export')
13171  , redefine       = _dereq_('./$.redefine')
13172  , hide           = _dereq_('./$.hide')
13173  , has            = _dereq_('./$.has')
13174  , Iterators      = _dereq_('./$.iterators')
13175  , $iterCreate    = _dereq_('./$.iter-create')
13176  , setToStringTag = _dereq_('./$.set-to-string-tag')
13177  , getProto       = _dereq_('./$').getProto
13178  , ITERATOR       = _dereq_('./$.wks')('iterator')
13179  , BUGGY          = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next`
13180  , FF_ITERATOR    = '@@iterator'
13181  , KEYS           = 'keys'
13182  , VALUES         = 'values';
13183
13184var returnThis = function(){ return this; };
13185
13186module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){
13187  $iterCreate(Constructor, NAME, next);
13188  var getMethod = function(kind){
13189    if(!BUGGY && kind in proto)return proto[kind];
13190    switch(kind){
13191      case KEYS: return function keys(){ return new Constructor(this, kind); };
13192      case VALUES: return function values(){ return new Constructor(this, kind); };
13193    } return function entries(){ return new Constructor(this, kind); };
13194  };
13195  var TAG        = NAME + ' Iterator'
13196    , DEF_VALUES = DEFAULT == VALUES
13197    , VALUES_BUG = false
13198    , proto      = Base.prototype
13199    , $native    = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]
13200    , $default   = $native || getMethod(DEFAULT)
13201    , methods, key;
13202  // Fix native
13203  if($native){
13204    var IteratorPrototype = getProto($default.call(new Base));
13205    // Set @@toStringTag to native iterators
13206    setToStringTag(IteratorPrototype, TAG, true);
13207    // FF fix
13208    if(!LIBRARY && has(proto, FF_ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);
13209    // fix Array#{values, @@iterator}.name in V8 / FF
13210    if(DEF_VALUES && $native.name !== VALUES){
13211      VALUES_BUG = true;
13212      $default = function values(){ return $native.call(this); };
13213    }
13214  }
13215  // Define iterator
13216  if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){
13217    hide(proto, ITERATOR, $default);
13218  }
13219  // Plug for library
13220  Iterators[NAME] = $default;
13221  Iterators[TAG]  = returnThis;
13222  if(DEFAULT){
13223    methods = {
13224      values:  DEF_VALUES  ? $default : getMethod(VALUES),
13225      keys:    IS_SET      ? $default : getMethod(KEYS),
13226      entries: !DEF_VALUES ? $default : getMethod('entries')
13227    };
13228    if(FORCED)for(key in methods){
13229      if(!(key in proto))redefine(proto, key, methods[key]);
13230    } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
13231  }
13232  return methods;
13233};
13234},{"./$":71,"./$.export":54,"./$.has":58,"./$.hide":59,"./$.iter-create":66,"./$.iterators":70,"./$.library":72,"./$.redefine":78,"./$.set-to-string-tag":82,"./$.wks":93}],68:[function(_dereq_,module,exports){
13235var ITERATOR     = _dereq_('./$.wks')('iterator')
13236  , SAFE_CLOSING = false;
13237
13238try {
13239  var riter = [7][ITERATOR]();
13240  riter['return'] = function(){ SAFE_CLOSING = true; };
13241  Array.from(riter, function(){ throw 2; });
13242} catch(e){ /* empty */ }
13243
13244module.exports = function(exec, skipClosing){
13245  if(!skipClosing && !SAFE_CLOSING)return false;
13246  var safe = false;
13247  try {
13248    var arr  = [7]
13249      , iter = arr[ITERATOR]();
13250    iter.next = function(){ return {done: safe = true}; };
13251    arr[ITERATOR] = function(){ return iter; };
13252    exec(arr);
13253  } catch(e){ /* empty */ }
13254  return safe;
13255};
13256},{"./$.wks":93}],69:[function(_dereq_,module,exports){
13257module.exports = function(done, value){
13258  return {value: value, done: !!done};
13259};
13260},{}],70:[function(_dereq_,module,exports){
13261module.exports = {};
13262},{}],71:[function(_dereq_,module,exports){
13263var $Object = Object;
13264module.exports = {
13265  create:     $Object.create,
13266  getProto:   $Object.getPrototypeOf,
13267  isEnum:     {}.propertyIsEnumerable,
13268  getDesc:    $Object.getOwnPropertyDescriptor,
13269  setDesc:    $Object.defineProperty,
13270  setDescs:   $Object.defineProperties,
13271  getKeys:    $Object.keys,
13272  getNames:   $Object.getOwnPropertyNames,
13273  getSymbols: $Object.getOwnPropertySymbols,
13274  each:       [].forEach
13275};
13276},{}],72:[function(_dereq_,module,exports){
13277module.exports = true;
13278},{}],73:[function(_dereq_,module,exports){
13279var global    = _dereq_('./$.global')
13280  , macrotask = _dereq_('./$.task').set
13281  , Observer  = global.MutationObserver || global.WebKitMutationObserver
13282  , process   = global.process
13283  , Promise   = global.Promise
13284  , isNode    = _dereq_('./$.cof')(process) == 'process'
13285  , head, last, notify;
13286
13287var flush = function(){
13288  var parent, domain, fn;
13289  if(isNode && (parent = process.domain)){
13290    process.domain = null;
13291    parent.exit();
13292  }
13293  while(head){
13294    domain = head.domain;
13295    fn     = head.fn;
13296    if(domain)domain.enter();
13297    fn(); // <- currently we use it only for Promise - try / catch not required
13298    if(domain)domain.exit();
13299    head = head.next;
13300  } last = undefined;
13301  if(parent)parent.enter();
13302};
13303
13304// Node.js
13305if(isNode){
13306  notify = function(){
13307    process.nextTick(flush);
13308  };
13309// browsers with MutationObserver
13310} else if(Observer){
13311  var toggle = 1
13312    , node   = document.createTextNode('');
13313  new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new
13314  notify = function(){
13315    node.data = toggle = -toggle;
13316  };
13317// environments with maybe non-completely correct, but existent Promise
13318} else if(Promise && Promise.resolve){
13319  notify = function(){
13320    Promise.resolve().then(flush);
13321  };
13322// for other environments - macrotask based on:
13323// - setImmediate
13324// - MessageChannel
13325// - window.postMessag
13326// - onreadystatechange
13327// - setTimeout
13328} else {
13329  notify = function(){
13330    // strange IE + webpack dev server bug - use .call(global)
13331    macrotask.call(global, flush);
13332  };
13333}
13334
13335module.exports = function asap(fn){
13336  var task = {fn: fn, next: undefined, domain: isNode && process.domain};
13337  if(last)last.next = task;
13338  if(!head){
13339    head = task;
13340    notify();
13341  } last = task;
13342};
13343},{"./$.cof":45,"./$.global":57,"./$.task":87}],74:[function(_dereq_,module,exports){
13344// 19.1.2.1 Object.assign(target, source, ...)
13345var $        = _dereq_('./$')
13346  , toObject = _dereq_('./$.to-object')
13347  , IObject  = _dereq_('./$.iobject');
13348
13349// should work with symbols and should have deterministic property order (V8 bug)
13350module.exports = _dereq_('./$.fails')(function(){
13351  var a = Object.assign
13352    , A = {}
13353    , B = {}
13354    , S = Symbol()
13355    , K = 'abcdefghijklmnopqrst';
13356  A[S] = 7;
13357  K.split('').forEach(function(k){ B[k] = k; });
13358  return a({}, A)[S] != 7 || Object.keys(a({}, B)).join('') != K;
13359}) ? function assign(target, source){ // eslint-disable-line no-unused-vars
13360  var T     = toObject(target)
13361    , $$    = arguments
13362    , $$len = $$.length
13363    , index = 1
13364    , getKeys    = $.getKeys
13365    , getSymbols = $.getSymbols
13366    , isEnum     = $.isEnum;
13367  while($$len > index){
13368    var S      = IObject($$[index++])
13369      , keys   = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S)
13370      , length = keys.length
13371      , j      = 0
13372      , key;
13373    while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key];
13374  }
13375  return T;
13376} : Object.assign;
13377},{"./$":71,"./$.fails":55,"./$.iobject":62,"./$.to-object":91}],75:[function(_dereq_,module,exports){
13378// most Object methods by ES6 should accept primitives
13379var $export = _dereq_('./$.export')
13380  , core    = _dereq_('./$.core')
13381  , fails   = _dereq_('./$.fails');
13382module.exports = function(KEY, exec){
13383  var fn  = (core.Object || {})[KEY] || Object[KEY]
13384    , exp = {};
13385  exp[KEY] = exec(fn);
13386  $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
13387};
13388},{"./$.core":49,"./$.export":54,"./$.fails":55}],76:[function(_dereq_,module,exports){
13389module.exports = function(bitmap, value){
13390  return {
13391    enumerable  : !(bitmap & 1),
13392    configurable: !(bitmap & 2),
13393    writable    : !(bitmap & 4),
13394    value       : value
13395  };
13396};
13397},{}],77:[function(_dereq_,module,exports){
13398var redefine = _dereq_('./$.redefine');
13399module.exports = function(target, src){
13400  for(var key in src)redefine(target, key, src[key]);
13401  return target;
13402};
13403},{"./$.redefine":78}],78:[function(_dereq_,module,exports){
13404module.exports = _dereq_('./$.hide');
13405},{"./$.hide":59}],79:[function(_dereq_,module,exports){
13406// 7.2.9 SameValue(x, y)
13407module.exports = Object.is || function is(x, y){
13408  return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
13409};
13410},{}],80:[function(_dereq_,module,exports){
13411// Works with __proto__ only. Old v8 can't work with null proto objects.
13412/* eslint-disable no-proto */
13413var getDesc  = _dereq_('./$').getDesc
13414  , isObject = _dereq_('./$.is-object')
13415  , anObject = _dereq_('./$.an-object');
13416var check = function(O, proto){
13417  anObject(O);
13418  if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!");
13419};
13420module.exports = {
13421  set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
13422    function(test, buggy, set){
13423      try {
13424        set = _dereq_('./$.ctx')(Function.call, getDesc(Object.prototype, '__proto__').set, 2);
13425        set(test, []);
13426        buggy = !(test instanceof Array);
13427      } catch(e){ buggy = true; }
13428      return function setPrototypeOf(O, proto){
13429        check(O, proto);
13430        if(buggy)O.__proto__ = proto;
13431        else set(O, proto);
13432        return O;
13433      };
13434    }({}, false) : undefined),
13435  check: check
13436};
13437},{"./$":71,"./$.an-object":43,"./$.ctx":50,"./$.is-object":64}],81:[function(_dereq_,module,exports){
13438'use strict';
13439var core        = _dereq_('./$.core')
13440  , $           = _dereq_('./$')
13441  , DESCRIPTORS = _dereq_('./$.descriptors')
13442  , SPECIES     = _dereq_('./$.wks')('species');
13443
13444module.exports = function(KEY){
13445  var C = core[KEY];
13446  if(DESCRIPTORS && C && !C[SPECIES])$.setDesc(C, SPECIES, {
13447    configurable: true,
13448    get: function(){ return this; }
13449  });
13450};
13451},{"./$":71,"./$.core":49,"./$.descriptors":52,"./$.wks":93}],82:[function(_dereq_,module,exports){
13452var def = _dereq_('./$').setDesc
13453  , has = _dereq_('./$.has')
13454  , TAG = _dereq_('./$.wks')('toStringTag');
13455
13456module.exports = function(it, tag, stat){
13457  if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag});
13458};
13459},{"./$":71,"./$.has":58,"./$.wks":93}],83:[function(_dereq_,module,exports){
13460var global = _dereq_('./$.global')
13461  , SHARED = '__core-js_shared__'
13462  , store  = global[SHARED] || (global[SHARED] = {});
13463module.exports = function(key){
13464  return store[key] || (store[key] = {});
13465};
13466},{"./$.global":57}],84:[function(_dereq_,module,exports){
13467// 7.3.20 SpeciesConstructor(O, defaultConstructor)
13468var anObject  = _dereq_('./$.an-object')
13469  , aFunction = _dereq_('./$.a-function')
13470  , SPECIES   = _dereq_('./$.wks')('species');
13471module.exports = function(O, D){
13472  var C = anObject(O).constructor, S;
13473  return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
13474};
13475},{"./$.a-function":41,"./$.an-object":43,"./$.wks":93}],85:[function(_dereq_,module,exports){
13476module.exports = function(it, Constructor, name){
13477  if(!(it instanceof Constructor))throw TypeError(name + ": use the 'new' operator!");
13478  return it;
13479};
13480},{}],86:[function(_dereq_,module,exports){
13481var toInteger = _dereq_('./$.to-integer')
13482  , defined   = _dereq_('./$.defined');
13483// true  -> String#at
13484// false -> String#codePointAt
13485module.exports = function(TO_STRING){
13486  return function(that, pos){
13487    var s = String(defined(that))
13488      , i = toInteger(pos)
13489      , l = s.length
13490      , a, b;
13491    if(i < 0 || i >= l)return TO_STRING ? '' : undefined;
vendor: 6,411 bytes, lines 13492-13668
13492    a = s.charCodeAt(i);
13493    return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
13494      ? TO_STRING ? s.charAt(i) : a
13495      : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
13496  };
13497};
13498},{"./$.defined":51,"./$.to-integer":88}],87:[function(_dereq_,module,exports){
13499var ctx                = _dereq_('./$.ctx')
13500  , invoke             = _dereq_('./$.invoke')
13501  , html               = _dereq_('./$.html')
13502  , cel                = _dereq_('./$.dom-create')
13503  , global             = _dereq_('./$.global')
13504  , process            = global.process
13505  , setTask            = global.setImmediate
13506  , clearTask          = global.clearImmediate
13507  , MessageChannel     = global.MessageChannel
13508  , counter            = 0
13509  , queue              = {}
13510  , ONREADYSTATECHANGE = 'onreadystatechange'
13511  , defer, channel, port;
13512var run = function(){
13513  var id = +this;
13514  if(queue.hasOwnProperty(id)){
13515    var fn = queue[id];
13516    delete queue[id];
13517    fn();
13518  }
13519};
13520var listner = function(event){
13521  run.call(event.data);
13522};
13523// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
13524if(!setTask || !clearTask){
13525  setTask = function setImmediate(fn){
13526    var args = [], i = 1;
13527    while(arguments.length > i)args.push(arguments[i++]);
13528    queue[++counter] = function(){
13529      invoke(typeof fn == 'function' ? fn : Function(fn), args);
13530    };
13531    defer(counter);
13532    return counter;
13533  };
13534  clearTask = function clearImmediate(id){
13535    delete queue[id];
13536  };
13537  // Node.js 0.8-
13538  if(_dereq_('./$.cof')(process) == 'process'){
13539    defer = function(id){
13540      process.nextTick(ctx(run, id, 1));
13541    };
13542  // Browsers with MessageChannel, includes WebWorkers
13543  } else if(MessageChannel){
13544    channel = new MessageChannel;
13545    port    = channel.port2;
13546    channel.port1.onmessage = listner;
13547    defer = ctx(port.postMessage, port, 1);
13548  // Browsers with postMessage, skip WebWorkers
13549  // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
13550  } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){
13551    defer = function(id){
13552      global.postMessage(id + '', '*');
13553    };
13554    global.addEventListener('message', listner, false);
13555  // IE8-
13556  } else if(ONREADYSTATECHANGE in cel('script')){
13557    defer = function(id){
13558      html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){
13559        html.removeChild(this);
13560        run.call(id);
13561      };
13562    };
13563  // Rest old browsers
13564  } else {
13565    defer = function(id){
13566      setTimeout(ctx(run, id, 1), 0);
13567    };
13568  }
13569}
13570module.exports = {
13571  set:   setTask,
13572  clear: clearTask
13573};
13574},{"./$.cof":45,"./$.ctx":50,"./$.dom-create":53,"./$.global":57,"./$.html":60,"./$.invoke":61}],88:[function(_dereq_,module,exports){
13575// 7.1.4 ToInteger
13576var ceil  = Math.ceil
13577  , floor = Math.floor;
13578module.exports = function(it){
13579  return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
13580};
13581},{}],89:[function(_dereq_,module,exports){
13582// to indexed object, toObject with fallback for non-array-like ES3 strings
13583var IObject = _dereq_('./$.iobject')
13584  , defined = _dereq_('./$.defined');
13585module.exports = function(it){
13586  return IObject(defined(it));
13587};
13588},{"./$.defined":51,"./$.iobject":62}],90:[function(_dereq_,module,exports){
13589// 7.1.15 ToLength
13590var toInteger = _dereq_('./$.to-integer')
13591  , min       = Math.min;
13592module.exports = function(it){
13593  return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
13594};
13595},{"./$.to-integer":88}],91:[function(_dereq_,module,exports){
13596// 7.1.13 ToObject(argument)
13597var defined = _dereq_('./$.defined');
13598module.exports = function(it){
13599  return Object(defined(it));
13600};
13601},{"./$.defined":51}],92:[function(_dereq_,module,exports){
13602var id = 0
13603  , px = Math.random();
13604module.exports = function(key){
13605  return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
13606};
13607},{}],93:[function(_dereq_,module,exports){
13608var store  = _dereq_('./$.shared')('wks')
13609  , uid    = _dereq_('./$.uid')
13610  , Symbol = _dereq_('./$.global').Symbol;
13611module.exports = function(name){
13612  return store[name] || (store[name] =
13613    Symbol && Symbol[name] || (Symbol || uid)('Symbol.' + name));
13614};
13615},{"./$.global":57,"./$.shared":83,"./$.uid":92}],94:[function(_dereq_,module,exports){
13616var classof   = _dereq_('./$.classof')
13617  , ITERATOR  = _dereq_('./$.wks')('iterator')
13618  , Iterators = _dereq_('./$.iterators');
13619module.exports = _dereq_('./$.core').getIteratorMethod = function(it){
13620  if(it != undefined)return it[ITERATOR]
13621    || it['@@iterator']
13622    || Iterators[classof(it)];
13623};
13624},{"./$.classof":44,"./$.core":49,"./$.iterators":70,"./$.wks":93}],95:[function(_dereq_,module,exports){
13625var anObject = _dereq_('./$.an-object')
13626  , get      = _dereq_('./core.get-iterator-method');
13627module.exports = _dereq_('./$.core').getIterator = function(it){
13628  var iterFn = get(it);
13629  if(typeof iterFn != 'function')throw TypeError(it + ' is not iterable!');
13630  return anObject(iterFn.call(it));
13631};
13632},{"./$.an-object":43,"./$.core":49,"./core.get-iterator-method":94}],96:[function(_dereq_,module,exports){
13633'use strict';
13634var addToUnscopables = _dereq_('./$.add-to-unscopables')
13635  , step             = _dereq_('./$.iter-step')
13636  , Iterators        = _dereq_('./$.iterators')
13637  , toIObject        = _dereq_('./$.to-iobject');
13638
13639// 22.1.3.4 Array.prototype.entries()
13640// 22.1.3.13 Array.prototype.keys()
13641// 22.1.3.29 Array.prototype.values()
13642// 22.1.3.30 Array.prototype[@@iterator]()
13643module.exports = _dereq_('./$.iter-define')(Array, 'Array', function(iterated, kind){
13644  this._t = toIObject(iterated); // target
13645  this._i = 0;                   // next index
13646  this._k = kind;                // kind
13647// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
13648}, function(){
13649  var O     = this._t
13650    , kind  = this._k
13651    , index = this._i++;
13652  if(!O || index >= O.length){
13653    this._t = undefined;
13654    return step(1);
13655  }
13656  if(kind == 'keys'  )return step(0, index);
13657  if(kind == 'values')return step(0, O[index]);
13658  return step(0, [index, O[index]]);
13659}, 'values');
13660
13661// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
13662Iterators.Arguments = Iterators.Array;
13663
13664addToUnscopables('keys');
13665addToUnscopables('values');
13666addToUnscopables('entries');
13667},{"./$.add-to-unscopables":42,"./$.iter-define":67,"./$.iter-step":69,"./$.iterators":70,"./$.to-iobject":89}],97:[function(_dereq_,module,exports){
13668// 19.1.3.1 Object.assign(target, source)
13669var $export = _dereq_('./$.export');
13670
13671$export($export.S + $export.F, 'Object', {assign: _dereq_('./$.object-assign')});
13672},{"./$.export":54,"./$.object-assign":74}],98:[function(_dereq_,module,exports){
13673// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
13674var toIObject = _dereq_('./$.to-iobject');
13675
13676_dereq_('./$.object-sap')('getOwnPropertyDescriptor', function($getOwnPropertyDescriptor){
13677  return function getOwnPropertyDescriptor(it, key){
13678    return $getOwnPropertyDescriptor(toIObject(it), key);
13679  };
13680});
13681},{"./$.object-sap":75,"./$.to-iobject":89}],99:[function(_dereq_,module,exports){
13682// 19.1.2.14 Object.keys(O)
13683var toObject = _dereq_('./$.to-object');
13684
13685_dereq_('./$.object-sap')('keys', function($keys){
13686  return function keys(it){
13687    return $keys(toObject(it));
13688  };
13689});
13690},{"./$.object-sap":75,"./$.to-object":91}],100:[function(_dereq_,module,exports){
13691// 19.1.3.19 Object.setPrototypeOf(O, proto)
13692var $export = _dereq_('./$.export');
13693$export($export.S, 'Object', {setPrototypeOf: _dereq_('./$.set-proto').set});
13694},{"./$.export":54,"./$.set-proto":80}],101:[function(_dereq_,module,exports){
13695
13696},{}],102:[function(_dereq_,module,exports){
13697'use strict';
13698var $          = _dereq_('./$')
13699  , LIBRARY    = _dereq_('./$.library')
13700  , global     = _dereq_('./$.global')
13701  , ctx        = _dereq_('./$.ctx')
13702  , classof    = _dereq_('./$.classof')
13703  , $export    = _dereq_('./$.export')
13704  , isObject   = _dereq_('./$.is-object')
13705  , anObject   = _dereq_('./$.an-object')
13706  , aFunction  = _dereq_('./$.a-function')
13707  , strictNew  = _dereq_('./$.strict-new')
13708  , forOf      = _dereq_('./$.for-of')
13709  , setProto   = _dereq_('./$.set-proto').set
13710  , same       = _dereq_('./$.same-value')
13711  , SPECIES    = _dereq_('./$.wks')('species')
13712  , speciesConstructor = _dereq_('./$.species-constructor')
13713  , asap       = _dereq_('./$.microtask')
13714  , PROMISE    = 'Promise'
13715  , process    = global.process
13716  , isNode     = classof(process) == 'process'
13717  , P          = global[PROMISE]
13718  , empty      = function(){ /* empty */ }
13719  , Wrapper;
13720
13721var testResolve = function(sub){
13722  var test = new P(empty), promise;
13723  if(sub)test.constructor = function(exec){
13724    exec(empty, empty);
13725  };
13726  (promise = P.resolve(test))['catch'](empty);
13727  return promise === test;
13728};
13729
13730var USE_NATIVE = function(){
13731  var works = false;
13732  function P2(x){
13733    var self = new P(x);
13734    setProto(self, P2.prototype);
13735    return self;
13736  }
13737  try {
13738    works = P && P.resolve && testResolve();
13739    setProto(P2, P);
13740    P2.prototype = $.create(P.prototype, {constructor: {value: P2}});
13741    // actual Firefox has broken subclass support, test that
13742    if(!(P2.resolve(5).then(function(){}) instanceof P2)){
13743      works = false;
13744    }
13745    // actual V8 bug, https://code.google.com/p/v8/issues/detail?id=4162
13746    if(works && _dereq_('./$.descriptors')){
13747      var thenableThenGotten = false;
13748      P.resolve($.setDesc({}, 'then', {
13749        get: function(){ thenableThenGotten = true; }
13750      }));
13751      works = thenableThenGotten;
13752    }
13753  } catch(e){ works = false; }
13754  return works;
13755}();
13756
13757// helpers
13758var sameConstructor = function(a, b){
13759  // library wrapper special case
13760  if(LIBRARY && a === P && b === Wrapper)return true;
13761  return same(a, b);
13762};
13763var getConstructor = function(C){
13764  var S = anObject(C)[SPECIES];
13765  return S != undefined ? S : C;
13766};
13767var isThenable = function(it){
13768  var then;
13769  return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
13770};
13771var PromiseCapability = function(C){
13772  var resolve, reject;
13773  this.promise = new C(function($$resolve, $$reject){
13774    if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor');
13775    resolve = $$resolve;
13776    reject  = $$reject;
13777  });
13778  this.resolve = aFunction(resolve),
13779  this.reject  = aFunction(reject)
13780};
13781var perform = function(exec){
13782  try {
13783    exec();
13784  } catch(e){
13785    return {error: e};
13786  }
13787};
13788var notify = function(record, isReject){
13789  if(record.n)return;
13790  record.n = true;
13791  var chain = record.c;
13792  asap(function(){
13793    var value = record.v
13794      , ok    = record.s == 1
13795      , i     = 0;
13796    var run = function(reaction){
13797      var handler = ok ? reaction.ok : reaction.fail
13798        , resolve = reaction.resolve
13799        , reject  = reaction.reject
13800        , result, then;
13801      try {
13802        if(handler){
13803          if(!ok)record.h = true;
13804          result = handler === true ? value : handler(value);
13805          if(result === reaction.promise){
13806            reject(TypeError('Promise-chain cycle'));
13807          } else if(then = isThenable(result)){
13808            then.call(result, resolve, reject);
13809          } else resolve(result);
13810        } else reject(value);
13811      } catch(e){
13812        reject(e);
13813      }
13814    };
13815    while(chain.length > i)run(chain[i++]); // variable length - can't use forEach
13816    chain.length = 0;
13817    record.n = false;
13818    if(isReject)setTimeout(function(){
13819      var promise = record.p
13820        , handler, console;
13821      if(isUnhandled(promise)){
13822        if(isNode){
13823          process.emit('unhandledRejection', value, promise);
13824        } else if(handler = global.onunhandledrejection){
13825          handler({promise: promise, reason: value});
13826        } else if((console = global.console) && console.error){
13827          console.error('Unhandled promise rejection', value);
13828        }
13829      } record.a = undefined;
13830    }, 1);
13831  });
13832};
13833var isUnhandled = function(promise){
13834  var record = promise._d
13835    , chain  = record.a || record.c
13836    , i      = 0
13837    , reaction;
13838  if(record.h)return false;
13839  while(chain.length > i){
13840    reaction = chain[i++];
13841    if(reaction.fail || !isUnhandled(reaction.promise))return false;
13842  } return true;
13843};
13844var $reject = function(value){
13845  var record = this;
13846  if(record.d)return;
13847  record.d = true;
13848  record = record.r || record; // unwrap
13849  record.v = value;
13850  record.s = 2;
13851  record.a = record.c.slice();
13852  notify(record, true);
13853};
13854var $resolve = function(value){
13855  var record = this
13856    , then;
13857  if(record.d)return;
13858  record.d = true;
13859  record = record.r || record; // unwrap
13860  try {
13861    if(record.p === value)throw TypeError("Promise can't be resolved itself");
13862    if(then = isThenable(value)){
13863      asap(function(){
13864        var wrapper = {r: record, d: false}; // wrap
13865        try {
13866          then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
13867        } catch(e){
13868          $reject.call(wrapper, e);
13869        }
13870      });
13871    } else {
13872      record.v = value;
13873      record.s = 1;
13874      notify(record, false);
13875    }
13876  } catch(e){
13877    $reject.call({r: record, d: false}, e); // wrap
13878  }
13879};
13880
13881// constructor polyfill
13882if(!USE_NATIVE){
13883  // 25.4.3.1 Promise(executor)
13884  P = function Promise(executor){
13885    aFunction(executor);
13886    var record = this._d = {
13887      p: strictNew(this, P, PROMISE),         // <- promise
13888      c: [],                                  // <- awaiting reactions
13889      a: undefined,                           // <- checked in isUnhandled reactions
13890      s: 0,                                   // <- state
13891      d: false,                               // <- done
13892      v: undefined,                           // <- value
13893      h: false,                               // <- handled rejection
13894      n: false                                // <- notify
13895    };
13896    try {
13897      executor(ctx($resolve, record, 1), ctx($reject, record, 1));
13898    } catch(err){
13899      $reject.call(record, err);
13900    }
13901  };
13902  _dereq_('./$.redefine-all')(P.prototype, {
13903    // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
13904    then: function then(onFulfilled, onRejected){
13905      var reaction = new PromiseCapability(speciesConstructor(this, P))
13906        , promise  = reaction.promise
13907        , record   = this._d;
13908      reaction.ok   = typeof onFulfilled == 'function' ? onFulfilled : true;
13909      reaction.fail = typeof onRejected == 'function' && onRejected;
13910      record.c.push(reaction);
13911      if(record.a)record.a.push(reaction);
13912      if(record.s)notify(record, false);
13913      return promise;
13914    },
13915    // 25.4.5.1 Promise.prototype.catch(onRejected)
13916    'catch': function(onRejected){
13917      return this.then(undefined, onRejected);
13918    }
13919  });
13920}
13921
13922$export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: P});
13923_dereq_('./$.set-to-string-tag')(P, PROMISE);
13924_dereq_('./$.set-species')(PROMISE);
13925Wrapper = _dereq_('./$.core')[PROMISE];
13926
13927// statics
13928$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
13929  // 25.4.4.5 Promise.reject(r)
13930  reject: function reject(r){
13931    var capability = new PromiseCapability(this)
13932      , $$reject   = capability.reject;
13933    $$reject(r);
13934    return capability.promise;
13935  }
13936});
13937$export($export.S + $export.F * (!USE_NATIVE || testResolve(true)), PROMISE, {
13938  // 25.4.4.6 Promise.resolve(x)
13939  resolve: function resolve(x){
13940    // instanceof instead of internal slot check because we should fix it without replacement native Promise core
13941    if(x instanceof P && sameConstructor(x.constructor, this))return x;
13942    var capability = new PromiseCapability(this)
13943      , $$resolve  = capability.resolve;
13944    $$resolve(x);
13945    return capability.promise;
13946  }
13947});
13948$export($export.S + $export.F * !(USE_NATIVE && _dereq_('./$.iter-detect')(function(iter){
13949  P.all(iter)['catch'](function(){});
13950})), PROMISE, {
13951  // 25.4.4.1 Promise.all(iterable)
13952  all: function all(iterable){
13953    var C          = getConstructor(this)
13954      , capability = new PromiseCapability(C)
13955      , resolve    = capability.resolve
13956      , reject     = capability.reject
13957      , values     = [];
13958    var abrupt = perform(function(){
13959      forOf(iterable, false, values.push, values);
13960      var remaining = values.length
13961        , results   = Array(remaining);
13962      if(remaining)$.each.call(values, function(promise, index){
13963        var alreadyCalled = false;
13964        C.resolve(promise).then(function(value){
13965          if(alreadyCalled)return;
13966          alreadyCalled = true;
13967          results[index] = value;
13968          --remaining || resolve(results);
13969        }, reject);
13970      });
13971      else resolve(results);
13972    });
13973    if(abrupt)reject(abrupt.error);
13974    return capability.promise;
13975  },
13976  // 25.4.4.4 Promise.race(iterable)
13977  race: function race(iterable){
13978    var C          = getConstructor(this)
13979      , capability = new PromiseCapability(C)
13980      , reject     = capability.reject;
13981    var abrupt = perform(function(){
13982      forOf(iterable, false, function(promise){
13983        C.resolve(promise).then(capability.resolve, reject);
13984      });
13985    });
13986    if(abrupt)reject(abrupt.error);
13987    return capability.promise;
13988  }
13989});
13990},{"./$":71,"./$.a-function":41,"./$.an-object":43,"./$.classof":44,"./$.core":49,"./$.ctx":50,"./$.descriptors":52,"./$.export":54,"./$.for-of":56,"./$.global":57,"./$.is-object":64,"./$.iter-detect":68,"./$.library":72,"./$.microtask":73,"./$.redefine-all":77,"./$.same-value":79,"./$.set-proto":80,"./$.set-species":81,"./$.set-to-string-tag":82,"./$.species-constructor":84,"./$.strict-new":85,"./$.wks":93}],103:[function(_dereq_,module,exports){
13991'use strict';
13992var strong = _dereq_('./$.collection-strong');
13993
13994// 23.2 Set Objects
13995_dereq_('./$.collection')('Set', function(get){
13996  return function Set(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); };
13997}, {
13998  // 23.2.3.1 Set.prototype.add(value)
13999  add: function add(value){
14000    return strong.def(this, value = value === 0 ? 0 : value, value);
14001  }
14002}, strong);
14003},{"./$.collection":48,"./$.collection-strong":46}],104:[function(_dereq_,module,exports){
14004'use strict';
14005var $at  = _dereq_('./$.string-at')(true);
14006
14007// 21.1.3.27 String.prototype[@@iterator]()
14008_dereq_('./$.iter-define')(String, 'String', function(iterated){
14009  this._t = String(iterated); // target
14010  this._i = 0;                // next index
14011// 21.1.5.2.1 %StringIteratorPrototype%.next()
14012}, function(){
14013  var O     = this._t
14014    , index = this._i
14015    , point;
14016  if(index >= O.length)return {value: undefined, done: true};
14017  point = $at(O, index);
14018  this._i += point.length;
14019  return {value: point, done: false};
14020});
14021},{"./$.iter-define":67,"./$.string-at":86}],105:[function(_dereq_,module,exports){
14022// https://github.com/DavidBruant/Map-Set.prototype.toJSON
14023var $export  = _dereq_('./$.export');
14024
14025$export($export.P, 'Set', {toJSON: _dereq_('./$.collection-to-json')('Set')});
14026},{"./$.collection-to-json":47,"./$.export":54}],106:[function(_dereq_,module,exports){
14027_dereq_('./es6.array.iterator');
14028var Iterators = _dereq_('./$.iterators');
14029Iterators.NodeList = Iterators.HTMLCollection = Iterators.Array;
14030},{"./$.iterators":70,"./es6.array.iterator":96}],107:[function(_dereq_,module,exports){
14031(function (global){
14032/*!
14033ISC License
14034
14035Copyright (c) 2014-2018, Andrea Giammarchi, @WebReflection
14036
14037Permission to use, copy, modify, and/or distribute this software for any
14038purpose with or without fee is hereby granted, provided that the above
14039copyright notice and this permission notice appear in all copies.
14040
14041THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14042REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14043AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14044INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14045LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14046OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14047PERFORMANCE OF THIS SOFTWARE.
14048
14049*/
14050// global window Object
14051// optional polyfill info
14052//    'auto' used by default, everything is feature detected
14053//    'force' use the polyfill even if not fully needed
14054function installCustomElements(window, polyfill) {'use strict';
14055
14056  // DO NOT USE THIS FILE DIRECTLY, IT WON'T WORK
14057  // THIS IS A PROJECT BASED ON A BUILD SYSTEM
14058  // THIS FILE IS JUST WRAPPED UP RESULTING IN
14059  // build/document-register-element.node.js
vendor: 39,871 bytes, lines 14059-15557
14059
14060
14061  var
14062    document = window.document,
14063    Object = window.Object
14064  ;
14065
14066  var htmlClass = (function (info) {
14067    // (C) Andrea Giammarchi - @WebReflection - MIT Style
14068    var
14069      catchClass = /^[A-Z]+[a-z]/,
14070      filterBy = function (re) {
14071        var arr = [], tag;
14072        for (tag in register) {
14073          if (re.test(tag)) arr.push(tag);
14074        }
14075        return arr;
14076      },
14077      add = function (Class, tag) {
14078        tag = tag.toLowerCase();
14079        if (!(tag in register)) {
14080          register[Class] = (register[Class] || []).concat(tag);
14081          register[tag] = (register[tag.toUpperCase()] = Class);
14082        }
14083      },
14084      register = (Object.create || Object)(null),
14085      htmlClass = {},
14086      i, section, tags, Class
14087    ;
14088    for (section in info) {
14089      for (Class in info[section]) {
14090        tags = info[section][Class];
14091        register[Class] = tags;
14092        for (i = 0; i < tags.length; i++) {
14093          register[tags[i].toLowerCase()] =
14094          register[tags[i].toUpperCase()] = Class;
14095        }
14096      }
14097    }
14098    htmlClass.get = function get(tagOrClass) {
14099      return typeof tagOrClass === 'string' ?
14100        (register[tagOrClass] || (catchClass.test(tagOrClass) ? [] : '')) :
14101        filterBy(tagOrClass);
14102    };
14103    htmlClass.set = function set(tag, Class) {
14104      return (catchClass.test(tag) ?
14105        add(tag, Class) :
14106        add(Class, tag)
14107      ), htmlClass;
14108    };
14109    return htmlClass;
14110  }({
14111    "collections": {
14112      "HTMLAllCollection": [
14113        "all"
14114      ],
14115      "HTMLCollection": [
14116        "forms"
14117      ],
14118      "HTMLFormControlsCollection": [
14119        "elements"
14120      ],
14121      "HTMLOptionsCollection": [
14122        "options"
14123      ]
14124    },
14125    "elements": {
14126      "Element": [
14127        "element"
14128      ],
14129      "HTMLAnchorElement": [
14130        "a"
14131      ],
14132      "HTMLAppletElement": [
14133        "applet"
14134      ],
14135      "HTMLAreaElement": [
14136        "area"
14137      ],
14138      "HTMLAttachmentElement": [
14139        "attachment"
14140      ],
14141      "HTMLAudioElement": [
14142        "audio"
14143      ],
14144      "HTMLBRElement": [
14145        "br"
14146      ],
14147      "HTMLBaseElement": [
14148        "base"
14149      ],
14150      "HTMLBodyElement": [
14151        "body"
14152      ],
14153      "HTMLButtonElement": [
14154        "button"
14155      ],
14156      "HTMLCanvasElement": [
14157        "canvas"
14158      ],
14159      "HTMLContentElement": [
14160        "content"
14161      ],
14162      "HTMLDListElement": [
14163        "dl"
14164      ],
14165      "HTMLDataElement": [
14166        "data"
14167      ],
14168      "HTMLDataListElement": [
14169        "datalist"
14170      ],
14171      "HTMLDetailsElement": [
14172        "details"
14173      ],
14174      "HTMLDialogElement": [
14175        "dialog"
14176      ],
14177      "HTMLDirectoryElement": [
14178        "dir"
14179      ],
14180      "HTMLDivElement": [
14181        "div"
14182      ],
14183      "HTMLDocument": [
14184        "document"
14185      ],
14186      "HTMLElement": [
14187        "element",
14188        "abbr",
14189        "address",
14190        "article",
14191        "aside",
14192        "b",
14193        "bdi",
14194        "bdo",
14195        "cite",
14196        "code",
14197        "command",
14198        "dd",
14199        "dfn",
14200        "dt",
14201        "em",
14202        "figcaption",
14203        "figure",
14204        "footer",
14205        "header",
14206        "i",
14207        "kbd",
14208        "mark",
14209        "nav",
14210        "noscript",
14211        "rp",
14212        "rt",
14213        "ruby",
14214        "s",
14215        "samp",
14216        "section",
14217        "small",
14218        "strong",
14219        "sub",
14220        "summary",
14221        "sup",
14222        "u",
14223        "var",
14224        "wbr"
14225      ],
14226      "HTMLEmbedElement": [
14227        "embed"
14228      ],
14229      "HTMLFieldSetElement": [
14230        "fieldset"
14231      ],
14232      "HTMLFontElement": [
14233        "font"
14234      ],
14235      "HTMLFormElement": [
14236        "form"
14237      ],
14238      "HTMLFrameElement": [
14239        "frame"
14240      ],
14241      "HTMLFrameSetElement": [
14242        "frameset"
14243      ],
14244      "HTMLHRElement": [
14245        "hr"
14246      ],
14247      "HTMLHeadElement": [
14248        "head"
14249      ],
14250      "HTMLHeadingElement": [
14251        "h1",
14252        "h2",
14253        "h3",
14254        "h4",
14255        "h5",
14256        "h6"
14257      ],
14258      "HTMLHtmlElement": [
14259        "html"
14260      ],
14261      "HTMLIFrameElement": [
14262        "iframe"
14263      ],
14264      "HTMLImageElement": [
14265        "img"
14266      ],
14267      "HTMLInputElement": [
14268        "input"
14269      ],
14270      "HTMLKeygenElement": [
14271        "keygen"
14272      ],
14273      "HTMLLIElement": [
14274        "li"
14275      ],
14276      "HTMLLabelElement": [
14277        "label"
14278      ],
14279      "HTMLLegendElement": [
14280        "legend"
14281      ],
14282      "HTMLLinkElement": [
14283        "link"
14284      ],
14285      "HTMLMapElement": [
14286        "map"
14287      ],
14288      "HTMLMarqueeElement": [
14289        "marquee"
14290      ],
14291      "HTMLMediaElement": [
14292        "media"
14293      ],
14294      "HTMLMenuElement": [
14295        "menu"
14296      ],
14297      "HTMLMenuItemElement": [
14298        "menuitem"
14299      ],
14300      "HTMLMetaElement": [
14301        "meta"
14302      ],
14303      "HTMLMeterElement": [
14304        "meter"
14305      ],
14306      "HTMLModElement": [
14307        "del",
14308        "ins"
14309      ],
14310      "HTMLOListElement": [
14311        "ol"
14312      ],
14313      "HTMLObjectElement": [
14314        "object"
14315      ],
14316      "HTMLOptGroupElement": [
14317        "optgroup"
14318      ],
14319      "HTMLOptionElement": [
14320        "option"
14321      ],
14322      "HTMLOutputElement": [
14323        "output"
14324      ],
14325      "HTMLParagraphElement": [
14326        "p"
14327      ],
14328      "HTMLParamElement": [
14329        "param"
14330      ],
14331      "HTMLPictureElement": [
14332        "picture"
14333      ],
14334      "HTMLPreElement": [
14335        "pre"
14336      ],
14337      "HTMLProgressElement": [
14338        "progress"
14339      ],
14340      "HTMLQuoteElement": [
14341        "blockquote",
14342        "q",
14343        "quote"
14344      ],
14345      "HTMLScriptElement": [
14346        "script"
14347      ],
14348      "HTMLSelectElement": [
14349        "select"
14350      ],
14351      "HTMLShadowElement": [
14352        "shadow"
14353      ],
14354      "HTMLSlotElement": [
14355        "slot"
14356      ],
14357      "HTMLSourceElement": [
14358        "source"
14359      ],
14360      "HTMLSpanElement": [
14361        "span"
14362      ],
14363      "HTMLStyleElement": [
14364        "style"
14365      ],
14366      "HTMLTableCaptionElement": [
14367        "caption"
14368      ],
14369      "HTMLTableCellElement": [
14370        "td",
14371        "th"
14372      ],
14373      "HTMLTableColElement": [
14374        "col",
14375        "colgroup"
14376      ],
14377      "HTMLTableElement": [
14378        "table"
14379      ],
14380      "HTMLTableRowElement": [
14381        "tr"
14382      ],
14383      "HTMLTableSectionElement": [
14384        "thead",
14385        "tbody",
14386        "tfoot"
14387      ],
14388      "HTMLTemplateElement": [
14389        "template"
14390      ],
14391      "HTMLTextAreaElement": [
14392        "textarea"
14393      ],
14394      "HTMLTimeElement": [
14395        "time"
14396      ],
14397      "HTMLTitleElement": [
14398        "title"
14399      ],
14400      "HTMLTrackElement": [
14401        "track"
14402      ],
14403      "HTMLUListElement": [
14404        "ul"
14405      ],
14406      "HTMLUnknownElement": [
14407        "unknown",
14408        "vhgroupv",
14409        "vkeygen"
14410      ],
14411      "HTMLVideoElement": [
14412        "video"
14413      ]
14414    },
14415    "nodes": {
14416      "Attr": [
14417        "node"
14418      ],
14419      "Audio": [
14420        "audio"
14421      ],
14422      "CDATASection": [
14423        "node"
14424      ],
14425      "CharacterData": [
14426        "node"
14427      ],
14428      "Comment": [
14429        "#comment"
14430      ],
14431      "Document": [
14432        "#document"
14433      ],
14434      "DocumentFragment": [
14435        "#document-fragment"
14436      ],
14437      "DocumentType": [
14438        "node"
14439      ],
14440      "HTMLDocument": [
14441        "#document"
14442      ],
14443      "Image": [
14444        "img"
14445      ],
14446      "Option": [
14447        "option"
14448      ],
14449      "ProcessingInstruction": [
14450        "node"
14451      ],
14452      "ShadowRoot": [
14453        "#shadow-root"
14454      ],
14455      "Text": [
14456        "#text"
14457      ],
14458      "XMLDocument": [
14459        "xml"
14460      ]
14461    }
14462  }));
14463  
14464  
14465    
14466  // passed at runtime, configurable via nodejs module
14467  if (typeof polyfill !== 'object') polyfill = {type: polyfill || 'auto'};
14468  
14469  var
14470    // V0 polyfill entry
14471    REGISTER_ELEMENT = 'registerElement',
14472  
14473    // pseudo-random number used as expando/unique name on feature detection
14474    UID = window.Math.random() * 10e4 >> 0,
14475  
14476    // IE < 11 only + old WebKit for attributes + feature detection
14477    EXPANDO_UID = '__' + REGISTER_ELEMENT + UID,
14478  
14479    // shortcuts and costants
14480    ADD_EVENT_LISTENER = 'addEventListener',
14481    ATTACHED = 'attached',
14482    CALLBACK = 'Callback',
14483    DETACHED = 'detached',
14484    EXTENDS = 'extends',
14485  
14486    ATTRIBUTE_CHANGED_CALLBACK = 'attributeChanged' + CALLBACK,
14487    ATTACHED_CALLBACK = ATTACHED + CALLBACK,
14488    CONNECTED_CALLBACK = 'connected' + CALLBACK,
14489    DISCONNECTED_CALLBACK = 'disconnected' + CALLBACK,
14490    CREATED_CALLBACK = 'created' + CALLBACK,
14491    DETACHED_CALLBACK = DETACHED + CALLBACK,
14492  
14493    ADDITION = 'ADDITION',
14494    MODIFICATION = 'MODIFICATION',
14495    REMOVAL = 'REMOVAL',
14496  
14497    DOM_ATTR_MODIFIED = 'DOMAttrModified',
14498    DOM_CONTENT_LOADED = 'DOMContentLoaded',
14499    DOM_SUBTREE_MODIFIED = 'DOMSubtreeModified',
14500  
14501    PREFIX_TAG = '<',
14502    PREFIX_IS = '=',
14503  
14504    // valid and invalid node names
14505    validName = /^[A-Z][._A-Z0-9]*-[-._A-Z0-9]*$/,
14506    invalidNames = [
14507      'ANNOTATION-XML',
14508      'COLOR-PROFILE',
14509      'FONT-FACE',
14510      'FONT-FACE-SRC',
14511      'FONT-FACE-URI',
14512      'FONT-FACE-FORMAT',
14513      'FONT-FACE-NAME',
14514      'MISSING-GLYPH'
14515    ],
14516  
14517    // registered types and their prototypes
14518    types = [],
14519    protos = [],
14520  
14521    // to query subnodes
14522    query = '',
14523  
14524    // html shortcut used to feature detect
14525    documentElement = document.documentElement,
14526  
14527    // ES5 inline helpers || basic patches
14528    indexOf = types.indexOf || function (v) {
14529      for(var i = this.length; i-- && this[i] !== v;){}
14530      return i;
14531    },
14532  
14533    // other helpers / shortcuts
14534    OP = Object.prototype,
14535    hOP = OP.hasOwnProperty,
14536    iPO = OP.isPrototypeOf,
14537  
14538    defineProperty = Object.defineProperty,
14539    empty = [],
14540    gOPD = Object.getOwnPropertyDescriptor,
14541    gOPN = Object.getOwnPropertyNames,
14542    gPO = Object.getPrototypeOf,
14543    sPO = Object.setPrototypeOf,
14544  
14545    // jshint proto: true
14546    hasProto = !!Object.__proto__,
14547  
14548    // V1 helpers
14549    fixGetClass = false,
14550    DRECEV1 = '__dreCEv1',
14551    customElements = window.customElements,
14552    usableCustomElements = !/^force/.test(polyfill.type) && !!(
14553      customElements &&
14554      customElements.define &&
14555      customElements.get &&
14556      customElements.whenDefined
14557    ),
14558    Dict = Object.create || Object,
14559    Map = window.Map || function Map() {
14560      var K = [], V = [], i;
14561      return {
14562        get: function (k) {
14563          return V[indexOf.call(K, k)];
14564        },
14565        set: function (k, v) {
14566          i = indexOf.call(K, k);
14567          if (i < 0) V[K.push(k) - 1] = v;
14568          else V[i] = v;
14569        }
14570      };
14571    },
14572    Promise = window.Promise || function (fn) {
14573      var
14574        notify = [],
14575        done = false,
14576        p = {
14577          'catch': function () {
14578            return p;
14579          },
14580          'then': function (cb) {
14581            notify.push(cb);
14582            if (done) setTimeout(resolve, 1);
14583            return p;
14584          }
14585        }
14586      ;
14587      function resolve(value) {
14588        done = true;
14589        while (notify.length) notify.shift()(value);
14590      }
14591      fn(resolve);
14592      return p;
14593    },
14594    justCreated = false,
14595    constructors = Dict(null),
14596    waitingList = Dict(null),
14597    nodeNames = new Map(),
14598    secondArgument = function (is) {
14599      return is.toLowerCase();
14600    },
14601  
14602    // used to create unique instances
14603    create = Object.create || function Bridge(proto) {
14604      // silly broken polyfill probably ever used but short enough to work
14605      return proto ? ((Bridge.prototype = proto), new Bridge()) : this;
14606    },
14607  
14608    // will set the prototype if possible
14609    // or copy over all properties
14610    setPrototype = sPO || (
14611      hasProto ?
14612        function (o, p) {
14613          o.__proto__ = p;
14614          return o;
14615        } : (
14616      (gOPN && gOPD) ?
14617        (function(){
14618          function setProperties(o, p) {
14619            for (var
14620              key,
14621              names = gOPN(p),
14622              i = 0, length = names.length;
14623              i < length; i++
14624            ) {
14625              key = names[i];
14626              if (!hOP.call(o, key)) {
14627                defineProperty(o, key, gOPD(p, key));
14628              }
14629            }
14630          }
14631          return function (o, p) {
14632            do {
14633              setProperties(o, p);
14634            } while ((p = gPO(p)) && !iPO.call(p, o));
14635            return o;
14636          };
14637        }()) :
14638        function (o, p) {
14639          for (var key in p) {
14640            o[key] = p[key];
14641          }
14642          return o;
14643        }
14644    )),
14645  
14646    // DOM shortcuts and helpers, if any
14647  
14648    MutationObserver = window.MutationObserver ||
14649                       window.WebKitMutationObserver,
14650  
14651    HTMLAnchorElement = window.HTMLAnchorElement,
14652  
14653    HTMLElementPrototype = (
14654      window.HTMLElement ||
14655      window.Element ||
14656      window.Node
14657    ).prototype,
14658  
14659    IE8 = !iPO.call(HTMLElementPrototype, documentElement),
14660  
14661    safeProperty = IE8 ? function (o, k, d) {
14662      o[k] = d.value;
14663      return o;
14664    } : defineProperty,
14665  
14666    isValidNode = IE8 ?
14667      function (node) {
14668        return node.nodeType === 1;
14669      } :
14670      function (node) {
14671        return iPO.call(HTMLElementPrototype, node);
14672      },
14673  
14674    targets = IE8 && [],
14675  
14676    attachShadow = HTMLElementPrototype.attachShadow,
14677    cloneNode = HTMLElementPrototype.cloneNode,
14678    closest = HTMLElementPrototype.closest || function (name) {
14679      var self = this;
14680      while (self && self.nodeName !== name)
14681        self = self.parentNode;
14682      return self;
14683    },
14684    dispatchEvent = HTMLElementPrototype.dispatchEvent,
14685    getAttribute = HTMLElementPrototype.getAttribute,
14686    hasAttribute = HTMLElementPrototype.hasAttribute,
14687    removeAttribute = HTMLElementPrototype.removeAttribute,
14688    setAttribute = HTMLElementPrototype.setAttribute,
14689  
14690    // replaced later on
14691    createElement = document.createElement,
14692    importNode = document.importNode,
14693    patchedCreateElement = createElement,
14694  
14695    // shared observer for all attributes
14696    attributesObserver = MutationObserver && {
14697      attributes: true,
14698      characterData: true,
14699      attributeOldValue: true
14700    },
14701  
14702    // useful to detect only if there's no MutationObserver
14703    DOMAttrModified = MutationObserver || function(e) {
14704      doesNotSupportDOMAttrModified = false;
14705      documentElement.removeEventListener(
14706        DOM_ATTR_MODIFIED,
14707        DOMAttrModified
14708      );
14709    },
14710  
14711    // will both be used to make DOMNodeInserted asynchronous
14712    asapQueue,
14713    asapTimer = 0,
14714  
14715    // internal flags
14716    V0 = REGISTER_ELEMENT in document &&
14717         !/^force-all/.test(polyfill.type),
14718    setListener = true,
14719    justSetup = false,
14720    doesNotSupportDOMAttrModified = true,
14721    dropDomContentLoaded = true,
14722  
14723    // needed for the innerHTML helper
14724    notFromInnerHTMLHelper = true,
14725  
14726    // optionally defined later on
14727    onSubtreeModified,
14728    callDOMAttrModified,
14729    getAttributesMirror,
14730    observer,
14731    observe,
14732  
14733    // based on setting prototype capability
14734    // will check proto or the expando attribute
14735    // in order to setup the node once
14736    patchIfNotAlready,
14737    patch,
14738  
14739    // used for tests
14740    tmp
14741  ;
14742  
14743  // IE11 disconnectedCallback issue #
14744  // to be tested before any createElement patch
14745  if (MutationObserver) {
14746    // original fix:
14747    // https://github.com/javan/mutation-observer-inner-html-shim
14748    tmp = document.createElement('div');
14749    tmp.innerHTML = '<div><div></div></div>';
14750    new MutationObserver(function (mutations, observer) {
14751      if (
14752        mutations[0] &&
14753        mutations[0].type == 'childList' &&
14754        !mutations[0].removedNodes[0].childNodes.length
14755      ) {
14756        tmp = gOPD(HTMLElementPrototype, 'innerHTML');
14757        var set = tmp && tmp.set;
14758        if (set)
14759          defineProperty(HTMLElementPrototype, 'innerHTML', {
14760            set: function (value) {
14761              while (this.lastChild)
14762                this.removeChild(this.lastChild);
14763              set.call(this, value);
14764            }
14765          });
14766      }
14767      observer.disconnect();
14768      tmp = null;
14769    }).observe(tmp, {childList: true, subtree: true});
14770    tmp.innerHTML = "";
14771  }
14772  
14773  // only if needed
14774  if (!V0) {
14775  
14776    if (sPO || hasProto) {
14777        patchIfNotAlready = function (node, proto) {
14778          if (!iPO.call(proto, node)) {
14779            setupNode(node, proto);
14780          }
14781        };
14782        patch = setupNode;
14783    } else {
14784        patchIfNotAlready = function (node, proto) {
14785          if (!node[EXPANDO_UID]) {
14786            node[EXPANDO_UID] = Object(true);
14787            setupNode(node, proto);
14788          }
14789        };
14790        patch = patchIfNotAlready;
14791    }
14792  
14793    if (IE8) {
14794      doesNotSupportDOMAttrModified = false;
14795      (function (){
14796        var
14797          descriptor = gOPD(HTMLElementPrototype, ADD_EVENT_LISTENER),
14798          addEventListener = descriptor.value,
14799          patchedRemoveAttribute = function (name) {
14800            var e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true});
14801            e.attrName = name;
14802            e.prevValue = getAttribute.call(this, name);
14803            e.newValue = null;
14804            e[REMOVAL] = e.attrChange = 2;
14805            removeAttribute.call(this, name);
14806            dispatchEvent.call(this, e);
14807          },
14808          patchedSetAttribute = function (name, value) {
14809            var
14810              had = hasAttribute.call(this, name),
14811              old = had && getAttribute.call(this, name),
14812              e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true})
14813            ;
14814            setAttribute.call(this, name, value);
14815            e.attrName = name;
14816            e.prevValue = had ? old : null;
14817            e.newValue = value;
14818            if (had) {
14819              e[MODIFICATION] = e.attrChange = 1;
14820            } else {
14821              e[ADDITION] = e.attrChange = 0;
14822            }
14823            dispatchEvent.call(this, e);
14824          },
14825          onPropertyChange = function (e) {
14826            // jshint eqnull:true
14827            var
14828              node = e.currentTarget,
14829              superSecret = node[EXPANDO_UID],
14830              propertyName = e.propertyName,
14831              event
14832            ;
14833            if (superSecret.hasOwnProperty(propertyName)) {
14834              superSecret = superSecret[propertyName];
14835              event = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true});
14836              event.attrName = superSecret.name;
14837              event.prevValue = superSecret.value || null;
14838              event.newValue = (superSecret.value = node[propertyName] || null);
14839              if (event.prevValue == null) {
14840                event[ADDITION] = event.attrChange = 0;
14841              } else {
14842                event[MODIFICATION] = event.attrChange = 1;
14843              }
14844              dispatchEvent.call(node, event);
14845            }
14846          }
14847        ;
14848        descriptor.value = function (type, handler, capture) {
14849          if (
14850            type === DOM_ATTR_MODIFIED &&
14851            this[ATTRIBUTE_CHANGED_CALLBACK] &&
14852            this.setAttribute !== patchedSetAttribute
14853          ) {
14854            this[EXPANDO_UID] = {
14855              className: {
14856                name: 'class',
14857                value: this.className
14858              }
14859            };
14860            this.setAttribute = patchedSetAttribute;
14861            this.removeAttribute = patchedRemoveAttribute;
14862            addEventListener.call(this, 'propertychange', onPropertyChange);
14863          }
14864          addEventListener.call(this, type, handler, capture);
14865        };
14866        defineProperty(HTMLElementPrototype, ADD_EVENT_LISTENER, descriptor);
14867      }());
14868    } else if (!MutationObserver) {
14869      documentElement[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, DOMAttrModified);
14870      documentElement.setAttribute(EXPANDO_UID, 1);
14871      documentElement.removeAttribute(EXPANDO_UID);
14872      if (doesNotSupportDOMAttrModified) {
14873        onSubtreeModified = function (e) {
14874          var
14875            node = this,
14876            oldAttributes,
14877            newAttributes,
14878            key
14879          ;
14880          if (node === e.target) {
14881            oldAttributes = node[EXPANDO_UID];
14882            node[EXPANDO_UID] = (newAttributes = getAttributesMirror(node));
14883            for (key in newAttributes) {
14884              if (!(key in oldAttributes)) {
14885                // attribute was added
14886                return callDOMAttrModified(
14887                  0,
14888                  node,
14889                  key,
14890                  oldAttributes[key],
14891                  newAttributes[key],
14892                  ADDITION
14893                );
14894              } else if (newAttributes[key] !== oldAttributes[key]) {
14895                // attribute was changed
14896                return callDOMAttrModified(
14897                  1,
14898                  node,
14899                  key,
14900                  oldAttributes[key],
14901                  newAttributes[key],
14902                  MODIFICATION
14903                );
14904              }
14905            }
14906            // checking if it has been removed
14907            for (key in oldAttributes) {
14908              if (!(key in newAttributes)) {
14909                // attribute removed
14910                return callDOMAttrModified(
14911                  2,
14912                  node,
14913                  key,
14914                  oldAttributes[key],
14915                  newAttributes[key],
14916                  REMOVAL
14917                );
14918              }
14919            }
14920          }
14921        };
14922        callDOMAttrModified = function (
14923          attrChange,
14924          currentTarget,
14925          attrName,
14926          prevValue,
14927          newValue,
14928          action
14929        ) {
14930          var e = {
14931            attrChange: attrChange,
14932            currentTarget: currentTarget,
14933            attrName: attrName,
14934            prevValue: prevValue,
14935            newValue: newValue
14936          };
14937          e[action] = attrChange;
14938          onDOMAttrModified(e);
14939        };
14940        getAttributesMirror = function (node) {
14941          for (var
14942            attr, name,
14943            result = {},
14944            attributes = node.attributes,
14945            i = 0, length = attributes.length;
14946            i < length; i++
14947          ) {
14948            attr = attributes[i];
14949            name = attr.name;
14950            if (name !== 'setAttribute') {
14951              result[name] = attr.value;
14952            }
14953          }
14954          return result;
14955        };
14956      }
14957    }
14958  
14959    // set as enumerable, writable and configurable
14960    document[REGISTER_ELEMENT] = function registerElement(type, options) {
14961      upperType = type.toUpperCase();
14962      if (setListener) {
14963        // only first time document.registerElement is used
14964        // we need to set this listener
14965        // setting it by default might slow down for no reason
14966        setListener = false;
14967        if (MutationObserver) {
14968          observer = (function(attached, detached){
14969            function checkEmAll(list, callback) {
14970              for (var i = 0, length = list.length; i < length; callback(list[i++])){}
14971            }
14972            return new MutationObserver(function (records) {
14973              for (var
14974                current, node, newValue,
14975                i = 0, length = records.length; i < length; i++
14976              ) {
14977                current = records[i];
14978                if (current.type === 'childList') {
14979                  checkEmAll(current.addedNodes, attached);
14980                  checkEmAll(current.removedNodes, detached);
14981                } else {
14982                  node = current.target;
14983                  if (notFromInnerHTMLHelper &&
14984                      node[ATTRIBUTE_CHANGED_CALLBACK] &&
14985                      current.attributeName !== 'style') {
14986                    newValue = getAttribute.call(node, current.attributeName);
14987                    if (newValue !== current.oldValue) {
14988                      node[ATTRIBUTE_CHANGED_CALLBACK](
14989                        current.attributeName,
14990                        current.oldValue,
14991                        newValue
14992                      );
14993                    }
14994                  }
14995                }
14996              }
14997            });
14998          }(executeAction(ATTACHED), executeAction(DETACHED)));
14999          observe = function (node) {
15000            observer.observe(
15001              node,
15002              {
15003                childList: true,
15004                subtree: true
15005              }
15006            );
15007            return node;
15008          };
15009          observe(document);
15010          if (attachShadow) {
15011            HTMLElementPrototype.attachShadow = function () {
15012              return observe(attachShadow.apply(this, arguments));
15013            };
15014          }
15015        } else {
15016          asapQueue = [];
15017          document[ADD_EVENT_LISTENER]('DOMNodeInserted', onDOMNode(ATTACHED));
15018          document[ADD_EVENT_LISTENER]('DOMNodeRemoved', onDOMNode(DETACHED));
15019        }
15020  
15021        document[ADD_EVENT_LISTENER](DOM_CONTENT_LOADED, onReadyStateChange);
15022        document[ADD_EVENT_LISTENER]('readystatechange', onReadyStateChange);
15023  
15024        document.importNode = function (node, deep) {
15025          switch (node.nodeType) {
15026            case 1:
15027              return setupAll(document, importNode, [node, !!deep]);
15028            case 11:
15029              for (var
15030                fragment = document.createDocumentFragment(),
15031                childNodes = node.childNodes,
15032                length = childNodes.length,
15033                i = 0; i < length; i++
15034              )
15035                fragment.appendChild(document.importNode(childNodes[i], !!deep));
15036              return fragment;
15037            default:
15038              return cloneNode.call(node, !!deep);
15039          }
15040        };
15041  
15042        HTMLElementPrototype.cloneNode = function (deep) {
15043          return setupAll(this, cloneNode, [!!deep]);
15044        };
15045      }
15046  
15047      if (justSetup) return (justSetup = false);
15048  
15049      if (-2 < (
15050        indexOf.call(types, PREFIX_IS + upperType) +
15051        indexOf.call(types, PREFIX_TAG + upperType)
15052      )) {
15053        throwTypeError(type);
15054      }
15055  
15056      if (!validName.test(upperType) || -1 < indexOf.call(invalidNames, upperType)) {
15057        throw new Error('The type ' + type + ' is invalid');
15058      }
15059  
15060      var
15061        constructor = function () {
15062          return extending ?
15063            document.createElement(nodeName, upperType) :
15064            document.createElement(nodeName);
15065        },
15066        opt = options || OP,
15067        extending = hOP.call(opt, EXTENDS),
15068        nodeName = extending ? options[EXTENDS].toUpperCase() : upperType,
15069        upperType,
15070        i
15071      ;
15072  
15073      if (extending && -1 < (
15074        indexOf.call(types, PREFIX_TAG + nodeName)
15075      )) {
15076        throwTypeError(nodeName);
15077      }
15078  
15079      i = types.push((extending ? PREFIX_IS : PREFIX_TAG) + upperType) - 1;
15080  
15081      query = query.concat(
15082        query.length ? ',' : '',
15083        extending ? nodeName + '[is="' + type.toLowerCase() + '"]' : nodeName
15084      );
15085  
15086      constructor.prototype = (
15087        protos[i] = hOP.call(opt, 'prototype') ?
15088          opt.prototype :
15089          create(HTMLElementPrototype)
15090      );
15091  
15092      if (query.length) loopAndVerify(
15093        document.querySelectorAll(query),
15094        ATTACHED
15095      );
15096  
15097      return constructor;
15098    };
15099  
15100    document.createElement = (patchedCreateElement = function (localName, typeExtension) {
15101      var
15102        is = getIs(typeExtension),
15103        node = is ?
15104          createElement.call(document, localName, secondArgument(is)) :
15105          createElement.call(document, localName),
15106        name = '' + localName,
15107        i = indexOf.call(
15108          types,
15109          (is ? PREFIX_IS : PREFIX_TAG) +
15110          (is || name).toUpperCase()
15111        ),
15112        setup = -1 < i
15113      ;
15114      if (is) {
15115        node.setAttribute('is', is = is.toLowerCase());
15116        if (setup) {
15117          setup = isInQSA(name.toUpperCase(), is);
15118        }
15119      }
15120      notFromInnerHTMLHelper = !document.createElement.innerHTMLHelper;
15121      if (setup) patch(node, protos[i]);
15122      return node;
15123    });
15124  
15125  }
15126  
15127  // needed due unbelievable IE11 behavior
15128  // https://github.com/WebReflection/document-register-element/issues/175#issuecomment-520904688
15129  addEventListener(
15130    'beforeunload',
15131    function () {
15132      delete document.createElement;
15133      delete document.importNode;
15134      delete document[REGISTER_ELEMENT];
15135    },
15136    false
15137  );
15138  
15139  function ASAP() {
15140    var queue = asapQueue.splice(0, asapQueue.length);
15141    asapTimer = 0;
15142    while (queue.length) {
15143      queue.shift().call(
15144        null, queue.shift()
15145      );
15146    }
15147  }
15148  
15149  function loopAndVerify(list, action) {
15150    for (var i = 0, length = list.length; i < length; i++) {
15151      verifyAndSetupAndAction(list[i], action);
15152    }
15153  }
15154  
15155  function loopAndSetup(list) {
15156    for (var i = 0, length = list.length, node; i < length; i++) {
15157      node = list[i];
15158      patch(node, protos[getTypeIndex(node)]);
15159    }
15160  }
15161  
15162  function executeAction(action) {
15163    return function (node) {
15164      if (isValidNode(node)) {
15165        verifyAndSetupAndAction(node, action);
15166        if (query.length) loopAndVerify(
15167          node.querySelectorAll(query),
15168          action
15169        );
15170      }
15171    };
15172  }
15173  
15174  function getTypeIndex(target) {
15175    var
15176      is = getAttribute.call(target, 'is'),
15177      nodeName = target.nodeName.toUpperCase(),
15178      i = indexOf.call(
15179        types,
15180        is ?
15181            PREFIX_IS + is.toUpperCase() :
15182            PREFIX_TAG + nodeName
15183      )
15184    ;
15185    return is && -1 < i && !isInQSA(nodeName, is) ? -1 : i;
15186  }
15187  
15188  function isInQSA(name, type) {
15189    return -1 < query.indexOf(name + '[is="' + type + '"]');
15190  }
15191  
15192  function onDOMAttrModified(e) {
15193    var
15194      node = e.currentTarget,
15195      attrChange = e.attrChange,
15196      attrName = e.attrName,
15197      target = e.target,
15198      addition = e[ADDITION] || 2,
15199      removal = e[REMOVAL] || 3
15200    ;
15201    if (notFromInnerHTMLHelper &&
15202        (!target || target === node) &&
15203        node[ATTRIBUTE_CHANGED_CALLBACK] &&
15204        attrName !== 'style' && (
15205          e.prevValue !== e.newValue ||
15206          // IE9, IE10, and Opera 12 gotcha
15207          e.newValue === '' && (
15208            attrChange === addition ||
15209            attrChange === removal
15210          )
15211    )) {
15212      node[ATTRIBUTE_CHANGED_CALLBACK](
15213        attrName,
15214        attrChange === addition ? null : e.prevValue,
15215        attrChange === removal ? null : e.newValue
15216      );
15217    }
15218  }
15219  
15220  function onDOMNode(action) {
15221    var executor = executeAction(action);
15222    return function (e) {
15223      asapQueue.push(executor, e.target);
15224      if (asapTimer) clearTimeout(asapTimer);
15225      asapTimer = setTimeout(ASAP, 1);
15226    };
15227  }
15228  
15229  function onReadyStateChange(e) {
15230    if (dropDomContentLoaded) {
15231      dropDomContentLoaded = false;
15232      e.currentTarget.removeEventListener(DOM_CONTENT_LOADED, onReadyStateChange);
15233    }
15234    if (query.length) loopAndVerify(
15235      (e.target || document).querySelectorAll(query),
15236      e.detail === DETACHED ? DETACHED : ATTACHED
15237    );
15238    if (IE8) purge();
15239  }
15240  
15241  function patchedSetAttribute(name, value) {
15242    // jshint validthis:true
15243    var self = this;
15244    setAttribute.call(self, name, value);
15245    onSubtreeModified.call(self, {target: self});
15246  }
15247  
15248  function setupAll(context, callback, args) {
15249    var
15250      node = callback.apply(context, args),
15251      i = getTypeIndex(node)
15252    ;
15253    if (-1 < i) patch(node, protos[i]);
15254    if (args.pop() && query.length)
15255      loopAndSetup(node.querySelectorAll(query));
15256    return node;
15257  }
15258  
15259  function setupNode(node, proto) {
15260    setPrototype(node, proto);
15261    if (observer) {
15262      observer.observe(node, attributesObserver);
15263    } else {
15264      if (doesNotSupportDOMAttrModified) {
15265        node.setAttribute = patchedSetAttribute;
15266        node[EXPANDO_UID] = getAttributesMirror(node);
15267        node[ADD_EVENT_LISTENER](DOM_SUBTREE_MODIFIED, onSubtreeModified);
15268      }
15269      node[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, onDOMAttrModified);
15270    }
15271    if (node[CREATED_CALLBACK] && notFromInnerHTMLHelper) {
15272      node.created = true;
15273      node[CREATED_CALLBACK]();
15274      node.created = false;
15275    }
15276  }
15277  
15278  function purge() {
15279    for (var
15280      node,
15281      i = 0,
15282      length = targets.length;
15283      i < length; i++
15284    ) {
15285      node = targets[i];
15286      if (!documentElement.contains(node)) {
15287        length--;
15288        targets.splice(i--, 1);
15289        verifyAndSetupAndAction(node, DETACHED);
15290      }
15291    }
15292  }
15293  
15294  function throwTypeError(type) {
15295    throw new Error('A ' + type + ' type is already registered');
15296  }
15297  
15298  function verifyAndSetupAndAction(node, action) {
15299    var
15300      fn,
15301      i = getTypeIndex(node),
15302      counterAction
15303    ;
15304    if ((-1 < i) && !closest.call(node, 'TEMPLATE')) {
15305      patchIfNotAlready(node, protos[i]);
15306      i = 0;
15307      if (action === ATTACHED && !node[ATTACHED]) {
15308        node[DETACHED] = false;
15309        node[ATTACHED] = true;
15310        counterAction = 'connected';
15311        i = 1;
15312        if (IE8 && indexOf.call(targets, node) < 0) {
15313          targets.push(node);
15314        }
15315      } else if (action === DETACHED && !node[DETACHED]) {
15316        node[ATTACHED] = false;
15317        node[DETACHED] = true;
15318        counterAction = 'disconnected';
15319        i = 1;
15320      }
15321      if (i && (fn = (
15322        node[action + CALLBACK] ||
15323        node[counterAction + CALLBACK]
15324      ))) fn.call(node);
15325    }
15326  }
15327  
15328  // V1 in da House!
15329  function CustomElementRegistry() {}
15330  
15331  CustomElementRegistry.prototype = {
15332    constructor: CustomElementRegistry,
15333    // a workaround for the stubborn WebKit
15334    define: usableCustomElements ?
15335      function (name, Class, options) {
15336        if (options) {
15337          CERDefine(name, Class, options);
15338        } else {
15339          var NAME = name.toUpperCase();
15340          constructors[NAME] = {
15341            constructor: Class,
15342            create: [NAME]
15343          };
15344          nodeNames.set(Class, NAME);
15345          customElements.define(name, Class);
15346        }
15347      } :
15348      CERDefine,
15349    get: usableCustomElements ?
15350      function (name) {
15351        return customElements.get(name) || get(name);
15352      } :
15353      get,
15354    whenDefined: usableCustomElements ?
15355      function (name) {
15356        return Promise.race([
15357          customElements.whenDefined(name),
15358          whenDefined(name)
15359        ]);
15360      } :
15361      whenDefined
15362  };
15363  
15364  function CERDefine(name, Class, options) {
15365    var
15366      is = options && options[EXTENDS] || '',
15367      CProto = Class.prototype,
15368      proto = create(CProto),
15369      attributes = Class.observedAttributes || empty,
15370      definition = {prototype: proto}
15371    ;
15372    // TODO: is this needed at all since it's inherited?
15373    // defineProperty(proto, 'constructor', {value: Class});
15374    safeProperty(proto, CREATED_CALLBACK, {
15375        value: function () {
15376          if (justCreated) justCreated = false;
15377          else if (!this[DRECEV1]) {
15378            this[DRECEV1] = true;
15379            new Class(this);
15380            if (CProto[CREATED_CALLBACK])
15381              CProto[CREATED_CALLBACK].call(this);
15382            var info = constructors[nodeNames.get(Class)];
15383            if (!usableCustomElements || info.create.length > 1) {
15384              notifyAttributes(this);
15385            }
15386          }
15387      }
15388    });
15389    safeProperty(proto, ATTRIBUTE_CHANGED_CALLBACK, {
15390      value: function (name) {
15391        if (-1 < indexOf.call(attributes, name)) {
15392          if (CProto[ATTRIBUTE_CHANGED_CALLBACK])
15393            CProto[ATTRIBUTE_CHANGED_CALLBACK].apply(this, arguments);
15394        }
15395      }
15396    });
15397    if (CProto[CONNECTED_CALLBACK]) {
15398      safeProperty(proto, ATTACHED_CALLBACK, {
15399        value: CProto[CONNECTED_CALLBACK]
15400      });
15401    }
15402    if (CProto[DISCONNECTED_CALLBACK]) {
15403      safeProperty(proto, DETACHED_CALLBACK, {
15404        value: CProto[DISCONNECTED_CALLBACK]
15405      });
15406    }
15407    if (is) definition[EXTENDS] = is;
15408    name = name.toUpperCase();
15409    constructors[name] = {
15410      constructor: Class,
15411      create: is ? [is, secondArgument(name)] : [name]
15412    };
15413    nodeNames.set(Class, name);
15414    document[REGISTER_ELEMENT](name.toLowerCase(), definition);
15415    whenDefined(name);
15416    waitingList[name].r();
15417  }
15418  
15419  function get(name) {
15420    var info = constructors[name.toUpperCase()];
15421    return info && info.constructor;
15422  }
15423  
15424  function getIs(options) {
15425    return typeof options === 'string' ?
15426        options : (options && options.is || '');
15427  }
15428  
15429  function notifyAttributes(self) {
15430    var
15431      callback = self[ATTRIBUTE_CHANGED_CALLBACK],
15432      attributes = callback ? self.attributes : empty,
15433      i = attributes.length,
15434      attribute
15435    ;
15436    while (i--) {
15437      attribute =  attributes[i]; // || attributes.item(i);
15438      callback.call(
15439        self,
15440        attribute.name || attribute.nodeName,
15441        null,
15442        attribute.value || attribute.nodeValue
15443      );
15444    }
15445  }
15446  
15447  function whenDefined(name) {
15448    name = name.toUpperCase();
15449    if (!(name in waitingList)) {
15450      waitingList[name] = {};
15451      waitingList[name].p = new Promise(function (resolve) {
15452        waitingList[name].r = resolve;
15453      });
15454    }
15455    return waitingList[name].p;
15456  }
15457  
15458  function polyfillV1() {
15459    if (customElements) delete window.customElements;
15460    defineProperty(window, 'customElements', {
15461      configurable: true,
15462      value: new CustomElementRegistry()
15463    });
15464    defineProperty(window, 'CustomElementRegistry', {
15465      configurable: true,
15466      value: CustomElementRegistry
15467    });
15468    for (var
15469      patchClass = function (name) {
15470        var Class = window[name];
15471        if (Class) {
15472          window[name] = function CustomElementsV1(self) {
15473            var info, isNative;
15474            if (!self) self = this;
15475            if (!self[DRECEV1]) {
15476              justCreated = true;
15477              info = constructors[nodeNames.get(self.constructor)];
15478              isNative = usableCustomElements && info.create.length === 1;
15479              self = isNative ?
15480                Reflect.construct(Class, empty, info.constructor) :
15481                document.createElement.apply(document, info.create);
15482              self[DRECEV1] = true;
15483              justCreated = false;
15484              if (!isNative) notifyAttributes(self);
15485            }
15486            return self;
15487          };
15488          window[name].prototype = Class.prototype;
15489          try {
15490            Class.prototype.constructor = window[name];
15491          } catch(WebKit) {
15492            fixGetClass = true;
15493            defineProperty(Class, DRECEV1, {value: window[name]});
15494          }
15495        }
15496      },
15497      Classes = htmlClass.get(/^HTML[A-Z]*[a-z]/),
15498      i = Classes.length;
15499      i--;
15500      patchClass(Classes[i])
15501    ) {}
15502    (document.createElement = function (name, options) {
15503      var is = getIs(options);
15504      return is ?
15505        patchedCreateElement.call(this, name, secondArgument(is)) :
15506        patchedCreateElement.call(this, name);
15507    });
15508    if (!V0) {
15509      justSetup = true;
15510      document[REGISTER_ELEMENT]('');
15511    }
15512  }
15513  
15514  // if customElements is not there at all
15515  if (!customElements || /^force/.test(polyfill.type)) polyfillV1();
15516  else if(!polyfill.noBuiltIn) {
15517    // if available test extends work as expected
15518    try {
15519      (function (DRE, options, name) {
15520        var re = new RegExp('^<a\\s+is=(\'|")' + name + '\\1></a>$');
15521        options[EXTENDS] = 'a';
15522        DRE.prototype = create(HTMLAnchorElement.prototype);
15523        DRE.prototype.constructor = DRE;
15524        window.customElements.define(name, DRE, options);
15525        if (
15526          !re.test(document.createElement('a', {is: name}).outerHTML) ||
15527          !re.test((new DRE()).outerHTML)
15528        ) {
15529          throw options;
15530        }
15531      }(
15532        function DRE() {
15533          return Reflect.construct(HTMLAnchorElement, [], DRE);
15534        },
15535        {},
15536        'document-register-element-a' + UID
15537      ));
15538    } catch(o_O) {
15539      // or force the polyfill if not
15540      // and keep internal original reference
15541      polyfillV1();
15542    }
15543  }
15544  
15545  // FireFox only issue
15546  if(!polyfill.noBuiltIn) {
15547    try {
15548      if (createElement.call(document, 'a', 'a').outerHTML.indexOf('is') < 0)
15549        throw {};
15550    } catch(FireFox) {
15551      secondArgument = function (is) {
15552        return {is: is.toLowerCase()};
15553      };
15554    }
15555  }
15556  
15557}
15557
15558
15559module.exports = installCustomElements;
15560installCustomElements(global);
15561
15562}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
15563
15564},{}],108:[function(_dereq_,module,exports){
15565(function (global){
15566var win;
15567
15568if (typeof window !== "undefined") {
15569    win = window;
15570} else if (typeof global !== "undefined") {
15571    win = global;
15572} else if (typeof self !== "undefined"){
15573    win = self;
15574} else {
15575    win = {};
15576}
15577
15578module.exports = win;
15579
15580}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
15581
15582},{}],109:[function(_dereq_,module,exports){
15583(function (global){
15584(function (global, factory) {
15585	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
15586	typeof define === 'function' && define.amd ? define(factory) :
15587	(global.GlslCanvas = factory());
15588}(this, (function () { 'use strict';
15589
15590var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
15591
15592var win;
15593
15594if (typeof window !== "undefined") {
15595    win = window;
15596} else if (typeof commonjsGlobal !== "undefined") {
15597    win = commonjsGlobal;
15598} else if (typeof self !== "undefined"){
15599    win = self;
15600} else {
15601    win = {};
15602}
15603
15604var window_1 = win;
15605
15606var isFunction_1 = isFunction;
15607
15608var toString = Object.prototype.toString;
15609
15610function isFunction (fn) {
15611  if (!fn) {
15612    return false
15613  }
15614  var string = toString.call(fn);
15615  return string === '[object Function]' ||
15616    (typeof fn === 'function' && string !== '[object RegExp]') ||
15617    (typeof window !== 'undefined' &&
15618     // IE8 and below
15619     (fn === window.setTimeout ||
15620      fn === window.alert ||
15621      fn === window.confirm ||
15622      fn === window.prompt))
15623}
15624
15625var trim = function(string) {
15626  return string.replace(/^\s+|\s+$/g, '');
15627};
15628var isArray = function(arg) {
15629      return Object.prototype.toString.call(arg) === '[object Array]';
15630    };
15631
15632var parseHeaders = function (headers) {
15633  if (!headers)
15634    return {}
15635
15636  var result = {};
15637
15638  var headersArr = trim(headers).split('\n');
15639
15640  for (var i = 0; i < headersArr.length; i++) {
15641    var row = headersArr[i];
15642    var index = row.indexOf(':')
15643    , key = trim(row.slice(0, index)).toLowerCase()
15644    , value = trim(row.slice(index + 1));
15645
15646    if (typeof(result[key]) === 'undefined') {
15647      result[key] = value;
15648    } else if (isArray(result[key])) {
15649      result[key].push(value);
15650    } else {
15651      result[key] = [ result[key], value ];
15652    }
15653  }
15654
15655  return result
15656};
15657
15658var immutable = extend;
15659
15660var hasOwnProperty = Object.prototype.hasOwnProperty;
15661
15662function extend() {
15663    var target = {};
15664
15665    for (var i = 0; i < arguments.length; i++) {
15666        var source = arguments[i];
15667
15668        for (var key in source) {
15669            if (hasOwnProperty.call(source, key)) {
15670                target[key] = source[key];
15671            }
15672        }
15673    }
15674
15675    return target
15676}
15677
15678"use strict";
15679
15680
15681
15682
15683
15684var xhr = createXHR;
15685// Allow use of default import syntax in TypeScript
15686var default_1 = createXHR;
15687createXHR.XMLHttpRequest = window_1.XMLHttpRequest || noop;
15688createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window_1.XDomainRequest;
15689
15690forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
15691    createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
15692        options = initParams(uri, options, callback);
15693        options.method = method.toUpperCase();
15694        return _createXHR(options)
15695    };
15696});
15697
15698function forEachArray(array, iterator) {
15699    for (var i = 0; i < array.length; i++) {
15700        iterator(array[i]);
15701    }
15702}
15703
15704function isEmpty(obj){
15705    for(var i in obj){
15706        if(obj.hasOwnProperty(i)) return false
15707    }
15708    return true
15709}
15710
15711function initParams(uri, options, callback) {
15712    var params = uri;
15713
15714    if (isFunction_1(options)) {
15715        callback = options;
15716        if (typeof uri === "string") {
15717            params = {uri:uri};
15718        }
15719    } else {
15720        params = immutable(options, {uri: uri});
15721    }
15722
15723    params.callback = callback;
15724    return params
15725}
15726
15727function createXHR(uri, options, callback) {
15728    options = initParams(uri, options, callback);
15729    return _createXHR(options)
15730}
15731
15732function _createXHR(options) {
15733    if(typeof options.callback === "undefined"){
15734        throw new Error("callback argument missing")
15735    }
15736
15737    var called = false;
15738    var callback = function cbOnce(err, response, body){
15739        if(!called){
15740            called = true;
15741            options.callback(err, response, body);
15742        }
15743    };
15744
15745    function readystatechange() {
15746        if (xhr.readyState === 4) {
15747            setTimeout(loadFunc, 0);
15748        }
15749    }
15750
15751    function getBody() {
15752        // Chrome with requestType=blob throws errors arround when even testing access to responseText
15753        var body = undefined;
15754
15755        if (xhr.response) {
15756            body = xhr.response;
15757        } else {
15758            body = xhr.responseText || getXml(xhr);
15759        }
15760
15761        if (isJson) {
15762            try {
15763                body = JSON.parse(body);
15764            } catch (e) {}
15765        }
15766
15767        return body
15768    }
15769
15770    function errorFunc(evt) {
15771        clearTimeout(timeoutTimer);
15772        if(!(evt instanceof Error)){
15773            evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") );
15774        }
15775        evt.statusCode = 0;
15776        return callback(evt, failureResponse)
15777    }
15778
15779    // will load the data & process the response in a special response object
15780    function loadFunc() {
15781        if (aborted) return
15782        var status;
15783        clearTimeout(timeoutTimer);
15784        if(options.useXDR && xhr.status===undefined) {
15785            //IE8 CORS GET successful response doesn't have a status field, but body is fine
15786            status = 200;
15787        } else {
15788            status = (xhr.status === 1223 ? 204 : xhr.status);
15789        }
15790        var response = failureResponse;
15791        var err = null;
15792
15793        if (status !== 0){
15794            response = {
15795                body: getBody(),
15796                statusCode: status,
15797                method: method,
15798                headers: {},
15799                url: uri,
15800                rawRequest: xhr
15801            };
15802            if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
15803                response.headers = parseHeaders(xhr.getAllResponseHeaders());
15804            }
15805        } else {
15806            err = new Error("Internal XMLHttpRequest Error");
15807        }
15808        return callback(err, response, response.body)
15809    }
15810
15811    var xhr = options.xhr || null;
15812
15813    if (!xhr) {
15814        if (options.cors || options.useXDR) {
15815            xhr = new createXHR.XDomainRequest();
15816        }else{
15817            xhr = new createXHR.XMLHttpRequest();
15818        }
15819    }
15820
15821    var key;
15822    var aborted;
15823    var uri = xhr.url = options.uri || options.url;
15824    var method = xhr.method = options.method || "GET";
15825    var body = options.body || options.data;
15826    var headers = xhr.headers = options.headers || {};
15827    var sync = !!options.sync;
15828    var isJson = false;
15829    var timeoutTimer;
15830    var failureResponse = {
15831        body: undefined,
15832        headers: {},
15833        statusCode: 0,
15834        method: method,
15835        url: uri,
15836        rawRequest: xhr
15837    };
15838
15839    if ("json" in options && options.json !== false) {
15840        isJson = true;
15841        headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user
15842        if (method !== "GET" && method !== "HEAD") {
15843            headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user
15844            body = JSON.stringify(options.json === true ? body : options.json);
15845        }
15846    }
15847
15848    xhr.onreadystatechange = readystatechange;
15849    xhr.onload = loadFunc;
15850    xhr.onerror = errorFunc;
15851    // IE9 must have onprogress be set to a unique function.
15852    xhr.onprogress = function () {
15853        // IE must die
15854    };
15855    xhr.onabort = function(){
15856        aborted = true;
15857    };
15858    xhr.ontimeout = errorFunc;
15859    xhr.open(method, uri, !sync, options.username, options.password);
15860    //has to be after open
15861    if(!sync) {
15862        xhr.withCredentials = !!options.withCredentials;
15863    }
15864    // Cannot set timeout with sync request
15865    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
15866    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
15867    if (!sync && options.timeout > 0 ) {
15868        timeoutTimer = setTimeout(function(){
15869            if (aborted) return
15870            aborted = true;//IE9 may still call readystatechange
15871            xhr.abort("timeout");
15872            var e = new Error("XMLHttpRequest timeout");
15873            e.code = "ETIMEDOUT";
15874            errorFunc(e);
15875        }, options.timeout );
15876    }
15877
15878    if (xhr.setRequestHeader) {
15879        for(key in headers){
15880            if(headers.hasOwnProperty(key)){
15881                xhr.setRequestHeader(key, headers[key]);
15882            }
15883        }
15884    } else if (options.headers && !isEmpty(options.headers)) {
15885        throw new Error("Headers cannot be set on an XDomainRequest object")
15886    }
15887
15888    if ("responseType" in options) {
15889        xhr.responseType = options.responseType;
15890    }
15891
15892    if ("beforeSend" in options &&
15893        typeof options.beforeSend === "function"
15894    ) {
15895        options.beforeSend(xhr);
15896    }
15897
15898    // Microsoft Edge browser sends "undefined" when send is called with undefined value.
15899    // XMLHttpRequest spec says to pass null as body to indicate no body
15900    // See https://github.com/naugtur/xhr/issues/100.
15901    xhr.send(body || null);
15902
15903    return xhr
15904
15905
15906}
15907
15908function getXml(xhr) {
15909    // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException"
15910    // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML.
15911    try {
15912        if (xhr.responseType === "document") {
15913            return xhr.responseXML
15914        }
15915        var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror";
15916        if (xhr.responseType === "" && !firefoxBugTakenEffect) {
15917            return xhr.responseXML
15918        }
15919    } catch (e) {}
15920
15921    return null
15922}
15923
15924function noop() {}
15925
15926xhr.default = default_1;
15927
15928var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
15929  return typeof obj;
15930} : function (obj) {
15931  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
15932};
15933
15934
15935
15936
15937
15938var asyncGenerator = function () {
15939  function AwaitValue(value) {
15940    this.value = value;
15941  }
15942
15943  function AsyncGenerator(gen) {
15944    var front, back;
15945
15946    function send(key, arg) {
15947      return new Promise(function (resolve, reject) {
15948        var request = {
15949          key: key,
15950          arg: arg,
15951          resolve: resolve,
15952          reject: reject,
15953          next: null
15954        };
15955
15956        if (back) {
15957          back = back.next = request;
15958        } else {
15959          front = back = request;
15960          resume(key, arg);
15961        }
15962      });
15963    }
15964
15965    function resume(key, arg) {
15966      try {
15967        var result = gen[key](arg);
15968        var value = result.value;
15969
15970        if (value instanceof AwaitValue) {
15971          Promise.resolve(value.value).then(function (arg) {
15972            resume("next", arg);
15973          }, function (arg) {
15974            resume("throw", arg);
15975          });
15976        } else {
15977          settle(result.done ? "return" : "normal", result.value);
15978        }
15979      } catch (err) {
15980        settle("throw", err);
15981      }
15982    }
15983
15984    function settle(type, value) {
15985      switch (type) {
15986        case "return":
15987          front.resolve({
15988            value: value,
15989            done: true
15990          });
15991          break;
15992
15993        case "throw":
15994          front.reject(value);
15995          break;
15996
15997        default:
15998          front.resolve({
15999            value: value,
16000            done: false
16001          });
16002          break;
16003      }
16004
16005      front = front.next;
16006
16007      if (front) {
16008        resume(front.key, front.arg);
16009      } else {
16010        back = null;
16011      }
16012    }
16013
16014    this._invoke = send;
16015
16016    if (typeof gen.return !== "function") {
16017      this.return = undefined;
16018    }
16019  }
16020
16021  if (typeof Symbol === "function" && Symbol.asyncIterator) {
16022    AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
16023      return this;
16024    };
16025  }
16026
16027  AsyncGenerator.prototype.next = function (arg) {
16028    return this._invoke("next", arg);
16029  };
16030
16031  AsyncGenerator.prototype.throw = function (arg) {
16032    return this._invoke("throw", arg);
16033  };
16034
16035  AsyncGenerator.prototype.return = function (arg) {
16036    return this._invoke("return", arg);
16037  };
16038
16039  return {
16040    wrap: function (fn) {
16041      return function () {
16042        return new AsyncGenerator(fn.apply(this, arguments));
16043      };
16044    },
16045    await: function (value) {
16046      return new AwaitValue(value);
16047    }
16048  };
16049}();
16050
16051
16052
16053
16054
16055var classCallCheck = function (instance, Constructor) {
16056  if (!(instance instanceof Constructor)) {
16057    throw new TypeError("Cannot call a class as a function");
16058  }
16059};
16060
16061var createClass = function () {
16062  function defineProperties(target, props) {
16063    for (var i = 0; i < props.length; i++) {
16064      var descriptor = props[i];
16065      descriptor.enumerable = descriptor.enumerable || false;
16066      descriptor.configurable = true;
16067      if ("value" in descriptor) descriptor.writable = true;
16068      Object.defineProperty(target, descriptor.key, descriptor);
16069    }
16070  }
16071
16072  return function (Constructor, protoProps, staticProps) {
16073    if (protoProps) defineProperties(Constructor.prototype, protoProps);
16074    if (staticProps) defineProperties(Constructor, staticProps);
16075    return Constructor;
16076  };
16077}();
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119var toConsumableArray = function (arr) {
16120  if (Array.isArray(arr)) {
16121    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
16122
16123    return arr2;
16124  } else {
16125    return Array.from(arr);
16126  }
16127};
16128
16129var lastError = '';
16130
16131/**
16132 * Creates the HTLM for a failure message
16133 * @param {string} canvasContainerId id of container of th
16134 *        canvas.
16135 * @return {string} The html.
16136 */
16137function makeFailHTML(msg) {
16138    return '\n<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>\n<td align="center">\n<div style="display: table-cell; vertical-align: middle;">\n<div style="">' + msg + '</div>\n</div>\n</td></tr></table>\n';
16139}
16140
16141/**
16142 * Message for getting a webgl browser
16143 * @type {string}
16144 */
16145var GET_A_WEBGL_BROWSER = '\n\tThis page requires a browser that supports WebGL.<br/>\n\t<a href="http://get.webgl.org">Click here to upgrade your browser.</a>\n';
16146
16147/**
16148 * Message for need better hardware
16149 * @type {string}
16150 */
16151var OTHER_PROBLEM = '\n\tIt does not appear your computer can support WebGL.<br/>\n\t<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>\n';
16152
16153/**
16154 * Code to return in `onError` callback when the browser doesn't support webgl
16155 * @type {number}
16156 */
16157var ERROR_BROWSER_SUPPORT = 1;
16158
16159/**
16160 * Code to return in `onError` callback there's any other problem related to webgl
16161 * @type {number}
16162 */
16163var ERROR_OTHER = 2;
16164
16165/**
16166 * Creates a webgl context. If creation fails it will
16167 * change the contents of the container of the <canvas>
16168 * tag to an error message with the correct links for WebGL,
16169 * unless `onError` option is defined to a callback,
16170 * which allows for custom error handling..
16171 * @param {Element} canvas. The canvas element to create a
16172 *     context from.
16173 * @param {WebGLContextCreationAttributes} optAttribs Any
16174 *     creation attributes you want to pass in.
16175 * @return {WebGLRenderingContext} The created context.
16176 */
16177function setupWebGL(canvas, optAttribs, onError) {
16178    function showLink(str) {
16179        var container = canvas.parentNode;
16180        if (container) {
16181            container.innerHTML = makeFailHTML(str);
16182        }
16183    }
16184
16185    function handleError(errorCode, msg) {
16186        if (typeof onError === 'function') {
16187            onError(errorCode);
16188        } else {
16189            showLink(msg);
16190        }
16191    }
16192
16193    if (!window.WebGLRenderingContext) {
16194        handleError(ERROR_BROWSER_SUPPORT, GET_A_WEBGL_BROWSER);
16195        return null;
16196    }
16197
16198    var context = create3DContext(canvas, optAttribs);
16199    if (!context) {
16200        handleError(ERROR_OTHER, OTHER_PROBLEM);
16201    } else {
16202        context.getExtension('OES_standard_derivatives');
16203    }
16204    return context;
16205}
16206
16207/**
16208 * Creates a webgl context.
16209 * @param {!Canvas} canvas The canvas tag to get context
16210 *     from. If one is not passed in one will be created.
16211 * @return {!WebGLContext} The created context.
16212 */
16213function create3DContext(canvas, optAttribs) {
16214    var names = ['webgl', 'experimental-webgl'];
16215    var context = null;
16216    for (var ii = 0; ii < names.length; ++ii) {
16217        try {
16218            context = canvas.getContext(names[ii], optAttribs);
16219        } catch (e) {
16220            if (context) {
16221                break;
16222            }
16223        }
16224    }
16225    return context;
16226}
16227
16228/*
16229 *	Create a Vertex of a specific type (gl.VERTEX_SHADER/)
16230 */
16231function createShader(main, source, type, offset) {
16232    var gl = main.gl;
16233
16234    var shader = gl.createShader(type);
16235    gl.shaderSource(shader, source);
16236    gl.compileShader(shader);
16237
16238    var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
16239
16240    if (!compiled) {
16241        // Something went wrong during compilation; get the error
16242        lastError = gl.getShaderInfoLog(shader);
16243        console.error('*** Error compiling shader ' + shader + ':' + lastError);
16244        main.trigger('error', {
16245            shader: shader,
16246            source: source,
16247            type: type,
16248            error: lastError,
16249            offset: offset || 0
16250        });
16251        gl.deleteShader(shader);
16252        return null;
16253    }
16254
16255    return shader;
16256}
16257
16258/**
16259 * Loads a shader.
16260 * @param {!WebGLContext} gl The WebGLContext to use.
16261 * @param {string} shaderSource The shader source.
16262 * @param {number} shaderType The type of shader.
16263 * @param {function(string): void) opt_errorCallback callback for errors.
16264 * @return {!WebGLShader} The created shader.
16265 */
16266function createProgram(main, shaders, optAttribs, optLocations) {
16267    var gl = main.gl;
16268
16269    var program = gl.createProgram();
16270    for (var ii = 0; ii < shaders.length; ++ii) {
16271        gl.attachShader(program, shaders[ii]);
16272    }
16273    if (optAttribs) {
16274        for (var _ii = 0; _ii < optAttribs.length; ++_ii) {
16275            gl.bindAttribLocation(program, optLocations ? optLocations[_ii] : _ii, optAttribs[_ii]);
16276        }
16277    }
16278    gl.linkProgram(program);
16279
16280    // Check the link status
16281    var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
16282    if (!linked) {
16283        // something went wrong with the link
16284        lastError = gl.getProgramInfoLog(program);
16285        console.log('Error in program linking:' + lastError);
16286        gl.deleteProgram(program);
16287        return null;
16288    }
16289    return program;
16290}
16291
16292// By Brett Camber on
16293// https://github.com/tangrams/tangram/blob/master/src/gl/glsl.js
16294function parseUniforms(uniforms) {
16295    var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
16296
16297    var parsed = [];
16298
16299    for (var name in uniforms) {
16300        var uniform = uniforms[name];
16301        var u = void 0;
16302
16303        if (prefix) {
16304            name = prefix + '.' + name;
16305        }
16306
16307        // Single float
16308        if (typeof uniform === 'number') {
16309            parsed.push({
16310                type: 'float',
16311                method: '1f',
16312                name: name,
16313                value: uniform
16314            });
16315        }
16316        // Array: vector, array of floats, array of textures, or array of structs
16317        else if (Array.isArray(uniform)) {
16318                // Numeric values
16319                if (typeof uniform[0] === 'number') {
16320                    // float vectors (vec2, vec3, vec4)
16321                    if (uniform.length === 1) {
16322                        parsed.push({
16323                            type: 'float',
16324                            method: '1f',
16325                            name: name,
16326                            value: uniform
16327                        });
16328                    }
16329                    // float vectors (vec2, vec3, vec4)
16330                    else if (uniform.length >= 2 && uniform.length <= 4) {
16331                            parsed.push({
16332                                type: 'vec' + uniform.length,
16333                                method: uniform.length + 'fv',
16334                                name: name,
16335                                value: uniform
16336                            });
16337                        }
16338                        // float array
16339                        else if (uniform.length > 4) {
16340                                parsed.push({
16341                                    type: 'float[]',
16342                                    method: '1fv',
16343                                    name: name + '[0]',
16344                                    value: uniform
16345                                });
16346                            }
16347                    // TODO: assume matrix for (typeof == Float32Array && length == 16)?
16348                }
16349                // Array of textures
16350                else if (typeof uniform[0] === 'string') {
16351                        parsed.push({
16352                            type: 'sampler2D',
16353                            method: '1i',
16354                            name: name,
16355                            value: uniform
16356                        });
16357                    }
16358                    // Array of arrays - but only arrays of vectors are allowed in this case
16359                    else if (Array.isArray(uniform[0]) && typeof uniform[0][0] === 'number') {
16360                            // float vectors (vec2, vec3, vec4)
16361                            if (uniform[0].length >= 2 && uniform[0].length <= 4) {
16362                                // Set each vector in the array
16363                                for (u = 0; u < uniform.length; u++) {
16364                                    parsed.push({
16365                                        type: 'vec' + uniform[0].length,
16366                                        method: uniform[u].length + 'fv',
16367                                        name: name + '[' + u + ']',
16368                                        value: uniform[u]
16369                                    });
16370                                }
16371                            }
16372                            // else error?
16373                        }
16374                        // Array of structures
16375                        else if (_typeof(uniform[0]) === 'object') {
16376                                for (u = 0; u < uniform.length; u++) {
16377                                    // Set each struct in the array
16378                                    parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform[u], name + '[' + u + ']')));
16379                                }
16380                            }
16381            }
16382            // Boolean
16383            else if (typeof uniform === 'boolean') {
16384                    parsed.push({
16385                        type: 'bool',
16386                        method: '1i',
16387                        name: name,
16388                        value: uniform
16389                    });
16390                }
16391                // Texture
16392                else if (typeof uniform === 'string') {
16393                        parsed.push({
16394                            type: 'sampler2D',
16395                            method: '1i',
16396                            name: name,
16397                            value: uniform
16398                        });
16399                    }
16400                    // Structure
16401                    else if ((typeof uniform === 'undefined' ? 'undefined' : _typeof(uniform)) === 'object') {
16402                            // Set each field in the struct
16403                            parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform, name)));
16404                        }
16405        // TODO: support other non-float types? (int, etc.)
16406    }
16407    return parsed;
16408}
16409
16410function isCanvasVisible(canvas) {
16411    var bound = canvas.getBoundingClientRect();
16412    return bound.top + bound.height > 0 && bound.top < (window.innerHeight || document.documentElement.clientHeight);
16413}
16414
16415function isPowerOf2(value) {
16416    return (value & value - 1) === 0;
16417}
16418
16419function isSafari() {
16420    return (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)
16421    );
16422}
16423
16424
16425
16426
16427
16428
16429
16430function isDiff(a, b) {
16431    if (a && b) {
16432        return a.toString() !== b.toString();
16433    }
16434    return false;
16435}
16436
16437function getFile(url) {
16438    var httpRequest = new XMLHttpRequest();
16439    httpRequest.open("GET", url, false);
16440    httpRequest.send();
16441    if (httpRequest.status == 200) return httpRequest.responseText;else return "";
16442}
16443
16444function subscribeMixin$1(target) {
16445    var listeners = new Set();
16446
16447    return Object.assign(target, {
16448        on: function on(type, f) {
16449            var listener = {};
16450            listener[type] = f;
16451            listeners.add(listener);
16452        },
16453        off: function off(type, f) {
16454            if (f) {
16455                var listener = {};
16456                listener[type] = f;
16457                listeners.delete(listener);
16458            } else {
16459                var _iteratorNormalCompletion = true;
16460                var _didIteratorError = false;
16461                var _iteratorError = undefined;
16462
16463                try {
16464                    for (var _iterator = listeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
16465                        var item = _step.value;
16466                        var _iteratorNormalCompletion2 = true;
16467                        var _didIteratorError2 = false;
16468                        var _iteratorError2 = undefined;
16469
16470                        try {
16471                            for (var _iterator2 = Object.keys(item)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
16472                                var key = _step2.value;
16473
16474                                if (key === type) {
16475                                    listeners.delete(item);
16476                                    return;
16477                                }
16478                            }
16479                        } catch (err) {
16480                            _didIteratorError2 = true;
16481                            _iteratorError2 = err;
16482                        } finally {
16483                            try {
16484                                if (!_iteratorNormalCompletion2 && _iterator2.return) {
16485                                    _iterator2.return();
16486                                }
16487                            } finally {
16488                                if (_didIteratorError2) {
16489                                    throw _iteratorError2;
16490                                }
16491                            }
16492                        }
16493                    }
16494                } catch (err) {
16495                    _didIteratorError = true;
16496                    _iteratorError = err;
16497                } finally {
16498                    try {
16499                        if (!_iteratorNormalCompletion && _iterator.return) {
16500                            _iterator.return();
16501                        }
16502                    } finally {
16503                        if (_didIteratorError) {
16504                            throw _iteratorError;
16505                        }
16506                    }
16507                }
16508            }
16509        },
16510        listSubscriptions: function listSubscriptions() {
16511            var _iteratorNormalCompletion3 = true;
16512            var _didIteratorError3 = false;
16513            var _iteratorError3 = undefined;
16514
16515            try {
16516                for (var _iterator3 = listeners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
16517                    var item = _step3.value;
16518
16519                    console.log(item);
16520                }
16521            } catch (err) {
16522                _didIteratorError3 = true;
16523                _iteratorError3 = err;
16524            } finally {
16525                try {
16526                    if (!_iteratorNormalCompletion3 && _iterator3.return) {
16527                        _iterator3.return();
16528                    }
16529                } finally {
16530                    if (_didIteratorError3) {
16531                        throw _iteratorError3;
16532                    }
16533                }
16534            }
16535        },
16536        subscribe: function subscribe(listener) {
16537            listeners.add(listener);
16538        },
16539        unsubscribe: function unsubscribe(listener) {
16540            listeners.delete(listener);
16541        },
16542        unsubscribeAll: function unsubscribeAll() {
16543            listeners.clear();
16544        },
16545        trigger: function trigger(event) {
16546            for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
16547                data[_key - 1] = arguments[_key];
16548            }
16549
16550            var _iteratorNormalCompletion4 = true;
16551            var _didIteratorError4 = false;
16552            var _iteratorError4 = undefined;
16553
16554            try {
16555                for (var _iterator4 = listeners[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
16556                    var listener = _step4.value;
16557
16558                    if (typeof listener[event] === 'function') {
16559                        listener[event].apply(listener, toConsumableArray(data));
16560                    }
16561                }
16562            } catch (err) {
16563                _didIteratorError4 = true;
16564                _iteratorError4 = err;
16565            } finally {
16566                try {
16567                    if (!_iteratorNormalCompletion4 && _iterator4.return) {
16568                        _iterator4.return();
16569                    }
16570                } finally {
16571                    if (_didIteratorError4) {
16572                        throw _iteratorError4;
16573                    }
16574                }
16575            }
16576        }
16577    });
16578}
16579
16580// Texture management
16581// GL texture wrapper object for keeping track of a global set of textures, keyed by a unique user-defined name
16582
16583var Texture = function () {
16584    function Texture(gl, name) {
16585        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
16586        classCallCheck(this, Texture);
16587
16588        subscribeMixin$1(this);
16589
16590        this.gl = gl;
16591        this.texture = gl.createTexture();
16592        if (this.texture) {
16593            this.valid = true;
16594        }
16595        this.bind();
16596
16597        this.name = name;
16598        this.source = null;
16599        this.sourceType = null;
16600        this.loading = null; // a Promise object to track the loading state of this texture
16601
16602        // Default to a 1-pixel black texture so we can safely render while we wait for an image to load
16603        // See: http://stackoverflow.com/questions/19722247/webgl-wait-for-texture-to-load
16604        this.setData(1, 1, new Uint8Array([0, 0, 0, 255]), { filtering: 'linear' });
16605        this.setFiltering(options.filtering);
16606
16607        this.load(options);
16608    }
16609
16610    // Destroy a single texture instance
16611
16612
16613    createClass(Texture, [{
16614        key: 'destroy',
16615        value: function destroy() {
16616            if (!this.valid) {
16617                return;
16618            }
16619            this.gl.deleteTexture(this.texture);
16620            this.texture = null;
16621            delete this.data;
16622            this.data = null;
16623            this.valid = false;
16624        }
16625    }, {
16626        key: 'bind',
16627        value: function bind(unit) {
16628            if (!this.valid) {
16629                return;
16630            }
16631            if (typeof unit === 'number') {
16632                if (Texture.activeUnit !== unit) {
16633                    this.gl.activeTexture(this.gl.TEXTURE0 + unit);
16634                    Texture.activeUnit = unit;
16635                }
16636            }
16637            if (Texture.activeTexture !== this.texture) {
16638                this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
16639                Texture.activeTexture = this.texture;
16640            }
16641        }
16642    }, {
16643        key: 'load',
16644        value: function load() {
16645            var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16646
16647            this.loading = null;
16648
16649            if (typeof options.url === 'string') {
16650                if (this.url === undefined || options.url !== this.url) {
16651                    this.setUrl(options.url, options);
16652                }
16653            } else if (options.element) {
16654                this.setElement(options.element, options);
16655            } else if (options.data && options.width && options.height) {
16656                this.setData(options.width, options.height, options.data, options);
16657            }
16658        }
16659
16660        // Sets texture from an url
16661
16662    }, {
16663        key: 'setUrl',
16664        value: function setUrl(url) {
16665            var _this = this;
16666
16667            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16668
16669            if (!this.valid) {
16670                return;
16671            }
16672
16673            this.url = url; // save URL reference (will be overwritten when element is loaded below)
16674            this.source = this.url;
16675            this.sourceType = 'url';
16676
16677            this.loading = new Promise(function (resolve, reject) {
16678                var ext = url.split('.').pop().toLowerCase();
16679                var isVideo = ext === 'ogv' || ext === 'webm' || ext === 'mp4';
16680
16681                var element = undefined;
16682                if (isVideo) {
16683                    element = document.createElement('video');
16684                    element.autoplay = true;
16685
16686                    element.muted = true; /* required for modern browsers to autoplay video */
16687                    setTimeout(function () {
16688                        element.play(); /* doesn't block promise but needs a more elegant solution */
16689                    }, 1);
16690
16691                    options.filtering = 'nearest';
16692                    // element.preload = 'auto';
16693                    // element.style.display = 'none';
16694                    // document.body.appendChild(element);
16695                } else {
16696                    element = new Image();
16697                }
16698
16699                element.onload = function () {
16700                    try {
16701                        _this.setElement(element, options);
16702                    } catch (e) {
16703                        console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options);
16704                    }
16705                    resolve(_this);
16706                };
16707                element.onerror = function (e) {
16708                    // Warn and resolve on error
16709                    console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options);
16710                    resolve(_this);
16711                };
16712
16713                // Safari has a bug loading data-URL elements with CORS enabled, so it must be disabled in that case
16714                // https://bugs.webkit.org/show_bug.cgi?id=123978
16715                if (!(isSafari() && _this.source.slice(0, 5) === 'data:')) {
16716                    element.crossOrigin = 'anonymous';
16717                }
16718
16719                element.src = _this.source;
16720                if (isVideo) {
16721                    _this.setElement(element, options);
16722                }
16723            });
16724            return this.loading;
16725        }
16726
16727        // Sets texture to a raw image buffer
16728
16729    }, {
16730        key: 'setData',
16731        value: function setData(width, height, data) {
16732            var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
16733
16734            this.width = width;
16735            this.height = height;
16736
16737            this.source = data;
16738            this.sourceType = 'data';
16739
16740            this.update(options);
16741            this.setFiltering(options);
16742
16743            this.loading = Promise.resolve(this);
16744            return this.loading;
16745        }
16746
16747        // Sets the texture to track a element (canvas/image)
16748
16749    }, {
16750        key: 'setElement',
16751        value: function setElement(element, options) {
16752            var _this2 = this;
16753
16754            var el = element;
16755
16756            // a string element is interpeted as a CSS selector
16757            if (typeof element === 'string') {
16758                element = document.querySelector(element);
16759            }
16760
16761            if (element instanceof HTMLCanvasElement || element instanceof HTMLImageElement || element instanceof HTMLVideoElement) {
16762                this.source = element;
16763                this.sourceType = 'element';
16764
16765                if (element instanceof HTMLVideoElement) {
16766                    this.width = this.source.videoWidth;
16767                    this.height = this.source.videoHeight;
16768                    element.addEventListener('canplaythrough', function () {
16769                        _this2.intervalID = setInterval(function () {
16770                            _this2.update(options);
16771                        }, 15);
16772                    }, true);
16773                    element.addEventListener('ended', function () {
16774                        element.currentTime = 0;
16775                        element.play();
16776                    }, true);
16777                } else {
16778                    this.update(options);
16779                }
16780                this.setFiltering(options);
16781            } else {
16782                var msg = 'the \'element\' parameter (`element: ' + JSON.stringify(el) + '`) must be a CSS ';
16783                msg += 'selector string, or a <canvas>, <image> or <video> object';
16784                console.log('Texture \'' + this.name + '\': ' + msg, options);
16785            }
16786
16787            this.loading = Promise.resolve(this);
16788            return this.loading;
16789        }
16790
16791        // Uploads current image or buffer to the GPU (can be used to update animated textures on the fly)
16792
16793    }, {
16794        key: 'update',
16795        value: function update() {
16796            var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16797
16798            if (!this.valid) {
16799                return;
16800            }
16801
16802            this.bind();
16803            this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, options.UNPACK_FLIP_Y_WEBGL === false ? false : true);
16804            this.gl.pixelStorei(this.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.UNPACK_PREMULTIPLY_ALPHA_WEBGL || false);
16805
16806            // Image or Canvas element
16807            if (this.sourceType === 'element' && (this.source instanceof HTMLCanvasElement || this.source instanceof HTMLVideoElement || this.source instanceof HTMLImageElement && this.source.complete)) {
16808                if (this.source instanceof HTMLVideoElement) {
16809                    this.width = this.source.videoWidth;
16810                    this.height = this.source.videoHeight;
16811                } else {
16812                    this.width = this.source.width;
16813                    this.height = this.source.height;
16814                }
16815                this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.source);
16816            }
16817            // Raw image buffer
16818            else if (this.sourceType === 'data') {
16819                    this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.width, this.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.source);
16820                }
16821            this.trigger('loaded', this);
16822        }
16823
16824        // Determines appropriate filtering mode
16825
16826    }, {
16827        key: 'setFiltering',
16828        value: function setFiltering() {
16829            var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16830
16831            if (!this.valid) {
16832                return;
16833            }
16834
16835            this.powerOf2 = isPowerOf2(this.width) && isPowerOf2(this.height);
16836            // let defualtFilter = (this.powerOf2 ? 'mipmap' : 'linear');
16837            // this.filtering = options.filtering || defualtFilter;
16838            this.filtering = options.filtering || 'linear';
16839
16840            var gl = this.gl;
16841            this.bind();
16842
16843            // For power-of-2 textures, the following presets are available:
16844            // mipmap: linear blend from nearest mip
16845            // linear: linear blend from original image (no mips)
16846            // nearest: nearest pixel from original image (no mips, 'blocky' look)
16847            if (this.powerOf2) {
16848                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, options.TEXTURE_WRAP_S || gl.REPEAT);
16849                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, options.TEXTURE_WRAP_T || gl.REPEAT);
16850
16851                if (this.filtering === 'mipmap') {
16852                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); // TODO: use trilinear filtering by defualt instead?
16853                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
16854                    gl.generateMipmap(gl.TEXTURE_2D);
16855                } else if (this.filtering === 'linear') {
16856                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
16857                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
16858                } else if (this.filtering === 'nearest') {
16859                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
16860                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
16861                }
16862            } else {
16863                // WebGL has strict requirements on non-power-of-2 textures:
16864                // No mipmaps and must clamp to edge
16865                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
16866                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
16867
16868                if (this.filtering === 'mipmap') {
16869                    this.filtering = 'linear';
16870                }
16871
16872                if (this.filtering === 'nearest') {
16873                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
16874                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
16875                } else {
16876                    // default to linear for non-power-of-2 textures
16877                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
16878                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
16879                }
16880            }
16881        }
16882    }]);
16883    return Texture;
16884}();
16885
16886Texture.getMaxTextureSize = function (gl) {
16887    return gl.getParameter(gl.MAX_TEXTURE_SIZE);
16888};
16889
16890// Global set of textures, by name
16891Texture.activeUnit = -1;
16892
16893/*
16894The MIT License (MIT)
16895
16896Copyright (c) 2015 Patricio Gonzalez Vivo ( http://www.patriciogonzalezvivo.com )
16897
16898Permission is hereby granted, free of charge, to any person obtaining a copy of
16899this software and associated documentation files (the 'Software'), to deal in
16900the Software without restriction, including without limitation the rights to
16901use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
16902the Software, and to permit persons to whom the Software is furnished to do so,
16903subject to the following conditions:
16904
16905The above copyright notice and this permission notice shall be included in all
16906copies or substantial portions of the Software.
16907
16908THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16909IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16910FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16911COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16912IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16913CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16914*/
16915
16916var GlslCanvas = function () {
16917    function GlslCanvas(canvas, contextOptions, options) {
16918        var _this = this;
16919
16920        classCallCheck(this, GlslCanvas);
16921
16922        subscribeMixin$1(this);
16923
16924        contextOptions = contextOptions || {};
16925        options = options || {};
16926
16927        if (canvas.hasAttribute('data-fullscreen') && (canvas.getAttribute('data-fullscreen') == "1" || canvas.getAttribute('data-fullscreen') == "true")) {
16928            this.width = window.innerWidth;
16929            this.height = window.innerHeight;
16930            canvas.width = window.innerWidth;
16931            canvas.height = window.innerHeight;
16932        } else {
16933            this.width = canvas.clientWidth;
16934            this.height = canvas.clientHeight;
16935        }
16936
16937        this.canvas = canvas;
16938        this.gl = undefined;
16939        this.deps = {};
16940        this.program = undefined;
16941        this.textures = {};
16942        this.buffers = {};
16943        this.uniforms = {};
16944        this.vbo = {};
16945        this.isValid = false;
16946        this.animationFrameRequest = undefined;
16947
16948        this.BUFFER_COUNT = 0;
16949        // this.TEXTURE_COUNT = 0;
16950
16951        this.vertexString = contextOptions.vertexString || '\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nattribute vec2 a_position;\nattribute vec2 a_texcoord;\n\nvarying vec2 v_texcoord;\n\nvoid main() {\n    gl_Position = vec4(a_position, 0.0, 1.0);\n    v_texcoord = a_texcoord;\n}\n';
16952        this.fragmentString = contextOptions.fragmentString || '\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec2 v_texcoord;\n\nvoid main(){\n    gl_FragColor = vec4(0.0);\n}\n';
16953
16954        // GL Context
16955        var gl = setupWebGL(canvas, contextOptions, options.onError);
16956        if (!gl) {
16957            return;
16958        }
16959        this.gl = gl;
16960        this.timeLoad = this.timePrev = performance.now();
16961        this.timeDelta = 0.0;
16962        this.forceRender = true;
16963        this.paused = false;
16964        this.realToCSSPixels = window.devicePixelRatio || 1;
16965
16966        // Allow alpha
16967        canvas.style.backgroundColor = contextOptions.backgroundColor || 'rgba(1,1,1,0)';
16968
16969        // Load shader
16970        if (canvas.hasAttribute('data-fragment')) {
16971            this.fragmentString = canvas.getAttribute('data-fragment');
16972        } else if (canvas.hasAttribute('data-fragment-url')) {
16973            var source = canvas.getAttribute('data-fragment-url');
16974            xhr.get(source, function (error, response, body) {
16975                _this.load(body, _this.vertexString);
16976            });
16977        }
16978
16979        // Load shader
16980        if (canvas.hasAttribute('data-vertex')) {
16981            this.vertexString = canvas.getAttribute('data-vertex');
16982        } else if (canvas.hasAttribute('data-vertex-url')) {
16983            var _source = canvas.getAttribute('data-vertex-url');
16984            xhr.get(_source, function (error, response, body) {
16985                _this.load(_this.fragmentString, body);
16986            });
16987        }
16988
16989        this.load();
16990
16991        if (!this.program) {
16992            return;
16993        }
16994
16995        // Define Vertex buffer
16996        var texCoordsLoc = gl.getAttribLocation(this.program, 'a_texcoord');
16997        this.vbo.texCoords = gl.createBuffer();
16998        this.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo.texCoords);
16999        this.gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW);
17000        this.gl.enableVertexAttribArray(texCoordsLoc);
17001        this.gl.vertexAttribPointer(texCoordsLoc, 2, gl.FLOAT, false, 0, 0);
17002
17003        var verticesLoc = gl.getAttribLocation(this.program, 'a_position');
17004        this.vbo.vertices = gl.createBuffer();
17005        this.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo.vertices);
17006        this.gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]), gl.STATIC_DRAW);
17007        this.gl.enableVertexAttribArray(verticesLoc);
17008        this.gl.vertexAttribPointer(verticesLoc, 2, gl.FLOAT, false, 0, 0);
17009
17010        // load TEXTURES
17011        if (canvas.hasAttribute('data-textures')) {
17012            var imgList = canvas.getAttribute('data-textures').split(',');
17013            for (var nImg in imgList) {
17014                this.setUniform('u_tex' + nImg, imgList[nImg]);
17015            }
17016        }
17017
17018        // ========================== EVENTS
17019        var mouse = {
17020            x: 0,
17021            y: 0
17022        };
17023        document.addEventListener('mousemove', function (e) {
17024            mouse.x = e.clientX || e.pageX;
17025            mouse.y = e.clientY || e.pageY;
17026        }, false);
17027
17028        var sandbox = this;
17029        function RenderLoop() {
17030            if (sandbox.nMouse > 1) {
17031                sandbox.setMouse(mouse);
17032            }
17033
17034            if (sandbox.resize()) {
17035                sandbox.forceRender = true;
17036            }
17037
17038            sandbox.render();
17039            sandbox.animationFrameRequest = window.requestAnimationFrame(RenderLoop);
17040        }
17041
17042        // Start
17043        this.setMouse({ x: 0, y: 0 });
17044        RenderLoop();
17045        return this;
17046    }
17047
17048    createClass(GlslCanvas, [{
17049        key: 'destroy',
17050        value: function destroy() {
17051            // Stop the animation
17052            cancelAnimationFrame(this.animationFrameRequest);
17053
17054            this.animated = false;
17055            this.isValid = false;
17056            for (var tex in this.textures) {
17057                if (tex.destroy) {
17058                    tex.destroy();
17059                }
17060            }
17061            this.textures = {};
17062            for (var att in this.attribs) {
17063                this.gl.deleteBuffer(this.attribs[att]);
17064            }
17065            this.gl.useProgram(null);
17066            this.gl.deleteProgram(this.program);
17067            for (var key in this.buffers) {
17068                var buffer = this.buffers[key];
17069                this.gl.deleteProgram(buffer.program);
17070            }
17071
17072            this.program = null;
17073            this.gl = null;
17074        }
17075    }, {
17076        key: 'load',
17077        value: function load(fragString, vertString) {
17078            var _this2 = this;
17079
17080            // Load vertex shader if there is one
17081            if (vertString) {
17082                this.vertexString = vertString;
17083            }
17084
17085            // Load fragment shader if there is one
17086            if (fragString) {
17087                this.fragmentString = fragString;
17088            }
17089
17090            var lines = this.fragmentString.split(/\r?\n/);
17091            this.fragmentString = "#define PLATFORM_WEBGL\n#line 0\n";
17092
17093            lines.forEach(function (line, i) {
17094                var line_trim = line.trim();
17095                if (line_trim.startsWith('#include \"lygia')) {
17096                    var dep = line_trim.substring(15).replace(/\'|\"|\;|\s/g, '');
17097                    if (dep.endsWith('glsl')) {
17098                        if (_this2.deps[dep] === undefined) {
17099                            var url = "https://lygia.xyz" + dep;
17100                            _this2.deps[dep] = getFile(url);
17101                        }
17102                        _this2.fragmentString += _this2.deps[dep] + '\n#line ' + (i + 1) + '\n';
17103                    }
17104                } else _this2.fragmentString += line + '\n';
17105            });
17106
17107            // console.log(this.fragmentString);
17108
17109            this.animated = false;
17110            this.nDelta = (this.fragmentString.match(/u_delta/g) || []).length;
17111            this.nTime = (this.fragmentString.match(/u_time/g) || []).length;
17112            this.nDate = (this.fragmentString.match(/u_date/g) || []).length;
17113            this.nMouse = (this.fragmentString.match(/u_mouse/g) || []).length;
17114            this.animated = this.nDate > 1 || this.nTime > 1 || this.nMouse > 1;
17115
17116            var nTextures = this.fragmentString.search(/sampler2D/g);
17117            if (nTextures) {
17118                var _lines = this.fragmentString.split('\n');
17119                for (var i = 0; i < _lines.length; i++) {
17120                    var match = _lines[i].match(/uniform\s*sampler2D\s*([\w]*);\s*\/\/\s*([\w|\:\/\/|\.|\-|\_]*)/i);
17121                    if (match) {
17122                        var ext = match[2].split('.').pop().toLowerCase();
17123                        if (match[1] && match[2] && (ext === 'jpg' || ext === 'jpeg' || ext === 'png' || ext === 'ogv' || ext === 'webm' || ext === 'mp4')) {
17124                            this.setUniform(match[1], match[2]);
17125                        }
17126                    }
17127                    var main = _lines[i].match(/\s*void\s*main\s*/g);
17128                    if (main) {
17129                        break;
17130                    }
17131                }
17132            }
17133
17134            var vertexShader = createShader(this, this.vertexString, this.gl.VERTEX_SHADER);
17135            var fragmentShader = createShader(this, this.fragmentString, this.gl.FRAGMENT_SHADER);
17136
17137            // If Fragment shader fails load a empty one to sign the error
17138            if (!fragmentShader) {
17139                fragmentShader = createShader(this, 'void main(){\n\tgl_FragColor = vec4(1.0);\n}', this.gl.FRAGMENT_SHADER);
17140                this.isValid = false;
17141            } else {
17142                this.isValid = true;
17143            }
17144
17145            // Create and use program
17146            var program = createProgram(this, [vertexShader, fragmentShader]); //, [0,1],['a_texcoord','a_position']);
17147            this.gl.useProgram(program);
17148
17149            // Delete shaders
17150            // this.gl.detachShader(program, vertexShader);
17151            // this.gl.detachShader(program, fragmentShader);
17152            this.gl.deleteShader(vertexShader);
17153            this.gl.deleteShader(fragmentShader);
17154
17155            this.program = program;
17156            this.change = true;
17157
17158            this.BUFFER_COUNT = 0;
17159            var buffers = this.getBuffers(this.fragmentString);
17160            if (Object.keys(buffers).length) {
17161                this.loadPrograms(buffers);
17162            }
17163            this.buffers = buffers;
17164            this.texureIndex = this.BUFFER_COUNT;
17165
17166            // Trigger event
17167            this.trigger('load', {});
17168
17169            this.forceRender = true;
17170            this.render();
17171        }
17172    }, {
17173        key: 'test',
17174        value: function test(callback, fragString, vertString) {
17175            // Thanks to @thespite for the help here
17176            // https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query/
17177            var pre_test_vert = this.vertexString;
17178            var pre_test_frag = this.fragmentString;
17179            var pre_test_paused = this.paused;
17180
17181            var ext = this.gl.getExtension('EXT_disjoint_timer_query');
17182            var query = ext.createQueryEXT();
17183            var wasValid = this.isValid;
17184
17185            if (fragString || vertString) {
17186                this.load(fragString, vertString);
17187                wasValid = this.isValid;
17188                this.forceRender = true;
17189                this.render();
17190            }
17191
17192            this.paused = true;
17193            ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
17194            this.forceRender = true;
17195            this.render();
17196            ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
17197
17198            var sandbox = this;
17199            function finishTest() {
17200                // Revert changes... go back to normal
17201                sandbox.paused = pre_test_paused;
17202                if (fragString || vertString) {
17203                    sandbox.load(pre_test_frag, pre_test_vert);
17204                }
17205            }
17206            function waitForTest() {
17207                sandbox.forceRender = true;
17208                sandbox.render();
17209                var available = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
17210                var disjoint = sandbox.gl.getParameter(ext.GPU_DISJOINT_EXT);
17211                if (available && !disjoint) {
17212                    var ret = {
17213                        wasValid: wasValid,
17214                        frag: fragString || sandbox.fragmentString,
17215                        vert: vertString || sandbox.vertexString,
17216                        timeElapsedMs: ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT) / 1000000.0
17217                    };
17218                    finishTest();
17219                    callback(ret);
17220                } else {
17221                    window.requestAnimationFrame(waitForTest);
17222                }
17223            }
17224            waitForTest();
17225        }
17226    }, {
17227        key: 'loadTexture',
17228        value: function loadTexture(name, urlElementOrData, options) {
17229            var _this3 = this;
17230
17231            if (!options) {
17232                options = {};
17233            }
17234
17235            if (typeof urlElementOrData === 'string') {
17236                options.url = urlElementOrData;
17237            } else if ((typeof urlElementOrData === 'undefined' ? 'undefined' : _typeof(urlElementOrData)) === 'object' && urlElementOrData.data && urlElementOrData.width && urlElementOrData.height) {
17238                options.data = urlElementOrData.data;
17239                options.width = urlElementOrData.width;
17240                options.height = urlElementOrData.height;
17241            } else if ((typeof urlElementOrData === 'undefined' ? 'undefined' : _typeof(urlElementOrData)) === 'object') {
17242                options.element = urlElementOrData;
17243            }
17244
17245            if (this.textures[name]) {
17246                if (this.textures[name]) {
17247                    this.textures[name].load(options);
17248                    this.textures[name].on('loaded', function (args) {
17249                        _this3.forceRender = true;
17250                    });
17251                }
17252            } else {
17253                this.textures[name] = new Texture(this.gl, name, options);
17254                this.textures[name].on('loaded', function (args) {
17255                    _this3.forceRender = true;
17256                });
17257            }
17258        }
17259    }, {
17260        key: 'refreshUniforms',
17261        value: function refreshUniforms() {
17262            this.uniforms = {};
17263        }
17264    }, {
17265        key: 'setUniform',
17266        value: function setUniform(name) {
17267            var u = {};
17268
17269            for (var _len = arguments.length, value = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
17270                value[_key - 1] = arguments[_key];
17271            }
17272
17273            u[name] = value;
17274            this.setUniforms(u);
17275        }
17276    }, {
17277        key: 'setUniforms',
17278        value: function setUniforms(uniforms) {
17279            var parsed = parseUniforms(uniforms);
17280            // Set each uniform
17281            for (var u in parsed) {
17282                if (parsed[u].type === 'sampler2D') {
17283                    // For textures, we need to track texture units, so we have a special setter
17284                    // this.uniformTexture(parsed[u].name, parsed[u].value[0]);
17285                    this.loadTexture(parsed[u].name, parsed[u].value[0]);
17286                } else {
17287                    this.uniform(parsed[u].method, parsed[u].type, parsed[u].name, parsed[u].value);
17288                }
17289            }
17290            this.forceRender = true;
17291        }
17292    }, {
17293        key: 'setMouse',
17294        value: function setMouse(mouse) {
17295            // set the mouse uniform
17296            var rect = this.canvas.getBoundingClientRect();
17297            if (mouse && mouse.x && mouse.x >= rect.left && mouse.x <= rect.right && mouse.y && mouse.y >= rect.top && mouse.y <= rect.bottom) {
17298
17299                var mouse_x = (mouse.x - rect.left) * this.realToCSSPixels;
17300                var mouse_y = this.canvas.height - (mouse.y - rect.top) * this.realToCSSPixels;
17301
17302                this.uniform('2f', 'vec2', 'u_mouse', mouse_x, mouse_y);
17303            }
17304        }
17305
17306        // ex: program.uniform('3f', 'position', x, y, z);
17307
17308    }, {
17309        key: 'uniform',
17310        value: function uniform(method, type, name) {
17311            // 'value' is a method-appropriate arguments list
17312            this.uniforms[name] = this.uniforms[name] || {};
17313            var uniform = this.uniforms[name];
17314
17315            for (var _len2 = arguments.length, value = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
17316                value[_key2 - 3] = arguments[_key2];
17317            }
17318
17319            var change = isDiff(uniform.value, value);
17320
17321            // remember and keep track of uniforms location to save calls
17322            if (change || this.change || !uniform.location || !uniform.value) {
17323                uniform.name = name;
17324                uniform.type = type;
17325                uniform.value = value;
17326                uniform.method = 'uniform' + method;
17327                this.gl.useProgram(this.program);
17328                uniform.location = this.gl.getUniformLocation(this.program, name);
17329                this.gl[uniform.method].apply(this.gl, [uniform.location].concat(uniform.value));
17330                // If there is change update and there is buffer update manually one by one
17331                for (var key in this.buffers) {
17332                    var buffer = this.buffers[key];
17333                    this.gl.useProgram(buffer.program);
17334                    var location = this.gl.getUniformLocation(buffer.program, name);
17335                    this.gl[uniform.method].apply(this.gl, [location].concat(uniform.value));
17336                }
17337            }
17338        }
17339    }, {
17340        key: 'uniformTexture',
17341        value: function uniformTexture(name, texture, options) {
17342            if (this.textures[name] === undefined) {
17343                this.loadTexture(name, texture, options);
17344            } else {
17345                this.uniform('1i', 'sampler2D', name, this.texureIndex);
17346
17347                for (var key in this.buffers) {
17348                    var buffer = this.buffers[key];
17349                    this.gl.useProgram(buffer.program);
17350                    this.gl.activeTexture(this.gl.TEXTURE0 + this.texureIndex);
17351                    this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[name].texture);
17352                }
17353                this.gl.useProgram(this.program);
17354                this.gl.activeTexture(this.gl.TEXTURE0 + this.texureIndex);
17355                this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[name].texture);
17356                this.uniform('2f', 'vec2', name + 'Resolution', this.textures[name].width, this.textures[name].height);
17357            }
17358        }
17359    }, {
17360        key: 'resize',
17361        value: function resize() {
17362            if (this.width !== this.canvas.clientWidth || this.height !== this.canvas.clientHeight) {
17363                this.realToCSSPixels = window.devicePixelRatio || 1;
17364
17365                // Lookup the size the browser is displaying the canvas in CSS pixels
17366                // and compute a size needed to make our drawingbuffer match it in
17367                // device pixels.
17368                var displayWidth = Math.floor(this.gl.canvas.clientWidth * this.realToCSSPixels);
17369                var displayHeight = Math.floor(this.gl.canvas.clientHeight * this.realToCSSPixels);
17370
17371                // Check if the canvas is not the same size.
17372                if (this.gl.canvas.width !== displayWidth || this.gl.canvas.height !== displayHeight) {
17373                    // Make the canvas the same size
17374                    this.gl.canvas.width = displayWidth;
17375                    this.gl.canvas.height = displayHeight;
17376                    // Set the viewport to match
17377                    this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
17378                }
17379                this.width = this.canvas.clientWidth;
17380                this.height = this.canvas.clientHeight;
17381                this.resizeSwappableBuffers();
17382                return true;
17383            } else {
17384                return false;
17385            }
17386        }
17387    }, {
17388        key: 'render',
17389        value: function render() {
17390            this.visible = isCanvasVisible(this.canvas);
17391            if (this.forceRender || this.change || this.animated && this.visible && !this.paused) {
17392
17393                // Update Uniforms when are need
17394                var date = new Date();
17395                var now = performance.now();
17396                this.timeDelta = (now - this.timePrev) / 1000.0;
17397                this.timePrev = now;
17398                if (this.nDelta > 1) {
17399                    // set the delta time uniform
17400                    this.uniform('1f', 'float', 'u_delta', this.timeDelta);
17401                }
17402
17403                if (this.nTime > 1) {
17404                    // set the elapsed time uniform
17405                    this.uniform('1f', 'float', 'u_time', (now - this.timeLoad) / 1000.0);
17406                }
17407
17408                if (this.nDate) {
17409                    // Set date uniform: year/month/day/time_in_sec
17410                    this.uniform('4f', 'float', 'u_date', date.getFullYear(), date.getMonth(), date.getDate(), date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds() + date.getMilliseconds() * 0.001);
17411                }
17412
17413                // set the resolution uniform
17414                this.uniform('2f', 'vec2', 'u_resolution', this.canvas.width, this.canvas.height);
17415
17416                for (var key in this.buffers) {
17417                    var buffer = this.buffers[key];
17418                    this.uniform('1i', 'sampler2D', buffer.name, buffer.bundle.input.index);
17419                }
17420
17421                this.texureIndex = this.BUFFER_COUNT;
17422                for (var tex in this.textures) {
17423                    this.uniformTexture(tex);
17424                    this.texureIndex++;
17425                }
17426
17427                this.renderPrograms();
17428
17429                // Trigger event
17430                this.trigger('render', {});
17431                this.change = false;
17432                this.forceRender = false;
17433            }
17434        }
17435    }, {
17436        key: 'pause',
17437        value: function pause() {
17438            this.paused = true;
17439        }
17440    }, {
17441        key: 'play',
17442        value: function play() {
17443            this.paused = false;
17444        }
17445
17446        // render main and buffers programs
17447
17448    }, {
17449        key: 'renderPrograms',
17450        value: function renderPrograms() {
17451            var gl = this.gl;
17452            var W = gl.canvas.width;
17453            var H = gl.canvas.height;
17454
17455            gl.viewport(0, 0, W, H);
17456
17457            for (var key in this.buffers) {
17458                var buffer = this.buffers[key];
17459                buffer.bundle.render(W, H, buffer.program, buffer.name);
17460                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
17461            }
17462
17463            gl.useProgram(this.program);
17464            gl.drawArrays(gl.TRIANGLES, 0, 6);
17465        }
17466
17467        // parse input strings
17468
17469    }, {
17470        key: 'getBuffers',
17471        value: function getBuffers(fragString) {
17472            var buffers = {};
17473            if (fragString) {
17474                fragString.replace(/(?:^\s*)((?:#if|#elif)(?:\s*)(defined\s*\(\s*BUFFER_)(\d+)(?:\s*\))|(?:#ifdef)(?:\s*BUFFER_)(\d+)(?:\s*))/gm, function () {
17475                    var i = arguments[3] || arguments[4];
17476                    buffers['u_buffer' + i] = {
17477                        fragment: '#define BUFFER_' + i + '\n' + fragString
17478                    };
17479                });
17480            }
17481            return buffers;
17482        }
17483
17484        // load buffers programs
17485
17486    }, {
17487        key: 'loadPrograms',
17488        value: function loadPrograms(buffers) {
17489            var glsl = this;
17490            var gl = this.gl;
17491            var vertex = createShader(glsl, glsl.vertexString, gl.VERTEX_SHADER);
17492            for (var key in buffers) {
17493                var buffer = buffers[key];
17494                var fragment = createShader(glsl, buffer.fragment, gl.FRAGMENT_SHADER, 1);
17495                if (!fragment) {
17496                    fragment = createShader(glsl, 'void main(){\n\tgl_FragColor = vec4(1.0);\n}', gl.FRAGMENT_SHADER);
17497                    glsl.isValid = false;
17498                } else {
17499                    glsl.isValid = true;
17500                }
17501                var program = createProgram(glsl, [vertex, fragment]);
17502                buffer.name = key;
17503                buffer.program = program;
17504                buffer.bundle = glsl.createSwappableBuffer(glsl.canvas.width, glsl.canvas.height, program);
17505                gl.deleteShader(fragment);
17506            }
17507            gl.deleteShader(vertex);
17508        }
17509
17510        // create an input / output swappable buffer
17511
17512    }, {
17513        key: 'createSwappableBuffer',
17514        value: function createSwappableBuffer(W, H, program) {
17515            var input = this.createBuffer(W, H, program);
17516            var output = this.createBuffer(W, H, program);
17517            var gl = this.gl;
17518            return {
17519                input: input,
17520                output: output,
17521                swap: function swap() {
17522                    var temp = input;
17523                    input = output;
17524                    output = temp;
17525                    this.input = input;
17526                    this.output = output;
17527                },
17528                render: function render(W, H, program, name) {
17529                    gl.useProgram(program);
17530                    gl.viewport(0, 0, W, H);
17531                    gl.bindFramebuffer(gl.FRAMEBUFFER, this.input.buffer);
17532                    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.output.texture, 0);
17533                    gl.drawArrays(gl.TRIANGLES, 0, 6);
17534                    this.swap();
17535                },
17536                resize: function resize(W, H, program, name) {
17537                    gl.useProgram(program);
17538                    gl.viewport(0, 0, W, H);
17539                    this.input.resize(W, H);
17540                    this.output.resize(W, H);
17541                }
17542            };
17543        }
17544
17545        // create a buffers
17546
17547    }, {
17548        key: 'createBuffer',
17549        value: function createBuffer(W, H, program) {
17550            var gl = this.gl;
17551            var index = this.BUFFER_COUNT;
17552            this.BUFFER_COUNT += 2;
17553            gl.getExtension('OES_texture_float');
17554            var texture = gl.createTexture();
17555            gl.activeTexture(gl.TEXTURE0 + index);
17556            gl.bindTexture(gl.TEXTURE_2D, texture);
17557            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, W, H, 0, gl.RGBA, gl.FLOAT, null);
17558            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
17559            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
17560            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
17561            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
17562            var buffer = gl.createFramebuffer();
17563            return {
17564                index: index,
17565                texture: texture,
17566                buffer: buffer,
17567                W: W,
17568                H: H,
17569                resize: function resize(W, H) {
17570                    gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
17571                    var minW = Math.min(W, this.W);
17572                    var minH = Math.min(H, this.H);
17573                    var pixels = new Float32Array(minW * minH * 4);
17574                    gl.readPixels(0, 0, minW, minH, gl.RGBA, gl.FLOAT, pixels);
17575                    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
17576                    var newIndex = index + 1;
17577                    var newTexture = gl.createTexture();
17578                    gl.activeTexture(gl.TEXTURE0 + newIndex);
17579                    gl.bindTexture(gl.TEXTURE_2D, newTexture);
17580                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, W, H, 0, gl.RGBA, gl.FLOAT, null);
17581                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
17582                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
17583                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
17584                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
17585                    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, minW, minH, gl.RGBA, gl.FLOAT, pixels);
17586                    var newBuffer = gl.createFramebuffer();
17587                    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
17588                    gl.deleteTexture(texture);
17589                    gl.activeTexture(gl.TEXTURE0 + index);
17590                    gl.bindTexture(gl.TEXTURE_2D, newTexture);
17591                    index = this.index = index;
17592                    texture = this.texture = newTexture;
17593                    buffer = this.buffer = newBuffer;
17594                    this.W = W;
17595                    this.H = H;
17596                }
17597            };
17598        }
17599
17600        // resize buffers on canvas resize
17601        // consider applying a throttle of 50 ms on canvas resize
17602        // to avoid requestAnimationFrame and Gl violations
17603
17604    }, {
17605        key: 'resizeSwappableBuffers',
17606        value: function resizeSwappableBuffers() {
17607            var gl = this.gl;
17608            var W = gl.canvas.width,
17609                H = gl.canvas.height;
17610            gl.viewport(0, 0, W, H);
17611            for (var key in this.buffers) {
17612                var buffer = this.buffers[key];
17613                buffer.bundle.resize(W, H, buffer.program, buffer.name);
17614            }
17615            gl.useProgram(this.program);
17616        }
17617    }, {
17618        key: 'version',
17619        value: function version() {
17620            return '0.1.7';
17621        }
17622    }]);
17623    return GlslCanvas;
17624}();
17625
17626function loadAllGlslCanvas() {
17627    var list = document.getElementsByClassName('glslCanvas');
17628    if (list.length > 0) {
17629        window.glslCanvases = [];
17630        for (var i = 0; i < list.length; i++) {
17631            var sandbox = new GlslCanvas(list[i]);
17632            if (sandbox.isValid) {
17633                window.glslCanvases.push(sandbox);
17634            }
17635        }
17636    }
17637}
17638
17639window.addEventListener('load', function () {
17640    loadAllGlslCanvas();
17641});
17642
17643return GlslCanvas;
17644
17645})));
17646
17647}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
17648
17649},{}],110:[function(_dereq_,module,exports){
17650module.exports = isFunction
17651
17652var toString = Object.prototype.toString
17653
17654function isFunction (fn) {
17655  if (!fn) {
17656    return false
17657  }
17658  var string = toString.call(fn)
17659  return string === '[object Function]' ||
17660    (typeof fn === 'function' && string !== '[object RegExp]') ||
17661    (typeof window !== 'undefined' &&
17662     // IE8 and below
17663     (fn === window.setTimeout ||
17664      fn === window.alert ||
17665      fn === window.confirm ||
17666      fn === window.prompt))
17667};
17668
17669},{}],111:[function(_dereq_,module,exports){
17670var trim = function(string) {
17671  return string.replace(/^\s+|\s+$/g, '');
17672}
17673  , isArray = function(arg) {
17674      return Object.prototype.toString.call(arg) === '[object Array]';
17675    }
17676
17677module.exports = function (headers) {
17678  if (!headers)
17679    return {}
17680
17681  var result = {}
17682
17683  var headersArr = trim(headers).split('\n')
17684
17685  for (var i = 0; i < headersArr.length; i++) {
17686    var row = headersArr[i]
17687    var index = row.indexOf(':')
17688    , key = trim(row.slice(0, index)).toLowerCase()
17689    , value = trim(row.slice(index + 1))
17690
17691    if (typeof(result[key]) === 'undefined') {
17692      result[key] = value
17693    } else if (isArray(result[key])) {
17694      result[key].push(value)
17695    } else {
17696      result[key] = [ result[key], value ]
17697    }
17698  }
17699
17700  return result
17701}
17702
17703},{}],112:[function(_dereq_,module,exports){
17704"use strict";
17705var window = _dereq_("global/window")
17706var isFunction = _dereq_("is-function")
17707var parseHeaders = _dereq_("parse-headers")
17708var xtend = _dereq_("xtend")
17709
17710module.exports = createXHR
17711// Allow use of default import syntax in TypeScript
17712module.exports.default = createXHR;
17713createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
17714createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
17715
17716forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
17717    createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
17718        options = initParams(uri, options, callback)
17719        options.method = method.toUpperCase()
17720        return _createXHR(options)
17721    }
17722})
17723
17724function forEachArray(array, iterator) {
17725    for (var i = 0; i < array.length; i++) {
17726        iterator(array[i])
17727    }
17728}
17729
17730function isEmpty(obj){
17731    for(var i in obj){
17732        if(obj.hasOwnProperty(i)) return false
17733    }
17734    return true
17735}
17736
17737function initParams(uri, options, callback) {
17738    var params = uri
17739
17740    if (isFunction(options)) {
17741        callback = options
17742        if (typeof uri === "string") {
17743            params = {uri:uri}
17744        }
17745    } else {
17746        params = xtend(options, {uri: uri})
17747    }
17748
17749    params.callback = callback
17750    return params
17751}
17752
17753function createXHR(uri, options, callback) {
17754    options = initParams(uri, options, callback)
17755    return _createXHR(options)
17756}
17757
17758function _createXHR(options) {
17759    if(typeof options.callback === "undefined"){
17760        throw new Error("callback argument missing")
17761    }
17762
17763    var called = false
17764    var callback = function cbOnce(err, response, body){
17765        if(!called){
17766            called = true
17767            options.callback(err, response, body)
17768        }
17769    }
17770
17771    function readystatechange() {
17772        if (xhr.readyState === 4) {
17773            setTimeout(loadFunc, 0)
17774        }
17775    }
17776
17777    function getBody() {
17778        // Chrome with requestType=blob throws errors arround when even testing access to responseText
17779        var body = undefined
17780
17781        if (xhr.response) {
17782            body = xhr.response
17783        } else {
17784            body = xhr.responseText || getXml(xhr)
17785        }
17786
17787        if (isJson) {
17788            try {
17789                body = JSON.parse(body)
17790            } catch (e) {}
17791        }
17792
17793        return body
17794    }
17795
17796    function errorFunc(evt) {
17797        clearTimeout(timeoutTimer)
17798        if(!(evt instanceof Error)){
17799            evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
17800        }
17801        evt.statusCode = 0
17802        return callback(evt, failureResponse)
17803    }
17804
17805    // will load the data & process the response in a special response object
17806    function loadFunc() {
17807        if (aborted) return
17808        var status
17809        clearTimeout(timeoutTimer)
17810        if(options.useXDR && xhr.status===undefined) {
17811            //IE8 CORS GET successful response doesn't have a status field, but body is fine
17812            status = 200
17813        } else {
17814            status = (xhr.status === 1223 ? 204 : xhr.status)
17815        }
17816        var response = failureResponse
17817        var err = null
17818
17819        if (status !== 0){
17820            response = {
17821                body: getBody(),
17822                statusCode: status,
17823                method: method,
17824                headers: {},
vendor: 4,146 bytes, lines 17825-17952
17825                url: uri,
17826                rawRequest: xhr
17827            }
17828            if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
17829                response.headers = parseHeaders(xhr.getAllResponseHeaders())
17830            }
17831        } else {
17832            err = new Error("Internal XMLHttpRequest Error")
17833        }
17834        return callback(err, response, response.body)
17835    }
17836
17837    var xhr = options.xhr || null
17838
17839    if (!xhr) {
17840        if (options.cors || options.useXDR) {
17841            xhr = new createXHR.XDomainRequest()
17842        }else{
17843            xhr = new createXHR.XMLHttpRequest()
17844        }
17845    }
17846
17847    var key
17848    var aborted
17849    var uri = xhr.url = options.uri || options.url
17850    var method = xhr.method = options.method || "GET"
17851    var body = options.body || options.data
17852    var headers = xhr.headers = options.headers || {}
17853    var sync = !!options.sync
17854    var isJson = false
17855    var timeoutTimer
17856    var failureResponse = {
17857        body: undefined,
17858        headers: {},
17859        statusCode: 0,
17860        method: method,
17861        url: uri,
17862        rawRequest: xhr
17863    }
17864
17865    if ("json" in options && options.json !== false) {
17866        isJson = true
17867        headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
17868        if (method !== "GET" && method !== "HEAD") {
17869            headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
17870            body = JSON.stringify(options.json === true ? body : options.json)
17871        }
17872    }
17873
17874    xhr.onreadystatechange = readystatechange
17875    xhr.onload = loadFunc
17876    xhr.onerror = errorFunc
17877    // IE9 must have onprogress be set to a unique function.
17878    xhr.onprogress = function () {
17879        // IE must die
17880    }
17881    xhr.onabort = function(){
17882        aborted = true;
17883    }
17884    xhr.ontimeout = errorFunc
17885    xhr.open(method, uri, !sync, options.username, options.password)
17886    //has to be after open
17887    if(!sync) {
17888        xhr.withCredentials = !!options.withCredentials
17889    }
17890    // Cannot set timeout with sync request
17891    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
17892    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
17893    if (!sync && options.timeout > 0 ) {
17894        timeoutTimer = setTimeout(function(){
17895            if (aborted) return
17896            aborted = true//IE9 may still call readystatechange
17897            xhr.abort("timeout")
17898            var e = new Error("XMLHttpRequest timeout")
17899            e.code = "ETIMEDOUT"
17900            errorFunc(e)
17901        }, options.timeout )
17902    }
17903
17904    if (xhr.setRequestHeader) {
17905        for(key in headers){
17906            if(headers.hasOwnProperty(key)){
17907                xhr.setRequestHeader(key, headers[key])
17908            }
17909        }
17910    } else if (options.headers && !isEmpty(options.headers)) {
17911        throw new Error("Headers cannot be set on an XDomainRequest object")
17912    }
17913
17914    if ("responseType" in options) {
17915        xhr.responseType = options.responseType
17916    }
17917
17918    if ("beforeSend" in options &&
17919        typeof options.beforeSend === "function"
17920    ) {
17921        options.beforeSend(xhr)
17922    }
17923
17924    // Microsoft Edge browser sends "undefined" when send is called with undefined value.
17925    // XMLHttpRequest spec says to pass null as body to indicate no body
17926    // See https://github.com/naugtur/xhr/issues/100.
17927    xhr.send(body || null)
17928
17929    return xhr
17930
17931
17932}
17933
17934function getXml(xhr) {
17935    // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException"
17936    // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML.
17937    try {
17938        if (xhr.responseType === "document") {
17939            return xhr.responseXML
17940        }
17941        var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
17942        if (xhr.responseType === "" && !firefoxBugTakenEffect) {
17943            return xhr.responseXML
17944        }
17945    } catch (e) {}
17946
17947    return null
17948}
17949
17950function noop() {}
17951
17952}
17952,{"global/window":108,"is-function":110,"parse-headers":111,"xtend":113}],113:[function(_dereq_,module,exports){
17953module.exports = extend
17954
17955var hasOwnProperty = Object.prototype.hasOwnProperty;
17956
17957function extend() {
17958    var target = {}
17959
17960    for (var i = 0; i < arguments.length; i++) {
17961        var source = arguments[i]
17962
17963        for (var key in source) {
17964            if (hasOwnProperty.call(source, key)) {
17965                target[key] = source[key]
17966            }
17967        }
17968    }
17969
17970    return target
17971}
17972
17973},{}],114:[function(_dereq_,module,exports){
17974"use strict";
17975
17976var _createClass = _dereq_("babel-runtime/helpers/create-class")["default"];
17977
17978var _classCallCheck = _dereq_("babel-runtime/helpers/class-call-check")["default"];
17979
17980var _Object$keys = _dereq_("babel-runtime/core-js/object/keys")["default"];
17981
17982var _Object$create = _dereq_("babel-runtime/core-js/object/create")["default"];
17983
17984var _interopRequireDefault = _dereq_("babel-runtime/helpers/interop-require-default")["default"];
17985
17986Object.defineProperty(exports, "__esModule", {
17987  value: true
17988});
17989
17990_dereq_("document-register-element");
17991
17992var _coreShader = _dereq_("./core/Shader");
17993
17994var _coreShader2 = _interopRequireDefault(_coreShader);
17995
17996var _coreEditor = _dereq_("./core/Editor");
17997
17998var _uiMenu = _dereq_("./ui/Menu");
17999
18000var _uiMenu2 = _interopRequireDefault(_uiMenu);
18001
18002var _uiHelpers = _dereq_("./ui/Helpers");
18003
18004var _uiHelpers2 = _interopRequireDefault(_uiHelpers);
18005
18006var _uiErrorsDisplay = _dereq_("./ui/ErrorsDisplay");
18007
18008var _uiErrorsDisplay2 = _interopRequireDefault(_uiErrorsDisplay);
18009
18010var _uiVisualDebugger = _dereq_("./ui/VisualDebugger");
18011
18012var _uiVisualDebugger2 = _interopRequireDefault(_uiVisualDebugger);
18013
18014var _uiExportIcon = _dereq_("./ui/ExportIcon");
18015
18016var _uiExportIcon2 = _interopRequireDefault(_uiExportIcon);
18017
18018var _ioFileDrop = _dereq_("./io/FileDrop");
18019
18020var _ioFileDrop2 = _interopRequireDefault(_ioFileDrop);
18021
18022var _ioHashWatch = _dereq_("./io/HashWatch");
18023
18024var _ioHashWatch2 = _interopRequireDefault(_ioHashWatch);
18025
18026var _ioBufferManager = _dereq_("./io/BufferManager");
18027
18028var _ioBufferManager2 = _interopRequireDefault(_ioBufferManager);
18029
18030var _ioLocalStorage = _dereq_("./io/LocalStorage");
18031
18032var _ioLocalStorage2 = _interopRequireDefault(_ioLocalStorage);
18033
18034// Import Utils
18035
18036var _xhr = _dereq_("xhr");
18037
18038var _xhr2 = _interopRequireDefault(_xhr);
18039
18040var _toolsMixin = _dereq_("./tools/mixin");
18041
18042var _toolsDownload = _dereq_("./tools/download");
18043
18044var _toolsCommon = _dereq_("./tools/common");
18045
18046var _codemirror = _dereq_("codemirror");
18047
18048var _codemirror2 = _interopRequireDefault(_codemirror);
18049
18050// // Cross storage for Openframe -- allows restricted access to certain localStorage operations
18051// // on the openframe domain
18052// import { CrossStorageClient } from "cross-storage";
18053// import { getMode } from "codemirror";
18054
18055var STORAGE_LAST_EDITOR_CONTENT = "last-content";var EMPTY_FRAG_SHADER = "// Author:\n// Title:\n\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 u_resolution;\nuniform vec2 u_mouse;\nuniform float u_time;\n\nvoid main() {\n    vec2 st = gl_FragCoord.xy/u_resolution.xy;\n    st.x *= u_resolution.x/u_resolution.y;\n\n    vec3 color = vec3(0.);\n    color = vec3(st.x,st.y,abs(sin(u_time)));\n\n    gl_FragColor = vec4(color,1.0);\n}";
18056
18057var GlslEditor = (function () {
18058  function GlslEditor(selector, options) {
18059    var _this = this;
18060
18061    _classCallCheck(this, GlslEditor);
18062
18063    this.createFontLink();
18064    (0, _toolsMixin.subscribeMixin)(this);
18065
18066    if (typeof selector === "object" && selector.nodeType && selector.nodeType === 1) {
18067      this.container = selector;
18068    } else if (typeof selector === "string") {
18069      this.container = document.querySelector(selector);
18070      if (!this.container) {
18071        throw new Error("element " + selector + " not present");
18072      }
18073    } else {
18074      console.log("Error, type " + typeof selector + " of " + selector + " is unknown");
18075      return;
18076    }
18077
18078    this.options = {};
18079    this.change = false;
18080    this.autoupdate = true;
18081    this.lygia_glob = null;
18082
18083    if (options) this.options = options;
18084
18085    if (this.options.imgs === undefined) this.options.imgs = [];
18086
18087    if (this.options.display_menu === undefined) this.options.display_menu = true;
18088
18089    if (this.container.hasAttribute("data-textures")) {
18090      var imgList = this.container.getAttribute("data-textures").split(",");
18091      for (var i in imgList) {
18092        this.options.imgs.push(imgList[i]);
18093      }
18094    }
18095
18096    // Default Theme
18097    if (!this.options.theme) this.options.theme = "default";
18098
18099    // Default Context
18100    if (!this.options.frag) {
18101      var innerHTML = this.container.innerHTML.replace(/&lt;br&gt;/g, "");
18102      innerHTML = innerHTML.replace(/<br>/g, "");
18103      innerHTML = innerHTML.replace(/&nbsp;/g, "");
18104      innerHTML = innerHTML.replace(/&lt;/g, "<");
18105      innerHTML = innerHTML.replace(/&gt;/g, ">");
18106      innerHTML = innerHTML.replace(/&amp;/g, "&");
18107      this.options.frag = innerHTML || EMPTY_FRAG_SHADER;
18108
18109      if (innerHTML) this.container.innerHTML = "";
18110    }
18111
18112    // Default invisible Fragment header
18113    if (!this.options.frag_header) this.options.frag_header = "";
18114
18115    // Default invisible Fragment footer
18116    if (!this.options.frag_footer) this.options.frag_footer = "";
18117
18118    // Listen to hash changes
18119    if (this.options.watchHash) new _ioHashWatch2["default"](this);
18120
18121    // Load UI
18122    if (this.options.menu) this.menu = new _uiMenu2["default"](this);
18123
18124    // Support for multiple buffers
18125    if (this.options.multipleBuffers) this.bufferManager = new _ioBufferManager2["default"](this);
18126
18127    // Listen to file drops
18128    if (this.options.fileDrops) new _ioFileDrop2["default"](this);
18129
18130    if (this.options.indentUnit === undefined) this.options.indentUnit = 4;
18131
18132    if (this.options.tabSize === undefined) this.options.tabSize = 4;
18133
18134    if (this.options.indentWithTabs === undefined) this.options.indentWithTabs = false;
18135
18136    if (this.options.lineWrapping === undefined) this.options.lineWrapping = true;
18137
18138    if (this.options.autofocus === undefined) this.options.autofocus = true;
18139
18140    // CORE elements
18141    this.shader = new _coreShader2["default"](this);
18142    this.editor = (0, _coreEditor.initEditor)(this);
18143
18144    this.helpers = new _uiHelpers2["default"](this);
18145    this.errorsDisplay = new _uiErrorsDisplay2["default"](this);
18146    this.visualDebugger = new _uiVisualDebugger2["default"](this);
18147
18148    if (this.options.exportIcon) this["export"] = new _uiExportIcon2["default"](this);
18149
18150    // EVENTS
18151    this.editor.on("change", function () {
18152      if (_this.autoupdate) {
18153        _this.update();
18154      }
18155    });
18156
18157    if (this.options.canvas_follow) {
18158      this.shader.el.style.position = "relative";
18159
18160      if (this.options.canvas_float) this.shader.el.style.float = this.options.canvas_float;
18161
18162      this.editor.on("cursorActivity", function (cm) {
18163        var height = cm.heightAtLine(cm.getCursor().line + 1, "local") - _this.shader.el.clientHeight;
18164        if (height < 0) {
18165          height = 0.0;
18166        }
18167        _this.shader.el.style.top = height.toString() + "px";
18168      });
18169    }
18170
18171    this.editor.on('inputRead', function (cm, change) {
18172      var cur = cm.getCursor(),
18173          token = cm.getTokenAt(cur);
18174      var line = token.string.trim();
18175
18176      if (line.startsWith('#include')) {
18177        (function () {
18178          var path = line.substring(10);
18179          if (_this.lygia_glob === null) {
18180            (0, _toolsCommon.getJSON)('https://lygia.xyz/glsl.json', function (err, data) {
18181              if (err === null) {
18182                _this.lygia_glob = data;
18183              }
18184            });
18185          }
18186          console.log('autocomplete for', path);
18187
18188          var start = token.start;
18189          var end = cur.ch;
18190          var lineN = cur.line;
18191
18192          var result = [];
18193
18194          if (_this.lygia_glob !== null) {
18195            _this.lygia_glob.forEach(function (w) {
18196              if (w.startsWith(path)) result.push('#include \"' + w + '\"');
18197            });
18198            result.sort();
18199          }
18200
18201          if (result.length > 0) {
18202            _codemirror2["default"].showHint(cm, function () {
18203              var rta = {
18204                list: result,
18205                from: _codemirror2["default"].Pos(lineN, start),
18206                to: _codemirror2["default"].Pos(lineN, end)
18207              };
18208
18209              console.log(rta);
18210              return rta;
18211            }, { completeSingle: true, alignWithWord: true });
18212          }
18213        })();
18214      }
18215    });
18216
18217    // If the user bails for whatever reason, hastily shove the contents of
18218    // the editor into some kind of storage. This overwrites whatever was
18219    // there before. Note that there is not really a way of handling unload
18220    // with our own UI and logic, since this allows for widespread abuse
18221    // of normal browser functionality.
18222    window.addEventListener("beforeunload", function (event) {
18223      var content = {};
18224      if (_this.bufferManager && _Object$keys(_this.bufferManager.buffers).length !== 0) {
18225        for (var key in _this.bufferManager.buffers) {
18226          content[key] = _this.bufferManager.buffers[key].getValue();
18227        }
18228      } else {
18229        content[new Date().getTime().toString()] = _this.editor.getValue();
18230      }
18231
18232      if (_this.options.menu) {
18233        _ioLocalStorage2["default"].setItem(STORAGE_LAST_EDITOR_CONTENT, JSON.stringify(content));
18234      }
18235    });
18236
18237    if (this.options.menu) {
18238      // If there is previus content load it.
18239      var oldContent = JSON.parse(_ioLocalStorage2["default"].getItem(STORAGE_LAST_EDITOR_CONTENT));
18240      if (oldContent) {
18241        for (var key in oldContent) {
18242          this.open(oldContent[key], key);
18243        }
18244      } else {
18245        this["new"]();
18246      }
18247    } else {
18248      this["new"]();
18249    }
18250
18251    // if (this.options.menu || this.options.exportIcon) {
18252    //   // setup CrossStorage client
18253    //   this.storage = new CrossStorageClient("https://openframe.io/hub.html");
18254    //   this.storage.onConnect().then(() => {
18255    //     console.log("Connected to OpenFrame [o]");
18256    //   });
18257    //   // }).bind(this);
18258    // }
18259
18260    return this;
18261  }
18262
18263  _createClass(GlslEditor, [{
18264    key: "new",
18265    value: function _new() {
18266      this.setContent(this.options.frag || EMPTY_FRAG_SHADER, new Date().getTime().toString());
18267      this.trigger("new_content", {});
18268      this.options.frag = null;
18269    }
18270  }, {
18271    key: "setContent",
18272    value: function setContent(shader, tabName) {
18273      // If the string is CODE
18274      if (this.shader && this.shader.canvas) {
18275        if (this.debugging) {
18276          this.debugging = false;
18277          (0, _coreEditor.focusAll)(this.editor);
18278        }
18279        this.shader.canvas.load(this.options.frag_header + shader + this.options.frag_footer);
18280      }
18281
18282      if (this.editor) {
18283        if (tabName !== undefined && this.bufferManager !== undefined) {
18284          this.bufferManager.open(tabName, shader);
18285          this.bufferManager.select(tabName);
18286        } else {
18287          this.editor.setValue(shader);
18288          this.editor.setSize(null, this.editor.getDoc().height + "px");
18289          this.editor.setSize(null, "auto");
18290          this.filename = tabName;
18291        }
18292      }
18293      this.change = true;
18294    }
18295  }, {
18296    key: "open",
18297    value: function open(shader, tabName) {
18298      var _this2 = this;
18299
18300      if (typeof shader === "object") {
18301        (function () {
18302          var reader = new FileReader();
18303          var ge = _this2;
18304          reader.onload = function (e) {
18305            ge.setContent(e.target.result, shader.name);
18306          };
18307          reader.readAsText(shader);
18308        })();
18309      } else if (typeof shader === "string") {
18310        if (/\.frag$/.test(shader) || /\.fs$/.test(shader)) {
18311          // If the string is an URL
18312          _xhr2["default"].get(shader, function (error, response, body) {
18313            if (error) {
18314              console.log("Error downloading ", shader, error);
18315              return;
18316            }
18317            _this2.setContent(body, tabName);
18318          });
18319        } else {
18320          this.setContent(shader, tabName);
18321        }
18322      }
18323    }
18324  }, {
18325    key: "getContent",
18326    value: function getContent() {
18327      return this.editor.getValue();
18328    }
18329  }, {
18330    key: "getAuthor",
18331    value: function getAuthor() {
18332      var content = this.getContent();
18333      var result = content.match(/\/\/\s*[A|a]uthor\s*[\:]?\s*([\w|\s|\@|\(|\)|\-|\_]*)/i);
18334      if (result && !(result[1] === " " || result[1] === "")) {
18335        var author = result[1].replace(/(\r\n|\n|\r)/gm, "");
18336        return author;
18337      } else {
18338        return "unknown";
18339      }
18340    }
18341  }, {
18342    key: "getTitle",
18343    value: function getTitle() {
18344      var content = this.getContent();
18345      var result = content.match(/\/\/\s*[T|t]itle\s*:\s*([\w|\s|\@|\(|\)|\-|\_]*)/i);
18346      if (result && !(result[1] === " " || result[1] === "")) {
18347        var title = result[1].replace(/(\r\n|\n|\r)/gm, "");
18348        return title;
18349      } else if (this.bufferManager !== undefined) {
18350        return this.bufferManager.current;
18351      } else {
18352        return "unknown";
18353      }
18354    }
18355
18356    // Returns Promise
18357  }, {
18358    key: "getOfToken",
18359    value: function getOfToken() {
18360      return this.storage.get("accessToken");
18361    }
18362  }, {
18363    key: "download",
18364    value: function download() {
18365      var content = this.getContent();
18366      var name = this.getTitle();
18367      if (name !== "") {
18368        name += "-";
18369      }
18370      name += new Date().getTime();
18371
18372      // Download code
18373      var blob = new Blob([content], { type: "text/plain" });
18374      (0, _toolsDownload.saveAs)(blob, name + ".frag");
18375      this.editor.doc.markClean();
18376      this.change = false;
18377    }
18378  }, {
18379    key: "update",
18380    value: function update() {
18381      if (this.debugging) {
18382        this.debugging = false;
18383        (0, _coreEditor.focusAll)(this.editor);
18384      }
18385
18386      if (this.visualDebugger.testingResults.length) this.visualDebugger.clean();
18387
18388      this.shader.canvas.load(this.options.frag_header + this.editor.getValue() + this.options.frag_footer);
18389    }
18390  }, {
18391    key: "createFontLink",
18392    value: function createFontLink() {
18393      var head = document.getElementsByTagName("head")[0];
18394      var link = document.createElement("link");
18395      link.href = "https://fonts.googleapis.com/icon?family=Material+Icons";
18396      link.type = "text/css";
18397      link.rel = "stylesheet";
18398      link.media = "screen,print";
18399      head.appendChild(link);
18400      document.getElementsByTagName("head")[0].appendChild(link);
18401    }
18402  }, {
18403    key: "togglePresentationWindow",
18404    value: function togglePresentationWindow(flag) {
18405      this.pWindowOpen = flag;
18406      if (flag) this.shader.openWindow();else this.shader.closeWindow();
18407    }
18408  }, {
18409    key: "onClosePresentationWindow",
18410    value: function onClosePresentationWindow() {
18411      this.pWindowOpen = false;
18412    }
18413  }]);
18414
18415  return GlslEditor;
18416})();
18417
18418exports["default"] = GlslEditor;
18419
18420window.GlslEditor = GlslEditor;
18421
18422var GlslWebComponent = function GlslWebComponent() {};
18423GlslWebComponent.prototype = _Object$create(HTMLElement.prototype);
18424GlslWebComponent.prototype.createdCallback = function createdCallback() {
18425  var options = {
18426    canvas_size: 150,
18427    canvas_follow: true,
18428    tooltips: true
18429  };
18430
18431  for (var i = 0; i < this.attributes.length; i++) {
18432    var attribute = this.attributes[i];
18433    if (attribute.specified) {
18434      var value = attribute.value;
18435
18436      if (value === "true") value = true;else if (value === "false") value = false;else if (parseInt(value)) value = parseInt(value);
18437
18438      options[attribute.name] = value;
18439    }
18440  }
18441
18442  this.glslEditor = new GlslEditor(this, options);
18443};
18444
18445document.registerElement("glsl-editor", GlslWebComponent);
18446module.exports = exports["default"];
18447
18448},{"./core/Editor":115,"./core/Shader":116,"./io/BufferManager":117,"./io/FileDrop":118,"./io/HashWatch":119,"./io/LocalStorage":120,"./tools/common":121,"./tools/download":123,"./tools/mixin":126,"./ui/ErrorsDisplay":128,"./ui/ExportIcon":129,"./ui/Helpers":130,"./ui/Menu":131,"./ui/VisualDebugger":133,"babel-runtime/core-js/object/create":3,"babel-runtime/core-js/object/keys":6,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14,"codemirror":30,"document-register-element":107,"xhr":112}],115:[function(_dereq_,module,exports){
18449// Import CodeMirror
18450'use strict';
18451
18452var _Promise = _dereq_('babel-runtime/core-js/promise')['default'];
18453
18454var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
18455
18456Object.defineProperty(exports, '__esModule', {
18457    value: true
18458});
18459exports.initEditor = initEditor;
18460exports.unfocusLine = unfocusLine;
18461exports.unfocusAll = unfocusAll;
18462exports.focusLine = focusLine;
18463exports.focusAll = focusAll;
18464
18465var _codemirror = _dereq_('codemirror');
18466
18467var _codemirror2 = _interopRequireDefault(_codemirror);
18468
18469// Import CodeMirror addons and modules
18470
18471_dereq_('codemirror/addon/search/search');
18472
18473_dereq_('codemirror/addon/search/searchcursor');
18474
18475_dereq_('codemirror/addon/comment/comment');
18476
18477_dereq_('codemirror/addon/dialog/dialog');
18478
18479_dereq_('codemirror/addon/edit/matchbrackets');
18480
18481_dereq_('codemirror/addon/edit/closebrackets');
18482
18483_dereq_('codemirror/addon/wrap/hardwrap');
18484
18485_dereq_('codemirror/addon/fold/foldcode');
18486
18487_dereq_('codemirror/addon/fold/foldgutter');
18488
18489_dereq_('codemirror/addon/fold/indent-fold');
18490
18491_dereq_('codemirror/addon/hint/show-hint');
18492
18493_dereq_('codemirror/addon/hint/javascript-hint');
18494
18495_dereq_('codemirror/addon/display/rulers');
18496
18497_dereq_('codemirror/addon/display/panel');
18498
18499_dereq_('codemirror/addon/hint/show-hint');
18500
18501_dereq_('codemirror/mode/clike/clike.js');
18502
18503// Keymap
18504
18505_dereq_('codemirror/keymap/sublime');
18506
18507var UNFOCUS_CLASS = 'ge_editor-unfocus';
18508
18509function initEditor(main) {
18510    if (main.options.lineNumbers === undefined) main.options.lineNumbers = true;
18511
18512    // CREATE AND START CODEMIRROR
18513    var el = document.createElement('div');
18514    el.setAttribute('class', 'ge_editor');
18515
18516    // If there is a menu offset the editor to come after it
18517    if (main.menu) el.style.paddingTop = (main.menu.el.clientHeight || main.menu.el.offsetHeight || main.menu.el.scrollHeight) + 'px';
18518
18519    main.container.appendChild(el);
18520
18521    function fillInclude(cm, option) {
18522        var _this = this;
18523
18524        return new _Promise(function (accept) {
18525            setTimeout(function () {
18526                var cur = cm.getCursor().line = cm.getLine(cur.line).trim();
18527                var start = cur.ch,
18528                    end = cur.ch;
18529
18530                if (line.startsWith('#include \"lygia')) {
18531                    var _ret = (function () {
18532                        var path = line.substring(10);
18533                        if (_this.lygia_glob === null) {
18534                            getJSON('https://lygia.xyz/glsl.json', function (err, data) {
18535                                if (err === null) {
18536                                    _this.lygia_glob = data;
18537                                }
18538                            });
18539                        }
18540                        console.log('autocomplete for', path);
18541
18542                        var start = token.start;
18543                        var end = cur.ch;
18544                        var lineN = cur.line;
18545
18546                        var result = [];
18547
18548                        if (_this.lygia_glob !== null) {
18549                            _this.lygia_glob.forEach(function (w) {
18550                                if (w.startsWith(path)) result.push('#include \"' + w + '\"');
18551                            });
18552                            result.sort();
18553                        }
18554
18555                        if (result.length > 0) {
18556                            console.log(lineN, result);
18557                            return {
18558                                v: accept({ list: result,
18559                                    from: _codemirror2['default'].Pos(cur.line, start),
18560                                    to: _codemirror2['default'].Pos(cur.line, end) })
18561                            };
18562                        }
18563                    })();
18564
18565                    if (typeof _ret === 'object') return _ret.v;
18566                }
18567                return accept(null);
18568            }, 100);
18569        });
18570    }
18571
18572    var cm = (0, _codemirror2['default'])(el, {
18573        value: main.options.frag,
18574        viewportMargin: Infinity,
18575        lineNumbers: main.options.lineNumbers,
18576        matchBrackets: true,
18577        mode: 'x-shader/x-fragment',
18578        keyMap: 'sublime',
18579        autoCloseBrackets: true,
18580        extraKeys: { 'Ctrl-Space': 'autocomplete' },
18581        showCursorWhenSelecting: true,
18582        theme: main.options.theme,
18583        dragDrop: false,
18584        indentUnit: main.options.indentUnit,
18585        tabSize: main.options.tabSize,
18586        indentWithTabs: main.options.indentWithTabs,
18587        gutters: main.options.lineNumbers ? ['CodeMirror-linenumbers', 'breakpoints'] : false,
18588        lineWrapping: main.options.lineWrapping,
18589        autofocus: main.options.autofocus
18590    });
18591
18592    return cm;
18593}
18594
18595function unfocusLine(cm, line) {
18596    if (line === null) {
18597        return;
18598    }
18599    cm.getDoc().addLineClass(line, 'gutter', UNFOCUS_CLASS);
18600    cm.getDoc().addLineClass(line, 'text', UNFOCUS_CLASS);
18601}
18602
18603function unfocusAll(cm) {
18604    for (var i = 0, j = cm.getDoc().lineCount(); i <= j; i++) {
18605        unfocusLine(cm, i);
18606    }
18607}
18608
18609function focusLine(cm, line) {
18610    if (line === null) {
18611        return;
18612    }
18613    cm.getDoc().removeLineClass(line, 'gutter', UNFOCUS_CLASS);
18614    cm.getDoc().removeLineClass(line, 'text', UNFOCUS_CLASS);
18615}
18616
18617function focusAll(cm) {
18618    for (var i = 0, j = cm.getDoc().lineCount(); i <= j; i++) {
18619        focusLine(cm, i);
18620    }
18621}
18622
18623},{"babel-runtime/core-js/promise":8,"babel-runtime/helpers/interop-require-default":14,"codemirror":30,"codemirror/addon/comment/comment":15,"codemirror/addon/dialog/dialog":16,"codemirror/addon/display/panel":17,"codemirror/addon/display/rulers":18,"codemirror/addon/edit/closebrackets":19,"codemirror/addon/edit/matchbrackets":20,"codemirror/addon/fold/foldcode":21,"codemirror/addon/fold/foldgutter":22,"codemirror/addon/fold/indent-fold":23,"codemirror/addon/hint/javascript-hint":24,"codemirror/addon/hint/show-hint":25,"codemirror/addon/search/search":26,"codemirror/addon/search/searchcursor":27,"codemirror/addon/wrap/hardwrap":28,"codemirror/keymap/sublime":29,"codemirror/mode/clike/clike.js":31}],116:[function(_dereq_,module,exports){
18624"use strict";
18625
18626var _createClass = _dereq_("babel-runtime/helpers/create-class")["default"];
18627
18628var _classCallCheck = _dereq_("babel-runtime/helpers/class-call-check")["default"];
18629
18630var _interopRequireDefault = _dereq_("babel-runtime/helpers/interop-require-default")["default"];
18631
18632Object.defineProperty(exports, "__esModule", {
18633  value: true
18634});
18635
18636var _glslCanvas = _dereq_("glslCanvas");
18637
18638var _glslCanvas2 = _interopRequireDefault(_glslCanvas);
18639
18640var _toolsInteractiveDom = _dereq_("../tools/interactiveDom");
18641
18642var _toolsMediaCapture = _dereq_("../tools/mediaCapture");
18643
18644var _toolsMediaCapture2 = _interopRequireDefault(_toolsMediaCapture);
18645
18646var _uiMenuItem = _dereq_("../ui/MenuItem");
18647
18648var _uiMenuItem2 = _interopRequireDefault(_uiMenuItem);
18649
18650var _toolsDownload = _dereq_("../tools/download");
18651
18652var CONTROLS_CLASSNAME = "ge_control";
18653var CONTROLS_PANEL_CLASSNAME = "ge_control_panel";
18654
18655var Shader = (function () {
18656  function Shader(main) {
18657    var _this = this;
18658
18659    _classCallCheck(this, Shader);
18660
18661    this.main = main;
18662    this.options = main.options;
18663    this.frag = "";
18664
18665    // DOM CONTAINER
18666    this.el = document.createElement("div");
18667    this.el.setAttribute("class", "ge_canvas_container");
18668    // CREATE AND START GLSLCANVAS
18669    this.elCanvas = document.createElement("canvas");
18670    this.elCanvas.setAttribute("class", "ge_canvas");
18671    this.elCanvas.setAttribute("data-fragment", this.options.frag_header + this.options.frag + this.options.frag_footer);
18672    this.el.appendChild(this.elCanvas);
18673    var glslcanvas = new _glslCanvas2["default"](this.elCanvas, {
18674      premultipliedAlpha: false,
18675      preserveDrawingBuffer: true,
18676      backgroundColor: "rgba(1,1,1,1)"
18677    });
18678
18679    var width = this.options.canvas_width || this.options.canvas_size || "250";
18680    var height = this.options.canvas_height || this.options.canvas_size || "250";
18681    glslcanvas.canvas.style.width = width + "px";
18682    glslcanvas.canvas.style.height = height + "px";
18683    glslcanvas.resize();
18684
18685    this.canvas = glslcanvas;
18686
18687    if (this.options.imgs && this.options.imgs.length > 0) {
18688      for (var i in this.options.imgs) {
18689        this.canvas.setUniform("u_tex" + i, this.options.imgs[i]);
18690      }
18691    }
18692
18693    // Media Capture
18694    this.mediaCapture = new _toolsMediaCapture2["default"]();
18695    this.mediaCapture.setCanvas(this.elCanvas);
18696    this.canvas.on("render", function () {
18697      _this.mediaCapture.completeScreenshot();
18698    });
18699
18700    if (main.options.displayMenu) {
18701      // CONTROLS
18702      this.controlsContainer = document.createElement("ul");
18703      this.controlsContainer.className = CONTROLS_CLASSNAME;
18704      this.controlPanel = document.createElement("ul");
18705      this.controlPanel.className = CONTROLS_PANEL_CLASSNAME;
18706      this.controlsContainer.appendChild(this.controlPanel);
18707      this.el.appendChild(this.controlsContainer);
18708      this.controls = {};
18709      // play/stop
18710      // this.controls.playPause = new MenuItem(this.controlPanel, 'ge_control_element', '<i class="material-icons">pause</i>', (event) => {
18711      this.controls.playPause = new _uiMenuItem2["default"](this.controlPanel, "ge_control_element", '<i class="material-icons">pause</i>', function (event) {
18712        event.stopPropagation();
18713        event.preventDefault();
18714        if (glslcanvas.paused) {
18715          glslcanvas.play();
18716          // this.controls.playPause.name = '<i class="material-icons">pause</i>';//'Pause';
18717          _this.controls.playPause.name = '<i class="material-icons">pause</i>'; //'Pause';
18718        } else {
18719            glslcanvas.pause();
18720            _this.controls.playPause.name = '<i class="material-icons">play_arrow</i>'; //'Play';
18721          }
18722      });
18723      // rec
18724      this.isCapturing = false;
18725      // let rec = new MenuItem(this.controlPanel, 'ge_control_element', '<i class="material-icons">fiber_manual_record</i>', (event) => {
18726      var rec = new _uiMenuItem2["default"](this.controlPanel, "ge_control_element", '<i class="material-icons">&#xE061;</i>', function (event) {
18727        event.stopPropagation();
18728        event.preventDefault();
18729        if (_this.isCapturing) {
18730          _this.stopVideoCapture();
18731        } else {
18732          _this.startVideoCapture();
18733        }
18734      });
18735      this.controls.rec = rec;
18736      this.controls.rec.button.style.color = "red";
18737
18738      // present mode (only if there is a presentation.html file to point to)
18739      // this.controls.presentationMode = new MenuItem(this.controlPanel, 'ge_control_element', '<i class="material-icons">open_in_new</i>', (event) => {
18740      this.controls.presentationMode = new _uiMenuItem2["default"](this.controlPanel, "ge_control_element", '<i class="material-icons">open_in_new</i>', function (event) {
18741        event.stopPropagation();
18742        event.preventDefault();
18743        if (main.pWindowOpen) {
18744          main.togglePresentationWindow(false);
18745        } else {
18746          main.togglePresentationWindow(true);
18747        }
18748      });
18749
18750      this.elControl = this.el.getElementsByClassName(CONTROLS_CLASSNAME)[0];
18751      this.elControl.addEventListener("mouseenter", function (event) {
18752        _this.showControls();
18753      });
18754      this.elControl.addEventListener("mouseleave", function (event) {
18755        _this.hideControls();
18756      });
18757      this.elCanvas.addEventListener("mousemove", function (event) {
18758        if (event.offsetY > _this.elCanvas.clientHeight * 0.66) {
18759          _this.showControls();
18760        } else {
18761          _this.hideControls();
18762        }
18763      });
18764      this.hideControls();
18765    }
18766
18767    // ========== EVENTS
18768    // Draggable/resizable/snappable
18769    if (main.options.canvas_draggable || main.options.canvas_resizable || main.options.canvas_snapable) {
18770      (0, _toolsInteractiveDom.subscribeInteractiveDom)(this.el, {
18771        move: main.options.canvas_draggable,
18772        resize: main.options.canvas_resizable,
18773        snap: main.options.canvas_snapable
18774      });
18775
18776      if (main.options.canvas_size === "halfscreen") {
18777        this.el.snapRight();
18778      }
18779
18780      this.el.on("move", function (event) {
18781        event.el.style.width = event.el.clientWidth + "px";
18782        event.el.style.height = event.el.clientHeight + "px";
18783      });
18784      this.el.on("resize", function (event) {
18785        glslcanvas.canvas.style.width = event.el.clientWidth + "px";
18786        glslcanvas.canvas.style.height = event.el.clientHeight + "px";
18787        glslcanvas.resize();
18788      });
18789    }
18790
18791    // If there is a menu offset the editor to come after it
18792    if (main.menu) {
18793      this.el.style.top = (main.menu.el.clientHeight || main.menu.el.offsetHeight || main.menu.el.scrollHeight) + "px";
18794    }
18795
18796    // Add all this to the main container
18797    main.container.appendChild(this.el);
18798    glslcanvas.resize();
18799  }
18800
18801  _createClass(Shader, [{
18802    key: "hideControls",
18803    value: function hideControls() {
18804      if (this.elControl && this.elControl.className === CONTROLS_CLASSNAME) {
18805        this.elControl.className = CONTROLS_CLASSNAME + " " + CONTROLS_CLASSNAME + "_hidden";
18806      }
18807    }
18808  }, {
18809    key: "showControls",
18810    value: function showControls() {
18811      if (this.elControl && this.elControl.className === CONTROLS_CLASSNAME + " " + CONTROLS_CLASSNAME + "_hidden") {
18812        this.elControl.className = CONTROLS_CLASSNAME;
18813      }
18814    }
18815  }, {
18816    key: "requestRedraw",
18817    value: function requestRedraw() {
18818      this.canvas.forceRender = true;
18819      this.canvas.render();
18820    }
18821  }, {
18822    key: "screenshot",
18823    value: function screenshot() {
18824      this.requestRedraw();
18825      return this.mediaCapture.screenshot();
18826    }
18827  }, {
18828    key: "startVideoCapture",
18829    value: function startVideoCapture() {
18830      this.requestRedraw();
18831      if (this.mediaCapture.startVideoCapture()) {
18832        this.isCapturing = true;
18833        this.controls.rec.button.style.color = "white";
18834        // this.controls.rec.name = '<i class="material-icons">stop</i>';
18835        this.controls.rec.name = '<i class="material-icons">&#xE061;</i>';
18836      }
18837    }
18838  }, {
18839    key: "stopVideoCapture",
18840    value: function stopVideoCapture() {
18841      if (this.isCapturing) {
18842        this.isCapturing = false;
18843        this.controls.rec.button.style.color = "red";
18844        // this.controls.rec.name = '<i class="material-icons">fiber_manual_record</i>';
18845        this.controls.rec.name = '<i class="material-icons">stop</i>';
18846        this.mediaCapture.stopVideoCapture().then(function (video) {
18847          (0, _toolsDownload.saveAs)(video.blob, Number(new Date()) + ".webm");
18848        });
18849      }
18850    }
18851  }, {
18852    key: "openWindow",
18853    value: function openWindow() {
18854      this.originalSize = {
18855        width: this.canvas.canvas.clientWidth,
18856        height: this.canvas.canvas.clientHeight
18857      };
18858      this.presentationWindow = window.open("", "_blank", "presentationWindow");
18859      this.setUpPresentationWindow();
18860    }
18861  }, {
18862    key: "closeWindow",
18863    value: function closeWindow() {
18864      if (this.presentationWindow) {
18865        this.presentationWindow.close();
18866      }
18867    }
18868  }, {
18869    key: "setCanvasSize",
18870    value: function setCanvasSize(w, h) {
18871      this.canvas.canvas.style.width = w + "px";
18872      this.canvas.canvas.style.height = h + "px";
18873    }
18874  }, {
18875    key: "setUpPresentationWindow",
18876    value: function setUpPresentationWindow() {
18877      this.presentationWindow.document.body.appendChild(this.canvas.canvas);
18878      var d = this.presentationWindow.document;
18879      var div = d.createElement("div");
18880      div.appendChild(d.createTextNode("Projector mode"));
18881      var span = this.presentationWindow.document.createElement("span");
18882      div.appendChild(span);
18883      span.appendChild(d.createTextNode(" - If the canvas doesn't update, drag this window and reveal the editor"));
18884      d.body.appendChild(div);
18885
18886      d.title = "GLSL Editor";
18887      d.body.style.padding = "0";
18888      d.body.style.margin = "0";
18889      d.body.style.background = "#171e22";
18890      d.body.style.overflow = "hidden";
18891
18892      div.style.position = "absolute";
18893      div.style.width = "100%";
18894      div.style.background = "rgba(0, 0, 0, 0.5)";
18895      div.style.position = "absolute";
18896      div.style.top = "0";
18897      div.style.left = "0";
18898      div.style.right = "0";
18899      div.style.padding = "16px";
18900      div.style.color = "#ffffff";
18901      div.style.fontSize = "14px";
18902      div.style.fontFamily = "Helvetica, Geneva, sans-serif";
18903      div.style.fontWeight = "400";
18904      div.style.letterSpacing = "0.1em";
18905      div.style.textAlign = "center";
18906      div.style.opacity = "1";
18907      div.style.zIndex = "9999";
18908      div.style.setProperty("-webkit-transition", "opacity 1.5s");
18909      div.style.setProperty("-moz-transition", "opacity 1.5s");
18910      div.style.setProperty("transition", "opacity 1.5s");
18911
18912      span.style.color = "rgba(255, 255, 255, 0.5)";
18913
18914      setTimeout(function () {
18915        div.style.opacity = 0;
18916      }, 4000);
18917
18918      this.setCanvasSize(this.presentationWindow.innerWidth, this.presentationWindow.innerHeight);
18919      this.presentationWindow.addEventListener("resize", this.onPresentationWindowResize.bind(this));
18920      this.presentationWindow.addEventListener("unload", this.onPresentationWindowClose.bind(this));
18921    }
18922  }, {
18923    key: "onPresentationWindowClose",
18924    value: function onPresentationWindowClose() {
18925      this.el.appendChild(this.canvas.canvas);
18926      this.setCanvasSize(this.originalSize.width, this.originalSize.height);
18927      this.canvas.resize();
18928
18929      this.main.onClosePresentationWindow();
18930      this.main.menu.onClosePresentationWindow();
18931      this.presentationWindow = null;
18932    }
18933  }, {
18934    key: "onPresentationWindowResize",
18935    value: function onPresentationWindowResize() {
18936      if (this.presentationWindow) {
18937        this.setCanvasSize(this.presentationWindow.innerWidth, this.presentationWindow.innerHeight);
18938        this.canvas.resize();
18939      }
18940    }
18941  }]);
18942
18943  return Shader;
18944})();
18945
18946exports["default"] = Shader;
18947module.exports = exports["default"];
18948
18949},{"../tools/download":123,"../tools/interactiveDom":124,"../tools/mediaCapture":125,"../ui/MenuItem":132,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14,"glslCanvas":109}],117:[function(_dereq_,module,exports){
18950// Import CodeMirror
18951'use strict';
18952
18953var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
18954
18955var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
18956
18957var _Object$keys = _dereq_('babel-runtime/core-js/object/keys')['default'];
18958
18959var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
18960
18961Object.defineProperty(exports, '__esModule', {
18962    value: true
18963});
18964
18965var _codemirror = _dereq_('codemirror');
18966
18967var _codemirror2 = _interopRequireDefault(_codemirror);
18968
18969_dereq_('codemirror/mode/clike/clike.js');
18970
18971var BufferManager = (function () {
18972    function BufferManager(main) {
18973        _classCallCheck(this, BufferManager);
18974
18975        this.main = main;
18976        this.buffers = {};
18977        this.tabs = {};
18978        this.current = 'untitled';
18979    }
18980
18981    _createClass(BufferManager, [{
18982        key: 'open',
18983        value: function open(name, content) {
18984            var _this = this;
18985
18986            if (!this.el) {
18987                // Create DOM element
18988                this.el = document.createElement('ul');
18989                this.el.className = 'ge_panel';
18990            }
18991
18992            if (this.main.change && this.current === 'untitled') {
18993                console.log('Open Current in a different tab');
18994                this.open(this.current, this.main.getContent());
18995            }
18996
18997            this.buffers[name] = _codemirror2['default'].Doc(content, 'x-shader/x-fragment');
18998
18999            // Create a new tab
19000            var tab = document.createElement('li');
19001            tab.setAttribute('class', 'ge_panel_tab');
19002            tab.textContent = name;
19003            _codemirror2['default'].on(tab, 'click', function () {
19004                _this.select(name);
19005            });
19006
19007            var close = tab.appendChild(document.createElement('a'));
19008            close.textContent = 'x';
19009            close.setAttribute('class', 'ge_panel_tab_close');
19010            _codemirror2['default'].on(close, 'click', function () {
19011                _this.close(name);
19012            });
19013
19014            this.el.appendChild(tab);
19015            this.tabs[name] = tab;
19016
19017            if (this.el && !this.panel && this.getLength() > 1) {
19018                // Create Panel CM element
19019                this.panel = this.main.editor.addPanel(this.el, { position: 'top' });
19020            }
19021        }
19022    }, {
19023        key: 'select',
19024        value: function select(name) {
19025            var buf = this.buffers[name];
19026
19027            if (buf === undefined) {
19028                return;
19029            }
19030
19031            if (buf.getEditor()) {
19032                buf = buf.linkedDoc({ sharedHist: true });
19033            }
19034            var old = this.main.editor.swapDoc(buf);
19035            var linked = old.iterLinkedDocs(function (doc) {
19036                linked = doc;
19037            });
19038            if (linked) {
19039                // Make sure the document in buffers is the one the other view is looking at
19040                for (var bufferName in this.buffers) {
19041                    if (this.buffers[bufferName] === old) {
19042                        this.buffers[bufferName] = linked;
19043                    }
19044                }
19045                old.unlinkDoc(linked);
19046            }
19047            if (this.main.options.autofocus) {
19048                this.main.editor.focus();
19049            }
19050            this.main.setContent(this.main.getContent());
19051
19052            if (this.tabs[this.current]) {
19053                this.tabs[this.current].setAttribute('class', 'ge_panel_tab');
19054            }
19055            this.tabs[name].setAttribute('class', 'ge_panel_tab_active');
19056            this.current = name;
19057
19058            this.main.editor.setSize(null, 'auto');
19059            this.main.editor.getWrapperElement().style.height = 'auto';
19060
19061            this.main.trigger('new_content', {});
19062        }
19063    }, {
19064        key: 'close',
19065        value: function close(name) {
19066            var needChange = name === this.getCurrent();
19067
19068            this.el.removeChild(this.tabs[name]);
19069            delete this.tabs[name];
19070            delete this.buffers[name];
19071
19072            if (this.getLength() === 1) {
19073                this.panel.clear();
19074                this.panel = undefined;
19075                this.el = undefined;
19076            }
19077
19078            if (needChange) {
19079                for (var prop in this.tabs) {
19080                    this.select(prop);
19081                    break;
19082                }
19083            }
19084        }
19085    }, {
19086        key: 'getCurrent',
19087        value: function getCurrent() {
19088            return this.current;
19089        }
19090    }, {
19091        key: 'getLength',
19092        value: function getLength() {
19093            return _Object$keys(this.buffers).length;
19094        }
19095    }]);
19096
19097    return BufferManager;
19098})();
19099
19100exports['default'] = BufferManager;
19101module.exports = exports['default'];
19102
19103},{"babel-runtime/core-js/object/keys":6,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14,"codemirror":30,"codemirror/mode/clike/clike.js":31}],118:[function(_dereq_,module,exports){
19104/*
19105Original: https://github.com/tangrams/tangram-play/blob/gh-pages/src/js/addons/ui/FileDrop.js
19106Author: Lou Huang (@saikofish)
19107*/
19108
19109'use strict';
19110
19111var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
19112
19113Object.defineProperty(exports, '__esModule', {
19114    value: true
19115});
19116
19117var FileDrop = function FileDrop(main) {
19118    _classCallCheck(this, FileDrop);
19119
19120    // Set up drag/drop file listeners
19121    main.container.addEventListener('dragenter', function (event) {
19122        // Check to make sure that dropped items are files.
19123        // This prevents other drags (e.g. text in editor)
19124        // from turning on the file drop area.
19125        // See here: http://stackoverflow.com/questions/6848043/how-do-i-detect-a-file-is-being-dragged-rather-than-a-draggable-element-on-my-pa
19126        // Tested in Chrome, Firefox, Safari 8
19127        var types = event.dataTransfer.types;
19128        if (types !== null && (types.indexOf ? types.indexOf('Files') !== -1 : types.contains('application/x-moz-file'))) {
19129            event.preventDefault();
19130            event.dataTransfer.dropEffect = 'copy';
19131        }
19132    }, true);
19133
19134    main.container.addEventListener('dragover', function (event) {
19135        // Required to prevent browser from navigating to a file
19136        // instead of receiving a data transfer
19137        event.preventDefault();
19138    }, false);
19139
19140    main.container.addEventListener('dragleave', function (event) {
19141        event.preventDefault();
19142    }, true);
19143
19144    main.container.addEventListener('drop', function (event) {
19145        event.preventDefault();
19146        if (event.dataTransfer.files.length > 0) {
19147            var file = event.dataTransfer.files[0];
19148            main.open(file);
19149        }
19150    }, false);
19151};
19152
19153exports['default'] = FileDrop;
19154module.exports = exports['default'];
19155
19156},{"babel-runtime/helpers/class-call-check":10}],119:[function(_dereq_,module,exports){
19157'use strict';
19158
19159var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
19160
19161var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
19162
19163Object.defineProperty(exports, '__esModule', {
19164    value: true
19165});
19166
19167var HashWatch = (function () {
19168    function HashWatch(main) {
19169        var _this = this;
19170
19171        _classCallCheck(this, HashWatch);
19172
19173        this.main = main;
19174        this.check();
19175
19176        window.addEventListener('hashchange', function () {
19177            _this.check();
19178        }, false);
19179    }
19180
19181    _createClass(HashWatch, [{
19182        key: 'check',
19183        value: function check() {
19184            if (window.location.hash !== '') {
19185                this.main.options.imgs = [];
19186
19187                var hashes = location.hash.split('&');
19188                for (var i in hashes) {
19189                    var ext = hashes[i].substr(hashes[i].lastIndexOf('.') + 1);
19190                    var path = hashes[i];
19191
19192                    // Extract hash if is present
19193                    if (path.search('#') === 0) {
19194                        path = path.substr(1);
19195                    }
19196
19197                    var filename = path.split('/').pop();
19198
19199                    if (ext === 'frag') {
19200                        this.main.open(path, filename.replace(/\.[^/.]+$/, ''));
19201                    } else if (ext === 'png' || ext === 'jpg' || ext === 'PNG' || ext === 'JPG') {
19202                        this.main.options.imgs.push(path);
19203                    }
19204                }
19205            }
19206
19207            var query = parseQuery(window.location.search.slice(1));
19208            if (query) {
19209                for (var key in query) {
19210                    if (key === 'log') {
19211                        if (this.main.bufferManager) {
19212                            var logs = query.log.split(',');
19213                            for (var i in logs) {
19214                                this.main.open('https://thebookofshaders.com/log/' + logs[i] + '.frag', logs[i]);
19215                            }
19216                        } else {
19217                            this.main.open('https://thebookofshaders.com/log/' + query.log + '.frag', query.log);
19218                        }
19219                    } else {
19220                        var value = query[key];
19221                        if (value === 'true' || value === 'false') {
19222                            value = value == 'true';
19223                        } else if (parseFloat(value)) {
19224                            value = parseFloat(value);
19225                        }
19226                        this.main.options[key] = value;
19227                    }
19228                }
19229            }
19230        }
19231    }]);
19232
19233    return HashWatch;
19234})();
19235
19236exports['default'] = HashWatch;
19237
19238function parseQuery(qstr) {
19239    var query = {};
19240    var a = qstr.split('&');
19241    for (var i in a) {
19242        var b = a[i].split('=');
19243        query[decodeURIComponent(b[0])] = decodeURIComponent(b[1]);
19244    }
19245    return query;
19246}
19247module.exports = exports['default'];
19248
19249},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],120:[function(_dereq_,module,exports){
19250/*
19251Original: https://github.com/tangrams/tangram-play/blob/gh-pages/src/js/addons/LocalStorage.js
19252Author: Lou Huang (@saikofish)
19253*/
19254
19255/**
19256 *  Local storage
19257 *
19258 *  Provides a common interface for the application where modules can
19259 *  request storage of values across multiple user sessions via the
19260 *  browser's LocalStorage API.
19261 *
19262 *  Browser support is good, so no fallbacks are implemented.
19263 *  This module manages namespacing for Tangram Play to prevent name
19264 *  collisions with other libraries, browser extensions, etc.
19265 */
19266'use strict';
19267
19268Object.defineProperty(exports, '__esModule', {
19269    value: true
19270});
19271var LOCAL_STORAGE_PREFIX = 'glslEditor-';
19272
19273var LocalStorage = {
19274    /**
19275     *  setItem()
19276     *  Namespaces key name to Tangram Play application and adds
19277     *  the value to LocalStorage.
19278     */
19279    setItem: function setItem(key, value) {
19280        if (window.localStorage) {
19281            window.localStorage.setItem(LOCAL_STORAGE_PREFIX + key, value);
19282        }
19283    },
19284
19285    /**
19286     *  pushItem()
19287     *  Store values as an array. If the key doesn't exist as an object, create it.
19288     *  Note that this overwrites an old value if it is present and not a JSON object
19288!
19289     *  If it exists, retreive it, serialize it into JSON, push the new value,
19290     *  re-encode to a string and then set it back in localStorage.
19291     *  No other array methods are implemented. If you need to delete items, etc
19292     *  then retrieve the string as normal, do the work in your script, and then
19293     *  set it to the new stringified array instead of pushing it.
19294     */
19295    pushItem: function pushItem(key, value) {
19296        var stored = undefined;
19297        stored = this.getItem(key);
19298        // In case there is a previously stored item here that is not
19299        // parseable JSON, don't fail
19300        try {
19301            stored = JSON.parse(stored);
19302            stored.arr = stored.arr || [];
19303        } catch (e) {
19304            stored = { arr: [] };
19305        }
19306        stored.arr.push(value);
19307        this.setItem(key, JSON.stringify(stored));
19308    },
19309
19310    /**
19311     *  getItem()
19312     *  Retrieves value for the given key name and application namespace.
19313     */
19314    getItem: function getItem(key) {
19315        if (window.localStorage) {
19316            return window.localStorage.getItem(LOCAL_STORAGE_PREFIX + key);
19317        }
19318    },
19319
19320    /**
19321     *  removeItem()
19322     *  Removes key-value pair under the application namespace.
19323     */
19324    removeItem: function removeItem(key) {
19325        if (window.localStorage) {
19326            window.localStorage.removeItem(LOCAL_STORAGE_PREFIX + key);
19327        }
19328    },
19329
19330    /**
19331     *  clear()
19332     *  Loops through all values in localStorage under the application
19333     *  namespace and removes them, preserving other key-value pairs in
19334     *  localStorage.
19335     */
19336    clear: function clear() {
19337        if (window.localStorage) {
19338            for (var key in window.localStorage) {
19339                if (key.indexOf(LOCAL_STORAGE_PREFIX) === 0) {
19340                    window.localStorage.removeItem(LOCAL_STORAGE_PREFIX + key);
19341                }
19342            }
19343        }
19344    }
19345};
19346
19347exports['default'] = LocalStorage;
19348module.exports = exports['default'];
19349
19350},{}],121:[function(_dereq_,module,exports){
19351'use strict';
19352
19353Object.defineProperty(exports, '__esModule', {
19354    value: true
19355});
19356exports.getDomOrigin = getDomOrigin;
19357exports.getDevicePixelRatio = getDevicePixelRatio;
19358exports.getJSON = getJSON;
19359
19360function getDomOrigin(el) {
19361    var box = el.getBoundingClientRect ? el.getBoundingClientRect() : { top: 0, left: 0 };
19362    var doc = el && el.ownerDocument;
19363    var body = doc.body;
19364    var win = doc.defaultView || doc.parentWindow || window;
19365    var docElem = doc.documentElement || body.parentNode;
19366    var clientTop = docElem.clientTop || body.clientTop || 0; // border on html or body or both
19367    var clientLeft = docElem.clientLeft || body.clientLeft || 0;
19368
19369    return {
19370        left: box.left + (win.pageXOffset || docElem.scrollLeft) - clientLeft,
19371        top: box.top + (win.pageYOffset || docElem.scrollTop) - clientTop
19372    };
19373}
19374
19375function getDevicePixelRatio(ctx) {
19376    var devicePixelRatio = window.devicePixelRatio || 1;
19377    var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
19378    return devicePixelRatio / backingStoreRatio;
19379}
19380
19381function getJSON(url, callback) {
19382    var xhr = new XMLHttpRequest();
19383    xhr.open('GET', url, true);
19384    xhr.responseType = 'json';
19385    xhr.onload = function () {
19386        var status = xhr.status;
19387        if (status === 200) {
19388            callback(null, xhr.response);
19389        } else {
19390            callback(status, xhr.response);
19391        }
19392    };
19393    xhr.send();
19394}
19395
19396;
19397
19398},{}],122:[function(_dereq_,module,exports){
19399'use strict';
19400
19401Object.defineProperty(exports, '__esModule', {
19402    value: true
19403});
19404exports.isCommented = isCommented;
19405exports.isLineAfterMain = isLineAfterMain;
19406exports.getVariableType = getVariableType;
19407exports.getShaderForTypeVarInLine = getShaderForTypeVarInLine;
19408exports.getResultRange = getResultRange;
19409exports.getMedian = getMedian;
19410exports.getDeltaSum = getDeltaSum;
19411exports.getHits = getHits;
19412
19413function isCommented(cm, nLine, match) {
19414    var token = cm.getTokenAt({ line: nLine, ch: match.index });
19415    if (token && token.type) {
19416        return token.type === 'comment';
19417    }
19418    return false;
19419}
19420
19421function isLineAfterMain(cm, nLine) {
19422    var totalLines = cm.getDoc().size;
19423    var voidRE = new RegExp('void main\\s*\\(\\s*[void]*\\)', 'i');
19424    for (var i = 0; i < nLine && i < totalLines; i++) {
19425        // Do not start until being inside the main function
19426        var voidMatch = voidRE.exec(cm.getLine(i));
19427        if (voidMatch) {
19428            return true;
19429        }
19430    }
19431    return false;
19432}
19433
19434function getVariableType(cm, sVariable) {
19435    var nLines = cm.getDoc().size;
19436
19437    // Show line where the value of the variable is been asigned
19438    var uniformRE = new RegExp('\\s*uniform\\s+(float|vec2|vec3|vec4)\\s+' + sVariable + '\\s*;');
19439    var voidRE = new RegExp('void main\\s*\\(\\s*[void]*\\)', 'i');
19440    var voidIN = false;
19441    var constructRE = new RegExp('(float|vec\\d)\\s+(' + sVariable + ')\\s*[;]?', 'i');
19442    for (var i = 0; i < nLines; i++) {
19443        if (!voidIN) {
19444            // Do not start until being inside the main function
19445            var voidMatch = voidRE.exec(cm.getLine(i));
19446            if (voidMatch) {
19447                voidIN = true;
19448            } else {
19449                var uniformMatch = uniformRE.exec(cm.getLine(i));
19450                if (uniformMatch && !isCommented(cm, i, uniformMatch)) {
19451                    return uniformMatch[1];
19452                }
19453            }
19454        } else {
19455            var constructMatch = constructRE.exec(cm.getLine(i));
19456            if (constructMatch && constructMatch[1] && !isCommented(cm, i, constructMatch)) {
19457                return constructMatch[1];
19458            }
19459        }
19460    }
19461    return 'none';
19462}
19463
19464function getShaderForTypeVarInLine(cm, sType, sVariable, nLine) {
19465    var frag = '';
19466    var offset = 1;
19467    for (var i = 0; i < nLine + 1 && i < cm.getDoc().size; i++) {
19468        if (cm.getLine(i)) {
19469            frag += cm.getLine(i) + '\n';
19470        }
19471    }
19472
19473    frag += '\tgl_FragColor = ';
19474    if (sType === 'float') {
19475        frag += 'vec4(vec3(' + sVariable + '),1.)';
19476    } else if (sType === 'vec2') {
19477        frag += 'vec4(vec3(' + sVariable + ',0.),1.)';
19478    } else if (sType === 'vec3') {
19479        frag += 'vec4(' + sVariable + ',1.)';
19480    } else if (sType === 'vec4') {
19481        frag += sVariable;
19482    }
19483    frag += ';\n}\n';
19484
19485    return frag;
19486}
19487
19488function getResultRange(testResults) {
19489    var minMS = '10000000.0';
19490    var minLine = 0;
19491    var maxMS = '0.0';
19492    var maxLine = 0;
19493    for (var i in testResults) {
19494        if (testResults[i].ms < minMS) {
19495            minMS = testResults[i].ms;
19496            minLine = testResults[i].line;
19497        }
19498        if (testResults[i].ms > maxMS) {
19499            maxMS = testResults[i].ms;
19500            maxLine = testResults[i].line;
19501        }
19502    }
19503    return { min: { line: minLine, ms: minMS }, max: { line: maxLine, ms: maxMS } };
19504}
19505
19506function getMedian(values) {
19507    values.sort(function (a, b) {
19508        return a - b;
19509    });
19510
19511    var half = Math.floor(values.length / 2);
19512
19513    if (values.length % 2) {
19514        return values[half];
19515    } else {
19516        return (values[half - 1] + values[half]) / 2.0;
19517    }
19518}
19519
19520function getDeltaSum(testResults) {
19521    var total = 0.0;
19522    for (var i in testResults) {
19523        if (testResults[i].delta > 0) {
19524            total += testResults[i].delta;
19525        }
19526    }
19527    return total;
19528}
19529
19530function getHits(testResults) {
19531    var total = 0;
19532    for (var i in testResults) {
19533        if (testResults[i].delta > 0) {
19534            total++;
19535        }
19536    }
19537    return total;
19538}
19539
19540},{}],123:[function(_dereq_,module,exports){
19541"use strict";
19542
19543Object.defineProperty(exports, "__esModule", {
19544    value: true
19545});
19546exports.saveAs = saveAs;
19547
19548function saveAs(blob, filename) {
19549    var url = URL.createObjectURL(blob);
19550    var link = document.createElement("a");
19551    link.setAttribute("download", filename);
19552    link.setAttribute("href", url);
19553    link.click();
19554}
19555
19556},{}],124:[function(_dereq_,module,exports){
19557/*
19558 * Original code from: https://twitter.com/blurspline / https://github.com/zz85
19559 * See post @ http://www.lab4games.net/zz85/blog/2014/11/15/resizing-moving-snapping-windows-with-js-css/
19560 */
19561
19562'use strict';
19563
19564Object.defineProperty(exports, '__esModule', {
19565    value: true
19566});
19567exports.subscribeInteractiveDom = subscribeInteractiveDom;
19568
19569var _mixin = _dereq_('./mixin');
19570
19571// Thresholds
19572var FULLSCREEN_MARGINS = -30;
19573var MARGINS = 10;
19574
19575function setBounds(element, x, y, w, h) {
19576    element.style.left = x + 'px';
19577    element.style.top = y + 'px';
19578    element.style.width = w + 'px';
19579    element.style.height = h + 'px';
19580}
19581
19582function subscribeInteractiveDom(dom, options) {
19583    (0, _mixin.subscribeMixin)(dom);
19584
19585    options = options || {};
19586    options.resize = options.resize !== undefined ? options.resize : false;
19587    options.move = options.move !== undefined ? options.move : false;
19588    options.snap = options.snap !== undefined ? options.snap : false;
19589
19590    // Minimum resizable area
19591    var minWidth = 100;
19592    var minHeight = 100;
19593
19594    // End of what's configurable.
19595    var clicked = null;
19596    var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
19597
19598    var rightScreenEdge, bottomScreenEdge;
19599
19600    var preSnapped;
19601
19602    var b, x, y;
19603
19604    var redraw = false;
19605
19606    var ghostdom = document.createElement('div');
19607    ghostdom.className = 'ghostdom';
19608
19609    if (options.snap) {
19610        dom.parentElement.appendChild(ghostdom);
19611    }
19612
19613    // Mouse events
19614    dom.addEventListener('mousedown', onMouseDown);
19615    document.addEventListener('mousemove', onMouseMove);
19616    document.addEventListener('mouseup', onMouseUp);
19617
19618    // Touch events
19619    dom.addEventListener('touchstart', onTouchDown, { passive: false });
19620    document.addEventListener('touchmove', onTouchMove, { passive: false });
19621    document.addEventListener('touchend', onTouchEnd, { passive: false });
19622
19623    function hintHide() {
19624        setBounds(ghostdom, b.left, b.top, b.width, b.height);
19625        ghostdom.style.opacity = 0;
19626    }
19627
19628    function onTouchDown(event) {
19629        event.preventDefault();
19630        event.stopPropagation();
19631        if (event.touches.length === 1) {
19632            onDown(event.changedTouches[0]);
19633        }
19634    }
19635
19636    function onTouchMove(event) {
19637        event.preventDefault();
19638        event.stopPropagation();
19639        if (event.touches.length === 1) {
19640            onMove(event.changedTouches[0]);
19641        }
19642    }
19643
19644    function onTouchEnd(event) {
19645        event.preventDefault();
19646        event.stopPropagation();
19647        if (event.touches.length === 0) {
19648            onUp(event.changedTouches[0]);
19649        }
19650    }
19651
19652    function onMouseDown(event) {
19653        event.preventDefault();
19654        event.stopPropagation();
19655        onDown(event);
19656    }
19657
19658    function onMouseMove(event) {
19659        event.preventDefault();
19660        event.stopPropagation();
19661        onMove(event);
19662    }
19663
19664    function onMouseUp(event) {
19665        event.preventDefault();
19666        event.stopPropagation();
19667        onUp(event);
19668    }
19669
19670    function onDown(event) {
19671        calc(event);
19672        var isResizing = options.resize && (onRightEdge || onBottomEdge || onTopEdge || onLeftEdge);
19673        clicked = {
19674            x: x,
19675            y: y,
19676            cx: event.clientX,
19677            cy: event.clientY,
19678            w: b.width,
19679            h: b.height,
19680            isResizing: isResizing,
19681            isMoving: !isResizing && canMove(),
19682            onTopEdge: onTopEdge,
19683            onLeftEdge: onLeftEdge,
19684            onRightEdge: onRightEdge,
19685            onBottomEdge: onBottomEdge
19686        };
19687    }
19688
19689    function canMove() {
19690        return options.move && x > 0 && x < b.width && y > 0 && y < b.height; // && y < 30;
19691    }
19692
19693    function calc(event) {
19694        b = dom.getBoundingClientRect();
19695        x = event.clientX - b.left;
19696        y = event.clientY - b.top;
19697
19698        onTopEdge = y < MARGINS;
19699        onLeftEdge = x < MARGINS;
19700        onRightEdge = x >= b.width - MARGINS;
19701        onBottomEdge = y >= b.height - MARGINS;
19702
19703        rightScreenEdge = window.innerWidth - MARGINS;
19704        bottomScreenEdge = window.innerHeight - MARGINS;
19705    }
19706
19707    var e;
19708
19709    function onMove(event) {
19710        calc(event);
19711        e = event;
19712        redraw = true;
19713    }
19714
19715    function animate() {
19716        requestAnimationFrame(animate);
19717
19718        if (!redraw) {
19719            return;
19720        }
19721        redraw = false;
19722
19723        if (clicked && clicked.isResizing) {
19724            if (clicked.onRightEdge) {
19725                dom.style.width = Math.max(x, minWidth) + 'px';
19726            }
19727            if (clicked.onBottomEdge) {
19728                dom.style.height = Math.max(y, minHeight) + 'px';
19729            }
19730
19731            if (clicked.onLeftEdge) {
19732                var currentWidth = Math.max(clicked.cx - e.clientX + clicked.w, minWidth);
19733                if (currentWidth > minWidth) {
19734                    dom.style.width = currentWidth + 'px';
19735                    dom.style.removeProperty('right');
19736                    dom.style.left = e.clientX + 'px';
19737                }
19738            }
19739
19740            if (clicked.onTopEdge) {
19741                var currentHeight = Math.max(clicked.cy - e.clientY + clicked.h, minHeight);
19742                if (currentHeight > minHeight) {
19743                    dom.style.height = currentHeight + 'px';
19744                    dom.style.removeProperty('bottom');
19745                    dom.style.top = e.clientY + 'px';
19746                }
19747            }
19748
19749            hintHide();
19750            dom.trigger('resize', { finish: false, el: dom });
19751            return;
19752        }
19753
19754        if (clicked && clicked.isMoving) {
19755            if (options.snap) {
19756                if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
19757                    setBounds(ghostdom, 0, 0, window.innerWidth, window.innerHeight);
19758                    ghostdom.style.opacity = 0.2;
19759                } else if (b.top < MARGINS) {
19760                    setBounds(ghostdom, 0, 0, window.innerWidth, window.innerHeight / 2);
19761                    ghostdom.style.opacity = 0.2;
19762                } else if (b.left < MARGINS) {
19763                    setBounds(ghostdom, 0, 0, window.innerWidth / 2, window.innerHeight);
19764                    ghostdom.style.opacity = 0.2;
19765                } else if (b.right > rightScreenEdge) {
19766                    setBounds(ghostdom, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
19767                    ghostdom.style.opacity = 0.2;
19768                } else if (b.bottom > bottomScreenEdge) {
19769                    setBounds(ghostdom, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
19770                    ghostdom.style.opacity = 0.2;
19771                } else {
19772                    hintHide();
19773                }
19774
19775                if (preSnapped) {
19776                    setBounds(dom, e.clientX - preSnapped.width / 2, e.clientY - Math.min(clicked.y, preSnapped.height), preSnapped.width, preSnapped.height);
19777                    return;
19778                }
19779
19780                // moving
19781                dom.style.removeProperty('right');
19782                dom.style.removeProperty('bottom');
19783                dom.style.top = e.clientY - clicked.y + 'px';
19784                dom.style.left = e.clientX - clicked.x + 'px';
19785            } else {
19786                var _x = e.clientX - clicked.x;
19787                var _y = e.clientY - clicked.y;
19788
19789                if (_x < 0) {
19790                    _x = 0;
19791                } else if (_y < 0) {
19792                    _y = 0;
19793                } else if (_x + dom.offsetWidth > window.innerWidth) {
19794                    _x = window.innerWidth - dom.offsetWidth;
19795                } else if (_y + dom.offsetHeight > window.innerHeight) {
19796                    _y = window.innerHeight - dom.offsetHeight;
19797                }
19798
19799                dom.style.removeProperty('right');
19800                dom.style.removeProperty('bottom');
19801                dom.style.left = _x + 'px';
19802                dom.style.top = _y + 'px';
19803            }
19804
19805            dom.trigger('move', { finish: false, el: dom });
19806            return;
19807        }
19808        // This code executes when mouse moves without clicking
19809
19810        // style cursor
19811        if (options.resize && (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge)) {
19812            dom.style.cursor = 'nwse-resize';
19813        } else if (options.resize && (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge)) {
19814            dom.style.cursor = 'nesw-resize';
19815        } else if (options.resize && (onRightEdge || onLeftEdge)) {
19816            dom.style.cursor = 'ew-resize';
19817        } else if (options.resize && (onBottomEdge || onTopEdge)) {
19818            dom.style.cursor = 'ns-resize';
19819        } else if (canMove()) {
19820            dom.style.cursor = 'move';
19821        } else {
19822            dom.style.cursor = 'default';
19823        }
19824    }
19825    animate();
19826
19827    function onUp(e) {
19828        calc(e);
19829
19830        if (clicked && clicked.isResizing) {
19831            dom.trigger('resize', { finish: true, el: dom });
19832        }
19833
19834        if (options.snap && clicked && clicked.isMoving) {
19835            // Snap
19836            var snapped = {
19837                width: b.width,
19838                height: b.height
19839            };
19840
19841            if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
19842                setBounds(dom, 0, 0, window.innerWidth, window.innerHeight);
19843                preSnapped = snapped;
19844            } else if (b.top < MARGINS) {
19845                setBounds(dom, 0, 0, window.innerWidth, window.innerHeight / 2);
19846                preSnapped = snapped;
19847            } else if (b.left < MARGINS) {
19848                setBounds(dom, 0, 0, window.innerWidth / 2, window.innerHeight);
19849                preSnapped = snapped;
19850            } else if (b.right > rightScreenEdge) {
19851                setBounds(dom, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
19852                preSnapped = snapped;
19853            } else if (b.bottom > bottomScreenEdge) {
19854                setBounds(dom, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
19855                preSnapped = snapped;
19856            } else {
19857                preSnapped = null;
19858            }
19859            hintHide();
19860            dom.trigger('move', { finish: true, el: dom });
19861            dom.trigger('resize', { finish: true, el: dom });
19862        }
19863        clicked = null;
19864    }
19865
19866    dom.snapRight = function () {
19867        var snapped = {
19868            width: dom.width,
19869            height: dom.height
19870        };
19871
19872        setBounds(dom, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
19873        preSnapped = snapped;
19874        // hintHide();
19875        dom.trigger('move', { finish: true, el: dom });
19876        dom.trigger('resize', { finish: true, el: dom });
19877    };
19878
19879    return dom;
19880}
19881
19882},{"./mixin":126}],125:[function(_dereq_,module,exports){
19883/* global MediaRecorder
19884Author: Brett Camper (@professorlemeza)
19885URL: https://github.com/tangrams/tangram/blob/master/src/utils/media_capture.js
19886*/
19887'use strict';
19888
19889var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
19890
19891var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
19892
19893var _Promise = _dereq_('babel-runtime/core-js/promise')['default'];
19894
19895Object.defineProperty(exports, '__esModule', {
19896    value: true
19897});
19898
19899var _urls = _dereq_('./urls');
19900
19901var MediaCapture = (function () {
19902    function MediaCapture() {
19903        _classCallCheck(this, MediaCapture);
19904
19905        this.queueScreenshot = null;
19906        this.videoCapture = null;
19907    }
19908
19909    _createClass(MediaCapture, [{
19910        key: 'setCanvas',
19911        value: function setCanvas(canvas) {
19912            this.canvas = canvas;
19913        }
19914
19915        // Take a screenshot, returns a promise that resolves with the screenshot data when available
19916    }, {
19917        key: 'screenshot',
19918        value: function screenshot() {
19919            var _this = this;
19920
19921            if (this.queueScreenshot != null) {
19922                return this.queueScreenshot.promise; // only capture one screenshot at a time
19923            }
19924
19925            // Will resolve once rendering is complete and render buffer is captured
19926            this.queueScreenshot = {};
19927            this.queueScreenshot.promise = new _Promise(function (resolve, reject) {
19928                _this.queueScreenshot.resolve = resolve;
19929                _this.queueScreenshot.reject = reject;
19930            });
19931            return this.queueScreenshot.promise;
19932        }
19933
19934        // Called after rendering, captures render buffer and resolves promise with the image data
19935    }, {
19936        key: 'completeScreenshot',
19937        value: function completeScreenshot() {
19938            if (this.queueScreenshot != null) {
19939                // Get data URL, convert to blob
19940                // Strip host/mimetype/etc., convert base64 to binary without UTF-8 mangling
19941                // Adapted from: https://gist.github.com/unconed/4370822
19942                var url = this.canvas.toDataURL('image/png');
19943                var data = atob(url.slice(22));
19944                var buffer = new Uint8Array(data.length);
19945                for (var i = 0; i < data.length; ++i) {
19946                    buffer[i] = data.charCodeAt(i);
19947                }
19948                var blob = new Blob([buffer], { type: 'image/png' });
19949
19950                // Resolve with screenshot data
19951                this.queueScreenshot.resolve({ url: url, blob: blob, type: 'png' });
19952                this.queueScreenshot = null;
19953            }
19954        }
19955
19956        // Starts capturing a video stream from the canvas
19957    }, {
19958        key: 'startVideoCapture',
19959        value: function startVideoCapture() {
19960            var _this2 = this;
19961
19962            if (typeof window.MediaRecorder !== 'function' || !this.canvas || typeof this.canvas.captureStream !== 'function') {
19963                console.log('warn: Video capture (Canvas.captureStream and/or MediaRecorder APIs) not supported by browser');
19964                return false;
19965            } else if (this.videoCapture) {
19966                console.log('warn: Video capture already in progress, call Scene.stopVideoCapture() first');
19967                return false;
19968            }
19969
19970            // Start a new capture
19971            try {
19972                (function () {
19973                    var cap = _this2.videoCapture = {};
19974                    cap.chunks = [];
19975                    cap.stream = _this2.canvas.captureStream();
19976                    cap.options = { mimeType: 'video/webm' }; // TODO: support other format options
19977                    cap.mediaRecorder = new MediaRecorder(cap.stream, cap.options);
19978                    cap.mediaRecorder.ondataavailable = function (event) {
19979                        if (event.data.size > 0) {
19980                            cap.chunks.push(event.data);
19981                        }
19982
19983                        // Stopped recording? Create the final capture file blob
19984                        if (cap.resolve) {
19985                            var blob = new Blob(cap.chunks, { type: cap.options.mimeType });
19986                            var url = (0, _urls.createObjectURL)(blob);
19987
19988                            // Explicitly remove all stream tracks, and set objects to null
19989                            if (cap.stream) {
19990                                var tracks = cap.stream.getTracks() || [];
19991                                tracks.forEach(function (track) {
19992                                    track.stop();
19993                                    cap.stream.removeTrack(track);
19994                                });
19995                            }
19996                            cap.stream = null;
19997                            cap.mediaRecorder = null;
19998                            _this2.videoCapture = null;
19999
20000                            cap.resolve({ url: url, blob: blob, type: 'webm' });
20001                        }
20002                    };
20003                    cap.mediaRecorder.start();
20004                })();
20005            } catch (e) {
20006                this.videoCapture = null;
20007                console.log('error: Scene video capture failed', e);
20008                return false;
20009            }
20010            return true;
20011        }
20012
20013        // Stops capturing a video stream from the canvas, returns a promise that resolves with the video when available
20014    }, {
20015        key: 'stopVideoCapture',
20016        value: function stopVideoCapture() {
20017            var _this3 = this;
20018
20019            if (!this.videoCapture) {
20020                console.log('warn: No scene video capture in progress, call Scene.startVideoCapture() first');
20021                return _Promise.resolve({});
20022            }
20023
20024            // Promise that will resolve when final stream is available
20025            this.videoCapture.promise = new _Promise(function (resolve, reject) {
20026                _this3.videoCapture.resolve = resolve;
20027                _this3.videoCapture.reject = reject;
20028            });
20029
20030            // Stop recording
20031            this.videoCapture.mediaRecorder.stop();
20032
20033            return this.videoCapture.promise;
20034        }
20035    }]);
20036
20037    return MediaCapture;
20038})();
20039
20040exports['default'] = MediaCapture;
20041module.exports = exports['default'];
20042
20043},{"./urls":127,"babel-runtime/core-js/promise":8,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],126:[function(_dereq_,module,exports){
20044/*
20045Add events to a class or object:
20046    class MyClass {
20047        constructor() {
20048            subscribeMixin(this); // Add the mixing functions to the class
20049            ...
20050            this.trigger('something', { owner: this, content: 'that'}); // trigger an event passing some arguments
20051
20052Subscribe to events by doing:
20053    myClass.on('something', (args) => {
20054        console.log(args);
20055    });
20056
20057Unsubscribe to events by doing:
20058    myClass.off('something');
20059
20060or more presicelly:
20061    myClass.off('something', (args) => {
20062        console.log(args);
20063    });
20064
20065Unsubscribe to all events by:
20066    myClass.offAll();
20067*/
20068
20069'use strict';
20070
20071var _Set = _dereq_('babel-runtime/core-js/set')['default'];
20072
20073var _Object$assign = _dereq_('babel-runtime/core-js/object/assign')['default'];
20074
20075var _getIterator = _dereq_('babel-runtime/core-js/get-iterator')['default'];
20076
20077var _Object$keys = _dereq_('babel-runtime/core-js/object/keys')['default'];
20078
20079Object.defineProperty(exports, '__esModule', {
20080    value: true
20081});
20082exports.subscribeMixin = subscribeMixin;
20083
20084function subscribeMixin(target) {
20085    var listeners = new _Set();
20086
20087    return _Object$assign(target, {
20088
20089        on: function on(type, f) {
20090            var listener = {};
20091            listener[type] = f;
20092            listeners.add(listener);
20093        },
20094
20095        off: function off(type, f) {
20096            if (f) {
20097                var listener = {};
20098                listener[type] = f;
20099                listeners['delete'](listener);
20100            } else {
20101                var _iteratorNormalCompletion = true;
20102                var _didIteratorError = false;
20103                var _iteratorError = undefined;
20104
20105                try {
20106                    for (var _iterator = _getIterator(listeners), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
20107                        var item = _step.value;
20108                        var _iteratorNormalCompletion2 = true;
20109                        var _didIteratorError2 = false;
20110                        var _iteratorError2 = undefined;
20111
20112                        try {
20113                            for (var _iterator2 = _getIterator(_Object$keys(item)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
20114                                var key = _step2.value;
20115
20116                                if (key === type) {
20117                                    listeners['delete'](item);
20118                                    return;
20119                                }
20120                            }
20121                        } catch (err) {
20122                            _didIteratorError2 = true;
20123                            _iteratorError2 = err;
20124                        } finally {
20125                            try {
20126                                if (!_iteratorNormalCompletion2 && _iterator2['return']) {
20127                                    _iterator2['return']();
20128                                }
20129                            } finally {
20130                                if (_didIteratorError2) {
20131                                    throw _iteratorError2;
20132                                }
20133                            }
20134                        }
20135                    }
20136                } catch (err) {
20137                    _didIteratorError = true;
20138                    _iteratorError = err;
20139                } finally {
20140                    try {
20141                        if (!_iteratorNormalCompletion && _iterator['return']) {
20142                            _iterator['return']();
20143                        }
20144                    } finally {
20145                        if (_didIteratorError) {
20146                            throw _iteratorError;
20147                        }
20148                    }
20149                }
20150            }
20151        },
20152
20153        offAll: function offAll() {
20154            listeners.clear();
20155        },
20156
20157        trigger: function trigger(event) {
20158            var _iteratorNormalCompletion3 = true;
20159            var _didIteratorError3 = false;
20160            var _iteratorError3 = undefined;
20161
20162            try {
20163                for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
20164                    data[_key - 1] = arguments[_key];
20165                }
20166
20167                for (var _iterator3 = _getIterator(listeners), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
20168                    var listener = _step3.value;
20169
20170                    if (typeof listener[event] === 'function') {
20171                        listener[event].apply(listener, data);
20172                    }
20173                }
20174            } catch (err) {
20175                _didIteratorError3 = true;
20176                _iteratorError3 = err;
20177            } finally {
20178                try {
20179                    if (!_iteratorNormalCompletion3 && _iterator3['return']) {
20180                        _iterator3['return']();
20181                    }
20182                } finally {
20183                    if (_didIteratorError3) {
20184                        throw _iteratorError3;
20185                    }
20186                }
20187            }
20188        },
20189
20190        listSubscriptions: function listSubscriptions() {
20191            var _iteratorNormalCompletion4 = true;
20192            var _didIteratorError4 = false;
20193            var _iteratorError4 = undefined;
20194
20195            try {
20196                for (var _iterator4 = _getIterator(listeners), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
20197                    var item = _step4.value;
20198
20199                    console.log(item);
20200                }
20201            } catch (err) {
20202                _didIteratorError4 = true;
20203                _iteratorError4 = err;
20204            } finally {
20205                try {
20206                    if (!_iteratorNormalCompletion4 && _iterator4['return']) {
20207                        _iterator4['return']();
20208                    }
20209                } finally {
20210                    if (_didIteratorError4) {
20211                        throw _iteratorError4;
20212                    }
20213                }
20214            }
20215        }
20216    });
20217}
20218
20219},{"babel-runtime/core-js/get-iterator":1,"babel-runtime/core-js/object/assign":2,"babel-runtime/core-js/object/keys":6,"babel-runtime/core-js/set":9}],127:[function(_dereq_,module,exports){
20220'use strict';
20221
20222Object.defineProperty(exports, '__esModule', {
20223    value: true
20224});
20225exports.createObjectURL = createObjectURL;
20226var _createObjectURL = undefined;
20227
20228function createObjectURL(url) {
20229    if (_createObjectURL === undefined) {
20230        _createObjectURL = window.URL && window.URL.createObjectURL || window.webkitURL && window.webkitURL.createObjectURL;
20231        if (typeof _createObjectURL !== 'function') {
20232            _createObjectURL = null;
20233            console.log('window.URL.createObjectURL (or vendor prefix) not found, unable to create local blob URLs');
20234        }
20235    }
20236
20237    if (_createObjectURL) {
20238        return _createObjectURL(url);
20239    } else {
20240        return url;
20241    }
20242}
20243
20244},{}],128:[function(_dereq_,module,exports){
20245'use strict';
20246
20247var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
20248
20249var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20250
20251Object.defineProperty(exports, '__esModule', {
20252    value: true
20253});
20254
20255var ErrorsDisplay = (function () {
20256    function ErrorsDisplay(main) {
20257        var _this = this;
20258
20259        _classCallCheck(this, ErrorsDisplay);
20260
20261        this.main = main;
20262
20263        //  private variables
20264        this.widgets = [];
20265
20266        // EVENTS
20267        this.main.shader.canvas.on('error', function (arg) {
20268            if (_this.main.visualDebugger && _this.main.visualDebugger.testing) {
20269                _this.clean();
20270            } else {
20271                _this.clean();
20272                _this.addError(arg);
20273            }
20274        });
20275
20276        this.main.editor.on('changes', function (cm, changesObjs) {
20277            if (_this.main.shader.canvas.isValid) {
20278                _this.clean();
20279            }
20280        });
20281    }
20282
20283    _createClass(ErrorsDisplay, [{
20284        key: 'clean',
20285        value: function clean() {
20286            for (var i = 0; i < this.widgets.length; i++) {
20287                this.main.editor.removeLineWidget(this.widgets[i]);
20288            }
20289            this.widgets.length = 0;
20290        }
20291    }, {
20292        key: 'addError',
20293        value: function addError(args) {
20294            var re = /ERROR:\s+\d+:(\d+):\s+('.*)/g;
20295            var matches = re.exec(args.error);
20296            if (matches) {
20297                var numLines = 0;
20298                if (this.main.options.frag_header.length > 0) numLines += (this.main.options.frag_header.match(/\r?\n/g) || '').length;
20299
20300                var line = parseInt(matches[1]) - numLines;
20301                var er = matches[2];
20302                var msg = document.createElement('div');
20303
20304                var icon = msg.appendChild(document.createElement('span'));
20305                icon.className = 'ge-error-icon';
20306                icon.innerHTML = 'x';
20307                msg.appendChild(document.createTextNode(er));
20308                msg.className = 'ge-error';
20309                this.widgets.push(this.main.editor.addLineWidget(line, msg)); //, { coverGutter: false, noHScroll: true }));
20310            }
20311        }
20312    }]);
20313
20314    return ErrorsDisplay;
20315})();
20316
20317exports['default'] = ErrorsDisplay;
20318module.exports = exports['default'];
20319
20320},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],129:[function(_dereq_,module,exports){
20321'use strict';
20322
20323var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20324
20325var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
20326
20327Object.defineProperty(exports, '__esModule', {
20328    value: true
20329});
20330
20331var _modalsExportModal = _dereq_('./modals/ExportModal');
20332
20333var _modalsExportModal2 = _interopRequireDefault(_modalsExportModal);
20334
20335var ExportIcon = function ExportIcon(main) {
20336    var _this = this;
20337
20338    _classCallCheck(this, ExportIcon);
20339
20340    this.main = main;
20341
20342    this.el = document.createElement('div');
20343    this.el.setAttribute('class', 'ge_export_icon');
20344    this.el.innerHTML = '△';
20345    // this.el.innerHTML = '<i class="material-icons">more_vert</i>';
20346    this.el.addEventListener('click', function (event) {
20347        if (main.change || !_this.modal) {
20348            _this.modal = new _modalsExportModal2['default']('ge_export', { main: main });
20349        }
20350        _this.modal.presentModal(event.target.offsetLeft, event.target.offsetTop);
20351    }, true);
20352
20353    this.main.container.appendChild(this.el);
20354};
20355
20356exports['default'] = ExportIcon;
20357module.exports = exports['default'];
20358
20359},{"./modals/ExportModal":134,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/interop-require-default":14}],130:[function(_dereq_,module,exports){
20360'use strict';
20361
20362var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
20363
20364var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20365
20366var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
20367
20368Object.defineProperty(exports, '__esModule', {
20369    value: true
20370});
20371
20372var _pickersColorPicker = _dereq_('./pickers/ColorPicker');
20373
20374var _pickersColorPicker2 = _interopRequireDefault(_pickersColorPicker);
20375
20376var _pickersVec3Picker = _dereq_('./pickers/Vec3Picker');
20377
20378var _pickersVec3Picker2 = _interopRequireDefault(_pickersVec3Picker);
20379
20380var _pickersVec2Picker = _dereq_('./pickers/Vec2Picker');
20381
20382var _pickersVec2Picker2 = _interopRequireDefault(_pickersVec2Picker);
20383
20384var _pickersFloatPicker = _dereq_('./pickers/FloatPicker');
20385
20386var _pickersFloatPicker2 = _interopRequireDefault(_pickersFloatPicker);
20387
20388var _pickersTypesColor = _dereq_('./pickers/types/Color');
20389
20390var _pickersTypesColor2 = _interopRequireDefault(_pickersTypesColor);
20391
20392var _modalsModal = _dereq_('./modals/Modal');
20393
20394var _modalsModal2 = _interopRequireDefault(_modalsModal);
20395
20396// Return all pattern matches with captured groups
20397RegExp.prototype.execAll = function (string) {
20398    var match = null;
20399    var matches = [];
20400    while (match = this.exec(string)) {
20401        var matchArray = [];
20402        for (var i in match) {
20403            if (parseInt(i) == i) {
20404                matchArray.push(match[i]);
20405            }
20406        }
20407        matchArray.index = match.index;
20408        matches.push(matchArray);
20409    }
20410    return matches;
20411};
20412
20413var Helpers = (function () {
20414    function Helpers(main) {
20415        var _this = this;
20416
20417        _classCallCheck(this, Helpers);
20418
20419        this.main = main;
20420        this.main.debugging = false;
20421
20422        var style = window.getComputedStyle(main.editor.getWrapperElement(), null);
20423        var bgColor = new _pickersTypesColor2['default'](style.background !== '' ? style.background : style.backgroundColor);
20424        var fgColor = new _pickersTypesColor2['default'](style.color);
20425
20426        this.properties = {
20427            bgColor: bgColor.getString('rgb'),
20428            fnColor: fgColor.getString('rgb'),
20429            dimColor: 'rgb(127, 127, 127)',
20430            selColor: 'rgb(40, 168, 107)',
20431            linkButton: true
20432        };
20433
20434        // EVENTS
20435        var wrapper = this.main.editor.getWrapperElement();
20436        wrapper.addEventListener('contextmenu', function (event) {
20437            var cursor = _this.main.editor.getCursor(true);
20438            var token = _this.main.editor.getTokenAt(cursor);
20439            if (token.type === 'variable') {
20440                _this.main.visualDebugger.debug(token.string, cursor.line);
20441            } else {
20442                _this.main.update();
20443            }
20444        });
20445
20446        wrapper.addEventListener('mouseup', function (event) {
20447            // bail out if we were doing a selection and not a click
20448            if (_this.main.editor.somethingSelected()) {
20449                return;
20450            }
20451
20452            var cursor = _this.main.editor.getCursor(true);
20453
20454            // see if there is a match on the cursor click
20455            var match = _this.getMatch(cursor);
20456            var token = _this.main.editor.getTokenAt(cursor);
20457            if (match) {
20458                _this.main.visualDebugger.clean(event);
20459                _this.main.update();
20460
20461                // Toggles the trackpad to be off if it's already present.
20462                if (_this.activeModal && _this.activeModal.isVisible) {
20463                    _this.activeModal.removeModal();
20464                    return;
20465                }
20466
20467                if (match.type === 'color') {
20468                    _this.activeModal = new _pickersColorPicker2['default'](match.string, _this.properties);
20469                    _this.activeModal.showAt(_this.main.editor);
20470                    _this.activeModal.on('changed', function (color) {
20471                        var newColor = color.getString('vec');
20472                        var start = { line: cursor.line, ch: match.start };
20473                        var end = { line: cursor.line, ch: match.end };
20474                        match.end = match.start + newColor.length;
20475                        _this.main.editor.replaceRange(newColor, start, end, '+' + match.type);
20476                    });
20477
20478                    _this.activeModal.on('linkButton', function (color) {
20479                        _this.activeModal = new _pickersVec3Picker2['default'](color.getString('vec'), _this.properties);
20480                        _this.activeModal.showAt(_this.main.editor);
20481                        _this.activeModal.on('changed', function (dir) {
20482                            var newDir = dir.getString('vec3');
20483                            var start = { line: cursor.line, ch: match.start };
20484                            var end = { line: cursor.line, ch: match.end };
20485                            match.end = match.start + newDir.length;
20486                            _this.main.editor.replaceRange(newDir, start, end, '+' + match.type);
20487                        });
20488                    });
20489                }
20490                if (match.type === 'vec3') {
20491                    _this.activeModal = new _pickersVec3Picker2['default'](match.string, _this.properties);
20492                    _this.activeModal.showAt(_this.main.editor);
20493                    _this.activeModal.on('changed', function (dir) {
20494                        var newDir = dir.getString('vec3');
20495                        var start = { line: cursor.line, ch: match.start };
20496                        var end = { line: cursor.line, ch: match.end };
20497                        match.end = match.start + newDir.length;
20498                        _this.main.editor.replaceRange(newDir, start, end, '+' + match.type);
20499                    });
20500                } else if (match.type === 'vec2') {
20501                    _this.activeModal = new _pickersVec2Picker2['default'](match.string, _this.properties);
20502                    _this.activeModal.showAt(_this.main.editor);
20503                    _this.activeModal.on('changed', function (pos) {
20504                        var newpos = pos.getString();
20505                        var start = { line: cursor.line, ch: match.start };
20506                        var end = { line: cursor.line, ch: match.end };
20507                        match.end = match.start + newpos.length;
20508                        _this.main.editor.replaceRange(newpos, start, end, '+' + match.type);
20509                    });
20510                } else if (match.type === 'number') {
20511                    _this.activeModal = new _pickersFloatPicker2['default'](match.string, _this.properties);
20512                    _this.activeModal.showAt(_this.main.editor);
20513                    _this.activeModal.on('changed', function (number) {
20514                        var newNumber = number.getString();
20515                        var start = { line: cursor.line, ch: match.start };
20516                        var end = { line: cursor.line, ch: match.end };
20517                        match.end = match.start + newNumber.length;
20518                        _this.main.editor.replaceRange(newNumber, start, end, '+' + match.type);
20519                    });
20520                }
20521            } else if (_this.main.options.tooltips && (token.type === 'builtin' || token.type === 'variable-3')) {
20522                _this.main.visualDebugger.clean(event);
20523                var html = '<p>Learn more about: <a href="https://thebookofshaders.com/glossary/?search=' + token.string + '" target="_blank">' + token.string + '</a></p>';
20524                _this.activeModal = new _modalsModal2['default']('ge_tooltip', { innerHTML: html });
20525                _this.activeModal.showAt(_this.main.editor);
20526            } else if (token.type === 'variable') {
20527                if (_this.main.visualDebugger) {
20528                    _this.main.visualDebugger.clean(event);
20529                    _this.main.visualDebugger.iluminate(token.string);
20530                }
20531            }
20532        });
20533    }
20534
20535    _createClass(Helpers, [{
20536        key: 'getMatch',
20537        value: function getMatch(cursor) {
20538            var types = ['color', 'vec3', 'vec2', 'number'];
20539            var rta = undefined;
20540            for (var i in types) {
20541                rta = this.getTypeMatch(cursor, types[i]);
20542                if (rta) {
20543                    return rta;
20544                }
20545            }
20546            return;
20547        }
20548    }, {
20549        key: 'getTypeMatch',
20550        value: function getTypeMatch(cursor, type) {
20551            if (!type) {
20552                return;
20553            }
20554            var re = undefined;
20555            switch (type.toLowerCase()) {
20556                case 'color':
20557                    re = /vec[3|4]\([\d|.|,\s]*\)/g;
20558                    break;
20559                case 'vec3':
20560                    re = /vec3\([-|\d|.|,\s]*\)/g;
20561                    break;
20562                case 'vec2':
20563                    re = /vec2\([-|\d|.|,\s]*\)/g;
20564                    break;
20565                case 'number':
20566                    re = /[-]?\d+\.\d+|\d+\.|\.\d+/g;
20567                    break;
20568                default:
20569                    console.error('invalid match selection');
20570                    return;
20571            }
20572            var line = this.main.editor.getLine(cursor.line);
20573            var matches = re.execAll(line);
20574
20575            if (matches) {
20576                for (var i = 0; i < matches.length; i++) {
20577                    var val = matches[i][0];
20578                    var len = val.length;
20579                    var start = matches[i].index;
20580                    var end = matches[i].index + len;
20581                    if (cursor.ch >= start && cursor.ch <= end) {
20582                        return {
20583                            type: type,
20584                            start: start,
20585                            end: end,
20586                            string: val
20587                        };
20588                    }
20589                }
20590            }
20591            return;
20592        }
20593    }]);
20594
20595    return Helpers;
20596})();
20597
20598exports['default'] = Helpers;
20599module.exports = exports['default'];
20600
20601},{"./modals/Modal":135,"./pickers/ColorPicker":136,"./pickers/FloatPicker":137,"./pickers/Vec2Picker":139,"./pickers/Vec3Picker":140,"./pickers/types/Color":141,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14}],131:[function(_dereq_,module,exports){
20602'use strict';
20603
20604var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20605
20606var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
20607
20608Object.defineProperty(exports, '__esModule', {
20609    value: true
20610});
20611
20612var _MenuItem = _dereq_('./MenuItem');
20613
20614var _MenuItem2 = _interopRequireDefault(_MenuItem);
20615
20616var _modalsExportModal = _dereq_('./modals/ExportModal');
20617
20618var _modalsExportModal2 = _interopRequireDefault(_modalsExportModal);
20619
20620var Menu = function Menu(main) {
20621    var _this = this;
20622
20623    _classCallCheck(this, Menu);
20624
20625    this.main = main;
20626    this.menus = {};
20627
20628    // CREATE MENU Container
20629    this.el = document.createElement('ul');
20630    this.el.setAttribute('class', 'ge_menu_bar');
20631
20632    // NEW
20633    this.menus['new'] = new _MenuItem2['default'](this.el, 'ge_menu', '<i class="material-icons">add</i> New', function (event) {
20634        main['new']();
20635    });
20636
20637    // OPEN
20638    this.fileInput = document.createElement('input');
20639    this.fileInput.setAttribute('type', 'file');
20640    this.fileInput.setAttribute('accept', 'text/x-yaml');
20641    this.fileInput.style.display = 'none';
20642    this.fileInput.addEventListener('change', function (event) {
20643        main.open(event.target.files[0]);
20644    });
20645    this.menus.open = new _MenuItem2['default'](this.el, 'ge_menu', '<i class="material-icons">folder_open</i>  Open', function (event) {
20646        _this.fileInput.click();
20647    });
20648
20649    // this.menus.autoupdate.button.style.color = main.autoupdate ? 'white' : 'gray';
20650
20651    // TEST
20652    this.menus.test = new _MenuItem2['default'](this.el, 'ge_menu', '<i class="material-icons">timeline</i> Test', function (event) {
20653        main.visualDebugger.check();
20654    });
20655
20656    // SHARE
20657    this.menus.share = new _MenuItem2['default'](this.el, 'ge_menu', '<i class="material-icons">arrow_upward</i> Export', function (event) {
20658        if (main.change || !_this.exportModal) {
20659            _this.exportModal = new _modalsExportModal2['default']('ge_export', { main: main, position: 'fixed' });
20660        }
20661
20662        var bbox = _this.menus.share.el.getBoundingClientRect();
20663        _this.exportModal.presentModal(bbox.left - 5, bbox.top + bbox.height + 5);
20664    });
20665
20666    // AUTOUPDATE
20667    this.menus.autoupdate = new _MenuItem2['default'](this.el, 'ge_menu', ' <i class="material-icons">autorenew</i> Update: ON', function (event) {
20668        if (main.autoupdate) {
20669            main.autoupdate = false;
20670            _this.menus.autoupdate.name = '<i class="material-icons">autorenew</i> Update: OFF';
20671            // this.menus.autoupdate.button.style.color = 'gray';
20672        } else {
20673                main.autoupdate = true;
20674                main.update();
20675                _this.menus.autoupdate.name = '<i class="material-icons">autorenew</i> Update: ON';
20676                // this.menus.autoupdate.button.style.color = 'white';
20677            }
20678    });
20679
20680    main.container.appendChild(this.el);
20681};
20682
20683exports['default'] = Menu;
20684module.exports = exports['default'];
20685
20686},{"./MenuItem":132,"./modals/ExportModal":134,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/interop-require-default":14}],132:[function(_dereq_,module,exports){
20687'use strict';
20688
20689var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
20690
20691var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20692
20693Object.defineProperty(exports, '__esModule', {
20694    value: true
20695});
20696
20697var MenuItem = (function () {
20698    function MenuItem(container, className, name, onClick) {
20699        _classCallCheck(this, MenuItem);
20700
20701        this.el = document.createElement('li');
20702        this.button = document.createElement('button');
20703        this.button.className = className + '_button';
20704        this.el.appendChild(this.button);
20705        this.el.setAttribute('class', className);
20706        this.button.innerHTML = name;
20707        this.className = className;
20708        this.hiddenClass = className + '--hidden';
20709
20710        // Attach listeners, including those for tooltip behavior
20711        this.button.addEventListener('click', onClick, true);
20712
20713        if (container) {
20714            container.appendChild(this.el);
20715        }
20716    }
20717
20718    _createClass(MenuItem, [{
20719        key: 'hide',
20720        value: function hide() {
20721            this.el.setAttribute('class', this.className + ' ' + this.hiddenClass);
20722        }
20723    }, {
20724        key: 'show',
20725        value: function show() {
20726            this.el.setAttribute('class', this.className);
20727        }
20728    }, {
20729        key: 'name',
20730        set: function set(name) {
20731            this.button.innerHTML = name;
20732        }
20733    }]);
20734
20735    return MenuItem;
20736})();
20737
20738exports['default'] = MenuItem;
20739module.exports = exports['default'];
20740
20741},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],133:[function(_dereq_,module,exports){
20742'use strict';
20743
20744var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
20745
20746var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
20747
20748Object.defineProperty(exports, '__esModule', {
20749    value: true
20750});
20751
20752var _toolsDebugging = _dereq_('../tools/debugging');
20753
20754var _coreEditorJs = _dereq_('../core/Editor.js');
20755
20756var mainGE = {};
20757var N_SAMPLES = 30;
20758
20759var VisualDebugger = (function () {
20760    function VisualDebugger(main) {
20761        var _this = this;
20762
20763        _classCallCheck(this, VisualDebugger);
20764
20765        this.main = main;
20766        this.breakpoint = null;
20767        mainGE = main;
20768
20769        this.testing = false;
20770        this.testingFrag = '';
20771        this.testingLine = 0;
20772        this.testingResults = [];
20773        this.testingSamples = [];
20774
20775        this.main.editor.on('gutterClick', function (cm, n) {
20776            var info = cm.lineInfo(n);
20777            if (info && info.gutterMarkers && info.gutterMarkers.breakpoints) {
20778                // Check for an active variable (a variable that have been declare or modify in this line)
20779                var variableRE = new RegExp('\\s*[float|vec2|vec3|vec4]?\\s+([\\w|\\_]*)[\\.\\w]*?\\s+[\\+|\\-|\\\\|\\*]?\\=', 'i');
20780                var match = variableRE.exec(info.text);
20781                if (match) {
20782                    _this.debug(match[1], info.line);
20783                    _this.breakpoint = info.line;
20784                }
20785            }
20786        });
20787    }
20788
20789    _createClass(VisualDebugger, [{
20790        key: 'check',
20791        value: function check() {
20792            // Clean previus records
20793            this.testingResults = [];
20794
20795            var cm = this.main.editor;
20796            var nLines = cm.getDoc().size;
20797
20798            var mainStartsAt = 0;
20799            for (var i = 0; i < nLines; i++) {
20800                if ((0, _toolsDebugging.isLineAfterMain)(cm, i)) {
20801                    mainStartsAt = i;
20802                    break;
20803                }
20804            }
20805            this.testLine(mainStartsAt);
20806        }
20807    }, {
20808        key: 'testLine',
20809        value: function testLine(nLine) {
20810            var cm = mainGE.editor;
20811            var visualDebugger = mainGE.visualDebugger;
20812
20813            // If is done testing...
20814            if (nLine >= cm.getDoc().size) {
20815                visualDebugger.testingLine = 0;
20816                visualDebugger.testing = false;
20817
20818                var results = visualDebugger.testingResults;
20819                var range = (0, _toolsDebugging.getResultRange)(results);
20820                var sum = (0, _toolsDebugging.getDeltaSum)(results);
20821                var hits = (0, _toolsDebugging.getHits)(results);
20822
20823                console.log('Test: ', range.max.ms + 'ms', results);
20824                cm.clearGutter('breakpoints');
20825                for (var i in results) {
20826                    var pct = results[i].delta / sum * 100;
20827                    var size = results[i].delta / sum * 30;
20828                    var markerHTML = '<div>' + results[i].ms.toFixed(2);
20829                    if (results[i].delta > 0.) {
20830                        markerHTML += '<span class="ge_assing_marker_pct ';
20831                        if (pct > 100.0 / hits) {
20832                            markerHTML += 'ge_assing_marker_slower';
20833                        }
20834                        markerHTML += '" style="width: ' + size.toFixed(0) + 'px;" data="' + pct.toFixed(0) + '%"></span>';
20835                    }
20836
20837                    cm.setGutterMarker(results[i].line, 'breakpoints', makeMarker(markerHTML + '</div>'));
20838                }
20839                return;
20840            }
20841
20842            if ((0, _toolsDebugging.isLineAfterMain)(cm, nLine)) {
20843                // If the line is inside the main function
20844                var shader = mainGE.shader.canvas;
20845
20846                // Check for an active variable (a variable that have been declare or modify in this line)
20847                var variableRE = new RegExp('\\s*[float|vec2|vec3|vec4]?\\s+([\\w|\\_]*)[\\.\\w]*?\\s+[\\+|\\-|\\\\|\\*]?\\=', 'i');
20848                var match = variableRE.exec(cm.getLine(nLine));
20849                if (match) {
20850                    // if there is an active variable, get what type is
20851                    var variable = match[1];
20852                    var type = (0, _toolsDebugging.getVariableType)(cm, variable);
20853                    if (type === 'none') {
20854                        // If it fails on finding the type keep going with the test on another line
20855                        visualDebugger.testLine(nLine + 1);
20856                        return;
20857                    }
20858
20859                    // Prepare
20860                    visualDebugger.testing = true;
20861                    visualDebugger.testingLine = nLine;
20862                    visualDebugger.testingFrag = (0, _toolsDebugging.getShaderForTypeVarInLine)(cm, type, variable, nLine);
20863                    visualDebugger.testingSamples = [];
20864
20865                    (0, _coreEditorJs.unfocusAll)(cm);
20866                    (0, _coreEditorJs.focusLine)(cm, nLine);
20867                    mainGE.debugging = true;
20868
20869                    shader.test(this.onTest, visualDebugger.testingFrag);
20870                } else {
20871                    visualDebugger.testLine(nLine + 1);
20872                }
20873            } else {
20874                // If the line is not inside main function, test the next one...
20875                visualDebugger.testLine(nLine + 1);
20876            }
20877        }
20878    }, {
20879        key: 'onTest',
20880        value: function onTest(target) {
20881            var cm = mainGE.editor;
20882            var shader = mainGE.shader.canvas;
20883            var visualDebugger = mainGE.visualDebugger;
20884
20885            // If the test shader compiled...
20886            if (target.wasValid) {
20887                // get data, process and store.
20888                var elapsedMs = target.timeElapsedMs;
20889
20890                if (visualDebugger.testingSamples.length < N_SAMPLES - 1) {
20891                    visualDebugger.testingSamples.push(elapsedMs);
20892                    shader.test(visualDebugger.onTest, visualDebugger.testingFrag);
20893                } else {
20894                    (0, _coreEditorJs.focusAll)(cm);
20895                    mainGE.debugging = false;
20896                    visualDebugger.testingSamples.push(elapsedMs);
20897                    elapsedMs = (0, _toolsDebugging.getMedian)(visualDebugger.testingSamples);
20898
20899                    var range = (0, _toolsDebugging.getResultRange)(visualDebugger.testingResults);
20900                    var delta = elapsedMs - range.max.ms;
20901                    if (visualDebugger.testingResults.length === 0) {
20902                        delta = 0.0;
20903                    }
20904                    visualDebugger.testingResults.push({ line: visualDebugger.testingLine, ms: target.timeElapsedMs, delta: delta });
20905                    // console.log('Testing line:', visualDebugger.testingLine, elapsedMs, delta, range);
20906
20907                    // Create gutter marker
20908                    cm.setGutterMarker(visualDebugger.testingLine, 'breakpoints', makeMarker(elapsedMs.toFixed(2)));
20909
20910                    // Test next line
20911                    visualDebugger.testLine(visualDebugger.testingLine + 1);
20912                };
20913            } else {
20914                console.log(target);
20915                // Test next line
20916                visualDebugger.testLine(visualDebugger.testingLine + 1);
20917            }
20918        }
20919    }, {
20920        key: 'debug',
20921        value: function debug(variable, nLine) {
20922            (0, _coreEditorJs.focusAll)(this.main.editor);
20923            this.main.debugging = false;
20924
20925            if ((0, _toolsDebugging.isLineAfterMain)(this.main.editor, nLine)) {
20926                var type = (0, _toolsDebugging.getVariableType)(this.main.editor, variable);
20927                if (type !== 'none') {
20928                    event.preventDefault();
20929                    this.main.shader.canvas.load((0, _toolsDebugging.getShaderForTypeVarInLine)(this.main.editor, type, variable, nLine));
20930                    (0, _coreEditorJs.unfocusAll)(this.main.editor);
20931                    (0, _coreEditorJs.focusLine)(this.main.editor, nLine);
20932                    this.main.debugging = true;
20933                }
20934            } else {
20935                this.main.update();
20936            }
20937        }
20938    }, {
20939        key: 'iluminate',
20940        value: function iluminate(variable) {
20941            if (this.main.debbuging && this.variable === this.variable) {
20942                return;
20943            }
20944            // this.clean();
20945
20946            var cm = this.main.editor;
20947
20948            // Highlight all calls to a variable
20949            this.overlay = searchOverlay(variable, true);
20950            cm.addOverlay(this.overlay);
20951            if (cm.showMatchesOnScrollbar) {
20952                if (this.annotate) {
20953                    this.annotate.clear();this.annotate = null;
20954                }
20955                this.annotate = cm.showMatchesOnScrollbar(variable, true);
20956            }
20957        }
20958    }, {
20959        key: 'clean',
20960        value: function clean(event) {
20961            if (event && event.target && event.target.className === 'ge_assing_marker') {
20962                return;
20963            }
20964
20965            var cm = this.main.editor;
20966            cm.clearGutter('breakpoints');
20967            if (this.overlay) {
20968                cm.removeOverlay(this.overlay, true);
20969            }
20970            this.type = null;
20971            if (this.main.debbuging) {
20972                this.main.shader.canvas.load(this.main.options.frag_header + this.main.editor.getValue() + this.main.options.frag_footer);
20973            }
20974            this.main.debbuging = false;
20975        }
20976    }]);
20977
20978    return VisualDebugger;
20979})();
20980
20981exports['default'] = VisualDebugger;
20982
20983function makeMarker(html, extraClass) {
20984    var marker = document.createElement('div');
20985    marker.setAttribute('class', 'ge_assing_marker');
20986    marker.innerHTML = html;
20987    return marker;
20988}
20989
20990function searchOverlay(query, caseInsensitive) {
20991    if (typeof query === 'string') {
20992        query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), caseInsensitive ? 'gi' : 'g');
20993    } else if (!query.global) {
20994        query = new RegExp(query.source, query.ignoreCase ? 'gi' : 'g');
20995    }
20996
20997    return {
20998        token: function token(stream) {
20999            query.lastIndex = stream.pos;
21000            var match = query.exec(stream.string);
21001            if (match && match.index === stream.pos) {
21002                stream.pos += match[0].length || 1;
21003                return 'searching';
21004            } else if (match) {
21005                stream.pos = match.index;
21006            } else {
21007                stream.skipToEnd();
21008            }
21009        }
21010    };
21011}
21012module.exports = exports['default'];
21013
21014},{"../core/Editor.js":115,"../tools/debugging":122,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],134:[function(_dereq_,module,exports){
21015'use strict';
21016
21017var _get = _dereq_('babel-runtime/helpers/get')['default'];
21018
21019var _inherits = _dereq_('babel-runtime/helpers/inherits')['default'];
21020
21021var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
21022
21023var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
21024
21025Object.defineProperty(exports, '__esModule', {
21026    value: true
21027});
21028
21029var _MenuItem = _dereq_('../MenuItem');
21030
21031var _MenuItem2 = _interopRequireDefault(_MenuItem);
21032
21033var _Modal2 = _dereq_('./Modal');
21034
21035var _Modal3 = _interopRequireDefault(_Modal2);
21036
21037// import { saveOnServer, createOpenFrameArtwork } from '../../io/share';
21038
21039var ExportModal = (function (_Modal) {
21040    _inherits(ExportModal, _Modal);
21041
21042    function ExportModal(CSS_PREFIX, properties) {
21043        _classCallCheck(this, ExportModal);
21044
21045        _get(Object.getPrototypeOf(ExportModal.prototype), 'constructor', this).call(this, CSS_PREFIX, properties);
21046        this.main = properties.main;
21047
21048        this.save = new _MenuItem2['default'](this.el, 'ge_sub_menu', 'Download file', function (event) {
21049            properties.main.download();
21050        });
21051
21052        // this.codeURL = new MenuItem(this.el, 'ge_sub_menu', 'Code URL...', (event) => {
21053        //     saveOnServer(this.main, (event) => {
21054        //         prompt('Use this url to share your code', 'http://thebookofshaders.com/edit.php?log=' + event.name);
21055        //         this.removeModal();
21056        //     });
21057        // });
21058
21059        // this.shaderURL = new MenuItem(this.el, 'ge_sub_menu', 'Artwork URL...', (event) => {
21060        //     saveOnServer(this.main, (event) => {
21061        //         prompt('Use this url to share your artwork', 'http://player.thebookofshaders.com/?log=' + event.name);
21062        //         this.removeModal();
21063        //     });
21064        // });
21065
21066        // let shareOF = new MenuItem(this.el, 'ge_sub_menu', 'Artwork to [o]', (event) => {
21067        //     shareOF.el.innerHTML = 'Artwork to [o]: adding to collection';
21068        //     saveOnServer(this.main, (event) => {
21069        //         createOpenFrameArtwork(this.main, event.name, event.url, (success) => {
21070        //             if (success) {
21071        //                 shareOF.el.innerHTML = 'Artwork to [o]: added!';
21072        //             }
21073        //             else {
21074        //                 shareOF.el.innerHTML = 'Artwork to [o]: failed :(';
21075        //             }
21076        //             setTimeout(() => {
21077        //                 shareOF.el.innerHTML = '[o]';
21078        //                 this.removeModal();
21079        //             }, 4000);
21080        //         });
21081        //     });
21082        // });
21083    }
21084
21085    return ExportModal;
21086})(_Modal3['default']);
21087
21088exports['default'] = ExportModal;
21089module.exports = exports['default'];
21090
21091},{"../MenuItem":132,"./Modal":135,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/get":12,"babel-runtime/helpers/inherits":13,"babel-runtime/helpers/interop-require-default":14}],135:[function(_dereq_,module,exports){
21092'use strict';
21093
21094var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
21095
21096var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
21097
21098Object.defineProperty(exports, '__esModule', {
21099    value: true
21100});
21101exports.addEvent = addEvent;
21102exports.removeEvent = removeEvent;
21103
21104var _toolsMixin = _dereq_('../../tools/mixin');
21105
21106var Modal = (function () {
21107    function Modal(CSS_PREFIX, properties) {
21108        _classCallCheck(this, Modal);
21109
21110        (0, _toolsMixin.subscribeMixin)(this);
21111        this.CSS_PREFIX = CSS_PREFIX;
21112
21113        properties = properties || {};
21114        for (var prop in properties) {
21115            this[prop] = properties[prop];
21116        }
21117
21118        this.el = document.createElement('div');
21119        this.el.className = this.CSS_PREFIX + '_modal ge_modal';
21120        this.el.style.backgroundColor = this.bgColor;
21121        this.el.innerHTML = this.innerHTML || '';
21122
21123        if (this.elements) {
21124            for (var i = 0; i < this.elements.length; i++) {
21125                this.el.appendChild(this.elements[i]);
21126            }
21127        }
21128
21129        this.isVisible = false;
21130    }
21131
21132    /* Event handling */
21133
21134    _createClass(Modal, [{
21135        key: 'close',
21136        value: function close() {
21137            this.trigger('close');
21138        }
21139    }, {
21140        key: 'showAt',
21141        value: function showAt(cm) {
21142            var cursor = cm.cursorCoords(true, 'page');
21143            var x = cursor.left;
21144            var y = cursor.top;
21145
21146            y += 30;
21147
21148            this.presentModal(x, y);
21149        }
21150    }, {
21151        key: 'presentModal',
21152        value: function presentModal(x, y) {
21153            var _this = this;
21154
21155            // Listen for interaction outside of the modal
21156            window.setTimeout(function () {
21157                _this.onClickOutsideHandler = addEvent(document.body, 'click', _this.onClickOutside, _this);
21158                _this.onKeyPressHandler = addEvent(window, 'keydown', _this.onKeyPress, _this);
21159            }, 0);
21160            this.isVisible = true;
21161
21162            this.el.style.left = x + 'px';
21163            this.el.style.top = y + 'px';
21164            this.el.style.width = this.width + 'px';
21165            this.el.style.height = this.height + 'px';
21166
21167            if (this.position) {
21168                this.el.style.position = this.position;
21169            }
21170
21171            document.body.appendChild(this.el);
21172
21173            this.trigger('show');
21174        }
21175    }, {
21176        key: 'getModalClass',
21177        value: function getModalClass() {
21178            return this.CSS_PREFIX + 'modal';
21179        }
21180    }, {
21181        key: 'onKeyPress',
21182        value: function onKeyPress(event) {
21183            this.removeModal();
21184        }
21185    }, {
21186        key: 'onClickOutside',
21187        value: function onClickOutside(event) {
21188            // HACKY!!
21189            // A click event fires on the body after mousedown - mousemove, simultaneously with
21190            // mouseup. So if someone started a mouse action inside the modal and then
21191            // mouseup'd outside of it, it fires a click event on the body, thus, causing the
21192            // modal to disappear when the user does not expect it to, since the mouse down event
21193            // did not start outside the modal.
21194            // There might be (or should be) a better way to track this, but right now, just cancel
21195            // the event if the target ends up being on the body directly rather than on one of the
21196            // other child elements.
21197            if (event.target === document.body) {
21198                return;
21199            }
21200            // end this specific hacky part
21201            var target = event.target;
21202            if (target) {
21203                while (target !== document.documentElement && !target.classList.contains(this.getModalClass())) {
21204                    target = target.parentNode;
21205                }
21206
21207                if (!target.classList.contains(this.getModalClass())) {
21208                    this.removeModal();
21209                }
21210            }
21211        }
21212
21213        /**
21214         *  Removes modal from DOM and destroys related event listeners
21215         */
21216    }, {
21217        key: 'removeModal',
21218        value: function removeModal() {
21219            if (this.el && this.el.parentNode) {
21220                this.el.parentNode.removeChild(this.el);
21221            }
21222            removeEvent(document.body, 'click', this.onClickOutsideHandler);
21223            this.onClickOutsideHandler = null;
21224            removeEvent(window, 'keydown', this.onKeyPressHandler);
21225            this.onKeyPressHandler = null;
21226
21227            this.close();
21228            this.isVisible = false;
21229        }
21230    }]);
21231
21232    return Modal;
21233})();
21234
21235exports['default'] = Modal;
21236
21237function addEvent(element, event, callback, caller) {
21238    var handler = undefined;
21239    element.addEventListener(event, handler = function (e) {
21240        callback.call(caller, e);
21241    }, false);
21242    return handler;
21243}
21244
21245function removeEvent(element, event, callback) {
21246    element.removeEventListener(event, callback, false);
21247}
21248
21249},{"../../tools/mixin":126,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],136:[function(_dereq_,module,exports){
21250/*
21251Original: https://github.com/tangrams/tangram-play/blob/gh-pages/src/js/addons/ui/widgets/ColorPickerModal.js
21252Author: Lou Huang (@saikofish)
21253*/
21254
21255'use strict';
21256
21257var _get = _dereq_('babel-runtime/helpers/get')['default'];
21258
21259var _inherits = _dereq_('babel-runtime/helpers/inherits')['default'];
21260
21261var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
21262
21263var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
21264
21265var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
21266
21267Object.defineProperty(exports, '__esModule', {
21268    value: true
21269});
21270
21271var _Picker2 = _dereq_('./Picker');
21272
21273var _Picker3 = _interopRequireDefault(_Picker2);
21274
21275var _typesColor = _dereq_('./types/Color');
21276
21277var _typesColor2 = _interopRequireDefault(_typesColor);
21278
21279var _toolsCommon = _dereq_('../../tools/common');
21280
21281var _toolsInteractiveDom = _dereq_('../../tools/interactiveDom');
21282
21283// Some common use variables
21284var currentTarget = undefined;
21285var currentTargetHeight = 0;
21286var domCache = undefined;
21287
21288var ColorPicker = (function (_Picker) {
21289    _inherits(ColorPicker, _Picker);
21290
21291    function ColorPicker() {
21292        var color = arguments.length <= 0 || arguments[0] === undefined ? 'vec3(1.0,0.0,0.0)' : arguments[0];
21293        var properties = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
21294
21295        _classCallCheck(this, ColorPicker);
21296
21297        _get(Object.getPrototypeOf(ColorPicker.prototype), 'constructor', this).call(this, 'ge_colorpicker_', properties);
21298
21299        this.width = 250; // in pixels
21300        this.height = 250; // in pixels
21301
21302        this.disc = { width: 200, height: 200 };
21303        this.barlum = { width: 25, height: 200 };
21304
21305        this.setValue(color);
21306        this.init();
21307    }
21308
21309    // generic function for drawing a canvas disc
21310
21311    _createClass(ColorPicker, [{
21312        key: 'init',
21313        value: function init() {
21314            var _this = this;
21315
21316            if (!domCache) {
21317                var modal = document.createElement('div');
21318                var patch = document.createElement('div');
21319                var map = document.createElement('div');
21320                var disc = document.createElement('canvas');
21321                var cover = document.createElement('div');
21322                var cursor = document.createElement('div');
21323                var barbg = document.createElement('div');
21324                var barwhite = document.createElement('div');
21325                var barlum = document.createElement('canvas');
21326                var barcursors = document.createElement('div');
21327                var leftcursor = document.createElement('div');
21328                var rightcursor = document.createElement('div');
21329
21330                modal.className = this.CSS_PREFIX + 'modal ge_picker_modal';
21331                modal.style.backgroundColor = this.bgColor;
21332                patch.className = this.CSS_PREFIX + 'patch';
21333                patch.style.backgroundColor = this.bgColor;
21334                map.className = this.CSS_PREFIX + 'hsv-map';
21335                disc.className = this.CSS_PREFIX + 'disc';
21336                disc.style.backgroundColor = this.bgColor;
21337                cover.className = this.CSS_PREFIX + 'disc-cover';
21338                cursor.className = this.CSS_PREFIX + 'disc-cursor';
21339                barbg.className = this.CSS_PREFIX + 'bar-bg';
21340                barwhite.className = this.CSS_PREFIX + 'bar-white';
21341                barlum.className = this.CSS_PREFIX + 'bar-luminance';
21342                barcursors.className = this.CSS_PREFIX + 'bar-cursors';
21343                leftcursor.className = this.CSS_PREFIX + 'bar-cursor-left';
21344                rightcursor.className = this.CSS_PREFIX + 'bar-cursor-right';
21345
21346                map.id = 'cp-map';
21347                barcursors.id = 'cp-bar';
21348
21349                modal.appendChild(patch);
21350                modal.appendChild(map);
21351
21352                map.appendChild(disc);
21353                map.appendChild(cover);
21354                map.appendChild(cursor);
21355                map.appendChild(barbg);
21356                map.appendChild(barwhite);
21357                map.appendChild(barlum);
21358                map.appendChild(barcursors);
21359                barcursors.appendChild(leftcursor);
21360                barcursors.appendChild(rightcursor);
21361
21362                domCache = modal;
21363            }
21364
21365            // Returns a clone of the cached document fragment
21366            this.el = domCache.cloneNode(true);
21367            (0, _toolsInteractiveDom.subscribeInteractiveDom)(this.el, { move: true, resize: false, snap: false });
21368
21369            // TODO: Improve these references
21370            // The caching of references is likely to be important for speed
21371            this.dom = {};
21372            this.dom.hsvMap = this.el.querySelector('.ge_colorpicker_hsv-map');
21373            this.dom.hsvMapCover = this.dom.hsvMap.children[1]; // well...
21374            this.dom.hsvMapCursor = this.dom.hsvMap.children[2];
21375            this.dom.hsvBarBGLayer = this.dom.hsvMap.children[3];
21376            this.dom.hsvBarWhiteLayer = this.dom.hsvMap.children[4];
21377            this.dom.hsvBarCursors = this.dom.hsvMap.children[6];
21378            this.dom.hsvLeftCursor = this.dom.hsvBarCursors.children[0];
21379            this.dom.hsvRightCursor = this.dom.hsvBarCursors.children[1];
21380
21381            this.dom.colorDisc = this.el.querySelector('.ge_colorpicker_disc');
21382            this.dom.luminanceBar = this.el.querySelector('.ge_colorpicker_bar-luminance');
21383
21384            if (this.linkButton) {
21385                var lbutton = document.createElement('div');
21386                lbutton.innerHTML = '+';
21387                lbutton.className = this.CSS_PREFIX + 'link-button';
21388                lbutton.style.color = this.fgColor;
21389                this.el.appendChild(lbutton);
21390
21391                lbutton.addEventListener('click', function () {
21392                    _this.trigger('linkButton', _this.value);
21393                    if (typeof _this.linkButton === 'function') {
21394                        _this.linkButton(_this.value);
21395                    }
21396                    _this.removeModal();
21397                });
21398            }
21399        }
21400    }, {
21401        key: 'draw',
21402        value: function draw() {
21403            //  Render color patch
21404            var patch = this.el.querySelector('.ge_colorpicker_patch');
21405            patch.style.backgroundColor = this.value.getString('rgb');
21406
21407            //  Render HSV picker
21408            var color = this.value.colors;
21409            var colorDiscRadius = this.dom.colorDisc.offsetHeight / 2;
21410            var pi2 = Math.PI * 2;
21411            var x = Math.cos(pi2 - color.hsv.h * pi2);
21412            var y = Math.sin(pi2 - color.hsv.h * pi2);
21413            var r = color.hsv.s * (colorDiscRadius - 5);
21414
21415            this.dom.hsvMapCover.style.opacity = 1 - color.hsv.v / 255;
21416            // this is the faster version...
21417            this.dom.hsvBarWhiteLayer.style.opacity = 1 - color.hsv.s;
21418            this.dom.hsvBarBGLayer.style.backgroundColor = 'rgb(' + color.hueRGB.r + ',' + color.hueRGB.g + ',' + color.hueRGB.b + ')';
21419
21420            this.dom.hsvMapCursor.style.cssText = 'left: ' + (x * r + colorDiscRadius) + 'px;' + 'top: ' + (y * r + colorDiscRadius) + 'px;' + 'border-color: ' + (color.luminance > 0.22 ? '#333;' : '#ddd');
21421
21422            if (color.luminance > 0.22) {
21423                this.dom.hsvBarCursors.classList.add('ge_colorpicker_dark');
21424            } else {
21425                this.dom.hsvBarCursors.classList.remove('ge_colorpicker_dark');
21426            }
21427
21428            if (this.dom.hsvLeftCursor) {
21429                this.dom.hsvLeftCursor.style.top = this.dom.hsvRightCursor.style.top = (1 - color.hsv.v / 255) * colorDiscRadius * 2 + 'px';
21430            }
21431        }
21432    }, {
21433        key: 'presentModal',
21434        value: function presentModal(x, y) {
21435            _get(Object.getPrototypeOf(ColorPicker.prototype), 'presentModal', this).call(this, x, y);
21436
21437            // // Listen for interaction on the HSV map
21438            this.onHsvDownHandler = (0, _Picker2.addEvent)(this.dom.hsvMap, 'mousedown', this.onHsvDown, this);
21439
21440            var colorDisc = this.dom.colorDisc;
21441
21442            if (colorDisc.getContext) {
21443                // HSV color wheel with white center
21444                var diskContext = colorDisc.getContext('2d');
21445                var ratio = (0, _toolsCommon.getDevicePixelRatio)(diskContext);
21446                var width = this.disc.width / ratio;
21447                var height = this.disc.height / ratio;
21448                this.dom.colorDisc.width = width * ratio;
21449                this.dom.colorDisc.height = height * ratio;
21450                diskContext.scale(ratio, ratio);
21451
21452                drawDisk(diskContext, [width / 2, height / 2], [width / 2 - 1, height / 2 - 1], 360, function (ctx, angle) {
21453                    var gradient = ctx.createRadialGradient(1, 1, 1, 1, 1, 0);
21454                    gradient.addColorStop(0, 'hsl(' + (360 - angle + 0) + ', 100%, 50%)');
21455                    gradient.addColorStop(1, '#fff');
21456
21457                    ctx.fillStyle = gradient;
21458                    ctx.fill();
21459                });
21460
21461                // gray border
21462                drawCircle(diskContext, [width / 2, height / 2], [width / 2, height / 2], this.bgColor, // '#303030',
21463                2 / ratio);
21464
21465                // draw the luminanceBar bar
21466                var ctx = this.dom.luminanceBar.getContext('2d');
21467                this.dom.luminanceBar.width = this.barlum.width;
21468                this.dom.luminanceBar.height = this.barlum.height * ratio;
21469                ctx.scale(ratio, ratio);
21470                var gradient = ctx.createLinearGradient(0, 0, 0, this.barlum.height / ratio);
21471
21472                gradient.addColorStop(0, 'transparent');
21473                gradient.addColorStop(1, 'black');
21474
21475                ctx.fillStyle = gradient;
21476                ctx.fillRect(0, 0, 30, 200);
21477            }
21478            this.draw();
21479        }
21480
21481        /**
21482         *  Updates only the color value of the color picker
21483         *  and the view. Designed to be called by external modules
21484         *  so that it can update its internal value from an outside source.
21485         *  Does no DOM creation & other initialization work.
21486         */
21487    }, {
21488        key: 'setValue',
21489        value: function setValue(color) {
21490            this.value = new _typesColor2['default'](color);
21491        }
21492
21493        /* ---------------------------------- */
21494        /* ---- HSV-circle color picker ----- */
21495        /* ---------------------------------- */
21496
21497        // Actions when user mouses down on HSV color map
21498    }, {
21499        key: 'onHsvDown',
21500        value: function onHsvDown(event) {
21501            var target = event.target || event.srcElement;
21502            event.preventDefault();
21503
21504            currentTarget = target.id ? target : target.parentNode;
21505            currentTargetHeight = currentTarget.offsetHeight; // as diameter of circle
21506
21507            // Starts listening for mousemove and mouseup events
21508            this.onHsvMoveHandler = (0, _Picker2.addEvent)(this.el, 'mousemove', this.onHsvMove, this);
21509            this.onHsvUpHandler = (0, _Picker2.addEvent)(window, 'mouseup', this.onHsvUp, this);
21510
21511            this.onHsvMove(event);
21512
21513            // Hides mouse cursor and begins rendering loop
21514            this.dom.hsvMap.classList.add('ge_colorpicker_no-cursor');
21515            this.renderer.start();
21516        }
21517
21518        // Actions when user moves around on HSV color map
21519    }, {
21520        key: 'onHsvMove',
21521        value: function onHsvMove(event) {
21522            event.preventDefault();
21523            event.stopPropagation();
21524
21525            var r = undefined,
21526                x = undefined,
21527                y = undefined,
21528                h = undefined,
21529                s = undefined;
21530            if (event.target === this.dom.hsvMapCover && currentTarget === this.dom.hsvMap) {
21531                // the circle
21532                r = currentTargetHeight / 2, x = event.offsetX - r, y = event.offsetY - r, h = (360 - (Math.atan2(y, x) * 180 / Math.PI + (y < 0 ? 360 : 0))) / 360, s = Math.sqrt(x * x + y * y) / r;
21533                this.value.set({ h: h, s: s }, 'hsv');
21534            } else if (event.target === this.dom.hsvBarCursors && currentTarget === this.dom.hsvBarCursors) {
21535                // the luminanceBar
21536                var v = (currentTargetHeight - event.offsetY) / currentTargetHeight;
21537                v = Math.max(0, Math.min(1, v)) * 255;
21538                this.value.set({ v: v }, 'hsv');
21539            }
21540
21541            this.trigger('changed', this.value);
21542        }
21543
21544        // Actions when user mouses up on HSV color map
21545    }, {
21546        key: 'onHsvUp',
21547        value: function onHsvUp(event) {
21548            // Stops rendering and returns mouse cursor
21549            this.renderer.stop();
21550            this.dom.hsvMap.classList.remove('ge_colorpicker_no-cursor');
21551            this.destroyEvents();
21552        }
21553
21554        // Destroy event listeners that exist during mousedown colorpicker interaction
21555    }, {
21556        key: 'destroyEvents',
21557        value: function destroyEvents() {
21558            (0, _Picker2.removeEvent)(this.el, 'mousemove', this.onHsvMoveHandler);
21559            this.onHsvMoveHandler = null;
21560            (0, _Picker2.removeEvent)(window, 'mouseup', this.onHsvUpHandler);
21561            this.onHsvUpHandler = null;
21562        }
21563    }, {
21564        key: 'close',
21565        value: function close() {
21566            this.destroyEvents();
21567            (0, _Picker2.removeEvent)(this.dom.hsvMap, 'mousedown', this.onHsvDownHandler);
21568            this.onHsvDownHandler = null;
21569        }
21570    }]);
21571
21572    return ColorPicker;
21573})(_Picker3['default']);
21574
21575exports['default'] = ColorPicker;
21576function drawDisk(ctx, coords, radius, steps, colorCallback) {
21577    var x = coords[0] || coords; // coordinate on x-axis
21578    var y = coords[1] || coords; // coordinate on y-axis
21579    var a = radius[0] || radius; // radius on x-axis
21580    var b = radius[1] || radius; // radius on y-axis
21581    var angle = 360;
21582    var coef = Math.PI / 180;
21583
21584    ctx.save();
21585    ctx.translate(x - a, y - b);
21586    ctx.scale(a, b);
21587
21588    steps = angle / steps || 360;
21589
21590    for (; angle > 0; angle -= steps) {
21591        ctx.beginPath();
21592        if (steps !== 360) {
21593            ctx.moveTo(1, 1); // stroke
21594        }
21595        ctx.arc(1, 1, 1, (angle - steps / 2 - 1) * coef, (angle + steps / 2 + 1) * coef);
21596
21597        if (colorCallback) {
21598            colorCallback(ctx, angle);
21599        } else {
21600            ctx.fillStyle = 'black';
21601            ctx.fill();
21602        }
21603    }
21604    ctx.restore();
21605}
21606
21607function drawCircle(ctx, coords, radius, color, width) {
21608    // uses drawDisk
21609    width = width || 1;
21610    radius = [(radius[0] || radius) - width / 2, (radius[1] || radius) - width / 2];
21611    drawDisk(ctx, coords, radius, 1, function (ctx, angle) {
21612        ctx.restore();
21613        ctx.lineWidth = width;
21614        ctx.strokeStyle = color || '#000';
21615        ctx.stroke();
21616    });
21617}
21618module.exports = exports['default'];
21619
21620},{"../../tools/common":121,"../../tools/interactiveDom":124,"./Picker":138,"./types/Color":141,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/get":12,"babel-runtime/helpers/inherits":13,"babel-runtime/helpers/interop-require-default":14}],137:[function(_dereq_,module,exports){
21621'use strict';
21622
21623var _get = _dereq_('babel-runtime/helpers/get')['default'];
21624
21625var _inherits = _dereq_('babel-runtime/helpers/inherits')['default'];
21626
21627var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
21628
21629var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
21630
21631var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
21632
21633Object.defineProperty(exports, '__esModule', {
21634    value: true
21635});
21636
21637var _Picker2 = _dereq_('./Picker');
21638
21639var _Picker3 = _interopRequireDefault(_Picker2);
21640
21641var _typesFloat = _dereq_('./types/Float');
21642
21643var _typesFloat2 = _interopRequireDefault(_typesFloat);
21644
21645var FloatPicker = (function (_Picker) {
21646    _inherits(FloatPicker, _Picker);
21647
21648    function FloatPicker(number, properties) {
21649        _classCallCheck(this, FloatPicker);
21650
21651        _get(Object.getPrototypeOf(FloatPicker.prototype), 'constructor', this).call(this, 'ge_floatpicker_', properties);
21652
21653        this.width = this.width || 250;
21654        this.height = this.height || 40;
21655
21656        this.prevOffset = 0;
21657        this.scale = 2;
21658
21659        this.setValue(number || 1);
21660        this.create();
21661    }
21662
21663    _createClass(FloatPicker, [{
21664        key: 'draw',
21665        value: function draw() {
21666            this.ctx.clearRect(0, 0, this.width, this.height);
21667
21668            // horizontal line
21669            this.ctx.strokeStyle = this.dimColor;
21670            this.ctx.lineWidth = 1;
21671            this.ctx.beginPath();
21672            this.ctx.moveTo(0, 0.5 + this.height * 0.5);
21673            this.ctx.lineTo(0 + this.width, 0.5 + this.height * 0.5);
21674            this.ctx.closePath();
21675            this.ctx.stroke();
21676
21677            // vertical line
21678            this.ctx.strokeStyle = this.fnColor;
21679            this.ctx.lineWidth = 1;
21680            this.ctx.beginPath();
21681            this.ctx.moveTo(this.width * 0.5, 0);
21682            this.ctx.lineTo(this.width * 0.5, this.height);
21683            this.ctx.closePath();
21684            this.ctx.stroke();
21685
21686            // Triangle line
21687            this.ctx.fillStyle = this.overPoint ? this.selColor : this.fnColor;
21688            this.ctx.beginPath();
21689            this.ctx.moveTo(this.width * 0.5, 5);
21690            this.ctx.lineTo(this.width * 0.48, 0);
21691            this.ctx.lineTo(this.width * 0.52, 0);
21692            this.ctx.closePath();
21693            this.ctx.fill();
21694
21695            var times = 3;
21696            var unit = 40;
21697            var step = this.width / unit;
21698            var sections = unit * times;
21699
21700            var offsetX = this.offsetX;
21701
21702            if (Math.abs(this.offsetX - this.width * 0.5) > this.width * 0.5) {
21703                offsetX = (this.offsetX - this.width * 0.5) % (this.width * 0.5) + this.width;
21704            }
21705
21706            this.ctx.strokeStyle = this.dimColor;
21707            this.ctx.beginPath();
21708            for (var i = 0; i < sections; i++) {
21709                var l = i % (unit / 2) === 0 ? this.height * 0.35 : i % (unit / 4) === 0 ? this.height * 0.2 : this.height * 0.1;
21710                this.ctx.moveTo(i * step - offsetX, this.height * 0.5 - l);
21711                this.ctx.lineTo(i * step - offsetX, this.height * 0.5 + l);
21712            }
21713            this.ctx.stroke();
21714
21715            var val = Math.round((this.value - this.min) / this.range * this.width);
21716
21717            // point
21718            this.ctx.strokeStyle = this.overPoint ? this.selColor : this.fnColor;
21719            this.ctx.lineWidth = 1;
21720            this.ctx.beginPath();
21721            this.ctx.moveTo(this.offsetX + val, this.height * 0.5);
21722            this.ctx.lineTo(this.offsetX + val, this.height);
21723            this.ctx.closePath();
21724            this.ctx.stroke();
21725
21726            this.overPoint = false;
21727        }
21728    }, {
21729        key: 'onMouseDown',
21730        value: function onMouseDown(event) {
21731            this.prevOffset = event.offsetX;
21732            _get(Object.getPrototypeOf(FloatPicker.prototype), 'onMouseDown', this).call(this, event);
21733        }
21734
21735        // Actions when user moves around on HSV color map
21736    }, {
21737        key: 'onMouseMove',
21738        value: function onMouseMove(event) {
21739            var x = event.offsetX;
21740
21741            var vel = x - this.prevOffset;
21742            var offset = this.offsetX - vel;
21743
21744            var center = this.width / this.scale;
21745            this.setValue(offset / center);
21746            this.prevOffset = x;
21747
21748            // fire 'changed'
21749            var number = new _typesFloat2['default'](this.getValue());
21750            this.trigger('changed', number);
21751            this.overPoint = true;
21752        }
21753    }, {
21754        key: 'setValue',
21755        value: function setValue(value) {
21756            if (typeof value === 'string') {
21757                this.value = parseFloat(value);
21758            } else if (typeof value === 'number') {
21759                this.value = value;
21760            }
21761            var center = this.width / this.scale;
21762            this.offsetX = this.value * center;
21763        }
21764    }]);
21765
21766    return FloatPicker;
21767})(_Picker3['default']);
21768
21769exports['default'] = FloatPicker;
21770module.exports = exports['default'];
21771
21772},{"./Picker":138,"./types/Float":143,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/get":12,"babel-runtime/helpers/inherits":13,"babel-runtime/helpers/interop-require-default":14}],138:[function(_dereq_,module,exports){
21773/*
21774Original: https://github.com/tangrams/tangram-play/blob/gh-pages/src/js/addons/ui/widgets/ColorPickerModal.js
21775Author: Lou Huang (@saikofish)
21776*/
21777
21778'use strict';
21779
21780var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
21781
21782var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
21783
21784Object.defineProperty(exports, '__esModule', {
21785    value: true
21786});
21787exports.addEvent = addEvent;
21788exports.removeEvent = removeEvent;
21789
21790var _toolsCommon = _dereq_('../../tools/common');
21791
21792var _toolsMixin = _dereq_('../../tools/mixin');
21793
21794var Picker = (function () {
21795    function Picker(CSS_PREFIX, properties) {
21796        var _this = this;
21797
21798        _classCallCheck(this, Picker);
21799
21800        (0, _toolsMixin.subscribeMixin)(this);
21801        this.CSS_PREFIX = CSS_PREFIX;
21802
21803        this.bgColor = 'rgb(46, 48, 51)';
21804        this.dimColor = 'rgb(100, 100, 100)';
21805        this.fnColor = 'rgb(230, 230, 230)';
21806        this.selColor = 'rgb(133, 204, 196)';
21807
21808        properties = properties || {};
21809        for (var prop in properties) {
21810            this[prop] = properties[prop];
21811        }
21812
21813        /**
21814         *  This initializes the renderer. It uses requestAnimationFrame() to
21815         *  smoothly render changes in the color picker as user interacts with it.
21816         */
21817        this.renderer = {
21818            // Stores a reference to the animation rendering loop.
21819            frame: null,
21820
21821            drawFrame: function drawFrame() {
21822                if (!_this.el) {
21823                    return;
21824                }
21825                _this.draw();
21826            },
21827
21828            // Starts animation rendering loop
21829            start: function start() {
21830                _this.renderer.drawFrame();
21831                _this.renderer.frame = window.requestAnimationFrame(_this.renderer.start);
21832            },
21833
21834            // Stops animation rendering loop
21835            stop: function stop() {
21836                window.cancelAnimationFrame(_this.renderer.frame);
21837            }
21838        };
21839        this.isVisible = false;
21840    }
21841
21842    /* Event handling */
21843
21844    _createClass(Picker, [{
21845        key: 'create',
21846        value: function create() {
21847            this.el = document.createElement('div');
21848            this.el.className = this.CSS_PREFIX + 'modal ge_picker_modal';
21849            this.el.style.backgroundColor = this.bgColor;
21850
21851            this.canvas = document.createElement('canvas');
21852            this.canvas.className = this.CSS_PREFIX + 'canvas ge_picker_canvas';
21853            this.canvas.style.backgroundColor = this.bgColor;
21854
21855            this.el.appendChild(this.canvas);
21856            this.ctx = this.canvas.getContext('2d');
21857
21858            var ratio = (0, _toolsCommon.getDevicePixelRatio)(this.ctx);
21859            this.canvas.width = this.width * ratio;
21860            this.canvas.height = this.height * ratio;
21861            this.ctx.scale(ratio, ratio);
21862        }
21863    }, {
21864        key: 'draw',
21865        value: function draw() {
21866            // render rutine
21867        }
21868    }, {
21869        key: 'close',
21870        value: function close() {
21871            // Close rutine
21872            this.destroyEvents();
21873            removeEvent(this.el, 'mousedown', this.onMouseDownHandler);
21874            this.onMouseDownHandler = null;
21875        }
21876    }, {
21877        key: 'destroyEvents',
21878        value: function destroyEvents() {
21879            removeEvent(this.el, 'mousemove', this.onMouseMoveHandler);
21880            this.onMouseMoveHandler = null;
21881            removeEvent(window, 'mouseup', this.onMouseUpHandler);
21882            this.onMouseUpHandler = null;
21883        }
21884    }, {
21885        key: 'setValue',
21886        value: function setValue(value) {
21887            this.value = value;
21888        }
21889    }, {
21890        key: 'getValue',
21891        value: function getValue() {
21892            return this.value;
21893        }
21894    }, {
21895        key: 'showAt',
21896        value: function showAt(cm) {
21897            var cursor = cm.cursorCoords(true, 'page');
21898            var x = cursor.left;
21899            var y = cursor.top;
21900
21901            x -= this.width * 0.5;
21902            y += 30;
21903
21904            // // Check if desired x, y will be outside the viewport.
21905            // // Do not allow the modal to disappear off the edge of the window.
21906            // x = (x + this.width < window.innerWidth) ? x : (window.innerWidth - 20 - this.width);
21907            // y = (y + this.height < window.innerHeight) ? y : (window.innerHeight - 20 - this.height);
21908
21909            this.presentModal(x, y);
21910        }
21911    }, {
21912        key: 'presentModal',
21913        value: function presentModal(x, y) {
21914            var _this2 = this;
21915
21916            // Listen for interaction outside of the modal
21917            window.setTimeout(function () {
21918                _this2.onClickOutsideHandler = addEvent(document.body, 'click', _this2.onClickOutside, _this2);
21919                _this2.onKeyPressHandler = addEvent(window, 'keydown', _this2.onKeyPress, _this2);
21920            }, 0);
21921            this.isVisible = true;
21922
21923            this.el.style.left = x + 'px';
21924            this.el.style.top = y + 'px';
21925            this.el.style.width = this.width + 'px';
21926            this.el.style.height = this.height + 'px';
21927            document.body.appendChild(this.el);
21928
21929            this.onMouseDownHandler = addEvent(this.el, 'mousedown', this.onMouseDown, this);
21930
21931            this.renderer.drawFrame();
21932        }
21933
21934        /**
21935         *  Removes modal from DOM and destroys related event listeners
21936         */
21937    }, {
21938        key: 'removeModal',
21939        value: function removeModal() {
21940            if (this.el && this.el.parentNode) {
21941                this.el.parentNode.removeChild(this.el);
21942            }
21943            removeEvent(document.body, 'click', this.onClickOutsideHandler);
21944            this.onClickOutsideHandler = null;
21945            removeEvent(window, 'keydown', this.onKeyPressHandler);
21946            this.onKeyPressHandler = null;
21947
21948            this.close();
21949            this.isVisible = false;
21950        }
21951    }, {
21952        key: 'onKeyPress',
21953        value: function onKeyPress(event) {
21954            this.removeModal();
21955        }
21956    }, {
21957        key: 'onClickOutside',
21958        value: function onClickOutside(event) {
21959            // HACKY!!
21960            // A click event fires on the body after mousedown - mousemove, simultaneously with
21961            // mouseup. So if someone started a mouse action inside the modal and then
21962            // mouseup'd outside of it, it fires a click event on the body, thus, causing the
21963            // modal to disappear when the user does not expect it to, since the mouse down event
21964            // did not start outside the modal.
21965            // There might be (or should be) a better way to track this, but right now, just cancel
21966            // the event if the target ends up being on the body directly rather than on one of the
21967            // other child elements.
21968            if (event.target === document.body) {
21969                return;
21970            }
21971            // end this specific hacky part
21972
21973            var target = event.target;
21974
21975            while (target !== document.documentElement && !target.classList.contains(this.CSS_PREFIX + 'modal')) {
21976                target = target.parentNode;
21977            }
21978
21979            if (!target.classList.contains(this.CSS_PREFIX + 'modal')) {
21980                this.removeModal();
21981            }
21982        }
21983    }, {
21984        key: 'onMouseDown',
21985        value: function onMouseDown(event) {
21986            event.preventDefault();
21987
21988            // Starts listening for mousemove and mouseup events
21989            this.onMouseMoveHandler = addEvent(this.el, 'mousemove', this.onMouseMove, this);
21990            this.onMouseUpHandler = addEvent(window, 'mouseup', this.onMouseUp, this);
21991
21992            this.onMouseMove(event);
21993
21994            this.renderer.start();
21995        }
21996    }, {
21997        key: 'onMouseMove',
21998        value: function onMouseMove(event) {}
21999    }, {
22000        key: 'onMouseUp',
22001        value: function onMouseUp(event) {
22002            this.renderer.stop();
22003            this.destroyEvents();
22004        }
22005    }]);
22006
22007    return Picker;
22008})();
22009
22010exports['default'] = Picker;
22011
22012function addEvent(element, event, callback, caller) {
22013    var handler = undefined;
22014    element.addEventListener(event, handler = function (e) {
22015        callback.call(caller, e);
22016    }, false);
22017    return handler;
22018}
22019
22020function removeEvent(element, event, callback) {
22021    element.removeEventListener(event, callback, false);
22022}
22023
22024},{"../../tools/common":121,"../../tools/mixin":126,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],139:[function(_dereq_,module,exports){
22025'use strict';
22026
22027var _get = _dereq_('babel-runtime/helpers/get')['default'];
22028
22029var _inherits = _dereq_('babel-runtime/helpers/inherits')['default'];
22030
22031var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
22032
22033var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
22034
22035var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
22036
22037Object.defineProperty(exports, '__esModule', {
22038    value: true
22039});
22040
22041var _Picker2 = _dereq_('./Picker');
22042
22043var _Picker3 = _interopRequireDefault(_Picker2);
22044
22045var _typesVector = _dereq_('./types/Vector');
22046
22047var _typesVector2 = _interopRequireDefault(_typesVector);
22048
22049var Vec2Picker = (function (_Picker) {
22050    _inherits(Vec2Picker, _Picker);
22051
22052    function Vec2Picker(pos, properties) {
22053        _classCallCheck(this, Vec2Picker);
22054
22055        _get(Object.getPrototypeOf(Vec2Picker.prototype), 'constructor', this).call(this, 'ge_vec2picker_', properties);
22056
22057        this.width = this.width || 200;
22058        this.height = this.height || 200;
22059
22060        this.min = this.min || -1;
22061        this.max = this.max || 1;
22062        this.size = this.size || 6;
22063        this.range = this.max - this.min;
22064        this.overPoint = false;
22065
22066        var center = (this.range / 2 - this.max) * -1;
22067        this.setValue(pos || [center, center]);
22068        this.create();
22069    }
22070
22071    _createClass(Vec2Picker, [{
22072        key: 'draw',
22073        value: function draw() {
22074            this.ctx.clearRect(0, 0, this.width, this.height);
22075
22076            // frame
22077            this.ctx.strokeStyle = this.dimColor;
22078            this.ctx.lineWidth = 2;
22079            this.ctx.strokeRect(0, 0, this.width, this.height);
22080
22081            this.ctx.beginPath();
22082            this.ctx.lineWidth = 0.25;
22083            var sections = 20;
22084            var step = this.width / sections;
22085            for (var i = 0; i < sections; i++) {
22086                this.ctx.moveTo(i * step, 0);
22087                this.ctx.lineTo(i * step, this.height);
22088                this.ctx.moveTo(0, i * step);
22089                this.ctx.lineTo(this.width, i * step);
22090            }
22091            this.ctx.stroke();
22092
22093            // horizontal line
22094            this.ctx.strokeStyle = this.dimColor;
22095            this.ctx.lineWidth = 1.0;
22096            this.ctx.beginPath();
22097            this.ctx.moveTo(0, 0.5 + this.height * 0.5);
22098            this.ctx.lineTo(this.width, 0.5 + this.height * 0.5);
22099            this.ctx.closePath();
22100            this.ctx.stroke();
22101
22102            // vertical line
22103            this.ctx.beginPath();
22104            this.ctx.moveTo(0.5 + this.width * 0.5, 0);
22105            this.ctx.lineTo(0.5 + this.width * 0.5, this.height);
22106            this.ctx.closePath();
22107            this.ctx.stroke();
22108
22109            // // Triangle line
22110            // this.ctx.fillStyle = this.dimColor;
22111            // this.ctx.beginPath();
22112            // this.ctx.moveTo(this.width * 0.5, 5);
22113            // this.ctx.lineTo(this.width * 0.48, 0);
22114            // this.ctx.lineTo(this.width * 0.52, 0);
22115            // this.ctx.closePath();
22116            // this.ctx.fill();
22117
22118            var x = Math.round((this.value.x - this.min) / this.range * this.width);
22119            var y = Math.round((1 - (this.value.y - this.min) / this.range) * this.height);
22120
22121            var half = this.size / 2;
22122
22123            if (x < half) {
22124                x = half;
22125            }
22126            if (x > this.width - half) {
22127                x = this.width - half;
22128            }
22129            if (y < half) {
22130                y = half;
22131            }
22132            if (y > this.height - half) {
22133                y = this.height - half;
22134            }
22135
22136            // point
22137            this.ctx.fillStyle = this.overPoint ? this.selColor : this.fnColor;
22138            this.ctx.beginPath();
22139            var radius = this.overPoint ? 4 : 2;
22140            this.ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
22141            this.ctx.fill();
22142
22143            this.ctx.restore();
22144            this.overPoint = false;
22145        }
22146
22147        // Actions when user moves around on HSV color map
22148    }, {
22149        key: 'onMouseMove',
22150        value: function onMouseMove(event) {
22151            var x = event.offsetX;
22152            var y = event.offsetY;
22153
22154            this.value.x = this.range / this.width * x - (this.range - this.max);
22155            this.value.y = (this.range / this.height * y - (this.range - this.max)) * -1;
22156
22157            // fire 'changed'
22158            this.trigger('changed', this.value);
22159            this.overPoint = true;
22160        }
22161    }, {
22162        key: 'setValue',
22163        value: function setValue(pos) {
22164            this.value = new _typesVector2['default'](pos);
22165        }
22166    }]);
22167
22168    return Vec2Picker;
22169})(_Picker3['default']);
22170
22171exports['default'] = Vec2Picker;
22172module.exports = exports['default'];
22173
22174},{"./Picker":138,"./types/Vector":145,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/get":12,"babel-runtime/helpers/inherits":13,"babel-runtime/helpers/interop-require-default":14}],140:[function(_dereq_,module,exports){
22175'use strict';
22176
22177var _get = _dereq_('babel-runtime/helpers/get')['default'];
22178
22179var _inherits = _dereq_('babel-runtime/helpers/inherits')['default'];
22180
22181var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
22182
22183var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
22184
22185var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
22186
22187Object.defineProperty(exports, '__esModule', {
22188    value: true
22189});
22190
22191var _Picker2 = _dereq_('./Picker');
22192
22193var _Picker3 = _interopRequireDefault(_Picker2);
22194
22195var _typesVector = _dereq_('./types/Vector');
22196
22197var _typesVector2 = _interopRequireDefault(_typesVector);
22198
22199var _typesMatrix = _dereq_('./types/Matrix');
22200
22201var _typesMatrix2 = _interopRequireDefault(_typesMatrix);
22202
22203var Vec3Picker = (function (_Picker) {
22204    _inherits(Vec3Picker, _Picker);
22205
22206    function Vec3Picker(dir, properties) {
22207        _classCallCheck(this, Vec3Picker);
22208
22209        _get(Object.getPrototypeOf(Vec3Picker.prototype), 'constructor', this).call(this, 'ge_vec3picker_', properties);
22210
22211        this.width = this.width || 200;
22212        this.height = this.width || 200;
22213        this.scale = 50;
22214
22215        this.setValue(dir || [0, 0, 1]);
22216        this.create();
22217
22218        this.camera = new _typesMatrix2['default']();
22219        this.shapes = [];
22220        this.center = [0, 0, 0];
22221
22222        this.shapes.push({
22223            edgeColour: this.dimColor,
22224            nodes: [[this.width / 2 - 50, this.height / 2, 100], [this.width / 2 + 50, this.height / 2, 100], [this.width / 2, this.height / 2 - 50, 100], [this.width / 2, this.height / 2 + 50, 100], [this.width / 2, this.height / 2, 50], [this.width / 2, this.height / 2, 150]],
22225            edges: [[0, 1], [2, 3], [4, 5]]
22226        });
22227
22228        this.shapes.push({
22229            textColour: this.fnColor,
22230            nodes: [[this.width / 2 + 68, this.height / 2, 100], [this.width / 2 - 68, this.height / 2, 100], [this.width / 2, this.height / 2 + 68, 100], [this.width / 2, this.height / 2 - 68, 100], [this.width / 2, this.height / 2, 168], [this.width / 2, this.height / 2, 32]],
22231            text: ['x', '-x', 'y', '-y', 'z', '-z']
22232        });
22233
22234        this.setCenter(this.width / 2, this.height / 2, 100);
22235
22236        // Mouse events
22237        this.dragOffset = [0, 0];
22238        this.overPoint = false;
22239    }
22240
22241    _createClass(Vec3Picker, [{
22242        key: 'setCenter',
22243        value: function setCenter(x, y, z) {
22244            for (var s in this.shapes) {
22245                var shape = this.shapes[s];
22246
22247                for (var n in shape.nodes) {
22248                    shape.nodes[n][0] -= x;
22249                    shape.nodes[n][1] -= y;
22250                    shape.nodes[n][2] -= z;
22251                }
22252            }
22253            this.center = [x, y, z];
22254        }
22255    }, {
22256        key: 'viewFromCamera',
22257        value: function viewFromCamera(node) {
22258            var A = this.camera.getMult(node);
22259            A.add(this.center);
22260            return [A.x, this.height - A.y];
22261        }
22262    }, {
22263        key: 'draw',
22264        value: function draw() {
22265            this.ctx.clearRect(0, 0, this.width, this.height);
22266
22267            for (var s in this.shapes) {
22268                var shape = this.shapes[s];
22269                if (shape.edgeColour) {
22270                    this.drawShapeEdges(shape);
22271                }
22272                if (shape.nodeColour) {
22273                    this.drawShapeNodes(shape);
22274                }
22275                if (shape.text) {
22276                    this.drawShapeText(shape);
22277                }
22278            }
22279
22280            this.drawShapeEdges({
22281                edgeColour: this.fnColor,
22282                nodes: [[0, 0, 0], this.point],
22283                edges: [[0, 1]]
22284            });
22285
22286            this.drawShapeNodes({
22287                nodeColour: this.overPoint ? this.selColor : this.fnColor,
22288                nodeRadius: this.overPoint ? 4 : 2,
22289                nodes: [this.point]
22290            });
22291        }
22292    }, {
22293        key: 'drawShapeEdges',
22294        value: function drawShapeEdges(shape) {
22295            var nodes = shape.nodes;
22296
22297            this.ctx.strokeStyle = shape.edgeColour;
22298            for (var e in shape.edges) {
22299                var coord = this.viewFromCamera(nodes[shape.edges[e][0]]);
22300                this.ctx.lineWidth = 1;
22301                this.ctx.beginPath();
22302                this.ctx.moveTo(coord[0], coord[1]);
22303                coord = this.viewFromCamera(nodes[shape.edges[e][1]]);
22304                this.ctx.lineTo(coord[0], coord[1]);
22305                this.ctx.stroke();
22306            }
22307        }
22308    }, {
22309        key: 'drawShapeNodes',
22310        value: function drawShapeNodes(shape) {
22311            var radius = shape.nodeRadius || 4;
22312            this.ctx.fillStyle = shape.nodeColour;
22313            for (var n in shape.nodes) {
22314                var coord = this.viewFromCamera(shape.nodes[n]);
22315                this.ctx.beginPath();
22316                this.ctx.arc(coord[0], coord[1], radius, 0, 2 * Math.PI, false);
22317                this.ctx.fill();
22318            }
22319        }
22320    }, {
22321        key: 'drawShapeText',
22322        value: function drawShapeText(shape) {
22323            this.ctx.fillStyle = shape.textColour;
22324            for (var n in shape.nodes) {
22325                var coord = this.viewFromCamera(shape.nodes[n]);
22326                this.ctx.textBaseline = 'middle';
22327                this.ctx.fillText(shape.text[n], coord[0], coord[1]);
22328            }
22329        }
22330    }, {
22331        key: 'onMouseDown',
22332        value: function onMouseDown(event) {
22333            var mouse = [event.offsetX, event.offsetY];
22334            this.dragOffset = mouse;
22335
22336            var pos = new _typesVector2['default'](this.viewFromCamera(this.point));
22337            var diff = pos.getSub(mouse);
22338            this.overPoint = diff.getLength() < 10;
22339
22340            _get(Object.getPrototypeOf(Vec3Picker.prototype), 'onMouseDown', this).call(this, event);
22341            this.onMouseUpHandler = (0, _Picker2.addEvent)(this.el, 'dblclick', this.onDbClick, this);
22342        }
22343
22344        // Actions when user moves around on HSV color map
22345    }, {
22346        key: 'onMouseMove',
22347        value: function onMouseMove(event) {
22348            var x = event.offsetX;
22349            var y = event.offsetY;
22350
22351            var dx = 0.01 * (x - this.dragOffset[0]);
22352            var dy = 0.01 * (y - this.dragOffset[1]);
22353
22354            if (this.overPoint) {
22355                var invM = this.camera.getInv();
22356                var vel = invM.getMult([dx, -dy, 0.0]);
22357                vel.mult(2);
22358                this.value.add(vel);
22359                this.point = [this.value.x * this.scale, this.value.y * this.scale, this.value.z * this.scale];
22360                // fire 'changed'
22361                this.trigger('changed', this.value);
22362            } else {
22363                this.camera.rotateX(dy);
22364                this.camera.rotateY(dx);
22365            }
22366
22367            this.dragOffset = [x, y];
22368        }
22369    }, {
22370        key: 'onDbClick',
22371        value: function onDbClick(event) {
22372            var mouse = new _typesVector2['default']([event.offsetX, event.offsetY]);
22373            var axis = {
22374                x: [68, 0, 0],
22375                negX: [-68, 0, 0],
22376                y: [0, 68, 100],
22377                negY: [0, -68, 0]
22378            };
22379            var selected = '';
22380            for (var i in axis) {
22381                var pos = new _typesVector2['default'](this.viewFromCamera(axis[i]));
22382                var diff = pos.getSub(mouse);
22383                if (diff.getLength() < 10) {
22384                    selected = i;
22385                    break;
22386                }
22387            }
22388            this.camera = new _typesMatrix2['default']();
22389
22390            if (selected === 'x') {
22391                this.camera.rotateY(-1.57079632679);
22392            } else if (selected === 'negX') {
22393                this.camera.rotateY(1.57079632679);
22394            } else if (selected === 'y') {
22395                this.camera.rotateX(-1.57079632679);
22396            } else if (selected === 'negY') {
22397                this.camera.rotateX(1.57079632679);
22398            }
22399
22400            this.draw();
22401        }
22402    }, {
22403        key: 'destroyEvents',
22404        value: function destroyEvents() {
22405            _get(Object.getPrototypeOf(Vec3Picker.prototype), 'destroyEvents', this).call(this);
22406            (0, _Picker2.removeEvent)(this.el, 'dblclick', this.onDbClick);
22407            this.onMouseMoveHandler = null;
22408        }
22409    }, {
22410        key: 'setValue',
22411        value: function setValue(dir) {
22412            this.value = new _typesVector2['default'](dir);
22413            this.point = [this.value.x * this.scale, this.value.y * this.scale, this.value.z * this.scale];
22414        }
22415    }]);
22416
22417    return Vec3Picker;
22418})(_Picker3['default']);
22419
22420exports['default'] = Vec3Picker;
22421module.exports = exports['default'];
22422
22423},{"./Picker":138,"./types/Matrix":144,"./types/Vector":145,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/get":12,"babel-runtime/helpers/inherits":13,"babel-runtime/helpers/interop-require-default":14}],141:[function(_dereq_,module,exports){
22424'use strict';
22425
22426var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
22427
22428var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
22429
22430var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
22431
22432Object.defineProperty(exports, '__esModule', {
22433    value: true
22434});
22435
22436var _ColorConverter = _dereq_('./ColorConverter');
22437
22438var _ColorConverter2 = _interopRequireDefault(_ColorConverter);
22439
22440var Color = (function () {
22441    function Color(color) {
22442        _classCallCheck(this, Color);
22443
22444        this.colors = {};
22445        this.set(color);
22446    }
22447
22448    _createClass(Color, [{
22449        key: 'set',
22450        value: function set(color, type) {
22451            // color only full range
22452            if (typeof color === 'number') {
22453                type = type ? type : 'rgb';
22454                this.colors[type] = {};
22455                for (var n = 3; n--;) {
22456                    var m = type[n] || type.charAt(n); // IE7
22457                    this.colors[type][m] = color;
22458                }
22459            } else if (typeof color === 'string') {
22460                var parts = color.replace(/(?:#|\)|%)/g, '').split('(');
22461                if (parts[1]) {
22462                    var values = (parts[1] || '').split(/,\s*/);
22463                    type = type ? type : parts[1] ? parts[0].substr(0, 3) : 'rgb';
22464                    this.set(values, type);
22465                } else {
22466                    this.set((0, _ColorConverter.getColorAsRGB)(color), 'rgb');
22467                }
22468            } else if (color) {
22469                if (Array.isArray(color)) {
22470                    var m = '';
22471                    type = type || 'rgb';
22472
22473                    this.colors[type] = this.colors[type] || {};
22474                    for (var _n = 3; _n--;) {
22475                        m = type[_n] || type.charAt(_n); // IE7
22476                        var i = color.length >= 3 ? _n : 0;
22477                        this.colors[type][m] = parseFloat(color[i]);
22478                    }
22479
22480                    if (color.length === 4) {
22481                        this.colors.alpha = parseFloat(color[3]);
22482                    }
22483                } else if (type) {
22484                    for (var _n2 in color) {
22485                        this.colors[type][_n2] = (0, _ColorConverter.limitValue)(color[_n2] / (0, _ColorConverter.getValueRanges)(type)[_n2][1], 0, 1) * (0, _ColorConverter.getValueRanges)(type)[_n2][1];
22486                    }
22487                }
22488            }
22489
22490            if (!type) {
22491                return;
22492            }
22493
22494            if (type !== 'rgb') {
22495                var convert = _ColorConverter2['default'];
22496                this.colors.rgb = convert[type + '2rgb'](this.colors[type]);
22497            }
22498            this.convert(type);
22499            this.colors.hueRGB = _ColorConverter2['default'].hue2RGB(this.colors.hsv.h);
22500            this.colors.luminance = (0, _ColorConverter.getLuminance)(this.colors.rgb);
22501        }
22502    }, {
22503        key: 'convert',
22504        value: function convert(type) {
22505            var convert = _ColorConverter2['default'],
22506                ranges = (0, _ColorConverter.getValueRanges)(),
22507                exceptions = { hsl: 'hsv', cmyk: 'cmy', rgb: type };
22508
22509            if (type !== 'alpha') {
22510                for (var typ in ranges) {
22511                    if (!ranges[typ][typ]) {
22512                        // no alpha|HEX
22513                        if (type !== typ && typ !== 'XYZ') {
22514                            var from = exceptions[typ] || 'rgb';
22515                            this.colors[typ] = convert[from + '2' + typ](this.colors[from]);
22516                        }
22517                    }
22518                }
22519            }
22520        }
22521    }, {
22522        key: 'get',
22523        value: function get(type) {
22524            if (type !== 'rgb') {
22525                var convert = _ColorConverter2['default'];
22526                this.colors[type] = convert['rgb2' + type](this.colors['rgb']);
22527                return this.colors[type];
22528            } else {
22529                return this.colors['rgb'];
22530            }
22531        }
22532    }, {
22533        key: 'getString',
22534        value: function getString(type) {
22535            if (type === 'HEX') {
22536                var convert = _ColorConverter2['default'];
22537                return convert['rgb2' + type](this.colors['rgb']);
22538            } else {
22539                var color = this.get(type);
22540                var str = type,
22541                    m = '';
22542                if (type === 'vec') {
22543                    str += this.colors.alpha ? 4 : 3;
22544                }
22545                str += '(';
22546                for (var n = 0; n < 3; n++) {
22547                    m = type[n] || type.charAt(n); // IE7
22548                    if (type === 'vec') {
22549                        str += color[m].toFixed(3);
22550                    } else {
22551                        str += Math.floor(color[m]);
22552                    }
22553                    if (n !== 2) {
22554                        str += ',';
22555                    }
22556                }
22557
22558                if (this.colors.alpha) {
22559                    str += ',' + this.colors.alpha.toFixed(3);
22560                }
22561                return str += ')';
22562            }
22563        }
22564    }, {
22565        key: 'uniformType',
22566        value: function uniformType() {
22567            if (this.colors.alpha) {
22568                return 'vec4';
22569            }
22570            return 'vec3';
22571        }
22572    }, {
22573        key: 'uniformValue',
22574        value: function uniformValue() {
22575            var vec = this.get('vec');
22576            var arr = [vec.v, vec.e, vec.c];
22577            if (this.colors.alpha) {
22578                arr.push(this.colors.alpha);
22579            }
22580            return arr;
22581        }
22582    }, {
22583        key: 'uniformMethod',
22584        value: function uniformMethod(type) {
22585            if (this.colors.alpha) {
22586                return '4f';
22587            }
22588            return '3f';
22589        }
22590    }]);
22591
22592    return Color;
22593})();
22594
22595exports['default'] = Color;
22596module.exports = exports['default'];
22597
22598},{"./ColorConverter":142,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14}],142:[function(_dereq_,module,exports){
22599'use strict';
22600
22601var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
22602
22603var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
22604
22605Object.defineProperty(exports, '__esModule', {
22606    value: true
22607});
22608exports.limitValue = limitValue;
22609exports.getLuminance = getLuminance;
22610exports.getColorAsRGB = getColorAsRGB;
22611exports.getValueRanges = getValueRanges;
22612var valueRanges = {
22613    rgb: { r: [0, 255], g: [0, 255], b: [0, 255] },
22614    hsv: { h: [0, 1], s: [0, 1], v: [0, 255] },
22615    hsl: { h: [0, 360], s: [0, 100], l: [0, 100] },
22616    cmy: { c: [0, 100], m: [0, 100], y: [0, 100] },
22617    cmyk: { c: [0, 100], m: [0, 100], y: [0, 100], k: [0, 100] },
22618    Lab: { L: [0, 100], a: [-128, 127], b: [-128, 127] },
22619    XYZ: { X: [0, 100], Y: [0, 100], Z: [0, 100] },
22620    vec: { v: [0, 1], e: [0, 1], c: [0, 1] },
22621    alpha: { alpha: [0, 1] },
22622    HEX: { HEX: [0, 16777215] } // maybe we don't need this
22623};
22624
22625// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html for more
22626var XYZMatrix = { // Observer = 2° (CIE 1931), Illuminant = D65
22627    X: [0.4124564, 0.3575761, 0.1804375],
22628    Y: [0.2126729, 0.7151522, 0.0721750],
22629    Z: [0.0193339, 0.1191920, 0.9503041],
22630    R: [3.2404542, -1.5371385, -0.4985314],
22631    G: [-0.9692660, 1.8760108, 0.0415560],
22632    B: [0.0556434, -0.2040259, 1.0572252]
22633};
22634
22635var XYZReference = {
22636    X: XYZMatrix.X[0] + XYZMatrix.X[1] + XYZMatrix.X[2],
22637    Y: XYZMatrix.Y[0] + XYZMatrix.Y[1] + XYZMatrix.Y[2],
22638    Z: XYZMatrix.Z[0] + XYZMatrix.Z[1] + XYZMatrix.Z[2]
22639};
22640
22641var luminance = { r: 0.2126, g: 0.7152, b: 0.0722 }; // W3C 2.0
22642
22643var _colors;
22644
22645var ColorConverter = (function () {
22646    function ColorConverter() {
22647        _classCallCheck(this, ColorConverter);
22648    }
22649
22650    _createClass(ColorConverter, null, [{
22651        key: 'vec2rgb',
22652
22653        // ------------------------ VEC ------------------------ //
22654        value: function vec2rgb(vec) {
22655            return {
22656                r: vec.v * valueRanges['rgb']['r'][1],
22657                g: vec.e * valueRanges['rgb']['g'][1],
22658                b: vec.c * valueRanges['rgb']['b'][1]
22659            };
22660        }
22661    }, {
22662        key: 'rgb2vec',
22663        value: function rgb2vec(rgb) {
22664            return {
22665                v: rgb.r / valueRanges['rgb']['r'][1],
22666                e: rgb.g / valueRanges['rgb']['g'][1],
22667                c: rgb.b / valueRanges['rgb']['b'][1]
22668            };
22669        }
22670
22671        // ------------------------ HEX ------------------------ //
22672
22673    }, {
22674        key: 'RGB2HEX',
22675        value: function RGB2HEX(rgb) {
22676            return ((rgb.r < 16 ? '0' : '') + rgb.r.toString(16) + (rgb.g < 16 ? '0' : '') + rgb.g.toString(16) + (rgb.b < 16 ? '0' : '') + rgb.b.toString(16)).toUpperCase();
22677        }
22678    }, {
22679        key: 'HEX2rgb',
22680        value: function HEX2rgb(HEX) {
22681            HEX = HEX.split(''); // IE7
22682            return {
22683                r: parseInt(HEX[0] + HEX[HEX[3] ? 1 : 0], 16) / 255,
22684                g: parseInt(HEX[HEX[3] ? 2 : 1] + (HEX[3] || HEX[1]), 16) / 25
226845,
22685                b: parseInt((HEX[4] || HEX[2]) + (HEX[5] || HEX[2]), 16) / 255
22686            };
22687        }
22688
22689        // ------------------------ HUE ------------------------ //
22690
22691    }, {
22692        key: 'hue2RGB',
22693        value: function hue2RGB(hue) {
22694            var h = hue * 6,
22695
22696            // mod = ~~h % 6, // Math.floor(h) -> faster in most browsers
22697            mod = Math.floor(h),
22698                i = h === 6 ? 0 : h - mod;
22699            return {
22700                r: Math.round([1, 1 - i, 0, 0, i, 1][mod] * 255),
22701                g: Math.round([i, 1, 1, 1 - i, 0, 0][mod] * 255),
22702                b: Math.round([0, 0, i, 1, 1, 1 - i][mod] * 255)
22703            };
22704        }
22705
22706        // ------------------------ HSV ------------------------ //
22707
22708    }, {
22709        key: 'rgb2hsv',
22710        value: function rgb2hsv(rgb) {
22711            // faster
22712            var r = rgb.r,
22713                g = rgb.g,
22714                b = rgb.b,
22715                k = 0,
22716                chroma,
22717                min,
22718                s;
22719
22720            if (g < b) {
22721                g = b + (b = g, 0);
22722                k = -1;
22723            }
22724            min = b;
22725            if (r < g) {
22726                r = g + (g = r, 0);
22727                k = -2 / 6 - k;
22728                min = Math.min(g, b); // g < b ? g : b; ???
22729            }
22730            chroma = r - min;
22731            s = r ? chroma / r : 0;
22732            return {
22733                h: s < 1e-15 ? _colors && _colors.hsl && _colors.hsl.h || 0 : chroma ? Math.abs(k + (g - b) / (6 * chroma)) : 0,
22734                s: r ? chroma / r : _colors && _colors.hsv && _colors.hsv.s || 0, // ??_colors.hsv.s || 0
22735                v: r
22736            };
22737        }
22738    }, {
22739        key: 'hsv2rgb',
22740        value: function hsv2rgb(hsv) {
22741            var h = hsv.h * 6,
22742                s = hsv.s,
22743                v = hsv.v,
22744
22745            // i = ~~h, // Math.floor(h) -> faster in most browsers
22746            i = Math.floor(h),
22747                f = h - i,
22748                p = v * (1 - s),
22749                q = v * (1 - f * s),
22750                t = v * (1 - (1 - f) * s),
22751                mod = i % 6;
22752
22753            return {
22754                r: [v, q, p, p, t, v][mod],
22755                g: [t, v, v, q, p, p][mod],
22756                b: [p, p, t, v, v, q][mod]
22757            };
22758        }
22759
22760        // ------------------------ HSL ------------------------ //
22761
22762    }, {
22763        key: 'hsv2hsl',
22764        value: function hsv2hsl(hsv) {
22765            var l = (2 - hsv.s) * hsv.v,
22766                s = hsv.s * hsv.v;
22767
22768            s = !hsv.s ? 0 : l < 1 ? l ? s / l : 0 : s / (2 - l);
22769
22770            return {
22771                h: hsv.h,
22772                s: !hsv.v && !s ? _colors && _colors.hsl && _colors.hsl.s || 0 : s, // ???
22773                l: l / 2
22774            };
22775        }
22776    }, {
22777        key: 'rgb2hsl',
22778        value: function rgb2hsl(rgb, dependent) {
22779            // not used in Color
22780            var hsv = ColorConverter.rgb2hsv(rgb);
22781
22782            return ColorConverter.hsv2hsl(dependent ? hsv : _colors.hsv = hsv);
22783        }
22784    }, {
22785        key: 'hsl2rgb',
22786        value: function hsl2rgb(hsl) {
22787            var h = hsl.h * 6,
22788                s = hsl.s,
22789                l = hsl.l,
22790                v = l < 0.5 ? l * (1 + s) : l + s - s * l,
22791                m = l + l - v,
22792                sv = v ? (v - m) / v : 0,
22793
22794            // sextant = ~~h, // Math.floor(h) -> faster in most browsers
22795            sextant = Math.floor(h),
22796                fract = h - sextant,
22797                vsf = v * sv * fract,
22798                t = m + vsf,
22799                q = v - vsf,
22800                mod = sextant % 6;
22801
22802            return {
22803                r: [v, q, m, m, t, v][mod],
22804                g: [t, v, v, q, m, m][mod],
22805                b: [m, m, t, v, v, q][mod]
22806            };
22807        }
22808
22809        // ------------------------ CMYK ------------------------ //
22810        // Quote from Wikipedia:
22811        // 'Since RGB and CMYK spaces are both device-dependent spaces, there is no
22812        // simple or general conversion formula that converts between them.
22813        // Conversions are generally done through color management systems, using
22814        // color profiles that describe the spaces being converted. Nevertheless, the
22815        // conversions cannot be exact, since these spaces have very different gamuts.'
22816        // Translation: the following are just simple RGB to CMY(K) and visa versa conversion functions.
22817
22818    }, {
22819        key: 'rgb2cmy',
22820        value: function rgb2cmy(rgb) {
22821            return {
22822                c: 1 - rgb.r,
22823                m: 1 - rgb.g,
22824                y: 1 - rgb.b
22825            };
22826        }
22827    }, {
22828        key: 'cmy2cmyk',
22829        value: function cmy2cmyk(cmy) {
22830            var k = Math.min(Math.min(cmy.c, cmy.m), cmy.y),
22831                t = 1 - k || 1e-20;
22832
22833            return { // regular
22834                c: (cmy.c - k) / t,
22835                m: (cmy.m - k) / t,
22836                y: (cmy.y - k) / t,
22837                k: k
22838            };
22839        }
22840    }, {
22841        key: 'cmyk2cmy',
22842        value: function cmyk2cmy(cmyk) {
22843            var k = cmyk.k;
22844
22845            return { // regular
22846                c: cmyk.c * (1 - k) + k,
22847                m: cmyk.m * (1 - k) + k,
22848                y: cmyk.y * (1 - k) + k
22849            };
22850        }
22851    }, {
22852        key: 'cmy2rgb',
22853        value: function cmy2rgb(cmy) {
22854            return {
22855                r: 1 - cmy.c,
22856                g: 1 - cmy.m,
22857                b: 1 - cmy.y
22858            };
22859        }
22860    }, {
22861        key: 'rgb2cmyk',
22862        value: function rgb2cmyk(rgb) {
22863            var cmy = ColorConverter.rgb2cmy(rgb); // doppelt??
22864            return ColorConverter.cmy2cmyk(cmy);
22865        }
22866    }, {
22867        key: 'cmyk2rgb',
22868        value: function cmyk2rgb(cmyk) {
22869            var cmy = ColorConverter.cmyk2cmy(cmyk); // doppelt??
22870            return ColorConverter.cmy2rgb(cmy);
22871        }
22872
22873        // ------------------------ LAB ------------------------ //
22874
22875    }, {
22876        key: 'XYZ2rgb',
22877        value: function XYZ2rgb(XYZ) {
22878            var M = XYZMatrix,
22879                X = XYZ.X,
22880                Y = XYZ.Y,
22881                Z = XYZ.Z,
22882                r = X * M.R[0] + Y * M.R[1] + Z * M.R[2],
22883                g = X * M.G[0] + Y * M.G[1] + Z * M.G[2],
22884                b = X * M.B[0] + Y * M.B[1] + Z * M.B[2],
22885                N = 1 / 2.4;
22886
22887            M = 0.0031308;
22888
22889            r = r > M ? 1.055 * Math.pow(r, N) - 0.055 : 12.92 * r;
22890            g = g > M ? 1.055 * Math.pow(g, N) - 0.055 : 12.92 * g;
22891            b = b > M ? 1.055 * Math.pow(b, N) - 0.055 : 12.92 * b;
22892
22893            return {
22894                r: limitValue(r, 0, 1),
22895                g: limitValue(g, 0, 1),
22896                b: limitValue(b, 0, 1)
22897            };
22898        }
22899    }, {
22900        key: 'rgb2XYZ',
22901        value: function rgb2XYZ(rgb) {
22902            var M = XYZMatrix,
22903                r = rgb.r,
22904                g = rgb.g,
22905                b = rgb.b,
22906                N = 0.04045;
22907
22908            r = r > N ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
22909            g = g > N ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
22910            b = b > N ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
22911
22912            return {
22913                X: r * M.X[0] + g * M.X[1] + b * M.X[2],
22914                Y: r * M.Y[0] + g * M.Y[1] + b * M.Y[2],
22915                Z: r * M.Z[0] + g * M.Z[1] + b * M.Z[2]
22916            };
22917        }
22918    }, {
22919        key: 'XYZ2Lab',
22920        value: function XYZ2Lab(XYZ) {
22921            var R = XYZReference,
22922                X = XYZ.X / R.X,
22923                Y = XYZ.Y / R.Y,
22924                Z = XYZ.Z / R.Z,
22925                N = 16 / 116,
22926                M = 1 / 3,
22927                K = 0.008856,
22928                L = 7.787037;
22929
22930            X = X > K ? Math.pow(X, M) : L * X + N;
22931            Y = Y > K ? Math.pow(Y, M) : L * Y + N;
22932            Z = Z > K ? Math.pow(Z, M) : L * Z + N;
22933
22934            return {
22935                L: 116 * Y - 16,
22936                a: 500 * (X - Y),
22937                b: 200 * (Y - Z)
22938            };
22939        }
22940    }, {
22941        key: 'Lab2XYZ',
22942        value: function Lab2XYZ(Lab) {
22943            var R = XYZReference,
22944                Y = (Lab.L + 16) / 116,
22945                X = Lab.a / 500 + Y,
22946                Z = Y - Lab.b / 200,
22947                X3 = Math.pow(X, 3),
22948                Y3 = Math.pow(Y, 3),
22949                Z3 = Math.pow(Z, 3),
22950                N = 16 / 116,
22951                K = 0.008856,
22952                L = 7.787037;
22953
22954            return {
22955                X: (X3 > K ? X3 : (X - N) / L) * R.X,
22956                Y: (Y3 > K ? Y3 : (Y - N) / L) * R.Y,
22957                Z: (Z3 > K ? Z3 : (Z - N) / L) * R.Z
22958            };
22959        }
22960    }, {
22961        key: 'rgb2Lab',
22962        value: function rgb2Lab(rgb) {
22963            var XYZ = ColorConverter.rgb2XYZ(rgb);
22964
22965            return ColorConverter.XYZ2Lab(XYZ);
22966        }
22967    }, {
22968        key: 'Lab2rgb',
22969        value: function Lab2rgb(Lab) {
22970            var XYZ = ColorConverter.Lab2XYZ(Lab);
22971
22972            return ColorConverter.XYZ2rgb(XYZ);
22973        }
22974    }]);
22975
22976    return ColorConverter;
22977})();
22978
22979exports['default'] = ColorConverter;
22980
22981function limitValue(value, min, max) {
22982    // return Math.max(min, Math.min(max, value)); // faster??
22983    return value > max ? max : value < min ? min : value;
22984}
22985
22986function getLuminance(rgb, normalized) {
22987    var div = normalized ? 1 : 255,
22988        RGB = [rgb.r / div, rgb.g / div, rgb.b / div];
22989
22990    for (var i = RGB.length; i--;) {
22991        RGB[i] = RGB[i] <= 0.03928 ? RGB[i] / 12.92 : Math.pow((RGB[i] + 0.055) / 1.055, 2.4);
22992    }
22993    return luminance.r * RGB[0] + luminance.g * RGB[1] + luminance.b * RGB[2];
22994}
22995
22996function getColorAsRGB(color) {
22997    // Create a test element to apply a CSS color and retrieve
22998    // a normalized value from.
22999    var test = document.createElement('div');
23000    test.style.backgroundColor = color;
23001
23002    // Chrome requires the element to be in DOM for styles to be computed.
23003    document.body.appendChild(test);
23004
23005    // Get the computed style from the browser, in the format of
23006    // rgb(x, x, x)
23007    var normalized = window.getComputedStyle(test).backgroundColor;
23008
23009    // In certain cases getComputedStyle() may return
23010    // 'transparent' as a value, which is useless(?) for the current
23011    // color picker. According to specifications, transparent
23012    // is a black with 0 alpha - rgba(0, 0, 0, 0) - but because
23013    // the picker does not currently handle alpha, we return the
23014    // black value.
23015    if (normalized === 'transparent') {
23016        normalized = 'rgb(0, 0, 0)';
23017    }
23018
23019    // Garbage collection
23020    test.parentNode.removeChild(test);
23021
23022    return normalized;
23023}
23024
23025function getValueRanges(type) {
23026    if (!type) {
23027        return valueRanges;
23028    } else {
23029        return valueRanges[type];
23030    }
23031}
23032
23033},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],143:[function(_dereq_,module,exports){
23034'use strict';
23035
23036var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
23037
23038var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
23039
23040Object.defineProperty(exports, '__esModule', {
23041    value: true
23042});
23043
23044var Float = (function () {
23045    function Float(value) {
23046        _classCallCheck(this, Float);
23047
23048        this.value = value;
23049    }
23050
23051    _createClass(Float, [{
23052        key: 'getString',
23053        value: function getString() {
23054            return this.value.toFixed(3);
23055        }
23056    }, {
23057        key: 'uniformType',
23058        value: function uniformType() {
23059            return 'float';
23060        }
23061    }, {
23062        key: 'uniformValue',
23063        value: function uniformValue() {
23064            return [this.value];
23065        }
23066    }, {
23067        key: 'uniformMethod',
23068        value: function uniformMethod() {
23069            return '1f';
23070        }
23071    }]);
23072
23073    return Float;
23074})();
23075
23076exports['default'] = Float;
23077module.exports = exports['default'];
23078
23079},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}],144:[function(_dereq_,module,exports){
23080'use strict';
23081
23082var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
23083
23084var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
23085
23086var _interopRequireDefault = _dereq_('babel-runtime/helpers/interop-require-default')['default'];
23087
23088Object.defineProperty(exports, '__esModule', {
23089    value: true
23090});
23091
23092var _Vector = _dereq_('./Vector');
23093
23094var _Vector2 = _interopRequireDefault(_Vector);
23095
23096// TODO:
23097//      - generalize this for mat2, mat3 and mat4
23098
23099var Matrix = (function () {
23100    function Matrix(m, type) {
23101        _classCallCheck(this, Matrix);
23102
23103        this.dim = 3;
23104        this.value = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
23105        if (m) {
23106            this.set(m, type);
23107        }
23108    }
23109
23110    _createClass(Matrix, [{
23111        key: 'set',
23112        value: function set(m, type) {
23113            if (m.value[0][0]) {
23114                this.value = m.value;
23115                this.dim = m.dim;
23116            } else if (m[0][0]) {
23117                this.value = m;
23118            }
23119        }
23120    }, {
23121        key: 'rotateX',
23122        value: function rotateX(theta) {
23123            var c = Math.cos(theta);
23124            var s = Math.sin(theta);
23125            var T = [[1, 0, 0], [0, c, -s], [0, s, c]];
23126
23127            this.value = this.getTransform(T);
23128        }
23129    }, {
23130        key: 'rotateY',
23131        value: function rotateY(theta) {
23132            var c = Math.cos(theta);
23133            var s = Math.sin(theta);
23134            var T = [[c, 0, s], [0, 1, 0], [-s, 0, c]];
23135
23136            this.value = this.getTransform(T);
23137        }
23138    }, {
23139        key: 'getMult',
23140        value: function getMult(v) {
23141            if (v[0][0] || v.value && v.value[0][0]) {
23142                // TODO: what If v is a matrix
23143                console.log('TODO: what If v is a matrix');
23144            } else {
23145                // If v is a vector
23146                var A = new _Vector2['default'](v);
23147                var B = [];
23148                for (var i = 0; i < A.dim; i++) {
23149                    B.push(A.value[0] * this.value[i][0] + A.value[1] * this.value[i][1] + A.value[2] * this.value[i][2]);
23150                }
23151                return new _Vector2['default'](B);
23152            }
23153        }
23154    }, {
23155        key: 'getTransform',
23156        value: function getTransform(m) {
23157            var newMatrix = [];
23158            for (var row in m) {
23159                var t = m[row];
23160                var newRow = [];
23161                newRow.push(t[0] * this.value[0][0] + t[1] * this.value[1][0] + t[2] * this.value[2][0]);
23162                newRow.push(t[0] * this.value[0][1] + t[1] * this.value[1][1] + t[2] * this.value[2][1]);
23163                newRow.push(t[0] * this.value[0][2] + t[1] * this.value[1][2] + t[2] * this.value[2][2]);
23164                newMatrix.push(newRow);
23165            }
23166            return newMatrix;
23167        }
23168    }, {
23169        key: 'getInv',
23170        value: function getInv() {
23171            var M = new Matrix();
23172            var determinant = this.value[0][0] * (this.value[1][1] * this.value[2][2] - this.value[2][1] * this.value[1][2]) - this.value[0][1] * (this.value[1][0] * this.value[2][2] - this.value[1][2] * this.value[2][0]) + this.value[0][2] * (this.value[1][0] * this.value[2][1] - this.value[1][1] * this.value[2][0]);
23173            var invdet = 1 / determinant;
23174            M.value[0][0] = (this.value[1][1] * this.value[2][2] - this.value[2][1] * this.value[1][2]) * invdet;
23175            M.value[0][1] = -(this.value[0][1] * this.value[2][2] - this.value[0][2] * this.value[2][1]) * invdet;
23176            M.value[0][2] = (this.value[0][1] * this.value[1][2] - this.value[0][2] * this.value[1][1]) * invdet;
23177            M.value[1][0] = -(this.value[1][0] * this.value[2][2] - this.value[1][2] * this.value[2][0]) * invdet;
23178            M.value[1][1] = (this.value[0][0] * this.value[2][2] - this.value[0][2] * this.value[2][0]) * invdet;
23179            M.value[1][2] = -(this.value[0][0] * this.value[1][2] - this.value[1][0] * this.value[0][2]) * invdet;
23180            M.value[2][0] = (this.value[1][0] * this.value[2][1] - this.value[2][0] * this.value[1][1]) * invdet;
23181            M.value[2][1] = -(this.value[0][0] * this.value[2][1] - this.value[2][0] * this.value[0][1]) * invdet;
23182            M.value[2][2] = (this.value[0][0] * this.value[1][1] - this.value[1][0] * this.value[0][1]) * invdet;
23183            return M;
23184        }
23185    }]);
23186
23187    return Matrix;
23188})();
23189
23190exports['default'] = Matrix;
23191module.exports = exports['default'];
23192
23193},{"./Vector":145,"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11,"babel-runtime/helpers/interop-require-default":14}],145:[function(_dereq_,module,exports){
23194'use strict';
23195
23196var _createClass = _dereq_('babel-runtime/helpers/create-class')['default'];
23197
23198var _classCallCheck = _dereq_('babel-runtime/helpers/class-call-check')['default'];
23199
23200Object.defineProperty(exports, '__esModule', {
23201    value: true
23202});
23203
23204var Vector = (function () {
23205    function Vector(vec, type) {
23206        _classCallCheck(this, Vector);
23207
23208        this.value = [0, 0];
23209        this.dim = 2;
23210        this.set(vec, type);
23211    }
23212
23213    _createClass(Vector, [{
23214        key: 'set',
23215        value: function set(vec, type) {
23216            if (typeof vec === 'number') {
23217                type = type || 'vec2';
23218                this.set([vec], type);
23219            } else if (typeof vec === 'string') {
23220                var parts = vec.replace(/(?:#|\)|\]|%)/g, '').split('(');
23221                var strValues = (parts[1] || parts[0].replace(/(\[)/g, '')).split(/,\s*/);
23222                type = type || (parts[1] ? parts[0].substr(0, 4) : 'vec' + strValues.length);
23223                var values = [];
23224                for (var i in strValues) {
23225                    values.push(parseFloat(strValues[i]));
23226                }
23227                this.set(values, type);
23228            } else if (vec) {
23229                if (Array.isArray(vec)) {
23230                    this.value = [];
23231                    this.value.length = 0;
23232                    this.dim = type ? Number(type.substr(3, 4)) : vec.length;
23233                    var filler = vec.length === 1 ? vec[0] : 0;
23234                    for (var i = 0; i < this.dim; i++) {
23235                        this.value.push(vec[i] || filler);
23236                    }
23237                } else if (vec.dim) {
23238                    this.value = vec.value;
23239                    this.dim = vec.dim;
23240                }
23241            }
23242        }
23243    }, {
23244        key: 'getString',
23245        value: function getString(type) {
23246            type = type || 'vec' + this.dim;
23247
23248            var len = this.dim;
23249            var str = '';
23250            var head = type + '(';
23251            var end = ')';
23252
23253            if (type === 'array') {
23254                head = '[';
23255                end = ']';
23256                len = this.dim;
23257            } else {
23258                len = Number(type.substr(3, 4));
23259            }
23260
23261            str = head;
23262            for (var i = 0; i < len; i++) {
23263                str += this.value[i].toFixed(3);
23264                if (i !== len - 1) {
23265                    str += ',';
23266                }
23267            }
23268            return str += end;
23269        }
23270    }, {
23271        key: 'uniformType',
23272        value: function uniformType() {
23273            return 'vec' + this.dim;
23274        }
23275    }, {
23276        key: 'uniformValue',
23277        value: function uniformValue() {
23278            var arr = [];
23279            for (var i = 0; i < this.dim; i++) {
23280                arr.push(this.value[i]);
23281            }
23282            return arr;
23283        }
23284    }, {
23285        key: 'uniformMethod',
23286        value: function uniformMethod() {
23287            return this.dim + 'f';
23288        }
23289
23290        // VECTOR OPERATIONS
23291
23292    }, {
23293        key: 'add',
23294        value: function add(v) {
23295            if (typeof v === 'number') {
23296                for (var i = 0; i < this.dim; i++) {
23297                    this.value[i] = this.value[i] + v;
23298                }
23299            } else {
23300                var A = new Vector(v);
23301                var lim = Math.min(this.dim, A.dim);
23302                for (var i = 0; i < lim; i++) {
23303                    this.value[i] = this.value[i] + A.value[i];
23304                }
23305            }
23306        }
23307    }, {
23308        key: 'sub',
23309        value: function sub(v) {
23310            if (typeof v === 'number') {
23311                for (var i = 0; i < this.dim; i++) {
23312                    this.value[i] = this.value[i] - v;
23313                }
23314            } else {
23315                var A = new Vector(v);
23316                var lim = Math.min(this.dim, A.dim);
23317                for (var i = 0; i < lim; i++) {
23318                    this.value[i] = this.value[i] - A.value[i];
23319                }
23320            }
23321        }
23322    }, {
23323        key: 'mult',
23324        value: function mult(v) {
23325            if (typeof v === 'number') {
23326                // Mulitply by scalar
23327                for (var i = 0; i < this.dim; i++) {
23328                    this.value[i] = this.value[i] * v;
23329                }
23330            } else {
23331                // Multiply two vectors
23332                var A = new Vector(v);
23333                var lim = Math.min(this.dim, A.dim);
23334                for (var i = 0; i < lim; i++) {
23335                    this.value[i] = this.value[i] * A.value[i];
23336                }
23337            }
23338        }
23339    }, {
23340        key: 'div',
23341        value: function div(v) {
23342            if (typeof v === 'number') {
23343                // Mulitply by scalar
23344                for (var i = 0; i < this.dim; i++) {
23345                    this.value[i] = this.value[i] / v;
23346                }
23347            } else {
23348                // Multiply two vectors
23349                var A = new Vector(v);
23350                var lim = Math.min(this.dim, A.dim);
23351                for (var i = 0; i < lim; i++) {
23352                    this.value[i] = this.value[i] / A.value[i];
23353                }
23354            }
23355        }
23356    }, {
23357        key: 'normalize',
23358        value: function normalize() {
23359            var l = this.getLength();
23360            this.div(l);
23361        }
23362    }, {
23363        key: 'getAdd',
23364        value: function getAdd(v) {
23365            var A = new Vector(this);
23366            A.add(v);
23367            return A;
23368        }
23369    }, {
23370        key: 'getSub',
23371        value: function getSub(v) {
23372            var A = new Vector(this);
23373            A.sub(v);
23374            return A;
23375        }
23376    }, {
23377        key: 'getMult',
23378        value: function getMult(v) {
23379            var A = new Vector(this);
23380            A.mult(v);
23381            return A;
23382        }
23383    }, {
23384        key: 'getDiv',
23385        value: function getDiv(v) {
23386            var A = new Vector(this);
23387            A.div(v);
23388            return A;
23389        }
23390    }, {
23391        key: 'getLengthSq',
23392        value: function getLengthSq() {
23393            if (this.dim === 2) {
23394                return this.value[0] * this.value[0] + this.value[1] * this.value[1];
23395            } else {
23396                return this.value[0] * this.value[0] + this.value[1] * this.value[1] + this.value[2] * this.value[2];
23397            }
23398        }
23399    }, {
23400        key: 'getLength',
23401        value: function getLength() {
23402            return Math.sqrt(this.getLengthSq());
23403        }
23404    }, {
23405        key: 'x',
23406        set: function set(v) {
23407            this.value[0] = v;
23408        },
23409        get: function get() {
23410            return this.value[0] || 0.0;
23411        }
23412    }, {
23413        key: 'y',
23414        set: function set(v) {
23415            this.value[1] = v;
23416        },
23417        get: function get() {
23418            return this.value[1] || 0.0;
23419        }
23420    }, {
23421        key: 'z',
23422        set: function set(v) {
23423            if (this.dim < 3) {
23424                while (this.dim < 3) {
23425                    this.value.push(0);
23426                }
23427                this.dim = 3;
23428            }
23429            this.value[2] = v;
23430        },
23431        get: function get() {
23432            return this.value[2] || 0.0;
23433        }
23434    }, {
23435        key: 'w',
23436        set: function set(v) {
23437            if (this.dim < 4) {
23438                while (this.dim < 4) {
23439                    this.value.push(0);
23440                }
23441                this.dim = 4;
23442            }
23443            this.value[3] = v;
23444        },
23445        get: function get() {
23446            return this.value[3] || 0.0;
23447        }
23448    }]);
23449
23450    return Vector;
23451})();
23452
23453exports['default'] = Vector;
23454module.exports = exports['default'];
23455
23456},{"babel-runtime/helpers/class-call-check":10,"babel-runtime/helpers/create-class":11}]},{},[114])(114)
23457});
23458
23459//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL2dldC1pdGVyYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2Fzc2lnbi5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2NyZWF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvci
234595qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2tleXMuanMiLCJub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwibm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9wcm9taXNlLmpzIiwibm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zZXQuanMiLCJub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9oZWxwZXJzL2NsYXNzLWNhbGwtY2hlY2suanMiLCJub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9oZWxwZXJzL2NyZWF0ZS1jbGFzcy5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvZ2V0LmpzIiwibm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9pbmhlcml0cy5qcyIsIm5vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvaW50ZXJvcC1yZXF1aXJlLWRlZmF1bHQuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9hZGRvbi9jb21tZW50L2NvbW1lbnQuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9hZGRvbi9kaWFsb2cvZGlhbG9nLmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvYWRkb24vZGlzcGxheS9wYW5lbC5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2Rpc3BsYXkvcnVsZXJzLmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvYWRkb24vZWRpdC9jbG9zZWJyYWNrZXRzLmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvYWRkb24vZWRpdC9tYXRjaGJyYWNrZXRzLmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvYWRkb24vZm9sZC9mb2xkY29kZS5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2ZvbGQvZm9sZGd1dHRlci5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2ZvbGQvaW5kZW50LWZvbGQuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9hZGRvbi9oaW50L2phdmFzY3JpcHQtaGludC5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2hpbnQvc2hvdy1oaW50LmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvYWRkb24vc2VhcmNoL3NlYXJjaC5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL3NlYXJjaC9zZWFyY2hjdXJzb3IuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9hZGRvbi93cmFwL2hhcmR3cmFwLmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3Iva2V5bWFwL3N1YmxpbWUuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9saWIvY29kZW1pcnJvci5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvY2xpa2UvY2xpa2UuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL2dldC1pdGVyYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnbi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvci
234595qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2tleXMuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9zZXQuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5hLWZ1bmN0aW9uLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuYWRkLXRvLXVuc2NvcGFibGVzLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuYW4tb2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuY2xhc3NvZi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLmNvZi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLmNvbGxlY3Rpb24tc3Ryb25nLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuY29sbGVjdGlvbi10by1qc29uLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuY29sbGVjdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLmNvcmUuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5jdHguanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5kZWZpbmVkLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuZGVzY3JpcHRvcnMuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5kb20tY3JlYXRlLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuZXhwb3J0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuZmFpbHMuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5mb3Itb2YuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5nbG9iYWwuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5oYXMuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5oaWRlLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaHRtbC5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLmludm9rZS5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLmlvYmplY3QuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5pcy1hcnJheS1pdGVyLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaXMtb2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaXRlci1jYWxsLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaXRlci1jcmVhdGUuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5pdGVyLWRlZmluZS5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLml0ZXItZGV0ZWN0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaXRlci1zdGVwLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuaXRlcmF0b3JzLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5saWJyYXJ5LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQubWljcm90YXNrLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQub2JqZWN0LWFzc2lnbi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLm9iamVjdC1zYXAuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5wcm9wZXJ0eS1kZXNjLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQucmVkZWZpbmUtYWxsLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQucmVkZWZpbmUuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5zYW1lLXZhbHVlLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuc2V0LXByb3RvLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuc2V0LXNwZWNpZXMuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5zZXQtdG8tc3RyaW5nLXRhZy5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLnNoYXJlZC5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLnNwZWNpZXMtY29uc3RydWN0b3IuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC5zdHJpY3QtbmV3LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQuc3RyaW5nLWF0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQudGFzay5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy8kLnRvLWludGVnZXIuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvJC50by1pb2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQudG8tbGVuZ3RoLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQudG8tb2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQudWlkLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzLyQud2tzLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZC5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuYXJyYXkuaXRlcmF0b3IuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5hc3NpZ24uanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3IuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5rZXlzLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3Quc2V0LXByb3RvdHlwZS1vZi5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYucHJvbWlzZS5qcyIsIm5vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc2V0LmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3IuanMiLCJub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzIiwibm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanMiLCJub2RlX21vZHVsZXMvZG9jdW1lbnQtcmVnaXN0ZXItZWxlbWVudC9idWlsZC9kb2N1bWVudC1yZWdpc3Rlci1lbGVtZW50Lm5vZGUuanMiLCJub2RlX21vZHVsZXMvZ2xvYmFsL3dpbmRvdy5qcyIsIm5vZGVfbW9kdWxlcy9nbHNsQ2FudmFzL2Rpc3QvR2xzbENhbnZhcy5qcyIsIm5vZGVfbW9kdWxlcy9pcy1mdW5jdGlvbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYXJzZS1oZWFkZXJzL3BhcnNlLWhlYWRlcnMuanMiLCJub2RlX21vZHVsZXMveGhyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3h0ZW5kL2ltbXV0YWJsZS5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvR2xzbEVkaXRvci5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvY29yZS9FZGl0b3IuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL2Nvcm
23459UvU2hhZGVyLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy9pby9CdWZmZXJNYW5hZ2VyLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy9pby9GaWxlRHJvcC5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvaW8vSGFzaFdhdGNoLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy9pby9Mb2NhbFN0b3JhZ2UuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3Rvb2xzL2NvbW1vbi5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdG9vbHMvZGVidWdnaW5nLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy90b29scy9kb3dubG9hZC5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdG9vbHMvaW50ZXJhY3RpdmVEb20uanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3Rvb2xzL21lZGlhQ2FwdHVyZS5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdG9vbHMvbWl4aW4uanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3Rvb2xzL3VybHMuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL0Vycm9yc0Rpc3BsYXkuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL0V4cG9ydEljb24uanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL0hlbHBlcnMuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL01lbnUuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL01lbnVJdGVtLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy91aS9WaXN1YWxEZWJ1Z2dlci5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdWkvbW9kYWxzL0V4cG9ydE1vZGFsLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy91aS9tb2RhbHMvTW9kYWwuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL3BpY2tlcnMvQ29sb3JQaWNrZXIuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL3BpY2tlcnMvRmxvYXRQaWNrZXIuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL3BpY2tlcnMvUGlja2VyLmpzIiwiL2hvbWUvcGF0cmljaW8vRGVza3RvcC9nbHNsRWRpdG9yL3NyYy9qcy91aS9waWNrZXJzL1ZlYzJQaWNrZXIuanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL3BpY2tlcnMvVmVjM1BpY2tlci5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdWkvcGlja2Vycy90eXBlcy9Db2xvci5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdWkvcGlja2Vycy90eXBlcy9Db2xvckNvbnZlcnRlci5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdWkvcGlja2Vycy90eXBlcy9GbG9hdC5qcyIsIi9ob21lL3BhdHJpY2lvL0Rlc2t0b3AvZ2xzbEVkaXRvci9zcmMvanMvdWkvcGlja2Vycy90eXBlcy9NYXRyaXguanMiLCIvaG9tZS9wYXRyaWNpby9EZXNrdG9wL2dsc2xFZGl0b3Ivc3JjL2pzL3VpL3BpY2tlcnMvdHlwZXMvVmVjdG9yLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QU
23459FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmpCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0
23459FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0
23459E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QU
23459FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4cFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QU
23459FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3h1QkE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBOztBQ0RBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBOztBQ0ZBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBOztBQ0ZBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7OztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0
23459FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUN6L0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0
23459E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlnRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O1FDbkJPLDJCQUEyQjs7MEJBQ2YsZUFBZTs7OzswQkFDRyxlQUFlOztzQkFFbkMsV0FBVzs7Ozt5QkFDUixjQUFjOzs7OytCQUNSLG9CQUFvQjs7OztnQ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UFDO0FBQy9DLG9CQUFJLFVBQVUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQy9DLG9CQUFJLFdBQVcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDOztBQUVoRCxxQkFBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxHQUFHLHVCQUF1QixDQUFDO0FBQzVELHFCQUFLLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO0FBQzNDLHFCQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBQzVDLHFCQUFLLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO0FBQzNDLG1CQUFHLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDO0FBQzVDLG9CQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO0FBQzFDLG9CQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO0FBQzFDLHFCQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsWUFBWSxDQUFDO0FBQ2pELHNCQUFNLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsYUFBYSxDQUFDO0FBQ25ELHFCQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsUUFBUSxDQUFDO0FBQzdDLHdCQUFRLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDO0FBQ25ELHNCQUFNLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsZUFBZSxDQUFDO0FBQ3JELDBCQUFVLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsYUFBYSxDQUFDO0FBQ3ZELDBCQUFVLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQ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UFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUMsR0FDNUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUMsR0FDOUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUMsQ0FBQztBQUNuSCxnQkFBSSxNQUFNLEdBQUcsQ0FBQyxHQUFHLFdBQVcsQ0FBQztBQUM3QixhQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQSxHQUFJLE1BQU0sQ0FBQztBQUNyRyxhQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQSxBQUFDLEdBQUcsTUFBTSxDQUFDO0FBQ3RHLGFBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEdBQUksTUFBTSxDQUFDO0FBQ3JHLGFBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUMsR0FBRyxNQUFNLENBQUM7QUFDdEcsYUFBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUEsR0FBSSxNQUFNLENBQUM7QUFDckcsYUFBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUEsQUFBQyxHQUFHLE1BQU0sQ0FBQztBQUN0RyxhQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDL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lsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vZ2V0LWl0ZXJhdG9yXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9hc3NpZ25cIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZGVmaW5lLXByb3BlcnR5XCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3JcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2tleXNcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L3NldC1wcm90b3R5cGUtb2ZcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vcHJvbWlzZVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zZXRcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBmdW5jdGlvbiAoaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7XG4gIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgfVxufTtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9PYmplY3QkZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKFwiYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9kZWZpbmUtcHJvcGVydHlcIilbXCJkZWZhdWx0XCJdO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07XG4gICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7XG4gICAgICBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlO1xuXG4gICAgICBfT2JqZWN0JGRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci
234595rZXksIGRlc2NyaXB0b3IpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7XG4gICAgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTtcbiAgICBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH07XG59KSgpO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlOyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX09iamVjdCRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSByZXF1aXJlKFwiYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3JcIilbXCJkZWZhdWx0XCJdO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHtcbiAgdmFyIF9hZ2FpbiA9IHRydWU7XG5cbiAgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7XG4gICAgdmFyIG9iamVjdCA9IF94LFxuICAgICAgICBwcm9wZXJ0eSA9IF94MixcbiAgICAgICAgcmVjZWl2ZXIgPSBfeDM7XG4gICAgX2FnYWluID0gZmFsc2U7XG4gICAgaWYgKG9iamVjdCA9PT0gbnVsbCkgb2JqZWN0ID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuXG4gICAgdmFyIGRlc2MgPSBfT2JqZWN0JGdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTtcblxuICAgIGlmIChkZXNjID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTtcblxuICAgICAgaWYgKHBhcmVudCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgX3ggPSBwYXJlbnQ7XG4gICAgICAgIF94MiA9IHByb3BlcnR5O1xuICAgICAgICBfeDMgPSByZWNlaXZlcjtcbiAgICAgICAgX2FnYWluID0gdHJ1ZTtcbiAgICAgICAgZGVzYyA9IHBhcmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgY29udGludWUgX2Z1bmN0aW9uO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXCJ2YWx1ZVwiIGluIGRlc2MpIHtcbiAgICAgIHJldHVybiBkZXNjLnZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB2Y
23459XIgZ2V0dGVyID0gZGVzYy5nZXQ7XG5cbiAgICAgIGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9PYmplY3QkY3JlYXRlID0gcmVxdWlyZShcImJhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3QvY3JlYXRlXCIpW1wiZGVmYXVsdFwiXTtcblxudmFyIF9PYmplY3Qkc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKFwiYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9zZXQtcHJvdG90eXBlLW9mXCIpW1wiZGVmYXVsdFwiXTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBmdW5jdGlvbiAoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHtcbiAgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpO1xuICB9XG5cbiAgc3ViQ2xhc3MucHJvdG90eXBlID0gX09iamVjdCRjcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwge1xuICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICB2YWx1ZTogc3ViQ2xhc3MsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfVxuICB9KTtcbiAgaWYgKHN1cGVyQ2xhc3MpIF9PYmplY3Qkc2V0UHJvdG90eXBlT2YgPyBfT2JqZWN0JHNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7XG59O1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlOyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICBcImRlZmF1bHRcIjogb2JqXG4gIH07XG59O1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlOyIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cDovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgdmFyIG5vT3B0aW9ucyA9IHt9O1xuICB2YXIgbm9uV1MgPSAvW15cXHNcXHUwMGEwXS87XG4gIHZhciBQb3MgPSBDb2RlTWlycm9yLlBvcztcblxuICBmdW5jdGlvbiBmaXJzdE5vbldTKHN0cikge1xuICAgIHZhciBmb3VuZCA9IHN0ci5zZWFyY2gobm9uV1MpO1xuICAgIHJldHVybiBmb3VuZCA9PSAtMSA/IDAgOiBmb3VuZDtcbiAgfVxuXG4gIENvZGVNaXJyb3IuY29tbWFuZHMudG9nZ2xlQ29tbWVudCA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgY20udG9nZ2xlQ29tbWVudCgpO1xuICB9O1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwidG9nZ2xlQ29tbWVudFwiLCBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0gbm9PcHRpb25zO1xuICAgIHZhciBjbSA9IHRoaXM7XG4gICAgdmFyIG1pbkxpbmUgPSBJbmZpbml0eSwgcmFuZ2VzID0gdGhpcy5saXN0U2VsZWN0aW9ucygpLCBtb2RlID0gbnVsbDtcbiAgICBmb3IgKHZhciBpID0gcmFuZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2Y
23459XIgZnJvbSA9IHJhbmdlc1tpXS5mcm9tKCksIHRvID0gcmFuZ2VzW2ldLnRvKCk7XG4gICAgICBpZiAoZnJvbS5saW5lID49IG1pbkxpbmUpIGNvbnRpbnVlO1xuICAgICAgaWYgKHRvLmxpbmUgPj0gbWluTGluZSkgdG8gPSBQb3MobWluTGluZSwgMCk7XG4gICAgICBtaW5MaW5lID0gZnJvbS5saW5lO1xuICAgICAgaWYgKG1vZGUgPT0gbnVsbCkge1xuICAgICAgICBpZiAoY20udW5jb21tZW50KGZyb20sIHRvLCBvcHRpb25zKSkgbW9kZSA9IFwidW5cIjtcbiAgICAgICAgZWxzZSB7IGNtLmxpbmVDb21tZW50KGZyb20sIHRvLCBvcHRpb25zKTsgbW9kZSA9IFwibGluZVwiOyB9XG4gICAgICB9IGVsc2UgaWYgKG1vZGUgPT0gXCJ1blwiKSB7XG4gICAgICAgIGNtLnVuY29tbWVudChmcm9tLCB0bywgb3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjbS5saW5lQ29tbWVudChmcm9tLCB0bywgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcImxpbmVDb21tZW50XCIsIGZ1bmN0aW9uKGZyb20sIHRvLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0gbm9PcHRpb25zO1xuICAgIHZhciBzZWxmID0gdGhpcywgbW9kZSA9IHNlbGYuZ2V0TW9kZUF0KGZyb20pO1xuICAgIHZhciBjb21tZW50U3RyaW5nID0gb3B0aW9ucy5saW5lQ29tbWVudCB8fCBtb2RlLmxpbmVDb21tZW50O1xuICAgIGlmICghY29tbWVudFN0cmluZykge1xuICAgICAgaWYgKG9wdGlvbnMuYmxvY2tDb21tZW50U3RhcnQgfHwgbW9kZS5ibG9ja0NvbW1lbnRTdGFydCkge1xuICAgICAgICBvcHRpb25zLmZ1bGxMaW5lcyA9IHRydWU7XG4gICAgICAgIHNlbGYuYmxvY2tDb21tZW50KGZyb20sIHRvLCBvcHRpb25zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGZpcnN0TGluZSA9IHNlbGYuZ2V0TGluZShmcm9tLmxpbmUpO1xuICAgIGlmIChmaXJzdExpbmUgPT0gbnVsbCkgcmV0dXJuO1xuICAgIHZhciBlbmQgPSBNYXRoLm1pbih0by5jaCAhPSAwIHx8IHRvLmxpbmUgPT0gZnJvbS5saW5lID8gdG8ubGluZSArIDEgOiB0by5saW5lLCBzZWxmLmxhc3RMaW5lKCkgKyAxKTtcbiAgICB2YXIgcGFkID0gb3B0aW9ucy5wYWRkaW5nID09IG51bGwgPyBcIiBcIiA6IG9wdGlvbnMucGFkZGluZztcbiAgICB2YXIgYmxhbmtMaW5lcyA9IG9wdGlvbnMuY29tbWVudEJsYW5rTGluZXMgfHwgZnJvbS5saW5lID09IHRvLmxpbmU7XG5cbiAgICBzZWxmLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIGlmIChvcHRpb25zLmluZGVudCkge1xuICAgICAgICB2Y
23459XIgYmFzZVN0cmluZyA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIGkgPSBmcm9tLmxpbmU7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgICAgIHZhciBsaW5lID0gc2VsZi5nZXRMaW5lKGkpO1xuICAgICAgICAgIHZhciB3aGl0ZXNwYWNlID0gbGluZS5zbGljZSgwLCBmaXJzdE5vbldTKGxpbmUpKTtcbiAgICAgICAgICBpZiAoYmFzZVN0cmluZyA9PSBudWxsIHx8IGJhc2VTdHJpbmcubGVuZ3RoID4gd2hpdGVzcGFjZS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGJhc2VTdHJpbmcgPSB3aGl0ZXNwYWNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gZnJvbS5saW5lOyBpIDwgZW5kOyArK2kpIHtcbiAgICAgICAgICB2YXIgbGluZSA9IHNlbGYuZ2V0TGluZShpKSwgY3V0ID0gYmFzZVN0cmluZy5sZW5ndGg7XG4gICAgICAgICAgaWYgKCFibGFua0xpbmVzICYmICFub25XUy50ZXN0KGxpbmUpKSBjb250aW51ZTtcbiAgICAgICAgICBpZiAobGluZS5zbGljZSgwLCBjdXQpICE9IGJhc2VTdHJpbmcpIGN1dCA9IGZpcnN0Tm9uV1MobGluZSk7XG4gICAgICAgICAgc2VsZi5yZXBsYWNlUmFuZ2UoYmFzZVN0cmluZyArIGNvbW1lbnRTdHJpbmcgKyBwYWQsIFBvcyhpLCAwKSwgUG9zKGksIGN1dCkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKHZhciBpID0gZnJvbS5saW5lOyBpIDwgZW5kOyArK2kpIHtcbiAgICAgICAgICBpZiAoYmxhbmtMaW5lcyB8fCBub25XUy50ZXN0KHNlbGYuZ2V0TGluZShpKSkpXG4gICAgICAgICAgICBzZWxmLnJlcGxhY2VSYW5nZShjb21tZW50U3RyaW5nICsgcGFkLCBQb3MoaSwgMCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwiYmxvY2tDb21tZW50XCIsIGZ1bmN0aW9uKGZyb20sIHRvLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0gbm9PcHRpb25zO1xuICAgIHZhciBzZWxmID0gdGhpcywgbW9kZSA9IHNlbGYuZ2V0TW9kZUF0KGZyb20pO1xuICAgIHZhciBzdGFydFN0cmluZyA9IG9wdGlvbnMuYmxvY2tDb21tZW50U3RhcnQgfHwgbW9kZS5ibG9ja0NvbW1lbnRTdGFydDtcbiAgICB2YXIgZW5kU3RyaW5nID0gb3B0aW9ucy5ibG9ja0NvbW1lbnRFbmQgfHwgbW9kZS5ibG9ja0NvbW1lbnRFbmQ7XG4gICAgaWYgKCFzdGFydFN0cmluZyB8fCAhZW5kU3RyaW5nKSB7XG4gICAgICBpZiAoKG9wdGlvbnMubGluZUNvbW1lbnQgfHwgbW9kZS5saW5lQ29tbWVudCkgJiYgb3B0aW9ucy5mdWxsTGluZXMgIT0gZmFsc2UpXG4gICAgICAgIHNlbGYubGluZUNvbW1lbnQoZnJvbSwgdG8sIG9wdGlvbnMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBlbmQgPSBNYXRoLm1pbih0by5saW5lLCBzZWxmLmxhc3RMaW5lKCkpO1xuICAgIGlmIChlbmQgIT0gZnJvbS5saW5lICYmIHRvLmNoID09IDAgJiYgbm9uV1MudGVzdChzZWxmLmdldExpbmUoZW5kKSkpIC0tZW5kO1xuXG4gICAgdmFyIHBhZCA9IG9wdGlvbnMucGFkZGluZyA9PSBudWxsID8gXCIgXCIgOiBvcHRpb25zLnBhZGRpbmc7XG4gICAgaWYgKGZyb20ubGluZSA+IGVuZCkgcmV0dXJuO1xuXG4gICAgc2VsZi5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICBpZiAob3B0aW9ucy5mdWxsTGluZXMgIT0gZmFsc2UpIHtcbiAgICAgICAgdmFyIGxhc3RMaW5lSGFzVGV4dCA9IG5vbldTLnRlc3Qoc2VsZi5nZXRMaW5lKGVuZCkpO1xuICAgICAgICBzZWxmLnJlcGxhY2VSYW5nZShwYWQgKyBlbmRTdHJpbmcsIFBvcyhlbmQpKTtcbiAgICAgICAgc2VsZi5yZXBsYWNlUmFuZ2Uoc3RhcnRTdHJpbmcgKyBwYWQsIFBvcyhmcm9tLmxpbmUsIDApKTtcbiAgICAgICAgdmFyIGxlYWQgPSBvcHRpb25zLmJsb2NrQ29tbWVudExlYWQgfHwgbW9kZS5ibG9ja0NvbW1lbnRMZWFkO1xuICAgICAgICBpZiAobGVhZCAhPSBudWxsKSBmb3IgKHZhciBpID0gZnJvbS5saW5lICsgMTsgaSA8PSBlbmQ7ICsraSlcbiAgICAgICAgICBpZiAoaSAhPSBlbmQgfHwgbGFzdExpbmVIYXNUZXh0KVxuICAgICAgICAgICAgc2VsZi5yZXBsYWNlUmFuZ2UobGVhZCArIHBhZCwgUG9zKGksIDApKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYucmVwbGFjZVJhbmdlKGVuZFN0cmluZywgdG8pO1xuICAgICAgICBzZWxmLnJlcGxhY2VSYW5nZShzdGFydFN0cmluZywgZnJvbSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwidW5jb21tZW50XCIsIGZ1bmN0aW9uKGZyb20sIHRvLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0gbm9PcHRpb25zO1xuICAgIHZhciBzZWxmID0gdGhpcywgbW9kZSA9IHNlbGYuZ2V0TW9kZUF0KGZyb20pO1xuICAgIHZhciBlbmQgPSBNYXRoLm1pbih0by5jaCAhPSAwIHx8IHRvLmxpbmUgPT0gZnJvbS5saW5lID8gdG8ubGluZSA6IHRvLmxpbmUgLSAxLCBzZWxmLmxhc3RMaW5lKCkpLCBzdGFydCA9IE1hdGgubWluKGZyb20ubGluZSwgZW5kKTtcblxuICAgIC8vIFRyeSBmaW5kaW5nIGxpbmUgY29tbWVudHNcbiAgICB2YXIgbGluZVN0cmluZyA9IG9wdGlvbnMubGluZUNvbW1lbnQgfHwgbW9kZS5saW5lQ29tbWVudCwgbGluZXMgPSBbXTtcbiAgICB2YXIgcGFkID0gb3B0aW9ucy5wYWRkaW5nID09IG51bGwgPyBcIiBcIiA6IG9wdGlvbnMucGFkZGluZywgZGlkU29tZXRoaW5nO1xuICAgIGxpbmVDb21tZW50OiB7XG4gICAgICBpZiAoIWxpbmVTdHJpbmcpIGJyZWFrIGxpbmVDb21tZW50O1xuICAgICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgKytpKSB7XG4gICAgICAgIHZhciBsaW5lID0gc2VsZi5nZXRMaW5lKGkpO1xuICAgICAgICB2Y
23459XIgZm91bmQgPSBsaW5lLmluZGV4T2YobGluZVN0cmluZyk7XG4gICAgICAgIGlmIChmb3VuZCA+IC0xICYmICEvY29tbWVudC8udGVzdChzZWxmLmdldFRva2VuVHlwZUF0KFBvcyhpLCBmb3VuZCArIDEpKSkpIGZvdW5kID0gLTE7XG4gICAgICAgIGlmIChmb3VuZCA9PSAtMSAmJiAoaSAhPSBlbmQgfHwgaSA9PSBzdGFydCkgJiYgbm9uV1MudGVzdChsaW5lKSkgYnJlYWsgbGluZUNvbW1lbnQ7XG4gICAgICAgIGlmIChmb3VuZCA+IC0xICYmIG5vbldTLnRlc3QobGluZS5zbGljZSgwLCBmb3VuZCkpKSBicmVhayBsaW5lQ29tbWVudDtcbiAgICAgICAgbGluZXMucHVzaChsaW5lKTtcbiAgICAgIH1cbiAgICAgIHNlbGYub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPD0gZW5kOyArK2kpIHtcbiAgICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2kgLSBzdGFydF07XG4gICAgICAgICAgdmFyIHBvcyA9IGxpbmUuaW5kZXhPZihsaW5lU3RyaW5nKSwgZW5kUG9zID0gcG9zICsgbGluZVN0cmluZy5sZW5ndGg7XG4gICAgICAgICAgaWYgKHBvcyA8IDApIGNvbnRpbnVlO1xuICAgICAgICAgIGlmIChsaW5lLnNsaWNlKGVuZFBvcywgZW5kUG9zICsgcGFkLmxlbmd0aCkgPT0gcGFkKSBlbmRQb3MgKz0gcGFkLmxlbmd0aDtcbiAgICAgICAgICBkaWRTb21ldGhpbmcgPSB0cnVlO1xuICAgICAgICAgIHNlbGYucmVwbGFjZVJhbmdlKFwiXCIsIFBvcyhpLCBwb3MpLCBQb3MoaSwgZW5kUG9zKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaWYgKGRpZFNvbWV0aGluZykgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gVHJ5IGJsb2NrIGNvbW1lbnRzXG4gICAgdmFyIHN0YXJ0U3RyaW5nID0gb3B0aW9ucy5ibG9ja0NvbW1lbnRTdGFydCB8fCBtb2RlLmJsb2NrQ29tbWVudFN0YXJ0O1xuICAgIHZhciBlbmRTdHJpbmcgPSBvcHRpb25zLmJsb2NrQ29tbWVudEVuZCB8fCBtb2RlLmJsb2NrQ29tbWVudEVuZDtcbiAgICBpZiAoIXN0YXJ0U3RyaW5nIHx8ICFlbmRTdHJpbmcpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgbGVhZCA9IG9wdGlvbnMuYmxvY2tDb21tZW50TGVhZCB8fCBtb2RlLmJsb2NrQ29tbWVudExlYWQ7XG4gICAgdmFyIHN0YXJ0TGluZSA9IHNlbGYuZ2V0TGluZShzdGFydCksIGVuZExpbmUgPSBlbmQgPT0gc3RhcnQgPyBzdGFydExpbmUgOiBzZWxmLmdldExpbmUoZW5kKTtcbiAgICB2YXIgb3BlbiA9IHN0YXJ0TGluZS5pbmRleE9mKHN0YXJ0U3RyaW5nKSwgY2xvc2UgPSBlbmRMaW5lLmxhc3RJbmRleE9mKGVuZFN0cmluZyk7XG4gICAgaWYgKGNsb3NlID09IC0xICYmIHN0YXJ0ICE9IGVuZCkge1xuICAgICAgZW5kTGluZSA9IHNlbGYuZ2V0TGluZSgtLWVuZCk7XG4gICAgICBjbG9zZSA9IGVuZExpbmUubGFzdEluZGV4T2YoZW5kU3RyaW5nKTtcbiAgICB9XG4gICAgaWYgKG9wZW4gPT0gLTEgfHwgY2xvc2UgPT0gLTEgfHxcbiAgICAgICAgIS9jb21tZW50Ly50ZXN0KHNlbGYuZ2V0VG9rZW5UeXBlQXQoUG9zKHN0YXJ0LCBvcGVuICsgMSkpKSB8fFxuICAgICAgICAhL2NvbW1lbnQvLnRlc3Qoc2VsZi5nZXRUb2tlblR5cGVBdChQb3MoZW5kLCBjbG9zZSArIDEpKSkpXG4gICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBBdm9pZCBraWxsaW5nIGJsb2NrIGNvbW1lbnRzIGNvbXBsZXRlbHkgb3V0c2lkZSB0aGUgc2VsZWN0aW9uLlxuICAgIC8vIFBvc2l0aW9ucyBvZiB0aGUgbGFzdCBzdGFydFN0cmluZyBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBzZWxlY3Rpb24sIGFuZCB0aGUgZmlyc3QgZW5kU3RyaW5nIGFmdGVyIGl0LlxuICAgIHZhciBsYXN0U3RhcnQgPSBzdGFydExpbmUubGFzdEluZGV4T2Yoc3RhcnRTdHJpbmcsIGZyb20uY2gpO1xuICAgIHZhciBmaXJzdEVuZCA9IGxhc3RTdGFydCA9PSAtMSA/IC0xIDogc3RhcnRMaW5lLnNsaWNlKDAsIGZyb20uY2gpLmluZGV4T2YoZW5kU3RyaW5nLCBsYXN0U3RhcnQgKyBzdGFydFN0cmluZy5sZW5ndGgpO1xuICAgIGlmIChsYXN0U3RhcnQgIT0gLTEgJiYgZmlyc3RFbmQgIT0gLTEgJiYgZmlyc3RFbmQgKyBlbmRTdHJpbmcubGVuZ3RoICE9IGZyb20uY2gpIHJldHVybiBmYWxzZTtcbiAgICAvLyBQb3NpdGlvbnMgb2YgdGhlIGZpcnN0IGVuZFN0cmluZyBhZnRlciB0aGUgZW5kIG9mIHRoZSBzZWxlY3Rpb24sIGFuZCB0aGUgbGFzdCBzdGFydFN0cmluZyBiZWZvcmUgaXQuXG4gICAgZmlyc3RFbmQgPSBlbmRMaW5lLmluZGV4T2YoZW5kU3RyaW5nLCB0by5jaCk7XG4gICAgdmFyIGFsbW9zdExhc3RTdGFydCA9IGVuZExpbmUuc2xpY2UodG8uY2gpLmxhc3RJbmRleE9mKHN0YXJ0U3RyaW5nLCBmaXJzdEVuZCAtIHRvLmNoKTtcbiAgICBsYXN0U3RhcnQgPSAoZmlyc3RFbmQgPT0gLTEgfHwgYWxtb3N0TGFzdFN0YXJ0ID09IC0xKSA/IC0xIDogdG8uY2ggKyBhbG1vc3RMYXN0U3RhcnQ7XG4gICAgaWYgKGZpcnN0RW5kICE9IC0xICYmIGxhc3RTdGFydCAhPSAtMSAmJiBsYXN0U3RhcnQgIT0gdG8uY2gpIHJldHVybiBmYWxzZTtcblxuICAgIHNlbGYub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgc2VsZi5yZXBsYWNlUmFuZ2UoXCJcIiwgUG9zKGVuZCwgY2xvc2UgLSAocGFkICYmIGVuZExpbmUuc2xpY2UoY2xvc2UgLSBwYWQubGVuZ3RoLCBjbG9zZSkgPT0gcGFkID8gcGFkLmxlbmd0aCA6IDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFBvcyhlbmQsIGNsb3NlICsgZW5kU3RyaW5nLmxlbmd0aCkpO1xuICAgICAgdmFyIG9wZW5FbmQgPSBvcGVuICsgc3RhcnRTdHJpbmcubGVuZ3RoO1xuICAgICAgaWYgKHBhZCAmJiBzdGFydExpbmUuc2xpY2Uob3BlbkVuZCwgb3BlbkVuZCArIHBhZC5sZW5ndGgpID09IHBhZCkgb3BlbkVuZCArPSBwYWQubGVuZ3RoO1xuICAgICAgc2VsZi5yZXBsYWNlUmFuZ2UoXCJcIiwgUG9zKHN0YXJ0LCBvcGVuKSwgUG9zKHN0YXJ0LCBvcGVuRW5kKSk7XG4gICAgICBpZiAobGVhZCkgZm9yICh2YXIgaSA9IHN0YXJ0ICsgMTsgaSA8PSBlbmQ7ICsraSkge1xuICAgICAgICB2Y
23459XIgbGluZSA9IHNlbGYuZ2V0TGluZShpKSwgZm91bmQgPSBsaW5lLmluZGV4T2YobGVhZCk7XG4gICAgICAgIGlmIChmb3VuZCA9PSAtMSB8fCBub25XUy50ZXN0KGxpbmUuc2xpY2UoMCwgZm91bmQpKSkgY29udGludWU7XG4gICAgICAgIHZhciBmb3VuZEVuZCA9IGZvdW5kICsgbGVhZC5sZW5ndGg7XG4gICAgICAgIGlmIChwYWQgJiYgbGluZS5zbGljZShmb3VuZEVuZCwgZm91bmRFbmQgKyBwYWQubGVuZ3RoKSA9PSBwYWQpIGZvdW5kRW5kICs9IHBhZC5sZW5ndGg7XG4gICAgICAgIHNlbGYucmVwbGFjZVJhbmdlKFwiXCIsIFBvcyhpLCBmb3VuZCksIFBvcyhpLCBmb3VuZEVuZCkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4vLyBPcGVuIHNpbXBsZSBkaWFsb2dzIG9uIHRvcCBvZiBhbiBlZGl0b3IuIFJlbGllcyBvbiBkaWFsb2cuY3NzLlxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBmdW5jdGlvbiBkaWFsb2dEaXYoY20sIHRlbXBsYXRlLCBib3R0b20pIHtcbiAgICB2YXIgd3JhcCA9IGNtLmdldFdyYXBwZXJFbGVtZW50KCk7XG4gICAgdmFyIGRpYWxvZztcbiAgICBkaWFsb2cgPSB3cmFwLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpO1xuICAgIGlmIChib3R0b20pXG4gICAgICBkaWFsb2cuY2xhc3NOYW1lID0gXCJDb2RlTWlycm9yLWRpYWxvZyBDb2RlTWlycm9yLWRpYWxvZy1ib3R0b21cIjtcbiAgICBlbHNlXG4gICAgICBkaWFsb2cuY2xhc3NOYW1lID0gXCJDb2RlTWlycm9yLWRpYWxvZyBDb2RlTWlycm9yLWRpYWxvZy10b3BcIjtcblxuICAgIGlmICh0eXBlb2YgdGVtcGxhdGUgPT0gXCJzdHJpbmdcIikge1xuICAgICAgZGlhbG9nLmlubmVySFRNTCA9IHRlbXBsYXRlO1xuICAgIH0gZWxzZSB7IC8vIEFzc3VtaW5nIGl0J3MgYSBkZXRhY2hlZCBET00gZWxlbWVudC5cbiAgICAgIGRpYWxvZy5hcHBlbmRDaGlsZCh0ZW1wbGF0ZSk7XG4gICAgfVxuICAgIHJldHVybiBkaWFsb2c7XG4gIH1cblxuICBmdW5jdGlvbiBjbG9zZU5vdGlmaWNhdGlvbihjbSwgbmV3VmFsKSB7XG4gICAgaWYgKGNtLnN0YXRlLmN1cnJlbnROb3RpZmljYXRpb25DbG9zZSlcbiAgICAgIGNtLnN0YXRlLmN1cnJlbnROb3RpZmljYXRpb25DbG9zZSgpO1xuICAgIGNtLnN0YXRlLmN1cnJlbnROb3RpZmljYXRpb25DbG9zZSA9IG5ld1ZhbDtcbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwib3BlbkRpYWxvZ1wiLCBmdW5jdGlvbih0ZW1wbGF0ZSwgY2FsbGJhY2ssIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fTtcblxuICAgIGNsb3NlTm90aWZpY2F0aW9uKHRoaXMsIG51bGwpO1xuXG4gICAgdmFyIGRpYWxvZyA9IGRpYWxvZ0Rpdih0aGlzLCB0ZW1wbGF0ZSwgb3B0aW9ucy5ib3R0b20pO1xuICAgIHZhciBjbG9zZWQgPSBmYWxzZSwgbWUgPSB0aGlzO1xuICAgIGZ1bmN0aW9uIGNsb3NlKG5ld1ZhbCkge1xuICAgICAgaWYgKHR5cGVvZiBuZXdWYWwgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgaW5wLnZhbHVlID0gbmV3VmFsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGNsb3NlZCkgcmV0dXJuO1xuICAgICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgICBkaWFsb2cucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkaWFsb2cpO1xuICAgICAgICBtZS5mb2N1cygpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLm9uQ2xvc2UpIG9wdGlvbnMub25DbG9zZShkaWFsb2cpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBpbnAgPSBkaWFsb2cuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJpbnB1dFwiKVswXSwgYnV0dG9uO1xuICAgIGlmIChpbnApIHtcbiAgICAgIGlmIChvcHRpb25zLnZhbHVlKSB7XG4gICAgICAgIGlucC52YWx1ZSA9IG9wdGlvbnMudmFsdWU7XG4gICAgICAgIGlmIChvcHRpb25zLnNlbGVjdFZhbHVlT25PcGVuICE9PSBmYWxzZSkge1xuICAgICAgICAgIGlucC5zZWxlY3QoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5vbklucHV0KVxuICAgICAgICBDb2RlTWlycm9yLm9uKGlucCwgXCJpbnB1dFwiLCBmdW5jdGlvbihlKSB7IG9wdGlvbnMub25JbnB1dChlLCBpbnAudmFsdWUsIGNsb3NlKTt9KTtcbiAgICAgIGlmIChvcHRpb25zLm9uS2V5VXApXG4gICAgICAgIENvZGVNaXJyb3Iub24oaW5wLCBcImtleXVwXCIsIGZ1bmN0aW9uKGUpIHtvcHRpb25zLm9uS2V5VXAoZSwgaW5wLnZhbHVlLCBjbG9zZSk7fSk7XG5cbiAgICAgIENvZGVNaXJyb3Iub24oaW5wLCBcImtleWRvd25cIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLm9uS2V5RG93biAmJiBvcHRpb25zLm9uS2V5RG93bihlLCBpbnAudmFsdWUsIGNsb3NlKSkgeyByZXR1cm47IH1cbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAyNyB8fCAob3B0aW9ucy5jbG9zZU9uRW50ZXIgIT09IGZhbHNlICYmIGUua2V5Q29kZSA9PSAxMykpIHtcbiAgICAgICAgICBpbnAuYmx1cigpO1xuICAgICAgICAgIENvZGVNaXJyb3IuZV9zdG9wKGUpO1xuICAgICAgICAgIGNsb3NlKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAxMykgY2FsbGJhY2soaW5wLnZhbHVlLCBlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAob3B0aW9ucy5jbG9zZU9uQmx1ciAhPT0gZmFsc2UpIENvZGVNaXJyb3Iub24oaW5wLCBcImJsdXJcIiwgY2xvc2UpO1xuXG4gICAgICBpbnAuZm9jdXMoKTtcbiAgICB9IGVsc2UgaWYgKGJ1dHRvbiA9IGRpYWxvZy5nZXRFbGVtZW50c0J5VGFnTmFtZShcImJ1dHRvblwiKVswXSkge1xuICAgICAgQ29kZU1pcnJvci5vbihidXR0b24sIFwiY2xpY2tcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NlKCk7XG4gICAgICAgIG1lLmZvY3VzKCk7XG4gICAgICB9KTtcblxuICAgICAgaWYgKG9wdGlvbnMuY2xvc2VPbkJsdXIgIT09IGZhbHNlKSBDb2RlTWlycm9yLm9uKGJ1dHRvbiwgXCJibHVyXCIsIGNsb3NlKTtcblxuICAgICAgYnV0dG9uLmZvY3VzKCk7XG4gICAgfVxuICAgIHJldHVybi
23459BjbG9zZTtcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJvcGVuQ29uZmlybVwiLCBmdW5jdGlvbih0ZW1wbGF0ZSwgY2FsbGJhY2tzLCBvcHRpb25zKSB7XG4gICAgY2xvc2VOb3RpZmljYXRpb24odGhpcywgbnVsbCk7XG4gICAgdmFyIGRpYWxvZyA9IGRpYWxvZ0Rpdih0aGlzLCB0ZW1wbGF0ZSwgb3B0aW9ucyAmJiBvcHRpb25zLmJvdHRvbSk7XG4gICAgdmFyIGJ1dHRvbnMgPSBkaWFsb2cuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJidXR0b25cIik7XG4gICAgdmFyIGNsb3NlZCA9IGZhbHNlLCBtZSA9IHRoaXMsIGJsdXJyaW5nID0gMTtcbiAgICBmdW5jdGlvbiBjbG9zZSgpIHtcbiAgICAgIGlmIChjbG9zZWQpIHJldHVybjtcbiAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICBkaWFsb2cucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkaWFsb2cpO1xuICAgICAgbWUuZm9jdXMoKTtcbiAgICB9XG4gICAgYnV0dG9uc1swXS5mb2N1cygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnV0dG9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGIgPSBidXR0b25zW2ldO1xuICAgICAgKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgIENvZGVNaXJyb3Iub24oYiwgXCJjbGlja1wiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgQ29kZU1pcnJvci5lX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgICAgIGNsb3NlKCk7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhtZSk7XG4gICAgICAgIH0pO1xuICAgICAgfSkoY2FsbGJhY2tzW2ldKTtcbiAgICAgIENvZGVNaXJyb3Iub24oYiwgXCJibHVyXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAtLWJsdXJyaW5nO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBpZiAoYmx1cnJpbmcgPD0gMCkgY2xvc2UoKTsgfSwgMjAwKTtcbiAgICAgIH0pO1xuICAgICAgQ29kZU1pcnJvci5vbihiLCBcImZvY3VzXCIsIGZ1bmN0aW9uKCkgeyArK2JsdXJyaW5nOyB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qXG4gICAqIG9wZW5Ob3RpZmljYXRpb25cbiAgICogT3BlbnMgYSBub3RpZmljYXRpb24sIHRoYXQgY2FuIGJlIGNsb3NlZCB3aXRoIGFuIG9wdGlvbmFsIHRpbWVyXG4gICAqIChkZWZhdWx0IDUwMDBtcyB0aW1lcikgYW5kIGFsd2F5cyBjbG9zZXMgb24gY2xpY2suXG4gICAqXG4gICAqIElmIGEgbm90aWZpY2F0aW9uIGlzIG9wZW5lZCB3aGlsZSBhbm90aGVyIGlzIG9wZW5lZCwgaXQgd2lsbCBjbG9zZSB0aGVcbiAgICogY3VycmVudGx5IG9wZW5lZCBvbmUgYW5kIG9wZW4gdGhlIG5ldyBvbmUgaW1tZWRpYXRlbHkuXG4gICAqL1xuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcIm9wZW5Ob3RpZmljYXRpb25cIiwgZnVuY3Rpb24odGVtcGxhdGUsIG9wdGlvbnMpIHtcbiAgICBjbG9zZU5vdGlmaWNhdGlvbih0aGlzLCBjbG9zZSk7XG4gICAgdmFyIGRpYWxvZyA9IGRpYWxvZ0Rpdih0aGlzLCB0ZW1wbGF0ZSwgb3B0aW9ucyAmJiBvcHRpb25zLmJvdHRvbSk7XG4gICAgdmFyIGNsb3NlZCA9IGZhbHNlLCBkb25lVGltZXI7XG4gICAgdmFyIGR1cmF0aW9uID0gb3B0aW9ucyAmJiB0eXBlb2Ygb3B0aW9ucy5kdXJhdGlvbiAhPT0gXCJ1bmRlZmluZWRcIiA/IG9wdGlvbnMuZHVyYXRpb24gOiA1MDAwO1xuXG4gICAgZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgICBpZiAoY2xvc2VkKSByZXR1cm47XG4gICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgY2xlYXJUaW1lb3V0KGRvbmVUaW1lcik7XG4gICAgICBkaWFsb2cucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkaWFsb2cpO1xuICAgIH1cblxuICAgIENvZGVNaXJyb3Iub24oZGlhbG9nLCAnY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICBDb2RlTWlycm9yLmVfcHJldmVudERlZmF1bHQoZSk7XG4gICAgICBjbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgaWYgKGR1cmF0aW9uKVxuICAgICAgZG9uZVRpbWVyID0gc2V0VGltZW91dChjbG9zZSwgZHVyYXRpb24pO1xuXG4gICAgcmV0dXJuIGNsb3NlO1xuICB9KTtcbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcImFkZFBhbmVsXCIsIGZ1bmN0aW9uKG5vZGUsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIGlmICghdGhpcy5zdGF0ZS5wYW5lbHMpIGluaXRQYW5lbHModGhpcyk7XG5cbiAgICB2YXIgaW5mbyA9IHRoaXMuc3RhdGUucGFuZWxzO1xuICAgIHZhciB3cmFwcGVyID0gaW5mby53cmFwcGVyO1xuICAgIHZhciBjbVdyYXBwZXIgPSB0aGlzLmdldFdyYXBwZXJFbGVtZW50KCk7XG5cbiAgICBpZiAob3B0aW9ucy5hZnRlciBpbnN0YW5jZW9mIFBhbmVsICYmICFvcHRpb25zLmFmdGVyLmNsZWFyZWQpIHtcbiAgICAgIHdyYXBwZXIuaW5zZXJ0QmVmb3JlKG5vZGUsIG9wdGlvbnMuYmVmb3JlLm5vZGUubmV4dFNpYmxpbmcpO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5iZWZvcmUgaW5zdGFuY2VvZiBQYW5lbCAmJiAhb3B0aW9ucy5iZWZvcmUuY2xlYXJlZCkge1xuICAgICAgd3JhcHBlci5pbnNlcnRCZWZvcmUobm9kZSwgb3B0aW9ucy5iZWZvcmUubm9kZSk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnJlcGxhY2UgaW5zdGFuY2VvZiBQYW5lbCAmJiAhb3B0aW9ucy5yZXBsYWNlLmNsZWFyZWQpIHtcbiAgICAgIHdyYXBwZXIuaW5zZXJ0QmVmb3JlKG5vZGUsIG9wdGlvbnMucmVwbGFjZS5ub2RlKTtcbiAgICAgIG9wdGlvbnMucmVwbGFjZS5jbGVhcigpO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5wb3NpdGlvbiA9PSBcImJvdHRvbVwiKSB7XG4gICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5wb3NpdGlvbiA9PSBcImJlZm9yZS1ib3R0b21cIikge1xuICAgICAgd3JhcHBlci5pbnNlcnRCZWZvcmUobm9kZSwgY21XcmFwcGVyLm5leHRTaWJsaW5nKTtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMucG9zaXRpb24gPT0gXCJhZnRlci10b3BcIikge1xuICAgICAgd3JhcHBlci5pbnNlcnRCZWZvcmUobm9kZSwgY21XcmFwcGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd3JhcHBlci5pbnNlcnRCZWZvcmUobm9kZSwgd3JhcHBlci5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB2YXIgaGVpZ2h0ID0gKG9wdGlvbnMgJiYgb3B0aW9ucy5oZWlnaHQpIHx8IG5vZGUub2Zmc2V0SGVpZ2h0O1xuICAgIHRoaXMuX3NldFNpemUobnVsbCwgaW5mby5oZWlnaHRMZWZ0IC09IGhlaWdodCk7XG4gICAgaW5mby5wYW5lbHMrKztcbiAgICByZXR1cm4gbmV3IFBhbmVsKHRoaXMsIG5vZGUsIG9wdGlvbnMsIGhlaWdodCk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIFBhbmVsKGNtLCBub2RlLCBvcHRpb25zLCBoZWlnaHQpIHtcbiAgICB0aGlzLmNtID0gY207XG4gICAgdGhpcy5ub2RlID0gbm9kZTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuY2xlYXJlZCA9IGZhbHNlO1xuICB9XG5cbiAgUGFuZWwucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuY2xlYXJlZCkgcmV0dXJuO1xuICAgIHRoaXMuY2xlYXJlZCA9IHRydWU7XG4gICAgdmFyIGluZm8gPSB0aGlzLmNtLnN0YXRlLnBhbmVscztcbiAgICB0aGlzLmNtLl9zZXRTaXplKG51bGwsIGluZm8uaGVpZ2h0TGVmdCArPSB0aGlzLmhlaWdodCk7XG4gICAgaW5mby53cmFwcGVyLnJlbW92ZUNoaWxkKHRoaXMubm9kZSk7XG4gICAgaWYgKC0taW5mby5wYW5lbHMgPT0gMCkgcmVtb3ZlUGFuZWxzKHRoaXMuY20pO1xuICB9O1xuXG4gIFBhbmVsLnByb3RvdHlwZS5jaGFuZ2VkI
23459D0gZnVuY3Rpb24oaGVpZ2h0KSB7XG4gICAgdmFyIG5ld0hlaWdodCA9IGhlaWdodCA9PSBudWxsID8gdGhpcy5ub2RlLm9mZnNldEhlaWdodCA6IGhlaWdodDtcbiAgICB2YXIgaW5mbyA9IHRoaXMuY20uc3RhdGUucGFuZWxzO1xuICAgIHRoaXMuY20uX3NldFNpemUobnVsbCwgaW5mby5oZWlnaHQgKz0gKG5ld0hlaWdodCAtIHRoaXMuaGVpZ2h0KSk7XG4gICAgdGhpcy5oZWlnaHQgPSBuZXdIZWlnaHQ7XG4gIH07XG5cbiAgZnVuY3Rpb24gaW5pdFBhbmVscyhjbSkge1xuICAgIHZhciB3cmFwID0gY20uZ2V0V3JhcHBlckVsZW1lbnQoKTtcbiAgICB2YXIgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSA/IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHdyYXApIDogd3JhcC5jdXJyZW50U3R5bGU7XG4gICAgdmFyIGhlaWdodCA9IHBhcnNlSW50KHN0eWxlLmhlaWdodCk7XG4gICAgdmFyIGluZm8gPSBjbS5zdGF0ZS5wYW5lbHMgPSB7XG4gICAgICBzZXRIZWlnaHQ6IHdyYXAuc3R5bGUuaGVpZ2h0LFxuICAgICAgaGVpZ2h0TGVmdDogaGVpZ2h0LFxuICAgICAgcGFuZWxzOiAwLFxuICAgICAgd3JhcHBlcjogZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKVxuICAgIH07XG4gICAgd3JhcC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShpbmZvLndyYXBwZXIsIHdyYXApO1xuICAgIHZhciBoYXNGb2N1cyA9IGNtLmhhc0ZvY3VzKCk7XG4gICAgaW5mby53cmFwcGVyLmFwcGVuZENoaWxkKHdyYXApO1xuICAgIGlmIChoYXNGb2N1cykgY20uZm9jdXMoKTtcblxuICAgIGNtLl9zZXRTaXplID0gY20uc2V0U2l6ZTtcbiAgICBpZiAoaGVpZ2h0ICE9IG51bGwpIGNtLnNldFNpemUgPSBmdW5jdGlvbih3aWR0aCwgbmV3SGVpZ2h0KSB7XG4gICAgICBpZiAobmV3SGVpZ2h0ID09IG51bGwpIHJldHVybiB0aGlzLl9zZXRTaXplKHdpZHRoLCBuZXdIZWlnaHQpO1xuICAgICAgaW5mby5zZXRIZWlnaHQgPSBuZXdIZWlnaHQ7XG4gICAgICBpZiAodHlwZW9mIG5ld0hlaWdodCAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgIHZhciBweCA9IC9eKFxcZCtcXC4/XFxkKilweCQvLmV4ZWMobmV3SGVpZ2h0KTtcbiAgICAgICAgaWYgKHB4KSB7XG4gICAgICAgICAgbmV3SGVpZ2h0ID0gTnVtYmVyKHB4WzFdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbmZvLndyYXBwZXIuc3R5bGUuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgICAgICAgIG5ld0hlaWdodCA9IGluZm8ud3JhcHBlci5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgaW5mby53cmFwcGVyLnN0eWxlLmhlaWdodCA9IFwiXCI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNtLl9zZXRTaXplKHdpZHRoLCBpbmZvLmhlaWdodExlZnQgKz0gKG5ld0hlaWdodCAtIGhlaWdodCkpO1xuICAgICAgaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQYW5lbHMoY20pIHtcbiAgICB2YXIgaW5mbyA9IGNtLnN0YXRlLnBhbmVscztcbiAgICBjbS5zdGF0ZS5wYW5lbHMgPSBudWxsO1xuXG4gICAgdmFyIHdyYXAgPSBjbS5nZXRXcmFwcGVyRWxlbWVudCgpO1xuICAgIGluZm8ud3JhcHBlci5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZCh3cmFwLCBpbmZvLndyYXBwZXIpO1xuICAgIHdyYXAuc3R5bGUuaGVpZ2h0ID0gaW5mby5zZXRIZWlnaHQ7XG4gICAgY20uc2V0U2l6ZSA9IGNtLl9zZXRTaXplO1xuICAgIGNtLnNldFNpemUoKTtcbiAgfVxufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lT3B0aW9uKFwicnVsZXJzXCIsIGZhbHNlLCBmdW5jdGlvbihjbSwgdmFsLCBvbGQpIHtcbiAgICBpZiAob2xkICYmIG9sZCAhPSBDb2RlTWlycm9yLkluaXQpIHtcbiAgICAgIGNsZWFyUnVsZXJzKGNtKTtcbiAgICAgIGNtLm9mZihcInJlZnJlc2hcIiwgcmVmcmVzaFJ1bGVycyk7XG4gICAgfVxuICAgIGlmICh2YWwgJiYgdmFsLmxlbmd0aCkge1xuICAgICAgc2V0UnVsZXJzKGNtKTtcbiAgICAgIGNtLm9uKFwicmVmcmVzaFwiLCByZWZyZXNoUnVsZXJzKTtcbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNsZWFyUnVsZXJzKGNtKSB7XG4gICAgZm9yICh2YXIgaSA9IGNtLmRpc3BsYXkubGluZVNwYWNlLmNoaWxkTm9kZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciBub2RlID0gY20uZGlzcGxheS5saW5lU3BhY2UuY2hpbGROb2Rlc1tpXTtcbiAgICAgIGlmICgvKF58XFxzKUNvZGVNaXJyb3ItcnVsZXIoJHxcXHMpLy50ZXN0KG5vZGUuY2xhc3NOYW1lKSlcbiAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldFJ1bGVycyhjbSkge1xuICAgIHZhciB2YWwgPSBjbS5nZXRPcHRpb24oXCJydWxlcnNcIik7XG4gICAgdmFyIGN3ID0gY20uZGVmYXVsdENoYXJXaWR0aCgpO1xuICAgIHZhciBsZWZ0ID0gY20uY2hhckNvb3JkcyhDb2RlTWlycm9yLlBvcyhjbS5maXJzdExpbmUoKSwgMCksIFwiZGl2XCIpLmxlZnQ7XG4gICAgdmFyIG1pbkggPSBjbS5kaXNwbGF5LnNjcm9sbGVyLm9mZnNldEhlaWdodCArIDMwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgZWx0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgIGVsdC5jbGFzc05hbWUgPSBcIkNvZGVNaXJyb3ItcnVsZXJcIjtcbiAgICAgIHZhciBjb2wsIGNvbmYgPSB2YWxbaV07XG4gICAgICBpZiAodHlwZW9mIGNvbmYgPT0gXCJudW1iZXJcIikge1xuICAgICAgICBjb2wgPSBjb25mO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29sID0gY29uZi5jb2x1bW47XG4gICAgICAgIGlmIChjb25mLmNsYXNzTmFtZSkgZWx0LmNsYXNzTmFtZSArPSBcIiBcIiArIGNvbmYuY2xhc3NOYW1lO1xuICAgICAgICBpZiAoY29uZi5jb2xvcikgZWx0LnN0eWxlLmJvcmRlckNvbG9yID0gY29uZi5jb2xvcjtcbiAgICAgICAgaWYgKGNvbmYubGluZVN0eWxlKSBlbHQuc3R5bGUuYm9yZGVyTGVmdFN0eWxlID0gY29uZi5saW5lU3R5bGU7XG4gICAgICAgIGlmIChjb25mLndpZHRoKSBlbHQuc3R5bGUuYm9yZGVyTGVmdFdpZHRoID0gY29uZi53aWR0aDtcbiAgICAgIH1cbiAgICAgIGVsdC5zdHlsZS5sZWZ0ID0gKGxlZnQgKyBjb2wgKiBjdykgKyBcInB4XCI7XG4gICAgICBlbHQuc3R5bGUudG9wID0gXCItNTBweFwiO1xuICAgICAgZWx0LnN0eWxlLmJvdHRvbSA9IFwiLTIwcHhcIjtcbiAgICAgIGVsdC5zdHlsZS5taW5IZWlnaHQgPSBtaW5IICsgXCJweFwiO1xuICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UuaW5zZXJ0QmVmb3JlKGVsdCwgY20uZGlzcGxheS5jdXJzb3JEaXYpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlZnJlc2hSdWxlcnMoY20pIHtcbiAgICBjbGVhclJ1bGVycyhjbSk7XG4gICAgc2V0UnVsZXJzKGNtKTtcbiAgfVxufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIHZhciBkZWZhdWx0cyA9IHtcbiAgICBwYWlyczogXCIoKVtde30nJ1xcXCJcXFwiXCIsXG4gICAgdHJpcGxlczogXCJcIixcbiAgICBleHBsb2RlOiBcIltde31cIlxuICB9O1xuXG4gIHZhciBQb3MgPSBDb2RlTWlycm9yLlBvcztcblxuICBDb2RlTWlycm9yLmRlZmluZU9wdGlvbihcImF1dG9DbG9zZUJyYWNrZXRzXCIsIGZhbHNlLCBmdW5jdGlvbihjbSwgdmFsLCBvbGQpIHtcbiAgICBpZiAob2xkICYmIG9sZCAhPSBDb2RlTWlycm9yLkluaXQpIHtcbiAgICAgIGNtLnJlbW92ZUtleU1hcChrZXlNYXApO1xuICAgICAgY20uc3RhdGUuY2xvc2VCcmFja2V0cyA9IG51bGw7XG4gICAgfVxuICAgIGlmICh2YWwpIHtcbiAgICAgIGNtLnN0YXRlLmNsb3NlQnJhY2tldHMgPSB2YWw7XG4gICAgICBjbS5hZGRLZXlNYXAoa2V5TWFwKTtcbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGdldE9wdGlvbihjb25mLCBuYW1lKSB7XG4gICAgaWYgKG5hbWUgPT0gXCJwYWlyc1wiICYmIHR5cGVvZiBjb25mID09IFwic3RyaW5nXCIpIHJldHVybiBjb25mO1xuICAgIGlmICh0eXBlb2YgY29uZiA9PSBcIm9iamVjdFwiICYmIGNvbmZbbmFtZV0gIT0gbnVsbCkgcmV0dXJuIGNvbmZbbmFtZV07XG4gICAgcmV0dXJuIGRlZmF1bHRzW25hbWVdO1xuICB9XG5cbiAgdmFyIGJpbmQgPSBkZWZhdWx0cy5wYWlycyArIFwiYFwiO1xuICB2YXIga2V5TWFwID0ge0JhY2tzcGFjZTogaGFuZGxlQmFja3NwYWNlLCBFbnRlcjogaGFuZGxlRW50ZXJ9O1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbmQubGVuZ3RoOyBpKyspXG4gICAga2V5TWFwW1wiJ1wiICsgYmluZC5jaGFyQXQoaSkgKyBcIidcIl0gPSBoYW5kbGVyKGJpbmQuY2hhckF0KGkpKTtcblxuICBmdW5jdGlvbiBoYW5kbGVyKGNoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGNtKSB7IHJldHVybiBoYW5kbGVDaGFyKGNtLCBjaCk7IH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRDb25maWcoY20pIHtcbiAgICB2YXIgZGVmbHQgPSBjbS5zdGF0ZS5jbG9zZUJyYWNrZXRzO1xuICAgIGlmICghZGVmbHQpIHJldHVybiBudWxsO1xuICAgIHZhciBtb2RlID0gY20uZ2V0TW9kZUF0KGNtLmdldEN1cnNvcigpKTtcbiAgICByZXR1cm4gbW9kZS5jbG9zZUJyYWNrZXRzIHx8IGRlZmx0O1xuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlQmFja3NwYWNlKGNtKSB7XG4gICAgdmFyIGNvbmYgPSBnZXRDb25maWcoY20pO1xuICAgIGlmICghY29uZiB8fCBjbS5nZXRPcHRpb24oXCJkaXNhYmxlSW5wdXRcIikpIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG5cbiAgICB2YXIgcGFpcnMgPSBnZXRPcHRpb24oY29uZiwgXCJwYWlyc1wiKTtcbiAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKCFyYW5nZXNbaV0uZW1wdHkoKSkgcmV0dXJuIENvZGVNaXJyb3IuUGFzcztcbiAgICAgIHZhciBhcm91bmQgPSBjaGFyc0Fyb3VuZChjbSwgcmFuZ2VzW2ldLmhlYWQpO1xuICAgICAgaWYgKCFhcm91bmQgfHwgcGFpcnMuaW5kZXhPZihhcm91bmQpICUgMiAhPSAwKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gcmFuZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2Y
23459XIgY3VyID0gcmFuZ2VzW2ldLmhlYWQ7XG4gICAgICBjbS5yZXBsYWNlUmFuZ2UoXCJcIiwgUG9zKGN1ci5saW5lLCBjdXIuY2ggLSAxKSwgUG9zKGN1ci5saW5lLCBjdXIuY2ggKyAxKSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlRW50ZXIoY20pIHtcbiAgICB2YXIgY29uZiA9IGdldENvbmZpZyhjbSk7XG4gICAgdmFyIGV4cGxvZGUgPSBjb25mICYmIGdldE9wdGlvbihjb25mLCBcImV4cGxvZGVcIik7XG4gICAgaWYgKCFleHBsb2RlIHx8IGNtLmdldE9wdGlvbihcImRpc2FibGVJbnB1dFwiKSkgcmV0dXJuIENvZGVNaXJyb3IuUGFzcztcblxuICAgIHZhciByYW5nZXMgPSBjbS5saXN0U2VsZWN0aW9ucygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIXJhbmdlc1tpXS5lbXB0eSgpKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgICAgdmFyIGFyb3VuZCA9IGNoYXJzQXJvdW5kKGNtLCByYW5nZXNbaV0uaGVhZCk7XG4gICAgICBpZiAoIWFyb3VuZCB8fCBleHBsb2RlLmluZGV4T2YoYXJvdW5kKSAlIDIgIT0gMCkgcmV0dXJuIENvZGVNaXJyb3IuUGFzcztcbiAgICB9XG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbihcIlxcblxcblwiLCBudWxsKTtcbiAgICAgIGNtLmV4ZWNDb21tYW5kKFwiZ29DaGFyTGVmdFwiKTtcbiAgICAgIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2Y
23459XIgbGluZSA9IHJhbmdlc1tpXS5oZWFkLmxpbmU7XG4gICAgICAgIGNtLmluZGVudExpbmUobGluZSwgbnVsbCwgdHJ1ZSk7XG4gICAgICAgIGNtLmluZGVudExpbmUobGluZSArIDEsIG51bGwsIHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gY29udHJhY3RTZWxlY3Rpb24oc2VsKSB7XG4gICAgdmFyIGludmVydGVkID0gQ29kZU1pcnJvci5jbXBQb3Moc2VsLmFuY2hvciwgc2VsLmhlYWQpID4gMDtcbiAgICByZXR1cm4ge2FuY2hvcjogbmV3IFBvcyhzZWwuYW5jaG9yLmxpbmUsIHNlbC5hbmNob3IuY2ggKyAoaW52ZXJ0ZWQgPyAtMSA6IDEpKSxcbiAgICAgICAgICAgIGhlYWQ6IG5ldyBQb3Moc2VsLmhlYWQubGluZSwgc2VsLmhlYWQuY2ggKyAoaW52ZXJ0ZWQgPyAxIDogLTEpKX07XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVDaGFyKGNtLCBjaCkge1xuICAgIHZhciBjb25mID0gZ2V0Q29uZmlnKGNtKTtcbiAgICBpZiAoIWNvbmYgfHwgY20uZ2V0T3B0aW9uKFwiZGlzYWJsZUlucHV0XCIpKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuXG4gICAgdmFyIHBhaXJzID0gZ2V0T3B0aW9uKGNvbmYsIFwicGFpcnNcIik7XG4gICAgdmFyIHBvcyA9IHBhaXJzLmluZGV4T2YoY2gpO1xuICAgIGlmIChwb3MgPT0gLTEpIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG4gICAgdmFyIHRyaXBsZXMgPSBnZXRPcHRpb24oY29uZiwgXCJ0cmlwbGVzXCIpO1xuXG4gICAgdmFyIGlkZW50aWNhbCA9IHBhaXJzLmNoYXJBdChwb3MgKyAxKSA9PSBjaDtcbiAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICB2YXIgb3BlbmluZyA9IHBvcyAlIDIgPT0gMDtcblxuICAgIHZhciB0eXBlLCBuZXh0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgcmFuZ2UgPSByYW5nZXNbaV0sIGN1ciA9IHJhbmdlLmhlYWQsIGN1clR5cGU7XG4gICAgICB2YXIgbmV4dCA9IGNtLmdldFJhbmdlKGN1ciwgUG9zKGN1ci5saW5lLCBjdXIuY2ggKyAxKSk7XG4gICAgICBpZiAob3BlbmluZyAmJiAhcmFuZ2UuZW1wdHkoKSkge1xuICAgICAgICBjdXJUeXBlID0gXCJzdXJyb3VuZFwiO1xuICAgICAgfSBlbHNlIGlmICgoaWRlbnRpY2FsIHx8ICFvcGVuaW5nKSAmJiBuZXh0ID09IGNoKSB7XG4gICAgICAgIGlmICh0cmlwbGVzLmluZGV4T2YoY2gpID49IDAgJiYgY20uZ2V0UmFuZ2UoY3VyLCBQb3MoY3VyLmxpbmUsIGN1ci5jaCArIDMpKSA9PSBjaCArIGNoICsgY2gpXG4gICAgICAgICAgY3VyVHlwZSA9IFwic2tpcFRocmVlXCI7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBjdXJUeXBlID0gXCJza2lwXCI7XG4gICAgICB9IGVsc2UgaWYgKGlkZW50aWNhbCAmJiBjdXIuY2ggPiAxICYmIHRyaXBsZXMuaW5kZXhPZihjaCkgPj0gMCAmJlxuICAgICAgICAgICAgICAgICBjbS5nZXRSYW5nZShQb3MoY3VyLmxpbmUsIGN1ci5jaCAtIDIpLCBjdXIpID09IGNoICsgY2ggJiZcbiAgICAgICAgICAgICAgICAgKGN1ci5jaCA8PSAyIHx8IGNtLmdldFJhbmdlKFBvcyhjdXIubGluZSwgY3VyLmNoIC0gMyksIFBvcyhjdXIubGluZSwgY3VyLmNoIC0gMikpICE9IGNoKSkge1xuICAgICAgICBjdXJUeXBlID0gXCJhZGRGb3VyXCI7XG4gICAgICB9IGVsc2UgaWYgKGlkZW50aWNhbCkge1xuICAgICAgICBpZiAoIUNvZGVNaXJyb3IuaXNXb3JkQ2hhcihuZXh0KSAmJiBlbnRlcmluZ1N0cmluZyhjbSwgY3VyLCBjaCkpIGN1clR5cGUgPSBcImJvdGhcIjtcbiAgICAgICAgZWxzZSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgICAgfSBlbHNlIGlmIChvcGVuaW5nICYmIChjbS5nZXRMaW5lKGN1ci5saW5lKS5sZW5ndGggPT0gY3VyLmNoIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQ2xvc2luZ0JyYWNrZXQobmV4dCwgcGFpcnMpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9cXHMvLnRlc3QobmV4dCkpKSB7XG4gICAgICAgIGN1clR5cGUgPSBcImJvdGhcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG4gICAgICB9XG4gICAgICBpZiAoIXR5cGUpIHR5cGUgPSBjdXJUeXBlO1xuICAgICAgZWxzZSBpZiAodHlwZSAhPSBjdXJUeXBlKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgIH1cblxuICAgIHZhciBsZWZ0ID0gcG9zICUgMiA/IHBhaXJzLmNoYXJBdChwb3MgLSAxKSA6IGNoO1xuICAgIHZhciByaWdodCA9IHBvcyAlIDIgPyBjaCA6IHBhaXJzLmNoYXJBdChwb3MgKyAxKTtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodHlwZSA9PSBcInNraXBcIikge1xuICAgICAgICBjbS5leGVjQ29tbWFuZChcImdvQ2hhclJpZ2h0XCIpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09IFwic2tpcFRocmVlXCIpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyBpKyspXG4gICAgICAgICAgY20uZXhlY0NvbW1hbmQoXCJnb0NoYXJSaWdodFwiKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PSBcInN1cnJvdW5kXCIpIHtcbiAgICAgICAgdmFyIHNlbHMgPSBjbS5nZXRTZWxlY3Rpb25zKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vscy5sZW5ndGg7IGkrKylcbiAgICAgICAgICBzZWxzW2ldID0gbGVmdCArIHNlbHNbaV0gKyByaWdodDtcbiAgICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbnMoc2VscywgXCJhcm91bmRcIik7XG4gICAgICAgIHNlbHMgPSBjbS5saXN0U2VsZWN0aW9ucygpLnNsaWNlKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vscy5sZW5ndGg7IGkrKylcbiAgICAgICAgICBzZWxzW2ldID0gY29udHJhY3RTZWxlY3Rpb24oc2Vsc1tpXSk7XG4gICAgICAgIGNtLnNldFNlbGVjdGlvbnMoc2Vscyk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJib3RoXCIpIHtcbiAgICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbihsZWZ0ICsgcmlnaHQsIG51bGwpO1xuICAgICAgICBjbS50cmlnZ2VyRWxlY3RyaWMobGVmdCArIHJpZ2h0KTtcbiAgICAgICAgY20uZXhlY0NvbW1hbmQoXCJnb0NoYXJMZWZ0XCIpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09IFwiYWRkRm91clwiKSB7XG4gICAgICAgIGNtLnJlcGxhY2VTZWxlY3Rpb24obGVmdCArIGxlZnQgKyBsZWZ0ICsgbGVmdCwgXCJiZWZvcmVcIik7XG4gICAgICAgIGNtLmV4ZWNDb21tYW5kKFwiZ29DaGFyUmlnaHRcIik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBpc0Nsb3NpbmdCcmFja2V0KGNoLCBwYWlycykge1xuICAgIHZhciBwb3MgPSBwYWlycy5sYXN0SW5kZXhPZihjaCk7XG4gICAgcmV0dXJuIHBvcyA+IC0xICYmIHBvcyAlIDIgPT0gMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoYXJzQXJvdW5kKGNtLCBwb3MpIHtcbiAgICB2YXIgc3RyID0gY20uZ2V0UmFuZ2UoUG9zKHBvcy5saW5lLCBwb3MuY2ggLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgUG9zKHBvcy5saW5lLCBwb3MuY2ggKyAxKSk7XG4gICAgcmV0dXJuIHN0ci5sZW5ndGggPT0gMiA/IHN0ciA6IG51bGw7XG4gIH1cblxuICAvLyBQcm9qZWN0IHRoZSB0b2tlbiB0eXBlIHRoYXQgd2lsbCBleGlzdHMgYWZ0ZXIgdGhlIGdpdmVuIGNoYXIgaXNcbiAgLy8gdHlwZWQsIGFuZCB1c2UgaXQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgaXQgd291bGQgY2F1c2UgdGhlIHN0YXJ0XG4gIC8vIG9mIGEgc3RyaW5nIHRva2VuLlxuICBmdW5jdGlvbiBlbnRlcmluZ1N0cmluZyhjbSwgcG9zLCBjaCkge1xuICAgIHZhciBsaW5lID0gY20uZ2V0TGluZShwb3MubGluZSk7XG4gICAgdmFyIHRva2VuID0gY20uZ2V0VG9rZW5BdChwb3MpO1xuICAgIGlmICgvXFxic3RyaW5nMj9cXGIvLnRlc3QodG9rZW4udHlwZSkpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgc3RyZWFtID0gbmV3IENvZGVNaXJyb3IuU3RyaW5nU3RyZWFtKGxpbmUuc2xpY2UoMCwgcG9zLmNoKSArIGNoICsgbGluZS5zbGljZShwb3MuY2gpLCA0KTtcbiAgICBzdHJlYW0ucG9zID0gc3RyZWFtLnN0YXJ0ID0gdG9rZW4uc3RhcnQ7XG4gICAgZm9yICg7Oykge1xuICAgICAgdmFyIHR5cGUxID0gY20uZ2V0TW9kZSgpLnRva2VuKHN0cmVhbSwgdG9rZW4uc3RhdGUpO1xuICAgICAgaWYgKHN0cmVhbS5wb3MgPj0gcG9zLmNoICsgMSkgcmV0dXJuIC9cXGJzdHJpbmcyP1xcYi8udGVzdCh0eXBlMSk7XG4gICAgICBzdHJlYW0uc3RhcnQgPSBzdHJlYW0ucG9zO1xuICAgIH1cbiAgfVxufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIHZhciBpZV9sdDggPSAvTVNJRSBcXGQvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiZcbiAgICAoZG9jdW1lbnQuZG9jdW1lbnRNb2RlID09IG51bGwgfHwgZG9jdW1lbnQuZG9jdW1lbnRNb2RlIDwgOCk7XG5cbiAgdmFyIFBvcyA9IENvZGVNaXJyb3IuUG9zO1xuXG4gIHZhciBtYXRjaGluZyA9IHtcIihcIjogXCIpPlwiLCBcIilcIjogXCIoPFwiLCBcIltc
23459IjogXCJdPlwiLCBcIl1cIjogXCJbPFwiLCBcIntcIjogXCJ9PlwiLCBcIn1cIjogXCJ7PFwifTtcblxuICBmdW5jdGlvbiBmaW5kTWF0Y2hpbmdCcmFja2V0KGNtLCB3aGVyZSwgc3RyaWN0LCBjb25maWcpIHtcbiAgICB2YXIgbGluZSA9IGNtLmdldExpbmVIYW5kbGUod2hlcmUubGluZSksIHBvcyA9IHdoZXJlLmNoIC0gMTtcbiAgICB2YXIgbWF0Y2ggPSAocG9zID49IDAgJiYgbWF0Y2hpbmdbbGluZS50ZXh0LmNoYXJBdChwb3MpXSkgfHwgbWF0Y2hpbmdbbGluZS50ZXh0LmNoYXJBdCgrK3BvcyldO1xuICAgIGlmICghbWF0Y2gpIHJldHVybiBudWxsO1xuICAgIHZhciBkaXIgPSBtYXRjaC5jaGFyQXQoMSkgPT0gXCI+XCIgPyAxIDogLTE7XG4gICAgaWYgKHN0cmljdCAmJiAoZGlyID4gMCkgIT0gKHBvcyA9PSB3aGVyZS5jaCkpIHJldHVybiBudWxsO1xuICAgIHZhciBzdHlsZSA9IGNtLmdldFRva2VuVHlwZUF0KFBvcyh3aGVyZS5saW5lLCBwb3MgKyAxKSk7XG5cbiAgICB2YXIgZm91bmQgPSBzY2FuRm9yQnJhY2tldChjbSwgUG9zKHdoZXJlLmxpbmUsIHBvcyArIChkaXIgPiAwID8gMSA6IDApKSwgZGlyLCBzdHlsZSB8fCBudWxsLCBjb25maWcpO1xuICAgIGlmIChmb3VuZCA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4ge2Zyb206IFBvcyh3aGVyZS5saW5lLCBwb3MpLCB0bzogZm91bmQgJiYgZm91bmQucG9zLFxuICAgICAgICAgICAgbWF0Y2g6IGZvdW5kICYmIGZvdW5kLmNoID09IG1hdGNoLmNoYXJBdCgwKSwgZm9yd2FyZDogZGlyID4gMH07XG4gIH1cblxuICAvLyBicmFja2V0UmVnZXggaXMgdXNlZCB0byBzcGVjaWZ5IHdoaWNoIHR5cGUgb2YgYnJhY2tldCB0byBzY2FuXG4gIC8vIHNob3VsZCBiZSBhIHJlZ2V4cCwgZS5nLiAvW1tcXF1dL1xuICAvL1xuICAvLyBOb3RlOiBJZiBcIndoZXJlXCIgaXMgb24gYW4gb3BlbiBicmFja2V0LCB0aGVuIHRoaXMgYnJhY2tldCBpcyBpZ25vcmVkLlxuICAvL1xuICAvLyBSZXR1cm5zIGZhbHNlIHdoZW4gbm8gYnJhY2tldCB3YXMgZm91bmQsIG51bGwgd2hlbiBpdCByZWFjaGVkXG4gIC8vIG1heFNjYW5MaW5lcyBhbmQgZ2F2ZSB1cFxuICBmdW5jdGlvbiBzY2FuRm9yQnJhY2tldChjbSwgd2hlcmUsIGRpciwgc3R5bGUsIGNvbmZpZykge1xuICAgIHZhciBtYXhTY2FuTGVuID0gKGNvbmZpZyAmJiBjb25maWcubWF4U2NhbkxpbmVMZW5ndGgpIHx8IDEwMDAwO1xuICAgIHZhciBtYXhTY2FuTGluZXMgPSAoY29uZmlnICYmIGNvbmZpZy5tYXhTY2FuTGluZXMpIHx8IDEwMDA7XG5cbiAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICB2YXIgcmUgPSBjb25maWcgJiYgY29uZmlnLmJyYWNrZXRSZWdleCA/IGNvbmZpZy5icmFja2V0UmVnZXggOiAvWygpe31bXFxdXS87XG4gICAgdmFyIGxpbmVFbmQgPSBkaXIgPiAwID8gTWF0aC5taW4od2hlcmUubGluZSArIG1heFNjYW5MaW5lcywgY20ubGFzdExpbmUoKSArIDEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogTWF0aC5tYXgoY20uZmlyc3RMaW5lKCkgLSAxLCB3aGVyZS5saW5lIC0gbWF4U2NhbkxpbmVzKTtcbiAgICBmb3IgKHZhciBsaW5lTm8gPSB3aGVyZS5saW5lOyBsaW5lTm8gIT0gbGluZUVuZDsgbGluZU5vICs9IGRpcikge1xuICAgICAgdmFyIGxpbmUgPSBjbS5nZXRMaW5lKGxpbmVObyk7XG4gICAgICBpZiAoIWxpbmUpIGNvbnRpbnVlO1xuICAgICAgdmFyIHBvcyA9IGRpciA+IDAgPyAwIDogbGluZS5sZW5ndGggLSAxLCBlbmQgPSBkaXIgPiAwID8gbGluZS5sZW5ndGggOiAtMTtcbiAgICAgIGlmIChsaW5lLmxlbmd0aCA+IG1heFNjYW5MZW4pIGNvbnRpbnVlO1xuICAgICAgaWYgKGxpbmVObyA9PSB3aGVyZS5saW5lKSBwb3MgPSB3aGVyZS5jaCAtIChkaXIgPCAwID8gMSA6IDApO1xuICAgICAgZm9yICg7IHBvcyAhPSBlbmQ7IHBvcyArPSBkaXIpIHtcbiAgICAgICAgdmFyIGNoID0gbGluZS5jaGFyQXQocG9zKTtcbiAgICAgICAgaWYgKHJlLnRlc3QoY2gpICYmIChzdHlsZSA9PT0gdW5kZWZpbmVkIHx8IGNtLmdldFRva2VuVHlwZUF0KFBvcyhsaW5lTm8sIHBvcyArIDEpKSA9PSBzdHlsZSkpIHtcbiAgICAgICAgICB2Y
23459XIgbWF0Y2ggPSBtYXRjaGluZ1tjaF07XG4gICAgICAgICAgaWYgKChtYXRjaC5jaGFyQXQoMSkgPT0gXCI+XCIpID09IChkaXIgPiAwKSkgc3RhY2sucHVzaChjaCk7XG4gICAgICAgICAgZWxzZSBpZiAoIXN0YWNrLmxlbmd0aCkgcmV0dXJuIHtwb3M6IFBvcyhsaW5lTm8sIHBvcyksIGNoOiBjaH07XG4gICAgICAgICAgZWxzZSBzdGFjay5wb3AoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbGluZU5vIC0gZGlyID09IChkaXIgPiAwID8gY20ubGFzdExpbmUoKSA6IGNtLmZpcnN0TGluZSgpKSA/IGZhbHNlIDogbnVsbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1hdGNoQnJhY2tldHMoY20sIGF1dG9jbGVhciwgY29uZmlnKSB7XG4gICAgLy8gRGlzYWJsZSBicmFjZSBtYXRjaGluZyBpbiBsb25nIGxpbmVzLCBzaW5jZSBpdCdsbCBjYXVzZSBodWdlbHkgc2xvdyB1cGRhdGVzXG4gICAgdmFyIG1heEhpZ2hsaWdodExlbiA9IGNtLnN0YXRlLm1hdGNoQnJhY2tldHMubWF4SGlnaGxpZ2h0TGluZUxlbmd0aCB8fCAxMDAwO1xuICAgIHZhciBtYXJrcyA9IFtdLCByYW5nZXMgPSBjbS5saXN0U2VsZWN0aW9ucygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbWF0Y2ggPSByYW5nZXNbaV0uZW1wdHkoKSAmJiBmaW5kTWF0Y2hpbmdCcmFja2V0KGNtLCByYW5nZXNbaV0uaGVhZCwgZmFsc2UsIGNvbmZpZyk7XG4gICAgICBpZiAobWF0Y2ggJiYgY20uZ2V0TGluZShtYXRjaC5mcm9tLmxpbmUpLmxlbmd0aCA8PSBtYXhIaWdobGlnaHRMZW4pIHtcbiAgICAgICAgdmFyIHN0eWxlID0gbWF0Y2gubWF0Y2ggPyBcIkNvZGVNaXJyb3ItbWF0Y2hpbmdicmFja2V0XCIgOiBcIkNvZGVNaXJyb3Itbm9ubWF0Y2hpbmdicmFja2V0XCI7XG4gICAgICAgIG1hcmtzLnB1c2goY20ubWFya1RleHQobWF0Y2guZnJvbSwgUG9zKG1hdGNoLmZyb20ubGluZSwgbWF0Y2guZnJvbS5jaCArIDEpLCB7Y2xhc3NOYW1lOiBzdHlsZX0pKTtcbiAgICAgICAgaWYgKG1hdGNoLnRvICYmIGNtLmdldExpbmUobWF0Y2gudG8ubGluZSkubGVuZ3RoIDw9IG1heEhpZ2hsaWdodExlbilcbiAgICAgICAgICBtYXJrcy5wdXNoKGNtLm1hcmtUZXh0KG1hdGNoLnRvLCBQb3MobWF0Y2gudG8ubGluZSwgbWF0Y2gudG8uY2ggKyAxKSwge2NsYXNzTmFtZTogc3R5bGV9KSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1hcmtzLmxlbmd0aCkge1xuICAgICAgLy8gS2x1ZGdlIHRvIHdvcmsgYXJvdW5kIHRoZSBJRSBidWcgZnJvbSBpc3N1ZSAjMTE5Mywgd2hlcmUgdGV4dFxuICAgICAgLy8gaW5wdXQgc3RvcHMgZ29pbmcgdG8gdGhlIHRleHRhcmUgd2hldmVyIHRoaXMgZmlyZXMuXG4gICAgICBpZiAoaWVfbHQ4ICYmIGNtLnN0YXRlLmZvY3VzZWQpIGNtLmZvY3VzKCk7XG5cbiAgICAgIHZhciBjbGVhciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXJrcy5sZW5ndGg7IGkrKykgbWFya3NbaV0uY2xlYXIoKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgICAgaWYgKGF1dG9jbGVhcikgc2V0VGltZW91dChjbGVhciwgODAwKTtcbiAgICAgIGVsc2UgcmV0dXJuIGNsZWFyO1xuICAgIH1cbiAgfVxuXG4gIHZhciBjdXJyZW50bHlIaWdobGlnaHRlZCA9IG51bGw7XG4gIGZ1bmN0aW9uIGRvTWF0Y2hCcmFja2V0cyhjbSkge1xuICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIGlmIChjdXJyZW50bHlIaWdobGlnaHRlZCkge2N1cnJlbnRseUhpZ2hsaWdodGVkKCk7IGN1cnJlbnRseUhpZ2hsaWdodGVkID0gbnVsbDt9XG4gICAgICBjdXJyZW50bHlIaWdobGlnaHRlZCA9IG1hdGNoQnJhY2tldHMoY20sIGZhbHNlLCBjbS5zdGF0ZS5tYXRjaEJyYWNrZXRzKTtcbiAgICB9KTtcbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lT3B0aW9uKFwibWF0Y2hCcmFja2V0c1wiLCBmYWxzZSwgZnVuY3Rpb24oY20sIHZhbCwgb2xkKSB7XG4gICAgaWYgKG9sZCAmJiBvbGQgIT0gQ29kZU1pcnJvci5Jbml0KVxuICAgICAgY20ub2ZmKFwiY3Vyc29yQWN0aXZpdHlcIiwgZG9NYXRjaEJyYWNrZXRzKTtcbiAgICBpZiAodmFsKSB7XG4gICAgICBjbS5zdGF0ZS5tYXRjaEJyYWNrZXRzID0gdHlwZW9mIHZhbCA9PSBcIm9iamVjdFwiID8gdmFsIDoge307XG4gICAgICBjbS5vbihcImN1cnNvckFjdGl2aXR5XCIsIGRvTWF0Y2hCcmFja2V0cyk7XG4gICAgfVxuICB9KTtcblxuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcIm1hdGNoQnJhY2tldHNcIiwgZnVuY3Rpb24oKSB7bWF0Y2hCcmFja2V0cyh0aGlzLCB0cnVlKTt9KTtcbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJmaW5kTWF0Y2hpbmdCcmFja2V0XCIsIGZ1bmN0aW9uKHBvcywgc3RyaWN0LCBjb25maWcpe1xuICAgIHJldHVybiBmaW5kTWF0Y2hpbmdCcmFja2V0KHRoaXMsIHBvcywgc3RyaWN0LCBjb25maWcpO1xuICB9KTtcbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJzY2FuRm9yQnJhY2tldFwiLCBmdW5jdGlvbihwb3MsIGRpciwgc3R5bGUsIGNvbmZpZyl7XG4gICAgcmV0dXJuIHNjYW5Gb3JCcmFja2V0KHRoaXMsIHBvcywgZGlyLCBzdHlsZSwgY29uZmlnKTtcbiAgfSk7XG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cDovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgZnVuY3Rpb24gZG9Gb2xkKGNtLCBwb3MsIG9wdGlvbnMsIGZvcmNlKSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5jYWxsKSB7XG4gICAgICB2Y
23459XIgZmluZGVyID0gb3B0aW9ucztcbiAgICAgIG9wdGlvbnMgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZmluZGVyID0gZ2V0T3B0aW9uKGNtLCBvcHRpb25zLCBcInJhbmdlRmluZGVyXCIpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHBvcyA9PSBcIm51bWJlclwiKSBwb3MgPSBDb2RlTWlycm9yLlBvcyhwb3MsIDApO1xuICAgIHZhciBtaW5TaXplID0gZ2V0T3B0aW9uKGNtLCBvcHRpb25zLCBcIm1pbkZvbGRTaXplXCIpO1xuXG4gICAgZnVuY3Rpb24gZ2V0UmFuZ2UoYWxsb3dGb2xkZWQpIHtcbiAgICAgIHZhciByYW5nZSA9IGZpbmRlcihjbSwgcG9zKTtcbiAgICAgIGlmICghcmFuZ2UgfHwgcmFuZ2UudG8ubGluZSAtIHJhbmdlLmZyb20ubGluZSA8IG1pblNpemUpIHJldHVybiBudWxsO1xuICAgICAgdmFyIG1hcmtzID0gY20uZmluZE1hcmtzQXQocmFuZ2UuZnJvbSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChtYXJrc1tpXS5fX2lzRm9sZCAmJiBmb3JjZSAhPT0gXCJmb2xkXCIpIHtcbiAgICAgICAgICBpZiAoIWFsbG93Rm9sZGVkKSByZXR1cm4gbnVsbDtcbiAgICAgICAgICByYW5nZS5jbGVhcmVkID0gdHJ1ZTtcbiAgICAgICAgICBtYXJrc1tpXS5jbGVhcigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlID0gZ2V0UmFuZ2UodHJ1ZSk7XG4gICAgaWYgKGdldE9wdGlvbihjbSwgb3B0aW9ucywgXCJzY2FuVXBcIikpIHdoaWxlICghcmFuZ2UgJiYgcG9zLmxpbmUgPiBjbS5maXJzdExpbmUoKSkge1xuICAgICAgcG9zID0gQ29kZU1pcnJvci5Qb3MocG9zLmxpbmUgLSAxLCAwKTtcbiAgICAgIHJhbmdlID0gZ2V0UmFuZ2UoZmFsc2UpO1xuICAgIH1cbiAgICBpZiAoIXJhbmdlIHx8IHJhbmdlLmNsZWFyZWQgfHwgZm9yY2UgPT09IFwidW5mb2xkXCIpIHJldHVybjtcblxuICAgIHZhciBteVdpZGdldCA9IG1ha2VXaWRnZXQoY20sIG9wdGlvbnMpO1xuICAgIENvZGVNaXJyb3Iub24obXlXaWRnZXQsIFwibW91c2Vkb3duXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIG15UmFuZ2UuY2xlYXIoKTtcbiAgICAgIENvZGVNaXJyb3IuZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICB9KTtcbiAgICB2YXIgbXlSYW5nZSA9IGNtLm1hcmtUZXh0KHJhbmdlLmZyb20sIHJhbmdlLnRvLCB7XG4gICAgICByZXBsYWNlZFdpdGg6IG15V2lkZ2V0LFxuICAgICAgY2xlYXJPbkVudGVyOiB0cnVlLFxuICAgICAgX19pc0ZvbGQ6IHRydWVcbiAgICB9KTtcbiAgICBteVJhbmdlLm9uKFwiY2xlYXJcIiwgZnVuY3Rpb24oZnJvbSwgdG8pIHtcbiAgICAgIENvZGVNaXJyb3Iuc2lnbmFsKGNtLCBcInVuZm9sZFwiLCBjbSwgZnJvbSwgdG8pO1xuICAgIH0pO1xuICAgIENvZGVNaXJyb3Iuc2lnbmFsKGNtLCBcImZvbGRcIiwgY20sIHJhbmdlLmZyb20sIHJhbmdlLnRvKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VXaWRnZXQoY20sIG9wdGlvbnMpIHtcbiAgICB2YXIgd2lkZ2V0ID0gZ2V0T3B0aW9uKGNtLCBvcHRpb25zLCBcIndpZGdldFwiKTtcbiAgICBpZiAodHlwZW9mIHdpZGdldCA9PSBcInN0cmluZ1wiKSB7XG4gICAgICB2Y
23459XIgdGV4dCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHdpZGdldCk7XG4gICAgICB3aWRnZXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgIHdpZGdldC5hcHBlbmRDaGlsZCh0ZXh0KTtcbiAgICAgIHdpZGdldC5jbGFzc05hbWUgPSBcIkNvZGVNaXJyb3ItZm9sZG1hcmtlclwiO1xuICAgIH1cbiAgICByZXR1cm4gd2lkZ2V0O1xuICB9XG5cbiAgLy8gQ2x1bXN5IGJhY2t3YXJkcy1jb21wYXRpYmxlIGludGVyZmFjZVxuICBDb2RlTWlycm9yLm5ld0ZvbGRGdW5jdGlvbiA9IGZ1bmN0aW9uKHJhbmdlRmluZGVyLCB3aWRnZXQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oY20sIHBvcykgeyBkb0ZvbGQoY20sIHBvcywge3JhbmdlRmluZGVyOiByYW5nZUZpbmRlciwgd2lkZ2V0OiB3aWRnZXR9KTsgfTtcbiAgfTtcblxuICAvLyBOZXctc3R5bGUgaW50ZXJmYWNlXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwiZm9sZENvZGVcIiwgZnVuY3Rpb24ocG9zLCBvcHRpb25zLCBmb3JjZSkge1xuICAgIGRvRm9sZCh0aGlzLCBwb3MsIG9wdGlvbnMsIGZvcmNlKTtcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJpc0ZvbGRlZFwiLCBmdW5jdGlvbihwb3MpIHtcbiAgICB2YXIgbWFya3MgPSB0aGlzLmZpbmRNYXJrc0F0KHBvcyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXJrcy5sZW5ndGg7ICsraSlcbiAgICAgIGlmIChtYXJrc1tpXS5fX2lzRm9sZCkgcmV0dXJuIHRydWU7XG4gIH0pO1xuXG4gIENvZGVNaXJyb3IuY29tbWFuZHMudG9nZ2xlRm9sZCA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgY20uZm9sZENvZGUoY20uZ2V0Q3Vyc29yKCkpO1xuICB9O1xuICBDb2RlTWlycm9yLmNvbW1hbmRzLmZvbGQgPSBmdW5jdGlvbihjbSkge1xuICAgIGNtLmZvbGRDb2RlKGNtLmdldEN1cnNvcigpLCBudWxsLCBcImZvbGRcIik7XG4gIH07XG4gIENvZGVNaXJyb3IuY29tbWFuZHMudW5mb2xkID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS5mb2xkQ29kZShjbS5nZXRDdXJzb3IoKSwgbnVsbCwgXCJ1bmZvbGRcIik7XG4gIH07XG4gIENvZGVNaXJyb3IuY29tbWFuZHMuZm9sZEFsbCA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgZm9yICh2YXIgaSA9IGNtLmZpcnN0TGluZSgpLCBlID0gY20ubGFzdExpbmUoKTsgaSA8PSBlOyBpKyspXG4gICAgICAgIGNtLmZvbGRDb2RlKENvZGVNaXJyb3IuUG9zKGksIDApLCBudWxsLCBcImZvbGRcIik7XG4gICAgfSk7XG4gIH07XG4gIENvZGVNaXJyb3IuY29tbWFuZHMudW5mb2xkQWxsID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICBmb3IgKHZhciBpID0gY20uZmlyc3RMaW5lKCksIGUgPSBjbS5sYXN0TGluZSgpOyBpIDw9IGU7IGkrKylcbiAgICAgICAgY20uZm9sZENvZGUoQ29kZU1pcnJvci5Qb3MoaSwgMCksIG51bGwsIFwidW5mb2xkXCIpO1xuICAgIH0pO1xuICB9O1xuXG4gIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJmb2xkXCIsIFwiY29tYmluZVwiLCBmdW5jdGlvbigpIHtcbiAgICB2YXIgZnVuY3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgIHJldHVybiBmdW5jdGlvbihjbSwgc3RhcnQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZnVuY3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGZvdW5kID0gZnVuY3NbaV0oY20sIHN0YXJ0KTtcbiAgICAgICAgaWYgKGZvdW5kKSByZXR1cm4gZm91bmQ7XG4gICAgICB9XG4gICAgfTtcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImZvbGRcIiwgXCJhdXRvXCIsIGZ1bmN0aW9uKGNtLCBzdGFydCkge1xuICAgIHZhciBoZWxwZXJzID0gY20uZ2V0SGVscGVycyhzdGFydCwgXCJmb2xkXCIpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGVscGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGN1ciA9IGhlbHBlcnNbaV0oY20sIHN0YXJ0KTtcbiAgICAgIGlmIChjdXIpIHJldHVybiBjdXI7XG4gICAgfVxuICB9KTtcblxuICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgcmFuZ2VGaW5kZXI6IENvZGVNaXJyb3IuZm9sZC5hdXRvLFxuICAgIHdpZGdldDogXCJcXHUyMTk0XCIsXG4gICAgbWluRm9sZFNpemU6IDAsXG4gICAgc2NhblVwOiBmYWxzZVxuICB9O1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lT3B0aW9uKFwiZm9sZE9wdGlvbnNcIiwgbnVsbCk7XG5cbiAgZnVuY3Rpb24gZ2V0T3B0aW9uKGNtLCBvcHRpb25zLCBuYW1lKSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9uc1tuYW1lXSAhPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIG9wdGlvbnNbbmFtZV07XG4gICAgdmFyIGVkaXRvck9wdGlvbnMgPSBjbS5vcHRpb25zLmZvbGRPcHRpb25zO1xuICAgIGlmIChlZGl0b3JPcHRpb25zICYmIGVkaXRvck9wdGlvbnNbbmFtZV0gIT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiBlZGl0b3JPcHRpb25zW25hbWVdO1xuICAgIHJldHVybiBkZWZhdWx0T3B0aW9uc1tuYW1lXTtcbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwiZm9sZE9wdGlvblwiLCBmdW5jdGlvbihvcHRpb25zLCBuYW1lKSB7XG4gICAgcmV0dXJuIGdldE9wdGlvbih0aGlzLCBvcHRpb25zLCBuYW1lKTtcbiAgfSk7XG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cDovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSwgcmVxdWlyZShcIi4vZm9sZGNvZGVcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIiwgXCIuL2ZvbGRjb2RlXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICBDb2RlTWlycm9yLmRlZmluZU9wdGlvbihcImZvbGRHdXR0ZXJcIiwgZmFsc2UsIGZ1bmN0aW9uKGNtLCB2YWwsIG9sZCkge1xuICAgIGlmIChvbGQgJiYgb2xkICE9IENvZGVNaXJyb3IuSW5pdCkge1xuICAgICAgY20uY2xlYXJHdXR0ZXIoY20uc3RhdGUuZm9sZEd1dHRlci5vcHRpb25zLmd1dHRlcik7XG4gICAgICBjbS5zdGF0ZS5mb2xkR3V0dGVyID0gbnVsbDtcbiAgICAgIGNtLm9mZihcImd1dHRlckNsaWNrXCIsIG9uR3V0dGVyQ2xpY2spO1xuICAgICAgY20ub2ZmKFwiY2hhbmdlXCIsIG9uQ2hhbmdlKTtcbiAgICAgIGNtLm9mZihcInZpZXdwb3J0Q2hhbmdlXCIsIG9uVmlld3BvcnRDaGFuZ2UpO1xuICAgICAgY20ub2ZmKFwiZm9sZFwiLCBvbkZvbGQpO1xuICAgICAgY20ub2ZmKFwidW5mb2xkXCIsIG9uRm9sZCk7XG4gICAgICBjbS5vZmYoXCJzd2FwRG9jXCIsIHVwZGF0ZUluVmlld3BvcnQpO1xuICAgIH1cbiAgICBpZiAodmFsKSB7XG4gICAgICBjbS5zdGF0ZS5mb2xkR3V0dGVyID0gbmV3IFN0YXRlKHBhcnNlT3B0aW9ucyh2YWwpKTtcbiAgICAgIHVwZGF0ZUluVmlld3BvcnQoY20pO1xuICAgICAgY20ub24oXCJndXR0ZXJDbGlja1wiLCBvbkd1dHRlckNsaWNrKTtcbiAgICAgIGNtLm9uKFwiY2hhbmdlXCIsIG9uQ2hhbmdlKTtcbiAgICAgIGNtLm9uKFwidmlld3BvcnRDaGFuZ2VcIiwgb25WaWV3cG9ydENoYW5nZSk7XG4gICAgICBjbS5vbihcImZvbGRcIiwgb25Gb2xkKTtcbiAgICAgIGNtLm9uKFwidW5mb2xkXCIsIG9uRm9sZCk7XG4gICAgICBjbS5vbihcInN3YXBEb2NcIiwgdXBkYXRlSW5WaWV3cG9ydCk7XG4gICAgfVxuICB9KTtcblxuICB2Y
23459XIgUG9zID0gQ29kZU1pcnJvci5Qb3M7XG5cbiAgZnVuY3Rpb24gU3RhdGUob3B0aW9ucykge1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgdGhpcy5mcm9tID0gdGhpcy50byA9IDA7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZU9wdGlvbnMob3B0cykge1xuICAgIGlmIChvcHRzID09PSB0cnVlKSBvcHRzID0ge307XG4gICAgaWYgKG9wdHMuZ3V0dGVyID09IG51bGwpIG9wdHMuZ3V0dGVyID0gXCJDb2RlTWlycm9yLWZvbGRndXR0ZXJcIjtcbiAgICBpZiAob3B0cy5pbmRpY2F0b3JPcGVuID09IG51bGwpIG9wdHMuaW5kaWNhdG9yT3BlbiA9IFwiQ29kZU1pcnJvci1mb2xkZ3V0dGVyLW9wZW5cIjtcbiAgICBpZiAob3B0cy5pbmRpY2F0b3JGb2xkZWQgPT0gbnVsbCkgb3B0cy5pbmRpY2F0b3JGb2xkZWQgPSBcIkNvZGVNaXJyb3ItZm9sZGd1dHRlci1mb2xkZWRcIjtcbiAgICByZXR1cm4gb3B0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRm9sZGVkKGNtLCBsaW5lKSB7XG4gICAgdmFyIG1hcmtzID0gY20uZmluZE1hcmtzQXQoUG9zKGxpbmUpKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtzLmxlbmd0aDsgKytpKVxuICAgICAgaWYgKG1hcmtzW2ldLl9faXNGb2xkICYmIG1hcmtzW2ldLmZpbmQoKS5mcm9tLmxpbmUgPT0gbGluZSkgcmV0dXJuIG1hcmtzW2ldO1xuICB9XG5cbiAgZnVuY3Rpb24gbWFya2VyKHNwZWMpIHtcbiAgICBpZiAodHlwZW9mIHNwZWMgPT0gXCJzdHJpbmdcIikge1xuICAgICAgdmFyIGVsdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICBlbHQuY2xhc3NOYW1lID0gc3BlYyArIFwiIENvZGVNaXJyb3ItZ3V0dGVybWFya2VyLXN1YnRsZVwiO1xuICAgICAgcmV0dXJuIGVsdDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHNwZWMuY2xvbmVOb2RlKHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZUZvbGRJbmZvKGNtLCBmcm9tLCB0bykge1xuICAgIHZhciBvcHRzID0gY20uc3RhdGUuZm9sZEd1dHRlci5vcHRpb25zLCBjdXIgPSBmcm9tO1xuICAgIHZhciBtaW5TaXplID0gY20uZm9sZE9wdGlvbihvcHRzLCBcIm1pbkZvbGRTaXplXCIpO1xuICAgIHZhciBmdW5jID0gY20uZm9sZE9wdGlvbihvcHRzLCBcInJhbmdlRmluZGVyXCIpO1xuICAgIGNtLmVhY2hMaW5lKGZyb20sIHRvLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICB2Y
23459XIgbWFyayA9IG51bGw7XG4gICAgICBpZiAoaXNGb2xkZWQoY20sIGN1cikpIHtcbiAgICAgICAgbWFyayA9IG1hcmtlcihvcHRzLmluZGljYXRvckZvbGRlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcG9zID0gUG9zKGN1ciwgMCk7XG4gICAgICAgIHZhciByYW5nZSA9IGZ1bmMgJiYgZnVuYyhjbSwgcG9zKTtcbiAgICAgICAgaWYgKHJhbmdlICYmIHJhbmdlLnRvLmxpbmUgLSByYW5nZS5mcm9tLmxpbmUgPj0gbWluU2l6ZSlcbiAgICAgICAgICBtYXJrID0gbWFya2VyKG9wdHMuaW5kaWNhdG9yT3Blbik7XG4gICAgICB9XG4gICAgICBjbS5zZXRHdXR0ZXJNYXJrZXIobGluZSwgb3B0cy5ndXR0ZXIsIG1hcmspO1xuICAgICAgKytjdXI7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVJblZpZXdwb3J0KGNtKSB7XG4gICAgdmFyIHZwID0gY20uZ2V0Vmlld3BvcnQoKSwgc3RhdGUgPSBjbS5zdGF0ZS5mb2xkR3V0dGVyO1xuICAgIGlmICghc3RhdGUpIHJldHVybjtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICB1cGRhdGVGb2xkSW5mbyhjbSwgdnAuZnJvbSwgdnAudG8pO1xuICAgIH0pO1xuICAgIHN0YXRlLmZyb20gPSB2cC5mcm9tOyBzdGF0ZS50byA9IHZwLnRvO1xuICB9XG5cbiAgZnVuY3Rpb24gb25HdXR0ZXJDbGljayhjbSwgbGluZSwgZ3V0dGVyKSB7XG4gICAgdmFyIHN0YXRlID0gY20uc3RhdGUuZm9sZEd1dHRlcjtcbiAgICBpZiAoIXN0YXRlKSByZXR1cm47XG4gICAgdmFyIG9wdHMgPSBzdGF0ZS5vcHRpb25zO1xuICAgIGlmIChndXR0ZXIgIT0gb3B0cy5ndXR0ZXIpIHJldHVybjtcbiAgICB2YXIgZm9sZGVkID0gaXNGb2xkZWQoY20sIGxpbmUpO1xuICAgIGlmIChmb2xkZWQpIGZvbGRlZC5jbGVhcigpO1xuICAgIGVsc2UgY20uZm9sZENvZGUoUG9zKGxpbmUsIDApLCBvcHRzLnJhbmdlRmluZGVyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uQ2hhbmdlKGNtKSB7XG4gICAgdmFyIHN0YXRlID0gY20uc3RhdGUuZm9sZEd1dHRlcjtcbiAgICBpZiAoIXN0YXRlKSByZXR1cm47XG4gICAgdmFyIG9wdHMgPSBzdGF0ZS5vcHRpb25zO1xuICAgIHN0YXRlLmZyb20gPSBzdGF0ZS50byA9IDA7XG4gICAgY2xlYXJUaW1lb3V0KHN0YXRlLmNoYW5nZVVwZGF0ZSk7XG4gICAgc3RhdGUuY2hhbmdlVXBkYXRlID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsgdXBkYXRlSW5WaWV3cG9ydChjbSk7IH0sIG9wdHMuZm9sZE9uQ2hhbmdlVGltZVNwYW4gfHwgNjAwKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uVmlld3BvcnRDaGFuZ2UoY20pIHtcbiAgICB2YXIgc3RhdGUgPSBjbS5zdGF0ZS5mb2xkR3V0dGVyO1xuICAgIGlmICghc3RhdGUpIHJldHVybjtcbiAgICB2YXIgb3B0cyA9IHN0YXRlLm9wdGlvbnM7XG4gICAgY2xlYXJUaW1lb3V0KHN0YXRlLmNoYW5nZVVwZGF0ZSk7XG4gICAgc3RhdGUuY2hhbmdlVXBkYXRlID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2cCA9IGNtLmdldFZpZXdwb3J0KCk7XG4gICAgICBpZiAoc3RhdGUuZnJvbSA9PSBzdGF0ZS50byB8fCB2cC5mcm9tIC0gc3RhdGUudG8gPiAyMCB8fCBzdGF0ZS5mcm9tIC0gdnAudG8gPiAyMCkge1xuICAgICAgICB1cGRhdGVJblZpZXdwb3J0KGNtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAodnAuZnJvbSA8IHN0YXRlLmZyb20pIHtcbiAgICAgICAgICAgIHVwZGF0ZUZvbGRJbmZvKGNtLCB2cC5mcm9tLCBzdGF0ZS5mcm9tKTtcbiAgICAgICAgICAgIHN0YXRlLmZyb20gPSB2cC5mcm9tO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodnAudG8gPiBzdGF0ZS50bykge1xuICAgICAgICAgICAgdXBkYXRlRm9sZEluZm8oY20sIHN0YXRlLnRvLCB2cC50byk7XG4gICAgICAgICAgICBzdGF0ZS50byA9IHZwLnRvO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwgb3B0cy51cGRhdGVWaWV3cG9ydFRpbWVTcGFuIHx8IDQwMCk7XG4gIH1cblxuICBmdW5jdGlvbiBvbkZvbGQoY20sIGZyb20pIHtcbiAgICB2YXIgc3RhdGUgPSBjbS5zdGF0ZS5mb2xkR3V0dGVyO1xuICAgIGlmICghc3RhdGUpIHJldHVybjtcbiAgICB2YXIgbGluZSA9IGZyb20ubGluZTtcbiAgICBpZiAobGluZSA+PSBzdGF0ZS5mcm9tICYmIGxpbmUgPCBzdGF0ZS50bylcbiAgICAgIHVwZGF0ZUZvbGRJbmZvKGNtLCBsaW5lLCBsaW5lICsgMSk7XG4gIH1cbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbkNvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJmb2xkXCIsIFwiaW5kZW50XCIsIGZ1bmN0aW9uKGNtLCBzdGFydCkge1xuICB2YXIgdGFiU2l6ZSA9IGNtLmdldE9wdGlvbihcInRhYlNpemVcIiksIGZpcnN0TGluZSA9IGNtLmdldExpbmUoc3RhcnQubGluZSk7XG4gIGlmICghL1xcUy8udGVzdChmaXJzdExpbmUpKSByZXR1cm47XG4gIHZhciBnZXRJbmRlbnQgPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIENvZGVNaXJyb3IuY291bnRDb2x1bW4obGluZSwgbnVsbCwgdGFiU2l6ZSk7XG4gIH07XG4gIHZhciBteUluZGVudCA9IGdldEluZGVudChmaXJzdExpbmUpO1xuICB2YXIgbGFzdExpbmVJbkZvbGQgPSBudWxsO1xuICAvLyBHbyB0aHJvdWdoIGxpbmVzIHVudGlsIHdlIGZpbmQgYSBsaW5lIHRoYXQgZGVmaW5pdGVseSBkb2Vzbid0IGJlbG9uZyBpblxuICAvLyB0aGUgYmxvY2sgd2UncmUgZm9sZGluZywgb3IgdG8gdGhlIGVuZC5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0LmxpbmUgKyAxLCBlbmQgPSBjbS5sYXN0TGluZSgpOyBpIDw9IGVuZDsgKytpKSB7XG4gICAgdmFyIGN1ckxpbmUgPSBjbS5nZXRMaW5lKGkpO1xuICAgIHZhciBjdXJJbmRlbnQgPSBnZXRJbmRlbnQoY3VyTGluZSk7XG4gICAgaWYgKGN1ckluZGVudCA+IG15SW5kZW50KSB7XG4gICAgICAvLyBMaW5lcyB3aXRoIGEgZ3JlYXRlciBpbmRlbnQgYXJlIGNvbnNpZGVyZWQgcGFydCBvZiB0aGUgYmxvY2suXG4gICAgICBsYXN0TGluZUluRm9sZCA9IGk7XG4gICAgfSBlbHNlIGlmICghL1xcUy8udGVzdChjdXJMaW5lKSkge1xuICAgICAgLy8gRW1wdHkgbGluZXMgbWlnaHQgYmUgYnJlYWtzIHdpdGhpbiB0aGUgYmxvY2sgd2UncmUgdHJ5aW5nIHRvIGZvbGQuXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEEgbm9uLWVtcHR5IGxpbmUgYXQgYW4gaW5kZW50IGVxdWFsIHRvIG9yIGxlc3MgdGhhbiBvdXJzIG1hcmtzIHRoZVxuICAgICAgLy8gc3RhcnQgb2YgYW5vdGhlciBibG9jay5cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAobGFzdExpbmVJbkZvbGQpIHJldHVybi
23459B7XG4gICAgZnJvbTogQ29kZU1pcnJvci5Qb3Moc3RhcnQubGluZSwgZmlyc3RMaW5lLmxlbmd0aCksXG4gICAgdG86IENvZGVNaXJyb3IuUG9zKGxhc3RMaW5lSW5Gb2xkLCBjbS5nZXRMaW5lKGxhc3RMaW5lSW5Gb2xkKS5sZW5ndGgpXG4gIH07XG59KTtcblxufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIHZhciBQb3MgPSBDb2RlTWlycm9yLlBvcztcblxuICBmdW5jdGlvbiBmb3JFYWNoKGFyciwgZikge1xuICAgIGZvciAodmFyIGkgPSAwLCBlID0gYXJyLmxlbmd0aDsgaSA8IGU7ICsraSkgZihhcnJbaV0pO1xuICB9XG5cbiAgZnVuY3Rpb24gYXJyYXlDb250YWlucyhhcnIsIGl0ZW0pIHtcbiAgICBpZiAoIUFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgICB2Y
23459XIgaSA9IGFyci5sZW5ndGg7XG4gICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIGlmIChhcnJbaV0gPT09IGl0ZW0pIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyLmluZGV4T2YoaXRlbSkgIT0gLTE7XG4gIH1cblxuICBmdW5jdGlvbiBzY3JpcHRIaW50KGVkaXRvciwga2V5d29yZHMsIGdldFRva2VuLCBvcHRpb25zKSB7XG4gICAgLy8gRmluZCB0aGUgdG9rZW4gYXQgdGhlIGN1cnNvclxuICAgIHZhciBjdXIgPSBlZGl0b3IuZ2V0Q3Vyc29yKCksIHRva2VuID0gZ2V0VG9rZW4oZWRpdG9yLCBjdXIpO1xuICAgIGlmICgvXFxiKD86c3RyaW5nfGNvbW1lbnQpXFxiLy50ZXN0KHRva2VuLnR5cGUpKSByZXR1cm47XG4gICAgdG9rZW4uc3RhdGUgPSBDb2RlTWlycm9yLmlubmVyTW9kZShlZGl0b3IuZ2V0TW9kZSgpLCB0b2tlbi5zdGF0ZSkuc3RhdGU7XG5cbiAgICAvLyBJZiBpdCdzIG5vdCBhICd3b3JkLXN0eWxlJyB0b2tlbiwgaWdub3JlIHRoZSB0b2tlbi5cbiAgICBpZiAoIS9eW1xcdyRfXSokLy50ZXN0KHRva2VuLnN0cmluZykpIHtcbiAgICAgIHRva2VuID0ge3N0YXJ0OiBjdXIuY2gsIGVuZDogY3VyLmNoLCBzdHJpbmc6IFwiXCIsIHN0YXRlOiB0b2tlbi5zdGF0ZSxcbiAgICAgICAgICAgICAgIHR5cGU6IHRva2VuLnN0cmluZyA9PSBcIi5cIiA/IFwicHJvcGVydHlcIiA6IG51bGx9O1xuICAgIH0gZWxzZSBpZiAodG9rZW4uZW5kID4gY3VyLmNoKSB7XG4gICAgICB0b2tlbi5lbmQgPSBjdXIuY2g7XG4gICAgICB0b2tlbi5zdHJpbmcgPSB0b2tlbi5zdHJpbmcuc2xpY2UoMCwgY3VyLmNoIC0gdG9rZW4uc3RhcnQpO1xuICAgIH1cblxuICAgIHZhciB0cHJvcCA9IHRva2VuO1xuICAgIC8vIElmIGl0IGlzIGEgcHJvcGVydHksIGZpbmQgb3V0IHdoYXQgaXQgaXMgYSBwcm9wZXJ0eSBvZi5cbiAgICB3aGlsZSAodHByb3AudHlwZSA9PSBcInByb3BlcnR5XCIpIHtcbiAgICAgIHRwcm9wID0gZ2V0VG9rZW4oZWRpdG9yLCBQb3MoY3VyLmxpbmUsIHRwcm9wLnN0YXJ0KSk7XG4gICAgICBpZiAodHByb3Auc3RyaW5nICE9IFwiLlwiKSByZXR1cm47XG4gICAgICB0cHJvcCA9IGdldFRva2VuKGVkaXRvciwgUG9zKGN1ci5saW5lLCB0cHJvcC5zdGFydCkpO1xuICAgICAgaWYgKCFjb250ZXh0KSB2YXIgY29udGV4dCA9IFtdO1xuICAgICAgY29udGV4dC5wdXNoKHRwcm9wKTtcbiAgICB9XG4gICAgcmV0dXJuIHtsaXN0OiBnZXRDb21wbGV0aW9ucyh0b2tlbiwgY29udGV4dCwga2V5d29yZHMsIG9wdGlvbnMpLFxuICAgICAgICAgICAgZnJvbTogUG9zKGN1ci5saW5lLCB0b2tlbi5zdGFydCksXG4gICAgICAgICAgICB0bzogUG9zKGN1ci5saW5lLCB0b2tlbi5lbmQpfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGphdmFzY3JpcHRIaW50KGVkaXRvciwgb3B0aW9ucykge1xuICAgIHJldHVybiBzY3JpcHRIaW50KGVkaXRvciwgamF2YXNjcmlwdEtleXdvcmRzLFxuICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChlLCBjdXIpIHtyZXR1cm4gZS5nZXRUb2tlbkF0KGN1cik7fSxcbiAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zKTtcbiAgfTtcbiAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImhpbnRcIiwgXCJqYXZhc2NyaXB0XCIsIGphdmFzY3JpcHRIaW50KTtcblxuICBmdW5jdGlvbiBnZXRDb2ZmZWVTY3JpcHRUb2tlbihlZGl0b3IsIGN1cikge1xuICAvLyBUaGlzIGdldFRva2VuLCBpdCBpcyBmb3IgY29mZmVlc2NyaXB0LCBpbWl0YXRlcyB0aGUgYmVoYXZpb3Igb2ZcbiAgLy8gZ2V0VG9rZW5BdCBtZXRob2QgaW4gamF2YXNjcmlwdC5qcywgdGhhdCBpcywgcmV0dXJuaW5nIFwicHJvcGVydHlcIlxuICAvLyB0eXBlIGFuZCB0cmVhdCBcIi5cIiBhcyBpbmRlcGVuZW50IHRva2VuLlxuICAgIHZhciB0b2tlbiA9IGVkaXRvci5nZXRUb2tlbkF0KGN1cik7XG4gICAgaWYgKGN1ci5jaCA9PSB0b2tlbi5zdGFydCArIDEgJiYgdG9rZW4uc3RyaW5nLmNoYXJBdCgwKSA9PSAnLicpIHtcbiAgICAgIHRva2VuLmVuZCA9IHRva2VuLnN0YXJ0O1xuICAgICAgdG9rZW4uc3RyaW5nID0gJy4nO1xuICAgICAgdG9rZW4udHlwZSA9IFwicHJvcGVydHlcIjtcbiAgICB9XG4gICAgZWxzZSBpZiAoL15cXC5bXFx3JF9dKiQvLnRlc3QodG9rZW4uc3RyaW5nKSkge1xuICAgICAgdG9rZW4udHlwZSA9IFwicHJvcGVydHlcIjtcbiAgICAgIHRva2VuLnN0YXJ0Kys7XG4gICAgICB0b2tlbi5zdHJpbmcgPSB0b2tlbi5zdHJpbmcucmVwbGFjZSgvXFwuLywgJycpO1xuICAgIH1cbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICBmdW5jdGlvbiBjb2ZmZWVzY3JpcHRIaW50KGVkaXRvciwgb3B0aW9ucykge1xuICAgIHJldHVybiBzY3JpcHRIaW50KGVkaXRvciwgY29mZmVlc2NyaXB0S2V5d29yZHMsIGdldENvZmZlZVNjcmlwdFRva2VuLCBvcHRpb25zKTtcbiAgfVxuICBDb2RlTWlycm9yLnJlZ2lzdGVySGVscGVyKFwiaGludFwiLCBcImNvZmZlZXNjcmlwdFwiLCBjb2ZmZWVzY3JpcHRIaW50KTtcblxuICB2YXIgc3RyaW5nUHJvcHMgPSAoXCJjaGFyQXQgY2hhckNvZGVBdCBpbmRleE9mIGxhc3RJbmRleE9mIHN1YnN0cmluZyBzdWJzdHIgc2xpY2UgdHJpbSB0cmltTGVmdCB0cmltUmlnaHQgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgXCJ0b1VwcGVyQ2FzZSB0b0xvd2VyQ2FzZSBzcGxpdCBjb25jYXQgbWF0Y2ggcmVwbGFjZSBzZWFyY2hcIikuc3BsaXQoXCIgXCIpO1xuICB2YXIgYXJyYXlQcm9wcyA9IChcImxlbmd0aCBjb25jYXQgam9pbiBzcGxpY2UgcHVzaCBwb3Agc2hpZnQgdW5zaGlmdCBzbGljZSByZXZlcnNlIHNvcnQgaW5kZXhPZiBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwibGFzdEluZGV4T2YgZXZlcnkgc29tZSBmaWx0ZXIgZm9yRWFjaCBtYXAgcmVkdWNlIHJlZHVjZVJpZ2h0IFwiKS5zcGxpdChcIiBcIik7XG4gIHZhciBmdW5jUHJvcHMgPSBcInByb3RvdHlwZSBhc
23459HBseSBjYWxsIGJpbmRcIi5zcGxpdChcIiBcIik7XG4gIHZhciBqYXZhc2NyaXB0S2V5d29yZHMgPSAoXCJicmVhayBjYXNlIGNhdGNoIGNvbnRpbnVlIGRlYnVnZ2VyIGRlZmF1bHQgZGVsZXRlIGRvIGVsc2UgZmFsc2UgZmluYWxseSBmb3IgZnVuY3Rpb24gXCIgK1xuICAgICAgICAgICAgICAgICAgXCJpZiBpbiBpbnN0YW5jZW9mIG5ldyBudWxsIHJldHVybiBzd2l0Y2ggdGhyb3cgdHJ1ZSB0cnkgdHlwZW9mIHZhciB2b2lkIHdoaWxlIHdpdGhcIikuc3BsaXQoXCIgXCIpO1xuICB2YXIgY29mZmVlc2NyaXB0S2V5d29yZHMgPSAoXCJhbmQgYnJlYWsgY2F0Y2ggY2xhc3MgY29udGludWUgZGVsZXRlIGRvIGVsc2UgZXh0ZW5kcyBmYWxzZSBmaW5hbGx5IGZvciBcIiArXG4gICAgICAgICAgICAgICAgICBcImlmIGluIGluc3RhbmNlb2YgaXNudCBuZXcgbm8gbm90IG51bGwgb2Ygb2ZmIG9uIG9yIHJldHVybiBzd2l0Y2ggdGhlbiB0aHJvdyB0cnVlIHRyeSB0eXBlb2YgdW50aWwgdm9pZCB3aGlsZSB3aXRoIHllc1wiKS5zcGxpdChcIiBcIik7XG5cbiAgZnVuY3Rpb24gZ2V0Q29tcGxldGlvbnModG9rZW4sIGNvbnRleHQsIGtleXdvcmRzLCBvcHRpb25zKSB7XG4gICAgdmFyIGZvdW5kID0gW10sIHN0YXJ0ID0gdG9rZW4uc3RyaW5nLCBnbG9iYWwgPSBvcHRpb25zICYmIG9wdGlvbnMuZ2xvYmFsU2NvcGUgfHwgd2luZG93O1xuICAgIGZ1bmN0aW9uIG1heWJlQWRkKHN0cikge1xuICAgICAgaWYgKHN0ci5sYXN0SW5kZXhPZihzdGFydCwgMCkgPT0gMCAmJiAhYXJyYXlDb250YWlucyhmb3VuZCwgc3RyKSkgZm91bmQucHVzaChzdHIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBnYXRoZXJDb21wbGV0aW9ucyhvYmopIHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqID09IFwic3RyaW5nXCIpIGZvckVhY2goc3RyaW5nUHJvcHMsIG1heWJlQWRkKTtcbiAgICAgIGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIEFycmF5KSBmb3JFYWNoKGFycmF5UHJvcHMsIG1heWJlQWRkKTtcbiAgICAgIGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIEZ1bmN0aW9uKSBmb3JFYWNoKGZ1bmNQcm9wcywgbWF5YmVBZGQpO1xuICAgICAgZm9yICh2YXIgbmFtZSBpbiBvYmopIG1heWJlQWRkKG5hbWUpO1xuICAgIH1cblxuICAgIGlmIChjb250ZXh0ICYmIGNvbnRleHQubGVuZ3RoKSB7XG4gICAgICAvLyBJZiB0aGlzIGlzIGEgcHJvcGVydHksIHNlZSBpZiBpdCBiZWxvbmdzIHRvIHNvbWUgb2JqZWN0IHdlIGNhblxuICAgICAgLy8gZmluZCBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudC5cbiAgICAgIHZhciBvYmogPSBjb250ZXh0LnBvcCgpLCBiYXNlO1xuICAgICAgaWYgKG9iai50eXBlICYmIG9iai50eXBlLmluZGV4T2YoXCJ2YXJpYWJsZVwiKSA9PT0gMCkge1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmFkZGl0aW9uYWxDb250ZXh0KVxuICAgICAgICAgIGJhc2UgPSBvcHRpb25zLmFkZGl0aW9uYWxDb250ZXh0W29iai5zdHJpbmddO1xuICAgICAgICBpZiAoIW9wdGlvbnMgfHwgb3B0aW9ucy51c2VHbG9iYWxTY29wZSAhPT0gZmFsc2UpXG4gICAgICAgICAgYmFzZSA9IGJhc2UgfHwgZ2xvYmFsW29iai5zdHJpbmddO1xuICAgICAgfSBlbHNlIGlmIChvYmoudHlwZSA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGJhc2UgPSBcIlwiO1xuICAgICAgfSBlbHNlIGlmIChvYmoudHlwZSA9PSBcImF0b21cIikge1xuICAgICAgICBiYXNlID0gMTtcbiAgICAgIH0gZWxzZSBpZiAob2JqLnR5cGUgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGlmIChnbG9iYWwualF1ZXJ5ICE9IG51bGwgJiYgKG9iai5zdHJpbmcgPT0gJyQnIHx8IG9iai5zdHJpbmcgPT0gJ2pRdWVyeScpICYmXG4gICAgICAgICAgICAodHlwZW9mIGdsb2JhbC5qUXVlcnkgPT0gJ2Z1bmN0aW9uJykpXG4gICAgICAgICAgYmFzZSA9IGdsb2JhbC5qUXVlcnkoKTtcbiAgICAgICAgZWxzZSBpZiAoZ2xvYmFsLl8gIT0gbnVsbCAmJiAob2JqLnN0cmluZyA9PSAnXycpICYmICh0eXBlb2YgZ2xvYmFsLl8gPT0gJ2Z1bmN0aW9uJykpXG4gICAgICAgICAgYmFzZSA9IGdsb2JhbC5fKCk7XG4gICAgICB9XG4gICAgICB3aGlsZSAoYmFzZSAhPSBudWxsICYmIGNvbnRleHQubGVuZ3RoKVxuICAgICAgICBiYXNlID0gYmFzZVtjb250ZXh0LnBvcCgpLnN0cmluZ107XG4gICAgICBpZiAoYmFzZSAhPSBudWxsKSBnYXRoZXJDb21wbGV0aW9ucyhiYXNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgbm90LCBqdXN0IGxvb2sgaW4gdGhlIGdsb2JhbCBvYmplY3QgYW5kIGFueSBsb2NhbCBzY29wZVxuICAgICAgLy8gKHJlYWRpbmcgaW50byBKUyBtb2RlIGludGVybmFscyB0byBnZXQgYXQgdGhlIGxvY2FsIGFuZCBnbG9iYWwgdmFyaWFibGVzKVxuICAgICAgZm9yICh2YXIgdiA9IHRva2VuLnN0YXRlLmxvY2FsVmFyczsgdjsgdiA9IHYubmV4dCkgbWF5YmVBZGQodi5uYW1lKTtcbiAgICAgIGZvciAodmFyIHYgPSB0b2tlbi5zdGF0ZS5nbG9iYWxWYXJzOyB2OyB2ID0gdi5uZXh0KSBtYXliZUFkZCh2Lm5hbWUpO1xuICAgICAgaWYgKCFvcHRpb25zIHx8IG9wdGlvbnMudXNlR2xvYmFsU2NvcGUgIT09IGZhbHNlKVxuICAgICAgICBnYXRoZXJDb21wbGV0aW9ucyhnbG9iYWwpO1xuICAgICAgZm9yRWFjaChrZXl3b3JkcywgbWF5YmVBZGQpO1xuICAgIH1cbiAgICByZXR1cm4gZm91bmQ7XG4gIH1cbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICB2Y
23459XIgSElOVF9FTEVNRU5UX0NMQVNTICAgICAgICA9IFwiQ29kZU1pcnJvci1oaW50XCI7XG4gIHZhciBBQ1RJVkVfSElOVF9FTEVNRU5UX0NMQVNTID0gXCJDb2RlTWlycm9yLWhpbnQtYWN0aXZlXCI7XG5cbiAgLy8gVGhpcyBpcyB0aGUgb2xkIGludGVyZmFjZSwga2VwdCBhcm91bmQgZm9yIG5vdyB0byBzdGF5XG4gIC8vIGJhY2t3YXJkcy1jb21wYXRpYmxlLlxuICBDb2RlTWlycm9yLnNob3dIaW50ID0gZnVuY3Rpb24oY20sIGdldEhpbnRzLCBvcHRpb25zKSB7XG4gICAgaWYgKCFnZXRIaW50cykgcmV0dXJuIGNtLnNob3dIaW50KG9wdGlvbnMpO1xuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuYXN5bmMpIGdldEhpbnRzLmFzeW5jID0gdHJ1ZTtcbiAgICB2YXIgbmV3T3B0cyA9IHtoaW50OiBnZXRIaW50c307XG4gICAgaWYgKG9wdGlvbnMpIGZvciAodmFyIHByb3AgaW4gb3B0aW9ucykgbmV3T3B0c1twcm9wXSA9IG9wdGlvbnNbcHJvcF07XG4gICAgcmV0dXJuIGNtLnNob3dIaW50KG5ld09wdHMpO1xuICB9O1xuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwic2hvd0hpbnRcIiwgZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBwYXJzZU9wdGlvbnModGhpcywgdGhpcy5nZXRDdXJzb3IoXCJzdGFydFwiKSwgb3B0aW9ucyk7XG4gICAgdmFyIHNlbGVjdGlvbnMgPSB0aGlzLmxpc3RTZWxlY3Rpb25zKClcbiAgICBpZiAoc2VsZWN0aW9ucy5sZW5ndGggPiAxKSByZXR1cm47XG4gICAgLy8gQnkgZGVmYXVsdCwgZG9uJ3QgYWxsb3cgY29tcGxldGlvbiB3aGVuIHNvbWV0aGluZyBpcyBzZWxlY3RlZC5cbiAgICAvLyBBIGhpbnQgZnVuY3Rpb24gY2FuIGhhdmUgYSBgc3VwcG9ydHNTZWxlY3Rpb25gIHByb3BlcnR5IHRvXG4gICAgLy8gaW5kaWNhdGUgdGhhdCBpdCBjYW4gaGFuZGxlIHNlbGVjdGlvbnMuXG4gICAgaWYgKHRoaXMuc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgaWYgKCFvcHRpb25zLmhpbnQuc3VwcG9ydHNTZWxlY3Rpb24pIHJldHVybjtcbiAgICAgIC8vIERvbid0IHRyeSB3aXRoIGNyb3NzLWxpbmUgc2VsZWN0aW9uc1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxlY3Rpb25zLmxlbmd0aDsgaSsrKVxuICAgICAgICBpZiAoc2VsZWN0aW9uc1tpXS5oZWFkLmxpbmUgIT0gc2VsZWN0aW9uc1tpXS5hbmNob3IubGluZSkgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRlLmNvbXBsZXRpb25BY3RpdmUpIHRoaXMuc3RhdGUuY29tcGxldGlvbkFjdGl2ZS5jbG9zZSgpO1xuICAgIHZhciBjb21wbGV0aW9uID0gdGhpcy5zdGF0ZS5jb21wbGV0aW9uQWN0aXZlID0gbmV3IENvbXBsZXRpb24odGhpcywgb3B0aW9ucyk7XG4gICAgaWYgKCFjb21wbGV0aW9uLm9wdGlvbnMuaGludCkgcmV0dXJuO1xuXG4gICAgQ29kZU1pcnJvci5zaWduYWwodGhpcywgXCJzdGFydENvbXBsZXRpb25cIiwgdGhpcyk7XG4gICAgY29tcGxldGlvbi51cGRhdGUodHJ1ZSk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIENvbXBsZXRpb24oY20sIG9wdGlvbnMpIHtcbiAgICB0aGlzLmNtID0gY207XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLndpZGdldCA9IG51bGw7XG4gICAgdGhpcy5kZWJvdW5jZSA9IDA7XG4gICAgdGhpcy50aWNrID0gMDtcbiAgICB0aGlzLnN0YXJ0UG9zID0gdGhpcy5jbS5nZXRDdXJzb3IoXCJzdGFydFwiKTtcbiAgICB0aGlzLnN0YXJ0TGVuID0gdGhpcy5jbS5nZXRMaW5lKHRoaXMuc3RhcnRQb3MubGluZSkubGVuZ3RoIC0gdGhpcy5jbS5nZXRTZWxlY3Rpb24oKS5sZW5ndGg7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgY20ub24oXCJjdXJzb3JBY3Rpdml0eVwiLCB0aGlzLmFjdGl2aXR5RnVuYyA9IGZ1bmN0aW9uKCkgeyBzZWxmLmN1cnNvckFjdGl2aXR5KCk7IH0pO1xuICB9XG5cbiAgdmFyIHJlcXVlc3RBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgZnVuY3Rpb24oZm4pIHtcbiAgICByZXR1cm4gc2V0VGltZW91dChmbiwgMTAwMC82MCk7XG4gIH07XG4gIHZhciBjYW5jZWxBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSB8fCBjbGVhclRpbWVvdXQ7XG5cbiAgQ29tcGxldGlvbi5wcm90b3R5cGUgPSB7XG4gICAgY2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCF0aGlzLmFjdGl2ZSgpKSByZXR1cm47XG4gICAgICB0aGlzLmNtLnN0YXRlLmNvbXBsZXRpb25BY3RpdmUgPSBudWxsO1xuICAgICAgdGhpcy50aWNrID0gbnVsbDtcbiAgICAgIHRoaXMuY20ub2ZmKFwiY3Vyc29yQWN0aXZpdHlcIiwgdGhpcy5hY3Rpdml0eUZ1bmMpO1xuXG4gICAgICBpZiAodGhpcy53aWRnZXQgJiYgdGhpcy5kYXRhKSBDb2RlTWlycm9yLnNpZ25hbCh0aGlzLmRhdGEsIFwiY2xvc2VcIik7XG4gICAgICBpZiAodGhpcy53aWRnZXQpIHRoaXMud2lkZ2V0LmNsb3NlKCk7XG4gICAgICBDb2RlTWlycm9yLnNpZ25hbCh0aGlzLmNtLCBcImVuZENvbXBsZXRpb25cIiwgdGhpcy5jbSk7XG4gICAgfSxcblxuICAgIGFjdGl2ZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5jbS5zdGF0ZS5jb21wbGV0aW9uQWN0aXZlID09IHRoaXM7XG4gICAgfSxcblxuICAgIHBpY2s6IGZ1bmN0aW9uKGRhdGEsIGkpIHtcbiAgICAgIHZhciBjb21wbGV0aW9uID0gZGF0YS5saXN0W2ldO1xuICAgICAgaWYgKGNvbXBsZXRpb24uaGludCkgY29tcGxldGlvbi5oaW50KHRoaXMuY20sIGRhdGEsIGNvbXBsZXRpb24pO1xuICAgICAgZWxzZSB0aGlzLmNtLnJlcGxhY2VSYW5nZShnZXRUZXh0KGNvbXBsZXRpb24pLCBjb21wbGV0aW9uLmZyb20gfHwgZGF0YS5mcm9tLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uLnRvIHx8IGRhdGEudG8sIFwiY29tcGxldGVcIik7XG4gICAgICBDb2RlTWlycm9yLnNpZ25hbChkYXRhLCBcInBpY2tcIiwgY29tcGxldGlvbik7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfSxcblxuICAgIGN1cnNvckFjdGl2aXR5OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmRlYm91bmNlKSB7XG4gICAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuZGVib3VuY2UpO1xuICAgICAgICB0aGlzLmRlYm91bmNlID0gMDtcbiAgICAgIH1cblxuICAgICAgdmFyIHBvcyA9IHRoaXMuY20uZ2V0Q3Vyc29yKCksIGxpbmUgPSB0aGlzLmNtLmdldExpbmUocG9zLmxpbmUpO1xuICAgICAgaWYgKHBvcy5saW5lICE9IHRoaXMuc3RhcnRQb3MubGluZSB8fCBsaW5lLmxlbmd0aCAtIHBvcy5jaCAhPSB0aGlzLnN0YXJ0TGVuIC0gdGhpcy5zdGFydFBvcy5jaCB8fFxuICAgICAgICAgI
23459HBvcy5jaCA8IHRoaXMuc3RhcnRQb3MuY2ggfHwgdGhpcy5jbS5zb21ldGhpbmdTZWxlY3RlZCgpIHx8XG4gICAgICAgICAgKHBvcy5jaCAmJiB0aGlzLm9wdGlvbnMuY2xvc2VDaGFyYWN0ZXJzLnRlc3QobGluZS5jaGFyQXQocG9zLmNoIC0gMSkpKSkge1xuICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgIHRoaXMuZGVib3VuY2UgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24oKSB7c2VsZi51cGRhdGUoKTt9KTtcbiAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB0aGlzLndpZGdldC5kaXNhYmxlKCk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIHVwZGF0ZTogZnVuY3Rpb24oZmlyc3QpIHtcbiAgICAgIGlmICh0aGlzLnRpY2sgPT0gbnVsbCkgcmV0dXJuO1xuICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuaGludC5hc3luYykge1xuICAgICAgICB0aGlzLmZpbmlzaFVwZGF0ZSh0aGlzLm9wdGlvbnMuaGludCh0aGlzLmNtLCB0aGlzLm9wdGlvbnMpLCBmaXJzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbXlUaWNrID0gKyt0aGlzLnRpY2ssIHNlbGYgPSB0aGlzO1xuICAgICAgICB0aGlzLm9wdGlvbnMuaGludCh0aGlzLmNtLCBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgaWYgKHNlbGYudGljayA9PSBteVRpY2spIHNlbGYuZmluaXNoVXBkYXRlKGRhdGEsIGZpcnN0KTtcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgZmluaXNoVXBkYXRlOiBmdW5jdGlvbihkYXRhLCBmaXJzdCkge1xuICAgICAgaWYgKHRoaXMuZGF0YSkgQ29kZU1pcnJvci5zaWduYWwodGhpcy5kYXRhLCBcInVwZGF0ZVwiKTtcbiAgICAgIGlmIChkYXRhICYmIHRoaXMuZGF0YSAmJiBDb2RlTWlycm9yLmNtcFBvcyhkYXRhLmZyb20sIHRoaXMuZGF0YS5mcm9tKSkgZGF0YSA9IG51bGw7XG4gICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuXG4gICAgICB2Y
23459XIgcGlja2VkID0gKHRoaXMud2lkZ2V0ICYmIHRoaXMud2lkZ2V0LnBpY2tlZCkgfHwgKGZpcnN0ICYmIHRoaXMub3B0aW9ucy5jb21wbGV0ZVNpbmdsZSk7XG4gICAgICBpZiAodGhpcy53aWRnZXQpIHRoaXMud2lkZ2V0LmNsb3NlKCk7XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLmxpc3QubGVuZ3RoKSB7XG4gICAgICAgIGlmIChwaWNrZWQgJiYgZGF0YS5saXN0Lmxlbmd0aCA9PSAxKSB7XG4gICAgICAgICAgdGhpcy5waWNrKGRhdGEsIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMud2lkZ2V0ID0gbmV3IFdpZGdldCh0aGlzLCBkYXRhKTtcbiAgICAgICAgICBDb2RlTWlycm9yLnNpZ25hbChkYXRhLCBcInNob3duXCIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIHBhcnNlT3B0aW9ucyhjbSwgcG9zLCBvcHRpb25zKSB7XG4gICAgdmFyIGVkaXRvciA9IGNtLm9wdGlvbnMuaGludE9wdGlvbnM7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIGZvciAodmFyIHByb3AgaW4gZGVmYXVsdE9wdGlvbnMpIG91dFtwcm9wXSA9IGRlZmF1bHRPcHRpb25zW3Byb3BdO1xuICAgIGlmIChlZGl0b3IpIGZvciAodmFyIHByb3AgaW4gZWRpdG9yKVxuICAgICAgaWYgKGVkaXRvcltwcm9wXSAhPT0gdW5kZWZpbmVkKSBvdXRbcHJvcF0gPSBlZGl0b3JbcHJvcF07XG4gICAgaWYgKG9wdGlvbnMpIGZvciAodmFyIHByb3AgaW4gb3B0aW9ucylcbiAgICAgIGlmIChvcHRpb25zW3Byb3BdICE9PSB1bmRlZmluZWQpIG91dFtwcm9wXSA9IG9wdGlvbnNbcHJvcF07XG4gICAgaWYgKG91dC5oaW50LnJlc29sdmUpIG91dC5oaW50ID0gb3V0LmhpbnQucmVzb2x2ZShjbSwgcG9zKVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUZXh0KGNvbXBsZXRpb24pIHtcbiAgICBpZiAodHlwZW9mIGNvbXBsZXRpb24gPT0gXCJzdHJpbmdcIikgcmV0dXJuIGNvbXBsZXRpb247XG4gICAgZWxzZSByZXR1cm4gY29tcGxldGlvbi50ZXh0O1xuICB9XG5cbiAgZnVuY3Rpb24gYnVpbGRLZXlNYXAoY29tcGxldGlvbiwgaGFuZGxlKSB7XG4gICAgdmFyIGJhc2VNYXAgPSB7XG4gICAgICBVcDogZnVuY3Rpb24oKSB7aGFuZGxlLm1vdmVGb2N1cygtMSk7fSxcbiAgICAgIERvd246IGZ1bmN0aW9uKCkge2hhbmRsZS5tb3ZlRm9jdXMoMSk7fSxcbiAgICAgIFBhZ2VVcDogZnVuY3Rpb24oKSB7aGFuZGxlLm1vdmVGb2N1cygtaGFuZGxlLm1lbnVTaXplKCkgKyAxLCB0cnVlKTt9LFxuICAgICAgUGFnZURvd246IGZ1bmN0aW9uKCkge2hhbmRsZS5tb3ZlRm9jdXMoaGFuZGxlLm1lbnVTaXplKCkgLSAxLCB0cnVlKTt9LFxuICAgICAgSG9tZTogZnVuY3Rpb24oKSB7aGFuZGxlLnNldEZvY3VzKDApO30sXG4gICAgICBFbmQ6IGZ1bmN0aW9uKCkge2hhbmRsZS5zZXRGb2N1cyhoYW5kbGUubGVuZ3RoIC0gMSk7fSxcbiAgICAgIEVudGVyOiBoYW5kbGUucGljayxcbiAgICAgIFRhYjogaGFuZGxlLnBpY2ssXG4gICAgICBFc2M6IGhhbmRsZS5jbG9zZVxuICAgIH07XG4gICAgdmFyIGN1c3RvbSA9IGNvbXBsZXRpb24ub3B0aW9ucy5jdXN0b21LZXlzO1xuICAgIHZhciBvdXJNYXAgPSBjdXN0b20gPyB7fSA6IGJhc2VNYXA7XG4gICAgZnVuY3Rpb24gYWRkQmluZGluZyhrZXksIHZhbCkge1xuICAgICAgdmFyIGJvdW5kO1xuICAgICAgaWYgKHR5cGVvZiB2YWwgIT0gXCJzdHJpbmdcIilcbiAgICAgICAgYm91bmQgPSBmdW5jdGlvbihjbSkgeyByZXR1cm4gdmFsKGNtLCBoYW5kbGUpOyB9O1xuICAgICAgLy8gVGhpcyBtZWNoYW5pc20gaXMgZGVwcmVjYXRlZFxuICAgICAgZWxzZSBpZiAoYmFzZU1hcC5oYXNPd25Qcm9wZXJ0eSh2YWwpKVxuICAgICAgICBib3VuZCA9IGJhc2VNYXBbdmFsXTtcbiAgICAgIGVsc2VcbiAgICAgICAgYm91bmQgPSB2YWw7XG4gICAgICBvdXJNYXBba2V5XSA9IGJvdW5kO1xuICAgIH1cbiAgICBpZiAoY3VzdG9tKVxuICAgICAgZm9yICh2YXIga2V5IGluIGN1c3RvbSkgaWYgKGN1c3RvbS5oYXNPd25Qcm9wZXJ0eShrZXkpKVxuICAgICAgICBhZGRCaW5kaW5nKGtleSwgY3VzdG9tW2tleV0pO1xuICAgIHZhciBleHRyYSA9IGNvbXBsZXRpb24ub3B0aW9ucy5leHRyYUtleXM7XG4gICAgaWYgKGV4dHJhKVxuICAgICAgZm9yICh2YXIga2V5IGluIGV4dHJhKSBpZiAoZXh0cmEuaGFzT3duUHJvcGVydHkoa2V5KSlcbiAgICAgICAgYWRkQmluZGluZyhrZXksIGV4dHJhW2tleV0pO1xuICAgIHJldHVybiBvdXJNYXA7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRIaW50RWxlbWVudChoaW50c0VsZW1lbnQsIGVsKSB7XG4gICAgd2hpbGUgKGVsICYmIGVsICE9IGhpbnRzRWxlbWVudCkge1xuICAgICAgaWYgKGVsLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT09IFwiTElcIiAmJiBlbC5wYXJlbnROb2RlID09IGhpbnRzRWxlbWVudCkgcmV0dXJuIGVsO1xuICAgICAgZWwgPSBlbC5wYXJlbnROb2RlO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIFdpZGdldChjb21wbGV0aW9uLCBkYXRhKSB7XG4gICAgdGhpcy5jb21wbGV0aW9uID0gY29tcGxldGlvbjtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIHRoaXMucGlja2VkID0gZmFsc2U7XG4gICAgdmFyIHdpZGdldCA9IHRoaXMsIGNtID0gY29tcGxldGlvbi5jbTtcblxuICAgIHZhciBoaW50cyA9IHRoaXMuaGludHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwidWxcIik7XG4gICAgaGludHMuY2xhc3NOYW1lID0gXCJDb2RlTWlycm9yLWhpbnRzXCI7XG4gICAgdGhpcy5zZWxlY3RlZEhpbnQgPSBkYXRhLnNlbGVjdGVkSGludCB8fCAwO1xuXG4gICAgdmFyIGNvbXBsZXRpb25zID0gZGF0YS5saXN0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29tcGxldGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBlbHQgPSBoaW50cy5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwibGlcIikpLCBjdXIgPSBjb21wbGV0aW9uc1tpXTtcbiAgICAgIHZhciBjbGFzc05hbWUgPSBISU5UX0VMRU1FTlRfQ0xBU1MgKyAoaSAhPSB0aGlzLnNlbGVjdGVkSGludCA/IFwiXCIgOiBcIiBcIiArIEFDVElWRV9ISU5UX0VMRU1FTlRfQ0xBU1MpO1xuICAgICAgaWYgKGN1ci5jbGFzc05hbWUgIT0gbnVsbCkgY2xhc3NOYW1lID0gY3VyLmNsYXNzTmFtZSArIFwiIFwiICsgY2xhc3NOYW1lO1xuICAgICAgZWx0LmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgICAgIGlmIChjdXIucmVuZGVyKSBjdXIucmVuZGVyKGVsdCwgZGF0YSwgY3VyKTtcbiAgICAgIGVsc2UgZWx0LmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGN1ci5kaXNwbGF5VGV4dCB8fCBnZXRUZXh0KGN1cikpKTtcbiAgICAgIGVsdC5oaW50SWQgPSBpO1xuICAgIH1cblxuICAgI
23459HZhciBwb3MgPSBjbS5jdXJzb3JDb29yZHMoY29tcGxldGlvbi5vcHRpb25zLmFsaWduV2l0aFdvcmQgPyBkYXRhLmZyb20gOiBudWxsKTtcbiAgICB2YXIgbGVmdCA9IHBvcy5sZWZ0LCB0b3AgPSBwb3MuYm90dG9tLCBiZWxvdyA9IHRydWU7XG4gICAgaGludHMuc3R5bGUubGVmdCA9IGxlZnQgKyBcInB4XCI7XG4gICAgaGludHMuc3R5bGUudG9wID0gdG9wICsgXCJweFwiO1xuICAgIC8vIElmIHdlJ3JlIGF0IHRoZSBlZGdlIG9mIHRoZSBzY3JlZW4sIHRoZW4gd2Ugd2FudCB0aGUgbWVudSB0byBhcHBlYXIgb24gdGhlIGxlZnQgb2YgdGhlIGN1cnNvci5cbiAgICB2YXIgd2luVyA9IHdpbmRvdy5pbm5lcldpZHRoIHx8IE1hdGgubWF4KGRvY3VtZW50LmJvZHkub2Zmc2V0V2lkdGgsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5vZmZzZXRXaWR0aCk7XG4gICAgdmFyIHdpbkggPSB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgTWF0aC5tYXgoZG9jdW1lbnQuYm9keS5vZmZzZXRIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5vZmZzZXRIZWlnaHQpO1xuICAgIChjb21wbGV0aW9uLm9wdGlvbnMuY29udGFpbmVyIHx8IGRvY3VtZW50LmJvZHkpLmFwcGVuZENoaWxkKGhpbnRzKTtcbiAgICB2YXIgYm94ID0gaGludHMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksIG92ZXJsYXBZID0gYm94LmJvdHRvbSAtIHdpbkg7XG4gICAgaWYgKG92ZXJsYXBZID4gMCkge1xuICAgICAgdmFyIGhlaWdodCA9IGJveC5ib3R0b20gLSBib3gudG9wLCBjdXJUb3AgPSBwb3MudG9wIC0gKHBvcy5ib3R0b20gLSBib3gudG9wKTtcbiAgICAgIGlmIChjdXJUb3AgLSBoZWlnaHQgPiAwKSB7IC8vIEZpdHMgYWJvdmUgY3Vyc29yXG4gICAgICAgIGhpbnRzLnN0eWxlLnRvcCA9ICh0b3AgPSBwb3MudG9wIC0gaGVpZ2h0KSArIFwicHhcIjtcbiAgICAgICAgYmVsb3cgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaGVpZ2h0ID4gd2luSCkge1xuICAgICAgICBoaW50cy5zdHlsZS5oZWlnaHQgPSAod2luSCAtIDUpICsgXCJweFwiO1xuICAgICAgICBoaW50cy5zdHlsZS50b3AgPSAodG9wID0gcG9zLmJvdHRvbSAtIGJveC50b3ApICsgXCJweFwiO1xuICAgICAgICB2Y
23459XIgY3Vyc29yID0gY20uZ2V0Q3Vyc29yKCk7XG4gICAgICAgIGlmIChkYXRhLmZyb20uY2ggIT0gY3Vyc29yLmNoKSB7XG4gICAgICAgICAgcG9zID0gY20uY3Vyc29yQ29vcmRzKGN1cnNvcik7XG4gICAgICAgICAgaGludHMuc3R5bGUubGVmdCA9IChsZWZ0ID0gcG9zLmxlZnQpICsgXCJweFwiO1xuICAgICAgICAgIGJveCA9IGhpbnRzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBvdmVybGFwWCA9IGJveC5yaWdodCAtIHdpblc7XG4gICAgaWYgKG92ZXJsYXBYID4gMCkge1xuICAgICAgaWYgKGJveC5yaWdodCAtIGJveC5sZWZ0ID4gd2luVykge1xuICAgICAgICBoaW50cy5zdHlsZS53aWR0aCA9ICh3aW5XIC0gNSkgKyBcInB4XCI7XG4gICAgICAgIG92ZXJsYXBYIC09IChib3gucmlnaHQgLSBib3gubGVmdCkgLSB3aW5XO1xuICAgICAgfVxuICAgICAgaGludHMuc3R5bGUubGVmdCA9IChsZWZ0ID0gcG9zLmxlZnQgLSBvdmVybGFwWCkgKyBcInB4XCI7XG4gICAgfVxuXG4gICAgY20uYWRkS2V5TWFwKHRoaXMua2V5TWFwID0gYnVpbGRLZXlNYXAoY29tcGxldGlvbiwge1xuICAgICAgbW92ZUZvY3VzOiBmdW5jdGlvbihuLCBhdm9pZFdyYXApIHsgd2lkZ2V0LmNoYW5nZUFjdGl2ZSh3aWRnZXQuc2VsZWN0ZWRIaW50ICsgbiwgYXZvaWRXcmFwKTsgfSxcbiAgICAgIHNldEZvY3VzOiBmdW5jdGlvbihuKSB7IHdpZGdldC5jaGFuZ2VBY3RpdmUobik7IH0sXG4gICAgICBtZW51U2l6ZTogZnVuY3Rpb24oKSB7IHJldHVybiB3aWRnZXQuc2NyZWVuQW1vdW50KCk7IH0sXG4gICAgICBsZW5ndGg6IGNvbXBsZXRpb25zLmxlbmd0aCxcbiAgICAgIGNsb3NlOiBmdW5jdGlvbigpIHsgY29tcGxldGlvbi5jbG9zZSgpOyB9LFxuICAgICAgcGljazogZnVuY3Rpb24oKSB7IHdpZGdldC5waWNrKCk7IH0sXG4gICAgICBkYXRhOiBkYXRhXG4gICAgfSkpO1xuXG4gICAgaWYgKGNvbXBsZXRpb24ub3B0aW9ucy5jbG9zZU9uVW5mb2N1cykge1xuICAgICAgdmFyIGNsb3NpbmdPbkJsdXI7XG4gICAgICBjbS5vbihcImJsdXJcIiwgdGhpcy5vbkJsdXIgPSBmdW5jdGlvbigpIHsgY2xvc2luZ09uQmx1ciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNvbXBsZXRpb24uY2xvc2UoKTsgfSwgMTAwKTsgfSk7XG4gICAgICBjbS5vbihcImZvY3VzXCIsIHRoaXMub25Gb2N1cyA9IGZ1bmN0aW9uKCkgeyBjbGVhclRpbWVvdXQoY2xvc2luZ09uQmx1cik7IH0pO1xuICAgIH1cblxuICAgIHZhciBzdGFydFNjcm9sbCA9IGNtLmdldFNjcm9sbEluZm8oKTtcbiAgICBjbS5vbihcInNjcm9sbFwiLCB0aGlzLm9uU2Nyb2xsID0gZnVuY3Rpb24oKSB7XG4gICAgICB2Y
23459XIgY3VyU2Nyb2xsID0gY20uZ2V0U2Nyb2xsSW5mbygpLCBlZGl0b3IgPSBjbS5nZXRXcmFwcGVyRWxlbWVudCgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgdmFyIG5ld1RvcCA9IHRvcCArIHN0YXJ0U2Nyb2xsLnRvcCAtIGN1clNjcm9sbC50b3A7XG4gICAgICB2YXIgcG9pbnQgPSBuZXdUb3AgLSAod2luZG93LnBhZ2VZT2Zmc2V0IHx8IChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgfHwgZG9jdW1lbnQuYm9keSkuc2Nyb2xsVG9wKTtcbiAgICAgIGlmICghYmVsb3cpIHBvaW50ICs9IGhpbnRzLm9mZnNldEhlaWdodDtcbiAgICAgIGlmIChwb2ludCA8PSBlZGl0b3IudG9wIHx8IHBvaW50ID49IGVkaXRvci5ib3R0b20pIHJldHVybiBjb21wbGV0aW9uLmNsb3NlKCk7XG4gICAgICBoaW50cy5zdHlsZS50b3AgPSBuZXdUb3AgKyBcInB4XCI7XG4gICAgICBoaW50cy5zdHlsZS5sZWZ0ID0gKGxlZnQgKyBzdGFydFNjcm9sbC5sZWZ0IC0gY3VyU2Nyb2xsLmxlZnQpICsgXCJweFwiO1xuICAgIH0pO1xuXG4gICAgQ29kZU1pcnJvci5vbihoaW50cywgXCJkYmxjbGlja1wiLCBmdW5jdGlvbihlKSB7XG4gICAgICB2YXIgdCA9IGdldEhpbnRFbGVtZW50KGhpbnRzLCBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnQpO1xuICAgICAgaWYgKHQgJiYgdC5oaW50SWQgIT0gbnVsbCkge3dpZGdldC5jaGFuZ2VBY3RpdmUodC5oaW50SWQpOyB3aWRnZXQucGljaygpO31cbiAgICB9KTtcblxuICAgIENvZGVNaXJyb3Iub24oaGludHMsIFwiY2xpY2tcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIHQgPSBnZXRIaW50RWxlbWVudChoaW50cywgZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50KTtcbiAgICAgIGlmICh0ICYmIHQuaGludElkICE9IG51bGwpIHtcbiAgICAgICAgd2lkZ2V0LmNoYW5nZUFjdGl2ZSh0LmhpbnRJZCk7XG4gICAgICAgIGlmIChjb21wbGV0aW9uLm9wdGlvbnMuY29tcGxldGVPblNpbmdsZUNsaWNrKSB3aWRnZXQucGljaygpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgQ29kZU1pcnJvci5vbihoaW50cywgXCJtb3VzZWRvd25cIiwgZnVuY3Rpb24oKSB7XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7Y20uZm9jdXMoKTt9LCAyMCk7XG4gICAgfSk7XG5cbiAgICBDb2RlTWlycm9yLnNpZ25hbChkYXRhLCBcInNlbGVjdFwiLCBjb21wbGV0aW9uc1swXSwgaGludHMuZmlyc3RDaGlsZCk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBXaWRnZXQucHJvdG90eXBlID0ge1xuICAgIGNsb3NlOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmNvbXBsZXRpb24ud2lkZ2V0ICE9IHRoaXMpIHJldHVybjtcbiAgICAgIHRoaXMuY29tcGxldGlvbi53aWRnZXQgPSBudWxsO1xuICAgICAgdGhpcy5oaW50cy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuaGludHMpO1xuICAgICAgdGhpcy5jb21wbGV0aW9uLmNtLnJlbW92ZUtleU1hcCh0aGlzLmtleU1hcCk7XG5cbiAgICAgIHZhciBjbSA9IHRoaXMuY29tcGxldGlvbi5jbTtcbiAgICAgIGlmICh0aGlzLmNvbXBsZXRpb24ub3B0aW9ucy5jbG9zZU9uVW5mb2N1cykge1xuICAgICAgICBjbS5vZmYoXCJibHVyXCIsIHRoaXMub25CbHVyKTtcbiAgICAgICAgY20ub2ZmKFwiZm9jdXNcIiwgdGhpcy5vbkZvY3VzKTtcbiAgICAgIH1cbiAgICAgIGNtLm9mZihcInNjcm9sbFwiLCB0aGlzLm9uU2Nyb2xsKTtcbiAgICB9LFxuXG4gICAgZGlzYWJsZTogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmNvbXBsZXRpb24uY20ucmVtb3ZlS2V5TWFwKHRoaXMua2V5TWFwKTtcbiAgICAgIHZhciB3aWRnZXQgPSB0aGlzO1xuICAgICAgdGhpcy5rZXlNYXAgPSB7RW50ZXI6IGZ1bmN0aW9uKCkgeyB3aWRnZXQucGlja2VkID0gdHJ1ZTsgfX07XG4gICAgICB0aGlzLmNvbXBsZXRpb24uY20uYWRkS2V5TWFwKHRoaXMua2V5TWFwKTtcbiAgICB9LFxuXG4gICAgcGljazogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmNvbXBsZXRpb24ucGljayh0aGlzLmRhdGEsIHRoaXMuc2VsZWN0ZWRIaW50KTtcbiAgICB9LFxuXG4gICAgY2hhbmdlQWN0aXZlOiBmdW5jdGlvbihpLCBhdm9pZFdyYXApIHtcbiAgICAgIGlmIChpID49IHRoaXMuZGF0YS5saXN0Lmxlbmd0aClcbiAgICAgICAgaSA9IGF2b2lkV3JhcCA/IHRoaXMuZGF0YS5saXN0Lmxlbmd0aCAtIDEgOiAwO1xuICAgICAgZWxzZSBpZiAoaSA8IDApXG4gICAgICAgIGkgPSBhdm9pZFdyYXAgPyAwICA6IHRoaXMuZGF0YS5saXN0Lmxlbmd0aCAtIDE7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZEhpbnQgPT0gaSkgcmV0dXJuO1xuICAgICAgdmFyIG5vZGUgPSB0aGlzLmhpbnRzLmNoaWxkTm9kZXNbdGhpcy5zZWxlY3RlZEhpbnRdO1xuICAgICAgbm9kZS5jbGFzc05hbWUgPSBub2RlLmNsYXNzTmFtZS5yZXBsYWNlKFwiIFwiICsgQUNUSVZFX0hJTlRfRUxFTUVOVF9DTEFTUywgXCJcIik7XG4gICAgICBub2RlID0gdGhpcy5oaW50cy5jaGlsZE5vZGVzW3RoaXMuc2VsZWN0ZWRIaW50ID0gaV07XG4gICAgICBub2RlLmNsYXNzTmFtZSArPSBcIiBcIiArIEFDVElWRV9ISU5UX0VMRU1FTlRfQ0xBU1M7XG4gICAgICBpZiAobm9kZS5vZmZzZXRUb3AgPCB0aGlzLmhpbnRzLnNjcm9sbFRvcClcbiAgICAgICAgdGhpcy5oaW50cy5zY3JvbGxUb3AgPSBub2RlLm9mZnNldFRvcCAtIDM7XG4gICAgICBlbHNlIGlmIChub2RlLm9mZnNldFRvcCArIG5vZGUub2Zmc2V0SGVpZ2h0ID4gdGhpcy5oaW50cy5zY3JvbGxUb3AgKyB0aGlzLmhpbnRzLmNsaWVudEhlaWdodClcbiAgICAgICAgdGhpcy5oaW50cy5zY3JvbGxUb3AgPSBub2RlLm9mZnNldFRvcCArIG5vZGUub2Zmc2V0SGVpZ2h0IC0gdGhpcy5oaW50cy5jbGllbnRIZWlnaHQgKyAzO1xuICAgICAgQ29kZU1pcnJvci5zaWduYWwodGhpcy5kYXRhLCBcInNlbGVjdFwiLCB0aGlzLmRhdGEubGlzdFt0aGlzLnNlbGVjdGVkSGludF0sIG5vZGUpO1xuICAgIH0sXG5cbiAgICBzY3JlZW5BbW91bnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IodGhpcy5oaW50cy5jbGllbnRIZWlnaHQgLyB0aGlzLmhpbnRzLmZpcnN0Q2hpbGQub2Zmc2V0SGVpZ2h0KSB8fCAxO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBhcHBsaWNhYmxlSGVscGVycyhjbSwgaGVscGVycykge1xuICAgIGlmICghY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkgcmV0dXJuIGhlbHBlcnNcbiAgICB2YXIgcmVzdWx0ID0gW11cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhlbHBlcnMubGVuZ3RoOyBpKyspXG4gICAgICBpZiAoaGVscGVyc1tpXS5zdXBwb3J0c1NlbGVjdGlvbikgcmVzdWx0LnB1c2goaGVscGVyc1tpXSlcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBmdW5jdGlvbiByZXNvbHZlQXV0b0hpbnRzKGNtLCBwb3MpIHtcbiAgICB2YXIgaGVscGVycyA9IGNtLmdldEhlbHBlcnMocG9zLCBcImhpbnRcIiksIHdvcmRzXG4gICAgaWYgKGhlbHBlcnMubGVuZ3RoKSB7XG4gICAgICB2Y
23459XIgYXN5bmMgPSBmYWxzZSwgcmVzb2x2ZWRcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGVscGVycy5sZW5ndGg7IGkrKykgaWYgKGhlbHBlcnNbaV0uYXN5bmMpIGFzeW5jID0gdHJ1ZVxuICAgICAgaWYgKGFzeW5jKSB7XG4gICAgICAgIHJlc29sdmVkID0gZnVuY3Rpb24oY20sIGNhbGxiYWNrLCBvcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGFwcCA9IGFwcGxpY2FibGVIZWxwZXJzKGNtLCBoZWxwZXJzKVxuICAgICAgICAgIGZ1bmN0aW9uIHJ1bihpLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChpID09IGFwcC5sZW5ndGgpIHJldHVybiBjYWxsYmFjayhudWxsKVxuICAgICAgICAgICAgdmFyIGhlbHBlciA9IGFwcFtpXVxuICAgICAgICAgICAgaWYgKGhlbHBlci5hc3luYykge1xuICAgICAgICAgICAgICBoZWxwZXIoY20sIGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIGNhbGxiYWNrKHJlc3VsdClcbiAgICAgICAgICAgICAgICBlbHNlIHJ1bihpICsgMSlcbiAgICAgICAgICAgICAgfSwgb3B0aW9ucylcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHZhciByZXN1bHQgPSBoZWxwZXIoY20sIG9wdGlvbnMpXG4gICAgICAgICAgICAgIGlmIChyZXN1bHQpIGNhbGxiYWNrKHJlc3VsdClcbiAgICAgICAgICAgICAgZWxzZSBydW4oaSArIDEpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJ1bigwKVxuICAgICAgICB9XG4gICAgICAgIHJlc29sdmVkLmFzeW5jID0gdHJ1ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZWQgPSBmdW5jdGlvbihjbSwgb3B0aW9ucykge1xuICAgICAgICAgIHZhciBhcHAgPSBhcHBsaWNhYmxlSGVscGVycyhjbSwgaGVscGVycylcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFwcC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGN1ciA9IGFwcFtpXShjbSwgb3B0aW9ucylcbiAgICAgICAgICAgIGlmIChjdXIgJiYgY3VyLmxpc3QubGVuZ3RoKSByZXR1cm4gY3VyXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXNvbHZlZC5zdXBwb3J0c1NlbGVjdGlvbiA9IHRydWVcbiAgICAgIHJldHVybiByZXNvbHZlZFxuICAgIH0gZWxzZSBpZiAod29yZHMgPSBjbS5nZXRIZWxwZXIoY20uZ2V0Q3Vyc29yKCksIFwiaGludFdvcmRzXCIpKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY20pIHsgcmV0dXJuIENvZGVNaXJyb3IuaGludC5mcm9tTGlzdChjbSwge3dvcmRzOiB3b3Jkc30pIH1cbiAgICB9IGVsc2UgaWYgKENvZGVNaXJyb3IuaGludC5hbnl3b3JkKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY20sIG9wdGlvbnMpIHsgcmV0dXJuIENvZGVNaXJyb3IuaGludC5hbnl3b3JkKGNtLCBvcHRpb25zKSB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHt9XG4gICAgfVxuICB9XG5cbiAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImhpbnRcIiwgXCJhdXRvXCIsIHtcbiAgICByZXNvbHZlOiByZXNvbHZlQXV0b0hpbnRzXG4gIH0pO1xuXG4gIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJoaW50XCIsIFwiZnJvbUxpc3RcIiwgZnVuY3Rpb24oY20sIG9wdGlvbnMpIHtcbiAgICB2YXIgY3VyID0gY20uZ2V0Q3Vyc29yKCksIHRva2VuID0gY20uZ2V0VG9rZW5BdChjdXIpO1xuICAgIHZhciB0byA9IENvZGVNaXJyb3IuUG9zKGN1ci5saW5lLCB0b2tlbi5lbmQpO1xuICAgIGlmICh0b2tlbi5zdHJpbmcgJiYgL1xcdy8udGVzdCh0b2tlbi5zdHJpbmdbdG9rZW4uc3RyaW5nLmxlbmd0aCAtIDFdKSkge1xuICAgICAgdmFyIHRlcm0gPSB0b2tlbi5zdHJpbmcsIGZyb20gPSBDb2RlTWlycm9yLlBvcyhjdXIubGluZSwgdG9rZW4uc3RhcnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2Y
23459XIgdGVybSA9IFwiXCIsIGZyb20gPSB0bztcbiAgICB9XG4gICAgdmFyIGZvdW5kID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcHRpb25zLndvcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgd29yZCA9IG9wdGlvbnMud29yZHNbaV07XG4gICAgICBpZiAod29yZC5zbGljZSgwLCB0ZXJtLmxlbmd0aCkgPT0gdGVybSlcbiAgICAgICAgZm91bmQucHVzaCh3b3JkKTtcbiAgICB9XG5cbiAgICBpZiAoZm91bmQubGVuZ3RoKSByZXR1cm4ge2xpc3Q6IGZvdW5kLCBmcm9tOiBmcm9tLCB0bzogdG99O1xuICB9KTtcblxuICBDb2RlTWlycm9yLmNvbW1hbmRzLmF1dG9jb21wbGV0ZSA9IENvZGVNaXJyb3Iuc2hvd0hpbnQ7XG5cbiAgdmFyIGRlZmF1bHRPcHRpb25zID0ge1xuICAgIGhpbnQ6IENvZGVNaXJyb3IuaGludC5hdXRvLFxuICAgIGNvbXBsZXRlU2luZ2xlOiB0cnVlLFxuICAgIGFsaWduV2l0aFdvcmQ6IHRydWUsXG4gICAgY2xvc2VDaGFyYWN0ZXJzOiAvW1xccygpXFxbXFxde307Oj4sXS8sXG4gICAgY2xvc2VPblVuZm9jdXM6IHRydWUsXG4gICAgY29tcGxldGVPblNpbmdsZUNsaWNrOiBmYWxzZSxcbiAgICBjb250YWluZXI6IG51bGwsXG4gICAgY3VzdG9tS2V5czogbnVsbCxcbiAgICBleHRyYUtleXM6IG51bGxcbiAgfTtcblxuICBDb2RlTWlycm9yLmRlZmluZU9wdGlvbihcImhpbnRPcHRpb25zXCIsIG51bGwpO1xufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbi8vIERlZmluZSBzZWFyY2ggY29tbWFuZHMuIERlcGVuZHMgb24gZGlhbG9nLmpzIG9yIGFub3RoZXJcbi8vIGltcGxlbWVudGF0aW9uIG9mIHRoZSBvcGVuRGlhbG9nIG1ldGhvZC5cblxuLy8gUmVwbGFjZSB3b3JrcyBhIGxpdHRsZSBvZGRseSAtLSBpdCB3aWxsIGRvIHRoZSByZXBsYWNlIG9uIHRoZSBuZXh0XG4vLyBDdHJsLUcgKG9yIHdoYXRldmVyIGlzIGJvdW5kIHRvIGZpbmROZXh0KSBwcmVzcy4gWW91IHByZXZlbnQgYVxuLy8gcmVwbGFjZSBieSBtYWtpbmcgc3VyZSB0aGUgbWF0Y2ggaXMgbm8gbG9uZ2VyIHNlbGVjdGVkIHdoZW4gaGl0dGluZ1xuLy8gQ3RybC1HLlxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpLCByZXF1aXJlKFwiLi9zZWFyY2hjdXJzb3JcIiksIHJlcXVpcmUoXCIuLi9kaWFsb2cvZGlhbG9nXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIsIFwiLi9zZWFyY2hjdXJzb3JcIiwgXCIuLi9kaWFsb2cvZGlhbG9nXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICBmdW5jdGlvbiBzZWFyY2hPdmVybGF5KHF1ZXJ5LCBjYXNlSW5zZW5zaXRpdmUpIHtcbiAgICBpZiAodHlwZW9mIHF1ZXJ5ID09IFwic3RyaW5nXCIpXG4gICAgICBxdWVyeSA9IG5ldyBSZWdFeHAocXVlcnkucmVwbGFjZSgvW1xcLVxcW1xcXVxcL1xce1xcfVxcKFxcKVxcKlxcK1xcP1xcLlxcXFxcXF5cXCRcXHxdL2csIFwiXFxcXCQmXCIpLCBjYXNlSW5zZW5zaXRpdmUgPyBcImdpXCIgOiBcImdcIik7XG4gICAgZWxzZSBpZiAoIXF1ZXJ5Lmdsb2JhbClcbiAgICAgIHF1ZXJ5ID0gbmV3IFJlZ0V4cChxdWVyeS5zb3VyY2UsIHF1ZXJ5Lmlnbm9yZUNhc2UgPyBcImdpXCIgOiBcImdcIik7XG5cbiAgICByZXR1cm4ge3Rva2VuOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHF1ZXJ5Lmxhc3RJbmRleCA9IHN0cmVhbS5wb3M7XG4gICAgICB2Y
23459XIgbWF0Y2ggPSBxdWVyeS5leGVjKHN0cmVhbS5zdHJpbmcpO1xuICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmluZGV4ID09IHN0cmVhbS5wb3MpIHtcbiAgICAgICAgc3RyZWFtLnBvcyArPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgIHJldHVybiBcInNlYXJjaGluZ1wiO1xuICAgICAgfSBlbHNlIGlmIChtYXRjaCkge1xuICAgICAgICBzdHJlYW0ucG9zID0gbWF0Y2guaW5kZXg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHJlYW0uc2tpcFRvRW5kKCk7XG4gICAgICB9XG4gICAgfX07XG4gIH1cblxuICBmdW5jdGlvbiBTZWFyY2hTdGF0ZSgpIHtcbiAgICB0aGlzLnBvc0Zyb20gPSB0aGlzLnBvc1RvID0gdGhpcy5sYXN0UXVlcnkgPSB0aGlzLnF1ZXJ5ID0gbnVsbDtcbiAgICB0aGlzLm92ZXJsYXkgPSBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U2VhcmNoU3RhdGUoY20pIHtcbiAgICByZXR1cm4gY20uc3RhdGUuc2VhcmNoIHx8IChjbS5zdGF0ZS5zZWFyY2ggPSBuZXcgU2VhcmNoU3RhdGUoKSk7XG4gIH1cblxuICBmdW5jdGlvbiBxdWVyeUNhc2VJbnNlbnNpdGl2ZShxdWVyeSkge1xuICAgIHJldHVybiB0eXBlb2YgcXVlcnkgPT0gXCJzdHJpbmdcIiAmJiBxdWVyeSA9PSBxdWVyeS50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U2VhcmNoQ3Vyc29yKGNtLCBxdWVyeSwgcG9zKSB7XG4gICAgLy8gSGV1cmlzdGljOiBpZiB0aGUgcXVlcnkgc3RyaW5nIGlzIGFsbCBsb3dlcmNhc2UsIGRvIGEgY2FzZSBpbnNlbnNpdGl2ZSBzZWFyY2guXG4gICAgcmV0dXJuIGNtLmdldFNlYXJjaEN1cnNvcihxdWVyeSwgcG9zLCBxdWVyeUNhc2VJbnNlbnNpdGl2ZShxdWVyeSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcGVyc2lzdGVudERpYWxvZyhjbSwgdGV4dCwgZGVmbHQsIGYpIHtcbiAgICBjbS5vcGVuRGlhbG9nKHRleHQsIGYsIHtcbiAgICAgIHZhbHVlOiBkZWZsdCxcbiAgICAgIHNlbGVjdFZhbHVlT25PcGVuOiB0cnVlLFxuICAgICAgY2xvc2VPbkVudGVyOiBmYWxzZSxcbiAgICAgIG9uQ2xvc2U6IGZ1bmN0aW9uKCkgeyBjbGVhclNlYXJjaChjbSk7IH1cbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRpYWxvZyhjbSwgdGV4dCwgc2hvcnRUZXh0LCBkZWZsdCwgZikge1xuICAgIGlmIChjbS5vcGVuRGlhbG9nKSBjbS5vcGVuRGlhbG9nKHRleHQsIGYsIHt2YWx1ZTogZGVmbHQsIHNlbGVjdFZhbHVlT25PcGVuOiB0cnVlfSk7XG4gICAgZWxzZSBmKHByb21wdChzaG9ydFRleHQsIGRlZmx0KSk7XG4gIH1cblxuICBmdW5jdGlvbiBjb25maXJtRGlhbG9nKGNtLCB0ZXh0LCBzaG9ydFRleHQsIGZzKSB7XG4gICAgaWYgKGNtLm9wZW5Db25maXJtKSBjbS5vcGVuQ29uZmlybSh0ZXh0LCBmcyk7XG4gICAgZWxzZSBpZiAoY29uZmlybShzaG9ydFRleHQpKSBmc1swXSgpO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VTdHJpbmcoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXFxcKC4pL2csIGZ1bmN0aW9uKF8sIGNoKSB7XG4gICAgICBpZiAoY2ggPT0gXCJuXCIpIHJldHVybiBcIlxcblwiXG4gICAgICBpZiAoY2ggPT0gXCJyXCIpIHJldHVybiBcIlxcclwiXG4gICAgICByZXR1cm4gY2hcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VRdWVyeShxdWVyeSkge1xuICAgIHZhciBpc1JFID0gcXVlcnkubWF0Y2goL15cXC8oLiopXFwvKFthLXpdKikkLyk7XG4gICAgaWYgKGlzUkUpIHtcbiAgICAgIHRyeSB7IHF1ZXJ5ID0gbmV3IFJlZ0V4cChpc1JFWzFdLCBpc1JFWzJdLmluZGV4T2YoXCJpXCIpID09IC0xID8gXCJcIiA6IFwiaVwiKTsgfVxuICAgICAgY2F0Y2goZSkge30gLy8gTm90IGEgcmVndWxhciBleHByZXNzaW9uIGFmdGVyIGFsbCwgZG8gYSBzdHJpbmcgc2VhcmNoXG4gICAgfSBlbHNlIHtcbiAgICAgIHF1ZXJ5ID0gcGFyc2VTdHJpbmcocXVlcnkpXG4gICAgfVxuICAgIGlmICh0eXBlb2YgcXVlcnkgPT0gXCJzdHJpbmdcIiA/IHF1ZXJ5ID09IFwiXCIgOiBxdWVyeS50ZXN0KFwiXCIpKVxuICAgICAgcXVlcnkgPSAveF4vO1xuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIHZhciBxdWVyeURpYWxvZyA9XG4gICAgJ1NlYXJjaDogPGlucHV0IHR5cGU9XCJ0ZXh0XCIgc3R5bGU9XCJ3aWR0aDogMTBlbVwiIGNsYXNzPVwiQ29kZU1pcnJvci1zZWFyY2gtZmllbGRcIi8+IDxzcGFuIHN0eWxlPVwiY29sb3I6ICM4ODhcIiBjbGFzcz1cIkNvZGVNaXJyb3Itc2VhcmNoLWhpbnRcIj4oVXNlIC9yZS8gc3ludGF4IGZvciByZWdleHAgc2VhcmNoKTwvc3Bhbj4nO1xuXG4gIGZ1bmN0aW9uIHN0YXJ0U2VhcmNoKGNtLCBzdGF0ZSwgcXVlcnkpIHtcbiAgICBzdGF0ZS5xdWVyeVRleHQgPSBxdWVyeTtcbiAgICBzdGF0ZS5xdWVyeSA9IHBhcnNlUXVlcnkocXVlcnkpO1xuICAgIGNtLnJlbW92ZU92ZXJsYXkoc3RhdGUub3ZlcmxheSwgcXVlcnlDYXNlSW5zZW5zaXRpdmUoc3RhdGUucXVlcnkpKTtcbiAgICBzdGF0ZS5vdmVybGF5ID0gc2VhcmNoT3ZlcmxheShzdGF0ZS5xdWVyeSwgcXVlcnlDYXNlSW5zZW5zaXRpdmUoc3RhdGUucXVlcnkpKTtcbiAgICBjbS5hZGRPdmVybGF5KHN0YXRlLm92ZXJsYXkpO1xuICAgIGlmIChjbS5zaG93TWF0Y2hlc09uU2Nyb2xsYmFyKSB7XG4gICAgICBpZiAoc3RhdGUuYW5ub3RhdGUpIHsgc3RhdGUuYW5ub3RhdGUuY2xlYXIoKTsgc3RhdGUuYW5ub3RhdGUgPSBudWxsOyB9XG4gICAgICBzdGF0ZS5hbm5vdGF0ZSA9IGNtLnNob3dNYXRjaGVzT25TY3JvbGxiYXIoc3RhdGUucXVlcnksIHF1ZXJ5Q2FzZUluc2Vuc2l0aXZlKHN0YXRlLnF1ZXJ5KSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZG9TZWFyY2goY20sIHJldiwgcGVyc2lzdGVudCkge1xuICAgIHZhciBzdGF0ZSA9IGdldFNlYXJjaFN0YXRlKGNtKTtcbiAgICBpZiAoc3RhdGUucXVlcnkpIHJldHVybiBmaW5kTmV4dChjbSwgcmV2KTtcbiAgICB2YXIgcSA9IGNtLmdldFNlbGVjdGlvbigpIHx8IHN0YXRlLmxhc3RRdWVyeTtcbiAgICBpZiAocGVyc2lzdGVudCAmJiBjbS5vcGVuRGlhbG9nKSB7XG4gICAgICB2Y
23459XIgaGlkaW5nID0gbnVsbFxuICAgICAgcGVyc2lzdGVudERpYWxvZyhjbSwgcXVlcnlEaWFsb2csIHEsIGZ1bmN0aW9uKHF1ZXJ5LCBldmVudCkge1xuICAgICAgICBDb2RlTWlycm9yLmVfc3RvcChldmVudCk7XG4gICAgICAgIGlmICghcXVlcnkpIHJldHVybjtcbiAgICAgICAgaWYgKHF1ZXJ5ICE9IHN0YXRlLnF1ZXJ5VGV4dCkgc3RhcnRTZWFyY2goY20sIHN0YXRlLCBxdWVyeSk7XG4gICAgICAgIGlmIChoaWRpbmcpIGhpZGluZy5zdHlsZS5vcGFjaXR5ID0gMVxuICAgICAgICBmaW5kTmV4dChjbSwgZXZlbnQuc2hpZnRLZXksIGZ1bmN0aW9uKF8sIHRvKSB7XG4gICAgICAgICAgdmFyIGRpYWxvZ1xuICAgICAgICAgIGlmICh0by5saW5lIDwgMyAmJiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yICYmXG4gICAgICAgICAgICAgIChkaWFsb2cgPSBjbS5kaXNwbGF5LndyYXBwZXIucXVlcnlTZWxlY3RvcihcIi5Db2RlTWlycm9yLWRpYWxvZ1wiKSkgJiZcbiAgICAgICAgICAgICAgZGlhbG9nLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmJvdHRvbSAtIDQgPiBjbS5jdXJzb3JDb29yZHModG8sIFwid2luZG93XCIpLnRvcClcbiAgICAgICAgICAgIChoaWRpbmcgPSBkaWFsb2cpLnN0eWxlLm9wYWNpdHkgPSAuNFxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpYWxvZyhjbSwgcXVlcnlEaWFsb2csIFwiU2VhcmNoIGZvcjpcIiwgcSwgZnVuY3Rpb24ocXVlcnkpIHtcbiAgICAgICAgaWYgKHF1ZXJ5ICYmICFzdGF0ZS5xdWVyeSkgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHN0YXJ0U2VhcmNoKGNtLCBzdGF0ZSwgcXVlcnkpO1xuICAgICAgICAgIHN0YXRlLnBvc0Zyb20gPSBzdGF0ZS5wb3NUbyA9IGNtLmdldEN1cnNvcigpO1xuICAgICAgICAgIGZpbmROZXh0KGNtLCByZXYpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmROZXh0KGNtLCByZXYsIGNhbGxiYWNrKSB7Y20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdGF0ZSA9IGdldFNlYXJjaFN0YXRlKGNtKTtcbiAgICB2YXIgY3Vyc29yID0gZ2V0U2VhcmNoQ3Vyc29yKGNtLCBzdGF0ZS5xdWVyeSwgcmV2ID8gc3RhdGUucG9zRnJvbSA6IHN0YXRlLnBvc1RvKTtcbiAgICBpZiAoIWN1cnNvci5maW5kKHJldikpIHtcbiAgICAgIGN1cnNvciA9IGdldFNlYXJjaEN1cnNvcihjbSwgc3RhdGUucXVlcnksIHJldiA/IENvZGVNaXJyb3IuUG9zKGNtLmxhc3RMaW5lKCkpIDogQ29kZU1pcnJvci5Qb3MoY20uZmlyc3RMaW5lKCksIDApKTtcbiAgICAgIGlmICghY3Vyc29yLmZpbmQocmV2KSkgcmV0dXJuO1xuICAgIH1cbiAgICBjbS5zZXRTZWxlY3Rpb24oY3Vyc29yLmZyb20oKSwgY3Vyc29yLnRvKCkpO1xuICAgIGNtLnNjcm9sbEludG9WaWV3KHtmcm9tOiBjdXJzb3IuZnJvbSgpLCB0bzogY3Vyc29yLnRvKCl9LCAyMCk7XG4gICAgc3RhdGUucG9zRnJvbSA9IGN1cnNvci5mcm9tKCk7IHN0YXRlLnBvc1RvID0gY3Vyc29yLnRvKCk7XG4gICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhjdXJzb3IuZnJvbSgpLCBjdXJzb3IudG8oKSlcbiAgfSk7fVxuXG4gIGZ1bmN0aW9uIGNsZWFyU2VhcmNoKGNtKSB7Y20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdGF0ZSA9IGdldFNlYXJjaFN0YXRlKGNtKTtcbiAgICBzdGF0ZS5sYXN0UXVlcnkgPSBzdGF0ZS5xdWVyeTtcbiAgICBpZiAoIXN0YXRlLnF1ZXJ5KSByZXR1cm47XG4gICAgc3RhdGUucXVlcnkgPSBzdGF0ZS5xdWVyeVRleHQgPSBudWxsO1xuICAgIGNtLnJlbW92ZU92ZXJsYXkoc3RhdGUub3ZlcmxheSk7XG4gICAgaWYgKHN0YXRlLmFubm90YXRlKSB7IHN0YXRlLmFubm90YXRlLmNsZWFyKCk7IHN0YXRlLmFubm90YXRlID0gbnVsbDsgfVxuICB9KTt9XG5cbiAgdmFyIHJlcGxhY2VRdWVyeURpYWxvZyA9XG4gICAgJyA8aW5wdXQgdHlwZT1cInRleHRcIiBzdHlsZT1cIndpZHRoOiAxMGVtXCIgY2xhc3M9XCJDb2RlTWlycm9yLXNlYXJjaC1maWVsZFwiLz4gPHNwYW4gc3R5bGU9XCJjb2xvcjogIzg4OFwiIGNsYXNzPVwiQ29kZU1pcnJvci1zZWFyY2gtaGludFwiPihVc2UgL3JlLyBzeW50YXggZm9yIHJlZ2V4cCBzZWFyY2gpPC9zcGFuPic7XG4gIHZhciByZXBsYWNlbWVudFF1ZXJ5RGlhbG9nID0gJ1dpdGg6IDxpbnB1dCB0eXBlPVwidGV4dFwiIHN0eWxlPVwid2lkdGg6IDEwZW1cIiBjbGFzcz1cIkNvZGVNaXJyb3Itc2VhcmNoLWZpZWxkXCIvPic7XG4gIHZhciBkb1JlcGxhY2VDb25maXJtID0gXCJSZXBsYWNlPyA8YnV0dG9uPlllczwvYnV0dG9uPiA8YnV0dG9uPk5vPC9idXR0b24+IDxidXR0b24+QWxsPC9idXR0b24+IDxidXR0b24+U3RvcDwvYnV0dG9uPlwiO1xuXG4gIGZ1bmN0aW9uIHJlcGxhY2VBbGwoY20sIHF1ZXJ5LCB0ZXh0KSB7XG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgZm9yICh2YXIgY3Vyc29yID0gZ2V0U2VhcmNoQ3Vyc29yKGNtLCBxdWVyeSk7IGN1cnNvci5maW5kTmV4dCgpOykge1xuICAgICAgICBpZiAodHlwZW9mIHF1ZXJ5ICE9IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICB2Y
23459XIgbWF0Y2ggPSBjbS5nZXRSYW5nZShjdXJzb3IuZnJvbSgpLCBjdXJzb3IudG8oKSkubWF0Y2gocXVlcnkpO1xuICAgICAgICAgIGN1cnNvci5yZXBsYWNlKHRleHQucmVwbGFjZSgvXFwkKFxcZCkvZywgZnVuY3Rpb24oXywgaSkge3JldHVybiBtYXRjaFtpXTt9KSk7XG4gICAgICAgIH0gZWxzZSBjdXJzb3IucmVwbGFjZSh0ZXh0KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlcGxhY2UoY20sIGFsbCkge1xuICAgIGlmIChjbS5nZXRPcHRpb24oXCJyZWFkT25seVwiKSkgcmV0dXJuO1xuICAgIHZhciBxdWVyeSA9IGNtLmdldFNlbGVjdGlvbigpIHx8IGdldFNlYXJjaFN0YXRlKGNtKS5sYXN0UXVlcnk7XG4gICAgdmFyIGRpYWxvZ1RleHQgPSBhbGwgPyBcIlJlcGxhY2UgYWxsOlwiIDogXCJSZXBsYWNlOlwiXG4gICAgZGlhbG9nKGNtLCBkaWFsb2dUZXh0ICsgcmVwbGFjZVF1ZXJ5RGlhbG9nLCBkaWFsb2dUZXh0LCBxdWVyeSwgZnVuY3Rpb24ocXVlcnkpIHtcbiAgICAgIGlmICghcXVlcnkpIHJldHVybjtcbiAgICAgIHF1ZXJ5ID0gcGFyc2VRdWVyeShxdWVyeSk7XG4gICAgICBkaWFsb2coY20sIHJlcGxhY2VtZW50UXVlcnlEaWFsb2csIFwiUmVwbGFjZSB3aXRoOlwiLCBcIlwiLCBmdW5jdGlvbih0ZXh0KSB7XG4gICAgICAgIHRleHQgPSBwYXJzZVN0cmluZyh0ZXh0KVxuICAgICAgICBpZiAoYWxsKSB7XG4gICAgICAgICAgcmVwbGFjZUFsbChjbSwgcXVlcnksIHRleHQpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2xlYXJTZWFyY2goY20pO1xuICAgICAgICAgIHZhciBjdXJzb3IgPSBnZXRTZWFyY2hDdXJzb3IoY20sIHF1ZXJ5LCBjbS5nZXRDdXJzb3IoKSk7XG4gICAgICAgICAgdmFyIGFkdmFuY2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzdGFydCA9IGN1cnNvci5mcm9tKCksIG1hdGNoO1xuICAgICAgICAgICAgaWYgKCEobWF0Y2ggPSBjdXJzb3IuZmluZE5leHQoKSkpIHtcbiAgICAgICAgICAgICAgY3Vyc29yID0gZ2V0U2VhcmNoQ3Vyc29yKGNtLCBxdWVyeSk7XG4gICAgICAgICAgICAgIGlmICghKG1hdGNoID0gY3Vyc29yLmZpbmROZXh0KCkpIHx8XG4gICAgICAgICAgICAgICAgICAoc3RhcnQgJiYgY3Vyc29yLmZyb20oKS5saW5lID09IHN0YXJ0LmxpbmUgJiYgY3Vyc29yLmZyb20oKS5jaCA9PSBzdGFydC5jaCkpIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNtLnNldFNlbGVjdGlvbihjdXJzb3IuZnJvbSgpLCBjdXJzb3IudG8oKSk7XG4gICAgICAgICAgICBjbS5zY3JvbGxJbnRvVmlldyh7ZnJvbTogY3Vyc29yLmZyb20oKSwgdG86IGN1cnNvci50bygpfSk7XG4gICAgICAgICAgICBjb25maXJtRGlhbG9nKGNtLCBkb1JlcGxhY2VDb25maXJtLCBcIlJlcGxhY2U/XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmdW5jdGlvbigpIHtkb1JlcGxhY2UobWF0Y2gpO30sIGFkdmFuY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbigpIHtyZXBsYWNlQWxsKGNtLCBxdWVyeSwgdGV4dCl9XSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICB2Y
23459XIgZG9SZXBsYWNlID0gZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgICAgIGN1cnNvci5yZXBsYWNlKHR5cGVvZiBxdWVyeSA9PSBcInN0cmluZ1wiID8gdGV4dCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0LnJlcGxhY2UoL1xcJChcXGQpL2csIGZ1bmN0aW9uKF8sIGkpIHtyZXR1cm4gbWF0Y2hbaV07fSkpO1xuICAgICAgICAgICAgYWR2YW5jZSgpO1xuICAgICAgICAgIH07XG4gICAgICAgICAgYWR2YW5jZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIENvZGVNaXJyb3IuY29tbWFuZHMuZmluZCA9IGZ1bmN0aW9uKGNtKSB7Y2xlYXJTZWFyY2goY20pOyBkb1NlYXJjaChjbSk7fTtcbiAgQ29kZU1pcnJvci5jb21tYW5kcy5maW5kUGVyc2lzdGVudCA9IGZ1bmN0aW9uKGNtKSB7Y2xlYXJTZWFyY2goY20pOyBkb1NlYXJjaChjbSwgZmFsc2UsIHRydWUpO307XG4gIENvZGVNaXJyb3IuY29tbWFuZHMuZmluZE5leHQgPSBkb1NlYXJjaDtcbiAgQ29kZU1pcnJvci5jb21tYW5kcy5maW5kUHJldiA9IGZ1bmN0aW9uKGNtKSB7ZG9TZWFyY2goY20sIHRydWUpO307XG4gIENvZGVNaXJyb3IuY29tbWFuZHMuY2xlYXJTZWFyY2ggPSBjbGVhclNlYXJjaDtcbiAgQ29kZU1pcnJvci5jb21tYW5kcy5yZXBsYWNlID0gcmVwbGFjZTtcbiAgQ29kZU1pcnJvci5jb21tYW5kcy5yZXBsYWNlQWxsID0gZnVuY3Rpb24oY20pIHtyZXBsYWNlKGNtLCB0cnVlKTt9O1xufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vLi4vbGliL2NvZGVtaXJyb3JcIikpO1xuICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSAvLyBBTURcbiAgICBkZWZpbmUoW1wiLi4vLi4vbGliL2NvZGVtaXJyb3JcIl0sIG1vZCk7XG4gIGVsc2UgLy8gUGxhaW4gYnJvd3NlciBlbnZcbiAgICBtb2QoQ29kZU1pcnJvcik7XG59KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuICB2YXIgUG9zID0gQ29kZU1pcnJvci5Qb3M7XG5cbiAgZnVuY3Rpb24gU2VhcmNoQ3Vyc29yKGRvYywgcXVlcnksIHBvcywgY2FzZUZvbGQpIHtcbiAgICB0aGlzLmF0T2NjdXJyZW5jZSA9IGZhbHNlOyB0aGlzLmRvYyA9IGRvYztcbiAgICBpZiAoY2FzZUZvbGQgPT0gbnVsbCAmJiB0eXBlb2YgcXVlcnkgPT0gXCJzdHJpbmdcIikgY2FzZUZvbGQgPSBmYWxzZTtcblxuICAgIHBvcyA9IHBvcyA/IGRvYy5jbGlwUG9zKHBvcykgOiBQb3MoMCwgMCk7XG4gICAgdGhpcy5wb3MgPSB7ZnJvbTogcG9zLCB0bzogcG9zfTtcblxuICAgIC8vIFRoZSBtYXRjaGVzIG1ldGhvZCBpcyBmaWxsZWQgaW4gYmFzZWQgb24gdGhlIHR5cGUgb2YgcXVlcnkuXG4gICAgLy8gSXQgdGFrZXMgYSBwb3NpdGlvbiBhbmQgYSBkaXJlY3Rpb24sIGFuZCByZXR1cm5zIGFuIG9iamVjdFxuICAgIC8vIGRlc2NyaWJpbmcgdGhlIG5leHQgb2NjdXJyZW5jZSBvZiB0aGUgcXVlcnksIG9yIG51bGwgaWYgbm9cbiAgICAvLyBtb3JlIG1hdGNoZXMgd2VyZSBmb3VuZC5cbiAgICBpZiAodHlwZW9mIHF1ZXJ5ICE9IFwic3RyaW5nXCIpIHsgLy8gUmVnZXhwIG1hdGNoXG4gICAgICBpZiAoIXF1ZXJ5Lmdsb2JhbCkgcXVlcnkgPSBuZXcgUmVnRXhwKHF1ZXJ5LnNvdXJjZSwgcXVlcnkuaWdub3JlQ2FzZSA/IFwiaWdcIiA6IFwiZ1wiKTtcbiAgICAgIHRoaXMubWF0Y2hlcyA9IGZ1bmN0aW9uKHJldmVyc2UsIHBvcykge1xuICAgICAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICAgIHF1ZXJ5Lmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgdmFyIGxpbmUgPSBkb2MuZ2V0TGluZShwb3MubGluZSkuc2xpY2UoMCwgcG9zLmNoKSwgY3V0T2ZmID0gMCwgbWF0Y2gsIHN0YXJ0O1xuICAgICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICAgIHF1ZXJ5Lmxhc3RJbmRleCA9IGN1dE9mZjtcbiAgICAgICAgICAgIHZhciBuZXdNYXRjaCA9IHF1ZXJ5LmV4ZWMobGluZSk7XG4gICAgICAgICAgICBpZiAoIW5ld01hdGNoKSBicmVhaztcbiAgICAgICAgICAgIG1hdGNoID0gbmV3TWF0Y2g7XG4gICAgICAgICAgICBzdGFydCA9IG1hdGNoLmluZGV4O1xuICAgICAgICAgICAgY3V0T2ZmID0gbWF0Y2guaW5kZXggKyAobWF0Y2hbMF0ubGVuZ3RoIHx8IDEpO1xuICAgICAgICAgICAgaWYgKGN1dE9mZiA9PSBsaW5lLmxlbmd0aCkgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBtYXRjaExlbiA9IChtYXRjaCAmJiBtYXRjaFswXS5sZW5ndGgpIHx8IDA7XG4gICAgICAgICAgaWYgKCFtYXRjaExlbikge1xuICAgICAgICAgICAgaWYgKHN0YXJ0ID09IDAgJiYgbGluZS5sZW5ndGggPT0gMCkge21hdGNoID0gdW5kZWZpbmVkO31cbiAgICAgICAgICAgIGVsc2UgaWYgKHN0YXJ0ICE9IGRvYy5nZXRMaW5lKHBvcy5saW5lKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgbWF0Y2hMZW4rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcXVlcnkubGFzdEluZGV4ID0gcG9zLmNoO1xuICAgICAgICAgIHZhciBsaW5lID0gZG9jLmdldExpbmUocG9zLmxpbmUpLCBtYXRjaCA9IHF1ZXJ5LmV4ZWMobGluZSk7XG4gICAgICAgICAgdmFyIG1hdGNoTGVuID0gKG1hdGNoICYmIG1hdGNoWzBdLmxlbmd0aCkgfHwgMDtcbiAgICAgICAgICB2Y
23459XIgc3RhcnQgPSBtYXRjaCAmJiBtYXRjaC5pbmRleDtcbiAgICAgICAgICBpZiAoc3RhcnQgKyBtYXRjaExlbiAhPSBsaW5lLmxlbmd0aCAmJiAhbWF0Y2hMZW4pIG1hdGNoTGVuID0gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF0Y2ggJiYgbWF0Y2hMZW4pXG4gICAgICAgICAgcmV0dXJuIHtmcm9tOiBQb3MocG9zLmxpbmUsIHN0YXJ0KSxcbiAgICAgICAgICAgICAgICAgIHRvOiBQb3MocG9zLmxpbmUsIHN0YXJ0ICsgbWF0Y2hMZW4pLFxuICAgICAgICAgICAgICAgICAgbWF0Y2g6IG1hdGNofTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHsgLy8gU3RyaW5nIHF1ZXJ5XG4gICAgICB2YXIgb3JpZ1F1ZXJ5ID0gcXVlcnk7XG4gICAgICBpZiAoY2FzZUZvbGQpIHF1ZXJ5ID0gcXVlcnkudG9Mb3dlckNhc2UoKTtcbiAgICAgIHZhciBmb2xkID0gY2FzZUZvbGQgPyBmdW5jdGlvbihzdHIpe3JldHVybiBzdHIudG9Mb3dlckNhc2UoKTt9IDogZnVuY3Rpb24oc3RyKXtyZXR1cm4gc3RyO307XG4gICAgICB2YXIgdGFyZ2V0ID0gcXVlcnkuc3BsaXQoXCJcXG5cIik7XG4gICAgICAvLyBEaWZmZXJlbnQgbWV0aG9kcyBmb3Igc2luZ2xlLWxpbmUgYW5kIG11bHRpLWxpbmUgcXVlcmllc1xuICAgICAgaWYgKHRhcmdldC5sZW5ndGggPT0gMSkge1xuICAgICAgICBpZiAoIXF1ZXJ5Lmxlbmd0aCkge1xuICAgICAgICAgIC8vIEVtcHR5IHN0cmluZyB3b3VsZCBtYXRjaCBhbnl0aGluZyBhbmQgbmV2ZXIgcHJvZ3Jlc3MsIHNvXG4gICAgICAgICAgLy8gd2UgZGVmaW5lIGl0IHRvIG1hdGNoIG5vdGhpbmcgaW5zdGVhZC5cbiAgICAgICAgICB0aGlzLm1hdGNoZXMgPSBmdW5jdGlvbigpIHt9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubWF0Y2hlcyA9IGZ1bmN0aW9uKHJldmVyc2UsIHBvcykge1xuICAgICAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICAgICAgdmFyIG9yaWcgPSBkb2MuZ2V0TGluZShwb3MubGluZSkuc2xpY2UoMCwgcG9zLmNoKSwgbGluZSA9IGZvbGQob3JpZyk7XG4gICAgICAgICAgICAgIHZhciBtYXRjaCA9IGxpbmUubGFzdEluZGV4T2YocXVlcnkpO1xuICAgICAgICAgICAgICBpZiAobWF0Y2ggPiAtMSkge1xuICAgICAgICAgICAgICAgIG1hdGNoID0gYWRqdXN0UG9zKG9yaWcsIGxpbmUsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge2Zyb206IFBvcyhwb3MubGluZSwgbWF0Y2gpLCB0bzogUG9zKHBvcy5saW5lLCBtYXRjaCArIG9yaWdRdWVyeS5sZW5ndGgpfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICB2Y
23459XIgb3JpZyA9IGRvYy5nZXRMaW5lKHBvcy5saW5lKS5zbGljZShwb3MuY2gpLCBsaW5lID0gZm9sZChvcmlnKTtcbiAgICAgICAgICAgICAgIHZhciBtYXRjaCA9IGxpbmUuaW5kZXhPZihxdWVyeSk7XG4gICAgICAgICAgICAgICBpZiAobWF0Y2ggPiAtMSkge1xuICAgICAgICAgICAgICAgICBtYXRjaCA9IGFkanVzdFBvcyhvcmlnLCBsaW5lLCBtYXRjaCkgKyBwb3MuY2g7XG4gICAgICAgICAgICAgICAgIHJldHVybiB7ZnJvbTogUG9zKHBvcy5saW5lLCBtYXRjaCksIHRvOiBQb3MocG9zLmxpbmUsIG1hdGNoICsgb3JpZ1F1ZXJ5Lmxlbmd0aCl9O1xuICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBvcmlnVGFyZ2V0ID0gb3JpZ1F1ZXJ5LnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICB0aGlzLm1hdGNoZXMgPSBmdW5jdGlvbihyZXZlcnNlLCBwb3MpIHtcbiAgICAgICAgICB2YXIgbGFzdCA9IHRhcmdldC5sZW5ndGggLSAxO1xuICAgICAgICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgICAgICBpZiAocG9zLmxpbmUgLSAodGFyZ2V0Lmxlbmd0aCAtIDEpIDwgZG9jLmZpcnN0TGluZSgpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoZm9sZChkb2MuZ2V0TGluZShwb3MubGluZSkuc2xpY2UoMCwgb3JpZ1RhcmdldFtsYXN0XS5sZW5ndGgpKSAhPSB0YXJnZXRbdGFyZ2V0Lmxlbmd0aCAtIDFdKSByZXR1cm47XG4gICAgICAgICAgICB2YXIgdG8gPSBQb3MocG9zLmxpbmUsIG9yaWdUYXJnZXRbbGFzdF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAodmFyIGxuID0gcG9zLmxpbmUgLSAxLCBpID0gbGFzdCAtIDE7IGkgPj0gMTsgLS1pLCAtLWxuKVxuICAgICAgICAgICAgICBpZiAodGFyZ2V0W2ldICE9IGZvbGQoZG9jLmdldExpbmUobG4pKSkgcmV0dXJuO1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBkb2MuZ2V0TGluZShsbiksIGN1dCA9IGxpbmUubGVuZ3RoIC0gb3JpZ1RhcmdldFswXS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoZm9sZChsaW5lLnNsaWNlKGN1dCkpICE9IHRhcmdldFswXSkgcmV0dXJuO1xuICAgICAgICAgICAgcmV0dXJuIHtmcm9tOiBQb3MobG4sIGN1dCksIHRvOiB0b307XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChwb3MubGluZSArICh0YXJnZXQubGVuZ3RoIC0gMSkgPiBkb2MubGFzdExpbmUoKSkgcmV0dXJuO1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBkb2MuZ2V0TGluZShwb3MubGluZSksIGN1dCA9IGxpbmUubGVuZ3RoIC0gb3JpZ1RhcmdldFswXS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoZm9sZChsaW5lLnNsaWNlKGN1dCkpICE9IHRhcmdldFswXSkgcmV0dXJuO1xuICAgICAgICAgICAgdmFyIGZyb20gPSBQb3MocG9zLmxpbmUsIGN1dCk7XG4gICAgICAgICAgICBmb3IgKHZhciBsbiA9IHBvcy5saW5lICsgMSwgaSA9IDE7IGkgPCBsYXN0OyArK2ksICsrbG4pXG4gICAgICAgICAgICAgIGlmICh0YXJnZXRbaV0gIT0gZm9sZChkb2MuZ2V0TGluZShsbikpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoZm9sZChkb2MuZ2V0TGluZShsbikuc2xpY2UoMCwgb3JpZ1RhcmdldFtsYXN0XS5sZW5ndGgpKSAhPSB0YXJnZXRbbGFzdF0pIHJldHVybjtcbiAgICAgICAgICAgIHJldHVybiB7ZnJvbTogZnJvbSwgdG86IFBvcyhsbiwgb3JpZ1RhcmdldFtsYXN0XS5sZW5ndGgpfTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgU2VhcmNoQ3Vyc29yLnByb3RvdHlwZSA9IHtcbiAgICBmaW5kTmV4dDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuZmluZChmYWxzZSk7fSxcbiAgICBmaW5kUHJldmlvdXM6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmZpbmQodHJ1ZSk7fSxcblxuICAgIGZpbmQ6IGZ1bmN0aW9uKHJldmVyc2UpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcywgcG9zID0gdGhpcy5kb2MuY2xpcFBvcyhyZXZlcnNlID8gdGhpcy5wb3MuZnJvbSA6IHRoaXMucG9zLnRvKTtcbiAgICAgIGZ1bmN0aW9uIHNhdmVQb3NBbmRGYWlsKGxpbmUp
23459IHtcbiAgICAgICAgdmFyIHBvcyA9IFBvcyhsaW5lLCAwKTtcbiAgICAgICAgc2VsZi5wb3MgPSB7ZnJvbTogcG9zLCB0bzogcG9zfTtcbiAgICAgICAgc2VsZi5hdE9jY3VycmVuY2UgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBmb3IgKDs7KSB7XG4gICAgICAgIGlmICh0aGlzLnBvcyA9IHRoaXMubWF0Y2hlcyhyZXZlcnNlLCBwb3MpKSB7XG4gICAgICAgICAgdGhpcy5hdE9jY3VycmVuY2UgPSB0cnVlO1xuICAgICAgICAgIHJldHVybiB0aGlzLnBvcy5tYXRjaCB8fCB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgICAgaWYgKCFwb3MubGluZSkgcmV0dXJuIHNhdmVQb3NBbmRGYWlsKDApO1xuICAgICAgICAgIHBvcyA9IFBvcyhwb3MubGluZS0xLCB0aGlzLmRvYy5nZXRMaW5lKHBvcy5saW5lLTEpLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIG1heExpbmUgPSB0aGlzLmRvYy5saW5lQ291bnQoKTtcbiAgICAgICAgICBpZiAocG9zLmxpbmUgPT0gbWF4TGluZSAtIDEpIHJldHVybiBzYXZlUG9zQW5kRmFpbChtYXhMaW5lKTtcbiAgICAgICAgICBwb3MgPSBQb3MocG9zLmxpbmUgKyAxLCAwKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBmcm9tOiBmdW5jdGlvbigpIHtpZiAodGhpcy5hdE9jY3VycmVuY2UpIHJldHVybiB0aGlzLnBvcy5mcm9tO30sXG4gICAgdG86IGZ1bmN0aW9uKCkge2lmICh0aGlzLmF0T2NjdXJyZW5jZSkgcmV0dXJuIHRoaXMucG9zLnRvO30sXG5cbiAgICByZXBsYWNlOiBmdW5jdGlvbihuZXdUZXh0LCBvcmlnaW4pIHtcbiAgICAgIGlmICghdGhpcy5hdE9jY3VycmVuY2UpIHJldHVybjtcbiAgICAgIHZhciBsaW5lcyA9IENvZGVNaXJyb3Iuc3BsaXRMaW5lcyhuZXdUZXh0KTtcbiAgICAgIHRoaXMuZG9jLnJlcGxhY2VSYW5nZShsaW5lcywgdGhpcy5wb3MuZnJvbSwgdGhpcy5wb3MudG8sIG9yaWdpbik7XG4gICAgICB0aGlzLnBvcy50byA9IFBvcyh0aGlzLnBvcy5mcm9tLmxpbmUgKyBsaW5lcy5sZW5ndGggLSAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZXNbbGluZXMubGVuZ3RoIC0gMV0ubGVuZ3RoICsgKGxpbmVzLmxlbmd0aCA9PSAxID8gdGhpcy5wb3MuZnJvbS5jaCA6IDApKTtcbiAgICB9XG4gIH07XG5cbiAgLy8gTWFwcyBhIHBvc2l0aW9uIGluIGEgY2FzZS1mb2xkZWQgbGluZSBiYWNrIHRvIGEgcG9zaXRpb24gaW4gdGhlIG9yaWdpbmFsIGxpbmVcbiAgLy8gKGNvbXBlbnNhdGluZyBmb3IgY29kZXBvaW50cyBpbmNyZWFzaW5nIGluIG51bWJlciBkdXJpbmcgZm9sZGluZylcbiAgZnVuY3Rpb24gYWRqdXN0UG9zKG9yaWcsIGZvbGRlZCwgcG9zKSB7XG4gICAgaWYgKG9yaWcubGVuZ3RoID09IGZvbGRlZC5sZW5ndGgpIHJldHVybiBwb3M7XG4gICAgZm9yICh2YXIgcG9zMSA9IE1hdGgubWluKHBvcywgb3JpZy5sZW5ndGgpOzspIHtcbiAgICAgIHZhciBsZW4xID0gb3JpZy5zbGljZSgwLCBwb3MxKS50b0xvd2VyQ2FzZSgpLmxlbmd0aDtcbiAgICAgIGlmIChsZW4xIDwgcG9zKSArK3BvczE7XG4gICAgICBlbHNlIGlmIChsZW4xID4gcG9zKSAtLXBvczE7XG4gICAgICBlbHNlIHJldHVybiBwb3MxO1xuICAgIH1cbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwiZ2V0U2VhcmNoQ3Vyc29yXCIsIGZ1bmN0aW9uKHF1ZXJ5LCBwb3MsIGNhc2VGb2xkKSB7XG4gICAgcmV0dXJuIG5ldyBTZWFyY2hDdXJzb3IodGhpcy5kb2MsIHF1ZXJ5LCBwb3MsIGNhc2VGb2xkKTtcbiAgfSk7XG4gIENvZGVNaXJyb3IuZGVmaW5lRG9jRXh0ZW5zaW9uKFwiZ2V0U2VhcmNoQ3Vyc29yXCIsIGZ1bmN0aW9uKHF1ZXJ5LCBwb3MsIGNhc2VGb2xkKSB7XG4gICAgcmV0dXJuIG5ldyBTZWFyY2hDdXJzb3IodGhpcywgcXVlcnksIHBvcywgY2FzZUZvbGQpO1xuICB9KTtcblxuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcInNlbGVjdE1hdGNoZXNcIiwgZnVuY3Rpb24ocXVlcnksIGNhc2VGb2xkKSB7XG4gICAgdmFyIHJhbmdlcyA9IFtdO1xuICAgIHZhciBjdXIgPSB0aGlzLmdldFNlYXJjaEN1cnNvcihxdWVyeSwgdGhpcy5nZXRDdXJzb3IoXCJmcm9tXCIpLCBjYXNlRm9sZCk7XG4gICAgd2hpbGUgKGN1ci5maW5kTmV4dCgpKSB7XG4gICAgICBpZiAoQ29kZU1pcnJvci5jbXBQb3MoY3VyLnRvKCksIHRoaXMuZ2V0Q3Vyc29yKFwidG9cIikpID4gMCkgYnJlYWs7XG4gICAgICByYW5nZXMucHVzaCh7YW5jaG9yOiBjdXIuZnJvbSgpLCBoZWFkOiBjdXIudG8oKX0pO1xuICAgIH1cbiAgICBpZiAocmFuZ2VzLmxlbmd0aClcbiAgICAgIHRoaXMuc2V0U2VsZWN0aW9ucyhyYW5nZXMsIDApO1xuICB9KTtcbn0pO1xuIiwiLy8gQ29kZU1pcnJvciwgY29weXJpZ2h0IChjKSBieSBNYXJpam4gSGF2ZXJiZWtlIGFuZCBvdGhlcnNcbi8vIERpc3RyaWJ1dGVkIHVuZGVyIGFuIE1JVCBsaWNlbnNlOiBodHRwOi8vY29kZW1pcnJvci5uZXQvTElDRU5TRVxuXG4oZnVuY3Rpb24obW9kKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUgPT0gXCJvYmplY3RcIikgLy8gQ29tbW9uSlNcbiAgICBtb2QocmVxdWlyZShcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uLy4uL2xpYi9jb2RlbWlycm9yXCJdLCBtb2QpO1xuICBlbHNlIC8vIFBsYWluIGJyb3dzZXIgZW52XG4gICAgbW9kKENvZGVNaXJyb3IpO1xufSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICB2YXIgUG9zID0gQ29kZU1pcnJvci5Qb3M7XG5cbiAgZnVuY3Rpb24gZmluZFBhcmFncmFwaChjbSwgcG9zLCBvcHRpb25zKSB7XG4gICAgdmFyIHN0YXJ0UkUgPSBvcHRpb25zLnBhcmFncmFwaFN0YXJ0IHx8IGNtLmdldEhlbHBlcihwb3MsIFwicGFyYWdyYXBoU3RhcnRcIik7XG4gICAgZm9yICh2YXIgc3RhcnQgPSBwb3MubGluZSwgZmlyc3QgPSBjbS5maXJzdExpbmUoKTsgc3RhcnQgPiBmaXJzdDsgLS1zdGFydCkge1xuICAgICAgdmFyIGxpbmUgPSBjbS5nZXRMaW5lKHN0YXJ0KTtcbiAgICAgIGlmIChzdGFydFJFICYmIHN0YXJ0UkUudGVzdChsaW5lKSkgYnJlYWs7XG4gICAgICBpZiAoIS9cXFMvLnRlc3QobGluZSkpIHsgKytzdGFydDsgYnJlYWs7IH1cbiAgICB9XG4gICAgdmFyIGVuZFJFID0gb3B0aW9ucy5wYXJhZ3JhcGhFbmQgfHwgY20uZ2V0SGVscGVyKHBvcywgXCJwYXJhZ3JhcGhFbmRcIik7XG4gICAgZm9yICh2YXIgZW5kID0gcG9zLmxpbmUgKyAxLCBsYXN0ID0gY20ubGFzdExpbmUoKTsgZW5kIDw9IGxhc3Q7ICsrZW5kKSB7XG4gICAgICB2Y
23459XIgbGluZSA9IGNtLmdldExpbmUoZW5kKTtcbiAgICAgIGlmIChlbmRSRSAmJiBlbmRSRS50ZXN0KGxpbmUpKSB7ICsrZW5kOyBicmVhazsgfVxuICAgICAgaWYgKCEvXFxTLy50ZXN0KGxpbmUpKSBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIHtmcm9tOiBzdGFydCwgdG86IGVuZH07XG4gIH1cblxuICBmdW5jdGlvbiBmaW5kQnJlYWtQb2ludCh0ZXh0LCBjb2x1bW4sIHdyYXBPbiwga2lsbFRyYWlsaW5nU3BhY2UpIHtcbiAgICBmb3IgKHZhciBhdCA9IGNvbHVtbjsgYXQgPiAwOyAtLWF0KVxuICAgICAgaWYgKHdyYXBPbi50ZXN0KHRleHQuc2xpY2UoYXQgLSAxLCBhdCArIDEpKSkgYnJlYWs7XG4gICAgZm9yICh2YXIgZmlyc3QgPSB0cnVlOzsgZmlyc3QgPSBmYWxzZSkge1xuICAgICAgdmFyIGVuZE9mVGV4dCA9IGF0O1xuICAgICAgaWYgKGtpbGxUcmFpbGluZ1NwYWNlKVxuICAgICAgICB3aGlsZSAodGV4dC5jaGFyQXQoZW5kT2ZUZXh0IC0gMSkgPT0gXCIgXCIpIC0tZW5kT2ZUZXh0O1xuICAgICAgaWYgKGVuZE9mVGV4dCA9PSAwICYmIGZpcnN0KSBhdCA9IGNvbHVtbjtcbiAgICAgIGVsc2UgcmV0dXJuIHtmcm9tOiBlbmRPZlRleHQsIHRvOiBhdH07XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gd3JhcFJhbmdlKGNtLCBmcm9tLCB0bywgb3B0aW9ucykge1xuICAgIGZyb20gPSBjbS5jbGlwUG9zKGZyb20pOyB0byA9IGNtLmNsaXBQb3ModG8pO1xuICAgIHZhciBjb2x1bW4gPSBvcHRpb25zLmNvbHVtbiB8fCA4MDtcbiAgICB2YXIgd3JhcE9uID0gb3B0aW9ucy53cmFwT24gfHwgL1xcc1xcU3wtW15cXC5cXGRdLztcbiAgICB2YXIga2lsbFRyYWlsaW5nID0gb3B0aW9ucy5raWxsVHJhaWxpbmdTcGFjZSAhPT0gZmFsc2U7XG4gICAgdmFyIGNoYW5nZXMgPSBbXSwgY3VyTGluZSA9IFwiXCIsIGN1ck5vID0gZnJvbS5saW5lO1xuICAgIHZhciBsaW5lcyA9IGNtLmdldFJhbmdlKGZyb20sIHRvLCBmYWxzZSk7XG4gICAgaWYgKCFsaW5lcy5sZW5ndGgpIHJldHVybiBudWxsO1xuICAgIHZhciBsZWFkaW5nU3BhY2UgPSBsaW5lc1swXS5tYXRjaCgvXlsgXFx0XSovKVswXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciB0ZXh0ID0gbGluZXNbaV0sIG9sZExlbiA9IGN1ckxpbmUubGVuZ3RoLCBzcGFjZUluc2VydGVkID0gMDtcbiAgICAgIGlmIChjdXJMaW5lICYmIHRleHQgJiYgIXdyYXBPbi50ZXN0KGN1ckxpbmUuY2hhckF0KGN1ckxpbmUubGVuZ3RoIC0gMSkgKyB0ZXh0LmNoYXJBdCgwKSkpIHtcbiAgICAgICAgY3VyTGluZSArPSBcIiBcIjtcbiAgICAgICAgc3BhY2VJbnNlcnRlZCA9IDE7XG4gICAgICB9XG4gICAgICB2Y
23459XIgc3BhY2VUcmltbWVkID0gXCJcIjtcbiAgICAgIGlmIChpKSB7XG4gICAgICAgIHNwYWNlVHJpbW1lZCA9IHRleHQubWF0Y2goL15cXHMqLylbMF07XG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKHNwYWNlVHJpbW1lZC5sZW5ndGgpO1xuICAgICAgfVxuICAgICAgY3VyTGluZSArPSB0ZXh0O1xuICAgICAgaWYgKGkpIHtcbiAgICAgICAgdmFyIGZpcnN0QnJlYWsgPSBjdXJMaW5lLmxlbmd0aCA+IGNvbHVtbiAmJiBsZWFkaW5nU3BhY2UgPT0gc3BhY2VUcmltbWVkICYmXG4gICAgICAgICAgZmluZEJyZWFrUG9pbnQoY3VyTGluZSwgY29sdW1uLCB3cmFwT24sIGtpbGxUcmFpbGluZyk7XG4gICAgICAgIC8vIElmIHRoaXMgaXNuJ3QgYnJva2VuLCBvciBpcyBicm9rZW4gYXQgYSBkaWZmZXJlbnQgcG9pbnQsIHJlbW92ZSBvbGQgYnJlYWtcbiAgICAgICAgaWYgKCFmaXJzdEJyZWFrIHx8IGZpcnN0QnJlYWsuZnJvbSAhPSBvbGRMZW4gfHwgZmlyc3RCcmVhay50byAhPSBvbGRMZW4gKyBzcGFjZUluc2VydGVkKSB7XG4gICAgICAgICAgY2hhbmdlcy5wdXNoKHt0ZXh0OiBbc3BhY2VJbnNlcnRlZCA/IFwiIFwiIDogXCJcIl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tOiBQb3MoY3VyTm8sIG9sZExlbiksXG4gICAgICAgICAgICAgICAgICAgICAgICB0bzogUG9zKGN1ck5vICsgMSwgc3BhY2VUcmltbWVkLmxlbmd0aCl9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjdXJMaW5lID0gbGVhZGluZ1NwYWNlICsgdGV4dDtcbiAgICAgICAgICArK2N1ck5vO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aGlsZSAoY3VyTGluZS5sZW5ndGggPiBjb2x1bW4pIHtcbiAgICAgICAgdmFyIGJwID0gZmluZEJyZWFrUG9pbnQoY3VyTGluZSwgY29sdW1uLCB3cmFwT24sIGtpbGxUcmFpbGluZyk7XG4gICAgICAgIGNoYW5nZXMucHVzaCh7dGV4dDogW1wiXCIsIGxlYWRpbmdTcGFjZV0sXG4gICAgICAgICAgICAgICAgICAgICAgZnJvbTogUG9zKGN1ck5vLCBicC5mcm9tKSxcbiAgICAgICAgICAgICAgICAgICAgICB0bzogUG9zKGN1ck5vLCBicC50byl9KTtcbiAgICAgICAgY3VyTGluZSA9IGxlYWRpbmdTcGFjZSArIGN1ckxpbmUuc2xpY2UoYnAudG8pO1xuICAgICAgICArK2N1ck5vO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5sZW5ndGgpIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2Y
23459XIgY2hhbmdlID0gY2hhbmdlc1tpXTtcbiAgICAgICAgaWYgKGNoYW5nZS50ZXh0IHx8IENvZGVNaXJyb3IuY21wUG9zKGNoYW5nZS5mcm9tLCBjaGFuZ2UudG8pKVxuICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShjaGFuZ2UudGV4dCwgY2hhbmdlLmZyb20sIGNoYW5nZS50byk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGNoYW5nZXMubGVuZ3RoID8ge2Zyb206IGNoYW5nZXNbMF0uZnJvbSwgdG86IENvZGVNaXJyb3IuY2hhbmdlRW5kKGNoYW5nZXNbY2hhbmdlcy5sZW5ndGggLSAxXSl9IDogbnVsbDtcbiAgfVxuXG4gIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwid3JhcFBhcmFncmFwaFwiLCBmdW5jdGlvbihwb3MsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICBpZiAoIXBvcykgcG9zID0gdGhpcy5nZXRDdXJzb3IoKTtcbiAgICB2YXIgcGFyYSA9IGZpbmRQYXJhZ3JhcGgodGhpcywgcG9zLCBvcHRpb25zKTtcbiAgICByZXR1cm4gd3JhcFJhbmdlKHRoaXMsIFBvcyhwYXJhLmZyb20sIDApLCBQb3MocGFyYS50byAtIDEpLCBvcHRpb25zKTtcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5jb21tYW5kcy53cmFwTGluZXMgPSBmdW5jdGlvbihjbSkge1xuICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIHZhciByYW5nZXMgPSBjbS5saXN0U2VsZWN0aW9ucygpLCBhdCA9IGNtLmxhc3RMaW5lKCkgKyAxO1xuICAgICAgZm9yICh2YXIgaSA9IHJhbmdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICB2Y
23459XIgcmFuZ2UgPSByYW5nZXNbaV0sIHNwYW47XG4gICAgICAgIGlmIChyYW5nZS5lbXB0eSgpKSB7XG4gICAgICAgICAgdmFyIHBhcmEgPSBmaW5kUGFyYWdyYXBoKGNtLCByYW5nZS5oZWFkLCB7fSk7XG4gICAgICAgICAgc3BhbiA9IHtmcm9tOiBQb3MocGFyYS5mcm9tLCAwKSwgdG86IFBvcyhwYXJhLnRvIC0gMSl9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNwYW4gPSB7ZnJvbTogcmFuZ2UuZnJvbSgpLCB0bzogcmFuZ2UudG8oKX07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNwYW4udG8ubGluZSA+PSBhdCkgY29udGludWU7XG4gICAgICAgIGF0ID0gc3Bhbi5mcm9tLmxpbmU7XG4gICAgICAgIHdyYXBSYW5nZShjbSwgc3Bhbi5mcm9tLCBzcGFuLnRvLCB7fSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJ3cmFwUmFuZ2VcIiwgZnVuY3Rpb24oZnJvbSwgdG8sIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gd3JhcFJhbmdlKHRoaXMsIGZyb20sIHRvLCBvcHRpb25zIHx8IHt9KTtcbiAgfSk7XG5cbiAgQ29kZU1pcnJvci5kZWZpbmVFeHRlbnNpb24oXCJ3cmFwUGFyYWdyYXBoc0luUmFuZ2VcIiwgZnVuY3Rpb24oZnJvbSwgdG8sIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICB2YXIgY20gPSB0aGlzLCBwYXJhcyA9IFtdO1xuICAgIGZvciAodmFyIGxpbmUgPSBmcm9tLmxpbmU7IGxpbmUgPD0gdG8ubGluZTspIHtcbiAgICAgIHZhciBwYXJhID0gZmluZFBhcmFncmFwaChjbSwgUG9zKGxpbmUsIDApLCBvcHRpb25zKTtcbiAgICAgIHBhcmFzLnB1c2gocGFyYSk7XG4gICAgICBsaW5lID0gcGFyYS50bztcbiAgICB9XG4gICAgdmFyIG1hZGVDaGFuZ2UgPSBmYWxzZTtcbiAgICBpZiAocGFyYXMubGVuZ3RoKSBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICBmb3IgKHZhciBpID0gcGFyYXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpXG4gICAgICAgIG1hZGVDaGFuZ2UgPSBtYWRlQ2hhbmdlIHx8IHdyYXBSYW5nZShjbSwgUG9zKHBhcmFzW2ldLmZyb20sIDApLCBQb3MocGFyYXNbaV0udG8gLSAxKSwgb3B0aW9ucyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG1hZGVDaGFuZ2U7XG4gIH0pO1xufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbi8vIEEgcm91Z2ggYXBwcm94aW1hdGlvbiBvZiBTdWJsaW1lIFRleHQncyBrZXliaW5kaW5nc1xuLy8gRGVwZW5kcyBvbiBhZGRvbi9zZWFyY2gvc2VhcmNoY3Vyc29yLmpzIGFuZCBvcHRpb25hbGx5IGFkZG9uL2RpYWxvZy9kaWFsb2dzLmpzXG5cbihmdW5jdGlvbihtb2QpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PSBcIm9iamVjdFwiKSAvLyBDb21tb25KU1xuICAgIG1vZChyZXF1aXJlKFwiLi4vbGliL2NvZGVtaXJyb3JcIiksIHJlcXVpcmUoXCIuLi9hZGRvbi9zZWFyY2gvc2VhcmNoY3Vyc29yXCIpLCByZXF1aXJlKFwiLi4vYWRkb24vZWRpdC9tYXRjaGJyYWNrZXRzXCIpKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgZGVmaW5lKFtcIi4uL2xpYi9jb2RlbWlycm9yXCIsIFwiLi4vYWRkb24vc2VhcmNoL3NlYXJjaGN1cnNvclwiLCBcIi4uL2FkZG9uL2VkaXQvbWF0Y2hicmFja2V0c1wiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgdmFyIG1hcCA9IENvZGVNaXJyb3Iua2V5TWFwLnN1YmxpbWUgPSB7ZmFsbHRocm91Z2g6IFwiZGVmYXVsdFwifTtcbiAgdmFyIGNtZHMgPSBDb2RlTWlycm9yLmNvbW1hbmRzO1xuICB2YXIgUG9zID0gQ29kZU1pcnJvci5Qb3M7XG4gIHZhciBtYWMgPSBDb2RlTWlycm9yLmtleU1hcFtcImRlZmF1bHRcIl0gPT0gQ29kZU1pcnJvci5rZXlNYXAubWFjRGVmYXVsdDtcbiAgdmFyIGN0cmwgPSBtYWMgPyBcIkNtZC1cIiA6IFwiQ3RybC1cIjtcblxuICAvLyBUaGlzIGlzIG5vdCBleGFjdGx5IFN1YmxpbWUncyBhbGdvcml0aG0uIEkgY291bGRuJ3QgbWFrZSBoZWFkcyBvciB0YWlscyBvZiB0aGF0LlxuICBmdW5jdGlvbiBmaW5kUG9zU3Vid29yZChkb2MsIHN0YXJ0LCBkaXIpIHtcbiAgICBpZiAoZGlyIDwgMCAmJiBzdGFydC5jaCA9PSAwKSByZXR1cm4gZG9jLmNsaXBQb3MoUG9zKHN0YXJ0LmxpbmUgLSAxKSk7XG4gICAgdmFyIGxpbmUgPSBkb2MuZ2V0TGluZShzdGFydC5saW5lKTtcbiAgICBpZiAoZGlyID4gMCAmJiBzdGFydC5jaCA+PSBsaW5lLmxlbmd0aCkgcmV0dXJuIGRvYy5jbGlwUG9zKFBvcyhzdGFydC5saW5lICsgMSwgMCkpO1xuICAgIHZhciBzdGF0ZSA9IFwic3RhcnRcIiwgdHlwZTtcbiAgICBmb3IgKHZhciBwb3MgPSBzdGFydC5jaCwgZSA9IGRpciA8IDAgPyAwIDogbGluZS5sZW5ndGgsIGkgPSAwOyBwb3MgIT0gZTsgcG9zICs9IGRpciwgaSsrKSB7XG4gICAgICB2Y
23459XIgbmV4dCA9IGxpbmUuY2hhckF0KGRpciA8IDAgPyBwb3MgLSAxIDogcG9zKTtcbiAgICAgIHZhciBjYXQgPSBuZXh0ICE9IFwiX1wiICYmIENvZGVNaXJyb3IuaXNXb3JkQ2hhcihuZXh0KSA/IFwid1wiIDogXCJvXCI7XG4gICAgICBpZiAoY2F0ID09IFwid1wiICYmIG5leHQudG9VcHBlckNhc2UoKSA9PSBuZXh0KSBjYXQgPSBcIldcIjtcbiAgICAgIGlmIChzdGF0ZSA9PSBcInN0YXJ0XCIpIHtcbiAgICAgICAgaWYgKGNhdCAhPSBcIm9cIikgeyBzdGF0ZSA9IFwiaW5cIjsgdHlwZSA9IGNhdDsgfVxuICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PSBcImluXCIpIHtcbiAgICAgICAgaWYgKHR5cGUgIT0gY2F0KSB7XG4gICAgICAgICAgaWYgKHR5cGUgPT0gXCJ3XCIgJiYgY2F0ID09IFwiV1wiICYmIGRpciA8IDApIHBvcy0tO1xuICAgICAgICAgIGlmICh0eXBlID09IFwiV1wiICYmIGNhdCA9PSBcIndcIiAmJiBkaXIgPiAwKSB7IHR5cGUgPSBcIndcIjsgY29udGludWU7IH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gUG9zKHN0YXJ0LmxpbmUsIHBvcyk7XG4gIH1cblxuICBmdW5jdGlvbiBtb3ZlU3Vid29yZChjbSwgZGlyKSB7XG4gICAgY20uZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uKHJhbmdlKSB7XG4gICAgICBpZiAoY20uZGlzcGxheS5zaGlmdCB8fCBjbS5kb2MuZXh0ZW5kIHx8IHJhbmdlLmVtcHR5KCkpXG4gICAgICAgIHJldHVybiBmaW5kUG9zU3Vid29yZChjbS5kb2MsIHJhbmdlLmhlYWQsIGRpcik7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiBkaXIgPCAwID8gcmFuZ2UuZnJvbSgpIDogcmFuZ2UudG8oKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNtZHNbbWFwW1wiQWx0LUxlZnRcIl0gPSBcImdvU3Vid29yZExlZnRcIl0gPSBmdW5jdGlvbihjbSkgeyBtb3ZlU3Vid29yZChjbSwgLTEpOyB9O1xuICBjbWRzW21hcFtcIkFsdC1SaWdodFwiXSA9IFwiZ29TdWJ3b3JkUmlnaHRcIl0gPSBmdW5jdGlvbihjbSkgeyBtb3ZlU3Vid29yZChjbSwgMSk7IH07XG5cbiAgdmFyIHNjcm9sbExpbmVDb21ibyA9IG1hYyA/IFwiQ3RybC1BbHQtXCIgOiBcIkN0cmwtXCI7XG5cbiAgY21kc1ttYXBbc2Nyb2xsTGluZUNvbWJvICsgXCJVcFwiXSA9IFwic2Nyb2xsTGluZVVwXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICB2YXIgaW5mbyA9IGNtLmdldFNjcm9sbEluZm8oKTtcbiAgICBpZiAoIWNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHtcbiAgICAgIHZhciB2aXNpYmxlQm90dG9tTGluZSA9IGNtLmxpbmVBdEhlaWdodChpbmZvLnRvcCArIGluZm8uY2xpZW50SGVpZ2h0LCBcImxvY2FsXCIpO1xuICAgICAgaWYgKGNtLmdldEN1cnNvcigpLmxpbmUgPj0gdmlzaWJsZUJvdHRvbUxpbmUpXG4gICAgICAgIGNtLmV4ZWNDb21tYW5kKFwiZ29MaW5lVXBcIik7XG4gICAgfVxuICAgIGNtLnNjcm9sbFRvKG51bGwsIGluZm8udG9wIC0gY20uZGVmYXVsdFRleHRIZWlnaHQoKSk7XG4gIH07XG4gIGNtZHNbbWFwW3Njcm9sbExpbmVDb21ibyArIFwiRG93blwiXSA9IFwic2Nyb2xsTGluZURvd25cIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBpbmZvID0gY20uZ2V0U2Nyb2xsSW5mbygpO1xuICAgIGlmICghY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgdmFyIHZpc2libGVUb3BMaW5lID0gY20ubGluZUF0SGVpZ2h0KGluZm8udG9wLCBcImxvY2FsXCIpKzE7XG4gICAgICBpZiAoY20uZ2V0Q3Vyc29yKCkubGluZSA8PSB2aXNpYmxlVG9wTGluZSlcbiAgICAgICAgY20uZXhlY0NvbW1hbmQoXCJnb0xpbmVEb3duXCIpO1xuICAgIH1cbiAgICBjbS5zY3JvbGxUbyhudWxsLCBpbmZvLnRvcCArIGNtLmRlZmF1bHRUZXh0SGVpZ2h0KCkpO1xuICB9O1xuXG4gIGNtZHNbbWFwW1wiU2hpZnQtXCIgKyBjdHJsICsgXCJMXCJdID0gXCJzcGxpdFNlbGVjdGlvbkJ5TGluZVwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgdmFyIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCksIGxpbmVSYW5nZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGZyb20gPSByYW5nZXNbaV0uZnJvbSgpLCB0byA9IHJhbmdlc1tpXS50bygpO1xuICAgICAgZm9yICh2YXIgbGluZSA9IGZyb20ubGluZTsgbGluZSA8PSB0by5saW5lOyArK2xpbmUpXG4gICAgICAgIGlmICghKHRvLmxpbmUgPiBmcm9tLmxpbmUgJiYgbGluZSA9PSB0by5saW5lICYmIHRvLmNoID09IDApKVxuICAgICAgICAgIGxpbmVSYW5nZXMucHVzaCh7YW5jaG9yOiBsaW5lID09IGZyb20ubGluZSA/IGZyb20gOiBQb3MobGluZSwgMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkOiBsaW5lID09IHRvLmxpbmUgPyB0byA6IFBvcyhsaW5lKX0pO1xuICAgIH1cbiAgICBjbS5zZXRTZWxlY3Rpb25zKGxpbmVSYW5nZXMsIDApO1xuICB9O1xuXG4gIG1hcFtcIlNoaWZ0LVRhYlwiXSA9IFwiaW5kZW50TGVzc1wiO1xuXG4gIGNtZHNbbWFwW1wiRXNjXCJdID0gXCJzaW5nbGVTZWxlY3Rpb25Ub3BcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciByYW5nZSA9IGNtLmxpc3RTZWxlY3Rpb25zKClbMF07XG4gICAgY20uc2V0U2VsZWN0aW9uKHJhbmdlLmFuY2hvciwgcmFuZ2UuaGVhZCwge3Njcm9sbDogZmFsc2V9KTtcbiAgfTtcblxuICBjbWRzW21hcFtjdHJsICsgXCJMXCJdID0gXCJzZWxlY3RMaW5lXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKSwgZXh0ZW5kZWQgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHJhbmdlID0gcmFuZ2VzW2ldO1xuICAgICAgZXh0ZW5kZWQucHVzaCh7YW5jaG9yOiBQb3MocmFuZ2UuZnJvbSgpLmxpbmUsIDApLFxuICAgICAgICAgICAgICAgICAgICAgaGVhZDogUG9zKHJhbmdlLnRvKCkubGluZSArIDEsIDApfSk7XG4gICAgfVxuICAgIGNtLnNldFNlbGVjdGlvbnMoZXh0ZW5kZWQpO1xuICB9O1xuXG4gIG1hcFtcIlNoaWZ0LVwiICsgY3RybCArIFwiS1wiXSA9IFwiZGVsZXRlTGluZVwiO1xuXG4gIGZ1bmN0aW9uIGluc2VydExpbmUoY20sIGFib3ZlKSB7XG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGxlbiA9IGNtLmxpc3RTZWxlY3Rpb25zKCkubGVuZ3RoLCBuZXdTZWxlY3Rpb24gPSBbXSwgbGFzdCA9IC0xO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2Y
23459XIgaGVhZCA9IGNtLmxpc3RTZWxlY3Rpb25zKClbaV0uaGVhZDtcbiAgICAgICAgaWYgKGhlYWQubGluZSA8PSBsYXN0KSBjb250aW51ZTtcbiAgICAgICAgdmFyIGF0ID0gUG9zKGhlYWQubGluZSArIChhYm92ZSA/IDAgOiAxKSwgMCk7XG4gICAgICAgIGNtLnJlcGxhY2VSYW5nZShcIlxcblwiLCBhdCwgbnVsbCwgXCIraW5zZXJ0TGluZVwiKTtcbiAgICAgICAgY20uaW5kZW50TGluZShhdC5saW5lLCBudWxsLCB0cnVlKTtcbiAgICAgICAgbmV3U2VsZWN0aW9uLnB1c2goe2hlYWQ6IGF0LCBhbmNob3I6IGF0fSk7XG4gICAgICAgIGxhc3QgPSBoZWFkLmxpbmUgKyAxO1xuICAgICAgfVxuICAgICAgY20uc2V0U2VsZWN0aW9ucyhuZXdTZWxlY3Rpb24pO1xuICAgIH0pO1xuICB9XG5cbiAgY21kc1ttYXBbY3RybCArIFwiRW50ZXJcIl0gPSBcImluc2VydExpbmVBZnRlclwiXSA9IGZ1bmN0aW9uKGNtKSB7IGluc2VydExpbmUoY20sIGZhbHNlKTsgfTtcblxuICBjbWRzW21hcFtcIlNoaWZ0LVwiICsgY3RybCArIFwiRW50ZXJcIl0gPSBcImluc2VydExpbmVCZWZvcmVcIl0gPSBmdW5jdGlvbihjbSkgeyBpbnNlcnRMaW5lKGNtLCB0cnVlKTsgfTtcblxuICBmdW5jdGlvbiB3b3JkQXQoY20sIHBvcykge1xuICAgIHZhciBzdGFydCA9IHBvcy5jaCwgZW5kID0gc3RhcnQsIGxpbmUgPSBjbS5nZXRMaW5lKHBvcy5saW5lKTtcbiAgICB3aGlsZSAoc3RhcnQgJiYgQ29kZU1pcnJvci5pc1dvcmRDaGFyKGxpbmUuY2hhckF0KHN0YXJ0IC0gMSkpKSAtLXN0YXJ0O1xuICAgIHdoaWxlIChlbmQgPCBsaW5lLmxlbmd0aCAmJiBDb2RlTWlycm9yLmlzV29yZENoYXIobGluZS5jaGFyQXQoZW5kKSkpICsrZW5kO1xuICAgIHJldHVybiB7ZnJvbTogUG9zKHBvcy5saW5lLCBzdGFydCksIHRvOiBQb3MocG9zLmxpbmUsIGVuZCksIHdvcmQ6IGxpbmUuc2xpY2Uoc3RhcnQsIGVuZCl9O1xuICB9XG5cbiAgY21kc1ttYXBbY3RybCArIFwiRFwiXSA9IFwic2VsZWN0TmV4dE9jY3VycmVuY2VcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBmcm9tID0gY20uZ2V0Q3Vyc29yKFwiZnJvbVwiKSwgdG8gPSBjbS5nZXRDdXJzb3IoXCJ0b1wiKTtcbiAgICB2YXIgZnVsbFdvcmQgPSBjbS5zdGF0ZS5zdWJsaW1lRmluZEZ1bGxXb3JkID09IGNtLmRvYy5zZWw7XG4gICAgaWYgKENvZGVNaXJyb3IuY21wUG9zKGZyb20sIHRvKSA9PSAwKSB7XG4gICAgICB2Y
23459XIgd29yZCA9IHdvcmRBdChjbSwgZnJvbSk7XG4gICAgICBpZiAoIXdvcmQud29yZCkgcmV0dXJuO1xuICAgICAgY20uc2V0U2VsZWN0aW9uKHdvcmQuZnJvbSwgd29yZC50byk7XG4gICAgICBmdWxsV29yZCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB0ZXh0ID0gY20uZ2V0UmFuZ2UoZnJvbSwgdG8pO1xuICAgICAgdmFyIHF1ZXJ5ID0gZnVsbFdvcmQgPyBuZXcgUmVnRXhwKFwiXFxcXGJcIiArIHRleHQgKyBcIlxcXFxiXCIpIDogdGV4dDtcbiAgICAgIHZhciBjdXIgPSBjbS5nZXRTZWFyY2hDdXJzb3IocXVlcnksIHRvKTtcbiAgICAgIGlmIChjdXIuZmluZE5leHQoKSkge1xuICAgICAgICBjbS5hZGRTZWxlY3Rpb24oY3VyLmZyb20oKSwgY3VyLnRvKCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3VyID0gY20uZ2V0U2VhcmNoQ3Vyc29yKHF1ZXJ5LCBQb3MoY20uZmlyc3RMaW5lKCksIDApKTtcbiAgICAgICAgaWYgKGN1ci5maW5kTmV4dCgpKVxuICAgICAgICAgIGNtLmFkZFNlbGVjdGlvbihjdXIuZnJvbSgpLCBjdXIudG8oKSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChmdWxsV29yZClcbiAgICAgIGNtLnN0YXRlLnN1YmxpbWVGaW5kRnVsbFdvcmQgPSBjbS5kb2Muc2VsO1xuICB9O1xuXG4gIHZhciBtaXJyb3IgPSBcIigpe31bXVwiO1xuICBmdW5jdGlvbiBzZWxlY3RCZXR3ZWVuQnJhY2tldHMoY20pIHtcbiAgICB2YXIgcG9zID0gY20uZ2V0Q3Vyc29yKCksIG9wZW5pbmcgPSBjbS5zY2FuRm9yQnJhY2tldChwb3MsIC0xKTtcbiAgICBpZiAoIW9wZW5pbmcpIHJldHVybjtcbiAgICBmb3IgKDs7KSB7XG4gICAgICB2Y
23459XIgY2xvc2luZyA9IGNtLnNjYW5Gb3JCcmFja2V0KHBvcywgMSk7XG4gICAgICBpZiAoIWNsb3NpbmcpIHJldHVybjtcbiAgICAgIGlmIChjbG9zaW5nLmNoID09IG1pcnJvci5jaGFyQXQobWlycm9yLmluZGV4T2Yob3BlbmluZy5jaCkgKyAxKSkge1xuICAgICAgICBjbS5zZXRTZWxlY3Rpb24oUG9zKG9wZW5pbmcucG9zLmxpbmUsIG9wZW5pbmcucG9zLmNoICsgMSksIGNsb3NpbmcucG9zLCBmYWxzZSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcG9zID0gUG9zKGNsb3NpbmcucG9zLmxpbmUsIGNsb3NpbmcucG9zLmNoICsgMSk7XG4gICAgfVxuICB9XG5cbiAgY21kc1ttYXBbXCJTaGlmdC1cIiArIGN0cmwgKyBcIlNwYWNlXCJdID0gXCJzZWxlY3RTY29wZVwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgc2VsZWN0QmV0d2VlbkJyYWNrZXRzKGNtKSB8fCBjbS5leGVjQ29tbWFuZChcInNlbGVjdEFsbFwiKTtcbiAgfTtcbiAgY21kc1ttYXBbXCJTaGlmdC1cIiArIGN0cmwgKyBcIk1cIl0gPSBcInNlbGVjdEJldHdlZW5CcmFja2V0c1wiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgaWYgKCFzZWxlY3RCZXR3ZWVuQnJhY2tldHMoY20pKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICB9O1xuXG4gIGNtZHNbbWFwW2N0cmwgKyBcIk1cIl0gPSBcImdvVG9CcmFja2V0XCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS5leHRlbmRTZWxlY3Rpb25zQnkoZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgIHZhciBuZXh0ID0gY20uc2NhbkZvckJyYWNrZXQocmFuZ2UuaGVhZCwgMSk7XG4gICAgICBpZiAobmV4dCAmJiBDb2RlTWlycm9yLmNtcFBvcyhuZXh0LnBvcywgcmFuZ2UuaGVhZCkgIT0gMCkgcmV0dXJuIG5leHQucG9zO1xuICAgICAgdmFyIHByZXYgPSBjbS5zY2FuRm9yQnJhY2tldChyYW5nZS5oZWFkLCAtMSk7XG4gICAgICByZXR1cm4gcHJldiAmJiBQb3MocHJldi5wb3MubGluZSwgcHJldi5wb3MuY2ggKyAxKSB8fCByYW5nZS5oZWFkO1xuICAgIH0pO1xuICB9O1xuXG4gIHZhciBzd2FwTGluZUNvbWJvID0gbWFjID8gXCJDbWQtQ3RybC1cIiA6IFwiU2hpZnQtQ3RybC1cIjtcblxuICBjbWRzW21hcFtzd2FwTGluZUNvbWJvICsgXCJVcFwiXSA9IFwic3dhcExpbmVVcFwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgdmFyIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCksIGxpbmVzVG9Nb3ZlID0gW10sIGF0ID0gY20uZmlyc3RMaW5lKCkgLSAxLCBuZXdTZWxzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXSwgZnJvbSA9IHJhbmdlLmZyb20oKS5saW5lIC0gMSwgdG8gPSByYW5nZS50bygpLmxpbmU7XG4gICAgICBuZXdTZWxzLnB1c2goe2FuY2hvcjogUG9zKHJhbmdlLmFuY2hvci5saW5lIC0gMSwgcmFuZ2UuYW5jaG9yLmNoKSxcbiAgICAgICAgICAgICAgICAgICAgaGVhZDogUG9zKHJhbmdlLmhlYWQubGluZSAtIDEsIHJhbmdlLmhlYWQuY2gpfSk7XG4gICAgICBpZiAocmFuZ2UudG8oKS5jaCA9PSAwICYmICFyYW5nZS5lbXB0eSgpKSAtLXRvO1xuICAgICAgaWYgKGZyb20gPiBhdCkgbGluZXNUb01vdmUucHVzaChmcm9tLCB0byk7XG4gICAgICBlbHNlIGlmIChsaW5lc1RvTW92ZS5sZW5ndGgpIGxpbmVzVG9Nb3ZlW2xpbmVzVG9Nb3ZlLmxlbmd0aCAtIDFdID0gdG87XG4gICAgICBhdCA9IHRvO1xuICAgIH1cbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzVG9Nb3ZlLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgIHZhciBmcm9tID0gbGluZXNUb01vdmVbaV0sIHRvID0gbGluZXNUb01vdmVbaSArIDFdO1xuICAgICAgICB2Y
23459XIgbGluZSA9IGNtLmdldExpbmUoZnJvbSk7XG4gICAgICAgIGNtLnJlcGxhY2VSYW5nZShcIlwiLCBQb3MoZnJvbSwgMCksIFBvcyhmcm9tICsgMSwgMCksIFwiK3N3YXBMaW5lXCIpO1xuICAgICAgICBpZiAodG8gPiBjbS5sYXN0TGluZSgpKVxuICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShcIlxcblwiICsgbGluZSwgUG9zKGNtLmxhc3RMaW5lKCkpLCBudWxsLCBcIitzd2FwTGluZVwiKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShsaW5lICsgXCJcXG5cIiwgUG9zKHRvLCAwKSwgbnVsbCwgXCIrc3dhcExpbmVcIik7XG4gICAgICB9XG4gICAgICBjbS5zZXRTZWxlY3Rpb25zKG5ld1NlbHMpO1xuICAgICAgY20uc2Nyb2xsSW50b1ZpZXcoKTtcbiAgICB9KTtcbiAgfTtcblxuICBjbWRzW21hcFtzd2FwTGluZUNvbWJvICsgXCJEb3duXCJdID0gXCJzd2FwTGluZURvd25cIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciByYW5nZXMgPSBjbS5saXN0U2VsZWN0aW9ucygpLCBsaW5lc1RvTW92ZSA9IFtdLCBhdCA9IGNtLmxhc3RMaW5lKCkgKyAxO1xuICAgIGZvciAodmFyIGkgPSByYW5nZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXSwgZnJvbSA9IHJhbmdlLnRvKCkubGluZSArIDEsIHRvID0gcmFuZ2UuZnJvbSgpLmxpbmU7XG4gICAgICBpZiAocmFuZ2UudG8oKS5jaCA9PSAwICYmICFyYW5nZS5lbXB0eSgpKSBmcm9tLS07XG4gICAgICBpZiAoZnJvbSA8IGF0KSBsaW5lc1RvTW92ZS5wdXNoKGZyb20sIHRvKTtcbiAgICAgIGVsc2UgaWYgKGxpbmVzVG9Nb3ZlLmxlbmd0aCkgbGluZXNUb01vdmVbbGluZXNUb01vdmUubGVuZ3RoIC0gMV0gPSB0bztcbiAgICAgIGF0ID0gdG87XG4gICAgfVxuICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIGZvciAodmFyIGkgPSBsaW5lc1RvTW92ZS5sZW5ndGggLSAyOyBpID49IDA7IGkgLT0gMikge1xuICAgICAgICB2Y
23459XIgZnJvbSA9IGxpbmVzVG9Nb3ZlW2ldLCB0byA9IGxpbmVzVG9Nb3ZlW2kgKyAxXTtcbiAgICAgICAgdmFyIGxpbmUgPSBjbS5nZXRMaW5lKGZyb20pO1xuICAgICAgICBpZiAoZnJvbSA9PSBjbS5sYXN0TGluZSgpKVxuICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShcIlwiLCBQb3MoZnJvbSAtIDEpLCBQb3MoZnJvbSksIFwiK3N3YXBMaW5lXCIpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgY20ucmVwbGFjZVJhbmdlKFwiXCIsIFBvcyhmcm9tLCAwKSwgUG9zKGZyb20gKyAxLCAwKSwgXCIrc3dhcExpbmVcIik7XG4gICAgICAgIGNtLnJlcGxhY2VSYW5nZShsaW5lICsgXCJcXG5cIiwgUG9zKHRvLCAwKSwgbnVsbCwgXCIrc3dhcExpbmVcIik7XG4gICAgICB9XG4gICAgICBjbS5zY3JvbGxJbnRvVmlldygpO1xuICAgIH0pO1xuICB9O1xuXG4gIG1hcFtjdHJsICsgXCIvXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS50b2dnbGVDb21tZW50KHsgaW5kZW50OiB0cnVlIH0pO1xuICB9XG5cbiAgY21kc1ttYXBbY3RybCArIFwiSlwiXSA9IFwiam9pbkxpbmVzXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKSwgam9pbmVkID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXSwgZnJvbSA9IHJhbmdlLmZyb20oKTtcbiAgICAgIHZhciBzdGFydCA9IGZyb20ubGluZSwgZW5kID0gcmFuZ2UudG8oKS5saW5lO1xuICAgICAgd2hpbGUgKGkgPCByYW5nZXMubGVuZ3RoIC0gMSAmJiByYW5nZXNbaSArIDFdLmZyb20oKS5saW5lID09IGVuZClcbiAgICAgICAgZW5kID0gcmFuZ2VzWysraV0udG8oKS5saW5lO1xuICAgICAgam9pbmVkLnB1c2goe3N0YXJ0OiBzdGFydCwgZW5kOiBlbmQsIGFuY2hvcjogIXJhbmdlLmVtcHR5KCkgJiYgZnJvbX0pO1xuICAgIH1cbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICB2Y
23459XIgb2Zmc2V0ID0gMCwgcmFuZ2VzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGpvaW5lZC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb2JqID0gam9pbmVkW2ldO1xuICAgICAgICB2YXIgYW5jaG9yID0gb2JqLmFuY2hvciAmJiBQb3Mob2JqLmFuY2hvci5saW5lIC0gb2Zmc2V0LCBvYmouYW5jaG9yLmNoKSwgaGVhZDtcbiAgICAgICAgZm9yICh2YXIgbGluZSA9IG9iai5zdGFydDsgbGluZSA8PSBvYmouZW5kOyBsaW5lKyspIHtcbiAgICAgICAgICB2YXIgYWN0dWFsID0gbGluZSAtIG9mZnNldDtcbiAgICAgICAgICBpZiAobGluZSA9PSBvYmouZW5kKSBoZWFkID0gUG9zKGFjdHVhbCwgY20uZ2V0TGluZShhY3R1YWwpLmxlbmd0aCArIDEpO1xuICAgICAgICAgIGlmIChhY3R1YWwgPCBjbS5sYXN0TGluZSgpKSB7XG4gICAgICAgICAgICBjbS5yZXBsYWNlUmFuZ2UoXCIgXCIsIFBvcyhhY3R1YWwpLCBQb3MoYWN0dWFsICsgMSwgL15cXHMqLy5leGVjKGNtLmdldExpbmUoYWN0dWFsICsgMSkpWzBdLmxlbmd0aCkpO1xuICAgICAgICAgICAgKytvZmZzZXQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJhbmdlcy5wdXNoKHthbmNob3I6IGFuY2hvciB8fCBoZWFkLCBoZWFkOiBoZWFkfSk7XG4gICAgICB9XG4gICAgICBjbS5zZXRTZWxlY3Rpb25zKHJhbmdlcywgMCk7XG4gICAgfSk7XG4gIH07XG5cbiAgY21kc1ttYXBbXCJTaGlmdC1cIiArIGN0cmwgKyBcIkRcIl0gPSBcImR1cGxpY2F0ZUxpbmVcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgIHZhciByYW5nZUNvdW50ID0gY20ubGlzdFNlbGVjdGlvbnMoKS5sZW5ndGg7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlQ291bnQ7IGkrKykge1xuICAgICAgICB2Y
23459XIgcmFuZ2UgPSBjbS5saXN0U2VsZWN0aW9ucygpW2ldO1xuICAgICAgICBpZiAocmFuZ2UuZW1wdHkoKSlcbiAgICAgICAgICBjbS5yZXBsYWNlUmFuZ2UoY20uZ2V0TGluZShyYW5nZS5oZWFkLmxpbmUpICsgXCJcXG5cIiwgUG9zKHJhbmdlLmhlYWQubGluZSwgMCkpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgY20ucmVwbGFjZVJhbmdlKGNtLmdldFJhbmdlKHJhbmdlLmZyb20oKSwgcmFuZ2UudG8oKSksIHJhbmdlLmZyb20oKSk7XG4gICAgICB9XG4gICAgICBjbS5zY3JvbGxJbnRvVmlldygpO1xuICAgIH0pO1xuICB9O1xuXG4gIG1hcFtjdHJsICsgXCJUXCJdID0gXCJ0cmFuc3Bvc2VDaGFyc1wiO1xuXG4gIGZ1bmN0aW9uIHNvcnRMaW5lcyhjbSwgY2FzZVNlbnNpdGl2ZSkge1xuICAgIHZhciByYW5nZXMgPSBjbS5saXN0U2VsZWN0aW9ucygpLCB0b1NvcnQgPSBbXSwgc2VsZWN0ZWQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgIGlmIChyYW5nZS5lbXB0eSgpKSBjb250aW51ZTtcbiAgICAgIHZhciBmcm9tID0gcmFuZ2UuZnJvbSgpLmxpbmUsIHRvID0gcmFuZ2UudG8oKS5saW5lO1xuICAgICAgd2hpbGUgKGkgPCByYW5nZXMubGVuZ3RoIC0gMSAmJiByYW5nZXNbaSArIDFdLmZyb20oKS5saW5lID09IHRvKVxuICAgICAgICB0byA9IHJhbmdlWysraV0udG8oKS5saW5lO1xuICAgICAgdG9Tb3J0LnB1c2goZnJvbSwgdG8pO1xuICAgIH1cbiAgICBpZiAodG9Tb3J0Lmxlbmd0aCkgc2VsZWN0ZWQgPSB0cnVlO1xuICAgIGVsc2UgdG9Tb3J0LnB1c2goY20uZmlyc3RMaW5lKCksIGNtLmxhc3RMaW5lKCkpO1xuXG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJhbmdlcyA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b1NvcnQubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgdmFyIGZyb20gPSB0b1NvcnRbaV0sIHRvID0gdG9Tb3J0W2kgKyAxXTtcbiAgICAgICAgdmFyIHN0YXJ0ID0gUG9zKGZyb20sIDApLCBlbmQgPSBQb3ModG8pO1xuICAgICAgICB2Y
23459XIgbGluZXMgPSBjbS5nZXRSYW5nZShzdGFydCwgZW5kLCBmYWxzZSk7XG4gICAgICAgIGlmIChjYXNlU2Vuc2l0aXZlKVxuICAgICAgICAgIGxpbmVzLnNvcnQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGxpbmVzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgdmFyIGF1ID0gYS50b1VwcGVyQ2FzZSgpLCBidSA9IGIudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIGlmIChhdSAhPSBidSkgeyBhID0gYXU7IGIgPSBidTsgfVxuICAgICAgICAgICAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID09IGIgPyAwIDogMTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgY20ucmVwbGFjZVJhbmdlKGxpbmVzLCBzdGFydCwgZW5kKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkKSByYW5nZXMucHVzaCh7YW5jaG9yOiBzdGFydCwgaGVhZDogZW5kfSk7XG4gICAgICB9XG4gICAgICBpZiAoc2VsZWN0ZWQpIGNtLnNldFNlbGVjdGlvbnMocmFuZ2VzLCAwKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNtZHNbbWFwW1wiRjlcIl0gPSBcInNvcnRMaW5lc1wiXSA9IGZ1bmN0aW9uKGNtKSB7IHNvcnRMaW5lcyhjbSwgdHJ1ZSk7IH07XG4gIGNtZHNbbWFwW2N0cmwgKyBcIkY5XCJdID0gXCJzb3J0TGluZXNJbnNlbnNpdGl2ZVwiXSA9IGZ1bmN0aW9uKGNtKSB7IHNvcnRMaW5lcyhjbSwgZmFsc2UpOyB9O1xuXG4gIGNtZHNbbWFwW1wiRjJcIl0gPSBcIm5leHRCb29rbWFya1wiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgdmFyIG1hcmtzID0gY20uc3RhdGUuc3VibGltZUJvb2ttYXJrcztcbiAgICBpZiAobWFya3MpIHdoaWxlIChtYXJrcy5sZW5ndGgpIHtcbiAgICAgIHZhciBjdXJyZW50ID0gbWFya3Muc2hpZnQoKTtcbiAgICAgIHZhciBmb3VuZCA9IGN1cnJlbnQuZmluZCgpO1xuICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgIG1hcmtzLnB1c2goY3VycmVudCk7XG4gICAgICAgIHJldHVybiBjbS5zZXRTZWxlY3Rpb24oZm91bmQuZnJvbSwgZm91bmQudG8pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBjbWRzW21hcFtcIlNoaWZ0LUYyXCJdID0gXCJwcmV2Qm9va21hcmtcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBtYXJrcyA9IGNtLnN0YXRlLnN1YmxpbWVCb29rbWFya3M7XG4gICAgaWYgKG1hcmtzKSB3aGlsZSAobWFya3MubGVuZ3RoKSB7XG4gICAgICBtYXJrcy51bnNoaWZ0KG1hcmtzLnBvcCgpKTtcbiAgICAgIHZhciBmb3VuZCA9IG1hcmtzW21hcmtzLmxlbmd0aCAtIDFdLmZpbmQoKTtcbiAgICAgIGlmICghZm91bmQpXG4gICAgICAgIG1hcmtzLnBvcCgpO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gY20uc2V0U2VsZWN0aW9uKGZvdW5kLmZyb20sIGZvdW5kLnRvKTtcbiAgICB9XG4gIH07XG5cbiAgY21kc1ttYXBbY3RybCArIFwiRjJcIl0gPSBcInRvZ2dsZUJvb2ttYXJrXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICB2YXIgbWFya3MgPSBjbS5zdGF0ZS5zdWJsaW1lQm9va21hcmtzIHx8IChjbS5zdGF0ZS5zdWJsaW1lQm9va21hcmtzID0gW10pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgZnJvbSA9IHJhbmdlc1tpXS5mcm9tKCksIHRvID0gcmFuZ2VzW2ldLnRvKCk7XG4gICAgICB2YXIgZm91bmQgPSBjbS5maW5kTWFya3MoZnJvbSwgdG8pO1xuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBmb3VuZC5sZW5ndGg7IGorKykge1xuICAgICAgICBpZiAoZm91bmRbal0uc3VibGltZUJvb2ttYXJrKSB7XG4gICAgICAgICAgZm91bmRbal0uY2xlYXIoKTtcbiAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IG1hcmtzLmxlbmd0aDsgaysrKVxuICAgICAgICAgICAgaWYgKG1hcmtzW2tdID09IGZvdW5kW2pdKVxuICAgICAgICAgICAgICBtYXJrcy5zcGxpY2Uoay0tLCAxKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGogPT0gZm91bmQubGVuZ3RoKVxuICAgICAgICBtYXJrcy5wdXNoKGNtLm1hcmtUZXh0KGZyb20sIHRvLCB7c3VibGltZUJvb2ttYXJrOiB0cnVlLCBjbGVhcldoZW5FbXB0eTogZmFsc2V9KSk7XG4gICAgfVxuICB9O1xuXG4gIGNtZHNbbWFwW1wiU2hpZnQtXCIgKyBjdHJsICsgXCJGMlwiXSA9IFwiY2xlYXJCb29rbWFya3NcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBtYXJrcyA9IGNtLnN0YXRlLnN1YmxpbWVCb29rbWFya3M7XG4gICAgaWYgKG1hcmtzKSBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtzLmxlbmd0aDsgaSsrKSBtYXJrc1tpXS5jbGVhcigpO1xuICAgIG1hcmtzLmxlbmd0aCA9IDA7XG4gIH07XG5cbiAgY21kc1ttYXBbXCJBbHQtRjJcIl0gPSBcInNlbGVjdEJvb2ttYXJrc1wiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgdmFyIG1hcmtzID0gY20uc3RhdGUuc3VibGltZUJvb2ttYXJrcywgcmFuZ2VzID0gW107XG4gICAgaWYgKG1hcmtzKSBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgZm91bmQgPSBtYXJrc1tpXS5maW5kKCk7XG4gICAgICBpZiAoIWZvdW5kKVxuICAgICAgICBtYXJrcy5zcGxpY2UoaS0tLCAwKTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmFuZ2VzLnB1c2goe2FuY2hvcjogZm91bmQuZnJvbSwgaGVhZDogZm91bmQudG99KTtcbiAgICB9XG4gICAgaWYgKHJhbmdlcy5sZW5ndGgpXG4gICAgICBjbS5zZXRTZWxlY3Rpb25zKHJhbmdlcywgMCk7XG4gIH07XG5cbiAgbWFwW1wiQWx0LVFcIl0gPSBcIndyYXBMaW5lc1wiO1xuXG4gIHZhciBjSyA9IGN0cmwgKyBcIksgXCI7XG5cbiAgZnVuY3Rpb24gbW9kaWZ5V29yZE9yU2VsZWN0aW9uKGNtLCBtb2QpIHtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKSwgaW5kaWNlcyA9IFtdLCByZXBsYWNlbWVudHMgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgICAgaWYgKHJhbmdlLmVtcHR5KCkpIHsgaW5kaWNlcy5wdXNoKGkpOyByZXBsYWNlbWVudHMucHVzaChcIlwiKTsgfVxuICAgICAgICBlbHNlIHJlcGxhY2VtZW50cy5wdXNoKG1vZChjbS5nZXRSYW5nZShyYW5nZS5mcm9tKCksIHJhbmdlLnRvKCkpKSk7XG4gICAgICB9XG4gICAgICBjbS5yZXBsYWNlU2VsZWN0aW9ucyhyZXBsYWNlbWVudHMsIFwiYXJvdW5kXCIsIFwiY2FzZVwiKTtcbiAgICAgIGZvciAodmFyIGkgPSBpbmRpY2VzLmxlbmd0aCAtIDEsIGF0OyBpID49IDA7IGktLSkge1xuICAgICAgICB2Y
23459XIgcmFuZ2UgPSByYW5nZXNbaW5kaWNlc1tpXV07XG4gICAgICAgIGlmIChhdCAmJiBDb2RlTWlycm9yLmNtcFBvcyhyYW5nZS5oZWFkLCBhdCkgPiAwKSBjb250aW51ZTtcbiAgICAgICAgdmFyIHdvcmQgPSB3b3JkQXQoY20sIHJhbmdlLmhlYWQpO1xuICAgICAgICBhdCA9IHdvcmQuZnJvbTtcbiAgICAgICAgY20ucmVwbGFjZVJhbmdlKG1vZCh3b3JkLndvcmQpLCB3b3JkLmZyb20sIHdvcmQudG8pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbWFwW2NLICsgY3RybCArIFwiQmFja3NwYWNlXCJdID0gXCJkZWxMaW5lTGVmdFwiO1xuXG4gIGNtZHNbbWFwW1wiQmFja3NwYWNlXCJdID0gXCJzbWFydEJhY2tzcGFjZVwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgaWYgKGNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG5cbiAgICB2YXIgY3Vyc29yID0gY20uZ2V0Q3Vyc29yKCk7XG4gICAgdmFyIHRvU3RhcnRPZkxpbmUgPSBjbS5nZXRSYW5nZSh7bGluZTogY3Vyc29yLmxpbmUsIGNoOiAwfSwgY3Vyc29yKTtcbiAgICB2YXIgY29sdW1uID0gQ29kZU1pcnJvci5jb3VudENvbHVtbih0b1N0YXJ0T2ZMaW5lLCBudWxsLCBjbS5nZXRPcHRpb24oXCJ0YWJTaXplXCIpKTtcbiAgICB2YXIgaW5kZW50VW5pdCA9IGNtLmdldE9wdGlvbihcImluZGVudFVuaXRcIik7XG5cbiAgICBpZiAodG9TdGFydE9mTGluZSAmJiAhL1xcUy8udGVzdCh0b1N0YXJ0T2ZMaW5lKSAmJiBjb2x1bW4gJSBpbmRlbnRVbml0ID09IDApIHtcbiAgICAgIHZhciBwcmV2SW5kZW50ID0gbmV3IFBvcyhjdXJzb3IubGluZSxcbiAgICAgICAgQ29kZU1pcnJvci5maW5kQ29sdW1uKHRvU3RhcnRPZkxpbmUsIGNvbHVtbiAtIGluZGVudFVuaXQsIGluZGVudFVuaXQpKTtcblxuICAgICAgLy8gSWYgbm8gc21hcnQgZGVsZXRlIGlzIGhhcHBlbmluZyAoZHVlIHRvIHRhYiBzaXppbmcpIGp1c3QgZG8gYSByZWd1bGFyIGRlbGV0ZVxuICAgICAgaWYgKHByZXZJbmRlbnQuY2ggPT0gY3Vyc29yLmNoKSByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuXG4gICAgICByZXR1cm4gY20ucmVwbGFjZVJhbmdlKFwiXCIsIHByZXZJbmRlbnQsIGN1cnNvciwgXCIrZGVsZXRlXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gQ29kZU1pcnJvci5QYXNzO1xuICAgIH1cbiAgfTtcblxuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIktcIl0gPSBcImRlbExpbmVSaWdodFwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgY20ub3BlcmF0aW9uKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7XG4gICAgICBmb3IgKHZhciBpID0gcmFuZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKVxuICAgICAgICBjbS5yZXBsYWNlUmFuZ2UoXCJcIiwgcmFuZ2VzW2ldLmFuY2hvciwgUG9zKHJhbmdlc1tpXS50bygpLmxpbmUpLCBcIitkZWxldGVcIik7XG4gICAgICBjbS5zY3JvbGxJbnRvVmlldygpO1xuICAgIH0pO1xuICB9O1xuXG4gIGNtZHNbbWFwW2NLICsgY3RybCArIFwiVVwiXSA9IFwidXBjYXNlQXRDdXJzb3JcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIG1vZGlmeVdvcmRPclNlbGVjdGlvbihjbSwgZnVuY3Rpb24oc3RyKSB7IHJldHVybiBzdHIudG9VcHBlckNhc2UoKTsgfSk7XG4gIH07XG4gIGNtZHNbbWFwW2NLICsgY3RybCArIFwiTFwiXSA9IFwiZG93bmNhc2VBdEN1cnNvclwiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgbW9kaWZ5V29yZE9yU2VsZWN0aW9uKGNtLCBmdW5jdGlvbihzdHIpIHsgcmV0dXJuIHN0ci50b0xvd2VyQ2FzZSgpOyB9KTtcbiAgfTtcblxuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIlNwYWNlXCJdID0gXCJzZXRTdWJsaW1lTWFya1wiXSA9IGZ1bmN0aW9uKGNtKSB7XG4gICAgaWYgKGNtLnN0YXRlLnN1YmxpbWVNYXJrKSBjbS5zdGF0ZS5zdWJsaW1lTWFyay5jbGVhcigpO1xuICAgIGNtLnN0YXRlLnN1YmxpbWVNYXJrID0gY20uc2V0Qm9va21hcmsoY20uZ2V0Q3Vyc29yKCkpO1xuICB9O1xuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIkFcIl0gPSBcInNlbGVjdFRvU3VibGltZU1hcmtcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBmb3VuZCA9IGNtLnN0YXRlLnN1YmxpbWVNYXJrICYmIGNtLnN0YXRlLnN1YmxpbWVNYXJrLmZpbmQoKTtcbiAgICBpZiAoZm91bmQpIGNtLnNldFNlbGVjdGlvbihjbS5nZXRDdXJzb3IoKSwgZm91bmQpO1xuICB9O1xuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIldcIl0gPSBcImRlbGV0ZVRvU3VibGltZU1hcmtcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBmb3VuZCA9IGNtLnN0YXRlLnN1YmxpbWVNYXJrICYmIGNtLnN0YXRlLnN1YmxpbWVNYXJrLmZpbmQoKTtcbiAgICBpZiAoZm91bmQpIHtcbiAgICAgIHZhciBmcm9tID0gY20uZ2V0Q3Vyc29yKCksIHRvID0gZm91bmQ7XG4gICAgICBpZiAoQ29kZU1pcnJvci5jbXBQb3MoZnJvbSwgdG8pID4gMCkgeyB2YXIgdG1wID0gdG87IHRvID0gZnJvbTsgZnJvbSA9IHRtcDsgfVxuICAgICAgY20uc3RhdGUuc3VibGltZUtpbGxlZCA9IGNtLmdldFJhbmdlKGZyb20sIHRvKTtcbiAgICAgIGNtLnJlcGxhY2VSYW5nZShcIlwiLCBmcm9tLCB0byk7XG4gICAgfVxuICB9O1xuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIlhcIl0gPSBcInN3YXBXaXRoU3VibGltZU1hcmtcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciBmb3VuZCA9IGNtLnN0YXRlLnN1YmxpbWVNYXJrICYmIGNtLnN0YXRlLnN1YmxpbWVNYXJrLmZpbmQoKTtcbiAgICBpZiAoZm91bmQpIHtcbiAgICAgIGNtLnN0YXRlLnN1YmxpbWVNYXJrLmNsZWFyKCk7XG4gICAgICBjbS5zdGF0ZS5zdWJsaW1lTWFyayA9IGNtLnNldEJvb2ttYXJrKGNtLmdldEN1cnNvcigpKTtcbiAgICAgIGNtLnNldEN1cnNvcihmb3VuZCk7XG4gICAgfVxuICB9O1xuICBjbWRzW21hcFtjSyArIGN0cmwgKyBcIllcIl0gPSBcInN1YmxpbWVZYW5rXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICBpZiAoY20uc3RhdGUuc3VibGltZUtpbGxlZCAhPSBudWxsKVxuICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbihjbS5zdGF0ZS5zdWJsaW1lS2lsbGVkLCBudWxsLCBcInBhc3RlXCIpO1xuICB9O1xuXG4gIG1hcFtjSyArIGN0cmwgKyBcIkdcIl0gPSBcImNsZWFyQm9va21hcmtzXCI7XG4gIGNtZ
23459HNbbWFwW2NLICsgY3RybCArIFwiQ1wiXSA9IFwic2hvd0luQ2VudGVyXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICB2YXIgcG9zID0gY20uY3Vyc29yQ29vcmRzKG51bGwsIFwibG9jYWxcIik7XG4gICAgY20uc2Nyb2xsVG8obnVsbCwgKHBvcy50b3AgKyBwb3MuYm90dG9tKSAvIDIgLSBjbS5nZXRTY3JvbGxJbmZvKCkuY2xpZW50SGVpZ2h0IC8gMik7XG4gIH07XG5cbiAgY21kc1ttYXBbXCJTaGlmdC1BbHQtVXBcIl0gPSBcInNlbGVjdExpbmVzVXB3YXJkXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgICAgaWYgKHJhbmdlLmhlYWQubGluZSA+IGNtLmZpcnN0TGluZSgpKVxuICAgICAgICAgIGNtLmFkZFNlbGVjdGlvbihQb3MocmFuZ2UuaGVhZC5saW5lIC0gMSwgcmFuZ2UuaGVhZC5jaCkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuICBjbWRzW21hcFtcIlNoaWZ0LUFsdC1Eb3duXCJdID0gXCJzZWxlY3RMaW5lc0Rvd253YXJkXCJdID0gZnVuY3Rpb24oY20pIHtcbiAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgICAgaWYgKHJhbmdlLmhlYWQubGluZSA8IGNtLmxhc3RMaW5lKCkpXG4gICAgICAgICAgY20uYWRkU2VsZWN0aW9uKFBvcyhyYW5nZS5oZWFkLmxpbmUgKyAxLCByYW5nZS5oZWFkLmNoKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgZnVuY3Rpb24gZ2V0VGFyZ2V0KGNtKSB7XG4gICAgdmFyIGZyb20gPSBjbS5nZXRDdXJzb3IoXCJmcm9tXCIpLCB0byA9IGNtLmdldEN1cnNvcihcInRvXCIpO1xuICAgIGlmIChDb2RlTWlycm9yLmNtcFBvcyhmcm9tLCB0bykgPT0gMCkge1xuICAgICAgdmFyIHdvcmQgPSB3b3JkQXQoY20sIGZyb20pO1xuICAgICAgaWYgKCF3b3JkLndvcmQpIHJldHVybjtcbiAgICAgIGZyb20gPSB3b3JkLmZyb207XG4gICAgICB0byA9IHdvcmQudG87XG4gICAgfVxuICAgIHJldHVybiB7ZnJvbTogZnJvbSwgdG86IHRvLCBxdWVyeTogY20uZ2V0UmFuZ2UoZnJvbSwgdG8pLCB3b3JkOiB3b3JkfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmRBbmRHb1RvKGNtLCBmb3J3YXJkKSB7XG4gICAgdmFyIHRhcmdldCA9IGdldFRhcmdldChjbSk7XG4gICAgaWYgKCF0YXJnZXQpIHJldHVybjtcbiAgICB2YXIgcXVlcnkgPSB0YXJnZXQucXVlcnk7XG4gICAgdmFyIGN1ciA9IGNtLmdldFNlYXJjaEN1cnNvcihxdWVyeSwgZm9yd2FyZCA/IHRhcmdldC50byA6IHRhcmdldC5mcm9tKTtcblxuICAgIGlmIChmb3J3YXJkID8gY3VyLmZpbmROZXh0KCkgOiBjdXIuZmluZFByZXZpb3VzKCkpIHtcbiAgICAgIGNtLnNldFNlbGVjdGlvbihjdXIuZnJvbSgpLCBjdXIudG8oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN1ciA9IGNtLmdldFNlYXJjaEN1cnNvcihxdWVyeSwgZm9yd2FyZCA/IFBvcyhjbS5maXJzdExpbmUoKSwgMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGNtLmNsaXBQb3MoUG9zKGNtLmxhc3RMaW5lKCkpKSk7XG4gICAgICBpZiAoZm9yd2FyZCA/IGN1ci5maW5kTmV4dCgpIDogY3VyLmZpbmRQcmV2aW91cygpKVxuICAgICAgICBjbS5zZXRTZWxlY3Rpb24oY3VyLmZyb20oKSwgY3VyLnRvKCkpO1xuICAgICAgZWxzZSBpZiAodGFyZ2V0LndvcmQpXG4gICAgICAgIGNtLnNldFNlbGVjdGlvbih0YXJnZXQuZnJvbSwgdGFyZ2V0LnRvKTtcbiAgICB9XG4gIH07XG4gIGNtZHNbbWFwW2N0cmwgKyBcIkYzXCJdID0gXCJmaW5kVW5kZXJcIl0gPSBmdW5jdGlvbihjbSkgeyBmaW5kQW5kR29UbyhjbSwgdHJ1ZSk7IH07XG4gIGNtZHNbbWFwW1wiU2hpZnQtXCIgKyBjdHJsICsgXCJGM1wiXSA9IFwiZmluZFVuZGVyUHJldmlvdXNcIl0gPSBmdW5jdGlvbihjbSkgeyBmaW5kQW5kR29UbyhjbSxmYWxzZSk7IH07XG4gIGNtZHNbbWFwW1wiQWx0LUYzXCJdID0gXCJmaW5kQWxsVW5kZXJcIl0gPSBmdW5jdGlvbihjbSkge1xuICAgIHZhciB0YXJnZXQgPSBnZXRUYXJnZXQoY20pO1xuICAgIGlmICghdGFyZ2V0KSByZXR1cm47XG4gICAgdmFyIGN1ciA9IGNtLmdldFNlYXJjaEN1cnNvcih0YXJnZXQucXVlcnkpO1xuICAgIHZhciBtYXRjaGVzID0gW107XG4gICAgdmFyIHByaW1hcnlJbmRleCA9IC0xO1xuICAgIHdoaWxlIChjdXIuZmluZE5leHQoKSkge1xuICAgICAgbWF0Y2hlcy5wdXNoKHthbmNob3I6IGN1ci5mcm9tKCksIGhlYWQ6IGN1ci50bygpfSk7XG4gICAgICBpZiAoY3VyLmZyb20oKS5saW5lIDw9IHRhcmdldC5mcm9tLmxpbmUgJiYgY3VyLmZyb20oKS5jaCA8PSB0YXJnZXQuZnJvbS5jaClcbiAgICAgICAgcHJpbWFyeUluZGV4Kys7XG4gICAgfVxuICAgIGNtLnNldFNlbGVjdGlvbnMobWF0Y2hlcywgcHJpbWFyeUluZGV4KTtcbiAgfTtcblxuICBtYXBbXCJTaGlmdC1cIiArIGN0cmwgKyBcIltc
23459Il0gPSBcImZvbGRcIjtcbiAgbWFwW1wiU2hpZnQtXCIgKyBjdHJsICsgXCJdXCJdID0gXCJ1bmZvbGRcIjtcbiAgbWFwW2NLICsgY3RybCArIFwiMFwiXSA9IG1hcFtjSyArIGN0cmwgKyBcImpcIl0gPSBcInVuZm9sZEFsbFwiO1xuXG4gIG1hcFtjdHJsICsgXCJJXCJdID0gXCJmaW5kSW5jcmVtZW50YWxcIjtcbiAgbWFwW1wiU2hpZnQtXCIgKyBjdHJsICsgXCJJXCJdID0gXCJmaW5kSW5jcmVtZW50YWxSZXZlcnNlXCI7XG4gIG1hcFtjdHJsICsgXCJIXCJdID0gXCJyZXBsYWNlXCI7XG4gIG1hcFtcIkYzXCJdID0gXCJmaW5kTmV4dFwiO1xuICBtYXBbXCJTaGlmdC1GM1wiXSA9IFwiZmluZFByZXZcIjtcblxuICBDb2RlTWlycm9yLm5vcm1hbGl6ZUtleU1hcChtYXApO1xufSk7XG4iLCIvLyBDb2RlTWlycm9yLCBjb3B5cmlnaHQgKGMpIGJ5IE1hcmlqbiBIYXZlcmJla2UgYW5kIG90aGVyc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgYW4gTUlUIGxpY2Vuc2U6IGh0dHA6Ly9jb2RlbWlycm9yLm5ldC9MSUNFTlNFXG5cbi8vIFRoaXMgaXMgQ29kZU1pcnJvciAoaHR0cDovL2NvZGVtaXJyb3IubmV0KSwgYSBjb2RlIGVkaXRvclxuLy8gaW1wbGVtZW50ZWQgaW4gSmF2YVNjcmlwdCBvbiB0b3Agb2YgdGhlIGJyb3dzZXIncyBET00uXG4vL1xuLy8gWW91IGNhbiBmaW5kIHNvbWUgdGVjaG5pY2FsIGJhY2tncm91bmQgZm9yIHNvbWUgb2YgdGhlIGNvZGUgYmVsb3dcbi8vIGF0IGh0dHA6Ly9tYXJpam5oYXZlcmJla2UubmwvYmxvZy8jY20taW50ZXJuYWxzIC5cblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBtb2QoKTtcbiAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgLy8gQU1EXG4gICAgcmV0dXJuIGRlZmluZShbXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIHRoaXMuQ29kZU1pcnJvciA9IG1vZCgpO1xufSkoZnVuY3Rpb24oKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIC8vIEJST1dTRVIgU05JRkZJTkdcblxuICAvLyBLbHVkZ2VzIGZvciBidWdzIGFuZCBiZWhhdmlvciBkaWZmZXJlbmNlcyB0aGF0IGNhbid0IGJlIGZlYXR1cmVcbiAgLy8gZGV0ZWN0ZWQgYXJlIGVuYWJsZWQgYmFzZWQgb24gdXNlckFnZW50IGV0YyBzbmlmZmluZy5cbiAgdmFyIHVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gIHZhciBwbGF0Zm9ybSA9IG5hdmlnYXRvci5wbGF0Zm9ybTtcblxuICB2YXIgZ2Vja28gPSAvZ2Vja29cXC9cXGQvaS50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBpZV91cHRvMTAgPSAvTVNJRSBcXGQvLnRlc3QodXNlckFnZW50KTtcbiAgdmFyIGllXzExdXAgPSAvVHJpZGVudFxcLyg/Ols3LTldfFxcZHsyLH0pXFwuLipydjooXFxkKykvLmV4ZWModXNlckFnZW50KTtcbiAgdmFyIGllID0gaWVfdXB0bzEwIHx8IGllXzExdXA7XG4gIHZhciBpZV92ZXJzaW9uID0gaWUgJiYgKGllX3VwdG8xMCA/IGRvY3VtZW50LmRvY3VtZW50TW9kZSB8fCA2IDogaWVfMTF1cFsxXSk7XG4gIHZhciB3ZWJraXQgPSAvV2ViS2l0XFwvLy50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBxdHdlYmtpdCA9IHdlYmtpdCAmJiAvUXRcXC9cXGQrXFwuXFxkKy8udGVzdCh1c2VyQWdlbnQpO1xuICB2YXIgY2hyb21lID0gL0Nocm9tZVxcLy8udGVzdCh1c2VyQWdlbnQpO1xuICB2YXIgcHJlc3RvID0gL09wZXJhXFwvLy50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBzYWZhcmkgPSAvQXBwbGUgQ29tcHV0ZXIvLnRlc3QobmF2aWdhdG9yLnZlbmRvcik7XG4gIHZhciBtYWNfZ2VNb3VudGFpbkxpb24gPSAvTWFjIE9TIFggMVxcZFxcRChbOC05XXxcXGRcXGQpXFxELy50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBwaGFudG9tID0gL1BoYW50b21KUy8udGVzdCh1c2VyQWdlbnQpO1xuXG4gIHZhciBpb3MgPSAvQXBwbGVXZWJLaXQvLnRlc3QodXNlckFnZW50KSAmJiAvTW9iaWxlXFwvXFx3Ky8udGVzdCh1c2VyQWdlbnQpO1xuICAvLyBUaGlzIGlzIHdvZWZ1bGx5IGluY29tcGxldGUuIFN1Z2dlc3Rpb25zIGZvciBhbHRlcm5hdGl2ZSBtZXRob2RzIHdlbGNvbWUuXG4gIHZhciBtb2JpbGUgPSBpb3MgfHwgL0FuZHJvaWR8d2ViT1N8QmxhY2tCZXJyeXxPcGVyYSBNaW5pfE9wZXJhIE1vYml8SUVNb2JpbGUvaS50ZXN0KHVzZXJBZ2VudCk7XG4gIHZhciBtYWMgPSBpb3MgfHwgL01hYy8udGVzdChwbGF0Zm9ybS
vendor: 19,395 bytes, line 23459
23459k7XG4gIHZhciB3aW5kb3dzID0gL3dpbi9pLnRlc3QocGxhdGZvcm0pO1xuXG4gIHZhciBwcmVzdG9fdmVyc2lvbiA9IHByZXN0byAmJiB1c2VyQWdlbnQubWF0Y2goL1ZlcnNpb25cXC8oXFxkKlxcLlxcZCopLyk7XG4gIGlmIChwcmVzdG9fdmVyc2lvbikgcHJlc3RvX3ZlcnNpb24gPSBOdW1iZXIocHJlc3RvX3ZlcnNpb25bMV0pO1xuICBpZiAocHJlc3RvX3ZlcnNpb24gJiYgcHJlc3RvX3ZlcnNpb24gPj0gMTUpIHsgcHJlc3RvID0gZmFsc2U7IHdlYmtpdCA9IHRydWU7IH1cbiAgLy8gU29tZSBicm93c2VycyB1c2UgdGhlIHdyb25nIGV2ZW50IHByb3BlcnRpZXMgdG8gc2lnbmFsIGNtZC9jdHJsIG9uIE9TIFhcbiAgdmFyIGZsaXBDdHJsQ21kID0gbWFjICYmIChxdHdlYmtpdCB8fCBwcmVzdG8gJiYgKHByZXN0b192ZXJzaW9uID09IG51bGwgfHwgcHJlc3RvX3ZlcnNpb24gPCAxMi4xMSkpO1xuICB2YXIgY2FwdHVyZVJpZ2h0Q2xpY2sgPSBnZWNrbyB8fCAoaWUgJiYgaWVfdmVyc2lvbiA+PSA5KTtcblxuICAvLyBPcHRpbWl6ZSBzb21lIGNvZGUgd2hlbiB0aGVzZSBmZWF0dXJlcyBhcmUgbm90IHVzZWQuXG4gIHZhciBzYXdSZWFkT25seVNwYW5zID0gZmFsc2UsIHNhd0NvbGxhcHNlZFNwYW5zID0gZmFsc2U7XG5cbiAgLy8gRURJVE9SIENPTlNUUlVDVE9SXG5cbiAgLy8gQSBDb2RlTWlycm9yIGluc3RhbmNlIHJlcHJlc2VudHMgYW4gZWRpdG9yLiBUaGlzIGlzIHRoZSBvYmplY3RcbiAgLy8gdGhhdCB1c2VyIGNvZGUgaXMgdXN1YWxseSBkZWFsaW5nIHdpdGguXG5cbiAgZnVuY3Rpb24gQ29kZU1pcnJvcihwbGFjZSwgb3B0aW9ucykge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBDb2RlTWlycm9yKSkgcmV0dXJuIG5ldyBDb2RlTWlycm9yKHBsYWNlLCBvcHRpb25zKTtcblxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgPSBvcHRpb25zID8gY29weU9iaihvcHRpb25zKSA6IHt9O1xuICAgIC8vIERldGVybWluZSBlZmZlY3RpdmUgb3B0aW9ucyBiYXNlZCBvbiBnaXZlbiB2YWx1ZXMgYW5kIGRlZmF1bHRzLlxuICAgIGNvcHlPYmooZGVmYXVsdHMsIG9wdGlvbnMsIGZhbHNlKTtcbiAgICBzZXRHdXR0ZXJzRm9yTGluZU51bWJlcnMob3B0aW9ucyk7XG5cbiAgICB2YXIgZG9jID0gb3B0aW9ucy52YWx1ZTtcbiAgICBpZiAodHlwZW9mIGRvYyA9PSBcInN0cmluZ1wiKSBkb2MgPSBuZXcgRG9jKGRvYywgb3B0aW9ucy5tb2RlLCBudWxsLCBvcHRpb25zLmxpbmVTZXBhcmF0b3IpO1xuICAgIHRoaXMuZG9jID0gZG9jO1xuXG4gICAgdmFyIGlucHV0ID0gbmV3IENvZGVNaXJyb3IuaW5wdXRTdHlsZXNbb3B0aW9ucy5pbnB1dFN0eWxlXSh0aGlzKTtcbiAgICB2YXIgZGlzcGxheSA9IHRoaXMuZGlzcGxheSA9IG5ldyBEaXNwbGF5KHBsYWNlLCBkb2MsIGlucHV0KTtcbiAgICBkaXNwbGF5LndyYXBwZXIuQ29kZU1pcnJvciA9IHRoaXM7XG4gICAgdXBkYXRlR3V0dGVycyh0aGlzKTtcbiAgICB0aGVtZUNoYW5nZWQodGhpcyk7XG4gICAgaWYgKG9wdGlvbnMubGluZVdyYXBwaW5nKVxuICAgICAgdGhpcy5kaXNwbGF5LndyYXBwZXIuY2xhc3NOYW1lICs9IFwiIENvZGVNaXJyb3Itd3JhcFwiO1xuICAgIGlmIChvcHRpb25zLmF1dG9mb2N1cyAmJiAhbW9iaWxlKSBkaXNwbGF5LmlucHV0LmZvY3VzKCk7XG4gICAgaW5pdFNjcm9sbGJhcnModGhpcyk7XG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAga2V5TWFwczogW10sICAvLyBzdG9yZXMgbWFwcyBhZGRlZCBieSBhZGRLZXlNYXBcbiAgICAgIG92ZXJsYXlzOiBbXSwgLy8gaGlnaGxpZ2h0aW5nIG92ZXJsYXlzLCBhcyBhZGRlZCBieSBhZGRPdmVybGF5XG4gICAgICBtb2RlR2VuOiAwLCAgIC8vIGJ1bXBlZCB3aGVuIG1vZGUvb3ZlcmxheSBjaGFuZ2VzLCB1c2VkIHRvIGludmFsaWRhdGUgaGlnaGxpZ2h0aW5nIGluZm9cbiAgICAgIG92ZXJ3cml0ZTogZmFsc2UsXG4gICAgICBkZWxheWluZ0JsdXJFdmVudDogZmFsc2UsXG4gICAgICBmb2N1c2VkOiBmYWxzZSxcbiAgICAgIHN1cHByZXNzRWRpdHM6IGZhbHNlLCAvLyB1c2VkIHRvIGRpc2FibGUgZWRpdGluZyBkdXJpbmcga2V5IGhhbmRsZXJzIHdoZW4gaW4gcmVhZE9ubHkgbW9kZVxuICAgICAgcGFzdGVJbmNvbWluZzogZmFsc2UsIGN1dEluY29taW5nOiBmYWxzZSwgLy8gaGVscCByZWNvZ25pemUgcGFzdGUvY3V0IGVkaXRzIGluIGlucHV0LnBvbGxcbiAgICAgIHNlbGVjdGluZ1RleHQ6IGZhbHNlLFxuICAgICAgZHJhZ2dpbmdUZXh0OiBmYWxzZSxcbiAgICAgIGhpZ2hsaWdodDogbmV3IERlbGF5ZWQoKSwgLy8gc3RvcmVzIGhpZ2hsaWdodCB3b3JrZXIgdGltZW91dFxuICAgICAga2V5U2VxOiBudWxsLCAgLy8gVW5maW5pc2hlZCBrZXkgc2VxdWVuY2VcbiAgICAgIHNwZWNpYWxDaGFyczogbnVsbFxuICAgIH07XG5cbiAgICB2YXIgY20gPSB0aGlzO1xuXG4gICAgLy8gT3ZlcnJpZGUgbWFnaWMgdGV4dGFyZWEgY29udGVudCByZXN0b3JlIHRoYXQgSUUgc29tZXRpbWVzIGRvZXNcbiAgICAvLyBvbiBvdXIgaGlkZGVuIHRleHRhcmVhIG9uIHJlbG9hZFxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgMTEpIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNtLmRpc3BsYXkuaW5wdXQucmVzZXQodHJ1ZSk7IH0sIDIwKTtcblxuICAgIHJlZ2lzdGVyRXZlbnRIYW5kbGVycyh0aGlzKTtcbiAgICBlbnN1cmVHbG9iYWxIYW5kbGVycygpO1xuXG4gICAgc3RhcnRPcGVyYXRpb24odGhpcyk7XG4gICAgdGhpcy5jdXJPcC5mb3JjZVVwZGF0ZSA9IHRydWU7XG4gICAgYXR0YWNoRG9jKHRoaXMsIGRvYyk7XG5cbiAgICBpZiAoKG9wdGlvbnMuYXV0b2ZvY3VzICYmICFtb2JpbGUpIHx8IGNtLmhhc0ZvY3VzKCkpXG4gICAgICBzZXRUaW1lb3V0KGJpbmQob25Gb2N1cywgdGhpcyksIDIwKTtcbiAgICBlbHNlXG4gICAgICBvbkJsdXIodGhpcyk7XG5cbiAgICBmb3IgKHZhciBvcHQgaW4gb3B0aW9uSGFuZGxlcnMpIGlmIChvcHRpb25IYW5kbGVycy5oYXNPd25Qcm9wZXJ0eShvcHQpKVxuICAgICAgb3B0aW9uSGFuZGxlcnNbb3B0XSh0aGlzLCBvcHRpb25zW29wdF0sIEluaXQpO1xuICAgIG1heWJlVXBkYXRlTGluZU51bWJlcldpZHRoKHRoaXMpO1xuICAgIGlmIChvcHRpb25zLmZpbmlzaEluaXQpIG9wdGlvbnMuZmluaXNoSW5pdCh0aGlzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRIb29rcy5sZW5ndGg7ICsraSkgaW5pdEhvb2tzW2ldKHRoaXMpO1xuICAgIGVuZE9wZXJhdGlvbih0aGlzKTtcbiAgICAvLyBTdXBwcmVzcyBvcHRpbWl6ZWxlZ2liaWxpdHkgaW4gV2Via2l0LCBzaW5jZSBpdCBicmVha3MgdGV4dFxuICAgIC8vIG1lYXN1cmluZyBvbiBsaW5lIHdyYXBwaW5nIGJvdW5kYXJpZXMuXG4gICAgaWYgKHdlYmtpdCAmJiBvcHRpb25zLmxpbmVXcmFwcGluZyAmJlxuICAgICAgICBnZXRDb21wdXRlZFN0eWxlKGRpc3BsYXkubGluZURpdikudGV4dFJlbmRlcmluZyA9PSBcIm9wdGltaXplbGVnaWJpbGl0eVwiKVxuICAgICAgZGlzcGxheS5saW5lRGl2LnN0eWxlLnRleHRSZW5kZXJpbmcgPSBcImF1dG9cIjtcbiAgfVxuXG4gIC8vIERJU1BMQVkgQ09OU1RSVUNUT1JcblxuICAvLyBUaGUgZGlzcGxheSBoYW5kbGVzIHRoZSBET00gaW50ZWdyYXRpb24sIGJvdGggZm9yIGlucHV0IHJlYWRpbmdcbiAgLy8gYW5kIGNvbnRlbnQgZHJhd2luZy4gSXQgaG9sZHMgcmVmZXJlbmNlcyB0byBET00gbm9kZXMgYW5kXG4gIC8vIGRpc3BsYXktcmVsYXRlZCBzdGF0ZS5cblxuICBmdW5jdGlvbiBEaXNwbGF5KHBsYWNlLCBkb2MsIGlucHV0KSB7XG4gICAgdmFyIGQgPSB0aGlzO1xuICAgIHRoaXMuaW5wdXQgPSBpbnB1dDtcblxuICAgIC8vIENvdmVycyBib3R0b20tcmlnaHQgc3F1YXJlIHdoZW4gYm90aCBzY3JvbGxiYXJzIGFyZSBwcmVzZW50LlxuICAgIGQuc2Nyb2xsYmFyRmlsbGVyID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1zY3JvbGxiYXItZmlsbGVyXCIpO1xuICAgIGQuc2Nyb2xsYmFyRmlsbGVyLnNldEF0dHJpYnV0ZShcImNtLW5vdC1jb250ZW50XCIsIFwidHJ1ZVwiKTtcbiAgICAvLyBDb3ZlcnMgYm90dG9tIG9mIGd1dHRlciB3aGVuIGNvdmVyR3V0dGVyTmV4dFRvU2Nyb2xsYmFyIGlzIG9uXG4gICAgLy8gYW5kIGggc2Nyb2xsYmFyIGlzIHByZXNlbnQuXG4gICAgZC5ndXR0ZXJGaWxsZXIgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWd1dHRlci1maWxsZXJcIik7XG4gICAgZC5ndXR0ZXJGaWxsZXIuc2V0QXR0cmlidXRlKFwiY20tbm90LWNvbnRlbnRcIiwgXCJ0cnVlXCIpO1xuICAgIC8vIFdpbGwgY29udGFpbiB0aGUgYWN0dWFsIGNvZGUsIHBvc2l0aW9uZWQgdG8gY292ZXIgdGhlIHZpZXdwb3J0LlxuICAgIGQubGluZURpdiA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItY29kZVwiKTtcbiAgICAvLyBFbGVtZW50cyBhcmUgYWRkZWQgdG8gdGhlc2UgdG8gcmVwcmVzZW50IHNlbGVjdGlvbiBhbmQgY3Vyc29ycy5cbiAgICBkLnNlbGVjdGlvbkRpdiA9IGVsdChcImRpdlwiLCBudWxsLCBudWxsLCBcInBvc2l0aW9uOiByZWxhdGl2ZTsgei1pbmRleDogMVwiKTtcbiAgICBkLmN1cnNvckRpdiA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItY3Vyc29yc1wiKTtcbiAgICAvLyBBIHZpc2liaWxpdHk6IGhpZGRlbiBlbGVtZW50IHVzZWQgdG8gZmluZCB0aGUgc2l6ZSBvZiB0aGluZ3MuXG4gICAgZC5tZWFzdXJlID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1tZWFzdXJlXCIpO1xuICAgIC8vIFdoZW4gbGluZXMgb3V0c2lkZSBvZiB0aGUgdmlld3BvcnQgYXJlIG1lYXN1cmVkLCB0aGV5IGFyZSBkcmF3biBpbiB0aGlzLlxuICAgIGQubGluZU1lYXN1cmUgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLW1lYXN1cmVcIik7XG4gICAgLy8gV3JhcHMgZXZlcnl0aGluZyB0aGF0IG5lZWRzIHRvIGV4aXN0IGluc2lkZSB0aGUgdmVydGljYWxseS1wYWRkZWQgY29vcmRpbmF0ZSBzeXN0ZW1cbiAgICBkLmxpbmVTcGFjZSA9IGVsdChcImRpdlwiLCBbZC5tZWFzdXJlLCBkLmxpbmVNZWFzdXJlLCBkLnNlbGVjdGlvbkRpdiwgZC5jdXJzb3JEaXYsIGQubGluZURpdl0sXG4gICAgICAgICAgICAgICAgICAgICAgbnVsbCwgXCJwb3NpdGlvbjogcmVsYXRpdmU7IG91dGxpbmU6IG5vbmVcIik7XG4gICAgLy8gTW92ZWQgYXJvdW5kIGl0cyBwYXJlbnQgdG8gY292ZXIgdmlzaWJsZSB2aWV3LlxuICAgIGQubW92ZXIgPSBlbHQoXCJkaXZcIiwgW2VsdChcImRpdlwiLCBbZC5saW5lU3BhY2VdLCBcIkNvZGVNaXJyb3ItbGluZXNcIildLCBudWxsLCBcInBvc2l0aW9uOiByZWxhdGl2ZVwiKTtcbiAgICAvLyBTZXQgdG8gdGhlIGhlaWdodCBvZiB0aGUgZG9jdW1lbnQsIGFsbG93aW5nIHNjcm9sbGluZy5cbiAgICBkLnNpemVyID0gZWx0KFwiZGl2XCIsIFtkLm1vdmVyXSwgXCJDb2RlTWlycm9yLXNpemVyXCIpO1xuICAgIGQuc2l6ZXJXaWR0aCA9IG51bGw7XG4gICAgLy8gQmVoYXZpb3Igb2YgZWx0cyB3aXRoIG92ZXJmbG93OiBhdXRvIGFuZCBwYWRkaW5nIGlzXG4gICAgLy8gaW5jb25zaXN0ZW50IGFjcm9zcyBicm93c2Vycy4gVGhpcyBpcyB1c2VkIHRvIGVuc3VyZSB0aGVcbiAgICAvLyBzY3JvbGxhYmxlIGFyZWEgaXMgYmlnIGVub3VnaC5cbiAgICBkLmhlaWdodEZvcmNlciA9IGVsdChcImRpdlwiLCBudWxsLCBudWxsLCBcInBvc2l0aW9uOiBhYnNvbHV0ZTsgaGVpZ2h0OiBcIiArIHNjcm9sbGVyR2FwICsgXCJweDsgd2lkdGg6IDFweDtcIik7XG4gICAgLy8gV2lsbCBjb250YWluIHRoZSBndXR0ZXJzLCBpZiBhbnkuXG4gICAgZC5ndXR0ZXJzID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1ndXR0ZXJzXCIpO1xuICAgIGQubGluZUd1dHRlciA9IG51bGw7XG4gICAgLy8gQWN0dWFsIHNjcm9sbGFibGUgZWxlbWVudC5cbiAgICBkLnNjcm9sbGVyID0gZWx0KFwiZGl2XCIsIFtkLnNpemVyLCBkLmhlaWdodEZvcmNlciwgZC5ndXR0ZXJzXSwgXCJDb2RlTWlycm9yLXNjcm9sbFwiKTtcbiAgICBkLnNjcm9sbGVyLnNldEF0dHJpYnV0ZShcInRhYkluZGV4XCIsIFwiLTFcIik7XG4gICAgLy8gVGhlIGVsZW1lbnQgaW4gd2hpY2ggdGhlIGVkaXRvciBsaXZlcy5cbiAgICBkLndyYXBwZXIgPSBlbHQoXCJkaXZcIiwgW2Quc2Nyb2xsYmFyRmlsbGVyLCBkLmd1dHRlckZpbGxlciwgZC5zY3JvbGxlcl0sIFwiQ29kZU1pcnJvclwiKTtcblxuICAgIC8vIFdvcmsgYXJvdW5kIElFNyB6LWluZGV4IGJ1ZyAobm90IHBlcmZlY3QsIGhlbmNlIElFNyBub3QgcmVhbGx5IGJlaW5nIHN1cHBvcnRlZClcbiAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDgpIHsgZC5ndXR0ZXJzLnN0eWxlLnpJbmRleCA9IC0xOyBkLnNjcm9sbGVyLnN0eWxlLnBhZGRpbmdSaWdodCA9IDA7IH1cbiAgICBpZiAoIXdlYmtpdCAmJiAhKGdlY2tvICYmIG1vYmlsZSkpIGQuc2Nyb2xsZXIuZHJhZ2dhYmxlID0gdHJ1ZTtcblxuICAgIGlmIChwbGFjZSkge1xuICAgICAgaWYgKHBsYWNlLmFwcGVuZENoaWxkKSBwbGFjZS5hcHBlbmRDaGlsZChkLndyYXBwZXIpO1xuICAgICAgZWxzZSBwbGFjZShkLndyYXBwZXIpO1xuICAgIH1cblxuICAgIC8vIEN1cnJlbnQgcmVuZGVyZWQgcmFuZ2UgKG1heSBiZSBiaWdnZXIgdGhhbiB0aGUgdmlldyB3aW5kb3cpLlxuICAgIGQudmlld0Zyb20gPSBkLnZpZXdUbyA9IGRvYy5maXJzdDtcbiAgICBkLnJlcG9ydGVkVmlld0Zyb20gPSBkLnJlcG9ydGVkVmlld1RvID0gZG9jLmZpcnN0O1xuICAgIC8vIEluZm9ybWF0aW9uIGFib3V0IHRoZSByZW5kZXJlZCBsaW5lcy5cbiAgICBkLnZpZXcgPSBbXTtcbiAgICBkLnJlbmRlcmVkVmlldyA9IG51bGw7XG4gICAgLy8gSG9sZHMgaW5mbyBhYm91dCBhIHNpbmdsZSByZW5kZXJlZCBsaW5lIHdoZW4gaXQgd2FzIHJlbmRlcmVkXG4gICAgLy8gZm9yIG1lYXN1cmVtZW50LCB3aGlsZSBub3QgaW4gdmlldy5cbiAgICBkLmV4dGVybmFsTWVhc3VyZWQgPSBudWxsO1xuICAgIC8vIEVtcHR5IHNwYWNlIChpbiBwaXhlbHMpIGFib3ZlIHRoZSB2aWV3XG4gICAgZC52aWV3T2Zmc2V0ID0gMDtcbiAgICBkLmxhc3RXcmFwSGVpZ2h0ID0gZC5sYXN0V3JhcFdpZHRoID0gMDtcbiAgICBkLnVwZGF0ZUxpbmVOdW1iZXJzID0gbnVsbDtcblxuICAgIGQubmF0aXZlQmFyV2lkdGggPSBkLmJhckhlaWdodCA9IGQuYmFyV2lkdGggPSAwO1xuICAgIGQuc2Nyb2xsYmFyc0NsaXBwZWQgPSBmYWxzZTtcblxuICAgIC8vIFVzZWQgdG8gb25seSByZXNpemUgdGhlIGxpbmUgbnVtYmVyIGd1dHRlciB3aGVuIG5lY2Vzc2FyeSAod2hlblxuICAgIC8vIHRoZSBhbW91bnQgb2YgbGluZXMgY3Jvc3NlcyBhIGJvdW5kYXJ5IHRoYXQgbWFrZXMgaXRzIHdpZHRoIGNoYW5nZSlcbiAgICBkLmxpbmVOdW1XaWR0aCA9IGQubGluZU51bUlubmVyV2lkdGggPSBkLmxpbmVOdW1DaGFycyA9IG51bGw7XG4gICAgLy8gU2V0IHRvIHRydWUgd2hlbiBhIG5vbi1ob3Jpem9udGFsLXNjcm9sbGluZyBsaW5lIHdpZGdldCBpc1xuICAgIC8vIGFkZGVkLiBBcyBhbiBvcHRpbWl6YXRpb24sIGxpbmUgd2lkZ2V0IGFsaWduaW5nIGlzIHNraXBwZWQgd2hlblxuICAgIC8vIHRoaXMgaXMgZmFsc2UuXG4gICAgZC5hbGlnbldpZGdldHMgPSBmYWxzZTtcblxuICAgIGQuY2FjaGVkQ2hhcldpZHRoID0gZC5jYWNoZWRUZXh0SGVpZ2h0ID0gZC5jYWNoZWRQYWRkaW5nSCA9IG51bGw7XG5cbiAgICAvLyBUcmFja3MgdGhlIG1heGltdW0gbGluZSBsZW5ndGggc28gdGhhdCB0aGUgaG9yaXpvbnRhbCBzY3JvbGxiYXJcbiAgICAvLyBjYW4gYmUga2VwdCBzdGF0aWMgd2hlbiBzY3JvbGxpbmcuXG4gICAgZC5tYXhMaW5lID0gbnVsbDtcbiAgICBkLm1heExpbmVMZW5ndGggPSAwO1xuICAgIGQubWF4TGluZUNoYW5nZWQgPSBmYWxzZTtcblxuICAgIC8vIFVzZWQgZm9yIG1lYXN1cmluZyB3aGVlbCBzY3JvbGxpbmcgZ3JhbnVsYXJpdHlcbiAgICBkLndoZWVsRFggPSBkLndoZWVsRFkgPSBkLndoZWVsU3RhcnRYID0gZC53aGVlbFN0YXJ0WSA9IG51bGw7XG5cbiAgICAvLyBUcnVlIHdoZW4gc2hpZnQgaXMgaGVsZCBkb3duLlxuICAgIGQuc2hpZnQgPSBmYWxzZTtcblxuICAgIC8vIFVzZWQgdG8gdHJhY2sgd2hldGhlciBhbnl0aGluZyBoYXBwZW5lZCBzaW5jZSB0aGUgY29udGV4dCBtZW51XG4gICAgLy8gd2FzIG9wZW5lZC5cbiAgICBkLnNlbEZvckNvbnRleHRNZW51ID0gbnVsbDtcblxuICAgIGQuYWN0aXZlVG91Y2ggPSBudWxsO1xuXG4gICAgaW5wdXQuaW5pdChkKTtcbiAgfVxuXG4gIC8vIFNUQVRFIFVQREFURVNcblxuICAvLyBVc2VkIHRvIGdldCB0aGUgZWRpdG9yIGludG8gYSBjb25zaXN0ZW50IHN0YXRlIGFnYWluIHdoZW4gb3B0aW9ucyBjaGFuZ2UuXG5cbiAgZnVuY3Rpb24gbG9hZE1vZGUoY20pIHtcbiAgICBjbS5kb2MubW9kZSA9IENvZGVNaXJyb3IuZ2V0TW9kZShjbS5vcHRpb25zLCBjbS5kb2MubW9kZU9wdGlvbik7XG4gICAgcmVzZXRNb2RlU3RhdGUoY20pO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzZXRNb2RlU3RhdGUoY20pIHtcbiAgICBjbS5kb2MuaXRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgICBpZiAobGluZS5zdGF0ZUFmdGVyKSBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsO1xuICAgICAgaWYgKGxpbmUuc3R5bGVzKSBsaW5lLnN0eWxlcyA9IG51bGw7XG4gICAgfSk7XG4gICAgY20uZG9jLmZyb250aWVyID0gY20uZG9jLmZpcnN0O1xuICAgIHN0YXJ0V29ya2VyKGNtLCAxMDApO1xuICAgIGNtLnN0YXRlLm1vZGVHZW4rKztcbiAgICBpZiAoY20uY3VyT3ApIHJlZ0NoYW5nZShjbSk7XG4gIH1cblxuICBmdW5jdGlvbiB3cmFwcGluZ0NoYW5nZWQoY20pIHtcbiAgICBpZiAoY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHtcbiAgICAgIGFkZENsYXNzKGNtLmRpc3BsYXkud3JhcHBlciwgXCJDb2RlTWlycm9yLXdyYXBcIik7XG4gICAgICBjbS5kaXNwbGF5LnNpemVyLnN0eWxlLm1pbldpZHRoID0gXCJcIjtcbiAgICAgIGNtLmRpc3BsYXkuc2l6ZXJXaWR0aCA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJtQ2xhc3MoY20uZGlzcGxheS53cmFwcGVyLCBcIkNvZGVNaXJyb3Itd3JhcFwiKTtcbiAgICAgIGZpbmRNYXhMaW5lKGNtKTtcbiAgICB9XG4gICAgZXN0aW1hdGVMaW5lSGVpZ2h0cyhjbSk7XG4gICAgcmVnQ2hhbmdlKGNtKTtcbiAgICBjbGVhckNhY2hlcyhjbSk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpe3VwZGF0ZVNjcm9sbGJhcnMoY20pO30sIDEwMCk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBlc3RpbWF0ZXMgdGhlIGhlaWdodCBvZiBhIGxpbmUsIHRvIHVzZSBhc1xuICAvLyBmaXJzdCBhcHByb3hpbWF0aW9uIHVudGlsIHRoZSBsaW5lIGJlY29tZXMgdmlzaWJsZSAoYW5kIGlzIHRodXNcbiAgLy8gcHJvcGVybHkgbWVhc3VyYWJsZSkuXG4gIGZ1bmN0aW9uIGVzdGltYXRlSGVpZ2h0KGNtKSB7XG4gICAgdmFyIHRoID0gdGV4dEhlaWdodChjbS5kaXNwbGF5KSwgd3JhcHBpbmcgPSBjbS5vcHRpb25zLmxpbmVXcmFwcGluZztcbiAgICB2YXIgcGVyTGluZSA9IHdyYXBwaW5nICYmIE1hdGgubWF4KDUsIGNtLmRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50V2lkdGggLyBjaGFyV2lkdGgoY20uZGlzcGxheSkgLSAzKTtcbiAgICByZXR1cm4gZnVuY3Rpb24obGluZSkge1xuICAgICAgaWYgKGxpbmVJc0hpZGRlbihjbS5kb2MsIGxpbmUpKSByZXR1cm4gMDtcblxuICAgICAgdmFyIHdpZGdldHNIZWlnaHQgPSAwO1xuICAgICAgaWYgKGxpbmUud2lkZ2V0cykgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lLndpZGdldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGxpbmUud2lkZ2V0c1tpXS5oZWlnaHQpIHdpZGdldHNIZWlnaHQgKz0gbGluZS53aWRnZXRzW2ldLmhlaWdodDtcbiAgICAgIH1cblxuICAgICAgaWYgKHdyYXBwaW5nKVxuICAgICAgICByZXR1cm4gd2lkZ2V0c0hlaWdodCArIChNYXRoLmNlaWwobGluZS50ZXh0Lmxlbmd0aCAvIHBlckxpbmUpIHx8IDEpICogdGg7XG4gICAgICBlbHNlXG4gICAgICAgIHJldHVybiB3aWRnZXRzSGVpZ2h0ICsgdGg7XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVzdGltYXRlTGluZUhlaWdodHMoY20pIHtcbiAgICB2YXIgZG9jID0gY20uZG9jLCBlc3QgPSBlc3RpbWF0ZUhlaWdodChjbSk7XG4gICAgZG9jLml0ZXIoZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIGVzdEhlaWdodCA9IGVzdChsaW5lKTtcbiAgICAgIGlmIChlc3RIZWlnaHQgIT0gbGluZS5oZWlnaHQpIHVwZGF0ZUxpbmVIZWlnaHQobGluZSwgZXN0SGVpZ2h0KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRoZW1lQ2hhbmdlZChjbSkge1xuICAgIGNtLmRpc3BsYXkud3JhcHBlci5jbGFzc05hbWUgPSBjbS5kaXNwbGF5LndyYXBwZXIuY2xhc3NOYW1lLnJlcGxhY2UoL1xccypjbS1zLVxcUysvZywgXCJcIikgK1xuICAgICAgY20ub3B0aW9ucy50aGVtZS5yZXBsYWNlKC8oXnxcXHMpXFxzKi9nLCBcIiBjbS1zLVwiKTtcbiAgICBjbGVhckNhY2hlcyhjbSk7XG4gIH1cblxuICBmdW5jdGlvbiBndXR0ZXJzQ2hhbmdlZChjbSkge1xuICAgIHVwZGF0ZUd1dHRlcnMoY20pO1xuICAgIHJlZ0NoYW5nZShjbSk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpe2FsaWduSG9yaXpvbnRhbGx5KGNtKTt9LCAyMCk7XG4gIH1cblxuICAvLyBSZWJ1aWxkIHRoZSBndXR0ZXIgZWxlbWVudHMsIGVuc3VyZSB0aGUgbWFyZ2luIHRvIHRoZSBsZWZ0IG9mIHRoZVxuICAvLyBjb2RlIG1hdGNoZXMgdGhlaXIgd2lkdGguXG4gIGZ1bmN0aW9uIHVwZGF0ZUd1dHRlcnMoY20pIHtcbiAgICB2YXIgZ3V0dGVycyA9IGNtLmRpc3BsYXkuZ3V0dGVycywgc3BlY3MgPSBjbS5vcHRpb25zLmd1dHRlcnM7XG4gICAgcmVtb3ZlQ2hpbGRyZW4oZ3V0dGVycyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzcGVjcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGd1dHRlckNsYXNzID0gc3BlY3NbaV07XG4gICAgICB2YXIgZ0VsdCA9IGd1dHRlcnMuYXBwZW5kQ2hpbGQoZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1ndXR0ZXIgXCIgKyBndXR0ZXJDbGFzcykpO1xuICAgICAgaWYgKGd1dHRlckNsYXNzID09IFwiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiKSB7XG4gICAgICAgIGNtLmRpc3BsYXkubGluZUd1dHRlciA9IGdFbHQ7XG4gICAgICAgIGdFbHQuc3R5bGUud2lkdGggPSAoY20uZGlzcGxheS5saW5lTnVtV2lkdGggfHwgMSkgKyBcInB4XCI7XG4gICAgICB9XG4gICAgfVxuICAgIGd1dHRlcnMuc3R5bGUuZGlzcGxheSA9IGkgPyBcIlwiIDogXCJub25lXCI7XG4gICAgdXBkYXRlR3V0dGVyU3BhY2UoY20pO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlR3V0dGVyU3BhY2UoY20pIHtcbiAgICB2YXIgd2lkdGggPSBjbS5kaXNwbGF5Lmd1dHRlcnMub2Zmc2V0V2lkdGg7XG4gICAgY20uZGlzcGxheS5zaXplci5zdHlsZS5tYXJnaW5MZWZ0ID0gd2lkdGggKyBcInB4XCI7XG4gIH1cblxuICAvLyBDb21wdXRlIHRoZSBjaGFyYWN0ZXIgbGVuZ3RoIG9mIGEgbGluZSwgdGFraW5nIGludG8gYWNjb3VudFxuICAvLyBjb2xsYXBzZWQgcmFuZ2VzIChzZWUgbWFya1RleHQpIHRoYXQgbWlnaHQgaGlkZSBwYXJ0cywgYW5kIGpvaW5cbiAgLy8gb3RoZXIgbGluZXMgb250byBpdC5cbiAgZnVuY3Rpb24gbGluZUxlbmd0aChsaW5lKSB7XG4gICAgaWYgKGxpbmUuaGVpZ2h0ID09IDApIHJldHVybiAwO1xuICAgIHZhciBsZW4gPSBsaW5lLnRleHQubGVuZ3RoLCBtZXJnZWQsIGN1ciA9IGxpbmU7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdFN0YXJ0KGN1cikpIHtcbiAgICAgIHZhciBmb3VuZCA9IG1lcmdlZC5maW5kKDAsIHRydWUpO1xuICAgICAgY3VyID0gZm91bmQuZnJvbS5saW5lO1xuICAgICAgbGVuICs9IGZvdW5kLmZyb20uY2ggLSBmb3VuZC50by5jaDtcbiAgICB9XG4gICAgY3VyID0gbGluZTtcbiAgICB3aGlsZSAobWVyZ2VkID0gY29sbGFwc2VkU3BhbkF0RW5kKGN1cikpIHtcbiAgICAgIHZhciBmb3VuZCA9IG1lcmdlZC5maW5kKDAsIHRydWUpO1xuICAgICAgbGVuIC09IGN1ci50ZXh0Lmxlbmd0aCAtIGZvdW5kLmZyb20uY2g7XG4gICAgICBjdXIgPSBmb3VuZC50by5saW5lO1xuICAgICAgbGVuICs9IGN1ci50ZXh0Lmxlbmd0aCAtIGZvdW5kLnRvLmNoO1xuICAgIH1cbiAgICByZXR1cm4gbGVuO1xuICB9XG5cbiAgLy8gRmluZCB0aGUgbG9uZ2VzdCBsaW5lIGluIHRoZSBkb2N1bWVudC5cbiAgZnVuY3Rpb24gZmluZE1heExpbmUoY20pIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXksIGRvYyA9IGNtLmRvYztcbiAgICBkLm1heExpbmUgPSBnZXRMaW5lKGRvYywgZG9jLmZpcnN0KTtcbiAgICBkLm1heExpbmVMZW5ndGggPSBsaW5lTGVuZ3RoKGQubWF4TGluZSk7XG4gICAgZC5tYXhMaW5lQ2hhbmdlZCA9IHRydWU7XG4gICAgZG9jLml0ZXIoZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIGxlbiA9IGxpbmVMZW5ndGgobGluZSk7XG4gICAgICBpZiAobGVuID4gZC5tYXhMaW5lTGVuZ3RoKSB7XG4gICAgICAgIGQubWF4TGluZUxlbmd0aCA9IGxlbjtcbiAgICAgICAgZC5tYXhMaW5lID0gbGluZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIE1ha2Ugc3VyZSB0aGUgZ3V0dGVycyBvcHRpb25zIGNvbnRhaW5zIHRoZSBlbGVtZW50XG4gIC8vIFwiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiIHdoZW4gdGhlIGxpbmVOdW1iZXJzIG9wdGlvbiBpcyB0cnVlLlxuICBmdW5jdGlvbiBzZXRHdXR0ZXJzRm9yTGluZU51bWJlcnMob3B0aW9ucykge1xuICAgIHZhciBmb3VuZCA9IGluZGV4T2Yob3B0aW9ucy5ndXR0ZXJzLCBcIkNvZGVNaXJyb3ItbGluZW51bWJlcnNcIik7XG4gICAgaWYgKGZvdW5kID09IC0xICYmIG9wdGlvbnMubGluZU51bWJlcnMpIHtcbiAgICAgIG9wdGlvbnMuZ3V0dGVycyA9IG9wdGlvbnMuZ3V0dGVycy5jb25jYXQoW1wiQ29kZU1pcnJvci1saW5lbnVtYmVyc1wiXSk7XG4gICAgfSBlbHNlIGlmIChmb3VuZCA+IC0xICYmICFvcHRpb25zLmxpbmVOdW1iZXJzKSB7XG4gICAgICBvcHRpb25zLmd1dHRlcnMgPSBvcHRpb25zLmd1dHRlcnMuc2xpY2UoMCk7XG4gICAgICBvcHRpb25zLmd1dHRlcnMuc3BsaWNlKGZvdW5kLCAxKTtcbiAgICB9XG4gIH1cblxuICAvLyBTQ1JPTExCQVJTXG5cbiAgLy8gUHJlcGFyZSBET00gcmVhZHMgbmVlZGVkIHRvIHVwZGF0ZSB0aGUgc2Nyb2xsYmFycy4gRG9uZSBpbiBvbmVcbiAgLy8gc2hvdCB0byBtaW5pbWl6ZSB1cGRhdGUvbWVhc3VyZSByb3VuZHRyaXBzLlxuICBmdW5jdGlvbiBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSkge1xuICAgIHZhciBkID0gY20uZGlzcGxheSwgZ3V0dGVyVyA9IGQuZ3V0dGVycy5vZmZzZXRXaWR0aDtcbiAgICB2YXIgZG9jSCA9IE1hdGgucm91bmQoY20uZG9jLmhlaWdodCArIHBhZGRpbmdWZXJ0KGNtLmRpc3BsYXkpKTtcbiAgICByZXR1cm4ge1xuICAgICAgY2xpZW50SGVpZ2h0OiBkLnNjcm9sbGVyLmNsaWVudEhlaWdodCxcbiAgICAgIHZpZXdIZWlnaHQ6IGQud3JhcHBlci5jbGllbnRIZWlnaHQsXG4gICAgICBzY3JvbGxXaWR0aDogZC5zY3JvbGxlci5zY3JvbGxXaWR0aCwgY2xpZW50V2lkdGg6IGQuc2Nyb2xsZXIuY2xpZW50V2lkdGgsXG4gICAgICB2aWV3V2lkdGg6IGQud3JhcHBlci5jbGllbnRXaWR0aCxcbiAgICAgIGJhckxlZnQ6IGNtLm9wdGlvbnMuZml4ZWRHdXR0ZXIgPyBndXR0ZXJXIDogMCxcbiAgICAgIGRvY0hlaWdodDogZG9jSCxcbiAgICAgIHNjcm9sbEhlaWdodDogZG9jSCArIHNjcm9sbEdhcChjbSkgKyBkLmJhckhlaWdodCxcbiAgICAgIG5hdGl2ZUJhcldpZHRoOiBkLm5hdGl2ZUJhcldpZHRoLFxuICAgICAgZ3V0dGVyV2lkdGg6IGd1dHRlcldcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gTmF0aXZlU2Nyb2xsYmFycyhwbGFjZSwgc2Nyb2xsLCBjbSkge1xuICAgIHRoaXMuY20gPSBjbTtcbiAgICB2YXIgdmVydCA9IHRoaXMudmVydCA9IGVsdChcImRpdlwiLCBbZWx0KFwiZGl2XCIsIG51bGwsIG51bGwsIFwibWluLXdpZHRoOiAxcHhcIildLCBcIkNvZGVNaXJyb3ItdnNjcm9sbGJhclwiKTtcbiAgICB2YXIgaG9yaXogPSB0aGlzLmhvcml6ID0gZWx0KFwiZGl2XCIsIFtlbHQoXCJkaXZcIiwgbnVsbCwgbnVsbCwgXCJoZWlnaHQ6IDEwMCU7IG1pbi1oZWlnaHQ6IDFweFwiKV0sIFwiQ29kZU1pcnJvci1oc2Nyb2xsYmFyXCIpO1xuICAgIHBsYWNlKHZlcnQpOyBwbGFjZShob3Jpeik7XG5cbiAgICBvbih2ZXJ0LCBcInNjcm9sbFwiLCBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh2ZXJ0LmNsaWVudEhlaWdodCkgc2Nyb2xsKHZlcnQuc2Nyb2xsVG9wLCBcInZlcnRpY2FsXCIpO1xuICAgIH0pO1xuICAgIG9uKGhvcml6LCBcInNjcm9sbFwiLCBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChob3Jpei5jbGllbnRXaWR0aCkgc2Nyb2xsKGhvcml6LnNjcm9sbExlZnQsIFwiaG9yaXpvbnRhbFwiKTtcbiAgICB9KTtcblxuICAgIHRoaXMuY2hlY2tlZ
23459E92ZXJsYXkgPSBmYWxzZTtcbiAgICAvLyBOZWVkIHRvIHNldCBhIG1pbmltdW0gd2lkdGggdG8gc2VlIHRoZSBzY3JvbGxiYXIgb24gSUU3IChidXQgbXVzdCBub3Qgc2V0IGl0IG9uIElFOCkuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA4KSB0aGlzLmhvcml6LnN0eWxlLm1pbkhlaWdodCA9IHRoaXMudmVydC5zdHlsZS5taW5XaWR0aCA9IFwiMThweFwiO1xuICB9XG5cbiAgTmF0aXZlU2Nyb2xsYmFycy5wcm90b3R5cGUgPSBjb3B5T2JqKHtcbiAgICB1cGRhdGU6IGZ1bmN0aW9uKG1lYXN1cmUpIHtcbiAgICAgIHZhciBuZWVkc0ggPSBtZWFzdXJlLnNjcm9sbFdpZHRoID4gbWVhc3VyZS5jbGllbnRXaWR0aCArIDE7XG4gICAgICB2YXIgbmVlZHNWID0gbWVhc3VyZS5zY3JvbGxIZWlnaHQgPiBtZWFzdXJlLmNsaWVudEhlaWdodCArIDE7XG4gICAgICB2YXIgc1dpZHRoID0gbWVhc3VyZS5uYXRpdmVCYXJXaWR0aDtcblxuICAgICAgaWYgKG5lZWRzVikge1xuICAgICAgICB0aGlzLnZlcnQuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgdGhpcy52ZXJ0LnN0eWxlLmJvdHRvbSA9IG5lZWRzSCA/IHNXaWR0aCArIFwicHhcIiA6IFwiMFwiO1xuICAgICAgICB2YXIgdG90YWxIZWlnaHQgPSBtZWFzdXJlLnZpZXdIZWlnaHQgLSAobmVlZHNIID8gc1dpZHRoIDogMCk7XG4gICAgICAgIC8vIEEgYnVnIGluIElFOCBjYW4gY2F1c2UgdGhpcyB2YWx1ZSB0byBiZSBuZWdhdGl2ZSwgc28gZ3VhcmQgaXQuXG4gICAgICAgIHRoaXMudmVydC5maXJzdENoaWxkLnN0eWxlLmhlaWdodCA9XG4gICAgICAgICAgTWF0aC5tYXgoMCwgbWVhc3VyZS5zY3JvbGxIZWlnaHQgLSBtZWFzdXJlLmNsaWVudEhlaWdodCArIHRvdGFsSGVpZ2h0KSArIFwicHhcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudmVydC5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcbiAgICAgICAgdGhpcy52ZXJ0LmZpcnN0Q2hpbGQuc3R5bGUuaGVpZ2h0ID0gXCIwXCI7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZWVkc0gpIHtcbiAgICAgICAgdGhpcy5ob3Jpei5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICB0aGlzLmhvcml6LnN0eWxlLnJpZ2h0ID0gbmVlZHNWID8gc1dpZHRoICsgXCJweFwiIDogXCIwXCI7XG4gICAgICAgIHRoaXMuaG9yaXouc3R5bGUubGVmdCA9IG1lYXN1cmUuYmFyTGVmdCArIFwicHhcIjtcbiAgICAgICAgdmFyIHRvdGFsV2lkdGggPSBtZWFzdXJlLnZpZXdXaWR0aCAtIG1lYXN1cmUuYmFyTGVmdCAtIChuZWVkc1YgPyBzV2lkdGggOiAwKTtcbiAgICAgICAgdGhpcy5ob3Jpei5maXJzdENoaWxkLnN0eWxlLndpZHRoID1cbiAgICAgICAgICAobWVhc3VyZS5zY3JvbGxXaWR0aCAtIG1lYXN1cmUuY2xpZW50V2lkdGggKyB0b3RhbFdpZHRoKSArIFwicHhcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaG9yaXouc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICAgIHRoaXMuaG9yaXouZmlyc3RDaGlsZC5zdHlsZS53aWR0aCA9IFwiMFwiO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuY2hlY2tlZE92ZXJsYXkgJiYgbWVhc3VyZS5jbGllbnRIZWlnaHQgPiAwKSB7XG4gICAgICAgIGlmIChzV2lkdGggPT0gMCkgdGhpcy5vdmVybGF5SGFjaygpO1xuICAgICAgICB0aGlzLmNoZWNrZWRPdmVybGF5ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtyaWdodDogbmVlZHNWID8gc1dpZHRoIDogMCwgYm90dG9tOiBuZWVkc0ggPyBzV2lkdGggOiAwfTtcbiAgICB9LFxuICAgIHNldFNjcm9sbExlZnQ6IGZ1bmN0aW9uKHBvcykge1xuICAgICAgaWYgKHRoaXMuaG9yaXouc2Nyb2xsTGVmdCAhPSBwb3MpIHRoaXMuaG9yaXouc2Nyb2xsTGVmdCA9IHBvcztcbiAgICB9LFxuICAgIHNldFNjcm9sbFRvcDogZnVuY3Rpb24ocG9zKSB7XG4gICAgICBpZiAodGhpcy52ZXJ0LnNjcm9sbFRvcCAhPSBwb3MpIHRoaXMudmVydC5zY3JvbGxUb3AgPSBwb3M7XG4gICAgfSxcbiAgICBvdmVybGF5SGFjazogZnVuY3Rpb24oKSB7XG4gICAgICB2Y
23459XIgdyA9IG1hYyAmJiAhbWFjX2dlTW91bnRhaW5MaW9uID8gXCIxMnB4XCIgOiBcIjE4cHhcIjtcbiAgICAgIHRoaXMuaG9yaXouc3R5bGUubWluSGVpZ2h0ID0gdGhpcy52ZXJ0LnN0eWxlLm1pbldpZHRoID0gdztcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBiYXJNb3VzZURvd24gPSBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlmIChlX3RhcmdldChlKSAhPSBzZWxmLnZlcnQgJiYgZV90YXJnZXQoZSkgIT0gc2VsZi5ob3JpeilcbiAgICAgICAgICBvcGVyYXRpb24oc2VsZi5jbSwgb25Nb3VzZURvd24pKGUpO1xuICAgICAgfTtcbiAgICAgIG9uKHRoaXMudmVydCwgXCJtb3VzZWRvd25cIiwgYmFyTW91c2VEb3duKTtcbiAgICAgIG9uKHRoaXMuaG9yaXosIFwibW91c2Vkb3duXCIsIGJhck1vdXNlRG93bik7XG4gICAgfSxcbiAgICBjbGVhcjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcGFyZW50ID0gdGhpcy5ob3Jpei5wYXJlbnROb2RlO1xuICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMuaG9yaXopO1xuICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMudmVydCk7XG4gICAgfVxuICB9LCBOYXRpdmVTY3JvbGxiYXJzLnByb3RvdHlwZSk7XG5cbiAgZnVuY3Rpb24gTnVsbFNjcm9sbGJhcnMoKSB7fVxuXG4gIE51bGxTY3JvbGxiYXJzLnByb3RvdHlwZSA9IGNvcHlPYmooe1xuICAgIHVwZGF0ZTogZnVuY3Rpb24oKSB7IHJldHVybiB7Ym90dG9tOiAwLCByaWdodDogMH07IH0sXG4gICAgc2V0U2Nyb2xsTGVmdDogZnVuY3Rpb24oKSB7fSxcbiAgICBzZXRTY3JvbGxUb3A6IGZ1bmN0aW9uKCkge30sXG4gICAgY2xlYXI6IGZ1bmN0aW9uKCkge31cbiAgfSwgTnVsbFNjcm9sbGJhcnMucHJvdG90eXBlKTtcblxuICBDb2RlTWlycm9yLnNjcm9sbGJhck1vZGVsID0ge1wibmF0aXZlXCI6IE5hdGl2ZVNjcm9sbGJhcnMsIFwibnVsbFwiOiBOdWxsU2Nyb2xsYmFyc307XG5cbiAgZnVuY3Rpb24gaW5pdFNjcm9sbGJhcnMoY20pIHtcbiAgICBpZiAoY20uZGlzcGxheS5zY3JvbGxiYXJzKSB7XG4gICAgICBjbS5kaXNwbGF5LnNjcm9sbGJhcnMuY2xlYXIoKTtcbiAgICAgIGlmIChjbS5kaXNwbGF5LnNjcm9sbGJhcnMuYWRkQ2xhc3MpXG4gICAgICAgIHJtQ2xhc3MoY20uZGlzcGxheS53cmFwcGVyLCBjbS5kaXNwbGF5LnNjcm9sbGJhcnMuYWRkQ2xhc3MpO1xuICAgIH1cblxuICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycyA9IG5ldyBDb2RlTWlycm9yLnNjcm9sbGJhck1vZGVsW2NtLm9wdGlvbnMuc2Nyb2xsYmFyU3R5bGVdKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGNtLmRpc3BsYXkud3JhcHBlci5pbnNlcnRCZWZvcmUobm9kZSwgY20uZGlzcGxheS5zY3JvbGxiYXJGaWxsZXIpO1xuICAgICAgLy8gUHJldmVudCBjbGlja3MgaW4gdGhlIHNjcm9sbGJhcnMgZnJvbSBraWxsaW5nIGZvY3VzXG4gICAgICBvbihub2RlLCBcIm1vdXNlZG93blwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKGNtLnN0YXRlLmZvY3VzZWQpIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNtLmRpc3BsYXkuaW5wdXQuZm9jdXMoKTsgfSwgMCk7XG4gICAgICB9KTtcbiAgICAgIG5vZGUuc2V0QXR0cmlidXRlKFwiY20tbm90LWNvbnRlbnRcIiwgXCJ0cnVlXCIpO1xuICAgIH0sIGZ1bmN0aW9uKHBvcywgYXhpcykge1xuICAgICAgaWYgKGF4aXMgPT0gXCJob3Jpem9udGFsXCIpIHNldFNjcm9sbExlZnQoY20sIHBvcyk7XG4gICAgICBlbHNlIHNldFNjcm9sbFRvcChjbSwgcG9zKTtcbiAgICB9LCBjbSk7XG4gICAgaWYgKGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5hZGRDbGFzcylcbiAgICAgIGFkZENsYXNzKGNtLmRpc3BsYXkud3JhcHBlciwgY20uZGlzcGxheS5zY3JvbGxiYXJzLmFkZENsYXNzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVNjcm9sbGJhcnMoY20sIG1lYXN1cmUpIHtcbiAgICBpZiAoIW1lYXN1cmUpIG1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7XG4gICAgdmFyIHN0YXJ0V2lkdGggPSBjbS5kaXNwbGF5LmJhcldpZHRoLCBzdGFydEhlaWdodCA9IGNtLmRpc3BsYXkuYmFySGVpZ2h0O1xuICAgIHVwZGF0ZVNjcm9sbGJhcnNJbm5lcihjbSwgbWVhc3VyZSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0ICYmIHN0YXJ0V2lkdGggIT0gY20uZGlzcGxheS5iYXJXaWR0aCB8fCBzdGFydEhlaWdodCAhPSBjbS5kaXNwbGF5LmJhckhlaWdodDsgaSsrKSB7XG4gICAgICBpZiAoc3RhcnRXaWR0aCAhPSBjbS5kaXNwbGF5LmJhcldpZHRoICYmIGNtLm9wdGlvbnMubGluZVdyYXBwaW5nKVxuICAgICAgICB1cGRhdGVIZWlnaHRzSW5WaWV3cG9ydChjbSk7XG4gICAgICB1cGRhdGVTY3JvbGxiYXJzSW5uZXIoY20sIG1lYXN1cmVGb3JTY3JvbGxiYXJzKGNtKSk7XG4gICAgICBzdGFydFdpZHRoID0gY20uZGlzcGxheS5iYXJXaWR0aDsgc3RhcnRIZWlnaHQgPSBjbS5kaXNwbGF5LmJhckhlaWdodDtcbiAgICB9XG4gIH1cblxuICAvLyBSZS1zeW5jaHJvbml6ZSB0aGUgZmFrZSBzY3JvbGxiYXJzIHdpdGggdGhlIGFjdHVhbCBzaXplIG9mIHRoZVxuICAvLyBjb250ZW50LlxuICBmdW5jdGlvbiB1cGRhdGVTY3JvbGxiYXJzSW5uZXIoY20sIG1lYXN1cmUpIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXk7XG4gICAgdmFyIHNpemVzID0gZC5zY3JvbGxiYXJzLnVwZGF0ZShtZWFzdXJlKTtcblxuICAgIGQuc2l6ZXIuc3R5bGUucGFkZGluZ1JpZ2h0ID0gKGQuYmFyV2lkdGggPSBzaXplcy5yaWdodCkgKyBcInB4XCI7XG4gICAgZC5zaXplci5zdHlsZS5wYWRkaW5nQm90dG9tID0gKGQuYmFySGVpZ2h0ID0gc2l6ZXMuYm90dG9tKSArIFwicHhcIjtcblxuICAgIGlmIChzaXplcy5yaWdodCAmJiBzaXplcy5ib3R0b20pIHtcbiAgICAgIGQuc2Nyb2xsYmFyRmlsbGVyLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICBkLnNjcm9sbGJhckZpbGxlci5zdHlsZS5oZWlnaHQgPSBzaXplcy5ib3R0b20gKyBcInB4XCI7XG4gICAgICBkLnNjcm9sbGJhckZpbGxlci5zdHlsZS53aWR0aCA9IHNpemVzLnJpZ2h0ICsgXCJweFwiO1xuICAgIH0gZWxzZSBkLnNjcm9sbGJhckZpbGxlci5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcbiAgICBpZiAoc2l6ZXMuYm90dG9tICYmIGNtLm9wdGlvbnMuY292ZXJHdXR0ZXJOZXh0VG9TY3JvbGxiYXIgJiYgY20ub3B0aW9ucy5maXhlZEd1dHRlcikge1xuICAgICAgZC5ndXR0ZXJGaWxsZXIuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgIGQuZ3V0dGVyRmlsbGVyLnN0eWxlLmhlaWdodCA9IHNpemVzLmJvdHRvbSArIFwicHhcIjtcbiAgICAgIGQuZ3V0dGVyRmlsbGVyLnN0eWxlLndpZHRoID0gbWVhc3VyZS5ndXR0ZXJXaWR0aCArIFwicHhcIjtcbiAgICB9IGVsc2UgZC5ndXR0ZXJGaWxsZXIuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gIH1cblxuICAvLyBDb21wdXRlIHRoZSBsaW5lcyB0aGF0IGFyZSB2aXN
23459pYmxlIGluIGEgZ2l2ZW4gdmlld3BvcnQgKGRlZmF1bHRzXG4gIC8vIHRoZSB0aGUgY3VycmVudCBzY3JvbGwgcG9zaXRpb24pLiB2aWV3cG9ydCBtYXkgY29udGFpbiB0b3AsXG4gIC8vIGhlaWdodCwgYW5kIGVuc3VyZSAoc2VlIG9wLnNjcm9sbFRvUG9zKSBwcm9wZXJ0aWVzLlxuICBmdW5jdGlvbiB2aXNpYmxlTGluZXMoZGlzcGxheSwgZG9jLCB2aWV3cG9ydCkge1xuICAgIHZhciB0b3AgPSB2aWV3cG9ydCAmJiB2aWV3cG9ydC50b3AgIT0gbnVsbCA/IE1hdGgubWF4KDAsIHZpZXdwb3J0LnRvcCkgOiBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcDtcbiAgICB0b3AgPSBNYXRoLmZsb29yKHRvcCAtIHBhZGRpbmdUb3AoZGlzcGxheSkpO1xuICAgIHZhciBib3R0b20gPSB2aWV3cG9ydCAmJiB2aWV3cG9ydC5ib3R0b20gIT0gbnVsbCA/IHZpZXdwb3J0LmJvdHRvbSA6IHRvcCArIGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQ7XG5cbiAgICB2YXIgZnJvbSA9IGxpbmVBdEhlaWdodChkb2MsIHRvcCksIHRvID0gbGluZUF0SGVpZ2h0KGRvYywgYm90dG9tKTtcbiAgICAvLyBFbnN1cmUgaXMgYSB7ZnJvbToge2xpbmUsIGNofSwgdG86IHtsaW5lLCBjaH19IG9iamVjdCwgYW5kXG4gICAgLy8gZm9yY2VzIHRob3NlIGxpbmVzIGludG8gdGhlIHZpZXdwb3J0IChpZiBwb3NzaWJsZSkuXG4gICAgaWYgKHZpZXdwb3J0ICYmIHZpZXdwb3J0LmVuc3VyZSkge1xuICAgICAgdmFyIGVuc3VyZUZyb20gPSB2aWV3cG9ydC5lbnN1cmUuZnJvbS5saW5lLCBlbnN1cmVUbyA9IHZpZXdwb3J0LmVuc3VyZS50by5saW5lO1xuICAgICAgaWYgKGVuc3VyZUZyb20gPCBmcm9tKSB7XG4gICAgICAgIGZyb20gPSBlbnN1cmVGcm9tO1xuICAgICAgICB0byA9IGxpbmVBdEhlaWdodChkb2MsIGhlaWdodEF0TGluZShnZXRMaW5lKGRvYywgZW5zdXJlRnJvbSkpICsgZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodCk7XG4gICAgICB9IGVsc2UgaWYgKE1hdGgubWluKGVuc3VyZVRvLCBkb2MubGFzdExpbmUoKSkgPj0gdG8pIHtcbiAgICAgICAgZnJvbSA9IGxpbmVBdEhlaWdodChkb2MsIGhlaWdodEF0TGluZShnZXRMaW5lKGRvYywgZW5zdXJlVG8pKSAtIGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQpO1xuICAgICAgICB0byA9IGVuc3VyZVRvO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge2Zyb206IGZyb20sIHRvOiBNYXRoLm1heCh0bywgZnJvbSArIDEpfTtcbiAgfVxuXG4gIC8vIExJTkUgTlVNQkVSU1xuXG4gIC8vIFJlLWFsaWduIGxpbmUgbnVtYmVycyBhbmQgZ3V0dGVyIG1hcmtzIHRvIGNvbXBlbnNhdGUgZm9yXG4gIC8vIGhvcml6b250YWwgc2Nyb2xsaW5nLlxuICBmdW5jdGlvbiBhbGlnbkhvcml6b250YWxseShjbSkge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheSwgdmlldyA9IGRpc3BsYXkudmlldztcbiAgICBpZiAoIWRpc3BsYXkuYWxpZ25XaWRnZXRzICYmICghZGlzcGxheS5ndXR0ZXJzLmZpcnN0Q2hpbGQgfHwgIWNtLm9wdGlvbnMuZml4ZWRHdXR0ZXIpKSByZXR1cm47XG4gICAgdmFyIGNvbXAgPSBjb21wZW5zYXRlRm9ySFNjcm9sbChkaXNwbGF5KSAtIGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsTGVmdCArIGNtLmRvYy5zY3JvbGxMZWZ0O1xuICAgIHZhciBndXR0ZXJXID0gZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoLCBsZWZ0ID0gY29tcCArIFwicHhcIjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZpZXcubGVuZ3RoOyBpKyspIGlmICghdmlld1tpXS5oaWRkZW4pIHtcbiAgICAgIGlmIChjbS5vcHRpb25zLmZpeGVkR3V0dGVyICYmIHZpZXdbaV0uZ3V0dGVyKVxuICAgICAgICB2aWV3W2ldLmd1dHRlci5zdHlsZS5sZWZ0ID0gbGVmdDtcbiAgICAgIHZhciBhbGlnbiA9IHZpZXdbaV0uYWxpZ25hYmxlO1xuICAgICAgaWYgKGFsaWduKSBmb3IgKHZhciBqID0gMDsgaiA8IGFsaWduLmxlbmd0aDsgaisrKVxuICAgICAgICBhbGlnbltqXS5zdHlsZS5sZWZ0ID0gbGVmdDtcbiAgICB9XG4gICAgaWYgKGNtLm9wdGlvbnMuZml4ZWRHdXR0ZXIpXG4gICAgICBkaXNwbGF5Lmd1dHRlcnMuc3R5bGUubGVmdCA9IChjb21wICsgZ3V0dGVyVykgKyBcInB4XCI7XG4gIH1cblxuICAvLyBVc2VkIHRvIGVuc3VyZSB0aGF0IHRoZSBsaW5lIG51bWJlciBndXR0ZXIgaXMgc3RpbGwgdGhlIHJpZ2h0XG4gIC8vIHNpemUgZm9yIHRoZSBjdXJyZW50IGRvY3VtZW50IHNpemUuIFJldHVybnMgdHJ1ZSB3aGVuIGFuIHVwZGF0ZVxuICAvLyBpcyBuZWVkZWQuXG4gIGZ1bmN0aW9uIG1heWJlVXBkYXRlTGluZU51bWJlcldpZHRoKGNtKSB7XG4gICAgaWYgKCFjbS5vcHRpb25zLmxpbmVOdW1iZXJzKSByZXR1cm4gZmFsc2U7XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgbGFzdCA9IGxpbmVOdW1iZXJGb3IoY20ub3B0aW9ucywgZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxKSwgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKGxhc3QubGVuZ3RoICE9IGRpc3BsYXkubGluZU51bUNoYXJzKSB7XG4gICAgICB2Y
23459XIgdGVzdCA9IGRpc3BsYXkubWVhc3VyZS5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgW2VsdChcImRpdlwiLCBsYXN0KV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJDb2RlTWlycm9yLWxpbmVudW1iZXIgQ29kZU1pcnJvci1ndXR0ZXItZWx0XCIpKTtcbiAgICAgIHZhciBpbm5lclcgPSB0ZXN0LmZpcnN0Q2hpbGQub2Zmc2V0V2lkdGgsIHBhZGRpbmcgPSB0ZXN0Lm9mZnNldFdpZHRoIC0gaW5uZXJXO1xuICAgICAgZGlzcGxheS5saW5lR3V0dGVyLnN0eWxlLndpZHRoID0gXCJcIjtcbiAgICAgIGRpc3BsYXkubGluZU51bUlubmVyV2lkdGggPSBNYXRoLm1heChpbm5lclcsIGRpc3BsYXkubGluZUd1dHRlci5vZmZzZXRXaWR0aCAtIHBhZGRpbmcpICsgMTtcbiAgICAgIGRpc3BsYXkubGluZU51bVdpZHRoID0gZGlzcGxheS5saW5lTnVtSW5uZXJXaWR0aCArIHBhZGRpbmc7XG4gICAgICBkaXNwbGF5LmxpbmVOdW1DaGFycyA9IGRpc3BsYXkubGluZU51bUlubmVyV2lkdGggPyBsYXN0Lmxlbmd0aCA6IC0xO1xuICAgICAgZGlzcGxheS5saW5lR3V0dGVyLnN0eWxlLndpZHRoID0gZGlzcGxheS5saW5lTnVtV2lkdGggKyBcInB4XCI7XG4gICAgICB1cGRhdGVHdXR0ZXJTcGFjZShjbSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gbGluZU51bWJlckZvcihvcHRpb25zLCBpKSB7XG4gICAgcmV0dXJuIFN0cmluZyhvcHRpb25zLmxpbmVOdW1iZXJGb3JtYXR0ZXIoaSArIG9wdGlvbnMuZmlyc3RMaW5lTnVtYmVyKSk7XG4gIH1cblxuICAvLyBDb21wdXRlcyBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQgKyBkaXNwbGF5Lmd1dHRlcnMub2Zmc2V0V2lkdGgsXG4gIC8vIGJ1dCB1c2luZyBnZXRCb3VuZGluZ0NsaWVudFJlY3QgdG8gZ2V0IGEgc3ViLXBpeGVsLWFjY3VyYXRlXG4gIC8vIHJlc3VsdC5cbiAgZnVuY3Rpb24gY29tcGVuc2F0ZUZvckhTY3JvbGwoZGlzcGxheSkge1xuICAgIHJldHVybiBkaXNwbGF5LnNjcm9sbGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLSBkaXNwbGF5LnNpemVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQ7XG4gIH1cblxuICAvLyBESVNQTEFZIERSQVdJTkdcblxuICBmdW5jdGlvbiBEaXNwbGF5VXBkYXRlKGNtLCB2aWV3cG9ydCwgZm9yY2UpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG5cbiAgICB0aGlzLnZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgLy8gU3RvcmUgc29tZSB2YWx1ZXMgdGhhdCB3ZSdsbCBuZWVkIGxhdGVyIChidXQgZG9uJ3Qgd2FudCB0byBmb3JjZSBhIHJlbGF5b3V0IGZvcilcbiAgICB0aGlzLnZpc2libGUgPSB2aXNpYmxlTGluZXMoZGlzcGxheSwgY20uZG9jLCB2aWV3cG9ydCk7XG4gICAgdGhpcy5lZGl0b3JJc0hpZGRlbiA9ICFkaXNwbGF5LndyYXBwZXIub2Zmc2V0V2lkdGg7XG4gICAgdGhpcy53cmFwcGVySGVpZ2h0ID0gZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodDtcbiAgICB0aGlzLndyYXBwZXJXaWR0aCA9IGRpc3BsYXkud3JhcHBlci5jbGllbnRXaWR0aDtcbiAgICB0aGlzLm9sZERpc3BsYXlXaWR0aCA9IGRpc3BsYXlXaWR0aChjbSk7XG4gICAgdGhpcy5mb3JjZSA9IGZvcmNlO1xuICAgIHRoaXMuZGltcyA9IGdldERpbWVuc2lvbnMoY20pO1xuICAgIHRoaXMuZXZlbnRzID0gW107XG4gIH1cblxuICBEaXNwbGF5VXBkYXRlLnByb3RvdHlwZS5zaWduYWwgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gICAgaWYgKGhhc0hhbmRsZXIoZW1pdHRlciwgdHlwZSkpXG4gICAgICB0aGlzLmV2ZW50cy5wdXNoKGFyZ3VtZW50cyk7XG4gIH07XG4gIERpc3BsYXlVcGRhdGUucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ldmVudHMubGVuZ3RoOyBpKyspXG4gICAgICBzaWduYWwuYXBwbHkobnVsbCwgdGhpcy5ldmVudHNbaV0pO1xuICB9O1xuXG4gIGZ1bmN0aW9uIG1heWJlQ2xpcFNjcm9sbGJhcnMoY20pIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKCFkaXNwbGF5LnNjcm9sbGJhcnNDbGlwcGVkICYmIGRpc3BsYXkuc2Nyb2xsZXIub2Zmc2V0V2lkdGgpIHtcbiAgICAgIGRpc3BsYXkubmF0aXZlQmFyV2lkdGggPSBkaXNwbGF5LnNjcm9sbGVyLm9mZnNldFdpZHRoIC0gZGlzcGxheS5zY3JvbGxlci5jbGllbnRXaWR0aDtcbiAgICAgIGRpc3BsYXkuaGVpZ2h0Rm9yY2VyLnN0eWxlLmhlaWdodCA9IHNjcm9sbEdhcChjbSkgKyBcInB4XCI7XG4gICAgICBkaXNwbGF5LnNpemVyLnN0eWxlLm1hcmdpbkJvdHRvbSA9IC1kaXNwbGF5Lm5hdGl2ZUJhcldpZHRoICsgXCJweFwiO1xuICAgICAgZGlzcGxheS5zaXplci5zdHlsZS5ib3JkZXJSaWdodFdpZHRoID0gc2Nyb2xsR2FwKGNtKSArIFwicHhcIjtcbiAgICAgIGRpc3BsYXkuc2Nyb2xsYmFyc0NsaXBwZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8vIERvZXMgdGhlIGFjdHVhbCB1cGRhdGluZyBvZiB0aGUgbGluZSBkaXNwbGF5LiBCYWlscyBvdXRcbiAgLy8gKHJldHVybmluZyBmYWxzZSkgd2hlbiB0aGVyZSBpcyBub3RoaW5nIHRvIGJlIGRvbmUgYW5kIGZvcmNlZCBpc1xuICAvLyBmYWxzZS5cbiAgZnVuY3Rpb24gdXBkYXRlRGlzcGxheUlmTmVlZGVkKGNtLCB1cGRhdGUpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIGRvYyA9IGNtLmRvYztcblxuICAgIGlmICh1cGRhdGUuZWRpdG9ySXNIaWRkZW4pIHtcbiAgICAgIHJlc2V0VmlldyhjbSk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gQmFpbCBvdXQgaWYgdGhlIHZpc2libGUgYXJlYSBpcyBhbHJlYWR5IHJlbmRlcmVkIGFuZCBub3RoaW5nIGNoYW5nZWQuXG4gICAgaWYgKCF1cGRhdGUuZm9yY2UgJiZcbiAgICAgICAgdXBkYXRlLnZpc2libGUuZnJvbSA+PSBkaXNwbGF5LnZpZXdGcm9tICYmIHVwZGF0ZS52aXNpYmxlLnRvIDw9IGRpc3BsYXkudmlld1RvICYmXG4gICAgICAgIChkaXNwbGF5LnVwZGF0ZUxpbmVOdW1iZXJzID09IG51bGwgfHwgZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA+PSBkaXNwbGF5LnZpZXdUbykgJiZcbiAgICAgICAgZGlzcGxheS5yZW5kZXJlZFZpZXcgPT0gZGlzcGxheS52aWV3ICYmIGNvdW50RGlydHlWaWV3KGNtKSA9PSAwKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKG1heWJlVXBkYXRlTGluZU51bWJlcldpZHRoKGNtKSkge1xuICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIHVwZGF0ZS5kaW1zID0gZ2V0RGltZW5zaW9ucyhjbSk7XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBhIHN1aXRhYmxlIG5ldyB2aWV3cG9ydCAoZnJvbSAmIHRvKVxuICAgIHZhciBlbmQgPSBkb2MuZmlyc3QgKyBkb2Muc2l6ZTtcbiAgICB2YXIgZnJvbSA9IE1hdGgubWF4KHVwZGF0ZS52aXNpYmxlLmZyb20gLSBjbS5vcHRpb25zLnZpZXdwb3J0TWFy
23459Z2luLCBkb2MuZmlyc3QpO1xuICAgIHZhciB0byA9IE1hdGgubWluKGVuZCwgdXBkYXRlLnZpc2libGUudG8gKyBjbS5vcHRpb25zLnZpZXdwb3J0TWFyZ2luKTtcbiAgICBpZiAoZGlzcGxheS52aWV3RnJvbSA8IGZyb20gJiYgZnJvbSAtIGRpc3BsYXkudmlld0Zyb20gPCAyMCkgZnJvbSA9IE1hdGgubWF4KGRvYy5maXJzdCwgZGlzcGxheS52aWV3RnJvbSk7XG4gICAgaWYgKGRpc3BsYXkudmlld1RvID4gdG8gJiYgZGlzcGxheS52aWV3VG8gLSB0byA8IDIwKSB0byA9IE1hdGgubWluKGVuZCwgZGlzcGxheS52aWV3VG8pO1xuICAgIGlmIChzYXdDb2xsYXBzZWRTcGFucykge1xuICAgICAgZnJvbSA9IHZpc3VhbExpbmVObyhjbS5kb2MsIGZyb20pO1xuICAgICAgdG8gPSB2aXN1YWxMaW5lRW5kTm8oY20uZG9jLCB0byk7XG4gICAgfVxuXG4gICAgdmFyIGRpZmZlcmVudCA9IGZyb20gIT0gZGlzcGxheS52aWV3RnJvbSB8fCB0byAhPSBkaXNwbGF5LnZpZXdUbyB8fFxuICAgICAgZGlzcGxheS5sYXN0V3JhcEhlaWdodCAhPSB1cGRhdGUud3JhcHBlckhlaWdodCB8fCBkaXNwbGF5Lmxhc3RXcmFwV2lkdGggIT0gdXBkYXRlLndyYXBwZXJXaWR0aDtcbiAgICBhZGp1c3RWaWV3KGNtLCBmcm9tLCB0byk7XG5cbiAgICBkaXNwbGF5LnZpZXdPZmZzZXQgPSBoZWlnaHRBdExpbmUoZ2V0TGluZShjbS5kb2MsIGRpc3BsYXkudmlld0Zyb20pKTtcbiAgICAvLyBQb3NpdGlvbiB0aGUgbW92ZXIgZGl2IHRvIGFsaWduIHdpdGggdGhlIGN1cnJlbnQgc2Nyb2xsIHBvc2l0aW9uXG4gICAgY20uZGlzcGxheS5tb3Zlci5zdHlsZS50b3AgPSBkaXNwbGF5LnZpZXdPZmZzZXQgKyBcInB4XCI7XG5cbiAgICB2YXIgdG9VcGRhdGUgPSBjb3VudERpcnR5VmlldyhjbSk7XG4gICAgaWYgKCFkaWZmZXJlbnQgJiYgdG9VcGRhdGUgPT0gMCAmJiAhdXBkYXRlLmZvcmNlICYmIGRpc3BsYXkucmVuZGVyZWRWaWV3ID09IGRpc3BsYXkudmlldyAmJlxuICAgICAgICAoZGlzcGxheS51cGRhdGVMaW5lTnVtYmVycyA9PSBudWxsIHx8IGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMgPj0gZGlzcGxheS52aWV3VG8pKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgLy8gRm9yIGJpZyBjaGFuZ2VzLCB3ZSBoaWRlIHRoZSBlbmNsb3NpbmcgZWxlbWVudCBkdXJpbmcgdGhlXG4gICAgLy8gdXBkYXRlLCBzaW5jZSB0aGF0IHNwZWVkcyB1cCB0aGUgb3BlcmF0aW9ucyBvbiBtb3N0IGJyb3dzZXJzLlxuICAgIHZhciBmb2N1c2VkID0gYWN0aXZlRWx0KCk7XG4gICAgaWYgKHRvVXBkYXRlID4gNCkgZGlzcGxheS5saW5lRGl2LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICBwYXRjaERpc3BsYXkoY20sIGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMsIHVwZGF0ZS5kaW1zKTtcbiAgICBpZiAodG9VcGRhdGUgPiA0KSBkaXNwbGF5LmxpbmVEaXYuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgZGlzcGxheS5yZW5kZXJlZFZpZXcgPSBkaXNwbGF5LnZpZXc7XG4gICAgLy8gVGhlcmUgbWlnaHQgaGF2ZSBiZWVuIGEgd2lkZ2V0IHdpdGggYSBmb2N1c2VkIGVsZW1lbnQgdGhhdCBnb3RcbiAgICAvLyBoaWRkZW4gb3IgdXBkYXRlZCwgaWYgc28gcmUtZm9jdXMgaX
23459QuXG4gICAgaWYgKGZvY3VzZWQgJiYgYWN0aXZlRWx0KCkgIT0gZm9jdXNlZCAmJiBmb2N1c2VkLm9mZnNldEhlaWdodCkgZm9jdXNlZC5mb2N1cygpO1xuXG4gICAgLy8gUHJldmVudCBzZWxlY3Rpb24gYW5kIGN1cnNvcnMgZnJvbSBpbnRlcmZlcmluZyB3aXRoIHRoZSBzY3JvbGxcbiAgICAvLyB3aWR0aCBhbmQgaGVpZ2h0LlxuICAgIHJlbW92ZUNoaWxkcmVuKGRpc3BsYXkuY3Vyc29yRGl2KTtcbiAgICByZW1vdmVDaGlsZHJlbihkaXNwbGF5LnNlbGVjdGlvbkRpdik7XG4gICAgZGlzcGxheS5ndXR0ZXJzLnN0eWxlLmhlaWdodCA9IGRpc3BsYXkuc2l6ZXIuc3R5bGUubWluSGVpZ2h0ID0gMDtcblxuICAgIGlmIChkaWZmZXJlbnQpIHtcbiAgICAgIGRpc3BsYXkubGFzdFdyYXBIZWlnaHQgPSB1cGRhdGUud3JhcHBlckhlaWdodDtcbiAgICAgIGRpc3BsYXkubGFzdFdyYXBXaWR0aCA9IHVwZGF0ZS53cmFwcGVyV2lkdGg7XG4gICAgICBzdGFydFdvcmtlcihjbSwgNDAwKTtcbiAgICB9XG5cbiAgICBkaXNwbGF5LnVwZGF0ZUxpbmVOdW1iZXJzID0gbnVsbDtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9zdFVwZGF0ZURpc3BsYXkoY20sIHVwZGF0ZSkge1xuICAgIHZhciB2aWV3cG9ydCA9IHVwZGF0ZS52aWV3cG9ydDtcbiAgICBmb3IgKHZhciBmaXJzdCA9IHRydWU7OyBmaXJzdCA9IGZhbHNlKSB7XG4gICAgICBpZiAoIWZpcnN0IHx8ICFjbS5vcHRpb25zLmxpbmVXcmFwcGluZyB8fCB1cGRhdGUub2xkRGlzcGxheVdpZHRoID09IGRpc3BsYXlXaWR0aChjbSkpIHtcbiAgICAgICAgLy8gQ2xpcCBmb3JjZWQgdmlld3BvcnQgdG8gYWN0dWFsIHNjcm9sbGFibGUgYXJlYS5cbiAgICAgICAgaWYgKHZpZXdwb3J0ICYmIHZpZXdwb3J0LnRvcCAhPSBudWxsKVxuICAgICAgICAgIHZpZXdwb3J0ID0ge3RvcDogTWF0aC5taW4oY20uZG9jLmhlaWdodCArIHBhZGRpbmdWZXJ0KGNtLmRpc3BsYXkpIC0gZGlzcGxheUhlaWdodChjbSksIHZpZXdwb3J0LnRvcCl9O1xuICAgICAgICAvLyBVcGRhdGVkIGxpbmUgaGVpZ2h0cyBtaWdodCByZXN1bHQgaW4gdGhlIGRyYXduIGFyZWEgbm90XG4gICAgICAgIC8vIGFjdHVhbGx5IGNvdmVyaW5nIHRoZSB2aWV3cG9ydC4gS2VlcCBsb29waW5nIHVudGlsIGl0IGRvZXMuXG4gICAgICAgIHVwZGF0ZS52aXNpYmxlID0gdmlzaWJsZUxpbmVzKGNtLmRpc3BsYXksIGNtLmRvYywgdmlld3BvcnQpO1xuICAgICAgICBpZiAodXBkYXRlLnZpc2libGUuZnJvbSA+PSBjbS5kaXNwbGF5LnZpZXdGcm9tICYmIHVwZGF0ZS52aXNpYmxlLnRvIDw9IGNtLmRpc3BsYXkudmlld1RvKVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKCF1cGRhdGVEaXNwbGF5SWZOZWVkZWQoY20sIHVwZGF0ZSkpIGJyZWFrO1xuICAgICAgdXBkYXRlSGVpZ2h0c0luVmlld3BvcnQoY20pO1xuICAgICAgdmFyIGJhck1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7XG4gICAgICB1cGRhdGVTZWxlY3Rpb24oY20pO1xuICAgICAgc2V0RG9jdW1lbnRIZWlnaHQoY20sIGJhck1lYXN1cmUpO1xuICAgICAgdXBkYXRlU2Nyb2xsYmFycyhjbSwgYmFyTWVhc3VyZSk7XG4gICAgfVxuXG4gICAgdXBkYXRlLnNpZ25hbChjbSwgXCJ1cGRhdGVcIiwgY20pO1xuICAgIGlmIChjbS5kaXNwbGF5LnZpZXdGcm9tICE9IGNtLmRpc3BsYXkucmVwb3J0ZWRWaWV3RnJvbSB8fCBjbS5kaXNwbGF5LnZpZXdUbyAhPSBjbS5kaXNwbGF5LnJlcG9ydGVkVmlld1RvKSB7XG4gICAgICB1cGRhdGUuc2lnbmFsKGNtLCBcInZpZXdwb3J0Q2hhbmdlXCIsIGNtLCBjbS5kaXNwbGF5LnZpZXdGcm9tLCBjbS5kaXNwbGF5LnZpZXdUbyk7XG4gICAgICBjbS5kaXNwbGF5LnJlcG9ydGVkVmlld0Zyb20gPSBjbS5kaXNwbGF5LnZpZXdGcm9tOyBjbS5kaXNwbGF5LnJlcG9ydGVkVmlld1RvID0gY20uZGlzcGxheS52aWV3VG87XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlRGlzcGxheVNpbXBsZShjbSwgdmlld3BvcnQpIHtcbiAgICB2YXIgdXBkYXRlID0gbmV3IERpc3BsYXlVcGRhdGUoY20sIHZpZXdwb3J0KTtcbiAgICBpZiAodXBkYXRlRGlzcGxheUlmTmVlZGVkKGNtLCB1cGRhdGUpKSB7XG4gICAgICB1cGRhdGVIZWlnaHRzSW5WaWV3cG9ydChjbSk7XG4gICAgICBwb3N0VXBkYXRlRGlzcGxheShjbSwgdXBkYXRlKTtcbiAgICAgIHZhciBiYXJNZWFzdXJlID0gbWVhc3VyZUZvclNjcm9sbGJhcnMoY20pO1xuICAgICAgdXBkYXRlU2VsZWN0aW9uKGNtKTtcbiAgICAgIHNldERvY3VtZW50SGVpZ2h0KGNtLCBiYXJNZWFzdXJlKTtcbiAgICAgIHVwZGF0ZVNjcm9sbGJhcnMoY20sIGJhck1lYXN1cmUpO1xuICAgICAgdXBkYXRlLmZpbmlzaCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldERvY3VtZW50SGVpZ2h0KGNtLCBtZWFzdXJlKSB7XG4gICAgY20uZGlzcGxheS5zaXplci5zdHlsZS5taW5IZWlnaHQgPSBtZWFzdXJlLmRvY0hlaWdodCArIFwicHhcIjtcbiAgICB2YXIgdG90YWwgPSBtZWFzdXJlLmRvY0hlaWdodCArIGNtLmRpc3BsYXkuYmFySGVpZ2h0O1xuICAgIGNtLmRpc3BsYXkuaGVpZ2h0Rm9yY2VyLnN0eWxlLnRvcCA9IHRvdGFsICsgXCJweFwiO1xuICAgIGNtLmRpc3BsYXkuZ3V0dGVycy5zdHlsZS5oZWlnaHQgPSBNYXRoLm1heCh0b3RhbCArIHNjcm9sbEdhcChjbSksIG1lYXN1cmUuY2xpZW50SGVpZ2h0KSArIFwicHhcIjtcbiAgfVxuXG4gIC8vIFJlYWQgdGhlIGFjdHVhbCBoZWlnaHRzIG9mIHRoZSByZW5kZXJlZCBsaW5lcywgYW5kIHVwZGF0ZSB0aGVpclxuICAvLyBzdG9yZWQgaGVpZ2h0cyB0byBtYXRjaC5cbiAgZnVuY3Rpb24gdXBkYXRlSGVpZ2h0c0luVmlld3BvcnQoY20pIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgdmFyIHByZXZCb3R0b20gPSBkaXNwbGF5LmxpbmVEaXYub2Zmc2V0VG9wO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGlzcGxheS52aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgY3VyID0gZGlzcGxheS52aWV3W2ldLCBoZWlnaHQ7XG4gICAgICBpZiAoY3VyLmhpZGRlbikgY29udGludWU7XG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDgpIHtcbiAgICAgICAgdmFyIGJvdCA9IGN1ci5ub2RlLm9mZnNldFRvcCArIGN1ci5ub2RlLm9mZnNldEhlaWdodDtcbiAgICAgICAgaGVpZ2h0ID0gYm90IC0gcHJldkJvdHRvbTtcbiAgICAgICAgcHJldkJvdHRvbSA9IGJvdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBib3ggPSBjdXIubm9kZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaGVpZ2h0ID0gYm94LmJvdHRvbSAtIGJveC50b3A7XG4gICAgICB9XG4gICAgICB2YXIgZGlmZiA9IGN1ci5saW5lLmhlaWdodCAtIGhlaWdodDtcbiAgICAgIGlmIChoZWlnaHQgPCAyKSBoZWlnaHQgPSB0ZXh0SGVpZ2h0KGRpc3BsYXkpO1xuICAgICAgaWYgKGRpZmYgPiAuMDAxIHx8IGRpZmYgPCAtLjAwMSkge1xuICAgICAgICB1cGRhdGVMaW5lSGVpZ2h0KGN1ci5saW5lLCBoZWlnaHQpO1xuICAgICAgICB1cGRhdGVXaWRnZXRIZWlnaHQoY3VyLmxpbmUpO1xuICAgICAgICBpZiAoY3VyLnJlc3QpIGZvciAodmFyIGogPSAwOyBqIDwgY3VyLnJlc3QubGVuZ3RoOyBqKyspXG4gICAgICAgICAgdXBkYXRlV2lkZ2V0SGVpZ2h0KGN1ci5yZXN0W2pdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBSZWFkIGFuZCBzdG9yZSB0aGUgaGVpZ2h0IG9mIGxpbmUgd2lkZ2V0cyBhc3NvY2lhdGVkIHdpdGggdGhlXG4gIC8vIGdpdmVuIGxpbmUuXG4gIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldEhlaWdodChsaW5lKSB7XG4gICAgaWYgKGxpbmUud2lkZ2V0cykgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lLndpZGdldHMubGVuZ3RoOyArK2kpXG4gICAgICBsaW5lLndpZGdldHNbaV0uaGVpZ2h0ID0gbGluZS53aWRnZXRzW2ldLm
vendor: 15,580 bytes, line 23459
234595vZGUub2Zmc2V0SGVpZ2h0O1xuICB9XG5cbiAgLy8gRG8gYSBidWxrLXJlYWQgb2YgdGhlIERPTSBwb3NpdGlvbnMgYW5kIHNpemVzIG5lZWRlZCB0byBkcmF3IHRoZVxuICAvLyB2aWV3LCBzbyB0aGF0IHdlIGRvbid0IGludGVybGVhdmUgcmVhZGluZyBhbmQgd3JpdGluZyB0byB0aGUgRE9NLlxuICBmdW5jdGlvbiBnZXREaW1lbnNpb25zKGNtKSB7XG4gICAgdmFyIGQgPSBjbS5kaXNwbGF5LCBsZWZ0ID0ge30sIHdpZHRoID0ge307XG4gICAgdmFyIGd1dHRlckxlZnQgPSBkLmd1dHRlcnMuY2xpZW50TGVmdDtcbiAgICBmb3IgKHZhciBuID0gZC5ndXR0ZXJzLmZpcnN0Q2hpbGQsIGkgPSAwOyBuOyBuID0gbi5uZXh0U2libGluZywgKytpKSB7XG4gICAgICBsZWZ0W2NtLm9wdGlvbnMuZ3V0dGVyc1tpXV0gPSBuLm9mZnNldExlZnQgKyBuLmNsaWVudExlZnQgKyBndXR0ZXJMZWZ0O1xuICAgICAgd2lkdGhbY20ub3B0aW9ucy5ndXR0ZXJzW2ldXSA9IG4uY2xpZW50V2lkdGg7XG4gICAgfVxuICAgIHJldHVybiB7Zml4ZWRQb3M6IGNvbXBlbnNhdGVGb3JIU2Nyb2xsKGQpLFxuICAgICAgICAgICAgZ3V0dGVyVG90YWxXaWR0aDogZC5ndXR0ZXJzLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgZ3V0dGVyTGVmdDogbGVmdCxcbiAgICAgICAgICAgIGd1dHRlcldpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgIHdyYXBwZXJXaWR0aDogZC53cmFwcGVyLmNsaWVudFdpZHRofTtcbiAgfVxuXG4gIC8vIFN5bmMgdGhlIGFjdHVhbCBkaXNwbGF5IERPTSBzdHJ1Y3R1cmUgd2l0aCBkaXNwbGF5LnZpZXcsIHJlbW92aW5nXG4gIC8vIG5vZGVzIGZvciBsaW5lcyB0aGF0IGFyZSBubyBsb25nZXIgaW4gdmlldywgYW5kIGNyZWF0aW5nIHRoZSBvbmVzXG4gIC8vIHRoYXQgYXJlIG5vdCB0aGVyZSB5ZXQsIGFuZCB1cGRhdGluZyB0aGUgb25lcyB0aGF0IGFyZSBvdXQgb2ZcbiAgLy8gZGF0ZS5cbiAgZnVuY3Rpb24gcGF0Y2hEaXNwbGF5KGNtLCB1cGRhdGVOdW1iZXJzRnJvbSwgZGltcykge1xuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheSwgbGluZU51bWJlcnMgPSBjbS5vcHRpb25zLmxpbmVOdW1iZXJzO1xuICAgIHZhciBjb250YWluZXIgPSBkaXNwbGF5LmxpbmVEaXYsIGN1ciA9IGNvbnRhaW5lci5maXJzdENoaWxkO1xuXG4gICAgZnVuY3Rpb24gcm0obm9kZSkge1xuICAgICAgdmFyIG5leHQgPSBub2RlLm5leHRTaWJsaW5nO1xuICAgICAgLy8gV29ya3MgYXJvdW5kIGEgdGhyb3ctc2Nyb2xsIGJ1ZyBpbiBPUyBYIFdlYmtpdFxuICAgICAgaWYgKHdlYmtpdCAmJiBtYWMgJiYgY20uZGlzcGxheS5jdXJyZW50V2hlZWxUYXJnZXQgPT0gbm9kZSlcbiAgICAgICAgbm9kZS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICBlbHNlXG4gICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgIHJldHVybiBuZXh0O1xuICAgIH1cblxuICAgIHZhciB2aWV3ID0gZGlzcGxheS52aWV3LCBsaW5lTiA9IGRpc3BsYXkudmlld0Zyb207XG4gICAgLy8gTG9vcCBvdmVyIHRoZSBlbGVtZW50cyBpbiB0aGUgdmlldywgc3luY2luZyBjdXIgKHRoZSBET00gbm9kZXNcbiAgICAvLyBpbiBkaXNwbGF5LmxpbmVEaXYpIHdpdGggdGhlIHZpZXcgYXMgd2UgZ28uXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbGluZVZpZXcgPSB2aWV3W2ldO1xuICAgICAgaWYgKGxpbmVWaWV3LmhpZGRlbikge1xuICAgICAgfSBlbHNlIGlmICghbGluZVZpZXcubm9kZSB8fCBsaW5lVmlldy5ub2RlLnBhcmVudE5vZGUgIT0gY29udGFpbmVyKSB7IC8vIE5vdCBkcmF3biB5ZXRcbiAgICAgICAgdmFyIG5vZGUgPSBidWlsZExpbmVFbGVtZW50KGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpO1xuICAgICAgICBjb250YWluZXIuaW5zZXJ0QmVmb3JlKG5vZGUsIGN1cik7XG4gICAgICB9IGVsc2UgeyAvLyBBbHJlYWR5IGRyYXduXG4gICAgICAgIHdoaWxlIChjdXIgIT0gbGluZVZpZXcubm9kZSkgY3VyID0gcm0oY3VyKTtcbiAgICAgICAgdmFyIHVwZGF0ZU51bWJlciA9IGxpbmVOdW1iZXJzICYmIHVwZGF0ZU51bWJlcnNGcm9tICE9IG51bGwgJiZcbiAgICAgICAgICB1cGRhdGVOdW1iZXJzRnJvbSA8PSBsaW5lTiAmJiBsaW5lVmlldy5saW5lTnVtYmVyO1xuICAgICAgICBpZiAobGluZVZpZXcuY2hhbmdlcykge1xuICAgICAgICAgIGlmIChpbmRleE9mKGxpbmVWaWV3LmNoYW5nZXMsIFwiZ3V0dGVyXCIpID4gLTEpIHVwZGF0ZU51bWJlciA9IGZhbHNlO1xuICAgICAgICAgIHVwZGF0ZUxpbmVGb3JDaGFuZ2VzKGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1cGRhdGVOdW1iZXIpIHtcbiAgICAgICAgICByZW1vdmVDaGlsZHJlbihsaW5lVmlldy5saW5lTnVtYmVyKTtcbiAgICAgICAgICBsaW5lVmlldy5saW5lTnVtYmVyLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGxpbmVOdW1iZXJGb3IoY20ub3B0aW9ucywgbGluZU4pKSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VyID0gbGluZVZpZXcubm9kZS5uZXh0U2libGluZztcbiAgICAgIH1cbiAgICAgIGxpbmVOICs9IGxpbmVWaWV3LnNpemU7XG4gICAgfVxuICAgIHdoaWxlIChjdXIpIGN1ciA9IHJtKGN1cik7XG4gIH1cblxuICAvLyBXaGVuIGFuIGFzcGVjdCBvZiBhIGxpbmUgY2hhbmdlcywgYSBzdHJpbmcgaXMgYWRkZWQgdG9cbiAgLy8gbGluZVZpZXcuY2hhbmdlcy4gVGhpcyB1cGRhdGVzIHRoZSByZWxldmFudCBwYXJ0IG9mIHRoZSBsaW5lJ3NcbiAgLy8gRE9NIHN0cnVjdHVyZS5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZUZvckNoYW5nZXMoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcykge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbGluZVZpZXcuY2hhbmdlcy5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIHR5cGUgPSBsaW5lVmlldy5jaGFuZ2VzW2pdO1xuICAgICAgaWYgKHR5cGUgPT0gXCJ0ZXh0XCIpIHVwZGF0ZUxpbmVUZXh0KGNtLCBsaW5lVmlldyk7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwiZ3V0dGVyXCIpIHVwZGF0ZUxpbmVHdXR0ZXIoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcyk7XG4gICAgICBlbHNlIGlmICh0eXBlID09IFwiY2xhc3NcIikgdXBkYXRlTGluZUNsYXNzZXMobGluZVZpZXcpO1xuICAgICAgZWxzZSBpZiAodHlwZSA9PSBcIndpZGdldFwiKSB1cGRhdGVMaW5lV2lkZ2V0cyhjbSwgbGluZVZpZXcsIGRpbXMpO1xuICAgIH1cbiAgICBsaW5lVmlldy5jaGFuZ2VzID0gbnVsbDtcbiAgfVxuXG4gIC8vIExpbmVzIHdpdGggZ3V0dGVyIGVsZW1lbnRzLCB3aWRnZXRzIG9yIGEgYmFja2dyb3VuZCBjbGFzcyBuZWVkIHRvXG4gIC8vIGJlIHdyYXBwZWQsIGFuZCBoYXZlIHRoZSBleHRyYSBlbGVtZW50cyBhZGRlZCB0byB0aGUgd3JhcHBlciBkaXZcbiAgZnVuY3Rpb24gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpIHtcbiAgICBpZiAobGluZVZpZXcubm9kZSA9PSBsaW5lVmlldy50ZXh0KSB7XG4gICAgICBsaW5lVmlldy5ub2RlID0gZWx0KFwiZGl2XCIsIG51bGwsIG51bGwsIFwicG9zaXRpb246IHJlbGF0aXZlXCIpO1xuICAgICAgaWYgKGxpbmVWaWV3LnRleHQucGFyZW50Tm9kZSlcbiAgICAgICAgbGluZVZpZXcudGV4dC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChsaW5lVmlldy5ub2RlLCBsaW5lVmlldy50ZXh0KTtcbiAgICAgIGxpbmVWaWV3Lm5vZGUuYXBwZW5kQ2hpbGQobGluZVZpZXcudGV4dCk7XG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDgpIGxpbmVWaWV3Lm5vZGUuc3R5bGUuekluZGV4ID0gMjtcbiAgICB9XG4gICAgcmV0dXJuIGxpbmVWaWV3Lm5vZGU7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVMaW5lQmFja2dyb3VuZChsaW5lVmlldykge1xuICAgIHZhciBjbHMgPSBsaW5lVmlldy5iZ0NsYXNzID8gbGluZVZpZXcuYmdDbGFzcyArIFwiIFwiICsgKGxpbmVWaWV3LmxpbmUuYmdDbGFzcyB8fCBcIlwiKSA6IGxpbmVWaWV3LmxpbmUuYmdDbGFzcztcbiAgICBpZiAoY2xzKSBjbHMgKz0gXCIgQ29kZU1pcnJvci1saW5lYmFja2dyb3VuZFwiO1xuICAgIGlmIChsaW5lVmlldy5iYWNrZ3JvdW5kKSB7XG4gICAgICBpZiAoY2xzKSBsaW5lVmlldy5iYWNrZ3JvdW5kLmNsYXNzTmFtZSA9IGNscztcbiAgICAgIGVsc2UgeyBsaW5lVmlldy5iYWNrZ3JvdW5kLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobGluZVZpZXcuYmFja2dyb3VuZCk7IGxpbmVWaWV3LmJhY2tncm91bmQgPSBudWxsOyB9XG4gICAgfSBlbHNlIGlmIChjbHMpIHtcbiAgICAgIHZhciB3cmFwID0gZW5zdXJlTGluZVdyYXBwZWQobGluZVZpZXcpO1xuICAgICAgbGluZVZpZXcuYmFja2dyb3VuZCA9IHdyYXAuaW5zZXJ0QmVmb3JlKGVsdChcImRpdlwiLCBudWxsLCBjbHMpLCB3cmFwLmZpcnN0Q2hpbGQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFdyYXBwZXIgYXJvdW5kIGJ1aWxkTGluZUNvbnRlbnQgd2hpY2ggd2lsbCByZXVzZSB0aGUgc3RydWN0dXJlXG4gIC8vIGluIGRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZCB3aGVuIHBvc3NpYmxlLlxuICBmdW5jdGlvbiBnZXRMaW5lQ29udGVudChjbSwgbGluZVZpZXcpIHtcbiAgICB2YXIgZXh0ID0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQgJiYgZXh0LmxpbmUgPT0gbGluZVZpZXcubGluZSkge1xuICAgICAgY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkID0gbnVsbDtcbiAgICAgIGxpbmVWaWV3Lm1lYXN1cmUgPSBleHQubWVhc3VyZTtcbiAgICAgIHJldHVybiBleHQuYnVpbHQ7XG4gICAgfVxuICAgIHJldHVybiBidWlsZExpbmVDb250ZW50KGNtLCBsaW5lVmlldyk7XG4gIH1cblxuICAvLyBSZWRyYXcgdGhlIGxpbmUncyB0ZXh0LiBJbnRlcmFjdHMgd2l0aCB0aGUgYmFja2dyb3VuZCBhbmQgdGV4dFxuICAvLyBjbGFzc2VzIGJlY2F1c2UgdGhlIG1vZGUgbWF5IG91dHB1dCB0b2tlbnMgdGhhdCBpbmZsdWVuY2UgdGhlc2VcbiAgLy8gY2xhc3Nlcy5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZVRleHQoY20sIGxpbmVWaWV3KSB7XG4gICAgdmFyIGNscyA9IGxpbmVWaWV3LnRleHQuY2xhc3NOYW1lO1xuICAgIHZhciBidWlsdCA9IGdldExpbmVDb250ZW50KGNtLCBsaW5lVmlldyk7XG4gICAgaWYgKGxpbmVWaWV3LnRleHQgPT0gbGluZVZpZXcubm9kZSkgbGluZVZpZXcubm9kZSA9IGJ1aWx0LnByZTtcbiAgICBsaW5lVmlldy50ZXh0LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGJ1aWx0LnByZSwgbGluZVZpZXcudGV4dCk7XG4gICAgbGluZVZpZXcudGV4dCA9IGJ1aWx0LnByZTtcbiAgICBpZiAoYnVpbHQuYmdDbGFzcyAhPSBsaW5lVmlldy5iZ0NsYXNzIHx8IGJ1aWx0LnRleHRDbGFzcyAhPSBsaW5lVmlldy50ZXh0Q2xhc3MpIHtcbiAgICAgIGxpbmVWaWV3LmJnQ2xhc3MgPSBidWlsdC5iZ0NsYXNzO1xuICAgICAgbGluZVZpZXcudGV4dENsYXNzID0gYnVpbHQudGV4dENsYXNzO1xuICAgICAgdXBkYXRlTGluZUNsYXNzZXMobGluZVZpZXcpO1xuICAgIH0gZWxzZSBpZiAoY2xzKSB7XG4gICAgICBsaW5lVmlldy50ZXh0LmNsYXNzTmFtZSA9IGNscztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVMaW5lQ2xhc3NlcyhsaW5lVmlldykge1xuICAgIHVwZGF0ZUxpbmVCYWNrZ3JvdW5kKGxpbmVWaWV3KTtcbiAgICBpZiAobGluZVZpZXcubGluZS53cmFwQ2xhc3MpXG4gICAgICBlbnN1cmVMaW5lV3JhcHBlZChsaW5lVmlldykuY2xhc3NOYW1lID0gbGluZVZpZXcubGluZS53cmFwQ2xhc3M7XG4gICAgZWxzZSBpZiAobGluZVZpZXcubm9kZSAhPSBsaW5lVmlldy50ZXh0KVxuICAgICAgbGluZVZpZXcubm9kZS5jbGFzc05hbWUgPSBcIlwiO1xuICAgIHZhciB0ZXh0Q2xhc3MgPSBsaW5lVmlldy50ZXh0Q2xhc3MgPyBsaW5lVmlldy50ZXh0Q2xhc3MgKyBcIiBcIiArIChsaW5lVmlldy5saW5lLnRleHRDbGFzcyB8fCBcIlwiKSA6IGxpbmVWaWV3LmxpbmUudGV4dENsYXNzO1xuICAgIGxpbmVWaWV3LnRleHQuY2xhc3NOYW1lID0gdGV4dENsYXNzIHx8IFwiXCI7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVMaW5lR3V0dGVyKGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpIHtcbiAgICBpZiAobGluZVZpZXcuZ3V0dGVyKSB7XG4gICAgICBsaW5lVmlldy5ub2RlLnJlbW92ZUNoaWxkKGxpbmVWaWV3Lmd1dHRlcik7XG4gICAgICBsaW5lVmlldy5ndXR0ZXIgPSBudWxsO1xuICAgIH1cbiAgICBpZiAobGluZVZpZXcuZ3V0dGVyQmFja2dyb3VuZCkge1xuICAgICAgbGluZVZpZXcubm9kZS5yZW1vdmVDaGlsZChsaW5lVmlldy5ndXR0ZXJCYWNrZ3JvdW5kKTtcbiAgICAgIGxpbmVWaWV3Lmd1dHRlckJhY2tncm91bmQgPSBudWxsO1xuICAgIH1cbiAgICBpZiAobGluZVZpZXcubGluZS5ndXR0ZXJDbGFzcykge1xuICAgICAgdmFyIHdyYXAgPSBlbnN1cmVMaW5lV3JhcHBlZChsaW5lVmlldyk7XG4gICAgICBsaW5lVmlldy5ndXR0ZXJCYWNrZ3JvdW5kID0gZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1ndXR0ZXItYmFja2dyb3VuZCBcIiArIGxpbmVWaWV3LmxpbmUuZ3V0dGVyQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibGVmdDogXCIgKyAoY20ub3B0aW9ucy5maXhlZEd1dHRlciA/IGRpbXMuZml4ZWRQb3MgOiAtZGltcy5ndXR0ZXJUb3RhbFdpZHRoKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicHg7IHdpZHRoOiBcIiArIGRpbXMuZ3V0dGVyVG90YWxXaWR0aCArIFwicHhcIik7XG4gICAgICB3cmFwLmluc2VydEJlZm9yZShsaW5lVmlldy5ndXR0ZXJCYWNrZ3JvdW5kLCBsaW5lVmlldy50ZXh0KTtcbiAgICB9XG4gICAgdmFyIG1hcmtlcnMgPSBsaW5lVmlldy5saW5lLmd1dHRlck1hcmtlcnM7XG4gICAgaWYgKGNtLm9wdGlvbnMubGluZU51bWJlcnMgfHwgbWFya2Vycykge1xuICAgICAgdmFyIHdyYXAgPSBlbnN1cmVMaW5lV3JhcHBlZChsaW5lVmlldyk7XG4gICAgICB2YXIgZ3V0dGVyV3JhcCA9IGxpbmVWaWV3Lmd1dHRlciA9IGVsdChcImRpdlwiLCBudWxsLCBcIkNvZGVNaXJyb3ItZ3V0dGVyLXdyYXBwZXJcIiwgXCJsZWZ0OiBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY20ub3B0aW9ucy5maXhlZEd1dHRlciA/IGRpbXMuZml4ZWRQb3MgOiAtZGltcy5ndXR0ZXJUb3RhbFdpZHRoKSArIFwicHhcIik7XG4gICAgICBjbS5kaXNwbGF5LmlucHV0LnNldFVuZWRpdGFibGUoZ3V0dGVyV3JhcCk7XG4gICAgICB3cmFwLmluc2VydEJlZm9yZShndXR0ZXJXcmFwLCBsaW5lVmlldy50ZXh0KTtcbiAgICAgIGlmIChsaW5lVmlldy5saW5lLmd1dHRlckNsYXNzKVxuICAgICAgICBndXR0ZXJXcmFwLmNsYXNzTmFtZSArPSBcIiBcIiArIGxpbmVWaWV3LmxpbmUuZ3V0dGVyQ2xhc3M7XG4gICAgICBpZiAoY20ub3B0aW9ucy5saW5lTnVtYmVycyAmJiAoIW1hcmtlcnMgfHwgIW1hcmtlcnNbXCJDb2RlTWlycm9yLWxpbmVudW1iZXJzXCJdKSlcbiAgICAgICAgbGluZVZpZXcubGluZU51bWJlciA9IGd1dHRlcldyYXAuYXBwZW5kQ2hpbGQoXG4gICAgICAgICAgZWx0KFwiZGl2XCIsIGxpbmVOdW1iZXJGb3IoY20ub3B0aW9ucywgbGluZU4pLFxuICAgICAgICAgICAgICBcIkNvZGVNaXJyb3ItbGluZW51bWJlciBDb2RlTWlycm9yLWd1dHRlci1lbHRcIixcbiAgICAgICAgICAgICAgXCJsZWZ0OiBcIiArIGRpbXMuZ3V0dGVyTGVmdFtcIkNvZGVNaXJyb3ItbGluZW51bWJlcnNcIl0gKyBcInB4OyB3aWR0aDogXCJcbiAgICAgICAgICAgICAgKyBjbS5kaXNwbGF5LmxpbmVOdW1Jbm5lcldpZHRoICsgXCJweFwiKSk7XG4gICAgICBpZiAobWFya2VycykgZm9yICh2YXIgayA9IDA7IGsgPCBjbS5vcHRpb25zLmd1dHRlcnMubGVuZ3RoOyArK2spIHtcbiAgICAgICAgdmFyIGlkID0gY20ub3B0aW9ucy5ndXR0ZXJzW2tdLCBmb3VuZCA9IG1hcmtlcnMuaGFzT3duUHJvcGVydHkoaWQpICYmIG1hcmtlcnNbaWRdO1xuICAgICAgICBpZiAoZm91bmQpXG4gICAgICAgICAgZ3V0dGVyV3JhcC5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgW2ZvdW5kXSwgXCJDb2RlTWlycm9yLWd1dHRlci1lbHRcIiwgXCJsZWZ0OiBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcy5ndXR0ZXJMZWZ0W2lkXSArIFwicHg7IHdpZHRoOiBcIiArIGRpbXMuZ3V0dGVyV2lkdGhbaWRdICsgXCJweFwiKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZVdpZGdldHMoY20sIGxpbmVWaWV3LCBkaW1zKSB7XG4gICAgaWYgKGxpbmVWaWV3LmFsaWduYWJsZSkgbGluZVZpZXcuYWxpZ25hYmxlID0gbnVsbDtcbiAgICBmb3IgKHZhciBub2RlID0gbGluZVZpZXcubm9kZS5maXJzdENoaWxkLCBuZXh0OyBub2RlOyBub2RlID0gbmV4dCkge1xuICAgICAgdmFyIG5leHQgPSBub2RlLm5leHRTaWJsaW5nO1xuICAgICAgaWYgKG5vZGUuY2xhc3NOYW1lID09IFwiQ29kZU1pcnJvci1saW5ld2lkZ2V0XCIpXG4gICAgICAgIGxpbmVWaWV3Lm5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgfVxuICAgIGluc2VydExpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcyk7XG4gIH1cblxuICAvLyBCdWlsZCBhIGxpbmUncyBET00gcmVwcmVzZW50YXRpb24gZnJvbSBzY3JhdGNoXG4gIGZ1bmN0aW9uIGJ1aWxkTGluZUVsZW1lbnQoY20sIGxpbmVWaWV3LCBsaW5lTiwgZGltcykge1xuICAgIHZhciBidWlsdCA9IGdldExpbmVDb250ZW50KGNtLCBsaW5lVmlldyk7XG4gICAgbGluZVZpZXcudGV4dCA9IGxpbmVWaWV3Lm5vZGUgPSBidWlsdC5wcmU7XG4gICAgaWYgKGJ1aWx0LmJnQ2xhc3MpIGxpbmVWaWV3LmJnQ2xhc3MgPSBidWlsdC5iZ0NsYXNzO1xuICAgIGlmIChidWlsdC50ZXh0Q2xhc3MpIGxpbmVWaWV3LnRleHRDbGFzcyA9IGJ1aWx0LnRleHRDbGFzcztcblxuICAgIHVwZGF0ZUxpbmVDbGFzc2VzKGxpbmVWaWV3KTtcbiAgICB1cGRhdGVMaW5lR3V0dGVyKGNtLCBsaW5lVmlldywgbGluZU4sIGRpbXMpO1xuICAgIGluc2VydExpbmVXaWRnZXRzKGNtLCBsaW5lVmlldywgZGltcyk7XG4gICAgcmV0dXJuIGxpbmVWaWV3Lm5vZGU7XG4gIH1cblxuICAvLyBBIGxpbmVWaWV3IG1heSBjb250YWluIG11bHRpcGxlIGxvZ2ljYWwgbGluZXMgKHdoZW4gbWVyZ2VkIGJ5XG4gIC8vIGNvbGxhcHNlZCBzcGFucykuIFRoZSB3aWRnZXRzIGZvciBhbGwgb2YgdGhlbSBuZWVkIHRvIGJlIGRyYXduLlxuICBmdW5jdGlvbiBpbnNlcnRMaW5lV2lkZ2V0cyhjbSwgbGluZVZpZXcsIGRpbXMpIHtcbiAgICBpbnNlcnRMaW5lV2lkZ2V0c0ZvcihjbSwgbGluZVZpZXcubGluZSwgbGluZVZpZXcsIGRpbXMsIHRydWUpO1xuICAgIGlmIChsaW5lVmlldy5yZXN0KSBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVWaWV3LnJlc3QubGVuZ3RoOyBpKyspXG4gICAgICBpbnNlcnRMaW5lV2lkZ2V0c0ZvcihjbSwgbGluZVZpZXcucmVzdFtpXSwgbGluZVZpZXcsIGRpbXMsIGZhbHNlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluc2VydExpbmVXaWRnZXRzRm9yKGNtLCBsaW5lLCBsaW5lVmlldywgZGltcywgYWxsb3dBYm92ZSkge1xuICAgIGlmICghbGluZS53aWRnZXRzKSByZXR1cm47XG4gICAgdmFyIHdyYXAgPSBlbnN1cmVMaW5lV3JhcHBlZChsaW5lVmlldyk7XG4gICAgZm9yICh2YXIgaSA9IDAsIHdzID0gbGluZS53aWRnZXRzOyBpIDwgd3MubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciB3aWRnZXQgPSB3c1tpXSwgbm9kZSA9IGVsdChcImRpdlwiLCBbd2lkZ2V0Lm5vZGVdLCBcIkNvZGVNaXJyb3ItbGluZXdpZGdldFwiKTtcbiAgICAgIGlmICghd2lkZ2V0LmhhbmRsZU1vdXNlRXZlbnRzKSBub2RlLnNldEF0dHJpYnV0ZShcImNtLWlnbm9yZS1ldmVudHNcIiwgXCJ0cnVlXCIpO1xuICAgICAgcG9zaXRpb25MaW5lV2lkZ2V0KHdpZGdldCwgbm9kZSwgbGluZVZpZXcsIGRpbXMpO1xuICAgICAgY20uZGlzcGxheS5pbnB1dC5zZXRVbmVkaXRhYmxlKG5vZGUpO1xuICAgICAgaWYgKGFsbG93QWJvdmUgJiYgd2lkZ2V0LmFib3ZlKVxuICAgICAgICB3cmFwLmluc2VydEJlZm9yZShub2RlLCBsaW5lVmlldy5ndXR0ZXIgfHwgbGluZVZpZXcudGV4dCk7XG4gICAgICBlbHNlXG4gICAgICAgIHdyYXAuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICBzaWduYWxMYXRlcih3aWRnZXQsIFwicmVkcmF3XCIpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBvc2l0aW9uTGluZVdpZGdldCh3aWRnZXQsIG5vZGUsIGxpbmVWaWV3LCBkaW1zKSB7XG4gICAgaWYgKHdpZGdldC5ub0hTY3JvbGwpIHtcbiAgICAgIChsaW5lVmlldy5hbGlnbmFibGUgfHwgKGxpbmVWaWV3LmFsaWduYWJsZSA9IFtdKSkucHVzaChub2RlKTtcbiAgICAgIHZhciB3aWR0aCA9IGRpbXMud3JhcHBlcldpZHRoO1xuICAgICAgbm9kZS5zdHlsZS5sZWZ0ID0gZGltcy5maXhlZFBvcyArIFwicHhcIjtcbiAgICAgIGlmICghd2lkZ2V0LmNvdmVyR3V0dGVyKSB7XG4gICAgICAgIHdpZHRoIC09IGRpbXMuZ3V0dGVyVG90YWxXaWR0aDtcbiAgICAgICAgbm9kZS5zdHlsZS5wYWRkaW5nTGVmdCA9IGRpbXMuZ3V0dGVyVG90YWxXaWR0aCArIFwicHhcIjtcbiAgICAgIH1cbiAgICAgIG5vZGUuc3R5bGUud2lkdGggPSB3aWR0aCArIFwicHhcIjtcbiAgICB9XG4gICAgaWYgKHdpZGdldC5jb3Zlckd1dHRlcikge1xuICAgICAgbm9kZS5zdHlsZS56SW5kZXggPSA1O1xuICAgICAgbm9kZS5zdHlsZS5wb3NpdGlvbiA9IFwicmVsYXRpdmVcIjtcbiAgICAgIGlmICghd2lkZ2V0Lm5vSFNjcm9sbCkgbm9kZS5zdHlsZS5tYXJnaW5MZWZ0ID0gLWRpbXMuZ3V0dGVyVG90YWxXaWR0aCArIFwicHhcIjtcbiAgICB9XG4gIH1cblxuICAvLyBQT1NJVElPTiBPQkpFQ1RcblxuICAvLyBBIFBvcyBpbnN0YW5jZSByZXByZXNlbnRzIGEgcG9zaXRpb24gd2l0aGluIHRoZSB0ZXh0LlxuICB2YXIgUG9zID0gQ29kZU1pcnJvci5Qb3MgPSBmdW5jdGlvbihsaW5lLCBjaCkge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBQb3MpKSByZXR1cm4gbmV3IFBvcyhsaW5lLCBjaCk7XG4gICAgdGhpcy5saW5lID0gbGluZTsgdGhpcy5jaCA9IGNoO1xuICB9O1xuXG4gIC8vIENvbXBhcmUgdHdvIHBvc2l0aW9ucywgcmV0dXJuIDAgaWYgdGhleSBhcmUgdGhlIHNhbWUsIGEgbmVnYXRpdmVcbiAgLy8gbnVtYmVyIHdoZW4gYSBpcyBsZXNzLCBhbmQgYSBwb3NpdGl2ZSBudW1iZXIgb3RoZXJ3aXNlLlxuICB2YXIgY21wID0gQ29kZU1pcnJvci5jbXBQb3MgPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhLmxpbmUgLSBiLmxpbmUgfHwgYS5jaCAtIGIuY2g7IH07XG5cbiAgZnVuY3Rpb24gY29weVBvcyh4KSB7cmV0dXJuIFBvcyh4LmxpbmUsIHguY2gpO31cbiAgZnVuY3Rpb24gbWF4UG9zKGEsIGIpIHsgcmV0dXJuIGNtcChhLCBiKSA8IDAgPyBiIDogYTsgfVxuICBmdW5jdGlvbiBtaW5Qb3MoYSwgYikgeyByZXR1cm4gY21wKGEsIGIpIDwgMCA/IGEgOiBiOyB9XG5cbiAgLy8gSU5QVVQgSEFORExJTkdcblxuICBmdW5jdGlvbiBlbnN1cmVGb2N1cyhjbSkge1xuICAgIGlmICghY20uc3RhdGUuZm9jdXNlZCkgeyBjbS5kaXNwbGF5LmlucHV0LmZvY3VzKCk7IG9uRm9jdXMoY20pOyB9XG4gIH1cblxuIC
23459BmdW5jdGlvbiBpc1JlYWRPbmx5KGNtKSB7XG4gICAgcmV0dXJuIGNtLm9wdGlvbnMucmVhZE9ubHkgfHwgY20uZG9jLmNhbnRFZGl0O1xuICB9XG5cbiAgLy8gVGhpcyB3aWxsIGJlIHNldCB0byBhbiBhcnJheSBvZiBzdHJpbmdzIHdoZW4gY29weWluZywgc28gdGhhdCxcbiAgLy8gd2hlbiBwYXN0aW5nLCB3ZSBrbm93IHdoYXQga2luZCBvZiBzZWxlY3Rpb25zIHRoZSBjb3BpZWQgdGV4dFxuICAvLyB3YXMgbWFkZSBvdXQgb2YuXG4gIHZhciBsYXN0Q29waWVkID0gbnVsbDtcblxuICBmdW5jdGlvbiBhcHBseVRleHRJbnB1dChjbSwgaW5zZXJ0ZWQsIGRlbGV0ZWQsIHNlbCwgb3JpZ2luKSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYztcbiAgICBjbS5kaXNwbGF5LnNoaWZ0ID0gZmFsc2U7XG4gICAgaWYgKCFzZWwpIHNlbCA9IGRvYy5zZWw7XG5cbiAgICB2YXIgcGFzdGUgPSBjbS5zdGF0ZS5wYXN0ZUluY29taW5nIHx8IG9yaWdpbiA9PSBcInBhc3RlXCI7XG4gICAgdmFyIHRleHRMaW5lcyA9IGRvYy5zcGxpdExpbmVzKGluc2VydGVkKSwgbXVsdGlQYXN0ZSA9IG51bGw7XG4gICAgLy8gV2hlbiBwYXNpbmcgTiBsaW5lcyBpbnRvIE4gc2VsZWN0aW9ucywgaW5zZXJ0IG9uZSBsaW5lIHBlciBzZWxlY3Rpb25cbiAgICBpZiAocGFzdGUgJiYgc2VsLnJhbmdlcy5sZW5ndGggPiAxKSB7XG4gICAgICBpZiAobGFzdENvcGllZCAmJiBsYXN0Q29waWVkLmpvaW4oXCJcXG5cIikgPT0gaW5zZXJ0ZWQpIHtcbiAgICAgICAgaWYgKHNlbC5yYW5nZXMubGVuZ3RoICUgbGFzdENvcGllZC5sZW5ndGggPT0gMCkge1xuICAgICAgICAgIG11bHRpUGFzdGUgPSBbXTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxhc3RDb3BpZWQubGVuZ3RoOyBpKyspXG4gICAgICAgICAgICBtdWx0aVBhc3RlLnB1c2goZG9jLnNwbGl0TGluZXMobGFzdENvcGllZFtpXSkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRleHRMaW5lcy5sZW5ndGggPT0gc2VsLnJhbmdlcy5sZW5ndGgpIHtcbiAgICAgICAgbXVsdGlQYXN0ZSA9IG1hcCh0ZXh0TGluZXMsIGZ1bmN0aW9uKGwpIHsgcmV0dXJuIFtsXTsgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTm9ybWFsIGJlaGF2aW9yIGlzIHRvIGluc2VydCB0aGUgbmV3IHRleHQgaW50byBldmVyeSBzZWxlY3Rpb25cbiAgICBmb3IgKHZhciBpID0gc2VsLnJhbmdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIHJhbmdlID0gc2VsLnJhbmdlc1tpXTtcbiAgICAgIHZhciBmcm9tID0gcmFuZ2UuZnJvbSgpLCB0byA9IHJhbmdlLnRvKCk7XG4gICAgICBpZiAocmFuZ2UuZW1wdHkoKSkge1xuICAgICAgICBpZiAoZGVsZXRlZCAmJiBkZWxldGVkID4gMCkgLy8gSGFuZGxlIGRlbGV0aW9uXG4gICAgICAgICAgZnJvbSA9IFBvcyhmcm9tLmxpbmUsIGZyb20uY2ggLSBkZWxldGVkKTtcbiAgICAgICAgZWxzZSBpZiAoY20uc3RhdGUub3ZlcndyaXRlICYmICFwYXN0ZSkgLy8gSGFuZGxlIG92ZXJ3cml0ZVxuICAgICAgICAgIHRvID0gUG9zKHRvLmxpbmUsIE1hdGgubWluKGdldExpbmUoZG9jLCB0by5saW5lKS50ZXh0Lmxlbmd0aCwgdG8uY2ggKyBsc3QodGV4dExpbmVzKS5sZW5ndGgpKTtcbiAgICAgIH1cbiAgICAgIHZhciB1cGRhdGVJbnB1dCA9IGNtLmN1ck9wLnVwZGF0ZUlucHV0O1xuICAgICAgdmFyIGNoYW5nZUV2ZW50ID0ge2Zyb206IGZyb20sIHRvOiB0bywgdGV4dDogbXVsdGlQYXN0ZSA/IG11bHRpUGFzdGVbaSAlIG11bHRpUGFzdGUubGVuZ3RoXSA6IHRleHRMaW5lcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW46IG9yaWdpbiB8fCAocGFzdGUgPyBcInBhc3RlXCIgOiBjbS5zdGF0ZS5jdXRJbmNvbWluZyA/IFwiY3V0XCIgOiBcIitpbnB1dFwiKX07XG4gICAgICBtYWtlQ2hhbmdlKGNtLmRvYywgY2hhbmdlRXZlbnQpO1xuICAgICAgc2lnbmFsTGF0ZXIoY20sIFwiaW5wdXRSZWFkXCIsIGNtLCBjaGFuZ2VFdmVudCk7XG4gICAgfVxuICAgIGlmIChpbnNlcnRlZCAmJiAhcGFzdGUpXG4gICAgICB0cmlnZ2VyRWxlY3RyaWMoY20sIGluc2VydGVkKTtcblxuICAgIGVuc3VyZUN1cnNvclZpc2libGUoY20pO1xuICAgIGNtLmN1ck9wLnVwZGF0ZUlucHV0ID0gdXBkYXRlSW5wdXQ7XG4gICAgY20uY3VyT3AudHlwaW5nID0gdHJ1ZTtcbiAgICBjbS5zdGF0ZS5wYXN0ZUluY29taW5nID0gY20uc3RhdGUuY3V0SW5jb21pbmcgPSBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZVBhc3RlKGUsIGNtKSB7XG4gICAgdmFyIHBhc3RlZCA9IGUuY2xpcGJvYXJkRGF0YSAmJiBlLmNsaXBib2FyZERhdGEuZ2V0RGF0YShcInRleHQvcGxhaW5cIik7XG4gICAgaWYgKHBhc3RlZCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKCFpc1JlYWRPbmx5KGNtKSAmJiAhY20ub3B0aW9ucy5kaXNhYmxlSW5wdXQpXG4gICAgICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkgeyBhcHBseVRleHRJbnB1dChjbSwgcGFzdGVkLCAwLCBudWxsLCBcInBhc3RlXCIpOyB9KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRyaWdnZXJFbGVjdHJpYyhjbSwgaW5zZXJ0ZWQpIHtcbiAgICAvLyBXaGVuIGFuICdlbGVjdHJpYycgY2hhcmFjdGVyIGlzIGluc2VydGVkLCBpbW1lZGlhdGVseSB0cmlnZ2VyIGEgcmVpbmRlbnRcbiAgICBpZiAoIWNtLm9wdGlvbnMuZWxlY3RyaWNDaGFycyB8fCAhY20ub3B0aW9ucy5zbWFydEluZGVudCkgcmV0dXJuO1xuICAgIHZhciBzZWwgPSBjbS5kb2Muc2VsO1xuXG4gICAgZm9yICh2YXIgaSA9IHNlbC5yYW5nZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciByYW5nZSA9IHNlbC5yYW5nZXNbaV07XG4gICAgICBpZiAocmFuZ2UuaGVhZC5jaCA+IDEwMCB8fCAoaSAmJiBzZWwucmFuZ2VzW2kgLSAxXS5oZWFkLmxpbmUgPT0gcmFuZ2UuaGVhZC5saW5lKSkgY29udGludWU7XG4gICAgICB2Y
23459XIgbW9kZSA9IGNtLmdldE1vZGVBdChyYW5nZS5oZWFkKTtcbiAgICAgIHZhciBpbmRlbnRlZCA9IGZhbHNlO1xuICAgICAgaWYgKG1vZGUuZWxlY3RyaWNDaGFycykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vZGUuZWxlY3RyaWNDaGFycy5sZW5ndGg7IGorKylcbiAgICAgICAgICBpZiAoaW5zZXJ0ZWQuaW5kZXhPZihtb2RlLmVsZWN0cmljQ2hhcnMuY2hhckF0KGopKSA+IC0xKSB7XG4gICAgICAgICAgICBpbmRlbnRlZCA9IGluZGVudExpbmUoY20sIHJhbmdlLmhlYWQubGluZSwgXCJzbWFydFwiKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAobW9kZS5lbGVjdHJpY0lucHV0KSB7XG4gICAgICAgIGlmIChtb2RlLmVsZWN0cmljSW5wdXQudGVzdChnZXRMaW5lKGNtLmRvYywgcmFuZ2UuaGVhZC5saW5lKS50ZXh0LnNsaWNlKDAsIHJhbmdlLmhlYWQuY2gpKSlcbiAgICAgICAgICBpbmRlbnRlZCA9IGluZGVudExpbmUoY20sIHJhbmdlLmhlYWQubGluZSwgXCJzbWFydFwiKTtcbiAgICAgIH1cbiAgICAgIGlmIChpbmRlbnRlZCkgc2lnbmFsTGF0ZXIoY20sIFwiZWxlY3RyaWNJbnB1dFwiLCBjbSwgcmFuZ2UuaGVhZC5saW5lKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjb3B5YWJsZVJhbmdlcyhjbSkge1xuICAgIHZhciB0ZXh0ID0gW10sIHJhbmdlcyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY20uZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBsaW5lID0gY20uZG9jLnNlbC5yYW5nZXNbaV0uaGVhZC5saW5lO1xuICAgICAgdmFyIGxpbmVSYW5nZSA9IHthbmNob3I6IFBvcyhsaW5lLCAwKSwgaGVhZDogUG9zKGxpbmUgKyAxLCAwKX07XG4gICAgICByYW5nZXMucHVzaChsaW5lUmFuZ2UpO1xuICAgICAgdGV4dC5wdXNoKGNtLmdldFJhbmdlKGxpbmVSYW5nZS5hbmNob3IsIGxpbmVSYW5nZS5oZWFkKSk7XG4gICAgfVxuICAgIHJldHVybiB7dGV4dDogdGV4dCwgcmFuZ2VzOiByYW5nZXN9O1xuICB9XG5cbiAgZnVuY3Rpb24gZGlzYWJsZUJyb3dzZXJNYWdpYyhmaWVsZCkge1xuICAgIGZpZWxkLnNldEF0dHJpYnV0ZShcImF1dG9jb3JyZWN0XCIsIFwib2ZmXCIpO1xuICAgIGZpZWxkLnNldEF0dHJpYnV0ZShcImF1dG9jYXBpdGFsaXplXCIsIFwib2ZmXCIpO1xuICAgIGZpZWxkLnNldEF0dHJpYnV0ZShcInNwZWxsY2hlY2tcIiwgXCJmYWxzZVwiKTtcbiAgfVxuXG4gIC8vIFRFWFRBUkVBIElOUFVUIFNUWUxFXG5cbiAgZnVuY3Rpb24gVGV4dGFyZWFJbnB1dChjbSkge1xuICAgIHRoaXMuY20gPSBjbTtcbiAgICAvLyBTZWUgaW5wdXQucG9sbCBhbmQgaW5wdXQucmVzZXRcbiAgICB0aGlzLnByZXZJbnB1dCA9IFwiXCI7XG5cbiAgICAvLyBGbGFnIHRoYXQgaW5kaWNhdGVzIHdoZXRoZXIgd2UgZXhwZWN0IGlucHV0IHRvIGFwcGVhciByZWFsIHNvb25cbiAgICAvLyBub3cgKGFmdGVyIHNvbWUgZXZlbnQgbGlrZSAna2V5cHJlc3MnIG9yICdpbnB1dCcpIGFuZCBhcmVcbiAgICAvLyBwb2xsaW5nIGludGVuc2l2ZWx5LlxuICAgIHRoaXMucG9sbGluZ0Zhc3QgPSBmYWxzZTtcbiAgICAvLyBTZWxmLXJlc2V0dGluZyB0aW1lb3V0IGZvciB0aGUgcG9sbGVyXG4gICAgdGhpcy5wb2xsaW5nID0gbmV3IERlbGF5ZWQoKTtcbiAgICAvLyBUcmFja3Mgd2hlbiBpbnB1dC5yZXNldCBoYXMgcHVudGVkIHRvIGp1c3QgcHV0dGluZyBhIHNob3J0XG4gICAgLy8gc3RyaW5nIGludG8gdGhlIHRleHRhcmVhIGluc3RlYWQgb2YgdGhlIGZ1bGwgc2VsZWN0aW9uLlxuICAgIHRoaXMuaW5hY2N1cmF0ZVNlbGVjdGlvbiA9IGZhbHNlO1xuICAgIC8vIFVzZWQgdG8gd29yayBhcm91bmQgSUUgaXNzdWUgd2l0aCBzZWxlY3Rpb24gYmVpbmcgZm9yZ290dGVuIHdoZW4gZm9jdXMgbW92ZXMgYXdheSBmcm9tIHRleHRhcmVhXG4gICAgdGhpcy5oYXNTZWxlY3Rpb24gPSBmYWxzZTtcbiAgICB0aGlzLmNvbXBvc2luZyA9IG51bGw7XG4gIH07XG5cbiAgZnVuY3Rpb24gaGlkZGVuVGV4dGFyZWEoKSB7XG4gICAgdmFyIHRlID0gZWx0KFwidGV4dGFyZWFcIiwgbnVsbCwgbnVsbCwgXCJwb3NpdGlvbjogYWJzb2x1dGU7IHBhZGRpbmc6IDA7IHdpZHRoOiAxcHg7IGhlaWdodDogMWVtOyBvdXRsaW5lOiBub25lXCIpO1xuICAgIHZhciBkaXYgPSBlbHQoXCJkaXZcIiwgW3RlXSwgbnVsbCwgXCJvdmVyZmxvdzogaGlkZGVuOyBwb3NpdGlvbjogcmVsYXRpdmU7IHdpZHRoOiAzcHg7IGhlaWdodDogMHB4O1wiKTtcbiAgICAvLyBUaGUgdGV4dGFyZWEgaXMga2VwdCBwb3NpdGlvbmVkIG5lYXIgdGhlIGN1cnNvciB0byBwcmV2ZW50IHRoZVxuICAgIC8vIGZhY3QgdGhhdCBpdCdsbCBiZSBzY3JvbGxlZCBpbnRvIHZpZXcgb24gaW5wdXQgZnJvbSBzY3JvbGxpbmdcbiAgICAvLyBvdXIgZmFrZSBjdXJzb3Igb3V0IG9mIHZpZXcuIE9uIHdlYmtpdCwgd2hlbiB3cmFwPW9mZiwgcGFzdGUgaXNcbiAgICAvLyB2ZXJ5IHNsb3cuIFNvIG1ha2UgdGhlIGFyZWEgd2lkZSBpbnN0ZWFkLlxuICAgIGlmICh3ZWJraXQpIHRlLnN0eWxlLndpZHRoID0gXCIxMDAwcHhcIjtcbiAgICBlbHNlIHRlLnNldEF0dHJpYnV0ZShcIndyYXBcIiwgXCJvZmZcIik7XG4gICAgLy8gSWYgYm9yZGVyOiAwOyAtLSBpT1MgZmFpbHMgdG8gb3BlbiBrZXlib2FyZCAoaXNzdWUgIzEyODcpXG4gICAgaWYgKGlvcykgdGUuc3R5bGUuYm9yZGVyID0gXCIxcHggc29saWQgYmxhY2tcIjtcbiAgICBkaXNhYmxlQnJvd3Nlck1hZ2ljKHRlKTtcbiAgICByZXR1cm4gZGl2O1xuICB9XG5cbiAgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUgPSBjb3B5T2JqKHtcbiAgICBpbml0OiBmdW5jdGlvbihkaXNwbGF5KSB7XG4gICAgICB2Y
23459XIgaW5wdXQgPSB0aGlzLCBjbSA9IHRoaXMuY207XG5cbiAgICAgIC8vIFdyYXBzIGFuZCBoaWRlcyBpbnB1dCB0ZXh0YXJlYVxuICAgICAgdmFyIGRpdiA9IHRoaXMud3JhcHBlciA9IGhpZGRlblRleHRhcmVhKCk7XG4gICAgICAvLyBUaGUgc2VtaWhpZGRlbiB0ZXh0YXJlYSB0aGF0IGlzIGZvY3VzZWQgd2hlbiB0aGUgZWRpdG9yIGlzXG4gICAgICAvLyBmb2N1c2VkLCBhbmQgcmVjZWl2ZXMgaW5wdXQuXG4gICAgICB2YXIgdGUgPSB0aGlzLnRleHRhcmVhID0gZGl2LmZpcnN0Q2hpbGQ7XG4gICAgICBkaXNwbGF5LndyYXBwZXIuaW5zZXJ0QmVmb3JlKGRpdiwgZGlzcGxheS53cmFwcGVyLmZpcnN0Q2hpbGQpO1xuXG4gICAgICAvLyBOZWVkZWQgdG8gaGlkZSBiaWcgYmx1ZSBibGlua2luZyBjdXJzb3Igb24gTW9iaWxlIFNhZmFyaSAoZG9lc24ndCBzZWVtIHRvIHdvcmsgaW4gaU9TIDggYW55bW9yZSlcbiAgICAgIGlmIChpb3MpIHRlLnN0eWxlLndpZHRoID0gXCIwcHhcIjtcblxuICAgICAgb24odGUsIFwiaW5wdXRcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uID49IDkgJiYgaW5wdXQuaGFzU2VsZWN0aW9uKSBpbnB1dC5oYXNTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICBpbnB1dC5wb2xsKCk7XG4gICAgICB9KTtcblxuICAgICAgb24odGUsIFwicGFzdGVcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICBpZiAoaGFuZGxlUGFzdGUoZSwgY20pKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgICBjbS5zdGF0ZS5wYXN0ZUluY29taW5nID0gdHJ1ZTtcbiAgICAgICAgaW5wdXQuZmFzdFBvbGwoKTtcbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiBwcmVwYXJlQ29weUN1dChlKSB7XG4gICAgICAgIGlmIChjbS5zb21ldGhpbmdTZWxlY3RlZCgpKSB7XG4gICAgICAgICAgbGFzdENvcGllZCA9IGNtLmdldFNlbGVjdGlvbnMoKTtcbiAgICAgICAgICBpZiAoaW5wdXQuaW5hY2N1cmF0ZVNlbGVjdGlvbikge1xuICAgICAgICAgICAgaW5wdXQucHJldklucHV0ID0gXCJcIjtcbiAgICAgICAgICAgIGlucHV0LmluYWNjdXJhdGVTZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRlLnZhbHVlID0gbGFzdENvcGllZC5qb2luKFwiXFxuXCIpO1xuICAgICAgICAgICAgc2VsZWN0SW5wdXQodGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghY20ub3B0aW9ucy5saW5lV2lzZUNvcHlDdXQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHJhbmdlcyA9IGNvcHlhYmxlUmFuZ2VzKGNtKTtcbiAgICAgICAgICBsYXN0Q29waWVkID0gcmFuZ2VzLnRleHQ7XG4gICAgICAgICAgaWYgKGUudHlwZSA9PSBcImN1dFwiKSB7XG4gICAgICAgICAgICBjbS5zZXRTZWxlY3Rpb25zKHJhbmdlcy5yYW5nZXMsIG51bGwsIHNlbF9kb250U2Nyb2xsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5wdXQucHJldklucHV0ID0gXCJcIjtcbiAgICAgICAgICAgIHRlLnZhbHVlID0gcmFuZ2VzLnRleHQuam9pbihcIlxcblwiKTtcbiAgICAgICAgICAgIHNlbGVjdElucHV0KHRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUudHlwZSA9PSBcImN1dFwiKSBjbS5zdGF0ZS5jdXRJbmNvbWluZyA9IHRydWU7XG4gICAgICB9XG4gICAgICBvbih0ZSwgXCJjdXRcIiwgcHJlcGFyZUNvcHlDdXQpO1xuICAgICAgb24odGUsIFwiY29weVwiLCBwcmVwYXJlQ29weUN1dCk7XG5cbiAgICAgIG9uKGRpc3BsYXkuc2Nyb2xsZXIsIFwicGFzdGVcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICBpZiAoZXZlbnRJbldpZGdldChkaXNwbGF5LCBlKSkgcmV0dXJuO1xuICAgICAgICBjbS5zdGF0ZS5wYXN0ZUluY29taW5nID0gdHJ1ZTtcbiAgICAgICAgaW5wdXQuZm9jdXMoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBQcmV2ZW50IG5vcm1hbCBzZWxlY3Rpb24gaW4gdGhlIGVkaXRvciAod2UgaGFuZGxlIG91ciBvd24pXG4gICAgICBvbihkaXNwbGF5LmxpbmVTcGFjZSwgXCJzZWxlY3RzdGFydFwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlmICghZXZlbnRJbldpZGdldChkaXNwbGF5LCBlKSkgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIH0pO1xuXG4gICAgICBvbih0ZSwgXCJjb21wb3NpdGlvbnN0YXJ0XCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2Y
23459XIgc3RhcnQgPSBjbS5nZXRDdXJzb3IoXCJmcm9tXCIpO1xuICAgICAgICBpZiAoaW5wdXQuY29tcG9zaW5nKSBpbnB1dC5jb21wb3NpbmcucmFuZ2UuY2xlYXIoKVxuICAgICAgICBpbnB1dC5jb21wb3NpbmcgPSB7XG4gICAgICAgICAgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICAgIHJhbmdlOiBjbS5tYXJrVGV4dChzdGFydCwgY20uZ2V0Q3Vyc29yKFwidG9cIiksIHtjbGFzc05hbWU6IFwiQ29kZU1pcnJvci1jb21wb3NpbmdcIn0pXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICAgIG9uKHRlLCBcImNvbXBvc2l0aW9uZW5kXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoaW5wdXQuY29tcG9zaW5nKSB7XG4gICAgICAgICAgaW5wdXQucG9sbCgpO1xuICAgICAgICAgIGlucHV0LmNvbXBvc2luZy5yYW5nZS5jbGVhcigpO1xuICAgICAgICAgIGlucHV0LmNvbXBvc2luZyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBwcmVwYXJlU2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIFJlZHJhdyB0aGUgc2VsZWN0aW9uIGFuZC9vciBjdXJzb3JcbiAgICAgIHZhciBjbSA9IHRoaXMuY20sIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBkb2MgPSBjbS5kb2M7XG4gICAgICB2YXIgcmVzdWx0ID0gcHJlcGFyZVNlbGVjdGlvbihjbSk7XG5cbiAgICAgIC8vIE1vdmUgdGhlIGhpZGRlbiB0ZXh0YXJlYSBuZWFyIHRoZSBjdXJzb3IgdG8gcHJldmVudCBzY3JvbGxpbmcgYXJ0aWZhY3RzXG4gICAgICBpZiAoY20ub3B0aW9ucy5tb3ZlSW5wdXRXaXRoQ3Vyc29yKSB7XG4gICAgICAgIHZhciBoZWFkUG9zID0gY3Vyc29yQ29vcmRzKGNtLCBkb2Muc2VsLnByaW1hcnkoKS5oZWFkLCBcImRpdlwiKTtcbiAgICAgICAgdmFyIHdyYXBPZmYgPSBkaXNwbGF5LndyYXBwZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksIGxpbmVPZmYgPSBkaXNwbGF5LmxpbmVEaXYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHJlc3VsdC50ZVRvcCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQgLSAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZFBvcy50b3AgKyBsaW5lT2ZmLnRvcCAtIHdyYXBPZmYudG9wKSk7XG4gICAgICAgIHJlc3VsdC50ZUxlZnQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihkaXNwbGF5LndyYXBwZXIuY2xpZW50V2lkdGggLSAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRQb3MubGVmdCArIGxpbmVPZmYubGVmdCAtIHdyYXBPZmYubGVmdCkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBzaG93U2VsZWN0aW9uOiBmdW5jdGlvbihkcmF3bikge1xuICAgICAgdmFyIGNtID0gdGhpcy5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChkaXNwbGF5LmN1cnNvckRpdiwgZHJhd24uY3Vyc29ycyk7XG4gICAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChkaXNwbGF5LnNlbGVjdGlvbkRpdiwgZHJhd24uc2VsZWN0aW9uKTtcbiAgICAgIGlmIChkcmF3bi50ZVRvcCAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMud3JhcHBlci5zdHlsZS50b3AgPSBkcmF3bi50ZVRvcCArIFwicHhcIjtcbiAgICAgICAgdGhpcy53cmFwcGVyLnN0eWxlLmxlZnQgPSBkcmF3bi50ZUxlZnQgKyBcInB4XCI7XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8vIFJlc2V0IHRoZSBpbnB1dCB0byBjb3JyZXNwb25kIHRvIHRoZSBzZWxlY3Rpb24gKG9yIHRvIGJlIGVtcHR5LFxuICAgIC8vIHdoZW4gbm90IHR5cGluZyBhbmQgbm90aGluZyBpcyBzZWxlY3RlZClcbiAgICByZXNldDogZnVuY3Rpb24odHlwaW5nKSB7XG4gICAgICBpZiAodGhpcy5jb250ZXh0TWVudVBlbmRpbmcpIHJldHVybjtcbiAgICAgIHZhciBtaW5pbWFsLCBzZWxlY3RlZCwgY20gPSB0aGlzLmNtLCBkb2MgPSBjbS5kb2M7XG4gICAgICBpZiAoY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgICB0aGlzLnByZXZJbnB1dCA9IFwiXCI7XG4gICAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucHJpbWFyeSgpO1xuICAgICAgICBtaW5pbWFsID0gaGFzQ29weUV2ZW50ICYmXG4gICAgICAgICAgKHJhbmdlLnRvKCkubGluZSAtIHJhbmdlLmZyb20oKS5saW5lID4gMTAwIHx8IChzZWxlY3RlZCA9IGNtLmdldFNlbGVjdGlvbigpKS5sZW5ndGggPiAxMDAwKTtcbiAgICAgICAgdmFyIGNvbnRlbnQgPSBtaW5pbWFsID8gXCItXCIgOiBzZWxlY3RlZCB8fCBjbS5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgdGhpcy50ZXh0YXJlYS52YWx1ZSA9IGNvbnRlbnQ7XG4gICAgICAgIGlmIChjbS5zdGF0ZS5mb2N1c2VkKSBzZWxlY3RJbnB1dCh0aGlzLnRleHRhcmVhKTtcbiAgICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPj0gOSkgdGhpcy5oYXNTZWxlY3Rpb24gPSBjb250ZW50O1xuICAgICAgfSBlbHNlIGlmICghdHlwaW5nKSB7XG4gICAgICAgIHRoaXMucHJldklucHV0ID0gdGhpcy50ZXh0YXJlYS52YWx1ZSA9IFwiXCI7XG4gICAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uID49IDkpIHRoaXMuaGFzU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIHRoaXMuaW5hY2N1cmF0ZVNlbGVjdGlvbiA9IG1pbmltYWw7XG4gICAgfSxcblxuICAgIGdldEZpZWxkOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudGV4dGFyZWE7IH0sXG5cbiAgICBzdXBwb3J0c1RvdWNoOiBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlOyB9LFxuXG4gICAgZm9jdXM6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuY20ub3B0aW9ucy5yZWFkT25seSAhPSBcIm5vY3Vyc29yXCIgJiYgKCFtb2JpbGUgfHwgYWN0aXZlRWx0KCkgIT0gdGhpcy50ZXh0YXJlYSkpIHtcbiAgICAgICAgdHJ5IHsgdGhpcy50ZXh0YXJlYS5mb2N1cygpOyB9XG4gICAgICAgIGNhdGNoIChlKSB7fSAvLyBJRTggd2lsbCB0aHJvdyBpZiB0aGUgdGV4dGFyZWEgaXMgZGlzcGxheTogbm9uZSBvciBub3QgaW4gRE9NXG4gICAgICB9XG4gICAgfSxcblxuICAgIGJsdXI6IGZ1bmN0aW9uKCkgeyB0aGlzLnRleHRhcmVhLmJsdXIoKTsgfSxcblxuICAgI
23459HJlc2V0UG9zaXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy53cmFwcGVyLnN0eWxlLnRvcCA9IHRoaXMud3JhcHBlci5zdHlsZS5sZWZ0ID0gMDtcbiAgICB9LFxuXG4gICAgcmVjZWl2ZWRGb2N1czogZnVuY3Rpb24oKSB7IHRoaXMuc2xvd1BvbGwoKTsgfSxcblxuICAgIC8vIFBvbGwgZm9yIGlucHV0IGNoYW5nZXMsIHVzaW5nIHRoZSBub3JtYWwgcmF0ZSBvZiBwb2xsaW5nLiBUaGlzXG4gICAgLy8gcnVucyBhcyBsb25nIGFzIHRoZSBlZGl0b3IgaXMgZm9jdXNlZC5cbiAgICBzbG93UG9sbDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaW5wdXQgPSB0aGlzO1xuICAgICAgaWYgKGlucHV0LnBvbGxpbmdGYXN0KSByZXR1cm47XG4gICAgICBpbnB1dC5wb2xsaW5nLnNldCh0aGlzLmNtLm9wdGlvbnMucG9sbEludGVydmFsLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaW5wdXQucG9sbCgpO1xuICAgICAgICBpZiAoaW5wdXQuY20uc3RhdGUuZm9jdXNlZCkgaW5wdXQuc2xvd1BvbGwoKTtcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvLyBXaGVuIGFuIGV2ZW50IGhhcyBqdXN0IGNvbWUgaW4gdGhhdCBpcyBsaWtlbHkgdG8gYWRkIG9yIGNoYW5nZVxuICAgIC8vIHNvbWV0aGluZyBpbiB0aGUgaW5wdXQgdGV4dGFyZWEsIHdlIHBvbGwgZmFzdGVyLCB0byBlbnN1cmUgdGhhdFxuICAgIC8vIHRoZSBjaGFuZ2UgYXBwZWFycyBvbiB0aGUgc2NyZWVuIHF1aWNrbHkuXG4gICAgZmFzdFBvbGw6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG1pc3NlZCA9IGZhbHNlLCBpbnB1dCA9IHRoaXM7XG4gICAgICBpbnB1dC5wb2xsaW5nRmFzdCA9IHRydWU7XG4gICAgICBmdW5jdGlvbiBwKCkge1xuICAgICAgICB2Y
23459XIgY2hhbmdlZCA9IGlucHV0LnBvbGwoKTtcbiAgICAgICAgaWYgKCFjaGFuZ2VkICYmICFtaXNzZWQpIHttaXNzZWQgPSB0cnVlOyBpbnB1dC5wb2xsaW5nLnNldCg2MCwgcCk7fVxuICAgICAgICBlbHNlIHtpbnB1dC5wb2xsaW5nRmFzdCA9IGZhbHNlOyBpbnB1dC5zbG93UG9sbCgpO31cbiAgICAgIH1cbiAgICAgIGlucHV0LnBvbGxpbmcuc2V0KDIwLCBwKTtcbiAgICB9LFxuXG4gICAgLy8gUmVhZCBpbnB1dCBmcm9tIHRoZSB0ZXh0YXJlYSwgYW5kIHVwZGF0ZSB0aGUgZG9jdW1lbnQgdG8gbWF0Y2guXG4gICAgLy8gV2hlbiBzb21ldGhpbmcgaXMgc2VsZWN0ZWQsIGl0IGlzIHByZXNlbnQgaW4gdGhlIHRleHRhcmVhLCBhbmRcbiAgICAvLyBzZWxlY3RlZCAodW5sZXNzIGl0IGlzIGh1Z2UsIGluIHdoaWNoIGNhc2UgYSBwbGFjZWhvbGRlciBpc1xuICAgIC8vIHVzZWQpLiBXaGVuIG5vdGhpbmcgaXMgc2VsZWN0ZWQsIHRoZSBjdXJzb3Igc2l0cyBhZnRlciBwcmV2aW91c2x5XG4gICAgLy8gc2VlbiB0ZXh0IChjYW4gYmUgZW1wdHkpLCB3aGljaCBpcyBzdG9yZWQgaW4gcHJldklucHV0ICh3ZSBtdXN0XG4gICAgLy8gbm90IHJlc2V0IHRoZSB0ZXh0YXJlYSB3aGVuIHR5cGluZywgYmVjYXVzZSB0aGF0IGJyZWFrcyBJTUUpLlxuICAgIHBvbGw6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGNtID0gdGhpcy5jbSwgaW5wdXQgPSB0aGlzLnRleHRhcmVhLCBwcmV2SW5wdXQgPSB0aGlzLnByZXZJbnB1dDtcbiAgICAgIC8vIFNpbmNlIHRoaXMgaXMgY2FsbGVkIGEgKmxvdCosIHRyeSB0byBiYWlsIG91dCBhcyBjaGVhcGx5IGFzXG4gICAgICAvLyBwb3NzaWJsZSB3aGVuIGl0IGlzIGNsZWFyIHRoYXQgbm90aGluZyBoYXBwZW5lZC4gaGFzU2VsZWN0aW9uXG4gICAgICAvLyB3aWxsIGJlIHRoZSBjYXNlIHdoZW4gdGhlcmUgaXMgYSBsb3Qgb2YgdGV4dCBpbiB0aGUgdGV4dGFyZWEsXG4gICAgICAvLyBpbiB3aGljaCBjYXNlIHJlYWRpbmcgaXRzIHZhbHVlIHdvdWxkIGJlIGV4cGVuc2l2ZS5cbiAgICAgIGlmICh0aGlzLmNvbnRleHRNZW51UGVuZGluZyB8fCAhY20uc3RhdGUuZm9jdXNlZCB8fFxuICAgICAgICAgIChoYXNTZWxlY3Rpb24oaW5wdXQpICYmICFwcmV2SW5wdXQgJiYgIXRoaXMuY29tcG9zaW5nKSB8fFxuICAgICAgICAgIGlzUmVhZE9ubHkoY20pIHx8IGNtLm9wdGlvbnMuZGlzYWJsZUlucHV0IHx8IGNtLnN0YXRlLmtleVNlcSlcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICB2Y
23459XIgdGV4dCA9IGlucHV0LnZhbHVlO1xuICAgICAgLy8gSWYgbm90aGluZyBjaGFuZ2VkLCBiYWlsLlxuICAgICAgaWYgKHRleHQgPT0gcHJldklucHV0ICYmICFjbS5zb21ldGhpbmdTZWxlY3RlZCgpKSByZXR1cm4gZmFsc2U7XG4gICAgICAvLyBXb3JrIGFyb3VuZCBub25zZW5zaWNhbCBzZWxlY3Rpb24gcmVzZXR0aW5nIGluIElFOS8xMCwgYW5kXG4gICAgICAvLyBpbmV4cGxpY2FibGUgYXBwZWFyYW5jZSBvZiBwcml2YXRlIGFyZWEgdW5pY29kZSBjaGFyYWN0ZXJzIG9uXG4gICAgICAvLyBzb21lIGtleSBjb21ib3MgaW4gTWFjICgjMjY4OSkuXG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA+PSA5ICYmIHRoaXMuaGFzU2VsZWN0aW9uID09PSB0ZXh0IHx8XG4gICAgICAgICAgbWFjICYmIC9bXFx1ZjcwMC1cXHVmN2ZmXS8udGVzdCh0ZXh0KSkge1xuICAgICAgICBjbS5kaXNwbGF5LmlucHV0LnJlc2V0KCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNtLmRvYy5zZWwgPT0gY20uZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSkge1xuICAgICAgICB2YXIgZmlyc3QgPSB0ZXh0LmNoYXJDb2RlQXQoMCk7XG4gICAgICAgIGlmIChmaXJzdCA9PSAweDIwMGIgJiYgIXByZXZJbnB1dCkgcHJldklucHV0ID0gXCJcXHUyMDBiXCI7XG4gICAgICAgIGlmIChmaXJzdCA9PSAweDIxZGEpIHsgdGhpcy5yZXNldCgpOyByZXR1cm4gdGhpcy5jbS5leGVjQ29tbWFuZChcInVuZG9cIik7IH1cbiAgICAgIH1cbiAgICAgIC8vIEZpbmQgdGhlIHBhcnQgb2YgdGhlIGlucHV0IHRoYXQgaXMgYWN0dWFsbHkgbmV3XG4gICAgICB2Y
23459XIgc2FtZSA9IDAsIGwgPSBNYXRoLm1pbihwcmV2SW5wdXQubGVuZ3RoLCB0ZXh0Lmxlbmd0aCk7XG4gICAgICB3aGlsZSAoc2FtZSA8IGwgJiYgcHJldklucHV0LmNoYXJDb2RlQXQoc2FtZSkgPT0gdGV4dC5jaGFyQ29kZUF0KHNhbWUpKSArK3NhbWU7XG5cbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgICBhcHBseVRleHRJbnB1dChjbSwgdGV4dC5zbGljZShzYW1lKSwgcHJldklucHV0Lmxlbmd0aCAtIHNhbWUsXG4gICAgICAgICAgICAgICAgICAgICAgIG51bGwsIHNlbGYuY29tcG9zaW5nID8gXCIqY29tcG9zZVwiIDogbnVsbCk7XG5cbiAgICAgICAgLy8gRG9uJ3QgbGVhdmUgbG9uZyB0ZXh0IGluIHRoZSB0ZXh0YXJlYSwgc2luY2UgaXQgbWFrZXMgZnVydGhlciBwb2xsaW5nIHNsb3dcbiAgICAgICAgaWYgKHRleHQubGVuZ3RoID4gMTAwMCB8fCB0ZXh0LmluZGV4T2YoXCJcXG5cIikgPiAtMSkgaW5wdXQudmFsdWUgPSBzZWxmLnByZXZJbnB1dCA9IFwiXCI7XG4gICAgICAgIGVsc2Ugc2VsZi5wcmV2SW5wdXQgPSB0ZXh0O1xuXG4gICAgICAgIGlmIChzZWxmLmNvbXBvc2luZykge1xuICAgICAgICAgIHNlbGYuY29tcG9zaW5nLnJhbmdlLmNsZWFyKCk7XG4gICAgICAgICAgc2VsZi5jb21wb3NpbmcucmFuZ2UgPSBjbS5tYXJrVGV4dChzZWxmLmNvbXBvc2luZy5zdGFydCwgY20uZ2V0Q3Vyc29yKFwidG9cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2xhc3NOYW1lOiBcIkNvZGVNaXJyb3ItY29tcG9zaW5nXCJ9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LFxuXG4gICAgZW5zdXJlUG9sbGVkOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLnBvbGxpbmdGYXN0ICYmIHRoaXMucG9sbCgpKSB0aGlzLnBvbGxpbmdGYXN0ID0gZmFsc2U7XG4gICAgfSxcblxuICAgIG9uS2V5UHJlc3M6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPj0gOSkgdGhpcy5oYXNTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgdGhpcy5mYXN0UG9sbCgpO1xuICAgIH0sXG5cbiAgICBvbkNvbnRleHRNZW51OiBmdW5jdGlvbihlKSB7XG4gICAgICB2Y
23459XIgaW5wdXQgPSB0aGlzLCBjbSA9IGlucHV0LmNtLCBkaXNwbGF5ID0gY20uZGlzcGxheSwgdGUgPSBpbnB1dC50ZXh0YXJlYTtcbiAgICAgIHZhciBwb3MgPSBwb3NGcm9tTW91c2UoY20sIGUpLCBzY3JvbGxQb3MgPSBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcDtcbiAgICAgIGlmICghcG9zIHx8IHByZXN0bykgcmV0dXJuOyAvLyBPcGVyYSBpcyBkaWZmaWN1bHQuXG5cbiAgICAgIC8vIFJlc2V0IHRoZSBjdXJyZW50IHRleHQgc2VsZWN0aW9uIG9ubHkgaWYgdGhlIGNsaWNrIGlzIGRvbmUgb3V0c2lkZSBvZiB0aGUgc2VsZWN0aW9uXG4gICAgICAvLyBhbmQgJ3Jlc2V0U2VsZWN0aW9uT25Db250ZXh0TWVudScgb3B0aW9uIGlzIHRydWUuXG4gICAgICB2YXIgcmVzZXQgPSBjbS5vcHRpb25zLnJlc2V0U2VsZWN0aW9uT25Db250ZXh0TWVudTtcbiAgICAgIGlmIChyZXNldCAmJiBjbS5kb2Muc2VsLmNvbnRhaW5zKHBvcykgPT0gLTEpXG4gICAgICAgIG9wZXJhdGlvbihjbSwgc2V0U2VsZWN0aW9uKShjbS5kb2MsIHNpbXBsZVNlbGVjdGlvbihwb3MpLCBzZWxfZG9udFNjcm9sbCk7XG5cbiAgICAgIHZhciBvbGRDU1MgPSB0ZS5zdHlsZS5jc3NUZXh0O1xuICAgICAgaW5wdXQud3JhcHBlci5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgIHRlLnN0eWxlLmNzc1RleHQgPSBcInBvc2l0aW9uOiBmaXhlZDsgd2lkdGg6IDMwcHg7IGhlaWdodDogMzBweDsgdG9wOiBcIiArIChlLmNsaWVudFkgLSA1KSArXG4gICAgICAgIFwicHg7IGxlZnQ6IFwiICsgKGUuY2xpZW50WCAtIDUpICsgXCJweDsgei1pbmRleDogMTAwMDsgYmFja2dyb3VuZDogXCIgK1xuICAgICAgICAoaWUgPyBcInJnYmEoMjU1LCAyNTUsIDI1NSwgLjA1KVwiIDogXCJ0cmFuc3BhcmVudFwiKSArXG4gICAgICAgIFwiOyBvdXRsaW5lOiBub25lOyBib3JkZXItd2lkdGg6IDA7IG91dGxpbmU6IG5vbmU7IG92ZXJmbG93OiBoaWRkZW47IG9wYWNpdHk6IC4wNTsgZmlsdGVyOiBhbHBoYShvcGFjaXR5PTUpO1wiO1xuICAgICAgaWYgKHdlYmtpdCkgdmFyIG9sZFNjcm9sbFkgPSB3aW5kb3cuc2Nyb2xsWTsgLy8gV29yayBhcm91bmQgQ2hyb21lIGlzc3VlICgjMjcxMilcbiAgICAgIGRpc3BsYXkuaW5wdXQuZm9jdXMoKTtcbiAgICAgIGlmICh3ZWJraXQpIHdpbmRvdy5zY3JvbGxUbyhudWxsLCBvbGRTY3JvbGxZKTtcbiAgICAgIGRpc3BsYXkuaW5wdXQucmVzZXQoKTtcbiAgICAgIC8vIEFkZHMgXCJTZWxlY3QgYWxsXCIgdG8gY29udGV4dCBtZW51IGluIEZGXG4gICAgICBpZiAoIWNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHRlLnZhbHVlID0gaW5wdXQucHJldklucHV0ID0gXCIgXCI7XG4gICAgICBpbnB1dC5jb250ZXh0TWVudVBlbmRpbmcgPSB0cnVlO1xuICAgICAgZGlzcGxheS5zZWxGb3JDb250ZXh0TWVudSA9IGNtLmRvYy5zZWw7XG4gICAgICBjbGVhclRpbWVvdXQoZGlzcGxheS5kZXRlY3RpbmdTZWxlY3RBbGwpO1xuXG4gICAgICAvLyBTZWxlY3QtYWxsIHdpbGwgYmUgZ3JleWVkIG91dCBpZiB0aGVyZSdzIG5vdGhpbmcgdG8gc2VsZWN0LCBzb1xuICAgICAgLy8gdGhpcyBhZGRzIGEgemVyby13aWR0aCBzcGFjZSBzbyB0aGF0IHdlIGNhbiBsYXRlciBjaGVjayB3aGV0aGVyXG4gICAgICAvLyBpdCBnb3Qgc2VsZWN0ZWQuXG4gICAgICBmdW5jdGlvbiBwcmVwYXJlU2VsZWN0QWxsSGFjaygpIHtcbiAgICAgICAgaWYgKHRlLnNlbGVjdGlvblN0YXJ0ICE9IG51bGwpIHtcbiAgICAgICAgICB2Y
23459XIgc2VsZWN0ZWQgPSBjbS5zb21ldGhpbmdTZWxlY3RlZCgpO1xuICAgICAgICAgIHZhciBleHR2YWwgPSBcIlxcdTIwMGJcIiArIChzZWxlY3RlZCA/IHRlLnZhbHVlIDogXCJcIik7XG4gICAgICAgICAgdGUudmFsdWUgPSBcIlxcdTIxZGFcIjsgLy8gVXNlZCB0byBjYXRjaCBjb250ZXh0LW1lbnUgdW5kb1xuICAgICAgICAgIHRlLnZhbHVlID0gZXh0dmFsO1xuICAgICAgICAgIGlucHV0LnByZXZJbnB1dCA9IHNlbGVjdGVkID8gXCJcIiA6IFwiXFx1MjAwYlwiO1xuICAgICAgICAgIHRlLnNlbGVjdGlvblN0YXJ0ID0gMTsgdGUuc2VsZWN0aW9uRW5kID0gZXh0dmFsLmxlbmd0aDtcbiAgICAgICAgICAvLyBSZS1zZXQgdGhpcywgaW4gY2FzZSBzb21lIG90aGVyIGhhbmRsZXIgdG91Y2hlZCB0aGVcbiAgICAgICAgICAvLyBzZWxlY3Rpb24gaW4gdGhlIG1lYW50aW1lLlxuICAgICAgICAgIGRpc3BsYXkuc2VsRm9yQ29udGV4dE1lbnUgPSBjbS5kb2Muc2VsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiByZWhpZGUoKSB7XG4gICAgICAgIGlucHV0LmNvbnRleHRNZW51UGVuZGluZyA9IGZhbHNlO1xuICAgICAgICBpbnB1dC53cmFwcGVyLnN0eWxlLnBvc2l0aW9uID0gXCJyZWxhdGl2ZVwiO1xuICAgICAgICB0ZS5zdHlsZS5jc3NUZXh0ID0gb2xkQ1NTO1xuICAgICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDkpIGRpc3BsYXkuc2Nyb2xsYmFycy5zZXRTY3JvbGxUb3AoZGlzcGxheS5zY3JvbGxlci5zY3JvbGxUb3AgPSBzY3JvbGxQb3MpO1xuXG4gICAgICAgIC8vIFRyeSB0byBkZXRlY3QgdGhlIHVzZXIgY2hvb3Npbmcgc2VsZWN0LWFsbFxuICAgICAgICBpZiAodGUuc2VsZWN0aW9uU3RhcnQgIT0gbnVsbCkge1xuICAgICAgICAgIGlmICghaWUgfHwgKGllICYmIGllX3ZlcnNpb24gPCA5KSkgcHJlcGFyZVNlbGVjdEFsbEhhY2soKTtcbiAgICAgICAgICB2Y
23459XIgaSA9IDAsIHBvbGwgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmIChkaXNwbGF5LnNlbEZvckNvbnRleHRNZW51ID09IGNtLmRvYy5zZWwgJiYgdGUuc2VsZWN0aW9uU3RhcnQgPT0gMCAmJlxuICAgICAgICAgICAgICAgIHRlLnNlbGVjdGlvbkVuZCA+IDAgJiYgaW5wdXQucHJldklucHV0ID09IFwiXFx1MjAwYlwiKVxuICAgICAgICAgICAgICBvcGVyYXRpb24oY20sIGNvbW1hbmRzLnNlbGVjdEFsbCkoY20pO1xuICAgICAgICAgICAgZWxzZSBpZiAoaSsrIDwgMTApIGRpc3BsYXkuZGV0ZWN0aW5nU2VsZWN0QWxsID0gc2V0VGltZW91dChwb2xsLCA1MDApO1xuICAgICAgICAgICAgZWxzZSBkaXNwbGF5LmlucHV0LnJlc2V0KCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBkaXNwbGF5LmRldGVjdGluZ1NlbGVjdEFsbCA9IHNldFRpbWVvdXQocG9sbCwgMjAwKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA+PSA5KSBwcmVwYXJlU2VsZWN0QWxsSGFjaygpO1xuICAgICAgaWYgKGNhcHR1cmVSaWdodENsaWNrKSB7XG4gICAgICAgIGVfc3RvcChlKTtcbiAgICAgICAgdmFyIG1vdXNldXAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICBvZmYod2luZG93LCBcIm1vdXNldXBcIiwgbW91c2V1cCk7XG4gICAgICAgICAgc2V0VGltZW91dChyZWhpZGUsIDIwKTtcbiAgICAgICAgfTtcbiAgICAgICAgb24od2luZG93LCBcIm1vdXNldXBcIiwgbW91c2V1cCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXRUaW1lb3V0KHJlaGlkZSwgNTApO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICByZWFkT25seUNoYW5nZWQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgaWYgKCF2YWwpIHRoaXMucmVzZXQoKTtcbiAgICB9LFxuXG4gICAgc2V0VW5lZGl0YWJsZTogbm90aGluZyxcblxuICAgIG5lZWRzQ29udGVudEF0dHJpYnV0ZTogZmFsc2VcbiAgfSwgVGV4dGFyZWFJbnB1dC5wcm90b3R5cGUpO1xuXG4gIC8vIENPTlRFTlRFRElUQUJMRSBJTlBVVCBTVFlMRVxuXG4gIGZ1bmN0aW9uIENvbnRlbnRFZGl0YWJsZUlucHV0KGNtKSB7XG4gICAgdGhpcy5jbSA9IGNtO1xuICAgIHRoaXMubGFzdEFuY2hvck5vZGUgPSB0aGlzLmxhc3RBbmNob3JPZmZzZXQgPSB0aGlzLmxhc3RGb2N1c05vZGUgPSB0aGlzLmxhc3RGb2N1c09mZnNldCA9IG51bGw7XG4gICAgdGhpcy5wb2xsaW5nID0gbmV3IERlbGF5ZWQoKTtcbiAgICB0aGlzLmdyYWNlUGVyaW9kID0gZmFsc2U7XG4gIH1cblxuICBDb250ZW50RWRpdGFibGVJbnB1dC5wcm90b3R5cGUgPSBjb3B5T2JqKHtcbiAgICBpbml0OiBmdW5jdGlvbihkaXNwbGF5KSB7XG4gICAgICB2Y
23459XIgaW5wdXQgPSB0aGlzLCBjbSA9IGlucHV0LmNtO1xuICAgICAgdmFyIGRpdiA9IGlucHV0LmRpdiA9IGRpc3BsYXkubGluZURpdjtcbiAgICAgIGRpc2FibGVCcm93c2VyTWFnaWMoZGl2KTtcblxuICAgICAgb24oZGl2LCBcInBhc3RlXCIsIGZ1bmN0aW9uKGUpIHsgaGFuZGxlUGFzdGUoZSwgY20pOyB9KVxuXG4gICAgICBvbihkaXYsIFwiY29tcG9zaXRpb25zdGFydFwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIHZhciBkYXRhID0gZS5kYXRhO1xuICAgICAgICBpbnB1dC5jb21wb3NpbmcgPSB7c2VsOiBjbS5kb2Muc2VsLCBkYXRhOiBkYXRhLCBzdGFydERhdGE6IGRhdGF9O1xuICAgICAgICBpZiAoIWRhdGEpIHJldHVybjtcbiAgICAgICAgdmFyIHByaW0gPSBjbS5kb2Muc2VsLnByaW1hcnkoKTtcbiAgICAgICAgdmFyIGxpbmUgPSBjbS5nZXRMaW5lKHByaW0uaGVhZC5saW5lKTtcbiAgICAgICAgdmFyIGZvdW5kID0gbGluZS5pbmRleE9mKGRhdGEsIE1hdGgubWF4KDAsIHByaW0uaGVhZC5jaCAtIGRhdGEubGVuZ3RoKSk7XG4gICAgICAgIGlmIChmb3VuZCA+IC0xICYmIGZvdW5kIDw9IHByaW0uaGVhZC5jaClcbiAgICAgICAgICBpbnB1dC5jb21wb3Npbmcuc2VsID0gc2ltcGxlU2VsZWN0aW9uKFBvcyhwcmltLmhlYWQubGluZSwgZm91bmQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUG9zKHByaW0uaGVhZC5saW5lLCBmb3VuZCArIGRhdGEubGVuZ3RoKSk7XG4gICAgICB9KTtcbiAgICAgIG9uKGRpdiwgXCJjb21wb3NpdGlvbnVwZGF0ZVwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlucHV0LmNvbXBvc2luZy5kYXRhID0gZS5kYXRhO1xuICAgICAgfSk7XG4gICAgICBvbihkaXYsIFwiY29tcG9zaXRpb25lbmRcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICB2Y
23459XIgb3VycyA9IGlucHV0LmNvbXBvc2luZztcbiAgICAgICAgaWYgKCFvdXJzKSByZXR1cm47XG4gICAgICAgIGlmIChlLmRhdGEgIT0gb3Vycy5zdGFydERhdGEgJiYgIS9cXHUyMDBiLy50ZXN0KGUuZGF0YSkpXG4gICAgICAgICAgb3Vycy5kYXRhID0gZS5kYXRhO1xuICAgICAgICAvLyBOZWVkIGEgc21hbGwgZGVsYXkgdG8gcHJldmVudCBvdGhlciBjb2RlIChpbnB1dCBldmVudCxcbiAgICAgICAgLy8gc2VsZWN0aW9uIHBvbGxpbmcpIGZyb20gZG9pbmcgZGFtYWdlIHdoZW4gZmlyZWQgcmlnaHQgYWZ0ZXJcbiAgICAgICAgLy8gY29tcG9zaXRpb25lbmQuXG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKCFvdXJzLmhhbmRsZWQpXG4gICAgICAgICAgICBpbnB1dC5hcHBseUNvbXBvc2l0aW9uKG91cnMpO1xuICAgICAgICAgIGlmIChpbnB1dC5jb21wb3NpbmcgPT0gb3VycylcbiAgICAgICAgICAgIGlucHV0LmNvbXBvc2luZyA9IG51bGw7XG4gICAgICAgIH0sIDUwKTtcbiAgICAgIH0pO1xuXG4gICAgICBvbihkaXYsIFwidG91Y2hzdGFydFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaW5wdXQuZm9yY2VDb21wb3NpdGlvbkVuZCgpO1xuICAgICAgfSk7XG5cbiAgICAgIG9uKGRpdiwgXCJpbnB1dFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKGlucHV0LmNvbXBvc2luZykgcmV0dXJuO1xuICAgICAgICBpZiAoaXNSZWFkT25seShjbSkgfHwgIWlucHV0LnBvbGxDb250ZW50KCkpXG4gICAgICAgICAgcnVuSW5PcChpbnB1dC5jbSwgZnVuY3Rpb24oKSB7cmVnQ2hhbmdlKGNtKTt9KTtcbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiBvbkNvcHlDdXQoZSkge1xuICAgICAgICBpZiAoY20uc29tZXRoaW5nU2VsZWN0ZWQoKSkge1xuICAgICAgICAgIGxhc3RDb3BpZWQgPSBjbS5nZXRTZWxlY3Rpb25zKCk7XG4gICAgICAgICAgaWYgKGUudHlwZSA9PSBcImN1dFwiKSBjbS5yZXBsYWNlU2VsZWN0aW9uKFwiXCIsIG51bGwsIFwiY3V0XCIpO1xuICAgICAgICB9IGVsc2UgaWYgKCFjbS5vcHRpb25zLmxpbmVXaXNlQ29weUN1dCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2Y
23459XIgcmFuZ2VzID0gY29weWFibGVSYW5nZXMoY20pO1xuICAgICAgICAgIGxhc3RDb3BpZWQgPSByYW5nZXMudGV4dDtcbiAgICAgICAgICBpZiAoZS50eXBlID09IFwiY3V0XCIpIHtcbiAgICAgICAgICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgY20uc2V0U2VsZWN0aW9ucyhyYW5nZXMucmFuZ2VzLCAwLCBzZWxfZG9udFNjcm9sbCk7XG4gICAgICAgICAgICAgIGNtLnJlcGxhY2VTZWxlY3Rpb24oXCJcIiwgbnVsbCwgXCJjdXRcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaU9TIGV4cG9zZXMgdGhlIGNsaXBib2FyZCBBUEksIGJ1dCBzZWVtcyB0byBkaXNjYXJkIGNvbnRlbnQgaW5zZXJ0ZWQgaW50byBpdFxuICAgICAgICBpZiAoZS5jbGlwYm9hcmREYXRhICYmICFpb3MpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgZS5jbGlwYm9hcmREYXRhLmNsZWFyRGF0YSgpO1xuICAgICAgICAgIGUuY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dC9wbGFpblwiLCBsYXN0Q29waWVkLmpvaW4oXCJcXG5cIikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIE9sZC1mYXNoaW9uZWQgYnJpZWZseS1mb2N1cy1hLXRleHRhcmVhIGhhY2tcbiAgICAgICAgICB2YXIga2x1ZGdlID0gaGlkZGVuVGV4dGFyZWEoKSwgdGUgPSBrbHVkZ2UuZmlyc3RDaGlsZDtcbiAgICAgICAgICBjbS5kaXNwbGF5LmxpbmVTcGFjZS5pbnNlcnRCZWZvcmUoa2x1ZGdlLCBjbS5kaXNwbGF5LmxpbmVTcGFjZS5maXJzdENoaWxkKTtcbiAgICAgICAgICB0ZS52YWx1ZSA9IGxhc3RDb3BpZWQuam9pbihcIlxcblwiKTtcbiAgICAgICAgICB2Y
23459XIgaGFkRm9jdXMgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuICAgICAgICAgIHNlbGVjdElucHV0KHRlKTtcbiAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY20uZGlzcGxheS5saW5lU3BhY2UucmVtb3ZlQ2hpbGQoa2x1ZGdlKTtcbiAgICAgICAgICAgIGhhZEZvY3VzLmZvY3VzKCk7XG4gICAgICAgICAgfSwgNTApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBvbihkaXYsIFwiY29weVwiLCBvbkNvcHlDdXQpO1xuICAgICAgb24oZGl2LCBcImN1dFwiLCBvbkNvcHlDdXQpO1xuICAgIH0sXG5cbiAgICBwcmVwYXJlU2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciByZXN1bHQgPSBwcmVwYXJlU2VsZWN0aW9uKHRoaXMuY20sIGZhbHNlKTtcbiAgICAgIHJlc3VsdC5mb2N1cyA9IHRoaXMuY20uc3RhdGUuZm9jdXNlZDtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIHNob3dTZWxlY3Rpb246IGZ1bmN0aW9uKGluZm8pIHtcbiAgICAgIGlmICghaW5mbyB8fCAhdGhpcy5jbS5kaXNwbGF5LnZpZXcubGVuZ3RoKSByZXR1cm47XG4gICAgICBpZiAoaW5mby5mb2N1cykgdGhpcy5zaG93UHJpbWFyeVNlbGVjdGlvbigpO1xuICAgICAgdGhpcy5zaG93TXVsdGlwbGVTZWxlY3Rpb25zKGluZm8pO1xuICAgIH0sXG5cbiAgICBzaG93UHJpbWFyeVNlbGVjdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpLCBwcmltID0gdGhpcy5jbS5kb2Muc2VsLnByaW1hcnkoKTtcbiAgICAgIHZhciBjdXJBbmNob3IgPSBkb21Ub1Bvcyh0aGlzLmNtLCBzZWwuYW5jaG9yTm9kZSwgc2VsLmFuY2hvck9mZnNldCk7XG4gICAgICB2Y
23459XIgY3VyRm9jdXMgPSBkb21Ub1Bvcyh0aGlzLmNtLCBzZWwuZm9jdXNOb2RlLCBzZWwuZm9jdXNPZmZzZXQpO1xuICAgICAgaWYgKGN1ckFuY2hvciAmJiAhY3VyQW5jaG9yLmJhZCAmJiBjdXJGb2N1cyAmJiAhY3VyRm9jdXMuYmFkICYmXG4gICAgICAgICAgY21wKG1pblBvcyhjdXJBbmNob3IsIGN1ckZvY3VzKSwgcHJpbS5mcm9tKCkpID09IDAgJiZcbiAgICAgICAgICBjbXAobWF4UG9zKGN1ckFuY2hvciwgY3VyRm9jdXMpLCBwcmltLnRvKCkpID09IDApXG4gICAgICAgIHJldHVybjtcblxuICAgICAgdmFyIHN0YXJ0ID0gcG9zVG9ET00odGhpcy5jbSwgcHJpbS5mcm9tKCkpO1xuICAgICAgdmFyIGVuZCA9IHBvc1RvRE9NKHRoaXMuY20sIHByaW0udG8oKSk7XG4gICAgICBpZiAoIXN0YXJ0ICYmICFlbmQpIHJldHVybjtcblxuICAgICAgdmFyIHZpZXcgPSB0aGlzLmNtLmRpc3BsYXkudmlldztcbiAgICAgIHZhciBvbGQgPSBzZWwucmFuZ2VDb3VudCAmJiBzZWwuZ2V0UmFuZ2VBdCgwKTtcbiAgICAgIGlmICghc3RhcnQpIHtcbiAgICAgICAgc3RhcnQgPSB7bm9kZTogdmlld1swXS5tZWFzdXJlLm1hcFsyXSwgb2Zmc2V0OiAwfTtcbiAgICAgIH0gZWxzZSBpZiAoIWVuZCkgeyAvLyBGSVhNRSBkYW5nZXJvdXNseSBoYWNreVxuICAgICAgICB2YXIgbWVhc3VyZSA9IHZpZXdbdmlldy5sZW5ndGggLSAxXS5tZWFzdXJlO1xuICAgICAgICB2YXIgbWFwID0gbWVhc3VyZS5tYXBzID8gbWVhc3VyZS5tYXBzW21lYXN1cmUubWFwcy5sZW5ndGggLSAxXSA6IG1lYXN1cmUubWFwO1xuICAgICAgICBlbmQgPSB7bm9kZTogbWFwW21hcC5sZW5ndGggLSAxXSwgb2Zmc2V0OiBtYXBbbWFwLmxlbmd0aCAtIDJdIC0gbWFwW21hcC5sZW5ndGggLSAzXX07XG4gICAgICB9XG5cbiAgICAgIHRyeSB7IHZhciBybmcgPSByYW5nZShzdGFydC5ub2RlLCBzdGFydC5vZmZzZXQsIGVuZC5vZmZzZXQsIGVuZC5ub2RlKTsgfVxuICAgICAgY2F0Y2goZSkge30gLy8gT3VyIG1vZGVsIG9mIHRoZSBET00gbWlnaHQgYmUgb3V0ZGF0ZWQsIGluIHdoaWNoIGNhc2UgdGhlIHJhbmdlIHdlIHRyeSB0byBzZXQgY2FuIGJlIGltcG9zc2libGVcbiAgICAgIGlmIChybmcpIHtcbiAgICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgICBzZWwuYWRkUmFuZ2Uocm5nKTt
vendor: 7,661 bytes, line 23459
23459cbiAgICAgICAgaWYgKG9sZCAmJiBzZWwuYW5jaG9yTm9kZSA9PSBudWxsKSBzZWwuYWRkUmFuZ2Uob2xkKTtcbiAgICAgICAgZWxzZSBpZiAoZ2Vja28pIHRoaXMuc3RhcnRHcmFjZVBlcmlvZCgpO1xuICAgICAgfVxuICAgICAgdGhpcy5yZW1lbWJlclNlbGVjdGlvbigpO1xuICAgIH0sXG5cbiAgICBzdGFydEdyYWNlUGVyaW9kOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5ncmFjZVBlcmlvZCk7XG4gICAgICB0aGlzLmdyYWNlUGVyaW9kID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgaW5wdXQuZ3JhY2VQZXJpb2QgPSBmYWxzZTtcbiAgICAgICAgaWYgKGlucHV0LnNlbGVjdGlvbkNoYW5nZWQoKSlcbiAgICAgICAgICBpbnB1dC5jbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7IGlucHV0LmNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSB0cnVlOyB9KTtcbiAgICAgIH0sIDIwKTtcbiAgICB9LFxuXG4gICAgc2hvd011bHRpcGxlU2VsZWN0aW9uczogZnVuY3Rpb24oaW5mbykge1xuICAgICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQodGhpcy5jbS5kaXNwbGF5LmN1cnNvckRpdiwgaW5mby5jdXJzb3JzKTtcbiAgICAgIHJlbW92ZUNoaWxkcmVuQW5kQWRkKHRoaXMuY20uZGlzcGxheS5zZWxlY3Rpb25EaXYsIGluZm8uc2VsZWN0aW9uKTtcbiAgICB9LFxuXG4gICAgcmVtZW1iZXJTZWxlY3Rpb246IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgIHRoaXMubGFzdEFuY2hvck5vZGUgPSBzZWwuYW5jaG9yTm9kZTsgdGhpcy5sYXN0QW5jaG9yT2Zmc2V0ID0gc2VsLmFuY2hvck9mZnNldDtcbiAgICAgIHRoaXMubGFzdEZvY3VzTm9kZSA9IHNlbC5mb2N1c05vZGU7IHRoaXMubGFzdEZvY3VzT2Zmc2V0ID0gc2VsLmZvY3VzT2Zmc2V0O1xuICAgIH0sXG5cbiAgICBzZWxlY3Rpb25JbkVkaXRvcjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgaWYgKCFzZWwucmFuZ2VDb3VudCkgcmV0dXJuIGZhbHNlO1xuICAgICAgdmFyIG5vZGUgPSBzZWwuZ2V0UmFuZ2VBdCgwKS5jb21tb25BbmNlc3RvckNvbnRhaW5lcjtcbiAgICAgIHJldHVybiBjb250YWlucyh0aGlzLmRpdiwgbm9kZSk7XG4gICAgfSxcblxuICAgIGZvY3VzOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmNtLm9wdGlvbnMucmVhZE9ubHkgIT0gXCJub2N1cnNvclwiKSB0aGlzLmRpdi5mb2N1cygpO1xuICAgIH0sXG4gICAgYmx1cjogZnVuY3Rpb24oKSB7IHRoaXMuZGl2LmJsdXIoKTsgfSxcbiAgICBnZXRGaWVsZDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmRpdjsgfSxcblxuICAgIHN1cHBvcnRzVG91Y2g6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfSxcblxuICAgIHJlY2VpdmVkRm9jdXM6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgIGlmICh0aGlzLnNlbGVjdGlvbkluRWRpdG9yKCkpXG4gICAgICAgIHRoaXMucG9sbFNlbGVjdGlvbigpO1xuICAgICAgZWxzZVxuICAgICAgICBydW5Jbk9wKHRoaXMuY20sIGZ1bmN0aW9uKCkgeyBpbnB1dC5jbS5jdXJPcC5zZWxlY3Rpb25DaGFuZ2VkID0gdHJ1ZTsgfSk7XG5cbiAgICAgIGZ1bmN0aW9uIHBvbGwoKSB7XG4gICAgICAgIGlmIChpbnB1dC5jbS5zdGF0ZS5mb2N1c2VkKSB7XG4gICAgICAgICAgaW5wdXQucG9sbFNlbGVjdGlvbigpO1xuICAgICAgICAgIGlucHV0LnBvbGxpbmcuc2V0KGlucHV0LmNtLm9wdGlvbnMucG9sbEludGVydmFsLCBwb2xsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5wb2xsaW5nLnNldCh0aGlzLmNtLm9wdGlvbnMucG9sbEludGVydmFsLCBwb2xsKTtcbiAgICB9LFxuXG4gICAgc2VsZWN0aW9uQ2hhbmdlZDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgcmV0dXJuIHNlbC5hbmNob3JOb2RlICE9IHRoaXMubGFzdEFuY2hvck5vZGUgfHwgc2VsLmFuY2hvck9mZnNldCAhPSB0aGlzLmxhc3RBbmNob3JPZmZzZXQgfHxcbiAgICAgICAgc2VsLmZvY3VzTm9kZSAhPSB0aGlzLmxhc3RGb2N1c05vZGUgfHwgc2VsLmZvY3VzT2Zmc2V0ICE9IHRoaXMubGFzdEZvY3VzT2Zmc2V0O1xuICAgIH0sXG5cbiAgICBwb2xsU2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghdGhpcy5jb21wb3NpbmcgJiYgIXRoaXMuZ3JhY2VQZXJpb2QgJiYgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkKCkpIHtcbiAgICAgICAgdmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKSwgY20gPSB0aGlzLmNtO1xuICAgICAgICB0aGlzLnJlbWVtYmVyU2VsZWN0aW9uKCk7XG4gICAgICAgIHZhciBhbmNob3IgPSBkb21Ub1BvcyhjbSwgc2VsLmFuY2hvck5vZGUsIHNlbC5hbmNob3JPZmZzZXQpO1xuICAgICAgICB2YXIgaGVhZCA9IGRvbVRvUG9zKGNtLCBzZWwuZm9jdXNOb2RlLCBzZWwuZm9jdXNPZmZzZXQpO1xuICAgICAgICBpZiAoYW5jaG9yICYmIGhlYWQpIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHNldFNlbGVjdGlvbihjbS5kb2MsIHNpbXBsZVNlbGVjdGlvbihhbmNob3IsIGhlYWQpLCBzZWxfZG9udFNjcm9sbCk7XG4gICAgICAgICAgaWYgKGFuY2hvci5iYWQgfHwgaGVhZC5iYWQpIGNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgcG9sbENvbnRlbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGNtID0gdGhpcy5jbSwgZGlzcGxheSA9IGNtLmRpc3BsYXksIHNlbCA9IGNtLmRvYy5zZWwucHJpbWFyeSgpO1xuICAgICAgdmFyIGZyb20gPSBzZWwuZnJvbSgpLCB0byA9IHNlbC50bygpO1xuICAgICAgaWYgKGZyb20ubGluZSA8IGRpc3BsYXkudmlld0Zyb20gfHwgdG8ubGluZSA+IGRpc3BsYXkudmlld1RvIC0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICB2YXIgZnJvbUluZGV4O1xuICAgICAgaWYgKGZyb20ubGluZSA9PSBkaXNwbGF5LnZpZXdGcm9tIHx8IChmcm9tSW5kZXggPSBmaW5kVmlld0luZGV4KGNtLCBmcm9tLmxpbmUpKSA9PSAwKSB7XG4gICAgICAgIHZhciBmcm9tTGluZSA9IGxpbmVObyhkaXNwbGF5LnZpZXdbMF0ubGluZSk7XG4gICAgICAgIHZhciBmcm9tTm9kZSA9IGRpc3BsYXkudmlld1swXS5ub2RlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGZyb21MaW5lID0gbGluZU5vKGRpc3BsYXkudmlld1tmcm9tSW5kZXhdLmxpbmUpO1xuICAgICAgICB2YXIgZnJvbU5vZGUgPSBkaXNwbGF5LnZpZXdbZnJvbUluZGV4IC0gMV0ubm9kZS5uZXh0U2libGluZztcbiAgICAgIH1cbiAgICAgIHZhciB0b0luZGV4ID0gZmluZFZpZXdJbmRleChjbSwgdG8ubGluZSk7XG4gICAgICBpZiAodG9JbmRleCA9PSBkaXNwbGF5LnZpZXcubGVuZ3RoIC0gMSkge1xuICAgICAgICB2YXIgdG9MaW5lID0gZGlzcGxheS52aWV3VG8gLSAxO1xuICAgICAgICB2YXIgdG9Ob2RlID0gZGlzcGxheS5saW5lRGl2Lmxhc3RDaGlsZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB0b0xpbmUgPSBsaW5lTm8oZGlzcGxheS52aWV3W3RvSW5kZXggKyAxXS5saW5lKSAtIDE7XG4gICAgICAgIHZhciB0b05vZGUgPSBkaXNwbGF5LnZpZXdbdG9JbmRleCArIDFdLm5vZGUucHJldmlvdXNTaWJsaW5nO1xuICAgICAgfVxuXG4gICAgICB2YXIgbmV3VGV4dCA9IGNtLmRvYy5zcGxpdExpbmVzKGRvbVRleHRCZXR3ZWVuKGNtLCBmcm9tTm9kZSwgdG9Ob2RlLCBmcm9tTGluZSwgdG9MaW5lKSk7XG4gICAgICB2YXIgb2xkVGV4dCA9IGdldEJldHdlZW4oY20uZG9jLCBQb3MoZnJvbUxpbmUsIDApLCBQb3ModG9MaW5lLCBnZXRMaW5lKGNtLmRvYywgdG9MaW5lKS50ZXh0Lmxlbmd0aCkpO1xuICAgICAgd2hpbGUgKG5ld1RleHQubGVuZ3RoID4gMSAmJiBvbGRUZXh0Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgaWYgKGxzdChuZXdUZXh0KSA9PSBsc3Qob2xkVGV4dCkpIHsgbmV3VGV4dC5wb3AoKTsgb2xkVGV4dC5wb3AoKTsgdG9MaW5lLS07IH1cbiAgICAgICAgZWxzZSBpZiAobmV3VGV4dFswXSA9PSBvbGRUZXh0WzBdKSB7IG5ld1RleHQuc2hpZnQoKTsgb2xkVGV4dC5zaGlmdCgpOyBmcm9tTGluZSsrOyB9XG4gICAgICAgIGVsc2UgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXRGcm9udCA9IDAsIGN1dEVuZCA9IDA7XG4gICAgICB2YXIgbmV3VG9wID0gbmV3VGV4dFswXSwgb2xkVG9wID0gb2xkVGV4dFswXSwgbWF4Q3V0RnJvbnQgPSBNYXRoLm1pbihuZXdUb3AubGVuZ3RoLCBvbGRUb3AubGVuZ3RoKTtcbiAgICAgIHdoaWxlIChjdXRGcm9udCA8IG1heEN1dEZyb250ICYmIG5ld1RvcC5jaGFyQ29kZUF0KGN1dEZyb250KSA9PSBvbGRUb3AuY2hhckNvZGVBdChjdXRGcm9udCkpXG4gICAgICAgICsrY3V0RnJvbnQ7XG4gICAgICB2YXIgbmV3Qm90ID0gbHN0KG5ld1RleHQpLCBvbGRCb3QgPSBsc3Qob2xkVGV4dCk7XG4gICAgICB2YXIgbWF4Q3V0RW5kID0gTWF0aC5taW4obmV3Qm90Lmxlbmd0aCAtIChuZXdUZXh0Lmxlbmd0aCA9PSAxID8gY3V0RnJvbnQgOiAwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRCb3QubGVuZ3RoIC0gKG9sZFRleHQubGVuZ3RoID09IDEgPyBjdXRGcm9udCA6IDApKTtcbiAgICAgIHdoaWxlIChjdXRFbmQgPCBtYXhDdXRFbmQgJiZcbiAgICAgICAgICAgICBuZXdCb3QuY2hhckNvZGVBdChuZXdCb3QubGVuZ3RoIC0gY3V0RW5kIC0gMSkgPT0gb2xkQm90LmNoYXJDb2RlQXQob2xkQm90Lmxlbmd0aCAtIGN1dEVuZCAtIDEpKVxuICAgICAgICArK2N1dEVuZDtcblxuICAgICAgbmV3VGV4dFtuZXdUZXh0Lmxlbmd0aCAtIDFdID0gbmV3Qm90LnNsaWNlKDAsIG5ld0JvdC5sZW5ndGggLSBjdXRFbmQpO1xuICAgICAgbmV3VGV4dFswXSA9IG5ld1RleHRbMF0uc2xpY2UoY3V0RnJvbnQpO1xuXG4gICAgICB2YXIgY2hGcm9tID0gUG9zKGZyb21MaW5lLCBjdXRGcm9udCk7XG4gICAgICB2YXIgY2hUbyA9IFBvcyh0b0xpbmUsIG9sZFRleHQubGVuZ3RoID8gbHN0KG9sZFRleHQpLmxlbmd0aCAtIGN1dEVuZCA6IDApO1xuICAgICAgaWYgKG5ld1RleHQubGVuZ3RoID4gMSB8fCBuZXdUZXh0WzBdIHx8IGNtcChjaEZyb20sIGNoVG8pKSB7XG4gICAgICAgIHJlcGxhY2VSYW5nZShjbS5kb2MsIG5ld1RleHQsIGNoRnJvbSwgY2hUbywgXCIraW5wdXRcIik7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBlbnN1cmVQb2xsZWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5mb3JjZUNvbXBvc2l0aW9uRW5kKCk7XG4gICAgfSxcbiAgICByZXNldDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmZvcmNlQ29tcG9zaXRpb25FbmQoKTtcbiAgICB9LFxuICAgIGZvcmNlQ29tcG9zaXRpb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCF0aGlzLmNvbXBvc2luZyB8fCB0aGlzLmNvbXBvc2luZy5oYW5kbGVkKSByZXR1cm47XG4gICAgICB0aGlzLmFwcGx5Q29tcG9zaXRpb24odGhpcy5jb21wb3NpbmcpO1xuICAgICAgdGhpcy5jb21wb3NpbmcuaGFuZGxlZCA9IHRydWU7XG4gICAgICB0aGlzLmRpdi5ibHVyKCk7XG4gICAgICB0aGlzLmRpdi5mb2N1cygpO1xuICAgIH0sXG4gICAgYXBwbHlDb21wb3NpdGlvbjogZnVuY3Rpb24oY29tcG9zaW5nKSB7XG4gICAgICBpZiAo
23459aXNSZWFkT25seSh0aGlzLmNtKSlcbiAgICAgICAgb3BlcmF0aW9uKHRoaXMuY20sIHJlZ0NoYW5nZSkodGhpcy5jbSlcbiAgICAgIGVsc2UgaWYgKGNvbXBvc2luZy5kYXRhICYmIGNvbXBvc2luZy5kYXRhICE9IGNvbXBvc2luZy5zdGFydERhdGEpXG4gICAgICAgIG9wZXJhdGlvbih0aGlzLmNtLCBhcHBseVRleHRJbnB1dCkodGhpcy5jbSwgY29tcG9zaW5nLmRhdGEsIDAsIGNvbXBvc2luZy5zZWwpO1xuICAgIH0sXG5cbiAgICBzZXRVbmVkaXRhYmxlOiBmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLmNvbnRlbnRFZGl0YWJsZSA9IFwiZmFsc2VcIlxuICAgIH0sXG5cbiAgICBvbktleVByZXNzOiBmdW5jdGlvbihlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBpZiAoIWlzUmVhZE9ubHkodGhpcy5jbSkpXG4gICAgICAgIG9wZXJhdGlvbih0aGlzLmNtLCBhcHBseVRleHRJbnB1dCkodGhpcy5jbSwgU3RyaW5nLmZyb21DaGFyQ29kZShlLmNoYXJDb2RlID09IG51bGwgPyBlLmtleUNvZGUgOiBlLmNoYXJDb2RlKSwgMCk7XG4gICAgfSxcblxuICAgIHJlYWRPbmx5Q2hhbmdlZDogZnVuY3Rpb24odmFsKSB7XG4gICAgICB0aGlzLmRpdi5jb250ZW50RWRpdGFibGUgPSBTdHJpbmcodmFsICE9IFwibm9jdXJzb3JcIilcbiAgICB9LFxuXG4gICAgb25Db250ZXh0TWVudTogbm90aGluZyxcbiAgICByZXNldFBvc2l0aW9uOiBub3RoaW5nLFxuXG4gICAgbmVlZHNDb250ZW50QXR0cmlidXRlOiB0cnVlXG4gIH0sIENvbnRlbnRFZGl0YWJsZUlucHV0LnByb3RvdHlwZSk7XG5cbiAgZnVuY3Rpb24gcG9zVG9ET00oY20sIHBvcykge1xuICAgIHZhciB2aWV3ID0gZmluZFZpZXdGb3JMaW5lKGNtLCBwb3MubGluZSk7XG4gICAgaWYgKCF2aWV3IHx8IHZpZXcuaGlkZGVuKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgbGluZSA9IGdldExpbmUoY20uZG9jLCBwb3MubGluZSk7XG4gICAgdmFyIGluZm8gPSBtYXBGcm9tTGluZVZpZXcodmlldywgbGluZSwgcG9zLmxpbmUpO1xuXG4gICAgdmFyIG9yZGVyID0gZ2V0T3JkZXIobGluZSksIHNpZGUgPSBcImxlZnRcIjtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIHZhciBwYXJ0UG9zID0gZ2V0QmlkaVBhcnRBdChvcmRlciwgcG9zLmNoKTtcbiAgICAgIHNpZGUgPSBwYXJ0UG9zICUgMiA/IFwicmlnaHRcIiA6IFwibGVmdFwiO1xuICAgIH1cbiAgICB2YXIgcmVzdWx0ID0gbm9kZUFuZE9mZnNldEluTGluZU1hcChpbmZvLm1hcCwgcG9zLmNoLCBzaWRlKTtcbiAgICByZXN1bHQub2Zmc2V0ID0gcmVzdWx0LmNvbGxhcHNlID09IFwicmlnaHRcIiA/IHJlc3VsdC5lbmQgOiByZXN1bHQuc3RhcnQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJhZFBvcyhwb3MsIGJhZCkgeyBpZiAoYmFkKSBwb3MuYmFkID0gdHJ1ZTsgcmV0dXJuIHBvczsgfVxuXG4gIGZ1bmN0aW9uIGRvbVRvUG9zKGNtLCBub2RlLCBvZmZzZXQpIHtcbiAgICB2YXIgbGluZU5vZGU7XG4gICAgaWYgKG5vZGUgPT0gY20uZGlzcGxheS5saW5lRGl2KSB7XG4gICAgICBsaW5lTm9kZSA9IGNtLmRpc3BsYXkubGluZURpdi5jaGlsZE5vZGVzW29mZnNldF07XG4gICAgICBpZiAoIWxpbmVOb2RlKSByZXR1cm4gYmFkUG9zKGNtLmNsaXBQb3MoUG9zKGNtLmRpc3BsYXkudmlld1RvIC0gMSkpLCB0cnVlKTtcbiAgICAgIG5vZGUgPSBudWxsOyBvZmZzZXQgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxpbmVOb2RlID0gbm9kZTs7IGxpbmVOb2RlID0gbGluZU5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICBpZiAoIWxpbmVOb2RlIHx8IGxpbmVOb2RlID09IGNtLmRpc3BsYXkubGluZURpdikgcmV0dXJuIG51bGw7XG4gICAgICAgIGlmIChsaW5lTm9kZS5wYXJlbnROb2RlICYmIGxpbmVOb2RlLnBhcmVudE5vZGUgPT0gY20uZGlzcGxheS5saW5lRGl2KSBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbS5kaXNwbGF5LnZpZXcubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBsaW5lVmlldyA9IGNtLmRpc3BsYXkudmlld1tpXTtcbiAgICAgIGlmIChsaW5lVmlldy5ub2RlID09IGxpbmVOb2RlKVxuICAgICAgICByZXR1cm4gbG9jYXRlTm9kZUluTGluZVZpZXcobGluZVZpZXcsIG5vZGUsIG9mZnNldCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gbG9jYXRlTm9kZUluTGluZVZpZXcobGluZVZpZXcsIG5vZGUsIG9mZnNldCkge1xuICAgIHZhciB3cmFwcGVyID0gbGluZVZpZXcudGV4dC5maXJzdENoaWxkLCBiYWQgPSBmYWxzZTtcbiAgICBpZiAoIW5vZGUgfHwgIWNvbnRhaW5zKHdyYXBwZXIsIG5vZGUpKSByZXR1cm4gYmFkUG9zKFBvcyhsaW5lTm8obGluZVZpZXcubGluZSksIDApLCB0cnVlKTtcbiAgICBpZiAobm9kZSA9PSB3cmFwcGVyKSB7XG4gICAgICBiYWQgPSB0cnVlO1xuICAgICAgbm9kZSA9IHdyYXBwZXIuY2hpbGROb2Rlc1tvZmZzZXRdO1xuICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgIGlmICghbm9kZSkge1xuICAgICAgICB2Y
23459XIgbGluZSA9IGxpbmVWaWV3LnJlc3QgPyBsc3QobGluZVZpZXcucmVzdCkgOiBsaW5lVmlldy5saW5lO1xuICAgICAgICByZXR1cm4gYmFkUG9zKFBvcyhsaW5lTm8obGluZSksIGxpbmUudGV4dC5sZW5ndGgpLCBiYWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciB0ZXh0Tm9kZSA9IG5vZGUubm9kZVR5cGUgPT0gMyA/IG5vZGUgOiBudWxsLCB0b3BOb2RlID0gbm9kZTtcbiAgICBpZiAoIXRleHROb2RlICYmIG5vZGUuY2hpbGROb2Rlcy5sZW5ndGggPT0gMSAmJiBub2RlLmZpcnN0Q2hpbGQubm9kZVR5cGUgPT0gMykge1xuICAgICAgdGV4dE5vZGUgPSBub2RlLmZpcnN0Q2hpbGQ7XG4gICAgICBpZiAob2Zmc2V0KSBvZmZzZXQgPSB0ZXh0Tm9kZS5ub2RlVmFsdWUubGVuZ3RoO1xuICAgIH1cbiAgICB3aGlsZSAodG9wTm9kZS5wYXJlbnROb2RlICE9IHdyYXBwZXIpIHRvcE5vZGUgPSB0b3BOb2RlLnBhcmVudE5vZGU7XG4gICAgdmFyIG1lYXN1cmUgPSBsaW5lVmlldy5tZWFzdXJlLCBtYXBzID0gbWVhc3VyZS5tYXBzO1xuXG4gICAgZnVuY3Rpb24gZmluZCh0ZXh0Tm9kZSwgdG9wTm9kZSwgb2Zmc2V0KSB7XG4gICAgICBmb3IgKHZhciBpID0gLTE7IGkgPCAobWFwcyA/IG1hcHMubGVuZ3RoIDogMCk7IGkrKykge1xuICAgICAgICB2YXIgbWFwID0gaSA8IDAgPyBtZWFzdXJlLm1hcCA6IG1hcHNbaV07XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWFwLmxlbmd0aDsgaiArPSAzKSB7XG4gICAgICAgICAgdmFyIGN1ck5vZGUgPSBtYXBbaiArIDJdO1xuICAgICAgICAgIGlmIChjdXJOb2RlID09IHRleHROb2RlIHx8IGN1ck5vZGUgPT0gdG9wTm9kZSkge1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBsaW5lTm8oaSA8IDAgPyBsaW5lVmlldy5saW5lIDogbGluZVZpZXcucmVzdFtpXSk7XG4gICAgICAgICAgICB2Y
23459XIgY2ggPSBtYXBbal0gKyBvZmZzZXQ7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBjdXJOb2RlICE9IHRleHROb2RlKSBjaCA9IG1hcFtqICsgKG9mZnNldCA/IDEgOiAwKV07XG4gICAgICAgICAgICByZXR1cm4gUG9zKGxpbmUsIGNoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGZvdW5kID0gZmluZCh0ZXh0Tm9kZSwgdG9wTm9kZSwgb2Zmc2V0KTtcbiAgICBpZiAoZm91bmQpIHJldHVybiBiYWRQb3MoZm91bmQsIGJhZCk7XG5cbiAgICAvLyBGSVhNRSB0aGlzIGlzIGFsbCByZWFsbHkgc2hha3kuIG1pZ2h0IGhhbmRsZSB0aGUgZmV3IGNhc2VzIGl0IG5lZWRzIHRvIGhhbmRsZSwgYnV0IGxpa2VseSB0byBjYXVzZSBwcm9ibGVtc1xuICAgIGZvciAodmFyIGFmdGVyID0gdG9wTm9kZS5uZXh0U2libGluZywgZGlzdCA9IHRleHROb2RlID8gdGV4dE5vZGUubm9kZVZhbHVlLmxlbmd0aCAtIG9mZnNldCA6IDA7IGFmdGVyOyBhZnRlciA9IGFmdGVyLm5leHRTaWJsaW5nKSB7XG4gICAgICBmb3VuZCA9IGZpbmQoYWZ0ZXIsIGFmdGVyLmZpcnN0Q2hpbGQsIDApO1xuICAgICAgaWYgKGZvdW5kKVxuICAgICAgICByZXR1cm4gYmFkUG9zKFBvcyhmb3VuZC5saW5lLCBmb3VuZC5jaCAtIGRpc3QpLCBiYWQpO1xuICAgICAgZWxzZVxuICAgICAgICBkaXN0ICs9IGFmdGVyLnRleHRDb250ZW50Lmxlbmd0aDtcbiAgICB9XG4gICAgZm9yICh2YXIgYmVmb3JlID0gdG9wTm9kZS5wcmV2aW91c1NpYmxpbmcsIGRpc3QgPSBvZmZzZXQ7IGJlZm9yZTsgYmVmb3JlID0gYmVmb3JlLnByZXZpb3VzU2libGluZykge1xuICAgICAgZm91bmQgPSBmaW5kKGJlZm9yZSwgYmVmb3JlLmZpcnN0Q2hpbGQsIC0xKTtcbiAgICAgIGlmIChmb3VuZClcbiAgICAgICAgcmV0dXJuIGJhZFBvcyhQb3MoZm91bmQubGluZSwgZm91bmQuY2ggKyBkaXN0KSwgYmFkKTtcbiAgICAgIGVsc2VcbiAgICAgICAgZGlzdCArPSBhZnRlci50ZXh0Q29udGVudC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZG9tVGV4dEJldHdlZW4oY20sIGZyb20sIHRvLCBmcm9tTGluZSwgdG9MaW5lKSB7XG4gICAgdmFyIHRleHQgPSBcIlwiLCBjbG9zaW5nID0gZmFsc2UsIGxpbmVTZXAgPSBjbS5kb2MubGluZVNlcGFyYXRvcigpO1xuICAgIGZ1bmN0aW9uIHJlY29nbml6ZU1hcmtlcihpZCkgeyByZXR1cm4gZnVuY3Rpb24obWFya2VyKSB7IHJldHVybiBtYXJrZXIuaWQgPT0gaWQ7IH07IH1cbiAgICBmdW5jdGlvbiB3YWxrKG5vZGUpIHtcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IDEpIHtcbiAgICAgICAgdmFyIGNtVGV4dCA9IG5vZGUuZ2V0QXR0cmlidXRlKFwiY20tdGV4dFwiKTtcbiAgICAgICAgaWYgKGNtVGV4dCAhPSBudWxsKSB7XG4gICAgICAgICAgaWYgKGNtVGV4dCA9PSBcIlwiKSBjbVRleHQgPSBub2RlLnRleHRDb250ZW50LnJlcGxhY2UoL1xcdTIwMGIvZywgXCJcIik7XG4gICAgICAgICAgdGV4dCArPSBjbVRleHQ7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtYXJrZXJJRCA9IG5vZGUuZ2V0QXR0cmlidXRlKFwiY20tbWFya2VyXCIpLCByYW5nZTtcbiAgICAgICAgaWYgKG1hcmtlcklEKSB7XG4gICAgICAgICAgdmFyIGZvdW5kID0gY20uZmluZE1hcmtzKFBvcyhmcm9tTGluZSwgMCksIFBvcyh0b0xpbmUgKyAxLCAwKSwgcmVjb2duaXplTWFya2VyKCttYXJrZXJJRCkpO1xuICAgICAgICAgIGlmIChmb3VuZC5sZW5ndGggJiYgKHJhbmdlID0gZm91bmRbMF0uZmluZCgpKSlcbiAgICAgICAgICAgIHRleHQgKz0gZ2V0QmV0d2VlbihjbS5kb2MsIHJhbmdlLmZyb20sIHJhbmdlLnRvKS5qb2luKGxpbmVTZXApO
234591xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoXCJjb250ZW50ZWRpdGFibGVcIikgPT0gXCJmYWxzZVwiKSByZXR1cm47XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKVxuICAgICAgICAgIHdhbGsobm9kZS5jaGlsZE5vZGVzW2ldKTtcbiAgICAgICAgaWYgKC9eKHByZXxkaXZ8cCkkL2kudGVzdChub2RlLm5vZGVOYW1lKSlcbiAgICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAobm9kZS5ub2RlVHlwZSA9PSAzKSB7XG4gICAgICAgIHZhciB2YWwgPSBub2RlLm5vZGVWYWx1ZTtcbiAgICAgICAgaWYgKCF2YWwpIHJldHVybjtcbiAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICB0ZXh0ICs9IGxpbmVTZXA7XG4gICAgICAgICAgY2xvc2luZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRleHQgKz0gdmFsO1xuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKDs7KSB7XG4gICAgICB3YWxrKGZyb20pO1xuICAgICAgaWYgKGZyb20gPT0gdG8pIGJyZWFrO1xuICAgICAgZnJvbSA9IGZyb20ubmV4dFNpYmxpbmc7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgQ29kZU1pcnJvci5pbnB1dFN0eWxlcyA9IHtcInRleHRhcmVhXCI6IFRleHRhcmVhSW5wdXQsIFwiY29udGVudGVkaXRhYmxlXCI6IENvbnRlbnRFZGl0YWJsZUlucHV0fTtcblxuICAvLyBTRUxFQ1RJT04gLyBDVVJTT1JcblxuICAvLyBTZWxlY3Rpb24gb2JqZWN0cyBhcmUgaW1tdXRhYmxlLiBBIG5ldyBvbmUgaXMgY3JlYXRlZCBldmVyeSB0aW1lXG4gIC8vIHRoZSBzZWxlY3Rpb24gY2hhbmdlcy4gQSBzZWxlY3Rpb24gaXMgb25lIG9yIG1vcmUgbm9uLW92ZXJsYXBwaW5nXG4gIC8vIChhbmQgbm9uLXRvdWNoaW5nKSByYW5nZXMsIHNvcnRlZCwgYW5kIGFuIGludGVnZXIgdGhhdCBpbmRpY2F0ZXNcbiAgLy8gd2hpY2ggb25lIGlzIHRoZSBwcmltYXJ5IHNlbGVjdGlvbiAodGhlIG9uZSB0aGF0J3Mgc2Nyb2xsZWQgaW50b1xuICAvLyB2aWV3LCB0aGF0IGdldEN1cnNvciByZXR1cm5zLCBldGMpLlxuICBmdW5jdGlvbiBTZWxlY3Rpb24ocmFuZ2VzLCBwcmltSW5kZXgpIHtcbiAgICB0aGlzLnJhbmdlcyA9IHJhbmdlcztcbiAgICB0aGlzLnByaW1JbmRleCA9IHByaW1JbmRleDtcbiAgfVxuXG4gIFNlbGVjdGlvbi5wcm90b3R5cGUgPSB7XG4gICAgcHJpbWFyeTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnJhbmdlc1t0aGlzLnByaW1JbmRleF07IH0sXG4gICAgZXF1YWxzOiBmdW5jdGlvbihvdGhlcikge1xuICAgICAgaWYgKG90aGVyID09IHRoaXMpIHJldHVybiB0cnVlO1xuICAgICAgaWYgKG90aGVyLnByaW1JbmRleCAhPSB0aGlzLnByaW1JbmRleCB8fCBvdGhlci5yYW5nZXMubGVuZ3RoICE9IHRoaXMucmFuZ2VzLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2Y
23459XIgaGVyZSA9IHRoaXMucmFuZ2VzW2ldLCB0aGVyZSA9IG90aGVyLnJhbmdlc1tpXTtcbiAgICAgICAgaWYgKGNtcChoZXJlLmFuY2hvciwgdGhlcmUuYW5jaG9yKSAhPSAwIHx8IGNtcChoZXJlLmhlYWQsIHRoZXJlLmhlYWQpICE9IDApIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgZGVlcENvcHk6IGZ1bmN0aW9uKCkge1xuICAgICAgZm9yICh2YXIgb3V0ID0gW10sIGkgPSAwOyBpIDwgdGhpcy5yYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICAgIG91dFtpXSA9IG5ldyBSYW5nZShjb3B5UG9zKHRoaXMucmFuZ2VzW2ldLmFuY2hvciksIGNvcHlQb3ModGhpcy5yYW5nZXNbaV0uaGVhZCkpO1xuICAgICAgcmV0dXJuIG5ldyBTZWxlY3Rpb24ob3V0LCB0aGlzLnByaW1JbmRleCk7XG4gICAgfSxcbiAgICBzb21ldGhpbmdTZWxlY3RlZDogZnVuY3Rpb24oKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucmFuZ2VzLmxlbmd0aDsgaSsrKVxuICAgICAgICBpZiAoIXRoaXMucmFuZ2VzW2ldLmVtcHR5KCkpIHJldHVybiB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgY29udGFpbnM6IGZ1bmN0aW9uKHBvcywgZW5kKSB7XG4gICAgICBpZiAoIWVuZCkgZW5kID0gcG9zO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmFuZ2UgPSB0aGlzLnJhbmdlc1tpXTtcbiAgICAgICAgaWYgKGNtcChlbmQsIHJhbmdlLmZyb20oKSkgPj0gMCAmJiBjbXAocG9zLCByYW5nZS50bygpKSA8PSAwKVxuICAgICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBSYW5nZShhbmNob3IsIGhlYWQpIHtcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjsgdGhpcy5oZWFkID0gaGVhZDtcbiAgfVxuXG4gIFJhbmdlLnByb3RvdHlwZSA9IHtcbiAgICBmcm9tOiBmdW5jdGlvbigpIHsgcmV0dXJuIG1pblBvcyh0aGlzLmFuY2hvciwgdGhpcy5oZWFkKTsgfSxcbiAgICB0bzogZnVuY3Rpb24oKSB7IHJldHVybiBtYXhQb3ModGhpcy5hbmNob3IsIHRoaXMuaGVhZCk7IH0sXG4gICAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuaGVhZC5saW5lID09IHRoaXMuYW5jaG9yLmxpbmUgJiYgdGhpcy5oZWFkLmNoID09IHRoaXMuYW5jaG9yLmNoO1xuICAgIH1cbiAgfTtcblxuICAvLyBUYWtlIGFuIHVuc29ydGVkLCBwb3RlbnRpYWxseSBvdmVybGFwcGluZyBzZXQgb2YgcmFuZ2VzLCBhbmRcbiAgLy8gYnVpbGQgYSBzZWxlY3Rpb24gb3V0IG9mIGl0LiAnQ29uc3VtZXMnIHJhbmdlcyBhcnJheSAobW9kaWZ5aW5nXG4gIC8vIGl0KS5cbiAgZnVuY3Rpb24gbm9ybWFsaXplU2VsZWN0aW9uKHJhbmdlcywgcHJpbUluZGV4KSB7XG4gICAgdmFyIHByaW0gPSByYW5nZXNbcHJpbUluZGV4XTtcbiAgICByYW5nZXMuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBjbXAoYS5mcm9tKCksIGIuZnJvbSgpKTsgfSk7XG4gICAgcHJpbUluZGV4ID0gaW5kZXhPZihyYW5nZXMsIHByaW0pO1xuICAgIGZvciAodmFyIGkgPSAxOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgY3VyID0gcmFuZ2VzW2ldLCBwcmV2ID0gcmFuZ2VzW2kgLSAxXTtcbiAgICAgIGlmIChjbXAocHJldi50bygpLCBjdXIuZnJvbSgpKSA+PSAwKSB7XG4gICAgICAgIHZhciBmcm9tID0gbWluUG9zKHByZXYuZnJvbSgpLCBjdXIuZnJvbSgpKSwgdG8gPSBtYXhQb3MocHJldi50bygpLCBjdXIudG8oKSk7XG4gICAgICAgIHZhciBpbnYgPSBwcmV2LmVtcHR5KCkgPyBjdXIuZnJvbSgpID09IGN1ci5oZWFkIDogcHJldi5mcm9tKCkgPT0gcHJldi5oZWFkO1xuICAgICAgICBpZiAoaSA8PSBwcmltSW5kZXgpIC0tcHJpbUluZGV4O1xuICAgICAgICByYW5nZXMuc3BsaWNlKC0taSwgMiwgbmV3IFJhbmdlKGludiA/IHRvIDogZnJvbSwgaW52ID8gZnJvbSA6IHRvKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgU2VsZWN0aW9uKHJhbmdlcywgcHJpbUluZGV4KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNpbXBsZVNlbGVjdGlvbihhbmNob3IsIGhlYWQpIHtcbiAgICByZXR1cm4gbmV3IFNlbGVjdGlvbihbbmV3IFJhbmdlKGFuY2hvciwgaGVhZCB8fCBhbmNob3IpXSwgMCk7XG4gIH1cblxuICAvLyBNb3N0IG9mIHRoZSBleHRlcm5hbCBBUEkgY2xpcHMgZ2l2ZW4gcG9zaXRpb25zIHRvIG1ha2Ugc3VyZSB0aGV5XG4gIC8vIGFjdHVhbGx5IGV4aXN0IHdpdGhpbiB0aGUgZG9jdW1lbnQuXG4gIGZ1bmN0aW9uIGNsaXBMaW5lKGRvYywgbikge3JldHVybiBNYXRoLm1heChkb2MuZmlyc3QsIE1hdGgubWluKG4sIGRvYy5maXJzdCArIGRvYy5zaXplIC0gMSkpO31cbiAgZnVuY3Rpb24gY2xpcFBvcyhkb2MsIHBvcykge1xuICAgIGlmIChwb3MubGluZSA8IGRvYy5maXJzdCkgcmV0dXJuIFBvcyhkb2MuZmlyc3QsIDApO1xuICAgIHZhciBsYXN0ID0gZG9jLmZpcnN0ICsgZG9jLnNpemUgLSAxO1xuICAgIGlmIChwb3MubGluZSA+IGxhc3QpIHJldHVybiBQb3MobGFzdCwgZ2V0TGluZShkb2MsIGxhc3QpLnRleHQubGVuZ3RoKTtcbiAgICByZXR1cm4gY2xpcFRvTGVuKHBvcywgZ2V0TGluZShkb2MsIHBvcy5saW5lKS50ZXh0Lmxlbmd0aCk7XG4gIH1cbiAgZnVuY3Rpb24gY2xpcFRvTGVuKHBvcywgbGluZWxlbikge1xuICAgIHZhciBjaCA9IHBvcy5jaDtcbiAgICBpZiAoY2ggPT0gbnVsbCB8fCBjaCA+IGxpbmVsZW4pIHJldHVybiBQb3MocG9zLmxpbmUsIGxpbmVsZW4pO1xuICAgIGVsc2UgaWYgKGNoIDwgMCkgcmV0dXJuIFBvcyhwb3MubGluZSwgMCk7XG4gICAgZWxzZSByZXR1cm4gcG9zO1xuICB9XG4gIGZ1bmN0aW9uIGlzTGluZShkb2MsIGwpIHtyZXR1cm4gbCA+PSBkb2MuZmlyc3QgJiYgbCA8IGRvYy5maXJzdCArIGRvYy5zaXplO31cbiAgZnVuY3Rpb24gY2xpcFBvc0FycmF5KGRvYywgYXJyYXkpIHtcbiAgICBmb3IgKHZhciBvdXQgPSBbXSwgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykgb3V0W2ldID0gY2xpcFBvcyhkb2MsIGFycmF5W2ldKTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLy8gU0VMRUNUSU9OIFVQREFURVNcblxuICAvLyBUaGUgJ3Njcm9sbCcgcGFyYW1ldGVyIGdpdmVuIHRvIG1hbnkgb2YgdGhlc2UgaW5kaWNhdGVkIHdoZXRoZXJcbiAgLy8gdGhlIG5ldyBjdXJzb3IgcG9zaXRpb24gc2hvdWxkIGJlIHNjcm9sbGVkIGludG8gdmlldyBhZnRlclxuICAvLyBtb2RpZnlpbmcgdGhlIHNlbGVjdGlvbi5cblxuICAvLyBJZiBzaGlmdCBpcyBoZWxkIG9yIHRoZSBleHRlbmQgZmxhZyBpcyBzZXQsIGV4dGVuZHMgYSByYW5nZSB0b1xuICAvLyBpbmNsdWRlIGEgZ2l2ZW4gcG9zaXRpb24gKGFuZCBvcHRpb25hbGx5IGEgc2Vjb25kIHBvc2l0aW9uKS5cbiAgLy8gT3RoZXJ3aXNlLCBzaW1wbHkgcmV0dXJucyB0aGUgcmFuZ2UgYmV0d2VlbiB0aGUgZ2l2ZW4gcG9zaXRpb25zLlxuICAvLyBVc2VkIGZvciBjdXJzb3IgbW90aW9uIGFuZCBzdWNoLlxuICBmdW5jdGlvbiBleHRlbmRSYW5nZShkb2MsIHJhbmdlLCBoZWFkLCBvdGhlcikge1xuICAgIGlmIChkb2MuY20gJiYgZG9jLmNtLmRpc3BsYXkuc2hpZnQgfHwgZG9jLmV4dGVuZCkge1xuICAgICAgdmFyIGFuY2hvciA9IHJhbmdlLmFuY2hvcjtcbiAgICAgIGlmIChvdGhlcikge1xuICAgICAgICB2Y
23459XIgcG9zQmVmb3JlID0gY21wKGhlYWQsIGFuY2hvcikgPCAwO1xuICAgICAgICBpZiAocG9zQmVmb3JlICE9IChjbXAob3RoZXIsIGFuY2hvcikgPCAwKSkge1xuICAgICAgICAgIGFuY2hvciA9IGhlYWQ7XG4gICAgICAgICAgaGVhZCA9IG90aGVyO1xuICAgICAgICB9IGVsc2UgaWYgKHBvc0JlZm9yZSAhPSAoY21wKGhlYWQsIG90aGVyKSA8IDApKSB7XG4gICAgICAgICAgaGVhZCA9IG90aGVyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJhbmdlKGFuY2hvciwgaGVhZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgUmFuZ2Uob3RoZXIgfHwgaGVhZCwgaGVhZCk7XG4gICAgfVxuICB9XG5cbiAgLy8gRXh0ZW5kIHRoZSBwcmltYXJ5IHNlbGVjdGlvbiByYW5nZSwgZGlzY2FyZCB0aGUgcmVzdC5cbiAgZnVuY3Rpb24gZXh0ZW5kU2VsZWN0aW9uKGRvYywgaGVhZCwgb3RoZXIsIG9wdGlvbnMpIHtcbiAgICBzZXRTZWxlY3Rpb24oZG9jLCBuZXcgU2VsZWN0aW9uKFtleHRlbmRSYW5nZShkb2MsIGRvYy5zZWwucHJpbWFyeSgpLCBoZWFkLCBvdGhlcildLCAwKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvLyBFeHRlbmQgYWxsIHNlbGVjdGlvbnMgKHBvcyBpcyBhbiBhcnJheSBvZiBzZWxlY3Rpb25zIHdpdGggbGVuZ3RoXG4gIC8vIGVxdWFsIHRoZSBudW1iZXIgb2Ygc2VsZWN0aW9ucylcbiAgZnVuY3Rpb24gZXh0ZW5kU2VsZWN0aW9ucyhkb2MsIGhlYWRzLCBvcHRpb25zKSB7XG4gICAgZm9yICh2YXIgb3V0ID0gW10sIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICBvdXRbaV0gPSBleHRlbmRSYW5nZShkb2MsIGRvYy5zZWwucmFuZ2VzW2ldLCBoZWFkc1tpXSwgbnVsbCk7XG4gICAgdmFyIG5ld1NlbCA9IG5vcm1hbGl6ZVNlbGVjdGlvbihvdXQsIGRvYy5zZWwucHJpbUluZGV4KTtcbiAgICBzZXRTZWxlY3Rpb24oZG9jLCBuZXdTZWwsIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gVXBkYXRlcyBhIHNpbmdsZSByYW5nZSBpbiB0aGUgc2VsZWN0aW9uLlxuICBmdW5jdGlvbiByZXBsYWNlT25lU2VsZWN0aW9uKGRvYywgaSwgcmFuZ2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgcmFuZ2VzID0gZG9jLnNlbC5yYW5nZXMuc2xpY2UoMCk7XG4gICAgcmFuZ2VzW2ldID0gcmFuZ2U7XG4gICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKHJhbmdlcywgZG9jLnNlbC5wcmltSW5kZXgpLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8vIFJlc2V0IHRoZSBzZWxlY3Rpb24gdG8gYSBzaW5nbGUgcmFuZ2UuXG4gIGZ1bmN0aW9uIHNldFNpbXBsZVNlbGVjdGlvbihkb2MsIGFuY2hvciwgaGVhZCwgb3B0aW9ucykge1xuICAgIHNldFNlbGVjdGlvbihkb2MsIHNpbXBsZVNlbGVjdGlvbihhbmNob3IsIGhlYWQpLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8vIEdpdmUgYmVmb3JlU2VsZWN0aW9uQ2hhbmdlIGhhbmRsZXJzIGEgY2hhbmdlIHRvIGluZmx1ZW5jZSBhXG4gIC8vIHNlbGVjdGlvbiB1cGRhdGUuXG4gIGZ1bmN0aW9uIGZpbHRlclNlbGVjdGlvbkNoYW5nZShkb2MsIHNlbCkge1xuICAgIHZhciBvYmogPSB7XG4gICAgICByYW5nZXM6IHNlbC5yYW5nZXMsXG4gICAgICB1cGRhdGU6IGZ1bmN0aW9uKHJhbmdlcykge1xuICAgICAgICB0aGlzLnJhbmdlcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKylcbiAgICAgICAgICB0aGlzLnJhbmdlc1tpXSA9IG5ldyBSYW5nZShjbGlwUG9zKGRvYywgcmFuZ2VzW2ldLmFuY2hvciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcFBvcyhkb2MsIHJhbmdlc1tpXS5oZWFkKSk7XG4gICAgICB9XG4gICAgfTtcbiAgICBzaWduYWwoZG9jLCBcImJlZm9yZVNlbGVjdGlvbkNoYW5nZVwiLCBkb2MsIG9iaik7XG4gICAgaWYgKGRvYy5jbSkgc2lnbmFsKGRvYy5jbSwgXCJiZWZvcmVTZWxlY3Rpb25DaGFuZ2VcIiwgZG9jLmNtLCBvYmopO1xuICAgIGlmIChvYmoucmFuZ2VzICE9IHNlbC5yYW5nZXMpIHJldHVybiBub3JtYWxpemVTZWxlY3Rpb24ob2JqLnJhbmdlcywgb2JqLnJhbmdlcy5sZW5ndGggLSAxKTtcbiAgICBlbHNlIHJldHVybiBzZWw7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb25SZXBsYWNlSGlzdG9yeShkb2MsIHNlbCwgb3B0aW9ucykge1xuICAgIHZhciBkb25lID0gZG9jLmhpc3RvcnkuZG9uZSwgbGFzdCA9IGxzdChkb25lKTtcbiAgICBpZiAobGFzdCAmJiBsYXN0LnJhbmdlcykge1xuICAgICAgZG9uZVtkb25lLmxlbmd0aCAtIDFdID0gc2VsO1xuICAgICAgc2V0U2VsZWN0aW9uTm9VbmRvKGRvYywgc2VsLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2V0U2VsZWN0aW9uKGRvYywgc2VsLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvLyBTZXQgYSBuZXcgc2VsZWN0aW9uLlxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb24oZG9jLCBzZWwsIG9wdGlvbnMpIHtcbiAgICBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWwsIG9wdGlvbnMpO1xuICAgIGFkZFNlbGVjdGlvblRvSGlzdG9yeShkb2MsIGRvYy5zZWwsIGRvYy5jbSA/IGRvYy5jbS5jdXJPcC5pZCA6IE5hTiwgb3B0aW9ucyk7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWwsIG9wdGlvbnMpIHtcbiAgICBpZiAoaGFzSGFuZGxlcihkb2MsIFwiYmVmb3JlU2VsZWN0aW9uQ2hhbmdlXCIpIHx8IGRvYy5jbSAmJiBoYXNIYW5kbGVyKGRvYy5jbSwgXCJiZWZvcmVTZWxlY3Rpb25DaGFuZ2VcIikpXG4gICAgICBzZWwgPSBmaWx0ZXJTZWxlY3Rpb25DaGFuZ2UoZG9jLCBzZWwpO1xuXG4gICAgdmFyIGJpYXMgP
23459SBvcHRpb25zICYmIG9wdGlvbnMuYmlhcyB8fFxuICAgICAgKGNtcChzZWwucHJpbWFyeSgpLmhlYWQsIGRvYy5zZWwucHJpbWFyeSgpLmhlYWQpIDwgMCA/IC0xIDogMSk7XG4gICAgc2V0U2VsZWN0aW9uSW5uZXIoZG9jLCBza2lwQXRvbWljSW5TZWxlY3Rpb24oZG9jLCBzZWwsIGJpYXMsIHRydWUpKTtcblxuICAgIGlmICghKG9wdGlvbnMgJiYgb3B0aW9ucy5zY3JvbGwgPT09IGZhbHNlKSAmJiBkb2MuY20pXG4gICAgICBlbnN1cmVDdXJzb3JWaXNpYmxlKGRvYy5jbSk7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRTZWxlY3Rpb25Jbm5lcihkb2MsIHNlbCkge1xuICAgIGlmIChzZWwuZXF1YWxzKGRvYy5zZWwpKSByZXR1cm47XG5cbiAgICBkb2Muc2VsID0gc2VsO1xuXG4gICAgaWYgKGRvYy5jbSkge1xuICAgICAgZG9jLmNtLmN1ck9wLnVwZGF0ZUlucHV0ID0gZG9jLmNtLmN1ck9wLnNlbGVjdGlvbkNoYW5nZWQgPSB0cnVlO1xuICAgICAgc2lnbmFsQ3Vyc29yQWN0aXZpdHkoZG9jLmNtKTtcbiAgICB9XG4gICAgc2lnbmFsTGF0ZXIoZG9jLCBcImN1cnNvckFjdGl2aXR5XCIsIGRvYyk7XG4gIH1cblxuICAvLyBWZXJpZnkgdGhhdCB0aGUgc2VsZWN0aW9uIGRvZXMgbm90IHBhcnRpYWxseSBzZWxlY3QgYW55IGF0b21pY1xuICAvLyBtYXJrZWQgcmFuZ2VzLlxuICBmdW5jdGlvbiByZUNoZWNrU2VsZWN0aW9uKGRvYykge1xuICAgIHNldFNlbGVjdGlvbklubmVyKGRvYywgc2tpcEF0b21pY0luU2VsZWN0aW9uKGRvYywgZG9jLnNlbCwgbnVsbCwgZmFsc2UpLCBzZWxfZG9udFNjcm9sbCk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBzZWxlY3Rpb24gdGhhdCBkb2VzIG5vdCBwYXJ0aWFsbHkgc2VsZWN0IGFueSBhdG9taWNcbiAgLy8gcmFuZ2VzLlxuICBmdW5jdGlvbiBza2lwQXRvbWljSW5TZWxlY3Rpb24oZG9jLCBzZWwsIGJpYXMsIG1heUNsZWFyKSB7XG4gICAgdmFyIG91dDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbC5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IHNlbC5yYW5nZXNbaV07XG4gICAgICB2Y
23459XIgbmV3QW5jaG9yID0gc2tpcEF0b21pYyhkb2MsIHJhbmdlLmFuY2hvciwgYmlhcywgbWF5Q2xlYXIpO1xuICAgICAgdmFyIG5ld0hlYWQgPSBza2lwQXRvbWljKGRvYywgcmFuZ2UuaGVhZCwgYmlhcywgbWF5Q2xlYXIpO1xuICAgICAgaWYgKG91dCB8fCBuZXdBbmNob3IgIT0gcmFuZ2UuYW5jaG9yIHx8IG5ld0hlYWQgIT0gcmFuZ2UuaGVhZCkge1xuICAgICAgICBpZiAoIW91dCkgb3V0ID0gc2VsLnJhbmdlcy5zbGljZSgwLCBpKTtcbiAgICAgICAgb3V0W2ldID0gbmV3IFJhbmdlKG5ld0FuY2hvciwgbmV3SGVhZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXQgPyBub3JtYWxpemVTZWxlY3Rpb24ob3V0LCBzZWwucHJpbUluZGV4KSA6IHNlbDtcbiAgfVxuXG4gIC8vIEVuc3VyZSBhIGdpdmVuIHBvc2l0aW9uIGlzIG5vdCBpbnNpZGUgYW4gYXRvbWljIHJhbmdlLlxuICBmdW5jdGlvbiBza2lwQXRvbWljKGRvYywgcG9zLCBiaWFzLCBtYXlDbGVhcikge1xuICAgIHZhciBmbGlwcGVkID0gZmFsc2UsIGN1clBvcyA9IHBvcztcbiAgICB2YXIgZGlyID0gYmlhcyB8fCAxO1xuICAgIGRvYy5jYW50RWRpdCA9IGZhbHNlO1xuICAgIHNlYXJjaDogZm9yICg7Oykge1xuICAgICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgY3VyUG9zLmxpbmUpO1xuICAgICAgaWYgKGxpbmUubWFya2VkU3BhbnMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lLm1hcmtlZFNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgdmFyIHNwID0gbGluZS5tYXJrZWRTcGFuc1tpXSwgbSA9IHNwLm1hcmtlcjtcbiAgICAgICAgICBpZiAoKHNwLmZyb20gPT0gbnVsbCB8fCAobS5pbmNsdXNpdmVMZWZ0ID8gc3AuZnJvbSA8PSBjdXJQb3MuY2ggOiBzcC5mcm9tIDwgY3VyUG9zLmNoKSkgJiZcbiAgICAgICAgICAgICAgKHNwLnRvID09IG51bGwgfHwgKG0uaW5jbHVzaXZlUmlnaHQgPyBzcC50byA+PSBjdXJQb3MuY2ggOiBzcC50byA+IGN1clBvcy5jaCkpKSB7XG4gICAgICAgICAgICBpZiAobWF5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgc2lnbmFsKG0sIFwiYmVmb3JlQ3Vyc29yRW50ZXJcIik7XG4gICAgICAgICAgICAgIGlmIChtLmV4cGxpY2l0bHlDbGVhcmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsaW5lLm1hcmtlZFNwYW5zKSBicmVhaztcbiAgICAgICAgICAgICAgICBlbHNlIHstLWk7IGNvbnRpbnVlO31cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtLmF0b21pYykgY29udGludWU7XG4gICAgICAgICAgICB2Y
23459XIgbmV3UG9zID0gbS5maW5kKGRpciA8IDAgPyAtMSA6IDEpO1xuICAgICAgICAgICAgaWYgKGNtcChuZXdQb3MsIGN1clBvcykgPT0gMCkge1xuICAgICAgICAgICAgICBuZXdQb3MuY2ggKz0gZGlyO1xuICAgICAgICAgICAgICBpZiAobmV3UG9zLmNoIDwgMCkge1xuICAgICAgICAgICAgICAgIGlmIChuZXdQb3MubGluZSA+IGRvYy5maXJzdCkgbmV3UG9zID0gY2xpcFBvcyhkb2MsIFBvcyhuZXdQb3MubGluZSAtIDEpKTtcbiAgICAgICAgICAgICAgICBlbHNlIG5ld1BvcyA9IG51bGw7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobmV3UG9zLmNoID4gbGluZS50ZXh0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmIChuZXdQb3MubGluZSA8IGRvYy5maXJzdCArIGRvYy5zaXplIC0gMSkgbmV3UG9zID0gUG9zKG5ld1Bvcy5saW5lICsgMSwgMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBuZXdQb3MgPSBudWxsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmICghbmV3UG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZsaXBwZWQpIHtcbiAgICAgICAgICAgICAgICAgIC8vIERyaXZlbiBpbiBhIGNvcm5lciAtLSBubyB2YWxpZCBjdXJzb3IgcG9zaXRpb24gZm91bmQgYXQgYWxsXG4gICAgICAgICAgICAgICAgICAvLyAtLSB0cnkgYWdhaW4gKndpdGgqIGNsZWFyaW5nLCBpZiB3ZSBkaWRuJ3QgYWxyZWFkeVxuICAgICAgICAgICAgICAgICAgaWYgKCFtYXlDbGVhcikgcmV0dXJuIHNraXBBdG9taWMoZG9jLCBwb3MsIGJpYXMsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCB0dXJuIG9mZiBlZGl0aW5nIHVudGlsIGZ1cnRoZXIgbm90aWNlLCBhbmQgcmV0dXJuIHRoZSBzdGFydCBvZiB0aGUgZG9jXG4gICAgICAgICAgICAgICAgICBkb2MuY2FudEVkaXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIFBvcyhkb2MuZmlyc3QsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmbGlwcGVkID0gdHJ1ZTsgbmV3UG9zID0gcG9zOyBkaXIgPSAtZGlyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJQb3MgPSBuZXdQb3M7XG4gICAgICAgICAgICBjb250aW51ZSBzZWFyY2g7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gY3VyUG9zO1xuICAgIH1cbiAgfVxuXG4gIC8vIFNFTEVDVElPTiBEUkFXSU5HXG5cbiAgZnVuY3Rpb24gdXBkYXRlU2VsZWN0aW9uKGNtKSB7XG4gICAgY20uZGlzcGxheS5pbnB1dC5zaG93U2VsZWN0aW9uKGNtLmRpc3BsYXkuaW5wdXQucHJlcGFyZVNlbGVjdGlvbigpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHByZXBhcmVTZWxlY3Rpb24oY20sIHByaW1hcnkpIHtcbiAgICB2YXIgZG9jID0gY20uZG9jLCByZXN1bHQgPSB7fTtcbiAgICB2YXIgY3VyRnJhZ21lbnQgPSByZXN1bHQuY3Vyc29ycyA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICB2YXIgc2VsRnJhZ21lbnQgPSByZXN1bHQuc2VsZWN0aW9uID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkb2Muc2VsLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHByaW1hcnkgPT09IGZhbHNlICYmIGkgPT0gZG9jLnNlbC5wcmltSW5kZXgpIGNvbnRpbnVlO1xuICAgICAgdmFyIHJhbmdlID0gZG9jLnNlbC5yYW5nZXNbaV07XG4gICAgICB2Y
23459XIgY29sbGFwc2VkID0gcmFuZ2UuZW1wdHkoKTtcbiAgICAgIGlmIChjb2xsYXBzZWQgfHwgY20ub3B0aW9ucy5zaG93Q3Vyc29yV2hlblNlbGVjdGluZylcbiAgICAgICAgZHJhd1NlbGVjdGlvbkN1cnNvcihjbSwgcmFuZ2UuaGVhZCwgY3VyRnJhZ21lbnQpO1xuICAgICAgaWYgKCFjb2xsYXBzZWQpXG4gICAgICAgIGRyYXdTZWxlY3Rpb25SYW5nZShjbSwgcmFuZ2UsIHNlbEZyYWdtZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIERyYXdzIGEgY3Vyc29yIGZvciB0aGUgZ2l2ZW4gcmFuZ2VcbiAgZnVuY3Rpb24gZHJhd1NlbGVjdGlvbkN1cnNvcihjbSwgaGVhZCwgb3V0cHV0KSB7XG4gICAgdmFyIHBvcyA9IGN1cnNvckNvb3JkcyhjbSwgaGVhZCwgXCJkaXZcIiwgbnVsbCwgbnVsbCwgIWNtLm9wdGlvbnMuc2luZ2xlQ3Vyc29ySGVpZ2h0UGVyTGluZSk7XG5cbiAgICB2YXIgY3Vyc29yID0gb3V0cHV0LmFwcGVuZENoaWxkKGVsdChcImRpdlwiLCBcIlxcdTAwYTBcIiwgXCJDb2RlTWlycm9yLWN1cnNvclwiKSk7XG4gICAgY3Vyc29yLnN0eWxlLmxlZnQgPSBwb3MubGVmdCArIFwicHhcIjtcbiAgICBjdXJzb3Iuc3R5bGUudG9wID0gcG9zLnRvcCArIFwicHhcIjtcbiAgICBjdXJzb3Iuc3R5bGUuaGVpZ2h0ID0gTWF0aC5tYXgoMCwgcG9zLmJvdHRvbSAtIHBvcy50b3ApICogY20ub3B0aW9ucy5jdXJzb3JIZWlnaHQgKyBcInB4XCI7XG5cbiAgICBpZiAocG9zLm90aGVyKSB7XG4gICAgICAvLyBTZWNvbmRhcnkgY3Vyc29yLCBzaG93biB3aGVuIG9uIGEgJ2p1bXAnIGluIGJpLWRpcmVjdGlvbmFsIHRleHRcbiAgICAgIHZhciBvdGhlckN1cnNvciA9IG91dHB1dC5hcHBlbmRDaGlsZChlbHQoXCJkaXZcIiwgXCJcXHUwMGEwXCIsIFwiQ29kZU1pcnJvci1jdXJzb3IgQ29kZU1pcnJvci1zZWNvbmRhcnljdXJzb3JcIikpO1xuICAgICAgb3RoZXJDdXJzb3Iuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICBvdGhlckN1cnNvci5zdHlsZS5sZWZ0ID0gcG9zLm90aGVyLmxlZnQgKyBcInB4XCI7XG4gICAgICBvdGhlckN1cnNvci5zdHlsZS50b3AgPSBwb3Mub3RoZXIudG9wICsgXCJweFwiO1xuICAgICAgb3RoZXJDdXJzb3Iuc3R5bGUuaGVpZ2h0ID0gKHBvcy5vdGhlci5ib3R0b20gLSBwb3Mub3RoZXIudG9wKSAqIC44NSArIFwicHhcIjtcbiAgICB9XG4gIH1cblxuICAvLyBEcmF3cyB0aGUgZ2l2ZW4gcmFuZ2UgYXMgYSBoaWdobGlnaHRlZCBzZWxlY3Rpb25cbiAgZnVuY3Rpb24gZHJhd1NlbGVjdGlvblJhbmdlKGNtLCByYW5nZSwgb3V0cHV0KSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBkb2MgPSBjbS5kb2M7XG4gICAgdmFyIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgIHZhciBwYWRkaW5nID0gcGFkZGluZ0goY20uZGlzcGxheSksIGxlZnRTaWRlID0gcGFkZGluZy5sZWZ0O1xuICAgIHZhciByaWdodFNpZGUgPSBNYXRoLm1heChkaXNwbGF5LnNpemVyV2lkdGgsIGRpc3BsYXlXaWR0aChjbSkgLSBkaXNwbGF5LnNpemVyLm9mZnNldExlZnQpIC0gcGFkZGluZy5yaWdodDtcblxuICAgIGZ1bmN0aW9uIGFkZChsZWZ0LCB0b3AsIHdpZHRoLCBib3R0b20pIHtcbiAgICAgIGlmICh0b3AgPCAwKSB0b3AgPSAwO1xuICAgICAgdG9wID0gTWF0aC5yb3VuZCh0b3ApO1xuICAgICAgYm90dG9tID0gTWF0aC5yb3VuZChib3R0b20pO1xuICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoZWx0KFwiZGl2XCIsIG51bGwsIFwiQ29kZU1pcnJvci1zZWxlY3RlZFwiLCBcInBvc2l0aW9uOiBhYnNvbHV0ZTsgbGVmdDogXCIgKyBsZWZ0ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInB4OyB0b3A6IFwiICsgdG9wICsgXCJweDsgd2lkdGg6IFwiICsgKHdpZHRoID09IG51bGwgPyByaWdodFNpZGUgLSBsZWZ0IDogd2lkdGgpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInB4OyBoZWlnaHQ6IFwiICsgKGJvdHRvbSAtIHRvcCkgKyBcInB4XCIpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3Rm9yTGluZShsaW5lLCBmcm9tQXJnLCB0b0FyZykge1xuICAgICAgdmFyIGxpbmVPYmogPSBnZXRMaW5lKGRvYywgbGluZSk7XG4gICAgICB2Y
23459XIgbGluZUxlbiA9IGxpbmVPYmoudGV4dC5sZW5ndGg7XG4gICAgICB2YXIgc3RhcnQsIGVuZDtcbiAgICAgIGZ1bmN0aW9uIGNvb3JkcyhjaCwgYmlhcykge1xuICAgICAgICByZXR1cm4gY2hhckNvb3JkcyhjbSwgUG9zKGxpbmUsIGNoKSwgXCJkaXZcIiwgbGluZU9iaiwgYmlhcyk7XG4gICAgICB9XG5cbiAgICAgIGl0ZXJhdGVCaWRpU2VjdGlvbnMoZ2V0T3JkZXIobGluZU9iaiksIGZyb21BcmcgfHwgMCwgdG9BcmcgPT0gbnVsbCA/IGxpbmVMZW4gOiB0b0FyZywgZnVuY3Rpb24oZnJvbSwgdG8sIGRpcikge1xuICAgICAgICB2YXIgbGVmdFBvcyA9IGNvb3Jkcyhmcm9tLCBcImxlZnRcIiksIHJpZ2h0UG9zLCBsZWZ0LCByaWdodDtcbiAgICAgICAgaWYgKGZyb20gPT0gdG8pIHtcbiAgICAgICAgICByaWdodFBvcyA9IGxlZnRQb3M7XG4gICAgICAgICAgbGVmdCA9IHJpZ2h0ID0gbGVmdFBvcy5sZWZ0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJpZ2h0UG9zID0gY29vcmRzKHRvIC0gMSwgXCJyaWdodFwiKTtcbiAgICAgICAgICBpZiAoZGlyID09IFwicnRsXCIpIHsgdmFyIHRtcCA9IGxlZnRQb3M7IGxlZnRQb3MgPSByaWdodFBvczsgcmlnaHRQb3MgPSB0bXA7IH1cbiAgICAgICAgICBsZWZ0ID0gbGVmdFBvcy5sZWZ0O1xuICAgICAgICAgIHJpZ2h0ID0gcmlnaHRQb3MucmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZyb21BcmcgPT0gbnVsbCAmJiBmcm9tID09IDApIGxlZnQgPSBsZWZ0U2lkZTtcbiAgICAgICAgaWYgKHJpZ2h0UG9zLnRvcCAtIGxlZnRQb3MudG9wID4gMykgeyAvLyBEaWZmZXJlbnQgbGluZXMsIGRyYXcgdG9wIHBhcnRcbiAgICAgICAgICBhZGQobGVmdCwgbGVmdFBvcy50b3AsIG51bGwsIGxlZnRQb3MuYm90dG9tKTtcbiAgICAgICAgICBsZWZ0ID0gbGVmdFNpZGU7XG4gICAgICAgICAgaWYgKGxlZnRQb3MuYm90dG9tIDwgcmlnaHRQb3MudG9wKSBhZGQobGVmdCwgbGVmdFBvcy5ib3R0b20sIG51bGwsIHJpZ2h0UG9zLnRvcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRvQXJnID09IG51bGwgJiYgdG8gPT0gbGluZUxlbikgcmlnaHQgPSByaWdodFNpZGU7XG4gICAgICAgIGlmICghc3RhcnQgfHwgbGVmdFBvcy50b3AgPCBzdGFydC50b3AgfHwgbGVmdFBvcy50b3AgPT0gc3RhcnQudG9wICYmIGxlZnRQb3MubGVmdCA8IHN0YXJ0LmxlZnQpXG4gICAgICAgICAgc3RhcnQgPSBsZWZ0UG9zO1xuICAgICAgICBpZiAoIWVuZCB8fCByaWdodFBvcy5ib3R0b20gPiBlbmQuYm90dG9tIHx8IHJpZ2h0UG9zLmJvdHRvbSA9PSBlbmQuYm90dG9tICYmIHJpZ2h0UG9zLnJpZ2h0ID4gZW5kLnJpZ2h0KVxuICAgICAgICAgIGVuZCA9IHJpZ2h0UG9zO1xuICAgICAgICBpZiAobGVmdCA8IGxlZnRTaWRlICsgMSkgbGVmdCA9IGxlZnRTaWRlO1xuICAgICAgICBhZGQobGVmdCwgcmlnaHRQb3MudG9wLCByaWdodCAtIGxlZnQsIHJpZ2h0UG9zLmJvdHRvbSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7c3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZH07XG4gICAgfVxuXG4gICAgdmFyIHNGcm9tID0gcmFuZ2UuZnJvbSgpLCBzVG8gPSByYW5nZS50bygpO1xuICAgIGlmIChzRnJvbS5saW5lID09IHNUby5saW5lKSB7XG4gICAgICBkcmF3Rm9yTGluZShzRnJvbS5saW5lLCBzRnJvbS5jaCwgc1RvLmNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGZyb21MaW5lID0gZ2V0TGluZShkb2MsIHNGcm9tLmxpbmUpLCB0b0xpbmUgPSBnZXRMaW5lKGRvYywgc1RvLmxpbmUpO1xuICAgICAgdmFyIHNpbmdsZVZMaW5lID0gdmlzdWFsTGluZShmcm9tTGluZSkgPT0gdmlzdWFsTGluZSh0b0xpbmUpO1xuICAgICAgdmFyIGxlZnRFbmQgPSBkcmF3Rm9yTGluZShzRnJvbS5saW5lLCBzRnJvbS5jaCwgc2luZ2xlVkxpbmUgPyBmcm9tTGluZS50ZXh0Lmxlbmd0aCArIDEgOiBudWxsKS5lbmQ7XG4gICAgICB2Y
23459XIgcmlnaHRTdGFydCA9IGRyYXdGb3JMaW5lKHNUby5saW5lLCBzaW5nbGVWTGluZSA/IDAgOiBudWxsLCBzVG8uY2gpLnN0YXJ0O1xuICAgICAgaWYgKHNpbmdsZVZMaW5lKSB7XG4gICAgICAgIGlmIChsZWZ0RW5kLnRvcCA8IHJpZ2h0U3RhcnQudG9wIC0gMikge1xuICAgICAgICAgIGFkZChsZWZ0RW5kLnJpZ2h0LCBsZWZ0RW5kLnRvcCwgbnVsbCwgbGVmdEVuZC5ib3R0b20pO1xuICAgICAgICAgIGFkZChsZWZ0U2lkZSwgcmlnaHRTdGFydC50b3AsIHJpZ2h0U3RhcnQubGVmdCwgcmlnaHRTdGFydC5ib3R0b20pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFkZChsZWZ0RW5kLnJpZ2h0LCBsZWZ0RW5kLnRvcCwgcmlnaHRTdGFydC5sZWZ0IC0gbGVmdEVuZC5yaWdodCwgbGVmdEVuZC5ib3R0b20pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobGVmdEVuZC5ib3R0b20gPCByaWdodFN0YXJ0LnRvcClcbiAgICAgICAgYWRkKGxlZnRTaWRlLCBsZWZ0RW5kLmJvdHRvbSwgbnVsbCwgcmlnaHRTdGFydC50b3ApO1xuICAgIH1cblxuICAgIG91dHB1dC5hcHBlbmRDaGlsZChmcmFnbWVudCk7XG4gIH1cblxuICAvLyBDdXJzb3ItYmxpbmtpbmdcbiAgZnVuY3Rpb24gcmVzdGFydEJsaW5rKGNtKSB7XG4gICAgaWYgKCFjbS5zdGF0ZS5mb2N1c2VkKSByZXR1cm47XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIGNsZWFySW50ZXJ2YWwoZGlzcGxheS5ibGlua2VyKTtcbiAgICB2YXIgb24gPSB0cnVlO1xuICAgIGRpc3BsYXkuY3Vyc29yRGl2LnN0eWxlLnZpc2liaWxpdHkgPSBcIlwiO1xuICAgIGlmIChjbS5vcHRpb25zLmN1cnNvckJsaW5rUmF0ZSA+IDApXG4gICAgICBkaXNwbGF5LmJsaW5rZXIgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcbiAgICAgICAgZGlzcGxheS5jdXJzb3JEaXYuc3R5bGUudmlzaWJpbGl0eSA9IChvbiA9ICFvbikgPyBcIlwiIDogXCJoaWRkZW5cIjtcbiAgICAgIH0sIGNtLm9wdGlvbnMuY3Vyc29yQmxpbmtSYXRlKTtcbiAgICBlbHNlIGlmIChjbS5vcHRpb25zLmN1cnNvckJsaW5rUmF0ZSA8IDApXG4gICAgICBkaXNwbGF5LmN1cnNvckRpdi5zdHlsZS52aXNpYmlsaXR5ID0gXCJoaWRkZW5cIjtcbiAgfVxuXG4gIC8vIEhJR0hMSUdIVCBXT1JLRVJcblxuICBmdW5jdGlvbiBzdGFydFdvcmtlcihjbSwgdGltZSkge1xuICAgIGlmIChjbS5kb2MubW9kZS5zdGFydFN0YXRlICYmIGNtLmRvYy5mcm9udGllciA8IGNtLmRpc3BsYXkudmlld1RvKVxuICAgICAgY20uc3RhdGUuaGlnaGxpZ2h0LnNldCh0aW1lLCBiaW5kKGhpZ2hsaWdodFdvcmtlciwgY20pKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhpZ2hsaWdodFdvcmtlcihjbSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2M7XG4gICAgaWYgKGRvYy5mcm9udGllciA8IGRvYy5maXJzdCkgZG9jLmZyb250aWVyID0gZG9jLmZpcnN0O1xuICAgIGlmIChkb2MuZnJvbnRpZXIgPj0gY20uZGlzcGxheS52aWV3VG8pIHJldHVybjtcbiAgICB2YXIgZW5kID0gK25ldyBEYXRlICsgY20ub3B0aW9ucy53b3JrVGltZTtcbiAgICB2YXIgc3RhdGUgPSBjb3B5U3RhdGUoZG9jLm1vZGUsIGdldFN0YXRlQmVmb3JlKGNtLCBkb2MuZnJvbnRpZXIpKTtcbiAgICB2YXIgY2hhbmdlZExpbmVzID0gW107XG5cbiAgICBkb2MuaXRlcihkb2MuZnJvbnRpZXIsIE1hdGgubWluKGRvYy5maXJzdCArIGRvYy5zaXplLCBjbS5kaXNwbGF5LnZpZXdUbyArIDUwMCksIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIGlmIChkb2MuZnJvbnRpZXIgPj0gY20uZGlzcGxheS52aWV3RnJvbSkgeyAvLyBWaXNpYmxlXG4gICAgICAgIHZhciBvbGRTdHlsZXMgPSBsaW5lLnN0eWxlcywgdG9vTG9uZyA9IGxpbmUudGV4dC5sZW5ndGggPiBjbS5vcHRpb25zLm1heEhpZ2hsaWdodExlbmd0aDtcbiAgICAgICAgdmFyIGhpZ2hsaWdodGVkID0gaGlnaGxpZ2h0TGluZShjbSwgbGluZSwgdG9vTG9uZyA/IGNvcHlTdGF0ZShkb2MubW9kZSwgc3RhdGUpIDogc3RhdGUsIHRydWUpO1xuICAgICAgICBsaW5lLnN0eWxlcyA9IGhpZ2hsaWdodGVkLnN0eWxlcztcbiAgICAgICAgdmFyIG9sZENscyA9IGxpbmUuc3R5bGVDbGFzc2VzLCBuZXdDbHMgPSBoaWdobGlnaHRlZC5jbGFzc2VzO1xuICAgICAgICBpZiAobmV3Q2xzKSBsaW5lLnN0eWxlQ2xhc3NlcyA9IG5ld0NscztcbiAgICAgICAgZWxzZSBpZiAob2xkQ2xzKSBsaW5lLnN0eWxlQ2xhc3NlcyA9IG51bGw7XG4gICAgICAgIHZhciBpc2NoYW5nZSA9ICFvbGRTdHlsZXMgfHwgb2xkU3R5bGVzLmxlbmd0aCAhPSBsaW5lLnN0eWxlcy5sZW5ndGggfHxcbiAgICAgICAgICBvbGRDbHMgIT0gbmV3Q2xzICYmICghb2xkQ2xzIHx8ICFuZXdDbHMgfHwgb2xkQ2xzLmJnQ2xhc3MgIT0gbmV3Q2xzLmJnQ2xhc3MgfHwgb2xkQ2xzLnRleHRDbGFzcyAhPSBuZXdDbHMudGV4dENsYXNzKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7ICFpc2NoYW5nZSAmJiBpIDwgb2xkU3R5bGVzLmxlbmd0aDsgKytpKSBpc2NoYW5nZSA9IG9sZFN0eWxlc1tpXSAhPSBsaW5lLnN0eWxlc1tpXTtcbiAgICAgICAgaWYgKGlzY2hhbmdlKSBjaGFuZ2VkTGluZXMucHVzaChkb2MuZnJvbnRpZXIpO1xuICAgICAgICBsaW5lLnN0YXRlQWZ0ZXIgPSB0b29Mb25nID8gc3RhdGUgOiBjb3B5U3RhdGUoZG9jLm1vZGUsIHN0YXRlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsaW5lLnRleHQubGVuZ3RoIDw9IGNtLm9wdGlvbnMubWF4SGlnaGxpZ2h0TGVuZ3RoKVxuICAgICAgICAgIHByb2Nlc3NMaW5lKGNtLCBsaW5lLnRleHQsIHN0YXRlKTtcbiAgICAgICAgbGluZS5zdGF0ZUFmdGVyID0gZG9jLmZyb250aWVyICUgNSA9PSAwID8gY29weVN0YXRl
23459KGRvYy5tb2RlLCBzdGF0ZSkgOiBudWxsO1xuICAgICAgfVxuICAgICAgKytkb2MuZnJvbnRpZXI7XG4gICAgICBpZiAoK25ldyBEYXRlID4gZW5kKSB7XG4gICAgICAgIHN0YXJ0V29ya2VyKGNtLCBjbS5vcHRpb25zLndvcmtEZWxheSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChjaGFuZ2VkTGluZXMubGVuZ3RoKSBydW5Jbk9wKGNtLCBmdW5jdGlvbigpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlZExpbmVzLmxlbmd0aDsgaSsrKVxuICAgICAgICByZWdMaW5lQ2hhbmdlKGNtLCBjaGFuZ2VkTGluZXNbaV0sIFwidGV4dFwiKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEZpbmRzIHRoZSBsaW5lIHRvIHN0YXJ0IHdpdGggd2hlbiBzdGFydGluZyBhIHBhcnNlLiBUcmllcyB0b1xuICAvLyBmaW5kIGEgbGluZSB3aXRoIGEgc3RhdGVBZnRlciwgc28gdGhhdCBpdCBjYW4gc3RhcnQgd2l0aCBhXG4gIC8vIHZhbGlkIHN0YXRlLiBJZiB0aGF0IGZhaWxzLCBpdCByZXR1cm5zIHRoZSBsaW5lIHdpdGggdGhlXG4gIC8vIHNtYWxsZXN0IGluZGVudGF0aW9uLCB3aGljaCB0ZW5kcyB0byBuZWVkIHRoZSBsZWFzdCBjb250ZXh0IHRvXG4gIC8vIHBhcnNlIGNvcnJlY3RseS5cbiAgZnVuY3Rpb24gZmluZFN0YXJ0TGluZShjbSwgbiwgcHJlY2lzZSkge1xuICAgIHZhciBtaW5pbmRlbnQsIG1pbmxpbmUsIGRvYyA9IGNtLmRvYztcbiAgICB2YXIgbGltID0gcHJlY2lzZSA/IC0xIDogbiAtIChjbS5kb2MubW9kZS5pbm5lck1vZGUgPyAxMDAwIDogMTAwKTtcbiAgICBmb3IgKHZhciBzZWFyY2ggPSBuOyBzZWFyY2ggPiBsaW07IC0tc2VhcmNoKSB7XG4gICAgICBpZiAoc2VhcmNoIDw9IGRvYy5maXJzdCkgcmV0dXJuIGRvYy5maXJzdDtcbiAgICAgIHZhciBsaW5lID0gZ2V0TGluZShkb2MsIHNlYXJjaCAtIDEpO1xuICAgICAgaWYgKGxpbmUuc3RhdGVBZnRlciAmJiAoIXByZWNpc2UgfHwgc2VhcmNoIDw9IGRvYy5mcm9udGllcikpIHJldHVybiBzZWFyY2g7XG4gICAgICB2Y
23459XIgaW5kZW50ZWQgPSBjb3VudENvbHVtbihsaW5lLnRleHQsIG51bGwsIGNtLm9wdGlvbnMudGFiU2l6ZSk7XG4gICAgICBpZiAobWlubGluZSA9PSBudWxsIHx8IG1pbmluZGVudCA+IGluZGVudGVkKSB7XG4gICAgICAgIG1pbmxpbmUgPSBzZWFyY2ggLSAxO1xuICAgICAgICBtaW5pbmRlbnQgPSBpbmRlbnRlZDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1pbmxpbmU7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTdGF0ZUJlZm9yZShjbSwgbiwgcHJlY2lzZSkge1xuICAgIHZhciBkb2MgPSBjbS5kb2MsIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIGlmICghZG9jLm1vZGUuc3RhcnRTdGF0ZSkgcmV0dXJuIHRydWU7XG4gICAgdmFyIHBvcyA9IGZpbmRTdGFydExpbmUoY20sIG4sIHByZWNpc2UpLCBzdGF0ZSA9IHBvcyA+IGRvYy5maXJzdCAmJiBnZXRMaW5lKGRvYywgcG9zLTEpLnN0YXRlQWZ0ZXI7XG4gICAgaWYgKCFzdGF0ZSkgc3RhdGUgPSBzdGFydFN0YXRlKGRvYy5tb2RlKTtcbiAgICBlbHNlIHN0YXRlID0gY29weVN0YXRlKGRvYy5tb2RlLCBzdGF0ZSk7XG4gICAgZG9jLml0ZXIocG9zLCBuLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICBwcm9jZXNzTGluZShjbSwgbGluZS50ZXh0LCBzdGF0ZSk7XG4gICAgICB2YXIgc2F2ZSA9IHBvcyA9PSBuIC0gMSB8fCBwb3MgJSA1ID09IDAgfHwgcG9zID49IGRpc3BsYXkudmlld0Zyb20gJiYgcG9zIDwgZGlzcGxheS52aWV3VG87XG4gICAgICBsaW5lLnN0YXRlQWZ0ZXIgPSBzYXZlID8gY29weVN0YXRlKGRvYy5tb2RlLCBzdGF0ZSkgOiBudWxsO1xuICAgICAgKytwb3M7XG4gICAgfSk7XG4gICAgaWYgKHByZWNpc2UpIGRvYy5mcm9udGllciA9IHBvcztcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvLyBQT1NJVElPTiBNRUFTVVJFTUVOVFxuXG4gIGZ1bmN0aW9uIHBhZGRpbmdUb3AoZGlzcGxheSkge3JldHVybiBkaXNwbGF5LmxpbmVTcGFjZS5vZmZzZXRUb3A7fVxuICBmdW5jdGlvbiBwYWRkaW5nVmVydChkaXNwbGF5KSB7cmV0dXJuIGRpc3BsYXkubW92ZXIub2Zmc2V0SGVpZ2h0IC0gZGlzcGxheS5saW5lU3BhY2Uub2Zmc2V0SGVpZ2h0O31cbiAgZnVuY3Rpb24gcGFkZGluZ0goZGlzcGxheSkge1xuICAgIGlmIChkaXNwbGF5LmNhY2hlZFBhZGRpbmdIKSByZXR1cm4gZGlzcGxheS5jYWNoZWRQYWRkaW5nSDtcbiAgICB2YXIgZSA9IHJlbW92ZUNoaWxkcmVuQW5kQWRkKGRpc3BsYXkubWVhc3VyZSwgZWx0KFwicHJlXCIsIFwieFwiKSk7XG4gICAgdmFyIHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUgPyB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlKSA6IGUuY3VycmVudFN0eWxlO1xuICAgIHZhciBkYXRhID0ge2xlZnQ6IHBhcnNlSW50KHN0eWxlLnBhZGRpbmdMZWZ0KSwgcmlnaHQ6IHBhcnNlSW50KHN0eWxlLnBhZGRpbmdSaWdodCl9O1xuICAgIGlmICghaXNOYU4oZGF0YS5sZWZ0KSAmJiAhaXNOYU4oZGF0YS5yaWdodCkpIGRpc3BsYXkuY2FjaGVkUGFkZGluZ0ggPSBkYXRhO1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgZnVuY3Rpb24gc2Nyb2xsR2FwKGNtKSB7IHJldHVybiBzY3JvbGxlckdhcCAtIGNtLmRpc3BsYXkubmF0aXZlQmFyV2lkdGg7IH1cbiAgZnVuY3Rpb24gZGlzcGxheVdpZHRoKGNtKSB7XG4gICAgcmV0dXJuIGNtLmRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50V2lkdGggLSBzY3JvbGxHYXAoY20pIC0gY20uZGlzcGxheS5iYXJXaWR0aDtcbiAgfVxuICBmdW5jdGlvbiBkaXNwbGF5SGVpZ2h0KGNtKSB7XG4gICAgcmV0dXJuIGNtLmRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50SGVpZ2h0IC0gc2Nyb2xsR2FwKGNtKSAtIGNtLmRpc3BsYXkuYmFySGVpZ2h0O1xuICB9XG5cbiAgLy8gRW5zdXJlIHRoZSBsaW5lVmlldy53cmFwcGluZy5oZWlnaHRzIGFycmF5IGlzIHBvcHVsYXRlZC4gVGhpcyBpc1xuICAvLyBhbiBhcnJheSBvZiBib3R0b20gb2Zmc2V0cyBmb3IgdGhlIGxpbmVzIHRoYXQgbWFrZSB1cCBhIGRyYXduXG4gIC8vIGxpbmUuIFdoZW4gbGluZVdyYXBwaW5nIGlzIG9uLCB0aGVyZSBtaWdodCBiZSBtb3JlIHRoYW4gb25lXG4gIC8vIGhlaWdodC5cbiAgZnVuY3Rpb24gZW5zdXJlTGluZUhlaWdodHMoY20sIGxpbmVWaWV3LCByZWN0KSB7XG4gICAgdmFyIHdyYXBwaW5nID0gY20ub3B0aW9ucy5saW5lV3JhcHBpbmc7XG4gICAgdmFyIGN1cldpZHRoID0gd3JhcHBpbmcgJiYgZGlzcGxheVdpZHRoKGNtKTtcbiAgICBpZiAoIWxpbmVWaWV3Lm1lYXN1cmUuaGVpZ2h0cyB8fCB3cmFwcGluZyAmJiBsaW5lVmlldy5tZWFzdXJlLndpZHRoICE9IGN1cldpZHRoKSB7XG4gICAgICB2Y
23459XIgaGVpZ2h0cyA9IGxpbmVWaWV3Lm1lYXN1cmUuaGVpZ2h0cyA9IFtdO1xuICAgICAgaWYgKHdyYXBwaW5nKSB7XG4gICAgICAgIGxpbmVWaWV3Lm1lYXN1cmUud2lkdGggPSBjdXJXaWR0aDtcbiAgICAgICAgdmFyIHJlY3RzID0gbGluZVZpZXcudGV4dC5maXJzdENoaWxkLmdldENsaWVudFJlY3RzKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjdHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgdmFyIGN1ciA9IHJlY3RzW2ldLCBuZXh0ID0gcmVjdHNbaSArIDFdO1xuICAgICAgICAgIGlmIChNYXRoLmFicyhjdXIuYm90dG9tIC0gbmV4dC5ib3R0b20pID4gMilcbiAgICAgICAgICAgIGhlaWdodHMucHVzaCgoY3VyLmJvdHRvbSArIG5leHQudG9wKSAvIDIgLSByZWN0LnRvcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhlaWdodHMucHVzaChyZWN0LmJvdHRvbSAtIHJlY3QudG9wKTtcbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIGEgbGluZSBtYXAgKG1hcHBpbmcgY2hhcmFjdGVyIG9mZnNldHMgdG8gdGV4dCBub2RlcykgYW5kIGFcbiAgLy8gbWVhc3VyZW1lbnQgY2FjaGUgZm9yIHRoZSBnaXZlbiBsaW5lIG51bWJlci4gKEEgbGluZSB2aWV3IG1pZ2h0XG4gIC8vIGNvbnRhaW4gbXVsdGlwbGUgbGluZXMgd2hlbiBjb2xsYXBzZWQgcmFuZ2VzIGFyZSBwcmVzZW50LilcbiAgZnVuY3Rpb24gbWFwRnJvbUxpbmVWaWV3KGxpbmVWaWV3LCBsaW5lLCBsaW5lTikge1xuICAgIGlmIChsaW5lVmlldy5saW5lID09IGxpbmUpXG4gICAgICByZXR1cm4ge21hcDogbGluZVZpZXcubWVhc3VyZS5tYXAsIGNhY2hlOiBsaW5lVmlldy5tZWFzdXJlLmNhY2hlfTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVWaWV3LnJlc3QubGVuZ3RoOyBpKyspXG4gICAgICBpZiAobGluZVZpZXcucmVzdFtpXSA9PSBsaW5lKVxuICAgICAgICByZXR1cm4ge21hcDogbGluZVZpZXcubWVhc3VyZS5tYXBzW2ldLCBjYWNoZTogbGluZVZpZXcubWVhc3VyZS5jYWNoZXNbaV19O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZVZpZXcucmVzdC5sZW5ndGg7IGkrKylcbiAgICAgIGlmIChsaW5lTm8obGluZVZpZXcucmVzdFtpXSkgPiBsaW5lTilcbiAgICAgICAgcmV0dXJuIHttYXA6IGxpbmVWaWV3Lm1lYXN1cmUubWFwc1tpXSwgY2FjaGU6IGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGVzW2ldLCBiZWZvcmU6IHRydWV9O1xuICB9XG5cbiAgLy8gUmVuZGVyIGEgbGluZSBpbnRvIHRoZSBoaWRkZW4gbm9kZSBkaXNwbGF5LmV4dGVybmFsTWVhc3VyZWQuIFVzZWRcbiAgLy8gd2hlbiBtZWFzdXJlbWVudCBpcyBuZWVkZWQgZm9yIGEgbGluZSB0aGF0J3Mgbm90IGluIHRoZSB2aWV3cG9ydC5cbiAgZnVuY3Rpb24gdXBkYXRlRXh0ZXJuYWxNZWFzdXJlbWVudChjbSwgbGluZSkge1xuICAgIGxpbmUgPSB2aXN1YWxMaW5lKGxpbmUpO1xuICAgIHZhciBsaW5lTiA9IGxpbmVObyhsaW5lKTtcbiAgICB2YXIgdmlldyA9IGNtLmRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZCA9IG5ldyBMaW5lVmlldyhjbS5kb2MsIGxpbmUsIGxpbmVOKTtcbiAgICB2aWV3LmxpbmVOID0gbGluZU47XG4gICAgdmFyIGJ1aWx0ID0gdmlldy5idWlsdCA9IGJ1aWxkTGluZUNvbnRlbnQoY20sIHZpZXcpO1xuICAgIHZpZXcudGV4dCA9IGJ1aWx0LnByZTtcbiAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChjbS5kaXNwbGF5LmxpbmVNZWFzdXJlLCBidWlsdC5wcmUpO1xuICAgIHJldHVybiB2aWV3O1xuICB9XG5cbiAgLy8gR2V0IGEge3RvcCwgYm90dG9tLCBsZWZ0LCByaWdodH0gYm94IChpbiBsaW5lLWxvY2FsIGNvb3JkaW5hdGVzKVxuICAvLyBmb3IgYSBnaXZlbiBjaGFyYWN0ZXIuXG4gIGZ1bmN0aW9uIG1lYXN1cmVDaGFyKGNtLCBsaW5lLCBjaCwgYmlhcykge1xuICAgIHJldHVybiBtZWFzdXJlQ2hhclByZXBhcmVkKGNtLCBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmUpLCBjaCwgYmlhcyk7XG4gIH1cblxuICAvLyBGaW5kIGEgbGluZSB2aWV3IHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIGdpdmVuIGxpbmUgbnVtYmVyLlxuICBmdW5jdGlvbiBmaW5kVmlld0ZvckxpbmUoY20sIGxpbmVOKSB7XG4gICAgaWYgKGxpbmVOID49IGNtLmRpc3BsYXkudmlld0Zyb20gJiYgbGluZU4gPCBjbS5kaXNwbGF5LnZpZXdUbylcbiAgICAgIHJldHVybiBjbS5kaXNwbGF5LnZpZXdbZmluZFZpZXdJbmRleChjbSwgbGluZU4pXTtcbiAgICB2YXIgZXh0ID0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQgJiYgbGluZU4gPj0gZXh0LmxpbmVOICYmIGxpbmVOIDwgZXh0LmxpbmVOICsgZXh0LnNpemUpXG4gICAgICByZXR1cm4gZXh0O1xuICB9XG5cbiAgLy8gTWVhc3VyZW1lbnQgY2FuIGJlIHNwbGl0IGluIHR3byBzdGVwcywgdGhlIHNldC11cCB3b3JrIHRoYXRcbiAgLy8gYXBwbGllcyB0byB0aGUgd2hvbGUgbGluZSwgYW5kIHRoZSBtZWFzdXJlbWVudCBvZiB0aGUgYWN0dWFsXG4gIC8vIGNoYXJhY3Rlci4gRnVuY3Rpb25zIGxpa2UgY29vcmRzQ2hhciwgdGhhdCBuZWVkIHRvIGRvIGEgbG90IG9mXG4gIC8vIG1lYXN1cmVtZW50cyBpbiBhIHJvdywgY2FuIHRodXMgZW5zdXJlIHRoYXQgdGhlIHNldC11cCB3b3JrIGlzXG4gIC8vIG9ubHkgZG9uZSBvbmNlLlxuICBmdW5jdGlvbiBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmUpIHtcbiAgICB2YXIgbGluZU4gPSBsaW5lTm8obGluZSk7XG4gICAgdmFyIHZpZXcgPSBmaW5kVmlld0ZvckxpbmUoY20sIGxpbmVOKTtcbiAgICBpZiAodmlldyAmJiAhdmlldy50ZXh0KSB7XG4gICAgICB2aWV3ID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHZpZXcgJiYgdmlldy5jaGFuZ2VzKSB7XG4gICAgICB1cGRhdGVMaW5lRm9yQ2hhbmdlcyhjbSwgdmlldywgbGluZU4sIGdldERpbWVuc2lvbnMoY20pKTtcbiAgICAgIGNtLmN1ck9wLmZvcmNlVXBkYXRlID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCF2aWV3KVxuICAgICAgdmlldyA9IHVwZGF0ZUV4dGVybmFsTWVhc3VyZW1lbnQoY20sIGxpbmUpO1xuXG4gICAgdmFyIGluZm8gPSBtYXBGcm9tTGluZVZpZXcodmlldywgbGluZSwgbGluZU4pO1xuICAgIHJldHVybi
23459B7XG4gICAgICBsaW5lOiBsaW5lLCB2aWV3OiB2aWV3LCByZWN0OiBudWxsLFxuICAgICAgbWFwOiBpbmZvLm1hcCwgY2FjaGU6IGluZm8uY2FjaGUsIGJlZm9yZTogaW5mby5iZWZvcmUsXG4gICAgICBoYXNIZWlnaHRzOiBmYWxzZVxuICAgIH07XG4gIH1cblxuICAvLyBHaXZlbiBhIHByZXBhcmVkIG1lYXN1cmVtZW50IG9iamVjdCwgbWVhc3VyZXMgdGhlIHBvc2l0aW9uIG9mIGFuXG4gIC8vIGFjdHVhbCBjaGFyYWN0ZXIgKG9yIGZldGNoZXMgaXQgZnJvbSB0aGUgY2FjaGUpLlxuICBmdW5jdGlvbiBtZWFzdXJlQ2hhclByZXBhcmVkKGNtLCBwcmVwYXJlZCwgY2gsIGJpYXMsIHZhckhlaWdodCkge1xuICAgIGlmIChwcmVwYXJlZC5iZWZvcmUpIGNoID0gLTE7XG4gICAgdmFyIGtleSA9IGNoICsgKGJpYXMgfHwgXCJcIiksIGZvdW5kO1xuICAgIGlmIChwcmVwYXJlZC5jYWNoZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICBmb3VuZCA9IHByZXBhcmVkLmNhY2hlW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghcHJlcGFyZWQucmVjdClcbiAgICAgICAgcHJlcGFyZWQucmVjdCA9IHByZXBhcmVkLnZpZXcudGV4dC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGlmICghcHJlcGFyZWQuaGFzSGVpZ2h0cykge1xuICAgICAgICBlbnN1cmVMaW5lSGVpZ2h0cyhjbSwgcHJlcGFyZWQudmlldywgcHJlcGFyZWQucmVjdCk7XG4gICAgICAgIHByZXBhcmVkLmhhc0hlaWdodHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgZm91bmQgPSBtZWFzdXJlQ2hhcklubmVyKGNtLCBwcmVwYXJlZCwgY2gsIGJpYXMpO1xuICAgICAgaWYgKCFmb3VuZC5ib2d1cykgcHJlcGFyZWQuY2FjaGVba2V5XSA9IGZvdW5kO1xuICAgIH1cbiAgICByZXR1cm4ge2xlZnQ6IGZvdW5kLmxlZnQsIHJpZ2h0OiBmb3VuZC5yaWdodCxcbiAgICAgICAgICAgIHRvcDogdmFySGVpZ2h0ID8gZm91bmQucnRvcCA6IGZvdW5kLnRvcCxcbiAgICAgICAgICAgIGJvdHRvbTogdmFySGVpZ2h0ID8gZm91bmQucmJvdHRvbSA6IGZvdW5kLmJvdHRvbX07XG4gIH1cblxuICB2YXIgbnVsbFJlY3QgPSB7bGVmdDogMCwgcmlnaHQ6IDAsIHRvcDogMCwgYm90dG9tOiAwfTtcblxuICBmdW5jdGlvbiBub2RlQW5kT2Zmc2V0SW5MaW5lTWFwKG1hcCwgY2gsIGJpYXMpIHtcbiAgICB2YXIgbm9kZSwgc3RhcnQsIGVuZCwgY29sbGFwc2U7XG4gICAgLy8gRmlyc3QsIHNlYXJjaCB0aGUgbGluZSBtYXAgZm9yIHRoZSB0ZXh0IG5vZGUgY29ycmVzcG9uZGluZyB0byxcbiAgICAvLyBvciBjbG9zZXN0IHRvLCB0aGUgdGFyZ2V0IGNoYXJhY3Rlci5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcC5sZW5ndGg7IGkgKz0gMykge1xuICAgICAgdmFyIG1TdGFydCA9IG1hcFtpXSwgbUVuZCA9IG1hcFtpICsgMV07XG4gICAgICBpZiAoY2ggPCBtU3RhcnQpIHtcbiAgICAgICAgc3RhcnQgPSAwOyBlbmQgPSAxO1xuICAgICAgICBjb2xsYXBzZSA9IFwibGVmdFwiO1xuICAgICAgfSBlbHNlIGlmIChjaCA8IG1FbmQpIHtcbiAgICAgICAgc3RhcnQgPSBjaCAtIG1TdGFydDtcbiAgICAgICAgZW5kID0gc3RhcnQgKyAxO1xuICAgICAgfSBlbHNlIGlmIChpID09IG1hcC5sZW5ndGggLSAzIHx8IGNoID09IG1FbmQgJiYgbWFwW2kgKyAzXSA+IGNoKSB7XG4gICAgICAgIGVuZCA9IG1FbmQgLSBtU3RhcnQ7XG4gICAgICAgIHN0YXJ0ID0gZW5kIC0gMTtcbiAgICAgICAgaWYgKGNoID49IG1FbmQpIGNvbGxhcHNlID0gXCJyaWdodFwiO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0ICE9IG51bGwpIHtcbiAgICAgICAgbm9kZSA9IG1hcFtpICsgMl07XG4gICAgICAgIGlmIChtU3RhcnQgPT0gbUVuZCAmJiBiaWFzID09IChub2RlLmluc2VydExlZnQgPyBcImxlZnRcIiA6IFwicmlnaHRcIikpXG4gICAgICAgICAgY29sbGFwc2UgPSBiaWFzO1xuICAgICAgICBpZiAoYmlhcyA9PSBcImxlZnRcIiAmJiBzdGFydCA9PSAwKVxuICAgICAgICAgIHdoaWxlIChpICYmIG1hcFtpIC0gMl0gPT0gbWFwW2kgLSAzXSAmJiBtYXBbaSAtIDFdLmluc2VydExlZnQpIHtcbiAgICAgICAgICAgIG5vZGUgPSBtYXBbKGkgLT0gMykgKyAyXTtcbiAgICAgICAgICAgIGNvbGxhcHNlID0gXCJsZWZ0XCI7XG4gICAgICAgICAgfVxuICAgICAgICBpZiAoYmlhcyA9PSBcInJpZ2h0XCIgJiYgc3RhcnQgPT0gbUVuZCAtIG1TdGFydClcbiAgICAgICAgICB3aGlsZSAoaSA8IG1hcC5sZW5ndGggLSAzICYmIG1hcFtpICsgM10gPT0gbWFwW2kgKyA0XSAmJiAhbWFwW2kgKyA1XS5pbnNlcnRMZWZ0KSB7XG4gICAgICAgICAgICBub2RlID0gbWFwWyhpICs9IDMpICsgMl07XG4gICAgICAgICAgICBjb2xsYXBzZSA9IFwicmlnaHRcIjtcbiAgICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge25vZGU6IG5vZGUsIHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQsIGNvbGxhcHNlOiBjb2xsYXBzZSwgY292ZXJTdGFydDogbVN0YXJ0LCBjb3ZlckVuZDogbUVuZH07XG4gIH1cblxuICBmdW5jdGlvbiBtZWFzdXJlQ2hhcklubmVyKGNtLCBwcmVwYXJlZCwgY2gsIGJpYXMpIHtcbiAgICB2YXIgcGxhY2UgPSBub2RlQW5kT2Zmc2V0SW5MaW5lTWFwKHByZXBhcmVkLm1hcCwgY2gsIGJpYXMpO1xuICAgIHZhciBub2RlID0gcGxhY2Uubm9kZSwgc3RhcnQgPSBwbGFjZS5zdGFydCwgZW5kID0gcGxhY2UuZW5kLCBjb2xsYXBzZSA9IHBsYWNlLmNvbGxhcHNlO1xuXG4gICAgdmFyIHJlY3Q7XG4gICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMykgeyAvLyBJZiBpdCBpcyBhIHRleHQgbm9kZSwgdXNlIGEgcmFuZ2UgdG8gcmV0cmlldmUgdGhlIGNvb3JkaW5hdGVzLlxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHsgLy8gUmV0cnkgYSBtYXhpbXVtIG9mIDQgdGltZXMgd2hlbiBub25zZW5zZSByZWN0YW5nbGVzIGFyZSByZXR1cm5lZFxuICAgICAgICB3aGlsZSAoc3RhcnQgJiYgaXNFeHRlbmRpbmdDaGFyKHByZXBhcmVkLmxpbmUudGV4dC5jaGFyQXQocGxhY2UuY292ZXJTdGFydCArIHN0YXJ0KSkpIC0tc3RhcnQ7XG4gICAgICAgIHdoaWxlIChwbGFjZS5jb3ZlclN0YXJ0ICsgZW5kIDwgcGxhY2UuY292ZXJFbmQgJiYgaXNFeHRlbmRpbmdDaGFyKHByZXBhcmVkLmxpbmUudGV4dC5jaGFyQXQocGxhY2UuY292ZXJTdGFydCArIGVuZCkpKSArK2VuZDtcbiAgICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5ICYmIHN0YXJ0ID09IDAgJiYgZW5kID09IHBsYWNlLmNvdmVyRW5kIC0gcGxhY2UuY292ZXJTdGFydCkge1xuICAgICAgICAgI
23459HJlY3QgPSBub2RlLnBhcmVudE5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoaWUgJiYgY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHtcbiAgICAgICAgICB2YXIgcmVjdHMgPSByYW5nZShub2RlLCBzdGFydCwgZW5kKS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgIGlmIChyZWN0cy5sZW5ndGgpXG4gICAgICAgICAgICByZWN0ID0gcmVjdHNbYmlhcyA9PSBcInJpZ2h0XCIgPyByZWN0cy5sZW5ndGggLSAxIDogMF07XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmVjdCA9IG51bGxSZWN0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlY3QgPSByYW5nZShub2RlLCBzdGFydCwgZW5kKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSB8fCBudWxsUmVjdDtcbiAgICAgICAgf
vendor: 13,208 bytes, line 23459
23459VxuICAgICAgICBpZiAocmVjdC5sZWZ0IHx8IHJlY3QucmlnaHQgfHwgc3RhcnQgPT0gMCkgYnJlYWs7XG4gICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IHN0YXJ0IC0gMTtcbiAgICAgICAgY29sbGFwc2UgPSBcInJpZ2h0XCI7XG4gICAgICB9XG4gICAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDExKSByZWN0ID0gbWF5YmVVcGRhdGVSZWN0Rm9yWm9vbWluZyhjbS5kaXNwbGF5Lm1lYXN1cmUsIHJlY3QpO1xuICAgIH0gZWxzZSB7IC8vIElmIGl0IGlzIGEgd2lkZ2V0LCBzaW1wbHkgZ2V0IHRoZSBib3ggZm9yIHRoZSB3aG9sZSB3aWRnZXQuXG4gICAgICBpZiAoc3RhcnQgPiAwKSBjb2xsYXBzZSA9IGJpYXMgPSBcInJpZ2h0XCI7XG4gICAgICB2YXIgcmVjdHM7XG4gICAgICBpZiAoY20ub3B0aW9ucy5saW5lV3JhcHBpbmcgJiYgKHJlY3RzID0gbm9kZS5nZXRDbGllbnRSZWN0cygpKS5sZW5ndGggPiAxKVxuICAgICAgICByZWN0ID0gcmVjdHNbYmlhcyA9PSBcInJpZ2h0XCIgPyByZWN0cy5sZW5ndGggLSAxIDogMF07XG4gICAgICBlbHNlXG4gICAgICAgIHJlY3QgPSBub2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH1cbiAgICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDkgJiYgIXN0YXJ0ICYmICghcmVjdCB8fCAhcmVjdC5sZWZ0ICYmICFyZWN0LnJpZ2h0KSkge1xuICAgICAgdmFyIHJTcGFuID0gbm9kZS5wYXJlbnROb2RlLmdldENsaWVudFJlY3RzKClbMF07XG4gICAgICBpZiAoclNwYW4pXG4gICAgICAgIHJlY3QgPSB7bGVmdDogclNwYW4ubGVmdCwgcmlnaHQ6IHJTcGFuLmxlZnQgKyBjaGFyV2lkdGgoY20uZGlzcGxheSksIHRvcDogclNwYW4udG9wLCBib3R0b206IHJTcGFuLmJvdHRvbX07XG4gICAgICBlbHNlXG4gICAgICAgIHJlY3QgPSBudWxsUmVjdDtcbiAgICB9XG5cbiAgICB2YXIgcnRvcCA9IHJlY3QudG9wIC0gcHJlcGFyZWQucmVjdC50b3AsIHJib3QgPSByZWN0LmJvdHRvbSAtIHByZXBhcmVkLnJlY3QudG9wO1xuICAgIHZhciBtaWQgPSAocnRvcCArIHJib3QpIC8gMjtcbiAgICB2YXIgaGVpZ2h0cyA9IHByZXBhcmVkLnZpZXcubWVhc3VyZS5oZWlnaHRzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGVpZ2h0cy5sZW5ndGggLSAxOyBpKyspXG4gICAgICBpZiAobWlkIDwgaGVpZ2h0c1tpXSkgYnJlYWs7XG4gICAgdmFyIHRvcCA9IGkgPyBoZWlnaHRzW2kgLSAxXSA6IDAsIGJvdCA9IGhlaWdodHNbaV07XG4gICAgdmFyIHJlc3VsdCA9IHtsZWZ0OiAoY29sbGFwc2UgPT0gXCJyaWdodFwiID8gcmVjdC5yaWdodCA6IHJlY3QubGVmdCkgLSBwcmVwYXJlZC5yZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgICByaWdodDogKGNvbGxhcHNlID09IFwibGVmdFwiID8gcmVjdC5sZWZ0IDogcmVjdC5yaWdodCkgLSBwcmVwYXJlZC5yZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgICB0b3A6IHRvcCwgYm90dG9tOiBib3R9O1xuICAgIGlmICghcmVjdC5sZWZ0ICYmICFyZWN0LnJpZ2h0KSByZXN1bHQuYm9ndXMgPSB0cnVlO1xuICAgIGlmICghY20ub3B0aW9ucy5zaW5nbGVDdXJzb3JIZWlnaHRQZXJMaW5lKSB7IHJlc3VsdC5ydG9wID0gcnRvcDsgcmVzdWx0LnJib3R0b20gPSByYm90OyB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gV29yayBhcm91bmQgcHJvYmxlbSB3aXRoIGJvdW5kaW5nIGNsaWVudCByZWN0cyBvbiByYW5nZXMgYmVpbmdcbiAgLy8gcmV0dXJuZWQgaW5jb3JyZWN0bHkgd2hlbiB6b29tZWQgb24gSUUxMCBhbmQgYmVsb3cuXG4gIGZ1bmN0aW9uIG1heWJlVXBkYXRlUmVjdEZvclpvb21pbmcobWVhc3VyZSwgcmVjdCkge1xuICAgIGlmICghd2luZG93LnNjcmVlbiB8fCBzY3JlZW4ubG9naWNhbFhEUEkgPT0gbnVsbCB8fFxuICAgICAgICBzY3JlZW4ubG9naWNhbFhEUEkgPT0gc2NyZWVuLmRldmljZVhEUEkgfHwgIWhhc0JhZFpvb21lZFJlY3RzKG1lYXN1cmUpKVxuICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgdmFyIHNjYWxlWCA9IHNjcmVlbi5sb2dpY2FsWERQSSAvIHNjcmVlbi5kZXZpY2VYRFBJO1xuICAgIHZhciBzY2FsZVkgPSBzY3JlZW4ubG9naWNhbFlEUEkgLyBzY3JlZW4uZGV2aWNlWURQSTtcbiAgICByZXR1cm4ge2xlZnQ6IHJlY3QubGVmdCAqIHNjYWxlWCwgcmlnaHQ6IHJlY3QucmlnaHQgKiBzY2FsZVgsXG4gICAgICAgICAgICB0b3A6IHJlY3QudG9wICogc2NhbGVZLCBib3R0b206IHJlY3QuYm90dG9tICogc2NhbGVZfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGVGb3IobGluZVZpZXcpIHtcbiAgICBpZiAobGluZVZpZXcubWVhc3VyZSkge1xuICAgICAgbGluZVZpZXcubWVhc3VyZS5jYWNoZSA9IHt9O1xuICAgICAgbGluZVZpZXcubWVhc3VyZS5oZWlnaHRzID0gbnVsbDtcbiAgICAgIGlmIChsaW5lVmlldy5yZXN0KSBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVWaWV3LnJlc3QubGVuZ3RoOyBpKyspXG4gICAgICAgIGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGVzW2ldID0ge307XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJMaW5lTWVhc3VyZW1lbnRDYWNoZShjbSkge1xuICAgIGNtLmRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlID0gbnVsbDtcbiAgICByZW1vdmVDaGlsZHJlbihjbS5kaXNwbGF5LmxpbmVNZWFzdXJlKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNtLmRpc3BsYXkudmlldy5sZW5ndGg7IGkrKylcbiAgICAgIGNsZWFyTGluZU1lYXN1cmVtZW50Q2FjaGVGb3IoY20uZGlzcGxheS52aWV3W2ldKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFyQ2FjaGVzKGNtKSB7XG4gICAgY2xlYXJMaW5lTWVhc3VyZW1lbnRDYWNoZShjbSk7XG4gICAgY20uZGlzcGxheS5jYWNoZWRDaGFyV2lkdGggPSBjbS5kaXNwbGF5LmNhY2hlZFRleHRIZWlnaHQgPSBjbS5kaXNwbGF5LmNhY2hlZFBhZGRpbmdIID0gbnVsbDtcbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSBjbS5kaXNwbGF5Lm1heExpbmVDaGFuZ2VkID0gdHJ1ZTtcbiAgICBjbS5kaXNwbGF5LmxpbmVOdW1DaGFycyA9IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBwYWdlU2Nyb2xsWCgpIHsgcmV0dXJuIHdpbmRvdy5wYWdlWE9mZnNldCB8fCAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IHx8IGRvY3VtZW50LmJvZHkpLnNjcm9sbExlZnQ7IH1cbiAgZnVuY3Rpb24gcGFnZVNjcm9sbFkoKSB7IHJldHVybiB3aW5kb3cucGFnZVlPZmZzZXQgfHwgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCB8fCBkb2N1bWVudC5ib2R5KS5zY3JvbGxUb3A7IH1cblxuICAvLyBDb252ZXJ0cyBhIHt0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHR9IGJveCBmcm9tIGxpbmUtbG9jYWxcbiAgLy8gY29vcmRpbmF0ZXMgaW50byBhbm90aGVyIGNvb3JkaW5hdGUgc3lzdGVtLiBDb250ZXh0IG1heSBiZSBvbmUgb2ZcbiAgLy8gXCJsaW5lXCIsIFwiZGl2XCIgKGRpc3BsYXkubGluZURpdiksIFwibG9jYWxcIi9udWxsIChlZGl0b3IpLCBcIndpbmRvd1wiLFxuICAvLyBvciBcInBhZ2VcIi5cbiAgZnVuY3Rpb24gaW50b0Nvb3JkU3lzdGVtKGNtLCBsaW5lT2JqLCByZWN0LCBjb250ZXh0KSB7XG4gICAgaWYgKGxpbmVPYmoud2lkZ2V0cykgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lT2JqLndpZGdldHMubGVuZ3RoOyArK2kpIGlmIChsaW5lT2JqLndpZGdldHNbaV0uYWJvdmUpIHtcbiAgICAgIHZhciBzaXplID0gd2lkZ2V0SGVpZ2h0KGxpbmVPYmoud2lkZ2V0c1tpXSk7XG4gICAgICByZWN0LnRvcCArPSBzaXplOyByZWN0LmJvdHRvbSArPSBzaXplO1xuICAgIH1cbiAgICBpZiAoY29udGV4dCA9PSBcImxpbmVcIikgcmV0dXJuIHJlY3Q7XG4gICAgaWYgKCFjb250ZXh0KSBjb250ZXh0ID0gXCJsb2NhbFwiO1xuICAgIHZhciB5T2ZmID0gaGVpZ2h0QXRMaW5lKGxpbmVPYmopO1xuICAgIGlmIChjb250ZXh0ID09IFwibG9jYWxcIikgeU9mZiArPSBwYWRkaW5nVG9wKGNtLmRpc3BsYXkpO1xuICAgIGVsc2UgeU9mZiAtPSBjbS5kaXNwbGF5LnZpZXdPZmZzZXQ7XG4gICAgaWYgKGNvbnRleHQgPT0gXCJwYWdlXCIgfHwgY29udGV4dCA9PSBcIndpbmRvd1wiKSB7XG4gICAgICB2YXIgbE9mZiA9IGNtLmRpc3BsYXkubGluZVNwYWNlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgeU9mZiArPSBsT2ZmLnRvcCArIChjb250ZXh0ID09IFwid2luZG93XCIgPyAwIDogcGFnZVNjcm9sbFkoKSk7XG4gICAgICB2YXIgeE9mZiA9IGxPZmYubGVmdCArIChjb250ZXh0ID09IFwid2luZG93XCIgPyAwIDogcGFnZVNjcm9sbFgoKSk7XG4gICAgICByZWN0LmxlZnQgKz0geE9mZjsgcmVjdC5yaWdodCArPSB4T2ZmO1xuICAgIH1cbiAgICByZWN0LnRvcCArPSB5T2ZmOyByZWN0LmJvdHRvbSArPSB5T2ZmO1xuICAgIHJldHVybiByZWN0O1xuICB9XG5cbiAgLy8gQ292ZXJ0cyBhIGJveCBmcm9tIFwiZGl2XCIgY29vcmRzIHRvIGFub3RoZXIgY29vcmRpbmF0ZSBzeXN0ZW0uXG4gIC8vIENvbnRleHQgbWF5IGJlIFwid2luZG93XCIsIFwicGFnZVwiLCBcImRpdlwiLCBvciBcImxvY2FsXCIvbnVsbC5cbiAgZnVuY3Rpb24gZnJvbUNvb3JkU3lzdGVtKGNtLCBjb29yZHMsIGNvbnRleHQpIHtcbiAgICBpZiAoY29udGV4dCA9PSBcImRpdlwiKSByZXR1cm4gY29vcmRzO1xuICAgIHZhciBsZWZ0ID0gY29vcmRzLmxlZnQsIHRvcCA9IGNvb3Jkcy50b3A7XG4gICAgLy8gRmlyc3QgbW92ZSBpbnRvIFwicGFnZVwiIGNvb3JkaW5hdGUgc3lzdGVtXG4gICAgaWYgKGNvbnRleHQgPT0gXCJwYWdlXCIpIHtcbiAgICAgIGxlZnQgLT0gcGFnZVNjcm9sbFgoKTtcbiAgICAgIHRvcCAtPSBwYWdlU2Nyb2xsWSgpO1xuICAgIH0gZWxzZSBpZiAoY29udGV4dCA9PSBcImxvY2FsXCIgfHwgIWNvbnRleHQpIHtcbiAgICAgIHZhciBsb2NhbEJveCA9IGNtLmRpc3BsYXkuc2l6ZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBsZWZ0ICs9IGxvY2FsQm94LmxlZnQ7XG4gICAgICB0b3AgKz0gbG9jYWxCb3gudG9wO1xuICAgIH1cblxuICAgIHZhciBsaW5lU3BhY2VCb3ggPSBjbS5kaXNwbGF5LmxpbmVTcGFjZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICByZXR1cm4ge2xlZnQ6IGxlZnQgLSBsaW5lU3BhY2VCb3gubGVmdCwgdG9wOiB0b3AgLSBsaW5lU3BhY2VCb3gudG9wfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoYXJDb29yZHMoY20sIHBvcywgY29udGV4dCwgbGluZU9iaiwgYmlhcykge1xuICAgIGlmICghbGluZU9iaikgbGluZU9iaiA9IGdldExpbmUoY20uZG9jLCBwb3MubGluZSk7XG4gICAgcmV0dXJuIGludG9Db29yZFN5c3RlbShjbSwgbGluZU9iaiwgbWVhc3VyZUNoYXIoY20sIGxpbmVPYmosIHBvcy5jaCwgYmlhcyksIGNvbnRleHQpO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIGJveCBmb3IgYSBnaXZlbiBjdXJzb3IgcG9zaXRpb24sIHdoaWNoIG1heSBoYXZlIGFuXG4gIC8vICdvdGhlcicgcHJvcGVydHkgY29udGFpbmluZyB0aGUgcG9zaXRpb24gb2YgdGhlIHNlY29uZGFyeSBjdXJzb3JcbiAgLy8gb24gYSBiaWRpIGJvdW5kYXJ5LlxuICBmdW5jdGlvbiBjdXJzb3JDb29yZHMoY20sIHBvcywgY29udGV4dCwgbGluZU9iaiwgcHJlcGFyZWRNZWFzdXJlLCB2YXJIZWlnaHQpIHtcbiAgICBsaW5lT2JqID0gbGluZU9iaiB8fCBnZXRMaW5lKGNtLmRvYywgcG9zLmxpbmUpO1xuICAgIGlmICghcHJlcGFyZWRNZWFzdXJlKSBwcmVwYXJlZE1lYXN1cmUgPSBwcmVwYXJlTWVhc3VyZUZvckxpbmUoY20sIGxpbmVPYmopO1xuICAgIGZ1bmN0aW9uIGdldChjaCwgcmlnaHQpIHtcbiAgICAgIHZhciBtID0gbWVhc3VyZUNoYXJQcmVwYXJlZChjbSwgcHJlcGFyZWRNZWFzdXJlLCBjaCwgcmlnaHQgPyBcInJpZ2h0XCIgOiBcImxlZnRcIiwgdmFySGVpZ2h0KTtcbiAgICAgIGlmIChyaWdodCkgbS5sZWZ0ID0gbS5yaWdodDsgZWxzZSBtLnJpZ2h0ID0gbS5sZWZ0O1xuICAgICAgcmV0dXJuIGludG9Db29yZFN5c3RlbShjbSwgbGluZU9iaiwgbSwgY29udGV4dCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGdldEJpZGkoY2gsIHBhcnRQb3MpIHtcbiAgICAgIHZhciBwYXJ0ID0gb3JkZXJbcGFydFBvc10sIHJpZ2h0ID0gcGFydC5sZXZlbCAlIDI7XG4gICAgICBpZiAoY2ggPT0gYmlkaUxlZnQocGFydCkgJiYgcGFydFBvcyAmJiBwYXJ0LmxldmVsIDwgb3JkZXJbcGFydFBvcyAtIDFdLmxldmVsKSB7XG4gICAgICAgIHBhcnQgPSBvcmRlclstLXBhcnRQb3NdO1xuICAgICAgICBjaCA9IGJpZGlSaWdodChwYXJ0KSAtIChwYXJ0LmxldmVsICUgMiA/IDAgOiAxKTtcbiAgICAgICAgcmlnaHQgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChjaCA9PSBiaWRpUmlnaHQocGFydCkgJiYgcGFydFBvcyA8IG9yZGVyLmxlbmd0aCAtIDEgJiYgcGFydC5sZXZlbCA8IG9yZGVyW3BhcnRQb3MgKyAxXS5sZXZlbCkge1xuICAgICAgICBwYXJ0ID0gb3JkZXJbKytwYXJ0UG9zXTtcbiAgICAgICAgY2ggPSBiaWRpTGVmdChwYXJ0KSAtIHBhcnQubGV2ZWwgJSAyO1xuICAgICAgICByaWdodCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKHJpZ2h0ICYmIGNoID09IHBhcnQudG8gJiYgY2ggPiBwYXJ0LmZyb20pIHJldHVybiBnZXQoY2ggLSAxKTtcbiAgICAgIHJldHVybiBnZXQoY2gsIHJpZ2h0KTtcbiAgICB9XG4gICAgdmFyIG9yZGVyID0gZ2V0T3JkZXIobGluZU9iaiksIGNoID0gcG9zLmNoO1xuICAgIGlmICghb3JkZXIpIHJldHVybiBnZXQoY2gpO1xuICAgIHZhciBwYXJ0UG9zID0gZ2V0QmlkaVBhcnRBdChvcmRlciwgY2gpO1xuICAgIHZhciB2YWwgPSBnZXRCaWRpKGNoLCBwYXJ0UG9zKTtcbiAgICBpZiAoYmlkaU90aGVyICE9IG51bGwpIHZhbC5vdGhlciA9IGdldEJpZGkoY2gsIGJpZGlPdGhlcik7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIC8vIFVzZWQgdG8gY2hlYXBseSBlc3RpbWF0ZSB0aGUgY29vcmRpbmF0ZXMgZm9yIGEgcG9zaXRpb24uIFVzZWQgZm9yXG4gIC8vIGludGVybWVkaWF0ZSBzY3JvbGwgdXBkYXRlcy5cbiAgZnVuY3Rpb24gZXN0aW1hdGVDb29yZHMoY20sIHBvcykge1xuICAgIHZhciBsZWZ0ID0gMCwgcG9zID0gY2xpcFBvcyhjbS5kb2MsIHBvcyk7XG4gICAgaWYgKCFjbS5vcHRpb25zLmxpbmVXcmFwcGluZykgbGVmdCA9IGNoYXJXaWR0aChjbS5kaXNwbGF5KSAqIHBvcy5jaDtcbiAgICB2YXIgbGluZU9iaiA9IGdldExpbmUoY20uZG9jLCBwb3MubGluZSk7XG4gICAgdmFyIHRvcCA9IGhlaWdodEF0TGluZShsaW5lT2JqKSArIHBhZGRpbmdUb3AoY20uZGlzcGxheSk7XG4gICAgcmV0dXJuIHtsZWZ0OiBsZWZ0LCByaWdodDogbGVmdCwgdG9wOiB0b3AsIGJvdHRvbTogdG9wICsgbGluZU9iai5oZWlnaHR9O1xuICB9XG5cbiAgLy8gUG9zaXRpb25zIHJldHVybmVkIGJ5IGNvb3Jkc0NoYXIgY29udGFpbiBzb21lIGV4dHJhIGluZm9ybWF0aW9uLlxuICAvLyB4UmVsIGlzIHRoZSByZWxhdGl2ZSB4IHBvc2l0aW9uIG9mIHRoZSBpbnB1dCBjb29yZGluYXRlcyBjb21wYXJlZFxuICAvLyB0byB0aGUgZm91bmQgcG9zaXRpb24gKHNvIHhSZWwgPiAwIG1lYW5zIHRoZSBjb29yZGluYXRlcyBhcmUgdG9cbiAgLy8gdGhlIHJpZ2h0IG9mIHRoZSBjaGFyYWN0ZXIgcG9zaXRpb24sIGZvciBleGFtcGxlKS4gV2hlbiBvdXRzaWRlXG4gIC8vIGlzIHRydWUsIHRoYXQgbWVhbnMgdGhlIGNvb3JkaW5hdGVzIGxpZSBvdXRzaWRlIHRoZSBsaW5lJ3NcbiAgLy8gdmVydGljYWwgcmFuZ2UuXG4gIGZ1bmN0aW9uIFBvc1dpdGhJbmZvKGxpbmUsIGNoLCBvdXRzaWRlLCB4UmVsKSB7XG4gICAgdmFyIHBvcyA9IFBvcyhsaW5lLCBjaCk7XG4gICAgcG9zLnhSZWwgPSB4UmVsO1xuICAgIGlmIChvdXRzaWRlKSBwb3Mub3V0c2lkZSA9IHRydWU7XG4gICAgcmV0dXJuIHBvcztcbiAgfVxuXG4gIC8vIENvbXB1dGUgdGhlIGNoYXJhY3RlciBwb3NpdGlvbiBjbG9zZXN0IHRvIHRoZSBnaXZlbiBjb29yZGluYXRlcy5cbiAgLy8gSW5wdXQgbXVzdCBiZSBsaW5lU3BhY2UtbG9jYWwgKFwiZGl2XCIgY29vcmRpbmF0ZSBzeXN0ZW0pLlxuICBmdW5jdGlvbiBjb29yZHNDaGFyKGNtLCB4LCB5KSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYztcbiAgICB5ICs9IGNtLmRpc3BsYXkudmlld09mZnNldDtcbiAgICBpZiAoeSA8IDApIHJldHVybiBQb3NXaXRoSW5mbyhkb2MuZmlyc3QsIDAsIHRydWUsIC0xKTtcbiAgICB2YXIgbGluZU4gPSBsaW5lQXRIZWlnaHQoZG9jLCB5KSwgbGFzdCA9IGRvYy5maXJzdCArIGRvYy5zaXplIC0gMTtcbiAgICBpZiAobGluZU4gPiBsYXN0KVxuICAgICAgcmV0dXJuIFBvc1dpdGhJbmZvKGRvYy5maXJzdCArIGRvYy5zaXplIC0gMSwgZ2V0TGluZShkb2MsIGxhc3QpLnRleHQubGVuZ3RoLCB0cnVlLCAxKTtcbiAgICBpZiAoeCA8IDApIHggPSAwO1xuXG4gICAgdmFyIGxpbmVPYmogPSBnZXRMaW5lKGRvYywgbGluZU4pO1xuICAgIGZvciAoOzspIHtcbiAgICAgIHZhciBmb3VuZCA9IGNvb3Jkc0NoYXJJbm5lcihjbSwgbGluZU9iaiwgbGluZU4sIHgsIHkpO1xuICAgICAgdmFyIG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdEVuZChsaW5lT2JqKTtcbiAgICAgIHZhciBtZXJnZWRQb3MgPSBtZXJnZWQgJiYgbWVyZ2VkLmZpbmQoMCwgdHJ1ZSk7XG4gICAgICBpZiAobWVyZ2VkICYmIChmb3VuZC5jaCA+IG1lcmdlZFBvcy5mcm9tLmNoIHx8IGZvdW5kLmNoID09IG1lcmdlZFBvcy5mcm9tLmNoICYmIGZvdW5kLnhSZWwgPiAwKSlcbiAgICAgICAgbGluZU4gPSBsaW5lTm8obGluZU9iaiA9IG1lcmdlZFBvcy50by5saW5lKTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIGZvdW5kO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNvb3Jkc0NoYXJJbm5lcihjbSwgbGluZU9iaiwgbGluZU5vLCB4LCB5KSB7XG4gICAgdmFyIGlubmVyT2ZmID0geSAtIGhlaWdodEF0TGluZShsaW5lT2JqKTtcbiAgICB2YXIgd3JvbmdMaW5lID0gZmFsc2UsIGFkanVzdCA9IDIgKiBjbS5kaXNwbGF5LndyYXBwZXIuY2xpZW50V2lkdGg7XG4gICAgdmFyIHByZXBhcmVkTWVhc3VyZSA9IHByZXBhcmVNZWFzdXJlRm9yTGluZShjbSwgbGluZU9iaik7XG5cbiAgICBmdW5jdGlvbiBnZXRYKGNoKSB7XG4gICAgICB2YXIgc3AgPSBjdXJzb3JDb29yZHMoY20sIFBvcyhsaW5lTm8sIGNoKSwgXCJsaW5lXCIsIGxpbmVPYmosIHByZXBhcmVkTWVhc3VyZSk7XG4gICAgICB3cm9uZ0xpbmUgPSB0cnVlO1xuICAgICAgaWYgKGlubmVyT2ZmID4gc3AuYm90dG9tKSByZXR1cm4gc3AubGVmdCAtIGFkanVzdDtcbiAgICAgIGVsc2UgaWYgKGlubmVyT2ZmIDwgc3AudG9wKSByZXR1cm4gc3AubGVmdCArIGFkanVzdDtcbiAgICAgIGVsc2Ugd3JvbmdMaW5lID0gZmFsc2U7XG4gICAgICByZXR1cm4gc3AubGVmdDtcbiAgICB9XG5cbiAgICB2YXIgYmlkaSA9IGdldE9yZGVyKGxpbmVPYmopLCBkaXN0ID0gbGluZU9iai50ZXh0Lmxlbmd0aDtcbiAgICB2YXIgZnJvbSA9IGxpbmVMZWZ0KGxpbmVPYmopLCB0byA9IGxpbmVSaWdodChsaW5lT2JqKTtcbiAgICB2YXIgZnJvbVggPSBnZXRYKGZyb20pLCBmcm9tT3V0c2lkZSA9IHdyb25nTGluZSwgdG9YID0gZ2V0WCh0byksIHRvT3V0c2lkZSA9IHdyb25nTGluZTtcblxuICAgIGlmICh4ID4gdG9YKSByZXR1cm4gUG9zV2l0aEluZm8obGluZU5vLCB0bywgdG9PdXRzaWRlLCAxKTtcbiAgICAvLyBEbyBhIGJpbmFyeSBzZWFyY2ggYmV0d2VlbiB0aGVzZSBib3VuZHMuXG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKGJpZGkgPyB0byA9PSBmcm9tIHx8IHRvID09IG1vdmVWaXN1YWxseShsaW5lT2JqLCBmcm9tLCAxKSA6IHRvIC0gZnJvbSA8PSAxKSB7XG4gICAgICAgIHZhciBjaCA9IHggPCBmcm9tWCB8fCB4IC0gZnJvbVggPD0gdG9YIC0geCA/IGZyb20gOiB0bztcbiAgICAgICAgdmFyI
23459HhEaWZmID0geCAtIChjaCA9PSBmcm9tID8gZnJvbVggOiB0b1gpO1xuICAgICAgICB3aGlsZSAoaXNFeHRlbmRpbmdDaGFyKGxpbmVPYmoudGV4dC5jaGFyQXQoY2gpKSkgKytjaDtcbiAgICAgICAgdmFyIHBvcyA9IFBvc1dpdGhJbmZvKGxpbmVObywgY2gsIGNoID09IGZyb20gPyBmcm9tT3V0c2lkZSA6IHRvT3V0c2lkZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhEaWZmIDwgLTEgPyAtMSA6IHhEaWZmID4gMSA/IDEgOiAwKTtcbiAgICAgICAgcmV0dXJuIHBvcztcbiAgICAgIH1cbiAgICAgIHZhciBzdGVwID0gTWF0aC5jZWlsKGRpc3QgLyAyKSwgbWlkZGxlID0gZnJvbSArIHN0ZXA7XG4gICAgICBpZiAoYmlkaSkge1xuICAgICAgICBtaWRkbGUgPSBmcm9tO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ZXA7ICsraSkgbWlkZGxlID0gbW92ZVZpc3VhbGx5KGxpbmVPYmosIG1pZGRsZSwgMSk7XG4gICAgICB9XG4gICAgICB2YXIgbWlkZGxlWCA9IGdldFgobWlkZGxlKTtcbiAgICAgIGlmIChtaWRkbGVYID4geCkge3RvID0gbWlkZGxlOyB0b1ggPSBtaWRkbGVYOyBpZiAodG9PdXRzaWRlID0gd3JvbmdMaW5lKSB0b1ggKz0gMTAwMDsgZGlzdCA9IHN0ZXA7fVxuICAgICAgZWxzZSB7ZnJvbSA9IG1pZGRsZTsgZnJvbVggPSBtaWRkbGVYOyBmcm9tT3V0c2lkZSA9IHdyb25nTGluZTsgZGlzdCAtPSBzdGVwO31cbiAgICB9XG4gIH1cblxuICB2YXIgbWVhc3VyZVRleHQ7XG4gIC8vIENvbXB1dGUgdGhlIGRlZmF1bHQgdGV4dCBoZWlnaHQuXG4gIGZ1bmN0aW9uIHRleHRIZWlnaHQoZGlzcGxheSkge1xuICAgIGlmIChkaXNwbGF5LmNhY2hlZFRleHRIZWlnaHQgIT0gbnVsbCkgcmV0dXJuIGRpc3BsYXkuY2FjaGVkVGV4dEhlaWdodDtcbiAgICBpZiAobWVhc3VyZVRleHQgPT0gbnVsbCkge1xuICAgICAgbWVhc3VyZVRleHQgPSBlbHQoXCJwcmVcIik7XG4gICAgICAvLyBNZWFzdXJlIGEgYnVuY2ggb2YgbGluZXMsIGZvciBicm93c2VycyB0aGF0IGNvbXB1dGVcbiAgICAgIC8vIGZyYWN0aW9uYWwgaGVpZ2h0cy5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDk7ICsraSkge1xuICAgICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcInhcIikpO1xuICAgICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChlbHQoXCJiclwiKSk7XG4gICAgICB9XG4gICAgICBtZWFzdXJlVGV4dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcInhcIikpO1xuICAgIH1cbiAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChkaXNwbGF5Lm1lYXN1cmUsIG1lYXN1cmVUZXh0KTtcbiAgICB2YXIgaGVpZ2h0ID0gbWVhc3VyZVRleHQub2Zmc2V0SGVpZ2h0IC8gNTA7XG4gICAgaWYgKGhlaWdodCA+IDMpIGRpc3BsYXkuY2FjaGVkVGV4dEhlaWdodCA9IGhlaWdodDtcbiAgICByZW1vdmVDaGlsZHJlbihkaXNwbGF5Lm1lYXN1cmUpO1xuICAgIHJldHVybiBoZWlnaHQgfHwgMTtcbiAgfVxuXG4gIC8vIENvbXB1dGUgdGhlIGRlZmF1bHQgY2hhcmFjdGVyIHdpZHRoLlxuICBmdW5jdGlvbiBjaGFyV2lkdGgoZGlzcGxheSkge1xuICAgIGlmIChkaXNwbGF5LmNhY2hlZENoYXJXaWR0aCAhPSBudWxsKSByZXR1cm4gZGlzcGxheS5jYWNoZWRDaGFyV2lkdGg7XG4gICAgdmFyIGFuY2hvciA9IGVsdChcInNwYW5cIiwgXCJ4eHh4eHh4eHh4XCIpO1xuICAgIHZhciBwcmUgPSBlbHQoXCJwcmVcIiwgW2FuY2hvcl0pO1xuICAgIHJlbW92ZUNoaWxkcmVuQW5kQWRkKGRpc3BsYXkubWVhc3VyZSwgcHJlKTtcbiAgICB2YXIgcmVjdCA9IGFuY2hvci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSwgd2lkdGggPSAocmVjdC5yaWdodCAtIHJlY3QubGVmdCkgLyAxMDtcbiAgICBpZiAod2lkdGggPiAyKSBkaXNwbGF5LmNhY2hlZENoYXJXaWR0aCA9IHdpZHRoO1xuICAgIHJldHVybiB3aWR0aCB8fCAxMDtcbiAgfVxuXG4gIC8vIE9QRVJBVElPTlNcblxuICAvLyBPcGVyYXRpb25zIGFyZSB1c2VkIHRvIHdyYXAgYSBzZXJpZXMgb2YgY2hhbmdlcyB0byB0aGUgZWRpdG9yXG4gIC8vIHN0YXRlIGluIHN1Y2ggYSB3YXkgdGhhdCBlYWNoIGNoYW5nZSB3b24ndCBoYXZlIHRvIHVwZGF0ZSB0aGVcbiAgLy8gY3Vyc29yIGFuZCBkaXNwbGF5ICh3aGljaCB3b3VsZCBiZSBhd2t3YXJkLCBzbG93LCBhbmRcbiAgLy8gZXJyb3ItcHJvbmUpLiBJbnN0ZWFkLCBkaXNwbGF5IHVwZGF0ZXMgYXJlIGJhdGNoZWQgYW5kIHR
23459oZW4gYWxsXG4gIC8vIGNvbWJpbmVkIGFuZCBleGVjdXRlZCBhdCBvbmNlLlxuXG4gIHZhciBvcGVyYXRpb25Hcm91cCA9IG51bGw7XG5cbiAgdmFyIG5leHRPcElkID0gMDtcbiAgLy8gU3RhcnQgYSBuZXcgb3BlcmF0aW9uLlxuICBmdW5jdGlvbiBzdGFydE9wZXJhdGlvbihjbSkge1xuICAgIGNtLmN1ck9wID0ge1xuICAgICAgY206IGNtLFxuICAgICAgdmlld0NoYW5nZWQ6IGZhbHNlLCAgICAgIC8vIEZsYWcgdGhhdCBpbmRpY2F0ZXMgdGhhdCBsaW5lcyBtaWdodCBuZWVkIHRvIGJlIHJlZHJhd25cbiAgICAgIHN0YXJ0SGVpZ2h0OiBjbS5kb2MuaGVpZ2h0LCAvLyBVc2VkIHRvIGRldGVjdCBuZWVkIHRvIHVwZGF0ZSBzY3JvbGxiYXJcbiAgICAgIGZvcmNlVXBkYXRlOiBmYWxzZSwgICAgICAvLyBVc2VkIHRvIGZvcmNlIGEgcmVkcmF3XG4gICAgICB1cGRhdGVJbnB1dDogbnVsbCwgICAgICAgLy8gV2hldGhlciB0byByZXNldCB0aGUgaW5wdXQgdGV4dGFyZWFcbiAgICAgIHR5cGluZzogZmFsc2UsICAgICAgICAgICAvLyBXaGV0aGVyIHRoaXMgcmVzZXQgc2hvdWxkIGJlIGNhcmVmdWwgdG8gbGVhdmUgZXhpc3RpbmcgdGV4dCAoZm9yIGNvbXBvc2l0aW5nKVxuICAgICAgY2hhbmdlT2JqczogbnVsbCwgICAgICAgIC8vIEFjY3VtdWxhdGVkIGNoYW5nZXMsIGZvciBmaXJpbmcgY2hhbmdlIGV2ZW50c1xuICAgICAgY3Vyc29yQWN0aXZpdHlIYW5kbGVyczogbnVsbCwgLy8gU2V0IG9mIGhhbmRsZXJzIHRvIGZpcmUgY3Vyc29yQWN0aXZpdHkgb25cbiAgICAgIGN1cnNvckFjdGl2aXR5Q2FsbGVkOiAwLCAvLyBUcmFja3Mgd2hpY2ggY3Vyc29yQWN0aXZpdHkgaGFuZGxlcnMgaGF2ZSBiZWVuIGNhbGxlZCBhbHJlYWR5XG4gICAgICBzZWxlY3Rpb25DaGFuZ2VkOiBmYWxzZSwgLy8gV2hldGhlciB0aGUgc2VsZWN0aW9uIG5lZWRzIHRvIGJlIHJlZHJhd25cbiAgICAgIHVwZGF0ZU1heExpbmU6IGZhbHNlLCAgICAvLyBTZXQgd2hlbiB0aGUgd2lkZXN0IGxpbmUgbmVlZHMgdG8gYmUgZGV0ZXJtaW5lZCBhbmV3XG4gICAgICBzY3JvbGxMZWZ0OiBudWxsLCBzY3JvbGxUb3A6IG51bGwsIC8vIEludGVybWVkaWF0ZSBzY3JvbGwgcG9zaXRpb24sIG5vdCBwdXNoZWQgdG8gRE9NIHlldFxuICAgICAgc2Nyb2xsVG9Qb3M6IG51bGwsICAgICAgIC8vIFVzZWQgdG8gc2Nyb2xsIHRvIGEgc3BlY2lmaWMgcG9zaXRpb25cbiAgICAgIGZvY3VzOiBmYWxzZSxcbiAgICAgIGlkOiArK25leHRPcElkICAgICAgICAgICAvLyBVbmlxdWUgSURcbiAgICB9O1xuICAgIGlmIChvcGVyYXRpb25Hcm91cCkge1xuICAgICAgb3BlcmF0aW9uR3JvdXAub3BzLnB1c2goY20uY3VyT3ApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbS5jdXJPcC5vd25zR3JvdXAgPSBvcGVyYXRpb25Hcm91cCA9IHtcbiAgICAgICAgb3BzOiBbY20uY3VyT3BdLFxuICAgICAgICBkZWxheWVkQ2FsbGJhY2tzOiBbXVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBmaXJlQ2FsbGJhY2tzRm9yT3BzKGdyb3VwKSB7XG4gICAgLy8gQ2FsbHMgZGVsYXllZCBjYWxsYmFja3MgYW5kIGN1cnNvckFjdGl2aXR5IGhhbmRsZXJzIHVudGlsIG5vXG4gICAgLy8gbmV3IG9uZXMgYXBwZWFyXG4gICAgdmFyIGNhbGxiYWNrcyA9IGdyb3VwLmRlbGF5ZWRDYWxsYmFja3MsIGkgPSAwO1xuICAgIGRvIHtcbiAgICAgIGZvciAoOyBpIDwgY2FsbGJhY2tzLmxlbmd0aDsgaSsrKVxuICAgICAgICBjYWxsYmFja3NbaV0uY2FsbChudWxsKTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZ3JvdXAub3BzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBvcCA9IGdyb3VwLm9wc1tqXTtcbiAgICAgICAgaWYgKG9wLmN1cnNvckFjdGl2aXR5SGFuZGxlcnMpXG4gICAgICAgICAgd2hpbGUgKG9wLmN1cnNvckFjdGl2aXR5Q2FsbGVkIDwgb3AuY3Vyc29yQWN0aXZpdHlIYW5kbGVycy5sZW5ndGgpXG4gICAgICAgICAgICBvcC5jdXJzb3JBY3Rpdml0eUhhbmRsZXJzW29wLmN1cnNvckFjdGl2aXR5Q2FsbGVkKytdLmNhbGwobnVsbCwgb3AuY20pO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKGkgPCBjYWxsYmFja3MubGVuZ3RoKTtcbiAgfVxuXG4gIC8vIEZpbmlzaCBhbiBvcGVyYXRpb24sIHVwZGF0aW5nIHRoZSBkaXNwbGF5IGFuZCBzaWduYWxsaW5nIGRlbGF5ZWQgZXZlbnRzXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbihjbSkge1xuICAgIHZhciBvcCA9IGNtLmN1ck9wLCBncm91cCA9IG9wLm93bnNHcm91cDtcbiAgICBpZiAoIWdyb3VwKSByZXR1cm47XG5cbiAgICB0cnkgeyBmaXJlQ2FsbGJhY2tzRm9yT3BzKGdyb3VwKTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgb3BlcmF0aW9uR3JvdXAgPSBudWxsO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBncm91cC5vcHMubGVuZ3RoOyBpKyspXG4gICAgICAgIGdyb3VwLm9wc1tpXS5jbS5jdXJPcCA9IG51bGw7XG4gICAgICBlbmRPcGVyYXRpb25zKGdyb3VwKTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgRE9NIHVwZGF0ZXMgZG9uZSB3aGVuIGFuIG9wZXJhdGlvbiBmaW5pc2hlcyBhcmUgYmF0Y2hlZCBzb1xuICAvLyB0aGF0IHRoZSBtaW5pbXVtIG51bWJlciBvZiByZWxheW91dHMgYXJlIHJlcXVpcmVkLlxuICBmdW5jdGlvbiBlbmRPcGVyYXRpb25zKGdyb3VwKSB7XG4gICAgdmFyIG9wcyA9IGdyb3VwLm9wcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9wcy5sZW5ndGg7IGkrKykgLy8gUmVhZCBET01cbiAgICAgIGVuZE9wZXJhdGlvbl9SMShvcHNbaV0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3BzLmxlbmd0aDsgaSsrKSAvLyBXcml0ZSBET00gKG1heWJlKVxuICAgICAgZW5kT3BlcmF0aW9uX1cxKG9wc1tpXSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcHMubGVuZ3RoOyBpKyspIC8vIFJlYWQgRE9NXG4gICAgICBlbmRPcGVyYXRpb25fUjIob3BzW2ldKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9wcy5sZW5ndGg7IGkrKykgLy8gV3JpdGUgRE9NIChtYXliZSlcbiAgICAgIGVuZE9wZXJhdGlvbl9XMihvcHNbaV0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3BzLmxlbmd0aDsgaSsrKSAvLyBSZWFkIERPTVxuICAgICAgZW5kT3BlcmF0aW9uX2ZpbmlzaChvcHNbaV0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZW5kT3BlcmF0aW9uX1IxKG9wKSB7XG4gICAgdmFyIGNtID0gb3AuY20sIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIG1heWJlQ2xpcFNjcm9sbGJhcnMoY20pO1xuICAgIGlmIChvcC51cGRhdGVNYXhMaW5lKSBmaW5kTWF4TGluZShjbSk7XG5cbiAgICBvcC5tdXN0VXBkYXRlID0gb3Audmlld0NoYW5nZWQgfHwgb3AuZm9yY2VVcGRhdGUgfHwgb3Auc2Nyb2xsVG9wICE9IG51bGwgfHxcbiAgICAgIG9wLnNjcm9sbFRvUG9zICYmIChvcC5zY3JvbGxUb1Bvcy5mcm9tLmxpbmUgPCBkaXNwbGF5LnZpZXdGcm9tIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgb3Auc2Nyb2xsVG9Qb3MudG8ubGluZSA+PSBkaXNwbGF5LnZpZXdUbykgfHxcbiAgICAgIGRpc3BsYXkubWF4TGluZUNoYW5nZWQgJiYgY20ub3B0aW9ucy5saW5lV3JhcHBpbmc7XG4gICAgb3AudXBkYXRlID0gb3AubXVzdFVwZGF0ZSAmJlxuICAgICAgbmV3IERpc3BsYXlVcGRhdGUoY20sIG9wLm11c3RVcGRhdGUgJiYge3RvcDogb3Auc2Nyb2xsVG9wLCBlbnN1cmU6IG9wLnNjcm9sbFRvUG9zfSwgb3AuZm9yY2VVcGRhdGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gZW5kT3BlcmF0aW9uX1cxKG9wKSB7XG4gICAgb3AudXBkYXRlZERpc3BsYXkgPSBvcC5tdXN0VXBkYXRlICYmIHVwZGF0ZURpc3BsYXlJZk5lZWRlZChvcC5jbSwgb3AudXBkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZE9wZXJhdGlvbl9SMihvcCkge1xuICAgIHZhciBjbSA9IG9wLmNtLCBkaXNwbGF5ID0gY20uZGlzcGxheTtcbiAgICBpZiAob3AudXBkYXRlZERpc3BsYXkpIHVwZGF0ZUhlaWdodHNJblZpZXdwb3J0KGNtKTtcblxuICAgIG9wLmJhck1lYXN1cmUgPSBtZWFzdXJlRm9yU2Nyb2xsYmFycyhjbSk7XG5cbiAgICAvLyBJZiB0aGUgbWF4IGxpbmUgY2hhbmdlZCBzaW5jZSBpdCB3YXMgbGFzdCBtZWFzdXJlZCwgbWVhc3VyZSBpdCxcbiAgICAvLyBhbmQgZW5zdXJlIHRoZSBkb2N1bWVudCdzIHdpZHRoIG1hdGNoZXMgaXQuXG4gICAgLy8gdXBkYXRlRGlzcGxheV9XMiB3aWxsIHVzZSB0aGVzZSBwcm9wZXJ0aWVzIHRvIGRvIHRoZSBhY3R1YWwgcmVzaXppbmdcbiAgICBpZiAoZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCAmJiAhY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHtcbiAgICAgIG9wLmFkanVzdFdpZHRoVG8gPSBtZWFzdXJlQ2hhcihjbSwgZGlzcGxheS5tYXhMaW5lLCBkaXNwbGF5Lm1heExpbmUudGV4dC5sZW5ndGgpLmxlZnQgKyAzO1xuICAgICAgY20uZGlzcGxheS5zaXplcldpZHRoID0gb3AuYWRqdXN0V2lkdGhUbztcbiAgICAgIG9wLmJhck1lYXN1cmUuc2Nyb2xsV2lkdGggPVxuICAgICAgICBNYXRoLm1heChkaXNwbGF5LnNjcm9sbGVyLmNsaWVudFdpZHRoLCBkaXNwbGF5LnNpemVyLm9mZnNldExlZnQgKyBvcC5hZGp1c3RXaWR0aFRvICsgc2Nyb2xsR2FwKGNtKSArIGNtLmRpc3BsYXkuYmFyV2lkdGgpO1xuICAgICAgb3AubWF4U2Nyb2xsTGVmdCA9IE1hdGgubWF4KDAsIGRpc3BsYXkuc2l6ZXIub2Zmc2V0TGVmdCArIG9wLmFkanVzdFdpZHRoVG8gLSBkaXNwbGF5V2lkdGgoY20pKTtcbiAgICB9XG5cbiAgICBpZiAob3AudXBkYXRlZERpc3BsYXkgfHwgb3Auc2VsZWN0aW9uQ2hhbmdlZClcbiAgICAgIG9wLnByZXBhcmVkU2VsZWN0aW9uID0gZGlzcGxheS5pbnB1dC5wcmVwYXJlU2VsZWN0aW9uKCk7XG4gIH1cblxuICBmdW5jdGlvbiBlbmRPcGVyYXRpb25fVzIob3ApIHtcbiAgICB2YXIgY20gPSBvcC5jbTtcblxuICAgIGlmIChvcC5hZGp1c3RXaWR0aFRvICE9IG51bGwpIHtcbiAgICAgIGNtLmRpc3BsYXkuc2l6ZXIuc3R5bGUubWluV2lk
23459dGggPSBvcC5hZGp1c3RXaWR0aFRvICsgXCJweFwiO1xuICAgICAgaWYgKG9wLm1heFNjcm9sbExlZnQgPCBjbS5kb2Muc2Nyb2xsTGVmdClcbiAgICAgICAgc2V0U2Nyb2xsTGVmdChjbSwgTWF0aC5taW4oY20uZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0LCBvcC5tYXhTY3JvbGxMZWZ0KSwgdHJ1ZSk7XG4gICAgICBjbS5kaXNwbGF5Lm1heExpbmVDaGFuZ2VkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKG9wLnByZXBhcmVkU2VsZWN0aW9uKVxuICAgICAgY20uZGlzcGxheS5pbnB1dC5zaG93U2VsZWN0aW9uKG9wLnByZXBhcmVkU2VsZWN0aW9uKTtcbiAgICBpZiAob3AudXBkYXRlZERpc3BsYXkpXG4gICAgICBzZXREb2N1bWVudEhlaWdodChjbSwgb3AuYmFyTWVhc3VyZSk7XG4gICAgaWYgKG9wLnVwZGF0ZWREaXNwbGF5IHx8IG9wLnN0YXJ0SGVpZ2h0ICE9IGNtLmRvYy5oZWlnaHQpXG4gICAgICB1cGRhdGVTY3JvbGxiYXJzKGNtLCBvcC5iYXJNZWFzdXJlKTtcblxuICAgIGlmIChvcC5zZWxlY3Rpb25DaGFuZ2VkKSByZXN0YXJ0QmxpbmsoY20pO1xuXG4gICAgaWYgKGNtLnN0YXRlLmZvY3VzZWQgJiYgb3AudXBkYXRlSW5wdXQpXG4gICAgICBjbS5kaXNwbGF5LmlucHV0LnJlc2V0KG9wLnR5cGluZyk7XG4gICAgaWYgKG9wLmZvY3VzICYmIG9wLmZvY3VzID09IGFjdGl2ZUVsdCgpKSBlbnN1cmVGb2N1cyhvcC5jbSk7XG4gIH1cblxuICBmdW5jdGlvbiBlbmRPcGVyYXRpb25fZmluaXNoKG9wKSB7XG4gICAgdmFyIGNtID0gb3AuY20sIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBkb2MgPSBjbS5kb2M7XG5cbiAgICBpZiAob3AudXBkYXRlZERpc3BsYXkpIHBvc3RVcGRhdGVEaXNwbGF5KGNtLCBvcC51cGRhdGUpO1xuXG4gICAgLy8gQWJvcnQgbW91c2Ugd2hlZWwgZGVsdGEgbWVhc3VyZW1lbnQsIHdoZW4gc2Nyb2xsaW5nIGV4cGxpY2l0bHlcbiAgICBpZiAoZGlzcGxheS53aGVlbFN0YXJ0WCAhPSBudWxsICYmIChvcC5zY3JvbGxUb3AgIT0gbnVsbCB8fCBvcC5zY3JvbGxMZWZ0ICE9IG51bGwgfHwgb3Auc2Nyb2xsVG9Qb3MpKVxuICAgICAgZGlzcGxheS53aGVlbFN0YXJ0WCA9IGRpc3BsYXkud2hlZWxTdGFydFkgPSBudWxsO1xuXG4gICAgLy8gUHJvcGFnYXRlIHRoZSBzY3JvbGwgcG9zaXRpb24gdG8gdGhlIGFjdHVhbCBET00gc2Nyb2xsZXJcbiAgICBpZiAob3Auc2Nyb2xsVG9wICE9IG51bGwgJiYgKGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wICE9IG9wLnNjcm9sbFRvcCB8fCBvcC5mb3JjZVNjcm9sbCkpIHtcbiAgICAgIGRvYy5zY3JvbGxUb3AgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbEhlaWdodCAtIGRpc3BsYXkuc2Nyb2xsZXIuY2xpZW50SGVpZ2h0LCBvcC5zY3JvbGxUb3ApKTtcbiAgICAgIGRpc3BsYXkuc2Nyb2xsYmFycy5zZXRTY3JvbGxUb3AoZG9jLnNjcm9sbFRvcCk7XG4gICAgICBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcCA9IGRvYy5zY3JvbGxUb3A7XG4gICAgfVxuICAgIGlmIChvcC5zY3JvbGxMZWZ0ICE9IG51bGwgJiYgKGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsTGVmdCAhPSBvcC5zY3JvbGxMZWZ0IHx8IG9wLmZvcmNlU2Nyb2xsKSkge1xuICAgICAgZG9jLnNjcm9sbExlZnQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFdpZHR
23459oIC0gZGlzcGxheVdpZHRoKGNtKSwgb3Auc2Nyb2xsTGVmdCkpO1xuICAgICAgZGlzcGxheS5zY3JvbGxiYXJzLnNldFNjcm9sbExlZnQoZG9jLnNjcm9sbExlZnQpO1xuICAgICAgZGlzcGxheS5zY3JvbGxlci5zY3JvbGxMZWZ0ID0gZG9jLnNjcm9sbExlZnQ7XG4gICAgICBhbGlnbkhvcml6b250YWxseShjbSk7XG4gICAgfVxuICAgIC8vIElmIHdlIG5lZWQgdG8gc2Nyb2xsIGEgc3BlY2lmaWMgcG9zaXRpb24gaW50byB2aWV3LCBkbyBzby5cbiAgICBpZiAob3Auc2Nyb2xsVG9Qb3MpIHtcbiAgICAgIHZhciBjb29yZHMgPSBzY3JvbGxQb3NJbnRvVmlldyhjbSwgY2xpcFBvcyhkb2MsIG9wLnNjcm9sbFRvUG9zLmZyb20pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXBQb3MoZG9jLCBvcC5zY3JvbGxUb1Bvcy50byksIG9wLnNjcm9sbFRvUG9zLm1hcmdpbik7XG4gICAgICBpZiAob3Auc2Nyb2xsVG9Qb3MuaXNDdXJzb3IgJiYgY20uc3RhdGUuZm9jdXNlZCkgbWF5YmVTY3JvbGxXaW5kb3coY20sIGNvb3Jkcyk7XG4gICAgfVxuXG4gICAgLy8gRmlyZSBldmVudHMgZm9yIG1hcmtlcnMgdGhhdCBhcmUgaGlkZGVuL3VuaWRkZW4gYnkgZWRpdGluZyBvclxuICAgIC8vIHVuZG9pbmdcbiAgICB2YXIgaGlkZGVuID0gb3AubWF5YmVIaWRkZW5NYXJrZXJzLCB1bmhpZGRlbiA9IG9wLm1heWJlVW5oaWRkZW5NYXJrZXJzO1xuICAgIGlmIChoaWRkZW4pIGZvciAodmFyIGkgPSAwOyBpIDwgaGlkZGVuLmxlbmd0aDsgKytpKVxuICAgICAgaWYgKCFoaWRkZW5baV0ubGluZXMubGVuZ3RoKSBzaWduYWwoaGlkZGVuW2ldLCBcImhpZGVcIik7XG4gICAgaWYgKHVuaGlkZGVuKSBmb3IgKHZhciBpID0gMDsgaSA8IHVuaGlkZGVuLmxlbmd0aDsgKytpKVxuICAgICAgaWYgKHVuaGlkZGVuW2ldLmxpbmVzLmxlbmd0aCkgc2lnbmFsKHVuaGlkZGVuW2ldLCBcInVuaGlkZVwiKTtcblxuICAgIGlmIChkaXNwbGF5LndyYXBwZXIub2Zmc2V0SGVpZ2h0KVxuICAgICAgZG9jLnNjcm9sbFRvcCA9IGNtLmRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wO1xuXG4gICAgLy8gRmlyZSBjaGFuZ2UgZXZlbnRzLCBhbmQgZGVsYXllZCBldmVudCBoYW5kbGVyc1xuICAgIGlmIChvcC5jaGFuZ2VPYmpzKVxuICAgICAgc2lnbmFsKGNtLCBcImNoYW5nZXNcIiwgY20sIG9wLmNoYW5nZU9ianMpO1xuICAgIGlmIChvcC51cGRhdGUpXG4gICAgICBvcC51cGRhdGUuZmluaXNoKCk7XG4gIH1cblxuICAvLyBSdW4gdGhlIGdpdmVuIGZ1bmN0aW9uIGluIGFuIG9wZXJhdGlvblxuICBmdW5jdGlvbiBydW5Jbk9wKGNtLCBmKSB7XG4gICAgaWYgKGNtLmN1ck9wKSByZXR1cm4gZigpO1xuICAgIHN0YXJ0T3BlcmF0aW9uKGNtKTtcbiAgICB0cnkgeyByZXR1cm4gZigpOyB9XG4gICAgZmluYWxseSB7IGVuZE9wZXJhdGlvbihjbSk7IH1cbiAgfVxuICAvLyBXcmFwcyBhIGZ1bmN0aW9uIGluIGFuIG9wZXJhdGlvbi4gUmV0dXJucyB0aGUgd3JhcHBlZCBmdW5jdGlvbi5cbiAgZnVuY3Rpb24gb3BlcmF0aW9uKGNtLCBmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKGNtLmN1ck9wKSByZXR1cm4gZi5hcHBseShjbSwgYXJndW1lbnRzKTtcbiAgICAgIHN0YXJ0T3BlcmF0aW9uKGNtKTtcbiAgICAgIHRyeSB7IHJldHVybiBmLmFwcGx5KGNtLCBhcmd1bWVudHMpOyB9XG4gICAgICBmaW5hbGx5IHsgZW5kT3BlcmF0aW9uKGNtKTsgfVxuICAgIH07XG4gIH1cbiAgLy8gVXNlZCB0byBhZGQgbWV0aG9kcyB0byBlZGl0b3IgYW5kIGRvYyBpbnN0YW5jZXMsIHdyYXBwaW5nIHRoZW0gaW5cbiAgLy8gb3BlcmF0aW9ucy5cbiAgZnVuY3Rpb24gbWV0aG9kT3AoZikge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmN1ck9wKSByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgc3RhcnRPcGVyYXRpb24odGhpcyk7XG4gICAgICB0cnkgeyByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyB9XG4gICAgICBmaW5hbGx5IHsgZW5kT3BlcmF0aW9uKHRoaXMpOyB9XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkb2NNZXRob2RPcChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGNtID0gdGhpcy5jbTtcbiAgICAgIGlmICghY20gfHwgY20uY3VyT3ApIHJldHVybiBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBzdGFydE9wZXJhdGlvbihjbSk7XG4gICAgICB0cnkgeyByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyB9XG4gICAgICBmaW5hbGx5IHsgZW5kT3BlcmF0aW9uKGNtKTsgfVxuICAgIH07XG4gIH1cblxuICAvLyBWSUVXIFRSQUNLSU5HXG5cbiAgLy8gVGhlc2Ugb2JqZWN0cyBhcmUgdXNlZCB0byByZXByZXNlbnQgdGhlIHZpc2libGUgKGN1cnJlbnRseSBkcmF3bilcbiAgLy8gcGFydCBvZiB0aGUgZG9jdW1lbnQuIEEgTGluZVZpZXcgbWF5IGNvcnJlc3BvbmQgdG8gbXVsdGlwbGVcbiAgLy8gbG9naWNhbCBsaW5lcywgaWYgdGhvc2UgYXJlIGNvbm5lY3RlZCBieSBjb2xsYXBzZWQgcmFuZ2VzLlxuICBmdW5jdGlvbiBMaW5lVmlldyhkb2MsIGxpbmUsIGxpbmVOKSB7XG4gICAgLy8gVGhlIHN0YXJ0aW5nIGxpbmVcbiAgICB0aGlzLmxpbmUgPSBsaW5lO1xuICAgIC8vIENvbnRpbnVpbmcgbGluZXMsIGlmIGFueVxuICAgIHRoaXMucmVzdCA9IHZpc3VhbExpbmVDb250aW51ZWQobGluZSk7XG4gICAgLy8gTnVtYmVyIG9mIGxvZ2ljYWwgbGluZXMgaW4gdGhpcyB2aXN1YWwgbGluZVxuICAgIHRoaXMuc2l6ZSA9IHRoaXMucmVzdCA/IGxpbmVObyhsc3QodGhpcy5yZXN0KSkgLSBsaW5lTiArIDEgOiAxO1xuICAgIHRoaXMubm9kZSA9IHRoaXMudGV4dCA9IG51bGw7XG4gICAgdGhpcy5oaWRkZW4gPSBsaW5lSXNIaWRkZW4oZG9jLCBsaW5lKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHJhbmdlIG9mIExpbmVWaWV3IG9iamVjdHMgZm9yIHRoZSBnaXZlbiBsaW5lcy5cbiAgZnVuY3Rpb24gYnVpbGRWaWV3QXJyYXkoY20sIGZyb20sIHRvKSB7XG4gICAgdmFyIGFycmF5ID0gW10sIG5leHRQb3M7XG4gICAgZm9yICh2YXIgcG9zID0gZnJvbTsgcG9zIDwgdG87IHBvcyA9IG5leHRQb3MpIHtcbiAgICAgIHZhciB2aWV3ID0gbmV3IExpbmVWaWV3KGNtLmRvYywgZ2V0TGluZShjbS5kb2MsIHBvcyksIHBvcyk7XG4gICAgICBuZXh0UG9zID0gcG9zICsgdmlldy5zaXplO1xuICAgICAgYXJyYXkucHVzaCh2aWV3KTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLy8gVXBkYXRlcyB0aGUgZGlzcGxheS52aWV3IGRhdGEgc3RydWN0dXJlIGZvciBhIGdpdmVuIGNoYW5nZSB0byB0aG
23459VcbiAgLy8gZG9jdW1lbnQuIEZyb20gYW5kIHRvIGFyZSBpbiBwcmUtY2hhbmdlIGNvb3JkaW5hdGVzLiBMZW5kaWZmIGlzXG4gIC8vIHRoZSBhbW91bnQgb2YgbGluZXMgYWRkZWQgb3Igc3VidHJhY3RlZCBieSB0aGUgY2hhbmdlLiBUaGlzIGlzXG4gIC8vIHVzZWQgZm9yIGNoYW5nZXMgdGhhdCBzcGFuIG11bHRpcGxlIGxpbmVzLCBvciBjaGFuZ2UgdGhlIHdheVxuICAvLyBsaW5lcyBhcmUgZGl2aWRlZCBpbnRvIHZpc3VhbCBsaW5lcy4gcmVnTGluZUNoYW5nZSAoYmVsb3cpXG4gIC8vIHJlZ2lzdGVycyBzaW5nbGUtbGluZSBjaGFuZ2VzLlxuICBmdW5jdGlvbiByZWdDaGFuZ2UoY20sIGZyb20sIHRvLCBsZW5kaWZmKSB7XG4gICAgaWYgKGZyb20gPT0gbnVsbCkgZnJvbSA9IGNtLmRvYy5maXJzdDtcbiAgICBpZiAodG8gPT0gbnVsbCkgdG8gPSBjbS5kb2MuZmlyc3QgKyBjbS5kb2Muc2l6ZTtcbiAgICBpZiAoIWxlbmRpZmYpIGxlbmRpZmYgPSAwO1xuXG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIGlmIChsZW5kaWZmICYmIHRvIDwgZGlzcGxheS52aWV3VG8gJiZcbiAgICAgICAgKGRpc3BsYXkudXBkYXRlTGluZU51bWJlcnMgPT0gbnVsbCB8fCBkaXNwbGF5LnVwZGF0ZUxpbmVOdW1iZXJzID4gZnJvbSkpXG4gICAgICBkaXNwbGF5LnVwZGF0ZUxpbmVOdW1iZXJzID0gZnJvbTtcblxuICAgIGNtLmN1ck9wLnZpZXdDaGFuZ2VkID0gdHJ1ZTtcblxuICAgIGlmIChmcm9tID49IGRpc3BsYXkudmlld1RvKSB7IC8vIENoYW5nZSBhZnRlclxuICAgICAgaWYgKHNhd0NvbGxhcHNlZFNwYW5zICYmIHZpc3VhbExpbmVObyhjbS5kb2MsIGZyb20pIDwgZGlzcGxheS52aWV3VG8pXG4gICAgICAgIHJlc2V0VmlldyhjbSk7XG4gICAgfSBlbHNlIGlmICh0byA8PSBkaXNwbGF5LnZpZXdGcm9tKSB7IC8vIENoYW5nZSBiZWZvcmVcbiAgICAgIGlmIChzYXdDb2xsYXBzZWRTcGFucyAmJiB2aXN1YWxMaW5lRW5kTm8oY20uZG9jLCB0byArIGxlbmRpZmYpID4gZGlzcGxheS52aWV3RnJvbSkge1xuICAgICAgICByZXNldFZpZXcoY20pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlzcGxheS52aWV3RnJvbSArPSBsZW5kaWZmO1xuICAgICAgICBkaXNwbGF5LnZpZXdUbyArPSBsZW5kaWZmO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZnJvbSA8PSBkaXNwbGF5LnZpZXdGcm9tICYmIHRvID49IGRpc3BsYXkudmlld1RvKSB7IC8vIEZ1bGwgb3ZlcmxhcFxuICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICB9IGVsc2UgaWYgKGZyb20gPD0gZGlzcGxheS52aWV3RnJvbSkgeyAvLyBUb3Agb3ZlcmxhcFxuICAgICAgdmFyIGN1dCA9IHZpZXdDdXR0aW5nUG9pbnQoY20sIHRvLCB0byArIGxlbmRpZmYsIDEpO1xuICAgICAgaWYgKGN1dCkge1xuICAgICAgICBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuc2xpY2UoY3V0LmluZGV4KTtcbiAgICAgICAgZGlzcGxheS52aWV3RnJvbSA9IGN1dC5saW5lTjtcbiAgICAgICAgZGlzcGxheS52aWV3VG8gKz0gbGVuZGlmZjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc2V0VmlldyhjbSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0byA+PSBkaXNwbGF5LnZpZXdUbykgeyAvLyBCb3R0b20gb3ZlcmxhcFxuICAgICAgdmFyIGN1dCA9IHZpZXdDdXR0aW5nUG9pbnQoY20sIGZyb20sIGZyb20sIC0xKTtcbiAgICAgIGlmIChjdXQpIHtcbiAgICAgICAgZGlzcGxheS52aWV3ID0gZGlzcGxheS52aWV3LnNsaWNlKDAsIGN1dC5pbmRleCk7XG4gICAgICAgIGRpc3BsYXkudmlld1RvID0gY3V0LmxpbmVOO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgeyAvLyBHYXAgaW4gdGhlIG1pZGRsZVxuICAgICAgdmFyIGN1dFRvcCA9IHZpZXdDdXR0aW5nUG9pbnQoY20sIGZyb20sIGZyb20sIC0xKTtcbiAgICAgIHZhciBjdXRCb3QgPSB2aWV3Q3V0dGluZ1BvaW50KGNtLCB0bywgdG8gKyBsZW5kaWZmLCAxKTtcbiAgICAgIGlmIChjdXRUb3AgJiYgY3V0Qm90KSB7XG4gICAgICAgIGRpc3BsYXkudmlldyA9IGRpc3BsYXkudmlldy5zbGljZSgwLCBjdXRUb3AuaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdChidWlsZFZpZXdBcnJheShjbSwgY3V0VG9wLmxpbmVOLCBjdXRCb3QubGluZU4pKVxuICAgICAgICAgIC5jb25jYXQoZGlzcGxheS52aWV3LnNsaWNlKGN1dEJvdC5pbmRleCkpO1xuICAgICAgICBkaXNwbGF5LnZpZXdUbyArPSBsZW5kaWZmO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzZXRWaWV3KGNtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXh0ID0gZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkO1xuICAgIGlmIChleHQpIHtcbiAgICAgIGlmICh0byA8IGV4dC5saW5lTilcbiAgICAgICAgZXh0LmxpbmVOICs9IGxlbmRpZmY7XG4gICAgICBlbHNlIGlmIChmcm9tIDwgZXh0LmxpbmVOICsgZXh0LnNpemUpXG4gICAgICAgIGRpc3BsYXkuZXh0ZXJuYWxNZWFzdXJlZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVnaXN0ZXIgYSBjaGFuZ2UgdG8gYSBzaW5nbGUgbGluZS4gVHlwZSBtdXN0IGJlIG9uZSBvZiBcInRleHRcIixcbiAgLy8gXCJndXR0ZXJcIiwgXCJjbGFzc1wiLCBcIndpZGdldFwiXG4gIGZ1bmN0aW9uIHJlZ0xpbmVDaGFuZ2UoY20sIGxpbmUsIHR5cGUpIHtcbiAgICBjbS5jdXJPcC52aWV3Q2hhbmdlZCA9IHRydWU7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBleHQgPSBjbS5kaXNwbGF5LmV4dGVybmFsTWVhc3VyZWQ7XG4gICAgaWYgKGV4dCAmJiBsaW5lID49IGV4dC5saW5lTiAmJiBsaW5lIDwgZXh0LmxpbmVOICsgZXh0LnNpemUpXG4gICAgICBkaXNwbGF5LmV4dGVybmFsTWVhc3VyZWQgPSBudWxsO1xuXG4gICAgaWYgKGxpbmUgPCBkaXNwbGF5LnZpZXdGcm9tIHx8IGxpbmUgPj0gZGlzcGxheS52aWV3VG8pIHJldHVybjtcbiAgICB2YXIgbGluZVZpZXcgPSBkaXNwbGF5LnZpZXdbZmluZFZpZXdJbmRleChjbSwgbGluZSldO1xuICAgIGlmIChsaW5lVmlldy5ub2RlID09IG51bGwpIHJldHVybjtcbiAgICB2YXIgYXJyID0gbGluZVZpZXcuY2hhbmdlcyB8fCAobGluZVZpZXcuY2hhbmdlcyA9IFtdKTtcbiAgICBpZiAoaW5kZX
23459hPZihhcnIsIHR5cGUpID09IC0xKSBhcnIucHVzaCh0eXBlKTtcbiAgfVxuXG4gIC8vIENsZWFyIHRoZSB2aWV3LlxuICBmdW5jdGlvbiByZXNldFZpZXcoY20pIHtcbiAgICBjbS5kaXNwbGF5LnZpZXdGcm9tID0gY20uZGlzcGxheS52aWV3VG8gPSBjbS5kb2MuZmlyc3Q7XG4gICAgY20uZGlzcGxheS52aWV3ID0gW107XG4gICAgY20uZGlzcGxheS52aWV3T2Zmc2V0ID0gMDtcbiAgfVxuXG4gIC8vIEZpbmQgdGhlIHZpZXcgZWxlbWVudCBjb3JyZXNwb25kaW5nIHRvIGEgZ2l2ZW4gbGluZS4gUmV0dXJuIG51bGxcbiAgLy8gd2hlbiB0aGUgbGluZSBpc24ndCB2aXNpYmxlLlxuICBmdW5jdGlvbiBmaW5kVmlld0luZGV4KGNtLCBuKSB7XG4gICAgaWYgKG4gPj0gY20uZGlzcGxheS52aWV3VG8pIHJldHVybiBudWxsO1xuICAgIG4gLT0gY20uZGlzcGxheS52aWV3RnJvbTtcbiAgICBpZiAobiA8IDApIHJldHVybiBudWxsO1xuICAgIHZhciB2aWV3ID0gY20uZGlzcGxheS52aWV3O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgbiAtPSB2aWV3W2ldLnNpemU7XG4gICAgICBpZiAobiA8IDApIHJldHVybiBpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHZpZXdDdXR0aW5nUG9pbnQoY20sIG9sZE4sIG5ld04sIGRpcikge1xuICAgIHZhciBpbmRleCA9IGZpbmRWaWV3SW5kZXgoY20sIG9sZE4pLCBkaWZmLCB2aWV3ID0gY20uZGlzcGxheS52aWV3O1xuICAgIGlmICghc2F3Q29sbGFwc2VkU3BhbnMgfHwgbmV3TiA9PSBjbS5kb2MuZmlyc3QgKyBjbS5kb2Muc2l6ZSlcbiAgICAgIHJldHVybiB7aW5kZXg6IGluZGV4LCBsaW5lTjogbmV3Tn07XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBjbS5kaXNwbGF5LnZpZXdGcm9tOyBpIDwgaW5kZXg7IGkrKylcbiAgICAgIG4gKz0gdmlld1tpXS5zaXplO1xuICAgIGlmIChuICE9IG9sZE4pIHtcbiAgICAgIGlmIChkaXIgPiAwKSB7XG4gICAgICAgIGlmIChpbmRleCA9PSB2aWV3Lmxlbmd0aCAtIDEpIHJldHVybiBudWxsO1xuICAgICAgICBkaWZmID0gKG4gKyB2aWV3W2luZGV4XS5zaXplKSAtIG9sZE47XG4gICAgICAgIGluZGV4Kys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaWZmID0gbiAtIG9sZE47XG4gICAgICB9XG4gICAgICBvbGROICs9IGRpZmY7IG5ld04gKz0gZGlmZjtcbiAgICB9XG4gICAgd2hpbGUgKHZpc3VhbExpbmVObyhjbS5kb2MsIG5ld04pICE9IG5ld04pIHtcbiAgICAgIGlmIChpbmRleCA9PSAoZGlyIDwgMCA/IDAgOiB2aWV3Lmxlbmd0aCAtIDEpKSByZXR1cm4gbnVsbDtcbiAgICAgIG5ld04gKz0gZGlyICogdmlld1tpbmRleCAtIChkaXIgPCAwID8gMSA6IDApXS5zaXplO1xuICAgICAgaW5kZXggKz0gZGlyO1xuICAgIH1cbiAgICByZXR1cm4ge2luZGV4OiBpbmRleCwgbGluZU46IG5ld059O1xuICB9XG5cbiAgLy8gRm9yY2UgdGhlIHZpZXcgdG8gY292ZXIgYSBnaXZlbiByYW5nZSwgYWRkaW5nIGVtcHR5IHZpZXcgZWxlbWVudFxuICAvLyBvciBjbGlwcGluZyBvZmYgZXhpc3Rpbmcgb25lcyBhcyBuZWVkZWQuXG4gIGZ1bmN0aW9uIGFkanVzdFZpZXcoY20sIGZyb20sIHRvKSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCB2aWV3ID0gZGlzcGxheS52aWV3O1xuICAgIGlmICh2aWV3Lmxlbmd0aCA9PSAwIHx8IGZyb20gPj0gZGlzcGxheS52aWV3VG8gfHwgdG8gPD0gZGlzcGxheS52aWV3RnJvbSkge1xuICAgICAgZGlzcGxheS52aWV3ID0gYnVpbGRWaWV3QXJyYXkoY20sIGZyb20sIHRvKTtcbiAgICAgIGRpc3BsYXkudmlld0Zyb20gPSBmcm9tO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoZGlzcGxheS52aWV3RnJvbSA+IGZyb20pXG4gICAgICAgIGRpc3BsYXkudmlldyA9IGJ1aWxkVmlld0FycmF5KGNtLCBmcm9tLCBkaXNwbGF5LnZpZXdGcm9tKS5jb25jYXQoZGlzcGxheS52aWV3KTtcbiAgICAgIGVsc2UgaWYgKGRpc3BsYXkudmlld0Zyb20gPCBmcm9tKVxuICAgICAgICBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuc2xpY2UoZmluZFZpZXdJbmRleChjbSwgZnJvbSkpO1xuICAgICAgZGlzcGxheS52aWV3RnJvbSA9IGZyb207XG4gICAgICBpZiAoZGlzcGxheS52aWV3VG8gPCB0bylcbiAgICAgICAgZGlzcGxheS52aWV3ID0gZGlzcGxheS52aWV3LmNvbmNhdChidWlsZFZpZXdBcnJheShjbSwgZGlzcGxheS52aWV3VG8sIHRvKSk7XG4gICAgICBlbHNlIGlmIChkaXNwbGF5LnZpZXdUbyA+IHRvKVxuICAgICAgICBkaXNwbGF5LnZpZXcgPSBkaXNwbGF5LnZpZXcuc2xpY2UoMCwgZmluZFZpZXdJbmRleChjbSwgdG8pKTtcbiAgICB9XG4gICAgZGlzcGxheS52aWV3VG8gPSB0bztcbiAgfVxuXG4gIC8vIENvdW50IHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhlIHZpZXcgd2hvc2UgRE9NIHJlcHJlc2VudGF0aW9uIGlzXG4gIC8vIG91dCBvZiBkYXRlIChvciBub25leGlzdGVudCkuXG4gIGZ1bmN0aW9uIGNvdW50RGlydHlWaWV3KGNtKSB7XG4gICAgdmFyIHZpZXcgPSBjbS5kaXNwbGF5LnZpZXcsIGRpcnR5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZpZXcubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBsaW5lVmlldyA9IHZpZXdbaV07XG4gICAgICBpZiAoIWxpbmVWaWV3LmhpZGRlbiAmJiAoIWxpbmVWaWV3Lm5vZGUgfHwgbGluZVZpZXcuY2hhbmdlcykpICsrZGlydHk7XG4gICAgfVxuICAgIHJldHVybiBkaXJ0eTtcbiAgfVxuXG4gIC8vIEVWRU5UIEhBTkRMRVJTXG5cbiAgLy8gQXR0YWNoIHRoZSBuZWNlc3NhcnkgZXZlbnQgaGFuZGxlcnMgd2hlbiBpbml0aWFsaXppbmcgdGhlIGVkaXRvclxuICBmdW5jdGlvbiByZWdpc3RlckV2ZW50SGFuZGxlcnMoY20pIHtcbiAgICB2YXIgZCA9IGNtLmRpc3BsYXk7XG4gICAgb24oZC5zY3JvbGxlciwgXCJtb3VzZWRvd25cIiwgb3BlcmF0aW9uKGNtLCBvbk1vdXNlRG93bikpO1xuICAgIC8vIE9sZGVyIElFJ3Mgd2lsbCBub3QgZmlyZSBhIHNlY29uZCBtb3VzZWRvd24gZm9yIGEgZG91YmxlIGNsaWNrXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCAxMSlcbiAgICAgIG9uKGQuc2Nyb2xsZXIsIFwiZGJsY2xpY2tcIiwgb3BlcmF0aW9uKGNtLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlmIChzaWduYWxET01FdmVudChjbSwgZSkpIHJldHVybjtcbiAgICAgICAgdmFyIHBvcyA9IHBvc0Zyb21Nb3VzZShjbSwgZSk7XG4gICAgICAgIGlmICghcG9zIHx8IGNsaWNrSW5HdXR0ZXIoY20sIGUpIHx8IGV2ZW50SW5XaWRnZXQ
23459oY20uZGlzcGxheSwgZSkpIHJldHVybjtcbiAgICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgICAgdmFyIHdvcmQgPSBjbS5maW5kV29yZEF0KHBvcyk7XG4gICAgICAgIGV4dGVuZFNlbGVjdGlvbihjbS5kb2MsIHdvcmQuYW5jaG9yLCB3b3JkLmhlYWQpO1xuICAgICAgfSkpO1xuICAgIGVsc2VcbiAgICAgIG9uKGQuc2Nyb2xsZXIsIFwiZGJsY2xpY2tcIiwgZnVuY3Rpb24oZSkgeyBzaWduYWxET01FdmVudChjbSwgZSkgfHwgZV9wcmV2ZW50RGVmYXVsdChlKTsgfSk7XG4gICAgLy8gU29tZSBicm93c2VycyBmaXJlIGNvbnRleHRtZW51ICphZnRlciogb3BlbmluZyB0aGUgbWVudSwgYXRcbiAgICAvLyB3aGljaCBwb2ludCB3ZSBjYW4ndCBtZXNzIHdpdGggaXQgYW55bW9yZS4gQ29udGV4dCBtZW51IGlzXG4gICAgLy8gaGFuZGxlZCBpbiBvbk1vdXNlRG93biBmb3IgdGhlc2UgYnJvd3NlcnMuXG4gICAgaWYgKCFjYXB0dXJlUmlnaHRDbGljaykgb24oZC5zY3JvbGxlciwgXCJjb250ZXh0bWVudVwiLCBmdW5jdGlvbihlKSB7b25Db250ZXh0TWVudShjbSwgZSk7fSk7XG5cbiAgICAvLyBVc2VkIHRvIHN1cHByZXNzIG1vdXNlIGV2ZW50IGhhbmRsaW5nIHdoZW4gYSB0b3VjaCBoYXBwZW5zXG4gICAgdmFyIHRvdWNoRmluaXNoZWQsIHByZXZUb3VjaCA9IHtlbmQ6IDB9O1xuICAgIGZ1bmN0aW9uIGZpbmlzaFRvdWNoKCkge1xuICAgICAgaWYgKGQuYWN0aXZlVG91Y2gpIHtcbiAgICAgICAgdG91Y2hGaW5pc2hlZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7ZC5hY3RpdmVUb3VjaCA9IG51bGw7fSwgMTAwMCk7XG4gICAgICAgIHByZXZUb3VjaCA9IGQuYWN0aXZlVG91Y2g7XG4gICAgICAgIHByZXZUb3VjaC5lbmQgPSArbmV3IERhdGU7XG4gICAgICB9XG4gICAgfTtcbiAgICBmdW5jdGlvbiBpc01vdXNlTGlrZVRvdWNoRXZlbnQoZSkge1xuICAgICAgaWYgKGUudG91Y2hlcy5sZW5ndGggIT0gMSkgcmV0dXJuIGZhbHNlO1xuICAgICAgdmFyIHRvdWNoID0gZS50b3VjaGVzWzBdO1xuICAgICAgcmV0dXJuIHRvdWNoLnJhZGl1c1ggPD0gMSAmJiB0b3VjaC5yYWRpdXNZIDw9IDE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGZ
23459hckF3YXkodG91Y2gsIG90aGVyKSB7XG4gICAgICBpZiAob3RoZXIubGVmdCA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcbiAgICAgIHZhciBkeCA9IG90aGVyLmxlZnQgLSB0b3VjaC5sZWZ0LCBkeSA9IG90aGVyLnRvcCAtIHRvdWNoLnRvcDtcbiAgICAgIHJldHVybiBkeCAqIGR4ICsgZHkgKiBkeSA+IDIwICogMjA7XG4gICAgfVxuICAgIG9uKGQuc2Nyb2xsZXIsIFwidG91Y2hzdGFydFwiLCBmdW5jdGlvbihlKSB7XG4gICAgICBpZiAoIWlzTW91c2VMaWtlVG91Y2hFdmVudChlKSkge1xuICAgICAgICBjbGVhclRpbWVvdXQodG91Y2hGaW5pc2hlZCk7XG4gICAgICAgIHZhciBub3cgPSArbmV3IERhdGU7XG4gICAgICAgIGQuYWN0aXZlVG91Y2ggPSB7c3RhcnQ6IG5vdywgbW92ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHByZXY6IG5vdyAtIHByZXZUb3VjaC5lbmQgPD0gMzAwID8gcHJldlRvdWNoIDogbnVsbH07XG4gICAgICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICBkLmFjdGl2ZVRvdWNoLmxlZnQgPSBlLnRvdWNoZXNbMF0ucGFnZVg7XG4gICAgICAgICAgZC5hY3RpdmVUb3VjaC50b3AgPSBlLnRvdWNoZXNbMF0ucGFnZVk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICBvbihkLnNjcm9sbGVyLCBcInRvdWNobW92ZVwiLCBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChkLmFjdGl2ZVRvdWNoKSBkLmFjdGl2ZVRvdWNoLm1vdmVkID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBvbihkLnNjcm9sbGVyLCBcInRvdWNoZW5kXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciB0b3VjaCA9IGQuYWN0aXZlVG91Y2g7XG4gICAgICBpZiAodG91Y2ggJiYgIWV2ZW50SW5XaWRnZXQoZCwgZSkgJiYgdG91Y2gubGVmdCAhPSBudWxsICYmXG4gICAgICAgICAgIXRvdWNoLm1vdmVkICYmIG5ldyBEYXRlIC0gdG91Y2guc3RhcnQgPCAzMDApIHtcbiAgICAgICAgdmFyIHBvcyA9IGNtLmNvb3Jkc0NoYX
23459IoZC5hY3RpdmVUb3VjaCwgXCJwYWdlXCIpLCByYW5nZTtcbiAgICAgICAgaWYgKCF0b3VjaC5wcmV2IHx8IGZhckF3YXkodG91Y2gsIHRvdWNoLnByZXYpKSAvLyBTaW5nbGUgdGFwXG4gICAgICAgICAgcmFuZ2UgPSBuZXcgUmFuZ2UocG9zLCBwb3MpO1xuICAgICAgICBlbHNlIGlmICghdG91Y2gucHJldi5wcmV2IHx8IGZhckF3YXkodG91Y2gsIHRvdWNoLnByZXYucHJldikpIC8vIERvdWJsZSB0YXBcbiAgICAgICAgICByYW5nZSA9IGNtLmZpbmRXb3JkQXQocG9zKTtcbiAgICAgICAgZWxzZSAvLyBUcmlwbGUgdGFwXG4gICAgICAgICAgcmFuZ2UgPSBuZXcgUmFuZ2UoUG9zKHBvcy5saW5lLCAwKSwgY2xpcFBvcyhjbS5kb2MsIFBvcyhwb3MubGluZSArIDEsIDApKSk7XG4gICAgICAgIGNtLnNldFNlbGVjdGlvbihyYW5nZS5hbmNob3IsIHJhbmdlLmhlYWQpO1xuICAgICAgICBjbS5mb2N1cygpO1xuICAgICAgICBlX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgfVxuICAgICAgZmluaXNoVG91Y2goKTtcbiAgICB9KTtcbiAgICBvbihkLnNjcm9sbGVyLCBcInRvdWNoY2FuY2VsXCIsIGZpbmlzaFRvdWNoKTtcblxuICAgIC8vIFN5bmMgc2Nyb2xsaW5nIGJldHdlZW4gZmFrZSBzY3JvbGxiYXJzIGFuZCByZWFsIHNjcm9sbGFibGVcbiAgICAvLyBhcmVhLCBlbnN1cmUgdmlld3BvcnQgaXMgdXBkYXRlZCB3aGVuIHNjcm9sbGluZy5cbiAgICBvbihkLnNjcm9sbGVyLCBcInNjcm9sbFwiLCBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChkLnNjcm9sbGVyLmNsaWVudEhlaWdodCkge1xuICAgICAgICBzZXRTY3JvbGxUb3AoY20sIGQuc2Nyb2xsZXIuc2Nyb2xsVG9wKTtcbiAgICAgICAgc2V0U2Nyb2xsTGVmdChjbSwgZC5zY3JvbGxlci5zY3JvbGxMZWZ0LCB0cnVlKTtcbiAgICAgICAgc2lnbmFsKGNtLCBcInNjcm9sbFwiLCBjbSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBMaXN0ZW4gdG8gd2hlZWwgZXZlbnRzIGluIG9yZGVyIHRvIHRyeSBhbmQgdXBkYXRlIHRoZSB2aWV3cG9ydCBvbiB0aW1lLlxuICAgIG9uKGQuc2Nyb2xsZXIsIFwibW91c2V3aGVlbFwiLCBmdW5jdGlvbihlKXtvblNjcm9sbFdoZWVsKGNtLCBlKTt9KTtcbiAgICBvbihkLnNjcm9sbGVyLCBcIkRPTU1vdXNlU2Nyb2xsXCIsIGZ1bmN0aW9uKGUpe29uU2Nyb2xsV2hlZWwoY20sIGUpO30pO1xuXG4gICAgLy8gUHJldmVudCB3cmFwcGVyIGZyb20gZXZlciBzY3JvbGxpbmdcbiAgICBvbihkLndyYXBwZXIsIFwic2Nyb2xsXCIsIGZ1bmN0aW9uKCkgeyBkLndyYXBwZXIuc2Nyb2xsVG9wID0gZC53cmFwcGVyLnNjcm9sbExlZnQgPSAwOyB9KTtcblxuICAgIGQuZHJhZ0Z1bmN0aW9ucyA9IHtcbiAgICAgIGVudGVyOiBmdW5jdGlvbihlKSB7aWYgKCFzaWduYWxET01FdmVudChjbSwgZSkpIGVfc3RvcChlKTt9LFxuICAgICAgb3ZlcjogZnVuY3Rpb24oZSkge2lmICghc2lnbmFsRE9NRXZlbnQoY20sIGUpKSB7IG9uRHJhZ092ZXIoY20sIGUpOyBlX3N0b3AoZSk7IH19LFxuICAgICAgc3RhcnQ6IGZ1bmN0aW9uKGUpe29uRHJhZ1N0YXJ0KGNtLCBlKTt9LFxuICAgICAgZHJvcDogb3BlcmF0aW9uKGNtLCBvbkRyb3ApLFxuICAgICAgbGVhdmU6IGZ1bmN0aW9uKCkge2NsZWFyRHJhZ0N1cnNvcihjbSk7fVxuICAgIH07XG5cbiAgICB2YXIgaW5wID0gZC5pbnB1dC5nZXRGaWVsZCgpO1xuICAgIG9uKGlucCwgXCJrZXl1cFwiLCBmdW5jdGlvbihlKSB7IG9uS2V5VXAuY2FsbChjbSwgZSk7IH0pO1xuICAgIG9uKGlucCwgXCJrZXlkb3duXCIsIG9wZXJhdGlvbihjbSwgb25LZXlEb3duKSk7XG4gICAgb24oaW5wLCBcImtleXByZXNzXCIsIG9wZXJhdGlvbihjbSwgb25LZXlQcmVzcykpO1xuICAgIG9uKGlucCwgXCJmb2N1c1wiLCBiaW5kKG9uRm9jdXMsIGNtKSk7XG4gICAgb24oaW5wLCBcImJsdXJcIiwgYmluZChvbkJsdXIsIGNtKSk7XG4gIH1cblxuICBmdW5jdGlvbiBkcmFnRHJvcENoYW5nZWQoY20sIHZhbHVlLCBvbGQpIHtcbiAgICB2YXIgd2FzT24gPSBvbGQgJiYgb2xkICE9IENvZGVNaXJyb3IuSW5pdDtcbiAgICBpZiAoIXZhbHVlICE9ICF3YXNPbikge1xuICAgICAgdmFyIGZ1bmNzID0gY20uZGlzcGxheS5kcmFnRnVuY3Rpb25zO1xuICAgICAgdmFyIHRvZ2dsZSA9IHZhbHVlID8gb24gOiBvZmY7XG4gICAgICB0b2dnbGUoY20uZGlzcGxheS5zY3JvbGxlciwgXCJkcmFnc3RhcnRcIiwgZnVuY3Muc3RhcnQpO1xuICAgICAgdG9nZ2xlKGNtLmRpc3BsYXkuc2Nyb2xsZXIsIFwiZHJhZ2VudGVyXCIsIGZ1bmNzLmVudGVyKTtcbiAgICAgIHRvZ2dsZShjbS5kaXNwbGF5LnNjcm9sbGVyLCBcImRyYWdvdmVyXCIsIGZ1bmNzLm92ZXIpO1xuICAgICAgdG9nZ2xlKGNtLmRpc3BsYXkuc2Nyb2xsZXIsIFwiZHJhZ2xlYXZlXCIsIGZ1bmNzLmxlYXZlKTtcbiAgICAgIHRvZ2dsZShjbS5kaXNwbGF5LnNjcm9sbGVyLCBcImRyb3BcIiwgZnVuY3MuZHJvcCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ2FsbGVkIHdoZW4gdGhlIHdpbmRvdyByZXNpemVzXG4gIGZ1bmN0aW9uIG9uUmVzaXplKGNtKSB7XG4gICAgdmFyIGQgPSBjbS5kaXNwbGF5O1xuICAgIGlmIChkLmxhc3RXcmFwSGVpZ2h0ID09IGQud3JhcHBlci5jbGllbnRIZWlnaHQgJiYgZC5sYXN0V3JhcFdpZHRoID09IGQud3JhcHBlci5jbGllbnRXaWR0aClcbiAgICAgIHJldHVybjtcbiAgICAvLyBNaWdodCBiZSBhIHRleHQgc2NhbGluZyBvcGVyYXRpb24sIGNsZWFyIHNpemUgY2FjaGVzLlxuICAgIGQuY2FjaGVkQ2hhcldpZHRoID0gZC5jYWNoZWRUZXh0SGVpZ2h0ID0gZC5jYWNoZWRQYWRkaW5nSCA9IG51bGw7XG4gICAgZC5zY3JvbGxiYXJzQ2xpcHBlZCA9IGZhbHNlO1xuICAgIGNtLnNldFNpemUoKTtcbiAgfVxuXG4gIC8vIE1PVVNFIEVWRU5UU1xuXG4gIC8vIFJldHVybiB0cnVlIHdoZW4gdGhlIGdpdmVuIG1vdXNlIGV2ZW50IGhhcHBlbmVkIGluIGEgd2lkZ2V0XG4gIGZ1bmN0aW9uIGV2ZW50SW5XaWRnZXQoZGlzcGxheSwgZSkge1xuICAgIGZvciAodmFyIG4gPSBlX3RhcmdldChlKTsgbiAhPSBkaXNwbGF5LndyYXBwZXI7IG4gPSBuLnBhcmVudE5vZGUpIHtcbiAgICAgIGlmICghbiB8fCAobi5ub2RlVHlwZSA9PSAxICYmIG4uZ2V0QXR0cmlidXRlKFwiY20taWdub3JlLWV2ZW50c1wiKSA9PSBcInRydWVcIikgfHxcbiAgICAgICAgICAobi5wYXJlbnROb2RlID09IGRpc3BsYXkuc2l6ZXIgJiYgbiAhPSBkaXNwbGF5Lm1vdmVyKSlcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gR2l2ZW4gYSBtb3VzZSBldmVudCwgZmluZCB0aGUgY29ycmVzcG9uZGluZyBwb3NpdGlvbi4gSWYgbGliZXJhbFxuICAvLyBpcyBmYWxzZSwgaXQgY2hlY2tzIHdoZXRoZXIgYSBndXR0ZXIgb3Igc2Nyb2xsYmFyIHdhcyBjbGlja2VkLFxuICAvLyBhbmQgcmV0dXJucyBudWxsIGlmIGl0IHdhcy4gZm9yUmVjdCBpcyB1c2VkIGJ5IHJlY3Rhbmd1bGFyXG4gIC8vIHNlbGVjdGlvbnMsIGFuZCB0cmllcyB0byBlc3RpbWF0ZSBhIGNoYXJhY3RlciBwb3NpdGlvbiBldmVuIGZvclxuICAvLyBjb29yZGluYX
23459RlcyBiZXlvbmQgdGhlIHJpZ2h0IG9mIHRoZSB0ZXh0LlxuICBmdW5jdGlvbiBwb3NGcm9tTW91c2UoY20sIGUsIGxpYmVyYWwsIGZvclJlY3QpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKCFsaWJlcmFsICYmIGVfdGFyZ2V0KGUpLmdldEF0dHJpYnV0ZShcImNtLW5vdC1jb250ZW50XCIpID09IFwidHJ1ZVwiKSByZXR1cm4gbnVsbDtcblxuICAgIHZhciB4LCB5LCBzcGFjZSA9IGRpc3BsYXkubGluZVNwYWNlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIC8vIEZhaWxzIHVucHJlZGljdGFibHkgb24gSUVbNjddIHdoZW4gbW91c2UgaXMgZHJhZ2dlZCBhcm91bmQgcXVpY2tseS5cbiAgICB0cnkgeyB4ID0gZS5jbGllbnRYIC0gc3BhY2UubGVmdDsgeSA9IGUuY2xpZW50WSAtIHNwYWNlLnRvcDsgfVxuICAgIGNhdGNoIChlKSB7IHJldHVybiBudWxsOyB9XG4gICAgdmFyIGNvb3JkcyA9IGNvb3Jkc0NoYXIoY20sIHgsIHkpLCBsaW5lO1xuICAgIGlmIChmb3JSZWN0ICYmIGNvb3Jkcy54UmVsID09IDEgJiYgKGxpbmUgPSBnZXRMaW5lKGNtLmRvYywgY29vcmRzLmxpbmUpLnRleHQpLmxlbmd0aCA9PSBjb29yZHMuY2gpIHtcbiAgICAgIHZhciBjb2xEaWZmID0gY291bnRDb2x1bW4obGluZSwgbGluZS5sZW5ndGgsIGNtLm9wdGlvbnMudGFiU2l6ZSkgLSBsaW5lLmxlbmd0aDtcbiAgICAgIGNvb3JkcyA9IFBvcyhjb29yZHMubGluZSwgTWF0aC5tYXgoMCwgTWF0aC5yb3VuZCgoeCAtIHBhZGRpbmdIKGNtLmRpc3BsYXkpLmxlZnQpIC8gY2hhcldpZHRoKGNtLmRpc3BsYXkpKSAtIGNvbERpZmYpKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvb3JkcztcbiAgfVxuXG4gIC8vIEEgbW91c2UgZG93biBjYW4gYmUgYSBzaW5nbGUgY2xpY2ssIGRvdWJsZSBjbGljaywgdHJpcGxlIGNsaWNrLFxuICAvLyBzdGFydCBvZiBzZWxlY3Rpb24gZHJhZywgc3RhcnQgb2YgdGV4dCBkcmFnLCBuZXcgY3Vyc29yXG4gIC8vIChjdHJsLWNsaWNrKSwgcmVjdGFuZ2xlIGRyYWcgKGFsdC1kcmFnKSwgb3IgeHdpblxuICAvLyBtaWRkbGUtY2xpY2stcGFzdGUuIE9yIGl0IG1pZ2h0IGJlIGEgY2xpY2sgb24gc29tZXRoaW5nIHdlIHNob3VsZFxuICAvLyBub3QgaW50ZXJmZXJlIHdpdGgsIHN1Y2ggYXMgYSBzY3JvbGxiYXIgb3Igd2lkZ2V0LlxuICBmdW5jdGlvbiBvbk1vdXNlRG93bihlKSB7XG4gICAgdmFyIGNtID0gdGhpcywgZGlzcGxheSA9IGNtLmRpc3BsYXk7XG4gICAgaWYgKGRpc3BsYXkuYWN0aXZlVG91Y2ggJiYgZGlzcGxheS5pbnB1dC5zdXBwb3J0c1RvdWNoKCkgfHwgc2lnbmFsRE9NRXZlbnQoY20sIGUpKSByZXR1cm47XG4gICAgZGlzcGxheS5zaGlmdCA9IGUuc2hpZnRLZXk7XG5cbiAgICBpZiAoZXZlbnRJbldpZGdldChkaXNwbGF5LCBlKSkge1xuICAgICAgaWYgKCF3ZWJraXQpIHtcbiAgICAgICAgLy8gQnJpZWZseSB0dXJuIG9mZiBkcmFnZ2FiaWxpdHksIHRvIGFsbG93IHdpZGdldHMgdG8gZG9cbiAgICAgICAgLy8gbm9ybWFsIGRyYWdnaW5nIHRoaW5ncy5cbiAgICAgICAgZGlzcGxheS5zY3JvbGxlci5kcmFnZ2FibGUgPSBmYWxzZTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpe2Rpc3BsYXkuc2Nyb2xsZXIuZHJhZ2dhYmxlID0gdHJ1ZTt9LCAxMDApO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoY2xpY2tJbkd1dHRlcihjbSwgZSkpIHJldHVybjtcbiAgICB2YXIgc3RhcnQgPSBwb3NGcm9tTW91c2UoY20sIGUpO1xuICAgIHdpbmRvdy5mb2N1cygpO1xuXG4gICAgc3dpdGNoIChlX2J1dHRvbihlKSkge1xuICAgIGNhc2UgMTpcbiAgICAgIC8vICMzMjYxOiBtYWtlIHN1cmUsIHRoYXQgd2UncmUgbm90IHN0YXJ0aW5nIGEgc2Vjb25kIHNlbGVjdGlvblxuICAgICAgaWYgKGNtLnN0YXRlLnNlbGVjdGluZ1RleHQpXG4gICAgICAgIGNtLnN0YXRlLnNlbGVjdGluZ1RleHQoZSk7XG4gICAgICBlbHNlIGlmIChzdGFydClcbiAgICAgICAgbGVmdEJ1dHRvbkRvd24oY20sIGUsIHN0YXJ0KTtcbiAgICAgIGVsc2UgaWYgKGVfdGFyZ2V0KGUpID09IGRpc3BsYXkuc2Nyb2xsZXIpXG4gICAgICAgIGVfcHJldmVudERlZmF1bHQoZSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBpZiAod2Via2l0KSBjbS5zdGF0ZS5sYXN0TWlkZGxlRG93biA9ICtuZXcgRGF0ZTtcbiAgICAgIGlmIChzdGFydCkgZXh0ZW5kU2VsZWN0aW9uKGNtLmRvYywgc3RhcnQpO1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtkaXNwbGF5LmlucHV0LmZvY3VzKCk7fSwgMjApO1xuICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMzpcbiAgICAgIGlmIChjYXB0dXJlUmlnaHRDbGljaykgb25Db250ZXh0TWVudShjbSwgZSk7XG4gICAgICBlbHNlIGRlbGF5Qmx1ckV2ZW50KGNtKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHZhciBsYXN0Q2xpY2ssIGxhc3REb3VibGVDbGljaztcbiAgZnVuY3Rpb24gbGVmdEJ1dHRvbkRvd24oY20sIGUsIHN0YXJ0KSB7XG4gICAgaWYgKGllKSBzZXRUaW1lb3V0KGJpbmQoZW5zdXJlRm9jdXMsIGNtKSwgMCk7XG4gICAgZWxzZSBjbS5jdXJPcC5mb2N1cyA9IGFjdGl2ZUVsdCgpO1xuXG4gICAgdmFyIG5vdyA9ICtuZXcgRGF0ZSwgdHlwZTtcbiAgICBpZiAobGFzdERvdWJsZUNsaWNrICYmIGxhc3REb3VibGVDbGljay50aW1lID4gbm93IC0gNDAwICYmIGNtcChsYXN0RG91YmxlQ2xpY2sucG9zLCBzdGFydCkgPT0gMCkge1xuICAgICAgdHlwZSA9IFwidHJpcGxlXCI7XG4gICAgfSBlbHNlIGlmIChsYXN0Q2xpY2sgJiYgbGFzdENsaWNrLnRpbWUgPiBub3cgLSA0MDAgJiYgY21wKGxhc3RDbGljay5wb3MsIHN0YXJ0KSA9PSAwKSB7XG4gICAgICB0eXBlID0gXCJkb3VibGVcIjtcbiAgICAgIGxhc3REb3VibGVDbGljayA9IHt0aW1lOiBub3csIHBvczogc3RhcnR9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0eXBlID0gXCJzaW5nbGVcIjtcbiAgICAgIGxhc3RDbGljayA9IHt0aW1lOiBub3csIHBvczogc3RhcnR9O1xuICAgIH1cblxuICAgIHZhciBzZWwgPSBjbS5kb2Muc2VsLCBtb2RpZmllciA9IG1hYyA/IGUubWV0YUtleSA6IGUuY3RybEtleSwgY29udGFpbmVkO1xuICAgIGlmIChjbS5vcHRpb25zLmRyYWdEcm9wICYmIGRyYWdBbmREcm9wICYmICFpc1JlYWRPbmx5KGNtKSAmJlxuICAgICAgICB0eX
23459BlID09IFwic2luZ2xlXCIgJiYgKGNvbnRhaW5lZCA9IHNlbC5jb250YWlucyhzdGFydCkpID4gLTEgJiZcbiAgICAgICAgKGNtcCgoY29udGFpbmVkID0gc2VsLnJhbmdlc1tjb250YWluZWRdKS5mcm9tKCksIHN0YXJ0KSA8IDAgfHwgc3RhcnQueFJlbCA+IDApICYmXG4gICAgICAgIChjbXAoY29udGFpbmVkLnRvKCksIHN0YXJ0KSA+IDAgfHwgc3RhcnQueFJlbCA8IDApKVxuICAgICAgbGVmdEJ1dHRvblN0YXJ0RHJhZyhjbSwgZSwgc3RhcnQsIG1vZGlmaWVyKTtcbiAgICBlbHNlXG4gICAgICBsZWZ0QnV0dG9uU2VsZWN0KGNtLCBlLCBzdGFydCwgdHlwZSwgbW9kaWZpZXIpO1xuICB9XG5cbiAgLy8gU3RhcnQgYSB0ZXh0IGRyYWcuIFdoZW4gaXQgZW5kcywgc2VlIGlmIGFueSBkcmFnZ2luZyBhY3R1YWxseVxuICAvLyBoYXBwZW4sIGFuZCB0cmVhdCBhcyBhIGNsaWNrIGlmIGl0IGRpZG4ndC5cbiAgZnVuY3Rpb24gbGVmdEJ1dHRvblN0YXJ0RHJhZyhjbSwgZSwgc3RhcnQsIG1vZGlmaWVyKSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBzdGFydFRpbWUgPSArbmV3IERhdGU7XG4gICAgdmFyIGRyYWdFbmQgPSBvcGVyYXRpb24oY20sIGZ1bmN0aW9uKGUyKSB7XG4gICAgICBpZiAod2Via2l0KSBkaXNwbGF5LnNjcm9sbGVyLmRyYWdnYWJsZSA9IGZhbHNlO1xuICAgICAgY20uc3RhdGUuZHJhZ2dpbmdUZXh0ID0gZmFsc2U7XG4gICAgICBvZmYoZG9jdW1lbnQsIFwibW91c2V1cFwiLCBkcmFnRW5kKTtcbiAgICAgIG9mZihkaXNwbGF5LnNjcm9sbGVyLCBcImRyb3BcIiwgZHJhZ0VuZCk7XG4gICAgICBpZiAoTWF0aC5hYnMoZS5jbGllbnRYIC0gZTIuY2xpZW50WCkgKyBNYXRoLmFicyhlLmNsaWVudFkgLSBlMi5jbGllbnRZKSA8IDEwKSB7XG4gICAgICAgIGVfcHJldmVudERlZmF1bHQoZTIpO1xuICAgICAgICBpZiAoIW1vZGlmaWVyICYmICtuZXcgRGF0ZSAtIDIwMCA8IHN0YXJ0VGltZSlcbiAgICAgICAgICBleHRlbmRTZWxlY3Rpb24oY20uZG9jLCBzdGFydCk7XG4gICAgICAgIC8vIFdvcmsgYXJvdW5kIHVuZXhwbGFpbmFibGUgZm9jdXMgcHJvYmxlbSBpbiBJRTkgKCMyMTI3KSBhbmQgQ2hyb21lICgjMzA4MSlcbiAgICAgICAgaWYgKHdlYmtpdCB8fCBpZSAmJiBpZV92ZXJzaW9uID09IDkpXG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtkb2N1bWVudC5ib2R5LmZvY3VzKCk7IGRpc3BsYXkuaW5wdXQuZm9jdXMoKTt9LCAyMCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBkaXNwbGF5LmlucHV0LmZvY3VzKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gTGV0IHRoZSBkcmFnIGhhbmRsZXIgaGFuZGxlIHRoaXMuXG4gICAgaWYgKHdlYmtpdCkgZGlzcGxheS5zY3JvbGxlci5kcmFnZ2FibGUgPSB0cnVlO1xuICAgIGNtLnN0YXRlLmRyYWdnaW5nVGV4dCA9IGRyYWdFbmQ7XG4gICAgLy8gSUUncyBhcHByb2FjaCB0byBkcmFnZ2FibGVcbiAgICBpZiAoZGlzcGxheS5zY3JvbGxlci5kcmFnRHJvcCkgZGlzcGxheS5zY3JvbGxlci5kcmFnRHJvcCgpO1xuICAgIG9uKGRvY3VtZW50LCBcIm1vdXNldXBcIiwgZHJhZ0VuZCk7XG4gICAgb24oZGlzcGxheS5zY3JvbGxlciwgXCJkcm9wXCIsIGRyYWdFbmQpO1xuICB9XG5cbiAgLy8gTm9ybWFsIHNlbGVjdGlvbiwgYXMgb3Bwb3NlZCB0byB0ZXh0IGRyYWdnaW5nLlxuICBmdW5jdGlvbiBsZWZ0QnV0dG9uU2VsZWN0KGNtLCBlLCBzdGFydCwgdHlwZSwgYWRkTmV3KSB7XG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBkb2MgPSBjbS5kb2M7XG4gICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcblxuICAgIHZhciBvdXJSYW5nZSwgb3VySW5kZXgsIHN0YXJ0U2VsID0gZG9jLnNlbCwgcmFuZ2VzID0gc3RhcnRTZWwucmFuZ2VzO1xuICAgIGlmIChhZGROZXcgJiYgIWUuc2hpZnRLZXkpIHtcbiAgICAgIG91ckluZGV4ID0gZG9jLnNlbC5jb250YWlucyhzdGFydCk7XG4gICAgICBpZiAob3VySW5kZXggPiAtMSlcbiAgICAgICAgb3VyUmFuZ2UgPSByYW5nZXNbb3VySW5kZXhdO1xuICAgICAgZWxzZVxuICAgICAgICBvdXJSYW5nZSA9IG5ldyBSYW5nZShzdGFydCwgc3RhcnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXJSYW5nZSA9IGRvYy5zZWwucHJpbWFyeSgpO1xuICAgICAgb3VySW5kZXggPSBkb2Muc2VsLnByaW1JbmRleDtcbiAgICB9XG5cbiAgICBpZiAoZS5hbHRLZXkpIHtcbiAgICAgIHR5cGUgPSBcInJlY3RcIjtcbiAgICAgIGlmICghYWRkTmV3KSBvdXJSYW5nZSA9IG5ldyBSYW5nZShzdGFydCwgc3RhcnQpO1xuICAgICAgc3RhcnQgPSBwb3NGcm9tTW91c2UoY20sIGUsIHRydWUsIHRydWUpO1xuICAgICAgb3VySW5kZXggPSAtMTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJkb3VibGVcIikge1xuICAgICAgdmFyIHdvcmQgPSBjbS5maW5kV29yZEF0KHN0YXJ0KTtcbiAgICAgIGlmIChjbS5kaXNwbGF5LnNoaWZ0IHx8IGRvYy5leHRlbmQpXG4gICAgICAgIG91clJhbmdlID0gZXh0ZW5kUmFuZ2UoZG9jLCBvdXJSYW5nZSwgd29yZC5hbmNob3IsIHdvcmQuaGVhZCk7XG4gICAgICBlbHNlXG4gICAgICAgIG91clJhbmdlID0gd29yZDtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gXCJ0cmlwbGVcIikge1xuICAgICAgdmFyIGxpbmUgPSBuZXcgUmFuZ2UoUG9zKHN0YXJ0LmxpbmUsIDApLCBjbGlwUG9zKGRvYywgUG9zKHN0YXJ0LmxpbmUgKyAxLCAwKSkpO1xuICAgICAgaWYgKGNtLmRpc3BsYXkuc2hpZnQgfHwgZG9jLmV4dGVuZClcbiAgICAgICAgb3VyUmFuZ2UgPSBleHRlbmRSYW5nZShkb2MsIG91clJhbmdlLCBsaW5lLmFuY2hvciwgbGluZS5oZWFkKTtcbiAgICAgIGVsc2VcbiAgICAgICAgb3VyUmFuZ2UgPSBsaW5lO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXJSYW5nZSA9IGV4dGVuZFJhbmdlKGRvYywgb3VyUmFuZ2UsIHN0YXJ0KTtcbiAgICB9XG5cbiAgICBpZiAoIWFkZE5ldykge1xuICAgICAgb3VySW5kZXggPSAwO1xuICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbmV3IFNlbGVjdGlvbihbb3VyUmFuZ2VdLCAwKSwgc2VsX21vdXNlKTtcbiAgICAgIHN0YXJ0U2VsID0gZG9jLnNlbDtcbiAgICB9IGVsc2UgaWYgKG91ckluZGV4ID09IC0xKSB7XG4gICAgICBvdXJJbmRleCA9IHJhbmdlcy5sZW5ndGg7XG4gICAgICBzZXRTZWxlY3Rpb24oZG9jLCBub3JtYWxpem
23459VTZWxlY3Rpb24ocmFuZ2VzLmNvbmNhdChbb3VyUmFuZ2VdKSwgb3VySW5kZXgpLFxuICAgICAgICAgICAgICAgICAgIHtzY3JvbGw6IGZhbHNlLCBvcmlnaW46IFwiKm1vdXNlXCJ9KTtcbiAgICB9IGVsc2UgaWYgKHJhbmdlcy5sZW5ndGggPiAxICYmIHJhbmdlc1tvdXJJbmRleF0uZW1wdHkoKSAmJiB0eXBlID09IFwic2luZ2xlXCIgJiYgIWUuc2hpZnRLZXkpIHtcbiAgICAgIHNldFNlbGVjdGlvbihkb2MsIG5vcm1hbGl6ZVNlbGVjdGlvbihyYW5nZXMuc2xpY2UoMCwgb3VySW5kZXgpLmNvbmNhdChyYW5nZXMuc2xpY2Uob3VySW5kZXggKyAxKSksIDApLFxuICAgICAgICAgICAgICAgICAgIHtzY3JvbGw6IGZhbHNlLCBvcmlnaW46IFwiKm1vdXNlXCJ9KTtcbiAgICAgIHN0YXJ0U2VsID0gZG9jLnNlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVwbGFjZU9uZVNlbGVjdGlvbihkb2MsIG91ckluZGV4LCBvdXJSYW5nZSwgc2VsX21vdXNlKTtcbiAgICB9XG5cbiAgICB2YXIgbGFzdFBvcyA9IHN0YXJ0O1xuICAgIGZ1bmN0aW9uIGV4dGVuZFRvKHBvcykge1xuICAgICAgaWYgKGNtcChsYXN0UG9zLCBwb3MpID09IDApIHJldHVybjtcbiAgICAgIGxhc3RQb3MgPSBwb3M7XG5cbiAgICAgIGlmICh0eXBlID09IFwicmVjdFwiKSB7XG4gICAgICAgIHZhciByYW5nZXMgPSBbXSwgdGFiU2l6ZSA9IGNtLm9wdGlvbnMudGFiU2l6ZTtcbiAgICAgICAgdmFyIHN0YXJ0Q29sID0gY291bnRDb2x1bW4oZ2V0TGluZShkb2MsIHN0YXJ0LmxpbmUpLnRleHQsIHN0YXJ0LmNoLCB0YWJTaXplKTtcbiAgICAgICAgdmFyIHBvc0NvbCA9IGNvdW50Q29sdW1uKGdldExpbmUoZG9jLCBwb3MubGluZSkudGV4dCwgcG9zLmNoLCB0YWJTaXplKTtcbiAgICAgICAgdmFyIGxlZnQgPSBNYXRoLm1pbihzdGFydENvbCwgcG9zQ29sKSwgcmlnaHQgPSBNYXRoLm1heChzdGFydENvbCwgcG9zQ29sKTtcbiAgICAgICAgZm9yICh2YXIgbGluZSA9IE1hdGgubWluKHN0YXJ0LmxpbmUsIHBvcy5saW5lKSwgZW5kID0gTWF0aC5taW4oY20ubGFzdExpbmUoKSwgTWF0aC5tYXgoc3RhcnQubGluZSwgcG9zLmxpbmUpKTtcbiAgICAgICAgICAgICBsaW5lIDw9IGVuZDsgbGluZSsrKSB7XG4gICAgICAgICAgdmFyIHRleHQgPSBnZXRMaW5lKGRvYywgbGluZSkudGV4dCwgbGVmdFBvcyA9IGZpbmRDb2x1bW4odGV4dCwgbGVmdCwgdGFiU2l6ZSk7XG4gICAgICAgICAgaWYgKGxlZnQgPT0gcmlnaHQpXG4gICAgICAgICAgICByYW5nZXMucHVzaChuZXcgUmFuZ2UoUG9zKGxpbmUsIGxlZnRQb3MpLCBQb3MobGluZSwgbGVmdFBvcykpKTtcbiAgICAgICAgICBlbHNlIGlmICh0ZXh0Lmxlbmd0aCA+IGxlZnRQb3MpXG4gICAgICAgICAgICByYW5nZXMucHVzaChuZXcgUmFuZ2UoUG9zKGxpbmUsIGxlZnRQb3MpLCBQb3MobGluZSwgZmluZENvbHVtbih0ZXh0LCByaWdodCwgdGFiU2l6ZSkpKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFyYW5nZXMubGVuZ3RoKSByYW5nZXMucHVzaChuZXcgUmFuZ2Uoc3RhcnQsIHN0YXJ0KSk7XG4gICAgICAgIHNldFNlbGVjdGlvbihkb2MsIG5vcm1hbGl6ZVNlbGVjdGlvbihzdGFydFNlbC5yYW5nZXMuc2xpY2UoMCwgb3VySW5kZXgpLmNvbmNhdChyYW5nZXMpLCBvdXJJbmRleCksXG4gICAgICAgICAgICAgICAgICAgICB7b3JpZ2luOiBcIiptb3VzZVwiLCBzY3JvbGw6IGZhbHNlfSk7XG4gICAgICAgIGNtLnNjcm9sbEludG9WaWV3KHBvcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2Y
23459XIgb2xkUmFuZ2UgPSBvdXJSYW5nZTtcbiAgICAgICAgdmFyIGFuY2hvciA9IG9sZFJhbmdlLmFuY2hvciwgaGVhZCA9IHBvcztcbiAgICAgICAgaWYgKHR5cGUgIT0gXCJzaW5nbGVcIikge1xuICAgICAgICAgIGlmICh0eXBlID09IFwiZG91YmxlXCIpXG4gICAgICAgICAgICB2YXIgcmFuZ2UgPSBjbS5maW5kV29yZEF0KHBvcyk7XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgdmFyIHJhbmdlID0gbmV3IFJhbmdlKFBvcyhwb3MubGluZSwgMCksIGNsaXBQb3MoZG9jLCBQb3MocG9zLmxpbmUgKyAxLCAwKSkpO1xuICAgICAgICAgIGlmIChjbXAocmFuZ2UuYW5jaG9yLCBhbmNob3IpID4gMCkge1xuICAgICAgICAgICAgaGVhZCA9IHJhbmdlLmhlYWQ7XG4gICAgICAgICAgICBhbmNob3IgPSBtaW5Qb3Mob2xkUmFuZ2UuZnJvbSgpLCByYW5nZS5hbmNob3IpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoZWFkID0gcmFuZ2UuYW5jaG9yO1xuICAgICAgICAgICAgYW5jaG9yID0gbWF4UG9zKG9sZFJhbmdlLnRvKCksIHJhbmdlLmhlYWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcmFuZ2VzID0gc3RhcnRTZWwucmFuZ2VzLnNsaWNlKDApO1xuICAgICAgICByYW5nZXNbb3VySW5kZXhdID0gbmV3IFJhbmdlKGNsaXBQb3MoZG9jLCBhbmNob3IpLCBoZWFkKTtcbiAgICAgICAgc2V0U2VsZWN0aW9uKGRvYywgbm9ybWFsaXplU2VsZWN0aW9uKHJhbmdlcywgb3VySW5kZXgpLCBzZWxfbW91c2UpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBlZGl0b3JTaXplID0gZGlzcGxheS53cmFwcGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIC8vIFVzZWQgdG8gZW5zdXJlIHRpbWVvdXQgcmUtdHJpZXMgZG9uJ3QgZmlyZSB3aGVuIGFub3RoZXIgZXh0ZW5kXG4gICAgLy8gaGFwcGVuZWQgaW4gdGhlIG1lYW50aW1lIChjbGVhclRpbWVvdXQgaXNuJ3QgcmVsaWFibGUgLS0gYXRcbiAgICAvLyBsZWFzdCBvbiBDaHJvbWUsIHRoZSB0aW1lb3V0cyBzdGlsbCBoYXBwZW4gZXZlbiB3aGVuIGNsZWFyZWQsXG4gICAgLy8gaWYgdGhlIGNsZWFyIGhhcHBlbnMgYWZ0ZXIgdGhlaXIgc2NoZWR1bGVkIGZpcmluZyB0aW1lKS5cbiAgICB2YXIgY291bnRlciA9IDA7XG5cbiAgICBmdW5jdGlvbiBleHRlbmQoZSkge1xuICAgICAgdmFyIGN1ckNvdW50ID0gKytjb3VudGVyO1xuICAgICAgdmFyIGN1ciA9IHBvc0Zyb21Nb3VzZShjbSwgZSwgdHJ1ZSwgdHlwZSA9PSBcInJlY3RcIik7XG4gICAgICBpZiAoIWN1cikgcmV0dXJuO1xuICAgICAgaWYgKGNtcChjdXIsIGxhc3RQb3MpICE9IDApIHtcbiAgICAgICAgY20uY3VyT3AuZm9jdXMgPSBhY3RpdmVFbHQoKTtcbiAgICAgICAgZXh0ZW5kVG8oY3VyKTtcbiAgICAgICAgdmFyIHZpc2libGUgPSB2aXNpYmxlTGluZXMoZGlzcGxheSwgZG9jKTtcbiAgICAgICAgaWYgKGN1ci5saW5lID49IHZpc2libGUudG8gfHwgY3VyLmxpbmUgPCB2aXNpYmxlLmZyb20pXG4gICAgICAgICAgc2V0VGltZW91dChvcGVyYXRpb24oY20sIGZ1bmN0aW9uKCl7aWYgKGNvdW50ZXIgPT0gY3VyQ291bnQpIGV4dGVuZChlKTt9KSwgMTUwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBvdXRzaWRlID0gZS5jbGllbnRZIDwgZWRpdG9yU2l6ZS50b3AgPyAtMjAgOiBlLmNsaWVudFkgPiBlZGl0b3JTaXplLmJvdHRvbSA/IDIwIDogMDtcbiAgICAgICAgaWYgKG91dHNpZGUpIHNldFRpbWVvdXQob3BlcmF0aW9uKGNtLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAoY291bnRlciAhPSBjdXJDb3VudCkgcmV0dXJuO1xuICAgICAgICAgIGRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wICs9IG91dHNpZGU7XG4gICAgICAgICAgZXh0ZW5kKGUpO1xuICAgICAgICB9KSwgNTApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbmUoZSkge1xuICAgICAgY20uc3RhdGUuc2VsZWN0aW5nVGV4dCA9IGZhbHNlO1xuICAgICAgY291bnRlciA9IEluZmluaXR5O1xuICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIGRpc3BsYXkuaW5wdXQuZm9jdXMoKTtcbiAgICAgIG9mZihkb2N1bWVudCwgXCJtb3VzZW1vdmVcIiwgbW92ZSk7XG4gICAgICBvZmYoZG9jdW1lbnQsIFwibW91c2V1cFwiLCB1cCk7XG4gICAgICBkb2MuaGlzdG9yeS5sYXN0U2VsT3JpZ2luID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbW92ZSA9IG9wZXJhdGlvbihjbSwgZnVuY3Rpb24oZSkge1xuICAgICAgaWYgKCFlX2J1dHRvbihlKSkgZG9uZShlKTtcbiAgICAgIGVsc2UgZXh0ZW5kKGUpO1xuICAgIH0pO1xuICAgIHZhciB1cCA9IG9wZXJhdGlvbihjbSwgZG9uZSk7XG4gICAgY20uc3RhdGUuc2VsZWN0aW5nVGV4dCA9IHVwO1xuICAgIG9uKGRvY3VtZW50LCBcIm1vdXNlbW92ZVwiLCBtb3ZlKTtcbiAgICBvbihkb2N1bWVudCwgXCJtb3VzZXVwXCIsIHVwKTtcbiAgfVxuXG4gIC8vIERldGVybWluZXMgd2hldGhlciBhbiBldmVudCBoYXBwZW5lZCBpbiB0aGUgZ3V0dGVyLCBhbmQgZmlyZXMgdGhlXG4gIC8vIGhhbmRsZXJzIGZvciB0aGUgY29ycmVzcG9uZGluZyBldmVudC5cbiAgZnVuY3Rpb24gZ3V0dGVyRXZlbnQoY20sIGUsIHR5cGUsIHByZXZlbnQsIHNpZ25hbGZuKSB7XG4gICAgdHJ5IHsgdmFyIG1YID0gZS5jbGllbnRYLCBtWSA9IGUuY2xpZW50WTsgfVxuICAgIGNhdGNoKGUpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgaWYgKG1YID49IE1hdGguZmxvb3IoY20uZGlzcGxheS5ndXR0ZXJzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0KSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChwcmV2ZW50KSBlX3ByZXZlbnREZWZhdWx0KGUpO1xuXG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5O1xuICAgIHZhciBsaW5lQm94ID0gZGlzcGxheS5saW5lRGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgaWYgKG1ZID4gbGluZUJveC5ib3R0b20gfHwgIWhhc0hhbmRsZXIoY20sIHR5cGUpKSByZXR1cm4gZV9kZWZhdWx0UHJldmVudGVkKGUpO1xuICAgIG1ZIC09IGxpbmVCb3gudG9wIC0gZGlzcGxheS52aWV3T2Zmc2V0O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbS5vcHRpb25zLmd1dHRlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBnID0gZGlzcGxheS5ndXR0ZXJzLmNoaWxkTm9kZXNbaV07XG4gICAgICBpZiAoZyAmJiBnLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0ID49IG1YKSB7XG4gICAgICAgI
23459HZhciBsaW5lID0gbGluZUF0SGVpZ2h0KGNtLmRvYywgbVkpO1xuICAgICAgICB2YXIgZ3V0dGVyID0gY20ub3B0aW9ucy5ndXR0ZXJzW2ldO1xuICAgICAgICBzaWduYWxmbihjbSwgdHlwZSwgY20sIGxpbmUsIGd1dHRlciwgZSk7XG4gICAgICAgIHJldHVybiBlX2RlZmF1bHRQcmV2ZW50ZWQoZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xpY2tJbkd1dHRlcihjbSwgZSkge1xuICAgIHJldHVybiBndXR0ZXJFdmVudChjbSwgZSwgXCJndXR0ZXJDbGlja1wiLCB0cnVlLCBzaWduYWxMYXRlcik7XG4gIH1cblxuICAvLyBLbHVkZ2UgdG8gd29yayBhcm91bmQgc3RyYW5nZSBJRSBiZWhhdmlvciB3aGVyZSBpdCdsbCBzb21ldGltZXNcbiAgLy8gcmUtZmlyZSBhIHNlcmllcyBvZiBkcmFnLXJlbGF0ZWQgZXZlbnRzIHJpZ2h0IGFmdGVyIHRoZSBkcm9wICgjMTU1MSlcbiAgdmFyIGxhc3REcm9wID0gMDtcblxuICBmdW5jdGlvbiBvbkRyb3AoZSkge1xuICAgIHZhciBjbSA9IHRoaXM7XG4gICAgY2xlYXJEcmFnQ3Vyc29yKGNtKTtcbiAgICBpZiAoc2lnbmFsRE9NRXZlbnQoY20sIGUpIHx8IGV2ZW50SW5XaWRnZXQoY20uZGlzcGxheSwgZSkpXG4gICAgICByZXR1cm47XG4gICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICBpZiAoaWUpIGxhc3REcm9wID0gK25ldyBEYXRlO1xuICAgIHZhciBwb3MgPSBwb3NGcm9tTW91c2UoY20sIGUsIHRydWUpLCBmaWxlcyA9IGUuZGF0YVRyYW5zZmVyLmZpbGVzO1xuICAgIGlmICghcG9zIHx8IGlzUmVhZE9ubHkoY20pKSByZXR1cm47XG4gICAgLy8gTWlnaHQgYmUgYSBmaWxlIGRyb3AsIGluIHdoaWNoIGNhc2Ugd2Ugc2ltcGx5IGV4dHJhY3QgdGhlIHRleHRcbiAgICAvLyBhbmQgaW5zZXJ0IGl0LlxuICAgIGlmIChmaWxlcyAmJiBmaWxlcy5sZW5ndGggJiYgd2luZG93LkZpbGVSZWFkZXIgJiYgd2luZG93LkZpbGUpIHtcbiAgICAgIHZhciBuID0gZmlsZXMubGVuZ3RoLCB0ZXh0ID0gQXJyYXkobiksIHJlYWQgPSAwO1xuICAgICAgdmFyIGxvYWRGaWxlID0gZnVuY3Rpb24oZmlsZSwgaSkge1xuICAgICAgICBpZiAoY20ub3B0aW9ucy5hbGxvd0Ryb3BGaWxlVHlwZXMgJiZcbiAgICAgICAgICAgIGluZGV4T2YoY20ub3B0aW9ucy5hbGxvd0Ryb3BGaWxlVHlwZXMsIGZpbGUudHlwZSkgPT0gLTEpXG4gICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcjtcbiAgICAgICAgcmVhZGVyLm9ubG9hZCA9IG9wZXJhdGlvbihjbSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIGNvbnRlbnQgPSByZWFkZXIucmVzdWx0O1xuICAgICAgICAgIGlmICgvW1xceDAwLVxceDA4XFx4MGUtXFx4MWZdezJ9Ly50ZXN0KGNvbnRlbnQpKSBjb250ZW50ID0gXCJcIjtcbiAgICAgICAgICB0ZXh0W2ldID0gY29udGVudDtcbiAgICAgICAgICBpZiAoKytyZWFkID09IG4pIHtcbiAgICAgICAgICAgIHBvcyA9IGNsaXBQb3MoY20uZG9jLCBwb3MpO1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IHtmcm9tOiBwb3MsIHRvOiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGNtLmRvYy5zcGxpdExpbmVzKHRleHQuam9pbihjbS5kb2MubGluZVNlcGFyYXRvcigpKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbjogXCJwYXN0ZVwifTtcbiAgICAgICAgICAgIG1ha2VDaGFuZ2UoY20uZG9jLCBjaGFuZ2UpO1xuICAgICAgICAgICAgc2V0U2VsZWN0aW9uUmVwbGFjZUhpc3RvcnkoY20uZG9jLCBzaW1wbGVTZWxlY3Rpb24ocG9zLCBjaGFuZ2VFbmQoY2hhbmdlKSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUpO1xuICAgICAgfTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSBsb2FkRmlsZShmaWxlc1tpXSwgaSk7XG4gICAgfSBlbHNlIHsgLy8gTm9ybWFsIGRyb3BcbiAgICAgIC8vIERvbid0IGRvIGEgcmVwbGFjZSBpZiB0aGUgZHJvcCBoYXBwZW5lZCBpbnNpZGUgb2YgdGhlIHNlbGVjdGVkIHRleHQuXG4gICAgICBpZiAoY20uc3RhdGUuZHJhZ2dpbmdUZXh0ICYmIGNtLmRvYy5zZWwuY29udGFpbnMocG9zKSA+IC0xKSB7XG4gICAgICAgIGNtLnN0YXRlLmRyYWdnaW5nVGV4dChlKTtcbiAgICAgICAgLy8gRW5zdXJlIHRoZSBlZGl0b3IgaXMgcmUtZm9jdXNlZFxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge2NtLmRpc3BsYXkuaW5wdXQuZm9jdXMoKTt9LCAyMCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciB0ZXh0ID0gZS5kYXRhVHJhbnNmZXIuZ2V0RGF0YShcIlRleHRcIik7XG4gICAgICAgIGlmICh0ZXh0KSB7XG4gICAgICAgICAgaWYgKGNtLnN0YXRlLmRyYWdnaW5nVGV4dCAmJiAhKG1hYyA/IGUuYWx0S2V5IDogZS5jdHJsS2V5KSlcbiAgICAgICAgICAgIHZhciBzZWxlY3RlZCA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7XG4gICAgICAgICAgc2V0U2VsZWN0aW9uTm9VbmRvKGNtLmRvYywgc2ltcGxlU2VsZWN0aW9uKHBvcywgcG9zKSk7XG4gICAgICAgICAgaWYgKHNlbGVjdGVkKSBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGVjdGVkLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgcmVwbGFjZVJhbmdlKGNtLmRvYywgXCJcIiwgc2VsZWN0ZWRbaV0uYW5jaG9yLCBzZWxlY3RlZFtpXS5oZWFkLCBcImRyYWdcIik7XG4gICAgICAgICAgY20ucmVwbGFjZVNlbGVjdGlvbih0ZXh0LCBcImFyb3VuZFwiLCBcInBhc3RlXCIpO1xuICAgICAgICAgIGNtLmRpc3BsYXkuaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2F0Y2goZSl7fVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG9uRHJhZ1N0YXJ0KGNtLCBlKSB7XG4gICAgaWYgKGllICYmICghY20uc3RhdGUuZHJhZ2dpbmdUZXh0IHx8ICtuZXcgRGF0ZSAtIGxhc3REcm9wIDwgMTAwKSkgeyBlX3N0b3AoZSk7IHJldHVybjsgfVxuICAgIGlmIChzaWduYWxET01FdmVudChjbSwgZSkgfHwgZXZlbnRJbldpZGdldChjbS5kaXNwbGF5LCBlKSkgcmV0dXJuO1xuXG4gICAgZS5kYXRhV
23459HJhbnNmZXIuc2V0RGF0YShcIlRleHRcIiwgY20uZ2V0U2VsZWN0aW9uKCkpO1
vendor: 10,548 bytes, line 23459
23459xuXG4gICAgLy8gVXNlIGR1bW15IGltYWdlIGluc3RlYWQgb2YgZGVmYXVsdCBicm93c2VycyBpbWFnZS5cbiAgICAvLyBSZWNlbnQgU2FmYXJpICh+Ni4wLjIpIGhhdmUgYSB0ZW5kZW5jeSB0byBzZWdmYXVsdCB3aGVuIHRoaXMgaGFwcGVucywgc28gd2UgZG9uJ3QgZG8gaXQgdGhlcmUuXG4gICAgaWYgKGUuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZSAmJiAhc2FmYXJpKSB7XG4gICAgICB2YXIgaW1nID0gZWx0KFwiaW1nXCIsIG51bGwsIG51bGwsIFwicG9zaXRpb246IGZpeGVkOyBsZWZ0OiAwOyB0b3A6IDA7XCIpO1xuICAgICAgaW1nLnNyYyA9IFwiZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFBQUFBQ0g1QkFFS0FBRUFMQUFBQUFBQkFBRUFBQUlDVEFFQU93PT1cIjtcbiAgICAgIGlmIChwcmVzdG8pIHtcbiAgICAgICAgaW1nLndpZHRoID0gaW1nLmhlaWdodCA9IDE7XG4gICAgICAgIGNtLmRpc3BsYXkud3JhcHBlci5hcHBlbmRDaGlsZChpbWcpO1xuICAgICAgICAvLyBGb3JjZSBhIHJlbGF5b3V0LCBvciBPcGVyYSB3b24ndCB1c2Ugb3VyIGltYWdlIGZvciBzb21lIG9ic2N1cmUgcmVhc29uXG4gICAgICAgIGltZy5fdG9wID0gaW1nLm9mZnNldFRvcDtcbiAgICAgIH1cbiAgICAgIGUuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZShpbWcsIDAsIDApO1xuICAgICAgaWYgKHByZXN0bykgaW1nLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaW1nKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBvbkRyYWdPdmVyKGNtLCBlKSB7XG4gICAgdmFyIHBvcyA9IHBvc0Zyb21Nb3VzZShjbSwgZSk7XG4gICAgaWYgKCFwb3MpIHJldHVybjtcbiAgICB2YXIgZnJhZyA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICBkcmF3U2VsZWN0aW9uQ3Vyc29yKGNtLCBwb3MsIGZyYWcpO1xuICAgIGlmICghY20uZGlzcGxheS5kcmFnQ3Vyc29yKSB7XG4gICAgICBjbS5kaXNwbGF5LmRyYWdDdXJzb3IgPSBlbHQoXCJkaXZcIiwgbnVsbCwgXCJDb2RlTWlycm9yLWN1cnNvcnMgQ29kZU1pcnJvci1kcmFnY3Vyc29yc1wiKTtcbiAgICAgIGNtLmRpc3BsYXkubGluZVNwYWNlLmluc2VydEJlZm9yZShjbS5kaXNwbGF5LmRyYWdDdXJzb3IsIGNtLmRpc3BsYXkuY3Vyc29yRGl2KTtcbiAgICB9XG4gICAgcmVtb3ZlQ2hpbGRyZW5BbmRBZGQoY20uZGlzcGxheS5kcmFnQ3Vyc29yLCBmcmFnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFyRHJhZ0N1cnNvcihjbSkge1xuICAgIGlmIChjbS5kaXNwbGF5LmRyYWdDdXJzb3IpIHtcbiAgICAgIGNtLmRpc3BsYXkubGluZVNwYWNlLnJlbW92ZUNoaWxkKGNtLmRpc3BsYXkuZHJhZ0N1cnNvcik7XG4gICAgICBjbS5kaXNwbGF5LmRyYWdDdXJzb3IgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIFNDUk9MTCBFVkVOVFNcblxuICAvLyBTeW5jIHRoZSBzY3JvbGxhYmxlIGFyZWEgYW5kIHNjcm9sbGJhcnMsIGVuc3VyZSB0aGUgdmlld3BvcnRcbiAgLy8gY292ZXJzIHRoZSB2aXNpYmxlIGFyZWEuXG4gIGZ1bmN0aW9uIHNldFNjcm9sbFRvcChjbSwgdmFsKSB7XG4gICAgaWYgKE1hdGguYWJzKGNtLmRvYy5zY3JvbGxUb3AgLSB2YWwpIDwgMikgcmV0dXJuO1xuICAgIGNtLmRvYy5zY3JvbGxUb3AgPSB2YWw7XG4gICAgaWYgKCFnZWNrbykgdXBkYXRlRGlzcGxheVNpbXBsZShjbSwge3RvcDogdmFsfSk7XG4gICAgaWYgKGNtLmRpc3BsYXkuc2Nyb2xsZXIuc2Nyb2xsVG9wICE9IHZhbCkgY20uZGlzcGxheS5zY3JvbGxlci5zY3JvbGxUb3AgPSB2YWw7XG4gICAgY20uZGlzcGxheS5zY3JvbGxiYXJzLnNldFNjcm9sbFRvcCh2YWwpO1xuICAgIGlmIChnZWNrbykgdXBkYXRlRGlzcGxheVNpbXBsZShjbSk7XG4gICAgc3RhcnRXb3JrZXIoY20sIDEwMCk7XG4gIH1cbiAgLy8gU3luYyBzY3JvbGxlciBhbmQgc2Nyb2xsYmFyLCBlbnN1cmUgdGhlIGd1dHRlciBlbGVtZW50cyBhcmVcbiAgLy8gYWxpZ25lZC5cbiAgZnVuY3Rpb24gc2V0U2Nyb2xsTGVmdChjbSwgdmFsLCBpc1Njcm9sbGVyKSB7XG4gICAgaWYgKGlzU2Nyb2xsZXIgPyB2YWwgPT0gY20uZG9jLnNjcm9sbExlZnQgOiBNYXRoLmFicyhjbS5kb2Muc2Nyb2xsTGVmdCAtIHZhbCkgPCAyKSByZXR1cm47XG4gICAgdmFsID0gTWF0aC5taW4odmFsLCBjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFdpZHRoIC0gY20uZGlzcGxheS5zY3JvbGxlci5jbGllbnRXaWR0aCk7XG4gICAgY20uZG9jLnNjcm9sbExlZnQgPSB2YWw7XG4gICAgYWxpZ25Ib3Jpem9udGFsbHkoY20pO1xuICAgIGlmIChjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQgIT0gdmFsKSBjbS5kaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQgPSB2YWw7XG4gICAgY20uZGlzcGxheS5zY3JvbGxiYXJzLnNldFNjcm9sbExlZnQodmFsKTtcbiAgfVxuXG4gIC8vIFNpbmNlIHRoZSBkZWx0YSB2YWx1ZXMgcmVwb3J0ZWQgb24gbW91c2Ugd2hlZWwgZXZlbnRzIGFyZVxuICAvLyB1bnN0YW5kYXJkaXplZCBiZXR3ZWVuIGJyb3dzZXJzIGFuZCBldmVuIGJyb3dzZXIgdmVyc2lvbnMsIGFuZFxuICAvLyBnZW5lcmFsbHkgaG9ycmlibHkgdW5wcmVkaWN0YWJsZSwgdGhpcyBjb2RlIHN0YXJ0cyBieSBtZWFzdXJpbmdcbiAgLy8gdGhlIHNjcm9sbCBlZmZlY3QgdGhhdCB0aGUgZmlyc3QgZmV3IG1vdXNlIHdoZWVsIGV2ZW50cyBoYXZlLFxuICAvLyBhbmQsIGZyb20gdGhhdCwgZGV0ZWN0cyB0aGUgd2F5IGl0IGNhbiBjb252ZXJ0IGRlbHRhcyB0byBwaXhlbFxuICAvLyBvZmZzZXRzIGFmdGVyd2FyZHMuXG4gIC8vXG4gIC8vIFRoZSByZWFzb24gd2Ugd2FudCB0byBrbm93IHRoZSBhbW91bnQgYSB3aGVlbCBldmVudCB3aWxsIHNjcm9sbFxuICAvLyBpcyB0aGF0IGl0IGdpdmVzIHVzIGEgY2hhbmNlIHRvIHVwZGF0ZSB0aGUgZGlzcGxheSBiZWZvcmUgdGhlXG4gIC8vIGFjdHVhbCBzY3JvbGxpbmcgaGFwcGVucywgcmVkdWNpbmcgZmxpY2tlcmluZy5cblxuICB2YXIgd2hlZWxTYW1wbGVzID0gMCwgd2hlZWxQaXhlbHNQZXJVbml0ID0gbnVsbDtcbiAgLy8gRmlsbCBpbiBhIGJyb3dzZXItZGV0ZWN0ZWQgc3RhcnRpbmcgdmFsdWUgb24gYnJvd3NlcnMgd2hlcmUgd2VcbiAgLy8ga25vdyBvbmUuIFRoZXNlIGRvbid0IGhhdmUgdG8gYmUgYWNjdXJhdGUgLS0gdGhlIHJlc3VsdCBvZiB0aGVtXG4gIC8vIGJlaW5nIHdyb25nIHdvdWxkIGp1c3QgYmUgYSBzbGlnaHQgZmxpY2tlciBvbiB0aGUgZmlyc3Qgd2hlZWxcbiAgLy8gc2Nyb2xsIChpZiBpdCBpcyBsYXJnZSBlbm91Z2gpLlxuICBpZiAoaWUpIHdoZWVsUGl4ZWxzUGVyVW5pdCA9IC0uNTM7XG4gIGVsc2UgaWYgKGdlY2tvKSB3aGVlbFBpeGVsc1BlclVuaXQgPSAxNTtcbiAgZWxzZSBpZiAoY2hyb21lKSB3aGVlbFBpeGVsc1BlclVuaXQgPSAtLjc7XG4gIGVsc2UgaWYgKHNhZmFyaSkgd2hlZWxQaXhlbHNQZXJVbml0ID0gLTEvMztcblxuICB2YXIgd2hlZWxFdmVudERlbHRhID0gZnVuY3Rpb24oZSkge1xuICAgIHZhciBkeCA9IGUud2hlZWxEZWx0YVgsIGR5ID0gZS53aGVlbERlbHRhWTtcbiAgICBpZiAoZHggPT0gbnVsbCAmJiBlLmRldGFpbCAmJiBlLmF4aXMgPT0gZS5IT1JJWk9OVEFMX0FYSVMpIGR4ID0gZS5kZXRhaWw7XG4gICAgaWYgKGR5ID09IG51bGwgJiYgZS5kZXRhaWwgJiYgZS5heGlzID09IGUuVkVSVElDQUxfQVhJUykgZHkgPSBlLmRldGFpbDtcbiAgICBlbHNlIGlmIChkeSA9PSBudWxsKSBkeSA9IGUud2hlZWxEZWx0YTtcbiAgICByZXR1cm4ge3g6IGR4LCB5OiBkeX07XG4gIH07XG4gIENvZGVNaXJyb3Iud2hlZWxFdmVudFBpeGVscyA9IGZ1bmN0aW9uKGUpIHtcbiAgICB2YXIgZGVsdGEgPSB3aGVlbEV2ZW50RGVsdGEoZSk7XG4gICAgZGVsdGEueCAqPSB3aGVlbFBpeGVsc1BlclVuaXQ7XG4gICAgZGVsdGEueSAqPSB3aGVlbFBpeGVsc1BlclVuaXQ7XG4gICAgcmV0dXJuIGRlbHRhO1xuICB9O1xuXG4gIGZ1bmN0aW9uIG9uU2Nyb2xsV2hlZWwoY20sIGUpIHtcbiAgICB2YXIgZGVsdGEgPSB3aGVlbEV2ZW50RGVsdGEoZSksIGR4ID0gZGVsdGEueCwgZHkgPSBkZWx0YS55O1xuXG4gICAgdmFyIGRpc3BsYXkgPSBjbS5kaXNwbGF5LCBzY3JvbGwgPSBkaXNwbGF5LnNjcm9sbGVyO1xuICAgIC8vIFF1aXQgaWYgdGhlcmUncyBub3RoaW5nIHRvIHNjcm9sbCBoZXJlXG4gICAgdmFyIGNhblNjcm9sbFggPSBzY3JvbGwuc2Nyb2xsV2lkdGggPiBzY3JvbGwuY2xpZW50V2lkdGg7XG4gICAgdmFyIGNhblNjcm9sbFkgPSBzY3JvbGwuc2Nyb2xsSGVpZ2h0ID4gc2Nyb2xsLmNsaWVudEhlaWdodDtcbiAgICBpZiAoIShkeCAmJiBjYW5TY3JvbGxYIHx8IGR5ICYmIGNhblNjcm9sbFkpKSByZXR1cm47XG5cbiAgICAvLyBXZWJraXQgYnJvd3NlcnMgb24gT1MgWCBhYm9ydCBtb21lbnR1bSBzY3JvbGxzIHdoZW4gdGhlIHRhcmdldFxuICAgIC8vIG9mIHRoZSBzY3JvbGwgZXZlbnQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBzY3JvbGxhYmxlIGVsZW1lbnQuXG4gICAgLy8gVGhpcyBoYWNrIChzZWUgcmVsYXRlZCBjb2RlIGluIHBhdGNoRGlzcGxheSkgbWFrZXMgc3VyZSB0aGVcbiAgICAvLyBlbGVtZW50IGlzIGtlcHQgYXJvdW5kLlxuICAgIGlmIChkeSAmJiBtYWMgJiYgd2Via2l0KSB7XG4gICAgICBvdXRlcjogZm9yICh2YXIgY3VyID0gZS50YXJnZXQsIHZpZXcgPSBkaXNwbGF5LnZpZXc7IGN1ciAhPSBzY3JvbGw7IGN1ciA9IGN1ci5wYXJlbnROb2RlKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmICh2aWV3W2ldLm5vZGUgPT0gY3VyKSB7XG4gICAgICAgICAgICBjbS5kaXNwbGF5LmN1cnJlbnRXaGVlbFRhcmdldCA9IGN1cjtcbiAgICAgICAgICAgIGJyZWFrIG91dGVyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9uIHNvbWUgYnJvd3NlcnMsIGhvcml6b250YWwgc2Nyb2xsaW5nIHdpbGwgY2F1c2UgcmVkcmF3cyB0b1xuICAgIC8vIGhhcHBlbiBiZWZvcmUgdGhlIGd1dHRlciBoYXMgYmVlbiByZWFsaWduZWQsIGNhdXNpbmcgaXQgdG9cbiAgICAvLyB3cmlnZ2xlIGFyb3VuZCBpbiBhIG1vc3QgdW5zZWVtbHkgd2F5LiBXaGVuIHdlIGhhdmUgYW5cbiAgICAvLyBlc3RpbWF0ZWQgcGl4ZWxzL2RlbHRhIHZhbHVlLCB3ZSBqdXN0IGhhbmRsZSBob3Jpem9udGFsXG4gICAgLy8gc2Nyb2xsaW5nIGVudGlyZWx5IGhlcmUuIEl0J2xsIGJlIHNsaWdodGx5IG9mZiBmcm9tIG5hdGl2ZSwgYnV0XG4gICAgLy8gYmV0dGVyIHRoYW4gZ2xpdGNoaW5nIG91dC5cbiAgICBpZiAoZHggJiYgIWdlY2tvICYmICFwcmVzdG8gJiYgd2hlZWxQaXhlbHNQZXJVbml0ICE9IG51bGwpIHtcbiAgICAgIGlmIChkeSAmJiBjYW5TY3JvbGxZKVxuICAgICAgICBzZXRTY3JvbGxUb3AoY20sIE1hdGgubWF4KDAsIE1hdGgubWluKHNjcm9sbC5zY3JvbGxUb3AgKyBkeSAqIHdoZWVsUGl4ZWxzUGVyVW5pdCwgc2Nyb2xsLnNjcm9sbEhlaWdodCAtIHNjcm9sbC5jbGllbnRIZWlnaHQpKSk7XG4gICAgICBzZXRTY3JvbGxMZWZ0KGNtLCBNYXRoLm1heCgwLCBNYXRoLm1pbihzY3JvbGwuc2Nyb2xsTGVmdCArIGR4ICogd2hlZWxQaXhlbHNQZXJVbml0LCBzY3JvbGwuc2Nyb2xsV2lkdGggLSBzY3JvbGwuY2xpZW50V2lkdGgpKSk7XG4gICAgICAvLyBPbmx5IHByZXZlbnQgZGVmYXVsdCBzY3JvbGxpbmcgaWYgdmVydGljYWwgc2Nyb2xsaW5nIGlzXG4gICAgICAvLyBhY3R1YWxseSBwb3NzaWJsZS4gT3RoZXJ3aXNlLCBpdCBjYXVzZXMgdmVydGljYWwgc2Nyb2xsXG4gICAgICAvLyBqaXR0ZXIgb24gT1NYIHRyYWNrcGFkcyB3aGVuIGRlbHRhWCBpcyBzbWFsbCBhbmQgZGVsdGFZXG4gICAgICAvLyBpcyBsYXJnZSAoaXNzdWUgIzM1NzkpXG4gICAgICBpZiAoIWR5IHx8IChkeSAmJiBjYW5TY3JvbGxZKSlcbiAgICAgICAgZV9wcmV2ZW50RGVmYXVsdChlKTtcbiAgICAgIGRpc3BsYXkud2hlZWxTdGFydFggPSBudWxsOyAvLyBBYm9ydCBtZWFzdXJlbWVudCwgaWYgaW4gcHJvZ3Jlc3NcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyAnUHJvamVjdCcgdGhlIHZpc2libGUgdmlld3BvcnQgdG8gY292ZXIgdGhlIGFyZWEgdGhhdCBpcyBiZWluZ1xuICAgIC8vIHNjcm9sbGVkIGludG8gdmlldyAoaWYgd2Uga25vdyBlbm91Z2ggdG8gZXN0aW1hdGUgaXQpLlxuICAgIGlmIChkeSAmJiB3aGVlbFBpeGVsc1BlclVuaXQgIT0gbnVsbCkge1xuICAgICAgdmFyIHBpeGVscyA9IGR5ICogd2hlZWxQaXhlbHNQZXJVbml0O1xuICAgICAgdmFyIHRvcCA9IGNtLmRvYy5zY3JvbGxUb3AsIGJvdCA9IHRvcCArIGRpc3BsYXkud3JhcHBlci5jbGllbnRIZWlnaHQ7XG4gICAgICBpZiAocGl4ZWxzIDwgMCkgdG9wID0gTWF0aC5tYXgoMCwgdG9wICsgcGl4ZWxzIC0gNTApO1xuICAgICAgZWxzZSBib3QgPSBNYXRoLm1pbihjbS5kb2MuaGVpZ2h0LCBib3QgKyBwaXhlbHMgKyA1MCk7XG4gICAgICB1cGRhdGVEaXNwbGF5U2ltcGxlKGNtLCB7dG9wOiB0b3AsIGJvdHRvbTogYm90fSk7XG4gICAgfVxuXG4gICAgaWYgKHdoZWVsU2FtcGxlcyA8IDIwKSB7XG4gICAgICBpZiAoZGlzcGxheS53aGVlbFN0YXJ0WCA9PSBudWxsKSB7XG4gICAgICAgIGRpc3BsYXkud2hlZWxTdGFydFggPSBzY3JvbGwuc2Nyb2xsTGVmdDsgZGlzcGxheS53aGVlbFN0YXJ0WSA9IHNjcm9sbC5zY3JvbGxUb3A7XG4gICAgICAgIGRpc3BsYXkud2hlZWxEWCA9IGR4OyBkaXNwbGF5LndoZWVsRFkgPSBkeTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAoZGlzcGxheS53aGVlbFN0YXJ0WCA9PSBudWxsKSByZXR1cm47XG4gICAgICAgICAgdmFyIG1vdmVkWCA9IHNjcm9sbC5zY3JvbGxMZWZ0IC0gZGlzcGxheS53aGVlbFN0YXJ0WDtcbiAgICAgICAgICB2YXIgbW92ZWRZID0gc2Nyb2xsLnNjcm9sbFRvcCAtIGRpc3BsYXkud2hlZWxTdGFydFk7XG4gICAgICAgICAgdmFyIHNhbXBsZSA9IChtb3ZlZFkgJiYgZGlzcGxheS53aGVlbERZICYmIG1vdmVkWSAvIGRpc3BsYXkud2hlZWxEWSkgfHxcbiAgICAgICAgICAgIChtb3ZlZFggJiYgZGlzcGxheS53aGVlbERYICYmIG1vdmVkWCAvIGRpc3BsYXkud2hlZWxEWCk7XG4gICAgICAgICAgZGlzcGxheS53aGVlbFN0YXJ0WCA9IGRpc3BsYXkud2hlZWxTdGFydFkgPSBudWxsO1xuICAgICAgICAgIGlmICghc2FtcGxlKSByZXR1cm47XG4gICAgICAgICAgd2hlZWxQaXhlbHNQZXJVbml0ID0gKHdoZWVsUGl4ZWxzUGVyVW5pdCAqIHdoZWVsU2FtcGxlcyArIHNhbXBsZSkgLyAod2hlZWxTYW1wbGVzICsgMSk7XG4gICAgICAgICAgKyt3aGVlbFNhbXBsZXM7XG4gICAgICAgIH0sIDIwMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaXNwbGF5LndoZWVsRFggKz0gZHg7IGRpc3BsYXkud2hlZWxEWSArPSBkeTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBLRVkgRVZFTlRTXG5cbiAgLy8gUnVuIGEgaGFuZGxlciB0aGF0IHdhcyBib3VuZCB0byBhIGtleS5cbiAgZnVuY3Rpb24gZG9IYW5kbGVCaW5kaW5nKGNtLCBib3VuZCwgZHJvcFNoaWZ0KSB7XG4gICAgaWYgKHR5cGVvZiBib3VuZCA9PSBcInN0cmluZ1wiKSB7XG4gICAgICBib3VuZCA9IGNvbW1hbmRzW2JvdW5kXTtcbiAgICAgIGlmICghYm91bmQpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gRW5zdXJlIHByZXZpb3VzIGlucHV0IGhhcyBiZWVuIHJlYWQsIHNvIHRoYXQgdGhlIGhhbmRsZXIgc2VlcyBhXG4gICAgLy8gY29uc2lzdGVudCB2aWV3IG9mIHRoZSBkb2N1bWVudFxuICAgIGNtLmRpc3BsYXkuaW5wdXQuZW5zdXJlUG9sbGVkKCk7XG4gICAgdmFyIHByZXZTaGlmdCA9IGNtLmRpc3BsYXkuc2hpZnQsIGRvbmUgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgaWYgKG
23459lzUmVhZE9ubHkoY20pKSBjbS5zdGF0ZS5zdXBwcmVzc0VkaXRzID0gdHJ1ZTtcbiAgICAgIGlmIChkcm9wU2hpZnQpIGNtLmRpc3BsYXkuc2hpZnQgPSBmYWxzZTtcbiAgICAgIGRvbmUgPSBib3VuZChjbSkgIT0gUGFzcztcbiAgICB9IGZpbmFsbHkge1xuICAgICAgY20uZGlzcGxheS5zaGlmdCA9IHByZXZTaGlmdDtcbiAgICAgIGNtLnN0YXRlLnN1cHByZXNzRWRpdHMgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGRvbmU7XG4gIH1cblxuICBmdW5jdGlvbiBsb29rdXBLZXlGb3JFZGl0b3IoY20sIG5hbWUsIGhhbmRsZSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY20uc3RhdGUua2V5TWFwcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHJlc3VsdCA9IGxvb2t1cEtleShuYW1lLCBjbS5zdGF0ZS5rZXlNYXBzW2ldLCBoYW5kbGUsIGNtKTtcbiAgICAgIGlmIChyZXN1bHQpIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIHJldHVybiAoY20ub3B0aW9ucy5leHRyYUtleXMgJiYgbG9va3VwS2V5KG5hbWUsIGNtLm9wdGlvbnMuZXh0cmFLZXlzLCBoYW5kbGUsIGNtKSlcbiAgICAgIHx8IGxvb2t1cEtleShuYW1lLCBjbS5vcHRpb25zLmtleU1hcCwgaGFuZGxlLCBjbSk7XG4gIH1cblxuICB2YXIgc3RvcFNlcSA9IG5ldyBEZWxheWVkO1xuICBmdW5jdGlvbiBkaXNwYXRjaEtleShjbSwgbmFtZSwgZSwgaGFuZGxlKSB7XG4gICAgdmFyIHNlcSA9IGNtLnN0YXRlLmtleVNlcTtcbiAgICBpZiAoc2VxKSB7XG4gICAgICBpZiAoaXNNb2RpZmllcktleShuYW1lKSkgcmV0dXJuIFwiaGFuZGxlZFwiO1xuICAgICAgc3RvcFNlcS5zZXQoNTAsIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoY20uc3RhdGUua2V5U2VxID09IHNlcSkge1xuICAgICAgICAgIGNtLnN0YXRlLmtleVNlcSA9IG51bGw7XG4gICAgICAgICAgY20uZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG5hbWUgPSBzZXEgKyBcIiBcIiArIG5hbWU7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSBsb29rdXBLZXlGb3JFZGl0b3IoY20sIG5hbWUsIGhhbmRsZSk7XG5cbiAgICBpZiAocmVzdWx0ID09IFwibXVsdGlcIilcbiAgICAgIGNtLnN0YXRlLmtleVNlcSA9IG5hbWU7XG4gICAgaWYgKHJlc3VsdCA9PSBcImhhbmRsZWRcIilcbiAgICAgIHNpZ25hbExhdGVyKGNtLCBcImtleUhhbmRsZWRcIiwgY20sIG5hbW
23459UsIGUpO1xuXG4gICAgaWYgKHJlc3VsdCA9PSBcImhhbmRsZWRcIiB8fCByZXN1bHQgPT0gXCJtdWx0aVwiKSB7XG4gICAgICBlX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgcmVzdGFydEJsaW5rKGNtKTtcbiAgICB9XG5cbiAgICBpZiAoc2VxICYmICFyZXN1bHQgJiYgL1xcJyQvLnRlc3QobmFtZSkpIHtcbiAgICAgIGVfcHJldmVudERlZmF1bHQoZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuICEhcmVzdWx0O1xuICB9XG5cbiAgLy8gSGFuZGxlIGEga2V5IGZyb20gdGhlIGtleWRvd24gZXZlbnQuXG4gIGZ1bmN0aW9uIGhhbmRsZUtleUJpbmRpbmcoY20sIGUpIHtcbiAgICB2YXIgbmFtZSA9IGtleU5hbWUoZSwgdHJ1ZSk7XG4gICAgaWYgKCFuYW1lKSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZiAoZS5zaGlmdEtleSAmJiAhY20uc3RhdGUua2V5U2VxKSB7XG4gICAgICAvLyBGaXJzdCB0cnkgdG8gcmVzb2x2ZSBmdWxsIG5hbWUgKGluY2x1ZGluZyAnU2hpZnQtJykuIEZhaWxpbmdcbiAgICAgIC8vIHRoYXQsIHNlZSBpZiB0aGVyZSBpcyBhIGN1cnNvci1tb3Rpb24gY29tbWFuZCAoc3RhcnRpbmcgd2l0aFxuICAgICAgLy8gJ2dvJykgYm91bmQgdG8gdGhlIGtleW5hbWUgd2l0aG91dCAnU2hpZnQtJy5cbiAgICAgIHJldHVybiBkaXNwYXRjaEtleShjbSwgXCJTaGlmdC1cIiArIG5hbWUsIGUsIGZ1bmN0aW9uKGIpIHtyZXR1cm4gZG9IYW5kbGVCaW5kaW5nKGNtLCBiLCB0cnVlKTt9KVxuICAgICAgICAgIHx8IGRpc3BhdGNoS2V5KGNtLCBuYW1lLCBlLCBmdW5jdGlvbihiKSB7XG4gICAgICAgICAgICAgICBpZiAodHlwZW9mIGIgPT0gXCJzdHJpbmdcIiA/IC9eZ29bQS1aXS8udGVzdChiKSA6IGIubW90aW9uKVxuICAgICAgICAgICAgICAgICByZXR1cm4gZG9IYW5kbGVCaW5kaW5nKGNtLCBiKTtcbiAgICAgICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRpc3BhdGNoS2V5KGNtLCBuYW1lLCBlLCBmdW5jdGlvbihiKSB7IHJldHVybiBkb0hhbmRsZUJpbmRpbmcoY20sIGIpOyB9KTtcbiAgICB9XG4gIH1cblxuICAvLyBIYW5kbGUgYSBrZXkgZnJvbSB0aGUga2V5cHJlc3MgZXZlbnRcbiAgZnVuY3Rpb24gaGFuZGxlQ2hhckJpbmRpbmcoY20sIGUsIGNoKSB7XG4gICAgcmV0dXJuIGRpc3BhdGNoS2V5KGNtLCBcIidcIiArIGNoICsgXCInXCIsIGUsXG4gICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGIpIHsgcmV0dXJuIGRvSGFuZGxlQmluZGluZyhjbSwgYiwgdHJ1ZSk7IH0pO1xuICB9XG5cbiAgdmFyIGxhc3RTdG9wcGVkS2V5ID0gbnVsbDtcbiAgZnVuY3Rpb24gb25LZXlEb3duKGUpIHtcbiAgICB2YXIgY20gPSB0aGlzO1xuICAgIGNtLmN1ck9wLmZvY3VzID0gYWN0aXZlRWx0KCk7XG4gICAgaWYgKHNpZ25hbERPTUV2ZW50KGNtLCBlKSkgcmV0dXJuO1xuICAgIC8vIElFIGRvZXMgc3RyYW5nZSB0aGluZ3Mgd2l0aCBlc2NhcGUuXG4gICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCAxMSAmJiBlLmtleUNvZGUgPT0gMjcpIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICB2YXIgY29kZSA9IGUua2V5Q29kZTtcbiAgICBjbS5kaXNwbGF5LnNoaWZ0ID0gY29kZSA9PSAxNiB8fCBlLnNoaWZ0S2V5O1xuICAgIHZhciBoYW5kbGVkID0gaGFuZGxlS2V5QmluZGluZyhjbSwgZSk7XG4gICAgaWYgKHByZXN0bykge1xuICAgICAgbGFzdFN0b3BwZWRLZXkgPSBoYW5kbGVkID8gY29kZSA6IG51bGw7XG4gICAgICAvLyBPcGVyYSBoYXMgbm8gY3V0IGV2ZW50Li4uIHdlIHRyeSB0byBhdCBsZWFzdCBjYXRjaCB0aGUga2V5IGNvbWJvXG4gICAgICBpZiAoIWhhbmRsZWQgJiYgY29kZSA9PSA4OCAmJiAhaGFzQ29weUV2ZW50ICYmIChtYWMgPyBlLm1ldGFLZXkgOiBlLmN0cmxLZXkpKVxuICAgICAgICBjbS5yZXBsYWNlU2VsZWN0aW9uKFwiXCIsIG51bGwsIFwiY3V0XCIpO1xuICAgIH1cblxuICAgIC8vIFR1cm4gbW91c2UgaW50byBjcm9zc2hhaXIgd2hlbiBBbHQgaXMgaGVsZCBvbiBNYWMuXG4gICAgaWYgKGNvZGUgPT0gMTggJiYgIS9cXGJDb2RlTWlycm9yLWNyb3NzaGFpclxcYi8udGVzdChjbS5kaXNwbGF5LmxpbmVEaXYuY2xhc3NOYW1lKSlcbiAgICAgIHNob3dDcm9zc0hhaXIoY20pO1xuICB9XG5cbiAgZnVuY3Rpb24gc2hvd0Nyb3NzSGFpcihjbSkge1xuICAgIHZhciBsaW5lRGl2ID0gY20uZGlzcGxheS5saW5lRGl2O1xuICAgIGFkZENsYXNzKGxpbmVEaXYsIFwiQ29kZU1pcnJvci1jcm9zc2hhaXJcIik7XG5cbiAgICBmdW5jdGlvbiB1cChlKSB7XG4gICAgICBpZiAoZS5rZXlDb2RlID09IDE4IHx8ICFlLmFsdEtleSkge1xuICAgICAgICBybUNsYXNzKGxpbmVEaXYsIFwiQ29kZU1pcnJvci1jcm9zc2hhaXJcIik7XG4gICAgICAgIG9mZihkb2N1bWVudCwgXCJrZXl1cFwiLCB1cCk7XG4gICAgICAgIG9mZihkb2N1bWVudCwgXCJtb3VzZW92ZXJcIiwgdXApO1xuICAgICAgfVxuICAgIH1cbiAgICBvbihkb2N1bWVudCwgXCJrZXl1cFwiLCB1cCk7XG4gICAgb24oZG9jdW1lbnQsIFwibW91c2VvdmVyXCIsIHVwKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uS2V5VXAoZSkge1xuICAgIGlmIChlLmtleUNvZGUgPT0gMTYpIHRoaXMuZG9jLnNlbC5zaGlmdCA9IGZhbHNlO1xuICAgIHNpZ25hbERPTUV2ZW50KHRoaXMsIGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gb25LZXlQcmVzcyhlKSB7XG4gICAgdmFyIGNtID0gdGhpcztcbiAgICBpZiAoZXZlbnRJbldpZGdldChjbS5kaXNwbGF5LCBlKSB8fCBzaWduYWxET01FdmVudChjbSwgZSkgfHwgZS5jdHJsS2V5ICYmICFlLmFsdEtleSB8fCBtYWMgJiYgZS5tZXRhS2V5KSByZXR1cm47XG4gICAgdmFyIGtleUNvZGUgPSBlLmtleUNvZGUsIGNoYXJDb2RlID0gZS5jaGFyQ29kZTtcbiAgICBpZiAocHJlc3RvICYmIGtleUNvZGUgPT0gbGFzdFN0b3BwZWRLZXkpIHtsYXN0U3RvcHBlZEtleSA9IG51bGw7IGVfcHJldmVudERlZmF1bHQoZSk7IHJldHVybjt9XG4gICAgaWYgKChwcmVzdG8gJiYgKCFlLndoaWNoIHx8IGUud2hpY2ggPCAxMCkpICYmIGhhbmRsZUtleUJpbmRpbmcoY20sIGUpKSByZXR1cm47XG4gICAgdmFyIGNoID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSA9PSBudWxsID8ga2V5Q29kZSA6IGNoYXJDb2RlKTtcbiAgICBpZiAoaGFuZGxlQ2hhckJpbmRpbmcoY20sIGUsIGNoKSkgcmV0dXJuO1xuICAgIGNtLmRpc3BsYXkuaW5wdXQub25LZXlQcmVzcyhlKTtcbiAgfVxuXG4gIC8vIEZPQ1VTL0JMVVIgRVZFTlRTXG5cbiAgZnVuY3Rpb24gZGVsYXlCbHVyRXZlbnQoY20pIHtcbiAgICBjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCA9IHRydWU7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIGlmIChjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCkge1xuICAgICAgICBjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCA9IGZhbHNlO1xuICAgICAgICBvbkJsdXIoY20pO1xuICAgICAgfVxuICAgIH0sIDEwMCk7XG4gIH1cblxuICBmdW5jdGlvbiBvbkZvY3VzKGNtKSB7XG4gICAgaWYgKGNtLnN0YXRlLmRlbGF5aW5nQmx1ckV2ZW50KSBjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCA9IGZhbHNlO1xuXG4gICAgaWYgKGNtLm9wdGlvbnMucmVhZE9ubHkgPT0gXCJub2N1cnNvclwiKSByZXR1cm47XG4gICAgaWYgKCFjbS5zdGF0ZS5mb2N1c2VkKSB7XG4gICAgICBzaWduYWwoY20sIFwiZm9jdXNcIiwgY20pO1xuICAgICAgY20uc3RhdGUuZm9jdXNlZCA9IHRydWU7XG4gICAgICBhZGRDbGFzcyhjbS5kaXNwbGF5LndyYXBwZXIsIFwiQ29kZU1pcnJvci1mb2N1c2VkXCIpO1xuICAgICAgLy8gVGhpcyB0ZXN0IH
23459ByZXZlbnRzIHRoaXMgZnJvbSBmaXJpbmcgd2hlbiBhIGNvbnRleHRcbiAgICAgIC8vIG1lbnUgaXMgY2xvc2VkIChzaW5jZSB0aGUgaW5wdXQgcmVzZXQgd291bGQga2lsbCB0aGVcbiAgICAgIC8vIHNlbGVjdC1hbGwgZGV0ZWN0aW9uIGhhY2spXG4gICAgICBpZiAoIWNtLmN1ck9wICYmIGNtLmRpc3BsYXkuc2VsRm9yQ29udGV4dE1lbnUgIT0gY20uZG9jLnNlbCkge1xuICAgICAgICBjbS5kaXNwbGF5LmlucHV0LnJlc2V0KCk7XG4gICAgICAgIGlmICh3ZWJraXQpIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNtLmRpc3BsYXkuaW5wdXQucmVzZXQodHJ1ZSk7IH0sIDIwKTsgLy8gSXNzdWUgIzE3MzBcbiAgICAgIH1cbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQucmVjZWl2ZWRGb2N1cygpO1xuICAgIH1cbiAgICByZXN0YXJ0QmxpbmsoY20pO1xuICB9XG4gIGZ1bmN0aW9uIG9uQmx1cihjbSkge1xuICAgIGlmIChjbS5zdGF0ZS5kZWxheWluZ0JsdXJFdmVudCkgcmV0dXJuO1xuXG4gICAgaWYgKGNtLnN0YXRlLmZvY3VzZWQpIHtcbiAgICAgIHNpZ25hbChjbSwgXCJibHVyXCIsIGNtKTtcbiAgICAgIGNtLnN0YXRlLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgIHJtQ2xhc3MoY20uZGlzcGxheS53cmFwcGVyLCBcIkNvZGVNaXJyb3ItZm9jdXNlZFwiKTtcbiAgICB9XG4gICAgY2xlYXJJbnRlcnZhbChjbS5kaXNwbGF5LmJsaW5rZXIpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7aWYgKCFjbS5zdGF0ZS5mb2N1c2VkKSBjbS5kaXNwbGF5LnNoaWZ0ID0gZmFsc2U7fSwgMTUwKTtcbiAgfVxuXG4gIC8vIENPTlRFWFQgTUVOVSBIQU5ETElOR1xuXG4gIC8vIFRvIG1ha2UgdGhlIGNvbnRleHQgbWVudSB3b3JrLCB3ZSBuZWVkIHRvIGJyaWVmbHkgdW5oaWRlIHRoZVxuICAvLyB0ZXh0YXJlYSAobWFraW5nIGl0IGFzIHVub2J0cnVzaXZlIGFzIHBvc3NpYmxlKSB0byBsZXQgdGhlXG4gIC8vIHJpZ2h0LWNsaWNrIHRha2UgZWZmZWN0IG9uIGl0LlxuICBmdW5jdGlvbiBvbkNvbnRleHRNZW51KGNtLCBlKSB7XG4gICAgaWYgKGV2ZW50SW5XaWRnZXQoY20uZGlzcGxheSwgZSkgfHwgY29udGV4dE1lbnVJbkd1dHRlcihjbSwgZSkpIHJldHVybjtcbiAgICBpZiAoc2lnbmFsRE9NRXZlbnQoY20sIGUsIFwiY29udGV4dG1lbnVcIikpIHJldHVybjtcbiAgICBjbS5kaXNwbGF5LmlucHV0Lm9uQ29udGV4dE1lbnUoZSk7XG4gIH1cblxuICBmdW5jdGlvbiBjb250ZXh0TWVudUluR3V0dGVyKGNtLCBlKSB7XG4gICAgaWYgKCFoYXNIYW5kbGVyKGNtLCBcImd1dHRlckNvbnRleHRNZW51XCIpKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIGd1dHRlckV2ZW50KGNtLCBlLCBcImd1dHRlckNvbnRleHRNZW51XCIsIGZhbHNlLCBzaWduYWwpO1xuICB9XG5cbiAgLy8gVVBEQVRJTkdcblxuICAvLyBDb21wdXRlIHRoZSBwb3NpdGlvbiBvZiB0aGUgZW5kIG9mIGEgY2hhbmdlIChpdHMgJ3RvJyBwcm9wZXJ0eVxuICAvLyByZWZlcnMgdG8gdGhlIHByZS1jaGFuZ2UgZW5kKS5cbiAgdmFyIGNoYW5nZUVuZCA9IENvZGVNaXJyb3IuY2hhbmdlRW5kID0gZnVuY3Rpb24oY2hhbmdlKSB7XG4gICAgaWYgKCFjaGFuZ2UudGV4dCkgcmV0dXJuIGNoYW5nZS50bztcbiAgICByZXR1cm4gUG9zKGNoYW5nZS5mcm9tLmxpbmUgKyBjaGFuZ2UudGV4dC5sZW5ndGggLSAxLFxuICAgICAgICAgICAgICAgbHN0KGNoYW5nZS50ZXh0KS5sZW5ndGggKyAoY2hhbmdlLnRleHQubGVuZ3RoID09IDEgPyBjaGFuZ2UuZnJvbS5jaCA6IDApKTtcbiAgfTtcblxuICAvLyBBZGp1c3QgYSBwb3NpdGlvbiB0byByZWZlciB0byB0aGUgcG9zdC1jaGFuZ2UgcG9zaXRpb24gb2YgdGhlXG4gIC8vIHNhbWUgdGV4dCwgb3IgdGhlIGVuZCBvZiB0aGUgY2hhbmdlIGlmIHRoZSBjaGFuZ2UgY292ZXJzIGl0LlxuICBmdW5jdGlvbiBhZGp1c3RGb3JDaGFuZ2UocG9zLCBjaGFuZ2UpIHtcbiAgICBpZiAoY21wKHBvcywgY2hhbmdlLmZyb20pIDwgMCkgcmV0dXJuIHBvcztcbiAgICBpZiAoY21wKHBvcywgY2hhbmdlLnRvKSA8PSAwKSByZXR1cm4gY2hhbmdlRW5kKGNoYW5nZSk7XG5cbiAgICB2YXIgbGluZSA9IHBvcy5saW5lICsgY2hhbmdlLnRleHQubGVuZ3RoIC0gKGNoYW5nZS50by5saW5lIC0gY2hhbmdlLmZyb20ubGluZSkgLSAxLCBjaCA9IHBvcy5jaDtcbiAgICBpZiAocG9zLmxpbmUgPT0gY2hhbmdlLnRvLmxpbmUpIGNoICs9IGNoYW5nZUVuZChjaGFuZ2UpLmNoIC0gY2hhbmdlLnRvLmNoO1xuICAgIHJldHVybiBQb3MobGluZSwgY2gpO1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcHV0ZVNlbEFmdGVyQ2hhbmdlKGRvYywgY2hhbmdlKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucmFuZ2VzW2ldO1xuICAgICAgb3V0LnB1c2gobmV3IFJhbmdlKGFkanVzdEZvckNoYW5nZShyYW5nZS5hbmNob3IsIGNoYW5nZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgYWRqdXN0Rm9yQ2hhbmdlKHJhbmdlLmhlYWQsIGNoYW5nZSkpKTtcbiAgICB9XG4gICAgcmV0dXJuIG5vcm1hbGl6ZVNlbGVjdGlvbihvdXQsIGRvYy5zZWwucHJpbUluZGV4KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9mZnNldFBvcyhwb3MsIG9sZCwgbncpIHtcbiAgICBpZiAocG9zLmxpbmUgPT0gb2xkLmxpbmUpXG4gICAgICByZXR1cm4gUG9zKG53LmxpbmUsIHBvcy5jaCAtIG9sZC5jaCArIG53LmNoKTtcbiAgICBlbHNlXG4gICAgICByZXR1cm4gUG9zKG53LmxpbmUgKyAocG9zLmxpbmUgLSBvbGQubGluZSksIHBvcy5jaCk7XG4gIH1cblxuICAvLyBVc2VkIGJ5IHJlcGxhY2VTZWxlY3Rpb25zIHRvIGFsbG93IG1vdmluZyB0aGUgc2VsZWN0aW9uIHRvIHRoZVxuICAvLyBzdGFydCBvciBhcm91bmQgdGhlIHJlcGxhY2VkIHRlc3QuIEhpbnQgbWF5IGJlIFwic3RhcnRcIiBvciBcImFyb3VuZFwiLlxuICBmdW5jdGlvbiBjb21wdXRlUmVwbGFjZWRTZWwoZG9jLCBjaGFuZ2VzLCBoaW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBvbGRQcmV2ID0gUG9zKGRvYy5maXJzdCwgMCksIG5ld1ByZXYgPSBvbGRQcmV2O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYW5nZSA9IGNoYW5nZXNbaV07XG4gICAgICB2Y
23459XIgZnJvbSA9IG9mZnNldFBvcyhjaGFuZ2UuZnJvbSwgb2xkUHJldiwgbmV3UHJldik7XG4gICAgICB2YXIgdG8gPSBvZmZzZXRQb3MoY2hhbmdlRW5kKGNoYW5nZSksIG9sZFByZXYsIG5ld1ByZXYpO1xuICAgICAgb2xkUHJldiA9IGNoYW5nZS50bztcbiAgICAgIG5ld1ByZXYgPSB0bztcbiAgICAgIGlmIChoaW50ID09IFwiYXJvdW5kXCIpIHtcbiAgICAgICAgdmFyIHJhbmdlID0gZG9jLnNlbC5yYW5nZXNbaV0sIGludiA9IGNtcChyYW5nZS5oZWFkLCByYW5nZS5hbmNob3IpIDwgMDtcbiAgICAgICAgb3V0W2ldID0gbmV3IFJhbmdlKGludiA/IHRvIDogZnJvbSwgaW52ID8gZnJvbSA6IHRvKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFtpXSA9IG5ldyBSYW5nZShmcm9tLCBmcm9tKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBTZWxlY3Rpb24ob3V0LCBkb2Muc2VsLnByaW1JbmRleCk7XG4gIH1cblxuICAvLyBBbGxvdyBcImJlZm9yZUNoYW5nZVwiIGV2ZW50IGhhbmRsZXJzIHRvIGluZmx1ZW5jZSBhIGNoYW5nZVxuICBmdW5jdGlvbiBmaWx0ZXJDaGFuZ2UoZG9jLCBjaGFuZ2UsIHVwZGF0ZSkge1xuICAgIHZhciBvYmogPSB7XG4gICAgICBjYW5jZWxlZDogZmFsc2UsXG4gICAgICBmcm9tOiBjaGFuZ2UuZnJvbSxcbiAgICAgIHRvOiBjaGFuZ2UudG8sXG4gICAgICB0ZXh0OiBjaGFuZ2UudGV4dCxcbiAgICAgIG9yaWdpbjogY2hhbmdlLm9yaWdpbixcbiAgICAgIGNhbmNlbDogZnVuY3Rpb24oKSB7IHRoaXMuY2FuY2VsZWQgPSB0cnVlOyB9XG4gICAgfTtcbiAgICBpZiAodXBkYXRlKSBvYmoudXBkYXRlID0gZnVuY3Rpb24oZnJvbSwgdG8sIHRleHQsIG9yaWdpbikge1xuICAgICAgaWYgKGZyb20pIHRoaXMuZnJvbSA9IGNsaXBQb3MoZG9jLCBmcm9tKTtcbiAgICAgIGlmICh0bykgdGhpcy50byA9IGNsaXBQb3MoZG9jLCB0byk7XG4gICAgICBpZiAodGV4dCkgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICAgIGlmIChvcmlnaW4gIT09IHVuZGVmaW5lZCkgdGhpcy5vcmlnaW4gPSBvcmlnaW47XG4gICAgfTtcbiAgICBzaWduYWwoZG9jLCBcImJlZm9yZUNoYW5nZVwiLCBkb2MsIG9iaik7XG4gICAgaWYgKGRvYy5jbSkgc2lnbmFsKGRvYy5jbSwgXCJiZWZvcmVDaGFuZ2VcIiwgZG9jLmNtLCBvYmopO1xuXG4gICAgaWYgKG9iai5jYW5jZWxlZCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHtmcm9tOiBvYmouZnJvbSwgdG86IG9iai50bywgdGV4dDogb2JqLnRleHQsIG9yaWdpbjogb2JqLm9yaWdpbn07XG4gIH1cblxuICAvLyBBcHBseSBhIGNoYW5nZSB0byBhIGRvY3VtZW50LCBhbmQgYWRkIGl0IHRvIHRoZSBkb2N1bWVudCdzXG4gIC8vIGhpc3RvcnksIGFuZCBwcm9wYWdhdGluZyBpdCB0byBhbGwgbGlua2VkIGRvY3VtZW50cy5cbiAgZnVuY3Rpb24gbWFrZUNoYW5nZShkb2MsIGNoYW5nZSwgaWdub3JlUmVhZE9ubHkpIHtcbiAgICBpZiAoZG9jLmNtKSB7XG4gICAgICBpZiAoIWRvYy5jbS5jdXJPcCkgcmV0dXJuIG9wZXJhdGlvbihkb2MuY20sIG1ha2VDaGFuZ2UpKGRvYywgY2hhbmdlLCBpZ25vcmVSZWFkT25seSk7XG4gICAgICBpZiAoZG9jLmNtLnN0YXRlLnN1cHByZXNzRWRpdHMpIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaGFzSGFuZGxlcihkb2MsIFwiYmVmb3JlQ2hhbmdlXCIpIHx8IGRvYy5jbSAmJiBoYXNIYW5kbGVyKGRvYy5jbSwgXCJiZWZvcmVDaGFuZ2VcIikpIHtcbiAgICAgIGNoYW5nZSA9IGZpbHRlckNoYW5nZShkb2MsIGNoYW5nZSwgdHJ1ZSk7XG4gICAgICBpZiAoIWNoYW5nZSkgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFBvc3NpYmx5IHNwbGl0IG9yIHN1cHByZXNzIHRoZSB1cGRhdGUgYmFzZWQgb24gdGhlIHByZXNlbmNlXG4gICAgLy8gb2YgcmVhZC1vbmx5IHNwYW5zIGluIGl0cyByYW5nZS5cbiAgICB2YXIgc3BsaXQgPSBzYXdSZWFkT25seVNwYW5zICYmICFpZ25vcmVSZWFkT25seSAmJiByZW1vdmVSZWFkT25seVJhbmdlcyhkb2MsIGNoYW5nZS5mcm9tLCBjaGFuZ2UudG8pO1xuICAgIGlmIChzcGxpdCkge1xuICAgICAgZm9yICh2YXIgaSA9IHNwbGl0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKVxuICAgICAgICBtYWtlQ2hhbmdlSW5uZXIoZG9jLCB7ZnJvbTogc3BsaXRbaV0uZnJvbSwgdG86IHNwbGl0W2ldLnRvLCB0ZXh0OiBpID8gW1wiXCJdIDogY2hhbmdlLnRleHR9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWFrZUNoYW5nZUlubmVyKGRvYywgY2hhbmdlKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBtYWtlQ2hhbmdlSW5uZXIoZG9jLCBjaGFuZ2UpIHtcbiAgICBpZiAoY2hhbmdlLnRleHQubGVuZ3RoID09IDEgJiYgY2hhbmdlLnRleHRbMF0gPT0gXCJcIiAmJiBjbXAoY2hhbmdlLmZyb20sIGNoYW5nZS50bykgPT0gMCkgcmV0dXJuO1xuICAgIHZhciBzZWxBZnRlciA9IGNvbXB1dGVTZWxBZnRlckNoYW5nZShkb2MsIGNoYW5nZSk7XG4gICAgYWRkQ2hhbmdlVG9IaXN0b3J5KGRvYywgY2hhbmdlLCBzZWxBZnRlciwgZG9jLmNtID8gZG9jLmNtLmN1ck9wLmlkIDogTmFOKTtcblxuICAgIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIHNlbEFmdGVyLCBzdHJldGNoU3BhbnNPdmVyQ2hhbmdlKGRvYywgY2hhbmdlKSk7XG4gICAgdmFyIHJlYmFzZWQgPSBbXTtcblxuICAgIGxpbmtlZERvY3MoZG9jLCBmdW5jdGlvbihkb2MsIHNoYXJlZEhpc3QpIHtcbiAgICAgIGlmICghc2hhcmVkSGlzdCAmJiBpbmRleE9mKHJlYmFzZWQsIGRvYy5oaXN0b3J5KSA9PSAtMSkge1xuICAgICAgICByZWJhc2VIaXN0KGRvYy5oaXN0b3J5LCBjaGFuZ2UpO1xuICAgICAgICByZWJhc2VkLnB1c2goZG9jLmhpc3RvcnkpO1xuICAgICAgfVxuICAgICAgbWFrZUNoYW5nZVNpbmdsZURvYyhkb2MsIGNoYW5nZSwgbnVsbCwgc3RyZXRjaFNwYW5zT3ZlckNoYW5nZShkb2MsIGNoYW5nZSkpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gUmV2ZXJ0IGEgY2hhbmdlIHN0b3JlZCBpbiBhIGRvY3VtZW50J3MgaGlzdG9yeS5cbiAgZnVuY3Rpb24gbWFrZUNoYW5nZUZyb21IaXN0b3J5KGRvYywgdHlwZSwgYWxsb3dTZWxlY3Rpb25Pbmx5KSB7XG4gICAgaWYgKGRvYy5jbSAmJiBkb2MuY20uc3RhdGUuc3VwcHJlc3NFZGl0cykgcmV0dXJuO1xuXG4gICAgdmFyIGhpc3QgPSBkb2MuaGlzdG9yeSwgZXZlbnQsIHNlbEFmdGVyID0gZG9jLnNlbDtcbiAgICB2YXIgc291cmNlID0gdHlwZSA9PSBcInVuZG9cIiA/IGhpc3QuZG9uZSA6IGhpc3QudW5kb25lLCBkZXN0ID0gdHlwZSA9PSBcInVuZG9cIiA/IGhpc3QudW5kb25lIDogaGlzdC5kb25lO1xuXG4gICAgLy8gVmVyaWZ5IHRoYXQgdGhlcmUgaXMgYSB1c2VhYmxlIGV2ZW50IChzbyB0aGF0IGN0cmwteiB3b24ndFxuICAgIC8vIG5lZWRsZXNzbHkgY2xlYXIgc2VsZWN0aW9uIGV2ZW50cylcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuICAgICAgZXZlbnQgPSBzb3VyY2VbaV07XG4gICAgICBpZiAoYWxsb3dTZWxlY3Rpb25Pbmx5ID8gZXZlbnQucmFuZ2VzICYmICFldmVudC5lcXVhbHMoZG9jLnNlbCkgOiAhZXZlbnQucmFuZ2VzKVxuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgaWYgKGkgPT0gc291cmNlLmxlbmd0aCkgcmV0dXJuO1xuICAgIGhpc3QubGFzdE9yaWdpbiA9IGhpc3QubGFzdFNlbE9yaWdpbiA9IG51bGw7XG5cbiAgICBmb3IgKDs7KSB7XG4gICAgICBldmVudCA9IHNvdXJjZS5wb3AoKTtcbiAgICAgIGlmIChldmVudC5yYW5nZXMpIHtcbiAgICAgICAgcHVzaFNlbGVjdGlvblRvSGlzdG9yeShldmVudCwgZGVzdCk7XG4gICAgICAgIGlmIChhbGxvd1NlbGVjdGlvbk9ubHkgJiYgIWV2ZW50LmVxdWFscyhkb2Muc2VsKSkge1xuICAgICAgICAgI
23459HNldFNlbGVjdGlvbihkb2MsIGV2ZW50LCB7Y2xlYXJSZWRvOiBmYWxzZX0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzZWxBZnRlciA9IGV2ZW50O1xuICAgICAgfVxuICAgICAgZWxzZSBicmVhaztcbiAgICB9XG5cbiAgICAvLyBCdWlsZCB1cCBhIHJldmVyc2UgY2hhbmdlIG9iamVjdCB0byBhZGQgdG8gdGhlIG9wcG9zaXRlIGhpc3RvcnlcbiAgICAvLyBzdGFjayAocmVkbyB3aGVuIHVuZG9pbmcsIGFuZCB2aWNlIHZlcnNhKS5cbiAgICB2YXIgYW50aUNoYW5nZXMgPSBbXTtcbiAgICBwdXNoU2VsZWN0aW9uVG9IaXN0b3J5KHNlbEFmdGVyLCBkZXN0KTtcbiAgICBkZXN0LnB1c2goe2NoYW5nZXM6IGFudGlDaGFuZ2VzLCBnZW5lcmF0aW9uOiBoaXN0LmdlbmVyYXRpb259KTtcbiAgICBoaXN0LmdlbmVyYXRpb24gPSBldmVudC5nZW5lcmF0aW9uIHx8ICsraGlzdC5tYXhHZW5lcmF0aW9uO1xuXG4gICAgdmFyIGZpbHRlciA9IGhhc0hhbmRsZXIoZG9jLCBcImJlZm9yZUNoYW5nZVwiKSB8fCBkb2MuY20gJiYgaGFzSGFuZGxlcihkb2MuY20sIFwiYmVmb3JlQ2hhbmdlXCIpO1xuXG4gICAgZm9yICh2YXIgaSA9IGV2ZW50LmNoYW5nZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHZhciBjaGFuZ2UgPSBldmVudC5jaGFuZ2VzW2ldO1xuICAgICAgY2hhbmdlLm9yaWdpbiA9IHR5cGU7XG4gICAgICBpZiAoZmlsdGVyICYmICFmaWx0ZXJDaGFuZ2UoZG9jLCBjaGFuZ2UsIGZhbHNlKSkge1xuICAgICAgICBzb3VyY2UubGVuZ3RoID0gMDtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBhbnRpQ2hhbmdlcy5wdXNoKGhpc3RvcnlDaGFuZ2VGcm9tQ2hhbmdlKGRvYywgY2hhbmdlKSk7XG5cbiAgICAgIHZhciBhZnRlciA9IGkgPyBjb21wdXRlU2VsQWZ0ZXJDaGFuZ2UoZG9jLCBjaGFuZ2UpIDogbHN0KHNvdXJjZSk7XG4gICAgICBtYWtlQ2hhbmdlU2luZ2xlRG9jKGRvYywgY2hhbmdlLCBhZnRlciwgbWVyZ2VPbGRTcGFucyhkb2MsIGNoYW5nZSkpO1xuICAgICAgaWYgKCFpICYmIGRvYy5jbSkgZG9jLmNtLnNjcm9sbEludG9WaWV3KHtmcm9tOiBjaGFuZ2UuZnJvbSwgdG86IGNoYW5nZUVuZChjaGFuZ2UpfSk7XG4gICAgICB2Y
23459XIgcmViYXNlZCA9IFtdO1xuXG4gICAgICAvLyBQcm9wYWdhdGUgdG8gdGhlIGxpbmtlZCBkb2N1bWVudHNcbiAgICAgIGxpbmtlZERvY3MoZG9jLCBmdW5jdGlvbihkb2MsIHNoYXJlZEhpc3QpIHtcbiAgICAgICAgaWYgKCFzaGFyZWRIaXN0ICYmIGluZGV4T2YocmViYXNlZCwgZG9jLmhpc3RvcnkpID09IC0xKSB7XG4gICAgICAgICAgcmViYXNlSGlzdChkb2MuaGlzdG9yeSwgY2hhbmdlKTtcbiAgICAgICAgICByZWJhc2VkLnB1c2goZG9jLmhpc3RvcnkpO1xuICAgICAgICB9XG4gICAgICAgIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIG51bGwsIG1lcmdlT2xkU3BhbnMoZG9jLCBjaGFuZ2UpKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFN1Yi12aWV3cyBuZWVkIHRoZWlyIGxpbmUgbnVtYmVycyBzaGlmdGVkIHdoZW4gdGV4dCBpcyBhZGRlZFxuICAvLyBhYm92ZSBvciBiZWxvdyB0aGVtIGluIHRoZSBwYXJlbnQgZG9jdW1lbnQuXG4gIGZ1bmN0aW9uIHNoaWZ0RG9jKGRvYywgZGlzdGFuY2UpIHtcbiAgICBpZiAoZGlzdGFuY2UgPT0gMCkgcmV0dXJuO1xuICAgIGRvYy5maXJzdCArPSBkaXN0YW5jZTtcbiAgICBkb2Muc2VsID0gbmV3IFNlbGVjdGlvbihtYXAoZG9jLnNlbC5yYW5nZXMsIGZ1bmN0aW9uKHJhbmdlKSB7XG4gICAgICByZXR1cm4gbmV3IFJhbmdlKFBvcyhyYW5nZS5hbmNob3IubGluZSArIGRpc3RhbmNlLCByYW5nZS5hbmNob3IuY2gpLFxuICAgICAgICAgICAgICAgICAgICAgICBQb3MocmFuZ2UuaGVhZC5saW5lICsgZGlzdGFuY2UsIHJhbmdlLmhlYWQuY2gpKTtcbiAgICB9KSwgZG9jLnNlbC5wcmltSW5kZXgpO1xuICAgIGlmIChkb2MuY20pIHtcbiAgICAgIHJlZ0NoYW5nZShkb2MuY20sIGRvYy5maXJzdCwgZG9jLmZpcnN0IC0gZGlzdGFuY2UsIGRpc3RhbmNlKTtcbiAgICAgIGZvciAodmFyIGQgPSBkb2MuY20uZGlzcGxheSwgbCA9IGQudmlld0Zyb207IGwgPCBkLnZpZXdUbzsgbCsrKVxuICAgICAgICByZWdMaW5lQ2hhbmdlKGRvYy5jbSwgbCwgXCJndXR0ZXJcIik7XG4gICAgfVxuICB9XG5cbiAgLy8gTW9yZSBsb3dlci1sZXZlbCBjaGFuZ2UgZnVuY3Rpb24sIGhhbmRsaW5nIG9ubHkgYSBzaW5nbGUgZG9jdW1lbnRcbiAgLy8gKG5vdCBsaW5rZWQgb25lcykuXG4gIGZ1bmN0aW9uIG1ha2VDaGFuZ2VTaW5nbGVEb2MoZG9jLCBjaGFuZ2UsIHNlbEFmdGVyLCBzcGFucykge1xuICAgIGlmIChkb2MuY20gJiYgIWRvYy5jbS5jdXJPcClcbiAgICAgIHJldHVybiBvcGVyYXRpb24oZG9jLmNtLCBtYWtlQ2hhbmdlU2luZ2xlRG9jKShkb2MsIGNoYW5nZSwgc2VsQWZ0ZXIsIHNwYW5zKTtcblxuICAgIGlmIChjaGFuZ2UudG8ubGluZSA8IGRvYy5maXJzdCkge1xuICAgICAgc2hpZnREb2MoZG9jLCBjaGFuZ2UudGV4dC5sZW5ndGggLSAxIC0gKGNoYW5nZS50by5saW5lIC0gY2hhbmdlLmZyb20ubGluZSkpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlLmZyb20ubGluZSA+IGRvYy5sYXN0TGluZSgpKSByZXR1cm47XG5cbiAgICAvLyBDbGlwIHRoZSBjaGFuZ2UgdG8gdGhlIHNpemUgb2YgdGhpcyBkb2NcbiAgICBpZiAoY2hhbmdlLmZyb20ubGluZSA8IGRvYy5maXJzdCkge1xuICAgICAgdmFyIHNoaWZ0ID0gY2hhbmdlLnRleHQubGVuZ3RoIC0gMSAtIChkb2MuZmlyc3QgLSBjaGFuZ2UuZnJvbS5saW5lKTtcbiAgICAgIHNoaWZ0RG9jKGRvYywgc2hpZnQpO1xuICAgICAgY2hhbmdlID0ge2Zyb206IFBvcyhkb2MuZmlyc3QsIDApLCB0bzogUG9zKGNoYW5nZS50by5saW5lICsgc2hpZnQsIGNoYW5nZS50by5jaCksXG4gICAgICAgICAgICAgICAgdGV4dDogW2xzdChjaGFuZ2UudGV4dCldLCBvcmlnaW46IGNoYW5nZS5vcmlnaW59O1xuICAgIH1cbiAgICB2YXIgbGFzdCA9IGRvYy5sYXN0TGluZSgpO1xuICAgIGlmIChjaGFuZ2UudG8ubGluZSA+IGxhc3QpIHtcbiAgICAgIGNoYW5nZSA9IHtmcm9tOiBjaGFuZ2UuZnJvbSwgdG86IFBvcyhsYXN0LCBnZXRMaW5lKGRvYywgbGFzdCkudGV4dC5sZW5ndGgpLFxuICAgICAgICAgICAgICAgIHRleHQ6IFtjaGFuZ2UudGV4dFswXV0sIG9yaWdpbjogY2hhbmdlLm9yaWdpbn07XG4gICAgfVxuXG4gICAgY2hhbmdlLnJlbW92ZWQgPSBnZXRCZXR3ZWVuKGRvYywgY2hhbmdlLmZyb20sIGNoYW5nZS50byk7XG5cbiAgICBpZiAoIXNlbEFmdGVyKSBzZWxBZnRlciA9IGNvbXB1dGVTZWxBZnRlckNoYW5nZShkb2MsIGNoYW5nZSk7XG4gICAgaWYgKGRvYy5jbSkgbWFrZUNoYW5nZVNpbmdsZURvY0luRWRpdG9yKGRvYy5jbSwgY2hhbmdlLCBzcGFucyk7XG4gICAgZWxzZSB1cGRhdGVEb2MoZG9jLCBjaGFuZ2UsIHNwYW5zKTtcbiAgICBzZXRTZWxlY3Rpb25Ob1VuZG8oZG9jLCBzZWxBZnRlciwgc2VsX2RvbnRTY3JvbGwpO1xuICB9XG5cbiAgLy8gSGFuZGxlIHRoZSBpbnRlcmFjdGlvbiBvZiBhIGNoYW5nZSB0byBhIGRvY3VtZW50IHdpdGggdGhlIGVkaXRvclxuICAvLyB0aGF0IHRoaXMgZG9jdW1lbnQgaXMgcGFydCBvZi5cbiAgZnVuY3Rpb24gbWFrZUNoYW5nZVNpbmdsZURvY0luRWRpdG9yKGNtLCBjaGFuZ2UsIHNwYW5zKSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgZGlzcGxheSA9IGNtLmRpc3BsYXksIGZyb20gPSBjaGFuZ2UuZnJvbSwgdG8gPSBjaGFuZ2UudG87XG5cbiAgICB2YXIgcmVjb21wdXRlTWF4TGVuZ3RoID0gZmFsc2UsIGNoZWNrV2lkdGhTdGFydCA9IGZyb20ubGluZTtcbiAgICBpZiAoIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSB7XG4gICAgICBjaGVja1dpZHRoU3RhcnQgPSBsaW5lTm8odmlzdWFsTGluZShnZXRMaW5lKGRvYywgZnJvbS5saW5lKSkpO1xuICAgICAgZG9jLml0ZXIoY2hlY2tXaWR0aFN0YXJ0LCB0by5saW5lICsgMSwgZnVuY3Rpb24obGluZSkge1xuICAgICAgICBpZiAobGluZSA9PSBkaXNwbGF5Lm1heExpbmUpIHtcbiAgICAgICAgICByZWNvbXB1dGVNYXhMZW5ndGggPSB0cnVlO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoZG9jLnNlbC5jb250YWlucyhjaGFuZ2UuZnJvbSwgY2hhbmdlLnRvKSA+IC0xKVxuICAgICAgc2lnbmFsQ3Vyc29yQWN0aXZpdHkoY20pO1xuXG4gICAgdXBkYXRlRG9jKGRvYywgY2hhbmdlLCBzcGFucywgZXN0aW1hdGVIZWlnaHQoY20pKTtcblxuICAgIGlmICghY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHtcbiAgICAgIGRvYy5pdGVyKGNoZWNrV2lk
23459dGhTdGFydCwgZnJvbS5saW5lICsgY2hhbmdlLnRleHQubGVuZ3RoLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHZhciBsZW4gPSBsaW5lTGVuZ3RoKGxpbmUpO1xuICAgICAgICBpZiAobGVuID4gZGlzcGxheS5tYXhMaW5lTGVuZ3RoKSB7XG4gICAgICAgICAgZGlzcGxheS5tYXhMaW5lID0gbGluZTtcbiAgICAgICAgICBkaXNwbGF5Lm1heExpbmVMZW5ndGggPSBsZW47XG4gICAgICAgICAgZGlzcGxheS5tYXhMaW5lQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgcmVjb21wdXRlTWF4TGVuZ3RoID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaWYgKHJlY29tcHV0ZU1heExlbmd0aCkgY20uY3VyT3AudXBkYXRlTWF4TGluZSA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gQWRqdXN0IGZyb250aWVyLCBzY2hlZHVsZSB3b3JrZXJcbiAgICBkb2MuZnJvbnRpZXIgPSBNYXRoLm1pbihkb2MuZnJvbnRpZXIsIGZyb20ubGluZSk7XG4gICAgc3RhcnRXb3JrZXIoY20sIDQwMCk7XG5cbiAgICB2YXIgbGVuZGlmZiA9IGNoYW5nZS50ZXh0Lmxlbmd0aCAtICh0by5saW5lIC0gZnJvbS5saW5lKSAtIDE7XG4gICAgLy8gUmVtZW1iZXIgdGhhdCB0aGVzZSBsaW5lcyBjaGFuZ2VkLCBmb3IgdXBkYXRpbmcgdGhlIGRpc3BsYXlcbiAgICBpZiAoY2hhbmdlLmZ1bGwpXG4gICAgICByZWdDaGFuZ2UoY20pO1xuICAgIGVsc2UgaWYgKGZyb20ubGluZSA9PSB0by5saW5lICYmIGNoYW5nZS50ZXh0Lmxlbmd0aCA9PSAxICYmICFpc1dob2xlTGluZVVwZGF0ZShjbS5kb2MsIGNoYW5nZSkpXG4gICAgICByZWdMaW5lQ2hhbmdlKGNtLCBmcm9tLmxpbmUsIFwidGV4dFwiKTtcbiAgICBlbHNlXG4gICAgICByZWdDaGFuZ2UoY20sIGZyb20ubGluZSwgdG8ubGluZSArIDEsIGxlbmRpZmYpO1xuXG4gICAgdmFyIGNoYW5nZXNIYW5kbGVyID0gaGFzSGFuZGxlcihjbSwgXCJjaGFuZ2VzXCIpLCBjaGFuZ2VIYW5kbGVyID0gaGFzSGFuZGxlcihjbSwgXCJjaGFuZ2VcIik7XG4gICAgaWYgKGNoYW5nZUhhbmRsZXIgfHwgY2hhbmdlc0hhbmRsZXIpIHtcbiAgICAgIHZhciBvYmogPSB7XG4gICAgICAgIGZyb206IGZyb20sIHRvOiB0byxcbiAgICAgICAgdGV4dDogY2hhbmdlLnRleHQsXG4gICAgICAgIHJlbW92ZWQ6IGNoYW5nZS5yZW1vdmVkLFxuICAgICAgICBvcmlnaW46IGNoYW5nZS5vcmlnaW5cbiAgICAgIH07XG4gICAgICBpZiAoY2hhbmdlSGFuZGxlcikgc2lnbmFsTGF0ZXIoY20sIFwiY2hhbmdlXCIsIGNtLCBvYmopO1xuICAgICAgaWYgKGNoYW5nZXNIYW5kbGVyKSAoY20uY3VyT3AuY2hhbmdlT2JqcyB8fCAoY20uY3VyT3AuY2hhbmdlT2JqcyA9IFtdKSkucHVzaChvYmopO1xuICAgIH1cbiAgICBjbS5kaXNwbGF5LnNlbEZvckNvbnRleHRNZW51ID0gbnVsbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlcGxhY2VSYW5nZShkb2MsIGNvZGUsIGZyb20sIHRvLCBvcmlnaW4pIHtcbiAgICBpZiAoIXRvKSB0byA9IGZyb207XG4gICAgaWYgKGNtcCh0bywgZnJvbSkgPCAwKSB7IHZhciB0bXAgPSB0bzsgdG8gPSBmcm9tOyBmcm9tID0gdG1wOyB9XG4gICAgaWYgKHR5cGVvZiBjb2RlID09IFwic3RyaW5nXCIpIGNvZGUgPSBkb2Muc3BsaXRMaW5lcyhjb2RlKTtcbiAgICBtYWtlQ2hhbmdlKGRvYywge2Zyb206IGZyb20sIHRvOiB0bywgdGV4dDogY29kZSwgb3JpZ2luOiBvcmlnaW59KTtcbiAgfVxuXG4gIC8vIFNDUk9MTElORyBUSElOR1MgSU5UTyBWSUVXXG5cbiAgLy8gSWYgYW4gZWRpdG9yIHNpdHMgb24gdGhlIHRvcCBvciBib3R0b20gb2YgdGhlIHdpbmRvdywgcGFydGlhbGx5XG4gIC8vIHNjcm9sbGVkIG91dCBvZiB2aWV3LCB0aGlzIGVuc3VyZXMgdGhhdCB0aGUgY3Vyc29yIGlzIHZpc2libGUuXG4gIGZ1bmN0aW9uIG1heWJlU2Nyb2xsV2luZG93KGNtLCBjb29yZHMpIHtcbiAgICBpZiAoc2lnbmFsRE9NRXZlbnQoY20sIFwic2Nyb2xsQ3Vyc29ySW50b1ZpZXdcIikpIHJldHVybjtcblxuICAgIHZhciBkaXNwbGF5ID0gY20uZGlzcGxheSwgYm94ID0gZGlzcGxheS5zaXplci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSwgZG9TY3JvbGwgPSBudWxsO1xuICAgIGlmIChjb29yZHMudG9wICsgYm94LnRvcCA8IDApIGRvU2Nyb2xsID0gdHJ1ZTtcbiAgICBlbHNlIGlmIChjb29yZHMuYm90dG9tICsgYm94LnRvcCA+ICh3aW5kb3cuaW5uZXJIZWlnaHQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCkpIGRvU2Nyb2xsID0gZmFsc2U7XG4gICAgaWYgKGRvU2Nyb2xsICE9IG51bGwgJiYgIXBoYW50b20pIHtcbiAgICAgIHZhciBzY3JvbGxOb2RlID0gZWx0KFwiZGl2XCIsIFwiXFx1MjAwYlwiLCBudWxsLCBcInBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAoY29vcmRzLnRvcCAtIGRpc3BsYXkudmlld09mZnNldCAtIHBhZGRpbmdUb3AoY20uZGlzcGxheSkpICsgXCJweDsgaGVpZ2h0OiBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAoY29vcmRzLmJvdHRvbSAtIGNvb3Jkcy50b3AgKyBzY3JvbGxHYXAoY20pICsgZGlzcGxheS5iYXJIZWlnaHQpICsgXCJweDsgbGVmdDogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRzLmxlZnQgKyBcInB4OyB3aWR0aDogMnB4O1wiKTtcbiAgICAgIGNtLmRpc3BsYXkubGluZVNwYWNlLmFwcGVuZENoaWxkKHNjcm9sbE5vZGUpO1xuICAgICAgc2Nyb2xsTm9kZS5zY3JvbGxJbnRvVmlldyhkb1Njcm9sbCk7XG4gICAgICBjbS5kaXNwbGF5LmxpbmVTcGFjZS5yZW1vdmVDaGlsZChzY3JvbGxOb2RlKTtcbiAgICB9XG4gIH1cblxuICAvLyBTY3JvbGwgYSBnaXZlbiBwb3NpdGlvbiBpbnRvIHZpZXcgKGltbWVkaWF0ZWx5KSwgdmVyaWZ5aW5nIHRoYXRcbiAgLy8gaXQgYWN0dWFsbHkgYmVjYW1lIHZpc2libGUgKGFzIGxpbmUgaGVpZ2h0cyBhcmUgYWNjdXJhdGVseVxuICAvLyBtZWFzdXJlZCwgdGhlIHBvc2l0aW9uIG9mIHNvbWV0aGluZyBtYXkgJ2RyaWZ0JyBkdXJpbmcgZHJhd2luZykuXG4gIGZ1bmN0aW9uIHNjcm9sbFBvc0ludG9WaWV3KGNtLCBwb3MsIGVuZCwgbWFyZ2luKSB7XG4gICAgaWYgKG1hcmdpbiA9PSBudWxsKSBtY
23459XJnaW4gPSAwO1xuICAgIGZvciAodmFyIGxpbWl0ID0gMDsgbGltaXQgPCA1OyBsaW1pdCsrKSB7XG4gICAgICB2YXIgY2hhbmdlZCA9IGZhbHNlLCBjb29yZHMgPSBjdXJzb3JDb29yZHMoY20sIHBvcyk7XG4gICAgICB2YXIgZW5kQ29vcmRzID0gIWVuZCB8fCBlbmQgPT0gcG9zID8gY29vcmRzIDogY3Vyc29yQ29vcmRzKGNtLCBlbmQpO1xuICAgICAgdmFyIHNjcm9sbFBvcyA9IGNhbGN1bGF0ZVNjcm9sbFBvcyhjbSwgTWF0aC5taW4oY29vcmRzLmxlZnQsIGVuZENvb3Jkcy5sZWZ0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5taW4oY29vcmRzLnRvcCwgZW5kQ29vcmRzLnRvcCkgLSBtYXJnaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGgubWF4KGNvb3Jkcy5sZWZ0LCBlbmRDb29yZHMubGVmdCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGgubWF4KGNvb3Jkcy5ib3R0b20sIGVuZENvb3Jkcy5ib3R0b20pICsgbWFyZ2luKTtcbiAgICAgIHZhciBzdGFydFRvcCA9IGNtLmRvYy5zY3JvbGxUb3AsIHN0YXJ0TGVmdCA9IGNtLmRvYy5zY3JvbGxMZWZ0O1xuICAgICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxUb3AgIT0gbnVsbCkge1xuICAgICAgICBzZXRTY3JvbGxUb3AoY20sIHNjcm9sbFBvcy5zY3JvbGxUb3ApO1xuICAgICAgICBpZiAoTWF0aC5hYnMoY20uZG9jLnNjcm9sbFRvcCAtIHN0YXJ0VG9wKSA+IDEpIGNoYW5nZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxMZWZ0ICE9IG51bGwpIHtcbiAgICAgICAgc2V0U2Nyb2xsTGVmdChjbSwgc2Nyb2xsUG9zLnNjcm9sbExlZnQpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoY20uZG9jLnNjcm9sbExlZnQgLSBzdGFydExlZnQpID4gMSkgY2hhbmdlZCA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAoIWNoYW5nZWQpIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gY29vcmRzO1xuICB9XG5cbiAgLy8gU2Nyb2xsIGEgZ2l2ZW4gc2V0IG9mIGNvb3JkaW5hdGVzIGludG8gdmlldyAoaW1tZWRpYXRlbHkpLlxuICBmdW5jdGlvbiBzY3JvbGxJbnRvVmlldyhjbSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgc2Nyb2xsUG9zID0gY2FsY3VsYXRlU2Nyb2xsUG9zKGNtLCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgaWYgKHNjcm9sbFBvcy5zY3JvbGxUb3AgIT0gbnVsbCkgc2V0U2Nyb2xsVG9wKGNtLCBzY3JvbGxQb3Muc2Nyb2xsVG9wKTtcbiAgICBpZiAoc2Nyb2xsUG9zLnNjcm9sbExlZnQgIT0gbnVsbCkgc2V0U2Nyb2xsTGVmdChjbSwgc2Nyb2xsUG9zLnNjcm9sbExlZnQpO1xuICB9XG5cbiAgLy8gQ2FsY3VsYXRlIGEgbmV3IHNjcm9sbCBwb3NpdGlvbiBuZWVkZWQgdG8gc2Nyb2xsIHRoZSBnaXZlblxuICAvLyByZWN0YW5nbGUgaW50byB2aWV3LiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIHNjcm9sbFRvcCBhbmRcbiAgLy8gc2Nyb2xsTGVmdCBwcm9wZXJ0aWVzLiBXaGVuIHRoZXNlIGFyZSB1bmRlZmluZWQsIHRoZVxuICAvLyB2ZXJ0aWNhbC9ob3Jpem9udGFsIHBvc2l0aW9uIGRvZXMgbm90IG5lZWQgdG8gYmUgYWRqdXN0ZWQuXG4gIGZ1bmN0aW9uIGNhbGN1bGF0ZVNjcm9sbFBvcyhjbSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgZGlzcGxheSA9IGNtLmRpc3BsYXksIHNuYXBNYXJnaW4gPSB0ZXh0SGVpZ2h0KGNtLmRpc3BsYXkpO1xuICAgIGlmICh5MSA8IDApIHkxID0gMDtcbiAgICB2YXIgc2NyZWVudG9wID0gY20uY3VyT3AgJiYgY20uY3VyT3Auc2Nyb2xsVG9wICE9IG51bGwgPyBjbS5jdXJPcC5zY3JvbGxUb3AgOiBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbFRvcDtcbiAgICB2YXIgc2NyZWVuID0gZGlzcGxheUhlaWdodChjbSksIHJlc3VsdCA9IHt9O1xuICAgIGlmICh5MiAtIHkxID4gc2NyZWVuKSB5MiA9IHkxICsgc2NyZWVuO1xuICAgIHZhciBkb2NCb3R0b20gPSBjbS5kb2MuaGVpZ2h0ICsgcGFkZGluZ1ZlcnQoZGlzcGxheSk7XG4gICAgdmFyIGF0VG9wID0geTEgPCBzbmFwTWFyZ2luLCBhdEJvdHRvbSA9IHkyID4gZG9jQm90dG9tIC0gc25hcE1hcmdpbjtcbiAgICBpZiAoeTEgPCBzY3JlZW50b3ApIHtcbiAgICAgIHJlc3VsdC5zY3JvbGxUb3AgPSBhdFRvcCA/IDAgOiB5MTtcbiAgICB9IGVsc2UgaWYgKHkyID4gc2NyZWVudG9wICsgc2NyZWVuKSB7XG4gICAgICB2Y
23459XIgbmV3VG9wID0gTWF0aC5taW4oeTEsIChhdEJvdHRvbSA/IGRvY0JvdHRvbSA6IHkyKSAtIHNjcmVlbik7XG4gICAgICBpZiAobmV3VG9wICE9IHNjcmVlbnRvcCkgcmVzdWx0LnNjcm9sbFRvcCA9IG5ld1RvcDtcbiAgICB9XG5cbiAgICB2YXIgc2NyZWVubGVmdCA9IGNtLmN1ck9wICYmIGNtLmN1ck9wLnNjcm9sbExlZnQgIT0gbnVsbCA/IGNtLmN1ck9wLnNjcm9sbExlZnQgOiBkaXNwbGF5LnNjcm9sbGVyLnNjcm9sbExlZnQ7XG4gICAgdmFyIHNjcmVlbncgPSBkaXNwbGF5V2lkdGgoY20pIC0gKGNtLm9wdGlvbnMuZml4ZWRHdXR0ZXIgPyBkaXNwbGF5Lmd1dHRlcnMub2Zmc2V0V2lkdGggOiAwKTtcbiAgICB2YXIgdG9vV2lkZSA9IHgyIC0geDEgPiBzY3JlZW53O1xuICAgIGlmICh0b29XaWRlKSB4MiA9IHgxICsgc2NyZWVudztcbiAgICBpZiAoeDEgPCAxMClcbiAgICAgIHJlc3VsdC5zY3JvbGxMZWZ0ID0gMDtcbiAgICBlbHNlIGlmICh4MSA8IHNjcmVlbmxlZnQpXG4gICAgICByZXN1bHQuc2Nyb2xsTGVmdCA9IE1hdGgubWF4KDAsIHgxIC0gKHRvb1dpZGUgPyAwIDogMTApKTtcbiAgICBlbHNlIGlmICh4MiA+IHNjcmVlbncgKyBzY3JlZW5sZWZ0IC0gMylcbiAgICAgIHJlc3VsdC5zY3JvbGxMZWZ0ID0geDIgKyAodG9vV2lkZSA/IDAgOiAxMCkgLSBzY3JlZW53O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBTdG9yZSBhIHJlbGF0aXZlIGFkanVzdG1lbnQgdG8gdGhlIHNjcm9sbCBwb3NpdGlvbiBpbiB0aGUgY3VycmVudFxuICAvLyBvcGVyYXRpb24gKHRvIGJlIGFwcGxpZWQgd2hlbiB0aGUgb3BlcmF0aW9uIGZpbmlzaGVzKS5cbiAgZnVuY3Rpb24gYWRkVG9TY3JvbGxQb3MoY20sIGxlZnQsIHRvcCkge1xuICAgIGlmIChsZWZ0ICE9IG51bGwgfHwgdG9wICE9IG51bGwpIHJlc29sdmVTY3JvbGxUb1BvcyhjbSk7XG4gICAgaWYgKGxlZnQgIT0gbnVsbClcbiAgICAgIGNtLmN1ck9wLnNjcm9sbExlZnQgPSAoY20uY3VyT3Auc2Nyb2xsTGVmdCA9PSBudWxsID8gY20uZG9jLnNjcm9sbExlZnQgOiBjbS5jdXJPcC5zY3JvbGxMZWZ0KSArIGxlZnQ7XG4gICAgaWYgKHRvcCAhPSBudWxsKVxuICAgICAgY20uY3VyT3Auc2Nyb2xsVG9wID0gKGNtLmN1ck9wLnNjcm9sbFRvcCA9PSBudWxsID8gY20uZG9jLnNjcm9sbFRvcCA6IGNtLmN1ck9wLnNjcm9sbFRvcCkgKyB0b3A7XG4gIH1cblxuICAvLyBNYWtlIHN1cmUgdGhhdCBhdCB0aGUgZW5kIG9mIHRoZSBvcGVyYXRpb24gdGhlIGN1cnJlbnQgY3Vyc29yIGlzXG4gIC8vIHNob3duLlxuICBmdW5jdGlvbiBlbnN1cmVDdXJzb3JWaXNpYmxlKGNtKSB7XG4gICAgcmVzb2x2ZVNjcm9sbFRvUG9zKGNtKTtcbiAgICB2YXIgY3VyID0gY20uZ2V0Q3Vyc29yKCksIGZyb20gPSBjdXIsIHRvID0gY3VyO1xuICAgIGlmICghY20ub3B0aW9ucy5saW5lV3JhcHBpbmcpIHtcbiAgICAgIGZyb20gPSBjdXIuY2ggPyBQb3MoY3VyLmxpbmUsIGN1ci5jaCAtIDEpIDogY3VyO1xuICAgICAgdG8gPSBQb3MoY3VyLmxpbmUsIGN1ci5jaCArIDEpO1xuICAgIH1cbiAgICBjbS5jdXJPcC5zY3JvbGxUb1BvcyA9IHtmcm9tOiBmcm9tLCB0bzogdG8sIG1hcmdpbjogY20ub3B0aW9ucy5jdXJzb3JTY3JvbGxNYXJnaW4sIGlzQ3Vyc29yOiB0cnVlfTtcbiAgfVxuXG4gIC8vIFdoZW4gYW4gb3BlcmF0aW9uIGhhcyBpdHMgc2Nyb2xsVG9Qb3MgcHJvcGVydHkgc2V0LCBhbmQgYW5vdGhlclxuICAvLyBzY3JvbGwgYWN0aW9uIGlzIGFwcGxpZWQgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIG9wZXJhdGlvbiwgdGhpc1xuICAvLyAnc2ltdWxhdGVzJyBzY3JvbGxpbmcgdGhhdCBwb3NpdGlvbiBpbnRvIHZpZXcgaW4gYSBjaGVhcCB3YXksIHNvXG4gIC8vIHRoYXQgdGhlIGVmZmVjdCBvZiBpbnRlcm1lZGlhdGUgc2Nyb2xsIGNvbW1hbmRzIGlzIG5vdCBpZ25vcmVkLlxuICBmdW5jdGlvbiByZXNvbHZlU2Nyb2xsVG9Qb3MoY20pIHtcbiAgICB2YXIgcmFuZ2UgPSBjbS5jdXJPcC5zY3JvbGxUb1BvcztcbiAgICBpZiAocmFuZ2UpIHtcbiAgICAgIGNtLmN1ck9wLnNjcm9sbFRvUG9zID0gbnVsbDtcbiAgICAgIHZhciBmcm9tID0gZXN0aW1hdGVDb29yZHMoY20sIHJhbmdlLmZyb20pLCB0byA9IGVzdGltYXRlQ29vcmRzKGNtLCByYW5nZS50byk7XG4gICAgICB2Y
23459XIgc1BvcyA9IGNhbGN1bGF0ZVNjcm9sbFBvcyhjbSwgTWF0aC5taW4oZnJvbS5sZWZ0LCB0by5sZWZ0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGgubWluKGZyb20udG9wLCB0by50b3ApIC0gcmFuZ2UubWFyZ2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5tYXgoZnJvbS5yaWdodCwgdG8ucmlnaHQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5tYXgoZnJvbS5ib3R0b20sIHRvLmJvdHRvbSkgKyByYW5nZS5tYXJnaW4pO1xuICAgICAgY20uc2Nyb2xsVG8oc1Bvcy5zY3JvbGxMZWZ0LCBzUG9zLnNjcm9sbFRvcCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQVBJIFVUSUxJVElFU1xuXG4gIC8vIEluZGVudCB0aGUgZ2l2ZW4gbGluZS4gVGhlIGhvdyBwYXJhbWV0ZXIgY2FuIGJlIFwic21hcnRcIixcbiAgLy8gXCJhZGRcIi9udWxsLCBcInN1YnRyYWN0XCIsIG9yIFwicHJldlwiLiBXaGVuIGFnZ3Jlc3NpdmUgaXMgZmFsc2VcbiAgLy8gKHR5cGljYWxseSBzZXQgdG8gdHJ1ZSBmb3IgZm9yY2VkIHNpbmdsZS1saW5lIGluZGVudHMpLCBlbXB0eVxuICAvLyBsaW5lcyBhcmUgbm90IGluZGVudGVkLCBhbmQgcGxhY2VzIHdoZXJlIHRoZSBtb2RlIHJldHVybnMgUGFzc1xuICAvLyBhcmUgbGVmdCBhbG9uZS5cbiAgZnVuY3Rpb24gaW5kZW50TGluZShjbSwgbiwgaG93LCBhZ2dyZXNzaXZlKSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgc3RhdGU7XG4gICAgaWYgKGhvdyA9PSBudWxsKSBob3cgPSBcImFkZFwiO1xuICAgIGlmIChob3cgPT0gXCJzbWFydFwiKSB7XG4gICAgICAvLyBGYWxsIGJhY2sgdG8gXCJwcmV2XCIgd2hlbiB0aGUgbW9kZSBkb2Vzbid0IGhhdmUgYW4gaW5kZW50YXRpb25cbiAgICAgIC8vIG1ldGhvZC5cbiAgICAgIGlmICghZG9jLm1vZGUuaW5kZW50KSBob3cgPSBcInByZXZcIjtcbiAgICAgIGVsc2Ugc3RhdGUgPSBnZXRTdGF0ZUJlZm9yZShjbSwgbik7XG4gICAgfVxuXG4gICAgdmFyIHRhYlNpemUgPSBjbS5vcHRpb25zLnRhYlNpemU7XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgbiksIGN1clNwYWNlID0gY291bnRDb2x1bW4obGluZS50ZXh0LCBudWxsLCB0YWJTaXplKTtcbiAgICBpZiAobGluZS5zdGF0ZUFmdGVyKSBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsO1xuICAgIHZhciBjdXJTcGFjZVN0cmluZyA9IGxpbmUudGV4dC5tYXRjaCgvXlxccyovKVswXSwgaW5kZW50YXRpb247XG4gICAgaWYgKCFhZ2dyZXNzaXZlICYmICEvXFxTLy50ZXN0KGxpbmUudGV4dCkpIHtcbiAgICAgIGluZGVudGF0aW9uID0gMDtcbiAgICAgIGhvdyA9IFwibm90XCI7XG4gICAgfSBlbHNlIGlmIChob3cgPT0gXCJzbWFydFwiKSB7XG4gICAgICBpbmRlbnRhdGlvbiA9IGRvYy5tb2RlLmluZGVudChzdGF0ZSwgbGluZS50ZXh0LnNsaWNlKGN1clNwYWNlU3RyaW5nLmxlbmd0aCksIGxpbmUudGV4dCk7XG4gICAgICBpZiAoaW5kZW50YXRpb24gPT0gUGFzcyB8fCBpbmRlbnRhdGlvbiA+IDE1MCkge1xuICAgICAgICBpZiAoIWFnZ3Jlc3NpdmUpIHJldHVybjtcbiAgICAgICAgaG93ID0gXCJwcmV2XCI7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChob3cgPT0gXCJwcmV2XCIpIHtcbiAgICAgIGlmIChuID4gZG9jLmZpcnN0KSBpbmRlbnRhdGlvbiA9IGNvdW50Q29sdW1uKGdldExpbmUoZG9jLCBuLTEpLnRleHQsIG51bGwsIHRhYlNpemUpO1xuICAgICAgZWxzZSBpbmRlbnRhdGlvbiA9IDA7XG4gICAgfSBlbHNlIGlmIChob3cgPT0gXCJhZGRcIikge1xuICAgICAgaW5kZW50YXRpb24gPSBjdXJTcGFjZSArIGNtLm9wdGlvbnMuaW5kZW50VW5pdDtcbiAgICB9IGVsc2UgaWYgKGhvdyA9PSBcInN1YnRyYWN0XCIpIHtcbiAgICAgIGluZGVudGF0aW9uID0gY3VyU3BhY2UgLSBjbS5vcHRpb25zLmluZGVudFVuaXQ7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgaG93ID09IFwibnVtYmVyXCIpIHtcbiAgICAgIGluZGVudGF0aW9uID0gY3VyU3BhY2UgKyBob3c7XG4gICAgfVxuICAgIGluZGVudGF0aW9uID0gTWF0aC5tYXgoMCwgaW5kZW50YXRpb24pO1xuXG4gICAgdmFyIGluZGVudFN0cmluZyA9IFwiXCIsIHBvcyA9IDA7XG4gICAgaWYgKGNtLm9wdGlvbnMuaW5kZW50V2l0aFRhYnMpXG4gICAgICBmb3IgKHZhciBpID0gTWF0aC5mbG9vcihpbmRlbnRhdGlvbiAvIHRhYlNpemUpOyBpOyAtLWkpIHtwb3MgKz0gdGFiU2l6ZTsgaW5kZW50U3RyaW5nICs9IFwiXFx0XCI7fVxuICAgIGlmIChwb3MgPCBpbmRlbnRhdGlvbikgaW5kZW50U3RyaW5nICs9IHNwYWNlU3RyKGluZGVudGF0aW9uIC0gcG9zKTtcblxuICAgIGlmIChpbmRlbnRTdHJpbmcgIT0gY3VyU3BhY2VTdHJpbmcpIHtcbiAgICAgIHJlcGxhY2VSYW5nZShkb2MsIGluZGVudFN0cmluZywgUG9zKG4sIDApLCBQb3MobiwgY3VyU3BhY2VTdHJpbmcubGVuZ3RoKSwgXCIraW5wdXRcIik7XG4gICAgICBsaW5lLnN0YXRlQWZ0ZXIgPSBudWxsO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEVuc3VyZSB0aGF0LCBpZiB0aGUgY3Vyc29yIHdhcyBpbiB0aGUgd2hpdGVzcGFjZSBhdCB0aGUgc3RhcnRcbiAgICAgIC8vIG9mIHRoZSBsaW5lLCBpdCBpcyBtb3ZlZCB0byB0aGUgZW5kIG9mIHRoYXQgc3BhY2UuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRvYy5zZWwucmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByYW5nZSA9IGRvYy5zZWwucmFuZ2VzW2ldO1xuICAgICAgICBpZiAocmFuZ2UuaGVhZC5saW5lID09IG4gJiYgcmFuZ2UuaGVhZC5jaCA8IGN1clNwYWNlU3RyaW5nLmxlbmd0aCkge1xuICAgICAgICAgIHZhciBwb3MgPSBQb3MobiwgY3VyU3BhY2VTdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgICByZXBsYWNlT25lU2VsZWN0aW9uKGRvYywgaSwgbmV3IFJhbmdlKHBvcywgcG9zKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBVdGlsaXR5IGZvciBhcHBseWluZyBhIGNoYW5nZSB0byBhIGxpbmUgYnkgaGFuZGxlIG9yIG51bWJlcixcbiAgLy8gcmV0dXJuaW5nIHRoZSBudW1iZXIgYW5kIG9wdGlvbmFsbHkgcmVnaXN0ZXJpbmcgdGhlIGxpbmUgYXNcbiAgLy8gY2hhbmdlZC5cbiAgZnVuY3Rpb24gY2hhbmdlTGluZShkb2MsIGhhbmRsZSwgY2hhbmdlVHlwZSwgb3ApIHtcbiAgICB2YXIgbm8gPSBoYW5kbGUsIGxpbmUgPSBoYW5kbGU7XG4gICAgaWYgKHR5cGVvZiBoYW5kbGUgPT0gXCJudW1iZXJcIikgbGluZSA9IGdldExpbmUoZG9jLCBjbGlwTGluZShkb2MsIGhhbmRsZSkpO1xuICAgIGVsc2Ugbm8gPSBsaW5lTm8oaGFuZGxlKTtcbiAgICBpZiAobm8gPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKG9wKGxpbmUsIG5vKSAmJiBkb2MuY20pIHJlZ0xpbmVDaGFuZ2UoZG9jLmNtLCBubywgY2hhbmdlVHlwZSk7XG4gICAgcmV0dXJuIGxpbmU7XG4gIH1cblxuICAvLyBIZWxwZXIgZm9yIGRlbGV0aW5nIHRleHQgbmVhciB0aGUgc2VsZWN0aW9uKHMpLCB1c2VkIHRvIGltcGxlbWVudFxuICAvLyBiYWNrc3BhY2UsIGRlbGV0ZSwgYW5kIHNpbWlsYXIgZnVuY3Rpb25hbGl0eS5cbiAgZnVuY3Rpb24gZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgY29tcHV0ZSkge1xuICAgIHZhciByYW5nZXMgPSBjbS5kb2Muc2VsLnJhbmdlcywga2lsbCA9I
23459FtdO1xuICAgIC8vIEJ1aWxkIHVwIGEgc2V0IG9mIHJhbmdlcyB0byBraWxsIGZpcnN0LCBtZXJnaW5nIG92ZXJsYXBwaW5nXG4gICAgLy8gcmFuZ2VzLlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdG9LaWxsID0gY29tcHV0ZShyYW5nZXNbaV0pO1xuICAgICAgd2hpbGUgKGtpbGwubGVuZ3RoICYmIGNtcCh0b0tpbGwuZnJvbSwgbHN0KGtpbGwpLnRvKSA8PSAwKSB7XG4gICAgICAgIHZhciByZXBsYWNlZCA9IGtpbGwucG9wKCk7XG4gICAgICAgIGlmIChjbXAocmVwbGFjZWQuZnJvbSwgdG9LaWxsLmZyb20pIDwgMCkge1xuICAgICAgICAgIHRvS2lsbC5mcm9tID0gcmVwbGFjZWQuZnJvbTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAga2lsbC5wdXNoKHRvS2lsbCk7XG4gICAgfVxuICAgIC8vIE5leHQsIHJlbW92ZSB0aG9zZSBhY3R1YWwgcmFuZ2VzLlxuICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgZm9yICh2YXIgaSA9IGtpbGwubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pXG4gICAgICAgIHJlcGxhY2VSYW5nZShjbS5kb2MsIFwiXCIsIGtpbGxbaV0uZnJvbSwga2lsbFtpXS50bywgXCIrZGVsZXRlXCIpO1xuICAgICAgZW5zdXJlQ3Vyc29yVmlzaWJsZShjbSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBVc2VkIGZvciBob3Jpem9udGFsIHJlbGF0aXZlIG1vdGlvbi4gRGlyIGlzIC0xIG9yIDEgKGxlZnQgb3JcbiAgLy8gcmlnaHQpLCB1bml0IGNhbiBiZSBcImNoYXJcIiwgXCJjb2x1bW5cIiAobGlrZSBjaGFyLCBidXQgZG9lc24ndFxuICAvLyBjcm9zcyBsaW5lIGJvdW5kYXJpZXMpLCBcIndvcmRcIiAoYWNyb3NzIG5leHQgd29yZCksIG9yIFwiZ3JvdXBcIiAodG9cbiAgLy8gdGhlIHN0YXJ0IG9mIG5leHQgZ3JvdXAgb2Ygd29yZCBvciBub24td29yZC1ub24td2hpdGVzcGFjZVxuICAvLyBjaGFycykuIFRoZSB2aXN1YWxseSBwYXJhbSBjb250cm9scyB3aGV0aGVyLCBpbiByaWdodC10by1sZWZ0XG4gIC8vIHRleHQsIGRpcmVjdGlvbiAxIG1lYW5zIHRvIG1vdmUgdG93YXJkcyB0aGUgbmV4dCBpbmRleCBpbiB0aGVcbiAgLy8gc3RyaW5nLCBvciB0b3dhcmRzIHRoZSBjaGFyYWN0ZXIgdG8gdGhlIHJpZ2h0IG9mIHRoZSBjdXJyZW50XG4gIC8vIHBvc2l0aW9uLiBUaGUgcmVzdWx0aW5nIHBvc2l0aW9uIHdpbGwgaGF2ZSBhIGhpdFNpZGU9dHJ1ZVxuICAvLyBwcm9wZXJ0eSBpZiBpdCByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIGRvY3VtZW50LlxuICBmdW5jdGlvbiBmaW5kUG9zSChkb2MsIHBvcywgZGlyLCB1bml0LCB2aXN1YWxseSkge1xuICAgIHZhciBsaW5lID0gcG9zLmxpbmUsIGNoID0gcG9zLmNoLCBvcmlnRGlyID0gZGlyO1xuICAgIHZhciBsaW5lT2JqID0gZ2V0TGluZShkb2MsIGxpbmUpO1xuICAgIHZhciBwb3NzaWJsZSA9IHRydWU7XG4gICAgZnVuY3Rpb24gZmluZE5leHRMaW5lKCkge1xuICAgICAgdmFyIGwgPSBsaW5lICsgZGlyO1xuICAgICAgaWYgKGwgPCBkb2MuZmlyc3QgfHwgbCA+PSBkb2MuZmlyc3QgKyBkb2Muc2l6ZSkgcmV0dXJuIChwb3NzaWJsZSA9IGZhbHNlKTtcbiAgICAgIGxpbmUgPSBsO1xuICAgICAgcmV0dXJuIGxpbmVPYmogPSBnZXRMaW5lKGRvYywgbCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIG1vdmVPbmNlKGJvdW5kVG9MaW5lKSB7XG4gICAgICB2Y
23459XIgbmV4dCA9ICh2aXN1YWxseSA/IG1vdmVWaXN1YWxseSA6IG1vdmVMb2dpY2FsbHkpKGxpbmVPYmosIGNoLCBkaXIsIHRydWUpO1xuICAgICAgaWYgKG5leHQgPT0gbnVsbCkge1xuICAgICAgICBpZiAoIWJvdW5kVG9MaW5lICYmIGZpbmROZXh0TGluZSgpKSB7XG4gICAgICAgICAgaWYgKHZpc3VhbGx5KSBjaCA9IChkaXIgPCAwID8gbGluZVJpZ2h0IDogbGluZUxlZnQpKGxpbmVPYmopO1xuICAgICAgICAgIGVsc2UgY2ggPSBkaXIgPCAwID8gbGluZU9iai50ZXh0Lmxlbmd0aCA6IDA7XG4gICAgICAgIH0gZWxzZSByZXR1cm4gKHBvc3NpYmxlID0gZmFsc2UpO1xuICAgICAgfSBlbHNlIGNoID0gbmV4dDtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmICh1bml0ID09IFwiY2hhclwiKSBtb3ZlT25jZSgpO1xuICAgIGVsc2UgaWYgKHVuaXQgPT0gXCJjb2x1bW5cIikgbW92ZU9uY2UodHJ1ZSk7XG4gICAgZWxzZSBpZiAodW5pdCA9PSBcIndvcmRcIiB8fCB1bml0ID09IFwiZ3JvdXBcIikge1xuICAgICAgdmFyIHNhd1R5cGUgPSBudWxsLCBncm91cCA9IHVuaXQgPT0gXCJncm91cFwiO1xuICAgICAgdmFyIGhlbHBlciA9IGRvYy5jbSAmJiBkb2MuY20uZ2V0SGVscGVyKHBvcywgXCJ3b3JkQ2hhcnNcIik7XG4gICAgICBmb3IgKHZhciBmaXJzdCA9IHRydWU7OyBmaXJzdCA9IGZhbHNlKSB7XG4gICAgICAgIGlmIChkaXIgPCAwICYmICFtb3ZlT25jZSghZmlyc3QpKSBicmVhaztcbiAgICAgICAgdmFyIGN1ciA9IGxpbmVPYmoudGV4dC5jaGFyQXQoY2gpIHx8IFwiXFxuXCI7XG4gICAgICAgIHZhciB0eXBlID0gaXNXb3JkQ2hhcihjdXIsIGhlbHBlcikgPyBcIndcIlxuICAgICAgICAgIDogZ3JvdXAgJiYgY3VyID09IFwiXFxuXCIgPyBcIm5cIlxuICAgICAgICAgIDogIWdyb3VwIHx8IC9cXHMvLnRlc3QoY3VyKSA/IG51bGxcbiAgICAgICAgICA6IFwicFwiO1xuICAgICAgICBpZiAoZ3JvdXAgJiYgIWZpcnN0ICYmICF0eXBlKSB0eXBlID0gXCJzXCI7XG4gICAgICAgIGlmIChzYXdUeXBlICYmIHNhd1R5cGUgIT0gdHlwZSkge1xuICAgICAgICAgIGlmIChkaXIgPCAwKSB7ZGlyID0gMTsgbW92ZU9uY2UoKTt9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSkgc2F3VHlwZSA9IHR5cGU7XG4gICAgICAgIGlmIChkaXIgPiAwICYmICFtb3ZlT25jZSghZmlyc3QpKSBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IHNraXBBdG9taWMoZG9jLCBQb3MobGluZSwgY2gpLCBvcmlnRGlyLCB0cnVlKTtcbiAgICBpZiAoIXBvc3NpYmxlKSByZXN1bHQuaGl0U2lkZSA9IHRydWU7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIEZvciByZWxhdGl2ZSB2ZXJ0aWNhbCBtb3ZlbWVudC4gRGlyIG1heSBiZSAtMSBvciAxLiBVbml0IGNhbiBiZVxuICAvLyBcInBhZ2VcIiBvciBcImxpbmVcIi4gVGhlIHJlc3VsdGluZyBwb3NpdGlvbiB3aWxsIGhhdmUgYSBoaXRTaWRlPXRydWVcbiAgLy8gcHJvcGVydHkgaWYgaXQgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBkb2N1bWVudC5cbiAgZnVuY3Rpb24gZmluZFBvc1YoY20sIHBvcywgZGlyLCB1bml0KSB7XG4gICAgdmFyIGRvYyA9IGNtLmRvYywgeCA9IHBvcy5sZWZ0LCB5O1xuICAgIGlmICh1bml0ID09IFwicGFnZVwiKSB7XG4gICAgICB2Y
23459XIgcGFnZVNpemUgPSBNYXRoLm1pbihjbS5kaXNwbGF5LndyYXBwZXIuY2xpZW50SGVpZ2h0LCB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCk7XG4gICAgICB5ID0gcG9zLnRvcCArIGRpciAqIChwYWdlU2l6ZSAtIChkaXIgPCAwID8gMS41IDogLjUpICogdGV4dEhlaWdodChjbS5kaXNwbGF5KSk7XG4gICAgfSBlbHNlIGlmICh1bml0ID09IFwibGluZVwiKSB7XG4gICAgICB5ID0gZGlyID4gMCA/IHBvcy5ib3R0b20gKyAzIDogcG9zLnRvcCAtIDM7XG4gICAgfVxuICAgIGZvciAoOzspIHtcbiAgICAgIHZhciB0YXJnZXQgPSBjb29yZHNDaGFyKGNtLCB4LCB5KTtcbiAgICAgIGlmICghdGFyZ2V0Lm91dHNpZGUpIGJyZWFrO1xuICAgICAgaWYgKGRpciA8IDAgPyB5IDw9IDAgOiB5ID49IGRvYy5oZWlnaHQpIHsgdGFyZ2V0LmhpdFNpZGUgPSB0cnVlOyBicmVhazsgfVxuICAgICAgeSArPSBkaXIgKiA1O1xuICAgIH1cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9XG5cbiAgLy8gRURJVE9SIE1FVEhPRFNcblxuICAvLyBUaGUgcHVibGljbHkgdmlzaWJsZSBBUEkuIE5vdGUgdGhhdCBtZXRob2RPcChmKSBtZWFuc1xuICAvLyAnd3JhcCBmIGluIGFuIG9wZXJhdGlvbiwgcGVyZm9ybWVkIG9uIGl0cyBgdGhpc2AgcGFyYW1ldGVyJy5cblxuICAvLyBUaGlzIGlzIG5vdCB0aGUgY29tcGxldGUgc2V0IG9mIGVkaXRvciBtZXRob2RzLiBNb3N0IG9mIHRoZVxuICAvLyBtZXRob2RzIGRlZmluZWQgb24gdGhlIERvYyB0eXBlIGFyZSBhbHNvIGluamVjdGVkIGludG9cbiAgLy8gQ29kZU1pcnJvci5wcm90b3R5cGUsIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBhbmRcbiAgLy8gY29udmVuaWVuY2UuXG5cbiAgQ29kZU1pcnJvci5wcm90b3R5cGUgPSB7XG4gICAgY29uc3RydWN0b3I6IENvZGVNaXJyb3IsXG4gICAgZm9jdXM6IGZ1bmN0aW9uKCl7d2luZG93LmZvY3VzKCk7IHRoaXMuZGlzcGxheS5pbnB1dC5mb2N1cygpO30sXG5cbiAgICBzZXRPcHRpb246IGZ1bmN0aW9uKG9wdGlvbiwgdmFsdWUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLCBvbGQgPSBvcHRpb25zW29wdGlvbl07XG4gICAgICBpZiAob3B0aW9uc1tvcHRpb25dID09IHZhbHVlICYmIG9wdGlvbiAhPSBcIm1vZGVcIikgcmV0dXJuO1xuICAgICAgb3B0aW9uc1tvcHRpb25dID0gdmFsdWU7XG4gICAgICBpZiAob3B0aW9uSGFuZGxlcnMuaGFzT3duUHJvcGVydHkob3B0aW9uKSlcbiAgICAgICAgb3BlcmF0aW9uKHRoaXMsIG9wdGlvbkhhbmRsZXJzW29wdGlvbl0pKHRoaXMsIHZhbHVlLCBvbGQpO1xuICAgIH0sXG5cbiAgICBnZXRPcHRpb246IGZ1bmN0aW9uKG9wdGlvbikge3JldHVybiB0aGlzLm9wdGlvbnNbb3B0aW9uXTt9LFxuICAgIGdldERvYzogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuZG9jO30sXG5cbiAgICBhZGRLZXlNYXA6IGZ1bmN0aW9uKG1hcCwgYm90dG9tKSB7XG4gICAgICB0aGlzLnN0YXRlLmtleU1hcHNbYm90dG9tID8gXCJwdXNoXCIgOiBcInVuc2hpZnRcIl0oZ2V0S2V5TWFwKG1hcCkpO1xuICAgIH0sXG4gICAgcmVtb3ZlS2V5TWFwOiBmdW5jdGlvbihtYXApIHtcbiAgICAgIHZhciBtYXBzID0gdGhpcy5zdGF0ZS5rZXlNYXBzO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXBzLmxlbmd0aDsgKytpKVxuICAgICAgICBpZiAobWFwc1tpXSA9PSBtYXAgfHwgbWFwc1tpXS5uYW1lID09IG1hcCkge1xuICAgICAgICAgIG1hcHMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIGFkZE92ZXJsYXk6IG1ldGhvZE9wKGZ1bmN0aW9uKHNwZWMsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBtb2RlID0gc3BlYy50b2tlbiA/IHNwZWMgOiBDb2RlTWlycm9yLmdldE1vZGUodGhpcy5vcHRpb25zLCBzcGVjKTtcbiAgICAgIGlmIChtb2RlLnN0YXJ0U3RhdGUpIHRocm93IG5ldyBFcnJvcihcIk92ZXJsYXlzIG1heSBub3QgYmUgc3RhdGVmdWwuXCIpO1xuICAgICAgdGhpcy5zdGF0ZS5vdmVybGF5cy5wdXNoKHttb2RlOiBtb2RlLCBtb2RlU3BlYzogc3BlYywgb3BhcXVlOiBvcHRpb25zICYmIG9wdGlvbnMub3BhcXVlfSk7XG4gICAgICB0aGlzLnN0YXRlLm1vZGVHZW4rKztcbiAgICAgIHJlZ0NoYW5nZSh0aGlzKTtcbiAgICB9KSxcbiAgICByZW1vdmVPdmVybGF5OiBtZXRob2RPcChmdW5jdGlvbihzcGVjKSB7XG4gICAgICB2Y
23459XIgb3ZlcmxheXMgPSB0aGlzLnN0YXRlLm92ZXJsYXlzO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvdmVybGF5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY3VyID0gb3ZlcmxheXNbaV0ubW9kZVNwZWM7XG4gICAgICAgIGlmIChjdXIgPT0gc3BlYyB8fCB0eXBlb2Ygc3BlYyA9PSBcInN0cmluZ1wiICYmIGN1ci5uYW1lID09IHNwZWMpIHtcbiAgICAgICAgICBvdmVybGF5cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgdGhpcy5zdGF0ZS5tb2RlR2VuKys7XG4gICAgICAgICAgcmVnQ2hhbmdlKHRoaXMpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pLFxuXG4gICAgaW5kZW50TGluZTogbWV0aG9kT3AoZnVuY3Rpb24obiwgZGlyLCBhZ2dyZXNzaXZlKSB7XG4gICAgICBpZiAodHlwZW9mIGRpciAhPSBcInN0cmluZ1wiICYmIHR5cGVvZiBkaXIgIT0gXCJudW1iZXJcIikge1xuICAgICAgICBpZiAoZGlyID09IG51bGwpIGRpciA9IHRoaXMub3B0aW9ucy5zbWFydEluZGVudCA/IFwic21hcnRcIiA6IFwicHJldlwiO1xuICAgICAgICBlbHNlIGRpciA9IGRpciA/IFwiYWRkXCIgOiBcInN1YnRyYWN0XCI7XG4gICAgICB9XG4gICAgICBpZiAoaXNMaW5lKHRoaXMuZG9jLCBuKSkgaW5kZW50TGluZSh0aGlzLCBuLCBkaXIsIGFnZ3Jlc3NpdmUpO1xuICAgIH0pLFxuICAgIGluZGVudFNlbGVjdGlvbjogbWV0aG9kT3AoZnVuY3Rpb24oaG93KSB7XG4gICAgICB2YXIgcmFuZ2VzID0gdGhpcy5kb2Muc2VsLnJhbmdlcywgZW5kID0gLTE7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2Y
23459XIgcmFuZ2UgPSByYW5nZXNbaV07XG4gICAgICAgIGlmICghcmFuZ2UuZW1wdHkoKSkge1xuICAgICAgICAgIHZhciBmcm9tID0gcmFuZ2UuZnJvbSgpLCB0byA9IHJhbmdlLnRvKCk7XG4gICAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5tYXgoZW5kLCBmcm9tLmxpbmUpO1xuICAgICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGFzdExpbmUoKSwgdG8ubGluZSAtICh0by5jaCA/IDAgOiAxKSkgKyAxO1xuICAgICAgICAgIGZvciAodmFyIGogPSBzdGFydDsgaiA8IGVuZDsgKytqKVxuICAgICAgICAgICAgaW5kZW50TGluZSh0aGlzLCBqLCBob3cpO1xuICAgICAgICAgIHZhciBuZXdSYW5nZXMgPSB0aGlzLmRvYy5zZWwucmFuZ2VzO1xuICAgICAgICAgIGlmIChmcm9tLmNoID09IDAgJiYgcmFuZ2VzLmxlbmd0aCA9PSBuZXdSYW5nZXMubGVuZ3RoICYmIG5ld1Jhbmdlc1tpXS5mcm9tKCkuY2ggPiAwKVxuICAgICAgICAgICAgcmVwbGFjZU9uZVNlbGVjdGlvbih0aGlzLmRvYywgaSwgbmV3IFJhbmdlKGZyb20sIG5ld1Jhbmdlc1tpXS50bygpKSwgc2VsX2RvbnRTY3JvbGwpO1xuICAgICAgICB9IGVsc2UgaWYgKHJhbmdlLmhlYWQubGluZSA+IGVuZCkge1xuICAgICAgICAgIGluZGVudExpbmUodGhpcywgcmFuZ2UuaGVhZC5saW5lLCBob3csIHRydWUpO1xuICAgICAgICAgIGVuZCA9IHJhbmdlLmhlYWQubGluZTtcbiAgICAgICAgICBpZiAoaSA9PSB0aGlzLmRvYy5zZWwucHJpbUluZGV4KSBlbnN1cmVDdXJzb3JWaXNpYmxlKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSksXG5cbiAgICAvLyBGZXRjaCB0aGUgcGFyc2VyIHRva2VuIGZvciBhIGdpdmVuIGNoYXJhY3Rlci4gVXNlZnVsIGZvciBoYWNrc1xuICAgIC8vIHRoYXQgd2FudCB0byBpbnNwZWN0IHRoZSBtb2RlIHN0YXRlIChzYXksIGZvciBjb21wbGV0aW9uKS5cbiAgICBnZXRUb2tlbkF0OiBmdW5jdGlvbihwb3MsIHByZWNpc2UpIHtcbiAgICAgIHJldHVybiB0YWtlVG9rZW4odGhpcywgcG9zLCBwcmVjaXNlKTtcbiAgICB9LFxuXG4gICAgZ2V0TGluZVRva2VuczogZnVuY3Rpb24obGluZSwgcHJlY2lzZSkge1xuICAgICAgcmV0dXJuIHRha2VUb2tlbih0aGlzLCBQb3MobGluZSksIHByZWNpc2UsIHRydWUpO1xuICAgIH0sXG5cbiAgICBnZXRUb2tlblR5cGVBdDogZnVuY3Rpb24ocG9zKSB7XG4gICAgICBwb3MgPSBjbGlwUG9zKHRoaXMuZG9jLCBwb3MpO1xuICAgICAgdmFyIHN0eWxlcyA9IGdldExpbmVTdHlsZXModGhpcywgZ2V0TGluZSh0aGlzLmRvYywgcG9zLmxpbmUpKTtcbiAgICAgIHZhciBiZWZvcmUgPSAwLCBhZnRlciA9IChzdHlsZXMubGVuZ3RoIC0gMSkgLyAyLCBjaCA9IHBvcy5jaDtcbiAgICAgIHZhciB0eXBlO1xuICAgICAgaWYgKGNoID09IDApIHR5cGUgPSBzdHlsZXNbMl07XG4gICAgICBlbHNlIGZvciAoOzspIHtcbiAgICAgICAgdmFyIG1pZCA9IChiZWZvcmUgKyBhZnRlcikgPj4gMTtcbiAgICAgICAgaWYgKChtaWQgPyBzdHlsZXNbbWlkICogMiAtIDFdIDogMCkgPj0gY2gpIGFmdGVyID0gbWlkO1xuICAgICAgICBlbHNlIGlmIChzdHlsZXNbbWlkICogMiArIDFdIDwgY2gpIGJlZm9yZSA9IG1pZCArIDE7XG4gICAgICAgIGVsc2UgeyB0eXBlID0gc3R5bGVzW21pZCAqIDIgKyAyXTsgYnJlYWs7IH1cbiAgICAgIH1cbiAgICAgIHZhciBjdXQgPSB0eXBlID8gdHlwZS5pbmRleE9mKFwiY20tb3ZlcmxheSBcIikgOiAtMTtcbiAgICAgIHJldHVybiBjdXQgPCAwID8gdHlwZSA6IGN1dCA9PSAwID8gbnVsbCA6IHR5cGUuc2xpY2UoMCwgY3V0IC0gMSk7XG4gICAgfSxcblxuICAgIGdldE1vZGVBdDogZnVuY3Rpb24ocG9zKSB7XG4gICAgICB2Y
23459XIgbW9kZSA9IHRoaXMuZG9jLm1vZGU7XG4gICAgICBpZiAoIW1vZGUuaW5uZXJNb2RlKSByZXR1cm4gbW9kZTtcbiAgICAgIHJldHVybiBDb2RlTWlycm9yLmlubmVyTW9kZShtb2RlLCB0aGlzLmdldFRva2VuQXQocG9zKS5zdGF0ZSkubW9kZTtcbiAgICB9LFxuXG4gICAgZ2V0SGVscGVyOiBmdW5jdGlvbihwb3MsIHR5cGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEhlbHBlcnMocG9zLCB0eXBlKVswXTtcbiAgICB9LFxuXG4gICAgZ2V0SGVscGVyczogZnVuY3Rpb24ocG9zLCB0eXBlKSB7XG4gICAgICB2YXIgZm91bmQgPSBbXTtcbiAgICAgIGlmICghaGVscGVycy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgcmV0dXJuIGZvdW5kO1xuICAgICAgdmFyIGhlbHAgPSBoZWxwZXJzW3R5cGVdLCBtb2RlID0gdGhpcy5nZXRNb2RlQXQocG9zKTtcbiAgICAgIGlmICh0eXBlb2YgbW9kZVt0eXBlXSA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGlmIChoZWxwW21vZGVbdHlwZV1dKSBmb3VuZC5wdXNoKGhlbHBbbW9kZVt0eXBlXV0pO1xuICAgICAgfSBlbHNlIGlmIChtb2RlW3R5cGVdKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kZVt0eXBlXS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciB2YWwgPSBoZWxwW21vZGVbdHlwZV1baV1dO1xuICAgICAgICAgIGlmICh2YWwpIGZvdW5kLnB1c2godmFsKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChtb2RlLmhlbHBlclR5cGUgJiYgaGVscFttb2RlLmhlbHBlclR5cGVdKSB7XG4gICAgICAgIGZvdW5kLnB1c2goaGVscFttb2RlLmhlbHBlclR5cGVdKTtcbiAgICAgIH0gZWxzZSBpZiAoaGVscFttb2RlLm5hbWVdKSB7XG4gICAgICAgIGZvdW5kLnB1c2goaGVscFttb2RlLm5hbWVdKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGVscC5fZ2xvYmFsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjdXIgPSBoZWxwLl9nbG9iYWxbaV07XG4gICAgICAgIGlmIChjdXIucHJlZChtb2RlLCB0aGlzKSAmJiBpbmRleE9mKGZvdW5kLCBjdXIudmFsKSA9PSAtMSlcbiAgICAgICAgICBmb3VuZC5wdXNoKGN1ci52YWwpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZvdW5kO1xuICAgIH0sXG5cbiAgICBnZXRTdGF0ZUFmdGVyOiBmdW5jdGlvbihsaW5lLCBwcmVjaXNlKSB7XG4gICAgICB2Y
23459XIgZG9jID0gdGhpcy5kb2M7XG4gICAgICBsaW5lID0gY2xpcExpbmUoZG9jLCBsaW5lID09IG51bGwgPyBkb2MuZmlyc3QgKyBkb2Muc2l6ZSAtIDE6IGxpbmUpO1xuICAgICAgcmV0dXJuIGdldFN0YXRlQmVmb3JlKHRoaXMsIGxpbmUgKyAxLCBwcmVjaXNlKTtcbiAgICB9LFxuXG4gICAgY3Vyc29yQ29vcmRzOiBmdW5jdGlvbihzdGFydCwgbW9kZSkge1xuICAgICAgdmFyIHBvcywgcmFuZ2UgPSB0aGlzLmRvYy5zZWwucHJpbWFyeSgpO1xuICAgICAgaWYgKHN0YXJ0ID09IG51bGwpIHBvcyA9IHJhbmdlLmhlYWQ7XG4gICAgICBlbHNlIGlmICh0eXBlb2Ygc3RhcnQgPT0gXCJvYmplY3RcIikgcG9zID0gY2xpcFBvcyh0aGlzLmRvYywgc3RhcnQpO1xuICAgICAgZWxzZSBwb3MgPSBzdGFydCA/IHJhbmdlLmZyb20oKSA6IHJhbmdlLnRvKCk7XG4gICAgICByZXR1cm4gY3Vyc29yQ29vcmRzKHRoaXMsIHBvcywgbW9kZSB8fCBcInBhZ2VcIik7XG4gICAgfSxcblxuICAgIGNoYXJDb29yZHM6IGZ1bmN0aW9uKHBvcywgbW9kZSkge1xuICAgICAgcmV0dXJuIGNoYXJDb29yZHModGhpcywgY2xpcFBvcyh0aGlzLmRvYywgcG9zKSwgbW9kZSB8fCBcInBhZ2VcIik7XG4gICAgfSxcblxuICAgIGNvb3Jkc0NoYXI6IGZ1bmN0aW9uKGNvb3JkcywgbW9kZSkge1xuICAgICAgY29vcmRzID0gZnJvbUNvb3JkU3lzdGVtKHRoaXMsIGNvb3JkcywgbW9kZSB8fCBcInBhZ2VcIik7XG4gICAgICByZXR1cm4gY29vcmRzQ2hhcih0aGlzLCBjb29yZHMubGVmdCwgY29vcmRzLnRvcCk7XG4gICAgfSxcblxuICAgIGxpbmVBdEhlaWdodDogZnVuY3Rpb24oaGVpZ2h0LCBtb2RlKSB7XG4gICAgICBoZWlnaHQgPSBmcm9tQ29vcmRTeXN0ZW0odGhpcywge3RvcDogaGVpZ2h0LCBsZWZ0OiAwfSwgbW9kZSB8fCBcInBhZ2VcIikudG9wO1xuICAgICAgcmV0dXJuIGxpbmVBdEhlaWdodCh0aGlzLmRvYywgaGVpZ2h0ICsgdGh
23459pcy5kaXNwbGF5LnZpZXdPZmZzZXQpO1xuICAgIH0sXG4gICAgaGVpZ2h0QXRMaW5lOiBmdW5jdGlvbihsaW5lLCBtb2RlKSB7XG4gICAgICB2YXIgZW5kID0gZmFsc2UsIGxpbmVPYmo7XG4gICAgICBpZiAodHlwZW9mIGxpbmUgPT0gXCJudW1iZXJcIikge1xuICAgICAgICB2YXIgbGFzdCA9IHRoaXMuZG9jLmZpcnN0ICsgdGhpcy5kb2Muc2l6ZSAtIDE7XG4gICAgICAgIGlmIChsaW5lIDwgdGhpcy5kb2MuZmlyc3QpIGxpbmUgPSB0aGlzLmRvYy5maXJzdDtcbiAgICAgICAgZWxzZSBpZiAobGluZSA+IGxhc3QpIHsgbGluZSA9IGxhc3Q7IGVuZCA9IHRydWU7IH1cbiAgICAgICAgbGluZU9iaiA9IGdldExpbmUodGhpcy5kb2MsIGxpbmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGluZU9iaiA9IGxpbmU7XG4gICAgICB9XG4gICAgICByZXR1cm4gaW50b0Nvb3JkU3lzdGVtKHRoaXMsIGxpbmVPYmosIHt0b3A6IDAsIGxlZnQ6IDB9LCBtb2RlIHx8IFwicGFnZVwiKS50b3AgK1xuICAgICAgICAoZW5kID8gdGhpcy5kb2MuaGVpZ2h0IC0gaGVpZ2h0QXRMaW5lKGxpbmVPYmopIDogMCk7XG4gICAgfSxcblxuICAgIGRlZmF1bHRUZXh0SGVpZ2h0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHRleHRIZWlnaHQodGhpcy5kaXNwbGF5KTsgfSxcbiAgICBkZWZhdWx0Q2hhcldpZHRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIGNoYXJXaWR0aCh0aGlzLmRpc3BsYXkpOyB9LFxuXG4gICAgc2V0R3V0dGVyTWFya2VyOiBtZXRob2RPcChmdW5jdGlvbihsaW5lLCBndXR0ZXJJRCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBjaGFuZ2VMaW5lKHRoaXMuZG9jLCBsaW5lLCBcImd1dHRlclwiLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHZhciBtYXJrZXJzID0gbGluZS5ndXR0ZXJNYXJrZXJzIHx8IChsaW5lLmd1dHRlck1hcmtlcnMgPSB7fSk7XG4gICAgICAgIG1hcmtlcnNbZ3V0dGVySURdID0gdmFsdWU7XG4gICAgICAgIGlmICghdmFsdWUgJiYgaXNFbXB0eShtY
23459XJrZXJzKSkgbGluZS5ndXR0ZXJNYXJrZXJzID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KTtcbiAgICB9KSxcblxuICAgIGNsZWFyR3V0dGVyOiBtZXRob2RPcChmdW5jdGlvbihndXR0ZXJJRCkge1xuICAgICAgdmFyIGNtID0gdGhpcywgZG9jID0gY20uZG9jLCBpID0gZG9jLmZpcnN0O1xuICAgICAgZG9jLml0ZXIoZnVuY3Rpb24obGluZSkge1xuICAgICAgICBpZiAobGluZS5ndXR0ZXJNYXJrZXJzICYmIGxpbmUuZ3V0dGVyTWFya2Vyc1tndXR0ZXJJRF0pIHtcbiAgICAgICAgICBsaW5lLmd1dHRlck1hcmtlcnNbZ3V0dGVySURdID0gbnVsbDtcbiAgICAgICAgICByZWdMaW5lQ2hhbmdlKGNtLCBpLCBcImd1dHRlclwiKTtcbiAgICAgICAgICBpZiAoaXNFbXB0eShsaW5lLmd1dHRlck1hcmtlcnMpKSBsaW5lLmd1dHRlck1hcmtlcnMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgICsraTtcbiAgICAgIH0pO1xuICAgIH0pLFxuXG4gICAgbGluZUluZm86IGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIGlmICh0eXBlb2YgbGluZSA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgIGlmICghaXNMaW5lKHRoaXMuZG9jLCBsaW5lKSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHZhciBuID0gbGluZTtcbiAgICAgICAgbGluZSA9IGdldExpbmUodGhpcy5kb2MsIGxpbmUpO1xuICAgICAgICBpZiAoIWxpbmUpIHJldHVybiBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG4gPSBsaW5lTm8obGluZSk7XG4gICAgICAgIGlmIChuID09IG51bGwpIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtsaW5lOiBuLCBoYW5kbGU6IGxpbmUsIHRleHQ6IGxpbmUudGV4dCwgZ3V0dGVyTWFya2VyczogbGluZS5ndXR0ZXJNYXJrZXJzLFxuICAgICAgICAgICAgICB0ZXh0Q2xhc3M6IGxpbmUudGV4dENsYXNzLCBiZ0NsYXNzOiBsaW5lLmJnQ2xhc3MsIHdyYXBDbGFzczogbGluZS53cmFwQ2xhc3MsXG4gICAgICAgICAgICAgIHdpZGdldHM6IGxpbmUud2lkZ2V0c307XG4gICAgfSxcblxuICAgIGdldFZpZXdwb3J0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHtmcm9tOiB0aGlzLmRpc3BsYXkudmlld0Zyb20sIHRvOiB0aGlzLmRpc3BsYXkudmlld1RvfTt9LFxuXG4gICAgYWRkV2lkZ2V0OiBmdW5jdGlvbihwb3MsIG5vZGUsIHNjcm9sbCwgdmVydCwgaG9yaXopIHtcbiAgICAgIHZhciBkaXNwbGF5ID0gdGhpcy5kaXNwbGF5O1xuICAgICAgcG9zID0gY3Vyc29yQ29vcmRzKHRoaXMsIGNsaXBQb3ModGhpcy5kb2MsIHBvcykpO1xuICAgICAgdmFyIHRvcCA9IHBvcy5ib3R0b20sIGxlZnQgPSBwb3MubGVmdDtcbiAgICAgIG5vZGUuc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICBub2RlLnNldEF0dHJpYnV0ZShcImNtLWlnbm9yZS1ldmVud
23459HNcIiwgXCJ0cnVlXCIpO1xuICAgICAgdGhpcy5kaXNwbGF5LmlucHV0LnNldFVuZWRpdGFibGUobm9kZSk7XG4gICAgICBkaXNwbGF5LnNpemVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgaWYgKHZlcnQgPT0gXCJvdmVyXCIpIHtcbiAgICAgICAgdG9wID0gcG9zLnRvcDtcbiAgICAgIH0gZWxzZSBpZiAodmVydCA9PSBcImFib3ZlXCIgfHwgdmVydCA9PSBcIm5lYXJcIikge1xuICAgICAgICB2YXIgdnNwYWNlID0gTWF0aC5tYXgoZGlzcGxheS53cmFwcGVyLmNsaWVudEhlaWdodCwgdGhpcy5kb2MuaGVpZ2h0KSxcbiAgICAgICAgaHNwYWNlID0gTWF0aC5tYXgoZGlzcGxheS5zaXplci5jbGllbnRXaWR0aCwgZGlzcGxheS5saW5lU3BhY2UuY2xpZW50V2lkdGgpO1xuICAgICAgICAvLyBEZWZhdWx0IHRvIHBvc2l0aW9uaW5nIGFib3ZlIChpZiBzcGVjaWZpZWQgYW5kIHBvc3NpYmxlKTsgb3RoZXJ3aXNlIGRlZmF1bHQgdG8gcG9zaXRpb25pbmcgYmVsb3dcbiAgICAgICAgaWYgKCh2ZXJ0ID09ICdhYm92ZScgfHwgcG9zLmJvdHRvbSArIG5vZGUub2Zmc2V0SGVpZ2h0ID4gdnNwYWNlKSAmJiBwb3MudG9wID4gbm9kZS5vZmZzZXRIZWlnaHQpXG4gICAgICAgICAgdG9wID0gcG9zLnRvcCAtIG5vZGUub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBlbHNlIGlmIChwb3MuYm90dG9tICsgbm9kZS5vZmZzZXRIZWlnaHQgPD0gdnNwYWNlKVxuICAgICAgICAgIHRvcCA9IHBvcy5ib3R0b207XG4gICAgICAgIGlmIChsZWZ0ICsgbm9kZS5vZmZzZXRXaWR0aCA+IGhzcGFjZSlcbiAgICAgICAgICBsZWZ0ID0gaHNwYWNlIC0gbm9kZS5vZmZzZXRXaWR0aDtcbiAgICAgIH1cbiAgICAgIG5vZGUuc3R5bGUudG9wID0gdG9wICsgXCJweFwiO1xuICAgICAgbm9kZS5zdHlsZS5sZWZ0ID0gbm9kZS5zdHlsZS5yaWdodCA9IFwiXCI7XG4gICAgICBpZiAoaG9yaXogPT0gXCJyaWdodFwiKSB7XG4gICAgICAgIGxlZnQgPSBkaXNwbGF5LnNpemVyLmNsaWVudFdpZHRoIC0gbm9kZS5vZmZzZXRXaWR0aDtcbiAgICAgICAgbm9kZS5zdHlsZS5yaWdodCA9IFwiMHB4XCI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaG9yaXogPT0gXCJsZWZ0XCIpIGxlZnQgPSAwO1xuICAgICAgICBlbHNlIGlmIChob3JpeiA9PSBcIm1pZGRsZVwiKSBsZWZ0ID0gKGRpc3BsYXkuc2l6ZXIuY2xpZW50V2lkdGggLSBub2RlLm9mZnNldFdpZHRoKSAvIDI7XG4gICAgICAgIG5vZGUuc3R5bGUubGVmdCA9IGxlZnQgKyBcInB4XCI7XG4gICAgICB9XG4gICAgICBpZiAoc2Nyb2xsKVxuICAgICAgICBzY3JvbGxJbnRvVmlldyh0aGlzLCBsZWZ0LCB0b3AsIGxlZnQgKyBub2RlLm9mZnNldFdpZHRoLCB0b3AgKyBub2RlLm9mZnNldEhlaWdodCk7XG4gICAgfSxcblxuICAgIHRyaWdnZXJPbktleURvd246IG1ldGhvZE9wKG9uS2V5RG93biksXG4gICAgdHJpZ2dlck9uS2V5UHJlc3M6IG1ldGhvZE9wKG9uS2V5UHJlc3MpLFxuICAgIHRyaWdnZXJPbktleVVwOiBvbktleVVwLFxuXG4gICAgZXhlY0NvbW1hbmQ6IGZ1bmN0aW9uKGNtZCkge1xuICAgICAgaWYgKGNvbW1hbmRzLmhhc093blByb3BlcnR5KGNtZCkpXG4gICAgICAgIHJldHVybiBjb21tYW5kc1tjbWRdLmNhbGwobnVsbCwgdGhpcyk7XG4gICAgfSxcblxuICAgIHRyaWdnZXJFbGVjdHJpYzogbWV0aG9kT3AoZnVuY3Rpb24odGV4dCkgeyB0cmlnZ2VyRWxlY3RyaWModGhpcywgdGV4dCk7IH0pLFxuXG4gICAgZmluZFBvc0g6IGZ1bmN0aW9uKGZyb20sIGFtb3VudCwgdW5pdCwgdmlzdWFsbHkpIHtcbiAgICAgIHZhciBkaXIgPSAxO1xuICAgICAgaWYgKGFtb3VudCA8IDApIHsgZGlyID0gLTE7IGFtb3VudCA9IC1hbW91bnQ7IH1cbiAgICAgIGZvciAodmFyIGkgPSAwLCBjdXIgPSBjbGlwUG9zKHRoaXMuZG9jLCBmcm9tKTsgaSA8IGFtb3VudDsgKytpKSB7XG4gICAgICAgIGN1ciA9IGZpbmRQb3NIKHRoaXMuZG9jLCBjdXIsIGRpciwgdW5pdCwgdmlzdWFsbHkpO1xuICAgICAgICBpZiAoY3VyLmhpdFNpZGUpIGJyZWFrO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGN1cjtcbiAgICB9LFxuXG4gICAgbW92ZUg6IG1ldGhvZE9wKGZ1bmN0aW9uKGRpciwgdW5pdCkge1xuICAgICAgdmFyIGNtID0gdGhpcztcbiAgICAgIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbihyYW5nZSkge1xuICAgICAgICBpZiAoY20uZGlzcGxheS5zaGlmdCB8fCBjbS5kb2MuZXh0ZW5kIHx8IHJhbmdlLmVtcHR5KCkpXG4gICAgICAgICAgcmV0dXJuIGZpbmRQb3NIKGNtLmRvYywgcmFuZ2UuaGVhZCwgZGlyLCB1bml0LCBjbS5vcHRpb25zLnJ0bE1vdmVWaXN1YWxseSk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gZGlyIDwgMCA/IHJhbmdlLmZyb20oKSA6IHJhbmdlLnRvKCk7XG4gICAgICB9LCBzZWxfbW92ZSk7XG4gICAgfSksXG5cbiAgICBkZWxldGVIOiBtZXRob2RPcChmdW5jdGlvbihkaXIsIHVuaXQpIHtcbiAgICAgIHZhciBzZWwgPSB0aGlzLmRvYy5zZWwsIGRvYyA9IHRoaXMuZG9jO1xuICAgICAgaWYgKHNlbC5zb21ldGhpbmdTZWxlY3RlZCgpKVxuICAgICAgICBkb2MucmVwbGFjZVNlbGVjdGlvbihcIlwiLCBudWxsLCBcIitkZWxldGVcIik7XG4gICAgICBlbHNlXG4gICAgICAgIGRlbGV0ZU5lYXJTZWxlY3Rpb24odGhpcywgZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgICB2Y
23459XIgb3RoZXIgPSBmaW5kUG9zSChkb2MsIHJhbmdlLmhlYWQsIGRpciwgdW5pdCwgZmFsc2UpO1xuICAgICAgICAgIHJldHVybiBkaXIgPCAwID8ge2Zyb206IG90aGVyLCB0bzogcmFuZ2UuaGVhZH0gOiB7ZnJvbTogcmFuZ2UuaGVhZCwgdG86IG90aGVyfTtcbiAgICAgICAgfSk7XG4gICAgfSksXG5cbiAgICBmaW5kUG9zVjogZnVuY3Rpb24oZnJvbSwgYW1vdW50LCB1bml0LCBnb2FsQ29sdW1uKSB7XG4gICAgICB2YXIgZGlyID0gMSwgeCA9IGdvYWxDb2x1bW47XG4gICAgICBpZiAoYW1vdW50IDwgMCkgeyBkaXIgPSAtMTsgYW1vdW50ID0gLWFtb3VudDsgfVxuICAgICAgZm9yICh2YXIgaSA9IDAsIGN1ciA9IGNsaXBQb3ModGhpcy5kb2MsIGZyb20pOyBpIDwgYW1vdW50OyArK2kpIHtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGN1cnNvckNvb3Jkcyh0aGlzLCBjdXIsIFwiZGl2XCIpO1xuICAgICAgICBpZiAoeCA9PSBudWxsKSB4ID0gY29vcmRzLmxlZnQ7XG4gICAgICAgIGVsc2UgY29vcmRzLmxlZnQgPSB4O1xuICAgICAgICBjdXIgPSBmaW5kUG9zVih0aGlzLCBjb29yZHMsIGRpciwgdW5pdCk7XG4gICAgICAgIGlmIChjdXIuaGl0U2lkZSkgYnJlYWs7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3VyO1xuICAgIH0sXG5cbiAgICBtb3ZlVjogbWV0aG9kT3AoZnVuY3Rpb24oZGlyLCB1bml0KSB7XG4gICAgICB2YXIgY20gPSB0aGlzLCBkb2MgPSB0aGlzLmRvYywgZ29hbHMgPSBbXTtcbiAgICAgIHZhciBjb2xsYXBzZSA9ICFjbS5kaXNwbGF5LnNoaWZ0ICYmICFkb2MuZXh0ZW5kICYmIGRvYy5zZWwuc29tZXRoaW5nU2VsZWN0ZWQoKTtcbiAgICAgIGRvYy5leHRlbmRTZWxlY3Rpb25zQnkoZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgaWYgKGNvbGxhcHNlKVxuICAgICAgICAgIHJldHVybiBkaXIgPCAwID8gcmFuZ2UuZnJvbSgpIDogcmFuZ2UudG8oKTtcbiAgICAgICAgdmFyIGhlYWRQb3MgPSBjdXJzb3JDb29yZHMoY20sIHJhbmdlLmhlYWQsIFwiZGl2XCIpO1xuICAgICAgICBpZiAocmFuZ2UuZ29hbENvbHVtbiAhPSBudWxsKSBoZWFkUG9zLmxlZnQgPSByYW5nZS5nb2FsQ29sdW1uO1xuICAgICAgICBnb2Fscy5wdXNoKGhlYWRQb3MubGVmdCk7XG4gICAgICAgIHZhciBwb3MgPSBmaW5kUG9zVihjbSwgaGVhZFBvcywgZGlyLCB1bml0KTtcbiAgICAgICAgaWYgKHVuaXQgPT0gXCJwYWdlXCIgJiYgcmFuZ2UgPT0gZG9jLnNlbC5wcmltYXJ5KCkpXG4gICAgICAgICAgYWRkVG9TY3JvbGxQb3MoY20sIG51bGwsIGNoYXJDb29yZHMoY20sIHBvcywgXCJkaXZcIikudG9wIC0gaGVhZFBvcy50b3ApO1xuICAgICAgICByZXR1cm4gcG9zO1xuICAgICAgfSwgc2VsX21vdmUpO1xuICAgICAgaWYgKGdvYWxzLmxlbmd0aCkgZm9yICh2YXIgaSA9IDA7IGkgPCBkb2Muc2VsLnJhbmdlcy5sZW5ndGg7IGkrKylcbiAgICAgICAgZG9jLnNlbC5yYW5nZXNbaV0uZ29hbENvbHVtbiA9IGdvYWxzW2ldO1xuICAgIH0pLFxuXG4gICAgLy8gRmluZCB0aGUgd29yZCBhdCB0aGUgZ2l2ZW4gcG9zaXRpb24gKGFzIHJldHVybmVkIGJ5IGNvb3Jkc0NoYX
23459IpLlxuICAgIGZpbmRXb3JkQXQ6IGZ1bmN0aW9uKHBvcykge1xuICAgICAgdmFyIGRvYyA9IHRoaXMuZG9jLCBsaW5lID0gZ2V0TGluZShkb2MsIHBvcy5saW5lKS50ZXh0O1xuICAgICAgdmFyIHN0YXJ0ID0gcG9zLmNoLCBlbmQgPSBwb3MuY2g7XG4gICAgICBpZiAobGluZSkge1xuICAgICAgICB2YXIgaGVscGVyID0gdGhpcy5nZXRIZWxwZXIocG9zLCBcIndvcmRDaGFyc1wiKTtcbiAgICAgICAgaWYgKChwb3MueFJlbCA8IDAgfHwgZW5kID09IGxpbmUubGVuZ3RoKSAmJiBzdGFydCkgLS1zdGFydDsgZWxzZSArK2VuZDtcbiAgICAgICAgdmFyIHN0YXJ0Q2hhciA9IGxpbmUuY2hhckF0KHN0YXJ0KTtcbiAgICAgICAgdmFyIGNoZWNrID0gaXNXb3JkQ2hhcihzdGFydENoYXIsIGhlbHBlcilcbiAgICAgICAgICA/IGZ1bmN0aW9uKGNoKSB7IHJldHVybiBpc1dvcmRDaGFyKGNoLCBoZWxwZXIpOyB9XG4gICAgICAgICAgOiAvXFxzLy50ZXN0KHN0YXJ0Q2hhcikgPyBmdW5jdGlvbihjaCkge3JldHVybiAvXFxzLy50ZXN0KGNoKTt9XG4gICAgICAgICAgOiBmdW5jdGlvbihjaCkge3JldHVybiAhL1xccy8udGVzdChjaCkgJiYgIWlzV29yZENoYXIoY2gpO307XG4gICAgICAgIHdoaWxlIChzdGFydCA+IDAgJiYgY2hlY2sobGluZS5jaGFyQXQoc3RhcnQgLSAxKSkpIC0tc3RhcnQ7XG4gICAgICAgIHdoaWxlIChlbmQgPCBsaW5lLmxlbmd0aCAmJiBjaGVjayhsaW5lLmNoYXJBdChlbmQpKSkgKytlbmQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJhbmdlKFBvcyhwb3MubGluZSwgc3RhcnQpLCBQb3MocG9zLmxpbmUsIGVuZCkpO1xuICAgIH0sXG5cbiAgICB0b2dnbGVPdmVyd3JpdGU6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAodmFsdWUgIT0gbnVsbCAmJiB2YWx1ZSA9PSB0aGlzLnN0YXRlLm92ZXJ3cml0ZSkgcmV0dXJuO1xuICAgICAgaWYgKHRoaXMuc3RhdGUub3ZlcndyaXRlID0gIXRoaXMuc3RhdGUub3ZlcndyaXRlKVxuICAgICAgICBhZGRDbGFzcyh0aGlzLmRpc3BsYXkuY3Vyc29yRGl2LCBcIkNvZGVNaXJyb3Itb3ZlcndyaXRlXCIpO1xuICAgICAgZWxzZVxuICAgICAgICBybUNsYXNzKHRoaXMuZGlzcGxheS5jdXJzb3JEaXYsIFwiQ29kZU1pcnJvci1vdmVyd3JpdGVcIik7XG5cbiAgICAgIHNpZ25hbCh0aGlzLCBcIm92ZXJ3cml0ZVRvZ2dsZVwiLCB0aGlzLCB0aGlzLnN0YXRlLm92ZXJ3cml0ZSk7XG4gICAgfSxcbiAgICBoYXNGb2N1czogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmRpc3BsYXkuaW5wdXQuZ2V0RmllbGQoKSA9PSBhY3RpdmVFbHQoKTsgfSxcblxuICAgIHNjcm9sbFRvOiBtZXRob2RPcChmdW5jdGlvbih4LCB5KSB7XG4gICAgICBpZiAoeCAhPSBudWxsIHx8IHkgIT0gbnVsbCkgcmVzb2x2ZVNjcm9sbFRvUG9zKHRoaXMpO1xuICAgICAgaWYgKHggIT0gbnVsbCkgdGhpcy5jdXJPcC5zY3JvbGxMZWZ0ID0geDtcbiAgICAgIGlmICh5ICE9IG51bGwpIHRoaXMuY3VyT3Auc2Nyb2xsVG9wID0geTtcbiAgICB9KSxcbiAgICBnZXRTY3JvbGxJbmZvOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBzY3JvbGxlciA9IHRoaXMuZGlzcGxheS5zY3JvbGxlcjtcbiAgICAgIHJldHVybiB7bGVmdDogc2Nyb2xsZXIuc2Nyb2xsTGVmdCwgdG9wOiBzY3JvbGxlci5zY3JvbGxUb3AsXG4gICAgICAgICAgICAgIGhlaWdodDogc2Nyb2xsZXIuc2Nyb2xsSGVpZ2h0IC0gc2Nyb2xsR2FwKHRoaXMpIC0gdGhpcy5kaXNwbGF5LmJhckhlaWdodCxcbiAgICAgICAgICAgICAgd2lkdGg6IHNjcm9sbGVyLnNjcm9sbFdpZHR
23459oIC0gc2Nyb2xsR2FwKHRoaXMpIC0gdGhpcy5kaXNwbGF5LmJhcldpZHRoLFxuICAgICAgICAgICAgICBjbGllbnRIZWlnaHQ6IGRpc3BsYXlIZWlnaHQodGhpcyksIGNsaWVudFdpZHRoOiBkaXNwbGF5V2lkdGgodGhpcyl9O1xuICAgIH0sXG5cbiAgICBzY3JvbGxJbnRvVmlldzogbWV0aG9kT3AoZnVuY3Rpb24ocmFuZ2UsIG1hcmdpbikge1xuICAgICAgaWYgKHJhbmdlID09IG51bGwpIHtcbiAgICAgICAgcmFuZ2UgPSB7ZnJvbTogdGhpcy5kb2Muc2VsLnByaW1hcnkoKS5oZWFkLCB0bzogbnVsbH07XG4gICAgICAgIGlmIChtYXJnaW4gPT0gbnVsbCkgbWFyZ2luID0gdGhpcy5vcHRpb25zLmN1cnNvclNjcm9sbE1hcmdpbjtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJhbmdlID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgcmFuZ2UgPSB7ZnJvbTogUG9zKHJhbmdlLCAwKSwgdG86IG51bGx9O1xuICAgICAgfSBlbHNlIGlmIChyYW5nZS5mcm9tID09IG51bGwpIHtcbiAgICAgICAgcmFuZ2UgPSB7ZnJvbTogcmFuZ2UsIHRvOiBudWxsfTtcbiAgICAgIH1cbiAgICAgIGlmICghcmFuZ2UudG8pIHJhbmdlLnRvID0gcmFuZ2UuZnJvbTtcbiAgICAgIHJhbmdlLm1hcmdpbiA9IG1hcmdpbiB8fCAwO1xuXG4gICAgICBpZiAocmFuZ2UuZnJvbS5saW5lICE9IG51bGwpIHtcbiAgICAgICAgcmVzb2x2ZVNjcm9sbFRvUG9zKHRoaXMpO1xuICAgICAgICB0aGlzLmN1ck9wLnNjcm9sbFRvUG9zID0gcmFuZ2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgc1BvcyA9IGNhbGN1bGF0ZVNjcm9sbFBvcyh0aGlzLCBNYXRoLm1pbihyYW5nZS5mcm9tLmxlZnQsIHJhbmdlLnRvLmxlZnQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1pbihyYW5nZS5mcm9tLnRvcCwgcmFuZ2UudG8udG9wKSAtIHJhbmdlLm1hcmdpbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5tYXgocmFuZ2UuZnJvbS5yaWdodCwgcmFuZ2UudG8ucmlnaHQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1heChyYW5nZS5mcm9tLmJvdHRvbSwgcmFuZ2UudG8uYm90dG9tKSArIHJhbmdlLm1hcmdpbik7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG8oc1Bvcy5zY3JvbGxMZWZ0LCBzUG9zLnNjcm9sbFRvcCk7XG4gICAgICB9XG4gICAgfSksXG5cbiAgICBzZXRTaXplOiBtZXRob2RPcChmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICB2Y
23459XIgY20gPSB0aGlzO1xuICAgICAgZnVuY3Rpb24gaW50ZXJwcmV0KHZhbCkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbCA9PSBcIm51bWJlclwiIHx8IC9eXFxkKyQvLnRlc3QoU3RyaW5nKHZhbCkpID8gdmFsICsgXCJweFwiIDogdmFsO1xuICAgICAgfVxuICAgICAgaWYgKHdpZHRoICE9IG51bGwpIGNtLmRpc3BsYXkud3JhcHBlci5zdHlsZS53aWR0aCA9IGludGVycHJldCh3aWR0aCk7XG4gICAgICBpZiAoaGVpZ2h0ICE9IG51bGwpIGNtLmRpc3BsYXkud3JhcHBlci5zdHlsZS5oZWlnaHQgPSBpbnRlcnByZXQoaGVpZ2h0KTtcbiAgICAgIGlmIChjbS5vcHRpb25zLmxpbmVXcmFwcGluZykgY2xlYXJMaW5lTWVhc3VyZW1lbnRDYWNoZSh0aGlzKTtcbiAgICAgIHZhciBsaW5lTm8gPSBjbS5kaXNwbGF5LnZpZXdGcm9tO1xuICAgICAgY20uZG9jLml0ZXIobGluZU5vLCBjbS5kaXNwbGF5LnZpZXdUbywgZnVuY3Rpb24obGluZSkge1xuICAgICAgICBpZiAobGluZS53aWRnZXRzKSBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUud2lkZ2V0cy5sZW5ndGg7IGkrKylcbiAgICAgICAgICBpZiAobGluZS53aWRnZXRzW2ldLm5vSFNjcm9sbCkgeyByZWdMaW5lQ2hhbmdlKGNtLCBsaW5lTm8sIFwid2lkZ2V0XCIpOyBicmVhazsgfVxuICAgICAgICArK2xpbmVObztcbiAgICAgIH0pO1xuICAgICAgY20uY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgICAgc2lnbmFsKGNtLCBcInJlZnJlc2hcIiwgdGhpcyk7XG4gICAgfSksXG5cbiAgICBvcGVyYXRpb246IGZ1bmN0aW9uKGYpe3JldHVybiBydW5Jbk9wKHRoaXMsIGYpO30sXG5cbiAgICByZWZyZXNoOiBtZXRob2RPcChmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvbGRIZWlnaHQgPSB0aGlzLmRpc3BsYXkuY2FjaGVkVGV4dEhlaWdodDtcbiAgICAgIHJlZ0NoYW5nZSh0aGlzKTtcbiAgICAgIHRoaXMuY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgICAgY2xlYXJDYWNoZXModGhpcyk7XG4gICAgICB0aGlzLnNjcm9sbFRvKHRoaXMuZG9jLnNjcm9sbExlZnQsIHRoaXMuZG9jLnNjcm9sbFRvcCk7XG4gICAgICB1cGRhdGVHdXR0ZXJTcGFjZSh0aGlzKTtcbiAgICAgIGlmIChvbGRIZWlnaHQgPT0gbnVsbCB8fCBNYXRoLmFicyhvbGRIZWlnaHQgLSB0ZXh0SGVpZ2h0KHRoaXMuZGlzcGxheSkpID4gLjUpXG4gICAgICAgIGVzdGltYXRlTGluZUhlaWdodHModGhpcyk7XG4gICAgICBzaWduYWwodGhpcywgXCJyZWZyZXNoXCIsIHRoaXMpO1xuICAgIH0pLFxuXG4gICAgc3dhcERvYzogbWV0aG9kT3AoZnVuY3Rpb24oZG9jKSB7XG4gICAgICB2Y
23459XIgb2xkID0gdGhpcy5kb2M7XG4gICAgICBvbGQuY20gPSBudWxsO1xuICAgICAgYXR0YWNoRG9jKHRoaXMsIGRvYyk7XG4gICAgICBjbGVhckNhY2hlcyh0aGlzKTtcbiAgICAgIHRoaXMuZGlzcGxheS5pbnB1dC5yZXNldCgpO1xuICAgICAgdGhpcy5zY3JvbGxUbyhkb2Muc2Nyb2xsTGVmdCwgZG9jLnNjcm9sbFRvcCk7XG4gICAgICB0aGlzLmN1ck9wLmZvcmNlU2Nyb2xsID0gdHJ1ZTtcbiAgICAgIHNpZ25hbExhdGVyKHRoaXMsIFwic3dhcERvY1wiLCB0aGlzLCBvbGQpO1xuICAgICAgcmV0dXJuIG9sZDtcbiAgICB9KSxcblxuICAgIGdldElucHV0RmllbGQ6IGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGlzcGxheS5pbnB1dC5nZXRGaWVsZCgpO30sXG4gICAgZ2V0V3JhcHBlckVsZW1lbnQ6IGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGlzcGxheS53cmFwcGVyO30sXG4gICAgZ2V0U2Nyb2xsZXJFbGVtZW50OiBmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpc3BsYXkuc2Nyb2xsZXI7fSxcbiAgICBnZXRHdXR0ZXJFbGVtZW50OiBmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpc3BsYXkuZ3V0dGVyczt9XG4gIH07XG4gIGV2ZW50TWl4aW4oQ29kZU1pcnJvcik7XG5cbiAgLy8gT1BUSU9OIERFRkFVTFRTXG5cbiAgLy8gVGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICB2YXIgZGVmYXVsdHMgPSBDb2RlTWlycm9yLmRlZmF1bHRzID0ge307XG4gIC8vIEZ1bmN0aW9ucyB0byBydW4gd2hlbiBvcHRpb25zIGFyZSBjaGFuZ2VkLlxuICB2YXIgb3B0aW9uSGFuZGxlcnMgPSBDb2RlTWlycm9yLm9wdGlvbkhhbmRsZXJzID0ge307XG5cbiAgZnVuY3Rpb24gb3B0aW9uKG5hbWUsIGRlZmx0LCBoYW5kbGUsIG5vdE9uSW5pdCkge1xuICAgIENvZGVNaXJyb3IuZGVmYXVsdHNbbmFtZV0gPSBkZWZsdDtcbiAgICBpZiAoaGFuZGxlKSBvcHRpb25IYW5kbGVyc1tuYW1lXSA9XG4gICAgICBub3RPbkluaXQgPyBmdW5jdGlvbihjbSwgdmFsLCBvbGQpIHtpZiAob2xkICE9IEluaXQpIGhhbmRsZShjbSwgdmFsLCBvbGQpO30gOiBoYW5kbGU7XG4gIH1cblxuICAvLyBQYXNzZWQgdG8gb3B0aW9uIGhhbmRsZXJzIHdoZW4gdGhlcmUgaXMgbm8gb2xkIHZhbHVlLlxuICB2YXIgSW5pdCA9IENvZGVNaXJyb3IuSW5pdCA9IHt0b1N0cmluZzogZnVuY3Rpb24oKXtyZXR1cm4gXCJDb2RlTWlycm9yLkluaXRcIjt9fTtcblxuICAvLyBUaGVzZSB0d28gYXJlLCBvbiBpbml0LCBjYWxsZWQgZnJvbSB0aGUgY29uc3RydWN0b3IgYmVjYXVzZSB0aGV5XG4gIC8vIGhhdmUgdG8gYmUgaW5pdGlhbGl6ZWQgYmVmb3JlIHRoZSBlZGl0b3IgY2FuIHN0YXJ0IGF0IGFsbC5cbiAgb3B0aW9uKFwidmFsdWVcIiwgXCJcIiwgZnVuY3Rpb24oY20sIHZhbCkge1xuICAgIGNtLnNldFZhbHVlKHZhbCk7XG4gIH0sIHRydWUpO1xuICBvcHRpb24oXCJtb2RlXCIsIG51bGwsIGZ1bmN0aW9uKGNtLCB2YWwpIHtcbiAgICBjbS5kb2MubW9kZU9wdGlvbiA9IHZhbDtcbiAgICBsb2FkTW9kZShjbSk7XG4gIH0sIHRydWUpO1xuXG4gIG9wdGlvbihcImluZGVudFVuaXRcIiwgMiwgbG9hZE1vZGUsIHRydWUpO1xuICBvcHRpb24oXCJpbmRlbnRXaXRoVGFic1wiLCBmYWxzZSk7XG4gIG9wdGlvbihcInNtYXJ0SW5kZW50XCIsIHRydWUpO1xuICBvcHRpb24oXCJ0YWJTaXplXCIsIDQsIGZ1bmN0aW9uKGNtKSB7XG4gICAgcmVzZXRNb2RlU3RhdGUoY20pO1xuICAgIGNsZWFyQ2FjaGVzKGNtKTtcbiAgICByZWdDaGFuZ2UoY20pO1xuICB9LCB0cnVlKTtcbiAgb3B0aW9uKFwibGluZVNlcGFyYXRvclwiLCBudWxsLCBmdW5jdGlvbihjbSwgdmFsKSB7XG4gICAgY20uZG9jLmxpbmVTZXAgPSB2YWw7XG4gICAgaWYgKCF2YWwpIHJldHVybjtcbiAgICB2YXIgbmV3QnJlYWtzID0gW10sIGxpbmVObyA9IGNtLmRvYy5maXJzdDtcbiAgICBjbS5kb2MuaXRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgICBmb3IgKHZhciBwb3MgPSAwOzspIHtcbiAgICAgICAgdmFyIGZvdW5kID0gbGluZS50ZXh0LmluZGV4T2YodmFsLCBwb3MpO1xuICAgICAgICBpZiAoZm91bmQgPT0gLTEpIGJyZWFrO1xuICAgICAgICBwb3MgPSBmb3VuZCArIHZhbC5sZW5ndGg7XG4gICAgICAgIG5ld0JyZWFrcy5wdXNoKFBvcyhsaW5lTm8sIGZvdW5kKSk7XG4gICAgICB9XG4gICAgICBsaW5lTm8rKztcbiAgICB9KTtcbiAgICBmb3IgKHZhciBpID0gbmV3QnJlYWtzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKVxuICAgICAgcmVwbGFjZVJhbmdlKGNtLmRvYywgdmFsLCBuZXdCcmVha3NbaV0sIFBvcyhuZXdCcmVha3NbaV0ubGluZSwgbmV3QnJlYWtzW2ldLmNoICsgdmFsLmxlbmd0aCkpXG4gIH0pO1xuICBvcHRpb24oXCJzcGVjaWFsQ2hhcnNcIiwgL1tcXHRcXHUwMDAwLVxcdTAwMTl
vendor: 18,294 bytes, line 23459
23459cXHUwMGFkXFx1MjAwYi1cXHUyMDBmXFx1MjAyOFxcdTIwMjlcXHVmZWZmXS9nLCBmdW5jdGlvbihjbSwgdmFsLCBvbGQpIHtcbiAgICBjbS5zdGF0ZS5zcGVjaWFsQ2hhcnMgPSBuZXcgUmVnRXhwKHZhbC5zb3VyY2UgKyAodmFsLnRlc3QoXCJcXHRcIikgPyBcIlwiIDogXCJ8XFx0XCIpLCBcImdcIik7XG4gICAgaWYgKG9sZCAhPSBDb2RlTWlycm9yLkluaXQpIGNtLnJlZnJlc2goKTtcbiAgfSk7XG4gIG9wdGlvbihcInNwZWNpYWxDaGFyUGxhY2Vob2xkZXJcIiwgZGVmYXVsdFNwZWNpYWxDaGFyUGxhY2Vob2xkZXIsIGZ1bmN0aW9uKGNtKSB7Y20ucmVmcmVzaCgpO30sIHRydWUpO1xuICBvcHRpb24oXCJlbGVjdHJpY0NoYXJzXCIsIHRydWUpO1xuICBvcHRpb24oXCJpbnB1dFN0eWxlXCIsIG1vYmlsZSA/IFwiY29udGVudGVkaXRhYmxlXCIgOiBcInRleHRhcmVhXCIsIGZ1bmN0aW9uKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcImlucHV0U3R5bGUgY2FuIG5vdCAoeWV0KSBiZSBjaGFuZ2VkIGluIGEgcnVubmluZyBlZGl0b3JcIik7IC8vIEZJWE1FXG4gIH0sIHRydWUpO1xuICBvcHRpb24oXCJydGxNb3ZlVmlzdWFsbHlcIiwgIXdpbmRvd3MpO1xuICBvcHRpb24oXCJ3aG9sZUxpbmVVcGRhdGVCZWZvcmVcIiwgdHJ1ZSk7XG5cbiAgb3B0aW9uKFwidGhlbWVcIiwgXCJkZWZhdWx0XCIsIGZ1bmN0aW9uKGNtKSB7XG4gICAgdGhlbWVDaGFuZ2VkKGNtKTtcbiAgICBndXR0ZXJzQ2hhbmdlZChjbSk7XG4gIH0sIHRydWUpO1xuICBvcHRpb24oXCJrZXlNYXBcIiwgXCJkZWZhdWx0XCIsIGZ1bmN0aW9uKGNtLCB2YWwsIG9sZCkge1xuICAgIHZhciBuZXh0ID0gZ2V0S2V5TWFwKHZhbCk7XG4gICAgdmFyIHByZXYgPSBvbGQgIT0gQ29kZU1pcnJvci5Jbml0ICYmIGdldEtleU1hcChvbGQpO1xuICAgIGlmIChwcmV2ICYmIHByZXYuZGV0YWNoKSBwcmV2LmRldGFjaChjbSwgbmV4dCk7XG4gICAgaWYgKG5leHQuYXR0YWNoKSBuZXh0LmF0dGFjaChjbSwgcHJldiB8fCBudWxsKTtcbiAgfSk7XG4gIG9wdGlvbihcImV4dHJhS2V5c1wiLCBudWxsKTtcblxuICBvcHRpb24oXCJsaW5lV3JhcHBpbmdcIiwgZmFsc2UsIHdyYXBwaW5nQ2hhbmdlZCwgdHJ1ZSk7XG4gIG9wdGlvbihcImd1dHRlcnNcIiwgW10sIGZ1bmN0aW9uKGNtKSB7XG4gICAgc2V0R3V0dGVyc0ZvckxpbmVOdW1iZXJzKGNtLm9wdGlvbnMpO1xuICAgIGd1dHRlcnNDaGFuZ2VkKGNtKTtcbiAgfSwgdHJ1ZSk7XG4gIG9wdGlvbihcImZpeGVkR3V0dGVyXCIsIHRydWUsIGZ1bmN0aW9uKGNtLCB2YWwpIHtcbiAgICBjbS5kaXNwbGF5Lmd1dHRlcnMuc3R5bGUubGVmdCA9IHZhbCA/IGNvbXBlbnNhdGVGb3JIU2Nyb2xsKGNtLmRpc3BsYXkpICsgXCJweFwiIDogXCIwXCI7XG4gICAgY20ucmVmcmVzaCgpO1xuICB9LCB0cnVlKTtcbiAgb3B0aW9uKFwiY292ZXJHdXR0ZXJOZXh0VG9TY3JvbGxiYXJcIiwgZmFsc2UsIGZ1bmN0aW9uKGNtKSB7dXBkYXRlU2Nyb2xsYmFycyhjbSk7fSwgdHJ1ZSk7XG4gIG9wdGlvbihcInNjcm9sbGJhclN0eWxlXCIsIFwibmF0aXZlXCIsIGZ1bmN0aW9uKGNtKSB7XG4gICAgaW5pdFNjcm9sbGJhcnMoY20pO1xuICAgIHVwZGF0ZVNjcm9sbGJhcnMoY20pO1xuICAgIGNtLmRpc3BsYXkuc2Nyb2xsYmFycy5zZXRTY3JvbGxUb3AoY20uZG9jLnNjcm9sbFRvcCk7XG4gICAgY20uZGlzcGxheS5zY3JvbGxiYXJzLnNldFNjcm9sbExlZnQoY20uZG9jLnNjcm9sbExlZnQpO1xuICB9LCB0cnVlKTtcbiAgb3B0aW9uKFwibGluZU51bWJlcnNcIiwgZmFsc2UsIGZ1bmN0aW9uKGNtKSB7XG4gICAgc2V0R3V0dGVyc0ZvckxpbmVOdW1iZXJzKGNtLm9wdGlvbnMpO1xuICAgIGd1dHRlcnNDaGFuZ2VkKGNtKTtcbiAgfSwgdHJ1ZSk7XG4gIG9wdGlvbihcImZpcnN0TGluZU51bWJlclwiLCAxLCBndXR0ZXJzQ2hhbmdlZCwgdHJ1ZSk7XG4gIG9wdGlvbihcImxpbmVOdW1iZXJGb3JtYXR0ZXJcIiwgZnVuY3Rpb24oaW50ZWdlcikge3JldHVybiBpbnRlZ2VyO30sIGd1dHRlcnNDaGFuZ2VkLCB0cnVlKTtcbiAgb3B0aW9uKFwic2hvd0N1cnNvcldoZW5TZWxlY3RpbmdcIiwgZmFsc2UsIHVwZGF0ZVNlbGVjdGlvbiwgdHJ1ZSk7XG5cbiAgb3B0aW9uKFwicmVzZXRTZWxlY3Rpb25PbkNvbnRleHRNZW51XCIsIHRydWUpO1xuICBvcHRpb24oXCJsaW5lV2lzZUNvcHlDdXRcIiwgdHJ1ZSk7XG5cbiAgb3B0aW9uKFwicmVhZE9ubHlcIiwgZmFsc2UsIGZ1bmN0aW9uKGNtLCB2YWwpIHtcbiAgICBpZiAodmFsID09IFwibm9jdXJzb3JcIikge1xuICAgICAgb25CbHVyKGNtKTtcbiAgICAgIGNtLmRpc3BsYXkuaW5wdXQuYmx1cigpO1xuICAgICAgY20uZGlzcGxheS5kaXNhYmxlZCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNtLmRpc3BsYXkuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgY20uZGlzcGxheS5pbnB1dC5yZWFkT25seUNoYW5nZWQodmFsKVxuICB9KTtcbiAgb3B0aW9uKFwiZGlzYWJsZUlucHV0XCIsIGZhbHNlLCBmdW5jdGlvbihjbSwgdmFsKSB7aWYgKCF2YWwpIGNtLmRpc3BsYXkuaW5wdXQucmVzZXQoKTt9LCB0cnVlKTtcbiAgb3B0aW9uKFwiZHJhZ0Ryb3BcIiwgdHJ1ZSwgZHJhZ0Ryb3BDaGFuZ2VkKTtcbiAgb3B0aW9uKFwiYWxsb3dEcm9wRmlsZVR5cGVzXCIsIG51bGwpO1xuXG4gIG9wdGlvbihcImN1cnNvckJsaW5rUmF0ZVwiLCA1MzApO1xuICBvcHRpb24oXCJjdXJzb3JTY3JvbGxNYXJnaW5cIiwgMCk7XG4gIG9wdGlvbihcImN1cnNvckhlaWdodFwiLCAxLCB1cGRhdGVTZWxlY3Rpb24sIHRydWUpO1xuICBvcHRpb24oXCJzaW5nbGVDdXJzb3JIZWlnaHRQZXJMaW5lXCIsIHRydWUsIHVwZGF0ZVNlbGVjdGlvbiwgdHJ1ZSk7XG4gIG9wdGlvbihcIndvcmtUaW1lXCIsIDEwMCk7XG4gIG9wdGlvbihcIndvcmtEZWxheVwiLCAxMDApO1xuICBvcHRpb24oXCJmbGF0dGVuU3BhbnNcIiwgdHJ1ZSwgcmVzZXRNb2RlU3RhdGUsIHRydWUpO1xuICBvcHRpb24oXCJhZGRNb2RlQ2xhc3NcIiwgZmFsc2UsIHJlc2V0TW9kZVN0YXRlLCB0cnVlKTtcbiAgb3B0aW9uKFwicG9sbEludGVydmFsXCIsIDEwMCk7XG4gIG9wdGlvbihcInVuZG9EZXB0aFwiLCAyMDAsIGZ1bmN0aW9uKGNtLCB2YWwpe2NtLmRvYy5oaXN0b3J5LnVuZG9EZXB0aCA9IHZhbDt9KTtcbiAgb3B0aW9uKFwiaGlzdG9yeUV2ZW50RGVsYXlcIiwgMTI1MCk7XG4gIG9wdGlvbihcInZpZXdwb3J0TWFyZ2luXCIsIDEwLCBmdW5jdGlvbihjbSl7Y20ucmVmcmVzaCgpO30sIHRydWUpO1xuICBvcHRpb24oXCJtYXhIaWdobGlnaHRMZW5ndGhcIiwgMTAwMDAsIHJlc2V0TW9kZVN0YXRlLCB0cnVlKTtcbiAgb3B0aW9uKFwibW92ZUlucHV0V2l0aEN1cnNvclwiLCB0cnVlLCBmdW5jdGlvbihjbSwgdmFsKSB7XG4gICAgaWYgKCF2YWwpIGNtLmRpc3BsYXkuaW5wdXQucmVzZXRQb3NpdGlvbigpO1xuICB9KTtcblxuICBvcHRpb24oXCJ0YWJpbmRleFwiLCBudWxsLCBmdW5jdGlvbihjbSwgdmFsKSB7XG4gICAgY20uZGlzcGxheS5pbnB1dC5nZXRGaWVsZCgpLnRhYkluZGV4ID0gdmFsIHx8IFwiXCI7XG4gIH0pO1xuICBvcHRpb24oXCJhdXRvZm9jdXNcIiwgbnVsbCk7XG5cbiAgLy8gTU9ERSBERUZJTklUSU9OIEFORCBRVUVSWUlOR1xuXG4gIC8vIEtub3duIG1vZGVzLCBieSBuYW1lIGFuZCBieSBNSU1FXG4gIHZhciBtb2RlcyA9IENvZGVNaXJyb3IubW9kZXMgPSB7fSwgbWltZU1vZGVzID0gQ29kZU1pcnJvci5taW1lTW9kZXMgPSB7fTtcblxuICAvLyBFeHRyYSBhcmd1bWVudHMgYXJlIHN0b3JlZCBhcyB0aGUgbW9kZSdzIGRlcGVuZGVuY2llcywgd2hpY2ggaXNcbiAgLy8gdXNlZCBieSAobGVnYWN5KSBtZWNoYW5pc21zIGxpa2UgbG9hZG1vZGUuanMgdG8gYXV0b21hdGljYWxseVxuICAvLyBsb2FkIGEgbW9kZS4gKFByZWZlcnJlZCBtZWNoYW5pc20gaXMgdGhlIHJlcXVpcmUvZGVmaW5lIGNhbGxzLilcbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlID0gZnVuY3Rpb24obmFtZSwgbW9kZSkge1xuICAgIGlmICghQ29kZU1pcnJvci5kZWZhdWx0cy5tb2RlICYmIG5hbWUgIT0gXCJudWxsXCIpIENvZGVNaXJyb3IuZGVmYXVsdHMubW9kZSA9IG5hbWU7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgbW9kZS5kZXBlbmRlbmNpZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIG1vZGVzW25hbWVdID0gbW9kZTtcbiAgfTtcblxuICBDb2RlTWlycm9yLmRlZmluZU1JTUUgPSBmdW5jdGlvbihtaW1lLCBzcGVjKSB7XG4gICAgbWltZU1vZGVzW21pbWVdID0gc3BlYztcbiAgfTtcblxuICAvLyBHaXZlbiBhIE1JTUUgdHlwZSwgYSB7bmFtZSwgLi4ub3B0aW9uc30gY29uZmlnIG9iamVjdCwgb3IgYSBuYW1lXG4gIC8vIHN0cmluZywgcmV0dXJuIGEgbW9kZSBjb25maWcgb2JqZWN0LlxuICBDb2RlTWlycm9yLnJlc29sdmVNb2RlID0gZnVuY3Rpb24oc3BlYykge1xuICAgIGlmICh0eXBlb2Ygc3BlYyA9PSBcInN0cmluZ1wiICYmIG1pbWVNb2Rlcy5oYXNPd25Qcm9wZXJ0eShzcGVjKSkge1xuICAgICAgc3BlYyA9IG1pbWVNb2Rlc1tzcGVjXTtcbiAgICB9IGVsc2UgaWYgKHNwZWMgJiYgdHlwZW9mIHNwZWMubmFtZSA9PSBcInN0cmluZ1wiICYmIG1pbWVNb2Rlcy5oYXNPd25Qcm9wZXJ0eShzcGVjLm5hbWUpKSB7XG4gICAgICB2YXIgZm91bmQgPSBtaW1lTW9kZXNbc3BlYy5uYW1lXTtcbiAgICAgIGlmICh0eXBlb2YgZm91bmQgPT0gXCJzdHJpbmdcIikgZm91bmQgPSB7bmFtZTogZm91bmR9O1xuICAgICAgc3BlYyA9IGNyZWF0ZU9iaihmb3VuZCwgc3BlYyk7XG4gICAgICBzcGVjLm5hbWUgPSBmb3VuZC5uYW1lO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHNwZWMgPT0gXCJzdHJpbmdcIiAmJiAvXltcXHdcXC1dK1xcL1tcXHdcXC1dK1xcK3htbCQvLnRlc3Qoc3BlYykpIHtcbiAgICAgIHJldHVybiBDb2RlTWlycm9yLnJlc29sdmVNb2RlKFwiYXBwbGljYXRpb24veG1sXCIpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHNwZWMgPT0gXCJzdHJpbmdcIikgcmV0dXJuIHtuYW1lOiBzcGVjfTtcbiAgICBlbHNlIHJldHVybiBzcGVjIHx8IHtuYW1lOiBcIm51bGxcIn07XG4gIH07XG5cbiAgLy8gR2l2ZW4gYSBtb2RlIHNwZWMgKGFueXRoaW5nIHRoYXQgcmVzb2x2ZU1vZGUgYWNjZXB0cyksIGZpbmQgYW5kXG4gIC8vIGluaXRpYWxpemUgYW4gYWN0dWFsIG1vZGUgb2JqZWN0LlxuICBDb2RlTWlycm9yLmdldE1vZGUgPSBmdW5jdGlvbihvcHRpb25zLCBzcGVjKSB7XG4gICAgdmFyIHNwZWMgPSBDb2RlTWlycm9yLnJlc29sdmVNb2RlKHNwZWMpO1xuICAgIHZhciBtZmFjdG9yeSA9IG1vZGVzW3NwZWMubmFtZV07XG4gICAgaWYgKCFtZmFjdG9yeSkgcmV0dXJuIENvZGVNaXJyb3IuZ2V0TW9kZShvcHRpb25zLCBcInRleHQvcGxhaW5cIik7XG4gICAgdmFyIG1vZGVPYmogPSBtZmFjdG9yeShvcHRpb25zLCBzcGVjKTtcbiAgICBpZiAobW9kZUV4dGVuc2lvbnMuaGFzT3duUHJvcGVydHkoc3BlYy5uYW1lKSkge1xuICAgICAgdmFyIGV4dHMgPSBtb2RlRXh0ZW5zaW9uc1tzcGVjLm5hbWVdO1xuICAgICAgZm9yICh2YXIgcHJvcCBpbiBleHRzKSB7XG4gICAgICAgIGlmICghZXh0cy5oYXNPd25Qcm9wZXJ0eShwcm9wKSkgY29udGludWU7XG4gICAgICAgIGlmIChtb2RlT2JqLmhhc093blByb3BlcnR5KHByb3ApKSBtb2RlT2JqW1wiX1wiICsgcHJvcF0gPSBtb2RlT2JqW3Byb3BdO1xuICAgICAgICBtb2RlT2JqW3Byb3BdID0gZXh0c1twcm9wXTtcbiAgICAgIH1cbiAgICB9XG4gICAgbW9kZU9iai5uYW1lID0gc3BlYy5uYW1lO1xuICAgIGlmIChzcGVjLmhlbHBlclR5cGUpIG1vZGVPYmouaGVscGVyVHlwZSA9IHNwZWMuaGVscGVyVHlwZTtcbiAgICBpZiAoc3BlYy5tb2RlUHJvcHMpIGZvciAodmFyIHByb3AgaW4gc3BlYy5tb2RlUHJvcHMpXG4gICAgICBtb2RlT2JqW3Byb3BdID0gc3BlYy5tb2RlUHJvcHNbcHJvcF07XG5cbiAgICByZXR1cm4gbW9kZU9iajtcbiAgfTtcblxuICAvLyBNaW5pbWFsIGRlZmF1bHQgbW9kZS5cbiAgQ29kZU1pcnJvci5kZWZpbmVNb2RlKFwibnVsbFwiLCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge3Rva2VuOiBmdW5jdGlvbihzdHJlYW0pIHtzdHJlYW0uc2tpcFRvRW5kKCk7fX07XG4gIH0pO1xuICBDb2RlTWlycm9yLmRlZmluZU1JTUUoXCJ0ZXh0L3BsYWluXCIsIFwibnVsbFwiKTtcblxuICAvLyBUaGlzIGNhbiBiZSB1c2VkIHRvIGF0dGFjaCBwcm9wZXJ0aWVzIHRvIG1vZGUgb2JqZWN0cyBmcm9tXG4gIC8vIG91dHNpZGUgdGhlIGFjdHVhbCBtb2RlIGRlZmluaXRpb24uXG4gIHZhciBtb2RlRXh0ZW5zaW9ucyA9IENvZGVNaXJyb3IubW9kZUV4dGVuc2lvbnMgPSB7fTtcbiAgQ29kZU1pcnJvci5leHRlbmRNb2RlID0gZnVuY3Rpb24obW9kZSwgcHJvcGVydGllcykge1xuICAgIHZhciBleHRzID0gbW9kZUV4dGVuc2lvbnMuaGFzT3duUHJvcGVydHkobW9kZSkgPyBtb2RlRXh0ZW5zaW9uc1ttb2RlXSA6IChtb2RlRXh0ZW5zaW9uc1ttb2RlXSA9IHt9KTtcbiAgICBjb3B5T2JqKHByb3BlcnRpZXMsIGV4dHMpO1xuICB9O1xuXG4gIC8vIEVYVEVOU0lPTlNcblxuICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbiA9IGZ1bmN0aW9uKG5hbWUsIGZ1bmMpIHtcbiAgICBDb2RlTWlycm9yLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmM7XG4gIH07XG4gIENvZGVNaXJyb3IuZGVmaW5lRG9jRXh0ZW5zaW9uID0gZnVuY3Rpb24obmFtZSwgZnVuYykge1xuICAgIERvYy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jO1xuICB9O1xuICBDb2RlTWlycm9yLmRlZmluZU9wdGlvbiA9IG9wdGlvbjtcblxuICB2YXIgaW5pdEhvb2tzID0gW107XG4gIENvZGVNaXJyb3IuZGVmaW5lSW5pdEhvb2sgPSBmdW5jdGlvbihmKSB7aW5pdEhvb2tzLnB1c2goZik7fTtcblxuICB2YXIgaGVscGVycyA9IENvZGVNaXJyb3IuaGVscGVycyA9IHt9O1xuICBDb2RlTWlycm9yLnJlZ2lzdGVySGVscGVyID0gZnVuY3Rpb24odHlwZSwgbmFtZSwgdmFsdWUpIHtcbiAgICBpZiAoIWhlbHBlcnMuaGFzT3duUHJvcGVydHkodHlwZSkpIGhlbHBlcnNbdHlwZV0gPSBDb2RlTWlycm9yW3R5cGVdID0ge19nbG9iYWw6IFtdfTtcbiAgICBoZWxwZXJzW3R5cGVdW25hbWVdID0gdmFsdWU7XG4gIH07XG4gIENvZGVNaXJyb3IucmVnaXN0ZXJHbG9iYWxIZWxwZXIgPSBmdW5jdGlvbih0eXBlLCBuYW1lLCBwcmVkaWNhdGUsIHZhbHVlKSB7XG4gICAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcih0eXBlLCBuYW1lLCB2YWx1ZSk7XG4gICAgaGVscGVyc1t0eXBlXS5fZ2xvYmFsLnB1c2goe3ByZWQ6IHByZWRpY2F0ZSwgdmFsOiB2YWx1ZX0pO1xuICB9O1xuXG4gIC8vIE1PREUgU1RBVEUgSEFORExJTkdcblxuICAvLyBVdGlsaXR5IGZ1bmN0aW9ucyBmb3Igd29ya2luZyB3aXRoIHN0YXRlLiBFeHBvcnRlZCBiZWNhdXNlIG5lc3RlZFxuICAvLyBtb2RlcyBuZWVkIHRvIGRvIHRoaXMgZm9yIHRoZWlyIGlubmVyIG1vZGVzLlxuXG4gIHZhciBjb3B5U3RhdGUgPSBDb2RlTWlycm9yLmNvcHlTdGF0ZSA9IGZ1bmN0aW9uKG1vZGUsIHN0YXRlKSB7XG4gICAgaWYgKHN0YXRlID09PSB0cnVlKSByZXR1cm4gc3RhdGU7XG4gICAgaWYgKG1vZGUuY29weVN0YXRlKSByZXR1cm4gbW9kZS5jb3B5U3RhdGUoc3RhdGUpO1xuICAgIHZhciBuc3RhdGUgPSB7fTtcbiAgICBmb3IgKHZhciBuIGluIHN0YXRlKSB7XG4gICAgICB2YXIgdmFsID0gc3RhdGVbbl07XG4gICAgICBpZiAodmFsIGluc3RhbmNlb2YgQXJyYXkpIHZhbCA9IHZhbC5jb25jYXQoW10pO1xuICAgICAgbnN0YXRlW25dID0gdmFsO1xuICAgIH1cbiAgICByZXR1cm4gbnN0YXRlO1xuICB9O1xuXG4gIHZhciBzdGFydFN0YXRlID0gQ29kZU1pcnJvci5zdGFydFN0YXRlID0gZnVuY3Rpb24obW9kZSwgYTEsIGEyKSB7XG4gICAgcmV0dXJuIG1vZGUuc3RhcnRTdGF0ZSA/IG1vZGUuc3RhcnRTdGF0ZShhMSwgYTIpIDogdHJ1ZTtcbiAgfTtcblxuICAvLyBHaXZlbiBhIG1vZGUgYW5kIGEgc3RhdGUgKGZvciB0aGF0IG1vZGUpLCBmaW5kIHRoZSBpbm5lciBtb2RlIGFuZFxuICAvLyBzdGF0ZSBhdCB0aGUgcG9zaXRpb24gdGhhdCB0aGUgc3RhdGUgcmVmZXJzIHRvLlxuICBDb2RlTWlycm9yLmlubmVyTW9kZSA9IGZ1bmN0aW9uKG1vZGUsIHN0YXRlKSB7XG4gICAgd2hpbGUgKG1vZGUuaW5uZXJNb2RlKSB7XG4gICAgICB2YXIgaW5mbyA9IG1vZGUuaW5uZXJNb2RlKHN0YXRlKTtcbiAgICAgIGlmICghaW5mbyB8fCBpbmZvLm1vZGUgPT0gbW9kZSkgYnJlYWs7XG4gICAgICBzdGF0ZSA9IGluZm8uc3RhdGU7XG4gICAgICBtb2RlID0gaW5mby5tb2RlO1xuICAgIH1cbiAgICByZXR1cm4gaW5mbyB8fCB7bW9kZTogbW9kZSwgc3RhdGU6IHN0YXRlfTtcbiAgfTtcblxuICAvLyBTVEFOREFSRCBDT01NQU5EU1xuXG4gIC8vIENvbW1hbmRzIGFyZSBwYXJhbWV0ZXItbGVzcyBhY3Rpb25zIHRoYXQgY2FuIGJlIHBlcmZvcm1lZCBvbiBhblxuICAvLyBlZGl0b3IsIG1vc3RseSB1c2VkIGZvciBrZXliaW5kaW5ncy5cbiAgdmFyIGNvbW1hbmRzID0gQ29kZU1pcnJvci5jb21tYW5kcyA9IHtcbiAgICBzZWxlY3RBbGw6IGZ1bmN0aW9uKGNtKSB7Y20uc2V0U2VsZWN0aW9uKFBvcyhjbS5maXJzdExpbmUoKSwgMCksIFBvcyhjbS5sYXN0TGluZSgpKSwgc2VsX2RvbnRTY3JvbGwpO30sXG4gICAgc2luZ2xlU2VsZWN0aW9uOiBmdW5jdGlvbihjbSkge1xuICAgICAgY20uc2V0U2VsZWN0aW9uKGNtLmdldEN1cnNvcihcImFuY2hvclwiKSwgY20uZ2V0Q3Vyc29yKFwiaGVhZFwiKSwgc2VsX2RvbnRTY3JvbGwpO1xuICAgIH0sXG4gICAga2lsbExpbmU6IGZ1bmN0aW9uKGNtKSB7XG4gICAgICBkZWxldGVOZWFyU2VsZWN0aW9uKGNtLCBmdW5jdGlvbihyYW5nZSkge1xuICAgICAgICBpZiAocmFuZ2UuZW1wdHkoKSkge1xuICAgICAgICAgIHZhciBsZW4gPSBnZXRMaW5lKGNtLmRvYywgcmFuZ2UuaGVhZC5saW5lKS50ZXh0Lmxlbmd0aDtcbiAgICAgICAgICBpZiAocmFuZ2UuaGVhZC5jaCA9PSBsZW4gJiYgcmFuZ2UuaGVhZC5saW5lIDwgY20ubGFzdExpbmUoKSlcbiAgICAgICAgICAgIHJldHVybiB7ZnJvbTogcmFuZ2UuaGVhZCwgdG86IFBvcyhyYW5nZS5oZWFkLmxpbmUgKyAxLCAwKX07XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmV0dXJuIHtmcm9tOiByYW5nZS5oZWFkLCB0bzogUG9zKHJhbmdlLmhlYWQubGluZSwgbGVuKX07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHtmcm9tOiByYW5nZS5mcm9tKCksIHRvOiByYW5nZS50bygpfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkZWxldGVMaW5lOiBmdW5jdGlvbihjbSkge1xuICAgICAgZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHtmcm9tOiBQb3MocmFuZ2UuZnJvbSgpLmxpbmUsIDApLFxuICAgICAgICAgICAgICAgIHRvOiBjbGlwUG9zKGNtLmRvYywgUG9zKHJhbmdlLnRvKCkubGluZSArIDEsIDApKX07XG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRlbExpbmVMZWZ0OiBmdW5jdGlvbihjbSkge1xuICAgICAgZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHtmcm9tOiBQb3MocmFuZ2UuZnJvbSgpLmxpbmUsIDApLCB0bzogcmFuZ2UuZnJvbSgpfTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGVsV3JhcHBlZExpbmVMZWZ0OiBmdW5jdGlvbihjbSkge1xuICAgICAgZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgdmFyIHRvcCA9IGNtLmNoYXJDb29yZHMocmFuZ2UuaGVhZCwgXCJkaXZcIikudG9wICsgNTtcbiAgICAgICAgdmFyIGxlZnRQb3MgPSBjbS5jb29yZHNDaGFyKHtsZWZ0OiAwLCB0b3A6IHRvcH0sIFwiZGl2XCIpO1xuICAgICAgICByZXR1cm4ge2Zyb206IGxlZnRQb3MsIHRvOiByYW5nZS5mcm9tKCl9O1xuICAgICAgfSk7XG4gICAgfSxcbiAgICBkZWxXcmFwcGVkTGluZVJpZ2h0OiBmdW5jdGlvbihjbSkge1xuICAgICAgZGVsZXRlTmVhclNlbGVjdGlvbihjbSwgZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgdmFyIHRvcCA9IGNtLmNoYXJDb29yZHMocmFuZ2UuaGVhZCwgXCJkaXZcIikudG9wICsgNTtcbiAgICAgICAgdmFyIHJpZ2h0UG9zID0gY20uY29vcmRzQ2hhcih7bGVmdDogY20uZGlzcGxheS5saW5lRGl2Lm9mZnNldFdpZHRoICsgMTAwLCB0b3A6IHRvcH0sIFwiZGl2XCIpO1xuICAgICAgICByZXR1cm4ge2Zyb206IHJhbmdlLmZyb20oKSwgdG86IHJpZ2h0UG9zIH07XG4gICAgICB9KTtcbiAgICB9LFxuICAgIHVuZG86IGZ1bmN0aW9uKGNtKSB7Y20udW5kbygpO30sXG4gICAgcmVkbzogZnVuY3Rpb24oY20pIHtjbS5yZWRvKCk7fSxcbiAgICB1bmRvU2VsZWN0aW9uOiBmdW5jdGlvbihjbSkge2NtLnVuZG9TZWxlY3Rpb24oKTt9LFxuICAgIHJlZG9TZWxlY3Rpb246IGZ1bmN0aW9uKGNtKSB7Y20ucmVkb1NlbGVjdGlvbigpO30sXG4gICAgZ29Eb2NTdGFydDogZnVuY3Rpb24oY20pIHtjbS5leHRlbmRTZWxlY3Rpb24oUG9zKGNtLmZpcnN0TGluZSgpLCAwKSk7fSxcbiAgICBnb0RvY0VuZDogZnVuY3Rpb24oY20pIHtjbS5leHRlbmRTZWxlY3Rpb24oUG9zKGNtLmxhc3RMaW5lKCkpKTt9LFxuICAgIGdvTGluZVN0YXJ0OiBmdW5jdGlvbihjbSkge1xuICAgICAgY20uZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uKHJhbmdlKSB7IHJldHVybiBsaW5lU3RhcnQoY20sIHJhbmdlLmhlYWQubGluZSk7IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge29yaWdpbjogXCIrbW92ZVwiLCBiaWFzOiAxfSk7XG4gICAgfSxcbiAgICBnb0xpbmVTdGFydFNtYXJ0OiBmdW5jdGlvbihjbSkge1xuICAgICAgY20uZXh0ZW5kU2VsZWN0aW9uc0J5KGZ1bmN0aW9uKHJhbmdlKSB7XG4gICAgICAgIHJldHVybiBsaW5lU3RhcnRTbWFydChjbSwgcmFuZ2UuaGVhZCk7XG4gICAgICB9LCB7b3JpZ2luOiBcIittb3ZlXCIsIGJpYXM6IDF9KTtcbiAgICB9LFxuICAgIGdvTGluZUVuZDogZnVuY3Rpb24oY20pIHtcbiAgICAgIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbihyYW5nZSkgeyByZXR1cm4gbGluZUVuZChjbSwgcmFuZ2UuaGVhZC5saW5lKTsgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7b3JpZ2luOiBcIittb3ZlXCIsIGJpYXM6IC0xfSk7XG4gICAgfSxcbiAgICBnb0xpbmVSaWdodDogZnVuY3Rpb24oY20pIHtcbiAgICAgIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbihyYW5nZSkge1xuICAgICAgICB2YXIgdG9wID0gY20uY2hhckNvb3JkcyhyYW5nZS5oZWFkLCBcImRpdlwiKS50b3AgKyA1O1xuICAgICAgICByZXR1cm4gY20uY29vcmRzQ2hhcih7bGVmdDogY20uZGlzcGxheS5saW5lRGl2Lm9mZnNldFdpZHRoICsgMTAwLCB0b3A6IHRvcH0sIFwiZGl2XCIpO1xuICAgICAgfSwgc2VsX21vdmUpO1xuICAgIH0sXG4gICAgZ29MaW5lTGVmdDogZnVuY3Rpb24oY20pIHtcbiAgICAgIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbihyYW5nZSkge1xuICAgICAgICB2YXIgdG9wID0gY20uY2hhckNvb3JkcyhyYW5nZS5oZWFkLCBcImRpdlwiKS50b3AgKyA1O1xuICAgICAgICByZXR1cm4gY20uY29vcmRzQ2hhcih7bGVmdDogMCwgdG9wOiB0b3B9LCBcImRpdlwiKTtcbiAgICAgIH0sIHNlbF9tb3ZlKTtcbiAgICB9LFxuICAgIGdvTGluZUxlZnRTbWFydDogZnVuY3Rpb24oY20pIHtcbiAgICAgIGNtLmV4dGVuZFNlbGVjdGlvbnNCeShmdW5jdGlvbihyYW5nZSkge1xuICAgICAgICB2YXIgdG9wID0gY20uY2hhckNvb3JkcyhyYW5nZS5oZWFkLCBcImRpdlwiKS50b3AgKyA1O1xuICAgICAgICB2YXIgcG9zID0gY20uY29vcmRzQ2hhcih7bGVmdDogMCwgdG9wOiB0b3B9LCBcImRpdlwiKTtcbiAgICAgICAgaWYgKHBvcy5jaCA8IGNtLmdldExpbmUocG9zLmxpbmUpLnNlYXJjaCgvXFxTLykpIHJldHVybiBsaW5lU3RhcnRTbWFydChjbSwgcmFuZ2UuaGVhZCk7XG4gICAgICAgIHJldHVybiBwb3M7XG4gICAgICB9LCBzZWxfbW92ZSk7XG4gICAgfSxcbiAgICBnb0xpbmVVcDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlVigtMSwgXCJsaW5lXCIpO30sXG4gICAgZ29MaW5lRG93bjogZnVuY3Rpb24oY20pIHtjbS5tb3ZlVigxLCBcImxpbmVcIik7fSxcbiAgICBnb1BhZ2VVcDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlVigtMSwgXCJwYWdlXCIpO30sXG4gICAgZ29QYWdlRG93bjogZnVuY3Rpb24oY20pIHtjbS5tb3ZlVigxLCBcInBhZ2VcIik7fSxcbiAgICBnb0NoYXJMZWZ0OiBmdW5jdGlvbihjbSkge2NtLm1vdmVIKC0xLCBcImNoYXJcIik7fSxcbiAgICBnb0NoYXJSaWdodDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlSCgxLCBcImNoYXJcIik7fSxcbiAgICBnb0NvbHVtbkxlZnQ6IGZ1bmN0aW9uKGNtKSB7Y20ubW92ZUgoLTEsIFwiY29sdW1uXCIpO30sXG4gICAgZ29Db2x1bW5SaWdodDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlSCgxLCBcImNvbHVtblwiKTt9LFxuICAgIGdvV29yZExlZnQ6IGZ1bmN0aW9uKGNtKSB7Y20ubW92ZUgoLTEsIFwid29yZFwiKTt9LFxuICAgIGdvR3JvdXBSaWdodDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlSCgxLCBcImdyb3VwXCIpO30sXG4gICAgZ29Hcm91cExlZnQ6IGZ1bmN0aW9uKGNtKSB7Y20ubW92ZUgoLTEsIFwiZ3JvdXBcIik7fSxcbiAgICBnb1dvcmRSaWdodDogZnVuY3Rpb24oY20pIHtjbS5tb3ZlSCgxLCBcIndvcmRcIik7fSxcbiAgICBkZWxDaGFyQmVmb3JlOiBmdW5jdGlvbihjbSkge2NtLmRlbGV0ZUgoLTEsIFwiY2hhclwiKTt9LFxuICAgIGRlbENoYXJBZnRlcjogZnVuY3Rpb24oY20pIHtjbS5kZWxldGVIKDEsIFwiY2hhclwiKTt9LFxuICAgIGRlbFdvcmRCZWZvcmU6IGZ1bmN0aW9uKGNtKSB7Y20uZGVsZXRlSCgtMSwgXCJ3b3JkXCIpO30sXG4gICAgZGVsV29yZEFmdGVyOiBmdW5jdGlvbihjbSkge2NtLmRlbGV0ZUgoMSwgXCJ3b3JkXCIpO30sXG4gICAgZGVsR3JvdXBCZWZvcmU6IGZ1bmN0aW9uKGNtKSB7Y20uZGVsZXRlSCgtMSwgXCJncm91cFwiKTt9LFxuICAgIGRlbEdyb3VwQWZ0ZXI6IGZ1bmN0aW9uKGNtKSB7Y20uZGVsZXRlSCgxLCBcImdyb3VwXCIpO30sXG4gICAgaW5kZW50QXV0bzogZnVuY3Rpb24oY20pIHtjbS5pbmRlbnRTZWxlY3Rpb24oXCJzbWFydFwiKTt9LFxuICAgIGluZGVudE1vcmU6IGZ1bmN0aW9uKGNtKSB7Y20uaW5kZW50U2VsZWN0aW9uKFwiYWRkXCIpO30sXG4gICAgaW5kZW50TGVzczogZnVuY3Rpb24oY20pIHtjbS5pbmRlbnRTZWxlY3Rpb24oXCJzdWJ0cmFjdFwiKTt9LFxuICAgIGluc2VydFRhYjogZnVuY3Rpb24oY20pIHtjbS5yZXBsYWNlU2VsZWN0aW9uKFwiXFx0XCIpO30sXG4gICAgaW5zZXJ0U29mdFRhYjogZnVuY3Rpb24oY20pIHtcbiAgICAgIHZhciBzcGFjZXMgPSBbXSwgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKSwgdGFiU2l6ZSA9IGNtLm9wdGlvbnMudGFiU2l6ZTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwb3MgPSByYW5nZXNbaV0uZnJvbSgpO1xuICAgICAgICB2YXIgY29sID0gY291bnRDb2x1bW4oY20uZ2V0TGluZShwb3MubGluZSksIHBvcy5jaCwgdGFiU2l6ZSk7XG4gICAgICAgIHNwYWNlcy5wdXNoK
23459G5ldyBBcnJheSh0YWJTaXplIC0gY29sICUgdGFiU2l6ZSArIDEpLmpvaW4oXCIgXCIpKTtcbiAgICAgIH1cbiAgICAgIGNtLnJlcGxhY2VTZWxlY3Rpb25zKHNwYWNlcyk7XG4gICAgfSxcbiAgICBkZWZhdWx0VGFiOiBmdW5jdGlvbihjbSkge1xuICAgICAgaWYgKGNtLnNvbWV0aGluZ1NlbGVjdGVkKCkpIGNtLmluZGVudFNlbGVjdGlvbihcImFkZFwiKTtcbiAgICAgIGVsc2UgY20uZXhlY0NvbW1hbmQoXCJpbnNlcnRUYWJcIik7XG4gICAgfSxcbiAgICB0cmFuc3Bvc2VDaGFyczogZnVuY3Rpb24oY20pIHtcbiAgICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmFuZ2VzID0gY20ubGlzdFNlbGVjdGlvbnMoKSwgbmV3U2VsID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGN1ciA9IHJhbmdlc1tpXS5oZWFkLCBsaW5lID0gZ2V0TGluZShjbS5kb2MsIGN1ci5saW5lKS50ZXh0O1xuICAgICAgICAgIGlmIChsaW5lKSB7XG4gICAgICAgICAgICBpZiAoY3VyLmNoID09IGxpbmUubGVuZ3RoKSBjdXIgPSBuZXcgUG9zKGN1ci5saW5lLCBjdXIuY2ggLSAxKTtcbiAgICAgICAgICAgIGlmIChjdXIuY2ggPiAwKSB7XG4gICAgICAgICAgICAgIGN1ciA9IG5ldyBQb3MoY3VyLmxpbmUsIGN1ci5jaCArIDEpO1xuICAgICAgICAgICAgICBjbS5yZXBsYWNlUmFuZ2UobGluZS5jaGFyQXQoY3VyLmNoIC0gMSkgKyBsaW5lLmNoYXJBdChjdXIuY2ggLSAyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcyhjdXIubGluZSwgY3VyLmNoIC0gMiksIGN1ciwgXCIrdHJhbnNwb3NlXCIpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjdXIubGluZSA+IGNtLmRvYy5maXJzdCkge1xuICAgICAgICAgICAgICB2Y
23459XIgcHJldiA9IGdldExpbmUoY20uZG9jLCBjdXIubGluZSAtIDEpLnRleHQ7XG4gICAgICAgICAgICAgIGlmIChwcmV2KVxuICAgICAgICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShsaW5lLmNoYXJBdCgwKSArIGNtLmRvYy5saW5lU2VwYXJhdG9yKCkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2LmNoYXJBdChwcmV2Lmxlbmd0aCAtIDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQb3MoY3VyLmxpbmUgLSAxLCBwcmV2Lmxlbmd0aCAtIDEpLCBQb3MoY3VyLmxpbmUsIDEpLCBcIit0cmFuc3Bvc2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIG5ld1NlbC5wdXNoKG5ldyBSYW5nZShjdXIsIGN1cikpO1xuICAgICAgICB9XG4gICAgICAgIGNtLnNldFNlbGVjdGlvbnMobmV3U2VsKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgbmV3bGluZUFuZEluZGVudDogZnVuY3Rpb24oY20pIHtcbiAgICAgIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgbGVuID0gY20ubGlzdFNlbGVjdGlvbnMoKS5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICB2YXIgcmFuZ2UgPSBjbS5saXN0U2VsZWN0aW9ucygpW2ldO1xuICAgICAgICAgIGNtLnJlcGxhY2VSYW5nZShjbS5kb2MubGluZVNlcGFyYXRvcigpLCByYW5nZS5hbmNob3IsIHJhbmdlLmhlYWQsIFwiK2lucHV0XCIpO1xuICAgICAgICAgIGNtLmluZGVudExpbmUocmFuZ2UuZnJvbSgpLmxpbmUgKyAxLCBudWxsLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbnN1cmVDdXJzb3JWaXNpYmxlKGNtKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgdG9nZ2xlT3ZlcndyaXRlOiBmdW5jdGlvbihjbSkge2NtLnRvZ2dsZU92ZXJ3cml0ZSgpO31cbiAgfTtcblxuXG4gIC8vIFNUQU5EQVJEIEtFWU1BUFNcblxuICB2YXIga2V5TWFwID0gQ29kZU1pcnJvci5rZXlNYXAgPSB7fTtcblxuICBrZXlNYXAuYmFzaWMgPSB7XG4gICAgXCJMZWZ0XCI6IFwiZ29DaGFyTGVmdFwiLCBcIlJpZ2h0XCI6IFwiZ29DaGFyUmlnaHRcIiwgXCJVcFwiOiBcImdvTGluZVVwXCIsIFwiRG93blwiOiBcImdvTGluZURvd25cIixcbiAgICBcIkVuZFwiOiBcImdvTGluZUVuZFwiLCBcIkhvbWVcIjogXCJnb0xpbmVTdGFydFNtYXJ0XCIsIFwiUGFnZVVwXCI6IFwiZ29QYWdlVXBcIiwgXCJQYWdlRG93blwiOiBcImdvUGFnZURvd25cIixcbiAgICBcIkRlbGV0ZVwiOiBcImRlbENoYXJBZnRlclwiLCBcIkJhY2tzcGFjZVwiOiBcImRlbENoYXJCZWZvcmVcIiwgXCJTaGlmdC1CYWNrc3BhY2VcIjogXCJkZWxDaGFyQmVmb3JlXCIsXG4gICAgXCJUYWJcIjogXCJkZWZhdWx0VGFiXCIsIFwiU2hpZnQtVGFiXCI6IFwiaW5kZW50QXV0b1wiLFxuICAgIFwiRW50ZXJcIjogXCJuZXdsaW5lQW5kSW5kZW50XCIsIFwiSW5zZXJ0XCI6IFwidG9nZ2xlT3ZlcndyaXRlXCIsXG4gICAgXCJFc2NcIjogXCJzaW5nbGVTZWxlY3Rpb25cIlxuICB9O1xuICAvLyBOb3RlIHRoYXQgdGhlIHNhdmUgYW5kIGZpbmQtcmVsYXRlZCBjb21tYW5kcyBhcmVuJ3QgZGVmaW5lZCBieVxuICAvLyBkZWZhdWx0LiBVc2VyIGNvZGUgb3IgYWRkb25zIGNhbiBkZWZpbmUgdGhlbS4gVW5rbm93biBjb21tYW5kc1xuICAvLyBhcmUgc2ltcGx5IGlnbm9yZWQuXG4gIGtleU1hcC5wY0RlZmF1bHQgPSB7XG4gICAgXCJDdHJsLUFcIjogXCJzZWxlY3RBbGxcIiwgXCJDdHJsLURcIjogXCJkZWxldGVMaW5lXCIsIFwiQ3RybC1aXCI6IFwidW5kb1wiLCBcIlNoaWZ0LUN0cmwtWlwiOiBcInJlZG9cIiwgXCJDdHJsLVlcIjogXCJyZWRvXCIsXG4gICAgXCJDdHJsLUhvbWVcIjogXCJnb0RvY1N0YXJ0XCIsIFwiQ3RybC1FbmRcIjogXCJnb0RvY0VuZFwiLCBcIkN0cmwtVXBcIjogXCJnb0xpbmVVcFwiLCBcIkN0cmwtRG93blwiOiBcImdvTGluZURvd25cIixcbiAgICBcIkN0cmwtTGVmdFwiOiBcImdvR3JvdXBMZWZ0XCIsIFwiQ3RybC1SaWdodFwiOiBcImdvR3JvdXBSaWdodFwiLCBcIkFsdC1MZWZ0XCI6IFwiZ29MaW5lU3RhcnRcIiwgXCJBbHQtUmlnaHRcIjogXCJnb0xpbmVFbmRcIixcbiAgICBcIkN0cmwtQmFja3NwYWNlXCI6IFwiZGVsR3JvdXBCZWZvcmVcIiwgXCJDdHJsLURlbGV0ZVwiOiBcImRlbEdyb3VwQWZ0ZXJcIiwgXCJDdHJsLVNcIjogXCJzYXZlXCIsIFwiQ3RybC1GXCI6IFwiZmluZFwiLFxuICAgIFwiQ3RybC1HXCI6IFwiZmluZE5leHRcIiwgXCJTaGlmdC1DdHJsLUdcIjogXCJmaW5kUHJldlwiLCBcIlNoaWZ0LUN0cmwtRlwiOiBcInJlcGxhY2VcIiwgXCJTaGlmdC1DdHJsLVJcIjogXCJyZXBsYWNlQWxsXCIsXG4gICAgXCJDdHJsLVtcIjogXCJpbmRlbnRMZXNzXCIsIFwiQ3RybC1dXCI6IFwiaW5kZW50TW9yZVwiLFxuICAgIFwiQ3RybC1VXCI6IFwidW5kb1NlbGVjdGlvblwiLCBcIlNoaWZ0LUN0cmwtVVwiOiBcInJlZG9TZWxlY3Rpb25cIiwgXCJBbHQtVVwiOiBcInJlZG9TZWxlY3Rpb25cIixcbiAgICBmYWxsdGhyb3VnaDogXCJiYXNpY1wiXG4gIH07XG4gIC8vIFZlcnkgYmFzaWMgcmVhZGxpbmUvZW1hY3Mtc3R5bGUgYmluZGluZ3MsIHdoaWNoIGFyZSBzdGFuZGFyZCBvbiBNYWMuXG4gIGtleU1hcC5lbWFjc3kgPSB7XG4gICAgXCJDdHJsLUZcIjogXCJnb0NoYXJSaWdodFwiLCBcIkN0cmwtQlwiOiBcImdvQ2hhckxlZnRcIiwgXCJDdHJsLVBcIjogXCJnb0xpbmVVcFwiLCBcIkN0cmwtTlwiOiBcImdvTGluZURvd25cIixcbiAgICBcIkFsdC1GXCI6IFwiZ29Xb3JkUmlnaHRcIiwgXCJBbHQtQlwiOiBcImdvV29yZExlZnRcIiwgXCJDdHJsLUFcIjogXCJnb0xpbmVTdGFydFwiLCBcIkN0cmwtRVwiOiBcImdvTGluZUVuZFwiLFxuICAgIFwiQ3RybC1WXCI6IFwiZ29QYWdlRG93blwiLCBcIlNoaWZ0LUN0cmwtVlwiOiBcImdvUGFnZVVwXCIsIFwiQ3RybC1EXCI6IFwiZGVsQ2hhckFmdGVyXCIsIFwiQ3RybC1IXCI6IFwiZGVsQ2hhckJlZm9yZVwiLFxuICAgIFwiQWx0LURcIjogXCJkZWxXb3JkQWZ0ZXJcIiwgXCJBbHQtQmFja3NwYWNlXCI6IFwiZGVsV29yZEJlZm9yZVwiLCBcIkN0cmwtS1wiOiBcImtpbGxMaW5lXCIsIFwiQ3RybC1UXCI6IFwidHJhbnNwb3NlQ2hhcnNcIlxuICB9O1xuICBrZXlNYXAubWFjRGVmYXVsdCA9IHtcbiAgICBcIkNtZC1BXCI6IFwic2VsZWN0QWxsXCIsIFwiQ21kLURcIjogXCJkZWxldGVMaW5lXCIsIFwiQ21kLVpcIjogXCJ1bmRvXCIsIFwiU2hpZnQtQ21kLVpcIjogXCJyZWRvXCIsIFwiQ21kLVlcIjogXCJyZWRvXCIsXG4gICAgXCJDbWQtSG9tZVwiOiBcImdvRG9jU3RhcnRcIiwgXCJDbWQtVXBcIjogXCJnb0RvY1N0YXJ0XCIsIFwiQ21kLUVuZFwiOiBcImdvRG9jRW5kXCIsIFwiQ21kLURvd25cIjogXCJnb0RvY0VuZFwiLCBcIkFsdC1MZWZ0XCI6IFwiZ29Hcm91cExlZnRcIixcbiAgICBcIkFsdC1SaWdodFwiOiBcImdvR3JvdXBSaWdodFwiLCBcIkNtZC1MZWZ0XCI6IFwiZ29MaW5lTGVmdFwiLCBcIkNtZC1SaWdodFwiOiBcImdvTGluZVJpZ2h0XCIsIFwiQWx0LUJhY2tzcGFjZVwiOiBcImRlbEdyb3VwQmVmb3JlXCIsXG4gICAgXCJDdHJsLUFsdC1CYWNrc3BhY2VcIjogXCJkZWxHcm91cEFmdGVyXCIsIFwiQWx0LURlbGV0ZVwiOiBcImRlbEdyb3VwQWZ0ZXJcIiwgXCJDbWQtU1wiOiBcInNhdmVcIiwgXCJDbWQtRlwiOiBcImZpbmRcIixcbiAgICBcIkNtZC1HXCI6IFwiZmluZE5leHRcIiwgXCJTaGlmdC1DbWQtR1wiOiBcImZpbmRQcmV2XCIsIFwiQ21kLUFsdC1GXCI6IFwicmVwbGFjZVwiLCBcIlNoaWZ0LUNtZC1BbHQtRlwiOiBcInJlcGxhY2VBbGxcIixcbiAgICBcIkNtZC1bXCI6IFwiaW5kZW50TGVzc1wiLCBcIkNtZC1dXCI6IFwiaW5kZW50TW9yZVwiLCBcIkNtZC1CYWNrc3BhY2VcIjogXCJkZWxXcmFwcGVkTGluZUxlZnRcIiwgXCJDbWQtRGVsZXRlXCI6IFwiZGVsV3JhcHBlZExpbmVSaWdodFwiLFxuICAgIFwiQ21kLVVcIjogXCJ1bmRvU2VsZWN0aW9uXCIsIFwiU2hpZnQtQ21kLVVcIjogXCJyZWRvU2VsZWN0aW9uXCIsIFwiQ3RybC1VcFwiOiBcImdvRG9jU3RhcnRcIiwgXCJDdHJsLURvd25cIjogXCJnb0RvY0VuZFwiLFxuICAgIGZhbGx0aHJvdWdoOiBbXCJiYXNpY1wiLCBcImVtYWNzeVwiXVxuICB9O1xuICBrZXlNYXBbXCJkZWZhdWx0XCJdID0gbWFjID8ga2V5TWFwLm1hY0RlZmF1bHQgOiBrZXlNYXAucGNEZWZhdWx0O
234591xuXG4gIC8vIEtFWU1BUCBESVNQQVRDSFxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZUtleU5hbWUobmFtZSkge1xuICAgIHZhciBwYXJ0cyA9IG5hbWUuc3BsaXQoLy0oPyEkKS8pLCBuYW1lID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV07XG4gICAgdmFyIGFsdCwgY3RybCwgc2hpZnQsIGNtZDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgdmFyIG1vZCA9IHBhcnRzW2ldO1xuICAgICAgaWYgKC9eKGNtZHxtZXRhfG0pJC9pLnRlc3QobW9kKSkgY21kID0gdHJ1ZTtcbiAgICAgIGVsc2UgaWYgKC9eYShsdCk/JC9pLnRlc3QobW9kKSkgYWx0ID0gdHJ1ZTtcbiAgICAgIGVsc2UgaWYgKC9eKGN8Y3RybHxjb250cm9sKSQvaS50ZXN0KG1vZCkpIGN0cmwgPSB0cnVlO1xuICAgICAgZWxzZSBpZiAoL15zKGhpZnQpJC9pLnRlc3QobW9kKSkgc2hpZnQgPSB0cnVlO1xuICAgICAgZWxzZSB0aHJvdyBuZXcgRXJyb3IoXCJVbnJlY29nbml6ZWQgbW9kaWZpZXIgbmFtZTogXCIgKyBtb2QpO1xuICAgIH1cbiAgICBpZiAoYWx0KSBuYW1lID0gXCJBbHQtXCIgKyBuYW1lO1xuICAgIGlmIChjdHJsKSBuYW1lID0gXCJDdHJsLVwiICsgbmFtZTtcbiAgICBpZiAoY21kKSBuYW1lID0gXCJDbWQtXCIgKyBuYW1lO1xuICAgIGlmIChzaGlmdCkgbmFtZSA9IFwiU2hpZnQtXCIgKyBuYW1lO1xuICAgIHJldHVybiBuYW1lO1xuICB9XG5cbiAgLy8gVGhpcyBpcyBhIGtsdWRnZSB0byBrZWVwIGtleW1hcHMgbW9zdGx5IHdvcmtpbmcgYXMgcmF3IG9iamVjdHNcbiAgLy8gKGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5KSB3aGlsZSBhdCB0aGUgc2FtZSB0aW1lIHN1cHBvcnQgZmVhdHVyZXNcbiAgLy8gbGlrZSBub3JtYWxpemF0aW9uIGFuZCBtdWx0aS1zdHJva2Uga2V5IGJpbmRpbmdzLiBJdCBjb21waWxlcyBhXG4gIC8vIG5ldyBub3JtYWxpemVkIGtleW1hcCwgYW5kIHRoZW4gdXBkYXRlcyB0aGUgb2xkIG9iamVjdCB0byByZWZsZWN0XG4gIC8vIHRoaXMuXG4gIENvZGVNaXJyb3Iubm9ybWFsaXplS2V5TWFwID0gZnVuY3Rpb24oa2V5bWFwKSB7XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICBmb3IgKHZhciBrZXluYW1lIGluIGtleW1hcCkgaWYgKGtleW1hcC5oYXNPd25Qcm9wZXJ0eShrZXluYW1lKSkge1xuICAgICAgdmFyIHZhbHVlID0ga2V5bWFwW2tleW5hbWVdO1xuICAgICAgaWYgKC9eKG5hbWV8ZmFsbHRocm91Z2h8KGRlfGF0KXRhY2gpJC8udGVzdChrZXluYW1lKSkgY29udGludWU7XG4gICAgICBpZiAodmFsdWUgPT0gXCIuLi5cIikgeyBkZWxldGUga2V5bWFwW2tleW5hbWVdOyBjb250aW51ZTsgfVxuXG4gICAgICB2Y
23459XIga2V5cyA9IG1hcChrZXluYW1lLnNwbGl0KFwiIFwiKSwgbm9ybWFsaXplS2V5TmFtZSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbCwgbmFtZTtcbiAgICAgICAgaWYgKGkgPT0ga2V5cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgbmFtZSA9IGtleXMuam9pbihcIiBcIik7XG4gICAgICAgICAgdmFsID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZSA9IGtleXMuc2xpY2UoMCwgaSArIDEpLmpvaW4oXCIgXCIpO1xuICAgICAgICAgIHZhbCA9IFwiLi4uXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXYgPSBjb3B5W25hbWVdO1xuICAgICAgICBpZiAoIXByZXYpIGNvcHlbbmFtZV0gPSB2YWw7XG4gICAgICAgIGVsc2UgaWYgKHByZXYgIT0gdmFsKSB0aHJvdyBuZXcgRXJyb3IoXCJJbmNvbnNpc3RlbnQgYmluZGluZ3MgZm9yIFwiICsgbmFtZSk7XG4gICAgICB9XG4gICAgICBkZWxldGUga2V5bWFwW2tleW5hbWVdO1xuICAgIH1cbiAgICBmb3IgKHZhciBwcm9wIGluIGNvcHkpIGtleW1hcFtwcm9wXSA9IGNvcHlbcHJvcF07XG4gICAgcmV0dXJuIGtleW1hcDtcbiAgfTtcblxuICB2YXIgbG9va3VwS2V5ID0gQ29kZU1pcnJvci5sb29rdXBLZXkgPSBmdW5jdGlvbihrZXksIG1hcCwgaGFuZGxlLCBjb250ZXh0KSB7XG4gICAgbWFwID0gZ2V0S2V5TWFwKG1hcCk7XG4gICAgdmFyIGZvdW5kID0gbWFwLmNhbGwgPyBtYXAuY2FsbChrZXksIGNvbnRleHQpIDogbWFwW2tleV07XG4gICAgaWYgKGZvdW5kID09PSBmYWxzZSkgcmV0dXJuIFwibm90aGluZ1wiO1xuICAgIGlmIChmb3VuZCA9PT0gXCIuLi5cIikgcmV0dXJuIFwibXVsdGlcIjtcbiAgICBpZiAoZm91bmQgIT0gbnVsbCAmJiBoYW5kbGUoZm91bmQpKSByZXR1cm4gXCJoYW5kbGVkXCI7XG5cbiAgICBpZiAobWFwLmZhbGx0aHJvdWdoKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1hcC5mYWxsdGhyb3VnaCkgIT0gXCJbb2JqZWN0IEFycmF5XVwiKVxuICAgICAgICByZXR1cm4gbG9va3VwS2V5KGtleSwgbWFwLmZhbGx0aHJvdWdoLCBoYW5kbGUsIGNvbnRleHQpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXAuZmFsbHRocm91Z2gubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGxvb2t1cEtleShrZXksIG1hcC5mYWxsdGhyb3VnaFtpXSwgaGFuZGxlLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKHJlc3VsdCkgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLy8gTW9kaWZpZXIga2V5IHByZXNzZXMgZG9uJ3QgY291bnQgYXMgJ3JlYWwnIGtleSBwcmVzc2VzIGZvciB0aGVcbiAgLy8gcHVycG9zZSBvZiBrZXltYXAgZmFsbHRocm91Z2guXG4gIHZhciBpc01vZGlmaWVyS2V5ID0gQ29kZU1pcnJvci5pc01vZGlmaWVyS2V5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YXIgbmFtZSA9IHR5cGVvZiB2YWx1ZSA9PSBcInN0cmluZ1wiID8gdmFsdWUgOiBrZXlOYW1lc1t2YWx1ZS5rZXlDb2RlXTtcbiAgICByZXR1cm4gbmFtZSA9PSBcIkN0cmxcIiB8fCBuYW1lID09IFwiQWx0XCIgfHwgbmFtZSA9PSBcIlNoaWZ0XCIgfHwgbmFtZSA9PSBcIk1vZFwiO1xuICB9O1xuXG4gIC8vIExvb2sgdXAgdGhlIG5hbWUgb2YgYSBrZXkgYXMgaW5kaWNhdGVkIGJ5IGFuIGV2ZW50IG9iamVjdC5cbiAgdmFyIGtleU5hbWUgPSBDb2RlTWlycm9yLmtleU5hbWUgPSBmdW5jdGlvbihldmVudCwgbm9TaGlmdCkge1xuICAgIGlmIChwcmVzdG8gJiYgZXZlbnQua2V5Q29kZSA9PSAzNCAmJiBldmVudFtcImNoYXJcIl0pIHJldHVybiBmYWxzZTtcbiAgICB2YXIgYmFzZSA9IGtleU5hbWVzW2V2ZW50LmtleUNvZGVdLCBuYW1lID0gYmFzZTtcbiAgICBpZiAobmFtZSA9PSBudWxsIHx8IGV2ZW50LmFsdEdyYXBoS2V5KSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKGV2ZW50LmFsdEtleSAmJiBiYXNlICE9IFwiQWx0XCIpIG5hbWUgPSBcIkFsdC1cIiArIG5hbWU7XG4gICAgaWYgKChmbGlwQ3RybENtZCA/IGV2ZW50Lm1ldGFLZXkgOiBldmVudC5jdHJsS2V5KSAmJiBiYXNlICE9IFwiQ3RybFwiKSBuYW1lID0gXCJDdHJsLVwiICsgbmFtZTtcbiAgICBpZiAoKGZsaXBDdHJsQ21kID8gZXZlbnQuY3RybEtleSA6IGV2ZW50Lm1ldGFLZXkpICYmIGJhc2UgIT0gXCJDbWRcIikgbmFtZSA9IFwiQ21kLVwiICsgbmFtZTtcbiAgICBpZiAoIW5vU2hpZnQgJiYgZXZlbnQuc2hpZnRLZXkgJiYgYmFzZSAhPSBcIlNoaWZ0XCIpIG5hbWUgPSBcIlNoaWZ0LVwiICsgbmFtZTtcbiAgICByZXR1cm4gbmFtZTtcbiAgfTtcblxuICBmdW5jdGlvbiBnZXRLZXlNYXAodmFsKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWwgPT0gXCJzdHJpbmdcIiA/IGtleU1hcFt2YWxdIDogdmFsO1xuICB9XG5cbiAgLy8gRlJPTVRFWFRBUkVBXG5cbiAgQ29kZU1pcnJvci5mcm9tVGV4dEFyZWEgPSBmdW5jdGlvbih0ZXh0YXJlYSwgb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zID8gY29weU9iaihvcHRpb25zKSA6IHt9O1xuICAgIG9wdGlvbnMudmFsdWUgPSB0ZXh0YXJlYS52YWx1ZTtcbiAgICBpZiAoIW9wdGlvbnMudGFiaW5kZXggJiYgdGV4dGFyZWEudGFiSW5kZXgpXG4gICAgICBvcHRpb25zLnRhYmluZGV4ID0gdGV4dGFyZWEudGFiSW5kZXg7XG4gICAgaWYgKCFvcHRpb25zLnBsYWNlaG9sZGVyICYmIHRleHRhcmVhLnBsYWNlaG9sZGVyKVxuICAgICAgb3B0aW9ucy5wbGFjZWhvbGRlciA9IHRleHRhcmVhLnBsYWNlaG9sZGVyO1xuICAgIC8vIFNldCBhdXRvZm9jdXMgdG8gdHJ1ZSBpZiB0aGlzIHRleHRhcmVhIGlzIGZvY3VzZWQsIG9yIGlmIGl0IGhhc1xuICAgIC8vIGF1dG9mb2N1cyBhbmQgbm8gb3RoZXIgZWxlbWVudCBpcyBmb2N1c2VkLlxuICAgIGlmIChvcHRpb25zLmF1dG9mb2N1cyA9PSBudWxsKSB7XG4gICAgICB2Y
23459XIgaGFzRm9jdXMgPSBhY3RpdmVFbHQoKTtcbiAgICAgIG9wdGlvbnMuYXV0b2ZvY3VzID0gaGFzRm9jdXMgPT0gdGV4dGFyZWEgfHxcbiAgICAgICAgdGV4dGFyZWEuZ2V0QXR0cmlidXRlKFwiYXV0b2ZvY3VzXCIpICE9IG51bGwgJiYgaGFzRm9jdXMgPT0gZG9jdW1lbnQuYm9keTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzYXZlKCkge3RleHRhcmVhLnZhbHVlID0gY20uZ2V0VmFsdWUoKTt9XG4gICAgaWYgKHRleHRhcmVhLmZvcm0pIHtcbiAgICAgIG9uKHRleHRhcmVhLmZvcm0sIFwic3VibWl0XCIsIHNhdmUpO1xuICAgICAgLy8gRGVwbG9yYWJsZSBoYWNrIHRvIG1ha2UgdGhlIHN1Ym1pdCBtZXRob2QgZG8gdGhlIHJpZ2h0IHRoaW5nLlxuICAgICAgaWYgKCFvcHRpb25zLmxlYXZlU3VibWl0TWV0aG9kQWxvbmUpIHtcbiAgICAgICAgdmFyIGZvcm0gPSB0ZXh0YXJlYS5mb3JtLCByZWFsU3VibWl0ID0gZm9ybS5zdWJtaXQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdmFyIHdyYXBwZWRTdWJtaXQgPSBmb3JtLnN1Ym1pdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2F2ZSgpO1xuICAgICAgICAgICAgZm9ybS5zdWJtaXQgPSByZWFsU3VibWl0O1xuICAgICAgICAgICAgZm9ybS5zdWJtaXQoKTtcbiAgICAgICAgICAgIGZvcm0uc3VibWl0ID0gd3JhcHBlZFN1Ym1pdDtcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoKGUpIHt9XG4gICAgICB9XG4gICAgfVxuXG4gICAgb3B0aW9ucy5maW5pc2hJbml0ID0gZnVuY3Rpb24oY20pIHtcbiAgICAgIGNtLnNhdmUgPSBzYXZlO1xuICAgICAgY20uZ2V0VGV4dEFyZWEgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRleHRhcmVhOyB9O1xuICAgICAgY20udG9UZXh0QXJlYSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjbS50b1RleHRBcmVhID0gaXNOYU47IC8vIFByZXZlbnQgdGhpcyBmcm9tIGJlaW5nIHJhbiB0d2ljZVxuICAgICAgICBzYXZlKCk7XG4gICAgICAgIHRleHRhcmVhLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY20uZ2V0V3JhcHBlckVsZW1lbnQoKSk7XG4gICAgICAgIHRleHRhcmVhLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuICAgICAgICBpZiAodGV4dGFyZWEuZm9ybSkge1xuICAgICAgICAgIG9mZih0ZXh0YXJlYS5mb3JtLCBcInN1Ym1pdFwiLCBzYXZlKTtcbiAgICAgICAgICBpZiAodHlwZW9mIHRleHRhcmVhLmZvcm0uc3VibWl0ID09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgICAgIHRleHRhcmVhLmZvcm0uc3VibWl0ID0gcmVhbFN1Ym1pdDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9O1xuXG4gICAgdGV4dGFyZWEuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIHZhciBjbSA9IENvZGVNaXJyb3IoZnVuY3Rpb24obm9kZSkge1xuICAgICAgdGV4dGFyZWEucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgdGV4dGFyZWEubmV4dFNpYmxpbmcpO1xuICAgIH0sIG9wdGlvbnMpO1xuICAgIHJldHVybiBjbTtcbiAgfTtcblxuICAvLyBTVFJJTkcgU1RSRUFNXG5cbiAgLy8gRmVkIHRvIHRoZSBtb2RlIHBhcnNlcnMsIHByb3ZpZGVzIGhlbHBlciBmdW5jdGlvbnMgdG8gbWFrZVxuICAvLyBwYXJzZXJzIG1vcmUgc3VjY2luY3QuXG5cbiAgdmFyIFN0cmluZ1N0cmVhbSA9IENvZGVNaXJyb3IuU3RyaW5nU3RyZWFtID0gZnVuY3Rpb24oc3RyaW5nLCB0YWJTaXplKSB7XG4gICAgdGhpcy5wb3MgPSB0aGlzLnN0YXJ0ID0gMDtcbiAgICB0aGlzLnN0cmluZyA9IHN0cmluZztcbiAgICB0aGlzLnRhYlNpemUgPSB0YWJTaXplIHx8IDg7XG4gICAgdGhpcy5sYXN0Q29sdW1uUG9zID0gdGhpcy5sYXN0Q29sdW1uVmFsdWUgPSAwO1xuICAgIHRoaXMubGluZVN0YXJ0ID0gMDtcbiAgfTtcblxuICBTdHJpbmdTdHJlYW0ucHJvdG90eXBlID0ge1xuICAgIGVvbDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucG9zID49IHRoaXMuc3RyaW5nLmxlbmd0aDt9LFxuICAgIHNvbDogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMucG9zID09IHRoaXMubGluZVN0YXJ0O30sXG4gICAgcGVlazogZnVuY3Rpb24oKSB7cmV0dXJuIHRoaXMuc3RyaW5nLmNoYXJBdCh0aGlzLnBvcykgfHwgdW5kZWZpbmVkO30sXG4gICAgbmV4dDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5wb3MgPCB0aGlzLnN0cmluZy5sZW5ndGgpXG4gICAgICAgIHJldHVybiB0aGlzLnN0cmluZy5jaGFyQXQodGhpcy5wb3MrKyk7XG4gICAgfSxcbiAgICBlYXQ6IGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgICB2Y
23459XIgY2ggPSB0aGlzLnN0cmluZy5jaGFyQXQodGhpcy5wb3MpO1xuICAgICAgaWYgKHR5cGVvZiBtYXRjaCA9PSBcInN0cmluZ1wiKSB2YXIgb2sgPSBjaCA9PSBtYXRjaDtcbiAgICAgIGVsc2UgdmFyIG9rID0gY2ggJiYgKG1hdGNoLnRlc3QgPyBtYXRjaC50ZXN0KGNoKSA6IG1hdGNoKGNoKSk7XG4gICAgICBpZiAob2spIHsrK3RoaXMucG9zOyByZXR1cm4gY2g7fVxuICAgIH0sXG4gICAgZWF0V2hpbGU6IGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgICB2YXIgc3RhcnQgPSB0aGlzLnBvcztcbiAgICAgIHdoaWxlICh0aGlzLmVhdChtYXRjaCkpe31cbiAgICAgIHJldHVybiB0aGlzLnBvcyA+IHN0YXJ0O1xuICAgIH0sXG4gICAgZWF0U3BhY2U6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5wb3M7XG4gICAgICB3aGlsZSAoL1tcXHNcXHUwMGEwXS8udGVzdCh0aGlzLnN0cmluZy5jaGFyQXQodGhpcy5wb3MpKSkgKyt0aGlzLnBvcztcbiAgICAgIHJldHVybiB0aGlzLnBvcyA+IHN0YXJ0O1xuICAgIH0sXG4gICAgc2tpcFRvRW5kOiBmdW5jdGlvbigpIHt0aGlzLnBvcyA9IHRoaXMuc3RyaW5nLmxlbmd0aDt9LFxuICAgIHNraXBUbzogZnVuY3Rpb24oY2gpIHtcbiAgICAgIHZhciBmb3VuZCA9IHRoaXMuc3RyaW5nLmluZGV4T2YoY2gsIHRoaXMucG9zKTtcbiAgICAgIGlmIChmb3VuZCA+IC0xKSB7dGhpcy5wb3MgPSBmb3VuZDsgcmV0dXJuIHRydWU7fVxuICAgIH0sXG4gICAgYmFja1VwOiBmdW5jdGlvbihuKSB7dGhpcy5wb3MgLT0gbjt9LFxuICAgIGNvbHVtbjogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5sYXN0Q29sdW1uUG9zIDwgdGhpcy5zdGFydCkge1xuICAgICAgICB0aGlzLmxhc3RDb2x1bW5WYWx1ZSA9IGNvdW50Q29sdW1uKHRoaXMuc3RyaW5nLCB0aGlzLnN0YXJ0LCB0aGlzLnRhYlNpemUsIHRoaXMubGFzdENvbHVtblBvcywgdGhpcy5sYXN0Q29sdW1uVmFsdWUpO1xuICAgICAgICB0aGlzLmxhc3RDb2x1bW5Qb3MgPSB0aGlzLnN0YXJ0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMubGFzdENvbHVtblZhbHVlIC0gKHRoaXMubGluZVN0YXJ0ID8gY291bnRDb2x1bW4odGhpcy5zdHJpbmcsIHRoaXMubGluZVN0YXJ0LCB0aGlzLnRhYlNpemUpIDogMCk7XG4gICAgfSxcbiAgICBpbmRlbnRhdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gY291bnRDb2x1bW4odGhpcy5zdHJpbmcsIG51bGwsIHRoaXMudGFiU2l6ZSkgLVxuICAgICAgICAodGhpcy5saW5lU3RhcnQgPyBjb3VudENvbHVtbih0aGlzLnN0cmluZywgdGhpcy5saW5lU3RhcnQsIHRoaXMudGFiU2l6ZSkgOiAwKTtcbiAgICB9LFxuICAgIG1hdGNoOiBmdW5jdGlvbihwYXR0ZXJuLCBjb25zdW1lLCBjYXNlSW5zZW5zaXRpdmUpIHtcbiAgICAgIGlmICh0eXBlb2YgcGF0dGVybiA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHZhciBjYXNlZCA9IGZ1bmN0aW9uKHN0cikge3JldHVybiBjYXNlSW5zZW5zaXRpdmUgPyBzdHIudG9Mb3dlckNhc2UoKSA6IHN0cjt9O1xuICAgICAgICB2Y
23459XIgc3Vic3RyID0gdGhpcy5zdHJpbmcuc3Vic3RyKHRoaXMucG9zLCBwYXR0ZXJuLmxlbmd0aCk7XG4gICAgICAgIGlmIChjYXNlZChzdWJzdHIpID09IGNhc2VkKHBhdHRlcm4pKSB7XG4gICAgICAgICAgaWYgKGNvbnN1bWUgIT09IGZhbHNlKSB0aGlzLnBvcyArPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG1hdGNoID0gdGhpcy5zdHJpbmcuc2xpY2UodGhpcy5wb3MpLm1hdGNoKHBhdHRlcm4pO1xuICAgICAgICBpZiAobWF0Y2ggJiYgbWF0Y2guaW5kZXggPiAwKSByZXR1cm4gbnVsbDtcbiAgICAgICAgaWYgKG1hdGNoICYmIGNvbnN1bWUgIT09IGZhbHNlKSB0aGlzLnBvcyArPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgIHJldHVybiBtYXRjaDtcbiAgICAgIH1cbiAgICB9LFxuICAgIGN1cnJlbnQ6IGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc3RyaW5nLnNsaWNlKHRoaXMuc3RhcnQsIHRoaXMucG9zKTt9LFxuICAgIGhpZGVGaXJzdENoYXJzOiBmdW5jdGlvbihuLCBpbm5lcikge1xuICAgICAgdGhpcy5saW5lU3RhcnQgKz0gbjtcbiAgICAgIHRyeSB7IHJldHVybiBpbm5lcigpOyB9XG4gICAgICBmaW5hbGx5IHsgdGhpcy5saW5lU3RhcnQgLT0gbjsgfVxuICAgIH1cbiAgfTtcblxuICAvLyBURVhUTUFSS0VSU1xuXG4gIC8vIENyZWF0ZWQgd2l0aCBtYXJrVGV4dCBhbmQgc2V0Qm9va21hcmsgbWV0aG9kcy4gQSBUZXh0TWFya2VyIGlzIGFcbiAgLy8gaGFuZGxlIHRoYXQgY2FuIGJlIHVzZWQgdG8gY2xlYXIgb3IgZmluZCBhIG1hcmtlZCBwb3NpdGlvbiBpbiB0aGVcbiAgLy8gZG9jdW1lbnQuIExpbmUgb2JqZWN0cyBob2xkIGFycmF5cyAobWFya2VkU3BhbnMpIGNvbnRhaW5pbmdcbiAgLy8ge2Zyb20sIHRvLCBtYXJrZXJ9IG9iamVjdCBwb2ludGluZyB0byBzdWNoIG1hcmtlciBvYmplY3RzLCBhbmRcbiAgLy8gaW5kaWNhdGluZyB0aGF0IHN1Y2ggYSBtYXJrZXIgaXMgcHJlc2VudCBvbiB0aGF0IGxpbmUuIE11bHRpcGxlXG4gIC8vIGxpbmVzIG1heSBwb2ludCB0byB0aGUgc2FtZSBtYXJrZXIgd2hlbiBpdCBzcGFucyBhY3Jvc3MgbGluZXMuXG4gIC8vIFRoZSBzcGFucyB3aWxsIGhhdmUgbnVsbCBmb3IgdGhlaXIgZnJvbS90byBwcm9wZXJ0aWVzIHdoZW4gdGhlXG4gIC8vIG1hcmtlciBjb250aW51ZXMgYmV5b25kIHRoZSBzdGFydC9lbmQgb2YgdGhlIGxpbmUuIE1hcmtlcnMgaGF2ZVxuICAvLyBsaW5rcyBiYWNrIHRvIHRoZSBsaW5lcyB0aGV5IGN1cnJlbnRseSB0b3VjaC5cblxuICB2YXIgbmV4dE1hcmtlcklkID0gMDtcblxuICB2YXIgVGV4dE1hcmtlciA9IENvZGVNaXJyb3IuVGV4dE1hcmtlciA9IGZ1bmN0aW9uKGRvYywgdHlwZSkge1xuICAgIHRoaXMubGluZXMgPSBbXTtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMuZG9jID0gZG9jO1xuICAgIHRoaXMuaWQgPSArK25leHRNYXJrZXJJZDtcbiAgfTtcbiAgZXZlbnRNaXhpbihUZXh0TWFya2VyKTtcblxuICAvLyBDbGVhciB0aGUgbWFya2VyLlxuICBUZXh0TWFya2VyLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLmV4cGxpY2l0bHlDbGVhcmVkKSByZXR1cm47XG4gICAgdmFyIGNtID0gdGhpcy5kb2MuY20sIHdpdGhPcCA9IGNtICYmICFjbS5jdXJPcDtcbiAgICBpZiAod2l0aE9wKSBzdGFydE9wZXJhdGlvbihjbSk7XG4gICAgaWYgKGhhc0hhbmRsZXIodGhpcywgXCJjbGVhclwiKSkge1xuICAgICAgdmFyIGZvdW5kID0gdGhpcy5maW5kKCk7XG4gICAgICBpZiAoZm91bmQpIHNpZ25hbExhdGVyKHRoaXMsIFwiY2xlYXJcIiwgZm91bmQuZnJvbSwgZm91bmQudG8pO1xuICAgIH1cbiAgICB2YXIgbWluID0gbnVsbCwgbWF4ID0gbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBsaW5lID0gdGhpcy5saW5lc1tpXTtcbiAgICAgIHZhciBzcGFuID0gZ2V0TWFya2VkU3BhbkZvcihsaW5lLm1hcmtlZFNwYW5zLCB0aGlzKTtcbiAgICAgIGlmIChjbSAmJiAhdGhpcy5jb2xsYXBzZWQpIHJlZ0xpbmVDaGFuZ2UoY20sIGxpbmVObyhsaW5lKSwgXCJ0ZXh0XCIpO1xuICAgICAgZWxzZSBpZiAoY20pIHtcbiAgICAgICAgaWYgKHNwYW4udG8gIT0gbnVsbCkgbWF4ID0gbGluZU5vKGxpbmUpO1xuICAgICAgICBpZiAoc3Bhbi5mcm9tICE9IG51bGwpIG1pbiA9IGxpbmVObyhsaW5lKTtcbiAgICAgIH1cbiAgICAgIGxpbmUubWFya2VkU3BhbnMgPSByZW1vdmVNYXJrZWRTcGFuKGxpbmUubWFya2VkU3BhbnMsIHNwYW4pO1xuICAgICAgaWYgKHNwYW4uZnJvbSA9PSBudWxsICYmIHRoaXMuY29sbGFwc2VkICYmICFsaW5lSXNIaWRkZW4odGhpcy5kb2MsIGxpbmUpICYmIGNtKVxuICAgICAgICB1cGRhdGVMaW5lSGVpZ2h0KGxpbmUsIHRleHRIZWlnaHQoY20uZGlzcGxheSkpO1xuICAgIH1cbiAgICBpZiAoY20gJiYgdGhpcy5jb2xsYXBzZWQgJiYgIWNtLm9wdGlvbnMubGluZVdyYXBwaW5nKSBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciB2aXN1YWwgPSB2aXN1YWxMaW5lKHRoaXMubGluZXNbaV0pLCBsZW4gPSBsaW5lTGVuZ3RoKHZpc3VhbCk7XG4gICAgICBpZiAobGVuID4gY20uZGlzcGxheS5tYXhMaW5lTGVuZ3RoKSB7XG4gICAgICAgIGNtLmRpc3BsYXkubWF4TGluZSA9IHZpc3VhbDtcbiAgICAgICAgY20uZGlzcGxheS5tYXhMaW5lTGVuZ3RoID0gbGVuO1xuICAgICAgICBjbS5kaXNwbGF5Lm1heExpbmVDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWluICE9IG51bGwgJiYgY20gJiYgdGhpcy5jb2xsYXBzZWQpIHJlZ0NoYW5nZShjbSwgbWluLCBtYXggKyAxKTtcbiAgICB0aGlzLmxpbmVzLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5leHBsaWNpdGx5Q2xlYXJlZCA9IHRydWU7XG4gICAgaWYgKHRoaXMuYXRvbWljICYmIHRoaXMuZG9jLmNhbnRFZGl0KSB7XG4gICAgICB0aGlzLmRvYy5jYW50RWRpdCA9IGZhbHNlO1xuICAgICAgaWYgKGNtKSByZUNoZWNrU2VsZWN0aW9uKGNtLmRvYyk7XG4gICAgfVxuICAgIGlmIChjbSkgc2lnbmFsTGF0ZXIoY20sIFwibWFya2VyQ2xlYXJlZFwiLCBjbSwgdGhpcyk7XG4gICAgaWYgKHdpdGhPcCkgZW5kT3BlcmF0aW9uKGNtKTtcbiAgICBpZiAodGhpcy5wYXJlbnQpIHRoaXMucGFyZW50LmNsZWFyKCk7XG4gIH07XG5cbiAgLy8gRmluZCB0aGUgcG9zaXRpb24gb2YgdGhlIG1hcmtlciBpbiB0aGUgZG9jdW1lbnQuIFJldHVybnMgYSB7ZnJvbSxcbiAgLy8gdG99IG9iamVjdCBieSBkZWZh
23459dWx0LiBTaWRlIGNhbiBiZSBwYXNzZWQgdG8gZ2V0IGEgc3BlY2lmaWMgc2lkZVxuICAvLyAtLSAwIChib3RoKSwgLTEgKGxlZnQpLCBvciAxIChyaWdodCkuIFdoZW4gbGluZU9iaiBpcyB0cnVlLCB0aGVcbiAgLy8gUG9zIG9iamVjdHMgcmV0dXJuZWQgY29udGFpbiBhIGxpbmUgb2JqZWN0LCByYXRoZXIgdGhhbiBhIGxpbmVcbiAgLy8gbnVtYmVyICh1c2VkIHRvIHByZXZlbnQgbG9va2luZyB1cCB0aGUgc2FtZSBsaW5lIHR3aWNlKS5cbiAgVGV4dE1hcmtlci5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uKHNpZGUsIGxpbmVPYmopIHtcbiAgICBpZiAoc2lkZSA9PSBudWxsICYmIHRoaXMudHlwZSA9PSBcImJvb2ttYXJrXCIpIHNpZGUgPSAxO1xuICAgIHZhciBmcm9tLCB0bztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBsaW5lID0gdGhpcy5saW5lc1tpXTtcbiAgICAgIHZhciBzcGFuID0gZ2V0TWFya2VkU3BhbkZvcihsaW5lLm1hcmtlZFNwYW5zLCB0aGlzKTtcbiAgICAgIGlmIChzcGFuLmZyb20gIT0gbnVsbCkge1xuICAgICAgICBmcm9tID0gUG9zKGxpbmVPYmogPyBsaW5lIDogbGluZU5vKGxpbmUpLCBzcGFuLmZyb20pO1xuICAgICAgICBpZiAoc2lkZSA9PSAtMSkgcmV0dXJuIGZyb207XG4gICAgICB9XG4gICAgICBpZiAoc3Bhbi50byAhPSBudWxsKSB7XG4gICAgICAgIHRvID0gUG9zKGxpbmVPYmogPyBsaW5lIDogbGluZU5vKGxpbmUpLCBzcGFuLnRvKTtcbiAgICAgICAgaWYgKHNpZGUgPT0gMSkgcmV0dXJuIHRvO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZnJvbSAmJiB7ZnJvbTogZnJvbSwgdG86IHRvfTtcbiAgfTtcblxuICAvLyBTaWduYWxzIHRoYXQgdGhlIG1hcmtlcidzIHdpZGdldCBjaGFuZ2VkLCBhbmQgc3Vycm91bmRpbmcgbGF5b3V0XG4gIC8vIHNob3VsZCBiZSByZWNvbXB1dGVkLlxuICBUZXh0TWFya2VyLnByb3RvdHlwZS5jaGFuZ2VkI
23459D0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBvcyA9IHRoaXMuZmluZCgtMSwgdHJ1ZSksIHdpZGdldCA9IHRoaXMsIGNtID0gdGhpcy5kb2MuY207XG4gICAgaWYgKCFwb3MgfHwgIWNtKSByZXR1cm47XG4gICAgcnVuSW5PcChjbSwgZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbGluZSA9IHBvcy5saW5lLCBsaW5lTiA9IGxpbmVObyhwb3MubGluZSk7XG4gICAgICB2YXIgdmlldyA9IGZpbmRWaWV3Rm9yTGluZShjbSwgbGluZU4pO1xuICAgICAgaWYgKHZpZXcpIHtcbiAgICAgICAgY2xlYXJMaW5lTWVhc3VyZW1lbnRDYWNoZUZvcih2aWV3KTtcbiAgICAgICAgY20uY3VyT3Auc2VsZWN0aW9uQ2hhbmdlZCA9IGNtLmN1ck9wLmZvcmNlVXBkYXRlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGNtLmN1ck9wLnVwZGF0ZU1heExpbmUgPSB0cnVlO1xuICAgICAgaWYgKCFsaW5lSXNIaWRkZW4od2lkZ2V0LmRvYywgbGluZSkgJiYgd2lkZ2V0LmhlaWdodCAhPSBudWxsKSB7XG4gICAgICAgIHZhciBvbGRIZWlnaHQgPSB3aWRnZXQuaGVpZ2h0O1xuICAgICAgICB3aWRnZXQuaGVpZ2h0ID0gbnVsbDtcbiAgICAgICAgdmFyIGRIZWlnaHQgPSB3aWRnZXRIZWlnaHQod2lkZ2V0KSAtIG9sZEhlaWdodDtcbiAgICAgICAgaWYgKGRIZWlnaHQpXG4gICAgICAgICAgdXBkYXRlTGluZUhlaWdodChsaW5lLCBsaW5lLmhlaWdodCArIGRIZWlnaHQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFRleHRNYXJrZXIucHJvdG90eXBlLmF0dGFjaExpbmUgPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgaWYgKCF0aGlzLmxpbmVzLmxlbmd0aCAmJiB0aGlzLmRvYy5jbSkge1xuICAgICAgdmFyIG9wID0gdGhpcy5kb2MuY20uY3VyT3A7XG4gICAgICBpZiAoIW9wLm1heWJlSGlkZGVuTWFya2VycyB8fCBpbmRleE9mKG9wLm1heWJlSGlkZGVuTWFya2VycywgdGhpcykgPT0gLTEpXG4gICAgICAgIChvcC5tYXliZVVuaGlkZGVuTWFya2VycyB8fCAob3AubWF5YmVVbmhpZGRlbk1hcmtlcnMgPSBbXSkpLnB1c2godGhpcyk7XG4gICAgfVxuICAgIHRoaXMubGluZXMucHVzaChsaW5lKTtcbiAgfTtcbiAgVGV4dE1hcmtlci5wcm90b3R5cGUuZGV0YWNoTGluZSA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgICB0aGlzLmxpbmVzLnNwbGljZShpbmRleE9mKHRoaXMubGluZXMsIGxpbmUpLCAxKTtcbiAgICBpZiAoIXRoaXMubGluZXMubGVuZ3RoICYmIHRoaXMuZG9jLmNtKSB7XG4gICAgICB2Y
23459XIgb3AgPSB0aGlzLmRvYy5jbS5jdXJPcDtcbiAgICAgIChvcC5tYXliZUhpZGRlbk1hcmtlcnMgfHwgKG9wLm1heWJlSGlkZGVuTWFya2VycyA9IFtdKSkucHVzaCh0aGlzKTtcbiAgICB9XG4gIH07XG5cbiAgLy8gQ29sbGFwc2VkIG1hcmtlcnMgaGF2ZSB1bmlxdWUgaWRzLCBpbiBvcmRlciB0byBiZSBhYmxlIHRvIG9yZGVyXG4gIC8vIHRoZW0sIHdoaWNoIGlzIG5lZWRlZCBmb3IgdW5pcXVlbHkgZGV0ZXJtaW5pbmcgYW4gb3V0ZXIgbWFya2VyXG4gIC8vIHdoZW4gdGhleSBvdmVybGFwICh0aGV5IG1heSBuZXN0LCBidXQgbm90IHBhcnRpYWxseSBvdmVybGFwKS5cbiAgdmFyIG5leHRNYXJrZXJJZCA9IDA7XG5cbiAgLy8gQ3JlYXRlIGEgbWFya2VyLCB3aXJlIGl0IHVwIHRvIHRoZSByaWdodCBsaW5lcywgYW5kXG4gIGZ1bmN0aW9uIG1hcmtUZXh0KGRvYywgZnJvbSwgdG8sIG9wdGlvbnMsIHR5cGUpIHtcbiAgICAvLyBTaGFyZWQgbWFya2VycyAoYWNyb3NzIGxpbmtlZCBkb2N1bWVudHMpIGFyZSBoYW5kbGVkIHNlcGFyYXRlbHlcbiAgICAvLyAobWFya1RleHRTaGFyZWQgd2lsbCBjYWxsIG91dCB0byB0aGlzIGFnYWluLCBvbmNlIHBlclxuICAgIC8vIGRvY3VtZW50KS5cbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnNoYXJlZCkgcmV0dXJuIG1hcmtUZXh0U2hhcmVkKGRvYywgZnJvbSwgdG8sIG9wdGlvbnMsIHR5cGUpO1xuICAgIC8vIEVuc3VyZSB3ZSBhcmUgaW4gYW4gb3BlcmF0aW9uLlxuICAgIGlmIChkb2MuY20gJiYgIWRvYy5jbS5jdXJPcCkgcmV0dXJuIG9wZXJhdGlvbihkb2MuY20sIG1hcmtUZXh0KShkb2MsIGZyb20sIHRvLCBvcHRpb25zLCB0eXBlKTtcblxuICAgIHZhciBtYXJrZXIgPSBuZXcgVGV4dE1hcmtlcihkb2MsIHR5cGUpLCBkaWZmID0gY21wKGZyb20sIHRvKTtcbiAgICBpZiAob3B0aW9ucykgY29weU9iaihvcHRpb25zLCBtYXJrZXIsIGZhbHNlKTtcbiAgICAvLyBEb24ndCBjb25uZWN0IGVtcHR5IG1hcmtlcnMgdW5sZXNzIGNsZWFyV2hlbkVtcHR5IGlzIGZhbHNlXG4gICAgaWYgKGRpZmYgPiAwIHx8IGRpZmYgPT0gMCAmJiBtYXJrZXIuY2xlYXJXaGVuRW1wdHkgIT09IGZhbHNlKVxuICAgICAgcmV0dXJuIG1hcmtlcjtcbiAgICBpZiAobWFya2VyLnJlcGxhY2VkV2l0aCkge1xuICAgICAgLy8gU2hvd2luZyB1cCBhcyBhIHdpZGdldCBpbXBsaWVzIGNvbGxhcHNlZCAod2lkZ2V0IHJlcGxhY2VzIHRleHQpXG4gICAgICBtYXJrZXIuY29sbGFwc2VkID0gdHJ1ZTtcbiAgICAgIG1hcmtlci53aWRnZXROb2RlID0gZWx0KFwic3BhblwiLCBbbWFya2VyLnJlcGxhY2VkV2l0aF0sIFwiQ29kZU1pcnJvci13aWRnZXRcIik7XG4gICAgICBpZiAoIW9wdGlvbnMuaGFuZGxlTW91c2VFdmVudHMpIG1hcmtlci53aWRnZXROb2RlLnNldEF0dHJpYnV0ZShcImNtLWlnbm9yZS1ldmVud
23459HNcIiwgXCJ0cnVlXCIpO1xuICAgICAgaWYgKG9wdGlvbnMuaW5zZXJ0TGVmdCkgbWFya2VyLndpZGdldE5vZGUuaW5zZXJ0TGVmdCA9IHRydWU7XG4gICAgfVxuICAgIGlmIChtYXJrZXIuY29sbGFwc2VkKSB7XG4gICAgICBpZiAoY29uZmxpY3RpbmdDb2xsYXBzZWRSYW5nZShkb2MsIGZyb20ubGluZSwgZnJvbSwgdG8sIG1hcmtlcikgfHxcbiAgICAgICAgICBmcm9tLmxpbmUgIT0gdG8ubGluZSAmJiBjb25mbGljdGluZ0NvbGxhcHNlZFJhbmdlKGRvYywgdG8ubGluZSwgZnJvbSwgdG8sIG1hcmtlcikpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkluc2VydGluZyBjb2xsYXBzZWQgbWFya2VyIHBhcnRpYWxseSBvdmVybGFwcGluZyBhbiBleGlzdGluZyBvbmVcIik7XG4gICAgICBzYXdDb2xsYXBzZWRTcGFucyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG1hcmtlci5hZGRUb0hpc3RvcnkpXG4gICAgICBhZGRDaGFuZ2VUb0hpc3RvcnkoZG9jLCB7ZnJvbTogZnJvbSwgdG86IHRvLCBvcmlnaW46IFwibWFya1RleHRcIn0sIGRvYy5zZWwsIE5hTik7XG5cbiAgICB2YXIgY3VyTGluZSA9IGZyb20ubGluZSwgY20gPSBkb2MuY20sIHVwZGF0ZU1heExpbmU7XG4gICAgZG9jLml0ZXIoY3VyTGluZSwgdG8ubGluZSArIDEsIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIGlmIChjbSAmJiBtYXJrZXIuY29sbGFwc2VkICYmICFjbS5vcHRpb25zLmxpbmVXcmFwcGluZyAmJiB2aXN1YWxMaW5lKGxpbmUpID09IGNtLmRpc3BsYXkubWF4TGluZSlcbiAgICAgICAgdXBkYXRlTWF4TGluZSA9IHRydWU7XG4gICAgICBpZiAobWFya2VyLmNvbGxhcHNlZCAmJiBjdXJMaW5lICE9IGZyb20ubGluZSkgdXBkYXRlTGluZUhlaWdodChsaW5lLCAwKTtcbiAgICAgIGFkZE1hcmtlZFNwYW4obGluZSwgbmV3IE1hcmtlZFNwYW4obWFya2VyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJMaW5lID09IGZyb20ubGluZSA/IGZyb20uY2ggOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJMaW5lID09IHRvLmxpbmUgPyB0by5jaCA6IG51bGwpKTtcbiAgICAgICsrY3VyTGluZTtcbiAgICB9KTtcbiAgICAvLyBsaW5lSXNIaWRkZW4gZGVwZW5kcyBvbiB0aGUgcHJlc2VuY2Ugb2YgdGhlIHNwYW5zLCBzbyBuZWVkcyBhIHNlY29uZCBwYXNzXG4gICAgaWYgKG1hcmtlci5jb2xsYXBzZWQpIGRvYy5pdGVyKGZyb20ubGluZSwgdG8ubGluZSArIDEsIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIGlmIChsaW5lSXNIaWRkZW4oZG9jLCBsaW5lKSkgdXBkYXRlTGluZUhlaWdodChsaW5lLCAwKTtcbiAgICB9KTtcblxuICAgIGlmIChtYXJrZXIuY2xlYXJPbkVudGVyKSBvbihtYXJrZXIsIFwiYmVmb3JlQ3Vyc29yRW50ZXJcIiwgZnVuY3Rpb24oKSB7IG1hcmtlci5jbGVhcigpOyB9KTtcblxuICAgIGlmIChtYXJrZXIucmVhZE9ubHkpIHtcbiAgICAgIHNhd1JlYWRPbmx5U3BhbnMgPSB0cnVlO1xuICAgICAgaWYgKGRvYy5oaXN0b3J5LmRvbmUubGVuZ3RoIHx8IGRvYy5oaXN0b3J5LnVuZG9uZS5sZW5ndGgpXG4gICAgICAgIGRvYy5jbGVhckhpc3RvcnkoKTtcbiAgICB9XG4gICAgaWYgKG1hcmtlci5jb2xsYXBzZWQpIHtcbiAgICAgIG1hcmtlci5pZCA9ICsrbmV4dE1hcmtlcklkO1xuICAgICAgbWFya2VyLmF0b21pYyA9IHRydWU7XG4gICAgfVxuICAgIGlmIChjbSkge1xuICAgICAgLy8gU3luYyBlZGl0b3Igc3RhdGVcbiAgICAgIGlmICh1cGRhdGVNYXhMaW5lKSBjbS5jdXJPcC51cGRhdGVNYXhMaW5lID0gdHJ1ZTtcbiAgICAgIGlmIChtYXJrZXIuY29sbGFwc2VkKVxuICAgICAgICByZWdDaGFuZ2UoY20sIGZyb20ubGluZSwgdG8ubGluZSArIDEpO1xuICAgICAgZWxzZSBpZiAobWFya2VyLmNsYXNzTmFtZSB8fCBtYXJrZXIudGl0bGUgfHwgbWFya2VyLnN0YXJ0U3R5bGUgfHwgbWFya2VyLmVuZFN0eWxlIHx8IG1hcmtlci5jc3MpXG4gICAgICAgIGZvciAodmFyIGkgPSBmcm9tLmxpbmU7IGkgPD0gdG8ubGluZTsgaSsrKSByZWdMaW5lQ2hhbmdlKGNtLCBpLCBcInRleHRcIik7XG4gICAgICBpZiAobWFya2VyLmF0b21pYykgcmVDaGVja1NlbGVjdGlvbihjbS5kb2MpO1xuICAgICAgc2lnbmFsTGF0ZXIoY20sIFwibWFya2VyQWRkZWRcIiwgY20sIG1hcmtlcik7XG4gICAgfVxuICAgIHJldHVybiBtYXJrZXI7XG4gIH1cblxuICAvLyBTSEFSRUQgVEVYVE1BUktFUlNcblxuICAvLyBBIHNoYXJlZCBtYXJrZXIgc3BhbnMgbXVsdGlwbGUgbGlua2VkIGRvY3VtZW50cy4gSXQgaXNcbiAgLy8gaW1wbGVtZW50ZWQgYXMgYSBtZXRhLW1hcmtlci1vYmplY3QgY29udHJvbGxpbmcgbXVsdGlwbGUgbm9ybWFsXG4gIC8vIG1hcmtlcnMuXG4gIHZhciBTaGFyZWRUZXh0TWFya2VyID0gQ29kZU1pcnJvci5TaGFyZWRUZXh0TWFya2VyID0gZnVuY3Rpb24obWFya2VycywgcHJpbWFyeSkge1xuICAgIHRoaXMubWFya2VycyA9IG1hcmtlcnM7XG4gICAgdGhpcy5wcmltYXJ5ID0gcHJpbWFyeTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcmtlcnMubGVuZ3RoOyArK2kpXG4gICAgICBtYXJrZXJzW2ldLnBhcmVudCA9IHRoaXM7XG4gIH07XG4gIGV2ZW50TWl4aW4oU2hhcmVkVGV4dE1hcmtlcik7XG5cbiAgU2hhcmVkVGV4dE1hcmtlci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5leHBsaWNpdGx5Q2xlYXJlZCkgcmV0dXJuO1xuICAgIHRoaXMuZXhwbGljaXRseUNsZWFyZWQgPSB0cnVlO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5tYXJrZXJzLmxlbmd0aDsgKytpKVxuICAgICAgdGhpcy5tYXJrZXJzW2ldLmNsZWFyKCk7XG4gICAgc2lnbmFsTGF0ZXIodGhpcywgXCJjbGVhclwiKTtcbiAgfTtcbiAgU2hhcmVkVGV4dE1hcmtlci5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uKHNpZGUsIGxpbmVPYmopIHtcbiAgICByZXR1cm4gdGhpcy5wcmltYXJ5LmZpbmQoc2lkZSwgbGluZU9iaik7XG4gIH07XG5cbiAgZnVuY3Rpb24gbWFya1RleHRTaGFyZWQoZG9jLCBmcm9tLCB0bywgb3B0aW9ucywgdHlwZSkge1xuICAgIG9wdGlvbnMgPSBjb3B5T2JqKG9wdGlvbnMpO1xuICAgIG9wdGlvbnMuc2hhcmVkID0gZmFsc2U7XG4gICAgdmFyIG1hcmtlcnMgPSBbbWFya1RleHQoZG9jLCBmcm9tLCB0bywgb3B0aW9ucywgdHlwZSldLCBwcmltYXJ5ID0gbWFya2Vyc1swXTtcbiAgICB2YXIgd2lkZ2V0ID0gb3B0aW9ucy53aWRnZXROb2RlO1xuICAgIGxpbmtlZERvY3MoZG9jLCBmdW5jdGlvbihkb2MpIHtcbiAgICAgIGlmICh3aWRnZXQpIG9wdGlvbnMud2lkZ2V0Tm9kZSA9IHdpZGdldC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICBtYXJrZXJzLnB1c2gobWFya1RleHQoZG9jLCBjbGlwUG9zKGRvYywgZnJvbSksIGNsaXBQb3MoZG9jLCB0byksIG9wdGlvbnMsIHR5cGUpKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jLmxpbmtlZC5sZW5ndGg7ICsraSlcbiAgICAgICAgaWYgKGRvYy5saW5rZWRbaV0uaXNQYXJlbnQpIHJldHVybjtcbiAgICAgIHByaW1hcnkgPSBsc3QobWFya2Vycyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBTaGFyZWRUZXh0TWFya2VyKG1hcmtlcnMsIHByaW1hcnkpO1xuICB9XG5cbiAgZnVuY3Rpb24gZmluZFNoYXJlZE1hcmtlcnMoZG9jKSB7XG4gICAgcmV0dXJuIGRvYy5maW5kTWFya3MoUG9zKGRvYy5maXJzdCwgMCksIGRvYy5jbGlwUG9zKFBvcyhkb2MubGFzdExpbmUoKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKG0pIHsgcmV0dXJuIG0ucGFyZW50OyB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvcHlTaGFyZWRNYXJrZXJzKGRvYywgbWFya2Vycykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG1hcmtlciA9IG1hcmtlcnNbaV0sIHBvcyA9IG1hcmtlci5maW5kKCk7XG4gICAgICB2Y
23459XIgbUZyb20gPSBkb2MuY2xpcFBvcyhwb3MuZnJvbSksIG1UbyA9IGRvYy5jbGlwUG9zKHBvcy50byk7XG4gICAgICBpZiAoY21wKG1Gcm9tLCBtVG8pKSB7XG4gICAgICAgIHZhciBzdWJNYXJrID0gbWFya1RleHQoZG9jLCBtRnJvbSwgbVRvLCBtYXJrZXIucHJpbWFyeSwgbWFya2VyLnByaW1hcnkudHlwZSk7XG4gICAgICAgIG1hcmtlci5tYXJrZXJzLnB1c2goc3ViTWFyayk7XG4gICAgICAgIHN1Yk1hcmsucGFyZW50ID0gbWFya2VyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGRldGFjaFNoYXJlZE1hcmtlcnMobWFya2Vycykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG1hcmtlciA9IG1hcmtlcnNbaV0sIGxpbmtlZCA9IFttYXJrZXIucHJpbWFyeS5kb2NdOztcbiAgICAgIGxpbmtlZERvY3MobWFya2VyLnByaW1hcnkuZG9jLCBmdW5jdGlvbihkKSB7IGxpbmtlZC5wdXNoKGQpOyB9KTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWFya2VyLm1hcmtlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIHN1Yk1hcmtlciA9IG1hcmtlci5tYXJrZXJzW2pdO1xuICAgICAgICBpZiAoaW5kZXhPZihsaW5rZWQsIHN1Yk1hcmtlci5kb2MpID09IC0xKSB7XG4gICAgICAgICAgc3ViTWFya2VyLnBhcmVudCA9IG51bGw7XG4gICAgICAgICAgbWFya2VyLm1hcmtlcnMuc3BsaWNlKGotLSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBURVhUTUFSS0VSIFNQQU5TXG5cbiAgZnVuY3Rpb24gTWFya2VkU3BhbihtYXJrZXIsIGZyb20sIHRvKSB7XG4gICAgdGhpcy5tYXJrZXIgPSBtYXJrZXI7XG4gICAgdGhpcy5mcm9tID0gZnJvbTsgdGhpcy50byA9IHRvO1xuICB9XG5cbiAgLy8gU2VhcmNoIGFuIGFycmF5IG9mIHNwYW5zIGZvciBhIHNwYW4gbWF0Y2hpbmcgdGhlIGdpdmVuIG1hcmtlci5cbiAgZnVuY3Rpb24gZ2V0TWFya2VkU3BhbkZvcihzcGFucywgbWFya2VyKSB7XG4gICAgaWYgKHNwYW5zKSBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICB2Y
23459XIgc3BhbiA9IHNwYW5zW2ldO1xuICAgICAgaWYgKHNwYW4ubWFya2VyID09IG1hcmtlcikgcmV0dXJuIHNwYW47XG4gICAgfVxuICB9XG4gIC8vIFJlbW92ZSBhIHNwYW4gZnJvbSBhbiBhcnJheSwgcmV0dXJuaW5nIHVuZGVmaW5lZCBpZiBubyBzcGFucyBhcmVcbiAgLy8gbGVmdCAod2UgZG9uJ3Qgc3RvcmUgYXJyYXlzIGZvciBsaW5lcyB3aXRob3V0IHNwYW5zKS5cbiAgZnVuY3Rpb24gcmVtb3ZlTWFya2VkU3BhbihzcGFucywgc3Bhbikge1xuICAgIGZvciAodmFyIHIsIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpXG4gICAgICBpZiAoc3BhbnNbaV0gIT0gc3BhbikgKHIgfHwgKHIgPSBbXSkpLnB1c2goc3BhbnNbaV0pO1xuICAgIHJldHVybiByO1xuICB9XG4gIC8vIEFkZCBhIHNwYW4gdG8gYSBsaW5lLlxuICBmdW5jdGlvbiBhZGRNYXJrZWRTcGFuKGxpbmUsIHNwYW4pIHtcbiAgICBsaW5lLm1hcmtlZFNwYW5zID0gbGluZS5tYXJrZWRTcGFucyA/IGxpbmUubWFya2VkU3BhbnMuY29uY2F0KFtzcGFuXSkgOiBbc3Bhbl07XG4gICAgc3Bhbi5tYXJrZXIuYXR0YWNoTGluZShsaW5lKTtcbiAgfVxuXG4gIC8vIFVzZWQgZm9yIHRoZSBhbGdvcml0aG0gdGhhdCBhZGp1c3RzIG1hcmtlcnMgZm9yIGEgY2hhbmdlIGluIHRoZVxuICAvLyBkb2N1bWVudC4gVGhlc2UgZnVuY3Rpb25zIGN1dCBhbiBhcnJheSBvZiBzcGFucyBhdCBhIGdpdmVuXG4gIC8vIGNoYXJhY3RlciBwb3NpdGlvbiwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIHJlbWFpbmluZyBjaHVua3MgKG9yXG4gIC8vIHVuZGVmaW5lZCBpZiBub3RoaW5nIHJlbWFpbnMpLlxuICBmdW5jdGlvbiBtYXJrZWRTcGFuc0JlZm9yZShvbGQsIHN0YXJ0Q2gsIGlzSW5zZXJ0KSB7XG4gICAgaWYgKG9sZCkgZm9yICh2YXIgaSA9IDAsIG53OyBpIDwgb2xkLmxlbmd0aDsgKytpKSB7XG4gICAgICB2Y
23459XIgc3BhbiA9IG9sZFtpXSwgbWFya2VyID0gc3Bhbi5tYXJrZXI7XG4gICAgICB2YXIgc3RhcnRzQmVmb3JlID0gc3Bhbi5mcm9tID09IG51bGwgfHwgKG1hcmtlci5pbmNsdXNpdmVMZWZ0ID8gc3Bhbi5mcm9tIDw9IHN0YXJ0Q2ggOiBzcGFuLmZyb20gPCBzdGFydENoKTtcbiAgICAgIGlmIChzdGFydHNCZWZvcmUgfHwgc3Bhbi5mcm9tID09IHN0YXJ0Q2ggJiYgbWFya2VyLnR5cGUgPT0gXCJib29rbWFya1wiICYmICghaXNJbnNlcnQgfHwgIXNwYW4ubWFya2VyLmluc2VydExlZnQpKSB7XG4gICAgICAgIHZhciBlbmRzQWZ0ZXIgPSBzcGFuLnRvID09IG51bGwgfHwgKG1hcmtlci5pbmNsdXNpdmVSaWdodCA/IHNwYW4udG8gPj0gc3RhcnRDaCA6IHNwYW4udG8gPiBzdGFydENoKTtcbiAgICAgICAgKG53IHx8IChudyA9IFtdKSkucHVzaChuZXcgTWFya2VkU3BhbihtYXJrZXIsIHNwYW4uZnJvbSwgZW5kc0FmdGVyID8gbnVsbCA6IHNwYW4udG8pKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG53O1xuICB9XG4gIGZ1bmN0aW9uIG1hcmtlZFNwYW5zQWZ0ZXIob2xkLCBlbmRDaCwgaXNJbnNlcnQpIHtcbiAgICBpZiAob2xkKSBmb3IgKHZhciBpID0gMCwgbnc7IGkgPCBvbGQubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzcGFuID0gb2xkW2ldLCBtYXJrZXIgPSBzcGFuLm1hcmtlcjtcbiAgICAgIHZhciBlbmRzQWZ0ZXIgPSBzcGFuLnRvID09IG51bGwgfHwgKG1hcmtlci5pbmNsdXNpdmVSaWdodCA/IHNwYW4udG8gPj0gZW5kQ2ggOiBzcGFuLnRvID4gZW5kQ2gpO1xuICAgICAgaWYgKGVuZHNBZnRlciB8fCBzcGFuLmZyb20gPT0gZW5kQ2ggJiYgbWFya2VyLnR5cGUgPT0gXCJib29rbWFya1wiICYmICghaXNJbnNlcnQgfHwgc3Bhbi5tYXJrZXIuaW5zZXJ0TGVmdCkpIHtcbiAgICAgICAgdmFyIHN0YXJ0c0JlZm9yZSA9IHNwYW4uZnJvbSA9PSBudWxsIHx8IChtYXJrZXIuaW5jbHVzaXZlTGVmdCA/IHNwYW4uZnJvbSA8PSBlbmRDaCA6IHNwYW4uZnJvbSA8IGVuZENoKTtcbiAgICAgICAgKG53IHx8IChudyA9IFtdKSkucHVzaChuZXcgTWFya2VkU3BhbihtYXJrZXIsIHN0YXJ0c0JlZm9yZSA/IG51bGwgOiBzcGFuLmZyb20gLSBlbmRDaCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFuLnRvID09IG51bGwgPyBudWxsIDogc3Bhbi50byAtIGVuZENoKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudztcbiAgfVxuXG4gIC8vIEdpdmVuIGEgY2hhbmdlIG9iamVjdCwgY29tcHV0ZSB0aGUgbmV3IHNldCBvZiBtYXJrZXIgc3BhbnMgdGhhdFxuICAvLyBjb3ZlciB0aGUgbGluZSBpbiB3aGljaCB0aGUgY2hhbmdlIHRvb2sgcGxhY2UuIFJlbW92ZXMgc3BhbnNcbiAgLy8gZW50aXJlbHkgd2l0aGluIHRoZSBjaGFuZ2UsIHJlY29ubmVjdHMgc3BhbnMgYmVsb25naW5nIHRvIHRoZVxuICAvLyBzYW1lIG1hcmtlciB0aGF0IGFwcGVhciBvbiBib3RoIHNpZGVzIG9mIHRoZSBjaGFuZ2UsIGFuZCBjdXRzIG9mZlxuICAvLyBzcGFucyBwYXJ0aWFsbHkgd2l0aGluIHRoZSBjaGFuZ2UuIFJldHVybnMgYW4gYXJyYXkgb2Ygc3BhblxuICAvLyBhcnJheXMgd2l0aCBvbmUgZWxlbWVudCBmb3IgZWFjaCBsaW5lIGluIChhZnRlcikgdGhlIGNoYW5nZS5cbiAgZnVuY3Rpb24gc3RyZXRjaFNwYW5zT3ZlckNoYW5nZShkb2MsIGNoYW5nZSkge1xuICAgIGlmIChjaGFuZ2UuZnVsbCkgcmV0dXJuIG51bGw7XG4gICAgdmFyIG9sZEZpcnN0ID0gaXNMaW5lKGRvYywgY2hhbmdlLmZyb20ubGluZSkgJiYgZ2V0TGluZShkb2MsIGNoYW5nZS5mcm9tLmxpbmUpLm1hcmtlZFNwYW5zO1xuICAgIHZhciBvbGRMYXN0ID0gaXNMaW5lKGRvYywgY2hhbmdlLnRvLmxpbmUpICYmIGdldExpbmUoZG9jLCBjaGFuZ2UudG8ubGluZSkubWFya2VkU3BhbnM7XG4gICAgaWYgKCFvbGRGaXJzdCAmJiAhb2xkTGFzdCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgc3RhcnRDaCA9IGNoYW5nZS5mcm9tLmNoLCBlbmRDaCA9IGNoYW5nZS50by5jaCwgaXNJbnNlcnQgPSBjbXAoY2hhbmdlLmZyb20sIGNoYW5nZS50bykgPT0gMDtcbiAgICAvLyBHZXQgdGhlIHNwYW5zIHRoYXQgJ3N0aWNrIG91dCcgb24gYm90aCBzaWRlc1xuICAgIHZhciBmaXJzdCA9IG1hcmtlZFNwYW5zQmVmb3JlKG9sZEZpcnN0LCBzdGFydENoLCBpc0luc2VydCk7XG4gICAgdmFyIGxhc3QgPSBtYXJrZWRTcGFuc0FmdGVyKG9sZExhc3QsIGVuZENoLCBpc0luc2VydCk7XG5cbiAgICAvLyBOZXh0LCBtZXJnZSB0aG9zZSB0d28gZW5kc1xuICAgIHZhciBzYW1lTGluZSA9IGNoYW5nZS50ZXh0Lmxlbmd0aCA9PSAxLCBvZmZzZXQgPSBsc3QoY2hhbmdlLnRleHQpLmxlbmd0aCArIChzYW1lTGluZSA/IHN0YXJ0Q2ggOiAwKTtcbiAgICBpZiAoZmlyc3QpIHtcbiAgICAgIC8vIEZpeCB1cCAudG8gcHJvcGVydGllcyBvZiBmaXJzdFxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaXJzdC5sZW5ndGg7ICsraSkge1xuICAgICAgICB2Y
23459XIgc3BhbiA9IGZpcnN0W2ldO1xuICAgICAgICBpZiAoc3Bhbi50byA9PSBudWxsKSB7XG4gICAgICAgICAgdmFyIGZvdW5kID0gZ2V0TWFya2VkU3BhbkZvcihsYXN0LCBzcGFuLm1hcmtlcik7XG4gICAgICAgICAgaWYgKCFmb3VuZCkgc3Bhbi50byA9IHN0YXJ0Q2g7XG4gICAgICAgICAgZWxzZSBpZiAoc2FtZUxpbmUpIHNwYW4udG8gPSBmb3VuZC50byA9PSBudWxsID8gbnVsbCA6IGZvdW5kLnRvICsgb2Zmc2V0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChsYXN0KSB7XG4gICAgICAvLyBGaXggdXAgLmZyb20gaW4gbGFzdCAob3IgbW92ZSB0aGVtIGludG8gZmlyc3QgaW4gY2FzZSBvZiBzYW1lTGluZSlcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdC5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgc3BhbiA9IGxhc3RbaV07XG4gICAgICAgIGlmIChzcGFuLnRvICE9IG51bGwpIHNwYW4udG8gKz0gb2Zmc2V0O1xuICAgICAgICBpZiAoc3Bhbi5mcm9tID09IG51bGwpIHtcbiAgICAgICAgICB2YXIgZm91bmQgPSBnZXRNYXJrZWRTcGFuRm9yKGZpcnN0LCBzcGFuLm1hcmtlcik7XG4gICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgc3Bhbi5mcm9tID0gb2Zmc2V0O1xuICAgICAgICAgICAgaWYgKHNhbWVMaW5lKSAoZmlyc3QgfHwgKGZpcnN0ID0gW10pKS5wdXNoKHNwYW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzcGFuLmZyb20gKz0gb2Zmc2V0O1xuICAgICAgICAgIGlmIChzYW1lTGluZSkgKGZpcnN0IHx8IChmaXJzdCA9IFtdKSkucHVzaChzcGFuKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvLyBNYWtlIHN1cmUgd2UgZGlkbid0IGNyZWF0ZSBhbnkgemVyby1sZW5ndGggc3BhbnNcbiAgICBpZiAoZmlyc3QpIGZpcnN0ID0gY2xlYXJFbXB0eVNwYW5zKGZpcnN0KTtcbiAgICBpZiAobGFzdCAmJiBsYXN0ICE9IGZpcnN0KSBsYXN0ID0gY2xlYXJFbXB0eVNwYW5zKGxhc3QpO1xuXG4gICAgdmFyIG5ld01hcmtlcnMgPSBbZmlyc3RdO1xuICAgIGlmICghc2FtZUxpbmUpIHtcbiAgICAgIC8vIEZpbGwgZ2FwIHdpdGggd2hvbGUtbGluZS1zcGFuc1xuICAgICAgdmFyIGdhcCA9IGNoYW5nZS50ZXh0Lmxlbmd0aCAtIDIsIGdhcE1hcmtlcnM7XG4gICAgICBpZiAoZ2FwID4gMCAmJiBmaXJzdClcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaXJzdC5sZW5ndGg7ICsraSlcbiAgICAgICAgICBpZiAoZmlyc3RbaV0udG8gPT0gbnVsbClcbiAgICAgICAgICAgIChnYXBNYXJrZXJzIHx8IChnYXBNYXJrZXJzID0gW10pKS5wdXNoKG5ldyBNYXJrZWRTcGFuKGZpcnN0W2ldLm1hcmtlciwgbnVsbCwgbnVsbCkpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBnYXA7ICsraSlcbiAgICAgICAgbmV3TWFya2Vycy5wdXNoKGdhcE1hcmtlcnMpO1xuICAgICAgbmV3TWFya2Vycy5wdXNoKGxhc3QpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3TWFya2VycztcbiAgfVxuXG4gIC8vIFJlbW92ZSBzcGFucyB0aGF0IGFyZSBlbXB0eSBhbmQgZG9uJ3QgaGF2ZSBhIGNsZWFyV2hlbkVtcHR5XG4gIC8vIG9wdGlvbiBvZiBmYWxzZS5cbiAgZnVuY3Rpb24gY2xlYXJFbXB0eVNwYW5zKHNwYW5zKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzcGFucy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHNwYW4gPSBzcGFuc1tpXTtcbiAgICAgIGlmIChzcGFuLmZyb20gIT0gbnVsbCAmJiBzcGFuLmZyb20gPT0gc3Bhbi50byAmJiBzcGFuLm1hcmtlci5jbGVhcldoZW5FbXB0eSAhPT0gZmFsc2UpXG4gICAgICAgIHNwYW5zLnNwbGljZShpLS0sIDEpO1xuICAgIH1cbiAgICBpZiAoIXNwYW5zLmxlbmd0aCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHNwYW5zO1xuICB9XG5cbiAgLy8gVXNlZCBmb3IgdW4vcmUtZG9pbmcgY2hhbmdlcyBmcm9tIHRoZSBoaXN0b3J5LiBDb21iaW5lcyB0aGVcbiAgLy8gcmVzdWx0IG9mIGNvbXB1dGluZyB0aGUgZXhpc3Rpbmcgc3BhbnMgd2l0aCB0aGUgc2V0IG9mIHNwYW5zIHRoYXRcbiAgLy8gZXhpc3RlZCBpbiB0aGUgaGlzdG9yeSAoc28gdGhhdCBkZWxldGluZyBhcm91bmQgYSBzcGFuIGFuZCB0aGVuXG4gIC8vIHVuZG9pbmcgYnJpbmdzIGJhY2sgdGhlIHNwYW4pLlxuICBmdW5jdGlvbiBtZXJnZU9sZFNwYW5zKGRvYywgY2hhbmdlKSB7XG4gICAgdmFyIG9sZCA9IGdldE9sZFNwYW5zKGRvYywgY2hhbmdlKTtcbiAgICB2YXIgc3RyZXRjaGVkID0gc3RyZXRjaFNwYW5zT3ZlckNoYW5nZShkb2MsIGNoYW5nZSk7XG4gICAgaWYgKCFvbGQpIHJldHVybiBzdHJldGNoZWQ7XG4gICAgaWYgKCFzdHJldGNoZWQpIHJldHVybiBvbGQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9sZC5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIG9sZEN1ciA9IG9sZFtpXSwgc3RyZXRjaEN1ciA9IHN0cmV0Y2hlZFtpXTtcbiAgICAgIGlmIChvbGRDdXIgJiYgc3RyZXRjaEN1cikge1xuICAgICAgICBzcGFuczogZm9yICh2YXIgaiA9IDA7IGogPCBzdHJldGNoQ3VyLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgdmFyIHNwYW4gPSBzdHJldGNoQ3VyW2pdO1xuICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgb2xkQ3VyLmxlbmd0aDsgKytrKVxuICAgICAgICAgICAgaWYgKG9sZEN1cltrXS5tYXJrZXIgPT0gc3Bhbi5tYXJrZXIpIGNvbnRpbnVlIHNwYW5zO1xuICAgICAgICAgIG9sZEN1ci5wdXNoKHNwYW4pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmV0Y2hDdXIpIHtcbiAgICAgICAgb2xkW2ldID0gc3RyZXRjaEN1cjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG9sZDtcbiAgfVxuXG4gIC8vIFVzZWQgdG8gJ2NsaXAnIG91dCByZWFkT25seSByYW5nZXMgd2hlbiBtYWtpbmcgYSBjaGFuZ2UuXG4gIGZ1bmN0aW9uIHJlbW92ZVJlYWRPbmx5UmFuZ2VzKGRvYywgZnJvbSwgdG8pIHtcbiAgICB2YXIgbWFya2VycyA9IG51bGw7XG4gICAgZG9jLml0ZXIoZnJvbS5saW5lLCB0by5saW5lICsgMSwgZnVuY3Rpb24obGluZSkge1xuICAgICAgaWYgKGxpbmUubWFya2VkU3BhbnMpIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZS5tYXJrZWRTcGFucy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2Y
23459XIgbWFyayA9IGxpbmUubWFya2VkU3BhbnNbaV0ubWFya2VyO1xuICAgICAgICBpZiAobWFyay5yZWFkT25seSAmJiAoIW1hcmtlcnMgfHwgaW5kZXhPZihtYXJrZXJzLCBtYXJrKSA9PSAtMSkpXG4gICAgICAgICAgKG1hcmtlcnMgfHwgKG1hcmtlcnMgPSBbXSkpLnB1c2gobWFyayk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKCFtYXJrZXJzKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgcGFydHMgPSBbe2Zyb206IGZyb20sIHRvOiB0b31dO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFya2Vycy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIG1rID0gbWFya2Vyc1tpXSwgbSA9IG1rLmZpbmQoMCk7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHBhcnRzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIHZhciBwID0gcGFydHNbal07XG4gICAgICAgIGlmIChjbXAocC50bywgbS5mcm9tKSA8IDAgfHwgY21wKHAuZnJvbSwgbS50bykgPiAwKSBjb250aW51ZTtcbiAgICAgICAgdmFyIG5ld1BhcnRzID0gW2osIDFdLCBkZnJvbSA9IGNtcChwLmZyb20sIG0uZnJvbSksIGR0byA9IGNtcChwLnRvLCBtLnRvKTtcbiAgICAgICAgaWYgKGRmcm9tIDwgMCB8fCAhbWsuaW5jbHVzaXZlTGVmdCAmJiAhZGZyb20pXG4gICAgICAgICAgbmV3UGFydHMucHVzaCh7ZnJvbTogcC5mcm9tLCB0bzogbS5mcm9tfSk7XG4gICAgICAgIGlmIChkdG8gPiAwIHx8ICFtay5pbmNsdXNpdmVSaWdodCAmJiAhZHRvKVxuICAgICAgICAgIG5ld1BhcnRzLnB1c2goe2Zyb206IG0udG8sIHRvOiBwLnRvfSk7XG4gICAgICAgIHBhcnRzLnNwbGljZS5hcHBseShwYXJ0cywgbmV3UGFydHMpO1xuICAgICAgICBqICs9IG5ld1BhcnRzLmxlbmd0aCAtIDE7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0cztcbiAgfVxuXG4gIC8vIENvbm5lY3Qgb3IgZGlzY29ubmVjdCBzcGFucyBmcm9tIGEgbGluZS5cbiAgZnVuY3Rpb24gZGV0YWNoTWFya2VkU3BhbnMobGluZSkge1xuICAgIHZhciBzcGFucyA9IGxpbmUubWFya2VkU3BhbnM7XG4gICAgaWYgKCFzcGFucykgcmV0dXJuO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpXG4gICAgICBzcGFuc1tpXS5tYXJrZXIuZGV0YWNoTGluZShsaW5lKTtcbiAgICBsaW5lLm1hcmtlZFNwYW5zID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBhdHRhY2hNYXJrZWRTcGFucyhsaW5lLCBzcGFucykge1xuICAgIGlmICghc3BhbnMpIHJldHVybjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgKytpKVxuICAgICAgc3BhbnNbaV0ubWFya2VyLmF0dGFjaExpbmUobGluZSk7XG4gICAgbGluZS5tYXJrZWRTcGFucyA9IHNwYW5zO1xuICB9XG5cbiAgLy8gSGVscGVycyB1c2VkIHdoZW4gY29tcHV0aW5nIHdoaWNoIG92ZXJsYXBwaW5nIGNvbGxhcHNlZCBzcGFuXG4gIC8vIGNvdW50cyBhcyB0aGUgbGFyZ2VyIG9uZS5cbiAgZnVuY3Rpb24gZXh0cmFMZWZ0KG1hcmtlcikgeyByZXR1cm4gbWFya2VyLmluY2x1c2l2ZUxlZnQgPyAtMSA6IDA7IH1cbiAgZnVuY3Rpb24gZXh0cmFSaWdodChtYXJrZXIpIHsgcmV0dXJuIG1hcmtlci5pbmNsdXNpdmVSaWdodCA/IDEgOiAwOyB9XG5cbiAgLy8gUmV0dXJucyBhIG51bWJlciBpbmRpY2F0aW5nIHdoaWNoIG9mIHR3byBvdmVybGFwcGluZyBjb2xsYXBzZWRcbiAgLy8gc3BhbnMgaXMgbGFyZ2VyIChhbmQgdGh1cyBpbmNsdWRlcyB0aGUgb3RoZXIpLiBGYWxscyBiYWNrIHRvXG4gIC8vIGNvbXBhcmluZyBpZHMgd2hlbiB0aGUgc3BhbnMgY292ZXIgZXhhY3RseSB0aGUgc2FtZSByYW5nZS5cbiAgZnVuY3Rpb24gY29tcGFyZUNvbGxhcHNlZE1hcmtlcnMoYSwgYikge1xuICAgIHZhciBsZW5EaWZmID0gYS5saW5lcy5sZW5ndGggLSBiLmxpbmVzLmxlbmd0aDtcbiAgICBpZiAobGVuRGlmZiAhPSAwKSByZXR1cm4gbGVuRGlmZjtcbiAgICB2YXIgYVBvcyA9IGEuZmluZCgpLCBiUG9zID0gYi5maW5kKCk7XG4gICAgdmFyIGZyb21DbXAgPSBjbXAoYVBvcy5mcm9tLCBiUG9zLmZyb20pIHx8IGV4dHJhTGVmdChhKSAtIGV4dHJhTGVmdChiKTtcbiAgICBpZiAoZnJvbUNtcCkgcmV0dXJuIC1mcm9tQ21wO1xuICAgIHZhciB0b0NtcCA9IGNtcChhUG9zLnRvLCBiUG9zLnRvKSB8fCBleHRyYVJpZ2h0KGEpIC0gZXh0cmFSaWdodChiKTtcbiAgICBpZiAodG9DbXApIHJldHVybiB0b0NtcDtcbiAgICByZXR1cm4gYi5pZCAtIGEuaWQ7XG4gIH1cblxuICAvLyBGaW5kIG91dCB3aGV0aGVyIGEgbGluZSBlbmRzIG9yIHN0YXJ0cyBpbiBhIGNvbGxhcHNlZCBzcGFuLiBJZlxuICAvLyBzbywgcmV0dXJuIHRoZSBtYXJrZXIgZm9yIHRoYXQgc3Bhbi5cbiAgZnVuY3Rpb24gY29sbGFwc2VkU3BhbkF0U2lkZShsaW5lLCBzdGFydCkge1xuICAgIHZhciBzcHMgP
23459SBzYXdDb2xsYXBzZWRTcGFucyAmJiBsaW5lLm1hcmtlZFNwYW5zLCBmb3VuZDtcbiAgICBpZiAoc3BzKSBmb3IgKHZhciBzcCwgaSA9IDA7IGkgPCBzcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHNwID0gc3BzW2ldO1xuICAgICAgaWYgKHNwLm1hcmtlci5jb2xsYXBzZWQgJiYgKHN0YXJ0ID8gc3AuZnJvbSA6IHNwLnRvKSA9PSBudWxsICYmXG4gICAgICAgICAgKCFmb3VuZCB8fCBjb21wYXJlQ29sbGFwc2VkTWFya2Vycyhmb3VuZCwgc3AubWFya2VyKSA8IDApKVxuICAgICAgICBmb3VuZCA9IHNwLm1hcmtlcjtcbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kO1xuICB9XG4gIGZ1bmN0aW9uIGNvbGxhcHNlZFNwYW5BdFN0YXJ0KGxpbmUpIHsgcmV0dXJuIGNvbGxhcHNlZFNwYW5BdFNpZGUobGluZSwgdHJ1ZSk7IH1cbiAgZnVuY3Rpb24gY29sbGFwc2VkU3BhbkF0RW5kKGxpbmUpIHsgcmV0dXJuIGNvbGxhcHNlZFNwYW5BdFNpZGUobGluZSwgZmFsc2UpOyB9XG5cbiAgLy8gVGVzdCB3aGV0aGVyIHRoZXJlIGV4aXN0cyBhIGNvbGxhcHNlZCBzcGFuIHRoYXQgcGFydGlhbGx5XG4gIC8vIG92ZXJsYXBzIChjb3ZlcnMgdGhlIHN0YXJ0IG9yIGVuZCwgYnV0IG5vdCBib3RoKSBvZiBhIG5ldyBzcGFuLlxuICAvLyBTdWNoIG92ZXJsYXAgaXMgbm90IGFsbG93ZWQuXG4gIGZ1bmN0aW9uIGNvbmZsaWN0aW5nQ29sbGFwc2VkUmFuZ2UoZG9jLCBsaW5lTm8sIGZyb20sIHRvLCBtYXJrZXIpIHtcbiAgICB2YXIgbGluZSA9IGdldExpbmUoZG9jLCBsaW5lTm8pO1xuICAgIHZhciBzcHMgP
23459SBzYXdDb2xsYXBzZWRTcGFucyAmJiBsaW5lLm1hcmtlZFNwYW5zO1xuICAgIGlmIChzcHMpIGZvciAodmFyIGkgPSAwOyBpIDwgc3BzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgc3AgPSBzcHNbaV07XG4gICAgICBpZiAoIXNwLm1hcmtlci5jb2xsYXBzZWQpIGNvbnRpbnVlO1xuICAgICAgdmFyIGZvdW5kID0gc3AubWFya2VyLmZpbmQoMCk7XG4gICAgICB2YXIgZnJvbUNtcCA9IGNtcChmb3VuZC5mcm9tLCBmcm9tKSB8fCBleHRyYUxlZnQoc3AubWFya2VyKSAtIGV4dHJhTGVmdChtYXJrZXIpO1xuICAgICAgdmFyIHRvQ21wID0gY21wKGZvdW5kLnRvLCB0bykgfHwgZXh0cmFSaWdodChzcC5tYXJrZXIpIC0gZXh0cmFSaWdodChtYXJrZXIpO1xuICAgICAgaWYgKGZyb21DbXAgPj0gMCAmJiB0b0NtcCA8PSAwIHx8IGZyb21DbXAgPD0gMCAmJiB0b0NtcCA+PSAwKSBjb250aW51ZTtcbiAgICAgIGlmIChmcm9tQ21wIDw9IDAgJiYgKGNtcChmb3VuZC50bywgZnJvbSkgPiAwIHx8IChzcC5tYXJrZXIuaW5jbHVzaXZlUmlnaHQgJiYgbWFya2VyLmluY2x1c2l2ZUxlZnQpKSB8fFxuICAgICAgICAgIGZyb21DbXAgPj0gMCAmJiAoY21wKGZvdW5kLmZyb20sIHRvKSA8IDAgfHwgKHNwLm1hcmtlci5pbmNsdXNpdmVMZWZ0ICYmIG1hcmtlci5pbmNsdXNpdmVSaWdodCkpKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICAvLyBBIHZpc3VhbCBsaW5lIGlzIGEgbGluZSBhcyBkcmF3biBvbiB0aGUgc2NyZWVuLiBGb2xkaW5nLCBmb3JcbiAgLy8gZXhhbXBsZSwgY2FuIGNhdXNlIG11bHRpcGxlIGxvZ2ljYWwgbGluZXMgdG8gYXBwZWFyIG9uIHRoZSBzYW1lXG4gIC8vIHZpc3VhbCBsaW5lLiBUaGlzIGZpbmRzIHRoZSBzdGFydCBvZiB0aGUgdmlzdWFsIGxpbmUgdGhhdCB0aGVcbiAgLy8gZ2l2ZW4gbGluZSBpcyBwYXJ0IG9mICh1c3VhbGx5IHRoYXQgaXMgdGhlIGxpbmUgaXRzZWxmKS5cbiAgZnVuY3Rpb24gdmlzdWFsTGluZShsaW5lKSB7XG4gICAgdmFyIG1lcmdlZDtcbiAgICB3aGlsZSAobWVyZ2VkID0gY29sbGFwc2VkU3BhbkF0U3RhcnQobGluZSkpXG4gICAgICBsaW5lID0gbWVyZ2VkLmZpbmQoLTEsIHRydWUpLmxpbmU7XG4gICAgcmV0dXJuIGxpbmU7XG4gIH1cblxuICAvLyBSZXR1cm5zIGFuIGFycmF5IG9mIGxvZ2ljYWwgbGluZXMgdGhhdCBjb250aW51ZSB0aGUgdmlzdWFsIGxpbmVcbiAgLy8gc3RhcnRlZCBieSB0aGUgYXJndW1lbnQsIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBhcmUgbm8gc3VjaCBsaW5lcy5cbiAgZnVuY3Rpb24gdmlzdWFsTGluZUNvbnRpbnVlZChsaW5lKSB7XG4gICAgdmFyIG1lcmdlZCwgbGluZXM7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdEVuZChsaW5lKSkge1xuICAgICAgbGluZSA9IG1lcmdlZC5maW5kKDEsIHRydWUpLmxpbmU7XG4gICAgICAobGluZXMgfHwgKGxpbmVzID0gW10pKS5wdXNoKGxpbmUpO1xuICAgIH1cbiAgICByZXR1cm4gbGluZXM7XG4gIH1cblxuICAvLyBHZXQgdGhlIGxpbmUgbnVtYmVyIG9mIHRoZSBzdGFydCBvZiB0aGUgdmlzdWFsIGxpbmUgdGhhdCB0aGVcbiAgLy8gZ2l2ZW4gbGluZSBudW1iZXIgaXMgcGFydCBvZi5cbiAgZnVuY3Rpb24gdmlzdWFsTGluZU5vKGRvYywgbGluZU4pIHtcbiAgICB2YXIgbGluZSA9IGdldExpbmUoZG9jLCBsaW5lTiksIHZpcyA9IHZpc3VhbExpbmUobGluZSk7XG4gICAgaWYgKGxpbmUgPT0gdmlzKSByZXR1cm4gbGluZU47XG4gICAgcmV0dXJuIGxpbmVObyh2aXMpO1xuICB9XG4gIC8vIEdldCB0aGUgbGluZSBudW1iZXIgb2YgdGhlIHN0YXJ0IG9mIHRoZSBuZXh0IHZpc3VhbCBsaW5lIGFmdGVyXG4gIC8vIHRoZSBnaXZlbiBsaW5lLlxuICBmdW5jdGlvbiB2aXN1YWxMaW5lRW5kTm8oZG9jLCBsaW5lTikge1xuICAgIGlmIChsaW5lTiA+IGRvYy5sYXN0TGluZSgpKSByZXR1cm4gbGluZU47XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGRvYywgbGluZU4pLCBtZXJnZWQ7XG4gICAgaWYgKCFsaW5lSXNIaWRkZW4oZG9jLCBsaW5lKSkgcmV0dXJuIGxpbmVOO1xuICAgIHdoaWxlIChtZXJnZWQgPSBjb2xsYXBzZWRTcGFuQXRFbmQobGluZSkpXG4gICAgICBsaW5lID0gbWVyZ2VkLmZpbmQoMSwgdHJ1ZSkubGluZTtcbiAgICByZXR1cm4gbGluZU5vKGxpbmUpICsgMTtcbiAgfVxuXG4gIC8vIENvbXB1dGUgd2hldGhlciBhIGxpbmUgaXMgaGlkZGVuLiBMaW5lcyBjb3VudCBhcyBoaWRkZW4gd2hlbiB0aGV5XG4gIC8vIGFyZSBwYXJ0IG9mIGEgdmlzdWFsIGxpbmUgdGhhdCBzdGFydHMgd2l0aCBhbm90aGVyIGxpbmUsIG9yIHdoZW5cbiAgLy8gdGhleSBhcmUgZW50aXJlbHkgY292ZXJlZCBieSBjb2xsYXBzZWQsIG5vbi13aWRnZXQgc3Bhbi5cbiAgZnVuY3Rpb24gbGluZUlzSGlkZGVuKGRvYywgbGluZSkge1xuICAgIHZhciBzcHMgP
23459SBzYXdDb2xsYXBzZWRTcGFucyAmJiBsaW5lLm1hcmtlZFNwYW5zO1xuICAgIGlmIChzcHMpIGZvciAodmFyIHNwLCBpID0gMDsgaSA8IHNwcy5sZW5ndGg7ICsraSkge1xuICAgICAgc3AgPSBzcHNbaV07XG4gICAgICBpZiAoIXNwLm1hcmtlci5jb2xsYXBzZWQpIGNvbnRpbnVlO1xuICAgICAgaWYgKHNwLmZyb20gPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gICAgICBpZiAoc3AubWFya2VyLndpZGdldE5vZGUpIGNvbnRpbnVlO1xuICAgICAgaWYgKHNwLmZyb20gPT0gMCAmJiBzcC5tYXJrZXIuaW5jbHVzaXZlTGVmdCAmJiBsaW5lSXNIaWRkZW5Jbm5lcihkb2MsIGxpbmUsIHNwKSlcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGxpbmVJc0hpZGRlbklubmVyKGRvYywgbGluZSwgc3Bhbikge1xuICAgIGlmIChzcGFuLnRvID09IG51bGwpIHtcbiAgICAgIHZhciBlbmQgPSBzcGFuLm1hcmtlci5maW5kKDEsIHRydWUpO1xuICAgICAgcmV0dXJuIGxpbmVJc0hpZGRlbklubmVyKGRvYywgZW5kLmxpbmUsIGdldE1hcmtlZFNwYW5Gb3IoZW5kLmxpbmUubWFya2VkU3BhbnMsIHNwYW4ubWFya2VyKSk7XG4gICAgfVxuICAgIGlmIChzcGFuLm1hcmtlci5pbmNsdXNpdmVSaWdodCAmJiBzcGFuLnRvID09IGxpbmUudGV4dC5sZW5ndGgpXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICBmb3IgKHZhciBzcCwgaSA9IDA7IGkgPCBsaW5lLm1hcmtlZFNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICBzcCA9IGxpbmUubWFya2VkU3BhbnNbaV07XG4gICAgICBpZiAoc3AubWFya2VyLmNvbGxhcHNlZCAmJiAhc3AubWFya2VyLndpZGdldE5vZGUgJiYgc3AuZnJvbSA9PSBzcGFuLnRvICYmXG4gICAgICAgICAgKHNwLnRvID09IG51bGwgfHwgc3AudG8gIT0gc3Bhbi5mcm9tKSAmJlxuICAgICAgICAgIChzcC5tYXJrZXIuaW5jbHVzaXZlTGVmdCB8fCBzcGFuLm1hcmtlci5pbmNsdXNpdmVSaWdodCkgJiZcbiAgICAgICAgICBsaW5lSXNIaWRkZW5Jbm5lcihkb2MsIGxpbmUsIHNwKSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gTElORSBXSURHRVRTXG5cbiAgLy8gTGluZSB3aWRnZXRzIGFyZSBibG9jayBlbGVtZW50cyBkaXNwbGF5ZWQgYWJvdmUgb3IgYmVsb3cgYSBsaW5lLlxuXG4gIHZhciBMaW5lV2lkZ2V0ID0gQ29kZU1pcnJvci5MaW5lV2lkZ2V0ID0gZnVuY3Rpb24oZG9jLCBub2RlLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMpIGZvciAodmFyIG9wdCBpbiBvcHRpb25zKSBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHQpKVxuICAgICAgdGhpc1tvcHRdID0gb3B0aW9uc1tvcHRdO1xuICAgIHRoaXMuZG9jID0gZG9jO1xuICAgIHRoaXMubm9kZSA9IG5vZGU7XG4gIH07XG4gIGV2ZW50TWl4aW4oTGluZVdpZGdldCk7XG5cbiAgZnVuY3Rpb24gYWRqdXN0U2Nyb2xsV2hlbkFib3ZlVmlzaWJsZShjbSwgbGluZSwgZGlmZikge1xuICAgIGlmIChoZWlnaHRBdExpbmUobGluZSkgPCAoKGNtLmN1ck9wICYmIGNtLmN1ck9wLnNjcm9sbFRvcCkgfHwgY20uZG9jLnNjcm9sbFRvcCkpXG4gICAgICBhZGRUb1Njcm9sbFBvcyhjbSwgbnVsbCwgZGlmZik7XG4gIH1cblxuICBMaW5lV2lkZ2V0LnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjbSA9IHRoaXMuZG9jLmNtLCB3cyA9IHRoaXMubGluZS53aWRnZXRzLCBsaW5lID0gdGhpcy5saW5lLCBubyA9IGxpbmVObyhsaW5lKTtcbiAgICBpZiAobm8gPT0gbnVsbCB8fCAhd3MpIHJldHVybjtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHdzLmxlbmd0aDsgKytpKSBpZiAod3NbaV0gPT0gdGhpcykgd3Muc3BsaWNlKGktLSwgMSk7XG4gICAgaWYgKCF3cy5sZW5ndGgpIGxpbmUud2lkZ2V0cyA9IG51bGw7XG4gICAgdmFyIGhlaWdodCA9IHdpZGdldEhlaWdodCh0aGlzKTtcbiAgICB1cGRhdGVMaW5lSGVpZ2h0KGxpbmUsIE1hdGgubWF4KDAsIGxpbmUuaGVpZ2h0IC0gaGVpZ2h0KSk7XG4gICAgaWYgKGNtKSBydW5Jbk9wKGNtLCBmdW5jdGlvbigpIHtcbiAgICAgIGFkanVzdFNjcm9sbFdoZW5BYm92ZVZpc2libGUoY20sIGxpbmUsIC1oZWlnaHQpO1xuICAgICAgcmVnTGluZUNoYW5nZShjbSwgbm8sIFwid2lkZ2V0XCIpO1xuICAgIH0pO1xuICB9O1xuICBMaW5lV2lkZ2V0LnByb3RvdHlwZS5jaGFuZ2VkI
23459D0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG9sZEggPSB0aGlzLmhlaWdodCwgY20gPSB0aGlzLmRvYy5jbSwgbGluZSA9IHRoaXMubGluZTtcbiAgICB0aGlzLmhlaWdodCA9IG51bGw7XG4gICAgdmFyIGRpZmYgPSB3aWRnZXRIZWlnaHQodGhpcykgLSBvbGRIO1xuICAgIGlmICghZGlmZikgcmV0dXJuO1xuICAgIHVwZGF0ZUxpbmVIZWlnaHQobGluZSwgbGluZS5oZWlnaHQgKyBkaWZmKTtcbiAgICBpZiAoY20pIHJ1bkluT3AoY20sIGZ1bmN0aW9uKCkge1xuICAgICAgY20uY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgICAgYWRqdXN0U2Nyb2xsV2hlbkFib3ZlVmlzaWJsZShjbSwgbGluZSwgZGlmZik7XG4gICAgfSk7XG4gIH07XG5cbiAgZnVuY3Rpb24gd2lkZ2V0SGVpZ2h0KHdpZGdldCkge1xuICAgIGlmICh3aWRnZXQuaGVpZ2h0ICE9IG51bGwpIHJldHVybiB3aWRnZXQuaGVpZ2h0O1xuICAgIHZhciBjbSA9IHdpZGdldC5kb2MuY207XG4gICAgaWYgKCFjbSkgcmV0dXJuIDA7XG4gICAgaWYgKCFjb250YWlucyhkb2N1bWVudC5ib2R5LCB3aWRnZXQubm9kZSkpIHtcbiAgICAgIHZhciBwYXJlbnRTdHlsZSA9IFwicG9zaXRpb246IHJlbGF0aXZlO1wiO1xuICAgICAgaWYgKHdpZGdldC5jb3Zlckd1dHRlcilcbiAgICAgICAgcGFyZW50U3R5bGUgKz0gXCJtYXJnaW4tbGVmdDogLVwiICsgY20uZGlzcGxheS5ndXR0ZXJzLm9mZnNldFdpZHRoICsgXCJweDtcIjtcbiAgICAgIGlmICh3aWRnZXQubm9IU2Nyb2xsKVxuICAgICAgICBwYXJlbnRTdHlsZSArPSBcIndpZHRoOiBcIiArIGNtLmRpc3BsYXkud3JhcHBlci5jbGllbnRXaWR0aCArIFwicHg7XCI7XG4gICAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChjbS5kaXNwbGF5Lm1lYXN1cmUsIGVsdChcImRpdlwiLCBbd2lkZ2V0Lm5vZGVdLCBudWxsLCBwYXJlbnRTdHlsZSkpO1xuICAgIH1cbiAgICByZXR1cm4gd2lkZ2V0LmhlaWdodCA9IHdpZGdldC5u
vendor: 13,023 bytes, line 23459
23459b2RlLm9mZnNldEhlaWdodDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZExpbmVXaWRnZXQoZG9jLCBoYW5kbGUsIG5vZGUsIG9wdGlvbnMpIHtcbiAgICB2YXIgd2lkZ2V0ID0gbmV3IExpbmVXaWRnZXQoZG9jLCBub2RlLCBvcHRpb25zKTtcbiAgICB2YXIgY20gPSBkb2MuY207XG4gICAgaWYgKGNtICYmIHdpZGdldC5ub0hTY3JvbGwpIGNtLmRpc3BsYXkuYWxpZ25XaWRnZXRzID0gdHJ1ZTtcbiAgICBjaGFuZ2VMaW5lKGRvYywgaGFuZGxlLCBcIndpZGdldFwiLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICB2YXIgd2lkZ2V0cyA9IGxpbmUud2lkZ2V0cyB8fCAobGluZS53aWRnZXRzID0gW10pO1xuICAgICAgaWYgKHdpZGdldC5pbnNlcnRBdCA9PSBudWxsKSB3aWRnZXRzLnB1c2god2lkZ2V0KTtcbiAgICAgIGVsc2Ugd2lkZ2V0cy5zcGxpY2UoTWF0aC5taW4od2lkZ2V0cy5sZW5ndGggLSAxLCBNYXRoLm1heCgwLCB3aWRnZXQuaW5zZXJ0QXQpKSwgMCwgd2lkZ2V0KTtcbiAgICAgIHdpZGdldC5saW5lID0gbGluZTtcbiAgICAgIGlmIChjbSAmJiAhbGluZUlzSGlkZGVuKGRvYywgbGluZSkpIHtcbiAgICAgICAgdmFyIGFib3ZlVmlzaWJsZSA9IGhlaWdodEF0TGluZShsaW5lKSA8IGRvYy5zY3JvbGxUb3A7XG4gICAgICAgIHVwZGF0ZUxpbmVIZWlnaHQobGluZSwgbGluZS5oZWlnaHQgKyB3aWRnZXRIZWlnaHQod2lkZ2V0KSk7XG4gICAgICAgIGlmIChhYm92ZVZpc2libGUpIGFkZFRvU2Nyb2xsUG9zKGNtLCBudWxsLCB3aWRnZXQuaGVpZ2h0KTtcbiAgICAgICAgY20uY3VyT3AuZm9yY2VVcGRhdGUgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gICAgcmV0dXJuIHdpZGdldDtcbiAgfVxuXG4gIC8vIExJTkUgREFUQSBTVFJVQ1RVUkVcblxuICAvLyBMaW5lIG9iamVjdHMuIFRoZXNlIGhvbGQgc3RhdGUgcmVsYXRlZCB0byBhIGxpbmUsIGluY2x1ZGluZ1xuICAvLyBoaWdobGlnaHRpbmcgaW5mbyAodGhlIHN0eWxlcyBhcnJheSkuXG4gIHZhciBMaW5lID0gQ29kZU1pcnJvci5MaW5lID0gZnVuY3Rpb24odGV4dCwgbWFya2VkU3BhbnMsIGVzdGltYXRlSGVpZ2h0KSB7XG4gICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICBhdHRhY2hNYXJrZWRTcGFucyh0aGlzLCBtYXJrZWRTcGFucyk7XG4gICAgdGhpcy5oZWlnaHQgPSBlc3RpbWF0ZUhlaWdodCA/IGVzdGltYXRlSGVpZ2h0KHRoaXMpIDogMTtcbiAgfTtcbiAgZXZlbnRNaXhpbihMaW5lKTtcbiAgTGluZS5wcm90b3R5cGUubGluZU5vID0gZnVuY3Rpb24oKSB7IHJldHVybiBsaW5lTm8odGhpcyk7IH07XG5cbiAgLy8gQ2hhbmdlIHRoZSBjb250ZW50ICh0ZXh0LCBtYXJrZXJzKSBvZiBhIGxpbmUuIEF1dG9tYXRpY2FsbHlcbiAgLy8gaW52YWxpZGF0ZXMgY2FjaGVkIGluZm9ybWF0aW9uIGFuZCB0cmllcyB0byByZS1lc3RpbWF0ZSB0aGVcbiAgLy8gbGluZSdzIGhlaWdodC5cbiAgZnVuY3Rpb24gdXBkYXRlTGluZShsaW5lLCB0ZXh0LCBtYXJrZWRTcGFucywgZXN0aW1hdGVIZWlnaHQpIHtcbiAgICBsaW5lLnRleHQgPSB0ZXh0O1xuICAgIGlmIChsaW5lLnN0YXRlQWZ0ZXIpIGxpbmUuc3RhdGVBZnRlciA9IG51bGw7XG4gICAgaWYgKGxpbmUuc3R5bGVzKSBsaW5lLnN0eWxlcyA9IG51bGw7XG4gICAgaWYgKGxpbmUub3JkZXIgIT0gbnVsbCkgbGluZS5vcmRlciA9IG51bGw7XG4gICAgZGV0YWNoTWFya2VkU3BhbnMobGluZSk7XG4gICAgYXR0YWNoTWFya2VkU3BhbnMobGluZSwgbWFya2VkU3BhbnMpO1xuICAgIHZhciBlc3RIZWlnaHQgPSBlc3RpbWF0ZUhlaWdodCA/IGVzdGltYXRlSGVpZ2h0KGxpbmUpIDogMTtcbiAgICBpZiAoZXN0SGVpZ2h0ICE9IGxpbmUuaGVpZ2h0KSB1cGRhdGVMaW5lSGVpZ2h0KGxpbmUsIGVzdEhlaWdodCk7XG4gIH1cblxuICAvLyBEZXRhY2ggYSBsaW5lIGZyb20gdGhlIGRvY3VtZW50IHRyZWUgYW5kIGl0cyBtYXJrZXJzLlxuICBmdW5jdGlvbiBjbGVhblVwTGluZShsaW5lKSB7XG4gICAgbGluZS5wYXJlbnQgPSBudWxsO1xuICAgIGRldGFjaE1hcmtlZFNwYW5zKGxpbmUpO1xuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdExpbmVDbGFzc2VzKHR5cGUsIG91dHB1dCkge1xuICAgIGlmICh0eXBlKSBmb3IgKDs7KSB7XG4gICAgICB2YXIgbGluZUNsYXNzID0gdHlwZS5tYXRjaCgvKD86XnxcXHMrKWxpbmUtKGJhY2tncm91bmQtKT8oXFxTKykvKTtcbiAgICAgIGlmICghbGluZUNsYXNzKSBicmVhaztcbiAgICAgIHR5cGUgPSB0eXBlLnNsaWNlKDAsIGxpbmVDbGFzcy5pbmRleCkgKyB0eXBlLnNsaWNlKGxpbmVDbGFzcy5pbmRleCArIGxpbmVDbGFzc1swXS5sZW5ndGgpO1xuICAgICAgdmFyIHByb3AgPSBsaW5lQ2xhc3NbMV0gPyBcImJnQ2xhc3NcIiA6IFwidGV4dENsYXNzXCI7XG4gICAgICBpZiAob3V0cHV0W3Byb3BdID09IG51bGwpXG4gICAgICAgIG91dHB1dFtwcm9wXSA9IGxpbmVDbGFzc1syXTtcbiAgICAgIGVsc2UgaWYgKCEobmV3IFJlZ0V4cChcIig/Ol58XFxzKVwiICsgbGluZUNsYXNzWzJdICsgXCIoPzokfFxccylcIikpLnRlc3Qob3V0cHV0W3Byb3BdKSlcbiAgICAgICAgb3V0cHV0W3Byb3BdICs9IFwiIFwiICsgbGluZUNsYXNzWzJdO1xuICAgIH1cbiAgICByZXR1cm4gdHlwZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGxCbGFua0xpbmUobW9kZSwgc3RhdGUpIHtcbiAgICBpZiAobW9kZS5ibGFua0xpbmUpIHJldHVybiBtb2RlLmJsYW5rTGluZShzdGF0ZSk7XG4gICAgaWYgKCFtb2RlLmlubmVyTW9kZSkgcmV0dXJuO1xuICAgIHZhciBpbm5lciA9IENvZGVNaXJyb3IuaW5uZXJNb2RlKG1vZGUsIHN0YXRlKTtcbiAgICBpZiAoaW5uZXIubW9kZS5ibGFua0xpbmUpIHJldHVybiBpbm5lci5tb2RlLmJsYW5rTGluZShpbm5lci5zdGF0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiByZWFkVG9rZW4obW9kZSwgc3RyZWFtLCBzdGF0ZSwgaW5uZXIpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDEwOyBpKyspIHtcbiAgICAgIGlmIChpbm5lcikgaW5uZXJbMF0gPSBDb2RlTWlycm9yLmlubmVyTW9kZShtb2RlLCBzdGF0ZSkubW9kZTtcbiAgICAgIHZhciBzdHlsZSA9IG1vZGUudG9rZW4oc3RyZWFtLCBzdGF0ZSk7XG4gICAgICBpZiAoc3RyZWFtLnBvcyA+IHN0cmVhbS5zdGFydCkgcmV0dXJuIHN0eWxlO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJNb2RlIFwiICsgbW9kZS5uYW1lICsgXCIgZmFpbGVkIHRvIGFkdmFuY2Ugc3RyZWFtLlwiKTtcbiAgfVxuXG4gIC8vIFV0aWxpdHkgZm9yIGdldFRva2VuQXQgYW5kIGdldExpbmVUb2tlbnNcbiAgZnVuY3Rpb24gdGFrZVRva2VuKGNtLCBwb3MsIHByZWNpc2UsIGFzQXJyYXkpIHtcbiAgICBmdW5jdGlvbiBnZXRPYmooY29weSkge1xuICAgICAgcmV0dXJuIHtzdGFydDogc3RyZWFtLnN0YXJ0LCBlbmQ6IHN0cmVhbS5wb3MsXG4gICAgICAgICAgICAgIHN0cmluZzogc3RyZWFtLmN1cnJlbnQoKSxcbiAgICAgICAgICAgICAgdHlwZTogc3R5bGUgfHwgbnVsbCxcbiAgICAgICAgICAgICAgc3RhdGU6IGNvcHkgPyBjb3B5U3RhdGUoZG9jLm1vZGUsIHN0YXRlKSA6IHN0YXRlfTtcbiAgICB9XG5cbiAgICB2YXIgZG9jID0gY20uZG9jLCBtb2RlID0gZG9jLm1vZGUsIHN0eWxlO1xuICAgIHBvcyA9IGNsaXBQb3MoZG9jLCBwb3MpO1xuICAgIHZhciBsaW5lID0gZ2V0TGluZShkb2MsIHBvcy5saW5lKSwgc3RhdGUgPSBnZXRTdGF0ZUJlZm9yZShjbSwgcG9zLmxpbmUsIHByZWNpc2UpO1xuICAgIHZhciBzdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKGxpbmUudGV4dCwgY20ub3B0aW9ucy50YWJTaXplKSwgdG9rZW5zO1xuICAgIGlmIChhc0FycmF5KSB0b2tlbnMgPSBbXTtcbiAgICB3aGlsZSAoKGFzQXJyYXkgfHwgc3RyZWFtLnBvcyA8IHBvcy5jaCkgJiYgIXN0cmVhbS5lb2woKSkge1xuICAgICAgc3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcbiAgICAgIHN0eWxlID0gcmVhZFRva2VuKG1vZGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgICAgaWYgKGFzQXJyYXkpIHRva2Vucy5wdXNoKGdldE9iaih0cnVlKSk7XG4gICAgfVxuICAgIHJldHVybiBhc0FycmF5ID8gdG9rZW5zIDogZ2V0T2JqKCk7XG4gIH1cblxuICAvLyBSdW4gdGhlIGdpdmVuIG1vZGUncyBwYXJzZXIgb3ZlciBhIGxpbmUsIGNhbGxpbmcgZiBmb3IgZWFjaCB0b2tlbi5cbiAgZnVuY3Rpb24gcnVuTW9kZShjbSwgdGV4dCwgbW9kZSwgc3RhdGUsIGYsIGxpbmVDbGFzc2VzLCBmb3JjZVRvRW5kKSB7XG4gICAgdmFyIGZsYXR0ZW5TcGFucyA9IG1vZGUuZmxhdHRlblNwYW5zO1xuICAgIGlmIChmbGF0dGVuU3BhbnMgPT0gbnVsbCkgZmxhdHRlblNwYW5zID0gY20ub3B0aW9ucy5mbGF0dGVuU3BhbnM7XG4gICAgdmFyIGN1clN0YXJ0ID0gMCwgY3VyU3R5bGUgPSBudWxsO1xuICAgIHZhciBzdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKHRleHQsIGNtLm9wdGlvbnMudGFiU2l6ZSksIHN0eWxlO1xuICAgIHZhciBpbm5lciA9IGNtLm9wdGlvbnMuYWRkTW9kZUNsYXNzICYmIFtudWxsXTtcbiAgICBpZiAodGV4dCA9PSBcIlwiKSBleHRyYWN0TGluZUNsYXNzZXMoY2FsbEJsYW5rTGluZShtb2RlLCBzdGF0ZSksIGxpbmVDbGFzc2VzKTtcbiAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSkge1xuICAgICAgaWYgKHN0cmVhbS5wb3MgPiBjbS5vcHRpb25zLm1heEhpZ2hsaWdodExlbmd0aCkge1xuICAgICAgICBmbGF0dGVuU3BhbnMgPSBmYWxzZTtcbiAgICAgICAgaWYgKGZvcmNlVG9FbmQpIHByb2Nlc3NMaW5lKGNtLCB0ZXh0LCBzdGF0ZSwgc3RyZWFtLnBvcyk7XG4gICAgICAgIHN0cmVhbS5wb3MgPSB0ZXh0Lmxlbmd0aDtcbiAgICAgICAgc3R5bGUgPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3R5bGUgPSBleHRyYWN0TGluZUNsYXNzZXMocmVhZFRva2VuKG1vZGUsIHN0cmVhbSwgc3RhdGUsIGlubmVyKSwgbGluZUNsYXNzZXMpO1xuICAgICAgfVxuICAgICAgaWYgKGlubmVyKSB7XG4gICAgICAgIHZhciBtTmFtZSA9IGlubmVyWzBdLm5hbWU7XG4gICAgICAgIGlmIChtTmFtZSkgc3R5bGUgPSBcIm0tXCIgKyAoc3R5bGUgPyBtTmFtZSArIFwiIFwiICsgc3R5bGUgOiBtTmFtZSk7XG4gICAgICB9XG4gICAgICBpZiAoIWZsYXR0ZW5TcGFucyB8fCBjdXJTdHlsZSAhPSBzdHlsZSkge1xuICAgICAgICB3aGlsZSAoY3VyU3RhcnQgPCBzdHJlYW0uc3RhcnQpIHtcbiAgICAgICAgICBjdXJTdGFydCA9IE1hdGgubWluKHN0cmVhbS5zdGFydCwgY3VyU3RhcnQgKyA1MDAwMCk7XG4gICAgICAgICAgZihjdXJTdGFydCwgY3VyU3R5bGUpO1xuICAgICAgICB9XG4gICAgICAgIGN1clN0eWxlID0gc3R5bGU7XG4gICAgICB9XG4gICAgICBzdHJlYW0uc3RhcnQgPSBzdHJlYW0ucG9zO1xuICAgIH1cbiAgICB3aGlsZSAoY3VyU3RhcnQgPCBzdHJlYW0ucG9zKSB7XG4gICAgICAvLyBXZWJraXQgc2VlbXMgdG8gcmVmdXNlIHRvIHJlbmRlciB0ZXh0IG5vZGVzIGxvbmdlciB0aGFuIDU3NDQ0IGNoYXJhY3RlcnNcbiAgICAgIHZhciBwb3MgPSBNYXRoLm1pbihzdHJlYW0ucG9zLCBjdXJTdGFydCArIDUwMDAwKTtcbiAgICAgIGYocG9zLCBjdXJTdHlsZSk7XG4gICAgICBjdXJTdGFydCA9IHBvcztcbiAgICB9XG4gIH1cblxuICAvLyBDb21wdXRlIGEgc3R5bGUgYXJyYXkgKGFuIGFycmF5IHN0YXJ0aW5nIHdpdGggYSBtb2RlIGdlbmVyYXRpb25cbiAgLy8gLS0gZm9yIGludmFsaWRhdGlvbiAtLSBmb2xsb3dlZCBieSBwYWlycyBvZiBlbmQgcG9zaXRpb25zIGFuZFxuICAvLyBzdHlsZSBzdHJpbmdzKSwgd2hpY2ggaXMgdXNlZCB0byBoaWdobGlnaHQgdGhlIHRva2VucyBvbiB0aGVcbiAgLy8gbGluZS5cbiAgZnVuY3Rpb24gaGlnaGxpZ2h0TGluZShjbSwgbGluZSwgc3RhdGUsIGZvcmNlVG9FbmQpIHtcbiAgICAvLyBBIHN0eWxlcyBhcnJheSBhbHdheXMgc3RhcnRzIHdpdGggYSBudW1iZXIgaWRlbnRpZnlpbmcgdGhlXG4gICAgLy8gbW9kZS9vdmVybGF5cyB0aGF0IGl0IGlzIGJhc2VkIG9uIChmb3IgZWFzeSBpbnZhbGlkYXRpb24pLlxuICAgIHZhciBzdCA9IFtjbS5zdGF0ZS5tb2RlR2VuXSwgbGluZUNsYXNzZXMgPSB7fTtcbiAgICAvLyBDb21wdXRlIHRoZSBiYXNlIGFycmF5IG9mIHN0eWxlc1xuICAgIHJ1bk1vZGUoY20sIGxpbmUudGV4dCwgY20uZG9jLm1vZGUsIHN0YXRlLCBmdW5jdGlvbihlbmQsIHN0eWxlKSB7XG4gICAgICBzdC5wdXNoKGVuZCwgc3R5bGUpO1xuICAgIH0sIGxpbmVDbGFzc2VzLCBmb3JjZVRvRW5kKTtcblxuICAgIC8vIFJ1biBvdmVybGF5cywgYWRqdXN0IHN0eWxlIGFycmF5LlxuICAgIGZvciAodmFyIG8gPSAwOyBvIDwgY20uc3RhdGUub3ZlcmxheXMubGVuZ3RoOyArK28pIHtcbiAgICAgIHZhciBvdmVybGF5ID0gY20uc3RhdGUub3ZlcmxheXNbb10sIGkgPSAxLCBhdCA9IDA7XG4gICAgICBydW5Nb2RlKGNtLCBsaW5lLnRleHQsIG92ZXJsYXkubW9kZSwgdHJ1ZSwgZnVuY3Rpb24oZW5kLCBzdHlsZSkge1xuICAgICAgICB2YXIgc3RhcnQgPSBpO1xuICAgICAgICAvLyBFbnN1cmUgdGhlcmUncyBhIHRva2VuIGVuZCBhdCB0aGUgY3VycmVudCBwb3NpdGlvbiwgYW5kIHRoYXQgaSBwb2ludHMgYXQgaXRcbiAgICAgICAgd2hpbGUgKGF0IDwgZW5kKSB7XG4gICAgICAgICAgdmFyIGlfZW5kID0gc3RbaV07XG4gICAgICAgICAgaWYgKGlfZW5kID4gZW5kKVxuICAgICAgICAgICAgc3Quc3BsaWNlKGksIDEsIGVuZCwgc3RbaSsxXSwgaV9lbmQpO1xuICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICBhdCA9IE1hdGgubWluKGVuZCwgaV9lbmQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3R5bGUpIHJldHVybjtcbiAgICAgICAgaWYgKG92ZXJsYXkub3BhcXVlKSB7XG4gICAgICAgICAgc3Quc3BsaWNlKHN0YXJ0LCBpIC0gc3RhcnQsIGVuZCwgXCJjbS1vdmVybGF5IFwiICsgc3R5bGUpO1xuICAgICAgICAgIGkgPSBzdGFydCArIDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yICg7IHN0YXJ0IDwgaTsgc3RhcnQgKz0gMikge1xuICAgICAgICAgICAgdmFyIGN1ciA9IHN0W3N0YXJ0KzFdO1xuICAgICAgICAgICAgc3Rbc3RhcnQrMV0gPSAoY3VyID8gY3VyICsgXCIgXCIgOiBcIlwiKSArIFwiY20tb3ZlcmxheSBcIiArIHN0eWxlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgbGluZUNsYXNzZXMpO1xuICAgIH1cblxuICAgIHJldHVybiB7c3R5bGVzOiBzdCwgY2xhc3NlczogbGluZUNsYXNzZXMuYmdDbGFzcyB8fCBsaW5lQ2xhc3Nlcy50ZXh0Q2xhc3MgPyBsaW5lQ2xhc3NlcyA6IG51bGx9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0TGluZVN0eWxlcyhjbSwgbGluZSwgdXBkYXRlRnJvbnRpZXIpIHtcbiAgICBpZiAoIWxpbmUuc3R5bGVzIHx8IGxpbmUuc3R5bGVzWzBdICE9IGNtLnN0YXRlLm1vZGVHZW4pIHtcbiAgICAgIHZhciBzdGF0ZSA9IGdldFN0YXRlQmVmb3JlKGNtLCBsaW5lTm8obGluZSkpO1xuICAgICAgdmFyIHJlc3VsdCA9IGhpZ2hsaWdodExpbmUoY20sIGxpbmUsIGxpbmUudGV4dC5sZW5ndGggPiBjbS5vcHRpb25zLm1heEhpZ2hsaWdodExlbmd0aCA/IGNvcHlTdGF0ZShjbS5kb2MubW9kZSwgc3RhdGUpIDogc3RhdGUpO1xuICAgICAgbGluZS5zdGF0ZUFmdGVyID0gc3RhdGU7XG4gICAgICBsaW5lLnN0eWxlcyA9IHJlc3VsdC5zdHlsZXM7XG4gICAgICBpZiAocmVzdWx0LmNsYXNzZXMpIGxpbmUuc3R5bGVDbGFzc2VzID0gcmVzdWx0LmNsYXNzZXM7XG4gICAgICBlbHNlIGlmIChsaW5lLnN0eWxlQ2xhc3NlcykgbGluZS5zdHlsZUNsYXNzZXMgPSBudWxsO1xuICAgICAgaWYgKHVwZGF0ZUZyb250aWVyID09PSBjbS5kb2MuZnJvbnRpZXIpIGNtLmRvYy5mcm9udGllcisrO1xuICAgIH1cbiAgICByZXR1cm4gbGluZS5zdHlsZXM7XG4gIH1cblxuICAvLyBMaWdodHdlaWdodCBmb3JtIG9mIGhpZ2hsaWdodCAtLSBwcm9jZWVkIG92ZXIgdGhpcyBsaW5lIGFuZFxuICAvLyB1cGRhdGUgc3RhdGUsIGJ1dCBkb24ndCBzYXZlIGEgc3R5bGUgYXJyYXkuIFVzZWQgZm9yIGxpbmVzIHRoYXRcbiAgLy8gYXJlbid0IGN1cnJlbnRseSB2aXNpYmxlLlxuICBmdW5jdGlvbiBwcm9jZXNzTGluZShjbSwgdGV4dCwgc3RhdGUsIHN0YXJ0QXQpIHtcbiAgICB2YXIgbW9kZSA9IGNtLmRvYy5tb2RlO1xuICAgIHZhciBzdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKHRleHQsIGNtLm9wdGlvbnMudGFiU2l6ZSk7XG4gICAgc3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcyA9IHN0YXJ0QXQgfHwgMDtcbiAgICBpZiAodGV4dCA9PSBcIlwiKSBjYWxsQmxhbmtMaW5lKG1vZGUsIHN0YXRlKTtcbiAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSkge1xuICAgICAgcmVhZFRva2VuKG1vZGUsIHN0cmVhbSwgc3RhdGUpO1xuICAgICAgc3RyZWFtLnN0YXJ0ID0gc3RyZWFtLnBvcztcbiAgICB9XG4gIH1cblxuICAvLyBDb252ZXJ0IGEgc3R5bGUgYXMgcmV0dXJuZWQgYnkgYSBtb2RlIChlaXRoZXIgbnVsbCwgb3IgYSBzdHJpbmdcbiAgLy8gY29udGFpbmluZyBvbmUgb3IgbW9yZSBzdHlsZXMpIHRvIGEgQ1NTIHN0eWxlLiBUaGlzIGlzIGNhY2hlZCxcbiAgLy8gYW5kIGFsc28gbG9va3MgZm9yIGxpbmUtd2lkZSBzdHlsZXMuXG4gIHZhciBzdHlsZVRvQ2xhc3NDYWNoZSA9IHt9LCBzdHlsZVRvQ2xhc3NDYWNoZVdpdGhNb2RlID0ge307XG4gIGZ1bmN0aW9uIGludGVycHJldFRva2VuU3R5bGUoc3R5bGUsIG9wdGlvbnMpIHtcbiAgICBpZiAoIXN0eWxlIHx8IC9eXFxzKiQvLnRlc3Qoc3R5bGUpKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgY2FjaGUgPSBvcHRpb25zLmFkZE1vZGVDbGFzcyA/IHN0eWxlVG9DbGFzc0NhY2hlV2l0aE1vZGUgOiBzdHlsZVRvQ2xhc3NDYWNoZTtcbiAgICByZXR1cm4gY2FjaGVbc3R5bGVdIHx8XG4gICAgICAoY2FjaGVbc3R5bGVdID0gc3R5bGUucmVwbGFjZSgvXFxTKy9nLCBcImNtLSQmXCIpKTtcbiAgfVxuXG4gIC8vIFJlbmRlciB0aGUgRE9NIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0ZXh0IG9mIGEgbGluZS4gQWxzbyBidWlsZHNcbiAgLy8gdXAgYSAnbGluZSBtYXAnLCB3aGljaCBwb2ludHMgYXQgdGhlIERPTSBub2RlcyB0aGF0IHJlcHJlc2VudFxuICAvLyBzcGVjaWZpYyBzdHJldGNoZXMgb2YgdGV4dCwgYW5kIGlzIHVzZWQgYnkgdGhlIG1lYXN1cmluZyBjb2RlLlxuICAvLyBUaGUgcmV0dXJuZWQgb2JqZWN0IGNvbnRhaW5zIHRoZSBET00gbm9kZSwgdGhpcyBtYXAsIGFuZFxuICAvLyBpbmZvcm1hdGlvbiBhYm91dCBsaW5lLXdpZGUgc3R5bGVzIHRoYXQgd2VyZSBzZXQgYnkgdGhlIG1vZGUuXG4gIGZ1bmN0aW9uIGJ1aWxkTGluZUNvbnRlbnQoY20sIGxpbmVWaWV3KSB7XG4gICAgLy8gVGhlIHBhZGRpbmctcmlnaHQgZm9yY2VzIHRoZSBlbGVtZW50IHRvIGhhdmUgYSAnYm9yZGVyJywgd2hpY2hcbiAgICAvLyBpcyBuZWVkZWQgb24gV2Via2l0IHRvIGJlIGFibGUgdG8gZ2V0IGxpbmUtbGV2ZWwgYm91bmRpbmdcbiAgICAvLyByZWN0YW5nbGVzIGZvciBpdCAoaW4gbWVhc3VyZUNoYXIpLlxuICAgIHZhciBjb250ZW50ID0gZWx0KFwic3BhblwiLCBudWxsLCBudWxsLCB3ZWJraXQgPyBcInBhZGRpbmctcmlnaHQ6IC4xcHhcIiA6IG51bGwpO1xuICAgIHZhciBidWlsZGVyID0ge3ByZTogZWx0KFwicHJlXCIsIFtjb250ZW50XSwgXCJDb2RlTWlycm9yLWxpbmVcIiksIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgY29sOiAwLCBwb3M6IDAsIGNtOiBjbSxcbiAgICAgICAgICAgICAgICAgICB
23459zcGxpdFNwYWNlczogKGllIHx8IHdlYmtpdCkgJiYgY20uZ2V0T3B0aW9uKFwibGluZVdyYXBwaW5nXCIpfTtcbiAgICBsaW5lVmlldy5tZWFzdXJlID0ge307XG5cbiAgICAvLyBJdGVyYXRlIG92ZXIgdGhlIGxvZ2ljYWwgbGluZXMgdGhhdCBtYWtlIHVwIHRoaXMgdmlzdWFsIGxpbmUuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gKGxpbmVWaWV3LnJlc3QgPyBsaW5lVmlldy5yZXN0Lmxlbmd0aCA6IDApOyBpKyspIHtcbiAgICAgIHZhciBsaW5lID0gaSA/IGxpbmVWaWV3LnJlc3RbaSAtIDFdIDogbGluZVZpZXcubGluZSwgb3JkZXI7XG4gICAgICBidWlsZGVyLnBvcyA9IDA7XG4gICAgICBidWlsZGVyLmFkZFRva2VuID0gYnVpbGRUb2tlbjtcbiAgICAgIC8vIE9wdGlvbmFsbHkgd2lyZSBpbiBzb21lIGhhY2tzIGludG8gdGhlIHRva2VuLXJlbmRlcmluZ1xuICAgICAgLy8gYWxnb3JpdGhtLCB0byBkZWFsIHdpdGggYnJvd3NlciBxdWlya3MuXG4gICAgICBpZiAoaGFzQmFkQmlkaVJlY3RzKGNtLmRpc3BsYXkubWVhc3VyZSkgJiYgKG9yZGVyID0gZ2V0T3JkZXIobGluZSkpKVxuICAgICAgICBidWlsZGVyLmFkZFRva2VuID0gYnVpbGRUb2tlbkJhZEJpZGkoYnVpbGRlci5hZGRUb2tlbiwgb3JkZXIpO1xuICAgICAgYnVpbGRlci5tYXAgPSBbXTtcbiAgICAgIHZhciBhbGxvd0Zyb250aWVyVXBkYXRlID0gbGluZVZpZXcgIT0gY20uZGlzcGxheS5leHRlcm5hbE1lYXN1cmVkICYmIGxpbmVObyhsaW5lKTtcbiAgICAgIGluc2VydExpbmVDb250ZW50KGxpbmUsIGJ1aWxkZXIsIGdldExpbmVTdHlsZXMoY20sIGxpbmUsIGFsbG93RnJvbnRpZXJVcGRhdGUpKTtcbiAgICAgIGlmIChsaW5lLnN0eWxlQ2xhc3Nlcykge1xuICAgICAgICBpZiAobGluZS5zdHlsZUNsYXNzZXMuYmdDbGFzcylcbiAgICAgICAgICBidWlsZGVyLmJnQ2xhc3MgPSBqb2luQ2xhc3NlcyhsaW5lLnN0eWxlQ2xhc3Nlcy5iZ0NsYXNzLCBidWlsZGVyLmJnQ2xhc3MgfHwgXCJcIik7XG4gICAgICAgIGlmIChsaW5lLnN0eWxlQ2xhc3Nlcy50ZXh0Q2xhc3MpXG4gICAgICAgICAgYnVpbGRlci50ZXh0Q2xhc3MgPSBqb2luQ2xhc3NlcyhsaW5lLnN0eWxlQ2xhc3Nlcy50ZXh0Q2xhc3MsIGJ1aWxkZXIudGV4dENsYXNzIHx8IFwiXCIpO1xuICAgICAgfVxuXG4gICAgICAvLyBFbnN1cmUgYXQgbGVhc3QgYSBzaW5nbGUgbm9kZSBpcyBwcmVzZW50LCBmb3IgbWVhc3VyaW5nLlxuICAgICAgaWYgKGJ1aWxkZXIubWFwLmxlbmd0aCA9PSAwKVxuICAgICAgICBidWlsZGVyLm1hcC5wdXNoKDAsIDAsIGJ1aWxkZXIuY29udGVudC5hcHBlbmRDaGlsZCh6ZXJvV2lkdGhFbGVtZW50KGNtLmRpc3BsYXkubWVhc3VyZSkpKTtcblxuICAgICAgLy8gU3RvcmUgdGhlIG1hcCBhbmQgYSBjYWNoZSBvYmplY3QgZm9yIHRoZSBjdXJyZW50IGxvZ2ljYWwgbGluZVxuICAgICAgaWYgKGkgPT0gMCkge1xuICAgICAgICBsaW5lVmlldy5tZWFzdXJlLm1hcCA9IGJ1aWxkZXIubWFwO1xuICAgICAgICBsaW5lVmlldy5tZWFzdXJlLmNhY2hlID0ge307XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAobGluZVZpZXcubWVhc3VyZS5tYXBzIHx8IChsaW5lVmlldy5tZWFzdXJlLm1hcHMgPSBbXSkpLnB1c2goYnVpbGRlci5tYXApO1xuICAgICAgICAobGluZVZpZXcubWVhc3VyZS5jYWNoZXMgfHwgKGxpbmVWaWV3Lm1lYXN1cmUuY2FjaGVzID0gW10pKS5wdXNoKHt9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZWUgaXNzdWUgIzI5MDFcbiAgICBpZiAod2Via2l0ICYmIC9cXGJjbS10YWJcXGIvLnRlc3QoYnVpbGRlci5jb250ZW50Lmxhc3RDaGlsZC5jbGFzc05hbWUpKVxuICAgICAgYnVpbGRlci5jb250ZW50LmNsYXNzTmFtZSA9IFwiY20tdGFiLXdyYXAtaGFja1wiO1xuXG4gICAgc2lnbmFsKGNtLCBcInJlbmRlckxpbmVcIiwgY20sIGxpbmVWaWV3LmxpbmUsIGJ1aWxkZXIucHJlKTtcbiAgICBpZiAoYnVpbGRlci5wcmUuY2xhc3NOYW1lKVxuICAgICAgYnVpbGRlci50ZXh0Q2xhc3MgPSBqb2luQ2xhc3NlcyhidWlsZGVyLnByZS5jbGFzc05hbWUsIGJ1aWxkZXIudGV4dENsYXNzIHx8IFwiXCIpO1xuXG4gICAgcmV0dXJuIGJ1aWxkZXI7XG4gIH1cblxuICBmdW5jdGlvbiBkZWZhdWx0U3BlY2lhbENoYXJQbGFjZWhvbGRlcihjaCkge1xuICAgIHZhciB0b2tlbiA9IGVsdChcInNwYW5cIiwgXCJcXHUyMDIyXCIsIFwiY20taW52YWxpZGNoYXJcIik7XG4gICAgdG9rZW4udGl0bGUgPSBcIlxcXFx1XCIgKyBjaC5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KTtcbiAgICB0b2tlbi5zZXRBdHRyaWJ1dGUoXCJhcmlhLWxhYmVsXCIsIHRva2VuLnRpdGxlKTtcbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICAvLyBCdWlsZCB1cCB0aGUgRE9NIHJlcHJlc2VudGF0aW9uIGZvciBhIHNpbmdsZSB0b2tlbiwgYW5kIGFkZCBpdCB0b1xuICAvLyB0aGUgbGluZSBtYXAuIFRha2VzIGNhcmUgdG8gcmVuZGVyIHNwZWNpYWwgY2hhcmFjdGVycyBzZXBhcmF0ZWx5LlxuICBmdW5jdGlvbiBidWlsZFRva2VuKGJ1aWxkZXIsIHRleHQsIHN0eWxlLCBzdGFydFN0eWxlLCBlbmRTdHlsZSwgdGl0bGUsIGNzcykge1xuICAgIGlmICghdGV4dCkgcmV0dXJuO1xuICAgIHZhciBkaXNwbGF5VGV4dCA9IGJ1aWxkZXIuc3BsaXRTcGFjZXMgPyB0ZXh0LnJlcGxhY2UoLyB7Myx9L2csIHNwbGl0U3BhY2VzKSA6IHRleHQ7XG4gICAgdmFyIHNwZWNpYWwgPSBidWlsZGVyLmNtLnN0YXRlLnNwZWNpYWxDaGFycywgbXVzdFdyYXAgPSBmYWxzZTtcbiAgICBpZiAoIXNwZWNpYWwudGVzdCh0ZXh0KSkge1xuICAgICAgYnVpbGRlci5jb2wgKz0gdGV4dC5sZW5ndGg7XG4gICAgICB2Y
23459XIgY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGRpc3BsYXlUZXh0KTtcbiAgICAgIGJ1aWxkZXIubWFwLnB1c2goYnVpbGRlci5wb3MsIGJ1aWxkZXIucG9zICsgdGV4dC5sZW5ndGgsIGNvbnRlbnQpO1xuICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5KSBtdXN0V3JhcCA9IHRydWU7XG4gICAgICBidWlsZGVyLnBvcyArPSB0ZXh0Lmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksIHBvcyA9IDA7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBzcGVjaWFsLmxhc3RJbmRleCA9IHBvcztcbiAgICAgICAgdmFyIG0gPSBzcGVjaWFsLmV4ZWModGV4dCk7XG4gICAgICAgIHZhciBza2lwcGVkID0gbSA/IG0uaW5kZXggLSBwb3MgOiB0ZXh0Lmxlbmd0aCAtIHBvcztcbiAgICAgICAgaWYgKHNraXBwZWQpIHtcbiAgICAgICAgICB2YXIgdHh0ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoZGlzcGxheVRleHQuc2xpY2UocG9zLCBwb3MgKyBza2lwcGVkKSk7XG4gICAgICAgICAgaWYgKGllICYmIGllX3ZlcnNpb24gPCA5KSBjb250ZW50LmFwcGVuZENoaWxkKGVsdChcInNwYW5cIiwgW3R4dF0pKTtcbiAgICAgICAgICBlbHNlIGNvbnRlbnQuYXBwZW5kQ2hpbGQodHh0KTtcbiAgICAgICAgICBidWlsZGVyLm1hcC5wdXNoKGJ1aWxkZXIucG9zLCBidWlsZGVyLnBvcyArIHNraXBwZWQsIHR4dCk7XG4gICAgICAgICAgYnVpbGRlci5jb2wgKz0gc2tpcHBlZDtcbiAgICAgICAgICBidWlsZGVyLnBvcyArPSBza2lwcGVkO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbSkgYnJlYWs7XG4gICAgICAgIHBvcyArPSBza2lwcGVkICsgMTtcbiAgICAgICAgaWYgKG1bMF0gPT0gXCJcXHRcIikge1xuICAgICAgICAgIHZhciB0YWJTaXplID0gYnVpbGRlci5jbS5vcHRpb25zLnRhYlNpemUsIHRhYldpZHRoID0gdGFiU2l6ZSAtIGJ1aWxkZXIuY29sICUgdGFiU2l6ZTtcbiAgICAgICAgICB2Y
23459XIgdHh0ID0gY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIHNwYWNlU3RyKHRhYldpZHRoKSwgXCJjbS10YWJcIikpO1xuICAgICAgICAgIHR4dC5zZXRBdHRyaWJ1dGUoXCJyb2xlXCIsIFwicHJlc2VudGF0aW9uXCIpO1xuICAgICAgICAgIHR4dC5zZXRBdHRyaWJ1dGUoXCJjbS10ZXh0XCIsIFwiXFx0XCIpO1xuICAgICAgICAgIGJ1aWxkZXIuY29sICs9IHRhYldpZHRoO1xuICAgICAgICB9IGVsc2UgaWYgKG1bMF0gPT0gXCJcXHJcIiB8fCBtWzBdID09IFwiXFxuXCIpIHtcbiAgICAgICAgICB2YXIgdHh0ID0gY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIG1bMF0gPT0gXCJcXHJcIiA/IFwiXFx1MjQwZFwiIDogXCJcXHUyNDI0XCIsIFwiY20taW52YWxpZGNoYXJcIikpO1xuICAgICAgICAgIHR4dC5zZXRBdHRyaWJ1dGUoXCJjbS10ZXh0XCIsIG1bMF0pO1xuICAgICAgICAgIGJ1aWxkZXIuY29sICs9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHR4dCA9IGJ1aWxkZXIuY20ub3B0aW9ucy5zcGVjaWFsQ2hhclBsYWNlaG9sZGVyKG1bMF0pO1xuICAgICAgICAgIHR4dC5zZXRBdHRyaWJ1dGUoXCJjbS10ZXh0XCIsIG1bMF0pO1xuICAgICAgICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgOSkgY29udGVudC5hcHBlbmRDaGlsZChlbHQoXCJzcGFuXCIsIFt0eHRdKSk7XG4gICAgICAgICAgZWxzZSBjb250ZW50LmFwcGVuZENoaWxkKHR4dCk7XG4gICAgICAgICAgYnVpbGRlci5jb2wgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBidWlsZGVyLm1hcC5wdXNoKGJ1aWxkZXIucG9zLCBidWlsZGVyLnBvcyArIDEsIHR4dCk7XG4gICAgICAgIGJ1aWxkZXIucG9zKys7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzdHlsZSB8fCBzdGFydFN0eWxlIHx8IGVuZFN0eWxlIHx8IG11c3RXcmFwIHx8IGNzcykge1xuICAgICAgdmFyIGZ1bGxTdHlsZSA9IHN0eWxlIHx8IFwiXCI7XG4gICAgICBpZiAoc3RhcnRTdHlsZSkgZnVsbFN0eWxlICs9IHN0YXJ0U3R5bGU7XG4gICAgICBpZiAoZW5kU3R5bGUpIGZ1bGxTdHlsZSArPSBlbmRTdHlsZTtcbiAgICAgIHZhciB0b2tlbiA9IGVsdChcInNwYW5cIiwgW2NvbnRlbnRdLCBmdWxsU3R5bGUsIGNzcyk7XG4gICAgICBpZiAodGl0bGUpIHRva2VuLnRpdGxlID0gdGl0bGU7XG4gICAgICByZXR1cm4gYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKHRva2VuKTtcbiAgICB9XG4gICAgYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKGNvbnRlbnQpO1xuICB9XG5cbiAgZnVuY3Rpb24gc3BsaXRTcGFjZXMob2xkKSB7XG4gICAgdmFyIG91dCA9IFwiIFwiO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2xkLmxlbmd0aCAtIDI7ICsraSkgb3V0ICs9IGkgJSAyID8gXCIgXCIgOiBcIlxcdTAwYTBcIjtcbiAgICBvdXQgKz0gXCIgXCI7XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8vIFdvcmsgYXJvdW5kIG5vbnNlbnNlIGRpbWVuc2lvbnMgYmVpbmcgcmVwb3J0ZWQgZm9yIHN0cmV0Y2hlcyBvZlxuICAvLyByaWdodC10by1sZWZ0IHRleHQuXG4gIGZ1bmN0aW9uIGJ1aWxkVG9rZW5CYWRCaWRpKGlubmVyLCBvcmRlcikge1xuICAgIHJldHVybiBmdW5jdGlvbihidWlsZGVyLCB0ZXh0LCBzdHlsZSwgc3RhcnRTdHlsZSwgZW5kU3R5bGUsIHRpdGxlLCBjc3MpIHtcbiAgICAgIHN0eWxlID0gc3R5bGUgPyBzdHlsZSArIFwiIGNtLWZvcmNlLWJvcmRlclwiIDogXCJjbS1mb3JjZS1ib3JkZXJcIjtcbiAgICAgIHZhciBzdGFydCA9IGJ1aWxkZXIucG9zLCBlbmQgPSBzdGFydCArIHRleHQubGVuZ3RoO1xuICAgICAgZm9yICg7Oykge1xuICAgICAgICAvLyBGaW5kIHRoZSBwYXJ0IHRoYXQgb3ZlcmxhcHMgd2l0aCB0aGUgc3RhcnQgb2YgdGhpcyB0ZXh0XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3JkZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2Y
23459XIgcGFydCA9IG9yZGVyW2ldO1xuICAgICAgICAgIGlmIChwYXJ0LnRvID4gc3RhcnQgJiYgcGFydC5mcm9tIDw9IHN0YXJ0KSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFydC50byA+PSBlbmQpIHJldHVybiBpbm5lcihidWlsZGVyLCB0ZXh0LCBzdHlsZSwgc3RhcnRTdHlsZSwgZW5kU3R5bGUsIHRpdGxlLCBjc3MpO1xuICAgICAgICBpbm5lcihidWlsZGVyLCB0ZXh0LnNsaWNlKDAsIHBhcnQudG8gLSBzdGFydCksIHN0eWxlLCBzdGFydFN0eWxlLCBudWxsLCB0aXRsZSwgY3NzKTtcbiAgICAgICAgc3RhcnRTdHlsZSA9IG51bGw7XG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKHBhcnQudG8gLSBzdGFydCk7XG4gICAgICAgIHN0YXJ0ID0gcGFydC50bztcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gYnVpbGRDb2xsYXBzZWRTcGFuKGJ1aWxkZXIsIHNpemUsIG1hcmtlciwgaWdub3JlV2lkZ2V0KSB7XG4gICAgdmFyIHdpZGdldCA9ICFpZ25vcmVXaWRnZXQgJiYgbWFya2VyLndpZGdldE5vZGU7XG4gICAgaWYgKHdpZGdldCkgYnVpbGRlci5tYXAucHVzaChidWlsZGVyLnBvcywgYnVpbGRlci5wb3MgKyBzaXplLCB3aWRnZXQpO1xuICAgIGlmICghaWdub3JlV2lkZ2V0ICYmIGJ1aWxkZXIuY20uZGlzcGxheS5pbnB1dC5uZWVkc0NvbnRlbnRBdHRyaWJ1dGUpIHtcbiAgICAgIGlmICghd2lkZ2V0KVxuICAgICAgICB3aWRnZXQgPSBidWlsZGVyLmNvbnRlbnQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIikpO1xuICAgICAgd2lkZ2V0LnNldEF0dHJpYnV0ZShcImNtLW1hcmtlclwiLCBtYXJrZXIuaWQpO1xuICAgIH1cbiAgICBpZiAod2lkZ2V0KSB7XG4gICAgICBidWlsZGVyLmNtLmRpc3BsYXkuaW5wdXQuc2V0VW5lZGl0YWJsZSh3aWRnZXQpO1xuICAgICAgYnVpbGRlci5jb250ZW50LmFwcGVuZENoaWxkKHdpZGdldCk7XG4gICAgfVxuICAgIGJ1aWxkZXIucG9zICs9IHNpemU7XG4gIH1cblxuICAvLyBPdXRwdXRzIGEgbnVtYmVyIG9mIHNwYW5zIHRvIG1ha2UgdXAgYSBsaW5lLCB0YWtpbmcgaGlnaGxpZ2h0aW5nXG4gIC8vIGFuZCBtYXJrZWQgdGV4dCBpbnRvIGFjY291bnQuXG4gIGZ1bmN0aW9uIGluc2VydExpbmVDb250ZW50KGxpbmUsIGJ1aWxkZXIsIHN0eWxlcykge1xuICAgIHZhciBzcGFucyA9IGxpbmUubWFya2VkU3BhbnMsIGFsbFRleHQgPSBsaW5lLnRleHQsIGF0ID0gMDtcbiAgICBpZiAoIXNwYW5zKSB7XG4gICAgICBmb3IgKHZhciBpID0gMTsgaSA8IHN0eWxlcy5sZW5ndGg7IGkrPTIpXG4gICAgICAgIGJ1aWxkZXIuYWRkVG9rZW4oYnVpbGRlciwgYWxsVGV4dC5zbGljZShhdCwgYXQgPSBzdHlsZXNbaV0pLCBpbnRlcnByZXRUb2tlblN0eWxlKHN0eWxlc1tpKzFdLCBidWlsZGVyLmNtLm9wdGlvbnMpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gYWxsVGV4dC5sZW5ndGgsIHBvcyA9IDAsIGkgPSAxLCB0ZXh0ID0gXCJcIiwgc3R5bGUsIGNzcztcbiAgICB2YXIgbmV4dENoYW5nZSA9IDAsIHNwYW5TdHlsZSwgc3BhbkVuZFN0eWxlLCBzcGFuU3RhcnRTdHlsZSwgdGl0bGUsIGNvbGxhcHNlZDtcbiAgICBmb3IgKDs7KSB7XG4gICAgICBpZiAobmV4dENoYW5nZSA9PSBwb3MpIHsgLy8gVXBkYXRlIGN1cnJlbnQgbWFya2VyIHNldFxuICAgICAgICBzcGFuU3R5bGUgPSBzcGFuRW5kU3R5bGUgPSBzcGFuU3RhcnRTdHlsZSA9IHRpdGxlID0gY3NzID0gXCJcIjtcbiAgICAgICAgY29sbGFwc2VkID0gbnVsbDsgbmV4dENoYW5nZSA9IEluZmluaXR5O1xuICAgICAgICB2Y
23459XIgZm91bmRCb29rbWFya3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzcGFucy5sZW5ndGg7ICsraikge1xuICAgICAgICAgIHZhciBzcCA9IHNwYW5zW2pdLCBtID0gc3AubWFya2VyO1xuICAgICAgICAgIGlmIChtLnR5cGUgPT0gXCJib29rbWFya1wiICYmIHNwLmZyb20gPT0gcG9zICYmIG0ud2lkZ2V0Tm9kZSkge1xuICAgICAgICAgICAgZm91bmRCb29rbWFya3MucHVzaChtKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHNwLmZyb20gPD0gcG9zICYmIChzcC50byA9PSBudWxsIHx8IHNwLnRvID4gcG9zIHx8IG0uY29sbGFwc2VkICYmIHNwLnRvID09IHBvcyAmJiBzcC5mcm9tID09IHBvcykpIHtcbiAgICAgICAgICAgIGlmIChzcC50byAhPSBudWxsICYmIHNwLnRvICE9IHBvcyAmJiBuZXh0Q2hhbmdlID4gc3AudG8pIHtcbiAgICAgICAgICAgICAgbmV4dENoYW5nZSA9IHNwLnRvO1xuICAgICAgICAgICAgICBzcGFuRW5kU3R5bGUgPSBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG0uY2xhc3NOYW1lKSBzcGFuU3R5bGUgKz0gXCIgXCIgKyBtLmNsYXNzTmFtZTtcbiAgICAgICAgICAgIGlmIChtLmNzcykgY3NzID0gbS5jc3M7XG4gICAgICAgICAgICBpZiAobS5zdGFydFN0eWxlICYmIHNwLmZyb20gPT0gcG9zKSBzcGFuU3RhcnRTdHlsZSArPSBcIiBcIiArIG0uc3RhcnRTdHlsZTtcbiAgICAgICAgICAgIGlmIChtLmVuZFN0eWxlICYmIHNwLnRvID09IG5leHRDaGFuZ2UpIHNwYW5FbmRTdHlsZSArPSBcIiBcIiArIG0uZW5kU3R5bGU7XG4gICAgICAgICAgICBpZiAobS50aXRsZSAmJiAhdGl0bGUpIHRpdGxlID0gbS50aXRsZTtcbiAgICAgICAgICAgIGlmIChtLmNvbGxhcHNlZCAmJiAoIWNvbGxhcHNlZCB8fCBjb21wYXJlQ29sbGFwc2VkTWFya2Vycyhjb2xsYXBzZWQubWFya2VyLCBtKSA8IDApKVxuICAgICAgICAgICAgICBjb2xsYXBzZWQgPSBzcDtcbiAgICAgICAgICB9IGVsc2UgaWYgKHNwLmZyb20gPiBwb3MgJiYgbmV4dENoYW5nZSA+IHNwLmZyb20pIHtcbiAgICAgICAgICAgIG5leHRDaGFuZ2UgPSBzcC5mcm9tO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoY29sbGFwc2VkICYmIChjb2xsYXBzZWQuZnJvbSB8fCAwKSA9PSBwb3MpIHtcbiAgICAgICAgICBidWlsZENvbGxhcHNlZFNwYW4oYnVpbGRlciwgKGNvbGxhcHNlZC50byA9PSBudWxsID8gbGVuICsgMSA6IGNvbGxhcHNlZC50bykgLSBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlZC5tYXJrZXIsIGNvbGxhcHNlZC5mcm9tID09IG51bGwpO1xuICAgICAgICAgIGlmIChjb2xsYXBzZWQudG8gPT0gbnVsbCkgcmV0dXJuO1xuICAgICAgICAgIGlmIChjb2xsYXBzZWQudG8gPT0gcG9zKSBjb2xsYXBzZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbGxhcHNlZCAmJiBmb3VuZEJvb2ttYXJrcy5sZW5ndGgpIGZvciAodmFyIGogPSAwOyBqIDwgZm91bmRCb29rbWFya3MubGVuZ3RoOyArK2opXG4gICAgICAgICAgYnVpbGRDb2xsYXBzZWRTcGFuKGJ1aWxkZXIsIDAsIGZvdW5kQm9va21hcmtzW2pdKTtcbiAgICAgIH1cbiAgICAgIGlmIChwb3MgPj0gbGVuKSBicmVhaztcblxuICAgICAgdmFyIHVwdG8gPSBNYXRoLm1pbihsZW4sIG5leHRDaGFuZ2UpO1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHRleHQpIHtcbiAgICAgICAgICB2Y
23459XIgZW5kID0gcG9zICsgdGV4dC5sZW5ndGg7XG4gICAgICAgICAgaWYgKCFjb2xsYXBzZWQpIHtcbiAgICAgICAgICAgIHZhciB0b2tlblRleHQgPSBlbmQgPiB1cHRvID8gdGV4dC5zbGljZSgwLCB1cHRvIC0gcG9zKSA6IHRleHQ7XG4gICAgICAgICAgICBidWlsZGVyLmFkZFRva2VuKGJ1aWxkZXIsIHRva2VuVGV4dCwgc3R5bGUgPyBzdHlsZSArIHNwYW5TdHlsZSA6IHNwYW5TdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhblN0YXJ0U3R5bGUsIHBvcyArIHRva2VuVGV4dC5sZW5ndGggPT0gbmV4dENoYW5nZSA/IHNwYW5FbmRTdHlsZSA6IFwiXCIsIHRpdGxlLCBjc3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZW5kID49IHVwdG8pIHt0ZXh0ID0gdGV4dC5zbGljZSh1cHRvIC0gcG9zKTsgcG9zID0gdXB0bzsgYnJlYWs7fVxuICAgICAgICAgIHBvcyA9IGVuZDtcbiAgICAgICAgICBzcGFuU3RhcnRTdHlsZSA9IFwiXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGV4dCA9IGFsbFRleHQuc2xpY2UoYXQsIGF0ID0gc3R5bGVzW2krK10pO1xuICAgICAgICBzdHlsZSA9IGludGVycHJldFRva2VuU3R5bGUoc3R5bGVzW2krK10sIGJ1aWxkZXIuY20ub3B0aW9ucyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gRE9DVU1FTlQgREFUQSBTVFJVQ1RVUkVcblxuICAvLyBCeSBkZWZhdWx0LCB1cGRhdGVzIHRoYXQgc3RhcnQgYW5kIGVuZCBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZVxuICAvLyBhcmUgdHJlYXRlZCBzcGVjaWFsbHksIGluIG9yZGVyIHRvIG1ha2UgdGhlIGFzc29jaWF0aW9uIG9mIGxpbmVcbiAgLy8gd2lkZ2V0cyBhbmQgbWFya2VyIGVsZW1lbnRzIHdpdGggdGhlIHRleHQgYmVoYXZlIG1vcmUgaW50dWl0aXZlLlxuICBmdW5jdGlvbiBpc1dob2xlTGluZVVwZGF0ZShkb2MsIGNoYW5nZSkge1xuICAgIHJldHVybiBjaGFuZ2UuZnJvbS5jaCA9PSAwICYmIGNoYW5nZS50by5jaCA9PSAwICYmIGxzdChjaGFuZ2UudGV4dCkgPT0gXCJcIiAmJlxuICAgICAgKCFkb2MuY20gfHwgZG9jLmNtLm9wdGlvbnMud2hvbGVMaW5lVXBkYXRlQmVmb3JlKTtcbiAgfVxuXG4gIC8vIFBlcmZvcm0gYSBjaGFuZ2Ugb24gdGhlIGRvY3VtZW50IGRhdGEgc3RydWN0dXJlLlxuICBmdW5jdGlvbiB1cGRhdGVEb2MoZG9jLCBjaGFuZ2UsIG1hcmtlZFNwYW5zLCBlc3RpbWF0ZUhlaWdodCkge1xuICAgIGZ1bmN0aW9uIHNwYW5zRm9yKG4pIHtyZXR1cm4gbWFya2VkU3BhbnMgPyBtYXJrZWRTcGFuc1tuXSA6IG51bGw7fVxuICAgIGZ1bmN0aW9uIHVwZGF0ZShsaW5lLCB0ZXh0LCBzcGFucykge1xuICAgICAgdXBkYXRlTGluZShsaW5lLCB0ZXh0LCBzcGFucywgZXN0aW1hdGVIZWlnaHQpO1xuICAgICAgc2lnbmFsTGF0ZXIobGluZSwgXCJjaGFuZ2VcIiwgbGluZSwgY2hhbmdlKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZXNGb3Ioc3RhcnQsIGVuZCkge1xuICAgICAgZm9yICh2YXIgaSA9IHN0YXJ0LCByZXN1bHQgPSBbXTsgaSA8IGVuZDsgKytpKVxuICAgICAgICByZXN1bHQucHVzaChuZXcgTGluZSh0ZXh0W2ldLCBzcGFuc0ZvcihpKSwgZXN0aW1hdGVIZWlnaHQpKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgdmFyIGZyb20gPSBjaGFuZ2UuZnJvbSwgdG8gPSBjaGFuZ2UudG8sIHRleHQgPSBjaGFuZ2UudGV4dDtcbiAgICB2YXIgZmlyc3RMaW5lID0gZ2V0TGluZShkb2MsIGZyb20ubGluZSksIGxhc3RMaW5lID0gZ2V0TGluZShkb2MsIHRvLmxpbmUpO1xuICAgIHZhciBsYXN0VGV4dCA9IGxzdCh0ZXh0KSwgbGFzdFNwYW5zID0gc3BhbnNGb3IodGV4dC5sZW5ndGggLSAxKSwgbmxpbmVzID0gdG8ubGluZSAtIGZyb20ubGluZTtcblxuICAgIC8vIEFkanVzdCB0aGUgbGluZSBzdHJ1Y3R1cmVcbiAgICBpZiAoY2hhbmdlLmZ1bGwpIHtcbiAgICAgIGRvYy5pbnNlcnQoMCwgbGluZXNGb3IoMCwgdGV4dC5sZW5ndGgpKTtcbiAgICAgIGRvYy5yZW1vdmUodGV4dC5sZW5ndGgsIGRvYy5zaXplIC0gdGV4dC5sZW5ndGgpO1xuICAgIH0gZWxzZSBpZiAoaXNXaG9sZUxpbmVVcGRhdGUoZG9jLCBjaGFuZ2UpKSB7XG4gICAgICAvLyBUaGlzIGlzIGEgd2hvbGUtbGluZSByZXBsYWNlLiBUcmVhdGVkIHNwZWNpYWxseSB0byBtYWtlXG4gICAgICAvLyBzdXJlIGxpbmUgb2JqZWN0cyBtb3ZlIHRoZSB3YXkgdGhleSBhcmUgc3VwcG9zZWQgdG8uXG4gICAgICB2Y
23459XIgYWRkZWQgPSBsaW5lc0ZvcigwLCB0ZXh0Lmxlbmd0aCAtIDEpO1xuICAgICAgdXBkYXRlKGxhc3RMaW5lLCBsYXN0TGluZS50ZXh0LCBsYXN0U3BhbnMpO1xuICAgICAgaWYgKG5saW5lcykgZG9jLnJlbW92ZShmcm9tLmxpbmUsIG5saW5lcyk7XG4gICAgICBpZiAoYWRkZWQubGVuZ3RoKSBkb2MuaW5zZXJ0KGZyb20ubGluZSwgYWRkZWQpO1xuICAgIH0gZWxzZSBpZiAoZmlyc3RMaW5lID09IGxhc3RMaW5lKSB7XG4gICAgICBpZiAodGV4dC5sZW5ndGggPT0gMSkge1xuICAgICAgICB1cGRhdGUoZmlyc3RMaW5lLCBmaXJzdExpbmUudGV4dC5zbGljZSgwLCBmcm9tLmNoKSArIGxhc3RUZXh0ICsgZmlyc3RMaW5lLnRleHQuc2xpY2UodG8uY2gpLCBsYXN0U3BhbnMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGFkZGVkID0gbGluZXNGb3IoMSwgdGV4dC5sZW5ndGggLSAxKTtcbiAgICAgICAgYWRkZWQucHVzaChuZXcgTGluZShsYXN0VGV4dCArIGZpcnN0TGluZS50ZXh0LnNsaWNlKHRvLmNoKSwgbGFzdFNwYW5zLCBlc3RpbWF0ZUhlaWdodCkpO1xuICAgICAgICB1cGRhdGUoZmlyc3RMaW5lLCBmaXJzdExpbmUudGV4dC5zbGljZSgwLCBmcm9tLmNoKSArIHRleHRbMF0sIHNwYW5zRm9yKDApKTtcbiAgICAgICAgZG9jLmluc2VydChmcm9tLmxpbmUgKyAxLCBhZGRlZCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0ZXh0Lmxlbmd0aCA9PSAxKSB7XG4gICAgICB1cGRhdGUoZmlyc3RMaW5lLCBmaXJzdExpbmUudGV4dC5zbGljZSgwLCBmcm9tLmNoKSArIHRleHRbMF0gKyBsYXN0TGluZS50ZXh0LnNsaWNlKHRvLmNoKSwgc3BhbnNGb3IoMCkpO1xuICAgICAgZG9jLnJlbW92ZShmcm9tLmxpbmUgKyAxLCBubGluZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1cGRhdGUoZmlyc3RMaW5lLCBmaXJzdExpbmUudGV4dC5zbGljZSgwLCBmcm9tLmNoKSArIHRleHRbMF0sIHNwYW5zRm9yKDApKTtcbiAgICAgIHVwZGF0ZShsYXN0TGluZSwgbGFzdFRleHQgKyBsYXN0TGluZS50ZXh0LnNsaWNlKHRvLmNoKSwgbGFzdFNwYW5zKTtcbiAgICAgIHZhciBhZGRlZCA9IGxpbmVzRm9yKDEsIHRleHQubGVuZ3RoIC0gMSk7XG4gICAgICBpZiAobmxpbmVzID4gMSkgZG9jLnJlbW92ZShmcm9tLmxpbmUgKyAxLCBubGluZXMgLSAxKTtcbiAgICAgIGRvYy5pbnNlcnQoZnJvbS5saW5lICsgMSwgYWRkZWQpO1xuICAgIH1cblxuICAgIHNpZ25hbExhdGVyKGRvYywgXCJjaGFuZ2VcIiwgZG9jLCBjaGFuZ2UpO1xuICB9XG5cbiAgLy8gVGhlIGRvY3VtZW50IGlzIHJlcHJlc2VudGVkIGFzIGEgQlRyZWUgY29uc2lzdGluZyBvZiBsZWF2ZXMsIHdpdGhcbiAgLy8gY2h1bmsgb2YgbGluZXMgaW4gdGhlbSwgYW5kIGJyYW5jaGVzLCB3aXRoIHVwIHRvIHRlbiBsZWF2ZXMgb3JcbiAgLy8gb3RoZXIgYnJhbmNoIG5vZGVzIGJlbG93IHRoZW0uIFRoZSB0b3Agbm9kZSBpcyBhbHdheXMgYSBicmFuY2hcbiAgLy8gbm9kZSwgYW5kIGlzIHRoZSBkb2N1bWVudCBvYmplY3QgaXRzZWxmIChtZWFuaW5nIGl0IGhhc1xuICAvLyBhZGRpdGlvbmFsIG1ldGhvZHMgYW5kIHByb3BlcnRpZXMpLlxuICAvL1xuICAvLyBBbGwgbm9kZXMgaGF2ZSBwYXJlbnQgbGlua3MuIFRoZSB0cmVlIGlzIHVzZWQgYm90aCB0byBnbyBmcm9tXG4gIC8vIGxpbmUgbnVtYmVycyB0byBsaW5lIG9iamVjdHMsIGFuZCB0byBnbyBmcm9tIG9iamVjdHMgdG8gbnVtYmVycy5cbiAgLy8gSXQgYWxzbyBpbmRleGVzIGJ5IGhlaWdodCwgYW5kIGlzIHVzZWQgdG8gY29udmVydCBiZXR3ZWVuIGhlaWdodFxuICAvLyBhbmQgbGluZSBvYmplY3QsIGFuZCB0byBmaW5kIHRoZSB0b3RhbCBoZWlnaHQgb2YgdGhlIGRvY3VtZW50LlxuICAvL1xuICAvLyBTZWUgYWxzbyBodHRwOi8vbWFyaWpuaGF2ZXJiZWtlLm5sL2Jsb2cvY29kZW1pcnJvci1saW5lLXRyZWUuaHRtbFxuXG4gIGZ1bmN0aW9uIExlYWZDaHVuayhsaW5lcykge1xuICAgIHRoaXMubGluZXMgPSBsaW5lcztcbiAgICB0aGlzLnBhcmVudCA9IG51bGw7XG4gICAgZm9yICh2YXIgaSA9IDAsIGhlaWdodCA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgbGluZXNbaV0ucGFyZW50ID0gdGhpcztcbiAgICAgIGhlaWdodCArPSBsaW5lc1tpXS5oZWlnaHQ7XG4gICAgfVxuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICB9XG5cbiAgTGVhZkNodW5rLnByb3RvdHlwZSA9IHtcbiAgICBjaHVua1NpemU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5saW5lcy5sZW5ndGg7IH0sXG4gICAgLy8gUmVtb3ZlIHRoZSBuIGxpbmVzIGF0IG9mZnNldCAnYXQnLlxuICAgIHJlbW92ZUlubmVyOiBmdW5jdGlvbihhdCwgbikge1xuICAgICAgZm9yICh2YXIgaSA9IGF0LCBlID0gYXQgKyBuOyBpIDwgZTsgKytpKSB7XG4gICAgICAgIHZhciBsaW5lID0gdGhpcy5saW5lc1tpXTtcbiAgICAgICAgdGhpcy5oZWlnaHQgLT0gbGluZS5oZWlnaHQ7XG4gICAgICAgIGNsZWFuVXBMaW5lKGxpbmUpO1xuICAgICAgICBzaWduYWxMYXRlcihsaW5lLCBcImRlbGV0ZVwiKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubGluZXMuc3BsaWNlKGF0LCBuKTtcbiAgICB9LFxuICAgIC8vIEhlbHBlciB1c2VkIHRvIGNvbGxhcHNlIGEgc21hbGwgYnJhbmNoIGludG8gYSBzaW5nbGUgbGVhZi5cbiAgICBjb2xsYXBzZTogZnVuY3Rpb24obGluZXMpIHtcbiAgICAgIGxpbmVzLnB1c2guYXBwbHkobGluZXMsIHRoaXMubGluZXMpO1xuICAgIH0sXG4gICAgLy8gSW5zZXJ0IHRoZSBnaXZlbiBhcnJheSBvZiBsaW5lcyBhdCBvZmZzZXQgJ2F0JywgY291bnQgdGhlbSBhc1xuICAgIC8vIGhhdmluZyB0aGUgZ2l2ZW4gaGVpZ2h0LlxuICAgIGluc2VydElubmVyOiBmdW5jdGlvbihhdCwgbGluZXMsIGhlaWdodCkge1xuICAgICAgdGhpcy5oZWlnaHQgKz0gaGVpZ2h0O1xuICAgICAgdGhpcy5saW5lcyA9IHRoaXMubGluZXMuc2xpY2UoMCwgYXQpLmNvbmNhdChsaW5lcykuY29uY2F0KHRoaXMubGluZXMuc2xpY2UoYXQpKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyArK2kpIGxpbmVzW2ldLnBhcmVudCA9IHRoaXM7XG4gICAgfSxcbiAgICAvLyBVc2VkIHRvIGl0ZXJhdGUgb3ZlciBhIHBhcnQgb2YgdGhlIHRyZWUuXG4gICAgaXRlck46IGZ1bmN0aW9uKGF0LCBuLCBvcCkge1xuICAgICAgZm9yICh2YXIgZSA9IGF0ICsgbjsgYXQgPCBlOyArK2F0KVxuICAgICAgICBpZiAob3AodGhpcy5saW5lc1thdF0pKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gI
23459H07XG5cbiAgZnVuY3Rpb24gQnJhbmNoQ2h1bmsoY2hpbGRyZW4pIHtcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdmFyIHNpemUgPSAwLCBoZWlnaHQgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBjaCA9IGNoaWxkcmVuW2ldO1xuICAgICAgc2l6ZSArPSBjaC5jaHVua1NpemUoKTsgaGVpZ2h0ICs9IGNoLmhlaWdodDtcbiAgICAgIGNoLnBhcmVudCA9IHRoaXM7XG4gICAgfVxuICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgdGhpcy5wYXJlbnQgPSBudWxsO1xuICB9XG5cbiAgQnJhbmNoQ2h1bmsucHJvdG90eXBlID0ge1xuICAgIGNodW5rU2l6ZTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnNpemU7IH0sXG4gICAgcmVtb3ZlSW5uZXI6IGZ1bmN0aW9uKGF0LCBuKSB7XG4gICAgICB0aGlzLnNpemUgLT0gbjtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLmNoaWxkcmVuW2ldLCBzeiA9IGNoaWxkLmNodW5rU2l6ZSgpO1xuICAgICAgICBpZiAoYXQgPCBzeikge1xuICAgICAgICAgIHZhciBybSA9IE1hdGgubWluKG4sIHN6IC0gYXQpLCBvbGRIZWlnaHQgPSBjaGlsZC5oZWlnaHQ7XG4gICAgICAgICAgY2hpbGQucmVtb3ZlSW5uZXIoYXQsIHJtKTtcbiAgICAgICAgICB0aGlzLmhlaWdodCAtPSBvbGRIZWlnaHQgLSBjaGlsZC5oZWlnaHQ7XG4gICAgICAgICAgaWYgKHN6ID09IHJtKSB7IHRoaXMuY2hpbGRyZW4uc3BsaWNlKGktLSwgMSk7IGNoaWxkLnBhcmVudCA9IG51bGw7IH1cbiAgICAgICAgICBpZiAoKG4gLT0gcm0pID09IDApIGJyZWFrO1xuICAgICAgICAgIGF0ID0gMDtcbiAgICAgICAgfSBlbHNlIGF0IC09IHN6O1xuICAgICAgfVxuICAgICAgLy8gSWYgdGhlIHJlc3VsdCBpcyBzbWFsbGVyIHRoYW4gMjUgbGluZXMsIGVuc3VyZSB0aGF0IGl0IGlzIGFcbiAgICAgIC8vIHNpbmdsZSBsZWFmIG5vZGUuXG4gICAgICBpZiAodGhpcy5zaXplIC0gbiA8IDI1ICYmXG4gICAgICAgICAgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID4gMSB8fCAhKHRoaXMuY2hpbGRyZW5bMF0gaW5zdGFuY2VvZiBMZWFmQ2h1bmspKSkge1xuICAgICAgICB2Y
23459XIgbGluZXMgPSBbXTtcbiAgICAgICAgdGhpcy5jb2xsYXBzZShsaW5lcyk7XG4gICAgICAgIHRoaXMuY2hpbGRyZW4gPSBbbmV3IExlYWZDaHVuayhsaW5lcyldO1xuICAgICAgICB0aGlzLmNoaWxkcmVuWzBdLnBhcmVudCA9IHRoaXM7XG4gICAgICB9XG4gICAgfSxcbiAgICBjb2xsYXBzZTogZnVuY3Rpb24obGluZXMpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7ICsraSkgdGhpcy5jaGlsZHJlbltpXS5jb2xsYXBzZShsaW5lcyk7XG4gICAgfSxcbiAgICBpbnNlcnRJbm5lcjogZnVuY3Rpb24oYXQsIGxpbmVzLCBoZWlnaHQpIHtcbiAgICAgIHRoaXMuc2l6ZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICB0aGlzLmhlaWdodCArPSBoZWlnaHQ7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGNoaWxkID0gdGhpcy5jaGlsZHJlbltpXSwgc3ogPSBjaGlsZC5jaHVua1NpemUoKTtcbiAgICAgICAgaWYgKGF0IDw9IHN6KSB7XG4gICAgICAgICAgY2hpbGQuaW5zZXJ0SW5uZXIoYXQsIGxpbmVzLCBoZWlnaHQpO1xuICAgICAgICAgIGlmIChjaGlsZC5saW5lcyAmJiBjaGlsZC5saW5lcy5sZW5ndGggPiA1MCkge1xuICAgICAgICAgICAgd2hpbGUgKGNoaWxkLmxpbmVzLmxlbmd0aCA+IDUwKSB7XG4gICAgICAgICAgICAgIHZhciBzcGlsbGVkID0gY2hpbGQubGluZXMuc3BsaWNlKGNoaWxkLmxpbmVzLmxlbmd0aCAtIDI1LCAyNSk7XG4gICAgICAgICAgICAgIHZhciBuZXdsZWFmID0gbmV3IExlYWZDaHVuayhzcGlsbGVkKTtcbiAgICAgICAgICAgICAgY2hpbGQuaGVpZ2h0IC09IG5ld2xlYWYuaGVpZ2h0O1xuICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuLnNwbGljZShpICsgMSwgMCwgbmV3bGVhZik7XG4gICAgICAgICAgICAgIG5ld2xlYWYucGFyZW50ID0gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubWF5YmVTcGlsbCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBhdCAtPSBzejtcbiAgICAgIH1cbiAgICB9LFxuICAgIC8vIFdoZW4gYSBub2RlIGhhcyBncm93biwgY2hlY2sgd2hldGhlciBpdCBzaG91bGQgYmUgc3BsaXQuXG4gICAgbWF5YmVTcGlsbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPD0gMTApIHJldHVybjtcbiAgICAgIHZhciBtZSA9IHRoaXM7XG4gICAgICBkbyB7XG4gICAgICAgIHZhciBzcGlsbGVkID0gbWUuY2hpbGRyZW4uc3BsaWNlKG1lLmNoaWxkcmVuLmxlbmd0aCAtIDUsIDUpO1xuICAgICAgICB2Y
23459XIgc2libGluZyA9IG5ldyBCcmFuY2hDaHVuayhzcGlsbGVkKTtcbiAgICAgICAgaWYgKCFtZS5wYXJlbnQpIHsgLy8gQmVjb21lIHRoZSBwYXJlbnQgbm9kZVxuICAgICAgICAgIHZhciBjb3B5ID0gbmV3IEJyYW5jaENodW5rKG1lLmNoaWxkcmVuKTtcbiAgICAgICAgICBjb3B5LnBhcmVudCA9IG1lO1xuICAgICAgICAgIG1lLmNoaWxkcmVuID0gW2NvcHksIHNpYmxpbmddO1xuICAgICAgICAgIG1lID0gY29weTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBtZS5zaXplIC09IHNpYmxpbmcuc2l6ZTtcbiAgICAgICAgICBtZS5oZWlnaHQgLT0gc2libGluZy5oZWlnaHQ7XG4gICAgICAgICAgdmFyIG15SW5kZXggPSBpbmRleE9mKG1lLnBhcmVudC5jaGlsZHJlbiwgbWUpO1xuICAgICAgICAgIG1lLnBhcmVudC5jaGlsZHJlbi5zcGxpY2UobXlJbmRleCArIDEsIDAsIHNpYmxpbmcpO1xuICAgICAgICB9XG4gICAgICAgIHNpYmxpbmcucGFyZW50ID0gbWUucGFyZW50O1xuICAgICAgfSB3aGlsZSAobWUuY2hpbGRyZW4ubGVuZ3RoID4gMTApO1xuICAgICAgbWUucGFyZW50Lm1heWJlU3BpbGwoKTtcbiAgICB9LFxuICAgIGl0ZXJOOiBmdW5jdGlvbihhdCwgbiwgb3ApIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLmNoaWxkcmVuW2ldLCBzeiA9IGNoaWxkLmNodW5rU2l6ZSgpO1xuICAgICAgICBpZiAoYXQgPCBzeikge1xuICAgICAgICAgIHZhciB1c2VkID0gTWF0aC5taW4obiwgc3ogLSBhdCk7XG4gICAgICAgICAgaWYgKGNoaWxkLml0ZXJOKGF0LCB1c2VkLCBvcCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgIGlmICgobiAtPSB1c2VkKSA9PSAwKSBicmVhaztcbiAgICAgICAgICBhdCA9IDA7XG4gICAgICAgIH0gZWxzZSBhdCAtPSBzejtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgdmFyIG5leHREb2NJZCA9IDA7XG4gIHZhciBEb2MgPSBDb2RlTWlycm9yLkRvYyA9IGZ1bmN0aW9uKHRleHQsIG1vZGUsIGZpcnN0TGluZSwgbGluZVNlcCkge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBEb2MpKSByZXR1cm4gbmV3IERvYyh0ZXh0LCBtb2RlLCBmaXJzdExpbmUsIGxpbmVTZXApO
234591xuICAgIGlmIChmaXJzdExpbmUgPT0gbnVsbCkgZmlyc3RMaW5lID0gMDtcblxuICAgIEJyYW5jaENodW5rLmNhbGwodGhpcywgW25ldyBMZWFmQ2h1bmsoW25ldyBMaW5lKFwiXCIsIG51bGwpXSldKTtcbiAgICB0aGlzLmZpcnN0ID0gZmlyc3RMaW5lO1xuICAgIHRoaXMuc2Nyb2xsVG9wID0gdGhpcy5zY3JvbGxMZWZ0ID0gMDtcbiAgICB0aGlzLmNhbnRFZGl0ID0gZmFsc2U7XG4gICAgdGhpcy5jbGVhbkdlbmVyYXRpb24gPSAxO1xuICAgIHRoaXMuZnJvbnRpZXIgPSBmaXJzdExpbmU7XG4gICAgdmFyIHN0YXJ0ID0gUG9zKGZpcnN0TGluZSwgMCk7XG4gICAgdGhpcy5zZWwgPSBzaW1wbGVTZWxlY3Rpb24oc3RhcnQpO1xuICAgIHRoaXMuaGlzdG9yeSA9IG5ldyBIaXN0b3J5KG51bGwpO1xuICAgIHRoaXMuaWQgPSArK25leHREb2NJZDtcbiAgICB0aGlzLm1vZGVPcHRpb24gPSBtb2RlO1xuICAgIHRoaXMubGluZVNlcCA9IGxpbmVTZXA7XG5cbiAgICBpZiAodHlwZW9mIHRleHQgPT0gXCJzdHJpbmdcIikgdGV4dCA9IHRoaXMuc3BsaXRMaW5lcyh0ZXh0KTtcbiAgICB1cGRhdGVEb2ModGhpcywge2Zyb206IHN0YXJ0LCB0bzogc3RhcnQsIHRleHQ6IHRleHR9KTtcbiAgICBzZXRTZWxlY3Rpb24odGhpcywgc2ltcGxlU2VsZWN0aW9uKHN0YXJ0KSwgc2VsX2RvbnRTY3JvbGwpO1xuICB9O1xuXG4gIERvYy5wcm90b3R5cGUgPSBjcmVhdGVPYmooQnJhbmNoQ2h1bmsucHJvdG90eXBlLCB7XG4gICAgY29uc3RydWN0b3I6IERvYyxcbiAgICAvLyBJdGVyYXRlIG92ZXIgdGhlIGRvY3VtZW50LiBTdXBwb3J0cyB0d28gZm9ybXMgLS0gd2l0aCBvbmx5IG9uZVxuICAgIC8vIGFyZ3VtZW50LCBpdCBjYWxscyB0aGF0IGZvciBlYWNoIGxpbmUgaW4gdGhlIGRvY3VtZW50LiBXaXRoXG4gICAgLy8gdGhyZWUsIGl0IGl0ZXJhdGVzIG92ZXIgdGhlIHJhbmdlIGdpdmVuIGJ5IHRoZSBmaXJzdCB0d28gKHdpdGhcbiAgICAvLyB0aGUgc2Vjb25kIGJlaW5nIG5vbi1pbmNsdXNpdmUpLlxuICAgIGl0ZXI6IGZ1bmN0aW9uKGZyb20sIHRvLCBvcCkge1xuICAgICAgaWYgKG9wKSB0aGlzLml0ZXJOKGZyb20gLSB0aGlzLmZpcnN0LCB0byAtIGZyb20sIG9wKTtcbiAgICAgIGVsc2UgdGhpcy5pdGVyTih0aGlzLmZpcnN0LCB0aGlzLmZpcnN0ICsgdGhpcy5zaXplLCBmcm9tKTtcbiAgICB9LFxuXG4gICAgLy8gTm9uLXB1YmxpYyBpbnRlcmZhY2UgZm9yIGFkZGluZyBhbmQgcmVtb3ZpbmcgbGluZXMuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbihhdCwgbGluZXMpIHtcbiAgICAgIHZhciBoZWlnaHQgPSAwO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkgaGVpZ2h0ICs9IGxpbmVzW2ldLmhlaWdodDtcbiAgICAgIHRoaXMuaW5zZXJ0SW5uZXIoYXQgLSB0aGlzLmZpcnN0LCBsaW5lcywgaGVpZ2h0KTtcbiAgICB9LFxuICAgIHJlbW92ZTogZnVuY3Rpb24oYXQsIG4pIHsgdGhpcy5yZW1vdmVJbm5lcihhdCAtIHRoaXMuZmlyc3QsIG4pOyB9LFxuXG4gICAgLy8gRnJvbSBoZXJlLCB0aGUgbWV0aG9kcyBhcmUgcGFydCBvZiB0aGUgcHVibGljIGludGVyZmFjZS4gTW9zdFxuICAgIC8vIGFyZSBhbHNvIGF2YWlsYWJsZSBmcm9tIENvZGVNaXJyb3IgKGVkaXRvcikgaW5zdGFuY2VzLlxuXG4gICAgZ2V0VmFsdWU6IGZ1bmN0aW9uKGxpbmVTZXApIHtcbiAgICAgIHZhciBsaW5lcyA9IGdldExpbmVzKHR
23459oaXMsIHRoaXMuZmlyc3QsIHRoaXMuZmlyc3QgKyB0aGlzLnNpemUpO1xuICAgICAgaWYgKGxpbmVTZXAgPT09IGZhbHNlKSByZXR1cm4gbGluZXM7XG4gICAgICByZXR1cm4gbGluZXMuam9pbihsaW5lU2VwIHx8IHRoaXMubGluZVNlcGFyYXRvcigpKTtcbiAgICB9LFxuICAgIHNldFZhbHVlOiBkb2NNZXRob2RPcChmdW5jdGlvbihjb2RlKSB7XG4gICAgICB2YXIgdG9wID0gUG9zKHRoaXMuZmlyc3QsIDApLCBsYXN0ID0gdGhpcy5maXJzdCArIHRoaXMuc2l6ZSAtIDE7XG4gICAgICBtYWtlQ2hhbmdlKHRoaXMsIHtmcm9tOiB0b3AsIHRvOiBQb3MobGFzdCwgZ2V0TGluZSh0aGlzLCBsYXN0KS50ZXh0Lmxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiB0aGlzLnNwbGl0TGluZXMoY29kZSksIG9yaWdpbjogXCJzZXRWYWx1ZVwiLCBmdWxsOiB0cnVlfSwgdHJ1ZSk7XG4gICAgICBzZXRTZWxlY3Rpb24odGhpcywgc2ltcGxlU2VsZWN0aW9uKHRvcCkpO1xuICAgIH0pLFxuICAgIHJlcGxhY2VSYW5nZTogZnVuY3Rpb24oY29kZSwgZnJvbSwgdG8sIG9yaWdpbikge1xuICAgICAgZnJvbSA9IGNsaXBQb3ModGhpcywgZnJvbSk7XG4gICAgICB0byA9IHRvID8gY2xpcFBvcyh0aGlzLCB0bykgOiBmcm9tO1xuICAgICAgcmVwbGFjZVJhbmdlKHRoaXMsIGNvZGUsIGZyb20sIHRvLCBvcmlnaW4pO1xuICAgIH0sXG4gICAgZ2V0UmFuZ2U6IGZ1bmN0aW9uKGZyb20sIHRvLCBsaW5lU2VwKSB7XG4gICAgICB2YXIgbGluZXMgPSBnZXRCZXR3ZWVuKHRoaXMsIGNsaXBQb3ModGhpcywgZnJvbSksIGNsaXBQb3ModGhpcywgdG8pKTtcbiAgICAgIGlmIChsaW5lU2VwID09PSBmYWxzZSkgcmV0dXJuIGxpbmVzO1xuICAgICAgcmV0dXJuIGxpbmVzLmpvaW4obGluZVNlcCB8fCB0aGlzLmxpbmVTZXBhcmF0b3IoKSk7XG4gICAgfSxcblxuICAgIGdldExpbmU6IGZ1bmN0aW9uKGxpbmUpIHt2YXIgbCA9IHRoaXMuZ2V0TGluZUhhbmRsZShsaW5lKTsgcmV0dXJuIGwgJiYgbC50ZXh0O30sXG5cbiAgICBnZXRMaW5lSGFuZGxlOiBmdW5jdGlvbihsaW5lKSB7aWYgKGlzTGluZSh0aGlzLCBsaW5lKSkgcmV0dXJuIGdldExpbmUodGhpcywgbGluZSk7fSxcbiAgICBnZXRMaW5lTnVtYmVyOiBmdW5jdGlvbihsaW5lKSB7cmV0dXJuIGxpbmVObyhsaW5lKTt9LFxuXG4gICAgZ2V0TGluZUhhbmRsZVZpc3VhbFN0YXJ0OiBmdW5jdGlvbihsaW5lKSB7XG4gICAgICBpZiAodHlwZW9mIGxpbmUgPT0gXCJudW1iZXJcIikgbGluZSA9IGdldExpbmUodGhpcywgbGluZSk7XG4gICAgICByZXR1cm4gdmlzdWFsTGluZShsaW5lKTtcbiAgICB9LFxuXG4gICAgbGluZUNvdW50OiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5zaXplO30sXG4gICAgZmlyc3RMaW5lOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5maXJzdDt9LFxuICAgIGxhc3RMaW5lOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5maXJzdCArIHRoaXMuc2l6ZSAtIDE7fSxcblxuICAgIGNsaXBQb3M6IGZ1bmN0aW9uKHBvcykge3JldHVybiBjbGlwUG9zKHRoaXMsIHBvcyk7fSxcblxuICAgIGdldEN1cnNvcjogZnVuY3Rpb24oc3RhcnQpIHtcbiAgICAgIHZhciByYW5nZSA9IHRoaXMuc2VsLnByaW1hcnkoKSwgcG9zO1xuICAgICAgaWYgKHN0YXJ0ID09IG51bGwgfHwgc3RhcnQgPT0gXCJoZWFkXCIpIHBvcyA9IHJhbmdlLmhlYWQ7XG4gICAgICBlbHNlIGlmIChzdGFydCA9PSBcImFuY2hvclwiKSBwb3MgPSByYW5nZS5hbmNob3I7XG4gICAgICBlbHNlIGlmIChzdGFydCA9PSBcImVuZFwiIHx8IHN0YXJ0ID09IFwidG9cIiB8fCBzdGFydCA9PT0gZmFsc2UpIHBvcyA9IHJhbmdlLnRvKCk7XG4gICAgICBlbHNlIHBvcyA9IHJhbmdlLmZyb20oKTtcbiAgICAgIHJldHVybiBwb3M7XG4gICAgfSxcbiAgICBsaXN0U2VsZWN0aW9uczogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnNlbC5yYW5nZXM7IH0sXG4gICAgc29tZXRoaW5nU2VsZWN0ZWQ6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLnNlbC5zb21ldGhpbmdTZWxlY3RlZCgpO30sXG5cbiAgICBzZXRDdXJzb3I6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGxpbmUsIGNoLCBvcHRpb25zKSB7XG4gICAgICBzZXRTaW1wbGVTZWxlY3Rpb24odGhpcywgY2xpcFBvcyh0aGlzLCB0eXBlb2YgbGluZSA9PSBcIm51bWJlclwiID8gUG9zKGxpbmUsIGNoIHx8IDApIDogbGluZSksIG51bGwsIG9wdGlvbnMpO1xuICAgIH0pLFxuICAgIHNldFNlbGVjdGlvbjogZG9jTWV0aG9kT3AoZnVuY3Rpb24oYW5jaG9yLCBoZWFkLCBvcHRpb25zKSB7XG4gICAgICBzZXRTaW1wbGVTZWxlY3Rpb24odGhpcywgY2xpcFBvcyh0aGlzLCBhbmNob3IpLCBjbGlwUG9zKHRoaXMsIGhlYWQgfHwgYW5jaG9yKSwgb3B0aW9ucyk7XG4gICAgfSksXG4gICAgZXh0ZW5kU2VsZWN0aW9uOiBkb2NNZXRob2RPcChmdW5jdGlvbihoZWFkLCBvdGhlciwgb3B0aW9ucykge1xuICAgICAgZXh0ZW5kU2VsZWN0aW9uKHRoaXMsIGNsaXBQb3ModGhpcywgaGVhZCksIG90aGVyICYmIGNsaXBQb3ModGhpcywgb3RoZXIpLCBvcHRpb25zKTtcbiAgICB9KSxcbiAgICBleHRlbmRTZWxlY3Rpb25zOiBkb2NNZXRob2RPcChmdW5jdGlvbihoZWFkcywgb3B0aW9ucykge1xuICAgICAgZXh0ZW5kU2VsZWN0aW9ucyh0aGlzLCBjbGlwUG9zQXJyYXkodGhpcywgaGVhZHMsIG9wdGlvbnMpKTtcbiAgICB9KSxcbiAgICBleHRlbmRTZWxlY3Rpb25zQnk6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGYsIG9wdGlvbnMpIHtcbiAgICAgIGV4dGVuZFNlbGVjdGlvbnModGhpcywgbWFwKHRoaXMuc2VsLnJhbmdlcywgZi
vendor: 9,389 bytes, line 23459
23459ksIG9wdGlvbnMpO1xuICAgIH0pLFxuICAgIHNldFNlbGVjdGlvbnM6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKHJhbmdlcywgcHJpbWFyeSwgb3B0aW9ucykge1xuICAgICAgaWYgKCFyYW5nZXMubGVuZ3RoKSByZXR1cm47XG4gICAgICBmb3IgKHZhciBpID0gMCwgb3V0ID0gW107IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICAgIG91dFtpXSA9IG5ldyBSYW5nZShjbGlwUG9zKHRoaXMsIHJhbmdlc1tpXS5hbmNob3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcFBvcyh0aGlzLCByYW5nZXNbaV0uaGVhZCkpO1xuICAgICAgaWYgKHByaW1hcnkgPT0gbnVsbCkgcHJpbWFyeSA9IE1hdGgubWluKHJhbmdlcy5sZW5ndGggLSAxLCB0aGlzLnNlbC5wcmltSW5kZXgpO1xuICAgICAgc2V0U2VsZWN0aW9uKHRoaXMsIG5vcm1hbGl6ZVNlbGVjdGlvbihvdXQsIHByaW1hcnkpLCBvcHRpb25zKTtcbiAgICB9KSxcbiAgICBhZGRTZWxlY3Rpb246IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGFuY2hvciwgaGVhZCwgb3B0aW9ucykge1xuICAgICAgdmFyIHJhbmdlcyA9IHRoaXMuc2VsLnJhbmdlcy5zbGljZSgwKTtcbiAgICAgIHJhbmdlcy5wdXNoKG5ldyBSYW5nZShjbGlwUG9zKHRoaXMsIGFuY2hvciksIGNsaXBQb3ModGhpcywgaGVhZCB8fCBhbmNob3IpKSk7XG4gICAgICBzZXRTZWxlY3Rpb24odGhpcywgbm9ybWFsaXplU2VsZWN0aW9uKHJhbmdlcywgcmFuZ2VzLmxlbmd0aCAtIDEpLCBvcHRpb25zKTtcbiAgICB9KSxcblxuICAgIGdldFNlbGVjdGlvbjogZnVuY3Rpb24obGluZVNlcCkge1xuICAgICAgdmFyIHJhbmdlcyA9IHRoaXMuc2VsLnJhbmdlcywgbGluZXM7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2VsID0gZ2V0QmV0d2Vlbih0aGlzLCByYW5nZXNbaV0uZnJvbSgpLCByYW5nZXNbaV0udG8oKSk7XG4gICAgICAgIGxpbmVzID0gbGluZXMgPyBsaW5lcy5jb25jYXQoc2VsKSA6IHNlbDtcbiAgICAgIH1cbiAgICAgIGlmIChsaW5lU2VwID09PSBmYWxzZSkgcmV0dXJuIGxpbmVzO1xuICAgICAgZWxzZSByZXR1cm4gbGluZXMuam9pbihsaW5lU2VwIHx8IHRoaXMubGluZVNlcGFyYXRvcigpKTtcbiAgICB9LFxuICAgIGdldFNlbGVjdGlvbnM6IGZ1bmN0aW9uKGxpbmVTZXApIHtcbiAgICAgIHZhciBwYXJ0cyA9IFtdLCByYW5nZXMgPSB0aGlzLnNlbC5yYW5nZXM7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2VsID0gZ2V0QmV0d2Vlbih0aGlzLCByYW5nZXNbaV0uZnJvbSgpLCByYW5nZXNbaV0udG8oKSk7XG4gICAgICAgIGlmIChsaW5lU2VwICE9PSBmYWxzZSkgc2VsID0gc2VsLmpvaW4obGluZVNlcCB8fCB0aGlzLmxpbmVTZXBhcmF0b3IoKSk7XG4gICAgICAgIHBhcnRzW2ldID0gc2VsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBhcnRzO1xuICAgIH0sXG4gICAgcmVwbGFjZVNlbGVjdGlvbjogZnVuY3Rpb24oY29kZSwgY29sbGFwc2UsIG9yaWdpbikge1xuICAgICAgdmFyIGR1cCA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnNlbC5yYW5nZXMubGVuZ3RoOyBpKyspXG4gICAgICAgIGR1cFtpXSA9IGNvZGU7XG4gICAgICB0aGlzLnJlcGxhY2VTZWxlY3Rpb25zKGR1cCwgY29sbGFwc2UsIG9yaWdpbiB8fCBcIitpbnB1dFwiKTtcbiAgICB9LFxuICAgIHJlcGxhY2VTZWxlY3Rpb25zOiBkb2NNZXRob2RPcChmdW5jdGlvbihjb2RlLCBjb2xsYXBzZSwgb3JpZ2luKSB7XG4gICAgICB2YXIgY2hhbmdlcyA9IFtdLCBzZWwgPSB0aGlzLnNlbDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmFuZ2UgPSBzZWwucmFuZ2VzW2ldO1xuICAgICAgICBjaGFuZ2VzW2ldID0ge2Zyb206IHJhbmdlLmZyb20oKSwgdG86IHJhbmdlLnRvKCksIHRleHQ6IHRoaXMuc3BsaXRMaW5lcyhjb2RlW2ldKSwgb3JpZ2luOiBvcmlnaW59O1xuICAgICAgfVxuICAgICAgdmFyIG5ld1NlbCA9IGNvbGxhcHNlICYmIGNvbGxhcHNlICE9IFwiZW5kXCIgJiYgY29tcHV0ZVJlcGxhY2VkU2VsKHRoaXMsIGNoYW5nZXMsIGNvbGxhcHNlKTtcbiAgICAgIGZvciAodmFyIGkgPSBjaGFuZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKVxuICAgICAgICBtYWtlQ2hhbmdlKHRoaXMsIGNoYW5nZXNbaV0pO1xuICAgICAgaWYgKG5ld1NlbCkgc2V0U2VsZWN0aW9uUmVwbGFjZUhpc3RvcnkodGhpcywgbmV3U2VsKTtcbiAgICAgIGVsc2UgaWYgKHRoaXMuY20pIGVuc3VyZUN1cnNvclZpc2libGUodGhpcy5jbSk7XG4gICAgfSksXG4gICAgdW5kbzogZG9jTWV0aG9kT3AoZnVuY3Rpb24oKSB7bWFrZUNoYW5nZUZyb21IaXN0b3J5KHRoaXMsIFwidW5kb1wiKTt9KSxcbiAgICByZWRvOiBkb2NNZXRob2RPcChmdW5jdGlvbigpIHttYWtlQ2hhbmdlRnJvbUhpc3RvcnkodGhpcywgXCJyZWRvXCIpO30pLFxuICAgIHVuZG9TZWxlY3Rpb246IGRvY01ldGhvZE9wKGZ1bmN0aW9uKCkge21ha2VDaGFuZ2VGcm9tSGlzdG9yeSh0aGlzLCBcInVuZG9cIiwgdHJ1ZSk7fSksXG4gICAgcmVkb1NlbGVjdGlvbjogZG9jTWV0aG9kT3AoZnVuY3Rpb24oKSB7bWFrZUNoYW5nZUZyb21IaXN0b3J5KHRoaXMsIFwicmVkb1wiLCB0cnVlKTt9KSxcblxuICAgIHNldEV4dGVuZGluZzogZnVuY3Rpb24odmFsKSB7dGhpcy5leHRlbmQgPSB2YWw7fSxcbiAgICBnZXRFeHRlbmRpbmc6IGZ1bmN0aW9uKCkge3JldHVybiB0aGlzLmV4dGVuZDt9LFxuXG4gICAgaGlzdG9yeVNpemU6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGhpc3QgPSB0aGlzLmhpc3RvcnksIGRvbmUgPSAwLCB1bmRvbmUgPSAwO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0LmRvbmUubGVuZ3RoOyBpKyspIGlmICghaGlzdC5kb25lW2ldLnJhbmdlcykgKytkb25lO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0LnVuZG9uZS5sZW5ndGg7IGkrKykgaWYgKCFoaXN0LnVuZG9uZVtpXS5yYW5nZXMpICsrdW5kb25lO1xuICAgICAgcmV0dXJuIHt1bmRvOiBkb25lLCByZWRvOiB1bmRvbmV9O1xuICAgIH0sXG4gICAgY2xlYXJIaXN0b3J5OiBmdW5jdGlvbigpIHt0aGlzLmhpc3RvcnkgPSBuZXcgSGlzdG9yeSh0aGlzLmhpc3RvcnkubWF4R2VuZXJhdGlvbik7fSxcblxuICAgIG1hcmtDbGVhbjogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmNsZWFuR2VuZXJhdGlvbiA9IHRoaXMuY2hhbmdlR2VuZXJhdGlvbih0cnVlKTtcbiAgICB9LFxuICAgIGNoYW5nZUdlbmVyYXRpb246IGZ1bmN0aW9uKGZvcmNlU3BsaXQpIHtcbiAgICAgIGlmIChmb3JjZVNwbGl0KVxuICAgICAgICB0aGlzLmhpc3RvcnkubGFzdE9wID0gdGhpcy5oaXN0b3J5Lmxhc3RTZWxPcCA9IHRoaXMuaGlzdG9yeS5sYXN0T3JpZ2luID0gbnVsbDtcbiAgICAgIHJldHVybiB0aGlzLmhpc3RvcnkuZ2VuZXJhdGlvbjtcbiAgICB9LFxuICAgIGlzQ2xlYW46IGZ1bmN0aW9uIChnZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLmhpc3RvcnkuZ2VuZXJhdGlvbiA9PSAoZ2VuIHx8IHRoaXMuY2xlYW5HZW5lcmF0aW9uKTtcbiAgICB9LFxuXG4gICAgZ2V0SGlzdG9yeTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4ge2RvbmU6IGNvcHlIaXN0b3J5QXJyYXkodGhpcy5oaXN0b3J5LmRvbmUpLFxuICAgICAgICAgICAgICB1bmRvbmU6IGNvcHlIaXN0b3J5QXJyYXkodGhpcy5oaXN0b3J5LnVuZG9uZSl9O1xuICAgIH0sXG4gICAgc2V0SGlzdG9yeTogZnVuY3Rpb24oaGlzdERhdGEpIHtcbiAgICAgIHZhciBoaXN0ID0gdGhpcy5oaXN0b3J5ID0gbmV3IEhpc3RvcnkodGhpcy5oaXN0b3J5Lm1heEdlbmVyYXRpb24pO1xuICAgICAgaGlzdC5kb25lID0gY29weUhpc3RvcnlBcnJheShoaXN0RGF0YS5kb25lLnNsaWNlKDApLCBudWxsLCB0cnVlKTtcbiAgICAgIGhpc3QudW5kb25lID0gY29weUhpc3RvcnlBcnJheShoaXN0RGF0YS51bmRvbmUuc2xpY2UoMCksIG51bGwsIHRydWUpO1xuICAgIH0sXG5cbiAgICBhZGRMaW5lQ2xhc3M6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGhhbmRsZSwgd2hlcmUsIGNscykge1xuICAgICAgcmV0dXJuIGNoYW5nZUxpbmUodGhpcywgaGFuZGxlLCB3aGVyZSA9PSBcImd1dHRlclwiID8gXCJndXR0ZXJcIiA6IFwiY2xhc3NcIiwgZnVuY3Rpb24obGluZSkge1xuICAgICAgICB2YXIgcHJvcCA9IHdoZXJlID09IFwidGV4dFwiID8gXCJ0ZXh0Q2xhc3NcIlxuICAgICAgICAgICAgICAgICA6IHdoZXJlID09IFwiYmFja2dyb3VuZFwiID8gXCJiZ0NsYXNzXCJcbiAgICAgICAgICAgICAgICAgOiB3aGVyZSA9PSBcImd1dHRlclwiID8gXCJndXR0ZXJDbGFzc1wiIDogXCJ3cmFwQ2xhc3NcIjtcbiAgICAgICAgaWYgKCFsaW5lW3Byb3BdKSBsaW5lW3Byb3BdID0gY2xzO1xuICAgICAgICBlbHNlIGlmIChjbGFzc1Rlc3QoY2xzKS50ZXN0KGxpbmVbcHJvcF0pKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGVsc2UgbGluZVtwcm9wXSArPSBcIiBcIiArIGNscztcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KTtcbiAgICB9KSxcbiAgICByZW1vdmVMaW5lQ2xhc3M6IGRvY01ldGhvZE9wKGZ1bmN0aW9uKGhhbmRsZSwgd2hlcmUsIGNscykge1xuICAgICAgcmV0dXJuIGNoYW5nZUxpbmUodGhpcywgaGFuZGxlLCB3aGVyZSA9PSBcImd1dHRlclwiID8gXCJndXR0ZXJcIiA6IFwiY2xhc3NcIiwgZnVuY3Rpb24obGluZSkge1xuICAgICAgICB2YXIgcHJvcCA9IHdoZXJlID09IFwidGV4dFwiID8gXCJ0ZXh0Q2xhc3NcIlxuICAgICAgICAgICAgICAgICA6IHdoZXJlID09IFwiYmFja2dyb3VuZFwiID8gXCJiZ0NsYXNzXCJcbiAgICAgICAgICAgICAgICAgOiB3aGVyZSA9PSBcImd1dHRlclwiID8gXCJndXR0ZXJDbGFzc1wiIDogXCJ3cmFwQ2xhc3NcIjtcbiAgICAgICAgdmFyIGN1ciA9IGxpbmVbcHJvcF07XG4gICAgICAgIGlmICghY3VyKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGVsc2UgaWYgKGNscyA9PSBudWxsKSBsaW5lW3Byb3BdID0gbnVsbDtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIGZvdW5kID0gY3VyLm1hdGNoKGNsYXNzVGVzdChjbHMpKTtcbiAgICAgICAgICBpZiAoIWZvdW5kKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgdmFyIGVuZCA9IGZvdW5kLmluZGV4ICsgZm91bmRbMF0ubGVuZ3RoO1xuICAgICAgICAgIGxpbmVbcHJvcF0gPSBjdXIuc2xpY2UoMCwgZm91bmQuaW5kZXgpICsgKCFmb3VuZC5pbmRleCB8fCBlbmQgPT0gY3VyLmxlbmd0aCA/IFwiXCIgOiBcIiBcIikgKyBjdXIuc2xpY2UoZW5kKSB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSk7XG4gICAgfSksXG5cbiAgICBhZGRMaW5lV2lkZ2V0OiBkb2NNZXRob2RPcChmdW5jdGlvbihoYW5kbGUsIG5vZGUsIG9wdGlvbnMpIHtcbiAgICAgIHJldHVybiBhZGRMaW5lV2lkZ2V0KHRoaXMsIGhhbmRsZSwgbm9kZSwgb3B0aW9ucyk7XG4gICAgfSksXG4gICAgcmVtb3ZlTGluZVdpZGdldDogZnVuY3Rpb24od2lkZ2V0KSB7IHdpZGdldC5jbGVhcigpOyB9LFxuXG4gICAgbWFya1RleHQ6IGZ1bmN0aW9uKGZyb20sIHRvLCBvcHRpb25zKSB7XG4gICAgICByZXR1cm4gbWFya1RleHQodGhpcywgY2xpcFBvcyh0aGlzLCBmcm9tKSwgY2xpcFBvcyh0aGlzLCB0byksIG9wdGlvbnMsIG9wdGlvbnMgJiYgb3B0aW9ucy50eXBlIHx8IFwicmFuZ2VcIik7XG4gICAgfSxcbiAgICBzZXRCb29rbWFyazogZnVuY3Rpb24ocG9zLCBvcHRpb25zKSB7XG4gICAgICB2YXIgcmVhbE9wdHMgPSB7cmVwbGFjZWRXaXRoOiBvcHRpb25zICYmIChvcHRpb25zLm5vZGVUeXBlID09IG51bGwgPyBvcHRpb25zLndpZGdldCA6IG9wdGlvbnMpLFxuICAgICAgICAgICAgICAgICAgICAgIGluc2VydExlZnQ6IG9wdGlvbnMgJiYgb3B0aW9ucy5pbnNlcnRMZWZ0LFxuICAgICAgICAgICAgICAgICAgICAgIGNsZWFyV2hlbkVtcHR5OiBmYWxzZSwgc2hhcmVkOiBvcHRpb25zICYmIG9wdGlvbnMuc2hhcmVkLFxuICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZU1vdXNlRXZlbnRzOiBvcHRpb25zICYmIG9wdGlvbnMuaGFuZGxlTW91c2VFdmVudHN9O1xuICAgICAgcG9zID0gY2xpcFBvcyh0aGlzLCBwb3MpO1xuICAgICAgcmV0dXJuIG1hcmtUZXh0KHRoaXMsIHBvcywgcG9zLCByZWFsT3B0cywgXCJib29rbWFya1wiKTtcbiAgICB9LFxuICAgIGZpbmRNYXJrc0F0OiBmdW5jdGlvbihwb3MpIHtcbiAgICAgIHBvcyA9IGNsaXBQb3ModGhpcywgcG9zKTtcbiAgICAgIHZhciBtYXJrZXJzID0gW10sIHNwYW5zID0gZ2V0TGluZSh0aGlzLCBwb3MubGluZSkubWFya2VkU3BhbnM7XG4gICAgICBpZiAoc3BhbnMpIGZvciAodmFyIGkgPSAwOyBpIDwgc3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHNwYW4gPSBzcGFuc1tpXTtcbiAgICAgICAgaWYgKChzcGFuLmZyb20gPT0gbnVsbCB8fCBzcGFuLmZyb20gPD0gcG9zLmNoKSAmJlxuICAgICAgICAgICAgKHNwYW4udG8gPT0gbnVsbCB8fCBzcGFuLnRvID49IHBvcy5jaCkpXG4gICAgICAgICAgbWFya2Vycy5wdXNoKHNwYW4ubWFya2VyLnBhcmVudCB8fCBzcGFuLm1hcmtlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gbWFya2VycztcbiAgICB9LFxuICAgIGZpbmRNYXJrczogZnVuY3Rpb24oZnJvbSwgdG8sIGZpbHRlcikge1xuICAgICAgZnJvbSA9IGNsaXBQb3ModGhpcywgZnJvbSk7IHRvID0gY2xpcFBvcyh0aGlzLCB0byk7XG4gICAgICB2YXIgZm91bmQgPSBbXSwgbGluZU5vID0gZnJvbS5saW5lO1xuICAgICAgdGhpcy5pdGVyKGZyb20ubGluZSwgdG8ubGluZSArIDEsIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgdmFyIHNwYW5zID0gbGluZS5tYXJrZWRTcGFucztcbiAgICAgICAgaWYgKHNwYW5zKSBmb3IgKHZhciBpID0gMDsgaSA8IHNwYW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHNwYW4gPSBzcGFuc1tpXTtcbiAgICAgICAgICBpZiAoISh
23459saW5lTm8gPT0gZnJvbS5saW5lICYmIGZyb20uY2ggPiBzcGFuLnRvIHx8XG4gICAgICAgICAgICAgICAgc3Bhbi5mcm9tID09IG51bGwgJiYgbGluZU5vICE9IGZyb20ubGluZXx8XG4gICAgICAgICAgICAgICAgbGluZU5vID09IHRvLmxpbmUgJiYgc3Bhbi5mcm9tID4gdG8uY2gpICYmXG4gICAgICAgICAgICAgICghZmlsdGVyIHx8IGZpbHRlcihzcGFuLm1hcmtlcikpKVxuICAgICAgICAgICAgZm91bmQucHVzaChzcGFuLm1hcmtlci5wYXJlbnQgfHwgc3Bhbi5tYXJrZXIpO1xuICAgICAgICB9XG4gICAgICAgICsrbGluZU5vO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gZm91bmQ7XG4gICAgfSxcbiAgICBnZXRBbGxNYXJrczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbWFya2VycyA9IFtdO1xuICAgICAgdGhpcy5pdGVyKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgdmFyIHNwcyA9IGxpbmUubWFya2VkU3BhbnM7XG4gICAgICAgIGlmIChzcHMpIGZvciAodmFyIGkgPSAwOyBpIDwgc3BzLmxlbmd0aDsgKytpKVxuICAgICAgICAgIGlmIChzcHNbaV0uZnJvbSAhPSBudWxsKSBtYXJrZXJzLnB1c2goc3BzW2ldLm1hcmtlcik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBtYXJrZXJzO1xuICAgIH0sXG5cbiAgICBwb3NGcm9tSW5kZXg6IGZ1bmN0aW9uKG9mZikge1xuICAgICAgdmFyIGNoLCBsaW5lTm8gPSB0aGlzLmZpcnN0O1xuICAgICAgdGhpcy5pdGVyKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgdmFyIHN6ID0gbGluZS50ZXh0Lmxlbmd0aCArIDE7XG4gICAgICAgIGlmIChzeiA+IG9mZikgeyBjaCA9IG9mZjsgcmV0dXJuIHRydWU7IH1cbiAgICAgICAgb2ZmIC09IHN6O1xuICAgICAgICArK2xpbmVObztcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGNsaXBQb3ModGhpcywgUG9zKGxpbmVObywgY2gpKTtcbiAgICB9LFxuICAgIGluZGV4RnJvbVBvczogZnVuY3Rpb24gKGNvb3Jkcykge1xuICAgICAgY29vcmRzID0gY2xpcFBvcyh0aGlzLCBjb29yZHMpO1xuICAgICAgdmFyIGluZGV4ID0gY29vcmRzLmNoO1xuICAgICAgaWYgKGNvb3Jkcy5saW5lIDwgdGhpcy5maXJzdCB8fCBjb29yZHMuY2ggPCAwKSByZXR1cm4gMDtcbiAgICAgIHRoaXMuaXRlcih0aGlzLmZpcnN0LCBjb29yZHMubGluZSwgZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgaW5kZXggKz0gbGluZS50ZXh0Lmxlbmd0aCArIDE
vendor: 45,029 bytes, line 23459
234597XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBpbmRleDtcbiAgICB9LFxuXG4gICAgY29weTogZnVuY3Rpb24oY29weUhpc3RvcnkpIHtcbiAgICAgIHZhciBkb2MgPSBuZXcgRG9jKGdldExpbmVzKHRoaXMsIHRoaXMuZmlyc3QsIHRoaXMuZmlyc3QgKyB0aGlzLnNpemUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb2RlT3B0aW9uLCB0aGlzLmZpcnN0LCB0aGlzLmxpbmVTZXApO1xuICAgICAgZG9jLnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsVG9wOyBkb2Muc2Nyb2xsTGVmdCA9IHRoaXMuc2Nyb2xsTGVmdDtcbiAgICAgIGRvYy5zZWwgPSB0aGlzLnNlbDtcbiAgICAgIGRvYy5leHRlbmQgPSBmYWxzZTtcbiAgICAgIGlmIChjb3B5SGlzdG9yeSkge1xuICAgICAgICBkb2MuaGlzdG9yeS51bmRvRGVwdGggPSB0aGlzLmhpc3RvcnkudW5kb0RlcHRoO1xuICAgICAgICBkb2Muc2V0SGlzdG9yeSh0aGlzLmdldEhpc3RvcnkoKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZG9jO1xuICAgIH0sXG5cbiAgICBsaW5rZWREb2M6IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9O1xuICAgICAgdmFyIGZyb20gPSB0aGlzLmZpcnN0LCB0byA9IHRoaXMuZmlyc3QgKyB0aGlzLnNpemU7XG4gICAgICBpZiAob3B0aW9ucy5mcm9tICE9IG51bGwgJiYgb3B0aW9ucy5mcm9tID4gZnJvbSkgZnJvbSA9IG9wdGlvbnMuZnJvbTtcbiAgICAgIGlmIChvcHRpb25zLnRvICE9IG51bGwgJiYgb3B0aW9ucy50byA8IHRvKSB0byA9IG9wdGlvbnMudG87XG4gICAgICB2YXIgY29weSA9IG5ldyBEb2MoZ2V0TGluZXModGhpcywgZnJvbSwgdG8pLCBvcHRpb25zLm1vZGUgfHwgdGhpcy5tb2RlT3B0aW9uLCBmcm9tLCB0aGlzLmxpbmVTZXApO1xuICAgICAgaWYgKG9wdGlvbnMuc2hhcmVkSGlzdCkgY29weS5oaXN0b3J5ID0gdGhpcy5oaXN0b3J5O1xuICAgICAgKHRoaXMubGlua2VkIHx8ICh0aGlzLmxpbmtlZCA9IFtdKSkucHVzaCh7ZG9jOiBjb3B5LCBzaGFyZWRIaXN0OiBvcHRpb25zLnNoYXJlZEhpc3R9KTtcbiAgICAgIGNvcHkubGlua2VkID0gW3tkb2M6IHRoaXMsIGlzUGFyZW50OiB0cnVlLCBzaGFyZWRIaXN0OiBvcHRpb25zLnNoYXJlZEhpc3R9XTtcbiAgICAgIGNvcHlTaGFyZWRNYXJrZXJzKGNvcHksIGZpbmRTaGFyZWRNYXJrZXJzKHRoaXMpKTtcbiAgICAgIHJldHVybiBjb3B5O1xuICAgIH0sXG4gICAgdW5saW5rRG9jOiBmdW5jdGlvbihvdGhlcikge1xuICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgQ29kZU1pcnJvcikgb3RoZXIgPSBvdGhlci5kb2M7XG4gICAgICBpZiAodGhpcy5saW5rZWQpIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saW5rZWQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGxpbmsgPSB0aGlzLmxpbmtlZFtpXTtcbiAgICAgICAgaWYgKGxpbmsuZG9jICE9IG90aGVyKSBjb250aW51ZTtcbiAgICAgICAgdGhpcy5saW5rZWQuc3BsaWNlKGksIDEpO1xuICAgICAgICBvdGhlci51bmxpbmtEb2ModGhpcyk7XG4gICAgICAgIGRldGFjaFNoYXJlZE1hcmtlcnMoZmluZFNoYXJlZE1hcmtlcnModGhpcykpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vIElmIHRoZSBoaXN0b3JpZXMgd2VyZSBzaGFyZWQsIHNwbGl0IHRoZW0gYWdhaW5cbiAgICAgIGlmIChvdGhlci5oaXN0b3J5ID09IHRoaXMuaGlzdG9yeSkge1xuICAgICAgICB2YXIgc3BsaXRJZHMgPSBbb3RoZXIuaWRdO1xuICAgICAgICBsaW5rZWREb2NzKG90aGVyLCBmdW5jdGlvbihkb2MpIHtzcGxpdElkcy5wdXNoKGRvYy5pZCk7fSwgdHJ1ZSk7XG4gICAgICAgIG90aGVyLmhpc3RvcnkgPSBuZXcgSGlzdG9yeShudWxsKTtcbiAgICAgICAgb3RoZXIuaGlzdG9yeS5kb25lID0gY29weUhpc3RvcnlBcnJheSh0aGlzLmhpc3RvcnkuZG9uZSwgc3BsaXRJZHMpO1xuICAgICAgICBvdGhlci5oaXN0b3J5LnVuZG9uZSA9IGNvcHlIaXN0b3J5QXJyYXkodGhpcy5oaXN0b3J5LnVuZG9uZSwgc3BsaXRJZHMpO1xuICAgICAgfVxuICAgIH0sXG4gICAgaXRlckxpbmtlZERvY3M6IGZ1bmN0aW9uKGYpIHtsaW5rZWREb2NzKHRoaXMsIGYpO30sXG5cbiAgICBnZXRNb2RlOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5tb2RlO30sXG4gICAgZ2V0RWRpdG9yOiBmdW5jdGlvbigpIHtyZXR1cm4gdGhpcy5jbTt9LFxuXG4gICAgc3BsaXRMaW5lczogZnVuY3Rpb24oc3RyKSB7XG4gICAgICBpZiAodGhpcy5saW5lU2VwKSByZXR1cm4gc3RyLnNwbGl0KHRoaXMubGluZVNlcCk7XG4gICAgICByZXR1cm4gc3BsaXRMaW5lc0F1dG8oc3RyKTtcbiAgICB9LFxuICAgIGxpbmVTZXBhcmF0b3I6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5saW5lU2VwIHx8IFwiXFxuXCI7IH1cbiAgfSk7XG5cbiAgLy8gUHVibGljIGFsaWFzLlxuICBEb2MucHJvdG90eXBlLmVhY2hMaW5lID0gRG9jLnByb3RvdHlwZS5pdGVyO1xuXG4gIC8vIFNldCB1cCBtZXRob2RzIG9uIENvZGVNaXJyb3IncyBwcm90b3R5cGUgdG8gcmVkaXJlY3QgdG8gdGhlIGVkaXRvcidzIGRvY3VtZW50LlxuICB2YXIgZG9udERlbGVnYXRlID0gXCJpdGVyIGluc2VydCByZW1vdmUgY29weSBnZXRFZGl0b3IgY29uc3RydWN0b3JcIi5zcGxpdChcIiBcIik7XG4gIGZvciAodmFyIHByb3AgaW4gRG9jLnByb3RvdHlwZSkgaWYgKERvYy5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkocHJvcCkgJiYgaW5kZXhPZihkb250RGVsZWdhdGUsIHByb3ApIDwgMClcbiAgICBDb2RlTWlycm9yLnByb3RvdHlwZVtwcm9wXSA9IChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtyZXR1cm4gbWV0aG9kLmFwcGx5KHRoaXMuZG9jLCBhcmd1bWVudHMpO307XG4gICAgfSkoRG9jLnByb3RvdHlwZVtwcm9wXSk7XG5cbiAgZXZlbnRNaXhpbihEb2MpO1xuXG4gIC8vIENhbGwgZiBmb3IgYWxsIGxpbmtlZCBkb2N1bWVudHMuXG4gIGZ1bmN0aW9uIGxpbmtlZERvY3MoZG9jLCBmLCBzaGFyZWRIaXN0T25seSkge1xuICAgIGZ1bmN0aW9uIHByb3BhZ2F0ZShkb2MsIHNraXAsIHNoYXJlZEhpc3QpIHtcbiAgICAgIGlmIChkb2MubGlua2VkKSBmb3IgKHZhciBpID0gMDsgaSA8IGRvYy5saW5rZWQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHJlbCA9IGRvYy5saW5rZWRbaV07XG4gICAgICAgIGlmIChyZWwuZG9jID09IHNraXApIGNvbnRpbnVlO1xuICAgICAgICB2YXIgc2hhcmVkID0gc2hhcmVkSGlzdCAmJiByZWwuc2hhcmVkSGlzdDtcbiAgICAgICAgaWYgKHNoYXJlZEhpc3RPbmx5ICYmICFzaGFyZWQpIGNvbnRpbnVlO1xuICAgICAgICBmKHJlbC5kb2MsIHNoYXJlZCk7XG4gICAgICAgIHByb3BhZ2F0ZShyZWwuZG9jLCBkb2MsIHNoYXJlZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHByb3BhZ2F0ZShkb2MsIG51bGwsIHRydWUpO1xuICB9XG5cbiAgLy8gQXR0YWNoIGEgZG9jdW1lbnQgdG8gYW4gZWRpdG9yLlxuICBmdW5jdGlvbiBhdHRhY2hEb2MoY20sIGRvYykge1xuICAgIGlmIChkb2MuY20pIHRocm93IG5ldyBFcnJvcihcIlRoaXMgZG9jdW1lbnQgaXMgYWxyZWFkeSBpbiB1c2UuXCIpO1xuICAgIGNtLmRvYyA9IGRvYztcbiAgICBkb2MuY20gPSBjbTtcbiAgICBlc3RpbWF0ZUxpbmVIZWlnaHRzKGNtKTtcbiAgICBsb2FkTW9kZShjbSk7XG4gICAgaWYgKCFjbS5vcHRpb25zLmxpbmVXcmFwcGluZykgZmluZE1heExpbmUoY20pO1xuICAgIGNtLm9wdGlvbnMubW9kZSA9IGRvYy5tb2RlT3B0aW9uO1xuICAgIHJlZ0NoYW5nZShjbSk7XG4gIH1cblxuICAvLyBMSU5FIFVUSUxJVElFU1xuXG4gIC8vIEZpbmQgdGhlIGxpbmUgb2JqZWN0IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIGxpbmUgbnVtYmVyLlxuICBmdW5jdGlvbiBnZXRMaW5lKGRvYywgbikge1xuICAgIG4gLT0gZG9jLmZpcnN0O1xuICAgIGlmIChuIDwgMCB8fCBuID49IGRvYy5zaXplKSB0aHJvdyBuZXcgRXJyb3IoXCJUaGVyZSBpcyBubyBsaW5lIFwiICsgKG4gKyBkb2MuZmlyc3QpICsgXCIgaW4gdGhlIGRvY3VtZW50LlwiKTtcbiAgICBmb3IgKHZhciBjaHVuayA9IGRvYzsgIWNodW5rLmxpbmVzOykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7OyArK2kpIHtcbiAgICAgICAgdmFyIGNoaWxkID0gY2h1bmsuY2hpbGRyZW5baV0sIHN6ID0gY2hpbGQuY2h1bmtTaXplKCk7XG4gICAgICAgIGlmIChuIDwgc3opIHsgY2h1bmsgPSBjaGlsZDsgYnJlYWs7IH1cbiAgICAgICAgbiAtPSBzejtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNodW5rLmxpbmVzW25dO1xuICB9XG5cbiAgLy8gR2V0IHRoZSBwYXJ0IG9mIGEgZG9jdW1lbnQgYmV0d2VlbiB0d28gcG9zaXRpb25zLCBhcyBhbiBhcnJheSBvZlxuICAvLyBzdHJpbmdzLlxuICBmdW5jdGlvbiBnZXRCZXR3ZWVuKGRvYywgc3RhcnQsIGVuZCkge1xuICAgIHZhciBvdXQgPSBbXSwgbiA9IHN0YXJ0LmxpbmU7XG4gICAgZG9jLml0ZXIoc3RhcnQubGluZSwgZW5kLmxpbmUgKyAxLCBmdW5jdGlvbihsaW5lKSB7XG4gICAgICB2YXIgdGV4dCA9IGxpbmUudGV4dDtcbiAgICAgIGlmIChuID09IGVuZC5saW5lKSB0ZXh0ID0gdGV4dC5zbGljZSgwLCBlbmQuY2gpO1xuICAgICAgaWYgKG4gPT0gc3RhcnQubGluZSkgdGV4dCA9IHRleHQuc2xpY2Uoc3RhcnQuY2gpO1xuICAgICAgb3V0LnB1c2godGV4dCk7XG4gICAgICArK247XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuICAvLyBHZXQgdGhlIGxpbmVzIGJldHdlZW4gZnJvbSBhbmQgdG8sIGFzIGFycmF5IG9mIHN0cmluZ3MuXG4gIGZ1bmN0aW9uIGdldExpbmVzKGRvYywgZnJvbSwgdG8pIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgZG9jLml0ZXIoZnJvbSwgdG8sIGZ1bmN0aW9uKGxpbmUpIHsgb3V0LnB1c2gobGluZS50ZXh0KTsgfSk7XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8vIFVwZGF0ZSB0aGUgaGVpZ2h0IG9mIGEgbGluZSwgcHJvcGFnYXRpbmcgdGhlIGhlaWdodCBjaGFuZ2VcbiAgLy8gdXB3YXJkcyB0byBwYXJlbnQgbm9kZXMuXG4gIGZ1bmN0aW9uIHVwZGF0ZUxpbmVIZWlnaHQobGluZSwgaGVpZ2h0KSB7XG4gICAgdmFyIGRpZmYgPSBoZWlnaHQgLSBsaW5lLmhlaWdodDtcbiAgICBpZiAoZGlmZikgZm9yICh2YXIgbiA9IGxpbmU7IG47IG4gPSBuLnBhcmVudCkgbi5oZWlnaHQgKz0gZGlmZjtcbiAgfVxuXG4gIC8vIEdpdmVuIGEgbGluZSBvYmplY3QsIGZpbmQgaXRzIGxpbmUgbnVtYmVyIGJ5IHdhbGtpbmcgdXAgdGhyb3VnaFxuICAvLyBpdHMgcGFyZW50IGxpbmtzLlxuICBmdW5jdGlvbiBsaW5lTm8obGluZSkge1xuICAgIGlmIChsaW5lLnBhcmVudCA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgY3VyID0gbGluZS5wYXJlbnQsIG5vID0gaW5kZXhPZihjdXIubGluZXMsIGxpbmUpO1xuICAgIGZvciAodmFyIGNodW5rID0gY3VyLnBhcmVudDsgY2h1bms7IGN1ciA9IGNodW5rLCBjaHVuayA9IGNodW5rLnBhcmVudCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7OyArK2kpIHtcbiAgICAgICAgaWYgKGNodW5rLmNoaWxkcmVuW2ldID09IGN1cikgYnJlYWs7XG4gICAgICAgIG5vICs9IGNodW5rLmNoaWxkcmVuW2ldLmNodW5rU2l6ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbm8gKyBjdXIuZmlyc3Q7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBsaW5lIGF0IHRoZSBnaXZlbiB2ZXJ0aWNhbCBwb3NpdGlvbiwgdXNpbmcgdGhlIGhlaWdodFxuICAvLyBpbmZvcm1hdGlvbiBpbiB0aGUgZG9jdW1lbnQgdHJlZS5cbiAgZnVuY3Rpb24gbGluZUF0SGVpZ2h0KGNodW5rLCBoKSB7XG4gICAgdmFyIG4gPSBjaHVuay5maXJzdDtcbiAgICBvdXRlcjogZG8ge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaHVuay5jaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY2hpbGQgPSBjaHVuay5jaGlsZHJlbltpXSwgY2ggPSBjaGlsZC5oZWlnaHQ7XG4gICAgICAgIGlmIChoIDwgY2gpIHsgY2h1bmsgPSBjaGlsZDsgY29udGludWUgb3V0ZXI7IH1cbiAgICAgICAgaCAtPSBjaDtcbiAgICAgICAgbiArPSBjaGlsZC5jaHVua1NpemUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuO1xuICAgIH0gd2hpbGUgKCFjaHVuay5saW5lcyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaHVuay5saW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxpbmUgPSBjaHVuay5saW5lc1tpXSwgbGggPSBsaW5lLmhlaWdodDtcbiAgICAgIGlmIChoIDwgbGgpIGJyZWFrO1xuICAgICAgaCAtPSBsaDtcbiAgICB9XG4gICAgcmV0dXJuIG4gKyBpO1xuICB9XG5cblxuICAvLyBGaW5kIHRoZSBoZWlnaHQgYWJvdmUgdGhlIGdpdmVuIGxpbmUuXG4gIGZ1bmN0aW9uIGhlaWdodEF0TGluZShsaW5lT2JqKSB7XG4gICAgbGluZU9iaiA9IHZpc3VhbExpbmUobGluZU9iaik7XG5cbiAgICB2YXIgaCA9IDAsIGNodW5rID0gbGluZU9iai5wYXJlbnQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaHVuay5saW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxpbmUgPSBjaHVuay5saW5lc1tpXTtcbiAgICAgIGlmIChsaW5lID09IGxpbmVPYmopIGJyZWFrO1xuICAgICAgZWxzZSBoICs9IGxpbmUuaGVpZ2h0O1xuICAgIH1cbiAgICBmb3IgKHZhciBwID0gY2h1bmsucGFyZW50OyBwOyBjaHVuayA9IHAsIHAgPSBjaHVuay5wYXJlbnQpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcC5jaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgY3VyID0gcC5jaGlsZHJlbltpXTtcbiAgICAgICAgaWYgKGN1ciA9PSBjaHVuaykgYnJlYWs7XG4gICAgICAgIGVsc2UgaCArPSBjdXIuaGVpZ2h0O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaDtcbiAgfVxuXG4gIC8vIEdldCB0aGUgYmlkaSBvcmRlcmluZyBmb3IgdGhlIGdpdmVuIGxpbmUgKGFuZCBjYWNoZSBpdCkuIFJldHVybnNcbiAgLy8gZmFsc2UgZm9yIGxpbmVzIHRoYXQgYXJlIGZ1bGx5IGxlZnQtdG8tcmlnaHQsIGFuZCBhbiBhcnJheSBvZlxuICAvLyBCaWRpU3BhbiBvYmplY3RzIG90aGVyd2lzZS5cbiAgZnVuY3Rpb24gZ2V0T3JkZXIobGluZSkge1xuICAgIHZhciBvcmRlciA9IGxpbmUub3JkZXI7XG4gICAgaWYgKG9yZGVyID09IG51bGwpIG9yZGVyID0gbGluZS5vcmRlciA9IGJpZGlPcmRlcmluZyhsaW5lLnRleHQpO1xuICAgIHJldHVybiBvcmRlcjtcbiAgfVxuXG4gIC8vIEhJU1RPUllcblxuICBmdW5jdGlvbiBIaXN0b3J5KHN0YXJ0R2VuKSB7XG4gICAgLy8gQXJyYXlzIG9mIGNoYW5nZSBldmVudHMgYW5kIHNlbGVjdGlvbnMuIERvaW5nIHNvbWV0aGluZyBhZGRzIGFuXG4gICAgLy8gZXZlbnQgdG8gZG9uZSBhbmQgY2xlYXJzIHVuZG8uIFVuZG9pbmcgbW92ZXMgZXZlbnRzIGZyb20gZG9uZVxuICAgIC8vIHRvIHVuZG9uZSwgcmVkb2luZyBtb3ZlcyB0aGVtIGluIHRoZSBvdGhlciBkaXJlY3Rpb24uXG4gICAgdGhpcy5kb25lID0gW107IHRoaXMudW5kb25lID0gW107XG4gICAgdGhpcy51bmRvRGVwdGggPSBJbmZpbml0eTtcbiAgICAvLyBVc2VkIHRvIHRyYWNrIHdoZW4gY2hhbmdlcyBjYW4gYmUgbWVyZ2VkIGludG8gYSBzaW5nbGUgdW5kb1xuICAgIC8vIGV2ZW50XG4gICAgdGhpcy5sYXN0TW9kVGltZSA9IHRoaXMubGFzdFNlbFRpbWUgPSAwO1xuICAgIHRoaXMubGFzdE9wID0gdGhpcy5sYXN0U2VsT3AgPSBudWxsO1xuICAgIHRoaXMubGFzdE9yaWdpbiA9IHRoaXMubGFzdFNlbE9yaWdpbiA9IG51bGw7XG4gICAgLy8gVXNlZCBieSB0aGUgaXNDbGVhbigpIG1ldGhvZFxuICAgIHRoaXMuZ2VuZXJhdGlvbiA9IHRoaXMubWF4R2VuZXJhdGlvbiA9IHN0YXJ0R2VuIHx8IDE7XG4gIH1cblxuICAvLyBDcmVhdGUgYSBoaXN0b3J5IGNoYW5nZSBldmVudCBmcm9tIGFuIHVwZGF0ZURvYy1zdHlsZSBjaGFuZ2VcbiAgLy8gb2JqZWN0LlxuICBmdW5jdGlvbiBoaXN0b3J5Q2hhbmdlRnJvbUNoYW5nZShkb2MsIGNoYW5nZSkge1xuICAgIHZhciBoaXN0Q2hhbmdlID0ge2Zyb206IGNvcHlQb3MoY2hhbmdlLmZyb20pLCB0bzogY2hhbmdlRW5kKGNoYW5nZSksIHRleHQ6IGdldEJldHdlZW4oZG9jLCBjaGFuZ2UuZnJvbSwgY2hhbmdlLnRvKX07XG4gICAgYXR0YWNoTG9jYWxTcGFucyhkb2MsIGhpc3RDaGFuZ2UsIGNoYW5nZS5mcm9tLmxpbmUsIGNoYW5nZS50by5saW5lICsgMSk7XG4gICAgbGlua2VkRG9jcyhkb2MsIGZ1bmN0aW9uKGRvYykge2F0dGFjaExvY2FsU3BhbnMoZG9jLCBoaXN0Q2hhbmdlLCBjaGFuZ2UuZnJvbS5saW5lLCBjaGFuZ2UudG8ubGluZSArIDEpO30sIHRydWUpO1xuICAgIHJldHVybiBoaXN0Q2hhbmdlO1xuICB9XG5cbiAgLy8gUG9wIGFsbCBzZWxlY3Rpb24gZXZlbnRzIG9mZiB0aGUgZW5kIG9mIGEgaGlzdG9yeSBhcnJheS4gU3RvcCBhdFxuICAvLyBhIGNoYW5nZSBldmVudC5cbiAgZnVuY3Rpb24gY2xlYXJTZWxlY3Rpb25FdmVudHMoYXJyYXkpIHtcbiAgICB3aGlsZSAoYXJyYXkubGVuZ3RoKSB7XG4gICAgICB2YXIgbGFzdCA9IGxzdChhcnJheSk7XG4gICAgICBpZiAobGFzdC5yYW5nZXMpIGFycmF5LnBvcCgpO1xuICAgICAgZWxzZSBicmVhaztcbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIHRoZSB0b3AgY2hhbmdlIGV2ZW50IGluIHRoZSBoaXN0b3J5LiBQb3Agb2ZmIHNlbGVjdGlvblxuICAvLyBldmVudHMgdGhhdCBhcmUgaW4gdGhlIHdheS5cbiAgZnVuY3Rpb24gbGFzdENoYW5nZUV2ZW50KGhpc3QsIGZvcmNlKSB7XG4gICAgaWYgKGZvcmNlKSB7XG4gICAgICBjbGVhclNlbGVjdGlvbkV2ZW50cyhoaXN0LmRvbmUpO1xuICAgICAgcmV0dXJuIGxzdChoaXN0LmRvbmUpO1xuICAgIH0gZWxzZSBpZiAoaGlzdC5kb25lLmxlbmd0aCAmJiAhbHN0KGhpc3QuZG9uZSkucmFuZ2VzKSB7XG4gICAgICByZXR1cm4gbHN0KGhpc3QuZG9uZSk7XG4gICAgfSBlbHNlIGlmIChoaXN0LmRvbmUubGVuZ3RoID4gMSAmJiAhaGlzdC5kb25lW2hpc3QuZG9uZS5sZW5ndGggLSAyXS5yYW5nZXMpIHtcbiAgICAgIGhpc3QuZG9uZS5wb3AoKTtcbiAgICAgIHJldHVybiBsc3QoaGlzdC5kb25lKTtcbiAgICB9XG4gIH1cblxuICAvLyBSZWdpc3RlciBhIGNoYW5nZSBpbiB0aGUgaGlzdG9yeS4gTWVyZ2VzIGNoYW5nZXMgdGhhdCBhcmUgd2l0aGluXG4gIC8vIGEgc2luZ2xlIG9wZXJhdGlvbiwgb3JlIGFyZSBjbG9zZSB0b2dldGhlciB3aXRoIGFuIG9yaWdpbiB0aGF0XG4gIC8vIGFsbG93cyBtZXJnaW5nIChzdGFydGluZyB3aXRoIFwiK1wiKSBpbnRvIGEgc2luZ2xlIGV2ZW50LlxuICBmdW5jdGlvbiBhZGRDaGFuZ2VUb0hpc3RvcnkoZG9jLCBjaGFuZ2UsIHNlbEFmdGVyLCBvcElkKSB7XG4gICAgdmFyIGhpc3QgPSBkb2MuaGlzdG9yeTtcbiAgICBoaXN0LnVuZG9uZS5sZW5ndGggPSAwO1xuICAgIHZhciB0aW1lID0gK25ldyBEYXRlLCBjdXI7XG5cbiAgICBpZiAoKGhpc3QubGFzdE9wID09IG9wSWQgfHxcbiAgICAgICAgIGhpc3QubGFzdE9yaWdpbiA9PSBjaGFuZ2Uub3JpZ2luICYmIGNoYW5nZS5vcmlnaW4gJiZcbiAgICAgICAgICgoY2hhbmdlLm9yaWdpbi5jaGFyQXQoMCkgPT0gXCIrXCIgJiYgZG9jLmNtICYmIGhpc3QubGFzdE1vZFRpbWUgPiB0aW1lIC0gZG9jLmNtLm9wdGlvbnMuaGlzdG9yeUV2ZW50RGVsYXkpIHx8XG4gICAgICAgICAgY2hhbmdlLm9yaWdpbi5jaGFyQXQoMCkgPT0gXCIqXCIpKSAmJlxuICAgICAgICAoY3VyID0gbGFzdENoYW5nZUV2ZW50KGhpc3QsIGhpc3QubGFzdE9wID09IG9wSWQpKSkge1xuICAgICAgLy8gTWVyZ2UgdGhpcyBjaGFuZ2UgaW50byB0aGUgbGFzdCBldmVudFxuICAgICAgdmFyIGxhc3QgPSBsc3QoY3VyLmNoYW5nZXMpO1xuICAgICAgaWYgKGNtcChjaGFuZ2UuZnJvbSwgY2hhbmdlLnRvKSA9PSAwICYmIGNtcChjaGFuZ2UuZnJvbSwgbGFzdC50bykgPT0gMCkge1xuICAgICAgICAvLyBPcHRpbWl6ZWQgY2FzZSBmb3Igc2ltcGxlIGluc2VydGlvbiAtLSBkb24ndCB3YW50IHRvIGFkZFxuICAgICAgICAvLyBuZXcgY2hhbmdlc2V0cyBmb3IgZXZlcnkgY2hhcmFjdGVyIHR5cGVkXG4gICAgICAgIGxhc3QudG8gPSBjaGFuZ2VFbmQoY2hhbmdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEFkZCBuZXcgc3ViLWV2ZW50XG4gICAgICAgIGN1ci5jaGFuZ2VzLnB1c2goaGlzdG9yeUNoYW5nZUZyb21DaGFuZ2UoZG9jLCBjaGFuZ2UpKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ2FuIG5vdCBiZSBtZXJnZWQsIHN0YXJ0IGEgbmV3IGV2ZW50LlxuICAgICAgdmFyIGJlZm9yZSA9IGxzdChoaXN0LmRvbmUpO1xuICAgICAgaWYgKCFiZWZvcmUgfHwgIWJlZm9yZS5yYW5nZXMpXG4gICAgICAgIHB1c2hTZWxlY3Rpb25Ub0hpc3RvcnkoZG9jLnNlbCwgaGlzdC5kb25lKTtcbiAgICAgIGN1ciA9IHtjaGFuZ2VzOiBbaGlzdG9yeUNoYW5nZUZyb21DaGFuZ2UoZG9jLCBjaGFuZ2UpXSxcbiAgICAgICAgICAgICBnZW5lcmF0aW9uOiBoaXN0LmdlbmVyYXRpb259O1xuICAgICAgaGlzdC5kb25lLnB1c2goY3VyKTtcbiAgICAgIHdoaWxlIChoaXN0LmRvbmUubGVuZ3RoID4gaGlzdC51bmRvRGVwdGgpIHtcbiAgICAgICAgaGlzdC5kb25lLnNoaWZ0KCk7XG4gICAgICAgIGlmICghaGlzdC5kb25lWzBdLnJhbmdlcykgaGlzdC5kb25lLnNoaWZ0KCk7XG4gICAgICB9XG4gICAgfVxuICAgIGhpc3QuZG9uZS5wdXNoKHNlbEFmdGVyKTtcbiAgICBoaXN0LmdlbmVyYXRpb24gPSArK2hpc3QubWF4R2VuZXJhdGlvbjtcbiAgICBoaXN0Lmxhc3RNb2RUaW1lID0gaGlzdC5sYXN0U2VsVGltZSA9IHRpbWU7XG4gICAgaGlzdC5sYXN0T3AgPSBoaXN0Lmxhc3RTZWxPcCA9IG9wSWQ7XG4gICAgaGlzdC5sYXN0T3JpZ2luID0gaGlzdC5sYXN0U2VsT3JpZ2luID0gY2hhbmdlLm9yaWdpbjtcblxuICAgIGlmICghbGFzdCkgc2lnbmFsKGRvYywgXCJoaXN0b3J5QWRkZWRcIik7XG4gIH1cblxuICBmdW5jdGlvbiBzZWxlY3Rpb25FdmVudENhbkJlTWVyZ2VkKGRvYywgb3JpZ2luLCBwcmV2LCBzZWwpIHtcbiAgICB2YXIgY2ggPSBvcmlnaW4uY2hhckF0KDApO1xuICAgIHJldHVybiBjaCA9PSBcIipcIiB8fFxuICAgICAgY2ggPT0gXCIrXCIgJiZcbiAgICAgIHByZXYucmFuZ2VzLmxlbmd0aCA9PSBzZWwucmFuZ2VzLmxlbmd0aCAmJlxuICAgICAgcHJldi5zb21ldGhpbmdTZWxlY3RlZCgpID09IHNlbC5zb21ldGhpbmdTZWxlY3RlZCgpICYmXG4gICAgICBuZXcgRGF0ZSAtIGRvYy5oaXN0b3J5Lmxhc3RTZWxUaW1lIDw9IChkb2MuY20gPyBkb2MuY20ub3B0aW9ucy5oaXN0b3J5RXZlbnREZWxheSA6IDUwMCk7XG4gIH1cblxuICAvLyBDYWxsZWQgd2hlbmV2ZXIgdGhlIHNlbGVjdGlvbiBjaGFuZ2VzLCBzZXRzIHRoZSBuZXcgc2VsZWN0aW9uIGFzXG4gIC8vIHRoZSBwZW5kaW5nIHNlbGVjdGlvbiBpbiB0aGUgaGlzdG9yeSwgYW5kIHB1c2hlcyB0aGUgb2xkIHBlbmRpbmdcbiAgLy8gc2VsZWN0aW9uIGludG8gdGhlICdkb25lJyBhcnJheSB3aGVuIGl0IHdhcyBzaWduaWZpY2FudGx5XG4gIC8vIGRpZmZlcmVudCAoaW4gbnVtYmVyIG9mIHNlbGVjdGVkIHJhbmdlcywgZW1wdGluZXNzLCBvciB0aW1lKS5cbiAgZnVuY3Rpb24gYWRkU2VsZWN0aW9uVG9IaXN0b3J5KGRvYywgc2VsLCBvcElkLCBvcHRpb25zKSB7XG4gICAgdmFyIGhpc3QgPSBkb2MuaGlzdG9yeSwgb3JpZ2luID0gb3B0aW9ucyAmJiBvcHRpb25zLm9yaWdpbjtcblxuICAgIC8vIEEgbmV3IGV2ZW50IGlzIHN0YXJ0ZWQgd2hlbiB0aGUgcHJldmlvdXMgb3JpZ2luIGRvZXMgbm90IG1hdGNoXG4gICAgLy8gdGhlIGN1cnJlbnQsIG9yIHRoZSBvcmlnaW5zIGRvbid0IGFsbG93IG1hdGNoaW5nLiBPcmlnaW5zXG4gICAgLy8gc3RhcnRpbmcgd2l0aCAqIGFyZSBhbHdheXMgbWVyZ2VkLCB0aG9zZSBzdGFydGluZyB3aXRoICsgYXJlXG4gICAgLy8gbWVyZ2VkIHdoZW4gc2ltaWxhciBhbmQgY2xvc2UgdG9nZXRoZXIgaW4gdGltZS5cbiAgICBpZiAob3BJZCA9PSBoaXN0Lmxhc3RTZWxPcCB8fFxuICAgICAgICAob3JpZ2luICYmIGhpc3QubGFzdFNlbE9yaWdpbiA9PSBvcmlnaW4gJiZcbiAgICAgICAgIChoaXN0Lmxhc3RNb2RUaW1lID09IGhpc3QubGFzdFNlbFRpbWUgJiYgaGlzdC5sYXN0T3JpZ2luID09IG9yaWdpbiB8fFxuICAgICAgICAgIHNlbGVjdGlvbkV2ZW50Q2FuQmVNZXJnZWQoZG9jLCBvcmlnaW4sIGxzdChoaXN0LmRvbmUpLCBzZWwpKSkpXG4gICAgICBoaXN0LmRvbmVbaGlzdC5kb25lLmxlbmd0aCAtIDFdID0gc2VsO1xuICAgIGVsc2VcbiAgICAgIHB1c2hTZWxlY3Rpb25Ub0hpc3Rvcnkoc2VsLCBoaXN0LmRvbmUpO1xuXG4gICAgaGlzdC5sYXN0U2VsVGltZSA9ICtuZXcgRGF0ZTtcbiAgICBoaXN0Lmxhc3RTZWxPcmlnaW4gPSBvcmlnaW47XG4gICAgaGlzdC5sYXN0U2VsT3AgPSBvcElkO1xuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuY2xlYXJSZWRvICE9PSBmYWxzZSlcbiAgICAgIGNsZWFyU2VsZWN0aW9uRXZlbnRzKGhpc3QudW5kb25lKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHB1c2hTZWxlY3Rpb25Ub0hpc3Rvcnkoc2VsLCBkZXN0KSB7XG4gICAgdmFyIHRvcCA9IGxzdChkZXN0KTtcbiAgICBpZiAoISh0b3AgJiYgdG9wLnJhbmdlcyAmJiB0b3AuZXF1YWxzKHNlbCkpKVxuICAgICAgZGVzdC5wdXNoKHNlbCk7XG4gIH1cblxuICAvLyBVc2VkIHRvIHN0b3JlIG1hcmtlZCBzcGFuIGluZm9ybWF0aW9uIGluIHRoZSBoaXN0b3J5LlxuICBmdW5jdGlvbiBhdHRhY2hMb2NhbFNwYW5zKGRvYywgY2hhbmdlLCBmcm9tLCB0bykge1xuICAgIHZhciBleGlzdGluZyA9IGNoYW5nZVtcInNwYW5zX1wiICsgZG9jLmlkXSwgbiA9IDA7XG4gICAgZG9jLml0ZXIoTWF0aC5tYXgoZG9jLmZpcnN0LCBmcm9tKSwgTWF0aC5taW4oZG9jLmZpcnN0ICsgZG9jLnNpemUsIHRvKSwgZnVuY3Rpb24obGluZSkge1xuICAgICAgaWYgKGxpbmUubWFya2VkU3BhbnMpXG4gICAgICAgIChleGlzdGluZyB8fCAoZXhpc3RpbmcgPSBjaGFuZ2VbXCJzcGFuc19cIiArIGRvYy5pZF0gPSB7fSkpW25dID0gbGluZS5tYXJrZWRTcGFucztcbiAgICAgICsrbjtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFdoZW4gdW4vcmUtZG9pbmcgcmVzdG9yZXMgdGV4dCBjb250YWluaW5nIG1hcmtlZCBzcGFucywgdGhvc2VcbiAgLy8gdGhhdCBoYXZlIGJlZW4gZXhwbGljaXRseSBjbGVhcmVkIHNob3VsZCBub3QgYmUgcmVzdG9yZWQuXG4gIGZ1bmN0aW9uIHJlbW92ZUNsZWFyZWRTcGFucyhzcGFucykge1xuICAgIGlmICghc3BhbnMpIHJldHVybiBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwLCBvdXQ7IGkgPCBzcGFucy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKHNwYW5zW2ldLm1hcmtlci5leHBsaWNpdGx5Q2xlYXJlZCkgeyBpZiAoIW91dCkgb3V0ID0gc3BhbnMuc2xpY2UoMCwgaSk7IH1cbiAgICAgIGVsc2UgaWYgKG91dCkgb3V0LnB1c2goc3BhbnNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gIW91dCA/IHNwYW5zIDogb3V0Lmxlbmd0aCA/IG91dCA6IG51bGw7XG4gIH1cblxuICAvLyBSZXRyaWV2ZSBhbmQgZmlsdGVyIHRoZSBvbGQgbWFya2VkIHNwYW5zIHN0b3JlZCBpbiBhIGNoYW5nZSBldmVudC5cbiAgZnVuY3Rpb24gZ2V0T2xkU3BhbnMoZG9jLCBjaGFuZ2UpIHtcbiAgICB2YXIgZm91bmQgPSBjaGFuZ2VbXCJzcGFuc19cIiArIGRvYy5pZF07XG4gICAgaWYgKCFmb3VuZCkgcmV0dXJuIG51bGw7XG4gICAgZm9yICh2YXIgaSA9IDAsIG53ID0gW107IGkgPCBjaGFuZ2UudGV4dC5sZW5ndGg7ICsraSlcbiAgICAgIG53LnB1c2gocmVtb3ZlQ2xlYXJlZFNwYW5zKGZvdW5kW2ldKSk7XG4gICAgcmV0dXJuIG53O1xuICB9XG5cbiAgLy8gVXNlZCBib3RoIHRvIHByb3ZpZGUgYSBKU09OLXNhZmUgb2JqZWN0IGluIC5nZXRIaXN0b3J5LCBhbmQsIHdoZW5cbiAgLy8gZGV0YWNoaW5nIGEgZG9jdW1lbnQsIHRvIHNwbGl0IHRoZSBoaXN0b3J5IGluIHR3b1xuICBmdW5jdGlvbiBjb3B5SGlzdG9yeUFycmF5KGV2ZW50cywgbmV3R3JvdXAsIGluc3RhbnRpYXRlU2VsKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGNvcHkgPSBbXTsgaSA8IGV2ZW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGV2ZW50ID0gZXZlbnRzW2ldO1xuICAgICAgaWYgKGV2ZW50LnJhbmdlcykge1xuICAgICAgICBjb3B5LnB1c2goaW5zdGFudGlhdGVTZWwgPyBTZWxlY3Rpb24ucHJvdG90eXBlLmRlZXBDb3B5LmNhbGwoZXZlbnQpIDogZXZlbnQpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHZhciBjaGFuZ2VzID0gZXZlbnQuY2hhbmdlcywgbmV3Q2hhbmdlcyA9IFtdO1xuICAgICAgY29weS5wdXNoKHtjaGFuZ2VzOiBuZXdDaGFuZ2VzfSk7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNoYW5nZXMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGNoYW5nZSA9IGNoYW5nZXNbal0sIG07XG4gICAgICAgIG5ld0NoYW5nZXMucHVzaCh7ZnJvbTogY2hhbmdlLmZyb20sIHRvOiBjaGFuZ2UudG8sIHRleHQ6IGNoYW5nZS50ZXh0fSk7XG4gICAgICAgIGlmIChuZXdHcm91cCkgZm9yICh2YXIgcHJvcCBpbiBjaGFuZ2UpIGlmIChtID0gcHJvcC5tYXRjaCgvXnNwYW5zXyhcXGQrKSQvKSkge1xuICAgICAgICAgIGlmIChpbmRleE9mKG5ld0dyb3VwLCBOdW1iZXIobVsxXSkpID4gLTEpIHtcbiAgICAgICAgICAgIGxzdChuZXdDaGFuZ2VzKVtwcm9wXSA9IGNoYW5nZVtwcm9wXTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VbcHJvcF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xuICB9XG5cbiAgLy8gUmViYXNpbmcvcmVzZXR0aW5nIGhpc3RvcnkgdG8gZGVhbCB3aXRoIGV4dGVybmFsbHktc291cmNlZCBjaGFuZ2VzXG5cbiAgZnVuY3Rpb24gcmViYXNlSGlzdFNlbFNpbmdsZShwb3MsIGZyb20sIHRvLCBkaWZmKSB7XG4gICAgaWYgKHRvIDwgcG9zLmxpbmUpIHtcbiAgICAgIHBvcy5saW5lICs9IGRpZmY7XG4gICAgfSBlbHNlIGlmIChmcm9tIDwgcG9zLmxpbmUpIHtcbiAgICAgIHBvcy5saW5lID0gZnJvbTtcbiAgICAgIHBvcy5jaCA9IDA7XG4gICAgfVxuICB9XG5cbiAgLy8gVHJpZXMgdG8gcmViYXNlIGFuIGFycmF5IG9mIGhpc3RvcnkgZXZlbnRzIGdpdmVuIGEgY2hhbmdlIGluIHRoZVxuICAvLyBkb2N1bWVudC4gSWYgdGhlIGNoYW5nZSB0b3VjaGVzIHRoZSBzYW1lIGxpbmVzIGFzIHRoZSBldmVudCwgdGhlXG4gIC8vIGV2ZW50LCBhbmQgZXZlcnl0aGluZyAnYmVoaW5kJyBpdCwgaXMgZGlzY2FyZGVkLiBJZiB0aGUgY2hhbmdlIGlzXG4gIC8vIGJlZm9yZSB0aGUgZXZlbnQsIHRoZSBldmVudCdzIHBvc2l0aW9ucyBhcmUgdXBkYXRlZC4gVXNlcyBhXG4gIC8vIGNvcHktb24td3JpdGUgc2NoZW1lIGZvciB0aGUgcG9zaXRpb25zLCB0byBhdm9pZCBoYXZpbmcgdG9cbiAgLy8gcmVhbGxvY2F0ZSB0aGVtIGFsbCBvbiBldmVyeSByZWJhc2UsIGJ1dCBhbHNvIGF2b2lkIHByb2JsZW1zIHdpdGhcbiAgLy8gc2hhcmVkIHBvc2l0aW9uIG9iamVjdHMgYmVpbmcgdW5zYWZlbHkgdXBkYXRlZC5cbiAgZnVuY3Rpb24gcmViYXNlSGlzdEFycmF5KGFycmF5LCBmcm9tLCB0bywgZGlmZikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzdWIgPSBhcnJheVtpXSwgb2sgPSB0cnVlO1xuICAgICAgaWYgKHN1Yi5yYW5nZXMpIHtcbiAgICAgICAgaWYgKCFzdWIuY29waWVkKSB7IHN1YiA9IGFycmF5W2ldID0gc3ViLmRlZXBDb3B5KCk7IHN1Yi5jb3BpZWQgPSB0cnVlOyB9XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgc3ViLnJhbmdlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHJlYmFzZUhpc3RTZWxTaW5nbGUoc3ViLnJhbmdlc1tqXS5hbmNob3IsIGZyb20sIHRvLCBkaWZmKTtcbiAgICAgICAgICByZWJhc2VIaXN0U2VsU2luZ2xlKHN1Yi5yYW5nZXNbal0uaGVhZCwgZnJvbSwgdG8sIGRpZmYpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzdWIuY2hhbmdlcy5sZW5ndGg7ICsraikge1xuICAgICAgICB2YXIgY3VyID0gc3ViLmNoYW5nZXNbal07XG4gICAgICAgIGlmICh0byA8IGN1ci5mcm9tLmxpbmUpIHtcbiAgICAgICAgICBjdXIuZnJvbSA9IFBvcyhjdXIuZnJvbS5saW5lICsgZGlmZiwgY3VyLmZyb20uY2gpO1xuICAgICAgICAgIGN1ci50byA9IFBvcyhjdXIudG8ubGluZSArIGRpZmYsIGN1ci50by5jaCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZnJvbSA8PSBjdXIudG8ubGluZSkge1xuICAgICAgICAgIG9rID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghb2spIHtcbiAgICAgICAgYXJyYXkuc3BsaWNlKDAsIGkgKyAxKTtcbiAgICAgICAgaSA9IDA7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmViYXNlSGlzdChoaXN0LCBjaGFuZ2UpIHtcbiAgICB2YXIgZnJvbSA9IGNoYW5nZS5mcm9tLmxpbmUsIHRvID0gY2hhbmdlLnRvLmxpbmUsIGRpZmYgPSBjaGFuZ2UudGV4dC5sZW5ndGggLSAodG8gLSBmcm9tKSAtIDE7XG4gICAgcmViYXNlSGlzdEFycmF5KGhpc3QuZG9uZSwgZnJvbSwgdG8sIGRpZmYpO1xuICAgIHJlYmFzZUhpc3RBcnJheShoaXN0LnVuZG9uZSwgZnJvbSwgdG8sIGRpZmYpO1xuICB9XG5cbiAgLy8gRVZFTlQgVVRJTElUSUVTXG5cbiAgLy8gRHVlIHRvIHRoZSBmYWN0IHRoYXQgd2Ugc3RpbGwgc3VwcG9ydCBqdXJhc3NpYyBJRSB2ZXJzaW9ucywgc29tZVxuICAvLyBjb21wYXRpYmlsaXR5IHdyYXBwZXJzIGFyZSBuZWVkZWQuXG5cbiAgdmFyIGVfcHJldmVudERlZmF1bHQgPSBDb2RlTWlycm9yLmVfcHJldmVudERlZmF1bHQgPSBmdW5jdGlvbihlKSB7XG4gICAgaWYgKGUucHJldmVudERlZmF1bHQpIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBlbHNlIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgfTtcbiAgdmFyIGVfc3RvcFByb3BhZ2F0aW9uID0gQ29kZU1pcnJvci5lX3N0b3BQcm9wYWdhdGlvbiA9IGZ1bmN0aW9uKGUpIHtcbiAgICBpZiAoZS5zdG9wUHJvcGFnYXRpb24pIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZWxzZSBlLmNhbmNlbEJ1YmJsZSA9IHRydWU7XG4gIH07XG4gIGZ1bmN0aW9uIGVfZGVmYXVsdFByZXZlbnRlZChlKSB7XG4gICAgcmV0dXJuIGUuZGVmYXVsdFByZXZlbnRlZCAhPSBudWxsID8gZS5kZWZhdWx0UHJldmVudGVkIDogZS5yZXR1cm5WYWx1ZSA9PSBmYWxzZTtcbiAgfVxuICB2YXIgZV9zdG9wID0gQ29kZU1pcnJvci5lX3N0b3AgPSBmdW5jdGlvbihlKSB7ZV9wcmV2ZW50RGVmYXVsdChlKTsgZV9zdG9wUHJvcGFnYXRpb24oZSk7fTtcblxuICBmdW5jdGlvbiBlX3RhcmdldChlKSB7cmV0dXJuIGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudDt9XG4gIGZ1bmN0aW9uIGVfYnV0dG9uKGUpIHtcbiAgICB2YXIgYiA9IGUud2hpY2g7XG4gICAgaWYgKGIgPT0gbnVsbCkge1xuICAgICAgaWYgKGUuYnV0dG9uICYgMSkgYiA9IDE7XG4gICAgICBlbHNlIGlmIChlLmJ1dHRvbiAmIDIpIGIgPSAzO1xuICAgICAgZWxzZSBpZiAoZS5idXR0b24gJiA0KSBiID0gMjtcbiAgICB9XG4gICAgaWYgKG1hYyAmJiBlLmN0cmxLZXkgJiYgYiA9PSAxKSBiID0gMztcbiAgICByZXR1cm4gYjtcbiAgfVxuXG4gIC8vIEVWRU5UIEhBTkRMSU5HXG5cbiAgLy8gTGlnaHR3ZWlnaHQgZXZlbnQgZnJhbWV3b3JrLiBvbi9vZmYgYWxzbyB3b3JrIG9uIERPTSBub2RlcyxcbiAgLy8gcmVnaXN0ZXJpbmcgbmF0aXZlIERPTSBoYW5kbGVycy5cblxuICB2YXIgb24gPSBDb2RlTWlycm9yLm9uID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSwgZikge1xuICAgIGlmIChlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICBlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgZiwgZmFsc2UpO1xuICAgIGVsc2UgaWYgKGVtaXR0ZXIuYXR0YWNoRXZlbnQpXG4gICAgICBlbWl0dGVyLmF0dGFjaEV2ZW50KFwib25cIiArIHR5cGUsIGYpO1xuICAgIGVsc2Uge1xuICAgICAgdmFyIG1hcCA9IGVtaXR0ZXIuX2hhbmRsZXJzIHx8IChlbWl0dGVyLl9oYW5kbGVycyA9IHt9KTtcbiAgICAgIHZhciBhcnIgPSBtYXBbdHlwZV0gfHwgKG1hcFt0eXBlXSA9IFtdKTtcbiAgICAgIGFyci5wdXNoKGYpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgbm9IYW5kbGVycyA9IFtdXG4gIGZ1bmN0aW9uIGdldEhhbmRsZXJzKGVtaXR0ZXIsIHR5cGUsIGNvcHkpIHtcbiAgICB2YXIgYXJyID0gZW1pdHRlci5faGFuZGxlcnMgJiYgZW1pdHRlci5faGFuZGxlcnNbdHlwZV1cbiAgICBpZiAoY29weSkgcmV0dXJuIGFyciAmJiBhcnIubGVuZ3RoID4gMCA/IGFyci5zbGljZSgpIDogbm9IYW5kbGVyc1xuICAgIGVsc2UgcmV0dXJuIGFyciB8fCBub0hhbmRsZXJzXG4gIH1cblxuICB2YXIgb2ZmID0gQ29kZU1pcnJvci5vZmYgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlLCBmKSB7XG4gICAgaWYgKGVtaXR0ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcilcbiAgICAgIGVtaXR0ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG4gICAgZWxzZSBpZiAoZW1pdHRlci5kZXRhY2hFdmVudClcbiAgICAgIGVtaXR0ZXIuZGV0YWNoRXZlbnQoXCJvblwiICsgdHlwZSwgZik7XG4gICAgZWxzZSB7XG4gICAgICB2YXIgaGFuZGxlcnMgPSBnZXRIYW5kbGVycyhlbWl0dGVyLCB0eXBlLCBmYWxzZSlcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyArK2kpXG4gICAgICAgIGlmIChoYW5kbGVyc1tpXSA9PSBmKSB7IGhhbmRsZXJzLnNwbGljZShpLCAxKTsgYnJlYWs7IH1cbiAgICB9XG4gIH07XG5cbiAgdmFyIHNpZ25hbCA9IENvZGVNaXJyb3Iuc2lnbmFsID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSAvKiwgdmFsdWVzLi4uKi8pIHtcbiAgICB2YXIgaGFuZGxlcnMgPSBnZXRIYW5kbGVycyhlbWl0dGVyLCB0eXBlLCB0cnVlKVxuICAgIGlmICghaGFuZGxlcnMubGVuZ3RoKSByZXR1cm47XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyArK2kpIGhhbmRsZXJzW2ldLmFwcGx5KG51bGwsIGFyZ3MpO1xuICB9O1xuXG4gIHZhciBvcnBoYW5EZWxheWVkQ2FsbGJhY2tzID0gbnVsbDtcblxuICAvLyBPZnRlbiwgd2Ugd2FudCB0byBzaWduYWwgZXZlbnRzIGF0IGEgcG9pbnQgd2hlcmUgd2UgYXJlIGluIHRoZVxuICAvLyBtaWRkbGUgb2Ygc29tZSB3b3JrLCBidXQgZG9uJ3Qgd2FudCB0aGUgaGFuZGxlciB0byBzdGFydCBjYWxsaW5nXG4gIC8vIG90aGVyIG1ldGhvZHMgb24gdGhlIGVkaXRvciwgd2hpY2ggbWlnaHQgYmUgaW4gYW4gaW5jb25zaXN0ZW50XG4gIC8vIHN0YXRlIG9yIHNpbXBseSBub3QgZXhwZWN0IGFueSBvdGhlciBldmVudHMgdG8gaGFwcGVuLlxuICAvLyBzaWduYWxMYXRlciBsb29rcyB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgaGFuZGxlcnMsIGFuZCBzY2hlZHVsZXNcbiAgLy8gdGhlbSB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBsYXN0IG9wZXJhdGlvbiBlbmRzLCBvciwgaWYgbm9cbiAgLy8gb3BlcmF0aW9uIGlzIGFjdGl2ZSwgd2hlbiBhIHRpbWVvdXQgZmlyZXMuXG4gIGZ1bmN0aW9uIHNpZ25hbExhdGVyKGVtaXR0ZXIsIHR5cGUgLyosIHZhbHVlcy4uLiovKSB7XG4gICAgdmFyIGFyciA9IGdldEhhbmRsZXJzKGVtaXR0ZXIsIHR5cGUsIGZhbHNlKVxuICAgIGlmICghYXJyLmxlbmd0aCkgcmV0dXJuO1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSwgbGlzdDtcbiAgICBpZiAob3BlcmF0aW9uR3JvdXApIHtcbiAgICAgIGxpc3QgPSBvcGVyYXRpb25Hcm91cC5kZWxheWVkQ2FsbGJhY2tzO1xuICAgIH0gZWxzZSBpZiAob3JwaGFuRGVsYXllZENhbGxiYWNrcykge1xuICAgICAgbGlzdCA9IG9ycGhhbkRlbGF5ZWRDYWxsYmFja3M7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3QgPSBvcnBoYW5EZWxheWVkQ2FsbGJhY2tzID0gW107XG4gICAgICBzZXRUaW1lb3V0KGZpcmVPcnBoYW5EZWxheWVkLCAwKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYm5kKGYpIHtyZXR1cm4gZnVuY3Rpb24oKXtmLmFwcGx5KG51bGwsIGFyZ3MpO307fTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7ICsraSlcbiAgICAgIGxpc3QucHVzaChibmQoYXJyW2ldKSk7XG4gIH1cblxuICBmdW5jdGlvbiBmaXJlT3JwaGFuRGVsYXllZCgpIHtcbiAgICB2YXIgZGVsYXllZCA9IG9ycGhhbkRlbGF5ZWRDYWxsYmFja3M7XG4gICAgb3JwaGFuRGVsYXllZENhbGxiYWNrcyA9IG51bGw7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZWxheWVkLmxlbmd0aDsgKytpKSBkZWxheWVkW2ldKCk7XG4gIH1cblxuICAvLyBUaGUgRE9NIGV2ZW50cyB0aGF0IENvZGVNaXJyb3IgaGFuZGxlcyBjYW4gYmUgb3ZlcnJpZGRlbiBieVxuICAvLyByZWdpc3RlcmluZyBhIChub24tRE9NKSBoYW5kbGVyIG9uIHRoZSBlZGl0b3IgZm9yIHRoZSBldmVudCBuYW1lLFxuICAvLyBhbmQgcHJldmVudERlZmF1bHQtaW5nIHRoZSBldmVudCBpbiB0aGF0IGhhbmRsZXIuXG4gIGZ1bmN0aW9uIHNpZ25hbERPTUV2ZW50KGNtLCBlLCBvdmVycmlkZSkge1xuICAgIGlmICh0eXBlb2YgZSA9PSBcInN0cmluZ1wiKVxuICAgICAgZSA9IHt0eXBlOiBlLCBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7IHRoaXMuZGVmYXVsdFByZXZlbnRlZCA9IHRydWU7IH19O1xuICAgIHNpZ25hbChjbSwgb3ZlcnJpZGUgfHwgZS50eXBlLCBjbSwgZSk7XG4gICAgcmV0dXJuIGVfZGVmYXVsdFByZXZlbnRlZChlKSB8fCBlLmNvZGVtaXJyb3JJZ25vcmU7XG4gIH1cblxuICBmdW5jdGlvbiBzaWduYWxDdXJzb3JBY3Rpdml0eShjbSkge1xuICAgIHZhciBhcnIgPSBjbS5faGFuZGxlcnMgJiYgY20uX2hhbmRsZXJzLmN1cnNvckFjdGl2aXR5O1xuICAgIGlmICghYXJyKSByZXR1cm47XG4gICAgdmFyIHNldCA9IGNtLmN1ck9wLmN1cnNvckFjdGl2aXR5SGFuZGxlcnMgfHwgKGNtLmN1ck9wLmN1cnNvckFjdGl2aXR5SGFuZGxlcnMgPSBbXSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyArK2kpIGlmIChpbmRleE9mKHNldCwgYXJyW2ldKSA9PSAtMSlcbiAgICAgIHNldC5wdXNoKGFycltpXSk7XG4gIH1cblxuICBmdW5jdGlvbiBoYXNIYW5kbGVyKGVtaXR0ZXIsIHR5cGUpIHtcbiAgICByZXR1cm4gZ2V0SGFuZGxlcnMoZW1pdHRlciwgdHlwZSkubGVuZ3RoID4gMFxuICB9XG5cbiAgLy8gQWRkIG9uIGFuZCBvZmYgbWV0aG9kcyB0byBhIGNvbnN0cnVjdG9yJ3MgcHJvdG90eXBlLCB0byBtYWtlXG4gIC8vIHJlZ2lzdGVyaW5nIGV2ZW50cyBvbiBzdWNoIG9iamVjdHMgbW9yZSBjb252ZW5pZW50LlxuICBmdW5jdGlvbiBldmVudE1peGluKGN0b3IpIHtcbiAgICBjdG9yLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uKHR5cGUsIGYpIHtvbih0aGlzLCB0eXBlLCBmKTt9O1xuICAgIGN0b3IucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uKHR5cGUsIGYpIHtvZmYodGhpcywgdHlwZSwgZik7fTtcbiAgfVxuXG4gIC8vIE1JU0MgVVRJTElUSUVTXG5cbiAgLy8gTnVtYmVyIG9mIHBpeGVscyBhZGRlZCB0byBzY3JvbGxlciBhbmQgc2l6ZXIgdG8gaGlkZSBzY3JvbGxiYXJcbiAgdmFyIHNjcm9sbGVyR2FwID0gMzA7XG5cbiAgLy8gUmV0dXJuZWQgb3IgdGhyb3duIGJ5IHZhcmlvdXMgcHJvdG9jb2xzIHRvIHNpZ25hbCAnSSdtIG5vdFxuICAvLyBoYW5kbGluZyB0aGlzJy5cbiAgdmFyIFBhc3MgPSBDb2RlTWlycm9yLlBhc3MgPSB7dG9TdHJpbmc6IGZ1bmN0aW9uKCl7cmV0dXJuIFwiQ29kZU1pcnJvci5QYXNzXCI7fX07XG5cbiAgLy8gUmV1c2VkIG9wdGlvbiBvYmplY3RzIGZvciBzZXRTZWxlY3Rpb24gJiBmcmllbmRzXG4gIHZhciBzZWxfZG9udFNjcm9sbCA9IHtzY3JvbGw6IGZhbHNlfSwgc2VsX21vdXNlID0ge29yaWdpbjogXCIqbW91c2VcIn0sIHNlbF9tb3ZlID0ge29yaWdpbjogXCIrbW92ZVwifTtcblxuICBmdW5jdGlvbiBEZWxheWVkKCkge3RoaXMuaWQgPSBudWxsO31cbiAgRGVsYXllZC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24obXMsIGYpIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5pZCk7XG4gICAgdGhpcy5pZCA9IHNldFRpbWVvdXQoZiwgbXMpO1xuICB9O1xuXG4gIC8vIENvdW50cyB0aGUgY29sdW1uIG9mZnNldCBpbiBhIHN0cmluZywgdGFraW5nIHRhYnMgaW50byBhY2NvdW50LlxuICAvLyBVc2VkIG1vc3RseSB0byBmaW5kIGluZGVudGF0aW9uLlxuICB2YXIgY291bnRDb2x1bW4gPSBDb2RlTWlycm9yLmNvdW50Q29sdW1uID0gZnVuY3Rpb24oc3RyaW5nLCBlbmQsIHRhYlNpemUsIHN0YXJ0SW5kZXgsIHN0YXJ0VmFsdWUpIHtcbiAgICBpZiAoZW5kID09IG51bGwpIHtcbiAgICAgIGVuZCA9IHN0cmluZy5zZWFyY2goL1teXFxzXFx1MDBhMF0vKTtcbiAgICAgIGlmIChlbmQgPT0gLTEpIGVuZCA9IHN0cmluZy5sZW5ndGg7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSBzdGFydEluZGV4IHx8IDAsIG4gPSBzdGFydFZhbHVlIHx8IDA7Oykge1xuICAgICAgdmFyIG5leHRUYWIgPSBzdHJpbmcuaW5kZXhPZihcIlxcdFwiLCBpKTtcbiAgICAgIGlmIChuZXh0VGFiIDwgMCB8fCBuZXh0VGFiID49IGVuZClcbiAgICAgICAgcmV0dXJuIG4gKyAoZW5kIC0gaSk7XG4gICAgICBuICs9IG5leHRUYWIgLSBpO1xuICAgICAgbiArPSB0YWJTaXplIC0gKG4gJSB0YWJTaXplKTtcbiAgICAgIGkgPSBuZXh0VGFiICsgMTtcbiAgICB9XG4gIH07XG5cbiAgLy8gVGhlIGludmVyc2Ugb2YgY291bnRDb2x1bW4gLS0gZmluZCB0aGUgb2Zmc2V0IHRoYXQgY29ycmVzcG9uZHMgdG9cbiAgLy8gYSBwYXJ0aWN1bGFyIGNvbHVtbi5cbiAgdmFyIGZpbmRDb2x1bW4gPSBDb2RlTWlycm9yLmZpbmRDb2x1bW4gPSBmdW5jdGlvbihzdHJpbmcsIGdvYWwsIHRhYlNpemUpIHtcbiAgICBmb3IgKHZhciBwb3MgPSAwLCBjb2wgPSAwOzspIHtcbiAgICAgIHZhciBuZXh0VGFiID0gc3RyaW5nLmluZGV4T2YoXCJcXHRcIiwgcG9zKTtcbiAgICAgIGlmIChuZXh0VGFiID09IC0xKSBuZXh0VGFiID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIHZhciBza2lwcGVkID0gbmV4dFRhYiAtIHBvcztcbiAgICAgIGlmIChuZXh0VGFiID09IHN0cmluZy5sZW5ndGggfHwgY29sICsgc2tpcHBlZCA+PSBnb2FsKVxuICAgICAgICByZXR1cm4gcG9zICsgTWF0aC5taW4oc2tpcHBlZCwgZ29hbCAtIGNvbCk7XG4gICAgICBjb2wgKz0gbmV4dFRhYiAtIHBvcztcbiAgICAgIGNvbCArPSB0YWJTaXplIC0gKGNvbCAlIHRhYlNpemUpO1xuICAgICAgcG9zID0gbmV4dFRhYiArIDE7XG4gICAgICBpZiAoY29sID49IGdvYWwpIHJldHVybiBwb3M7XG4gICAgfVxuICB9XG5cbiAgdmFyIHNwYWNlU3RycyA9IFtcIlwiXTtcbiAgZnVuY3Rpb24gc3BhY2VTdHIobikge1xuICAgIHdoaWxlIChzcGFjZVN0cnMubGVuZ3RoIDw9IG4pXG4gICAgICBzcGFjZVN0cnMucHVzaChsc3Qoc3BhY2VTdHJzKSArIFwiIFwiKTtcbiAgICByZXR1cm4gc3BhY2VTdHJzW25dO1xuICB9XG5cbiAgZnVuY3Rpb24gbHN0KGFycikgeyByZXR1cm4gYXJyW2Fyci5sZW5ndGgtMV07IH1cblxuICB2YXIgc2VsZWN0SW5wdXQgPSBmdW5jdGlvbihub2RlKSB7IG5vZGUuc2VsZWN0KCk7IH07XG4gIGlmIChpb3MpIC8vIE1vYmlsZSBTYWZhcmkgYXBwYXJlbnRseSBoYXMgYSBidWcgd2hlcmUgc2VsZWN0KCkgaXMgYnJva2VuLlxuICAgIHNlbGVjdElucHV0ID0gZnVuY3Rpb24obm9kZSkgeyBub2RlLnNlbGVjdGlvblN0YXJ0ID0gMDsgbm9kZS5zZWxlY3Rpb25FbmQgPSBub2RlLnZhbHVlLmxlbmd0aDsgfTtcbiAgZWxzZSBpZiAoaWUpIC8vIFN1cHByZXNzIG15c3RlcmlvdXMgSUUxMCBlcnJvcnNcbiAgICBzZWxlY3RJbnB1dCA9IGZ1bmN0aW9uKG5vZGUpIHsgdHJ5IHsgbm9kZS5zZWxlY3QoKTsgfSBjYXRjaChfZSkge30gfTtcblxuICBmdW5jdGlvbiBpbmRleE9mKGFycmF5LCBlbHQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKVxuICAgICAgaWYgKGFycmF5W2ldID09IGVsdCkgcmV0dXJuIGk7XG4gICAgcmV0dXJuIC0xO1xuICB9XG4gIGZ1bmN0aW9uIG1hcChhcnJheSwgZikge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBvdXRbaV0gPSBmKGFycmF5W2ldLCBpKTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgZnVuY3Rpb24gbm90aGluZygpIHt9XG5cbiAgZnVuY3Rpb24gY3JlYXRlT2JqKGJhc2UsIHByb3BzKSB7XG4gICAgdmFyIGluc3Q7XG4gICAgaWYgKE9iamVjdC5jcmVhdGUpIHtcbiAgICAgIGluc3QgPSBPYmplY3QuY3JlYXRlKGJhc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBub3RoaW5nLnByb3RvdHlwZSA9IGJhc2U7XG4gICAgICBpbnN0ID0gbmV3IG5vdGhpbmcoKTtcbiAgICB9XG4gICAgaWYgKHByb3BzKSBjb3B5T2JqKHByb3BzLCBpbnN0KTtcbiAgICByZXR1cm4gaW5zdDtcbiAgfTtcblxuICBmdW5jdGlvbiBjb3B5T2JqKG9iaiwgdGFyZ2V0LCBvdmVyd3JpdGUpIHtcbiAgICBpZiAoIXRhcmdldCkgdGFyZ2V0ID0ge307XG4gICAgZm9yICh2YXIgcHJvcCBpbiBvYmopXG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApICYmIChvdmVyd3JpdGUgIT09IGZhbHNlIHx8ICF0YXJnZXQuaGFzT3duUHJvcGVydHkocHJvcCkpKVxuICAgICAgICB0YXJnZXRbcHJvcF0gPSBvYmpbcHJvcF07XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJpbmQoZikge1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZi5hcHBseShudWxsLCBhcmdzKTt9O1xuICB9XG5cbiAgdmFyIG5vbkFTQ0lJU2luZ2xlQ2FzZVdvcmRDaGFyID0gL1tcXHUwMGRmXFx1MDU4N1xcdTA1OTAtXFx1MDVmNFxcdTA2MDAtXFx1MDZmZlxcdTMwNDAtXFx1MzA5ZlxcdTMwYTAtXFx1MzBmZlxcdTM0MDAtXFx1NGRiNVxcdTRlMDAtXFx1OWZjY1xcdWFjMDAtXFx1ZDdhZl0vO1xuICB2YXIgaXNXb3JkQ2hhckJhc2ljID0gQ29kZU1pcnJvci5pc1dvcmRDaGFyID0gZnVuY3Rpb24oY2gpIHtcbiAgICByZXR1cm4gL1xcdy8udGVzdChjaCkgfHwgY2ggPiBcIlxceDgwXCIgJiZcbiAgICAgIChjaC50b1VwcGVyQ2FzZSgpICE9IGNoLnRvTG93ZXJDYXNlKCkgfHwgbm9uQVNDSUlTaW5nbGVDYXNlV29yZENoYXIudGVzdChjaCkpO1xuICB9O1xuICBmdW5jdGlvbiBpc1dvcmRDaGFyKGNoLCBoZWxwZXIpIHtcbiAgICBpZiAoIWhlbHBlcikgcmV0dXJuIGlzV29yZENoYXJCYXNpYyhjaCk7XG4gICAgaWYgKGhlbHBlci5zb3VyY2UuaW5kZXhPZihcIlxcXFx3XCIpID4gLTEgJiYgaXNXb3JkQ2hhckJhc2ljKGNoKSkgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGhlbHBlci50ZXN0KGNoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRW1wdHkob2JqKSB7XG4gICAgZm9yICh2YXIgbiBpbiBvYmopIGlmIChvYmouaGFzT3duUHJvcGVydHkobikgJiYgb2JqW25dKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBFeHRlbmRpbmcgdW5pY29kZSBjaGFyYWN0ZXJzLiBBIHNlcmllcyBvZiBhIG5vbi1leHRlbmRpbmcgY2hhciArXG4gIC8vIGFueSBudW1iZXIgb2YgZXh0ZW5kaW5nIGNoYXJzIGlzIHRyZWF0ZWQgYXMgYSBzaW5nbGUgdW5pdCBhcyBmYXJcbiAgLy8gYXMgZWRpdGluZyBhbmQgbWVhc3VyaW5nIGlzIGNvbmNlcm5lZC4gVGhpcyBpcyBub3QgZnVsbHkgY29ycmVjdCxcbiAgLy8gc2luY2Ugc29tZSBzY3JpcHRzL2ZvbnRzL2Jyb3dzZXJzIGFsc28gdHJlYXQgb3RoZXIgY29uZmlndXJhdGlvbnNcbiAgLy8gb2YgY29kZSBwb2ludHMgYXMgYSBncm91cC5cbiAgdmFyIGV4dGVuZGluZ0NoYXJzID0gL1tcXHUwMzAwLVxcdTAzNmZcXHUwNDgzLVxcdTA0ODlcXHUwNTkxLVxcdTA1YmRcXHUwNWJmXFx1MDVjMVxcdTA1YzJcXHUwNWM0XFx1MDVjNVxcdTA1YzdcXHUwNjEwLVxcdTA2MWFcXHUwNjRiLVxcdTA2NWVcXHUwNjcwXFx1MDZkNi1cXHUwNmRjXFx1MDZkZS1cXHUwNmU0XFx1MDZlN1xcdTA2ZThcXHUwNmVhLVxcdTA2ZWRcXHUwNzExXFx1MDczMC1cXHUwNzRhXFx1MDdhNi1cXHUwN2IwXFx1MDdlYi1cXHUwN2YzXFx1MDgxNi1cXHUwODE5XFx1MDgxYi1cXHUwODIzXFx1MDgyNS1cXHUwODI3XFx1MDgyOS1cXHUwODJkXFx1MDkwMC1cXHUwOTAyXFx1MDkzY1xcdTA5NDEtXFx1MDk0OFxcdTA5NGRcXHUwOTUxLVxcdTA5NTVcXHUwOTYyXFx1MDk2M1xcdTA5ODFcXHUwOWJjXFx1MDliZVxcdTA5YzEtXFx1MDljNFxcdTA5Y2RcXHUwOWQ3XFx1MDllMlxcdTA5ZTNcXHUwYTAxXFx1MGEwMlxcdTBhM2NcXHUwYTQxXFx1MGE0MlxcdTBhNDdcXHUwYTQ4XFx1MGE0Yi1cXHUwYTRkXFx1MGE1MVxcdTBhNzBcXHUwYTcxXFx1MGE3NVxcdTBhODFcXHUwYTgyXFx1MGFiY1xcdTBhYzEtXFx1MGFjNVxcdTBhYzdcXHUwYWM4XFx1MGFjZFxcdTBhZTJcXHUwYWUzXFx1MGIwMVxcdTBiM2NcXHUwYjNlXFx1MGIzZlxcdTBiNDEtXFx1MGI0NFxcdTBiNGRcXHUwYjU2XFx1MGI1N1xcdTBiNjJcXHUwYjYzXFx1MGI4MlxcdTBiYmVcXHUwYmMwXFx1MGJjZFxcdTBiZDdcXHUwYzNlLVxcdTBjNDBcXHUwYzQ2LVxcdTBjNDhcXHUwYzRhLVxcdTBjNGRcXHUwYzU1XFx1MGM1NlxcdTBjNjJcXHUwYzYzXFx1MGNiY1xcdTBjYmZcXHUwY2MyXFx1MGNjNlxcdTBjY2NcXHUwY2NkXFx1MGNkNVxcdTBjZDZcXHUwY2UyXFx1MGNlM1xcdTBkM2VcXHUwZDQxLVxcdTBkNDRcXHUwZDRkXFx1MGQ1N1xcdTBkNjJcXHUwZDYzXFx1MGRjYVxcdTBkY2ZcXHUwZGQyLVxcdTBkZDRcXHUwZGQ2XFx1MGRkZlxcdTBlMzFcXHUwZTM0LVxcdTBlM2FcXHUwZTQ3LVxcdTBlNGVcXHUwZWIxXFx1MGViNC1cXHUwZWI5XFx1MGViYlxcdTBlYmNcXHUwZWM4LVxcdTBlY2RcXHUwZjE4XFx1MGYxOVxcdTBmMzVcXHUwZjM3XFx1MGYzOVxcdTBmNzEtXFx1MGY3ZVxcdTBmODAtXFx1MGY4NFxcdTBmODZcXHUwZjg3XFx1MGY5MC1cXHUwZjk3XFx1MGY5OS1cXHUwZmJjXFx1MGZjNlxcdTEwMmQtXFx1MTAzMFxcdTEwMzItXFx1MTAzN1xcdTEwMzlcXHUxMDNhXFx1MTAzZFxcdTEwM2VcXHUxMDU4XFx1MTA1OVxcdTEwNWUtXFx1MTA2MFxcdTEwNzEtXFx1MTA3NFxcdTEwODJcXHUxMDg1XFx1MTA4NlxcdTEwOGRcXHUxMDlkXFx1MTM1ZlxcdTE3MTItXFx1MTcxNFxcdTE3MzItXFx1MTczNFxcdTE3NTJcXHUxNzUzXFx1MTc3MlxcdTE3NzNcXHUxN2I3LVxcdTE3YmRcXHUxN2M2XFx1MTdjOS1cXHUxN2QzXFx1MTdkZFxcdTE4MGItXFx1MTgwZFxcdTE4YTlcXHUxOTIwLVxcdTE5MjJcXHUxOTI3XFx1MTkyOFxcdTE5MzJcXHUxOTM5LVxcdTE5M2JcXHUxYTE3XFx1MWExOFxcdTFhNTZcXHUxYTU4LVxcdTFhNWVcXHUxYTYwXFx1MWE2MlxcdTFhNjUtXFx1MWE2Y1xcdTFhNzMtXFx1MWE3Y1xcdTFhN2ZcXHUxYjAwLVxcdTFiMDNcXHUxYjM0XFx1MWIzNi1cXHUxYjNhXFx1MWIzY1xcdTFiNDJcXHUxYjZiLVxcdTFiNzNcXHUxYjgwXFx1MWI4MVxcdTFiYTItXFx1MWJhNVxcdTFiYThcXHUxYmE5XFx1MWMyYy1cXHUxYzMzXFx1MWMzNlxcdTFjMzdcXHUxY2QwLVxcdTFjZDJcXHUxY2Q0LVxcdTFjZTBcXHUxY2UyLVxcdTFjZThcXHUxY2VkXFx1MWRjMC1cXHUxZGU2XFx1MWRmZC1cXHUxZGZmXFx1MjAwY1xcdTIwMGRcXHUyMGQwLVxcdTIwZjBcXHUyY2VmLVxcdTJjZjFcXHUyZGUwLVxcdTJkZmZcXHUzMDJhLVxcdTMwMmZcXHUzMDk5XFx1MzA5YVxcdWE2NmYtXFx1YTY3MlxcdWE2N2NcXHVhNjdkXFx1YTZmMFxcdWE2ZjFcXHVhODAyXFx1YTgwNlxcdWE4MGJcXHVhODI1XFx1YTgyNlxcdWE4YzRcXHVhOGUwLVxcdWE4ZjFcXHVhOTI2LVxcdWE5MmRcXHVhOTQ3LVxcdWE5NTFcXHVhOTgwLVxcdWE5ODJcXHVhOWIzXFx1YTliNi1cXHVhOWI5XFx1YTliY1xcdWFhMjktXFx1YWEyZVxcdWFhMzFcXHVhYTMyXFx1YWEzNVxcdWFhMzZcXHVhYTQzXFx1YWE0Y1xcdWFhYjBcXHVhYWIyLVxcdWFhYjRcXHVhYWI3XFx1YWFiOFxcdWFhYmVcXHVhYWJmXFx1YWFjMVxcdWFiZTVcXHVhYmU4XFx1YWJlZFxcdWRjMDAtXFx1ZGZmZlxcdWZiMWVcXHVmZTAwLVxcdWZlMGZcXHVmZTIwLVxcdWZlMjZcXHVmZjllXFx1ZmY5Zl0vO1xuICBmdW5jdGlvbiBpc0V4dGVuZGluZ0NoYXIoY2gpIHsgcmV0dXJuIGNoLmNoYXJDb2RlQXQoMCkgPj0gNzY4ICYmIGV4dGVuZGluZ0NoYXJzLnRlc3QoY2gpOyB9XG5cbiAgLy8gRE9NIFVUSUxJVElFU1xuXG4gIGZ1bmN0aW9uIGVsdCh0YWcsIGNvbnRlbnQsIGNsYXNzTmFtZSwgc3R5bGUpIHtcbiAgICB2YXIgZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgICBpZiAoc3R5bGUpIGUuc3R5bGUuY3NzVGV4dCA9IHN0eWxlO1xuICAgIGlmICh0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiKSBlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNvbnRlbnQpKTtcbiAgICBlbHNlIGlmIChjb250ZW50KSBmb3IgKHZhciBpID0gMDsgaSA8IGNvbnRlbnQubGVuZ3RoOyArK2kpIGUuYXBwZW5kQ2hpbGQoY29udGVudFtpXSk7XG4gICAgcmV0dXJuIGU7XG4gIH1cblxuICB2YXIgcmFuZ2U7XG4gIGlmIChkb2N1bWVudC5jcmVhdGVSYW5nZSkgcmFuZ2UgPSBmdW5jdGlvbihub2RlLCBzdGFydCwgZW5kLCBlbmROb2RlKSB7XG4gICAgdmFyIHIgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgIHIuc2V0RW5kKGVuZE5vZGUgfHwgbm9kZSwgZW5kKTtcbiAgICByLnNldFN0YXJ0KG5vZGUsIHN0YXJ0KTtcbiAgICByZXR1cm4gcjtcbiAgfTtcbiAgZWxzZSByYW5nZSA9IGZ1bmN0aW9uKG5vZGUsIHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgciA9IGRvY3VtZW50LmJvZHkuY3JlYXRlVGV4dFJhbmdlKCk7XG4gICAgdHJ5IHsgci5tb3ZlVG9FbGVtZW50VGV4dChub2RlLnBhcmVudE5vZGUpOyB9XG4gICAgY2F0Y2goZSkgeyByZXR1cm4gcjsgfVxuICAgIHIuY29sbGFwc2UodHJ1ZSk7XG4gICAgci5tb3ZlRW5kKFwiY2hhcmFjdGVyXCIsIGVuZCk7XG4gICAgci5tb3ZlU3RhcnQoXCJjaGFyYWN0ZXJcIiwgc3RhcnQpO1xuICAgIHJldHVybiByO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKGUpIHtcbiAgICBmb3IgKHZhciBjb3VudCA9IGUuY2hpbGROb2Rlcy5sZW5ndGg7IGNvdW50ID4gMDsgLS1jb3VudClcbiAgICAgIGUucmVtb3ZlQ2hpbGQoZS5maXJzdENoaWxkKTtcbiAgICByZXR1cm4gZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuQW5kQWRkKHBhcmVudCwgZSkge1xuICAgIHJldHVybiByZW1vdmVDaGlsZHJlbihwYXJlbnQpLmFwcGVuZENoaWxkKGUpO1xuICB9XG5cbiAgdmFyIGNvbnRhaW5zID0gQ29kZU1pcnJvci5jb250YWlucyA9IGZ1bmN0aW9uKHBhcmVudCwgY2hpbGQpIHtcbiAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT0gMykgLy8gQW5kcm9pZCBicm93c2VyIGFsd2F5cyByZXR1cm5zIGZhbHNlIHdoZW4gY2hpbGQgaXMgYSB0ZXh0bm9kZVxuICAgICAgY2hpbGQgPSBjaGlsZC5wYXJlbnROb2RlO1xuICAgIGlmIChwYXJlbnQuY29udGFpbnMpXG4gICAgICByZXR1cm4gcGFyZW50LmNvbnRhaW5zKGNoaWxkKTtcbiAgICBkbyB7XG4gICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT0gMTEpIGNoaWxkID0gY2hpbGQuaG9zdDtcbiAgICAgIGlmIChjaGlsZCA9PSBwYXJlbnQpIHJldHVybiB0cnVlO1xuICAgIH0gd2hpbGUgKGNoaWxkID0gY2hpbGQucGFyZW50Tm9kZSk7XG4gIH07XG5cbiAgZnVuY3Rpb24gYWN0aXZlRWx0KCkge1xuICAgIHZhciBhY3RpdmVFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICB3aGlsZSAoYWN0aXZlRWxlbWVudCAmJiBhY3RpdmVFbGVtZW50LnJvb3QgJiYgYWN0aXZlRWxlbWVudC5yb290LmFjdGl2ZUVsZW1lbnQpXG4gICAgICBhY3RpdmVFbGVtZW50ID0gYWN0aXZlRWxlbWVudC5yb290LmFjdGl2ZUVsZW1lbnQ7XG4gICAgcmV0dXJuIGFjdGl2ZUVsZW1lbnQ7XG4gIH1cbiAgLy8gT2xkZXIgdmVyc2lvbnMgb2YgSUUgdGhyb3dzIHVuc3BlY2lmaWVkIGVycm9yIHdoZW4gdG91Y2hpbmdcbiAgLy8gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBpbiBzb21lIGNhc2VzIChkdXJpbmcgbG9hZGluZywgaW4gaWZyYW1lKVxuICBpZiAoaWUgJiYgaWVfdmVyc2lvbiA8IDExKSBhY3RpdmVFbHQgPSBmdW5jdGlvbigpIHtcbiAgICB0cnkgeyByZXR1cm4gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDsgfVxuICAgIGNhdGNoKGUpIHsgcmV0dXJuIGRvY3VtZW50LmJvZHk7IH1cbiAgfTtcblxuICBmdW5jdGlvbiBjbGFzc1Rlc3QoY2xzKSB7IHJldHVybiBuZXcgUmVnRXhwKFwiKF58XFxcXHMpXCIgKyBjbHMgKyBcIig/OiR8XFxcXHMpXFxcXHMqXCIpOyB9XG4gIHZhciBybUNsYXNzID0gQ29kZU1pcnJvci5ybUNsYXNzID0gZnVuY3Rpb24obm9kZSwgY2xzKSB7XG4gICAgdmFyIGN1cnJlbnQgPSBub2RlLmNsYXNzTmFtZTtcbiAgICB2YXIgbWF0Y2ggPSBjbGFzc1Rlc3QoY2xzKS5leGVjKGN1cnJlbnQpO1xuICAgIGlmIChtYXRjaCkge1xuICAgICAgdmFyIGFmdGVyID0gY3VycmVudC5zbGljZShtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICBub2RlLmNsYXNzTmFtZSA9IGN1cnJlbnQuc2xpY2UoMCwgbWF0Y2guaW5kZXgpICsgKGFmdGVyID8gbWF0Y2hbMV0gKyBhZnRlciA6IFwiXCIpO1xuICAgIH1cbiAgfTtcbiAgdmFyIGFkZENsYXNzID0gQ29kZU1pcnJvci5hZGRDbGFzcyA9IGZ1bmN0aW9uKG5vZGUsIGNscykge1xuICAgIHZhciBjdXJyZW50ID0gbm9kZS5jbGFzc05hbWU7XG4gICAgaWYgKCFjbGFzc1Rlc3QoY2xzKS50ZXN0KGN1cnJlbnQpKSBub2RlLmNsYXNzTmFtZSArPSAoY3VycmVudCA/IFwiIFwiIDogXCJcIikgKyBjbHM7XG4gIH07XG4gIGZ1bmN0aW9uIGpvaW5DbGFzc2VzKGEsIGIpIHtcbiAgICB2YXIgYXMgPSBhLnNwbGl0KFwiIFwiKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFzLmxlbmd0aDsgaSsrKVxuICAgICAgaWYgKGFzW2ldICYmICFjbGFzc1Rlc3QoYXNbaV0pLnRlc3QoYikpIGIgKz0gXCIgXCIgKyBhc1tpXTtcbiAgICByZXR1cm4gYjtcbiAgfVxuXG4gIC8vIFdJTkRPVy1XSURFIEVWRU5UU1xuXG4gIC8vIFRoZXNlIG11c3QgYmUgaGFuZGxlZCBjYXJlZnVsbHksIGJlY2F1c2UgbmFpdmVseSByZWdpc3RlcmluZyBhXG4gIC8vIGhhbmRsZXIgZm9yIGVhY2ggZWRpdG9yIHdpbGwgY2F1c2UgdGhlIGVkaXRvcnMgdG8gbmV2ZXIgYmVcbiAgLy8gZ2FyYmFnZSBjb2xsZWN0ZWQuXG5cbiAgZnVuY3Rpb24gZm9yRWFjaENvZGVNaXJyb3IoZikge1xuICAgIGlmICghZG9jdW1lbnQuYm9keS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKSByZXR1cm47XG4gICAgdmFyIGJ5Q2xhc3MgPSBkb2N1bWVudC5ib2R5LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJDb2RlTWlycm9yXCIpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnlDbGFzcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNtID0gYnlDbGFzc1tpXS5Db2RlTWlycm9yO1xuICAgICAgaWYgKGNtKSBmKGNtKTtcbiAgICB9XG4gIH1cblxuICB2YXIgZ2xvYmFsc1JlZ2lzdGVyZWQgPSBmYWxzZTtcbiAgZnVuY3Rpb24gZW5zdXJlR2xvYmFsSGFuZGxlcnMoKSB7XG4gICAgaWYgKGdsb2JhbHNSZWdpc3RlcmVkKSByZXR1cm47XG4gICAgcmVnaXN0ZXJHbG9iYWxIYW5kbGVycygpO1xuICAgIGdsb2JhbHNSZWdpc3RlcmVkID0gdHJ1ZTtcbiAgfVxuICBmdW5jdGlvbiByZWdpc3Rlckdsb2JhbEhhbmRsZXJzKCkge1xuICAgIC8vIFdoZW4gdGhlIHdpbmRvdyByZXNpemVzLCB3ZSBuZWVkIHRvIHJlZnJlc2ggYWN0aXZlIGVkaXRvcnMuXG4gICAgdmFyIHJlc2l6ZVRpbWVyO1xuICAgIG9uKHdpbmRvdywgXCJyZXNpemVcIiwgZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocmVzaXplVGltZXIgPT0gbnVsbCkgcmVzaXplVGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICByZXNpemVUaW1lciA9IG51bGw7XG4gICAgICAgIGZvckVhY2hDb2RlTWlycm9yKG9uUmVzaXplKTtcbiAgICAgIH0sIDEwMCk7XG4gICAgfSk7XG4gICAgLy8gV2hlbiB0aGUgd2luZG93IGxvc2VzIGZvY3VzLCB3ZSB3YW50IHRvIHNob3cgdGhlIGVkaXRvciBhcyBibHVycmVkXG4gICAgb24od2luZG93LCBcImJsdXJcIiwgZnVuY3Rpb24oKSB7XG4gICAgICBmb3JFYWNoQ29kZU1pcnJvcihvbkJsdXIpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gRkVBVFVSRSBERVRFQ1RJT05cblxuICAvLyBEZXRlY3QgZHJhZy1hbmQtZHJvcFxuICB2YXIgZHJhZ0FuZERyb3AgPSBmdW5jdGlvbigpIHtcbiAgICAvLyBUaGVyZSBpcyAqc29tZSoga2luZCBvZiBkcmFnLWFuZC1kcm9wIHN1cHBvcnQgaW4gSUU2LTgsIGJ1dCBJXG4gICAgLy8gY291bGRuJ3QgZ2V0IGl0IHRvIHdvcmsgeWV0LlxuICAgIGlmIChpZSAmJiBpZV92ZXJzaW9uIDwgOSkgcmV0dXJuIGZhbHNlO1xuICAgIHZhciBkaXYgPSBlbHQoJ2RpdicpO1xuICAgIHJldHVybiBcImRyYWdnYWJsZVwiIGluIGRpdiB8fCBcImRyYWdEcm9wXCIgaW4gZGl2O1xuICB9KCk7XG5cbiAgdmFyIHp3c3BTdXBwb3J0ZWQ7XG4gIGZ1bmN0aW9uIHplcm9XaWR0aEVsZW1lbnQobWVhc3VyZSkge1xuICAgIGlmICh6d3NwU3VwcG9ydGVkID09IG51bGwpIHtcbiAgICAgIHZhciB0ZXN0ID0gZWx0KFwic3BhblwiLCBcIlxcdTIwMGJcIik7XG4gICAgICByZW1vdmVDaGlsZHJlbkFuZEFkZChtZWFzdXJlLCBlbHQoXCJzcGFuXCIsIFt0ZXN0LCBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcInhcIildKSk7XG4gICAgICBpZiAobWVhc3VyZS5maXJzdENoaWxkLm9mZnNldEhlaWdodCAhPSAwKVxuICAgICAgICB6d3NwU3VwcG9ydGVkID0gdGVzdC5vZmZzZXRXaWR0aCA8PSAxICYmIHRlc3Qub2Zmc2V0SGVpZ2h0ID4gMiAmJiAhKGllICYmIGllX3ZlcnNpb24gPCA4KTtcbiAgICB9XG4gICAgdmFyIG5vZGUgPSB6d3NwU3VwcG9ydGVkID8gZWx0KFwic3BhblwiLCBcIlxcdTIwMGJcIikgOlxuICAgICAgZWx0KFwic3BhblwiLCBcIlxcdTAwYTBcIiwgbnVsbCwgXCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdpZHRoOiAxcHg7IG1hcmdpbi1yaWdodDogLTFweFwiKTtcbiAgICBub2RlLnNldEF0dHJpYnV0ZShcImNtLXRleHRcIiwgXCJcIik7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICAvLyBGZWF0dXJlLWRldGVjdCBJRSdzIGNydW1teSBjbGllbnQgcmVjdCByZXBvcnRpbmcgZm9yIGJpZGkgdGV4dFxuICB2YXIgYmFkQmlkaVJlY3RzO1xuICBmdW5jdGlvbiBoYXNCYWRCaWRpUmVjdHMobWVhc3VyZSkge1xuICAgIGlmIChiYWRCaWRpUmVjdHMgIT0gbnVsbCkgcmV0dXJuIGJhZEJpZGlSZWN0cztcbiAgICB2YXIgdHh0ID0gcmVtb3ZlQ2hpbGRyZW5BbmRBZGQobWVhc3VyZSwgZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJBXFx1MDYyZUFcIikpO1xuICAgIHZhciByMCA9IHJhbmdlKHR4dCwgMCwgMSkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAg
23459aWYgKCFyMCB8fCByMC5sZWZ0ID09IHIwLnJpZ2h0KSByZXR1cm4gZmFsc2U7IC8vIFNhZmFyaSByZXR1cm5zIG51bGwgaW4gc29tZSBjYXNlcyAoIzI3ODApXG4gICAgdmFyIHIxID0gcmFuZ2UodHh0LCAxLCAyKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTt
vendor: 20,473 bytes, line 23459
23459cbiAgICByZXR1cm4gYmFkQmlkaVJlY3RzID0gKHIxLnJpZ2h0IC0gcjAucmlnaHQgPCAzKTtcbiAgfVxuXG4gIC8vIFNlZSBpZiBcIlwiLnNwbGl0IGlzIHRoZSBicm9rZW4gSUUgdmVyc2lvbiwgaWYgc28sIHByb3ZpZGUgYW5cbiAgLy8gYWx0ZXJuYXRpdmUgd2F5IHRvIHNwbGl0IGxpbmVzLlxuICB2YXIgc3BsaXRMaW5lc0F1dG8gPSBDb2RlTWlycm9yLnNwbGl0TGluZXMgPSBcIlxcblxcbmJcIi5zcGxpdCgvXFxuLykubGVuZ3RoICE9IDMgPyBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICB2YXIgcG9zID0gMCwgcmVzdWx0ID0gW10sIGwgPSBzdHJpbmcubGVuZ3RoO1xuICAgIHdoaWxlIChwb3MgPD0gbCkge1xuICAgICAgdmFyIG5sID0gc3RyaW5nLmluZGV4T2YoXCJcXG5cIiwgcG9zKTtcbiAgICAgIGlmIChubCA9PSAtMSkgbmwgPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgdmFyIGxpbmUgPSBzdHJpbmcuc2xpY2UocG9zLCBzdHJpbmcuY2hhckF0KG5sIC0gMSkgPT0gXCJcXHJcIiA/IG5sIC0gMSA6IG5sKTtcbiAgICAgIHZhciBydCA9IGxpbmUuaW5kZXhPZihcIlxcclwiKTtcbiAgICAgIGlmIChydCAhPSAtMSkge1xuICAgICAgICByZXN1bHQucHVzaChsaW5lLnNsaWNlKDAsIHJ0KSk7XG4gICAgICAgIHBvcyArPSBydCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQucHVzaChsaW5lKTtcbiAgICAgICAgcG9zID0gbmwgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IDogZnVuY3Rpb24oc3RyaW5nKXtyZXR1cm4gc3RyaW5nLnNwbGl0KC9cXHJcXG4/fFxcbi8pO307XG5cbiAgdmFyIGhhc1NlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24gPyBmdW5jdGlvbih0ZSkge1xuICAgIHRyeSB7IHJldHVybiB0ZS5zZWxlY3Rpb25TdGFydCAhPSB0ZS5zZWxlY3Rpb25FbmQ7IH1cbiAgICBjYXRjaChlKSB7IHJldHVybiBmYWxzZTsgfVxuICB9IDogZnVuY3Rpb24odGUpIHtcbiAgICB0cnkge3ZhciByYW5nZSA9IHRlLm93bmVyRG9jdW1lbnQuc2VsZWN0aW9uLmNyZWF0ZVJhbmdlKCk7fVxuICAgIGNhdGNoKGUpIHt9XG4gICAgaWYgKCFyYW5nZSB8fCByYW5nZS5wYXJlbnRFbGVtZW50KCkgIT0gdGUpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gcmFuZ2UuY29tcGFyZUVuZFBvaW50cyhcIlN0YXJ0VG9FbmRcIiwgcmFuZ2UpICE9IDA7XG4gIH07XG5cbiAgdmFyIGhhc0NvcHlFdmVudCA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgZSA9IGVsdChcImRpdlwiKTtcbiAgICBpZiAoXCJvbmNvcHlcIiBpbiBlKSByZXR1cm4gdHJ1ZTtcbiAgICBlLnNldEF0dHJpYnV0ZShcIm9uY29weVwiLCBcInJldHVybjtcIik7XG4gICAgcmV0dXJuIHR5cGVvZiBlLm9uY29weSA9PSBcImZ1bmN0aW9uXCI7XG4gIH0pKCk7XG5cbiAgdmFyIGJhZFpvb21lZFJlY3RzID0gbnVsbDtcbiAgZnVuY3Rpb24gaGFzQmFkWm9vbWVkUmVjdHMobWVhc3VyZSkge1xuICAgIGlmIChiYWRab29tZWRSZWN0cyAhPSBudWxsKSByZXR1cm4gYmFkWm9vbWVkUmVjdHM7XG4gICAgdmFyIG5vZGUgPSByZW1vdmVDaGlsZHJlbkFuZEFkZChtZWFzdXJlLCBlbHQoXCJzcGFuXCIsIFwieFwiKSk7XG4gICAgdmFyIG5vcm1hbCA9IG5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdmFyIGZyb21SYW5nZSA9IHJhbmdlKG5vZGUsIDAsIDEpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiBiYWRab29tZWRSZWN0cyA9IE1hdGguYWJzKG5vcm1hbC5sZWZ0IC0gZnJvbVJhbmdlLmxlZnQpID4gMTtcbiAgfVxuXG4gIC8vIEtFWSBOQU1FU1xuXG4gIHZhciBrZXlOYW1lcyA9IENvZGVNaXJyb3Iua2V5TmFtZXMgPSB7XG4gICAgMzogXCJFbnRlclwiLCA4OiBcIkJhY2tzcGFjZVwiLCA5OiBcIlRhYlwiLCAxMzogXCJFbnRlclwiLCAxNjogXCJTaGlmdFwiLCAxNzogXCJDdHJsXCIsIDE4OiBcIkFsdFwiLFxuICAgIDE5OiBcIlBhdXNlXCIsIDIwOiBcIkNhcHNMb2NrXCIsIDI3OiBcIkVzY1wiLCAzMjogXCJTcGFjZVwiLCAzMzogXCJQYWdlVXBcIiwgMzQ6IFwiUGFnZURvd25cIiwgMzU6IFwiRW5kXCIsXG4gICAgMzY6IFwiSG9tZVwiLCAzNzogXCJMZWZ0XCIsIDM4OiBcIlVwXCIsIDM5OiBcIlJpZ2h0XCIsIDQwOiBcIkRvd25cIiwgNDQ6IFwiUHJpbnRTY3JuXCIsIDQ1OiBcIkluc2VydFwiLFxuICAgIDQ2OiBcIkRlbGV0ZVwiLCA1OTogXCI7XCIsIDYxOiBcIj1cIiwgOTE6IFwiTW9kXCIsIDkyOiBcIk1vZFwiLCA5MzogXCJNb2RcIixcbiAgICAxMDY6IFwiKlwiLCAxMDc6IFwiPVwiLCAxMDk6IFwiLVwiLCAxMTA6IFwiLlwiLCAxMTE6IFwiL1wiLCAxMjc6IFwiRGVsZXRlXCIsXG4gICAgMTczOiBcIi1cIiwgMTg2OiBcIjtcIiwgMTg3OiBcIj1cIiwgMTg4OiBcIixcIiwgMTg5OiBcIi1cIiwgMTkwOiBcIi5cIiwgMTkxOiBcIi9cIiwgMTkyOiBcImBcIiwgMjE5OiBcIltcIiwgMjIwOiBcIlxcXFxcIixcbiAgICAyMjE6IFwiXVwiLCAyMjI6IFwiJ1wiLCA2MzIzMjogXCJVcFwiLCA2MzIzMzogXCJEb3duXCIsIDYzMjM0OiBcIkxlZnRcIiwgNjMyMzU6IFwiUmlnaHRcIiwgNjMyNzI6IFwiRGVsZXRlXCIsXG4gICAgNjMyNzM6IFwiSG9tZVwiLCA2MzI3NTogXCJFbmRcIiwgNjMyNzY6IFwiUGFnZVVwXCIsIDYzMjc3OiBcIlBhZ2VEb3duXCIsIDYzMzAyOiBcIkluc2VydFwiXG4gIH07XG4gIChmdW5jdGlvbigpIHtcbiAgICAvLyBOdW1iZXIga2V5c1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykga2V5TmFtZXNbaSArIDQ4XSA9IGtleU5hbWVzW2kgKyA5Nl0gPSBTdHJpbmcoaSk7XG4gICAgLy8gQWxwaGFiZXRpYyBrZXlzXG4gICAgZm9yICh2YXIgaSA9IDY1OyBpIDw9IDkwOyBpKyspIGtleU5hbWVzW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZShpKTtcbiAgICAvLyBGdW5jdGlvbiBrZXlzXG4gICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTI7IGkrKykga2V5TmFtZXNbaSArIDExMV0gPSBrZXlOYW1lc1tpICsgNjMyMzVdID0gXCJGXCIgKyBpO1xuICB9KSgpO1xuXG4gIC8vIEJJREkgSEVMUEVSU1xuXG4gIGZ1bmN0aW9uIGl0ZXJhdGVCaWRpU2VjdGlvbnMob3JkZXIsIGZyb20sIHRvLCBmKSB7XG4gICAgaWYgKCFvcmRlcikgcmV0dXJuIGYoZnJvbSwgdG8sIFwibHRyXCIpO1xuICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBwYXJ0ID0gb3JkZXJbaV07XG4gICAgICBpZiAocGFydC5mcm9tIDwgdG8gJiYgcGFydC50byA+IGZyb20gfHwgZnJvbSA9PSB0byAmJiBwYXJ0LnRvID09IGZyb20pIHtcbiAgICAgICAgZihNYXRoLm1heChwYXJ0LmZyb20sIGZyb20pLCBNYXRoLm1pbihwYXJ0LnRvLCB0byksIHBhcnQubGV2ZWwgPT0gMSA/IFwicnRsXCIgOiBcImx0clwiKTtcbiAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWZvdW5kKSBmKGZyb20sIHRvLCBcImx0clwiKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJpZGlMZWZ0KHBhcnQpIHsgcmV0dXJuIHBhcnQubGV2ZWwgJSAyID8gcGFydC50byA6IHBhcnQuZnJvbTsgfVxuICBmdW5jdGlvbiBiaWRpUmlnaHQocGFydCkgeyByZXR1cm4gcGFydC5sZXZlbCAlIDIgPyBwYXJ0LmZyb20gOiBwYXJ0LnRvOyB9XG5cbiAgZnVuY3Rpb24gbGluZUxlZnQobGluZSkgeyB2YXIgb3JkZXIgPSBnZXRPcmRlcihsaW5lKTsgcmV0dXJuIG9yZGVyID8gYmlkaUxlZnQob3JkZXJbMF0pIDogMDsgfVxuICBmdW5jdGlvbiBsaW5lUmlnaHQobGluZSkge1xuICAgIHZhciBvcmRlciA9IGdldE9yZGVyKGxpbmUpO1xuICAgIGlmICghb3JkZXIpIHJldHVybiBsaW5lLnRleHQubGVuZ3RoO1xuICAgIHJldHVybiBiaWRpUmlnaHQobHN0KG9yZGVyKSk7XG4gIH1cblxuICBmdW5jdGlvbiBsaW5lU3RhcnQoY20sIGxpbmVOKSB7XG4gICAgdmFyIGxpbmUgPSBnZXRMaW5lKGNtLmRvYywgbGluZU4pO1xuICAgIHZhciB2aXN1YWwgPSB2aXN1YWxMaW5lKGxpbmUpO1xuICAgIGlmICh2aXN1YWwgIT0gbGluZSkgbGluZU4gPSBsaW5lTm8odmlzdWFsKTtcbiAgICB2YXIgb3JkZXIgPSBnZXRPcmRlcih2aXN1YWwpO1xuICAgIHZhciBjaCA9ICFvcmRlciA/IDAgOiBvcmRlclswXS5sZXZlbCAlIDIgPyBsaW5lUmlnaHQodmlzdWFsKSA6IGxpbmVMZWZ0KHZpc3VhbCk7XG4gICAgcmV0dXJuIFBvcyhsaW5lTiwgY2gpO1xuICB9XG4gIGZ1bmN0aW9uIGxpbmVFbmQoY20sIGxpbmVOKSB7XG4gICAgdmFyIG1lcmdlZCwgbGluZSA9IGdldExpbmUoY20uZG9jLCBsaW5lTik7XG4gICAgd2hpbGUgKG1lcmdlZCA9IGNvbGxhcHNlZFNwYW5BdEVuZChsaW5lKSkge1xuICAgICAgbGluZSA9IG1lcmdlZC5maW5kKDEsIHRydWUpLmxpbmU7XG4gICAgICBsaW5lTiA9IG51bGw7XG4gICAgfVxuICAgIHZhciBvcmRlciA9IGdldE9yZGVyKGxpbmUpO1xuICAgIHZhciBjaCA9ICFvcmRlciA/IGxpbmUudGV4dC5sZW5ndGggOiBvcmRlclswXS5sZXZlbCAlIDIgPyBsaW5lTGVmdChsaW5lKSA6IGxpbmVSaWdodChsaW5lKTtcbiAgICByZXR1cm4gUG9zKGxpbmVOID09IG51bGwgPyBsaW5lTm8obGluZSkgOiBsaW5lTiwgY2gpO1xuICB9XG4gIGZ1bmN0aW9uIGxpbmVTdGFydFNtYXJ0KGNtLCBwb3MpIHtcbiAgICB2YXIgc3RhcnQgPSBsaW5lU3RhcnQoY20sIHBvcy5saW5lKTtcbiAgICB2YXIgbGluZSA9IGdldExpbmUoY20uZG9jLCBzdGFydC5saW5lKTtcbiAgICB2YXIgb3JkZXIgPSBnZXRPcmRlcihsaW5lKTtcbiAgICBpZiAoIW9yZGVyIHx8IG9yZGVyWzBdLmxldmVsID09IDApIHtcbiAgICAgIHZhciBmaXJzdE5vbldTID0gTWF0aC5tYXgoMCwgbGluZS50ZXh0LnNlYXJjaCgvXFxTLykpO1xuICAgICAgdmFyIGluV1MgPSBwb3MubGluZSA9PSBzdGFydC5saW5lICYmIHBvcy5jaCA8PSBmaXJzdE5vbldTICYmIHBvcy5jaDtcbiAgICAgIHJldHVybiBQb3Moc3RhcnQubGluZSwgaW5XUyA/IDAgOiBmaXJzdE5vbldTKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0O1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcGFyZUJpZGlMZXZlbChvcmRlciwgYSwgYikge1xuICAgIHZhciBsaW5lZGlyID0gb3JkZXJbMF0ubGV2ZWw7XG4gICAgaWYgKGEgPT0gbGluZWRpcikgcmV0dXJuIHRydWU7XG4gICAgaWYgKGIgPT0gbGluZWRpcikgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBhIDwgYjtcbiAgfVxuICB2YXIgYmlkaU90aGVyO1xuICBmdW5jdGlvbiBnZXRCaWRpUGFydEF0KG9yZGVyLCBwb3MpIHtcbiAgICBiaWRpT3RoZXIgPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwLCBmb3VuZDsgaSA8IG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgY3VyID0gb3JkZXJbaV07XG4gICAgICBpZiAoY3VyLmZyb20gPCBwb3MgJiYgY3VyLnRvID4gcG9zKSByZXR1cm4gaTtcbiAgICAgIGlmICgoY3VyLmZyb20gPT0gcG9zIHx8IGN1ci50byA9PSBwb3MpKSB7XG4gICAgICAgIGlmIChmb3VuZCA9PSBudWxsKSB7XG4gICAgICAgICAgZm91bmQgPSBpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbXBhcmVCaWRpTGV2ZWwob3JkZXIsIGN1ci5sZXZlbCwgb3JkZXJbZm91bmRdLmxldmVsKSkge1xuICAgICAgICAgIGlmIChjdXIuZnJvbSAhPSBjdXIudG8pIGJpZGlPdGhlciA9IGZvdW5kO1xuICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjdXIuZnJvbSAhPSBjdXIudG8pIGJpZGlPdGhlciA9IGk7XG4gICAgICAgICAgcmV0dXJuIGZvdW5kO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmb3VuZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1vdmVJbkxpbmUobGluZSwgcG9zLCBkaXIsIGJ5VW5pdCkge1xuICAgIGlmICghYnlVbml0KSByZXR1cm4gcG9zICsgZGlyO1xuICAgIGRvIHBvcyArPSBkaXI7XG4gICAgd2hpbGUgKHBvcyA+IDAgJiYgaXNFeHRlbmRpbmdDaGFyKGxpbmUudGV4dC5jaGFyQXQocG9zKSkpO1xuICAgIHJldHVybiBwb3M7XG4gIH1cblxuICAvLyBUaGlzIGlzIG5lZWRlZCBpbiBvcmRlciB0byBtb3ZlICd2aXN1YWxseScgdGhyb3VnaCBiaS1kaXJlY3Rpb25hbFxuICAvLyB0ZXh0IC0tIGkuZS4sIHByZXNzaW5nIGxlZnQgc2hvdWxkIG1ha2UgdGhlIGN1cnNvciBnbyBsZWZ0LCBldmVuXG4gIC8vIHdoZW4gaW4gUlRMIHRleHQuIFRoZSB0cmlja3kgcGFydCBpcyB0aGUgJ2p1bXBzJywgd2hlcmUgUlRMIGFuZFxuICAvLyBMVFIgdGV4dCB0b3VjaCBlYWNoIG90aGVyLiBUaGlzIG9mdGVuIHJlcXVpcmVzIHRoZSBjdXJzb3Igb2Zmc2V0XG4gIC8vIHRvIG1vdmUgbW9yZSB0aGFuIG9uZSB1bml0LCBpbiBvcmRlciB0byB2aXN1YWxseSBtb3ZlIG9uZSB1bml0LlxuICBmdW5jdGlvbiBtb3ZlVmlzdWFsbHkobGluZSwgc3RhcnQsIGRpciwgYnlVbml0KSB7XG4gICAgdmFyIGJpZGkgPSBnZXRPcmRlcihsaW5lKTtcbiAgICBpZiAoIWJpZGkpIHJldHVybiBtb3ZlTG9naWNhbGx5KGxpbmUsIHN0YXJ0LCBkaXIsIGJ5VW5pdCk7XG4gICAgdmFyIHBvcyA9IGdldEJpZGlQYXJ0QXQoYmlkaSwgc3RhcnQpLCBwYXJ0ID0gYmlkaVtwb3NdO1xuICAgIHZhciB0YXJnZXQgPSBtb3ZlSW5MaW5lKGxpbmUsIHN0YXJ0LCBwYXJ0LmxldmVsICUgMiA/IC1kaXIgOiBkaXIsIGJ5VW5pdCk7XG5cbiAgICBmb3IgKDs7KSB7XG4gICAgICBpZiAodGFyZ2V0ID4gcGFydC5mcm9tICYmIHRhcmdldCA8IHBhcnQudG8pIHJldHVybiB0YXJnZXQ7XG4gICAgICBpZiAodGFyZ2V0ID09IHBhcnQuZnJvbSB8fCB0YXJnZXQgPT0gcGFydC50bykge1xuICAgICAgICBpZiAoZ2V0QmlkaVBhcnRBdChiaWRpLCB0YXJnZXQpID09IHBvcykgcmV0dXJuIHRhcmdldDtcbiAgICAgICAgcGFydCA9IGJpZGlbcG9zICs9IGRpcl07XG4gICAgICAgIHJldHVybiAoZGlyID4gMCkgPT0gcGFydC5sZXZlbCAlIDIgPyBwYXJ0LnRvIDogcGFydC5mcm9tO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFydCA9IGJpZGlbcG9zICs9IGRpcl07XG4gICAgICAgIGlmICghcGFydCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGlmICgoZGlyID4gMCkgPT0gcGFydC5sZXZlbCAlIDIpXG4gICAgICAgICAgdGFyZ2V0ID0gbW92ZUluTGluZShsaW5lLCBwYXJ0LnRvLCAtMSwgYnlVbml0KTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHRhcmdldCA9IG1vdmVJbkxpbmUobGluZSwgcGFydC5mcm9tLCAxLCBieVVuaXQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG1vdmVMb2dpY2FsbHkobGluZSwgc3RhcnQsIGRpciwgYnlVbml0KSB7XG4gICAgdmFyIHRhcmdldCA9IHN0YXJ0ICsgZGlyO1xuICAgIGlmIChieVVuaXQpIHdoaWxlICh0YXJnZXQgPiAwICYmIGlzRXh0ZW5kaW5nQ2hhcihsaW5lLnRleHQuY2hhckF0KHRhcmdldCkpKSB0YXJnZXQgKz0gZGlyO1xuICAgIHJldHVybiB0YXJnZXQgPCAwIHx8IHRhcmdldCA+IGxpbmUudGV4dC5sZW5ndGggPyBudWxsIDogdGFyZ2V0O1xuICB9XG5cbiAgLy8gQmlkaXJlY3Rpb25hbCBvcmRlcmluZyBhbGdvcml0aG1cbiAgLy8gU2VlIGh0dHA6Ly91bmljb2RlLm9yZy9yZXBvcnRzL3RyOS90cjktMTMuaHRtbCBmb3IgdGhlIGFsZ29yaXRobVxuICAvLyB0aGF0IHRoaXMgKHBhcnRpYWxseSkgaW1wbGVtZW50cy5cblxuICAvLyBPbmUtY2hhciBjb2RlcyB1c2VkIGZvciBjaGFyYWN0ZXIgdHlwZXM6XG4gIC8vIEwgKEwpOiAgIExlZnQtdG8tUmlnaHRcbiAgLy8gUiAoUik6ICAgUmlnaHQtdG8tTGVmdFxuICAvLyByIChBTCk6ICBSaWdodC10by1MZWZ0IEFyYWJpY1xuICAvLyAxIChFTik6ICBFdXJvcGVhbiBOdW1iZXJcbiAgLy8gKyAoRVMpOiAgRXVyb3BlYW4gTnVtYmVyIFNlcGFyYXRvclxuICAvLyAlIChFVCk6ICBFdXJvcGVhbiBOdW1iZXIgVGVybWluYXRvclxuICAvLyBuIChBTik6ICBBcmFiaWMgTnVtYmVyXG4gIC8vICwgKENTKTogIENvbW1vbiBOdW1iZXIgU2VwYXJhdG9yXG4gIC8vIG0gKE5TTSk6IE5vbi1TcGFjaW5nIE1hcmtcbiAgLy8gYiAoQk4pOiAgQm91bmRhcnkgTmV1dHJhbFxuICAvLyBzIChCKTogICBQYXJhZ3JhcGggU2VwYXJhdG9yXG4gIC8vIHQgKFMpOiAgIFNlZ21lbnQgU2VwYXJhdG9yXG4gIC8vIHcgKFdTKTogIFdoaXRlc3BhY2VcbiAgLy8gTiAoT04pOiAgT3RoZXIgTmV1dHJhbHNcblxuICAvLyBSZXR1cm5zIG51bGwgaWYgY2hhcmFjdGVycyBhcmUgb3JkZXJlZCBhcyB0aGV5IGFwcGVhclxuICAvLyAobGVmdC10by1yaWdodCksIG9yIGFuIGFycmF5IG9mIHNlY3Rpb25zICh7ZnJvbSwgdG8sIGxldmVsfVxuICAvLyBvYmplY3RzKSBpbiB0aGUgb3JkZXIgaW4gd2hpY2ggdGhleSBvY2N1ciB2aXN1YWxseS5cbiAgdmFyIGJpZGlPcmRlcmluZyA9IChmdW5jdGlvbigpIHtcbiAgICAvLyBDaGFyYWN0ZXIgdHlwZXMgZm9yIGNvZGVwb2ludHMgMCB0byAweGZmXG4gICAgdmFyIGxvd1R5cGVzID0gXCJiYmJiYmJiYmJ0c3R3c2JiYmJiYmJiYmJiYmJic3NzdHdOTiUlJU5OTk5OTixOLE4xMTExMTExMTExTk5OTk5OTkxMTExMTExMTExMTExMTExMTExMTExMTExMTk5OTk5OTExMTExMTExMTExMTExMTExMTExMTExMTExOTk5OYmJiYmJic2JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiLE4lJSUlTk5OTkxOTk5OTiUlMTFOTE5OTjFMTk5OTk5MTExMTExMTExMTExMTExMTExMTExMTE5MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTlwiO1xuICAgIC8vIENoYXJhY3RlciB0eXBlcyBmb3IgY29kZXBvaW50cyAweDYwMCB0byAweDZmZlxuICAgIHZhciBhcmFiaWNUeXBlcyA9IFwicnJycnJycnJycnJyLHJOTm1tbW1tbXJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJybW1tbW1tbW1tbW1tbW1ycnJycnJybm5ubm5ubm5ubiVubnJycm1ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycm1tbW1tbW1tbW1tbW1tbW1tbW1ObW1tbVwiO1xuICAgIGZ1bmN0aW9uIGNoYXJUeXBlKGNvZGUpIHtcbiAgICAgIGlmIChjb2RlIDw9IDB4ZjcpIHJldHVybiBsb3dUeXBlcy5jaGFyQXQoY29kZSk7XG4gICAgICBlbHNlIGlmICgweDU5MCA8PSBjb2RlICYmIGNvZGUgPD0gMHg1ZjQpIHJldHVybiBcIlJcIjtcbiAgICAgIGVsc2UgaWYgKDB4NjAwIDw9IGNvZGUgJiYgY29kZSA8PSAweDZlZCkgcmV0dXJuIGFyYWJpY1R5cGVzLmNoYXJBdChjb2RlIC0gMHg2MDApO1xuICAgICAgZWxzZSBpZiAoMHg2ZWUgPD0gY29kZSAmJiBjb2RlIDw9IDB4OGFjKSByZXR1cm4gXCJyXCI7XG4gICAgICBlbHNlIGlmICgweDIwMDAgPD0gY29kZSAmJiBjb2RlIDw9IDB4MjAwYikgcmV0dXJuIFwid1wiO1xuICAgICAgZWxzZSBpZiAoY29kZSA9PSAweDIwMGMpIHJldHVybiBcImJcIjtcbiAgICAgIGVsc2UgcmV0dXJuIFwiTFwiO1xuICAgIH1cblxuICAgIHZhciBiaWRpUkUgPSAvW1xcdTA1OTAtXFx1MDVmNFxcdTA2MDAtXFx1MDZmZlxcdTA3MDAtXFx1MDhhY10vO1xuICAgIHZhciBpc05ldXRyYWwgPSAvW3N0d05dLywgaXNTdHJvbmcgPSAvW0xScl0vLCBjb3VudHNBc0xlZnQgPSAvW0xiMW5dLywgY291bnRzQXNOdW0gPSAvWzFuXS87XG4gICAgLy8gQnJvd3NlcnMgc2VlbSB0byBhbHdheXMgdHJlYXQgdGhlIGJvdW5kYXJpZXMgb2YgYmxvY2sgZWxlbWVudHMgYXMgYmVpbmcgTC5cbiAgICB2YXIgb3V0ZXJUeXBlID0gXCJMXCI7XG5cbiAgICBmdW5jdGlvbiBCaWRpU3BhbihsZXZlbCwgZnJvbSwgdG8pIHtcbiAgICAgIHRoaXMubGV2ZWwgPSBsZXZlbDtcbiAgICAgIHRoaXMuZnJvbSA9IGZyb207IHRoaXMudG8gPSB0bztcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyKSB7XG4gICAgICBpZiAoIWJpZGlSRS50ZXN0KHN0cikpIHJldHVybiBmYWxzZTtcbiAgICAgIHZhciBsZW4gPSBzdHIubGVuZ3RoLCB0eXBlcyA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIHR5cGU7IGkgPCBsZW47ICsraSlcbiAgICAgICAgdHlwZXMucHVzaCh0eXBlID0gY2hhclR5cGUoc3RyLmNoYXJDb2RlQXQoaSkpKTtcblxuICAgICAgLy8gVzEuIEV4YW1pbmUgZWFjaCBub24tc3BhY2luZyBtYXJrIChOU00pIGluIHRoZSBsZXZlbCBydW4sIGFuZFxuICAgICAgLy8gY2hhbmdlIHRoZSB0eXBlIG9mIHRoZSBOU00gdG8gdGhlIHR5cGUgb2YgdGhlIHByZXZpb3VzXG4gICAgICAvLyBjaGFyYWN0ZXIuIElmIHRoZSBOU00gaXMgYXQgdGhlIHN0YXJ0IG9mIHRoZSBsZXZlbCBydW4sIGl0IHdpbGxcbiAgICAgIC8vIGdldCB0aGUgdHlwZSBvZiBzb3IuXG4gICAgICBmb3IgKHZhciBpID0gMCwgcHJldiA9IG91dGVyVHlwZTsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZXNbaV07XG4gICAgICAgIGlmICh0eXBlID09IFwibVwiKSB0eXBlc1tpXSA9IHByZXY7XG4gICAgICAgIGVsc2UgcHJldiA9IHR5cGU7XG4gICAgICB9XG5cbiAgICAgIC8vIFcyLiBTZWFyY2ggYmFja3dhcmRzIGZyb20gZWFjaCBpbnN0YW5jZSBvZiBhIEV1cm9wZWFuIG51bWJlclxuICAgICAgLy8gdW50aWwgdGhlIGZpcnN0IHN0cm9uZyB0eXBlIChSLCBMLCBBTCwgb3Igc29yKSBpcyBmb3VuZC4gSWYgYW5cbiAgICAgIC8vIEFMIGlzIGZvdW5kLCBjaGFuZ2UgdGhlIHR5cGUgb2YgdGhlIEV1cm9wZWFuIG51bWJlciB0byBBcmFiaWNcbiAgICAgIC8vIG51bWJlci5cbiAgICAgIC8vIFczLiBDaGFuZ2UgYWxsIEFMcyB0byBSLlxuICAgICAgZm9yICh2YXIgaSA9IDAsIGN1ciA9IG91dGVyVHlwZTsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZXNbaV07XG4gICAgICAgIGlmICh0eXBlID09IFwiMVwiICYmIGN1ciA9PSBcInJcIikgdHlwZXNbaV0gPSBcIm5cIjtcbiAgICAgICAgZWxzZSBpZiAoaXNTdHJvbmcudGVzdCh0eXBlKSkgeyBjdXIgPSB0eXBlOyBpZiAodHlwZSA9PSBcInJcIikgdHlwZXNbaV0gPSBcIlJcIjsgfVxuICAgICAgfVxuXG4gICAgICAvLyBXNC4gQSBzaW5nbGUgRXVyb3BlYW4gc2VwYXJhdG9yIGJldHdlZW4gdHdvIEV1cm9wZWFuIG51bWJlcnNcbiAgICAgIC8vIGNoYW5nZXMgdG8gYSBFdXJvcGVhbiBudW1iZXIuIEEgc2luZ2xlIGNvbW1vbiBzZXBhcmF0b3IgYmV0d2VlblxuICAgICAgLy8gdHdvIG51bWJlcnMgb2YgdGhlIHNhbWUgdHlwZSBjaGFuZ2VzIHRvIHRoYXQgdHlwZS5cbiAgICAgIGZvciAodmFyIGkgPSAxLCBwcmV2ID0gdHlwZXNbMF07IGkgPCBsZW4gLSAxOyArK2kpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlc1tpXTtcbiAgICAgICAgaWYgKHR5cGUgPT0gXCIrXCIgJiYgcHJldiA9PSBcIjFcIiAmJiB0eXBlc1tpKzFdID09IFwiMVwiKSB0eXBlc1tpXSA9IFwiMVwiO1xuICAgICAgICBlbHNlIGlmICh0eXBlID09IFwiLFwiICYmIHByZXYgPT0gdHlwZXNbaSsxXSAmJlxuICAgICAgICAgICAgICAgICAocHJldiA9PSBcIjFcIiB8fCBwcmV2ID09IFwiblwiKSkgdHlwZXNbaV0gPSBwcmV2O1xuICAgICAgICBwcmV2ID0gdHlwZTtcbiAgICAgIH1cblxuICAgICAgLy8gVzUuIEEgc2VxdWVuY2Ugb2YgRXVyb3BlYW4gdGVybWluYXRvcnMgYWRqYWNlbnQgdG8gRXVyb3BlYW5cbiAgICAgIC8vIG51bWJlcnMgY2hhbmdlcyB0byBhbGwgRXVyb3BlYW4gbnVtYmVycy5cbiAgICAgIC8vIFc2LiBPdGhlcndpc2UsIHNlcGFyYXRvcnMgYW5kIHRlcm1pbmF0b3JzIGNoYW5nZSB0byBPdGhlclxuICAgICAgLy8gTmV1dHJhbC5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlc1tpXTtcbiAgICAgICAgaWYgKHR5cGUgPT0gXCIsXCIpIHR5cGVzW2ldID0gXCJOXCI7XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT0gXCIlXCIpIHtcbiAgICAgICAgICBmb3IgKHZhciBlbmQgPSBpICsgMTsgZW5kIDwgbGVuICYmIHR5cGVzW2VuZF0gPT0gXCIlXCI7ICsrZW5kKSB7fVxuICAgICAgICAgIHZhciByZXBsYWNlID0gKGkgJiYgdHlwZXNbaS0xXSA9PSBcIiFcIikgfHwgKGVuZCA8IGxlbiAmJiB0eXBlc1tlbmRdID09IFwiMVwiKSA/IFwiMVwiIDogXCJOXCI7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IGk7IGogPCBlbmQ7ICsraikgdHlwZXNbal0gPSByZXBsYWNlO1xuICAgICAgICAgIGkgPSBlbmQgLSAxO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFc3LiBTZWFyY2ggYmFja3dhcmRzIGZyb20gZWFjaCBpbnN0YW5jZSBvZiBhIEV1cm9wZWFuIG51bWJlclxuICAgICAgLy8gdW50aWwgdGhlIGZpcnN0IHN0cm9uZyB0eXBlIChSLCBMLCBvciBzb3IpIGlzIGZvdW5kLiBJZiBhbiBMIGlzXG4gICAgICAvLyBmb3VuZCwgdGhlbiBjaGFuZ2UgdGhlIHR5cGUgb2YgdGhlIEV1cm9wZWFuIG51bWJlciB0byBMLlxuICAgICAgZm9yICh2YXIgaSA9IDAsIGN1ciA9IG91dGVyVHlwZTsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZXNbaV07XG4gICAgICAgIGlmIChjdXIgPT0gXCJMXCIgJiYgdHlwZSA9PSBcIjFcIikgdHlwZXNbaV0gPSBcIkxcIjtcbiAgICAgICAgZWxzZSBpZiAoaXNTdHJvbmcudGVzdCh0eXBlKSkgY3VyID0gdHlwZTtcbiAgICAgIH1cblxuICAgICAgLy8gTjEuIEEgc2VxdWVuY2Ugb2YgbmV1dHJhbHMgdGFrZXMgdGhlIGRpcmVjdGlvbiBvZiB0aGVcbiAgICAgIC8vIHN1cnJvdW5kaW5nIHN0cm9uZyB0ZXh0IGlmIHRoZSB0ZXh0IG9uIGJvdGggc2lkZXMgaGFzIHRoZSBzYW1lXG4gICAgICAvLyBkaXJlY3Rpb24uIEV1cm9wZWFuIGFuZCBBcmFiaWMgbnVtYmVycyBhY3QgYXMgaWYgdGhleSB3ZXJlIFIgaW5cbiAgICAgIC8vIHRlcm1zIG9mIHRoZWlyIGluZmx1ZW5jZSBvbiBuZXV0cmFscy4gU3RhcnQtb2YtbGV2ZWwtcnVuIChzb3IpXG4gICAgICAvLyBhbmQgZW5kLW9mLWxldmVsLXJ1biAoZW9yKSBhcmUgdXNlZCBhdCBsZXZlbCBydW4gYm91bmRhcmllcy5cbiAgICAgIC8vIE4yLiBBbnkgcmVtYWluaW5nIG5ldXRyYWxzIHRha2UgdGhlIGVtYmVkZGluZyBkaXJlY3Rpb24uXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgIGlmIChpc05ldXRyYWwudGVzdCh0eXBlc1tpXSkpIHtcbiAgICAgICAgICBmb3IgKHZhciBlbmQgPSBpICsgMTsgZW5kIDwgbGVuICYmIGlzTmV1dHJhbC50ZXN0KHR5cGVzW2VuZF0pOyArK2VuZCkge31cbiAgICAgICAgICB2YXIgYmVmb3JlID0gKGkgPyB0eXBlc1tpLTFdIDogb3V0ZXJUeXBlKSA9PSBcIkxcIjtcbiAgICAgICAgICB2YXIgYWZ0ZXIgPSAoZW5kIDwgbGVuID8gdHlwZXNbZW5kXSA6IG91dGVyVHlwZSkgPT0gXCJMXCI7XG4gICAgICAgICAgdmFyIHJlcGxhY2UgPSBiZWZvcmUgfHwgYWZ0ZXIgPyBcIkxcIiA6IFwiUlwiO1xuICAgICAgICAgIGZvciAodmFyIGogPSBpOyBqIDwgZW5kOyArK2opIHR5cGVzW2pdID0gcmVwbGFjZTtcbiAgICAgICAgICBpID0gZW5kIC0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBIZXJlIHdlIGRlcGFydCBmcm9tIHRoZSBkb2N1bWVudGVkIGFsZ29yaXRobSwgaW4gb3JkZXIgdG8gYXZvaWRcbiAgICAgIC8vIGJ1aWxkaW5nIHVwIGFuIGFjdHVhbCBsZXZlbHMgYXJyYXkuIFNpbmNlIHRoZXJlIGFyZSBvbmx5IHRocmVlXG4gICAgICAvLyBsZXZlbHMgKDAsIDEsIDIpIGluIGFuIGltcGxlbWVudGF0aW9uIHRoYXQgZG9lc24ndCB0YWtlXG4gICAgICAvLyBleHBsaWNpdCBlbWJlZGRpbmcgaW50byBhY2NvdW50LCB3ZSBjYW4gYnVpbGQgdXAgdGhlIG9yZGVyIG9uXG4gICAgICAvLyB0aGUgZmx5LCB3aXRob3V0IGZvbGxvd2luZyB0aGUgbGV2ZWwtYmFzZWQgYWxnb3JpdGhtLlxuICAgICAgdmFyIG9yZGVyID0gW10sIG07XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjspIHtcbiAgICAgICAgaWYgKGNvdW50c0FzTGVmdC50ZXN0KHR5cGVzW2ldKSkge1xuICAgICAgICAgIHZhciBzdGFydCA9IGk7XG4gICAgICAgICAgZm9yICgrK2k7IGkgPCBsZW4gJiYgY291bnRzQXNMZWZ0LnRlc3QodHlwZXNbaV0pOyArK2kpIHt9XG4gICAgICAgICAgb3JkZXIucHVzaChuZXcgQmlkaVNwYW4oMCwgc3RhcnQsIGkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgcG9zID0gaSwgYXQgPSBvcmRlci5sZW5ndGg7XG4gICAgICAgICAgZm9yICgrK2k7IGkgPCBsZW4gJiYgdHlwZXNbaV0gIT0gXCJMXCI7ICsraSkge31cbiAgICAgICAgICBmb3IgKHZhciBqID0gcG9zOyBqIDwgaTspIHtcbiAgICAgICAgICAgIGlmIChjb3VudHNBc051bS50ZXN0KHR5cGVzW2pdKSkge1xuICAgICAgICAgICAgICBpZiAocG9zIDwgaikgb3JkZXIuc3BsaWNlKGF0LCAwLCBuZXcgQmlkaVNwYW4oMSwgcG9zLCBqKSk7XG4gICAgICAgICAgICAgIHZhciBuc3RhcnQgPSBqO1xuICAgICAgICAgICAgICBmb3IgKCsrajsgaiA8IGkgJiYgY291bnRzQXNOdW0udGVzdCh0eXBlc1tqXSk7ICsraikge31cbiAgICAgICAgICAgICAgb3JkZXIuc3BsaWNlKGF0LCAwLCBuZXcgQmlkaVNwYW4oMiwgbnN0YXJ0LCBqKSk7XG4gICAgICAgICAgICAgIHBvcyA9IGo7XG4gICAgICAgICAgICB9IGVsc2UgKytqO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocG9zIDwgaSkgb3JkZXIuc3BsaWNlKGF0LCAwLCBuZXcgQmlkaVNwYW4oMSwgcG9zLCBpKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChvcmRlclswXS5sZXZlbCA9PSAxICYmIChtID0gc3RyLm1hdGNoKC9eXFxzKy8pKSkge1xuICAgICAgICBvcmRlclswXS5mcm9tID0gbVswXS5sZW5ndGg7XG4gICAgICAgIG9yZGVyLnVuc2hpZnQobmV3IEJpZGlTcGFuKDAsIDAsIG1bMF0ubGVuZ3RoKSk7XG4gICAgICB9XG4gICAgICBpZiAobHN0KG9yZGVyKS5sZXZlbCA9PSAxICYmIChtID0gc3RyLm1hdGNoKC9cXHMrJC8pKSkge1xuICAgICAgICBsc3Qob3JkZXIpLnRvIC09IG1bMF0ubGVuZ3RoO1xuICAgICAgICBvcmRlci5wdXNoKG5ldyBCaWRpU3BhbigwLCBsZW4gLSBtWzBdLmxlbmd0aCwgbGVuKSk7XG4gICAgICB9XG4gICAgICBpZiAob3JkZXJbMF0ubGV2ZWwgPT0gMilcbiAgICAgICAgb3JkZXIudW5zaGlmdChuZXcgQmlkaVNwYW4oMSwgb3JkZXJbMF0udG8sIG9yZGVyWzBdLnRvKSk7XG4gICAgICBpZiAob3JkZXJbMF0ubGV2ZWwgIT0gbHN0KG9yZGVyKS5sZXZlbClcbiAgICAgICAgb3JkZXIucHVzaChuZXcgQmlkaVNwYW4ob3JkZXJbMF0ubGV2ZWwsIGxlbiwgbGVuKSk7XG5cbiAgICAgIHJldHVybiBvcmRlcjtcbiAgICB9O1xuICB9KSgpO1xuXG4gIC8vIFRIRSBFTkRcblxuICBDb2RlTWlycm9yLnZlcnNpb24gPSBcIjUu
23459OC4wXCI7XG5cbiAgcmV0dXJuIENvZGVNaXJyb3I7XG59KTtcbiIsIi8vIENvZGVNaXJyb3IsIGNvcHlyaWdodCAoYykgYnkgTWFyaWpuIEhhdmVyYmVrZSBhbmQgb3RoZXJzXG4vLyBEaXN0cmlidXRlZCB1bmRlciBhbiBNSVQgbGljZW5zZTogaHR0cDovL2NvZGVtaXJyb3IubmV0L0xJQ0VOU0VcblxuKGZ1bmN0aW9uKG1vZCkge1xuICBpZiAodHlwZW9mIGV4cG9ydHMgPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09IFwib2JqZWN0XCIpIC8vIENvbW1vbkpTXG4gICAgbW9kKHJlcXVpcmUoXCIuLi8uLi9saWIvY29kZW1pcnJvclwiKSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIC8vIEFNRFxuICAgIGRlZmluZShbXCIuLi8uLi9saWIvY29kZW1pcnJvclwiXSwgbW9kKTtcbiAgZWxzZSAvLyBQbGFpbiBicm93c2VyIGVudlxuICAgIG1vZChDb2RlTWlycm9yKTtcbn0pKGZ1bmN0aW9uKENvZGVNaXJyb3IpIHtcblwidXNlIHN0cmljdFwiO1xuXG5Db2RlTWlycm9yLmRlZmluZU1vZGUoXCJjbGlrZVwiLCBmdW5jdGlvbihjb25maWcsIHBhcnNlckNvbmZpZykge1xuICB2YXIgaW5kZW50VW5pdCA9IGNvbmZpZy5pbmRlbnRVbml0LFxuICAgICAgc3RhdGVtZW50SW5kZW50VW5pdCA9IHBhcnNlckNvbmZpZy5zdGF0ZW1lbnRJbmRlbnRVbml0IHx8IGluZGVudFVuaXQsXG4gICAgICBkb250QWxpZ25DYWxscyA9IHBhcnNlckNvbmZpZy5kb250QWxpZ25DYWxscyxcbiAgICAgIGtleXdvcmRzID0gcGFyc2VyQ29uZmlnLmtleXdvcmRzIHx8IHt9LFxuICAgICAgdHlwZXMgPSBwYXJzZXJDb25maWcudHlwZXMgfHwge30sXG4gICAgICBidWlsdGluID0gcGFyc2VyQ29uZmlnLmJ1aWx0aW4gfHwge30sXG4gICAgICBibG9ja0tleXdvcmRzID0gcGFyc2VyQ29uZmlnLmJsb2NrS2V5d29yZHMgfHwge30sXG4gICAgICBkZWZLZXl3b3JkcyA9IHBhcnNlckNvbmZpZy5kZWZLZXl3b3JkcyB8fCB7fSxcbiAgICAgIGF0b21zID0gcGFyc2VyQ29uZmlnLmF0b21zIHx8IHt9LFxuICAgICAgaG9va3MgPSBwYXJzZXJDb25maWcuaG9va3MgfHwge30sXG4gICAgICBtdWx0aUxpbmVTdHJpbmdzID0gcGFyc2VyQ29uZmlnLm11bHRpTGluZVN0cmluZ3MsXG4gICAgICBpbmRlbnRTdGF0ZW1lbnRzID0gcGFyc2VyQ29uZmlnLmluZGVudFN0YXRlbWVudHMgIT09IGZhbHNlLFxuICAgICAgaW5kZW50U3dpdGNoID0gcGFyc2VyQ29uZmlnLmluZGVudFN3aXRjaCAhPT0gZmFsc2UsXG4gICAgICBuYW1lc3BhY2VTZXBhcmF0b3IgPSBwYXJzZXJDb25maWcubmFtZXNwYWNlU2VwYXJhdG9yLFxuICAgICAgaXNQdW5jdHVhdGlvbkNoYXIgPSBwYXJzZXJDb25maWcuaXNQdW5jdHVhdGlvbkNoYXIgfHwgL1tcXFtcXF17fVxcKFxcKSw
234597XFw6XFwuXS8sXG4gICAgICBpc051bWJlckNoYXIgPSBwYXJzZXJDb25maWcuaXNOdW1iZXJDaGFyIHx8IC9cXGQvLFxuICAgICAgaXNPcGVyYXRvckNoYXIgPSBwYXJzZXJDb25maWcuaXNPcGVyYXRvckNoYXIgfHwgL1srXFwtKiYlPTw+IT98XFwvXS8sXG4gICAgICBlbmRTdGF0ZW1lbnQgPSBwYXJzZXJDb25maWcuZW5kU3RhdGVtZW50IHx8IC9eWzs6LF0kLztcblxuICB2YXIgY3VyUHVuYywgaXNEZWZLZXl3b3JkO1xuXG4gIGZ1bmN0aW9uIHRva2VuQmFzZShzdHJlYW0sIHN0YXRlKSB7XG4gICAgdmFyIGNoID0gc3RyZWFtLm5leHQoKTtcbiAgICBpZiAoaG9va3NbY2hdKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gaG9va3NbY2hdKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgaWYgKHJlc3VsdCAhPT0gZmFsc2UpIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIGlmIChjaCA9PSAnXCInIHx8IGNoID09IFwiJ1wiKSB7XG4gICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuU3RyaW5nKGNoKTtcbiAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG4gICAgaWYgKGlzUHVuY3R1YXRpb25DaGFyLnRlc3QoY2gpKSB7XG4gICAgICBjdXJQdW5jID0gY2g7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKGlzTnVtYmVyQ2hhci50ZXN0KGNoKSkge1xuICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwuXS8pO1xuICAgICAgcmV0dXJuIFwibnVtYmVyXCI7XG4gICAgfVxuICAgIGlmIChjaCA9PSBcIi9cIikge1xuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIqXCIpKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gdG9rZW5Db21tZW50O1xuICAgICAgICByZXR1cm4gdG9rZW5Db21tZW50KHN0cmVhbSwgc3RhdGUpO1xuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbS5lYXQoXCIvXCIpKSB7XG4gICAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICAgICAgcmV0dXJuIFwiY29tbWVudFwiO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaXNPcGVyYXRvckNoYXIudGVzdChjaCkpIHtcbiAgICAgIHN0cmVhbS5lYXRXaGlsZShpc09wZXJhdG9yQ2hhcik7XG4gICAgICByZXR1cm4gXCJvcGVyYXRvclwiO1xuICAgIH1cbiAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXFx4YTEtXFx1ZmZmZl0vKTtcbiAgICBpZiAobmFtZXNwYWNlU2VwYXJhdG9yKSB3aGlsZSAoc3RyZWFtLm1hdGNoKG5hbWVzcGFjZVNlcGFyYXRvcikpXG4gICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXFx4YTEtXFx1ZmZmZl0vKTtcblxuICAgIHZhciBjdXIgPSBzdHJlYW0uY3VycmVudCgpO1xuICAgIGlmIChjb250YWlucyhrZXl3b3JkcywgY3VyKSkge1xuICAgICAgaWYgKGNvbnRhaW5zKGJsb2NrS2V5d29yZHMsIGN1cikpIGN1clB1bmMgPSBcIm5ld3N0YXRlbWVudFwiO1xuICAgICAgaWYgKGNvbnRhaW5zKGRlZktleXdvcmRzLCBjdXIpKSBpc0RlZktleXdvcmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIFwia2V5d29yZFwiO1xuICAgIH1cbiAgICBpZiAoY29udGFpbnModHlwZXMsIGN1cikpIHJldHVybiBcInZhcmlhYmxlLTNcIjtcbiAgICBpZiAoY29udGFpbnMoYnVpbHRpbiwgY3VyKSkge1xuICAgICAgaWYgKGNvbnRhaW5zKGJsb2NrS2V5d29yZHMsIGN1cikpIGN1clB1bmMgPSBcIm5ld3N0YXRlbWVudFwiO1xuICAgICAgcmV0dXJuIFwiYnVpbHRpblwiO1xuICAgIH1cbiAgICBpZiAoY29udGFpbnMoYXRvbXMsIGN1cikpIHJldHVybiBcImF0b21cIjtcbiAgICByZXR1cm4gXCJ2YXJpYWJsZVwiO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9rZW5TdHJpbmcocXVvdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgdmFyIGVzY2FwZWQgPSBmYWxzZSwgbmV4dCwgZW5kID0gZmFsc2U7XG4gICAgICB3aGlsZSAoKG5leHQgPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICAgIGlmIChuZXh0ID09IHF1b3RlICYmICFlc2NhcGVkKSB7ZW5kID0gdHJ1ZTsgYnJlYWs7fVxuICAgICAgICBlc2NhcGVkID0gIWVzY2FwZWQgJiYgbmV4dCA9PSBcIlxcXFxcIjtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgfHwgIShlc2NhcGVkIHx8IG11bHRpTGluZVN0cmluZ3MpKVxuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG51bGw7XG4gICAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gdG9rZW5Db21tZW50KHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgbWF5YmVFbmQgPSBmYWxzZSwgY2g7XG4gICAgd2hpbGUgKGNoID0gc3RyZWFtLm5leHQoKSkge1xuICAgICAgaWYgKGNoID09IFwiL1wiICYmIG1heWJlRW5kKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBtYXliZUVuZCA9IChjaCA9PSBcIipcIik7XG4gICAgfVxuICAgIHJldHVybiBcImNvbW1lbnRcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIENvbnRleHQoaW5kZW50ZWQsIGNvbHVtbiwgdHlwZSwgYWxpZ24sIHByZXYpIHtcbiAgICB0aGlzLmluZGVudGVkID0gaW5kZW50ZWQ7XG4gICAgdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLmFsaWduID0gYWxpZ247XG4gICAgdGhpcy5wcmV2ID0gcHJldjtcbiAgfVxuICBmdW5jdGlvbiBpc1N0YXRlbWVudCh0eXBlKSB7XG4gICAgcmV0dXJuIHR5cGUgPT0gXCJzdGF0ZW1lbnRcIiB8fCB0eXBlID09IFwic3dpdGNoc3RhdGVtZW50XCIgfHwgdHlwZSA9PSBcIm5hbWVzcGFjZVwiO1xuICB9XG4gIGZ1bmN0aW9uIHB1c2hDb250ZXh0KHN0YXRlLCBjb2wsIHR5cGUpIHtcbiAgICB2YXIgaW5kZW50ID0gc3RhdGUuaW5kZW50ZWQ7XG4gICAgaWYgKHN0YXRlLmNvbnRleHQgJiYgaXNTdGF0ZW1lbnQoc3RhdGUuY29udGV4dC50eXBlKSAmJiAhaXNTdGF0ZW1lbnQodHlwZSkpXG4gICAgICBpbmRlbnQgPSBzdGF0ZS5jb250ZXh0LmluZGVudGVkO1xuICAgIHJldHVybiBzdGF0ZS5jb250ZXh0ID0gbmV3IENvbnRleHQoaW5kZW50LCBjb2wsIHR5cGUsIG51bGwsIHN0YXRlLmNvbnRleHQpO1xuICB9XG4gIGZ1bmN0aW9uIHBvcENvbnRleHQoc3RhdGUpIHtcbiAgICB2YXIgdCA9IHN0YXRlLmNvbnRleHQudHlwZTtcbiAgICBpZiAodCA9PSBcIilcIiB8fCB0ID09IFwiXVwiIHx8IHQgPT0gXCJ9XCIpXG4gICAgICBzdGF0ZS5pbmRlbnRlZCA9IHN0YXRlLmNvbnRleHQuaW5kZW50ZWQ7XG4gICAgcmV0dXJuIHN0YXRlLmNvbnRleHQgPSBzdGF0ZS5jb250ZXh0LnByZXY7XG4gIH1cblxuICBmdW5jdGlvbiB0eXBlQmVmb3JlKHN0cmVhbSwgc3Rh
23459dGUpIHtcbiAgICBpZiAoc3RhdGUucHJldlRva2VuID09IFwidmFyaWFibGVcIiB8fCBzdGF0ZS5wcmV2VG9rZW4gPT0gXCJ2YXJpYWJsZS0zXCIpIHJldHVybiB0cnVlO1xuICAgIGlmICgvXFxTKD86W14tIF0+fFsqXFxdXSlcXHMqJHxcXCokLy50ZXN0KHN0cmVhbS5zdHJpbmcuc2xpY2UoMCwgc3RyZWFtLnN0YXJ0KSkpIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNUb3BTY29wZShjb250ZXh0KSB7XG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKCFjb250ZXh0IHx8IGNvbnRleHQudHlwZSA9PSBcInRvcFwiKSByZXR1cm4gdHJ1ZTtcbiAgICAgIGlmIChjb250ZXh0LnR5cGUgPT0gXCJ9XCIgJiYgY29udGV4dC5wcmV2LnR5cGUgIT0gXCJuYW1lc3BhY2VcIikgcmV0dXJuIGZhbHNlO1xuICAgICAgY29udGV4dCA9IGNvbnRleHQucHJldjtcbiAgICB9XG4gIH1cblxuICAvLyBJbnRlcmZhY2VcblxuICByZXR1cm4ge1xuICAgIHN0YXJ0U3RhdGU6IGZ1bmN0aW9uKGJhc2Vjb2x1bW4pIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRva2VuaXplOiBudWxsLFxuICAgICAgICBjb250ZXh0OiBuZXcgQ29udGV4dCgoYmFzZWNvbHVtbiB8fCAwKSAtIGluZGVudFVuaXQsIDAsIFwidG9wXCIsIGZhbHNlKSxcbiAgICAgICAgaW5kZW50ZWQ6IDAsXG4gICAgICAgIHN0YXJ0T2ZMaW5lOiB0cnVlLFxuICAgICAgICBwcmV2VG9rZW46IG51bGxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICB2Y
23459XIgY3R4ID0gc3RhdGUuY29udGV4dDtcbiAgICAgIGlmIChzdHJlYW0uc29sKCkpIHtcbiAgICAgICAgaWYgKGN0eC5hbGlnbiA9PSBudWxsKSBjdHguYWxpZ24gPSBmYWxzZTtcbiAgICAgICAgc3RhdGUuaW5kZW50ZWQgPSBzdHJlYW0uaW5kZW50YXRpb24oKTtcbiAgICAgICAgc3RhdGUuc3RhcnRPZkxpbmUgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbS5lYXRTcGFjZSgpKSByZXR1cm4gbnVsbDtcbiAgICAgIGN1clB1bmMgPSBpc0RlZktleXdvcmQgPSBudWxsO1xuICAgICAgdmFyIHN0eWxlID0gKHN0YXRlLnRva2VuaXplIHx8IHRva2VuQmFzZSkoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICBpZiAoc3R5bGUgPT0gXCJjb21tZW50XCIgfHwgc3R5bGUgPT0gXCJtZXRhXCIpIHJldHVybiBzdHlsZTtcbiAgICAgIGlmIChjdHguYWxpZ24gPT0gbnVsbCkgY3R4LmFsaWduID0gdHJ1ZTtcblxuICAgICAgaWYgKGVuZFN0YXRlbWVudC50ZXN0KGN1clB1bmMpKSB3aGlsZSAoaXNTdGF0ZW1lbnQoc3RhdGUuY29udGV4dC50eXBlKSkgcG9wQ29udGV4dChzdGF0ZSk7XG4gICAgICBlbHNlIGlmIChjdXJQdW5jID09IFwie1wiKSBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLmNvbHVtbigpLCBcIn1cIik7XG4gICAgICBlbHNlIGlmIChjdXJQdW5jID09IFwiW1wiKSBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLmNvbHVtbigpLCBcIl1cIik7XG4gICAgICBlbHNlIGlmIChjdXJQdW5jID09IFwiKFwiKSBwdXNoQ29udGV4dChzdGF0ZSwgc3RyZWFtLmNvbHVtbigpLCBcIilcIik7XG4gICAgICBlbHNlIGlmIChjdXJQdW5jID09IFwifVwiKSB7XG4gICAgICAgIHdoaWxlIChpc1N0YXRlbWVudChjdHgudHlwZSkpIGN0eCA9IHBvcENvbnRleHQoc3RhdGUpO1xuICAgICAgICBpZiAoY3R4LnR5cGUgPT0gXCJ9XCIpIGN0eCA9IHBvcENvbnRleHQoc3RhdGUpO1xuICAgICAgICB3aGlsZSAoaXNTdGF0ZW1lbnQoY3R4LnR5cGUpKSBjdHggPSBwb3BDb250ZXh0KHN0YXRlKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGN1clB1bmMgPT0gY3R4LnR5cGUpIHBvcENvbnRleHQoc3RhdGUpO1xuICAgICAgZWxzZSBpZiAoaW5kZW50U3RhdGVtZW50cyAmJlxuICAgICAgICAgICAgICAgKCgoY3R4LnR5cGUgPT0gXCJ9XCIgfHwgY3R4LnR5cGUgPT0gXCJ0b3BcIikgJiYgY3VyUHVuYyAhPSBcIjtcIikgfHxcbiAgICAgICAgICAgICAgICAoaXNTdGF0ZW1lbnQoY3R4LnR5cGUpICYmIGN1clB1bmMgPT0gXCJuZXdzdGF0ZW1lbnRcIikpKSB7XG4gICAgICAgIHZhciB0eXBlID0gXCJzdGF0ZW1lbnRcIjtcbiAgICAgICAgaWYgKGN1clB1bmMgPT0gXCJuZXdzdGF0ZW1lbnRcIiAmJiBpbmRlbnRTd2l0Y2ggJiYgc3RyZWFtLmN1cnJlbnQoKSA9PSBcInN3aXRjaFwiKVxuICAgICAgICAgIHR5cGUgPSBcInN3aXRjaHN0YXRlbWVudFwiO1xuICAgICAgICBlbHNlIGlmIChzdHlsZSA9PSBcImtleXdvcmRcIiAmJiBzdHJlYW0uY3VycmVudCgpID09IFwibmFtZXNwYWNlXCIpXG4gICAgICAgICAgdHlwZSA9IFwibmFtZXNwYWNlXCI7XG4gICAgICAgIHB1c2hDb250ZXh0KHN0YXRlLCBzdHJlYW0uY29sdW1uKCksIHR5cGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3R5bGUgPT0gXCJ2YXJpYWJsZVwiICYmXG4gICAgICAgICAgKChzdGF0ZS5wcmV2VG9rZW4gPT0gXCJkZWZcIiB8fFxuICAgICAgICAgICAgKHBhcnNlckNvbmZpZy50eXBlRmlyc3REZWZpbml0aW9ucyAmJiB0eXBlQmVmb3JlKHN0cmVhbSwgc3RhdGUpICYmXG4gICAgICAgICAgICAgaXNUb3BTY29wZShzdGF0ZS5jb250ZXh0KSAmJiBzdHJlYW0ubWF0Y2goL15cXHMqXFwoLywgZmFsc2UpKSkpKVxuICAgICAgICBzdHlsZSA9IFwiZGVmXCI7XG5cbiAgICAgIGlmIChob29rcy50b2tlbikge1xuICAgICAgICB2Y
23459XIgcmVzdWx0ID0gaG9va3MudG9rZW4oc3RyZWFtLCBzdGF0ZSwgc3R5bGUpO1xuICAgICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHN0eWxlID0gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBpZiAoc3R5bGUgPT0gXCJkZWZcIiAmJiBwYXJzZXJDb25maWcuc3R5bGVEZWZzID09PSBmYWxzZSkgc3R5bGUgPSBcInZhcmlhYmxlXCI7XG5cbiAgICAgIHN0YXRlLnN0YXJ0T2ZMaW5lID0gZmFsc2U7XG4gICAgICBzdGF0ZS5wcmV2VG9rZW4gPSBpc0RlZktleXdvcmQgPyBcImRlZlwiIDogc3R5bGUgfHwgY3VyUHVuYztcbiAgICAgIHJldHVybiBzdHlsZTtcbiAgICB9LFxuXG4gICAgaW5kZW50OiBmdW5jdGlvbihzdGF0ZSwgdGV4dEFmdGVyKSB7XG4gICAgICBpZiAoc3RhdGUudG9rZW5pemUgIT0gdG9rZW5CYXNlICYmIHN0YXRlLnRva2VuaXplICE9IG51bGwpIHJldHVybiBDb2RlTWlycm9yLlBhc3M7XG4gICAgICB2YXIgY3R4ID0gc3RhdGUuY29udGV4dCwgZmlyc3RDaGFyID0gdGV4dEFmdGVyICYmIHRleHRBZnRlci5jaGFyQXQoMCk7XG4gICAgICBpZiAoaXNTdGF0ZW1lbnQoY3R4LnR5cGUpICYmIGZpcnN0Q2hhciA9PSBcIn1cIikgY3R4ID0gY3R4LnByZXY7XG4gICAgICBpZiAoaG9va3MuaW5kZW50KSB7XG4gICAgICAgIHZhciBob29rID0gaG9va3MuaW5kZW50KHN0YXRlLCBjdHgsIHRleHRBZnRlcik7XG4gICAgICAgIGlmICh0eXBlb2YgaG9vayA9PSBcIm51bWJlclwiKSByZXR1cm4gaG9va1xuICAgICAgfVxuICAgICAgdmFyIGNsb3NpbmcgPSBmaXJzdENoYXIgPT0gY3R4LnR5cGU7XG4gICAgICB2Y
23459XIgc3dpdGNoQmxvY2sgPSBjdHgucHJldiAmJiBjdHgucHJldi50eXBlID09IFwic3dpdGNoc3RhdGVtZW50XCI7XG4gICAgICBpZiAoaXNTdGF0ZW1lbnQoY3R4LnR5cGUpKVxuICAgICAgICByZXR1cm4gY3R4LmluZGVudGVkICsgKGZpcnN0Q2hhciA9PSBcIntcIiA/IDAgOiBzdGF0ZW1lbnRJbmRlbnRVbml0KTtcbiAgICAgIGlmIChjdHguYWxpZ24gJiYgKCFkb250QWxpZ25DYWxscyB8fCBjdHgudHlwZSAhPSBcIilcIikpXG4gICAgICAgIHJldHVybiBjdHguY29sdW1uICsgKGNsb3NpbmcgPyAwIDogMSk7XG4gICAgICBpZiAoY3R4LnR5cGUgPT0gXCIpXCIgJiYgIWNsb3NpbmcpXG4gICAgICAgIHJldHVybiBjdHguaW5kZW50ZWQgKyBzdGF0ZW1lbnRJbmRlbnRVbml0O1xuXG4gICAgICByZXR1cm4gY3R4LmluZGVudGVkICsgKGNsb3NpbmcgPyAwIDogaW5kZW50VW5pdCkgK1xuICAgICAgICAoIWNsb3NpbmcgJiYgc3dpdGNoQmxvY2sgJiYgIS9eKD86Y2FzZXxkZWZhdWx0KVxcYi8udGVzdCh0ZXh0QWZ0ZXIpID8gaW5kZW50VW5pdCA6IDApO1xuICAgIH0sXG5cbiAgICBlbGVjdHJpY0lucHV0OiBpbmRlbnRTd2l0Y2ggPyAvXlxccyooPzpjYXNlIC4qPzp8ZGVmYXVsdDp8XFx7XFx9P3xcXH0pJC8gOiAvXlxccypbe31dJC8sXG4gICAgYmxvY2tDb21tZW50U3RhcnQ6IFwiLypcIixcbiAgICBibG9ja0NvbW1lbnRFbmQ6IFwiKi9cIixcbiAgICBsaW5lQ29tbWVudDogXCIvL1wiLFxuICAgIGZvbGQ6IFwiYnJhY2VcIlxuICB9O1xufSk7XG5cbiAgZnVuY3Rpb24gd29yZHMoc3RyKSB7XG4gICAgdmFyIG9iaiA9IHt9LCB3b3JkcyA9IHN0ci5zcGxpdChcIiBcIik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB3b3Jkcy5sZW5ndGg7ICsraSkgb2JqW3dvcmRzW2ldXSA9IHRydWU7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuICBmdW5jdGlvbiBjb250YWlucyh3b3Jkcywgd29yZCkge1xuICAgIGlmICh0eXBlb2Ygd29yZHMgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgcmV0dXJuIHdvcmRzKHdvcmQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gd29yZHMucHJvcGVydHlJc0VudW1lcmFibGUod29yZCk7XG4gICAgfVxuICB9XG4gIHZhciBjS2V5d29yZHMgPSBcImF1dG8gaWYgYnJlYWsgY2FzZSByZWdpc3RlciBjb250aW51ZSByZXR1cm4gZGVmYXVsdCBkbyBzaXplb2YgXCIgK1xuICAgIFwic3RhdGljIGVsc2Ugc3RydWN0IHN3aXRjaCBleHRlcm4gdHlwZWRlZiBmbG9hdCB1bmlvbiBmb3IgXCIgK1xuICAgIFwiZ290byB3aGlsZSBlbnVtIGNvbnN0IHZvbGF0aWxlXCI7XG4gIHZhciBjVHlwZXMgPSBcImludCBsb25nIGNoYXIgc2hvcnQgZG91YmxlIGZsb2F0IHVuc2lnbmVkIHNpZ25lZCB2b2lkIHNpemVfdCBwdHJkaWZmX3RcIjtcblxuICBmdW5jdGlvbiBjcHBIb29rKHN0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAoIXN0YXRlLnN0YXJ0T2ZMaW5lKSByZXR1cm4gZmFsc2U7XG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKHN0cmVhbS5za2lwVG8oXCJcXFxcXCIpKSB7XG4gICAgICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgICAgIGlmIChzdHJlYW0uZW9sKCkpIHtcbiAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IGNwcEhvb2s7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFwibWV0YVwiO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9pbnRlckhvb2soX3N0cmVhbSwgc3RhdGUpIHtcbiAgICBpZiAoc3RhdGUucHJldlRva2VuID09IFwidmFyaWFibGUtM1wiKSByZXR1cm4gXCJ2YXJpYWJsZS0zXCI7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gY3BwMTRMaXRlcmFsKHN0cmVhbSkge1xuICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcLiddLyk7XG4gICAgcmV0dXJuIFwibnVtYmVyXCI7XG4gIH1cblxuICBmdW5jdGlvbiBjcHAxMVN0cmluZ0hvb2soc3RyZWFtLCBzdGF0ZSkge1xuICAgIHN0cmVhbS5iYWNrVXAoMSk7XG4gICAgLy8gUmF3IHN0cmluZ3MuXG4gICAgaWYgKHN0cmVhbS5tYXRjaCgvKFJ8dThSfHVSfFVSfExSKS8pKSB7XG4gICAgICB2Y
23459XIgbWF0Y2ggPSBzdHJlYW0ubWF0Y2goL1wiKFteXFxzXFxcXCgpXXswLDE2fSlcXCgvKTtcbiAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgc3RhdGUuY3BwMTFSYXdTdHJpbmdEZWxpbSA9IG1hdGNoWzFdO1xuICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlblJhd1N0cmluZztcbiAgICAgIHJldHVybiB0b2tlblJhd1N0cmluZyhzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG4gICAgLy8gVW5pY29kZSBzdHJpbmdzL2NoYXJzLlxuICAgIGlmIChzdHJlYW0ubWF0Y2goLyh1OHx1fFV8TCkvKSkge1xuICAgICAgaWYgKHN0cmVhbS5tYXRjaCgvW1wiJ10vLCAvKiBlYXQgKi8gZmFsc2UpKSB7XG4gICAgICAgIHJldHVybiBcInN0cmluZ1wiO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBJZ25vcmUgdGhpcyBob29rLlxuICAgIHN0cmVhbS5uZXh0KCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gY3BwTG9va3NMaWtlQ29uc3RydWN0b3Iod29yZCkge1xuICAgIHZhciBsYXN0VHdvID0gLyhcXHcrKTo6KFxcdyspJC8uZXhlYyh3b3JkKTtcbiAgICByZXR1cm4gbGFzdFR3byAmJiBsYXN0VHdvWzFdID09IGxhc3RUd29bMl07XG4gIH1cblxuICAvLyBDIy1zdHlsZSBzdHJpbmdzIHdoZXJlIFwiXCIgZXNjYXBlcyBhIHF1b3RlLlxuICBmdW5jdGlvbiB0b2tlbkF0U3RyaW5nKHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgbmV4dDtcbiAgICB3aGlsZSAoKG5leHQgPSBzdHJlYW0ubmV4dCgpKSAhPSBudWxsKSB7XG4gICAgICBpZiAobmV4dCA9PSAnXCInICYmICFzdHJlYW0uZWF0KCdcIicpKSB7XG4gICAgICAgIHN0YXRlLnRva2VuaXplID0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBcInN0cmluZ1wiO1xuICB9XG5cbiAgLy8gQysrMTEgcmF3IHN0cmluZyBsaXRlcmFsIGlzIDxwcmVmaXg+XCI8ZGVsaW0+KCBhbnl0aGluZyApPGRlbGltPlwiLCB3aGVyZVxuICAvLyA8ZGVsaW0+IGNhbiBiZSBhIHN0cmluZyB1cCB0byAxNiBjaGFyYWN0ZXJzIGxvbmcuXG4gIGZ1bmN0aW9uIHRva2VuUmF3U3RyaW5nKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAvLyBFc2NhcGUgY2hhcmFjdGVycyB0aGF0IGhhdmUgc3BlY2lhbCByZWdleCBtZWFuaW5ncy5cbiAgICB2YXIgZGVsaW0gPSBzdGF0ZS5jcHAxMVJhd1N0cmluZ0RlbGltLnJlcGxhY2UoL1teXFx3XFxzXS9nLCAnXFxcXCQmJyk7XG4gICAgdmFyIG1hdGNoID0gc3RyZWFtLm1hdGNoKG5ldyBSZWdFeHAoXCIuKj9cXFxcKVwiICsgZGVsaW0gKyAnXCInKSk7XG4gICAgaWYgKG1hdGNoKVxuICAgICAgc3RhdGUudG9rZW5pemUgPSBudWxsO1xuICAgIGVsc2VcbiAgICAgIHN0cmVhbS5za2lwVG9FbmQoKTtcbiAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlZihtaW1lcywgbW9kZSkge1xuICAgIGlmICh0eXBlb2YgbWltZXMgPT0gXCJzdHJpbmdcIikgbWltZXMgPSBbbWltZXNdO1xuICAgIHZhciB3b3JkcyA9IFtdO1xuICAgIGZ1bmN0aW9uIGFkZChvYmopIHtcbiAgICAgIGlmIChvYmopIGZvciAodmFyIHByb3AgaW4gb2JqKSBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApKVxuICAgICAgICB3b3Jkcy5wdXNoKHByb3ApO1xuICAgIH1cbiAgICBhZGQobW9kZS5rZXl3b3Jkcyk7XG4gICAgYWRkKG1vZGUudHlwZXMpO1xuICAgIGFkZChtb2RlLmJ1aWx0aW4pO1xuICAgIGFkZChtb2RlLmF0b21zKTtcbiAgICBpZiAod29yZHMubGVuZ3RoKSB7XG4gICAgICBtb2RlLmhlbHBlclR5cGUgPSBtaW1lc1swXTtcbiAgICAgIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJoaW50V29yZHNcIiwgbWltZXNbMF0sIHdvcmRzKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pbWVzLmxlbmd0aDsgKytpKVxuICAgICAgQ29kZU1pcnJvci5kZWZpbmVNSU1FKG1pbWVzW2ldLCBtb2RlKTtcbiAgfVxuXG4gIGRlZihbXCJ0ZXh0L3gtY3NyY1wiLCBcInRleHQveC1jXCIsIFwidGV4dC94LWNoZHJcIl0sIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKGNLZXl3b3JkcyksXG4gICAgdHlwZXM6IHdvcmRzKGNUeXBlcyArIFwiIGJvb2wgX0NvbXBsZXggX0Jvb2wgZmxvYXRfdCBkb3VibGVfdCBpbnRwdHJfdCBpbnRtYXhfdCBcIiArXG4gICAgICAgICAgICAgICAgIFwiaW50OF90IGludDE2X3QgaW50MzJfdCBpbnQ2NF90IHVpbnRwdHJfdCB1aW50bWF4X3QgdWludDhfdCB1aW50MTZfdCBcIiArXG4gICAgICAgICAgICAgICAgIFwidWludDMyX3QgdWludDY0X3RcIiksXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXNlIGRvIGVsc2UgZm9yIGlmIHN3aXRjaCB3aGlsZSBzdHJ1Y3RcIiksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKFwic3RydWN0XCIpLFxuICAgIHR5cGVGaXJzdERlZmluaXRpb25zOiB0cnVlLFxuICAgIGF0b21zOiB3b3JkcyhcIm51bGwgdHJ1ZSBmYWxzZVwiKSxcbiAgICBob29rczoge1wiI1wiOiBjcHBIb29rLCBcIipcIjogcG9pbnRlckhvb2t9LFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW5jbHVkZVwiXX1cbiAgfSk7XG5cbiAgZGVmKFtcInRleHQveC1jKytzcmNcIiwgXCJ0ZXh0L3gtYysraGRyXCJdLCB7XG4gICAgbmFtZTogXCJjbGlrZVwiLFxuICAgIGtleXdvcmRzOiB3b3JkcyhjS2V5d29yZHMgKyBcIiBhc20gZHluYW1pY19jYXN0IG5hbWVzcGFjZSByZWludGVycHJldF9jYXN0IHRyeSBleHBsaWNpdCBuZXcgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInN0YXRpY19jYXN0IHR5cGVpZCBjYXRjaCBvcGVyYXRvciB0ZW1wbGF0ZSB0eXBlbmFtZSBjbGFzcyBmcmllbmQgcHJpdmF0ZSBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwidGhpcyB1c2luZyBjb25zdF9jYXN0IGlubGluZSBwdWJsaWMgdGhyb3cgdmlydHVhbCBkZWxldGUgbXV0YWJsZSBwcm90ZWN0ZWQgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImFsaWduYXMgYWxpZ25vZiBjb25zdGV4cHIgZGVjbHR5cGUgbnVsbHB0ciBub2V4Y2VwdCB0aHJlYWRfbG9jYWwgZmluYWwgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInN0YXRpY19hc3NlcnQgb3ZlcnJpZGVcIiksXG4gICAgdHlwZXM6IHdvcmRzKGNUeXBlcyArIFwiIGJvb2wgd2NoYXJfdFwiKSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImNhdGNoIGNsYXNzIGRvIGVsc2UgZmluYWxseSBmb3IgaWYgc3RydWN0IHN3aXRjaCB0cnkgd2hpbGVcIiksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKFwiY2xhc3MgbmFtZXNwYWNlIHN0cnVjdCBlbnVtIHVuaW9uXCIpLFxuICAgIHR5cGVGaXJzdERlZmluaXRpb25zOiB0cnVlLFxuICAgIGF0b21zOiB3b3JkcyhcInRydWUgZmFsc2UgbnVsbFwiKSxcbiAgICBob29rczoge1xuICAgICAgXCIjXCI6IGNwcEhvb2ssXG4gICAgICBcIipcIjogcG9pbnRlckhvb2ssXG4gICAgICBcInVcIjogY3BwMTFTdHJpbmdIb29rLF
23459xuICAgICAgXCJVXCI6IGNwcDExU3RyaW5nSG9vayxcbiAgICAgIFwiTFwiOiBjcHAxMVN0cmluZ0hvb2ssXG4gICAgICBcIlJcIjogY3BwMTFTdHJpbmdIb29rLFxuICAgICAgXCIwXCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiMVwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjJcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCIzXCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiNFwiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjVcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI2XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIFwiN1wiOiBjcHAxNExpdGVyYWwsXG4gICAgICBcIjhcIjogY3BwMTRMaXRlcmFsLFxuICAgICAgXCI5XCI6IGNwcDE0TGl0ZXJhbCxcbiAgICAgIHRva2VuOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlLCBzdHlsZSkge1xuICAgICAgICBpZiAoc3R5bGUgPT0gXCJ2YXJpYWJsZVwiICYmIHN0cmVhbS5wZWVrKCkgPT0gXCIoXCIgJiZcbiAgICAgICAgICAgIChzdGF0ZS5wcmV2VG9rZW4gPT0gXCI7XCIgfHwgc3RhdGUucHJldlRva2VuID09IG51bGwgfHxcbiAgICAgICAgICAgICBzdGF0ZS5wcmV2VG9rZW4gPT0gXCJ9XCIpICYmXG4gICAgICAgICAgICBjcHBMb29rc0xpa2VDb25zdHJ1Y3RvcihzdHJlYW0uY3VycmVudCgpKSlcbiAgICAgICAgICByZXR1cm4gXCJkZWZcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIG5hbWVzcGFjZVNlcGFyYXRvcjogXCI6OlwiLFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW5jbHVkZVwiXX1cbiAgfSk7XG5cbiAgZGVmKFwidGV4dC94LWphdmFcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJhYnN0cmFjdCBhc3NlcnQgYnJlYWsgY2FzZSBjYXRjaCBjbGFzcyBjb25zdCBjb250aW51ZSBkZWZhdWx0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJkbyBlbHNlIGVudW0gZXh0ZW5kcyBmaW5hbCBmaW5hbGx5IGZsb2F0IGZvciBnb3RvIGlmIGltcGxlbWVudHMgaW1wb3J0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJpbnN0YW5jZW9mIGludGVyZmFjZSBuYXRpdmUgbmV3IHBhY2thZ2UgcHJpdmF0ZSBwcm90ZWN0ZWQgcHVibGljIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJyZXR1cm4gc3RhdGljIHN0cmljdGZwIHN1cGVyIHN3aXRjaCBzeW5jaHJvbml6ZWQgdGhpcyB0aHJvdyB0aHJvd3MgdHJhbnNpZW50IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJ0cnkgdm9sYXRpbGUgd2hpbGVcIiksXG4gICAgdHlwZXM6IHdvcmRzKFwiYnl0ZSBzaG9ydCBpbnQgbG9uZyBmbG9hdCBkb3VibGUgYm9vbGVhbiBjaGFyIHZvaWQgQm9vbGVhbiBCeXRlIENoYXJhY3RlciBEb3VibGUgRmxvYXQgXCIgK1xuICAgICAgICAgICAgICAgICBcIkludGVnZXIgTG9uZyBOdW1iZXIgT2JqZWN0IFNob3J0IFN0cmluZyBTdHJpbmdCdWZmZXIgU3RyaW5nQnVpbGRlciBWb2lkXCIpLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKFwiY2F0Y2ggY2xhc3MgZG8gZWxzZSBmaW5hbGx5IGZvciBpZiBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIGludGVyZmFjZSBwYWNrYWdlIGVudW1cIiksXG4gICAgdHlwZUZpcnN0RGVmaW5pdGlvbnM6IHRydWUsXG4gICAgYXRvbXM6IHdvcmRzKFwidHJ1ZSBmYWxzZSBudWxsXCIpLFxuICAgIGVuZFN0YXRlbWVudDogL15bOzpdJC8sXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX10vKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfVxuICAgIH0sXG4gICAgbW9kZVByb3BzOiB7Zm9sZDogW1wiYnJhY2VcIiwgXCJpbXBvcnRcIl19XG4gIH0pO1xuXG4gIGRlZihcInRleHQveC1jc2hhcnBcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJhYnN0cmFjdCBhcyBhc3luYyBhd2FpdCBiYXNlIGJyZWFrIGNhc2UgY2F0Y2ggY2hlY2tlZCBjbGFzcyBjb25zdCBjb250aW51ZVwiICtcbiAgICAgICAgICAgICAgICAgICAgXCIgZGVmYXVsdCBkZWxlZ2F0ZSBkbyBlbHNlIGVudW0gZXZlbnQgZXhwbGljaXQgZXh0ZXJuIGZpbmFsbHkgZml4ZWQgZm9yXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiBmb3JlYWNoIGdvdG8gaWYgaW1wbGljaXQgaW4gaW50ZXJmYWNlIGludGVybmFsIGlzIGxvY2sgbmFtZXNwYWNlIG5ld1wiICtcbiAgICAgICAgICAgICAgICAgICAgXCIgb3BlcmF0b3Igb3V0IG92ZXJyaWRlIHBhcmFtcyBwcml2YXRlIHByb3RlY3RlZCBwdWJsaWMgcmVhZG9ubHkgcmVmIHJldHVybiBzZWFsZWRcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIHNpemVvZiBzdGFja2FsbG9jIHN0YXRpYyBzdHJ1Y3Qgc3dpdGNoIHRoaXMgdGhyb3cgdHJ5IHR5cGVvZiB1bmNoZWNrZWRcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIHVuc2FmZSB1c2luZyB2aXJ0dWFsIHZvaWQgdm9sYXRpbGUgd2hpbGUgYWRkIGFsaWFzIGFzY2VuZGluZyBkZXNjZW5kaW5nIGR5bmFtaWMgZnJvbSBnZXRcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIGdsb2JhbCBncm91cCBpbnRvIGpvaW4gbGV0IG9yZGVyYnkgcGFydGlhbCByZW1vdmUgc2VsZWN0IHNldCB2YWx1ZSB2YXIgeWllbGRcIiksXG4gICAgdHlwZXM6IHdvcmRzKFwiQWN0aW9uIEJvb2xlYW4gQnl0ZSBDaGFyIERhdGVUaW1lIERhdGVUaW1lT2Zmc2V0IERlY2ltYWwgRG91YmxlIEZ1bmNcIiArXG4gICAgICAgICAgICAgICAgIFwiIEd1aWQgSW50MTYgSW50MzIgSW50NjQgT2JqZWN0IFNCeXRlIFNpbmdsZSBTdHJpbmcgVGFzayBUaW1lU3BhbiBVSW50MTYgVUludDMyXCIgK1xuICAgICAgICAgICAgICAgICBcIiBVSW50NjQgYm9vbCBieXRlIGNoYXIgZGVjaW1hbCBkb3VibGUgc2hvcnQgaW50IGxvbmcgb2JqZWN0XCIgICtcbiAgICAgICAgICAgICAgICAgXCIgc2J5dGUgZmxvYXQgc3RyaW5nIHVzaG9ydCB1aW50IHVsb25nXCIpLFxuICAgIGJsb2NrS2V5d29yZHM6IHdvcmRzKFwiY2F0Y2ggY2xhc3MgZG8gZWxzZSBmaW5hbGx5IGZvciBmb3JlYWNoIGlmIHN0cnVjdCBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIGludGVyZmFjZSBuYW1lc3BhY2Ugc3RydWN0IHZhclwiKSxcbiAgICB0eX
23459BlRmlyc3REZWZpbml0aW9uczogdHJ1ZSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIG51bGxcIiksXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0sIHN0YXRlKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZWF0KCdcIicpKSB7XG4gICAgICAgICAgc3RhdGUudG9rZW5pemUgPSB0b2tlbkF0U3RyaW5nO1xuICAgICAgICAgIHJldHVybiB0b2tlbkF0U3RyaW5nKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgICB9XG4gICAgICAgIHN0cmVhbS5lYXRXaGlsZSgvW1xcd1xcJF9dLyk7XG4gICAgICAgIHJldHVybiBcIm1ldGFcIjtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIHRva2VuVHJpcGxlU3RyaW5nKHN0cmVhbSwgc3RhdGUpIHtcbiAgICB2YXIgZXNjYXBlZCA9IGZhbHNlO1xuICAgIHdoaWxlICghc3RyZWFtLmVvbCgpKSB7XG4gICAgICBpZiAoIWVzY2FwZWQgJiYgc3RyZWFtLm1hdGNoKCdcIlwiXCInKSkge1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG51bGw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZXNjYXBlZCA9IHN0cmVhbS5uZXh0KCkgPT0gXCJcXFxcXCIgJiYgIWVzY2FwZWQ7XG4gICAgfVxuICAgIHJldHVybiBcInN0cmluZ1wiO1xuICB9XG5cbiAgZGVmKFwidGV4dC94LXNjYWxhXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFxuXG4gICAgICAvKiBzY2FsYSAqL1xuICAgICAgXCJhYnN0cmFjdCBjYXNlIGNhdGNoIGNsYXNzIGRlZiBkbyBlbHNlIGV4dGVuZHMgZmluYWwgZmluYWxseSBmb3IgZm9yU29tZSBpZiBcIiArXG4gICAgICBcImltcGxpY2l0IGltcG9ydCBsYXp5IG1hdGNoIG5ldyBudWxsIG9iamVjdCBvdmVycmlkZSBwYWNrYWdlIHByaXZhdGUgcHJvdGVjdGVkIHJldHVybiBcIiArXG4gICAgICBcInNlYWxlZCBzdXBlciB0aGlzIHRocm93IHRyYWl0IHRyeSB0eXBlIHZhbCB2YXIgd2hpbGUgd2l0aCB5aWVsZCBfIDogPSA9PiA8LSA8OiBcIiArXG4gICAgICBcIjwlID46ICMgQCBcIiArXG5cbiAgICAgIC8qIHBhY2thZ2Ugc2NhbGEgKi9cbiAgICAgIFwiYXNzZXJ0IGFzc3VtZSByZXF1aXJlIHByaW50IHByaW50bG4gcHJpbnRmIHJlYWRMaW5lIHJlYWRCb29sZWFuIHJlYWRCeXRlIHJlYWRTaG9ydCBcIiArXG4gICAgICBcInJlYWRDaGFyIHJlYWRJbnQgcmVhZExvbmcgcmVhZEZsb2F0IHJlYWREb3VibGUgXCIgK1xuXG4gICAgICBcIjo6ICM6OiBcIlxuICAgICksXG4gICAgdHlwZXM6IHdvcmRzKFxuICAgICAgXCJBbnlWYWwgQXBwIEFwcGxpY2F0aW9uIEFycmF5IEJ1ZmZlcmVkSXRlcmF0b3IgQmlnRGVjaW1hbCBCaWdJbnQgQ2hhciBDb25zb2xlIEVpdGhlciBcIiArXG4gICAgICBcIkVudW1lcmF0aW9uIEVxdWl2IEVycm9yIEV4Y2VwdGlvbiBGcmFjdGlvbmFsIEZ1bmN0aW9uIEluZGV4ZWRTZXEgSW50ZWdyYWwgSXRlcmFibGUgXCIgK1xuICAgICAgXCJJdGVyYXRvciBMaXN0IE1hcCBOdW1lcmljIE5pbCBOb3ROdWxsIE9wdGlvbiBPcmRlcmVkIE9yZGVyaW5nIFBhcnRpYWxGdW5jdGlvbiBQYXJ0aWFsT3JkZXJpbmcgXCIgK1xuICAgICAgXCJQcm9kdWN0IFByb3h5IFJhbmdlIFJlc3BvbmRlciBTZXEgU2VyaWFsaXphYmxlIFNldCBTcGVjaWFsaXphYmxlIFN0cmVhbSBTdHJpbmdCdWlsZGVyIFwiICtcbiAgICAgIFwiU3RyaW5nQ29udGV4dCBTeW1ib2wgVGhyb3dhYmxlIFRyYXZlcnNhYmxlIFRyYXZlcnNhYmxlT25jZSBUdXBsZSBVbml0IFZlY3RvciBcIiArXG5cbiAgICAgIC8qIHBhY2thZ2UgamF2YS5sYW5nICovXG4gICAgICBcIkJvb2xlYW4gQnl0ZSBDaGFyYWN0ZXIgQ2hhclNlcXVlbmNlIENsYXNzIENsYXNzTG9hZGVyIENsb25lYWJsZSBDb21wYXJhYmxlIFwiICtcbiAgICAgIFwiQ29tcGlsZXIgRG91YmxlIEV4Y2VwdGlvbiBGbG9hdCBJbnRlZ2VyIExvbmcgTWF0aCBOdW1iZXIgT2JqZWN0IFBhY2thZ2UgUGFpciBQcm9jZXNzIFwiICtcbiAgICAgIFwiUnVudGltZSBSdW5uYWJsZSBTZWN1cml0eU1hbmFnZXIgU2hvcnQgU3RhY2tUcmFjZUVsZW1lbnQgU3RyaWN0TWF0aCBTdHJpbmcgXCIgK1xuICAgICAgXCJTdHJpbmdCdWZmZXIgU3lzdGVtIFRocmVhZCBUaHJlYWRHcm91cCBUaHJlYWRMb2NhbCBUaHJvd2FibGUgVHJpcGxlIFZvaWRcIlxuICAgICksXG4gICAgbXVsdGlMaW5lU3RyaW5nczogdHJ1ZSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImNhdGNoIGNsYXNzIGRvIGVsc2UgZmluYWxseSBmb3IgZm9yU29tZSBpZiBtYXRjaCBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImNsYXNzIGRlZiBvYmplY3QgcGFja2FnZSB0cmFpdCB0eXBlIHZhbCB2YXJcIiksXG4gICAgYXRvbXM6IHdvcmRzKFwidHJ1ZSBmYWxzZSBudWxsXCIpLFxuICAgIGluZGVudFN0YXRlbWVudHM6IGZhbHNlLFxuICAgIGluZGVudFN3aXRjaDogZmFsc2UsXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX10vKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfSxcbiAgICAgICdcIic6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgaWYgKCFzdHJlYW0ubWF0Y2goJ1wiXCInKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuVHJpcGxlU3RyaW5nO1xuICAgICAgICByZXR1cm4gc3RhdGUudG9rZW5pemUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICB9LFxuICAgICAgXCInXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXFx4YTEtXFx1ZmZmZl0vKTtcbiAgICAgICAgcmV0dXJuIFwiYXRvbVwiO1xuICAgICAgfVxuICAgIH0sXG4gICAgbW9kZVByb3BzOiB7Y2xvc2VCcmFja2V0czoge3RyaXBsZXM6ICdcIid9fVxuICB9KTtcblxuICBkZWYoXCJ0ZXh0L3gta290bGluXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFxuICAgICAgLyprZXl3b3JkcyovXG4gICAgICBcInBhY2thZ2UgYXMgdHlwZWFsaWFzIGNsYXNzIGludGVyZmFjZSB0aGlzIHN1cGVyIHZhbCBcIiArXG4gICAgICBcInZhciBmdW4gZm9yIGlzIGluIFRoaXMgdGhyb3cgcmV0dXJuIFwiICtcbiAgICAgIFwiYnJlYWsgY29udGludWUgb2JqZWN0IGlmIGVsc2Ugd2h
23459pbGUgZG8gdHJ5IHdoZW4gIWluICFpcyBhcz9cIiArXG5cbiAgICAgIC8qc29mdCBrZXl3b3JkcyovXG4gICAgICBcImZpbGUgaW1wb3J0IHdoZXJlIGJ5IGdldCBzZXQgYWJzdHJhY3QgZW51bSBvcGVuIGlubmVyIG92ZXJyaWRlIHByaXZhdGUgcHVibGljIGludGVybmFsIFwiICtcbiAgICAgIFwicHJvdGVjdGVkIGNhdGNoIGZpbmFsbHkgb3V0IGZpbmFsIHZhcmFyZyByZWlmaWVkIGR5bmFtaWMgY29tcGFuaW9uIGNvbnN0cnVjdG9yIGluaXQgXCIgK1xuICAgICAgXCJzZWFsZWQgZmllbGQgcHJvcGVydHkgcmVjZWl2ZXIgcGFyYW0gc3BhcmFtIGxhdGVpbml0IGRhdGEgaW5saW5lIG5vaW5saW5lIHRhaWxyZWMgXCIgK1xuICAgICAgXCJleHRlcm5hbCBhbm5vdGF0aW9uIGNyb3NzaW5saW5lXCJcbiAgICApLFxuICAgIHR5cGVzOiB3b3JkcyhcbiAgICAgIC8qIHBhY2thZ2UgamF2YS5sYW5nICovXG4gICAgICBcIkJvb2xlYW4gQnl0ZSBDaGFyYWN0ZXIgQ2hhclNlcXVlbmNlIENsYXNzIENsYXNzTG9hZGVyIENsb25lYWJsZSBDb21wYXJhYmxlIFwiICtcbiAgICAgIFwiQ29tcGlsZXIgRG91YmxlIEV4Y2VwdGlvbiBGbG9hdCBJbnRlZ2VyIExvbmcgTWF0aCBOdW1iZXIgT2JqZWN0IFBhY2thZ2UgUGFpciBQcm9jZXNzIFwiICtcbiAgICAgIFwiUnVudGltZSBSdW5uYWJsZSBTZWN1cml0eU1hbmFnZXIgU2hvcnQgU3RhY2tUcmFjZUVsZW1lbnQgU3RyaWN0TWF0aCBTdHJpbmcgXCIgK1xuICAgICAgXCJTdHJpbmdCdWZmZXIgU3lzdGVtIFRocmVhZCBUaHJlYWRHcm91cCBUaHJlYWRMb2NhbCBUaHJvd2FibGUgVHJpcGxlIFZvaWRcIlxuICAgICksXG4gICAgbXVsdGlMaW5lU3RyaW5nczogdHJ1ZSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImNhdGNoIGNsYXNzIGRvIGVsc2UgZmluYWxseSBmb3IgaWYgd2hlcmUgdHJ5IHdoaWxlIGVudW1cIiksXG4gICAgZGVmS2V5d29yZHM6IHdvcmRzKFwiY2xhc3MgdmFsIHZhciBvYmplY3QgcGFja2FnZSBpbnRlcmZhY2UgZnVuXCIpLFxuICAgIGF0b21zOiB3b3JkcyhcInRydWUgZmFsc2UgbnVsbCB0aGlzXCIpLFxuICAgIG1vZGVQcm9wczoge2Nsb3NlQnJhY2tldHM6IHt0cmlwbGVzOiAnXCInfX1cbiAgfSk7XG5cbiAgZGVmKFtcIngtc2hhZGVyL3gtdmVydGV4XCIsIFwieC1zaGFkZXIveC1mcmFnbWVudFwiXSwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoXCJzYW1wbGVyMU
23459Qgc2FtcGxlcjJEIHNhbXBsZXIzRCBzYW1wbGVyQ3ViZSBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwic2FtcGxlcjFEU2hhZG93IHNhbXBsZXIyRFNoYWRvdyBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiY29uc3QgYXR0cmlidXRlIHVuaWZvcm0gdmFyeWluZyBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiYnJlYWsgY29udGludWUgZGlzY2FyZCByZXR1cm4gXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImZvciB3aGlsZSBkbyBpZiBlbHNlIHN0cnVjdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiaW4gb3V0IGlub3V0XCIpLFxuICAgIHR5cGVzOiB3b3JkcyhcImZsb2F0IGludCBib29sIHZvaWQgXCIgK1xuICAgICAgICAgICAgICAgICBcInZlYzIgdmVjMyB2ZWM0IGl2ZWMyIGl2ZWMzIGl2ZWM0IGJ2ZWMyIGJ2ZWMzIGJ2ZWM0IFwiICtcbiAgICAgICAgICAgICAgICAgXCJtYXQyIG1hdDMgbWF0NFwiKSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImZvciB3aGlsZSBkbyBpZiBlbHNlIHN0cnVjdFwiKSxcbiAgICBidWlsdGluOiB3b3JkcyhcInJhZGlhbnMgZGVncmVlcyBzaW4gY29zIHRhbiBhc2luIGFjb3MgYXRhbiBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwicG93IGV4cCBsb2cgZXhwMiBzcXJ0IGludmVyc2VzcXJ0IFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJhYnMgc2lnbiBmbG9vciBjZWlsIGZyYWN0IG1vZCBtaW4gbWF4IGNsYW1wIG1peCBzdGVwIHNtb290aHN0ZXAgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImxlbmd0aCBkaXN0YW5jZSBkb3QgY3Jvc3Mgbm9ybWFsaXplIGZ0cmFuc2Zvcm0gZmFjZWZvcndhcmQgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInJlZmxlY3QgcmVmcmFjdCBtYXRyaXhDb21wTXVsdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwibGVzc1RoYW4gbGVzc1RoYW5FcXVhbCBncmVhdGVyVGhhbiBncmVhdGVyVGhhbkVxdWFsIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJlcXVhbCBub3RFcXVhbCBhbnkgYWxsIG5vdCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwidGV4dHVyZTFEIHRleHR1cmUxRFByb2ogdGV4dHVyZTFETG9kIHRleHR1cmUxRFByb2pMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInRleHR1cmUyRCB0ZXh0dXJlMkRQcm9qIHRleHR1cmUyRExvZCB0ZXh0dXJlMkRQcm9qTG9kIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJ0ZXh0dXJlM0QgdGV4dHVyZTNEUHJvaiB0ZXh0dXJlM0RMb2QgdGV4dHVyZTNEUHJvakxvZCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwidGV4dHVyZUN1YmUgdGV4dHVyZUN1YmVMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInNoYWRvdzFEIHNoYWRvdzJEIHNoYWRvdzFEUHJvaiBzaGFkb3cyRFByb2ogXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInNoYWRvdzFETG9kIHNoYWRvdzJETG9kIHNoYWRvdzFEUHJvakxvZCBzaGFkb3cyRFByb2pMb2QgXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImRGZHggZEZkeSBmd2lkdGggXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIm5vaXNlMSBub2lzZTIgbm9pc2UzIG5vaXNlNFwiKSxcbiAgICBhdG9tczogd29yZHMoXCJ0cnVlIGZhbHNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZyYWdDb2xvciBnbF9TZWNvbmRhcnlDb2xvciBnbF9Ob3JtYWwgZ2xfVmVydGV4IFwiICtcbiAgICAgICAgICAgICAgICBcImdsX011bHRpVGV4Q29vcmQwIGdsX011bHRpVGV4Q29vcmQxIGdsX011bHRpVGV4Q29vcmQyIGdsX011bHRpVGV4Q29vcmQzIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX011bHRpVGV4Q29vcmQ0IGdsX011bHRpVGV4Q29vcmQ1IGdsX011bHRpVGV4Q29vcmQ2IGdsX011bHRpVGV4Q29vcmQ3IFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZvZ0Nvb3JkIGdsX1BvaW50Q29vcmQgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfUG9zaXRpb24gZ2xfUG9pbnRTaXplIGdsX0NsaXBWZXJ0ZXggXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfRnJvbnRDb2xvciBnbF9CYWNrQ29sb3IgZ2xfRnJvbnRTZWNvbmRhcnlDb2xvciBnbF9CYWNrU2Vjb25kYXJ5Q29sb3IgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfVGV4Q29vcmQgZ2xfRm9nRnJhZ0Nvb3JkIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX0ZyYWdDb29yZCBnbF9Gcm9udEZhY2luZyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9GcmFnRGF0YSBnbF9GcmFnRGVwdGggXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfTW9kZWxWaWV3TWF0cml4IGdsX1Byb2plY3Rpb25NYXRyaXggZ2xfTW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeCBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9UZXh0dXJlTWF0cml4IGdsX05vcm1hbE1hdHJpeCBnbF9Nb2RlbFZpZXdNYXRyaXhJbnZlcnNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlIGdsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1RleHVyZU1hdHJpeFRyYW5zcG9zZSBnbF9Nb2RlbFZpZXdNYXRyaXhJbnZlcnNlVHJhbnNwb3NlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlVHJhbnNwb3NlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlVHJhbnNwb3NlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1RleHR1cmVNYXRyaXhJbnZlcnNlVHJhbnNwb3NlIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX05vcm1hbFNjYWxlIGdsX0RlcHRoUmFuZ2UgZ2xfQ2xpcFBsYW5lIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX1BvaW50IGdsX0Zyb250TWF0ZXJpYWwgZ2xfQmFja01hdGVyaWFsIGdsX0xpZ2h0U291cmNlIGdsX0xpZ2h0TW9kZWwgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfRnJvbnRMaWdodE1vZGVsUHJvZHVjdCBnbF9CYWNrTGlnaHRNb2RlbFByb2R1Y3QgXCIgK1xuICAgICAgICAgICAgICAgIFwiZ2xfVGV4dHVyZUNvbG9yIGdsX0V5ZVBsYW5lUyBnbF9FeWVQbGFuZVQgZ2xfRXllUGxhbmVSIGdsX0V5ZVBsYW5lUSBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9Gb2dQYXJhbWV0ZXJzIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX01heExpZ2h0cyBnbF9NYXhDbGlwUGxhbmVzIGdsX01heFRleHR1cmVVbml0cyBnbF9NYXhUZXh0dXJlQ29vcmRzIFwiICtcbiAgICAgICAgICAgICAgICBcImdsX01heFZlcnRleEF0dHJpYnMgZ2xfTWF4VmVydGV4VW5pZm9ybUNvbXBvbmVudHMgZ2xfTWF4VmFyeWluZ0Zsb2F0cyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9NYXhWZXJ0ZXhUZXh0dXJlSW1hZ2VVbml0cyBnbF9NYXhUZXh0dXJlSW1hZ2VVbml0cyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9NYXhGcmFnbWVudFVuaWZvcm1
23459Db21wb25lbnRzIGdsX01heENvbWJpbmVUZXh0dXJlSW1hZ2VVbml0cyBcIiArXG4gICAgICAgICAgICAgICAgXCJnbF9NYXhEcmF3QnVmZmVyc1wiKSxcbiAgICBpbmRlbnRTd2l0Y2g6IGZhbHNlLFxuICAgIGhvb2tzOiB7XCIjXCI6IGNwcEhvb2t9LFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW5jbHVkZVwiXX1cbiAgfSk7XG5cbiAgZGVmKFwidGV4dC94LW5lc2NcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoY0tleXdvcmRzICsgXCJhcyBhdG9taWMgYXN5bmMgY2FsbCBjb21tYW5kIGNvbXBvbmVudCBjb21wb25lbnRzIGNvbmZpZ3VyYXRpb24gZXZlbnQgZ2VuZXJpYyBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiaW1wbGVtZW50YXRpb24gaW5jbHVkZXMgaW50ZXJmYWNlIG1vZHVsZSBuZXcgbm9yYWNlIG54X3N0cnVjdCBueF91bmlvbiBwb3N0IHByb3ZpZGVzIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJzaWduYWwgdGFzayB1c2VzIGFic3RyYWN0IGV4dGVuZHNcIiksXG4gICAgdHlwZXM6IHdvcmRzKGNUeXBlcyksXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXNlIGRvIGVsc2UgZm9yIGlmIHN3aXRjaCB3aGlsZSBzdHJ1Y3RcIiksXG4gICAgYXRvbXM6IHdvcmRzKFwibnVsbCB0cnVlIGZhbHNlXCIpLFxuICAgIGhvb2tzOiB7XCIjXCI6IGNwcEhvb2t9LFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFtcImJyYWNlXCIsIFwiaW5jbHVkZVwiXX1cbiAgfSk7XG5cbiAgZGVmKFwidGV4dC94LW9iamVjdGl2ZWNcIiwge1xuICAgIG5hbWU6IFwiY2xpa2VcIixcbiAgICBrZXl3b3Jkczogd29yZHMoY0tleXdvcmRzICsgXCJpbmxpbmUgcmVzdHJpY3QgX0Jvb2wgX0NvbXBsZXggX0ltYWdpbmVyeSBCT09MIENsYXNzIGJ5Y29weSBieXJlZiBpZCBJTVAgaW4gXCIgK1xuICAgICAgICAgICAgICAgICAgICBcImlub3V0IG5pbCBvbmV3YXkgb3V0IFByb3RvY29sIFNFTCBzZWxmIHN1cGVyIGF0b21pYyBub25hdG9taWMgcmV0YWluIGNvcHkgcmVhZHdyaXRlIHJlYWRvbmx5XCIpLFxuICAgIHR5cGVzOiB3b3JkcyhjVHlwZXMpLFxuICAgIGF0b21zOiB3b3JkcyhcIllFUyBOTyBOVUxMIE5JTEwgT04gT0ZGIHRydWUgZmFsc2VcIiksXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkXS8pO1xuICAgICAgICByZXR1cm4gXCJrZXl3b3JkXCI7XG4gICAgICB9LFxuICAgICAgXCIjXCI6IGNwcEhvb2ssXG4gICAgICBpbmRlbnQ6IGZ1bmN0aW9uKF9zdGF0ZSwgY3R4LCB0ZXh0QWZ0ZXIpIHtcbiAgICAgICAgaWYgKGN0eC50eXBlID09IFwic3RhdGVtZW50XCIgJiYgL15AXFx3Ly50ZXN0KHRleHRBZnRlcikpIHJldHVybiBjdHguaW5kZW50ZWRcbiAgICAgIH1cbiAgICB9LFxuICAgIG1vZGVQcm9wczoge2ZvbGQ6IFwiYnJhY2VcIn1cbiAgfSk7XG5cbiAgZGVmKFwidGV4dC94LXNxdWlycmVsXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFwiYmFzZSBicmVhayBjbG9uZSBjb250aW51ZSBjb25zdCBkZWZhdWx0IGRlbGV0ZSBlbnVtIGV4dGVuZHMgZnVuY3Rpb24gaW4gY2xhc3NcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIGZvcmVhY2ggbG9jYWwgcmVzdW1lIHJldHVybiB0aGlzIHRocm93IHR5cGVvZiB5aWVsZCBjb25zdHJ1Y3RvciBpbnN0YW5jZW9mIHN0YXRpY1wiKSxcbiAgICB0eXBlczogd29yZHMoY1R5cGVzKSxcbiAgICBibG9ja0tleXdvcmRzOiB3b3JkcyhcImNhc2UgY2F0Y2ggY2xhc3MgZWxzZSBmb3IgZm9yZWFjaCBpZiBzd2l0Y2ggdHJ5IHdoaWxlXCIpLFxuICAgIGRlZktleXdvcmRzOiB3b3JkcyhcImZ1bmN0aW9uIGxvY2FsIGNsYXNzXCIpLFxuICAgIHR5cGVGaXJzdERlZmluaXRpb25zOiB0cnVlLFxuICAgIGF0b21zOiB3b3JkcyhcInRydWUgZmFsc2UgbnVsbFwiKSxcbiAgICBob29rczoge1wiI1wiOiBjcHBIb29rfSxcbiAgICBtb2RlUHJvcHM6IHtmb2xkOiBbXCJicmFjZVwiLCBcImluY2x1ZGVcIl19XG4gIH0pO1xuXG4gIC8vIENleWxvbiBTdHJpbmdzIG5lZWQgdG8gZGVhbCB3aXRoIGludGVycG9sYXRpb25cbiAgdmFyIHN0cmluZ1Rva2VuaXplciA9IG51bGw7XG4gIGZ1bmN0aW9uIHRva2VuQ2V5bG9uU3RyaW5nKHR5cGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgdmFyIGVzY2FwZWQgPSBmYWxzZSwgbmV4dCwgZW5kID0gZmFsc2U7XG4gICAgICB3aGlsZSAoIXN0cmVhbS5lb2woKSkge1xuICAgICAgICBpZiAoIWVzY2FwZWQgJiYgc3RyZWFtLm1hdGNoKCdcIicpICYmXG4gICAgICAgICAgICAgICh0eXBlID09IFwic2luZ2xlXCIgfHwgc3RyZWFtLm1hdGNoKCdcIlwiJykpKSB7XG4gICAgICAgICAgZW5kID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWVzY2FwZWQgJiYgc3RyZWFtLm1hdGNoKCdgYCcpKSB7XG4gICAgICAgICAgc3RyaW5nVG9rZW5pemVyID0gdG9rZW5DZXlsb25TdHJpbmcodHlwZSk7XG4gICAgICAgICAgZW5kID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBuZXh0ID0gc3RyZWFtLm5leHQoKTtcbiAgICAgICAgZXNjYXBlZCA9IHR5cGUgPT0gXCJzaW5nbGVcIiAmJiAhZXNjYXBlZCAmJiBuZXh0ID09IFwiXFxcXFwiO1xuICAgICAgfVxuICAgICAgaWYgKGVuZClcbiAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IG51bGw7XG4gICAgICByZXR1cm4gXCJzdHJpbmdcIjtcbiAgICB9XG4gIH1cblxuICBkZWYoXCJ0ZXh0L3gtY2V5bG9uXCIsIHtcbiAgICBuYW1lOiBcImNsaWtlXCIsXG4gICAga2V5d29yZHM6IHdvcmRzKFwiYWJzdHJhY3RzIGFsaWFzIGFzc2VtYmx5IGFzc2VydCBhc3NpZ24gYnJlYWsgY2FzZSBjYXRjaCBjbGFzcyBjb250aW51ZSBkeW5hbWljIGVsc2VcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIGV4aXN0cyBleHRlbmRzIGZpbmFsbHkgZm9yIGZ1bmN0aW9uIGdpdmVuIGlmIGltcG9ydCBpbiBpbnRlcmZhY2UgaXMgbGV0IG1vZHVsZSBuZXdcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIG5vbmVtcHR5IG9iamVjdCBvZiBvdXQgb3V0ZXIgcGFja2FnZSByZXR1cm4gc2F0aXNmaWVzIHN1cGVyIHN3aXRjaCB0aGVuIHRoaXMgdGhyb3dcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiIHRyeSB2YWx1ZSB2b2lkIHdoaWxlXCIpLFxuICAgIHR5cGVzOiBmdW5jdGlvbih3b3JkKSB7XG4gICAgICAgIC8vIEluIENleWxvbiBhbGwgaWRlbnRpZmllcnMgdGhhdCBzdGFydCB3aXRoIGFuIHVwcGVyY2FzZSBhcmUgdHlwZXNcbiAgICAgICAgdmFyIGZpcnN0ID0gd29yZC5jaGFyQXQoMCk7XG4gICAgICAgI
23459HJldHVybiAoZmlyc3QgPT09IGZpcnN0LnRvVXBwZXJDYXNlKCkgJiYgZmlyc3QgIT09IGZpcnN0LnRvTG93ZXJDYXNlKCkpO1xuICAgIH0sXG4gICAgYmxvY2tLZXl3b3Jkczogd29yZHMoXCJjYXNlIGNhdGNoIGNsYXNzIGR5bmFtaWMgZWxzZSBmaW5hbGx5IGZvciBmdW5jdGlvbiBpZiBpbnRlcmZhY2UgbW9kdWxlIG5ldyBvYmplY3Qgc3dpdGNoIHRyeSB3aGlsZVwiKSxcbiAgICBkZWZLZXl3b3Jkczogd29yZHMoXCJjbGFzcyBkeW5hbWljIGZ1bmN0aW9uIGludGVyZmFjZSBtb2R1bGUgb2JqZWN0IHBhY2thZ2UgdmFsdWVcIiksXG4gICAgYnVpbHRpbjogd29yZHMoXCJhYnN0cmFjdCBhY3R1YWwgYWxpYXNlZCBhbm5vdGF0aW9uIGJ5IGRlZmF1bHQgZGVwcmVjYXRlZCBkb2MgZmluYWwgZm9ybWFsIGxhdGUgbGljZW5zZVwiICtcbiAgICAgICAgICAgICAgICAgICBcIiBuYXRpdmUgb3B0aW9uYWwgc2VhbGVkIHNlZSBzZXJpYWxpemFibGUgc2hhcmVkIHN1cHByZXNzV2FybmluZ3MgdGFnZ2VkIHRocm93cyB2YXJpYWJsZVwiKSxcbiAgICBpc1B1bmN0dWF0aW9uQ2hhcjogL1tcXFtcXF17fVxcKFxcKSw7XFw6XFwuYF0vLFxuICAgIGlzT3BlcmF0b3JDaGFyOiAvWytcXC0qJiU9PD4hP3xefjpcXC9dLyxcbiAgICBpc051bWJlckNoYXI6IC9bXFxkIyRdLyxcbiAgICBtdWx0aUxpbmVTdHJpbmdzOiB0cnVlLFxuICAgIHR5cGVGaXJzdERlZmluaXRpb25zOiB0cnVlLFxuICAgIGF0b21zOiB3b3JkcyhcInRydWUgZmFsc2UgbnVsbCBsYXJnZXIgc21hbGxlciBlcXVhbCBlbXB0eSBmaW5pc2hlZFwiKSxcbiAgICBpbmRlbnRTd2l0Y2g6IGZhbHNlLFxuICAgIHN0eWxlRGVmczogZmFsc2UsXG4gICAgaG9va3M6IHtcbiAgICAgIFwiQFwiOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc3RyZWFtLmVhdFdoaWxlKC9bXFx3XFwkX10vKTtcbiAgICAgICAgcmV0dXJuIFwibWV0YVwiO1xuICAgICAgfSxcbiAgICAgICdcIic6IGZ1bmN0aW9uKHN0cmVhbSwgc3RhdGUpIHtcbiAgICAgICAgICBzdGF0ZS50b2tlbml6ZSA9IHRva2VuQ2V5bG9uU3RyaW5nKHN0cmVhbS5tYXRjaCgnXCJcIicpID8gXCJ0cmlwbGVcIiA6IFwic2luZ2xlXCIpO1xuICAgICAgICAgIHJldHVybiBzdGF0ZS50b2tlbml6ZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgfSxcbiAgICAgICdgJzogZnVuY3Rpb24oc3RyZWFtLCBzdGF0ZSkge1xuICAgICAgICAgIGlmICghc3RyaW5nVG9rZW5pemVyIHx8ICFzdHJlYW0ubWF0Y2goJ2AnKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIHN0YXRlLnRva2VuaXplID0gc3RyaW5nVG9rZW5pemVyO1xuICAgICAgICAgIHN0cmluZ1Rva2VuaXplciA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIHN0YXRlLnRva2VuaXplKHN0cmVhbSwgc3RhdGUpO1xuICAgICAgICB9LFxuICAgICAgXCInXCI6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW0uZWF0V2hpbGUoL1tcXHdcXCRfXFx4YTEtXFx1ZmZmZl0vKTtcbiAgICAgICAgcmV0dXJuIFwiYXRvbVwiO1xuICAgICAgfSxcbiAgICAgIHRva2VuOiBmdW5jdGlvbihfc3RyZWFtLCBzdGF0ZSwgc3R5bGUpIHtcbiAgICAgICAgICBpZiAoKHN0eWxlID09IFwidmFyaWFibGVcIiB8fCBzdHlsZSA9PSBcInZhcmlhYmxlLTNcIikgJiZcbiAgICAgICAgICAgICAgc3RhdGUucHJldlRva2VuID09IFwiLlwiKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJ2YXJpYWJsZS0yXCI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBtb2RlUHJvcHM6IHtcbiAgICAgICAgZm9sZDogW1wiYnJhY2VcIiwgXCJpbXBvcnRcIl0sXG4gICAgICAgIGNsb3NlQnJhY2tldHM6IHt0cmlwbGVzOiAnXCInfVxuICAgIH1cbiAgfSk7XG5cbn0pO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvcicpOyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5hc3NpZ24nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy8kLmNvcmUnKS5PYmplY3QuYXNzaWduOyIsInZhciAkID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy8kJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZShQLCBEKXtcbiAgcmV0dXJuICQuY3JlYXRlKFAsIEQpO1xufTsiLCJ2YXIgJCA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvJCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShpdCwga2V5LCBkZXNjKXtcbiAgcmV0dXJuICQuc2V0RGVzYyhpdCwga2V5LCBkZXNjKTtcbn07IiwidmFyICQgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzLyQnKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3InKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpe1xuICByZXR1cm4gJC5nZXREZXNjKGl0LCBrZXkpO1xufTsiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5vYmplY3Qua2V5cycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzLyQuY29yZScpLk9iamVjdC5rZXlzOyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5zZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvJC5jb3JlJykuT2JqZWN0LnNldFByb3RvdHlwZU9mOyIsInJlcXVpcmUoJy4uL21vZHVsZXMvZXM2Lm9iamVjdC50by1zdHJpbmcnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvcicpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5wcm9taXNlJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL21vZHVsZXMvJC5jb3JlJykuUHJvbWlzZTsiLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc2V0Jyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5zZXQudG8tanNvbicpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9tb2R1bGVzLyQuY29yZScpLlNldDsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgaWYodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpdGhyb3cgVHlwZUVycm9yKGl0ICsgJyBpcyBub3QgYSBmdW5jdGlvbiEnKTtcbiAgcmV0dXJuIGl0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCl7IC8qIGVtcHR5ICovIH07IiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi8kLmlzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIGlmKCFpc09iamVjdChpdCkpdGhyb3cgVHlwZUVycm9yKGl0ICsgJyBpcyBub3QgYW4gb2JqZWN0IScpO1xuICByZXR1cm4gaXQ7XG59OyIsIi8vIGdldHRpbmcgdGFnIGZyb20gMTkuMS4zLjYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZygpXG52YXIgY29mID0gcmVxdWlyZSgnLi8kLmNvZicpXG4gICwgVEFHID0gcmVxdWlyZSgnLi8kLndrcycpKCd0b1N0cmluZ1RhZycpXG4gIC8vIEVTMyB3cm9uZyBoZXJlXG4gICwgQVJHID0gY29mKGZ1bmN0aW9uKCl7IHJldHVybi
23459Bhcmd1bWVudHM7IH0oKSkgPT0gJ0FyZ3VtZW50cyc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICB2YXIgTywgVCwgQjtcbiAgcmV0dXJuIGl0ID09PSB1bmRlZmluZWQgPyAnVW5kZWZpbmVkJyA6IGl0ID09PSBudWxsID8gJ051bGwnXG4gICAgLy8gQEB0b1N0cmluZ1RhZyBjYXNlXG4gICAgOiB0eXBlb2YgKFQgPSAoTyA9IE9iamVjdChpdCkpW1RBR10pID09ICdzdHJpbmcnID8gVFxuICAgIC8vIGJ1aWx0aW5UYWcgY2FzZVxuICAgIDogQVJHID8gY29mKE8pXG4gICAgLy8gRVMzIGFyZ3VtZW50cyBmYWxsYmFja1xuICAgIDogKEIgPSBjb2YoTykpID09ICdPYmplY3QnICYmIHR5cGVvZiBPLmNhbGxlZSA9PSAnZnVuY3Rpb24nID8gJ0FyZ3VtZW50cycgOiBCO1xufTsiLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKGl0KS5zbGljZSg4LCAtMSk7XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciAkICAgICAgICAgICAgPSByZXF1aXJlKCcuLyQnKVxuICAsIGhpZGUgICAgICAgICA9IHJlcXVpcmUoJy4vJC5oaWRlJylcbiAgLCByZWRlZmluZUFsbCAgPSByZXF1aXJlKCcuLyQucmVkZWZpbmUtYWxsJylcbiAgLCBjdHggICAgICAgICAgPSByZXF1aXJlKCcuLyQuY3R4JylcbiAgLCBzdHJpY3ROZXcgICAgPSByZXF1aXJlKCcuLyQuc3RyaWN0LW5ldycpXG4gICwgZGVmaW5lZCAgICAgID0gcmVxdWlyZSgnLi8kLmRlZmluZWQnKVxuICAsIGZvck9mICAgICAgICA9IHJlcXVpcmUoJy4vJC5mb3Itb2YnKVxuICAsICRpdGVyRGVmaW5lICA9IHJlcXVpcmUoJy4vJC5pdGVyLWRlZmluZScpXG4gICwgc3RlcCAgICAgICAgID0gcmVxdWlyZSgnLi8kLml0ZXItc3RlcCcpXG4gICwgSUQgICAgICAgICAgID0gcmVxdWlyZSgnLi8kLnVpZCcpKCdpZCcpXG4gICwgJGhhcyAgICAgICAgID0gcmVxdWlyZSgnLi8kLmhhcycpXG4gICwgaXNPYmplY3QgICAgID0gcmVxdWlyZSgnLi8kLmlzLW9iamVjdCcpXG4gICwgc2V0U3BlY2llcyAgID0gcmVxdWlyZSgnLi8kLnNldC1zcGVjaWVzJylcbiAgLCBERVNDUklQVE9SUyAgPSByZXF1aXJlKCcuLyQuZGVzY3JpcHRvcnMnKVxuICAsIGlzRXh0ZW5zaWJsZSA9IE9iamVjdC5pc0V4dGVuc2libGUgfHwgaXNPYmplY3RcbiAgLCBTSVpFICAgICAgICAgPSBERVNDUklQVE9SUyA/ICdfcycgOiAnc2l6ZSdcbiAgLCBpZCAgICAgICAgICAgPSAwO1xuXG52YXIgZmFzdEtleSA9IGZ1bmN0aW9uKGl0LCBjcmVhdGUpe1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmKCFpc09iamVjdChpdCkpcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJyA/IGl0IDogKHR5cGVvZiBpdCA9PSAnc3RyaW5nJyA/ICdTJyA6ICdQJykgKyBpdDtcbiAgaWYoISRoYXMoaXQsIElEKSl7XG4gICAgLy8gY2FuJ3Qgc2V0IGlkIHRvIGZyb3plbiBvYmplY3RcbiAgICBpZighaXNFeHRlbnNpYmxlKGl0KSlyZXR1cm4gJ0YnO1xuICAgIC8vIG5vdCBuZWNlc3NhcnkgdG8gYWRkIGlkXG4gICAgaWYoIWNyZWF0ZSlyZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG9iamVjdCBpZFxuICAgIGhpZGUoaXQsIElELCArK2lkKTtcbiAgLy8gcmV0dXJuIG9iamVjdCBpZCB3aXRoIHByZWZpeFxuICB9IHJldHVybiAnTycgKyBpdFtJRF07XG59O1xuXG52YXIgZ2V0RW50cnkgPSBmdW5jdGlvbih0aGF0LCBrZXkpe1xuICAvLyBmYXN0IGNhc2VcbiAgdmFyIGluZGV4ID0gZmFzdEtleShrZXkpLCBlbnRyeTtcbiAgaWYoaW5kZXggIT09ICdGJylyZXR1cm4gdGhhdC5faVtpbmRleF07XG4gIC8vIGZyb3plbiBvYmplY3QgY2FzZVxuICBmb3IoZW50cnkgPSB0aGF0Ll9mOyBlbnRyeTsgZW50cnkgPSBlbnRyeS5uKXtcbiAgICBpZihlbnRyeS5rID09IGtleSlyZXR1cm4gZW50cnk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBnZXRDb25zdHJ1Y3RvcjogZnVuY3Rpb24od3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUil7XG4gICAgdmFyIEMgPSB3cmFwcGVyKGZ1bmN0aW9uKHRoYXQsIGl0ZXJhYmxlKXtcbiAgICAgIHN0cmljdE5ldyh0aGF0LCBDLCBOQU1FKTtcbiAgICAgIHRoYXQuX2kgPSAkLmNyZWF0ZShudWxsKTsgLy8gaW5kZXhcbiAgICAgIHRoYXQuX2YgPSB1bmRlZmluZWQ7ICAgICAgLy8gZmlyc3QgZW50cnlcbiAgICAgIHRoYXQuX2wgPSB1bmRlZmluZWQ7ICAgICAgLy8gbGFzdCBlbnRyeVxuICAgICAgdGhhdFtTSVpFXSA9IDA7ICAgICAgICAgICAvLyBzaXplXG4gICAgICBpZihpdGVyYWJsZSAhPSB1bmRlZmluZWQpZm9yT2YoaXRlcmFibGUsIElTX01BUCwgdGhhdFtBRERFUl0sIHRoYXQpO1xuICAgIH0pO1xuICAgIHJlZGVmaW5lQWxsKEMucHJvdG90eXBlLCB7XG4gICAgICAvLyAyMy4xLjMuMSBNYXAucHJvdG90eXBlLmNsZWFyKClcbiAgICAgIC8vIDIzLjIuMy4yIFNldC5wcm90b3R5cGUuY2xlYXIoKVxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCl7XG4gICAgICAgIGZvcih2YXIgdGhhdCA9IHRoaXMsIGRhdGEgPSB0aGF0Ll9pLCBlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pe1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmKGVudHJ5LnApZW50cnkucCA9IGVudHJ5LnAubiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBkZWxldGUgZGF0YVtlbnRyeS5pXTtcbiAgICAgICAgfVxuICAgICAgICB0aGF0Ll9mID0gdGhhdC5fbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhhdFtTSVpFXSA9IDA7XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjMgTWFwLnByb3RvdHlwZS5kZWxldGUoa2V5KVxuICAgICAgLy8gMjMuMi4zLjQgU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24oa2V5KXtcbiAgICAgICAgdmFyIHRoYXQgID0gdGhpc1xuICAgICAgICAgICwgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpO1xuICAgICAgICBpZihlbnRyeSl7XG4gICAgICAgICAgdmFyIG5leHQgPSBlbnRyeS5uXG4gICAgICAgICAgICAsIHByZXYgPSBlbnRyeS5wO1xuICAgICAgICAgIGRlbGV0ZSB0aGF0Ll9pW2VudHJ5LmldO1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmKHByZXYpcHJldi5uID0gbmV4dDtcbiAgICAgICAgICBpZihuZXh0KW5leHQucCA9IHByZXY7XG4gICAgICAgICAgaWYodGhhdC5fZiA9PSBlbnRyeSl0aGF0Ll9mID0gbmV4dDtcbiAgICAgICAgICBpZih0aGF0Ll9sID09IGVudHJ5KXRoYXQuX2wgPSBwcmV2O1xuICAgICAgICAgI
23459HRoYXRbU0laRV0tLTtcbiAgICAgICAgfSByZXR1cm4gISFlbnRyeTtcbiAgICAgIH0sXG4gICAgICAvLyAyMy4yLjMuNiBTZXQucHJvdG90eXBlLmZvckVhY2goY2FsbGJhY2tmbiwgdGhpc0FyZyA9IHVuZGVmaW5lZClcbiAgICAgIC8vIDIzLjEuMy41IE1hcC5wcm90b3R5cGUuZm9yRWFjaChjYWxsYmFja2ZuLCB0aGlzQXJnID0gdW5kZWZpbmVkKVxuICAgICAgZm9yRWFjaDogZnVuY3Rpb24gZm9yRWFjaChjYWxsYmFja2ZuIC8qLCB0aGF0ID0gdW5kZWZpbmVkICovKXtcbiAgICAgICAgdmFyIGYgPSBjdHgoY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsIDMpXG4gICAgICAgICAgLCBlbnRyeTtcbiAgICAgICAgd2hpbGUoZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm4gOiB0aGlzLl9mKXtcbiAgICAgICAgICBmKGVudHJ5LnYsIGVudHJ5LmssIHRoaXMpO1xuICAgICAgICAgIC8vIHJldmVydCB0byB0aGUgbGFzdCBleGlzdGluZyBlbnRyeVxuICAgICAgICAgIHdoaWxlKGVudHJ5ICYmIGVudHJ5LnIpZW50cnkgPSBlbnRyeS5wO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjcgTWFwLnByb3RvdHlwZS5oYXMoa2V5KVxuICAgICAgLy8gMjMuMi4zLjcgU2V0LnByb3RvdHlwZS5oYXModmFsdWUpXG4gICAgICBoYXM6IGZ1bmN0aW9uIGhhcyhrZXkpe1xuICAgICAgICByZXR1cm4gISFnZXRFbnRyeSh0aGlzLCBrZXkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmKERFU0NSSVBUT1JTKSQuc2V0RGVzYyhDLnByb3RvdHlwZSwgJ3NpemUnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCl7XG4gICAgICAgIHJldHVybiBkZWZpbmVkKHRoaXNbU0laRV0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBDO1xuICB9LFxuICBkZWY6IGZ1bmN0aW9uKHRoYXQsIGtleSwgdmFsdWUpe1xuICAgIHZhciBlbnRyeSA9IGdldEVudHJ5KHRoYXQsIGtleSlcbiAgICAgICwgcHJldiwgaW5kZXg7XG4gICAgLy8gY2hhbmdlIGV4aXN0aW5nIGVudHJ5XG4gICAgaWYoZW50cnkpe1xuICAgICAgZW50cnkudiA9IHZhbHVlO1xuICAgIC8vIGNyZWF0ZSBuZXcgZW50cnlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhhdC5fbCA9IGVudHJ5ID0ge1xuICAgICAgICBpOiBpbmRleCA9IGZhc3RLZXkoa2V5LCB0cnVlKSwgLy8gPC0gaW5kZXhcbiAgICAgICAgazoga2V5LCAgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIGtleVxuICAgICAgICB2OiB2YWx1ZSwgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gdmFsdWVcbiAgICAgICAgcDogcHJldiA9IHRoYXQuX2wsICAgICAgICAgICAgIC8vIDwtIHByZXZpb3VzIGVudHJ5XG4gICAgICAgIG46IHVuZGVmaW5lZCwgICAgICAgICAgICAgICAgICAvLyA8LSBuZXh0IGVudHJ5XG4gICAgICAgIHI6IGZhbHNlICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSByZW1vdmVkXG4gICAgICB9O1xuICAgICAgaWYoIXRoYXQuX2YpdGhhdC5fZiA9IGVudHJ5O1xuICAgICAgaWYocHJldilwcmV2Lm4gPSBlbnRyeTtcbiAgICAgIHRoYXRbU0laRV0rKztcbiAgICAgIC8vIGFkZCB0byBpbmRleFxuICAgICAgaWYoaW5kZXggIT09ICdGJyl0aGF0Ll9pW2luZGV4XSA9IGVudHJ5O1xuICAgIH0gcmV0dXJuIHRoYXQ7XG4gIH0sXG4gIGdldEVudHJ5OiBnZXRFbnRyeSxcbiAgc2V0U3Ryb25nOiBmdW5jdGlvbihDLCBOQU1FLCBJU19NQVApe1xuICAgIC8vIGFkZCAua2V5cywgLnZhbHVlcywgLmVudHJpZXMsIFtAQGl0ZXJhdG9yXVxuICAgIC8vIDIzLjEuMy40LCAyMy4xLjMuOCwgMjMuMS4zLjExLCAyMy4xLjMuMTIsIDIzLjIuMy41LCAyMy4yLjMuOCwgMjMuMi4zLjEwLCAyMy4yLjMuMTFcbiAgICAkaXRlckRlZmluZShDLCBOQU1FLCBmdW5jdGlvbihpdGVyYXRlZCwga2luZCl7XG4gICAgICB0aGlzLl90ID0gaXRlcmF0ZWQ7ICAvLyB0YXJnZXRcbiAgICAgIHRoaXMuX2sgPSBraW5kOyAgICAgIC8vIGtpbmRcbiAgICAgIHRoaXMuX2wgPSB1bmRlZmluZWQ7IC8vIHByZXZpb3VzXG4gICAgfSwgZnVuY3Rpb24oKXtcbiAgICAgIHZhciB0aGF0ICA9IHRoaXNcbiAgICAgICAgLCBraW5kICA9IHRoYXQuX2tcbiAgICAgICAgLCBlbnRyeSA9IHRoYXQuX2w7XG4gICAgICAvLyByZXZlcnQgdG8gdGhlIGxhc3QgZXhpc3RpbmcgZW50cnlcbiAgICAgIHdoaWxlKGVudHJ5ICYmIGVudHJ5LnIpZW50cnkgPSBlbnRyeS5wO1xuICAgICAgLy8gZ2V0IG5leHQgZW50cnlcbiAgICAgIGlmKCF0aGF0Ll90IHx8ICEodGhhdC5fbCA9IGVudHJ5ID0gZW50cnkgPyBlbnRyeS5uIDogdGhhdC5fdC5fZikpe1xuICAgICAgICAvLyBvciBmaW5pc2ggdGhlIGl0ZXJhdGlvblxuICAgICAgICB0aGF0Ll90ID0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gc3RlcCgxKTtcbiAgICAgIH1cbiAgICAgIC8vIHJldHVybiBzdGVwIGJ5IGtpbmRcbiAgICAgIGlmKGtpbmQgPT0gJ2tleXMnICApcmV0dXJuIHN0ZXAoMCwgZW50cnkuayk7XG4gICAgICBpZihraW5kID09ICd2YWx1ZXMnKXJldHVybiBzdGVwKDAsIGVudHJ5LnYpO1xuICAgICAgcmV0dXJuIHN0ZXAoMCwgW2VudHJ5LmssIGVudHJ5LnZdKTtcbiAgICB9LCBJU19NQVAgPyAnZW50cmllcycgOiAndmFsdWVzJyAsICFJU19NQVAsIHRydWUpO1xuXG4gICAgLy8gYWRkIFtAQHNwZWNpZXNdLCAyMy4xLjIuMiwgMjMuMi4yLjJcbiAgICBzZXRTcGVjaWVzKE5BTUUpO1xuICB9XG59OyIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9EYXZpZEJydWFudC9NYXAtU2V0LnByb3RvdHlwZS50b0pTT05cbnZhciBmb3JPZiAgID0gcmVxdWlyZSgnLi8kLmZvci1vZicpXG4gICwgY2xhc3NvZiA9IHJlcXVpcmUoJy4vJC5jbGFzc29mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKE5BTUUpe1xuICByZXR1cm4gZnVuY3Rpb24gdG9KU09OKCl7XG4gICAgaWYoY2xhc3NvZih0aGlzKSAhPSBOQU1FKXRocm93IFR5cGVFcnJvcihOQU1FICsgXCIjdG9KU09OIGlzbid0IGdlbmVyaWNcIik7XG4gICAgdmFyIGFyciA9IFtdO1xuICAgIGZvck9mKHRoaXMsIGZhbHNlLCBhcnIucHVzaCwgYXJyKTtcbiAgICByZXR1cm4gYXJyO1xuICB9O1xufTsiLCIndXNlIHN0cmljdCc7XG52YXIgJCAgICAgICAgICAgICAgPSByZXF1aXJlKCcuLyQnKVxuICAsIGdsb2JhbCAgICAgICAgID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpXG4gICwgJGV4cG9ydCAgICAgICAgPSByZXF1aXJlKCcuLyQuZXhwb3J0JylcbiAgLCBmYWlscyAgICAgICAgICA9IHJlcXVpcmUoJy4vJC5mYWlscycpXG4gICwgaGlkZSAgICAgICAgICAgPSByZXF1aXJlKCcuLyQuaGlkZScpXG4gICwgcmVkZWZpbmVBbGwgICAgPSByZXF1aXJlKCcuLyQucmVkZWZpbmUtYWxsJylcbiAgLCBmb3JPZiAgICAgICAgICA9IHJlcXVpcmUoJy4vJC5mb3Itb2YnKVxuICAsIHN0cmljdE5ldyAgICAgID0gcmVxdWlyZSgnLi8kLnN0cmljdC1uZXcnKVxuICAsIGlzT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi8kLmlzLW9iamVjdCcpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuLyQuc2V0LXRvLXN0cmluZy10YWcnKVxuICAsIERFU0NSSVBUT1JTICAgID0gcmVxdWlyZSgnLi8kLmRlc2NyaXB0b3JzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oTkFNRSwgd3JhcHBlciwgbWV0aG9kcywgY29tbW9uLCBJU19NQVAsIElTX1dFQUspe1xuICB2YXIgQmFzZSAgPSBnbG9iYWxbTkFNRV1cbiAgICAsIEMgICAgID0gQmFzZVxuICAgICwgQURERVIgPSBJU19NQVAgPyAnc2V0JyA6ICdhZGQnXG4gICAgLCBwcm90byA9IEMgJiYgQy5wcm90b3R5cGVcbiAgICAsIE8gICAgID0ge307XG4gIGlmKCFERVNDUklQVE9SUyB8fCB0eXBlb2YgQyAhPSAnZnVuY3Rpb24nIHx8ICEoSVNfV0VBSyB8fCBwcm90by5mb3JFYWNoICYmICFmYWlscyhmdW5jdGlvbigpe1xuICAgIG5ldyBDKCkuZW50cmllcygpLm5leHQoKTtcbiAgfSkpKXtcbiAgICAvLyBjcmVhdGUgY29sbGVjdGlvbiBjb25zdHJ1Y3RvclxuICAgIEMgPSBjb21tb24uZ2V0Q29uc3RydWN0b3Iod3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUik7XG4gICAgcmVkZWZpbmVBbGwoQy5wcm90b3R5cGUsIG1ldGhvZHMpO1xuICB9IGVsc2Uge1xuICAgIEMgPSB3cmFwcGVyKGZ1bmN0aW9uKHRhcmdldCwgaXRlcmFibGUpe1xuICAgICAgc3RyaWN0TmV3KHRhcmdldCwgQywgTkFNRSk7XG4gICAgICB0YXJnZXQuX2MgPSBuZXcgQmFzZTtcbiAgICAgIGlmKGl0ZXJhYmxlICE9IHVuZGVmaW5lZClmb3JPZihpdGVyYWJsZSwgSVNfTUFQLCB0YXJnZXRbQURERVJdLCB0YXJnZXQpO1xuICAgIH0pO1xuICAgICQuZWFjaC5jYWxsKCdhZGQsY2xlYXIsZGVsZXRlLGZvckVhY2gsZ2V0LGhhcyxzZXQsa2V5cyx2YWx1ZXMsZW50cmllcycuc3BsaXQoJywnKSxmdW5jdGlvbihLRVkpe1xuICAgICAgdmFyIElTX0FEREVSID0gS0VZID09ICdhZGQnIHx8IEtFWSA9PSAnc2V0JztcbiAgICAgIGlmKEtFWSBpbiBwcm90byAmJiAhKElTX1dFQUsgJiYgS0VZID09ICdjbGVhcicpKWhpZGUoQy5wcm90b3R5cGUsIEtFWSwgZnVuY3Rpb24oYSwgYil7XG4gICAgICAgIGlmKCFJU19BRERFUiAmJiBJU19XRUFLICYmICFpc09iamVjdChhKSlyZXR1cm4gS0VZID09ICdnZXQnID8gdW5kZWZpbmVkIDogZmFsc2U7XG4gICAgICAgI
23459HZhciByZXN1bHQgPSB0aGlzLl9jW0tFWV0oYSA9PT0gMCA/IDAgOiBhLCBiKTtcbiAgICAgICAgcmV0dXJuIElTX0FEREVSID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGlmKCdzaXplJyBpbiBwcm90bykkLnNldERlc2MoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpe1xuICAgICAgICByZXR1cm4gdGhpcy5fYy5zaXplO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc2V0VG9TdHJpbmdUYWcoQywgTkFNRSk7XG5cbiAgT1tOQU1FXSA9IEM7XG4gICRleHBvcnQoJGV4cG9ydC5HICsgJGV4cG9ydC5XICsgJGV4cG9ydC5GLCBPKTtcblxuICBpZighSVNfV0VBSyljb21tb24uc2V0U3Ryb25nKEMsIE5BTUUsIElTX01BUCk7XG5cbiAgcmV0dXJuIEM7XG59OyIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7dmVyc2lvbjogJzEuMi42J307XG5pZih0eXBlb2YgX19lID09ICdudW1iZXInKV9fZSA9IGNvcmU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWYiLCIvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbnZhciBhRnVuY3Rpb24gPSByZXF1aXJlKCcuLyQuYS1mdW5jdGlvbicpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbiwgdGhhdCwgbGVuZ3RoKXtcbiAgYUZ1bmN0aW9uKGZuKTtcbiAgaWYodGhhdCA9PT0gdW5kZWZpbmVkKXJldHVybiBmbjtcbiAgc3dpdGNoKGxlbmd0aCl7XG4gICAgY2FzZSAxOiByZXR1cm4gZnVuY3Rpb24oYSl7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhKTtcbiAgICB9O1xuICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uKGEsIGIpe1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYik7XG4gICAgfTtcbiAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbihhLCBiLCBjKXtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIsIGMpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uKC8qIC4uLmFyZ3MgKi8pe1
23459xuICAgIHJldHVybiBmbi5hcHBseSh0aGF0LCBhcmd1bWVudHMpO1xuICB9O1xufTsiLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIGlmKGl0ID09IHVuZGVmaW5lZCl0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07IiwiLy8gVGhhbmsncyBJRTggZm9yIGhpcyBmdW5ueSBkZWZpbmVQcm9wZXJ0eVxubW9kdWxlLmV4cG9ydHMgPSAhcmVxdWlyZSgnLi8kLmZhaWxzJykoZnVuY3Rpb24oKXtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ2EnLCB7Z2V0OiBmdW5jdGlvbigpeyByZXR1cm4gNzsgfX0pLmEgIT0gNztcbn0pOyIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vJC5pcy1vYmplY3QnKVxuICAsIGRvY3VtZW50ID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpLmRvY3VtZW50XG4gIC8vIGluIG9sZCBJRSB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0J1xuICAsIGlzID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpcyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoaXQpIDoge307XG59OyIsInZhciBnbG9iYWwgICAgPSByZXF1aXJlKCcuLyQuZ2xvYmFsJylcbiAgLCBjb3JlICAgICAgPSByZXF1aXJlKCcuLyQuY29yZScpXG4gICwgY3R4ICAgICAgID0gcmVxdWlyZSgnLi8kLmN0eCcpXG4gICwgUFJPVE9UWVBFID0gJ3Byb3RvdHlwZSc7XG5cbnZhciAkZXhwb3J0ID0gZnVuY3Rpb24odHlwZSwgbmFtZSwgc291cmNlKXtcbiAgdmFyIElTX0ZPUkNFRCA9IHR5cGUgJiAkZXhwb3J0LkZcbiAgICAsIElTX0dMT0JBTCA9IHR5cGUgJiAkZXhwb3J0LkdcbiAgICAsIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlNcbiAgICAsIElTX1BST1RPICA9IHR5cGUgJiAkZXhwb3J0LlBcbiAgICAsIElTX0JJTkQgICA9IHR5cGUgJiAkZXhwb3J0LkJcbiAgICAsIElTX1dSQVAgICA9IHR5cGUgJiAkZXhwb3J0LldcbiAgICAsIGV4cG9ydHMgICA9IElTX0dMT0JBTCA/IGNvcmUgOiBjb3JlW25hbWVdIHx8IChjb3JlW25hbWVdID0ge30pXG4gICAgLCB0YXJnZXQgICAgPSBJU19HTE9CQUwgPyBnbG9iYWwgOiBJU19TVEFUSUMgPyBnbG9iYWxbbmFtZV0gOiAoZ2xvYmFsW25hbWVdIHx8IHt9KVtQUk9UT1RZUEVdXG4gICAgLCBrZXksIG93biwgb3V0O1xuICBpZihJU19HTE9CQUwpc291cmNlID0gbmFtZTtcbiAgZm9yKGtleSBpbiBzb3VyY2Upe1xuICAgIC8vIGNvbnRhaW5zIGluIG5hdGl2ZVxuICAgIG93biA9ICFJU19GT1JDRUQgJiYgdGFyZ2V0ICYmIGtleSBpbiB0YXJnZXQ7XG4gICAgaWYob3duICYmIGtleSBpbiBleHBvcnRzKWNvbnRpbnVlO1xuICAgIC8vIGV4cG9ydCBuYXRpdmUgb3IgcGFzc2VkXG4gICAgb3V0ID0gb3duID8gdGFyZ2V0W2tleV0gOiBzb3VyY2Vba2V5XTtcbiAgICAvLyBwcmV2ZW50IGdsb2JhbCBwb2xsdXRpb24gZm9yIG5hbWVzcGFjZXNcbiAgICBleHBvcnRzW2tleV0gPSBJU19HTE9CQUwgJiYgdHlwZW9mIHRhcmdldFtrZXldICE9ICdmdW5jdGlvbicgPyBzb3VyY2Vba2V5XVxuICAgIC8vIGJpbmQgdGltZXJzIHRvIGdsb2JhbCBmb3IgY2FsbCBmcm9tIGV4cG9ydCBjb250ZXh0XG4gICAgOiBJU19CSU5EICYmIG93biA/IGN0eChvdXQsIGdsb2JhbClcbiAgICAvLyB3cmFwIGdsb2JhbCBjb25zdHJ1Y3RvcnMgZm9yIHByZXZlbnQgY2hhbmdlIHRoZW0gaW4gbGlicmFyeVxuICAgIDogSVNfV1JBUCAmJiB0YXJnZXRba2V5XSA9PSBvdXQgPyAoZnVuY3Rpb24oQyl7XG4gICAgICB2Y
23459XIgRiA9IGZ1bmN0aW9uKHBhcmFtKXtcbiAgICAgICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBDID8gbmV3IEMocGFyYW0pIDogQyhwYXJhbSk7XG4gICAgICB9O1xuICAgICAgRltQUk9UT1RZUEVdID0gQ1tQUk9UT1RZUEVdO1xuICAgICAgcmV0dXJuIEY7XG4gICAgLy8gbWFrZSBzdGF0aWMgdmVyc2lvbnMgZm9yIHByb3RvdHlwZSBtZXRob2RzXG4gICAgfSkob3V0KSA6IElTX1BST1RPICYmIHR5cGVvZiBvdXQgPT0gJ2Z1bmN0aW9uJyA/IGN0eChGdW5jdGlvbi5jYWxsLCBvdXQpIDogb3V0O1xuICAgIGlmKElTX1BST1RPKShleHBvcnRzW1BST1RPVFlQRV0gfHwgKGV4cG9ydHNbUFJPVE9UWVBFXSA9IHt9KSlba2V5XSA9IG91dDtcbiAgfVxufTtcbi8vIHR5cGUgYml0bWFwXG4kZXhwb3J0LkYgPSAxOyAgLy8gZm9yY2VkXG4kZXhwb3J0LkcgPSAyOyAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgLy8gc3RhdGljXG4kZXhwb3J0LlAgPSA4OyAgLy8gcHJvdG9cbiRleHBvcnQuQiA9IDE2OyAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgLy8gd3JhcFxubW9kdWxlLmV4cG9ydHMgPSAkZXhwb3J0OyIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZXhlYyl7XG4gIHRyeSB7XG4gICAgcmV0dXJuICEhZXhlYygpO1xuICB9IGNhdGNoKGUpe1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59OyIsInZhciBjdHggICAgICAgICA9IHJlcXVpcmUoJy4vJC5jdHgnKVxuICAsIGNhbGwgICAgICAgID0gcmVxdWlyZSgnLi8kLml0ZXItY2FsbCcpXG4gICwgaXNBcnJheUl0ZXIgPSByZXF1aXJlKCcuLyQuaXMtYXJyYXktaXRlcicpXG4gICwgYW5PYmplY3QgICAgPSByZXF1aXJlKCcuLyQuYW4tb2JqZWN0JylcbiAgLCB0b0xlbmd0aCAgICA9IHJlcXVpcmUoJy4vJC50by1sZW5ndGgnKVxuICAsIGdldEl0ZXJGbiAgID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXRlcmFibGUsIGVudHJpZXMsIGZuLCB0aGF0KXtcbiAgdmFyIGl0ZXJGbiA9IGdldEl0ZXJGbihpdGVyYWJsZSlcbiAgICAsIGYgICAgICA9IGN0eChmbiwgdGhhdCwgZW50cmllcyA/IDIgOiAxKVxuICAgICwgaW5kZXggID0gMFxuICAgICwgbGVuZ3RoLCBzdGVwLCBpdGVyYXRvcjtcbiAgaWYodHlwZW9mIGl0ZXJGbiAhPSAnZnVuY3Rpb24nKXRocm93IFR5cGVFcnJvcihpdGVyYWJsZSArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICAvLyBmYXN0IGNhc2UgZm9yIGFycmF5cyB3aXRoIGRlZmF1bHQgaXRlcmF0b3JcbiAgaWYoaXNBcnJheUl0ZXIoaXRlckZuKSlmb3IobGVuZ3RoID0gdG9MZW5ndGgoaXRlcmFibGUubGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4Kyspe1xuICAgIGVudHJpZXMgPyBmKGFuT2JqZWN0KHN0ZXAgPSBpdGVyYWJsZVtpbmRleF0pWzBdLCBzdGVwWzFdKSA6IGYoaXRlcmFibGVbaW5kZXhdKTtcbiAgfSBlbHNlIGZvcihpdGVyYXRvciA9IGl0ZXJGbi5jYWxsKGl0ZXJhYmxlKTsgIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lOyApe1xuICAgIGNhbGwoaXRlcmF0b3IsIGYsIHN0ZXAudmFsdWUsIGVudHJpZXMpO1xuICB9XG59OyIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy84NiNpc3N1ZWNvbW1lbnQtMTE1NzU5MDI4XG52YXIgZ2xvYmFsID0gbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnICYmIHdpbmRvdy5NYXRoID09IE1hdGhcbiAgPyB3aW5kb3cgOiB0eXBlb2Ygc2VsZiAhPSAndW5kZWZpbmVkJyAmJiBzZWxmLk1hdGggPT0gTWF0aCA/IHNlbGYgOiBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuaWYodHlwZW9mIF9fZyA9PSAnbnVtYmVyJylfX2cgPSBnbG9iYWw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWYiLCJ2YXIgaGFzT3duUHJvcGVydHkgPSB7fS5oYXNPd25Qcm9wZXJ0eTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQsIGtleSl7XG4gIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGl0LCBrZXkpO1xufTsiLCJ2YXIgJCAgICAgICAgICA9IHJlcXVpcmUoJy4vJCcpXG4gICwgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vJC5wcm9wZXJ0eS1kZXNjJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vJC5kZXNjcmlwdG9ycycpID8gZnVuY3Rpb24ob2JqZWN0LCBrZXksIHZhbHVlKXtcbiAgcmV0dXJuICQuc2V0RGVzYyhvYmplY3QsIGtleSwgY3JlYXRlRGVzYygxLCB2YWx1ZSkpO1xufSA6IGZ1bmN0aW9uKG9iamVjdCwga2V5LCB2YWx1ZSl7XG4gIG9iamVjdFtrZXldID0gdmFsdWU7XG4gIHJldHVybiBvYmplY3Q7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpLmRvY3VtZW50ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDsiLCIvLyBmYXN0IGFwcGx5LCBodHRwOi8vanNwZXJmLmxua2l0LmNvbS9mYXN0LWFwcGx5LzVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZm4sIGFyZ3MsIHRoYXQpe1xuICB2YXIgdW4gPSB0aGF0ID09PSB1bmRlZmluZWQ7XG4gIHN3aXRjaChhcmdzLmxlbmd0aCl7XG4gICAgY2FzZSAwOiByZXR1cm4gdW4gPyBmbigpXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQpO1xuICAgIGNhc2UgMTogcmV0dXJuIHVuID8gZm4oYXJnc1swXSlcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCwgYXJnc1swXSk7XG4gICAgY2FzZSAyOiByZXR1cm4gdW4gPyBmbihhcmdzWzBdLCBhcmdzWzFdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICBjYXNlIDM6IHJldHVybiB1biA/IGZuKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQsIGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgIGNhc2UgNDogcmV0dXJuIHVuID8gZm4oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSlcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCwgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSk7XG4gIH0gcmV0dXJuICAgICAgICAgICAgICBmbi5hcHBseSh0aGF0LCBhcmdzKTtcbn07IiwiLy8gZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBhbmQgbm9uLWVudW1lcmFibGUgb2xkIFY4IHN0cmluZ3NcbnZhciBjb2YgPSByZXF1aXJlKCcuLyQuY29mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApID8gT2JqZWN0IDogZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gY29mKGl0KSA9PSAnU3RyaW5nJyA/IGl0LnNwbGl0KCcnKSA6IE9iamVjdChpdCk7XG59OyIsIi8vIGNoZWNrIG9uIGRlZmF1bHQgQXJyYXkgaXRlcmF0b3JcbnZhciBJdGVyYXRvcnMgID0gcmVxdWlyZSgnLi8kLml0ZXJhdG9ycycpXG4gICwgSVRFUkFUT1IgICA9IHJlcXVpcmUoJy4vJC53a3MnKSgnaXRlcmF0b3InKVxuICAsIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gaXQgIT09IHVuZGVmaW5lZCAmJiAoSXRlcmF0b3JzLkFycmF5ID09PSBpdCB8fCBBcnJheVByb3RvW0lURVJBVE9SXSA9PT0gaXQpO1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIHR5cGVvZiBpdCA9PT0gJ29iamVjdCcgPyBpdCAhPT0gbnVsbCA6IHR5cGVvZiBpdCA9PT0gJ2Z1bmN0aW9uJztcbn07IiwiLy8gY2FsbCBzb21ldGhpbmcgb24gaXRlcmF0b3Igc3RlcCB3aXRoIHNhZmUgY2xvc2luZyBvbiBlcnJvclxudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi8kLmFuLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdGVyYXRvciwgZm4sIHZhbHVlLCBlbnRyaWVzKXtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZW50cmllcyA/IGZuKGFuT2JqZWN0KHZhbHVlKVswXSwgdmFsdWVbMV0pIDogZm4odmFsdWUpO1xuICAvLyA3LjQuNiBJdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCBjb21wbGV0aW9uKVxuICB9IGNhdGNoKGUpe1xuICAgIHZhciByZXQgPSBpdGVyYXRvclsncmV0dXJuJ107XG4gICAgaWYocmV0ICE9PSB1bmRlZmluZWQpYW5PYmplY3QocmV0LmNhbGwoaXRlcmF0b3IpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciAkICAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vJCcpXG4gICwgZGVzY3JpcHRvciAgICAgPSByZXF1aXJlKCcuLyQucHJvcGVydHktZGVzYycpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuLyQuc2V0LXRvLXN0cmluZy10YWcnKVxuICAsIEl0ZXJhdG9yUHJvdG90eXBlID0ge307XG5cbi8vIDI1LjEuMi4xLjEgJUl0ZXJhdG9yUHJvdG90eXBlJVtAQGl0ZXJhdG9yXSgpXG5yZXF1aXJlKCcuLyQuaGlkZScpKEl0ZXJhdG9yUHJvdG90eXBlLCByZXF1aXJlKCcuLyQud2tzJykoJ2l0ZXJhdG9yJyksIGZ1bmN0aW9uKCl7IHJldHVybi
23459B0aGlzOyB9KTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCl7XG4gIENvbnN0cnVjdG9yLnByb3RvdHlwZSA9ICQuY3JlYXRlKEl0ZXJhdG9yUHJvdG90eXBlLCB7bmV4dDogZGVzY3JpcHRvcigxLCBuZXh0KX0pO1xuICBzZXRUb1N0cmluZ1RhZyhDb25zdHJ1Y3RvciwgTkFNRSArICcgSXRlcmF0b3InKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xudmFyIExJQlJBUlkgICAgICAgID0gcmVxdWlyZSgnLi8kLmxpYnJhcnknKVxuICAsICRleHBvcnQgICAgICAgID0gcmVxdWlyZSgnLi8kLmV4cG9ydCcpXG4gICwgcmVkZWZpbmUgICAgICAgPSByZXF1aXJlKCcuLyQucmVkZWZpbmUnKVxuICAsIGhpZGUgICAgICAgICAgID0gcmVxdWlyZSgnLi8kLmhpZGUnKVxuICAsIGhhcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi8kLmhhcycpXG4gICwgSXRlcmF0b3JzICAgICAgPSByZXF1aXJlKCcuLyQuaXRlcmF0b3JzJylcbiAgLCAkaXRlckNyZWF0ZSAgICA9IHJlcXVpcmUoJy4vJC5pdGVyLWNyZWF0ZScpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuLyQuc2V0LXRvLXN0cmluZy10YWcnKVxuICAsIGdldFByb3RvICAgICAgID0gcmVxdWlyZSgnLi8kJykuZ2V0UHJvdG9cbiAgLCBJVEVSQVRPUiAgICAgICA9IHJlcXVpcmUoJy4vJC53a3MnKSgnaXRlcmF0b3InKVxuICAsIEJVR0dZICAgICAgICAgID0gIShbXS5rZXlzICYmICduZXh0JyBpbiBbXS5rZXlzKCkpIC8vIFNhZmFyaSBoYXMgYnVnZ3kgaXRlcmF0b3JzIHcvbyBgbmV4dGBcbiAgLCBGRl9JVEVSQVRPUiAgICA9ICdAQGl0ZXJhdG9yJ1xuICAsIEtFWVMgICAgICAgICAgID0gJ2tleXMnXG4gICwgVkFMVUVTICAgICAgICAgPSAndmFsdWVzJztcblxudmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbigpeyByZXR1cm4gdGhpczsgfTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihCYXNlLCBOQU1FLCBDb25zdHJ1Y3RvciwgbmV4dCwgREVGQVVMVCwgSVNfU0VULCBGT1JDRUQpe1xuICAkaXRlckNyZWF0ZShDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCk7XG4gIHZhciBnZXRNZXRob2QgPSBmdW5jdGlvbihraW5kKXtcbiAgICBpZighQlVHR1kgJiYga2luZCBpbiBwcm90bylyZXR1cm4gcHJvdG9ba2luZF07XG4gICAgc3dpdGNoKGtpbmQpe1xuICAgICAgY2FzZSBLRVlTOiByZXR1cm4gZnVuY3Rpb24ga2V5cygpeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICAgICAgY2FzZSBWQUxVRVM6IHJldHVybiBmdW5jdGlvbiB2YWx1ZXMoKXsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgICB9IHJldHVybiBmdW5jdGlvbiBlbnRyaWVzKCl7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gIH07XG4gIHZhciBUQUcgICAgICAgID0gTkFNRSArICcgSXRlcmF0b3InXG4gICAgLCBERUZfVkFMVUVTID0gREVGQVVMVCA9PSBWQUxVRVNcbiAgICAsIFZBTFVFU19CVUcgPSBmYWxzZVxuICAgICwgcHJvdG8gICAgICA9IEJhc2UucHJvdG90eXBlXG4gICAgLCAkbmF0aXZlICAgID0gcHJvdG9bSVRFUkFUT1JdIHx8IHByb3RvW0ZGX0lURVJBVE9SXSB8fCBERUZBVUxUICYmIHByb3RvW0RFRkFVTFRdXG4gICAgLCAkZGVmYXVsdCAgID0gJG5hdGl2ZSB8fCBnZXRNZXRob2QoREVGQVVMVClcbiAgICAsIG1ldGhvZHMsIGtleTtcbiAgLy8gRml4IG5hdGl2ZVxuICBpZigkbmF0aXZlKXtcbiAgICB2YXIgSXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90bygkZGVmYXVsdC5jYWxsKG5ldyBCYXNlKSk7XG4gICAgLy8gU2V0IEBAdG9TdHJpbmdUYWcgdG8gbmF0aXZlIGl0ZXJhdG9yc1xuICAgIHNldFRvU3RyaW5nVGFnKEl0ZXJhdG9yUHJvdG90eXBlLCBUQUcsIHRydWUpO1xuICAgIC8vIEZGIGZpeFxuICAgIGlmKCFMSUJSQVJZICYmIGhhcyhwcm90bywgRkZfSVRFUkFUT1IpKWhpZGUoSXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SLCByZXR1cm5UaGlzKTtcbiAgICAvLyBmaXggQXJyYXkje3ZhbHVlcywgQEBpdGVyYXRvcn0ubmFtZSBpbiBWOCAvIEZGXG4gICAgaWYoREVGX1ZBTFVFUyAmJiAkbmF0aXZlLm5hbWUgIT09IFZBTFVFUyl7XG4gICAgICBWQUxVRVNfQlVHID0gdHJ1ZTtcbiAgICAgICRkZWZhdWx0ID0gZnVuY3Rpb24gdmFsdWVzKCl7IHJldHVybiAkbmF0aXZlLmNhbGwodGhpcyk7IH07XG4gICAgfVxuICB9XG4gIC8vIERlZmluZSBpdGVyYXRvclxuICBpZigoIUxJQlJBUlkgfHwgRk9SQ0VEKSAmJiAoQlVHR1kgfHwgVkFMVUVTX0JVRyB8fCAhcHJvdG9bSVRFUkFUT1JdKSl7XG4gICAgaGlkZShwcm90bywgSVRFUkFUT1IsICRkZWZhdWx0KTtcbiAgfVxuICAvLyBQbHVnIGZvciBsaWJyYXJ5XG4gIEl0ZXJhdG9yc1tOQU1FXSA9ICRkZWZhdWx0O
234591xuICBJdGVyYXRvcnNbVEFHXSAgPSByZXR1cm5UaGlzO1xuICBpZihERUZBVUxUKXtcbiAgICBtZXRob2RzID0ge1xuICAgICAgdmFsdWVzOiAgREVGX1ZBTFVFUyAgPyAkZGVmYXVsdCA6IGdldE1ldGhvZChWQUxVRVMpLFxuICAgICAga2V5czogICAgSVNfU0VUICAgICAgPyAkZGVmYXVsdCA6IGdldE1ldGhvZChLRVlTKSxcbiAgICAgIGVudHJpZXM6ICFERUZfVkFMVUVTID8gJGRlZmF1bHQgOiBnZXRNZXRob2QoJ2VudHJpZXMnKVxuICAgIH07XG4gICAgaWYoRk9SQ0VEKWZvcihrZXkgaW4gbWV0aG9kcyl7XG4gICAgICBpZighKGtleSBpbiBwcm90bykpcmVkZWZpbmUocHJvdG8sIGtleSwgbWV0aG9kc1trZXldKTtcbiAgICB9IGVsc2UgJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LkYgKiAoQlVHR1kgfHwgVkFMVUVTX0JVRyksIE5BTUUsIG1ldGhvZHMpO1xuICB9XG4gIHJldHVybiBtZXRob2RzO1xufTsiLCJ2YXIgSVRFUkFUT1IgICAgID0gcmVxdWlyZSgnLi8kLndrcycpKCdpdGVyYXRvcicpXG4gICwgU0FGRV9DTE9TSU5HID0gZmFsc2U7XG5cbnRyeSB7XG4gIHZhciByaXRlciA9IFs3XVtJVEVSQVRPUl0oKTtcbiAgcml0ZXJbJ3JldHVybiddID0gZnVuY3Rpb24oKXsgU0FGRV9DTE9TSU5HID0gdHJ1ZTsgfTtcbiAgQXJyYXkuZnJvbShyaXRlciwgZnVuY3Rpb24oKXsgdGhyb3cgMjsgfSk7XG59IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZXhlYywgc2tpcENsb3Npbmcpe1xuICBpZighc2tpcENsb3NpbmcgJiYgIVNBRkVfQ0xPU0lORylyZXR1cm4gZmFsc2U7XG4gIHZhciBzYWZlID0gZmFsc2U7XG4gIHRyeSB7XG4gICAgdmFyIGFyciAgPSBbN11cbiAgICAgICwgaXRlciA9IGFycltJVEVSQVRPUl0oKTtcbiAgICBpdGVyLm5leHQgPSBmdW5jdGlvbigpeyByZXR1cm4ge2RvbmU6IHNhZmUgPSB0cnVlfTsgfTtcbiAgICBhcnJbSVRFUkFUT1JdID0gZnVuY3Rpb24oKXsgcmV0dXJuIGl0ZXI7IH07XG4gICAgZXhlYyhhcnIpO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG4gIHJldHVybiBzYWZlO1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGRvbmUsIHZhbHVlKXtcbiAgcmV0dXJuIHt2YWx1ZTogdmFsdWUsIGRvbmU6ICEhZG9uZX07XG59OyIsIm1vZHVsZS5leHBvcnRzID0ge307IiwidmFyICRPYmplY3QgPSBPYmplY3Q7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY3JlYXRlOiAgICAgJE9iamVjdC5jcmVhdGUsXG4gIGdldFByb3RvOiAgICRPYmplY3QuZ2V0UHJvdG90eXBlT2YsXG4gIGlzRW51bTogICAgIHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlLFxuICBnZXREZXNjOiAgICAkT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixcbiAgc2V0RGVzYzogICAgJE9iamVjdC5kZWZpbmVQcm9wZXJ0eSxcbiAgc2V0RGVzY3M6ICAgJE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzLFxuICBnZXRLZXlzOiAgICAkT2JqZWN0LmtleXMsXG4gIGdldE5hbWVzOiAgICRPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyxcbiAgZ2V0U3ltYm9sczogJE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMsXG4gIGVhY2g6ICAgICAgIFtdLmZvckVhY2hcbn07IiwibW9kdWxlLmV4cG9ydHMgPSB0cnVlOyIsInZhciBnbG9iYWwgICAgPSByZXF1aXJlKCcuLyQuZ2xvYmFsJylcbiAgLCBtYWNyb3Rhc2sgPSByZXF1aXJlKCcuLyQudGFzaycpLnNldFxuICAsIE9ic2VydmVyICA9IGdsb2JhbC5NdXRhdGlvbk9ic2VydmVyIHx8IGdsb2JhbC5XZWJLaXRNdXRhdGlvbk9ic2VydmVyXG4gICwgcHJvY2VzcyAgID0gZ2xvYmFsLnByb2Nlc3NcbiAgLCBQcm9taXNlICAgPSBnbG9iYWwuUHJvbWlzZVxuICAsIGlzTm9kZSAgICA9IHJlcXVpcmUoJy4vJC5jb2YnKShwcm9jZXNzKSA9PSAncHJvY2VzcydcbiAgLCBoZWFkLCBsYXN0LCBub3RpZnk7XG5cbnZhciBmbHVzaCA9IGZ1bmN0aW9uKCl7XG4gIHZhciBwYXJlbnQsIGRvbWFpbiwgZm47XG4gIGlmKGlzTm9kZSAmJiAocGFyZW50ID0gcHJvY2Vzcy5kb21haW4pKXtcbiAgICBwcm9jZXNzLmRvbWFpbiA9IG51bGw7XG4gICAgcGFyZW50LmV4aXQoKTtcbiAgfVxuICB3aGlsZShoZWFkKXtcbiAgICBkb21haW4gPSBoZWFkLmRvbWFpbjtcbiAgICBmbiAgICAgPSBoZWFkLmZuO1xuICAgIGlmKGRvbWFpbilkb21haW4uZW50ZXIoKTtcbiAgICBmbigpOyAvLyA8LSBjdXJyZW50bHkgd2UgdXNlIGl0IG9ubHkgZm9yIFByb21pc2UgLSB0cnkgLyBjYXRjaCBub3QgcmVxdWlyZWRcbiAgICBpZihkb21haW4pZG9tYWluLmV4aXQoKTtcbiAgICBoZWFkID0gaGVhZC5uZXh0O1xuICB9IGxhc3QgPSB1bmRlZmluZWQ7XG4gIGlmKHBhcmVudClwYXJlbnQuZW50ZXIoKTtcbn07XG5cbi8vIE5vZGUuanNcbmlmKGlzTm9kZSl7XG4gIG5vdGlmeSA9IGZ1bmN0aW9uKCl7XG4gICAgcHJvY2Vzcy5uZXh0VGljayhmbHVzaCk7XG4gIH07XG4vLyBicm93c2VycyB3aXRoIE11dGF0aW9uT2JzZXJ2ZXJcbn0gZWxzZSBpZihPYnNlcnZlcil7XG4gIHZhciB0b2dnbGUgPSAxXG4gICAgLCBub2RlICAgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gIG5ldyBPYnNlcnZlcihmbHVzaCkub2JzZXJ2ZShub2RlLCB7Y2hhcmFjdGVyRGF0YTogdHJ1ZX0pOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLW5ld1xuICBub3RpZnkgPSBmdW5jdGlvbigpe1xuICAgIG5vZGUuZGF0YSA9IHRvZ2dsZSA9IC10b2dnbGU7XG4gIH07XG4vLyBlbnZpcm9ubWVudHMgd2l0aCBtYXliZSBub24tY29tcGxldGVseSBjb3JyZWN0LCBidXQgZXhpc3RlbnQgUHJvbWlzZVxufSBlbHNlIGlmKFByb21pc2UgJiYgUHJvbWlzZS5yZXNvbHZlKXtcbiAgbm90aWZ5ID0gZnVuY3Rpb24oKXtcbiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZsdXNoKTtcbiAgfTtcbi8vIGZvciBvdGhlciBlbnZpcm9ubWVudHMgLSBtYWNyb3Rhc2sgYmFzZWQgb246XG4vLyAtIHNldEltbWVkaWF0ZVxuLy8gLSBNZXNzYWdlQ2hhbm5lbFxuLy8gLSB3aW5kb3cucG9zdE1lc3NhZ1xuLy8gLSBvbnJlYWR5c3RhdGVjaGFuZ2Vcbi8vIC0gc2V0VGltZW91dFxufSBlbHNlIHtcbiAgbm90aWZ5ID0gZnVuY3Rpb24oKXtcbiAgICAvLyBzdHJhbmdlIElFICsgd2VicGFjayBkZXYgc2VydmVyIGJ1ZyAtIHVzZSAuY2FsbChnbG9iYWwpXG4gICAgbWFjcm90YXNrLmNhbGwoZ2xvYmFsLCBmbHVzaCk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYXNhcChmbil7XG4gIHZhciB0YXNrID0ge2ZuOiBmbiwgbmV4dDogdW5kZWZpbmVkLCBkb21haW46IGlzTm9kZSAmJiBwcm9jZXNzLmRvbWFpbn07XG4gIGlmKGxhc3QpbGFzdC5uZXh0ID0gdGFzaztcbiAgaWYoIWhlYWQpe1xuICAgIGhlYWQgPSB0YXNrO1xuICAgIG5vdGlmeSgpO1xuICB9IGxhc3QgPSB0YXNrO1xufTsiLCIvLyAxOS4xLjIuMSBPYmplY3QuYXNzaWduKHRhcmdldCwgc291cmNlLCAuLi4pXG52YXIgJCAgICAgICAgPSByZXF1aXJlKCcuLyQnKVxuICAsIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi8kLnRvLW9iamVjdCcpXG4gICwgSU9iamVjdCAgPSByZXF1aXJlKCcuLyQuaW9iamVjdCcpO1xuXG4vLyBzaG91bGQgd29yayB3aXRoIHN5bWJvbHMgYW5kIHNob3VsZCBoYXZlIGRldGVybWluaXN0aWMgcHJvcGVydHkgb3JkZXIgKFY4IGJ1Zylcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi8kLmZhaWxzJykoZnVuY3Rpb24oKXtcbiAgdmFyIGEgPSBPYmplY3QuYXNzaWduXG4gICAgLCBBID0ge31cbiAgICAsIEIgPSB7fVxuICAgICwgUyA9IFN5bWJvbCgpXG4gICAgLCBLID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0JztcbiAgQVtTXSA9IDc7XG4gIEsuc3BsaXQoJycpLmZvckVhY2goZnVuY3Rpb24oayl7IEJba10gPSBrOyB9KTtcbiAgcmV0dXJuIGEoe30sIEEpW1NdICE9IDcgfHwgT2JqZWN0LmtleXMoYSh7fSwgQikpLmpvaW4oJycpICE9IEs7XG59
23459KSA/IGZ1bmN0aW9uIGFzc2lnbih0YXJnZXQsIHNvdXJjZSl7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgdmFyIFQgICAgID0gdG9PYmplY3QodGFyZ2V0KVxuICAgICwgJCQgICAgPSBhcmd1bWVudHNcbiAgICAsICQkbGVuID0gJCQubGVuZ3RoXG4gICAgLCBpbmRleCA9IDFcbiAgICAsIGdldEtleXMgICAgPSAkLmdldEtleXNcbiAgICAsIGdldFN5bWJvbHMgPSAkLmdldFN5bWJvbHNcbiAgICAsIGlzRW51bSAgICAgPSAkLmlzRW51bTtcbiAgd2hpbGUoJCRsZW4gPiBpbmRleCl7XG4gICAgdmFyIFMgICAgICA9IElPYmplY3QoJCRbaW5kZXgrK10pXG4gICAgICAsIGtleXMgICA9IGdldFN5bWJvbHMgPyBnZXRLZXlzKFMpLmNvbmNhdChnZXRTeW1ib2xzKFMpKSA6IGdldEtleXMoUylcbiAgICAgICwgbGVuZ3RoID0ga2V5cy5sZW5ndGhcbiAgICAgICwgaiAgICAgID0gMFxuICAgICAgLCBrZXk7XG4gICAgd2hpbGUobGVuZ3RoID4gailpZihpc0VudW0uY2FsbChTLCBrZXkgPSBrZXlzW2orK10pKVRba2V5XSA9IFNba2V5XTtcbiAgfVxuICByZXR1cm4gVDtcbn0gOiBPYmplY3QuYXNzaWduOyIsIi8vIG1vc3QgT2JqZWN0IG1ldGhvZHMgYnkgRVM2IHNob3VsZCBhY2NlcHQgcHJpbWl0aXZlc1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuLyQuZXhwb3J0JylcbiAgLCBjb3JlICAgID0gcmVxdWlyZSgnLi8kLmNvcmUnKVxuICAsIGZhaWxzICAgPSByZXF1aXJlKCcuLyQuZmFpbHMnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oS0VZLCBleGVjKXtcbiAgdmFyIGZuICA9IChjb3JlLk9iamVjdCB8fCB7fSlbS0VZXSB8fCBPYmplY3RbS0VZXVxuICAgICwgZXhwID0ge307XG4gIGV4cFtLRVldID0gZXhlYyhmbik7XG4gICRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogZmFpbHMoZnVuY3Rpb24oKXsgZm4oMSk7IH0pLCAnT2JqZWN0JywgZXhwKTtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihiaXRtYXAsIHZhbHVlKXtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlICA6ICEoYml0bWFwICYgMSksXG4gICAgY29uZmlndXJhYmxlOiAhKGJpdG1hcCAmIDIpLFxuICAgIHdyaXRhYmxlICAgIDogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZSAgICAgICA6IHZhbHVlXG4gIH07XG59OyIsInZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4vJC5yZWRlZmluZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0YXJnZXQsIHNyYyl7XG4gIGZvcih2YXIga2V5IGluIHNyYylyZWRlZmluZSh0YXJnZXQsIGtleSwgc3JjW2tleV0pO1xuICByZXR1cm4gdGFyZ2V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vJC5oaWRlJyk7IiwiLy8gNy4yLjkgU2FtZVZhbHVlKHgsIHkpXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5pcyB8fCBmdW5jdGlvbiBpcyh4LCB5KXtcbiAgcmV0dXJuIHggPT09IHkgPyB4ICE9PSAwIHx8IDEgLyB4ID09PSAxIC8geSA6IHggIT0geCAmJiB5ICE9IHk7XG59OyIsIi8vIFdvcmtzIHdpdGggX19wcm90b19fIG9ubHkuIE9sZCB2OCBjYW4ndCB3b3JrIHdpdGggbnVsbCBwcm90byBvYmplY3RzLlxuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cbnZhciBnZXREZXNjICA9IHJlcXVpcmUoJy4vJCcpLmdldERlc2NcbiAgLCBpc09iamVjdCA9IHJlcXVpcmUoJy4vJC5pcy1vYmplY3QnKVxuICAsIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi8kLmFuLW9iamVjdCcpO1xudmFyIGNoZWNrID0gZnVuY3Rpb24oTywgcHJvdG8pe1xuICBhbk9iamVjdChPKTtcbiAgaWYoIWlzT2JqZWN0KHByb3RvKSAmJiBwcm90byAhPT0gbnVsbCl0aHJvdyBUeXBlRXJyb3IocHJvdG8gKyBcIjogY2FuJ3Qgc2V0IGFzIHByb3RvdHlwZSFcIik7XG59O1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNldDogT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8ICgnX19wcm90b19fJyBpbiB7fSA/IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcbiAgICBmdW5jdGlvbih0ZXN0LCBidWdneSwgc2V0KXtcbiAgICAgIHRyeSB7XG4gICAgICAgIHNldCA9IHJlcXVpcmUoJy4vJC5jdHgnKShGdW5jdGlvbi5jYWxsLCBnZXREZXNjKE9iamVjdC5wcm90b3R5cGUsICdfX3Byb3RvX18nKS5zZXQsIDIpO1xuICAgICAgICBzZXQodGVzdCwgW10pO1xuICAgICAgICBidWdneSA9ICEodGVzdCBpbnN0YW5jZW9mIEFycmF5KTtcbiAgICAgIH0gY2F0Y2goZSl7IGJ1Z2d5ID0gdHJ1ZTsgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uIHNldFByb3RvdHlwZU9mKE8sIHByb3RvKXtcbiAgICAgICAgY2hlY2soTywgcHJvdG8pO1xuICAgICAgICBpZihidWdneSlPLl9fcHJvdG9fXyA9IHByb3RvO1xuICAgICAgICBlbHNlIHNldChPLCBwcm90byk7XG4gICAgICAgIHJldHVybiBPO1xuICAgICAgfTtcbiAgICB9KHt9LCBmYWxzZSkgOiB1bmRlZmluZWQpLFxuICBjaGVjazogY2hlY2tcbn07IiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNvcm
23459UgICAgICAgID0gcmVxdWlyZSgnLi8kLmNvcmUnKVxuICAsICQgICAgICAgICAgID0gcmVxdWlyZSgnLi8kJylcbiAgLCBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4vJC5kZXNjcmlwdG9ycycpXG4gICwgU1BFQ0lFUyAgICAgPSByZXF1aXJlKCcuLyQud2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihLRVkpe1xuICB2YXIgQyA9IGNvcmVbS0VZXTtcbiAgaWYoREVTQ1JJUFRPUlMgJiYgQyAmJiAhQ1tTUEVDSUVTXSkkLnNldERlc2MoQywgU1BFQ0lFUywge1xuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiB0aGlzOyB9XG4gIH0pO1xufTsiLCJ2YXIgZGVmID0gcmVxdWlyZSgnLi8kJykuc2V0RGVzY1xuICAsIGhhcyA9IHJlcXVpcmUoJy4vJC5oYXMnKVxuICAsIFRBRyA9IHJlcXVpcmUoJy4vJC53a3MnKSgndG9TdHJpbmdUYWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCwgdGFnLCBzdGF0KXtcbiAgaWYoaXQgJiYgIWhhcyhpdCA9IHN0YXQgPyBpdCA6IGl0LnByb3RvdHlwZSwgVEFHKSlkZWYoaXQsIFRBRywge2NvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHRhZ30pO1xufTsiLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpXG4gICwgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXydcbiAgLCBzdG9yZSAgPSBnbG9iYWxbU0hBUkVEXSB8fCAoZ2xvYmFsW1NIQVJFRF0gPSB7fSk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGtleSl7XG4gIHJldHVybiBzdG9yZVtrZXldIHx8IChzdG9yZVtrZXldID0ge30pO1xufTsiLCIvLyA3LjMuMjAgU3BlY2llc0NvbnN0cnVjdG9yKE8sIGRlZmF1bHRDb25zdHJ1Y3RvcilcbnZhciBhbk9iamVjdCAgPSByZXF1aXJlKCcuLyQuYW4tb2JqZWN0JylcbiAgLCBhRnVuY3Rpb24gPSByZXF1aXJlKCcuLyQuYS1mdW5jdGlvbicpXG4gICwgU1BFQ0lFUyAgID0gcmVxdWlyZSgnLi8kLndrcycpKCdzcGVjaWVzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKE8sIEQpe1xuICB2YXIgQyA9IGFuT2JqZWN0KE8pLmNvbnN0cnVjdG9yLCBTO1xuICByZXR1cm4gQyA9PT0gdW5kZWZpbmVkIHx8IChTID0gYW5PYmplY3QoQylbU1BFQ0lFU10pID09IHVuZGVmaW5lZCA/IEQgOiBhRnVuY3Rpb24oUyk7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQsIENvbnN0cnVjdG9yLCBuYW1lKXtcbiAgaWYoIShpdCBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSl0aHJvdyBUeXBlRXJyb3IobmFtZSArIFwiOiB1c2UgdGhlICduZXcnIG9wZXJhdG9yIVwiKTtcbiAgcmV0dXJuIGl0O1xufTsiLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi8kLnRvLWludGVnZXInKVxuICAsIGRlZmluZWQgICA9IHJlcXVpcmUoJy4vJC5kZWZpbmVkJyk7XG4vLyB0cnVlICAtPiBTdHJpbmcjYXRcbi8vIGZhbHNlIC0+IFN0cmluZyNjb2RlUG9pbnRBdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihUT19TVFJJTkcpe1xuICByZXR1cm4gZnVuY3Rpb24odGhhdCwgcG9zKXtcbiAgICB2YXIgcyA9IFN0cmluZyhkZWZpbmVkKHRoYXQpKVxuICAgICAgLCBpID0gdG9JbnRlZ2VyKHBvcylcbiAgICAgICwgbCA9IHMubGVuZ3RoXG4gICAgICAsIGEsIGI7XG4gICAgaWYoaSA8IDAgfHwgaSA+PSBsKXJldHVybiBUT19TVFJJTkcgPyAnJyA6IHVuZGVmaW5lZDtcbiAgICBhID0gcy5jaGFyQ29kZUF0KGkpO1xuICAgIHJldHVybiBhIDwgMHhkODAwIHx8IGEgPiAweGRiZmYgfHwgaSArIDEgPT09IGwgfHwgKGIgPSBzLmNoYXJDb2RlQXQoaSArIDEpKSA8IDB4ZGMwMCB8fCBiID4gMHhkZmZmXG4gICAgICA/IFRPX1NUUklORyA/IHMuY2hhckF0KGkpIDogYVxuICAgICAgOiBUT19TVFJJTkcgPyBzLnNsaWNlKGksIGkgKyAyKSA6IChhIC0gMHhkODAwIDw8IDEwKSArIChiIC0gMHhkYzAwKSArIDB4MTAwMDA7XG4gIH07XG59OyIsInZhciBjdHggICAgICAgICAgICAgICAgPSByZXF1aXJlKCcuLyQuY3R4JylcbiAgLCBpbnZva2UgICAgICAgICAgICAgPSByZXF1aXJlKCcuLyQuaW52b2tlJylcbiAgLCBodG1sICAgICAgICAgICAgICAgPSByZXF1aXJlKCcuLyQuaHRtbCcpXG4gICwgY2VsICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi8kLmRvbS1jcmVhdGUnKVxuICAsIGdsb2JhbCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vJC5nbG9iYWwnKVxuICAsIHByb2Nlc3MgICAgICAgICAgICA9IGdsb2JhbC5wcm9jZXNzXG4gICwgc2V0VGFzayAgICAgICAgICAgID0gZ2xvYmFsLnNldEltbWVkaWF0ZVxuICAsIGNsZWFyVGFzayAgICAgICAgICA9IGdsb2JhbC5jbGVhckltbWVkaWF0ZVxuICAsIE1lc3NhZ2VDaGFubmVsICAgICA9IGdsb2JhbC5NZXNzYWdlQ2hhbm5lbFxuICAsIGNvdW50ZXIgICAgICAgICAgICA9IDBcbiAgLCBxdWV1ZSAgICAgICAgICAgICAgPSB7fVxuICAsIE9OUkVBRFlTVEFURUNIQU5HRSA9ICdvbnJlYWR5c3RhdGVjaGFuZ2UnXG4gICwgZGVmZXIsIGNoYW5uZWwsIHBvcnQ7XG52YXIgcnVuID0gZnVuY3Rpb24oKXtcbiAgdmFyIGlkID0gK3RoaXM7XG4gIGlmKHF1ZXVlLmhhc093blByb3BlcnR5KGlkKSl7XG4gICAgdmFyIGZuID0gcXVldWVbaWRdO1xuICAgIGRlbGV0ZSBxdWV1ZVtpZF07XG4gICAgZm4oKTtcbiAgfVxufTtcbnZhciBsaXN0bmVyID0gZnVuY3Rpb24oZXZlbnQpe1xuICBydW4uY2FsbChldmVudC5kYXRhKTtcbn07XG4vLyBOb2RlLmpzIDAuOSsgJiBJRTEwKyBoYXMgc2V0SW1tZWRpYXRlLCBvdGhlcndpc2U6XG5pZighc2V0VGFzayB8fCAhY2xlYXJUYXNrKXtcbiAgc2V0VGFzayA9IGZ1bmN0aW9uIHNldEltbWVkaWF0ZShmbil7XG4gICAgdmFyIGFyZ3MgPSBbXSwgaSA9IDE7XG4gICAgd2hpbGUoYXJndW1lbnRzLmxlbmd0aCA+IGkpYXJncy5wdXNoKGFyZ3VtZW50c1tpKytdKTtcbiAgICBxdWV1ZVsrK2NvdW50ZXJdID0gZnVuY3Rpb24oKXtcbiAgICAgIGludm9rZSh0eXBlb2YgZm4gPT0gJ2Z1bmN0aW9uJyA/IGZuIDogRnVuY3Rpb24oZm4pLCBhcmdzKTtcbiAgICB9O1xuICAgIGRlZmVyKGNvdW50ZXIpO1xuICAgIHJldHVybi
23459Bjb3VudGVyO1xuICB9O1xuICBjbGVhclRhc2sgPSBmdW5jdGlvbiBjbGVhckltbWVkaWF0ZShpZCl7XG4gICAgZGVsZXRlIHF1ZXVlW2lkXTtcbiAgfTtcbiAgLy8gTm9kZS5qcyAwLjgtXG4gIGlmKHJlcXVpcmUoJy4vJC5jb2YnKShwcm9jZXNzKSA9PSAncHJvY2Vzcycpe1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgcHJvY2Vzcy5uZXh0VGljayhjdHgocnVuLCBpZCwgMSkpO1xuICAgIH07XG4gIC8vIEJyb3dzZXJzIHdpdGggTWVzc2FnZUNoYW5uZWwsIGluY2x1ZGVzIFdlYldvcmtlcnNcbiAgfSBlbHNlIGlmKE1lc3NhZ2VDaGFubmVsKXtcbiAgICBjaGFubmVsID0gbmV3IE1lc3NhZ2VDaGFubmVsO1xuICAgIHBvcnQgICAgPSBjaGFubmVsLnBvcnQyO1xuICAgIGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gbGlzdG5lcjtcbiAgICBkZWZlciA9IGN0eChwb3J0LnBvc3RNZXNzYWdlLCBwb3J0LCAxKTtcbiAgLy8gQnJvd3NlcnMgd2l0aCBwb3N0TWVzc2FnZSwgc2tpcCBXZWJXb3JrZXJzXG4gIC8vIElFOCBoYXMgcG9zdE1lc3NhZ2UsIGJ1dCBpdCdzIHN5bmMgJiB0eXBlb2YgaXRzIHBvc3RNZXNzYWdlIGlzICdvYmplY3QnXG4gIH0gZWxzZSBpZihnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lciAmJiB0eXBlb2YgcG9zdE1lc3NhZ2UgPT0gJ2Z1bmN0aW9uJyAmJiAhZ2xvYmFsLmltcG9ydFNjcmlwdHMpe1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKGlkICsgJycsICcqJyk7XG4gICAgfTtcbiAgICBnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGxpc3RuZXIsIGZhbHNlKTtcbiAgLy8gSUU4LVxuICB9IGVsc2UgaWYoT05SRUFEWVNUQVRFQ0hBTkdF
23459IGluIGNlbCgnc2NyaXB0Jykpe1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgaHRtbC5hcHBlbmRDaGlsZChjZWwoJ3NjcmlwdCcpKVtPTlJFQURZU1RBVEVDSEFOR0VdID0gZnVuY3Rpb24oKXtcbiAgICAgICAgaHRtbC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgICAgICAgcnVuLmNhbGwoaWQpO1xuICAgICAgfTtcbiAgICB9O1xuICAvLyBSZXN0IG9sZCBicm93c2Vyc1xuICB9IGVsc2Uge1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgc2V0VGltZW91dChjdHgocnVuLCBpZCwgMSksIDApO1xuICAgIH07XG4gIH1cbn1cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6ICAgc2V0VGFzayxcbiAgY2xlYXI6IGNsZWFyVGFza1xufTsiLCIvLyA3LjEuNCBUb0ludGVnZXJcbnZhciBjZWlsICA9IE1hdGguY2VpbFxuICAsIGZsb29yID0gTWF0aC5mbG9vcjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gaXNOYU4oaXQgPSAraXQpID8gMCA6IChpdCA+IDAgPyBmbG9vciA6IGNlaWwpKGl0KTtcbn07IiwiLy8gdG8gaW5kZXhlZCBvYmplY3QsIHRvT2JqZWN0IHdpdGggZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBzdHJpbmdzXG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vJC5pb2JqZWN0JylcbiAgLCBkZWZpbmVkID0gcmVxdWlyZSgnLi8kLmRlZmluZWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gSU9iamVjdChkZWZpbmVkKGl0KSk7XG59OyIsIi8vIDcuMS4xNSBUb0xlbmd0aFxudmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vJC50by1pbnRlZ2VyJylcbiAgLCBtaW4gICAgICAgPSBNYXRoLm1pbjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gaXQgPiAwID8gbWluKHRvSW50ZWdlcihpdCksIDB4MWZmZmZmZmZmZmZmZmYpIDogMDsgLy8gcG93KDIsIDUzKSAtIDEgPT0gOTAwNzE5OTI1NDc0MDk5MVxufTsiLCIvLyA3LjEuMTMgVG9PYmplY3QoYXJndW1lbnQpXG52YXIgZGVmaW5lZCA9IHJlcXVpcmUoJy4vJC5kZWZpbmVkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIE9iamVjdChkZWZpbmVkKGl0KSk7XG59OyIsInZhciBpZCA9IDBcbiAgLCBweCA9IE1hdGgucmFuZG9tKCk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGtleSl7XG4gIHJldHVybiAnU3ltYm9sKCcuY29uY2F0KGtleSA9PT0gdW5kZWZpbmVkID8gJycgOiBrZXksICcpXycsICgrK2lkICsgcHgpLnRvU3RyaW5nKDM2KSk7XG59OyIsInZhciBzdG9yZSAgPSByZXF1aXJlKCcuLyQuc2hhcmVkJykoJ3drcycpXG4gICwgdWlkICAgID0gcmVxdWlyZSgnLi8kLnVpZCcpXG4gICwgU3ltYm9sID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpLlN5bWJvbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obmFtZSl7XG4gIHJldHVybiBzdG9yZVtuYW1lXSB8fCAoc3RvcmVbbmFtZV0gPVxuICAgIFN5bWJvbCAmJiBTeW1ib2xbbmFtZV0gfHwgKFN5bWJvbCB8fCB1aWQpKCdTeW1ib2wuJyArIG5hbWUpKTtcbn07IiwidmFyIGNsYXNzb2YgICA9IHJlcXVpcmUoJy4vJC5jbGFzc29mJylcbiAgLCBJVEVSQVRPUiAgPSByZXF1aXJlKCcuLyQud2tzJykoJ2l0ZXJhdG9yJylcbiAgLCBJdGVyYXRvcnMgPSByZXF1aXJlKCcuLyQuaXRlcmF0b3JzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vJC5jb3JlJykuZ2V0SXRlcmF0b3JNZXRob2QgPSBmdW5jdGlvbihpdCl7XG4gIGlmKGl0ICE9IHVuZGVmaW5lZClyZXR1cm4gaXRbSVRFUkFUT1JdXG4gICAgfHwgaXRbJ0BAaXRlcmF0b3InXVxuICAgIHx8IEl0ZXJhdG9yc1tjbGFzc29mKGl0KV07XG59OyIsInZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vJC5hbi1vYmplY3QnKVxuICAsIGdldCAgICAgID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi8kLmNvcmUnKS5nZXRJdGVyYXRvciA9IGZ1bmN0aW9uKGl0KXtcbiAgdmFyIGl0ZXJGbiA9IGdldChpdCk7XG4gIGlmKHR5cGVvZiBpdGVyRm4gIT0gJ2Z1bmN0aW9uJyl0aHJvdyBUeXBlRXJyb3IoaXQgKyAnIGlzIG5vdCBpdGVyYWJsZSEnKTtcbiAgcmV0dXJuIGFuT2JqZWN0KGl0ZXJGbi5jYWxsKGl0KSk7XG59OyIsIid1c2Ugc3RyaWN0JztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi8kLmFkZC10by11bnNjb3BhYmxlcycpXG4gICwgc3RlcCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vJC5pdGVyLXN0ZXAnKVxuICAsIEl0ZXJhdG9ycyAgICAgICAgPSByZXF1aXJlKCcuLyQuaXRlcmF0b3JzJylcbiAgLCB0b0lPYmplY3QgICAgICAgID0gcmVxdWlyZSgnLi8kLnRvLWlvYmplY3QnKTtcblxuLy8gMjIuMS4zLjQgQXJyYXkucHJvdG90eXBlLmVudHJpZXMoKVxuLy8gMjIuMS4zLjEzIEFycmF5LnByb3RvdHlwZS5rZXlzKClcbi8vIDIyLjEuMy4yOSBBcnJheS5wcm90b3R5cGUudmFsdWVzKClcbi8vIDIyLjEuMy4zMCBBcnJheS5wcm90b3R5cGVbQEBpdGVyYXRvcl0oKVxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLyQuaXRlci1kZWZpbmUnKShBcnJheSwgJ0FycmF5JywgZnVuY3Rpb24oaXRlcmF0ZWQsIGtpbmQpe1xuICB0aGlzLl90ID0gdG9JT2JqZWN0KGl0ZXJhdGVkKTsgLy8gdGFyZ2V0XG4gIHRoaXMuX2kgPSAwOyAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGluZGV4XG4gIHRoaXMuX2sgPSBraW5kOyAgICAgICAgICAgICAgICAvLyBraW5kXG4vLyAyMi4xLjUuMi4xICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uKCl7XG4gIHZhciBPICAgICA9IHRoaXMuX3RcbiAgICAsIGtpbmQgID0gdGhpcy5fa1xuICAgICwgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmKCFPIHx8IGluZGV4ID49IE8ubGVuZ3RoKXtcbiAgICB0aGlzLl90ID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiBzdGVwKDEpO1xuICB9XG4gIGlmKGtpbmQgPT0gJ2tleXMnICApcmV0dXJuIHN0ZXAoMCwgaW5kZXgpO1xuICBpZihraW5kID09ICd2YWx1ZXMnKXJldHVybiBzdGVwKDAsIE9baW5kZXhdKTtcbiAgcmV0dXJuIHN0ZXAoMCwgW2luZGV4LCBPW2luZGV4XV0pO1xufSwgJ3ZhbHVlcycpO1xuXG4vLyBhcmd1bWVudHNMaXN0W0BAaXRlcmF0b3JdIGlzICVBcnJheVByb3RvX3ZhbHVlcyUgKDkuNC40LjYsIDkuNC40LjcpXG5JdGVyYXRvcnMuQXJndW1lbnRzID0gSXRlcmF0b3JzLkFycmF5O1xuXG5hZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCd2YWx1ZXMnKTtcbmFkZFRvVW5zY29wYWJsZXMoJ2VudHJpZXMnKTsiLCIvLyAxOS4xLjMuMSBPYmplY3QuYXNzaWduKHRhcmdldCwgc291cmNlKVxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuLyQuZXhwb3J0Jyk7XG5cbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GLCAnT2JqZWN0Jywge2Fzc2lnbjogcmVxdWlyZSgnLi8kLm9iamVjdC1hc3NpZ24nKX0pOyIsIi8vIDE5LjEuMi42IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUClcbnZhciB0b0lPYmplY3QgPSByZXF1aXJlKCcuLyQudG8taW9iamVjdCcpO1xuXG5yZXF1aXJlKCcuLyQub2JqZWN0LXNhcCcpKCdnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3InLCBmdW5jdGlvbigkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKXtcbiAgcmV0dXJuIGZ1bmN0aW9uIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihpdCwga2V5KXtcbiAgICByZXR1cm4gJGdldE93blByb3BlcnR5RGVzY3JpcHRvcih0b0lPYmplY3QoaXQpLCBrZXkpO1xuICB9O1xufSk7IiwiLy8gMTkuMS4yLjE0IE9iamVjdC5rZXlzKE8pXG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuLyQudG8tb2JqZWN0Jyk7XG5cbnJlcXVpcmUoJy4vJC5vYmplY3Qtc2FwJykoJ2tleXMnLCBmdW5jdGlvbigka2V5cyl7XG4gIHJldHVybi
23459BmdW5jdGlvbiBrZXlzKGl0KXtcbiAgICByZXR1cm4gJGtleXModG9PYmplY3QoaXQpKTtcbiAgfTtcbn0pOyIsIi8vIDE5LjEuMy4xOSBPYmplY3Quc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vJC5leHBvcnQnKTtcbiRleHBvcnQoJGV4cG9ydC5TLCAnT2JqZWN0Jywge3NldFByb3RvdHlwZU9mOiByZXF1aXJlKCcuLyQuc2V0LXByb3RvJykuc2V0fSk7IixudWxsLCIndXNlIHN0cmljdCc7XG52YXIgJCAgICAgICAgICA9IHJlcXVpcmUoJy4vJCcpXG4gICwgTElCUkFSWSAgICA9IHJlcXVpcmUoJy4vJC5saWJyYXJ5JylcbiAgLCBnbG9iYWwgICAgID0gcmVxdWlyZSgnLi8kLmdsb2JhbCcpXG4gICwgY3R4ICAgICAgICA9IHJlcXVpcmUoJy4vJC5jdHgnKVxuICAsIGNsYXNzb2YgICAgPSByZXF1aXJlKCcuLyQuY2xhc3NvZicpXG4gICwgJGV4cG9ydCAgICA9IHJlcXVpcmUoJy4vJC5leHBvcnQnKVxuICAsIGlzT2JqZWN0ICAgPSByZXF1aXJlKCcuLyQuaXMtb2JqZWN0JylcbiAgLCBhbk9iamVjdCAgID0gcmVxdWlyZSgnLi8kLmFuLW9iamVjdCcpXG4gICwgYUZ1bmN0aW9uICA9IHJlcXVpcmUoJy4vJC5hLWZ1bmN0aW9uJylcbiAgLCBzdHJpY3ROZXcgID0gcmVxdWlyZSgnLi8kLnN0cmljdC1uZXcnKVxuICAsIGZvck9mICAgICAgPSByZXF1aXJlKCcuLyQuZm9yLW9mJylcbiAgLCBzZXRQcm90byAgID0gcmVxdWlyZSgnLi8kLnNldC1wcm90bycpLnNldFxuICAsIHNhbWUgICAgICAgPSByZXF1aXJlKCcuLyQuc2FtZS12YWx1ZScpXG4gICwgU1BFQ0lFUyAgICA9IHJlcXVpcmUoJy4vJC53a3MnKSgnc3BlY2llcycpXG4gICwgc3BlY2llc0NvbnN0cnVjdG9yID0gcmVxdWlyZSgnLi8kLnNwZWNpZXMtY29uc3RydWN0b3InKVxuICAsIGFzYXAgICAgICAgPSByZXF1aXJlKCcuLyQubWljcm90YXNrJylcbiAgLCBQUk9NSVNFICAgID0gJ1Byb21pc2UnXG4gICwgcHJvY2VzcyAgICA9IGdsb2JhbC5wcm9jZXNzXG4gICwgaXNOb2RlICAgICA9IGNsYXNzb2YocHJvY2VzcykgPT0gJ3Byb2Nlc3MnXG4gICwgUCAgICAgICAgICA9IGdsb2JhbFtQUk9NSVNFXVxuICAsIGVtcHR5ICAgICAgPSBmdW5jdGlvbigpeyAvKiBlbXB0eSAqLyB9XG4gICwgV3JhcHBlcjtcblxudmFyIHRlc3RSZXNvbHZlID0gZnVuY3Rpb24oc3ViKXtcbiAgdmFyIHRlc3QgPSBuZXcgUChlbXB0eSksIHByb21pc2U7XG4gIGlmKHN1Yil0ZXN0LmNvbnN0cnVjdG9yID0gZnVuY3Rpb24oZXhlYyl7XG4gICAgZXhlYyhlbXB0eSwgZW1wdHkpO1xuICB9O1xuICAocHJvbWlzZSA9IFAucmVzb2x2ZSh0ZXN0KSlbJ2NhdGNoJ10oZW1wdHkpO1xuICByZXR1cm4gcHJvbWlzZSA9PT0gdGVzdDtcbn07XG5cbnZhciBVU0VfTkFUSVZFID0gZnVuY3Rpb24oKXtcbiAgdmFyIHdvcmtzID0gZmFsc2U7XG4gIGZ1bmN0aW9uIFAyKHgpe1xuICAgIHZhciBzZWxmID0gbmV3IFAoeCk7XG4gICAgc2V0UHJvdG8oc2VsZiwgUDIucHJvdG90eXBlKTtcbiAgICByZXR1cm4gc2VsZjtcbiAgfVxuICB0cnkge1xuICAgIHdvcmtzID0gUCAmJiBQLnJlc29sdmUgJiYgdGVzdFJlc29sdmUoKTtcbiAgICBzZXRQcm90byhQMiwgUCk7XG4gICAgUDIucHJvdG90eXBlID0gJC5jcmVhdGUoUC5wcm90b3R5cGUsIHtjb25zdHJ1Y3Rvcjoge3ZhbHVlOiBQMn19KTtcbiAgICAvLyBhY3R1YWwgRmlyZWZveCBoYXMgYnJva2VuIHN1YmNsYXNzIHN1cHBvcnQsIHRlc3QgdGhhdFxuICAgIGlmKCEoUDIucmVzb2x2ZSg1KS50aGVuKGZ1bmN0aW9uKCl7fSkgaW5zdGFuY2VvZiBQMikpe1xuICAgICAgd29ya3MgPSBmYWxzZTtcbiAgICB9XG4gICAgLy8gYWN0dWFsIFY4IGJ1ZywgaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTQxNjJcbiAgICBpZih3b3JrcyAmJiByZXF1aXJlKCcuLyQuZGVzY3JpcHRvcnMnKSl7XG4gICAgICB2Y
23459XIgdGhlbmFibGVUaGVuR290dGVuID0gZmFsc2U7XG4gICAgICBQLnJlc29sdmUoJC5zZXREZXNjKHt9LCAndGhlbicsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbigpeyB0aGVuYWJsZVRoZW5Hb3R0ZW4gPSB0cnVlOyB9XG4gICAgICB9KSk7XG4gICAgICB3b3JrcyA9IHRoZW5hYmxlVGhlbkdvdHRlbjtcbiAgICB9XG4gIH0gY2F0Y2goZSl7IHdvcmtzID0gZmFsc2U7IH1cbiAgcmV0dXJuIHdvcmtzO1xufSgpO1xuXG4vLyBoZWxwZXJzXG52YXIgc2FtZUNvbnN0cnVjdG9yID0gZnVuY3Rpb24oYSwgYil7XG4gIC8vIGxpYnJhcnkgd3JhcHBlciBzcGVjaWFsIGNhc2VcbiAgaWYoTElCUkFSWSAmJiBhID09PSBQICYmIGIgPT09IFdyYXBwZXIpcmV0dXJuIHRydWU7XG4gIHJldHVybiBzYW1lKGEsIGIpO1xufTtcbnZhciBnZXRDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uKEMpe1xuICB2YXIgUyA9IGFuT2JqZWN0KEMpW1NQRUNJRVNdO1xuICByZXR1cm4gUyAhPSB1bmRlZmluZWQgPyBTIDogQztcbn07XG52YXIgaXNUaGVuYWJsZSA9IGZ1bmN0aW9uKGl0KXtcbiAgdmFyIHRoZW47XG4gIHJldHVybiBpc09iamVjdChpdCkgJiYgdHlwZW9mICh0aGVuID0gaXQudGhlbikgPT0gJ2Z1bmN0aW9uJyA/IHRoZW4gOiBmYWxzZTtcbn07XG52YXIgUHJvbWlzZUNhcGFiaWxpdHkgPSBmdW5jdGlvbihDKXtcbiAgdmFyIHJlc29sdmUsIHJlamVjdDtcbiAgdGhpcy5wcm9taXNlID0gbmV3IEMoZnVuY3Rpb24oJCRyZXNvbHZlLCAkJHJlamVjdCl7XG4gICAgaWYocmVzb2x2ZSAhPT0gdW5kZWZpbmVkIHx8IHJlamVjdCAhPT0gdW5kZWZpbmVkKXRocm93IFR5cGVFcnJvcignQmFkIFByb21pc2UgY29uc3RydWN0b3InKTtcbiAgICByZXNvbHZlID0gJCRyZXNvbHZlO1xuICAgIHJlamVjdCAgPSAkJHJlamVjdDtcbiAgfSk7XG4gIHRoaXMucmVzb2x2ZSA9IGFGdW5jdGlvbihyZXNvbHZlKSxcbiAgdGhpcy5yZWplY3QgID0gYUZ1bmN0aW9uKHJlamVjdClcbn07XG52YXIgcGVyZm9ybSA9IGZ1bmN0aW9uKGV4ZWMpe1xuICB0cnkge1xuICAgIGV4ZWMoKTtcbiAgfSBjYXRjaChlKXtcbiAgICByZXR1cm4ge2Vycm9yOiBlfTtcbiAgfVxufTtcbnZhciBub3RpZnkgPSBmdW5jdGlvbihyZWNvcmQsIGlzUmVqZWN0KXtcbiAgaWYocmVjb3JkLm4pcmV0dXJuO1xuICByZWNvcmQubiA9IHRydWU7XG4gIHZhciBjaGFpbiA9IHJlY29yZC5jO1xuICBhc2FwKGZ1bmN0aW9uKCl7XG4gICAgdmFyIHZhbHVlID0gcmVjb3JkLnZcbiAgICAgICwgb2sgICAgPSByZWNvcmQucyA9PSAxXG4gICAgICAsIGkgICAgID0gMDtcbiAgICB2YXIgcnVuID0gZnVuY3Rpb24ocmVhY3Rpb24pe1xuICAgICAgdmFyIGhhbmRsZXIgPSBvayA/IHJlYWN0aW9uLm9rIDogcmVhY3Rpb24uZmFpbFxuICAgICAgICAsIHJlc29sdmUgPSByZWFjdGlvbi5yZXNvbHZlXG4gICAgICAgICwgcmVqZWN0ICA9IHJlYWN0aW9uLnJlamVjdFxuICAgICAgICAsIHJlc3VsdCwgdGhlbjtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmKGhhbmRsZXIpe1xuICAgICAgICAgIGlmKCFvaylyZWNvcmQuaCA9IHRydWU7XG4gICAgICAgICAgcmVzdWx0ID0gaGFuZGxlciA9PT0gdHJ1ZSA/IHZhbHVlIDogaGFuZGxlcih2YWx1ZSk7XG4gICAgICAgICAgaWYocmVzdWx0ID09PSByZWFjdGlvbi5wcm9taXNlKXtcbiAgICAgICAgICAgIHJlamVjdChUeXBlRXJyb3IoJ1Byb21pc2UtY2hhaW4gY3ljbGUnKSk7XG4gICAgICAgICAgfSBlbHNlIGlmKHRoZW4gPSBpc1RoZW5hYmxlKHJlc3VsdCkpe1xuICAgICAgICAgICAgdGhlbi5jYWxsKHJlc3VsdCwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICB9IGVsc2UgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGVsc2UgcmVqZWN0KHZhbHVlKTtcbiAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHdoaWxlKGNoYWluLmxlbmd0aCA+IGkpcnVuKGNoYWluW2krK10pOyAvLyB2YXJpYWJsZSBsZW5ndGggLSBjYW4ndCB1c2UgZm9yRWFjaFxuICAgIGNoYWluLmxlbmd0aCA9IDA7XG4gICAgcmVjb3JkLm4gPSBmYWxzZTtcbiAgICBpZihpc1JlamVjdClzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICB2Y
23459XIgcHJvbWlzZSA9IHJlY29yZC5wXG4gICAgICAgICwgaGFuZGxlciwgY29uc29sZTtcbiAgICAgIGlmKGlzVW5oYW5kbGVkKHByb21pc2UpKXtcbiAgICAgICAgaWYoaXNOb2RlKXtcbiAgICAgICAgICBwcm9jZXNzLmVtaXQoJ3VuaGFuZGxlZFJlamVjdGlvbicsIHZhbHVlLCBwcm9taXNlKTtcbiAgICAgICAgfSBlbHNlIGlmKGhhbmRsZXIgPSBnbG9iYWwub251bmhhbmRsZWRyZWplY3Rpb24pe1xuICAgICAgICAgIGhhbmRsZXIoe3Byb21pc2U6IHByb21pc2UsIHJlYXNvbjogdmFsdWV9KTtcbiAgICAgICAgfSBlbHNlIGlmKChjb25zb2xlID0gZ2xvYmFsLmNvbnNvbGUpICYmIGNvbnNvbGUuZXJyb3Ipe1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1VuaGFuZGxlZCBwcm9taXNlIHJlamVjdGlvbicsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSByZWNvcmQuYSA9IHVuZGVmaW5lZDtcbiAgICB9LCAxKTtcbiAgfSk7XG59O1xudmFyIGlzVW5oYW5kbGVkID0gZnVuY3Rpb24ocHJvbWlzZSl7XG4gIHZhciByZWNvcmQgPSBwcm9taXNlLl9kXG4gICAgLCBjaGFpbiAgPSByZWNvcmQuYSB8fCByZWNvcmQuY1xuICAgICwgaSAgICAgID0gMFxuICAgICwgcmVhY3Rpb247XG4gIGlmKHJlY29yZC5oKXJldHVybiBmYWxzZTtcbiAgd2hpbGUoY2hhaW4ubGVuZ3RoID4gaSl7XG4gICAgcmVhY3Rpb24gPSBjaGFpbltpKytdO1xuICAgIGlmKHJlYWN0aW9uLmZhaWwgfHwgIWlzVW5oYW5kbGVkKHJlYWN0aW9uLnByb21pc2UpKXJldHVybiBmYWxzZTtcbiAgfSByZXR1cm4gdHJ1ZTtcbn07XG52YXIgJHJlamVjdCA9IGZ1bmN0aW9uKHZhbHVlKXtcbiAgdmFyIHJlY29yZCA9IHRoaXM7XG4gIGlmKHJlY29yZC5kKXJldHVybjtcbiAgcmVjb3JkLmQgPSB0cnVlO1xuICByZWNvcmQgPSByZWNvcmQuciB8fCByZWNvcmQ7IC8vIHVud3JhcFxuICByZWNvcmQudiA9IHZhbHVlO1xuICByZWNvcmQucyA9IDI7XG4gIHJlY29yZC5hID0gcmVjb3JkLmMuc2xpY2UoKTtcbiAgbm90aWZ5KHJlY29yZCwgdHJ1ZSk7XG59O1xudmFyICRyZXNvbHZlID0gZnVuY3Rpb24odmFsdWUpe1xuICB2YXIgcmVjb3JkID0gdGhpc1xuICAgICwgdGhlbjtcbiAgaWYocmVjb3JkLmQpcmV0dXJuO1xuICByZWNvcmQuZCA9IHRydWU7XG4gIHJlY29yZCA9IHJlY29yZC5yIHx8IHJlY29yZDsgLy8gdW53cmFwXG4gIHRyeSB7XG4gICAgaWYocmVjb3JkLnAgPT09IHZhbHVlKXRocm93IFR5cGVFcnJvcihcIlByb21pc2UgY2FuJ3QgYmUgcmVzb2x2ZWQgaXRzZWxmXCIpO1xuICAgIGlmKHRoZW4gPSBpc1RoZW5hYmxlKHZhbHVlKSl7XG4gICAgICBhc2FwKGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhciB3cmFwcGVyID0ge3I6IHJlY29yZCwgZDogZmFsc2V9OyAvLyB3cmFwXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhlbi5jYWxsKHZhbHVlLCBjdHgoJHJlc29sdmUsIHdyYXBwZXIsIDEpLCBjdHgoJHJlamVjdCwgd3JhcHBlciwgMSkpO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICRyZWplY3QuY2FsbCh3cmFwcGVyLCBlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlY29yZC52ID0gdmFsdWU7XG4gICAgICByZWNvcmQucyA9IDE7XG4gICAgICBub3RpZnkocmVjb3JkLCBmYWxzZSk7XG4gICAgfVxuICB9IGNhdGNoKGUpe1xuICAgICRyZWplY3QuY2FsbCh7cjogcmVjb3JkLCBkOiBmYWxzZX0sIGUpOyAvLyB3cmFwXG4gIH1cbn07XG5cbi8vIGNvbnN0cnVjdG9yIHBvbHlmaWxsXG5pZighVVNFX05BVElWRSl7XG4gIC8vIDI1LjQuMy4xIFByb21pc2UoZXhlY3V0b3IpXG4gIFAgPSBmdW5jdGlvbiBQcm9taXNlKGV4ZWN1dG9yKXtcbiAgICBhRnVuY3Rpb24oZXhlY3V0b3IpO1xuICAgIHZhciByZWNvcmQgPSB0aGlzLl9kID0ge1xuICAgICAgcDogc3RyaWN0TmV3KHRoaXMsIFAsIFBST01JU0UpLCAgICAgICAgIC8vIDwtIHByb21pc2VcbiAgICAgIGM6IFtdLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSBhd2FpdGluZyByZWFjdGlvbnNcbiAgICAgIGE6IHVuZGVmaW5lZCwgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSBjaGVja2VkIGluIGlzVW5oYW5kbGVkIHJlYWN0aW9uc1xuICAgICAgczogMCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIHN0YXRlXG4gICAgICBkOiBmYWxzZSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gZG9uZVxuICAgICAgdjogdW5kZWZpbmVkLCAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIHZhbHVlXG4gICAgICBoOiBmYWxzZSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gaGFuZGxlZCByZWplY3Rpb25cbiAgICAgIG46IGZhbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSBub3RpZnlcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBleGVjdXRvcihjdHgoJHJlc29sdmUsIHJlY29yZCwgMSksIGN0eCgkcmVqZWN0LCByZWNvcmQsIDEpKTtcbiAgICB9IGNhdGNoKGVycil7XG4gICAgICAkcmVqZWN0LmNhbGwocmVjb3JkLCBlcnIpO1xuICAgIH1cbiAgfTtcbiAgcmVxdWlyZSgnLi8kLnJlZGVmaW5lLWFsbCcpKFAucHJvdG90eXBlLCB7XG4gICAgLy8gMjUuNC41LjMgUHJvbWlzZS5wcm90b3R5cGUudGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZClcbiAgICB0aGVuOiBmdW5jdGlvbiB0aGVuKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKXtcbiAgICAgIHZhciByZWFjdGlvbiA9IG5ldyBQcm9taXNlQ2FwYWJpbGl0eShzcGVjaWVzQ29uc3RydWN0b3IodGhpcywgUCkpXG4gICAgICAgICwgcHJvbWlzZSAgPSByZWFjdGlvbi5wcm9taXNlXG4gICAgICAgICwgcmVjb3JkICAgPSB0aGlzLl9kO1xuICAgICAgcmVhY3Rpb24ub2sgICA9IHR5cGVvZiBvbkZ1bGZpbGxlZCA9PSAnZnVuY3Rpb24nID8gb25GdWxmaWxsZWQgOiB0cnVlO1xuICAgICAgcmVhY3Rpb24uZmFpbCA9IHR5cGVvZiBvblJlamVjdGVkID09ICdmdW5jdGlvbicgJiYgb25SZWplY3RlZDtcbiAgICAgIHJlY29yZC5jLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYocmVjb3JkLmEpcmVjb3JkLmEucHVzaChyZWFjdGlvbik7XG4gICAgICBpZihyZWNvcmQucylub3RpZnkocmVjb3JkLCBmYWxzZSk7XG4gICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9LFxuICAgIC8vIDI1LjQuNS4xIFByb21pc2UucHJvdG90eXBlLmNhdGNoKG9uUmVqZWN0ZWQpXG4gICAgJ2NhdGNoJzogZnVuY3Rpb24ob25SZWplY3RlZCl7XG4gICAgICByZXR1cm4gdGhpcy50aGVuKHVuZGVmaW5lZCwgb25SZWplY3RlZCk7XG4gICAgfVxuICB9KTtcbn1cblxuJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwge1Byb21pc2U6IFB9KTtcbnJlcXVpcmUoJy4vJC5zZXQtdG8tc3RyaW5nLXRhZycpKFAsIFBST01JU0UpO1xucmVxdWlyZSgnLi8kLnNldC1zcGVjaWVzJykoUFJPTUlTRSk7XG5XcmFwcGVyID0gcmVxdWlyZSgnLi8kLmNvcmUnKVtQUk9NSVNFXTtcblxuLy8gc3RhdGljc1xuJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwgUFJPTUlTRSwge1xuICAvLyAyNS40LjQuNSBQcm9taXNlLnJlamVjdChyKVxuICByZWplY3Q6IGZ1bmN0aW9uIHJlamVjdChyKXtcbiAgICB2YXIgY2FwYWJpbGl0eSA9IG5ldyBQcm9taXNlQ2FwYWJpbGl0eSh0aGlzKVxuICAgICAgLCAkJHJlamVjdCAgID0gY2FwYWJpbGl0eS5yZWplY3Q7XG4gICAgJCRyZWplY3Qocik7XG4gICAgcmV0dXJuIGNhcGFiaWxpdHkucHJvbWlzZTtcbiAgfVxufSk7XG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICghVVNFX05BVElWRSB8fCB0ZXN0UmVzb2x2ZSh0cnVlKSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjYgUHJvbWlzZS5yZXNvbHZlKHgpXG4gIHJlc29sdmU6IGZ1bmN0aW9uIHJlc29sdmUoeCl7XG4gICAgLy8gaW5zdGFuY2VvZiBpbnN0ZWFkIG9mIGludGVybmFsIHNsb3QgY2hlY2sgYmVjYXVzZSB3ZSBzaG91bGQgZml4IGl0IHdpdGhvdXQgcmVwbGFjZW1lbnQgbmF0aXZlIFByb21pc2UgY29yZVxuICAgIGlmKHggaW5zdGFuY2VvZiBQICYmIHNhbWVDb25zdHJ1Y3Rvcih4Lm
23459NvbnN0cnVjdG9yLCB0aGlzKSlyZXR1cm4geDtcbiAgICB2YXIgY2FwYWJpbGl0eSA9IG5ldyBQcm9taXNlQ2FwYWJpbGl0eSh0aGlzKVxuICAgICAgLCAkJHJlc29sdmUgID0gY2FwYWJpbGl0eS5yZXNvbHZlO1xuICAgICQkcmVzb2x2ZSh4KTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTtcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIShVU0VfTkFUSVZFICYmIHJlcXVpcmUoJy4vJC5pdGVyLWRldGVjdCcpKGZ1bmN0aW9uKGl0ZXIpe1xuICBQLmFsbChpdGVyKVsnY2F0Y2gnXShmdW5jdGlvbigpe30pO1xufSkpLCBQUk9NSVNFLCB7XG4gIC8vIDI1LjQuNC4xIFByb21pc2UuYWxsKGl0ZXJhYmxlKVxuICBhbGw6IGZ1bmN0aW9uIGFsbChpdGVyYWJsZSl7XG4gICAgdmFyIEMgICAgICAgICAgPSBnZXRDb25zdHJ1Y3Rvcih0aGlzKVxuICAgICAgLCBjYXBhYmlsaXR5ID0gbmV3IFByb21pc2VDYXBhYmlsaXR5KEMpXG4gICAgICAsIHJlc29sdmUgICAgPSBjYXBhYmlsaXR5LnJlc29sdmVcbiAgICAgICwgcmVqZWN0ICAgICA9IGNhcGFiaWxpdHkucmVqZWN0XG4gICAgICAsIHZhbHVlcyAgICAgPSBbXTtcbiAgICB2YXIgYWJydXB0ID0gcGVyZm9ybShmdW5jdGlvbigpe1xuICAgICAgZm9yT2YoaXRlcmFibGUsIGZhbHNlLCB2YWx1ZXMucHVzaCwgdmFsdWVzKTtcbiAgICAgIHZhciByZW1haW5pbmcgPSB2YWx1ZXMubGVuZ3RoXG4gICAgICAgICwgcmVzdWx0cyAgID0gQXJyYXkocmVtYWluaW5nKTtcbiAgICAgIGlmKHJlbWFpbmluZykkLmVhY2guY2FsbCh2YWx1ZXMsIGZ1bmN0aW9uKHByb21pc2UsIGluZGV4KXtcbiAgICAgICAgdmFyIGFscmVhZHlDYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgQy5yZXNvbHZlKHByb21pc2UpLnRoZW4oZnVuY3Rpb24odmFsdWUpe1xuICAgICAgICAgIGlmKGFscmVhZHlDYWxsZWQpcmV0dXJuO1xuICAgICAgICAgIGFscmVhZHlDYWxsZWQgPSB0cnVlO1xuICAgICAgICAgIHJlc3VsdHNbaW5kZXhdID0gdmFsdWU7XG4gICAgICAgICAgLS1yZW1haW5pbmcgfHwgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgICAgfSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgZWxzZSByZXNvbHZlKHJlc3VsdHMpO1xuICAgIH0pO1xuICAgIGlmKGFicnVwdClyZWplY3QoYWJydXB0LmVycm9yKTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9LFxuICAvLyAyNS40LjQuNCBQcm9taXNlLnJhY2UoaXRlcmFibGUpXG4gIHJhY2U6IGZ1bmN0aW9uIHJhY2UoaXRlcmFibGUpe1xuICAgIHZhciBDICAgICAgICAgID0gZ2V0Q29uc3RydWN0b3IodGhpcylcbiAgICAgICwgY2FwYWJpbGl0eSA9IG5ldyBQcm9taXNlQ2FwYWJpbGl0eShDKVxuICAgICAgLCByZWplY3QgICAgID0gY2FwYWJpbGl0eS5yZWplY3Q7XG4gICAgdmFyIGFicnVwdCA9IHBlcmZvcm0oZnVuY3Rpb24oKXtcbiAgICAgIGZvck9mKGl0ZXJhYmxlLCBmYWxzZSwgZnVuY3Rpb24ocHJvbWlzZSl7XG4gICAgICAgIEMucmVzb2x2ZShwcm9taXNlKS50aGVuKGNhcGFiaWxpdHkucmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGlmKGFicnVwdClyZWplY3QoYWJydXB0LmVycm9yKTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTsiLCIndXNlIHN0cmljdCc7XG52YXIgc3Ryb25nID0gcmVxdWlyZSgnLi8kLmNvbGxlY3Rpb24tc3Ryb25nJyk7XG5cbi8vIDIzLjIgU2V0IE9iamVjdHNcbnJlcXVpcmUoJy4vJC5jb2xsZWN0aW9uJykoJ1NldCcsIGZ1bmN0aW9uKGdldCl7XG4gIHJldHVybiBmdW5jdGlvbiBTZXQoKXsgcmV0dXJuIGdldCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID4gMCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7IH07XG59LCB7XG4gIC8vIDIzLjIuMy4xIFNldC5wcm90b3R5cGUuYWRkKHZhbHVlKVxuICBhZGQ6IGZ1bmN0aW9uIGFkZCh2YWx1ZSl7XG4gICAgcmV0dXJuIHN0cm9uZy5kZWYodGhpcywgdmFsdWUgPSB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZSwgdmFsdWUpO1xuICB9XG59LCBzdHJvbmcpOyIsIid1c2Ugc3RyaWN0JztcbnZhciAkYXQgID0gcmVxdWlyZSgnLi8kLnN0cmluZy1hdCcpKHRydWUpO1xuXG4vLyAyMS4xLjMuMjcgU3RyaW5nLnByb3RvdHlwZVtAQGl0ZXJhdG9yXSgpXG5yZXF1aXJlKCcuLyQuaXRlci1kZWZpbmUnKShTdHJpbmcsICdTdHJpbmcnLCBmdW5jdGlvbihpdGVyYXRlZCl7XG4gIHRoaXMuX3QgPSBTdHJpbmcoaXRlcmF0ZWQpOyAvLyB0YXJnZXRcbiAgdGhpcy5faSA9IDA7ICAgICAgICAgICAgICAgIC8vIG5leHQgaW5kZXhcbi8vIDIxLjEuNS4yLjEgJVN0cmluZ0l0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uKCl7XG4gIHZhciBPICAgICA9IHRoaXMuX3RcbiAgICAsIGluZGV4ID0gdGhpcy5faVxuICAgICwgcG9pbnQ7XG4gIGlmKGluZGV4ID49IE8ubGVuZ3RoKXJldHVybiB7dmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZX07XG4gIHBvaW50ID0gJGF0KE8sIGluZGV4KTtcbiAgdGhpcy5faSArPSBwb2ludC5sZW5ndGg7XG4gIHJldHVybiB7dmFsdWU6IHBvaW50LCBkb25lOiBmYWxzZX07XG59KTsiLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgJGV4cG9ydCAgPSByZXF1aXJlKCcuLyQuZXhwb3J0Jyk7XG5cbiRleHBvcnQoJGV4cG9ydC5QLCAnU2V0Jywge3RvSlNPTjogcmVxdWlyZSgnLi8kLmNvbGxlY3Rpb24tdG8tanNvbicpKCdTZXQnKX0pOyIsInJlcXVpcmUoJy4vZXM2LmFycmF5Lml0ZXJhdG9yJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi8kLml0ZXJhdG9ycycpO1xuSXRlcmF0b3JzLk5vZGVMaXN0ID0gSXRlcmF0b3JzLkhUTUxDb2xsZWN0aW9uID0gSXRlcmF0b3JzLkFycmF5OyIsIi8qIVxuSVNDIExpY2Vuc2VcblxuQ29weXJpZ2h0IChjKSAyMDE0LTIwMTgsIEFuZHJlYSBHaWFtbWFyY2hpLCBAV2ViUmVmbGVjdGlvblxuXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZCwgcHJvdmlkZWQgdGhhdCB0aGUgYWJvdmVcbmNvcHlyaWdodCBub3RpY2UgYW5kIHR
23459oaXMgcGVybWlzc2lvbiBub3RpY2UgYXBwZWFyIGluIGFsbCBjb3BpZXMuXG5cblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRVxuT1IgT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cblxuKi9cbi8vIGdsb2JhbCB3aW5kb3cgT2JqZWN0XG4vLyBvcHRpb25hbCBwb2x5ZmlsbCBpbmZvXG4vLyAgICAnYXV0bycgdXNlZCBieSBkZWZhdWx0LCBldmVyeXRoaW5nIGlzIGZlYXR1cmUgZGV0ZWN0ZWRcbi8vICAgICdmb3JjZScgdXNlIHRoZSBwb2x5ZmlsbCBldmVuIGlmIG5vdCBmdWxseSBuZWVkZWRcbmZ1bmN0aW9uIGluc3RhbGxDdXN0b21FbGVtZW50cyh3aW5kb3csIHBvbHlmaWxsKSB7J3VzZSBzdHJpY3QnO1xuXG4gIC8vIERPIE5PVCBVU0UgVEhJUyBGSUxFIERJUkVDVExZLCBJVCBXT04nVCBXT1JLXG4gIC8vIFRISVMgSVMgQSBQUk9KRUNUIEJBU0VEIE9OIEEgQlVJTEQgU1lTVEVNXG4gIC8vIFRISVMgRklMRSBJUyBKVVNUIFdSQVBQRUQgVVAgUkVTVUxUSU5HIElOXG4gIC8vIGJ1aWxkL2RvY3VtZW50LXJlZ2lzdGVyLWVsZW1lbnQubm9kZS5qc1xuXG4gIHZhclxuICAgIGRvY3VtZW50ID0gd2luZG93LmRvY3VtZW50LFxuICAgIE9iamVjdCA9IHdpbmRvdy5PYmplY3RcbiAgO1xuXG4gIHZhciBodG1sQ2xhc3MgPSAoZnVuY3Rpb24gKGluZm8pIHtcbiAgICAvLyAoQykgQW5kcmVhIEdpYW1tYXJjaGkgLSBAV2ViUmVmbGVjdGlvbiAtIE1JVCBTdHlsZVxuICAgIHZhclxuICAgICAgY2F0Y2hDbGFzcyA9IC9eW0EtWl0rW2Etel0vLFxuICAgICAgZmlsdGVyQnkgPSBmdW5jdGlvbiAocmUpIHtcbiAgICAgICAgdmFyIGFyciA9IFtdLCB0YWc7XG4gICAgICAgIGZvciAodGFnIGluIHJlZ2lzdGVyKSB7XG4gICAgICAgICAgaWYgKHJlLnRlc3QodGFnKSkgYXJyLnB1c2godGFnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyO1xuICAgICAgfSxcbiAgICAgIGFkZCA9IGZ1bmN0aW9uIChDbGFzcywgdGFnKSB7XG4gICAgICAgIHRhZyA9IHRhZy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoISh0YWcgaW4gcmVnaXN0ZXIpKSB7XG4gICAgICAgICAgcmVnaXN0ZXJbQ2xhc3NdID0gKHJlZ2lzdGVyW0NsYXNzXSB8fCBbXSkuY29uY2F0KHRhZyk7XG4gICAgICAgICAgcmVnaXN0ZXJbdGFnXSA9IChyZWdpc3Rlclt0YWcudG9VcHBlckNhc2UoKV0gPSBDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICByZWdpc3RlciA9IChPYmplY3QuY3JlYXRlIHx8IE9iamVjdCkobnVsbCksXG4gICAgICBodG1sQ2xhc3MgPSB7fSxcbiAgICAgIGksIHNlY3Rpb24sIHRhZ3MsIENsYXNzXG4gICAgO1xuICAgIGZvciAoc2VjdGlvbiBpbiBpbmZvKSB7XG4gICAgICBmb3IgKENsYXNzIGluIGluZm9bc2VjdGlvbl0pIHtcbiAgICAgICAgdGFncyA9IGluZm9bc2VjdGlvbl1bQ2xhc3NdO1xuICAgICAgICByZWdpc3RlcltDbGFzc10gPSB0YWdzO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHJlZ2lzdGVyW3RhZ3NbaV0udG9Mb3dlckNhc2UoKV0gPVxuICAgICAgICAgIHJlZ2lzdGVyW3RhZ3NbaV0udG9VcHBlckNhc2UoKV0gPSBDbGFzcztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBodG1sQ2xhc3MuZ2V0ID0gZnVuY3Rpb24gZ2V0KHRhZ09yQ2xhc3MpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdGFnT3JDbGFzcyA9PT0gJ3N0cmluZycgP1xuICAgICAgICAocmVnaXN0ZXJbdGFnT3JDbGFzc10gfHwgKGNhdGNoQ2xhc3MudGVzdCh0YWdPckNsYXNzKSA/IFtdIDogJycpKSA6XG4gICAgICAgIGZpbHRlckJ5KHRhZ09yQ2xhc3MpO1xuICAgIH07XG4gICAgaHRtbENsYXNzLnNldCA9IGZ1bmN0aW9uIHNldCh0YWcsIENsYXNzKSB7XG4gICAgICByZXR1cm4gKGNhdGNoQ2xhc3MudGVzdCh0YWcpID9cbiAgICAgICAgYWRkKHRhZywgQ2xhc3MpIDpcbiAgICAgICAgYWRkKENsYXNzLCB0YWcpXG4gICAgICApLCBodG1sQ2xhc3M7XG4gICAgfTtcbiAgICByZXR1cm4gaHRtbENsYXNzO1xuICB9KHtcbiAgICBcImNvbGxlY3Rpb25zXCI6IHtcbiAgICAgIFwiSFRNTEFsbENvbGxlY3Rpb25cIjogW1xuICAgICAgICBcImFsbFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQ29sbGVjdGlvblwiOiBbXG4gICAgICAgIFwiZm9ybXNcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEZvcm1Db250cm9sc0NvbGxlY3Rpb25cIjogW1xuICAgICAgICBcImVsZW1lbnRzXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxPcHRpb25zQ29sbGVjdGlvblwiOiBbXG4gICAgICAgIFwib3B0aW9uc1wiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImVsZW1lbnRzXCI6IHtcbiAgICAgIFwiRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZWxlbWVudFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQW5jaG9yRWxlbWVudFwiOiBbXG4gICAgICAgIFwiYVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQXBwbGV0RWxlbWVudFwiOiBbXG4gICAgICAgIFwiYXBwbGV0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxBcmVhRWxlbWVudFwiOiBbXG4gICAgICAgIFwiYXJlYVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQXR0YWNobWVudEVsZW1lbnRcIjogW1xuICAgICAgICBcImF0dGFjaG1lbnRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEF1ZGlvRWxlbWVudFwiOiBbXG4gICAgICAgIFwiYXVkaW9cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEJSRWxlbWVudFwiOiBbXG4gICAgICAgIFwiYnJcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEJhc2VFbGVtZW50XCI6IFtcbiAgICAgICAgXCJiYXNlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxCb2R5RWxlbWVudFwiOiBbXG4gICAgICAgIFwiYm9keVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQnV0dG9uRWxlbWVudFwiOiBbXG4gICAgICAgIFwiYnV0dG9uXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxDYW52YXNFbGVtZW50XCI6IFtcbiAgICAgICAgXCJjYW52YXNcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTENvbnRlbnRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJjb250ZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxETGlzdEVsZW1lbnRcIjogW1xuICAgICAgICBcImRsXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEYXRhRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGF0YVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRGF0YUxpc3RFbGVtZW50XCI6IFtcbiAgICAgICAgXCJkYXRhbGlzdFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRGV0YWlsc0VsZW1lbnRcIjogW1xuICAgICAgICBcImRldGFpbHNcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTERpYWxvZ0VsZW1lbnRcIjogW1xuICAgICAgICBcImRpYWxvZ1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRGlyZWN0b3J5RWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGlyXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEaXZFbGVtZW50XCI6IFtcbiAgICAgICAgXCJkaXZcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTERvY3VtZW50XCI6IFtcbiAgICAgICAgXCJkb2N1bWVudFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZWxlbWVudFwiLFxuICAgICAgICBcImFiYnJcIixcbiAgICAgICAgXCJhZGRyZXNzXCIsXG4gICAgICAgIFwiYXJ0aWNsZVwiLFxuICAgICAgICBcImFzaWRlXCIsXG4gICAgICAgIFwiYlwiLFxuICAgICAgICBcImJkaVwiLFxuICAgICAgICBcImJkb1wiLFxuICAgICAgICBcImNpdGVcIixcbiAgICAgICAgXCJjb2RlXCIsXG4gICAgICAgIFwiY29tbWFuZFwiLFxuICAgICAgICBcImRkXCIsXG4gICAgICAgIFwiZGZuXCIsXG4gICAgICAgIFwiZHRcIixcbiAgICAgICAgXCJlbVwiLFxuICAgICAgICBcImZpZ2NhcHRpb25cIixcbiAgICAgICAgXCJmaWd1cmVcIixcbiAgICAgICAgXCJmb290ZXJcIixcbiAgICAgICAgXCJoZWFkZXJcIixcbiAgICAgICAgXCJpXCIsXG4gICAgICAgIFwia2JkXCIsXG4gICAgICAgIFwibWFya1wiLFxuICAgICAgICBcIm5hdlwiLFxuICAgICAgICBcIm5vc2NyaXB0XCIsXG4gICAgICAgIFwicnBcIixcbiAgICAgICAgXCJydFwiLFxuICAgICAgICBcInJ1YnlcIixcbiAgICAgICAgXCJzXCIsXG4gICAgICAgIFwic2FtcFwiLFxuICAgICAgICBcInNlY3Rpb25cIixcbiAgICAgICAgXCJzbWFsbFwiLFxuICAgICAgICBcInN0cm9uZ1wiLFxuICAgICAgICBcInN1YlwiLFxuICAgICAgICBcInN1bW1hcnlcIixcbiAgICAgICAgXCJzdXBcIixcbiAgICAgICAgXCJ1XCIsXG4gICAgICAgIFwidmFyXCIsXG4gICAgICAgIFwid2JyXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxFbWJlZEVsZW1lbnRcIjogW1xuICAgICAgICBcImVtYmVkXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxGaWVsZFNldEVsZW1lbnRcIjogW1xuICAgICAgICBcImZpZWxkc2V0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxGb250RWxlbWVudFwiOiBbXG4gICAgICAgIFwiZm9udFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRm9ybUVsZW1lbnRcIjogW1xuICAgICAgICBcImZvcm1cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEZyYW1lRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZnJhbWVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEZyYW1lU2V0RWxlbWVudFwiOiBbXG4gICAgICAgIFwiZnJhbWVzZXRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEhSRWxlbWVudFwiOiBbXG4gICAgICAgIFwiaHJcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEhlYWRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJoZWFkXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxIZWFkaW5nRWxlbWVudFwiOiBbXG4gICAgICAgIFwiaDFcIixcbiAgICAgICAgXCJoMlwiLFxuICAgICAgICBcImgzXCIsXG4gICAgICAgIFwiaD
23459RcIixcbiAgICAgICAgXCJoNVwiLFxuICAgICAgICBcImg2XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxIdG1sRWxlbWVudFwiOiBbXG4gICAgICAgIFwiaHRtbFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MSUZyYW1lRWxlbWVudFwiOiBbXG4gICAgICAgIFwiaWZyYW1lXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxJbWFnZUVsZW1lbnRcIjogW1xuICAgICAgICBcImltZ1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MSW5wdXRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJpbnB1dFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MS2V5Z2VuRWxlbWVudFwiOiBbXG4gICAgICAgIFwia2V5Z2VuXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxMSUVsZW1lbnRcIjogW1xuICAgICAgICBcImxpXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxMYWJlbEVsZW1lbnRcIjogW1xuICAgICAgICBcImxhYmVsXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxMZWdlbmRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJsZWdlbmRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTExpbmtFbGVtZW50XCI6IFtcbiAgICAgICAgXCJsaW5rXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxNYXBFbGVtZW50XCI6IFtcbiAgICAgICAgXCJtYXBcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1hcnF1ZWVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJtYXJxdWVlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxNZWRpYUVsZW1lbnRcIjogW1xuICAgICAgICBcIm1lZGlhXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxNZW51RWxlbWVudFwiOiBbXG4gICAgICAgIFwibWVudVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTWVudUl0ZW1FbGVtZW50XCI6IFtcbiAgICAgICAgXCJtZW51aXRlbVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTWV0YUVsZW1lbnRcIjogW1xuICAgICAgICBcIm1ldGFcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1ldGVyRWxlbWVudFwiOiBbXG4gICAgICAgIFwibWV0ZXJcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1vZEVsZW1lbnRcIjogW1xuICAgICAgICBcImRlbFwiLFxuICAgICAgICBcImluc1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MT0xpc3RFbGVtZW50XCI6IFtcbiAgICAgICAgXCJvbFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MT2JqZWN0RWxlbWVudFwiOiBbXG4gICAgICAgIFwib2JqZWN0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxPcHRHcm91cEVsZW1lbnRcIjogW1xuICAgICAgICBcIm9wdGdyb3VwXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxPcHRpb25FbGVtZW50XCI6IFtcbiAgICAgICAgXCJvcHRpb25cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE91dHB1dEVsZW1lbnRcIjogW1xuICAgICAgICBcIm91dHB1dFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUGFyYWdyYXBoRWxlbWVudFwiOiBbXG4gICAgICAgIFwicFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUGFyYW1FbGVtZW50XCI6IFtcbiAgICAgICAgXCJwYXJhbVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUGljdHVyZUVsZW1lbnRcIjogW1xuICAgICAgICBcInBpY3R1cmVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFByZUVsZW1lbnRcIjogW1xuICAgICAgICBcInByZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUHJvZ3Jlc3NFbGVtZW50XCI6IFtcbiAgICAgICAgXCJwcm9ncmVzc1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUXVvdGVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJibG9ja3F1b3RlXCIsXG4gICAgICAgIFwicVwiLFxuICAgICAgICBcInF1b3RlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTY3JpcHRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJzY3JpcHRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFNlbGVjdEVsZW1lbnRcIjogW1xuICAgICAgICBcInNlbGVjdFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MU2hhZG93RWxlbWVudFwiOiBbXG4gICAgICAgIFwic2hhZG93XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTbG90RWxlbWVudFwiOiBbXG4gICAgICAgIFwic2xvdFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MU291cmNlRWxlbWVudFwiOiBbXG4gICAgICAgIFwic291cmNlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTcGFuRWxlbWVudFwiOiBbXG4gICAgICAgIFwic3BhblwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MU3R5bGVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJzdHlsZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVDYXB0aW9uRWxlbWVudFwiOiBbXG4gICAgICAgIFwiY2FwdGlvblwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVDZWxsRWxlbWVudFwiOiBbXG4gICAgICAgIFwidGRcIixcbiAgICAgICAgXCJ0aFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVDb2xFbGVtZW50XCI6IFtcbiAgICAgICAgXCJjb2xcIixcbiAgICAgICAgXCJjb2xncm91cFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0YWJsZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVSb3dFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0clwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGFibGVTZWN0aW9uRWxlbWVudFwiOiBbXG4gICAgICAgIFwidGhlYWRcIixcbiAgICAgICAgXCJ0Ym9keVwiLFxuICAgICAgICBcInRmb290XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUZW1wbGF0ZUVsZW1lbnRcIjogW1xuICAgICAgICBcInRlbXBsYXRlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUZXh0QXJlYUVsZW1lbnRcIjogW1xuICAgICAgICBcInRleHRhcmVhXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUaW1lRWxlbWVudFwiOiBbXG4gICAgICAgIFwidGltZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVGl0bGVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0aXRsZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVHJhY2tFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0cmFja1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVUxpc3RFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ1bFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVW5rbm93bkVsZW1lbnRcIjogW1xuICAgICAgICBcInVua25vd25cIixcbiAgICAgICAgXCJ2aGdyb3VwdlwiLFxuICAgICAgICBcInZrZXlnZW5cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFZpZGVvRWxlbWVudFwiOiBbXG4gICAgICAgIFwidmlkZW9cIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJub2Rlc1wiOiB7XG4gICAgICBcIkF0dHJcIjogW1xuICAgICAgICBcIm5vZGVcIlxuICAgICAgXSxcbiAgICAgIFwiQXVkaW9cIjogW1xuICAgICAgICBcImF1ZGlvXCJcbiAgICAgIF0sXG4gICAgICBcIkNEQVRBU2VjdGlvblwiOiBbXG4gICAgICAgIFwibm9kZVwiXG4gICAgICBdLFxuICAgICAgXCJDaGFyYWN0ZXJEYXRhXCI6IFtcbiAgICAgICAgXCJub2RlXCJcbiAgICAgIF0sXG4gICAgICBcIkNvbW1lbnRcIjogW1xuICAgICAgICBcIiNjb21tZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkRvY3VtZW50XCI6IFtcbiAgICAgICAgXCIjZG9jdW1lbnRcIlxuICAgICAgXSxcbiAgICAgIFwiRG9jdW1lbnRGcmFnbWVudFwiOiBbXG4gICAgICAgIFwiI2RvY3VtZW50LWZyYWdtZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkRvY3VtZW50VHlwZVwiOiBbXG4gICAgICAgIFwibm9kZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRG9jdW1lbnRcIjogW1xuICAgICAgICBcIiNkb2N1bWVudFwiXG4gICAgICBdLFxuICAgICAgXCJJbWFnZVwiOiBbXG4gICAgICAgIFwiaW1nXCJcbiAgICAgIF0sXG4gICAgICBcIk9wdGlvblwiOiBbXG4gICAgICAgIFwib3B0aW9uXCJcbiAgICAgIF0sXG4gICAgICBcIlByb2Nlc3NpbmdJbnN0cnVjdGlvblwiOiBbXG4gICAgICAgIFwibm9kZVwiXG4gICAgICBdLFxuICAgICAgXCJTaGFkb3dSb290XCI6IFtcbiAgICAgICAgXCIjc2hhZG93LXJvb3RcIlxuICAgICAgXSxcbiAgICAgIFwiVGV4dFwiOiBbXG4gICAgICAgIFwiI3RleHRcIlxuICAgICAgXSxcbiAgICAgIFwiWE1MRG9jdW1lbnRcIjogW1xuICAgICAgICBcInhtbFwiXG4gICAgICBdXG4gICAgfVxuICB9KSk7XG4gIFxuICBcbiAgICBcbiAgLy8gcGFzc2VkIGF0IHJ1bnRpbWUsIGNvbmZpZ3VyYWJsZSB2aWEgbm9kZWpzIG1vZHVsZVxuICBpZiAodHlwZW9mIHBvbHlmaWxsICE9PSAnb2JqZWN0JykgcG9seWZpbGwgPSB7dHlwZTogcG9seWZpbGwgfHwgJ2F1dG8nfTtcbiAgXG4gIHZhclxuICAgIC8vIFYwIHBvbHlmaWxsIGVudHJ5XG4gICAgUkVHSVNURVJfRUxFTUVOVCA9ICdyZWdpc3RlckVsZW1lbnQnLFxuICBcbiAgICAvLyBwc2V1ZG8tcmFuZG9tIG51bWJlciB1c2VkIGFzIGV4cGFuZG8vdW5pcXVlIG5hbWUgb24gZmVhdHVyZSBkZXRlY3Rpb25cbiAgICBVSUQgPSB3aW5kb3cuTWF0aC5yYW5kb20oKSAqIDEwZTQgPj4gMCxcbiAgXG4gICAgLy8gSUUgPCAxMSBvbmx5ICsgb2xkIFdlYktpdCBmb3IgYXR0cmlidXRlcyArIGZlYXR1cmUgZGV0ZWN0aW9uXG4gICAgRVhQQU5ET19VSUQgPSAnX18nICsgUkVHSVNURVJfRUxFTUVOVCArIFVJRCxcbiAgXG4gICAgLy8gc2hvcnRjdXRzIGFuZCBjb3N0YW50c1xuICAgIEFERF9FVkVOVF9MSVNURU5FUiA9ICdhZGRFdmVudExpc3RlbmVyJyxcbiAgICBBVFRBQ0hFRCA9ICdhdHRhY2hlZCcsXG4gICAgQ0FMTEJBQ0sgPSAnQ2FsbGJhY2snLFxuICAgIERFVEFDSEVEID0gJ2RldGFjaGVkJyxcbiAgICBFWFRFTkRTID0gJ2V4dGVuZHMnLFxuICBcbiAgICBBVFRSSUJVVEVfQ0hBTkdFRF9DQUxMQkFDSyA9ICdhdHRyaWJ1dGVDaGFuZ2VkJyArIENBTExCQUNLLFxuICAgIEFUVEFDSEVEX0NBTExCQUNLID0gQVRUQUNIRUQgKyBDQUxMQkFDSyxcbiAgICBDT05ORUNURURfQ0FMTEJBQ0sgPSAnY29ubmVjdGVkJyArIENBTExCQUNLLFxuICAgIERJU0NPTk5FQ1RFRF9DQUxMQkFDSyA9ICdkaXNjb25uZWN0ZWQnICsgQ0FMTEJBQ0ssXG4gICAgQ1JFQVRFRF9DQUxMQkFDSyA9ICdjcmVhdGVkJyArIENBTExCQUNLLFxuICAgIERFVEFDSEVEX0NBTExCQUNLID0gREVUQUNIRUQgKyBDQUxMQkFDSyxcbiAgXG4gICAgQURESVRJT04gPSAnQURESVRJT04nLFxuICAgIE1PRElGSUNBVElPTiA9ICdNT0RJRklDQVRJT04nLFxuICAgIFJFTU9WQUwgPSAnUkVNT1ZBTCcsXG4gIFxuICAgIERPTV9BVFRSX01PRElGSUVEID0gJ0RPTUF0dHJNb2RpZmllZCcsXG4gICAgRE9NX0NPTlRFTlRfTE9BREVEID0gJ0RPTUNvbnRlbnRMb2FkZWQnLFxuICAgIERPTV9TVUJUUkVFX01PRElGSUVEID0gJ0RPTVN1YnRyZWVNb2RpZmllZCcsXG4gIFxuICAgIFBSRUZJWF9UQUcgPSAnPCcsXG4gICAgUFJFRklYX0lTID0gJz0nLFxuICBcbiAgICAvLyB2YWxpZCBhbmQgaW52YWxpZCBub2RlIG5hbWVzXG4gICAgdmFsaWROYW1lID0gL15bQS1aXVsuX0EtWjAtOV0qLVstLl9BLVowLTldKiQvLFxuICAgIGludmFsaWROYW1lcyA9IFtcbiAgICAgICdBTk5PVEFUSU9OLVhNTCcsXG4gICAgICAnQ09MT1ItUFJPRklMRScsXG4gICAgICAnRk9OVC1GQUNFJyxcbiAgICAgICdGT05ULUZBQ0UtU1JDJyxcbiAgICAgICdGT05ULUZBQ0UtVVJJJyxcbiAgICAgICdGT05ULUZBQ0UtRk9STUFUJyxcbiAgICAgICdGT05ULUZBQ0UtTkFNRScsXG4gICAgICAnTUlTU0lORy1HTFlQSCdcbiAgICBdLFxuICBcbiAgICAvLyByZWdpc3RlcmVkIHR5cGVzIGFuZCB0aGVpciBwcm90b3R5cGVzXG4gICAgdHlwZXMgPSBbXSxcbiAgICBwcm90b3MgPSBbXSxcbiAgXG4gICAgLy8gdG8gcXVlcnkgc3Vibm9kZXNcbiAgICBxdWVyeSA9ICcnLFxuICBcbiAgICAvLyBodG1sIHNob3J0Y3V0IHVzZWQgdG8gZmVhdHVyZSBkZXRlY3RcbiAgICBkb2
23459N1bWVudEVsZW1lbnQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG4gIFxuICAgIC8vIEVTNSBpbmxpbmUgaGVscGVycyB8fCBiYXNpYyBwYXRjaGVzXG4gICAgaW5kZXhPZiA9IHR5cGVzLmluZGV4T2YgfHwgZnVuY3Rpb24gKHYpIHtcbiAgICAgIGZvcih2YXIgaSA9IHRoaXMubGVuZ3RoOyBpLS0gJiYgdGhpc1tpXSAhPT0gdjspe31cbiAgICAgIHJldHVybiBpO1xuICAgIH0sXG4gIFxuICAgIC8vIG90aGVyIGhlbHBlcnMgLyBzaG9ydGN1dHNcbiAgICBPUCA9IE9iamVjdC5wcm90b3R5cGUsXG4gICAgaE9QID0gT1AuaGFzT3duUHJvcGVydHksXG4gICAgaVBPID0gT1AuaXNQcm90b3R5cGVPZixcbiAgXG4gICAgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHksXG4gICAgZW1wdHkgPSBbXSxcbiAgICBnT1BEID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixcbiAgICBnT1BOID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMsXG4gICAgZ1BPID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLFxuICAgIHNQTyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZixcbiAgXG4gICAgLy8ganNoaW50IHByb3RvOiB0cnVlXG4gICAgaGFzUHJvdG8gPSAhIU9iamVjdC5fX3Byb3RvX18sXG4gIFxuICAgIC8vIFYxIGhlbHBlcnNcbiAgICBmaXhHZXRDbGFzcyA9IGZhbHNlLFxuICAgIERSRUNFVjEgPSAnX19kcmVDRXYxJyxcbiAgICBjdXN0b21FbGVtZW50cyA9IHdpbmRvdy5jdXN0b21FbGVtZW50cyxcbiAgICB1c2FibGVDdXN0b21FbGVtZW50cyA9ICEvXmZvcmNlLy50ZXN0KHBvbHlmaWxsLnR5cGUpICYmICEhKFxuICAgICAgY3VzdG9tRWxlbWVudHMgJiZcbiAgICAgIGN1c3RvbUVsZW1lbnRzLmRlZmluZSAmJlxuICAgICAgY3VzdG9tRWxlbWVudHMuZ2V0ICYmXG4gICAgICBjdXN0b21FbGVtZW50cy53aGVuRGVmaW5lZFxuICAgICksXG4gICAgRGljdCA9IE9iamVjdC5jcmVhdGUgfHwgT2JqZWN0LFxuICAgIE1hcCA9IHdpbmRvdy5NYXAgfHwgZnVuY3Rpb24gTWFwKCkge1xuICAgICAgdmFyIEsgPSBbXSwgViA9IFtdLCBpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoaykge1xuICAgICAgICAgIHJldHVybiBWW2luZGV4T2YuY2FsbChLLCBrKV07XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24gKGssIHYpIHtcbiAgICAgICAgICBpID0gaW5kZXhPZi5jYWxsKEssIGspO1xuICAgICAgICAgIGlmIChpIDwgMCkgVltLLnB1c2goaykgLSAxXSA9IHY7XG4gICAgICAgICAgZWxzZSBWW2ldID0gdjtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9LFxuICAgIFByb21pc2UgPSB3aW5kb3cuUHJvbWlzZSB8fCBmdW5jdGlvbiAoZm4pIHtcbiAgICAgIHZhclxuICAgICAgICBub3RpZnkgPSBbXSxcbiAgICAgICAgZG9uZSA9IGZhbHNlLFxuICAgICAgICBwID0ge1xuICAgICAgICAgICdjYXRjaCc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgJ3RoZW4nOiBmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgIG5vdGlmeS5wdXNoKGNiKTtcbiAgICAgICAgICAgIGlmIChkb25lKSBzZXRUaW1lb3V0KHJlc29sdmUsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICA7XG4gICAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgICB3aGlsZSAobm90aWZ5Lmxlbmd0aCkgbm90aWZ5LnNoaWZ0KCkodmFsdWUpO1xuICAgICAgfVxuICAgICAgZm4ocmVzb2x2ZSk7XG4gICAgICByZXR1cm4gcDtcbiAgICB9LFxuICAgIGp1c3RDcmVhdGVkID0gZmFsc2UsXG4gICAgY29uc3RydWN0b3JzID0gRGljdChudWxsKSxcbiAgICB3YWl0aW5nTGlzdCA9IERpY3QobnVsbCksXG4gICAgbm9kZU5hbWVzID0gbmV3IE1hcCgpLFxuICAgIHNlY29uZEFyZ3VtZW50ID0gZnVuY3Rpb24gKGlzKSB7XG4gICAgICByZXR1cm4gaXMudG9Mb3dlckNhc2UoKTtcbiAgICB9LFxuICBcbiAgICAvLyB1c2VkIHRvIGNyZWF0ZSB1bmlxdWUgaW5zdGFuY2VzXG4gICAgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBCcmlkZ2UocHJvdG8pIHtcbiAgICAgIC8vIHNpbGx5IGJyb2tlbiBwb2x5ZmlsbCBwcm9iYWJseSBldmVyIHVzZWQgYnV0IHNob3J0IGVub3VnaCB0byB3b3JrXG4gICAgICByZXR1cm4gcHJvdG8gPyAoKEJyaWRnZS5wcm90b3R5cGUgPSBwcm90byksIG5ldyBCcmlkZ2UoKSkgOiB0aGlzO1xuICAgIH0sXG4gIFxuICAgIC8vIHdpbGwgc2V0IHRoZSBwcm90b3R5cGUgaWYgcG9zc2libGVcbiAgICAvLyBvciBjb3B5IG92ZXIgYWxsIHByb3BlcnRpZXNcbiAgICBzZXRQcm90b3R5cGUgPSBzUE8gfHwgKFxuICAgICAgaGFzUHJvdG8gP1xuICAgICAgICBmdW5jdGlvbiAobywgcCkge1xuICAgICAgICAgIG8uX19wcm90b19fID0gcDtcbiAgICAgICAgICByZXR1cm4gbztcbiAgICAgICAgfSA6IChcbiAgICAgIChnT1BOICYmIGdPUEQpID9cbiAgICAgICAgKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgZnVuY3Rpb24gc2V0UHJvcGVydGllcyhvLCBwKSB7XG4gICAgICAgICAgICBmb3IgKHZhclxuICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgIG5hbWVzID0gZ09QTihwKSxcbiAgICAgICAgICAgICAgaSA9IDAsIGxlbmd0aCA9IG5hbWVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgaSA8IGxlbmd0aDsgaSsrXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAga2V5ID0gbmFtZXNbaV07XG4gICAgICAgICAgICAgIGlmICghaE9QLmNhbGwobywga2V5KSkge1xuICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KG8sIGtleSwgZ09QRChwLCBrZXkpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG8sIHApIHtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgc2V0UHJvcGVydGllcyhvLCBwKTtcbiAgICAgICAgICAgIH0gd2hpbGUgKChwID0gZ1BPKHApKSAmJiAhaVBPLmNhbGwocCwgbykpO1xuICAgICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgICAgfTtcbiAgICAgICAgfSgpKSA6XG4gICAgICAgIGZ1bmN0aW9uIChvLCBwKSB7XG4gICAgICAgICAgZm9yICh2YXIga2V5IGluIHApIHtcbiAgICAgICAgICAgIG9ba2V5XSA9IHBba2V5XTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgI
23459H1cbiAgICApKSxcbiAgXG4gICAgLy8gRE9NIHNob3J0Y3V0cyBhbmQgaGVscGVycywgaWYgYW55XG4gIFxuICAgIE11dGF0aW9uT2JzZXJ2ZXIgPSB3aW5kb3cuTXV0YXRpb25PYnNlcnZlciB8fFxuICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuV2ViS2l0TXV0YXRpb25PYnNlcnZlcixcbiAgXG4gICAgSFRNTEFuY2hvckVsZW1lbnQgPSB3aW5kb3cuSFRNTEFuY2hvckVsZW1lbnQsXG4gIFxuICAgIEhUTUxFbGVtZW50UHJvdG90eXBlID0gKFxuICAgICAgd2luZG93LkhUTUxFbGVtZW50IHx8XG4gICAgICB3aW5kb3cuRWxlbWVudCB8fFxuICAgICAgd2luZG93Lk5vZGVcbiAgICApLnByb3RvdHlwZSxcbiAgXG4gICAgSUU4ID0gIWlQTy5jYWxsKEhUTUxFbGVtZW50UHJvdG90eXBlLCBkb2N1bWVudEVsZW1lbnQpLFxuICBcbiAgICBzYWZlUHJvcGVydHkgPSBJRTggPyBmdW5jdGlvbiAobywgaywgZCkge1xuICAgICAgb1trXSA9IGQudmFsdWU7XG4gICAgICByZXR1cm4gbztcbiAgICB9IDogZGVmaW5lUHJvcGVydHksXG4gIFxuICAgIGlzVmFsaWROb2RlID0gSUU4ID9cbiAgICAgIGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHJldHVybiBub2RlLm5vZGVUeXBlID09PSAxO1xuICAgICAgfSA6XG4gICAgICBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICByZXR1cm4gaVBPLmNhbGwoSFRNTEVsZW1lbnRQcm90b3R5cGUsIG5vZGUpO1xuICAgICAgfSxcbiAgXG4gICAgdGFyZ2V0cyA9IElFOCAmJiBbXSxcbiAgXG4gICAgYXR0YWNoU2hhZG93ID0gSFRNTEVsZW1lbnRQcm90b3R5cGUuYXR0YWNoU2hhZG93LFxuICAgIGNsb25lTm9kZSA9IEhUTUxFbGVtZW50UHJvdG90eXBlLmNsb25lTm9kZSxcbiAgICBjbG9zZXN0ID0gSFRNTEVsZW1lbnRQcm90b3R5cGUuY2xvc2VzdCB8fCBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgd2hpbGUgKHNlbGYgJiYgc2VsZi5ub2RlTmFtZSAhPT0gbmFtZSlcbiAgICAgICAgc2VsZiA9IHNlbGYucGFyZW50Tm9kZTtcbiAgICAgIHJldHVybiBzZWxmO1xuICAgIH0sXG4gICAgZGlzcGF0Y2hFdmVudCA9IEhUTUxFbGVtZW50UHJvdG90eXBlLmRpc3BhdGNoRXZlbnQsXG4gICAgZ2V0QXR0cmlidXRlID0gSFRNTEVsZW1lbnRQcm90b3R5cGUuZ2V0QXR0cmlidXRlLFxuICAgIGhhc0F0dHJpYnV0ZSA9IEhUTUxFbGVtZW50UHJvdG90eXBlLmhhc0F0dHJpYnV0ZSxcbiAgICByZW1vdmVBdHRyaWJ1dGUgPSBIVE1MRWxlbWVudFByb3RvdHlwZS5yZW1vdmVBdHRyaWJ1dGUsXG4gICAgc2V0QXR0cmlidXRlID0gSFRNTEVsZW1lbnRQcm90b3R5cGUuc2V0QXR0cmlidXRlLFxuICBcbiAgICAvLyByZXBsYWNlZCBsYXRlciBvblxuICAgIGNyZWF0ZUVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50LFxuICAgIGltcG9ydE5vZGUgPSBkb2N1bWVudC5pbXBvcnROb2RlLFxuICAgIHBhdGNoZWRDcmVhdGVFbGVtZW50ID0gY3JlYXRlRWxlbWVudCxcbiAgXG4gICAgLy8gc2hhcmVkIG9ic2VydmVyIGZvciBhbGwgYXR0cmlidXRlc1xuICAgIGF0dHJpYnV0ZXNPYnNlcnZlciA9IE11dGF0aW9uT2JzZXJ2ZXIgJiYge1xuICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICBhdHRyaWJ1dGVPbGRWYWx1ZTogdHJ1ZVxuICAgIH0sXG4gIFxuICAgIC8vIHVzZWZ1bCB0byBkZXRlY3Qgb25seSBpZiB0aGVyZSdzIG5vIE11dGF0aW9uT2JzZXJ2ZXJcbiAgICBET01BdHRyTW9kaWZpZWQgPSBNdXRhdGlvbk9ic2VydmVyIHx8IGZ1bmN0aW9uKGUpIHtcbiAgICAgIGRvZXNOb3RTdXBwb3J0RE9NQXR0ck1vZGlmaWVkID0gZmFsc2U7XG4gICAgICBkb2
23459N1bWVudEVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgRE9NX0FUVFJfTU9ESUZJRUQsXG4gICAgICAgIERPTUF0dHJNb2RpZmllZFxuICAgICAgKTtcbiAgICB9LFxuICBcbiAgICAvLyB3aWxsIGJvdGggYmUgdXNlZCB0byBtYWtlIERPTU5vZGVJbnNlcnRlZCBhc3luY2hyb25vdXNcbiAgICBhc2FwUXVldWUsXG4gICAgYXNhcFRpbWVyID0gMCxcbiAgXG4gICAgLy8gaW50ZXJuYWwgZmxhZ3NcbiAgICBWMCA9IFJFR0lTVEVSX0VMRU1FTlQgaW4gZG9jdW1lbnQgJiZcbiAgICAgICAgICEvXmZvcmNlLWFsbC8udGVzdChwb2x5ZmlsbC50eXBlKSxcbiAgICBzZXRMaXN0ZW5lciA9IHRydWUsXG4gICAganVzdFNldHVwID0gZmFsc2UsXG4gICAgZG9lc05vdFN1cHBvcnRET01BdHRyTW9kaWZpZWQgPSB0cnVlLFxuICAgIGRyb3BEb21Db250ZW50TG9hZGVkID0gdHJ1ZSxcbiAgXG4gICAgLy8gbmVlZGVkIGZvciB0aGUgaW5uZXJIVE1MIGhlbHBlclxuICAgIG5vdEZyb21Jbm5lckhUTUxIZWxwZXIgPSB0cnVlLFxuICBcbiAgICAvLyBvcHRpb25hbGx5IGRlZmluZWQgbGF0ZXIgb25cbiAgICBvblN1YnRyZWVNb2RpZmllZCxcbiAgICBjYWxsRE9NQXR0ck1vZGlmaWVkLFxuICAgIGdldEF0dHJpYnV0ZXNNaXJyb3IsXG4gICAgb2JzZXJ2ZXIsXG4gICAgb2JzZXJ2ZSxcbiAgXG4gICAgLy8gYmFzZWQgb24gc2V0dGluZyBwcm90b3R5cGUgY2FwYWJpbGl0eVxuICAgIC8vIHdpbGwgY2hlY2sgcHJvdG8gb3IgdGhlIGV4cGFuZG8gYXR0cmlidXRlXG4gICAgLy8gaW4gb3JkZXIgdG8gc2V0dXAgdGhlIG5vZGUgb25jZVxuICAgIHBhdGNoSWZOb3RBbHJlYWR5LFxuICAgIHBhdGNoLFxuICBcbiAgICAvLyB1c2VkIGZvciB0ZXN0c1xuICAgIHRtcFxuICA7XG4gIFxuICAvLyBJRTExIGRpc2Nvbm5lY3RlZENhbGxiYWNrIGlzc3VlICNcbiAgLy8gdG8gYmUgdGVzdGVkIGJlZm9yZSBhbnkgY3JlYXRlRWxlbWVudCBwYXRjaFxuICBpZiAoTXV0YXRpb25PYnNlcnZlcikge1xuICAgIC8vIG9yaWdpbmFsIGZpeDpcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vamF2YW4vbXV0YXRpb24tb2JzZXJ2ZXItaW5uZXItaHRtbC1zaGltXG4gICAgdG1wID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdG1wLmlubmVySFRNTCA9ICc8ZGl2PjxkaXY+PC9kaXY+PC9kaXY+JztcbiAgICBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbiAobXV0YXRpb25zLCBvYnNlcnZlcikge1xuICAgICAgaWYgKFxuICAgICAgICBtdXRhdGlvbnNbMF0gJiZcbiAgICAgICAgbXV0YXRpb25zWzBdLnR5cGUgPT0gJ2NoaWxkTGlzdCcgJiZcbiAgICAgICAgIW11dGF0aW9uc1swXS5yZW1vdmVkTm9kZXNbMF0uY2hpbGROb2Rlcy5sZW5ndGhcbiAgICAgICkge1xuICAgICAgICB0bXAgPSBnT1BEKEhUTUxFbGVtZW50UHJvdG90eXBlLCAnaW5uZXJIVE1MJyk7XG4gICAgICAgIHZhciBzZXQgPSB0bXAgJiYgdG1wLnNldDtcbiAgICAgICAgaWYgKHNldClcbiAgICAgICAgICBkZWZpbmVQcm9wZXJ0eShIVE1MRWxlbWVudFByb3RvdHlwZSwgJ2lubmVySFRNTCcsIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIHdoaWxlICh0aGlzLmxhc3RDaGlsZClcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKHRoaXMubGFzdENoaWxkKTtcbiAgICAgICAgICAgICAgc2V0LmNhbGwodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgICAgdG1wID0gbnVsbDtcbiAgICB9KS5vYnNlcnZlKHRtcCwge2NoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZX0pO1xuICAgIHRtcC5pbm5lckhUTUwgPSBcIlwiO1xuICB9XG4gIFxuICAvLyBvbmx5IGlmIG5lZWRlZFxuICBpZiAoIVYwKSB7XG4gIFxuICAgIGlmIChzUE8gfHwgaGFzUHJvdG8pIHtcbiAgICAgICAgcGF0Y2hJZk5vdEFscmVhZHkgPSBmdW5jdGlvbiAobm9kZSwgcHJvdG8pIHtcbiAgICAgICAgICBpZiAoIWlQTy5jYWxsKHByb3RvLCBub2RlKSkge1xuICAgICAgICAgICAgc2V0dXBOb2RlKG5vZGUsIHByb3RvKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHBhdGNoID0gc2V0dXBOb2RlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdGNoSWZOb3RBbHJlYWR5ID0gZnVuY3Rpb24gKG5vZGUsIHByb3RvKSB7XG4gICAgICAgICAgaWYgKCFub2RlW0VYUEFORE9fVUlEXSkge1xuICAgICAgICAgICAgbm9kZVtFWFBBTkRPX1VJRF0gPSBPYmplY3QodHJ1ZSk7XG4gICAgICAgICAgICBzZXR1cE5vZGUobm9kZSwgcHJvdG8pO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcGF0Y2ggPSBwYXRjaElmTm90QWxyZWFkeTtcbiAgICB9XG4gIFxuICAgIGlmIChJRTgpIHtcbiAgICAgIGRvZXNOb3RTdXBwb3J0RE9NQXR0ck1vZGlmaWVkID0gZmFsc2U7XG4gICAgICAoZnVuY3Rpb24gKCl7XG4gICAgICAgIHZhclxuICAgICAgICAgIGRlc2NyaXB0b3IgPSBnT1BEKEhUTUxFbGVtZW50UHJvdG90eXBlLCBBRERfRVZFTlRfTElTVEVORVIpLFxuICAgICAgICAgIGFkZEV2ZW50TGlzdGVuZXIgPSBkZXNjcmlwdG9yLnZhbHVlLFxuICAgICAgICAgIHBhdGNoZWRSZW1vdmVBdHRyaWJ1dGUgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgdmFyIGUgPSBuZXcgQ3VzdG9tRXZlbnQoRE9NX0FUVFJfTU9ESUZJRUQsIHtidWJibGVzOiB0cnVlfSk7XG4gICAgICAgICAgICBlLmF0dHJOYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGUucHJldlZhbHVlID0gZ2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICAgICAgICBlLm5ld1ZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIGVbUkVNT1ZBTF0gPSBlLmF0dHJDaGFuZ2UgPSAyO1xuICAgICAgICAgICAgcmVtb3ZlQXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICAgICAgICBkaXNwYXRjaEV2ZW50LmNhbGwodGhpcywgZSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBwYXRjaGVkU2V0QXR0cmlidXRlID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgICAgICAgICB2Y
23459XJcbiAgICAgICAgICAgICAgaGFkID0gaGFzQXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSksXG4gICAgICAgICAgICAgIG9sZCA9IGhhZCAmJiBnZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKSxcbiAgICAgICAgICAgICAgZSA9IG5ldyBDdXN0b21FdmVudChET01fQVRUUl9NT0RJRklFRCwge2J1YmJsZXM6IHRydWV9KVxuICAgICAgICAgICAgO1xuICAgICAgICAgICAgc2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgZS5hdHRyTmFtZSA9IG5hbWU7XG4gICAgICAgICAgICBlLnByZXZWYWx1ZSA9IGhhZCA/IG9sZCA6IG51bGw7XG4gICAgICAgICAgICBlLm5ld1ZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICBpZiAoaGFkKSB7XG4gICAgICAgICAgICAgIGVbTU9ESUZJQ0FUSU9OXSA9IGUuYXR0ckNoYW5nZSA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlW0FERElUSU9OXSA9IGUuYXR0ckNoYW5nZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXNwYXRjaEV2ZW50LmNhbGwodGhpcywgZSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvblByb3BlcnR5Q2hhbmdlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIC8vIGpzaGludCBlcW51bGw6dHJ1ZVxuICAgICAgICAgICAgdmFyXG4gICAgICAgICAgICAgIG5vZGUgPSBlLmN1cnJlbnRUYXJnZXQsXG4gICAgICAgICAgICAgIHN1cGVyU2VjcmV0ID0gbm9kZVtFWFBBTkRPX1VJRF0sXG4gICAgICAgICAgICAgIHByb3BlcnR5TmFtZSA9IGUucHJvcGVydHlOYW1lLFxuICAgICAgICAgICAgICBldmVudFxuICAgICAgICAgICAgO1xuICAgICAgICAgICAgaWYgKHN1cGVyU2VjcmV0Lmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkpIHtcbiAgICAgICAgICAgICAgc3VwZXJTZWNyZXQgPSBzdXBlclNlY3JldFtwcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICBldmVudCA9IG5ldyBDdXN0b21FdmVudChET01fQVRUUl9NT0RJRklFRCwge2J1YmJsZXM6IHRydWV9KTtcbiAgICAgICAgICAgICAgZXZlbnQuYXR0ck5hbWUgPSBzdXBlclNlY3JldC5uYW1lO1xuICAgICAgICAgICAgICBldmVudC5wcmV2VmFsdWUgPSBzdXBlclNlY3JldC52YWx1ZSB8fCBudWxsO1xuICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IChzdXBlclNlY3JldC52YWx1ZSA9IG5vZGVbcHJvcGVydHlOYW1lXSB8fCBudWxsKTtcbiAgICAgICAgICAgICAgaWYgKGV2ZW50LnByZXZWYWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRbQURESVRJT05dID0gZXZlbnQuYXR0ckNoYW5nZSA9IDA7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXZlbnRbTU9ESUZJQ0FUSU9OXSA9IGV2ZW50LmF0dHJDaGFuZ2UgPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGRpc3BhdGNoRXZlbnQuY2FsbChub2RlLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICA7XG4gICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiAodHlwZSwgaGFuZGxlciwgY2FwdHVyZSkge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHR5cGUgPT09IERPTV9BVFRSX01PRElGSUVEICYmXG4gICAgICAgICAgICB0aGlzW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXSAmJlxuICAgICAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUgIT09IHBhdGNoZWRTZXRBdHRyaWJ1dGVcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXNbRVhQQU5ET19VSURdID0ge1xuICAgICAgICAgICAgICBjbGFzc05hbWU6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnY2xhc3MnLFxuICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmNsYXNzTmFtZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUgPSBwYXRjaGVkU2V0QXR0cmlidXRlO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVBdHRyaWJ1dGUgPSBwYXRjaGVkUmVtb3ZlQXR0cmlidXRlO1xuICAgICAgICAgICAgYWRkRXZlbnRMaXN0ZW5lci5jYWxsKHRoaXMsICdwcm9wZXJ0eWNoYW5nZScsIG9uUHJvcGVydHlDaGFuZ2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhZGRFdmVudExpc3RlbmVyLmNhbGwodGhpcywgdHlwZSwgaGFuZGxlciwgY2FwdHVyZSk7XG4gICAgICAgIH07XG4gICAgICAgIGRlZmluZVByb3BlcnR5KEhUTUxFbGVtZW50UHJvdG90eXBlLCBBRERfRVZFTlRfTElTVEVORVIsIGRlc2NyaXB0b3IpO1xuICAgICAgfSgpKTtcbiAgICB9IGVsc2UgaWYgKCFNdXRhdGlvbk9ic2VydmVyKSB7XG4gICAgICBkb2
23459N1bWVudEVsZW1lbnRbQUREX0VWRU5UX0xJU1RFTkVSXShET01fQVRUUl9NT0RJRklFRCwgRE9NQXR0ck1vZGlmaWVkKTtcbiAgICAgIGRvY3VtZW50RWxlbWVudC5zZXRBdHRyaWJ1dGUoRVhQQU5ET19VSUQsIDEpO1xuICAgICAgZG9jdW1lbnRFbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShFWFBBTkRPX1VJRCk7XG4gICAgICBpZiAoZG9lc05vdFN1cHBvcnRET01BdHRyTW9kaWZpZWQpIHtcbiAgICAgICAgb25TdWJ0cmVlTW9kaWZpZWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIHZhclxuICAgICAgICAgICAgbm9kZSA9IHRoaXMsXG4gICAgICAgICAgICBvbGRBdHRyaWJ1dGVzLFxuICAgICAgICAgICAgbmV3QXR0cmlidXRlcyxcbiAgICAgICAgICAgIGtleVxuICAgICAgICAgIDtcbiAgICAgICAgICBpZiAobm9kZSA9PT0gZS50YXJnZXQpIHtcbiAgICAgICAgICAgIG9sZEF0dHJpYnV0ZXMgPSBub2RlW0VYUEFORE9fVUlEXTtcbiAgICAgICAgICAgIG5vZGVbRVhQQU5ET19VSURdID0gKG5ld0F0dHJpYnV0ZXMgPSBnZXRBdHRyaWJ1dGVzTWlycm9yKG5vZGUpKTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIG5ld0F0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgICAgaWYgKCEoa2V5IGluIG9sZEF0dHJpYnV0ZXMpKSB7XG4gICAgICAgICAgICAgICAgLy8gYXR0cmlidXRlIHdhcyBhZGRlZFxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsRE9NQXR0ck1vZGlmaWVkKFxuICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICBvbGRBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBuZXdBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBBRERJVElPTlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobmV3QXR0cmlidXRlc1trZXldICE9PSBvbGRBdHRyaWJ1dGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgd2FzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbERPTUF0dHJNb2RpZmllZChcbiAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICBub2RlLFxuICAgICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgICAgb2xkQXR0cmlidXRlc1trZXldLFxuICAgICAgICAgICAgICAgICAgbmV3QXR0cmlidXRlc1trZXldLFxuICAgICAgICAgICAgICAgICAgTU9ESUZJQ0FUSU9OXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY2hlY2tpbmcgaWYgaXQgaGFzIGJlZW4gcmVtb3ZlZFxuICAgICAgICAgICAgZm9yIChrZXkgaW4gb2xkQXR0cmlidXRlcykge1xuICAgICAgICAgICAgICBpZiAoIShrZXkgaW4gbmV3QXR0cmlidXRlcykpIHtcbiAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgcmVtb3ZlZFxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsRE9NQXR0ck1vZGlmaWVkKFxuICAgICAgICAgICAgICAgICAgMixcbiAgICAgICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICBvbGRBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBuZXdBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBSRU1PVkFMXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY2FsbERPTUF0dHJNb2RpZmllZCA9IGZ1bmN0aW9uIChcbiAgICAgICAgICBhdHRyQ2hhbmdlLFxuICAgICAgICAgIGN1cnJlbnRUYXJnZXQsXG4gICAgICAgICAgYXR0ck5hbWUsXG4gICAgICAgICAgcHJldlZhbHVlLFxuICAgICAgICAgIG5ld1ZhbHVlLFxuICAgICAgICAgIGFjdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICB2Y
23459XIgZSA9IHtcbiAgICAgICAgICAgIGF0dHJDaGFuZ2U6IGF0dHJDaGFuZ2UsXG4gICAgICAgICAgICBjdXJyZW50VGFyZ2V0OiBjdXJyZW50VGFyZ2V0LFxuICAgICAgICAgICAgYXR0ck5hbWU6IGF0dHJOYW1lLFxuICAgICAgICAgICAgcHJldlZhbHVlOiBwcmV2VmFsdWUsXG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgICB9O1xuICAgICAgICAgIGVbYWN0aW9uXSA9IGF0dHJDaGFuZ2U7XG4gICAgICAgICAgb25ET01BdHRyTW9kaWZpZWQoZSk7XG4gICAgICAgIH07XG4gICAgICAgIGdldEF0dHJpYnV0ZXNNaXJyb3IgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgIGZvciAodmFyXG4gICAgICAgICAgICBhdHRyLCBuYW1lLFxuICAgICAgICAgICAgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICBhdHRyaWJ1dGVzID0gbm9kZS5hdHRyaWJ1dGVzLFxuICAgICAgICAgICAgaSA9IDAsIGxlbmd0aCA9IGF0dHJpYnV0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgaSA8IGxlbmd0aDsgaSsrXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBhdHRyID0gYXR0cmlidXRlc1tpXTtcbiAgICAgICAgICAgIG5hbWUgPSBhdHRyLm5hbWU7XG4gICAgICAgICAgICBpZiAobmFtZSAhPT0gJ3NldEF0dHJpYnV0ZScpIHtcbiAgICAgICAgICAgICAgcmVzdWx0W25hbWVdID0gYXR0ci52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gIFxuICAgIC8vIHNldCBhcyBlbnVtZXJhYmxlLCB3cml0YWJsZSBhbmQgY29uZmlndXJhYmxlXG4gICAgZG9jdW1lbnRbUkVHSVNURVJfRUxFTUVOVF0gPSBmdW5jdGlvbiByZWdpc3RlckVsZW1lbnQodHlwZSwgb3B0aW9ucykge1xuICAgICAgdXBwZXJUeXBlID0gdHlwZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgaWYgKHNldExpc3RlbmVyKSB7XG4gICAgICAgIC8vIG9ubHkgZmlyc3QgdGltZSBkb2N1bWVudC5yZWdpc3RlckVsZW1lbnQgaXMgdXNlZFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHNldCB0aGlzIGxpc3RlbmVyXG4gICAgICAgIC8vIHNldHRpbmcgaXQgYnkgZGVmYXVsdCBtaWdodCBzbG93IGRvd24gZm9yIG5vIHJlYXNvblxuICAgICAgICBzZXRMaXN0ZW5lciA9IGZhbHNlO1xuICAgICAgICBpZiAoTXV0YXRpb25PYnNlcnZlcikge1xuICAgICAgICAgIG9ic2VydmVyID0gKGZ1bmN0aW9uKGF0dGFjaGVkLCBkZXRhY2hlZCl7XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja0VtQWxsKGxpc3QsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBsaXN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgY2FsbGJhY2sobGlzdFtpKytdKSl7fVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBNdXRhdGlvbk9ic2VydmVyKGZ1bmN0aW9uIChyZWNvcmRzKSB7XG4gICAgICAgICAgICAgIGZvciAodmFyXG4gICAgICAgICAgICAgICAgY3VycmVudCwgbm9kZSwgbmV3VmFsdWUsXG4gICAgICAgICAgICAgICAgaSA9IDAsIGxlbmd0aCA9IHJlY29yZHMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKytcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudCA9IHJlY29yZHNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnQudHlwZSA9PT0gJ2NoaWxkTGlzdCcpIHtcbiAgICAgICAgICAgICAgICAgIGNoZWNrRW1BbGwoY3VycmVudC5hZGRlZE5vZGVzLCBhdHRhY2hlZCk7XG4gICAgICAgICAgICAgICAgICBjaGVja0VtQWxsKGN1cnJlbnQucmVtb3ZlZE5vZGVzLCBkZXRhY2hlZCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIG5vZGUgPSBjdXJyZW50LnRhcmdldDtcbiAgICAgICAgICAgICAgICAgIGlmIChub3RGcm9tSW5uZXJIVE1MSGVscGVyICYmXG4gICAgICAgICAgICAgICAgICAgICAgbm9kZVtBVFRSSUJVVEVfQ0hBTkdFRF9DQUxMQkFDS10gJiZcbiAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmF0dHJpYnV0ZU5hbWUgIT09ICdzdHlsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWUgPSBnZXRBdHRyaWJ1dGUuY2FsbChub2RlLCBjdXJyZW50LmF0dHJpYnV0ZU5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3VmFsdWUgIT09IGN1cnJlbnQub2xkVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICBub2RlW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXShcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuYXR0cmlidXRlTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQub2xkVmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0oZXhlY3V0ZUFjdGlvbihBVFRBQ0hFRCksIGV4ZWN1dGVBY3Rpb24oREVUQUNIRUQpKSk7XG4gICAgICAgICAgb2JzZXJ2ZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICBvYnNlcnZlci5vYnNlcnZlKFxuICAgICAgICAgICAgICBub2RlLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnRyZWU6IHRydWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgIH07XG4gICAgICAgICAgb2JzZXJ2ZShkb2N1bWVudCk7XG4gICAgICAgICAgaWYgKGF0dGFjaFNoYWRvdykge1xuICAgICAgICAgICAgSFRNTEVsZW1lbnRQcm90b3R5cGUuYXR0YWNoU2hhZG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gb2JzZXJ2ZShhdHRhY2hTaGFkb3cuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhc2FwUXVldWUgPSBbXTtcbiAgICAgICAgICBkb2
23459N1bWVudFtBRERfRVZFTlRfTElTVEVORVJdKCdET01Ob2RlSW5zZXJ0ZWQnLCBvbkRPTU5vZGUoQVRUQUNIRUQpKTtcbiAgICAgICAgICBkb2N1bWVudFtBRERfRVZFTlRfTElTVEVORVJdKCdET01Ob2RlUmVtb3ZlZCcsIG9uRE9NTm9kZShERVRBQ0hFRCkpO1xuICAgICAgICB9XG4gIFxuICAgICAgICBkb2N1bWVudFtBRERfRVZFTlRfTElTVEVORVJdKERPTV9DT05URU5UX0xPQURFRCwgb25SZWFkeVN0YXRlQ2hhbmdlKTtcbiAgICAgICAgZG9jdW1lbnRbQUREX0VWRU5UX0xJU1RFTkVSXSgncmVhZHlzdGF0ZWNoYW5nZScsIG9uUmVhZHlTdGF0ZUNoYW5nZSk7XG4gIFxuICAgICAgICBkb2N1bWVudC5pbXBvcnROb2RlID0gZnVuY3Rpb24gKG5vZGUsIGRlZXApIHtcbiAgICAgICAgICBzd2l0Y2ggKG5vZGUubm9kZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgcmV0dXJuIHNldHVwQWxsKGRvY3VtZW50LCBpbXBvcnROb2RlLCBbbm9kZSwgISFkZWVwXSk7XG4gICAgICAgICAgICBjYXNlIDExOlxuICAgICAgICAgICAgICBmb3IgKHZhclxuICAgICAgICAgICAgICAgIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpLFxuICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMgPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgICAgICAgICAgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgaSA9IDA7IGkgPCBsZW5ndGg7IGkrK1xuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuaW1wb3J0Tm9kZShjaGlsZE5vZGVzW2ldLCAhIWRlZXApKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGZyYWdtZW50O1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgcmV0dXJuIGNsb25lTm9kZS5jYWxsKG5vZGUsICEhZGVlcCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICBcbiAgICAgICAgSFRNTEVsZW1lbnRQcm90b3R5cGUuY2xvbmVOb2RlID0gZnVuY3Rpb24gKGRlZXApIHtcbiAgICAgICAgICByZXR1cm4gc2V0dXBBbGwodGhpcywgY2xvbmVOb2RlLCBbISFkZWVwXSk7XG4gICAgICAgIH07XG4gICAgICB9XG4gIFxuICAgICAgaWYgKGp1c3RTZXR1cCkgcmV0dXJuIChqdXN0U2V0dXAgPSBmYWxzZSk7XG4gIFxuICAgICAgaWYgKC0yIDwgKFxuICAgICAgICBpbmRleE9mLmNhbGwodHlwZXMsIFBSRUZJWF9JUyArIHVwcGVyVHlwZSkgK1xuICAgICAgICBpbmRleE9mLmNhbGwodHlwZXMsIFBSRUZJWF9UQUcgKyB1cHBlclR5cGUpXG4gICAgICApKSB7XG4gICAgICAgIHRocm93VHlwZUVycm9yKHR5cGUpO1xuICAgICAgfVxuICBcbiAgICAgIGlmICghdmFsaWROYW1lLnRlc3QodXBwZXJUeXBlKSB8fCAtMSA8IGluZGV4T2YuY2FsbChpbnZhbGlkTmFtZXMsIHVwcGVyVHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgdHlwZSAnICsgdHlwZSArICcgaXMgaW52YWxpZCcpO1xuICAgICAgfVxuICBcbiAgICAgIHZhclxuICAgICAgICBjb25zdHJ1Y3RvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZXh0ZW5kaW5nID9cbiAgICAgICAgICAgIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQobm9kZU5hbWUsIHVwcGVyVHlwZSkgOlxuICAgICAgICAgICAgZG9jdW1lbnQuY3JlYXRlRWxlbWVudChub2RlTmFtZSk7XG4gICAgICAgIH0sXG4gICAgICAgIG9wdCA9IG9wdGlvbnMgfHwgT1AsXG4gICAgICAgIGV4dGVuZGluZyA9IGhPUC5jYWxsKG9wdCwgRVhURU5EUyksXG4gICAgICAgIG5vZGVOYW1lID0gZXh0ZW5kaW5nID8gb3B0aW9uc1tFWFRFTkRTXS50b1VwcGVyQ2FzZSgpIDogdXBwZXJUeXBlLFxuICAgICAgICB1cHBlclR5cGUsXG4gICAgICAgIGlcbiAgICAgIDtcbiAgXG4gICAgICBpZiAoZXh0ZW5kaW5nICYmIC0xIDwgKFxuICAgICAgICBpbmRleE9mLmNhbGwodHlwZXMsIFBSRUZJWF9UQUcgKyBub2RlTmFtZSlcbiAgICAgICkpIHtcbiAgICAgICAgdGhyb3dUeXBlRXJyb3Iobm9kZU5hbWUpO1xuICAgICAgfVxuICBcbiAgICAgIGkgPSB0eXBlcy5wdXNoKChleHRlbmRpbmcgPyBQUkVGSVhfSVMgOiBQUkVGSVhfVEFHKSArIHVwcGVyVHlwZSkgLSAxO1xuICBcbiAgICAgIHF1ZXJ5ID0gcXVlcnkuY29uY2F0KFxuICAgICAgICBxdWVyeS5sZW5ndGggPyAnLCcgOiAnJyxcbiAgICAgICAgZXh0ZW5kaW5nID8gbm9kZU5hbWUgKyAnW2lzPVwiJyArIHR5cGUudG9Mb3dlckNhc2UoKSArICdcIl0nIDogbm9kZU5hbWVcbiAgICAgICk7XG4gIFxuICAgICAgY29uc3RydWN0b3IucHJvdG90eXBlID0gKFxuICAgICAgICBwcm90b3NbaV0gPSBoT1AuY2FsbChvcHQsICdwcm90b3R5cGUnKSA/XG4gICAgICAgICAgb3B0LnByb3RvdHlwZSA6XG4gICAgICAgICAgY3JlYXRlKEhUTUxFbGVtZW50UHJvdG90eXBlKVxuICAgICAgKTtcbiAgXG4gICAgICBpZiAocXVlcnkubGVuZ3RoKSBsb29wQW5kVmVyaWZ5KFxuICAgICAgICBkb2
23459N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSxcbiAgICAgICAgQVRUQUNIRURcbiAgICAgICk7XG4gIFxuICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yO1xuICAgIH07XG4gIFxuICAgIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgPSAocGF0Y2hlZENyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAobG9jYWxOYW1lLCB0eXBlRXh0ZW5zaW9uKSB7XG4gICAgICB2YXJcbiAgICAgICAgaXMgPSBnZXRJcyh0eXBlRXh0ZW5zaW9uKSxcbiAgICAgICAgbm9kZSA9IGlzID9cbiAgICAgICAgICBjcmVhdGVFbGVtZW50LmNhbGwoZG9jdW1lbnQsIGxvY2FsTmFtZSwgc2Vjb25kQXJndW1lbnQoaXMpKSA6XG4gICAgICAgICAgY3JlYXRlRWxlbWVudC5jYWxsKGRvY3VtZW50LCBsb2NhbE5hbWUpLFxuICAgICAgICBuYW1lID0gJycgKyBsb2NhbE5hbWUsXG4gICAgICAgIGkgPSBpbmRleE9mLmNhbGwoXG4gICAgICAgICAgdHlwZXMsXG4gICAgICAgICAgKGlzID8gUFJFRklYX0lTIDogUFJFRklYX1RBRykgK1xuICAgICAgICAgIChpcyB8fCBuYW1lKS50b1VwcGVyQ2FzZSgpXG4gICAgICAgICksXG4gICAgICAgIHNldHVwID0gLTEgPCBpXG4gICAgICA7XG4gICAgICBpZiAoaXMpIHtcbiAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoJ2lzJywgaXMgPSBpcy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgaWYgKHNldHVwKSB7XG4gICAgICAgICAgc2V0dXAgPSBpc0luUVNBKG5hbWUudG9VcHBlckNhc2UoKSwgaXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBub3RGcm9tSW5uZXJIVE1MSGVscGVyID0gIWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQuaW5uZXJIVE1MSGVscGVyO1xuICAgICAgaWYgKHNldHVwKSBwYXRjaChub2RlLCBwcm90b3NbaV0pO1xuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSk7XG4gIFxuICB9XG4gIFxuICAvLyBuZWVkZWQgZHVlIHVuYmVsaWV2YWJsZSBJRTExIGJlaGF2aW9yXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9XZWJSZWZsZWN0aW9uL2RvY3VtZW50LXJlZ2lzdGVyLWVsZW1lbnQvaXNzdWVzLzE3NSNpc3N1ZWNvbW1lbnQtNTIwOTA0Njg4XG4gIGFkZEV2ZW50TGlzdGVuZXIoXG4gICAgJ2JlZm9yZXVubG9hZCcsXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgZGVsZXRlIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQ7XG4gICAgICBkZWxldGUgZG9jdW1lbnQuaW1wb3J0Tm9kZTtcbiAgICAgIGRlbGV0ZSBkb2N1bWVudFtSRUdJU1RFUl9FTEVNRU5UXTtcbiAgICB9LFxuICAgIGZhbHNlXG4gICk7XG4gIFxuICBmdW5jdGlvbiBBU0FQKCkge1xuICAgIHZhciBxdWV1ZSA9IGFzYXBRdWV1ZS5zcGxpY2UoMCwgYXNhcFF1ZXVlLmxlbmd0aCk7XG4gICAgYXNhcFRpbWVyID0gMDtcbiAgICB3aGlsZSAocXVldWUubGVuZ3RoKSB7XG4gICAgICBxdWV1ZS5zaGlmdCgpLmNhbGwoXG4gICAgICAgIG51bGwsIHF1ZXVlLnNoaWZ0KClcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBsb29wQW5kVmVyaWZ5KGxpc3QsIGFjdGlvbikge1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBsaXN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2ZXJpZnlBbmRTZXR1cEFuZEFjdGlvbihsaXN0W2ldLCBhY3Rpb24pO1xuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gbG9vcEFuZFNldHVwKGxpc3QpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gbGlzdC5sZW5ndGgsIG5vZGU7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgbm9kZSA9IGxpc3RbaV07XG4gICAgICBwYXRjaChub2RlLCBwcm90b3NbZ2V0VHlwZUluZGV4KG5vZGUpXSk7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBleGVjdXRlQWN0aW9uKGFjdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgaWYgKGlzVmFsaWROb2RlKG5vZGUpKSB7XG4gICAgICAgIHZlcmlmeUFuZFNldHVwQW5kQWN0aW9uKG5vZGUsIGFjdGlvbik7XG4gICAgICAgIGlmIChxdWVyeS5sZW5ndGgpIGxvb3BBbmRWZXJpZnkoXG4gICAgICAgICAgbm9kZS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSxcbiAgICAgICAgICBhY3Rpb25cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIFxuICBmdW5jdGlvbiBnZXRUeXBlSW5kZXgodGFyZ2V0KSB7XG4gICAgdmFyXG4gICAgICBpcyA9IGdldEF0dHJpYnV0ZS5jYWxsKHRhcmdldCwgJ2lzJyksXG4gICAgICBub2RlTmFtZSA9IHRhcmdldC5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpLFxuICAgICAgaSA9IGluZGV4T2YuY2FsbChcbiAgICAgICAgdHlwZXMsXG4gICAgICAgIGlzID9cbiAgICAgICAgICAgIFBSRUZJWF9JUyArIGlzLnRvVXBwZXJDYXNlKCkgOlxuICAgICAgICAgICAgUFJFRklYX1RBRyArIG5vZGVOYW1lXG4gICAgICApXG4gICAgO1xuICAgIHJldHVybiBpcyAmJiAtMSA8IGkgJiYgIWlzSW5RU0Eobm9kZU5hbWUsIGlzKSA/IC0xIDogaTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gaXNJblFTQShuYW1lLCB0eXBlKSB7XG4gICAgcmV0dXJuIC0xIDwgcXVlcnkuaW5kZXhPZihuYW1lICsgJ1tpcz1cIicgKyB0eXBlICsgJ1wiXScpO1xuICB9XG4gIFxuICBmdW5jdGlvbiBvbkRPTUF0dHJNb2RpZmllZChlKSB7XG4gICAgdmFyXG4gICAgICBub2RlID0gZS5jdXJyZW50VGFyZ2V0LFxuICAgICAgYXR0ckNoYW5nZSA9IGUuYXR0ckNoYW5nZSxcbiAgICAgIGF0dHJOYW1lID0gZS5hdHRyTmFtZSxcbiAgICAgIHRhcmdldCA9IGUudGFyZ2V0LFxuICAgICAgYWRkaXRpb24gPSBlW0FERElUSU9OXSB8fCAyLFxuICAgICAgcmVtb3ZhbCA9IGVbUkVNT1ZBTF0gfHwgM1xuICAgIDtcbiAgICBpZiAobm90RnJvbUlubmVySFRNTEhlbHBlciAmJlxuICAgICAgICAoIXRhcmdldCB8fCB0YXJnZXQgPT09IG5vZGUpICYmXG4gICAgICAgIG5vZGVbQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdICYmXG4gICAgICAgIGF0dHJOYW1lICE9PSAnc3R5bGUnICYmIChcbiAgICAgICAgICBlLnByZXZWYWx1ZSAhPT0gZS5uZXdWYWx1ZSB8fFxuICAgICAgICAgIC8vIElFOSwgSUUxMCwgYW5kIE9wZXJhIDEyIGdvdGNoYVxuICAgICAgICAgIGUubmV3VmFsdWUgPT09ICcnICYmIChcbiAgICAgICAgICAgIGF0dHJDaGFuZ2UgPT09IGFkZGl0aW9uIHx8XG4gICAgICAgICAgICBhdHRyQ2hhbmdlID09PSByZW1vdmFsXG4gICAgICAgICAgKVxuICAgICkpIHtcbiAgICAgIG5vZGVbQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdKFxuICAgICAgICBhdHRyTmFtZSxcbiAgICAgICAgYXR0ckNoYW5nZSA9PT0gYWRkaXRpb24gPyBudWxsIDogZS5wcmV2VmFsdWUsXG4gICAgICAgIGF0dHJDaGFuZ2UgPT09IHJlbW92YWwgPyBudWxsIDogZS5uZXdWYWx1ZVxuICAgICAgKTtcbiAgICB9XG4gI
23459H1cbiAgXG4gIGZ1bmN0aW9uIG9uRE9NTm9kZShhY3Rpb24pIHtcbiAgICB2YXIgZXhlY3V0b3IgPSBleGVjdXRlQWN0aW9uKGFjdGlvbik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChlKSB7XG4gICAgICBhc2FwUXVldWUucHVzaChleGVjdXRvciwgZS50YXJnZXQpO1xuICAgICAgaWYgKGFzYXBUaW1lcikgY2xlYXJUaW1lb3V0KGFzYXBUaW1lcik7XG4gICAgICBhc2FwVGltZXIgPSBzZXRUaW1lb3V0KEFTQVAsIDEpO1xuICAgIH07XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIG9uUmVhZHlTdGF0ZUNoYW5nZShlKSB7XG4gICAgaWYgKGRyb3BEb21Db250ZW50TG9hZGVkKSB7XG4gICAgICBkcm9wRG9tQ29udGVudExvYWRlZCA9IGZhbHNlO1xuICAgICAgZS5jdXJyZW50VGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoRE9NX0NPTlRFTlRfTE9BREVELCBvblJlYWR5U3RhdGVDaGFuZ2UpO1xuICAgIH1cbiAgICBpZiAocXVlcnkubGVuZ3RoKSBsb29wQW5kVmVyaWZ5KFxuICAgICAgKGUudGFyZ2V0IHx8IGRvY3VtZW50KS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSxcbiAgICAgIGUuZGV0YWlsID09PSBERVRBQ0hFRCA/IERFVEFDSEVEIDogQVRUQUNIRURcbiAgICApO1xuICAgIGlmIChJRTgpIHB1cmdlKCk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHBhdGNoZWRTZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUpIHtcbiAgICAvLyBqc2hpbnQgdmFsaWR0aGlzOnRydWVcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgc2V0QXR0cmlidXRlLmNhbGwoc2VsZiwgbmFtZSwgdmFsdWUpO1xuICAgIG9uU3VidHJlZU1vZGlmaWVkLmNhbGwoc2VsZiwge3RhcmdldDogc2VsZn0pO1xuICB9XG4gIFxuICBmdW5jdGlvbiBzZXR1cEFsbChjb250ZXh0LCBjYWxsYmFjaywgYXJncykge1xuICAgIHZhclxuICAgICAgbm9kZSA9IGNhbGxiYWNrLmFwcGx5KGNvbnRleHQsIGFyZ3MpLFxuICAgICAgaSA9IGdldFR5cGVJbmRleChub2RlKVxuICAgIDtcbiAgICBpZiAoLTEgPCBpKSBwYXRjaChub2RlLCBwcm90b3NbaV0pO1xuICAgIGlmIChhcmdzLnBvcCgpICYmIHF1ZXJ5Lmxlbmd0aClcbiAgICAgIGxvb3BBbmRTZXR1cChub2RlLnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpKTtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gc2V0dXBOb2RlKG5vZGUsIHByb3RvKSB7XG4gICAgc2V0UHJvdG90eXBlKG5vZGUsIHByb3RvKTtcbiAgICBpZiAob2JzZXJ2ZXIpIHtcbiAgICAgIG9ic2VydmVyLm9ic2VydmUobm9kZSwgYXR0cmlidXRlc09ic2VydmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRvZXNOb3RTdXBwb3J0RE9NQXR0ck1vZGlmaWVkKSB7XG4gICAgICAgIG5vZGUuc2V0QXR0cmlidXRlID0gcGF0Y2hlZFNldEF0dHJpYnV0ZTtcbiAgICAgICAgbm9kZVtFWFBBTkRPX1VJRF0gPSBnZXRBdHRyaWJ1dGVzTWlycm9yKG5vZGUpO1xuICAgICAgICBub2RlW0FERF9FVkVOVF9MSVNURU5FUl0oRE9NX1NVQlRSRUVfTU9ESUZJRUQsIG9uU3VidHJlZU1vZGlmaWVkKTtcbiAgICAgIH1cbiAgICAgIG5vZGVbQUREX0VWRU5UX0xJU1RFTkVSXShET01fQVRUUl9NT0RJRklFRCwgb25ET01BdHRyTW9kaWZpZWQpO1xuICAgIH1cbiAgICBpZiAobm9kZVtDUkVBVEVEX0NBTExCQUNLXSAmJiBub3RGcm9tSW5uZXJIVE1MSGVscGVyKSB7XG4gICAgICBub2RlLmNyZWF0ZWQgPSB0cnVlO1xuICAgICAgbm9kZVtDUkVBVEVEX0NBTExCQUNLXSgpO1xuICAgICAgbm9kZS5jcmVhdGVkID0gZmFsc2U7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBwdXJnZSgpIHtcbiAgICBmb3IgKHZhclxuICAgICAgbm9kZSxcbiAgICAgIGkgPSAwLFxuICAgICAgbGVuZ3RoID0gdGFyZ2V0cy5sZW5ndGg7XG4gICAgICBpIDwgbGVuZ3RoOyBpKytcbiAgICApIHtcbiAgICAgIG5vZGUgPSB0YXJnZXRzW2ldO1xuICAgICAgaWYgKCFkb2N1bWVudEVsZW1lbnQuY29udGFpbnMobm9kZSkpIHtcbiAgICAgICAgbGVuZ3RoLS07XG4gICAgICAgIHRhcmdldHMuc3BsaWNlKGktLSwgMSk7XG4gICAgICAgIHZlcmlmeUFuZFNldHVwQW5kQWN0aW9uKG5vZGUsIERFVEFDSEVEKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHRocm93VHlwZUVycm9yKHR5cGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgJyArIHR5cGUgKyAnIHR5cGUgaXMgYWxyZWFkeSByZWdpc3RlcmVkJyk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHZlcmlmeUFuZFNldHVwQW5kQWN0aW9uKG5vZGUsIGFjdGlvbikge1xuICAgIHZhclxuICAgICAgZm4sXG4gICAgICBpID0gZ2V0VHlwZUluZGV4KG5vZGUpLFxuICAgICAgY291bnRlckFjdGlvblxuICAgIDtcbiAgICBpZiAoKC0xIDwgaSkgJiYgIWNsb3Nlc3QuY2FsbChub2RlLCAnVEVNUExBVEUnKSkge1xuICAgICAgcGF0Y2hJZk5vdEFscmVhZHkobm9kZSwgcHJvdG9zW2ldKTtcbiAgICAgIGkgPSAwO1xuICAgICAgaWYgKGFjdGlvbiA9PT0gQVRUQUNIRUQgJiYgIW5vZGVbQVRUQUNIRURdKSB7XG4gICAgICAgIG5vZGVbREVUQUNIRURdID0gZmFsc2U7XG4gICAgICAgIG5vZGVbQVRUQUNIRURdID0gdHJ1ZTtcbiAgICAgICAgY291bnRlckFjdGlvbiA9ICdjb25uZWN0ZWQnO1xuICAgICAgICBpID0gMTtcbiAgICAgICAgaWYgKElFOCAmJiBpbmRleE9mLmNhbGwodGFyZ2V0cywgbm9kZSkgPCAwKSB7XG4gICAgICAgICAgdGFyZ2V0cy5wdXNoKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGFjdGlvbiA9PT0gREVUQUNIRUQgJiYgIW5vZGVbREVUQUNIRURdKSB7XG4gICAgICAgIG5vZGVbQVRUQUNIRURdID0gZmFsc2U7XG4gICAgICAgIG5vZGVbREVUQUNIRURdID0gdHJ1ZTtcbiAgICAgICAgY291bnRlckFjdGlvbiA9ICdkaXNjb25uZWN0ZWQnO1xuICAgICAgICBpID0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChpICYmIChmbiA9IChcbiAgICAgICAgbm9kZVthY3Rpb24gKyBDQUxMQkFDS10gfHxcbiAgICAgICAgbm9kZVtjb3VudGVyQWN0aW9uICsgQ0FMTEJBQ0tdXG4gICAgICApKSkgZm4uY2FsbChub2RlKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8vIFYxIGluIGRhIEhvdXNlIVxuICBmdW5jdGlvbiBDdXN0b21FbGVtZW50UmVnaXN0cnkoKSB7fVxuICBcbiAgQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZSA9IHtcbiAgICBjb25zdHJ1Y3RvcjogQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LFxuICAgIC8vIGEgd29ya2Fyb3VuZCBmb3IgdGhlIHN0dWJib3JuIFdlYktpdFxuICAgIGRlZmluZTogdXNhYmxlQ3VzdG9tRWxlbWVudHMgP1xuICAgICAgZnVuY3Rpb24gKG5hbWUsIENsYXNzLCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zKSB7XG4gICAgICAgICAgQ0VSRGVmaW5lKG5hbWUsIENsYXNzLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2Y
23459XIgTkFNRSA9IG5hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICBjb25zdHJ1Y3RvcnNbTkFNRV0gPSB7XG4gICAgICAgICAgICBjb25zdHJ1Y3RvcjogQ2xhc3MsXG4gICAgICAgICAgICBjcmVhdGU6IFtOQU1FXVxuICAgICAgICAgIH07XG4gICAgICAgICAgbm9kZU5hbWVzLnNldChDbGFzcywgTkFNRSk7XG4gICAgICAgICAgY3VzdG9tRWxlbWVudHMuZGVmaW5lKG5hbWUsIENsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfSA6XG4gICAgICBDRVJEZWZpbmUsXG4gICAgZ2V0OiB1c2FibGVDdXN0b21FbGVtZW50cyA/XG4gICAgICBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gY3VzdG9tRWxlbWVudHMuZ2V0KG5hbWUpIHx8IGdldChuYW1lKTtcbiAgICAgIH0gOlxuICAgICAgZ2V0LFxuICAgIHdoZW5EZWZpbmVkOiB1c2FibGVDdXN0b21FbGVtZW50cyA/XG4gICAgICBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICBjdXN0b21FbGVtZW50cy53aGVuRGVmaW5lZChuYW1lKSxcbiAgICAgICAgICB3aGVuRGVmaW5lZChuYW1lKVxuICAgICAgICBdKTtcbiAgICAgIH0gOlxuICAgICAgd2hlbkRlZmluZWRcbiAgfTtcbiAgXG4gIGZ1bmN0aW9uIENFUkRlZmluZShuYW1lLCBDbGFzcywgb3B0aW9ucykge1xuICAgIHZhclxuICAgICAgaXMgPSBvcHRpb25zICYmIG9wdGlvbnNbRVhURU5EU10gfHwgJycsXG4gICAgICBDUHJvdG8gPSBDbGFzcy5wcm90b3R5cGUsXG4gICAgICBwcm90byA9IGNyZWF0ZShDUHJvdG8pLFxuICAgICAgYXR0cmlidXRlcyA9IENsYXNzLm9ic2VydmVkQXR0cmlidXRlcyB8fCBlbXB0eSxcbiAgICAgIGRlZmluaXRpb24gPSB7cHJvdG90eXBlOiBwcm90b31cbiAgICA7XG4gICAgLy8gVE9ETzogaXMgdGhpcyBuZWVkZWQgYXQgYWxsIHNpbmNlIGl0J3MgaW5oZXJpdGVkP1xuICAgIC8vIGRlZmluZVByb3BlcnR5KHByb3RvLCAnY29uc3RydWN0b3InLCB7dmFsdWU6IENsYXNzfSk7XG4gICAgc2FmZVByb3BlcnR5KHByb3RvLCBDUkVBVEVEX0NBTExCQUNLLCB7XG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKGp1c3RDcmVhdGVkKSBqdXN0Q3JlYXRlZCA9IGZhbHNlO1xuICAgICAgICAgIGVsc2UgaWYgKCF0aGlzW0RSRUNFVjFdKSB7XG4gICAgICAgICAgICB0aGlzW0RSRUNFVjFdID0gdHJ1ZTtcbiAgICAgICAgICAgIG5ldyBDbGFzcyh0aGlzKTtcbiAgICAgICAgICAgIGlmIChDUHJvdG9bQ1JFQVRFRF9DQUxMQkFDS10pXG4gICAgICAgICAgICAgIENQcm90b1tDUkVBVEVEX0NBTExCQUNLXS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgdmFyIGluZm8gPSBjb25zdHJ1Y3RvcnNbbm9kZU5hbWVzLmdldChDbGFzcyldO1xuICAgICAgICAgICAgaWYgKCF1c2FibGVDdXN0b21FbGVtZW50cyB8fCBpbmZvLmNyZWF0ZS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgIG5vdGlmeUF0dHJpYnV0ZXModGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHNhZmVQcm9wZXJ0eShwcm90bywgQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0ssIHtcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICBpZiAoLTEgPCBpbmRleE9mLmNhbGwoYXR0cmlidXRlcywgbmFtZSkpIHtcbiAgICAgICAgICBpZiAoQ1Byb3RvW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXSlcbiAgICAgICAgICAgIENQcm90b1tBVFRSSUJVVEVfQ0hBTkdFRF9DQUxMQkFDS10uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChDUHJvdG9bQ09OTkVDVEVEX0NBTExCQUNLXSkge1xuICAgICAgc2FmZVByb3BlcnR5KHByb3RvLCBBVFRBQ0hFRF9DQUxMQkFDSywge1xuICAgICAgICB2YWx1ZTogQ1Byb3RvW0NPTk5FQ1RFRF9DQUxMQkFDS11cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoQ1Byb3RvW0RJU0NPTk5FQ1RFRF9DQUxMQkFDS10pIHtcbiAgICAgIHNhZmVQcm9wZXJ0eShwcm90bywgREVUQUNIRURfQ0FMTEJBQ0ssIHtcbiAgICAgICAgdmFsdWU6IENQcm90b1tESVNDT05ORUNURURfQ0FMTEJBQ0tdXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGlzKSBkZWZpbml0aW9uW0VYVEVORFNdID0gaXM7XG4gICAgbmFtZSA9IG5hbWUudG9VcHBlckNhc2UoKTtcbiAgICBjb25zdHJ1Y3RvcnNbbmFtZV0gPSB7XG4gICAgICBjb25zdHJ1Y3RvcjogQ2xhc3MsXG4gICAgICBjcmVhdGU6IGlzID8gW2lzLCBzZWNvbmRBcmd1bWVudChuYW1lKV0gOiBbbmFtZV1cbiAgICB9O1xuICAgIG5vZGVOYW1lcy5zZXQoQ2xhc3MsIG5hbWUpO1xuICAgIGRvY3VtZW50W1JFR0lTVEVSX0VMRU1FTlRdKG5hbWUudG9Mb3dlckNhc2UoKSwgZGVmaW5pdGlvbik7XG4gICAgd2hlbkRlZmluZWQobmFtZSk7XG4gICAgd2FpdGluZ0xpc3RbbmFtZV0ucigpO1xuICB9XG4gIFxuICBmdW5jdGlvbiBnZXQobmFtZSkge1xuICAgIHZhciBpbmZvID0gY29uc3RydWN0b3JzW25hbWUudG9VcHBlckNhc2UoKV07XG4gICAgcmV0dXJuIGluZm8gJiYgaW5mby5jb25zdHJ1Y3RvcjtcbiAgfVxuICBcbiAgZnVuY3Rpb24gZ2V0SXMob3B0aW9ucykge1xuICAgIHJldHVybiB0eXBlb2Ygb3B0aW9ucyA9PT0gJ3N0cmluZycgP1xuICAgICAgICBvcHRpb25zIDogKG9wdGlvbnMgJiYgb3B0aW9ucy5pcyB8fCAnJyk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIG5vdGlmeUF0dHJpYnV0ZXMoc2VsZikge1xuICAgIHZhclxuICAgICAgY2FsbGJhY2sgPSBzZWxmW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXSxcbiAgICAgIGF0dHJpYnV0ZXMgPSBjYWxsYmFjayA/IHNlbGYuYXR0cmlidXRlcyA6IGVtcHR5LFxuICAgICAgaSA9IGF0dHJpYnV0ZXMubGVuZ3RoLFxuICAgICAgYXR0cmlidXRlXG4gICAgO1xuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgIGF0dHJpYnV0ZSA9ICBhdHRyaWJ1dGVzW2ldOyAvLyB8fCBhdHRyaWJ1dGVzLml0ZW0oaSk7XG4gICAgICBjYWxsYmFjay5jYWxsKFxuICAgICAgICBzZWxmLFxuICAgICAgICBhdHRyaWJ1dGUubmFtZSB8fCBhdHRyaWJ1dGUubm9kZU5hbWUsXG4gICAgICAgIG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZS52YWx1ZSB8fCBhdHRyaWJ1dGUubm9kZVZhbHVlXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gd2hlbkRlZmluZWQobmFtZSkge1xuICAgIG5hbWUgPSBuYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgaWYgKCEobmFtZSBpbiB3YWl0aW5nTGlzdCkpIHtcbiAgICAgIHdhaXRpbmdMaXN0W25hbWVdID0ge307XG4gICAgICB3YWl0aW5nTGlzdFtuYW1lXS5wID0gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICAgICAgd2FpdGluZ0xpc3RbbmFtZV0uciA9IHJlc29sdmU7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHdhaXRpbmdMaXN0W25hbWVdLnA7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHBvbHlmaWxsVjEoKSB7XG4gICAgaWYgKGN1c3RvbUVsZW1lbnRzKSBkZWxldGUgd2luZG93LmN1c3RvbUVsZW1lbnRzO1xuICAgIGRlZmluZVByb3BlcnR5KHdpbmRvdywgJ2N1c3RvbUVsZW1lbnRzJywge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgdmFsdWU6IG5ldyBDdXN0b21FbGVtZW50UmVnaXN0cnkoKVxuICAgIH0pO1xuICAgIGRlZmluZVByb3BlcnR5KHdpbmRvdywgJ0N1c3RvbUVsZW1lbnRSZWdpc3RyeScsIHtcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHZhbHVlOiBDdXN0b21FbGVtZW50UmVnaXN0cnlcbiAgICB9KTtcbiAgICBmb3IgKHZhclxuICAgICAgcGF0Y2hDbGFzcyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgI
23459HZhciBDbGFzcyA9IHdpbmRvd1tuYW1lXTtcbiAgICAgICAgaWYgKENsYXNzKSB7XG4gICAgICAgICAgd2luZG93W25hbWVdID0gZnVuY3Rpb24gQ3VzdG9tRWxlbWVudHNWMShzZWxmKSB7XG4gICAgICAgICAgICB2YXIgaW5mbywgaXNOYXRpdmU7XG4gICAgICAgICAgICBpZiAoIXNlbGYpIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmW0RSRUNFVjFdKSB7XG4gICAgICAgICAgICAgIGp1c3RDcmVhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgaW5mbyA9IGNvbnN0cnVjdG9yc1tub2RlTmFtZXMuZ2V0KHNlbGYuY29uc3RydWN0b3IpXTtcbiAgICAgICAgICAgICAgaXNOYXRpdmUgPSB1c2FibGVDdXN0b21FbGVtZW50cyAmJiBpbmZvLmNyZWF0ZS5sZW5ndGggPT09IDE7XG4gICAgICAgICAgICAgIHNlbGYgPSBpc05hdGl2ZSA/XG4gICAgICAgICAgICAgICAgUmVmbGVjdC5jb25zdHJ1Y3QoQ2xhc3MsIGVtcHR5LCBpbmZvLmNvbnN0cnVjdG9yKSA6XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuY3JlYXRlRWxlbWVudC5hcHBseShkb2N1bWVudCwgaW5mby5jcmVhdGUpO1xuICAgICAgICAgICAgICBzZWxmW0RSRUNFVjFdID0gdHJ1ZTtcbiAgICAgICAgICAgICAganVzdENyZWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgaWYgKCFpc05hdGl2ZSkgbm90aWZ5QXR0cmlidXRlcyhzZWxmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgIH07XG4gICAgICAgICAgd2luZG93W25hbWVdLnByb3RvdHlwZSA9IENsYXNzLnByb3RvdHlwZTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gd2luZG93W25hbWVdO1xuICAgICAgICAgIH0gY2F0Y2goV2ViS2l0KSB7XG4gICAgICAgICAgICBmaXhHZXRDbGFzcyA9IHRydWU7XG4gICAgICAgICAgICBkZWZpbmVQcm9wZXJ0eShDbGFzcywgRFJFQ0VWMSwge3ZhbHVlOiB3aW5kb3dbbmFtZV19KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBDbGFzc2VzID0gaHRtbENsYXNzLmdldCgvXkhUTUxbQS1aXSpbYS16XS8pLFxuICAgICAgaSA9IENsYXNzZXMubGVuZ3RoO1xuICAgICAgaS0tO1xuICAgICAgcGF0Y2hDbGFzcyhDbGFzc2VzW2ldKVxuICAgICkge31cbiAgICAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIChuYW1lLCBvcHRpb25zKSB7XG4gICAgICB2Y
23459XIgaXMgPSBnZXRJcyhvcHRpb25zKTtcbiAgICAgIHJldHVybiBpcyA/XG4gICAgICAgIHBhdGNoZWRDcmVhdGVFbGVtZW50LmNhbGwodGhpcywgbmFtZSwgc2Vjb25kQXJndW1lbnQoaXMpKSA6XG4gICAgICAgIHBhdGNoZWRDcmVhdGVFbGVtZW50LmNhbGwodGhpcywgbmFtZSk7XG4gICAgfSk7XG4gICAgaWYgKCFWMCkge1xuICAgICAganVzdFNldHVwID0gdHJ1ZTtcbiAgICAgIGRvY3VtZW50W1JFR0lTVEVSX0VMRU1FTlRdKCcnKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8vIGlmIGN1c3RvbUVsZW1lbnRzIGlzIG5vdCB0aGVyZSBhdCBhbGxcbiAgaWYgKCFjdXN0b21FbGVtZW50cyB8fCAvXmZvcmNlLy50ZXN0KHBvbHlmaWxsLnR5cGUpKSBwb2x5ZmlsbFYxKCk7XG4gIGVsc2UgaWYoIXBvbHlmaWxsLm5vQnVpbHRJbikge1xuICAgIC8vIGlmIGF2YWlsYWJsZSB0ZXN0IGV4dGVuZHMgd29yayBhcyBleHBlY3RlZFxuICAgIHRyeSB7XG4gICAgICAoZnVuY3Rpb24gKERSRSwgb3B0aW9ucywgbmFtZSkge1xuICAgICAgICB2YXIgcmUgPSBuZXcgUmVnRXhwKCdePGFcXFxccytpcz0oXFwnfFwiKScgKyBuYW1lICsgJ1xcXFwxPjwvYT4kJyk7XG4gICAgICAgIG9wdGlvbnNbRVhURU5EU10gPSAnYSc7XG4gICAgICAgIERSRS5wcm90b3R5cGUgPSBjcmVhdGUoSFRNTEFuY2hvckVsZW1lbnQucHJvdG90eXBlKTtcbiAgICAgICAgRFJFLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IERSRTtcbiAgICAgICAgd2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZShuYW1lLCBEUkUsIG9wdGlvbnMpO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgIXJlLnRlc3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScsIHtpczogbmFtZX0pLm91dGVySFRNTCkgfHxcbiAgICAgICAgICAhcmUudGVzdCgobmV3IERSRSgpKS5vdXRlckhUTUwpXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG9wdGlvbnM7XG4gICAgICAgIH1cbiAgICAgIH0oXG4gICAgICAgIGZ1bmN0aW9uIERSRSgpIHtcbiAgICAgICAgICByZXR1cm4gUmVmbGVjdC5jb25zdHJ1Y3QoSFRNTEFuY2hvckVsZW1lbnQsIFtdLCBEUkUpO1xuICAgICAgICB9LFxuICAgICAgICB7fSxcbiAgICAgICAgJ2RvY3VtZW50LXJlZ2lzdGVyLWVsZW1lbnQtYScgKyBVSURcbiAgICAgICkpO1xuICAgIH0gY2F0Y2gob19PKSB7XG4gICAgICAvLyBvciBmb3JjZSB0aGUgcG9seWZpbGwgaWYgbm90XG4gICAgICAvLyBhbmQga2VlcCBpbnRlcm5hbCBvcmlnaW5hbCByZWZlcmVuY2VcbiAgICAgIHBvbHlmaWxsVjEoKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8vIEZpcmVGb3ggb25seSBpc3N1ZVxuICBpZighcG9seWZpbGwubm9CdWlsdEluKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChjcmVhdGVFbGVtZW50LmNhbGwoZG9jdW1lbnQsICdhJywgJ2EnKS5vdXRlckhUTUwuaW5kZXhPZignaXMnKSA8IDApXG4gICAgICAgIHRocm93IHt9O1xuICAgIH0gY2F0Y2goRmlyZUZveCkge1xuICAgICAgc2Vjb25kQXJndW1lbnQgPSBmdW5jdGlvbiAoaXMpIHtcbiAgICAgICAgcmV0dXJuIHtpczogaXMudG9Mb3dlckNhc2UoKX07XG4gICAgICB9O1xuICAgIH1cbiAgfVxuICBcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbnN0YWxsQ3VzdG9tRWxlbWVudHM7XG5pbnN0YWxsQ3VzdG9tRWxlbWVudHMoZ2xvYmFsKTtcbiIsInZhciB3aW47XG5cbmlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgd2luID0gd2luZG93O1xufSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgd2luID0gZ2xvYmFsO1xufSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIil7XG4gICAgd2luID0gc2VsZjtcbn0gZWxzZSB7XG4gICAgd2luID0ge307XG59XG5cbm1vZHVsZS5leHBvcnRzID0gd2luO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuXHQoZ2xvYmFsLkdsc2xDYW52YXMgPSBmYWN0b3J5KCkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbnZhciBjb21tb25qc0dsb2JhbCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgPyBzZWxmIDoge307XG5cbnZhciB3aW47XG5cbmlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgd2luID0gd2luZG93O1xufSBlbHNlIGlmICh0eXBlb2YgY29tbW9uanNHbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB3aW4gPSBjb21tb25qc0dsb2JhbDtcbn0gZWxzZSBpZiAodHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIpe1xuICAgIHdpbiA9IHNlbGY7XG59IGVsc2Uge1xuICAgIHdpbiA9IHt9O1xufVxuXG52YXIgd2luZG93XzEgPSB3aW47XG5cbnZhciBpc0Z1bmN0aW9uXzEgPSBpc0Z1bmN0aW9uO1xuXG52YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uIChmbikge1xuICBpZiAoIWZuKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgdmFyIHN0cmluZyA9IHRvU3RyaW5nLmNhbGwoZm4pO1xuICByZXR1cm4gc3RyaW5nID09PSAnW29iamVjdCBGdW5jdGlvbl0nIHx8XG4gICAgKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyAmJiBzdHJpbmcgIT09ICdbb2JqZWN0IFJlZ0V4cF0nKSB8fFxuICAgICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAvLyBJRTggYW5kIGJlbG93XG4gICAgIChmbiA9PT0gd2luZG93LnNldFRpbWVvdXQgfHxcbiAgICAgIGZuID09PSB3aW5kb3cuYWxlcnQgfHxcbiAgICAgIGZuID09PSB3aW5kb3cuY29uZmlybSB8fFxuICAgICAgZm4gPT09IHdpbmRvdy5wcm9tcHQpKVxufVxuXG52YXIgdHJpbSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKTtcbn07XG52YXIgaXNBcnJheSA9IGZ1bmN0aW9uKGFyZykge1xuICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcmcpID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgIH07XG5cbnZhciBwYXJzZUhlYWRlcnMgPSBmdW5jdGlvbiAoaGVhZGVycykge1xuICBpZiAoIWhlYWRlcnMpXG4gICAgcmV0dXJuIHt9XG5cbiAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gIHZhciBoZWFkZXJzQXJyID0gdHJpbShoZWFkZXJzKS5zcGxpdCgnXFxuJyk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoZWFkZXJzQXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJvdyA9IGhlYWRlcnNBcnJbaV07XG4gICAgdmFyIGluZGV4ID0gcm93LmluZGV4T2YoJzonKVxuICAgICwga2V5ID0gdHJpbShyb3cuc2xpY2UoMCwgaW5kZXgpKS50b0xvd2VyQ2FzZSgpXG4gICAgLCB2YWx1ZSA9IHRyaW0ocm93LnNsaWNlKGluZGV4ICsgMSkpO1xuXG4gICAgaWYgKHR5cGVvZihyZXN1bHRba2V5XSkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheShyZXN1bHRba2V5XSkpIHtcbiAgICAgIHJlc3VsdFtrZXldLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRba2V5XSA9IFsgcmVzdWx0W2tleV0sIHZhbHVlIF07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufTtcblxudmFyIGltbXV0YWJsZSA9IGV4dGVuZDtcblxudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxuZnVuY3Rpb24gZXh0ZW5kKCkge1xuICAgIHZhciB0YXJnZXQgPSB7fTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgI
23459HZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07XG5cbiAgICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0YXJnZXRcbn1cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cblxuXG5cblxudmFyIHhociA9IGNyZWF0ZVhIUjtcbi8vIEFsbG93IHVzZSBvZiBkZWZhdWx0IGltcG9ydCBzeW50YXggaW4gVHlwZVNjcmlwdFxudmFyIGRlZmF1bHRfMSA9IGNyZWF0ZVhIUjtcbmNyZWF0ZVhIUi5YTUxIdHRwUmVxdWVzdCA9IHdpbmRvd18xLlhNTEh0dHBSZXF1ZXN0IHx8IG5vb3A7XG5jcmVhdGVYSFIuWERvbWFpblJlcXVlc3QgPSBcIndpdGhDcmVkZW50aWFsc1wiIGluIChuZXcgY3JlYXRlWEhSLlhNTEh0dHBSZXF1ZXN0KCkpID8gY3JlYXRlWEhSLlhNTEh0dHBSZXF1ZXN0IDogd2luZG93XzEuWERvbWFpblJlcXVlc3Q7XG5cbmZvckVhY2hBcnJheShbXCJnZXRcIiwgXCJwdXRcIiwgXCJwb3N0XCIsIFwicGF0Y2hcIiwgXCJoZWFkXCIsIFwiZGVsZXRlXCJdLCBmdW5jdGlvbihtZXRob2QpIHtcbiAgICBjcmVhdGVYSFJbbWV0aG9kID09PSBcImRlbGV0ZVwiID8gXCJkZWxcIiA6IG1ldGhvZF0gPSBmdW5jdGlvbih1cmksIG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gICAgICAgIG9wdGlvbnMgPSBpbml0UGFyYW1zKHVyaSwgb3B0aW9ucywgY2FsbGJhY2spO1xuICAgICAgICBvcHRpb25zLm1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gX2NyZWF0ZVhIUihvcHRpb25zKVxuICAgIH07XG59KTtcblxuZnVuY3Rpb24gZm9yRWFjaEFycmF5KGFycmF5LCBpdGVyYXRvcikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlcmF0b3IoYXJyYXlbaV0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNFbXB0eShvYmope1xuICAgIGZvcih2YXIgaSBpbiBvYmope1xuICAgICAgICBpZihvYmouaGFzT3duUHJvcGVydHkoaSkpIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBpbml0UGFyYW1zKHVyaSwgb3B0aW9ucywgY2FsbGJhY2spIHtcbiAgICB2YXIgcGFyYW1zID0gdXJpO1xuXG4gICAgaWYgKGlzRnVuY3Rpb25fMShvcHRpb25zKSkge1xuICAgICAgICBjYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgICAgIGlmICh0eXBlb2YgdXJpID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSB7dXJpOnVyaX07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBwYXJhbXMgPSBpbW11dGFibGUob3B0aW9ucywge3VyaTogdXJpfSk7XG4gICAgfVxuXG4gICAgcGFyYW1zLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgcmV0dXJuIHBhcmFtc1xufVxuXG5mdW5jdGlvbiBjcmVhdGVYSFIodXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIG9wdGlvbnMgPSBpbml0UGFyYW1zKHVyaSwgb3B0aW9ucywgY2FsbGJhY2spO1xuICAgIHJldHVybiBfY3JlYXRlWEhSKG9wdGlvbnMpXG59XG5cbmZ1bmN0aW9uIF9jcmVhdGVYSFIob3B0aW9ucykge1xuICAgIGlmKHR5cGVvZiBvcHRpb25zLmNhbGxiYWNrID09PSBcInVuZGVmaW5lZFwiKXtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2FsbGJhY2sgYXJndW1lbnQgbWlzc2luZ1wiKVxuICAgIH1cblxuICAgIHZhciBjYWxsZWQgPSBmYWxzZTtcbiAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiBjYk9uY2UoZXJyLCByZXNwb25zZSwgYm9keSl7XG4gICAgICAgIGlmKCFjYWxsZWQpe1xuICAgICAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2soZXJyLCByZXNwb25zZSwgYm9keSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVhZHlzdGF0ZWNoYW5nZSgpIHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGxvYWRGdW5jLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJvZHkoKSB7XG4gICAgICAgIC8vIENocm9tZSB3aXRoIHJlcXVlc3RUeXBlPWJsb2IgdGhyb3dzIGVycm9ycyBhcnJvdW5kIHdoZW4gZXZlbiB0ZXN0aW5nIGFjY2VzcyB0byByZXNwb25zZVRleHRcbiAgICAgICAgdmFyIGJvZHkgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKHhoci5yZXNwb25zZSkge1xuICAgICAgICAgICAgYm9keSA9IHhoci5yZXNwb25zZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJvZHkgPSB4aHIucmVzcG9uc2VUZXh0IHx8IGdldFhtbCh4aHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzSnNvbikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYm9keVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVycm9yRnVuYyhldnQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRUaW1lcik7XG4gICAgICAgIGlmKCEoZXZ0IGluc3RhbmNlb2YgRXJyb3IpKXtcbiAgICAgICAgICAgIGV2dCA9IG5ldyBFcnJvcihcIlwiICsgKGV2dCB8fCBcIlVua25vd24gWE1MSHR0cFJlcXVlc3QgRXJyb3JcIikgKTtcbiAgICAgICAgfVxuICAgICAgICBldnQuc3RhdHVzQ29kZSA9IDA7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhldnQsIGZhaWx1cmVSZXNwb25zZSlcbiAgICB9XG5cbiAgICAvLyB3aWxsIGxvYWQgdGhlIGRhdGEgJiBwcm9jZXNzIHRoZSByZXNwb25zZSBpbiBhIHNwZWNpYWwgcmVzcG9uc2Ugb2JqZWN0XG4gICAgZnVuY3Rpb24gbG9hZEZ1bmMoKSB7XG4gICAgICAgIGlmIChhYm9ydGVkKSByZXR1cm5cbiAgICAgICAgdmFyIHN0YXR1cztcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRUaW1lcik7XG4gICAgICAgIGlmKG9wdGlvbnMudXNlWERSICYmIHhoci5zdGF0dXM9PT11bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vSUU4IENPUlMgR0VUIHN1Y2Nlc3NmdWwgcmVzcG9uc2UgZG9lc24ndCBoYXZlIGEgc3RhdHVzIGZpZWxkLCBidXQgYm9keSBpcyBmaW5lXG4gICAgICAgICAgICBzdGF0dXMgPSAyMDA7XG4gICAgICAgI
23459H0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0dXMgPSAoeGhyLnN0YXR1cyA9PT0gMTIyMyA/IDIwNCA6IHhoci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXNwb25zZSA9IGZhaWx1cmVSZXNwb25zZTtcbiAgICAgICAgdmFyIGVyciA9IG51bGw7XG5cbiAgICAgICAgaWYgKHN0YXR1cyAhPT0gMCl7XG4gICAgICAgICAgICByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICBib2R5OiBnZXRCb2R5KCksXG4gICAgICAgICAgICAgICAgc3RhdHVzQ29kZTogc3RhdHVzLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICAgICAgICAgIHVybDogdXJpLFxuICAgICAgICAgICAgICAgIHJhd1JlcXVlc3Q6IHhoclxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmKHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMpeyAvL3JlbWVtYmVyIHhociBjYW4gaW4gZmFjdCBiZSBYRFIgZm9yIENPUlMgaW4gSUVcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXJzID0gcGFyc2VIZWFkZXJzKHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoXCJJbnRlcm5hbCBYTUxIdHRwUmVxdWVzdCBFcnJvclwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyLCByZXNwb25zZSwgcmVzcG9uc2UuYm9keSlcbiAgICB9XG5cbiAgICB2YXIgeGhyID0gb3B0aW9ucy54aHIgfHwgbnVsbDtcblxuICAgIGlmICgheGhyKSB7XG4gICAgICAgIGlmIChvcHRpb25zLmNvcnMgfHwgb3B0aW9ucy51c2VYRFIpIHtcbiAgICAgICAgICAgIHhociA9IG5ldyBjcmVhdGVYSFIuWERvbWFpblJlcXVlc3QoKTtcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICB4aHIgPSBuZXcgY3JlYXRlWEhSLlhNTEh0dHBSZXF1
23459ZXN0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIga2V5O1xuICAgIHZhciBhYm9ydGVkO1xuICAgIHZhciB1cmkgPSB4aHIudXJsID0gb3B0aW9ucy51cmkgfHwgb3B0aW9ucy51cmw7XG4gICAgdmFyIG1ldGhvZCA9IHhoci5tZXRob2QgPSBvcHRpb25zLm1ldGhvZCB8fCBcIkdFVFwiO1xuICAgIHZhciBib2R5ID0gb3B0aW9ucy5ib2R5IHx8IG9wdGlvbnMuZGF0YTtcbiAgICB2YXIgaGVhZGVycyA9IHhoci5oZWFkZXJzID0gb3B0aW9ucy5oZWFkZXJzIHx8IHt9O1xuICAgIHZhciBzeW5jID0gISFvcHRpb25zLnN5bmM7XG4gICAgdmFyIGlzSnNvbiA9IGZhbHNlO1xuICAgIHZhciB0aW1lb3V0VGltZXI7XG4gICAgdmFyIGZhaWx1cmVSZXNwb25zZSA9IHtcbiAgICAgICAgYm9keTogdW5kZWZpbmVkLFxuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICAgICAgc3RhdHVzQ29kZTogMCxcbiAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgIHVybDogdXJpLFxuICAgICAgICByYXdSZXF1ZXN0OiB4aHJcbiAgICB9O1xuXG4gICAgaWYgKFwianNvblwiIGluIG9wdGlvbnMgJiYgb3B0aW9ucy5qc29uICE9PSBmYWxzZSkge1xuICAgICAgICBpc0pzb24gPSB0cnVlO1xuICAgICAgICBoZWFkZXJzW1wiYWNjZXB0XCJdIHx8IGhlYWRlcnNbXCJBY2NlcHRcIl0gfHwgKGhlYWRlcnNbXCJBY2NlcHRcIl0gPSBcImFwcGxpY2F0aW9uL2pzb25cIik7IC8vRG9uJ3Qgb3ZlcnJpZGUgZXhpc3RpbmcgYWNjZXB0IGhlYWRlciBkZWNsYXJlZCBieSB1c2VyXG4gICAgICAgIGlmIChtZXRob2QgIT09IFwiR0VUXCIgJiYgbWV0aG9kICE9PSBcIkhFQURcIikge1xuICAgICAgICAgICAgaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSB8fCBoZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdIHx8IChoZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJhcHBsaWNhdGlvbi9qc29uXCIpOyAvL0Rvbid0IG92ZXJyaWRlIGV4aXN0aW5nIGFjY2VwdCBoZWFkZXIgZGVjbGFyZWQgYnkgdXNlclxuICAgICAgICAgICAgYm9keSA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMuanNvbiA9PT0gdHJ1ZSA/IGJvZHkgOiBvcHRpb25zLmpzb24pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IHJlYWR5c3RhdGVjaGFuZ2U7XG4gICAgeGhyLm9ubG9hZCA9IGxvYWRGdW5jO1xuICAgIHhoci5vbmVycm9yID0gZXJyb3JGdW5jO1xuICAgIC8vIElFOSBtdXN0IGhhdmUgb25wcm9ncmVzcyBiZSBzZXQgdG8gYSB1bmlxdWUgZnVuY3Rpb24uXG4gICAgeGhyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIElFIG11c3QgZGllXG4gICAgfTtcbiAgICB4aHIub25hYm9ydCA9IGZ1bmN0aW9uKCl7XG4gICAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgIH07XG4gICAgeGhyLm9udGltZW91dCA9IGVycm9yRnVuYztcbiAgICB4aHIub3BlbihtZXRob2QsIHVyaSwgIXN5bmMsIG9wdGlvbnMudXNlcm5hbWUsIG9wdGlvbnMucGFzc3dvcmQpO1xuICAgIC8vaGFzIHRvIGJlIGFmdGVyIG9wZW5cbiAgICBpZighc3luYykge1xuICAgICAgICB4aHIud2l0aENyZWRlbnRpYWxzID0gISFvcHRpb25zLndpdGhDcmVkZW50aWFscztcbiAgICB9XG4gICAgLy8gQ2Fubm90IHNldCB0aW1lb3V0IHdpdGggc3luYyByZXF1ZXN0XG4gICAgLy8gbm90IHNldHRpbmcgdGltZW91dCBvbiB0aGUgeGhyIG9iamVjdCwgYmVjYXVzZSBvZiBvbGQgd2Via2l0cyBldGMuIG5vdCBoYW5kbGluZyB0aGF0IGNvcnJlY3RseVxuICAgIC8vIGJvdGggbnBtJ3MgcmVxdWVzdCBhbmQganF1ZXJ5IDEueCB1c2UgdGhpcyBraW5kIG9mIHRpbWVvdXQsIHNvIHRoaXMgaXMgYmVpbmcgY29uc2lzdGVudFxuICAgIGlmICghc3luYyAmJiBvcHRpb25zLnRpbWVvdXQgPiAwICkge1xuICAgICAgICB0aW1lb3V0VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBpZiAoYWJvcnRlZCkgcmV0dXJuXG4gICAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTsvL0lFOSBtYXkgc3RpbGwgY2FsbCByZWFkeXN0YXRlY2hhbmdlXG4gICAgICAgICAgICB4aHIuYWJvcnQoXCJ0aW1lb3V0XCIpO1xuICAgICAgICAgICAgdmFyIGUgPSBuZXcgRXJyb3IoXCJYTUxIdHRwUmVxdWVzdCB0aW1lb3V0XCIpO1xuICAgICAgICAgICAgZS5jb2RlID0gXCJFVElNRURPVVRcIjtcbiAgICAgICAgICAgIGVycm9yRnVuYyhlKTtcbiAgICAgICAgfSwgb3B0aW9ucy50aW1lb3V0ICk7XG4gICAgfVxuXG4gICAgaWYgKHhoci5zZXRSZXF1ZXN0SGVhZGVyKSB7XG4gICAgICAgIGZvcihrZXkgaW4gaGVhZGVycyl7XG4gICAgICAgICAgICBpZihoZWFkZXJzLmhhc093blByb3BlcnR5KGtleSkpe1xuICAgICAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5oZWFkZXJzICYmICFpc0VtcHR5KG9wdGlvbnMuaGVhZGVycykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSGVhZGVycyBjYW5ub3QgYmUgc2V0IG9uIGFuIFhEb21haW5SZXF1ZXN0IG9iamVjdFwiKVxuICAgIH1cblxuICAgIGlmIChcInJlc3BvbnNlVHlwZVwiIGluIG9wdGlvbnMpIHtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IG9wdGlvbnMucmVzcG9uc2VUeXBlO1xuICAgIH1cblxuICAgIGlmIChcImJlZm9yZVNlbmRcIiBpbiBvcHRpb25zICYmXG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmJlZm9yZVNlbmQgPT09IFwiZnVuY3Rpb25cIlxuICAgICkge1xuICAgICAgICBvcHRpb25zLmJlZm9yZVNlbmQoeGhyKTtcbiAgICB9XG5cbiAgICAvLyBNaWNyb3NvZnQgRWRnZSBicm93c2VyIHNlbmRzIFwidW5kZWZpbmVkXCIgd2hlbiBzZW5kIGlzIGNhbGxlZCB3aXRoIHVuZGVmaW5lZCB2YWx1ZS5cbiAgICAvLyBYTUxIdHRwUmVxdWVzdCBzcGVjIHNheXMgdG8gcGFzcyBudWxsIGFzIGJvZHkgdG8gaW5kaWNhdGUgbm8gYm9keVxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbmF1Z3R1ci94aHIvaXNzdWVzLzEwMC5cbiAgICB4aHIuc2
23459VuZChib2R5IHx8IG51bGwpO1xuXG4gICAgcmV0dXJuIHhoclxuXG5cbn1cblxuZnVuY3Rpb24gZ2V0WG1sKHhocikge1xuICAgIC8vIHhoci5yZXNwb25zZVhNTCB3aWxsIHRocm93IEV4Y2VwdGlvbiBcIkludmFsaWRTdGF0ZUVycm9yXCIgb3IgXCJET01FeGNlcHRpb25cIlxuICAgIC8vIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvcmVzcG9uc2VYTUwuXG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHhoci5yZXNwb25zZVR5cGUgPT09IFwiZG9jdW1lbnRcIikge1xuICAgICAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVhNTFxuICAgICAgICB9XG4gICAgICAgIHZhciBmaXJlZm94QnVnVGFrZW5FZmZlY3QgPSB4aHIucmVzcG9uc2VYTUwgJiYgeGhyLnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PT0gXCJwYXJzZXJlcnJvclwiO1xuICAgICAgICBpZiAoeGhyLnJlc3BvbnNlVHlwZSA9PT0gXCJcIiAmJiAhZmlyZWZveEJ1Z1Rha2VuRWZmZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4geGhyLnJlc3BvbnNlWE1MXG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgcmV0dXJuIG51bGxcbn1cblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnhoci5kZWZhdWx0ID0gZGVmYXVsdF8xO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikge1xuICByZXR1cm4gdHlwZW9mIG9iajtcbn0gOiBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xufTtcblxuXG5cblxuXG52YXIgYXN5bmNHZW5lcmF0b3IgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEF3YWl0VmFsdWUodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiBBc3luY0dlbmVyYXRvcihnZW4pIHtcbiAgICB2YXIgZnJvbnQsIGJhY2s7XG5cbiAgICBmdW5jdGlvbiBzZW5kKGtleSwgYXJnKSB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICB2Y
23459XIgcmVxdWVzdCA9IHtcbiAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICBhcmc6IGFyZyxcbiAgICAgICAgICByZXNvbHZlOiByZXNvbHZlLFxuICAgICAgICAgIHJlamVjdDogcmVqZWN0LFxuICAgICAgICAgIG5leHQ6IG51bGxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoYmFjaykge1xuICAgICAgICAgIGJhY2sgPSBiYWNrLm5leHQgPSByZXF1ZXN0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZyb250ID0gYmFjayA9IHJlcXVlc3Q7XG4gICAgICAgICAgcmVzdW1lKGtleSwgYXJnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzdW1lKGtleSwgYXJnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZ2VuW2tleV0oYXJnKTtcbiAgICAgICAgdmFyIHZhbHVlID0gcmVzdWx0LnZhbHVlO1xuXG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEF3YWl0VmFsdWUpIHtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUodmFsdWUudmFsdWUpLnRoZW4oZnVuY3Rpb24gKGFyZykge1xuICAgICAgICAgICAgcmVzdW1lKFwibmV4dFwiLCBhcmcpO1xuICAgICAgICAgIH0sIGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgICAgIHJlc3VtZShcInRocm93XCIsIGFyZyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0dGxlKHJlc3VsdC5kb25lID8gXCJyZXR1cm5cIiA6IFwibm9ybWFsXCIsIHJlc3VsdC52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzZXR0bGUoXCJ0aHJvd1wiLCBlcnIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldHRsZSh0eXBlLCB2YWx1ZSkge1xuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgXCJyZXR1cm5cIjpcbiAgICAgICAgICBmcm9udC5yZXNvbHZlKHtcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgIGRvbmU6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIFwidGhyb3dcIjpcbiAgICAgICAgICBmcm9udC5yZWplY3QodmFsdWUpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgZnJvbnQucmVzb2x2ZSh7XG4gICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICBkb25lOiBmYWxzZVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBmcm9udCA9IGZyb250Lm5leHQ7XG5cbiAgICAgIGlmIChmcm9udCkge1xuICAgICAgICByZXN1bWUoZnJvbnQua2V5LCBmcm9udC5hcmcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYmFjayA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5faW52b2tlID0gc2VuZDtcblxuICAgIGlmICh0eXBlb2YgZ2VuLnJldHVybiAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aGlzLnJldHVybiA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBpZiAodHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5hc3luY0l0ZXJhdG9yKSB7XG4gICAgQXN5bmNHZW5lcmF0b3IucHJvdG90eXBlW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gIH1cblxuICBBc3luY0dlbmVyYXRvci5wcm90b3R5cGUubmV4dCA9IGZ1bmN0aW9uIChhcmcpIHtcbiAgICByZXR1cm4gdGhpcy5faW52b2tlKFwibmV4dFwiLCBhcmcpO1xuICB9O1xuXG4gIEFzeW5jR2VuZXJhdG9yLnByb3RvdHlwZS50aHJvdyA9IGZ1bmN0aW9uIChhcmcpIHtcbiAgICByZXR1cm4gdGhpcy5faW52b2tlKFwidGhyb3dcIiwgYXJnKTtcbiAgfTtcblxuICBBc3luY0dlbmVyYXRvci5wcm90b3R5cGUucmV0dXJuID0gZnVuY3Rpb24gKGFyZykge1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoXCJyZXR1cm5cIiwgYXJnKTtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIHdyYXA6IGZ1bmN0aW9uIChmbikge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBBc3luY0dlbmVyYXRvcihmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgIH07XG4gICAgfSxcbiAgICBhd2FpdDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICByZXR1cm4gbmV3IEF3YWl0VmFsdWUodmFsdWUpO1xuICAgIH1cbiAgfTtcbn0oKTtcblxuXG5cblxuXG52YXIgY2xhc3NDYWxsQ2hlY2sgPSBmdW5jdGlvbiAoaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7XG4gIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgfVxufTtcblxudmFyIGNyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2Y
23459XIgZGVzY3JpcHRvciA9IHByb3BzW2ldO1xuICAgICAgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlO1xuICAgICAgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlO1xuICAgICAgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gICAgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7XG4gICAgcmV0dXJuIENvbnN0cnVjdG9yO1xuICB9O1xufSgpO1xuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbnZhciB0b0NvbnN1bWFibGVBcnJheSA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIGFycjJbaV0gPSBhcnJbaV07XG5cbiAgICByZXR1cm4gYXJyMjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShhcnIpO1xuICB9XG59O1xuXG52YXIgbGFzdEVycm9yID0gJyc7XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgSFRMTSBmb3IgYSBmYWlsdXJlIG1lc3NhZ2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBjYW52YXNDb250YWluZXJJZCBpZCBvZiBjb250YWluZXIgb2YgdGhcbiAqICAgICAgICBjYW52YXMuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBodG1sLlxuICovXG5mdW5jdGlvbiBtYWtlRmFpbEhUTUwobXNnKSB7XG4gICAgcmV0dXJuICdcXG48dGFibGUgc3R5bGU9XCJiYWNrZ3JvdW5kLWNvbG9yOiAjOENFOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlO1wiPjx0cj5cXG48dGQgYWxpZ249XCJjZW50ZXJcIj5cXG48ZGl2IHN0eWxlPVwiZGlzcGxheTogdGFibGUtY2VsbDsgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcIj5cXG48ZGl2IHN0eWxlPVwiXCI+JyArIG1zZyArICc8L2Rpdj5cXG48L2Rpdj5cXG48L3RkPjwvdHI+PC90YWJsZT5cXG4nO1xufVxuXG4vKipcbiAqIE1lc3NhZ2UgZm9yIGdldHRpbmcgYSB3ZWJnbCBicm93c2VyXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG52YXIgR0VUX0FfV0VCR0xfQlJPV1NFUiA9ICdcXG5cXHRUaGlzIHBhZ2UgcmVxdWlyZXMgYSBicm93c2VyIHRoYXQgc3VwcG9ydHMgV2ViR0wuPGJyLz5cXG5cXHQ8YSBocmVmPVwiaHR0cDovL2dldC53ZWJnbC5vcmdcIj5DbGljayBoZXJlIHRvIHVwZ3JhZGUgeW91ciBicm93c2VyLjwvYT5cXG4nO1xuXG4vKipcbiAqIE1lc3NhZ2UgZm9yIG5lZWQgYmV0dGVyIGhhcmR3YXJlXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG52YXIgT1RIRVJfUFJPQkxFTSA9ICdcXG5cXHRJdCBkb2VzIG5vdCBhcHBlYXIgeW91ciBjb21wdXRlciBjYW4gc3VwcG9ydCBXZWJHTC48YnIvPlxcblxcdDxhIGhyZWY9XCJodHRwOi8vZ2V0LndlYmdsLm9yZy90cm91Ymxlc2hvb3RpbmcvXCI+Q2xpY2sgaGVyZSBmb3IgbW9yZSBpbmZvcm1hdGlvbi48L2E+XFxuJztcblxuLyoqXG4gKiBDb2RlIHRvIHJldHVybiBpbiBgb25FcnJvcmAgY2FsbGJhY2sgd2hlbiB0aGUgYnJvd3NlciBkb2Vzbid0IHN1cHBvcnQgd2ViZ2xcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cbnZhciBFUlJPUl9CUk9XU0VSX1NVUFBPUlQgPSAxO1xuXG4vKipcbiAqIENvZGUgdG8gcmV0dXJuIGluIGBvbkVycm9yYCBjYWxsYmFjayB0aGVyZSdzIGFueSBvdGhlciBwcm9ibGVtIHJlbGF0ZWQgdG8gd2ViZ2xcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cbnZhciBFUlJPUl9PVEhFUiA9IDI7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHdlYmdsIGNvbnRleHQuIElmIGNyZWF0aW9uIGZhaWxzIGl0IHdpbGxcbiAqIGNoYW5nZSB0aGUgY29udGVudHMgb2YgdGhlIGNvbnRhaW5lciBvZiB0aGUgPGNhbnZhcz5cbiAqIHRhZyB0byBhbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIGNvcnJlY3QgbGlua3MgZm9yIFdlYkdMLFxuICogdW5sZXNzIGBvbkVycm9yYCBvcHRpb24gaXMgZGVmaW5lZCB0byBhIGNhbGxiYWNrLFxuICogd2hpY2ggYWxsb3dzIGZvciBjdXN0b20gZXJyb3IgaGFuZGxpbmcuLlxuICogQHBhcmFtIHtFbGVtZW50fSBjYW52YXMuIFRoZSBjYW52YXMgZWxlbWVudCB0byBjcmVhdGUgYVxuICogICAgIGNvbnRleHQgZnJvbS5cbiAqIEBwYXJhbSB7V2ViR0xDb250ZXh0Q3JlYXRpb25BdHRyaWJ1dGVzfSBvcHRBdHRyaWJzIEFueVxuICogICAgIGNyZWF0aW9uIGF0dHJpYnV0ZXMgeW91IHdhbnQgdG8gcGFzcyBpbi5cbiAqIEByZXR1cm4ge1dlYkdMUmVuZGVyaW5nQ29udGV4dH0gVGhlIGNyZWF0ZWQgY29udGV4dC5cbiAqL1xuZnVuY3Rpb24gc2V0dXBXZWJHTChjYW52YXMsIG9wdEF0dHJpYnMsIG9uRXJyb3IpIHtcbiAgICBmdW5jdGlvbiBzaG93TGluayhzdHIpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IGNhbnZhcy5wYXJlbnROb2RlO1xuICAgICAgICBpZiAoY29udGFpbmVyKSB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gbWFrZUZhaWxIVE1MKHN0cik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVFcnJvcihlcnJvckNvZGUsIG1zZykge1xuICAgICAgICBpZiAodHlwZW9mIG9uRXJyb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG9uRXJyb3IoZXJyb3JDb2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNob3dMaW5rKG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXdpbmRvdy5XZWJHTFJlbmRlcmluZ0NvbnRleHQpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoRVJST1JfQlJPV1NFUl9TVVBQT1JULCBHRVRfQV9XRUJHTF9CUk9XU0VSKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIGNvbnRleHQgPSBjcmVhdGUzRENvbnRleHQoY2FudmFzLCBvcHRBdHRyaWJzKTtcbiAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoRVJST1JfT1RIRVIsIE9USEVSX1BST0JMRU0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRleHQuZ2V0RXh0ZW5zaW9uKCdPRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXMnKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHQ7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHdlYmdsIGNvbnRleHQuXG4gKiBAcGFyYW0geyFDYW52YXN9IGNhbnZhcyBUaGUgY2FudmFzIHRhZyB0byBnZXQgY29udGV4dFxuICogICAgIGZyb20uIElmIG9uZSBpcyBub3QgcGFzc2VkIGluIG9uZSB3aWxsIGJlIGNyZWF0ZWQuXG4gKiBAcmV0dXJuIHshV2ViR0xDb250ZXh0fSBUaGUgY3JlYXRlZCBjb250ZXh0LlxuICovXG5mdW5jdGlvbiBjcmVhdGUzRENvbnRleHQoY2FudmFzLCBvcHRBdHRyaWJzKSB7XG4gICAgdmFyIG5hbWVzID0gWyd3ZWJnbCcsICdleHBlcmltZW50YWwtd2ViZ2wnXTtcbiAgICB2YXIgY29udGV4dCA9IG51bGw7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IG5hbWVzLmxlbmd0aDsgKytpaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KG5hbWVzW2lpXSwgb3B0QXR0cmlicyk7XG4gICAgICAgI
23459H0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHQ7XG59XG5cbi8qXG4gKlx0Q3JlYXRlIGEgVmVydGV4IG9mIGEgc3BlY2lmaWMgdHlwZSAoZ2wuVkVSVEVYX1NIQURFUi8pXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVNoYWRlcihtYWluLCBzb3VyY2UsIHR5cGUsIG9mZnNldCkge1xuICAgIHZhciBnbCA9IG1haW4uZ2w7XG5cbiAgICB2YXIgc2hhZGVyID0gZ2wuY3JlYXRlU2hhZGVyKHR5cGUpO1xuICAgIGdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNvdXJjZSk7XG4gICAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuXG4gICAgdmFyIGNvbXBpbGVkID0gZ2wuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgZ2wuQ09NUElMRV9TVEFUVVMpO1xuXG4gICAgaWYgKCFjb21waWxlZCkge1xuICAgICAgICAvLyBTb21ldGhpbmcgd2VudCB3cm9uZyBkdXJpbmcgY29tcGlsYXRpb247IGdldCB0aGUgZXJyb3JcbiAgICAgICAgbGFzdEVycm9yID0gZ2wuZ2V0U2hhZGVySW5mb0xvZyhzaGFkZXIpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCcqKiogRXJyb3IgY29tcGlsaW5nIHNoYWRlciAnICsgc2hhZGVyICsgJzonICsgbGFzdEVycm9yKTtcbiAgICAgICAgbWFpbi50cmlnZ2VyKCdlcnJvcicsIHtcbiAgICAgICAgICAgIHNoYWRlcjogc2hhZGVyLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgZXJyb3I6IGxhc3RFcnJvcixcbiAgICAgICAgICAgIG9mZnNldDogb2Zmc2V0IHx8IDBcbiAgICAgICAgfSk7XG4gICAgICAgIGdsLmRlbGV0ZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2hhZGVyO1xufVxuXG4vKipcbiAqIExvYWRzIGEgc2hhZGVyLlxuICogQHBhcmFtIHshV2ViR0xDb250ZXh0fSBnbCBUaGUgV2ViR0xDb250ZXh0IHRvIHVzZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzaGFkZXJTb3VyY2UgVGhlIHNoYWRlciBzb3VyY2UuXG4gKiBAcGFyYW0ge251bWJlcn0gc2hhZGVyVHlwZSBUaGUgdHlwZSBvZiBzaGFkZXIuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKHN0cmluZyk6IHZvaWQpIG9wdF9lcnJvckNhbGxiYWNrIGNhbGxiYWNrIGZvciBlcnJvcnMuXG4gKiBAcmV0dXJuIHshV2ViR0xTaGFkZXJ9IFRoZSBjcmVhdGVkIHNoYWRlci5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlUHJvZ3JhbShtYWluLCBzaGFkZXJzLCBvcHRBdHRyaWJzLCBvcHRMb2NhdGlvbnMpIHtcbiAgICB2YXIgZ2wgPSBtYWluLmdsO1xuXG4gICAgdmFyIHByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IHNoYWRlcnMubGVuZ3RoOyArK2lpKSB7XG4gICAgICAgIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBzaGFkZXJzW2lpXSk7XG4gICAgfVxuICAgIGlmIChvcHRBdHRyaWJzKSB7XG4gICAgICAgIGZvciAodmFyIF9paSA9IDA7IF9paSA8IG9wdEF0dHJpYnMubGVuZ3RoOyArK19paSkge1xuICAgICAgICAgICAgZ2wuYmluZEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIG9wdExvY2F0aW9ucyA/IG9wdExvY2F0aW9uc1tfaWldIDogX2lpLCBvcHRBdHRyaWJzW19paV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuXG4gICAgLy8gQ2hlY2sgdGhlIGxpbmsgc3RhdHVzXG4gICAgdmFyIGxpbmtlZCA9IGdsLmdldFByb2dyYW1QYXJhbWV0ZXIocHJvZ3JhbSwgZ2wuTElOS19TVEFUVVMpO1xuICAgIGlmICghbGlua2VkKSB7XG4gICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggdGhlIGxpbmtcbiAgICAgICAgbGFzdEVycm9yID0gZ2wuZ2V0UHJvZ3JhbUluZm9Mb2cocHJvZ3JhbSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciBpbiBwcm9ncmFtIGxpbmtpbmc6JyArIGxhc3RFcnJvcik7XG4gICAgICAgIGdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gcHJvZ3JhbTtcbn1cblxuLy8gQnkgQnJldHQgQ2FtYmVyIG9uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vdGFuZ3JhbXMvdGFuZ3JhbS9ibG9iL21hc3Rlci9zcmMvZ2wvZ2xzbC5qc1xuZnVuY3Rpb24gcGFyc2VVbmlmb3Jtcyh1bmlmb3Jtcykge1xuICAgIHZhciBwcmVmaXggPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7XG5cbiAgICB2YXIgcGFyc2VkID0gW107XG5cbiAgICBmb3IgKHZhciBuYW1lIGluIHVuaWZvcm1zKSB7XG4gICAgICAgIHZhciB1bmlmb3JtID0gdW5pZm9ybXNbbmFtZV07XG4gICAgICAgIHZhciB1ID0gdm9pZCAwO1xuXG4gICAgICAgIGlmIChwcmVmaXgpIHtcbiAgICAgICAgICAgIG5hbWUgPSBwcmVmaXggKyAnLicgKyBuYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2luZ2xlIGZsb2F0XG4gICAgICAgIGlmICh0eXBlb2YgdW5pZm9ybSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHBhcnNlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnZmxvYXQnLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJzFmJyxcbiAgICAgICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgICAgIHZhbHVlOiB1bmlmb3JtXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBcnJheTogdmVjdG9yLCBhcnJheSBvZiBmbG9hdHMsIGFycmF5IG9mIHRleHR1cmVzLCBvciBhcnJheSBvZiBzdHJ1Y3RzXG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodW5pZm9ybSkpIHtcbiAgICAgICAgICAgICAgICAvLyBOdW1lcmljIHZhbHVlc1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdW5pZm9ybVswXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZmxvYXQgdmVjdG9ycyAodmVjMiwgdmVjMywgdmVjNClcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVuaWZvcm0ubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJzZWQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Zsb2F0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6ICcxZicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5pZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgI
23459H1cbiAgICAgICAgICAgICAgICAgICAgLy8gZmxvYXQgdmVjdG9ycyAodmVjMiwgdmVjMywgdmVjNClcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodW5pZm9ybS5sZW5ndGggPj0gMiAmJiB1bmlmb3JtLmxlbmd0aCA8PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndmVjJyArIHVuaWZvcm0ubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6IHVuaWZvcm0ubGVuZ3RoICsgJ2Z2JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuaWZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZsb2F0IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh1bmlmb3JtLmxlbmd0aCA+IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Zsb2F0W10nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnMWZ2JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG5hbWUgKyAnWzBdJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1bmlmb3JtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogYXNzdW1lIG1hdHJpeCBmb3IgKHR5cGVvZiA9PSBGbG9hdDMyQXJyYXkgJiYgbGVuZ3RoID09IDE2KT9cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gQXJyYXkgb2YgdGV4dHVyZXNcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgdW5pZm9ybVswXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc2FtcGxlcjJEJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6ICcxaScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5pZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gQXJyYXkgb2YgYXJyYXlzIC0gYnV0IG9ubHkgYXJyYXlzIG9mIHZlY3RvcnMgYXJlIGFsbG93ZWQgaW4gdGhpcyBjYXNlXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodW5pZm9ybVswXSkgJiYgdHlwZW9mIHVuaWZvcm1bMF1bMF0gPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmxvYXQgdmVjdG9ycyAodmVjMiwgdmVjMywgdmVjNClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodW5pZm9ybVswXS5sZW5ndGggPj0gMiAmJiB1bmlmb3JtWzBdLmxlbmd0aCA8PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh1ID0gMDsgdSA8IHVuaWZvcm0ubGVuZ3RoOyB1KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndmVjJyArIHVuaWZvcm1bMF0ubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogdW5pZm9ybVt1XS5sZW5ndGggKyAnZnYnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG5hbWUgKyAnWycgKyB1ICsgJ10nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1bmlmb3JtW3VdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBlbHNlIGVycm9yP1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXJyYXkgb2Ygc3RydWN0dXJlc1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoX3R5cGVvZih1bmlmb3JtWzBdKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh1ID0gMDsgdSA8IHVuaWZvcm0ubGVuZ3RoOyB1KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBlYWNoIHN0cnVjdCBpbiB0aGUgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZC5wdXNoLmFwcGx5KHBhcnNlZCwgdG9Db25zdW1hYmxlQXJyYXkocGFyc2VVbmlmb3Jtcyh1bmlmb3JtW3VdLCBuYW1lICsgJ1snICsgdSArICddJykpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEJvb2xlYW5cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiB1bmlmb3JtID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VkLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Jvb2wnLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnMWknLFxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1bmlmb3JtXG4gICAgICAgICAgICAgICAgICAgI
23459H0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBUZXh0dXJlXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHVuaWZvcm0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJzZWQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3NhbXBsZXIyRCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnMWknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuaWZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIFN0cnVjdHVyZVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgodHlwZW9mIHVuaWZvcm0gPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHVuaWZvcm0pKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgZWFjaCBmaWVsZCBpbiB0aGUgc3RydWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkLnB1c2guYXBwbHkocGFyc2VkLCB0b0NvbnN1bWFibGVBcnJheShwYXJzZVVuaWZvcm1zKHVuaWZvcm0sIG5hbWUpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IHN1cHBvcnQgb3RoZXIgbm9uLWZsb2F0IHR5cGVzPyAoaW50LCBldGMuKVxuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xufVxuXG5mdW5jdGlvbiBpc0NhbnZhc1Zpc2libGUoY2FudmFzKSB7XG4gICAgdmFyIGJvdW5kID0gY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiBib3VuZC50b3AgKyBib3VuZC5oZWlnaHQgPiAwICYmIGJvdW5kLnRvcCA8ICh3aW5kb3cuaW5uZXJIZWlnaHQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCk7XG59XG5cbmZ1bmN0aW9uIGlzUG93ZXJPZjIodmFsdWUpIHtcbiAgICByZXR1cm4gKHZhbHVlICYgdmFsdWUgLSAxKSA9PT0gMDtcbn1cblxuZnVuY3Rpb24gaXNTYWZhcmkoKSB7XG4gICAgcmV0dXJuICgvXigoPyFjaHJvbWV8YW5kcm9pZCkuKSpzYWZhcmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpXG4gICAgKTtcbn1cblxuXG5cblxuXG5cblxuZnVuY3Rpb24gaXNEaWZmKGEsIGIpIHtcbiAgICBpZiAoYSAmJiBiKSB7XG4gICAgICAgIHJldHVybiBhLnRvU3RyaW5nKCkgIT09IGIudG9TdHJpbmcoKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBnZXRGaWxlKHVybCkge1xuICAgIHZhciBodHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIGh0dHBSZXF1ZXN0Lm9wZW4oXCJHRVRcIiwgdXJsLCBmYWxzZSk7XG4gICAgaHR0cFJlcXVlc3Quc2VuZCgpO1xuICAgIGlmIChodHRwUmVxdWVzdC5zdGF0dXMgPT0gMjAwKSByZXR1cm4gaHR0cFJlcXVlc3QucmVzcG9uc2VUZXh0O2Vsc2UgcmV0dXJuIFwiXCI7XG59XG5cbmZ1bmN0aW9uIHN1YnNjcmliZU1peGluJDEodGFyZ2V0KSB7XG4gICAgdmFyIGxpc3RlbmVycyA9IG5ldyBTZXQoKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHRhcmdldCwge1xuICAgICAgICBvbjogZnVuY3Rpb24gb24odHlwZSwgZikge1xuICAgICAgICAgICAgdmFyIGxpc3RlbmVyID0ge307XG4gICAgICAgICAgICBsaXN0ZW5lclt0eXBlXSA9IGY7XG4gICAgICAgICAgICBsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgb2ZmOiBmdW5jdGlvbiBvZmYodHlwZSwgZikge1xuICAgICAgICAgICAgaWYgKGYpIHtcbiAgICAgICAgICAgICAgICB2Y
23459XIgbGlzdGVuZXIgPSB7fTtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lclt0eXBlXSA9IGY7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgX2RpZEl0ZXJhdG9yRXJyb3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgX2l0ZXJhdG9yRXJyb3IgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBfaXRlcmF0b3IgPSBsaXN0ZW5lcnNbU3ltYm9sLml0ZXJhdG9yXSgpLCBfc3RlcDsgIShfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gKF9zdGVwID0gX2l0ZXJhdG9yLm5leHQoKSkuZG9uZSk7IF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24gPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IF9zdGVwLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfZGlkSXRlcmF0b3JFcnJvcjIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfaXRlcmF0b3JFcnJvcjIgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2l0ZXJhdG9yMiA9IE9iamVjdC5rZXlzKGl0ZW0pW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3N0ZXAyOyAhKF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yID0gKF9zdGVwMiA9IF9pdGVyYXRvcjIubmV4dCgpKS5kb25lKTsgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjIgPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXkgPSBfc3RlcDIudmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzLmRlbGV0ZShpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kaWRJdGVyYXRvckVycm9yMiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yRXJyb3IyID0gZXJyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yICYmIF9pdGVyYXRvcjIucmV0dXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfaXRlcmF0b3IyLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgX2l0ZXJhdG9yRXJyb3IyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIF9kaWRJdGVyYXRvckVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yRXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbiAmJiBfaXRlcmF0b3IucmV0dXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgX2l0ZXJhdG9yRXJyb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxpc3RTdWJzY3JpcHRpb25zOiBmdW5jdGlvbiBsaXN0U3Vic2NyaXB0aW9ucygpIHtcbiAgICAgICAgICAgIHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyA9IHRydWU7XG4gICAgICAgICAgICB2Y
23459XIgX2RpZEl0ZXJhdG9yRXJyb3IzID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgX2l0ZXJhdG9yRXJyb3IzID0gdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pdGVyYXRvcjMgPSBsaXN0ZW5lcnNbU3ltYm9sLml0ZXJhdG9yXSgpLCBfc3RlcDM7ICEoX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjMgPSAoX3N0ZXAzID0gX2l0ZXJhdG9yMy5uZXh0KCkpLmRvbmUpOyBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyA9IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSBfc3RlcDMudmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coaXRlbSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgX2RpZEl0ZXJhdG9yRXJyb3IzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBfaXRlcmF0b3JFcnJvcjMgPSBlcnI7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjMgJiYgX2l0ZXJhdG9yMy5yZXR1cm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9pdGVyYXRvcjMucmV0dXJuKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX2RpZEl0ZXJhdG9yRXJyb3IzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBfaXRlcmF0b3JFcnJvcjM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHN1YnNjcmliZTogZnVuY3Rpb24gc3Vic2NyaWJlKGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdW5zdWJzY3JpYmU6IGZ1bmN0aW9uIHVuc3Vic2NyaWJlKGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdW5zdWJzY3JpYmVBbGw6IGZ1bmN0aW9uIHVuc3Vic2NyaWJlQWxsKCkge1xuICAgICAgICAgICAgbGlzdGVuZXJzLmNsZWFyKCk7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaWdnZXI6IGZ1bmN0aW9uIHRyaWdnZXIoZXZlbnQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBkYXRhID0gQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgICAgICAgICAgIGRhdGFbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2Y
23459XIgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjQgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIF9kaWRJdGVyYXRvckVycm9yNCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIF9pdGVyYXRvckVycm9yNCA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBfaXRlcmF0b3I0ID0gbGlzdGVuZXJzW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3N0ZXA0OyAhKF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb240ID0gKF9zdGVwNCA9IF9pdGVyYXRvcjQubmV4dCgpKS5kb25lKTsgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjQgPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lciA9IF9zdGVwNC52YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyW2V2ZW50XSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJbZXZlbnRdLmFwcGx5KGxpc3RlbmVyLCB0b0NvbnN1bWFibGVBcnJheShkYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBfZGlkSXRlcmF0b3JFcnJvcjQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIF9pdGVyYXRvckVycm9yNCA9IGVycjtcbiAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uNCAmJiBfaXRlcmF0b3I0LnJldHVybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yNC5yZXR1cm4oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfZGlkSXRlcmF0b3JFcnJvcjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IF9pdGVyYXRvckVycm9yNDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vLyBUZXh0dXJlIG1hbmFnZW1lbnRcbi8vIEdMIHRleHR1cmUgd3JhcHBlciBvYmplY3QgZm9yIGtlZXBpbmcgdHJhY2sgb2YgYSBnbG9iYWwgc2V0IG9mIHRleHR1cmVzLCBrZXllZCBieSBhIHVuaXF1ZSB1c2VyLWRlZmluZWQgbmFtZVxuXG52YXIgVGV4dHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUZXh0dXJlKGdsLCBuYW1lKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTtcbiAgICAgICAgY2xhc3NDYWxsQ2hlY2sodGhpcywgVGV4dHVyZSk7XG5cbiAgICAgICAgc3Vic2NyaWJlTWl4aW4kMSh0aGlzKTtcblxuICAgICAgICB0aGlzLmdsID0gZ2w7XG4gICAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgaWYgKHRoaXMudGV4dHVyZSkge1xuICAgICAgICAgICAgdGhpcy52YWxpZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5iaW5kKCk7XG5cbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5zb3VyY2UgPSBudWxsO1xuICAgICAgICB0aGlzLnNvdXJjZVR5cGUgPSBudWxsO1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBudWxsOyAvLyBhIFByb21pc2Ugb2JqZWN0IHRvIHRyYWNrIHRoZSBsb2FkaW5nIHN0YXRlIG9mIHRoaXMgdGV4dHVyZVxuXG4gICAgICAgIC8vIERlZmF1bHQgdG8gYSAxLXBpeGVsIGJsYWNrIHRleHR1cmUgc28gd2UgY2FuIHNhZmVseSByZW5kZXIgd2hpbGUgd2Ugd2FpdCBmb3IgYW4gaW1hZ2UgdG8gbG9hZFxuICAgICAgICAvLyBTZWU6IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTk3MjIyNDcvd2ViZ2wtd2FpdC1mb3ItdGV4dHVyZS10by1sb2FkXG4gICAgICAgIHRoaXMuc2V0RGF0YSgxLCAxLCBuZXcgVWludDhBcnJheShbMCwgMCwgMCwgMjU1XSksIHsgZmlsdGVyaW5nOiAnbGluZWFyJyB9KTtcbiAgICAgICAgdGhpcy5zZXRGaWx0ZXJpbmcob3B0aW9ucy5maWx0ZXJpbmcpO1xuXG4gICAgICAgIHRoaXMubG9hZChvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyBEZXN0cm95IGEgc2luZ2xlIHRleHR1cmUgaW5zdGFuY2VcblxuXG4gICAgY3JlYXRlQ2xhc3MoVGV4dHVyZSwgW3tcbiAgICAgICAga2V5OiAnZGVzdHJveScsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVUZXh0dXJlKHRoaXMudGV4dHVyZSk7XG4gICAgICAgICAgICB0aGlzLnRleHR1cmUgPSBudWxsO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuZGF0YTtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnZhbGlkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2JpbmQnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gYmluZCh1bml0KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMudmFsaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHVuaXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRleHR1cmUuYWN0aXZlVW5pdCAhPT0gdW5pdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdsLmFjdGl2ZVRleHR1cmUodGhpcy5nbC5URVhUVVJFMCArIHVuaXQpO1xuICAgICAgICAgICAgICAgICAgICBUZXh0dXJlLmFjdGl2ZVVuaXQgPSB1bml0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChUZXh0dXJlLmFjdGl2ZVRleHR1cmUgIT09IHRoaXMudGV4dHVyZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2wuYmluZFRleHR1cmUodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICAgICAgICAgIFRleHR1cmUuYWN0aXZlVGV4dHVyZSA9IHRoaXMudGV4dHVyZTtcbiAgICAgICAgICAgI
23459H1cbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnbG9hZCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBsb2FkKCkge1xuICAgICAgICAgICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9O1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBudWxsO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudXJsID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnVybCA9PT0gdW5kZWZpbmVkIHx8IG9wdGlvbnMudXJsICE9PSB0aGlzLnVybCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVybChvcHRpb25zLnVybCwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEVsZW1lbnQob3B0aW9ucy5lbGVtZW50LCBvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMud2lkdGggJiYgb3B0aW9ucy5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldERhdGEob3B0aW9ucy53aWR0aCwgb3B0aW9ucy5oZWlnaHQsIG9wdGlvbnMuZGF0YSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXRzIHRleHR1cmUgZnJvbSBhbiB1cmxcblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnc2V0VXJsJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNldFVybCh1cmwpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnVybCA9IHVybDsgLy8gc2F2ZSBVUkwgcmVmZXJlbmNlICh3aWxsIGJlIG92ZXJ3cml0dGVuIHdoZW4gZWxlbWVudCBpcyBsb2FkZWQgYmVsb3cpXG4gICAgICAgICAgICB0aGlzLnNvdXJjZSA9IHRoaXMudXJsO1xuICAgICAgICAgICAgdGhpcy5zb3VyY2VUeXBlID0gJ3VybCc7XG5cbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICB2Y
23459XIgZXh0ID0gdXJsLnNwbGl0KCcuJykucG9wKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgaXNWaWRlbyA9IGV4dCA9PT0gJ29ndicgfHwgZXh0ID09PSAnd2VibScgfHwgZXh0ID09PSAnbXA0JztcblxuICAgICAgICAgICAgICAgIHZhciBlbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGlmIChpc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm11dGVkID0gdHJ1ZTsgLyogcmVxdWlyZWQgZm9yIG1vZGVybiBicm93c2VycyB0byBhdXRvcGxheSB2aWRlbyAqL1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQucGxheSgpOyAvKiBkb2Vzbid0IGJsb2NrIHByb21pc2UgYnV0IG5lZWRzIGEgbW9yZSBlbGVnYW50IHNvbHV0aW9uICovXG4gICAgICAgICAgICAgICAgICAgIH0sIDEpO1xuXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuZmlsdGVyaW5nID0gJ25lYXJlc3QnO1xuICAgICAgICAgICAgICAgICAgICAvLyBlbGVtZW50LnByZWxvYWQgPSAnYXV0byc7XG4gICAgICAgICAgICAgICAgICAgIC8vIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgICAgICAgICAgLy8gZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZWxlbWVudC5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRFbGVtZW50KGVsZW1lbnQsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVGV4dHVyZSBcXCcnICsgX3RoaXMubmFtZSArICdcXCc6IGZhaWxlZCB0byBsb2FkIHVybDogXFwnJyArIF90aGlzLnNvdXJjZSArICdcXCcnLCBlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKF90aGlzKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGVsZW1lbnQub25lcnJvciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdhcm4gYW5kIHJlc29sdmUgb24gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1RleHR1cmUgXFwnJyArIF90aGlzLm5hbWUgKyAnXFwnOiBmYWlsZWQgdG8gbG9hZCB1cmw6IFxcJycgKyBfdGhpcy5zb3VyY2UgKyAnXFwnJywgZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoX3RoaXMpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAvLyBTYWZhcmkgaGFzIGEgYnVnIGxvYWRpbmcgZGF0YS1VUkwgZWxlbWVudHMgd2l0aCBDT1JTIGVuYWJsZWQsIHNvIGl0IG11c3QgYmUgZGlzYWJsZWQgaW4gdGhhdCBjYXNlXG4gICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEyMzk3OFxuICAgICAgICAgICAgICAgIGlmICghKGlzU2FmYXJpKCkgJiYgX3RoaXMuc291cmNlLnNsaWNlKDAsIDUpID09PSAnZGF0YTonKSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmNyb3NzT3JpZ2luID0gJ2Fub255bW91cyc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZWxlbWVudC5zcmMgPSBfdGhpcy5zb3VyY2U7XG4gICAgICAgICAgICAgICAgaWYgKGlzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0RWxlbWVudChlbGVtZW50LCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXRzIHRleHR1cmUgdG8gYSByYXcgaW1hZ2UgYnVmZmVyXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3NldERhdGEnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gc2V0RGF0YSh3aWR0aCwgaGVpZ2h0LCBkYXRhKSB7XG4gICAgICAgICAgICB2Y
23459XIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDoge307XG5cbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICAgICAgICB0aGlzLnNvdXJjZSA9IGRhdGE7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZVR5cGUgPSAnZGF0YSc7XG5cbiAgICAgICAgICAgIHRoaXMudXBkYXRlKG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5zZXRGaWx0ZXJpbmcob3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IFByb21pc2UucmVzb2x2ZSh0aGlzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXRzIHRoZSB0ZXh0dXJlIHRvIHRyYWNrIGEgZWxlbWVudCAoY2FudmFzL2ltYWdlKVxuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICdzZXRFbGVtZW50JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNldEVsZW1lbnQoZWxlbWVudCwgb3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBlbCA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgIC8vIGEgc3RyaW5nIGVsZW1lbnQgaXMgaW50ZXJwZXRlZCBhcyBhIENTUyBzZWxlY3RvclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBlbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50IHx8IGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50IHx8IGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zb3VyY2UgPSBlbGVtZW50O1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlVHlwZSA9ICdlbGVtZW50JztcblxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5zb3VyY2UudmlkZW9XaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLnNvdXJjZS52aWRlb0hlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5dGhyb3VnaCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzMi5pbnRlcnZhbElEID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzMi51cGRhdGUob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAxNSk7XG4gICAgICAgICAgICAgICAgICAgIH0sIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2VuZGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jdXJyZW50VGltZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnBsYXkoKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGUob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc2V0RmlsdGVyaW5nKG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2Y
23459XIgbXNnID0gJ3RoZSBcXCdlbGVtZW50XFwnIHBhcmFtZXRlciAoYGVsZW1lbnQ6ICcgKyBKU09OLnN0cmluZ2lmeShlbCkgKyAnYCkgbXVzdCBiZSBhIENTUyAnO1xuICAgICAgICAgICAgICAgIG1zZyArPSAnc2VsZWN0b3Igc3RyaW5nLCBvciBhIDxjYW52YXM+LCA8aW1hZ2U+IG9yIDx2aWRlbz4gb2JqZWN0JztcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVGV4dHVyZSBcXCcnICsgdGhpcy5uYW1lICsgJ1xcJzogJyArIG1zZywgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IFByb21pc2UucmVzb2x2ZSh0aGlzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGxvYWRzIGN1cnJlbnQgaW1hZ2Ugb3IgYnVmZmVyIHRvIHRoZSBHUFUgKGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSBhbmltYXRlZCB0ZXh0dXJlcyBvbiB0aGUgZmx5KVxuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICd1cGRhdGUnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlKCkge1xuICAgICAgICAgICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9O1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMudmFsaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuYmluZCgpO1xuICAgICAgICAgICAgdGhpcy5nbC5waXhlbFN0b3JlaSh0aGlzLmdsLlVOUEFDS19GTElQX1lfV0VCR0wsIG9wdGlvbnMuVU5QQUNLX0ZMSVBfWV9XRUJHTCA9PT0gZmFsc2UgPyBmYWxzZSA6IHRydWUpO1xuICAgICAgICAgICAgdGhpcy5nbC5waXhlbFN0b3JlaSh0aGlzLmdsLlVOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCwgb3B0aW9ucy5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wgfHwgZmFsc2UpO1xuXG4gICAgICAgICAgICAvLyBJbWFnZSBvciBDYW52YXMgZWxlbWVudFxuICAgICAgICAgICAgaWYgKHRoaXMuc291cmNlVHlwZSA9PT0gJ2VsZW1lbnQnICYmICh0aGlzLnNvdXJjZSBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50IHx8IHRoaXMuc291cmNlIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCB8fCB0aGlzLnNvdXJjZSBpbnN0YW5jZW9mIEhUTUxJbWFnZUVsZW1lbnQgJiYgdGhpcy5zb3VyY2UuY29tcGxldGUpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc291cmNlIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5zb3VyY2UudmlkZW9XaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLnNvdXJjZS52aWRlb0hlaWdodDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5zb3VyY2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5zb3VyY2UuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmdsLnRleEltYWdlMkQodGhpcy5nbC5URVhUVVJFXzJELCAwLCB0aGlzLmdsLlJHQkEsIHRoaXMuZ2wuUkdCQSwgdGhpcy5nbC5VTlNJR05FRF9CWVRFLCB0aGlzLnNvdXJjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSYXcgaW1hZ2UgYnVmZmVyXG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLnNvdXJjZVR5cGUgPT09ICdkYXRhJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdsLnRleEltYWdlMkQodGhpcy5nbC5URVhUVVJFXzJELCAwLCB0aGlzLmdsLlJHQkEsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCAwLCB0aGlzLmdsLlJHQkEsIHRoaXMuZ2wuVU5TSUdORURfQllURSwgdGhpcy5zb3VyY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudHJpZ2dlcignbG9hZGVkJywgdGhpcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZXRlcm1pbmVzIGFwcHJvcHJpYXRlIGZpbHRlcmluZyBtb2RlXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3NldEZpbHRlcmluZycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRGaWx0ZXJpbmcoKSB7XG4gICAgICAgICAgICB2Y
23459XIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307XG5cbiAgICAgICAgICAgIGlmICghdGhpcy52YWxpZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wb3dlck9mMiA9IGlzUG93ZXJPZjIodGhpcy53aWR0aCkgJiYgaXNQb3dlck9mMih0aGlzLmhlaWdodCk7XG4gICAgICAgICAgICAvLyBsZXQgZGVmdWFsdEZpbHRlciA9ICh0aGlzLnBvd2VyT2YyID8gJ21pcG1hcCcgOiAnbGluZWFyJyk7XG4gICAgICAgICAgICAvLyB0aGlzLmZpbHRlcmluZyA9IG9wdGlvbnMuZmlsdGVyaW5nIHx8IGRlZnVhbHRGaWx0ZXI7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcmluZyA9IG9wdGlvbnMuZmlsdGVyaW5nIHx8ICdsaW5lYXInO1xuXG4gICAgICAgICAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuICAgICAgICAgICAgdGhpcy5iaW5kKCk7XG5cbiAgICAgICAgICAgIC8vIEZvciBwb3dlci1vZi0yIHRleHR1cmVzLCB0aGUgZm9sbG93aW5nIHByZXNldHMgYXJlIGF2YWlsYWJsZTpcbiAgICAgICAgICAgIC8vIG1pcG1hcDogbGluZWFyIGJsZW5kIGZyb20gbmVhcmVzdCBtaXBcbiAgICAgICAgICAgIC8vIGxpbmVhcjogbGluZWFyIGJsZW5kIGZyb20gb3JpZ2luYWwgaW1hZ2UgKG5vIG1pcHMpXG4gICAgICAgICAgICAvLyBuZWFyZXN0OiBuZWFyZXN0IHBpeGVsIGZyb20gb3JpZ2luYWwgaW1hZ2UgKG5vIG1pcHMsICdibG9ja3knIGxvb2spXG4gICAgICAgICAgICBpZiAodGhpcy5wb3dlck9mMikge1xuICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIG9wdGlvbnMuVEVYVFVSRV9XUkFQX1MgfHwgZ2wuUkVQRUFUKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBvcHRpb25zLlRFWFRVUkVfV1JBUF9UIHx8IGdsLlJFUEVBVCk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maWx0ZXJpbmcgPT09ICdtaXBtYXAnKSB7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVJfTUlQTUFQX0xJTkVBUik7IC8vIFRPRE86IHVzZSB0cmlsaW5lYXIgZmlsdGVyaW5nIGJ5IGRlZnVhbHQgaW5zdGVhZD9cbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgICAgICAgICAgICAgIGdsLmdlbmVyYXRlTWlwbWFwKGdsLlRFWFRVUkVfMkQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5maWx0ZXJpbmcgPT09ICdsaW5lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmlsdGVyaW5nID09PSAnbmVhcmVzdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTkVBUkVTVCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBXZWJHTCBoYXMgc3RyaWN0IHJlcXVpcmVtZW50cyBvbiBub24tcG93ZXItb2YtMiB0ZXh0dXJlczpcbiAgICAgICAgICAgICAgICAvLyBObyBtaXBtYXBzIGFuZCBtdXN0IGNsYW1wIHRvIGVkZ2VcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbHRlcmluZyA9PT0gJ21pcG1hcCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJpbmcgPSAnbGluZWFyJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maWx0ZXJpbmcgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTkVBUkVTVCk7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IHRvIGxpbmVhciBmb3Igbm9uLXBvd2VyLW9mLTIgdGV4dHVyZXNcbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gVGV4dHVyZTtcbn0oKTtcblxuVGV4dHVyZS5nZXRNYXhUZXh0dXJlU2l6ZSA9IGZ1bmN0aW9uIChnbCkge1xuICAgIHJldHVybiBnbC5nZXRQYXJhbWV0ZXIoZ2wuTUFYX1RFWFRVUkVfU0laRSk7XG59O1xuXG4vLyBHbG9iYWwgc2V0IG9mIHRleHR1cmVzLCBieSBuYW1lXG5UZXh0dXJlLmFjdGl2ZVVuaXQgPSAtMTtcblxuLypcblRoZSBNSVQgTGljZW5zZSAoTUlUKVxuXG5Db3B5cmlnaHQgKGMpIDIwMTUgUGF0cmljaW8gR29uemFsZXogVml2byAoIGh0dHA6Ly93d3cucGF0cmljaW9nb256YWxlenZpdm8uY29tIClcblxuUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weSBvZlxudGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgJ1NvZnR3YXJlJyksIHRvIGRlYWwgaW5cbnRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG9cbnVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mXG50aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sXG5zdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHR
23459oaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG5jb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgJ0FTIElTJywgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1NcbkZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUlxuQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSXG5JTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTlxuQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiovXG5cbnZhciBHbHNsQ2FudmFzID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEdsc2xDYW52YXMoY2FudmFzLCBjb250ZXh0T3B0aW9ucywgb3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGNsYXNzQ2FsbENoZWNrKHRoaXMsIEdsc2xDYW52YXMpO1xuXG4gICAgICAgIHN1YnNjcmliZU1peGluJDEodGhpcyk7XG5cbiAgICAgICAgY29udGV4dE9wdGlvbnMgPSBjb250ZXh0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICAgICAgaWYgKGNhbnZhcy5oYXNBdHRyaWJ1dGUoJ2RhdGEtZnVsbHNjcmVlbicpICYmIChjYW52YXMuZ2V0QXR0cmlidXRlKCdkYXRhLWZ1bGxzY3JlZW4nKSA9PSBcIjFcIiB8fCBjYW52YXMuZ2V0QXR0cmlidXRlKCdkYXRhLWZ1bGxzY3JlZW4nKSA9PSBcInRydWVcIikpIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgICAgICAgICAgY2FudmFzLndpZHRoID0gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IGNhbnZhcy5jbGllbnRXaWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gY2FudmFzLmNsaWVudEhlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY2FudmFzID0gY2FudmFzO1xuICAgICAgICB0aGlzLmdsID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmRlcHMgPSB7fTtcbiAgICAgICAgdGhpcy5wcm9ncmFtID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnRleHR1cmVzID0ge307XG4gICAgICAgIHRoaXMuYnVmZmVycyA9IHt9O1xuICAgICAgICB0aGlzLnVuaWZvcm1zID0ge307XG4gICAgICAgIHRoaXMudmJvID0ge307XG4gICAgICAgIHRoaXMuaXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lUmVxdWVzdCA9IHVuZGVmaW5lZDtcblxuICAgICAgICB0aGlzLkJVRkZFUl9DT1VOVCA9IDA7XG4gICAgICAgIC8vIHRoaXMuVEVYVFVSRV9DT1VOVCA9IDA7XG5cbiAgICAgICAgdGhpcy52ZXJ0ZXhTdHJpbmcgPSBjb250ZXh0T3B0aW9ucy52ZXJ0ZXhTdHJpbmcgfHwgJ1xcbiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNlbmRpZlxcblxcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzIgYV90ZXhjb29yZDtcXG5cXG52YXJ5aW5nIHZlYzIgdl90ZXhjb29yZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNChhX3Bvc2l0aW9uLCAwLjAsIDEuMCk7XFxuICAgIHZfdGV4Y29vcmQgPSBhX3RleGNvb3JkO1xcbn1cXG4nO1xuICAgICAgICB0aGlzLmZyYWdtZW50U3RyaW5nID0gY29udGV4dE9wdGlvbnMuZnJhZ21lbnRTdHJpbmcgfHwgJ1xcbiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNlbmRpZlxcblxcbnZhcnlpbmcgdmVjMiB2X3RleGNvb3JkO1xcblxcbnZvaWQgbWFpbigpe1xcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDAuMCk7XFxufVxcbic7XG5cbiAgICAgICAgLy8gR0wgQ29udGV4dFxuICAgICAgICB2Y
23459XIgZ2wgPSBzZXR1cFdlYkdMKGNhbnZhcywgY29udGV4dE9wdGlvbnMsIG9wdGlvbnMub25FcnJvcik7XG4gICAgICAgIGlmICghZ2wpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdsID0gZ2w7XG4gICAgICAgIHRoaXMudGltZUxvYWQgPSB0aGlzLnRpbWVQcmV2ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIHRoaXMudGltZURlbHRhID0gMC4wO1xuICAgICAgICB0aGlzLmZvcmNlUmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZWFsVG9DU1NQaXhlbHMgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgICAgIC8vIEFsbG93IGFscGhhXG4gICAgICAgIGNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBjb250ZXh0T3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IgfHwgJ3JnYmEoMSwxLDEsMCknO1xuXG4gICAgICAgIC8vIExvYWQgc2hhZGVyXG4gICAgICAgIGlmIChjYW52YXMuaGFzQXR0cmlidXRlKCdkYXRhLWZyYWdtZW50JykpIHtcbiAgICAgICAgICAgIHRoaXMuZnJhZ21lbnRTdHJpbmcgPSBjYW52YXMuZ2V0QXR0cmlidXRlKCdkYXRhLWZyYWdtZW50Jyk7XG4gICAgICAgIH0gZWxzZSBpZiAoY2FudmFzLmhhc0F0dHJpYnV0ZSgnZGF0YS1mcmFnbWVudC11cmwnKSkge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IGNhbnZhcy5nZXRBdHRyaWJ1dGUoJ2RhdGEtZnJhZ21lbnQtdXJsJyk7XG4gICAgICAgICAgICB4aHIuZ2V0KHNvdXJjZSwgZnVuY3Rpb24gKGVycm9yLCByZXNwb25zZSwgYm9keSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmxvYWQoYm9keSwgX3RoaXMudmVydGV4U3RyaW5nKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTG9hZCBzaGFkZXJcbiAgICAgICAgaWYgKGNhbnZhcy5oYXNBdHRyaWJ1dGUoJ2RhdGEtdmVydGV4JykpIHtcbiAgICAgICAgICAgIHRoaXMudmVydGV4U3RyaW5nID0gY2FudmFzLmdldEF0dHJpYnV0ZSgnZGF0YS12ZXJ0ZXgnKTtcbiAgICAgICAgfSBlbHNlIGlmIChjYW52YXMuaGFzQXR0cmlidXRlKCdkYXRhLXZlcnRleC11cmwnKSkge1xuICAgICAgICAgICAgdmFyIF9zb3VyY2UgPSBjYW52YXMuZ2V0QXR0cmlidXRlKCdkYXRhLXZlcnRleC11cmwnKTtcbiAgICAgICAgICAgIHhoci5nZXQoX3NvdXJjZSwgZnVuY3Rpb24gKGVycm9yLCByZXNwb25zZSwgYm9keSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmxvYWQoX3RoaXMuZnJhZ21lbnRTdHJpbmcsIGJvZHkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvYWQoKTtcblxuICAgICAgICBpZiAoIXRoaXMucHJvZ3JhbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIFZlcnRleCBidWZmZXJcbiAgICAgICAgdmFyIHRleENvb3Jkc0xvYyA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHRoaXMucHJvZ3JhbSwgJ2FfdGV4Y29vcmQnKTtcbiAgICAgICAgdGhpcy52Ym8udGV4Q29vcmRzID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIHRoaXMuZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmJvLnRleENvb3Jkcyk7XG4gICAgICAgIHRoaXMuZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBGbG9hdDMyQXJyYXkoWzAuMCwgMC4wLCAxLjAsIDAuMCwgMC4wLCAxLjAsIDAuMCwgMS4wLCAxLjAsIDAuMCwgMS4wLCAxLjBdKSwgZ2wuU1RBVElDX0RSQVcpO1xuICAgICAgICB0aGlzLmdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KHRleENvb3Jkc0xvYyk7XG4gICAgICAgIHRoaXMuZ2wudmVydGV4QXR0cmliUG9pbnRlcih0ZXhDb29yZHNMb2MsIDIsIGdsLkZMT0FULCBmYWxzZSwgMCwgMCk7XG5cbiAgICAgICAgdmFyIHZlcnRpY2VzTG9jID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24odGhpcy5wcm9ncmFtLCAnYV9wb3NpdGlvbicpO1xuICAgICAgICB0aGlzLnZiby52ZXJ0aWNlcyA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICB0aGlzLmdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnZiby52ZXJ0aWNlcyk7XG4gICAgICAgIHRoaXMuZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBGbG9hdDMyQXJyYXkoWy0xLjAsIC0xLjAsIDEuMCwgLTEuMCwgLTEuMCwgMS4wLCAtMS4wLCAxLjAsIDEuMCwgLTEuMCwgMS4wLCAxLjBdKSwgZ2wuU1RBVElDX0RSQVcpO1xuICAgICAgICB0aGlzLmdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KHZlcnRpY2VzTG9jKTtcbiAgICAgICAgdGhpcy5nbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHZlcnRpY2VzTG9jLCAyLCBnbC5GTE9BVCwgZmFsc2UsIDAsIDApO1xuXG4gICAgICAgIC8vIGxvYWQgVEVYVFVSRVNcbiAgICAgICAgaWYgKGNhbnZhcy5oYXNBdHRyaWJ1dGUoJ2RhdGEtdGV4dHVyZXMnKSkge1xuICAgICAgICAgICAgdmFyIGltZ0xpc3QgPSBjYW52YXMuZ2V0QXR0cmlidXRlKCdkYXRhLXRleHR1cmVzJykuc3BsaXQoJywnKTtcbiAgICAgICAgICAgIGZvciAodmFyIG5JbWcgaW4gaW1nTGlzdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VW5pZm9ybSgndV90ZXgnICsgbkltZywgaW1nTGlzdFtuSW1nXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PSBFVkVOVFNcbiAgICAgICAgdmFyIG1vdXNlID0ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDBcbiAgICAgICAgfTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIG1vdXNlLnggPSBlLmNsaWVudFggfHwgZS5wYWdlWDtcbiAgICAgICAgICAgIG1vdXNlLnkgPSBlLmNsaWVudFkgfHwgZS5wYWdlWTtcbiAgICAgICAgfSwgZmFsc2UpO1xuXG4gICAgICAgIHZhciBzYW5kYm94ID0gdGhpcztcbiAgICAgICAgZnVuY3Rpb24gUmVuZGVyTG9vcCgpIHtcbiAgICAgICAgICAgIGlmIChzYW5kYm94Lm5Nb3VzZSA+IDEpIHtcbiAgICAgICAgICAgICAgICBzYW5kYm94LnNldE1vdXNlKG1vdXNlKTtcbiAgICAgICAgICAgI
23459H1cblxuICAgICAgICAgICAgaWYgKHNhbmRib3gucmVzaXplKCkpIHtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmZvcmNlUmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2FuZGJveC5yZW5kZXIoKTtcbiAgICAgICAgICAgIHNhbmRib3guYW5pbWF0aW9uRnJhbWVSZXF1ZXN0ID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShSZW5kZXJMb29wKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0YXJ0XG4gICAgICAgIHRoaXMuc2V0TW91c2UoeyB4OiAwLCB5OiAwIH0pO1xuICAgICAgICBSZW5kZXJMb29wKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNyZWF0ZUNsYXNzKEdsc2xDYW52YXMsIFt7XG4gICAgICAgIGtleTogJ2Rlc3Ryb3knLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICAgIC8vIFN0b3AgdGhlIGFuaW1hdGlvblxuICAgICAgICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRpb25GcmFtZVJlcXVlc3QpO1xuXG4gICAgICAgICAgICB0aGlzLmFuaW1hdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAodmFyIHRleCBpbiB0aGlzLnRleHR1cmVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRleC5kZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgICAgIHRleC5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy50ZXh0dXJlcyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYXR0IGluIHRoaXMuYXR0cmlicykge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2wuZGVsZXRlQnVmZmVyKHRoaXMuYXR0cmlic1thdHRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZ2wudXNlUHJvZ3JhbShudWxsKTtcbiAgICAgICAgICAgIHRoaXMuZ2wuZGVsZXRlUHJvZ3JhbSh0aGlzLnByb2dyYW0pO1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuYnVmZmVycykge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSB0aGlzLmJ1ZmZlcnNba2V5XTtcbiAgICAgICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVByb2dyYW0oYnVmZmVyLnByb2dyYW0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnByb2dyYW0gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5nbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2xvYWQnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gbG9hZChmcmFnU3RyaW5nLCB2ZXJ0U3RyaW5nKSB7XG4gICAgICAgICAgICB2Y
23459XIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICAgICAgLy8gTG9hZCB2ZXJ0ZXggc2hhZGVyIGlmIHRoZXJlIGlzIG9uZVxuICAgICAgICAgICAgaWYgKHZlcnRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZlcnRleFN0cmluZyA9IHZlcnRTdHJpbmc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExvYWQgZnJhZ21lbnQgc2hhZGVyIGlmIHRoZXJlIGlzIG9uZVxuICAgICAgICAgICAgaWYgKGZyYWdTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZyYWdtZW50U3RyaW5nID0gZnJhZ1N0cmluZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGxpbmVzID0gdGhpcy5mcmFnbWVudFN0cmluZy5zcGxpdCgvXFxyP1xcbi8pO1xuICAgICAgICAgICAgdGhpcy5mcmFnbWVudFN0cmluZyA9IFwiI2RlZmluZSBQTEFURk9STV9XRUJHTFxcbiNsaW5lIDBcXG5cIjtcblxuICAgICAgICAgICAgbGluZXMuZm9yRWFjaChmdW5jdGlvbiAobGluZSwgaSkge1xuICAgICAgICAgICAgICAgIHZhciBsaW5lX3RyaW0gPSBsaW5lLnRyaW0oKTtcbiAgICAgICAgICAgICAgICBpZiAobGluZV90cmltLnN0YXJ0c1dpdGgoJyNpbmNsdWRlIFxcXCJseWdpYScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZXAgPSBsaW5lX3RyaW0uc3Vic3RyaW5nKDE1KS5yZXBsYWNlKC9cXCd8XFxcInxcXDt8XFxzL2csICcnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlcC5lbmRzV2l0aCgnZ2xzbCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMyLmRlcHNbZGVwXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHVybCA9IFwiaHR0cHM6Ly9seWdpYS54eXpcIiArIGRlcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpczIuZGVwc1tkZXBdID0gZ2V0RmlsZSh1cmwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMyLmZyYWdtZW50U3RyaW5nICs9IF90aGlzMi5kZXBzW2RlcF0gKyAnXFxuI2xpbmUgJyArIChpICsgMSkgKyAnXFxuJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBfdGhpczIuZnJhZ21lbnRTdHJpbmcgKz0gbGluZSArICdcXG4nO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZnJhZ21lbnRTdHJpbmcpO1xuXG4gICAgICAgICAgICB0aGlzLmFuaW1hdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLm5EZWx0YSA9ICh0aGlzLmZyYWdtZW50U3RyaW5nLm1hdGNoKC91X2RlbHRhL2cpIHx8IFtdKS5sZW5ndGg7XG4gICAgICAgICAgICB0aGlzLm5UaW1lID0gKHRoaXMuZnJhZ21lbnRTdHJpbmcubWF0Y2goL3VfdGltZS9nKSB8fCBbXSkubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy5uRGF0ZSA9ICh0aGlzLmZyYWdtZW50U3RyaW5nLm1hdGNoKC91X2RhdGUvZykgfHwgW10pLmxlbmd0aDtcbiAgICAgICAgICAgIHRoaXMubk1vdXNlID0gKHRoaXMuZnJhZ21lbnRTdHJpbmcubWF0Y2goL3VfbW91c2UvZykgfHwgW10pLmxlbmd0aDtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0ZWQgPSB0aGlzLm5EYXRlID4gMSB8fCB0aGlzLm5UaW1lID4gMSB8fCB0aGlzLm5Nb3VzZSA+IDE7XG5cbiAgICAgICAgICAgIHZhciBuVGV4dHVyZXMgPSB0aGlzLmZyYWdtZW50U3RyaW5nLnNlYXJjaCgvc2FtcGxlcjJEL2cpO1xuICAgICAgICAgICAgaWYgKG5UZXh0dXJlcykge1xuICAgICAgICAgICAgICAgIHZhciBfbGluZXMgPSB0aGlzLmZyYWdtZW50U3RyaW5nLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF9saW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2Y
23459XIgbWF0Y2ggPSBfbGluZXNbaV0ubWF0Y2goL3VuaWZvcm1cXHMqc2FtcGxlcjJEXFxzKihbXFx3XSopO1xccypcXC9cXC9cXHMqKFtcXHd8XFw6XFwvXFwvfFxcLnxcXC18XFxfXSopL2kpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBleHQgPSBtYXRjaFsyXS5zcGxpdCgnLicpLnBvcCgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hbMV0gJiYgbWF0Y2hbMl0gJiYgKGV4dCA9PT0gJ2pwZycgfHwgZXh0ID09PSAnanBlZycgfHwgZXh0ID09PSAncG5nJyB8fCBleHQgPT09ICdvZ3YnIHx8IGV4dCA9PT0gJ3dlYm0nIHx8IGV4dCA9PT0gJ21wNCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRVbmlmb3JtKG1hdGNoWzFdLCBtYXRjaFsyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG1haW4gPSBfbGluZXNbaV0ubWF0Y2goL1xccyp2b2lkXFxzKm1haW5cXHMqL2cpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWFpbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB2ZXJ0ZXhTaGFkZXIgPSBjcmVhdGVTaGFkZXIodGhpcywgdGhpcy52ZXJ0ZXhTdHJpbmcsIHRoaXMuZ2wuVkVSVEVYX1NIQURFUik7XG4gICAgICAgICAgICB2Y
23459XIgZnJhZ21lbnRTaGFkZXIgPSBjcmVhdGVTaGFkZXIodGhpcywgdGhpcy5mcmFnbWVudFN0cmluZywgdGhpcy5nbC5GUkFHTUVOVF9TSEFERVIpO1xuXG4gICAgICAgICAgICAvLyBJZiBGcmFnbWVudCBzaGFkZXIgZmFpbHMgbG9hZCBhIGVtcHR5IG9uZSB0byBzaWduIHRoZSBlcnJvclxuICAgICAgICAgICAgaWYgKCFmcmFnbWVudFNoYWRlcikge1xuICAgICAgICAgICAgICAgIGZyYWdtZW50U2hhZGVyID0gY3JlYXRlU2hhZGVyKHRoaXMsICd2b2lkIG1haW4oKXtcXG5cXHRnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxufScsIHRoaXMuZ2wuRlJBR01FTlRfU0hBREVSKTtcbiAgICAgICAgICAgICAgICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc1ZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGFuZCB1c2UgcHJvZ3JhbVxuICAgICAgICAgICAgdmFyIHByb2dyYW0gPSBjcmVhdGVQcm9ncmFtKHRoaXMsIFt2ZXJ0ZXhTaGFkZXIsIGZyYWdtZW50U2hhZGVyXSk7IC8vLCBbMCwxXSxbJ2FfdGV4Y29vcmQnLCdhX3Bvc2l0aW9uJ10pO1xuICAgICAgICAgICAgdGhpcy5nbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgc2hhZGVyc1xuICAgICAgICAgICAgLy8gdGhpcy5nbC5kZXRhY2hTaGFkZXIocHJvZ3JhbSwgdmVydGV4U2hhZGVyKTtcbiAgICAgICAgICAgIC8vIHRoaXMuZ2wuZGV0YWNoU2hhZGVyKHByb2dyYW0sIGZyYWdtZW50U2hhZGVyKTtcbiAgICAgICAgICAgIHRoaXMuZ2wuZGVsZXRlU2hhZGVyKHZlcnRleFNoYWRlcik7XG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVNoYWRlcihmcmFnbWVudFNoYWRlcik7XG5cbiAgICAgICAgICAgIHRoaXMucHJvZ3JhbSA9IHByb2dyYW07XG4gICAgICAgICAgICB0aGlzLmNoYW5nZSA9IHRydWU7XG5cbiAgICAgICAgICAgIHRoaXMuQlVGRkVSX0NPVU5UID0gMDtcbiAgICAgICAgICAgIHZhciBidWZmZXJzID0gdGhpcy5nZXRCdWZmZXJzKHRoaXMuZnJhZ21lbnRTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKGJ1ZmZlcnMpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZFByb2dyYW1zKGJ1ZmZlcnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICAgICAgICAgIHRoaXMudGV4dXJlSW5kZXggPSB0aGlzLkJVRkZFUl9DT1VOVDtcblxuICAgICAgICAgICAgLy8gVHJpZ2dlciBldmVudFxuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKCdsb2FkJywge30pO1xuXG4gICAgICAgICAgICB0aGlzLmZvcmNlUmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3Rlc3QnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdGVzdChjYWxsYmFjaywgZnJhZ1N0cmluZywgdmVydFN0cmluZykge1xuICAgICAgICAgICAgLy8gVGhhbmtzIHRvIEB0aGVzcGl0ZSBmb3IgdGhlIGhlbHAgaGVyZVxuICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cua2hyb25vcy5vcmcvcmVnaXN0cnkvd2ViZ2wvZXh0ZW5zaW9ucy9FWFRfZGlzam9pbnRfdGltZXJfcXVlcnkvXG4gICAgICAgICAgICB2Y
23459XIgcHJlX3Rlc3RfdmVydCA9IHRoaXMudmVydGV4U3RyaW5nO1xuICAgICAgICAgICAgdmFyIHByZV90ZXN0X2ZyYWcgPSB0aGlzLmZyYWdtZW50U3RyaW5nO1xuICAgICAgICAgICAgdmFyIHByZV90ZXN0X3BhdXNlZCA9IHRoaXMucGF1c2VkO1xuXG4gICAgICAgICAgICB2YXIgZXh0ID0gdGhpcy5nbC5nZXRFeHRlbnNpb24oJ0VYVF9kaXNqb2ludF90aW1lcl9xdWVyeScpO1xuICAgICAgICAgICAgdmFyIHF1ZXJ5ID0gZXh0LmNyZWF0ZVF1ZXJ5RVhUKCk7XG4gICAgICAgICAgICB2YXIgd2FzVmFsaWQgPSB0aGlzLmlzVmFsaWQ7XG5cbiAgICAgICAgICAgIGlmIChmcmFnU3RyaW5nIHx8IHZlcnRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWQoZnJhZ1N0cmluZywgdmVydFN0cmluZyk7XG4gICAgICAgICAgICAgICAgd2FzVmFsaWQgPSB0aGlzLmlzVmFsaWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5mb3JjZVJlbmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYXVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgZXh0LmJlZ2luUXVlcnlFWFQoZXh0LlRJTUVfRUxBUFNFRF9FWFQsIHF1ZXJ5KTtcbiAgICAgICAgICAgIHRoaXMuZm9yY2VSZW5kZXIgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgICAgIGV4dC5lbmRRdWVyeUVYVChleHQuVElNRV9FTEFQU0VEX0VYVCk7XG5cbiAgICAgICAgICAgIHZhciBzYW5kYm94ID0gdGhpcztcbiAgICAgICAgICAgIGZ1bmN0aW9uIGZpbmlzaFRlc3QoKSB7XG4gICAgICAgICAgICAgICAgLy8gUmV2ZXJ0IGNoYW5nZXMuLi4gZ28gYmFjayB0byBub3JtYWxcbiAgICAgICAgICAgICAgICBzYW5kYm94LnBhdXNlZCA9IHByZV90ZXN0X3BhdXNlZDtcbiAgICAgICAgICAgICAgICBpZiAoZnJhZ1N0cmluZyB8fCB2ZXJ0U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3gubG9hZChwcmVfdGVzdF9mcmFnLCBwcmVfdGVzdF92ZXJ0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiB3YWl0Rm9yVGVzdCgpIHtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmZvcmNlUmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzYW5kYm94LnJlbmRlcigpO1xuICAgICAgICAgICAgICAgIHZhciBhdmFpbGFibGUgPSBleHQuZ2V0UXVlcnlPYmplY3RFWFQocXVlcnksIGV4dC5RVUVSWV9SRVNVTFRfQVZBSUxBQkxFX0VYVCk7XG4gICAgICAgICAgICAgICAgdmFyIGRpc2pvaW50ID0gc2FuZGJveC5nbC5nZXRQYXJhbWV0ZXIoZXh0LkdQVV9ESVNKT0lOVF9FWFQpO1xuICAgICAgICAgICAgICAgIGlmIChhdmFpbGFibGUgJiYgIWRpc2pvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXNWYWxpZDogd2FzVmFsaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBmcmFnOiBmcmFnU3RyaW5nIHx8IHNhbmRib3guZnJhZ21lbnRTdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0OiB2ZXJ0U3RyaW5nIHx8IHNhbmRib3gudmVydGV4U3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZUVsYXBzZWRNczogZXh0LmdldFF1ZXJ5T2JqZWN0RVhUKHF1ZXJ5LCBleHQuUVVFUllfUkVTVUxUX0VYVCkgLyAxMDAwMDAwLjBcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgZmluaXNoVGVzdCgpO1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhyZXQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUod2FpdEZvclRlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdhaXRGb3JUZXN0KCk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2xvYWRUZXh0dXJlJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGxvYWRUZXh0dXJlKG5hbWUsIHVybEVsZW1lbnRPckRhdGEsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdXJsRWxlbWVudE9yRGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLnVybCA9IHVybEVsZW1lbnRPckRhdGE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCh0eXBlb2YgdXJsRWxlbWVudE9yRGF0YSA9PT0gJ3VuZGVmaW5lZCcgPyAndW5kZWZpbmVkJyA6IF90eXBlb2YodXJsRWxlbWVudE9yRGF0YSkpID09PSAnb2JqZWN0JyAmJiB1cmxFbGVtZW50T3JEYXRhLmRhdGEgJiYgdXJsRWxlbWVudE9yRGF0YS53aWR0aCAmJi
23459B1cmxFbGVtZW50T3JEYXRhLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZGF0YSA9IHVybEVsZW1lbnRPckRhdGEuZGF0YTtcbiAgICAgICAgICAgICAgICBvcHRpb25zLndpZHRoID0gdXJsRWxlbWVudE9yRGF0YS53aWR0aDtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmhlaWdodCA9IHVybEVsZW1lbnRPckRhdGEuaGVpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIGlmICgodHlwZW9mIHVybEVsZW1lbnRPckRhdGEgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHVybEVsZW1lbnRPckRhdGEpKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmVsZW1lbnQgPSB1cmxFbGVtZW50T3JEYXRhO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy50ZXh0dXJlc1tuYW1lXSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRleHR1cmVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dHVyZXNbbmFtZV0ubG9hZChvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0dXJlc1tuYW1lXS5vbignbG9hZGVkJywgZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzMy5mb3JjZVJlbmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0dXJlc1tuYW1lXSA9IG5ldyBUZXh0dXJlKHRoaXMuZ2wsIG5hbWUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dHVyZXNbbmFtZV0ub24oJ2xvYWRlZCcsIGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMy5mb3JjZVJlbmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3JlZnJlc2hVbmlmb3JtcycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiByZWZyZXNoVW5pZm9ybXMoKSB7XG4gICAgICAgICAgICB0aGlzLnVuaWZvcm1zID0ge307XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3NldFVuaWZvcm0nLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gc2V0VW5pZm9ybShuYW1lKSB7XG4gICAgICAgICAgICB2Y
23459XIgdSA9IHt9O1xuXG4gICAgICAgICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgdmFsdWUgPSBBcnJheShfbGVuID4gMSA/IF9sZW4gLSAxIDogMCksIF9rZXkgPSAxOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1W25hbWVdID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnNldFVuaWZvcm1zKHUpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdzZXRVbmlmb3JtcycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRVbmlmb3Jtcyh1bmlmb3Jtcykge1xuICAgICAgICAgICAgdmFyIHBhcnNlZCA9IHBhcnNlVW5pZm9ybXModW5pZm9ybXMpO1xuICAgICAgICAgICAgLy8gU2V0IGVhY2ggdW5pZm9ybVxuICAgICAgICAgICAgZm9yICh2YXIgdSBpbiBwYXJzZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkW3VdLnR5cGUgPT09ICdzYW1wbGVyMkQnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZvciB0ZXh0dXJlcywgd2UgbmVlZCB0byB0cmFjayB0ZXh0dXJlIHVuaXRzLCBzbyB3ZSBoYXZlIGEgc3BlY2lhbCBzZXR0ZXJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy51bmlmb3JtVGV4dHVyZShwYXJzZWRbdV0ubmFtZSwgcGFyc2VkW3VdLnZhbHVlWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkVGV4dHVyZShwYXJzZWRbdV0ubmFtZSwgcGFyc2VkW3VdLnZhbHVlWzBdKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuaWZvcm0ocGFyc2VkW3VdLm1ldGhvZCwgcGFyc2VkW3VdLnR5cGUsIHBhcnNlZFt1XS5uYW1lLCBwYXJzZWRbdV0udmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZm9yY2VSZW5kZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdzZXRNb3VzZScsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRNb3VzZShtb3VzZSkge1xuICAgICAgICAgICAgLy8gc2V0IHRoZSBtb3VzZSB1bmlmb3JtXG4gICAgICAgICAgICB2Y
23459XIgcmVjdCA9IHRoaXMuY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgaWYgKG1vdXNlICYmIG1vdXNlLnggJiYgbW91c2UueCA+PSByZWN0LmxlZnQgJiYgbW91c2UueCA8PSByZWN0LnJpZ2h0ICYmIG1vdXNlLnkgJiYgbW91c2UueSA+PSByZWN0LnRvcCAmJiBtb3VzZS55IDw9IHJlY3QuYm90dG9tKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbW91c2VfeCA9IChtb3VzZS54IC0gcmVjdC5sZWZ0KSAqIHRoaXMucmVhbFRvQ1NTUGl4ZWxzO1xuICAgICAgICAgICAgICAgIHZhciBtb3VzZV95ID0gdGhpcy5jYW52YXMuaGVpZ2h0IC0gKG1vdXNlLnkgLSByZWN0LnRvcCkgKiB0aGlzLnJlYWxUb0NTU1BpeGVscztcblxuICAgICAgICAgICAgICAgIHRoaXMudW5pZm9ybSgnMmYnLCAndmVjMicsICd1X21vdXNlJywgbW91c2VfeCwgbW91c2VfeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBleDogcHJvZ3JhbS51bmlmb3JtKCczZicsICdwb3NpdGlvbicsIHgsIHksIHopO1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICd1bmlmb3JtJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVuaWZvcm0obWV0aG9kLCB0eXBlLCBuYW1lKSB7XG4gICAgICAgICAgICAvLyAndmFsdWUnIGlzIGEgbWV0aG9kLWFwcHJvcHJpYXRlIGFyZ3VtZW50cyBsaXN0XG4gICAgICAgICAgICB0aGlzLnVuaWZvcm1zW25hbWVdID0gdGhpcy51bmlmb3Jtc1tuYW1lXSB8fCB7fTtcbiAgICAgICAgICAgIHZhciB1bmlmb3JtID0gdGhpcy51bmlmb3Jtc1tuYW1lXTtcblxuICAgICAgICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCB2YWx1ZSA9IEFycmF5KF9sZW4yID4gMyA/IF9sZW4yIC0gMyA6IDApLCBfa2V5MiA9IDM7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtfa2V5MiAtIDNdID0gYXJndW1lbnRzW19rZXkyXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGlzRGlmZih1bmlmb3JtLnZhbHVlLCB2YWx1ZSk7XG5cbiAgICAgICAgICAgIC8vIHJlbWVtYmVyIGFuZCBrZWVwIHRyYWNrIG9mIHVuaWZvcm1zIGxvY2F0aW9uIHRvIHNhdmUgY2FsbHNcbiAgICAgICAgICAgIGlmIChjaGFuZ2UgfHwgdGhpcy5jaGFuZ2UgfHwgIXVuaWZvcm0ubG9jYXRpb24gfHwgIXVuaWZvcm0udmFsdWUpIHtcbiAgICAgICAgICAgICAgICB1bmlmb3JtLm5hbWUgPSBuYW1lO1xuICAgICAgICAgICAgICAgIHVuaWZvcm0udHlwZSA9IHR5cGU7XG4gICAgICAgICAgICAgICAgdW5pZm9ybS52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIHVuaWZvcm0ubWV0aG9kID0gJ3VuaWZvcm0nICsgbWV0aG9kO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2wudXNlUHJvZ3JhbSh0aGlzLnByb2dyYW0pO1xuICAgICAgICAgICAgICAgIHVuaWZvcm0ubG9jYXRpb24gPSB0aGlzLmdsLmdldFVuaWZvcm1Mb2NhdGlvbih0aGlzLnByb2dyYW0sIG5hbWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2xbdW5pZm9ybS5tZXRob2RdLmFwcGx5KHRoaXMuZ2wsIFt1bmlmb3JtLmxvY2F0aW9uXS5jb25jYXQodW5pZm9ybS52YWx1ZSkpO1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGNoYW5nZSB1cGRhdGUgYW5kIHRoZXJlIGlzIGJ1ZmZlciB1cGRhdGUgbWFudWFsbHkgb25lIGJ5IG9uZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmJ1ZmZlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVyc1trZXldO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdsLnVzZVByb2dyYW0oYnVmZmVyLnByb2dyYW0pO1xuICAgICAgICAgICAgICAgICAgICB2Y
23459XIgbG9jYXRpb24gPSB0aGlzLmdsLmdldFVuaWZvcm1Mb2NhdGlvbihidWZmZXIucHJvZ3JhbSwgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xbdW5pZm9ybS5tZXRob2RdLmFwcGx5KHRoaXMuZ2wsIFtsb2NhdGlvbl0uY29uY2F0KHVuaWZvcm0udmFsdWUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3VuaWZvcm1UZXh0dXJlJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHVuaWZvcm1UZXh0dXJlKG5hbWUsIHRleHR1cmUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRleHR1cmVzW25hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRUZXh0dXJlKG5hbWUsIHRleHR1cmUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVuaWZvcm0oJzFpJywgJ3NhbXBsZXIyRCcsIG5hbWUsIHRoaXMudGV4dXJlSW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuYnVmZmVycykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gdGhpcy5idWZmZXJzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2wudXNlUHJvZ3JhbShidWZmZXIucHJvZ3JhbSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2wuYWN0aXZlVGV4dHVyZSh0aGlzLmdsLlRFWFRVUkUwICsgdGhpcy50ZXh1cmVJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2wuYmluZFRleHR1cmUodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmVzW25hbWVdLnRleHR1cmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmdsLnVzZVByb2dyYW0odGhpcy5wcm9ncmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLmdsLmFjdGl2ZVRleHR1cmUodGhpcy5nbC5URVhUVVJFMCArIHRoaXMudGV4dXJlSW5kZXgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2wuYmluZFRleHR1cmUodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmVzW25hbWVdLnRleHR1cmUpO1xuICAgICAgICAgICAgICAgIHRoaXMudW5pZm9ybSgnMmYnLCAndmVjMicsIG5hbWUgKyAnUmVzb2x1dGlvbicsIHRoaXMudGV4dHVyZXNbbmFtZV0ud2lkdGgsIHRoaXMudGV4dHVyZXNbbmFtZV0uaGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAncmVzaXplJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2l6ZSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZHRoICE9PSB0aGlzLmNhbnZhcy5jbGllbnRXaWR0aCB8fCB0aGlzLmhlaWdodCAhPT0gdGhpcy5jYW52YXMuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsVG9DU1NQaXhlbHMgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgICAgICAgICAgICAgLy8gTG9va3VwIHRoZSBzaXplIHRoZSBicm93c2VyIGlzIGRpc3BsYXlpbmcgdGhlIGNhbnZhcyBpbiBDU1MgcGl4ZWxzXG4gICAgICAgICAgICAgICAgLy8gYW5kIGNvbXB1dGUgYSBzaXplIG5lZWRlZCB0byBtYWtlIG91ciBkcmF3aW5nYnVmZmVyIG1hdGNoIGl0IGluXG4gICAgICAgICAgICAgICAgLy8gZGV2aWNlIHBpeGVscy5cbiAgICAgICAgICAgICAgICB2Y
23459XIgZGlzcGxheVdpZHRoID0gTWF0aC5mbG9vcih0aGlzLmdsLmNhbnZhcy5jbGllbnRXaWR0aCAqIHRoaXMucmVhbFRvQ1NTUGl4ZWxzKTtcbiAgICAgICAgICAgICAgICB2YXIgZGlzcGxheUhlaWdodCA9IE1hdGguZmxvb3IodGhpcy5nbC5jYW52YXMuY2xpZW50SGVpZ2h0ICogdGhpcy5yZWFsVG9DU1NQaXhlbHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGNhbnZhcyBpcyBub3QgdGhlIHNhbWUgc2l6ZS5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5nbC5jYW52YXMud2lkdGggIT09IGRpc3BsYXlXaWR0aCB8fCB0aGlzLmdsLmNhbnZhcy5oZWlnaHQgIT09IGRpc3BsYXlIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FudmFzIHRoZSBzYW1lIHNpemVcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nbC5jYW52YXMud2lkdGggPSBkaXNwbGF5V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2wuY2FudmFzLmhlaWdodCA9IGRpc3BsYXlIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgdmlld3BvcnQgdG8gbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nbC52aWV3cG9ydCgwLCAwLCB0aGlzLmdsLmNhbnZhcy53aWR0aCwgdGhpcy5nbC5jYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMuY2FudmFzLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5jYW52YXMuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplU3dhcHBhYmxlQnVmZmVycygpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3JlbmRlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICAgICAgICB0aGlzLnZpc2libGUgPSBpc0NhbnZhc1Zpc2libGUodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9yY2VSZW5kZXIgfHwgdGhpcy5jaGFuZ2UgfHwgdGhpcy5hbmltYXRlZCAmJiB0aGlzLnZpc2libGUgJiYgIXRoaXMucGF1c2VkKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgVW5pZm9ybXMgd2hlbiBhcmUgbmVlZFxuICAgICAgICAgICAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgICAgICB2Y
23459XIgbm93ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lRGVsdGEgPSAobm93IC0gdGhpcy50aW1lUHJldikgLyAxMDAwLjA7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lUHJldiA9IG5vdztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5uRGVsdGEgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNldCB0aGUgZGVsdGEgdGltZSB1bmlmb3JtXG4gICAgICAgICAgICAgICAgICAgIHRoaXMudW5pZm9ybSgnMWYnLCAnZmxvYXQnLCAndV9kZWx0YScsIHRoaXMudGltZURlbHRhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5uVGltZSA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gc2V0IHRoZSBlbGFwc2VkIHRpbWUgdW5pZm9ybVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuaWZvcm0oJzFmJywgJ2Zsb2F0JywgJ3VfdGltZScsIChub3cgLSB0aGlzLnRpbWVMb2FkKSAvIDEwMDAuMCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubkRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGRhdGUgdW5pZm9ybTogeWVhci9tb250aC9kYXkvdGltZV9pbl9zZWNcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51bmlmb3JtKCc0ZicsICdmbG9hdCcsICd1X2RhdGUnLCBkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCksIGRhdGUuZ2V0SG91cnMoKSAqIDM2MDAgKyBkYXRlLmdldE1pbnV0ZXMoKSAqIDYwICsgZGF0ZS5nZXRTZWNvbmRzKCkgKyBkYXRlLmdldE1pbGxpc2Vjb25kcygpICogMC4wMDEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHNldCB0aGUgcmVzb2x1dGlvbiB1bmlmb3JtXG4gICAgICAgICAgICAgICAgdGhpcy51bmlmb3JtKCcyZicsICd2ZWMyJywgJ3VfcmVzb2x1dGlvbicsIHRoaXMuY2FudmFzLndpZHRoLCB0aGlzLmNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuYnVmZmVycykge1xuICAgICAgICAgICAgICAgICAgICB2Y
23459XIgYnVmZmVyID0gdGhpcy5idWZmZXJzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudW5pZm9ybSgnMWknLCAnc2FtcGxlcjJEJywgYnVmZmVyLm5hbWUsIGJ1ZmZlci5idW5kbGUuaW5wdXQuaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudGV4dXJlSW5kZXggPSB0aGlzLkJVRkZFUl9DT1VOVDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB0ZXggaW4gdGhpcy50ZXh0dXJlcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuaWZvcm1UZXh0dXJlKHRleCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dXJlSW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclByb2dyYW1zKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGV2ZW50XG4gICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyKCdyZW5kZXInLCB7fSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGFuZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcmNlUmVuZGVyID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3BhdXNlJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHBhdXNlKCkge1xuICAgICAgICAgICAgdGhpcy5wYXVzZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdwbGF5JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHBsYXkoKSB7XG4gICAgICAgICAgICB0aGlzLnBhdXNlZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVuZGVyIG1haW4gYW5kIGJ1ZmZlcnMgcHJvZ3JhbXNcblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAncmVuZGVyUHJvZ3JhbXMnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyUHJvZ3JhbXMoKSB7XG4gICAgICAgICAgICB2Y
23459XIgZ2wgPSB0aGlzLmdsO1xuICAgICAgICAgICAgdmFyIFcgPSBnbC5jYW52YXMud2lkdGg7XG4gICAgICAgICAgICB2YXIgSCA9IGdsLmNhbnZhcy5oZWlnaHQ7XG5cbiAgICAgICAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIFcsIEgpO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVyc1trZXldO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5idW5kbGUucmVuZGVyKFcsIEgsIGJ1ZmZlci5wcm9ncmFtLCBidWZmZXIubmFtZSk7XG4gICAgICAgICAgICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2wudXNlUHJvZ3JhbSh0aGlzLnByb2dyYW0pO1xuICAgICAgICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIDYpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcGFyc2UgaW5wdXQgc3RyaW5nc1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICdnZXRCdWZmZXJzJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldEJ1ZmZlcnMoZnJhZ1N0cmluZykge1xuICAgICAgICAgICAgdmFyIGJ1ZmZlcnMgPSB7fTtcbiAgICAgICAgICAgIGlmIChmcmFnU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgZnJhZ1N0cmluZy5yZXBsYWNlKC8oPzpeXFxzKikoKD86I2lmfCNlbGlmKSg/OlxccyopKGRlZmluZWRcXHMqXFwoXFxzKkJVRkZFUl8pKFxcZCspKD86XFxzKlxcKSl8KD86I2lmZGVmKSg/OlxccypCVUZGRVJfKShcXGQrKSg/OlxccyopKS9nbSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2Y
23459XIgaSA9IGFyZ3VtZW50c1szXSB8fCBhcmd1bWVudHNbNF07XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlcnNbJ3VfYnVmZmVyJyArIGldID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJhZ21lbnQ6ICcjZGVmaW5lIEJVRkZFUl8nICsgaSArICdcXG4nICsgZnJhZ1N0cmluZ1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBsb2FkIGJ1ZmZlcnMgcHJvZ3JhbXNcblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnbG9hZFByb2dyYW1zJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGxvYWRQcm9ncmFtcyhidWZmZXJzKSB7XG4gICAgICAgICAgICB2YXIgZ2xzbCA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuICAgICAgICAgICAgdmFyIHZlcnRleCA9IGNyZWF0ZVNoYWRlcihnbHNsLCBnbHNsLnZlcnRleFN0cmluZywgZ2wuVkVSVEVYX1NIQURFUik7XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gYnVmZmVycykge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBidWZmZXJzW2tleV07XG4gICAgICAgICAgICAgICAgdmFyIGZyYWdtZW50ID0gY3JlYXRlU2hhZGVyKGdsc2wsIGJ1ZmZlci5mcmFnbWVudCwgZ2wuRlJBR01FTlRfU0hBREVSLCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoIWZyYWdtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYWdtZW50ID0gY3JlYXRlU2hhZGVyKGdsc2wsICd2b2lkIG1haW4oKXtcXG5cXHRnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxufScsIGdsLkZSQUdNRU5UX1NIQURFUik7XG4gICAgICAgICAgICAgICAgICAgIGdsc2wuaXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGdsc2wuaXNWYWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBwcm9ncmFtID0gY3JlYXRlUHJvZ3JhbShnbHNsLCBbdmVydGV4LCBmcmFnbWVudF0pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5uYW1lID0ga2V5O1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5wcm9ncmFtID0gcHJvZ3JhbTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYnVuZGxlID0gZ2xzbC5jcmVhdGVTd2FwcGFibGVCdWZmZXIoZ2xzbC5jYW52YXMud2lkdGgsIGdsc2wuY2FudmFzLmhlaWdodCwgcHJvZ3JhbSk7XG4gICAgICAgICAgICAgICAgZ2wuZGVsZXRlU2hhZGVyKGZyYWdtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGdsLmRlbGV0ZVNoYWRlcih2ZXJ0ZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY3JlYXRlIGFuIGlucHV0IC8gb3V0cHV0IHN3YXBwYWJsZSBidWZmZXJcblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnY3JlYXRlU3dhcHBhYmxlQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNyZWF0ZVN3YXBwYWJsZUJ1ZmZlcihXLCBILCBwcm9ncmFtKSB7XG4gICAgICAgICAgICB2Y
23459XIgaW5wdXQgPSB0aGlzLmNyZWF0ZUJ1ZmZlcihXLCBILCBwcm9ncmFtKTtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSB0aGlzLmNyZWF0ZUJ1ZmZlcihXLCBILCBwcm9ncmFtKTtcbiAgICAgICAgICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGlucHV0OiBpbnB1dCxcbiAgICAgICAgICAgICAgICBvdXRwdXQ6IG91dHB1dCxcbiAgICAgICAgICAgICAgICBzd2FwOiBmdW5jdGlvbiBzd2FwKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcCA9IGlucHV0O1xuICAgICAgICAgICAgICAgICAgICBpbnB1dCA9IG91dHB1dDtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gdGVtcDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IGlucHV0O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm91dHB1dCA9IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlbmRlcjogZnVuY3Rpb24gcmVuZGVyKFcsIEgsIHByb2dyYW0sIG5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcbiAgICAgICAgICAgICAgICAgICAgZ2wudmlld3BvcnQoMCwgMCwgVywgSCk7XG4gICAgICAgICAgICAgICAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgdGhpcy5pbnB1dC5idWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIHRoaXMub3V0cHV0LnRleHR1cmUsIDApO1xuICAgICAgICAgICAgICAgICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgNik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3dhcCgpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVzaXplOiBmdW5jdGlvbiByZXNpemUoVywgSCwgcHJvZ3JhbSwgbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBnbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuICAgICAgICAgICAgICAgICAgICBnbC52aWV3cG9ydCgwLCAwLCBXLCBIKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5yZXNpemUoVywgSCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0LnJlc2l6ZShXLCBIKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY3JlYXRlIGEgYnVmZmVyc1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICdjcmVhdGVCdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gY3JlYXRlQnVmZmVyKFcsIEgsIHByb2dyYW0pIHtcbiAgICAgICAgICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgICAgICAgICB2Y
23459XIgaW5kZXggPSB0aGlzLkJVRkZFUl9DT1VOVDtcbiAgICAgICAgICAgIHRoaXMuQlVGRkVSX0NPVU5UICs9IDI7XG4gICAgICAgICAgICBnbC5nZXRFeHRlbnNpb24oJ09FU190ZXh0dXJlX2Zsb2F0Jyk7XG4gICAgICAgICAgICB2YXIgdGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTAgKyBpbmRleCk7XG4gICAgICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgVywgSCwgMCwgZ2wuUkdCQSwgZ2wuRkxPQVQsIG51bGwpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgIHZhciBidWZmZXIgPSBnbC5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgICAgICAgICAgdGV4dHVyZTogdGV4dHVyZSxcbiAgICAgICAgICAgICAgICBidWZmZXI6IGJ1ZmZlcixcbiAgICAgICAgICAgICAgICBXOiBXLFxuICAgICAgICAgICAgICAgIEg6IEgsXG4gICAgICAgICAgICAgICAgcmVzaXplOiBmdW5jdGlvbiByZXNpemUoVywgSCkge1xuICAgICAgICAgICAgICAgICAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtaW5XID0gTWF0aC5taW4oVywgdGhpcy5XKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbkggPSBNYXRoLm1pbihILCB0aGlzLkgpO1xuICAgICAgICAgICAgICAgICAgICB2Y
23459XIgcGl4ZWxzID0gbmV3IEZsb2F0MzJBcnJheShtaW5XICogbWluSCAqIDQpO1xuICAgICAgICAgICAgICAgICAgICBnbC5yZWFkUGl4ZWxzKDAsIDAsIG1pblcsIG1pbkgsIGdsLlJHQkEsIGdsLkZMT0FULCBwaXhlbHMpO1xuICAgICAgICAgICAgICAgICAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SW5kZXggPSBpbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdUZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICAgICAgICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKGdsLlRFWFRVUkUwICsgbmV3SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBuZXdUZXh0dXJlKTtcbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBXLCBILCAwLCBnbC5SR0JBLCBnbC5GTE9BVCwgbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgbWluVywgbWluSCwgZ2wuUkdCQSwgZ2wuRkxPQVQsIHBpeGVscyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdCdWZmZXIgPSBnbC5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgICAgICAgICAgICAgICAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBnbC5kZWxldGVUZXh0dXJlKHRleHR1cmUpO1xuICAgICAgICAgICAgICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKGdsLlRFWFRVUkUwICsgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBuZXdUZXh0dXJlKTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSB0aGlzLmluZGV4ID0gaW5kZXg7XG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUgPSB0aGlzLnRleHR1cmUgPSBuZXdUZXh0dXJlO1xuICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSB0aGlzLmJ1ZmZlciA9IG5ld0J1ZmZlcjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5XID0gVztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5IID0gSDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVzaXplIGJ1ZmZlcnMgb24gY2FudmFzIHJlc2l6ZVxuICAgICAgICAvLyBjb25zaWRlciBhcHBseWluZyBhIHRocm90dGxlIG9mIDUwIG1zIG9uIGNhbnZhcyByZXNpemVcbiAgICAgICAgLy8gdG8gYXZvaWQgcmVxdWVzdEFuaW1hdGlvbkZyYW1lIGFuZCBHbCB2aW9sYXRpb25zXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3Jlc2l6ZVN3YXBwYWJsZUJ1ZmZlcnMnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gcmVzaXplU3dhcHBhYmxlQnVmZmVycygpIHtcbiAgICAgICAgICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgICAgICAgICB2Y
23459XIgVyA9IGdsLmNhbnZhcy53aWR0aCxcbiAgICAgICAgICAgICAgICBIID0gZ2wuY2FudmFzLmhlaWdodDtcbiAgICAgICAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIFcsIEgpO1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuYnVmZmVycykge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSB0aGlzLmJ1ZmZlcnNba2V5XTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYnVuZGxlLnJlc2l6ZShXLCBILCBidWZmZXIucHJvZ3JhbSwgYnVmZmVyLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2wudXNlUHJvZ3JhbSh0aGlzLnByb2dyYW0pO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd2ZXJzaW9uJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZlcnNpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gJzAuMS43JztcbiAgICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gR2xzbENhbnZhcztcbn0oKTtcblxuZnVuY3Rpb24gbG9hZEFsbEdsc2xDYW52YXMoKSB7XG4gICAgdmFyIGxpc3QgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdnbHNsQ2FudmFzJyk7XG4gICAgaWYgKGxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICB3aW5kb3cuZ2xzbENhbnZhc2VzID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNhbmRib3ggPSBuZXcgR2xzbENhbnZhcyhsaXN0W2ldKTtcbiAgICAgICAgICAgIGlmIChzYW5kYm94LmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuZ2xzbENhbnZhc2VzLnB1c2goc2FuZGJveCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgIGxvYWRBbGxHbHNsQ2FudmFzKCk7XG59KTtcblxucmV0dXJuIEdsc2xDYW52YXM7XG5cbn0pKSk7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGlzRnVuY3Rpb25cblxudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uIChmbikge1xuICBpZiAoIWZuKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgdmFyIHN0cmluZyA9IHRvU3RyaW5nLmNhbGwoZm4pXG4gIHJldHVybiBzdHJpbmcgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXScgfHxcbiAgICAodHlwZW9mIGZuID09PSAnZnVuY3Rpb24nICYmIHN0cmluZyAhPT0gJ1tvYmplY3QgUmVnRXhwXScpIHx8XG4gICAgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgIC8vIElFOCBhbmQgYmVsb3dcbiAgICAgKGZuID09PSB3aW5kb3cuc2V0VGltZW91dCB8fFxuICAgICAgZm4gPT09IHdpbmRvdy5hbGVydCB8fFxuICAgICAgZm4gPT09IHdpbmRvdy5jb25maXJtIHx8XG4gICAgICBmbiA9PT0gd2luZG93LnByb21wdCkpXG59O1xuIiwidmFyIHRyaW0gPSBmdW5jdGlvbihzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJyk7XG59XG4gICwgaXNBcnJheSA9IGZ1bmN0aW9uKGFyZykge1xuICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcmcpID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgIH1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaGVhZGVycykge1xuICBpZiAoIWhlYWRlcnMpXG4gICAgcmV0dXJuIHt9XG5cbiAgdmFyIHJlc3VsdCA9IHt9XG5cbiAgdmFyIGhlYWRlcnNBcnIgPSB0cmltKGhlYWRlcnMpLnNwbGl0KCdcXG4nKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGVhZGVyc0Fyci5sZW5ndGg7IGkrKykge1xuICAgIHZhciByb3cgPSBoZWFkZXJzQXJyW2ldXG4gICAgdmFyIGluZGV4ID0gcm93LmluZGV4T2YoJzonKVxuICAgICwga2V5ID0gdHJpbShyb3cuc2xpY2UoMCwgaW5kZXgpKS50b0xvd2VyQ2FzZSgpXG4gICAgLCB2YWx1ZSA9IHRyaW0ocm93LnNsaWNlKGluZGV4ICsgMSkpXG5cbiAgICBpZiAodHlwZW9mKHJlc3VsdFtrZXldKSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWVcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkocmVzdWx0W2tleV0pKSB7XG4gICAgICByZXN1bHRba2V5XS5wdXNoKHZhbHVlKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRba2V5XSA9IFsgcmVzdWx0W2tleV0sIHZhbHVlIF1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcbnZhciB3aW5kb3cgPSByZXF1aXJlKFwiZ2xvYmFsL3dpbmRvd1wiKVxudmFyIGlzRnVuY3Rpb24gPSByZXF1aXJlKFwiaXMtZnVuY3Rpb25cIilcbnZhciBwYXJzZUhlYWRlcnMgPSByZXF1aXJlKFwicGFyc2UtaGVhZGVyc1wiKVxudmFyIHh0ZW5kID0gcmVxdWlyZShcInh0ZW5kXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlWEhSXG4vLyBBbGxvdyB1c2Ugb2YgZGVmYXVsdCBpbXBvcnQgc3ludGF4IGluIFR5cGVTY3JpcHRcbm1vZHVsZS5leHBvcnRzLmRlZmF1bHQgPSBjcmVhdGVYSFI7XG5jcmVhdGVYSFIuWE1MSHR0cFJlcXVlc3QgPSB3aW5kb3cuWE1MSHR0cFJlcXVlc3QgfHwgbm9vcFxuY3JlYXRlWEhSLlhEb21haW5SZXF1ZXN0ID0gXCJ3aXRoQ3JlZGVudGlhbHNcIiBpbiAobmV3IGNyZWF0ZVhIUi5YTUxIdHRwUmVxdWVzdCgpKSA/IGNyZWF0ZVhIUi5YTUxIdHRwUmVxdWVzdCA6IHdpbmRvdy5YRG9tYWluUmVxdWVzdFxuXG5mb3JFYWNoQXJyYXkoW1wiZ2V0XCIsIFwicHV0XCIsIFwicG9zdFwiLCBcInBhdGNoXCIsIFwiaGVhZFwiLCBcImRlbGV0ZVwiXSwgZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgY3JlYXRlWEhSW21ldGhvZCA9PT0gXCJkZWxldGVcIiA/IFwiZGVsXCIgOiBtZXRob2RdID0gZnVuY3Rpb24odXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgICAgICBvcHRpb25zID0gaW5pdFBhcmFtcyh1cmksIG9wdGlvbnMsIGNhbGxiYWNrKVxuICAgICAgICBvcHRpb25zLm1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gICAgICAgIHJldHVybiBfY3JlYXRlWEhSKG9wdGlvbnMpXG4gICAgfVxufSlcblxuZnVuY3Rpb24gZm9yRWFjaEFycmF
234595KGFycmF5LCBpdGVyYXRvcikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlcmF0b3IoYXJyYXlbaV0pXG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0VtcHR5KG9iail7XG4gICAgZm9yKHZhciBpIGluIG9iail7XG4gICAgICAgIGlmKG9iai5oYXNPd25Qcm9wZXJ0eShpKSkgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIGluaXRQYXJhbXModXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIHZhciBwYXJhbXMgPSB1cmlcblxuICAgIGlmIChpc0Z1bmN0aW9uKG9wdGlvbnMpKSB7XG4gICAgICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgICAgICBpZiAodHlwZW9mIHVyaSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcGFyYW1zID0ge3VyaTp1cml9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBwYXJhbXMgPSB4dGVuZChvcHRpb25zLCB7dXJpOiB1cml9KVxuICAgIH1cblxuICAgIHBhcmFtcy5jYWxsYmFjayA9IGNhbGxiYWNrXG4gICAgcmV0dXJuIHBhcmFtc1xufVxuXG5mdW5jdGlvbiBjcmVhdGVYSFIodXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIG9wdGlvbnMgPSBpbml0UGFyYW1zKHVyaSwgb3B0aW9ucywgY2FsbGJhY2spXG4gICAgcmV0dXJuIF9jcmVhdGVYSFIob3B0aW9ucylcbn1cblxuZnVuY3Rpb24gX2NyZWF0ZVhIUihvcHRpb25zKSB7XG4gICAgaWYodHlwZW9mIG9wdGlvbnMuY2FsbGJhY2sgPT09IFwidW5kZWZpbmVkXCIpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYWxsYmFjayBhcmd1bWVudCBtaXNzaW5nXCIpXG4gICAgfVxuXG4gICAgdmFyIGNhbGxlZCA9IGZhbHNlXG4gICAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24gY2JPbmNlKGVyciwgcmVzcG9uc2UsIGJvZHkpe1xuICAgICAgICBpZighY2FsbGVkKXtcbiAgICAgICAgICAgIGNhbGxlZCA9IHRydWVcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2soZXJyLCByZXNwb25zZSwgYm9keSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlYWR5c3RhdGVjaGFuZ2UoKSB7XG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgc2V0VGltZW91dChsb2FkRnVuYywgMClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJvZHkoKSB7XG4gICAgICAgIC8vIENocm9tZSB3aXRoIHJlcXVlc3RUeXBlPWJsb2IgdGhyb3dzIGVycm9ycyBhcnJvdW5kIHdoZW4gZXZlbiB0ZXN0aW5nIGFjY2VzcyB0byByZXNwb25zZVRleHRcbiAgICAgICAgdmFyIGJvZHkgPSB1bmRlZmluZWRcblxuICAgICAgICBpZiAoeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBib2R5ID0geGhyLnJlc3BvbnNlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBib2R5ID0geGhyLnJlc3BvbnNlVGV4dCB8fCBnZXRYbWwoeGhyKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzSnNvbikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBib2R5XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXJyb3JGdW5jKGV2dCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dFRpbWVyKVxuICAgICAgICBpZighKGV2dCBpbnN0YW5jZW9mIEVycm9yKSl7XG4gICAgICAgICAgICBldnQgPSBuZXcgRXJyb3IoXCJcIiArIChldnQgfHwgXCJVbmtub3duIFhNTEh0dHBSZXF1
23459ZXN0IEVycm9yXCIpIClcbiAgICAgICAgfVxuICAgICAgICBldnQuc3RhdHVzQ29kZSA9IDBcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGV2dCwgZmFpbHVyZVJlc3BvbnNlKVxuICAgIH1cblxuICAgIC8vIHdpbGwgbG9hZCB0aGUgZGF0YSAmIHByb2Nlc3MgdGhlIHJlc3BvbnNlIGluIGEgc3BlY2lhbCByZXNwb25zZSBvYmplY3RcbiAgICBmdW5jdGlvbiBsb2FkRnVuYygpIHtcbiAgICAgICAgaWYgKGFib3J0ZWQpIHJldHVyblxuICAgICAgICB2YXIgc3RhdHVzXG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0VGltZXIpXG4gICAgICAgIGlmKG9wdGlvbnMudXNlWERSICYmIHhoci5zdGF0dXM9PT11bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vSUU4IENPUlMgR0VUIHN1Y2Nlc3NmdWwgcmVzcG9uc2UgZG9lc24ndCBoYXZlIGEgc3RhdHVzIGZpZWxkLCBidXQgYm9keSBpcyBmaW5lXG4gICAgICAgICAgICBzdGF0dXMgPSAyMDBcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXR1cyA9ICh4aHIuc3RhdHVzID09PSAxMjIzID8gMjA0IDogeGhyLnN0YXR1cylcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzcG9uc2UgPSBmYWlsdXJlUmVzcG9uc2VcbiAgICAgICAgdmFyIGVyciA9IG51bGxcblxuICAgICAgICBpZiAoc3RhdHVzICE9PSAwKXtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge1xuICAgICAgICAgICAgICAgIGJvZHk6IGdldEJvZHkoKSxcbiAgICAgICAgICAgICAgICBzdGF0dXNDb2RlOiBzdGF0dXMsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgICAgICAgICAgdXJsOiB1cmksXG4gICAgICAgICAgICAgICAgcmF3UmVxdWVzdDogeGhyXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKXsgLy9yZW1lbWJlciB4aHIgY2FuIGluIGZhY3QgYmUgWERSIGZvciBDT1JTIGluIElFXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVycyA9IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoXCJJbnRlcm5hbCBYTUxIdHRwUmVxdWVzdCBFcnJvclwiKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIsIHJlc3BvbnNlLCByZXNwb25zZS5ib2R5KVxuICAgIH1cblxuICAgIHZhciB4aHIgPSBvcHRpb25zLnhociB8fCBudWxsXG5cbiAgICBpZiAoIXhocikge1xuICAgICAgICBpZiAob3B0aW9ucy5jb3JzIHx8IG9wdGlvbnMudXNlWERSKSB7XG4gICAgICAgICAgICB4aHIgPSBuZXcgY3JlYXRlWEhSLlhEb21haW5SZXF1ZXN0KClcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICB4aHIgPSBuZXcgY3JlYXRlWEhSLlhNTEh0dHBSZXF1
23459ZXN0KClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBrZXlcbiAgICB2YXIgYWJvcnRlZFxuICAgIHZhciB1cmkgPSB4aHIudXJsID0gb3B0aW9ucy51cmkgfHwgb3B0aW9ucy51cmxcbiAgICB2YXIgbWV0aG9kID0geGhyLm1ldGhvZCA9IG9wdGlvbnMubWV0aG9kIHx8IFwiR0VUXCJcbiAgICB2YXIgYm9keSA9IG9wdGlvbnMuYm9keSB8fCBvcHRpb25zLmRhdGFcbiAgICB2YXIgaGVhZGVycyA9IHhoci5oZWFkZXJzID0gb3B0aW9ucy5oZWFkZXJzIHx8IHt9XG4gICAgdmFyIHN5bmMgPSAhIW9wdGlvbnMuc3luY1xuICAgIHZhciBpc0pzb24gPSBmYWxzZVxuICAgIHZhciB0aW1lb3V0VGltZXJcbiAgICB2YXIgZmFpbHVyZVJlc3BvbnNlID0ge1xuICAgICAgICBib2R5OiB1bmRlZmluZWQsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBzdGF0dXNDb2RlOiAwLFxuICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgdXJsOiB1cmksXG4gICAgICAgIHJhd1JlcXVlc3Q6IHhoclxuICAgIH1cblxuICAgIGlmIChcImpzb25cIiBpbiBvcHRpb25zICYmIG9wdGlvbnMuanNvbiAhPT0gZmFsc2UpIHtcbiAgICAgICAgaXNKc29uID0gdHJ1ZVxuICAgICAgICBoZWFkZXJzW1wiYWNjZXB0XCJdIHx8IGhlYWRlcnNbXCJBY2NlcHRcIl0gfHwgKGhlYWRlcnNbXCJBY2NlcHRcIl0gPSBcImFwcGxpY2F0aW9uL2pzb25cIikgLy9Eb24ndCBvdmVycmlkZSBleGlzdGluZyBhY2NlcHQgaGVhZGVyIGRlY2xhcmVkIGJ5IHVzZXJcbiAgICAgICAgaWYgKG
234591ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSB7XG4gICAgICAgICAgICBoZWFkZXJzW1wiY29udGVudC10eXBlXCJdIHx8IGhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gfHwgKGhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gPSBcImFwcGxpY2F0aW9uL2pzb25cIikgLy9Eb24ndCBvdmVycmlkZSBleGlzdGluZyBhY2NlcHQgaGVhZGVyIGRlY2xhcmVkIGJ5IHVzZXJcbiAgICAgICAgICAgIGJvZHkgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zLmpzb24gPT09IHRydWUgPyBib2R5IDogb3B0aW9ucy5qc29uKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IHJlYWR5c3RhdGVjaGFuZ2VcbiAgICB4aHIub25sb2FkID0gbG9hZEZ1bmNcbiAgICB4aHIub25lcnJvciA9IGVycm9yRnVuY1xuICAgIC8vIElFOSBtdXN0IGhhdmUgb25wcm9ncmVzcyBiZSBzZXQgdG8gYSB1bmlxdWUgZnVuY3Rpb24uXG4gICAgeGhyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIElFIG11c3QgZGllXG4gICAgfVxuICAgIHhoci5vbmFib3J0ID0gZnVuY3Rpb24oKXtcbiAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgfVxuICAgIHhoci5vbnRpbWVvdXQgPSBlcnJvckZ1bmNcbiAgICB4aHIub3BlbihtZXRob2QsIHVyaSwgIXN5bmMsIG9wdGlvbnMudXNlcm5hbWUsIG9wdGlvbnMucGFzc3dvcmQpXG4gICAgLy9oYXMgdG8gYmUgYWZ0ZXIgb3BlblxuICAgIGlmKCFzeW5jKSB7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSAhIW9wdGlvbnMud2l0aENyZWRlbnRpYWxzXG4gICAgfVxuICAgIC8vIENhbm5vdCBzZXQgdGltZW91dCB3aXRoIHN5bmMgcmVxdWVzdFxuICAgIC8vIG5vdCBzZXR0aW5nIHRpbWVvdXQgb24gdGhlIHhociBvYmplY3QsIGJlY2F1c2Ugb2Ygb2xkIHdlYmtpdHMgZXRjLiBub3QgaGFuZGxpbmcgdGhhdCBjb3JyZWN0bHlcbiAgICAvLyBib3RoIG5wbSdzIHJlcXVlc3QgYW5kIGpxdWVyeSAxLnggdXNlIHRoaXMga2luZCBvZiB0aW1lb3V0LCBzbyB0aGlzIGlzIGJlaW5nIGNvbnNpc3RlbnRcbiAgICBpZiAoIXN5bmMgJiYgb3B0aW9ucy50aW1lb3V0ID4gMCApIHtcbiAgICAgICAgdGltZW91dFRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgICAgICAgaWYgKGFib3J0ZWQpIHJldHVyblxuICAgICAgICAgICAgYWJvcnRlZCA9IHRydWUvL0lFOSBtYXkgc3RpbGwgY2FsbCByZWFkeXN0YXRlY2hhbmdlXG4gICAgICAgICAgICB4aHIuYWJvcnQoXCJ0aW1lb3V0XCIpXG4gICAgICAgICAgICB2Y
23459XIgZSA9IG5ldyBFcnJvcihcIlhNTEh0dHBSZXF1ZXN0IHRpbWVvdXRcIilcbiAgICAgICAgICAgIGUuY29kZSA9IFwiRVRJTUVET1VUXCJcbiAgICAgICAgICAgIGVycm9yRnVuYyhlKVxuICAgICAgICB9LCBvcHRpb25zLnRpbWVvdXQgKVxuICAgIH1cblxuICAgIGlmICh4aHIuc2V0UmVxdWVzdEhlYWRlcikge1xuICAgICAgICBmb3Ioa2V5IGluIGhlYWRlcnMpe1xuICAgICAgICAgICAgaWYoaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKXtcbiAgICAgICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5oZWFkZXJzICYmICFpc0VtcHR5KG9wdGlvbnMuaGVhZGVycykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSGVhZGVycyBjYW5ub3QgYmUgc2V0IG9uIGFuIFhEb21haW5SZXF1ZXN0IG9iamVjdFwiKVxuICAgIH1cblxuICAgIGlmIChcInJlc3BvbnNlVHlwZVwiIGluIG9wdGlvbnMpIHtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IG9wdGlvbnMucmVzcG9uc2VUeXBlXG4gICAgfVxuXG4gICAgaWYgKFwiYmVmb3JlU2VuZFwiIGluIG9wdGlvbnMgJiZcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuYmVmb3JlU2VuZCA9PT0gXCJmdW5jdGlvblwiXG4gICAgKSB7XG4gICAgICAgIG9wdGlvbnMuYmVmb3JlU2VuZCh4aHIpXG4gICAgfVxuXG4gICAgLy8gTWljcm9zb2Z0IEVkZ2UgYnJvd3NlciBzZW5kcyBcInVuZGVmaW5lZFwiIHdoZW4gc2VuZCBpcyBjYWxsZWQgd2l0aCB1bmRlZmluZWQgdmFsdWUuXG4gICAgLy8gWE1MSHR0cFJlcXVlc3Qgc3BlYyBzYXlzIHRvIHBhc3MgbnVsbCBhcyBib2R5IHRvIGluZGljYXRlIG5vIGJvZHlcbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL25hdWd0dXIveGhyL2lzc3Vlcy8xMDAuXG4gICAgeGhyLnNlbmQoYm9keSB8fCBudWxsKVxuXG4gICAgcmV0dXJuIHhoclxuXG5cbn1cblxuZnVuY3Rpb24gZ2V0WG1sKHhocikge1xuICAgIC8vIHhoci5yZXNwb25zZVhNTCB3aWxsIHRocm93IEV4Y2VwdGlvbiBcIkludmFsaWRTdGF0ZUVycm9yXCIgb3IgXCJET01FeGNlcHRpb25cIlxuICAgIC8vIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvcmVzcG9uc2VYTUwuXG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHhoci5yZXNwb25zZVR5cGUgPT09IFwiZG9jdW1lbnRcIikge1xuICAgICAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVhNTFxuICAgICAgICB9XG4gICAgICAgIHZhciBmaXJlZm94QnVnVGFrZW5FZmZlY3QgPSB4aHIucmVzcG9uc2VYTUwgJiYgeGhyLnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PT0gXCJwYXJzZXJlcnJvclwiXG4gICAgICAgIGlmICh4aHIucmVzcG9uc2VUeXBlID09PSBcIlwiICYmICFmaXJlZm94QnVnVGFrZW5FZmZlY3QpIHtcbiAgICAgICAgICAgIHJldHVybiB4aHIucmVzcG9uc2VYTUxcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICByZXR1cm4gbnVsbFxufVxuXG5mdW5jdGlvbiBub29wKCkge31cbiIsIm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kXG5cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbmZ1bmN0aW9uIGV4dGVuZCgpIHtcbiAgICB2YXIgdGFyZ2V0ID0ge31cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV1cblxuICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0XG59XG4iLCJpbXBvcnQgXCJkb2N1bWVudC1yZWdpc3Rlci1lbGVtZW50XCI7XG5pbXBvcnQgU2hhZGVyIGZyb20gXCIuL2NvcmUvU2hhZGVyXCI7XG5pbXBvcnQgeyBpbml0RWRpdG9yLCBmb2N1c0FsbCB9IGZyb20gXCIuL2NvcmUvRWRpdG9yXCI7XG5cbmltcG9ydCBNZW51IGZyb20gXCIuL3VpL01lbnVcIjtcbmltcG9ydCBIZWxwZXJzIGZyb20gXCIuL3VpL0hlbHBlcnNcIjtcbmltcG9ydCBFcnJvcnNEaXNwbGF5IGZyb20gXCIuL3VpL0Vycm9yc0Rpc3BsYXlcIjtcbmltcG9ydCBWaXN1YWxEZWJ1Z2dlciBmcm9tIFwiLi91aS9WaXN1YWxEZWJ1Z2dlclwiO1xuaW1wb3J0IEV4cG9ydEljb24gZnJvbSBcIi4vdWkvRXhwb3J0SWNvblwiO1xuXG5pbXBvcnQgRmlsZURyb3AgZnJvbSBcIi4vaW8vRmlsZURyb3BcIjtcbmltcG9ydCBIYXNoV2F0Y2ggZnJvbSBcIi4vaW8vSGFzaFdhdGNoXCI7XG5pbXBvcnQgQnVmZmVyTWFuYWdlciBmcm9tIFwiLi9pby9CdWZmZXJNYW5hZ2VyXCI7XG5pbXBvcnQgTG9jYWxTdG9yYWdlIGZyb20gXCIuL2lvL0xvY2FsU3RvcmFnZVwiO1xuY29uc3QgU1RPUkFHRV9MQVNUX0VESVRPUl9DT05URU5UID0gXCJsYXN0LWNvbnRlbnRcIjtcblxuLy8gSW1wb3J0IFV0aWxzXG5pbXBvcnQgeGhyIGZyb20gXCJ4aHJcIjtcbmltcG9ydCB7IHN1YnNjcmliZU1peGluIH0gZnJvbSBcIi4vdG9vbHMvbWl4aW5cIjtcbmltcG9ydCB7IHNhdmVBcyB9IGZyb20gXCIuL3Rvb2xzL2Rvd25sb2FkXCI7XG5pbXBvcnQgeyBnZXRKU09OIH0gZnJvbSBcIi4vdG9vbHMvY29tbW9uXCI7XG5pbXBvcnQgQ29kZU1pcnJvciBmcm9tIFwiY29kZW1pcnJvclwiO1xuXG4vLyAvLyBDcm9zcyBzdG9yYWdlIGZvciBPcGVuZnJhbWUgLS0gYWxsb3dzIHJlc3RyaWN0ZWQgYWNjZXNzIHRvIGNlcnRhaW4gbG9jYWxTdG9yYWdlIG9wZXJhdGlvbnNcbi8vIC8vIG9uIHRoZSBvcGVuZnJhbWUgZG9tYWluXG4vLyBpbXBvcnQgeyBDcm9zc1N0b3JhZ2VDbGllbnQgfSBmcm9tIFwiY3Jvc3Mtc3RvcmFnZVwiO1xuLy8gaW1wb3J0IHsgZ2V0TW9kZSB9IGZyb20gXCJjb2RlbWlycm9yXCI7XG5cbmNvbnN0IEVNUFRZX0ZSQUdfU0hBREVSID0gYC8vIEF1dGhvcjpcbi8vIFRpdGxlOlxuXG4jaWZkZWYgR0xfRVNcbnByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xuI2VuZGlmXG5cbnVuaWZvcm0gdmVjMiB1X3Jlc29sdXRpb247XG51bmlmb3JtIHZlYzIgdV9tb3VzZTtcbnVuaWZvcm0gZmxvYXQgdV90aW1lO1xuXG52b2lkIG1haW4oKSB7XG4gICAgdmVjMiBzdCA9IGdsX0ZyYWdDb29yZC54eS91X3Jlc29sdXRpb24ueHk7XG4gICAgc3QueCAqPSB1X3Jlc29sdXRpb24ueC91X3Jlc29sdXRpb24ueTtcblxuICAgI
23459HZlYzMgY29sb3IgPSB2ZWMzKDAuKTtcbiAgICBjb2xvciA9IHZlYzMoc3QueCxzdC55LGFicyhzaW4odV90aW1lKSkpO1xuXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNChjb2xvciwxLjApO1xufWA7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdsc2xFZGl0b3Ige1xuICBjb25zdHJ1Y3RvcihzZWxlY3Rvciwgb3B0aW9ucykge1xuICAgIHRoaXMuY3JlYXRlRm9udExpbmsoKTtcbiAgICBzdWJzY3JpYmVNaXhpbih0aGlzKTtcblxuICAgIGlmIChcbiAgICAgIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgc2VsZWN0b3Iubm9kZVR5cGUgJiZcbiAgICAgIHNlbGVjdG9yLm5vZGVUeXBlID09PSAxXG4gICAgKSB7XG4gICAgICB0aGlzLmNvbnRhaW5lciA9IHNlbGVjdG9yO1xuICAgIH0gXG4gICAgZWxzZSBpZiAodHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgICAgaWYgKCF0aGlzLmNvbnRhaW5lcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGVsZW1lbnQgJHtzZWxlY3Rvcn0gbm90IHByZXNlbnRgKTtcbiAgICAgIH1cbiAgICB9IFxuICAgIGVsc2Uge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgIFwiRXJyb3IsIHR5cGUgXCIgKyB0eXBlb2Ygc2VsZWN0b3IgKyBcIiBvZiBcIiArIHNlbGVjdG9yICsgXCIgaXMgdW5rbm93blwiXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMub3B0aW9ucyA9IHt9O1xuICAgIHRoaXMuY2hhbmdlID0gZmFsc2U7XG4gICAgdGhpcy5hdXRvdXBkYXRlID0gdHJ1ZTtcbiAgICB0aGlzLmx5Z2lhX2dsb2IgPSBudWxsO1xuXG4gICAgaWYgKG9wdGlvbnMpXG4gICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pbWdzID09PSB1bmRlZmluZWQpXG4gICAgICB0aGlzLm9wdGlvbnMuaW1ncyA9IFtdO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kaXNwbGF5X21lbnUgPT09IHVuZGVmaW5lZClcbiAgICAgIHRoaXMub3B0aW9ucy5kaXNwbGF5X21lbnUgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMuY29udGFpbmVyLmhhc0F0dHJpYnV0ZShcImRhdGEtdGV4dHVyZXNcIikpIHtcbiAgICAgIGxldCBpbWdMaXN0ID0gdGhpcy5jb250YWluZXIuZ2V0QXR0cmlidXRlKFwiZGF0YS10ZXh0dXJlc1wiKS5zcGxpdChcIixcIik7XG4gICAgICBmb3IgKGxldCBpIGluIGltZ0xpc3QpXG4gICAgICAgIHRoaXMub3B0aW9ucy5pbWdzLnB1c2goaW1nTGlzdFtpXSk7XG4gICAgICBcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IFRoZW1lXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMudGhlbWUpXG4gICAgICB0aGlzLm9wdGlvbnMudGhlbWUgPSBcImRlZmF1bHRcIjtcblxuICAgIC8vIERlZmF1bHQgQ29udGV4dFxuICAgIGlmICghdGhpcy5vcHRpb25zLmZyYWcpIHtcbiAgICAgIHZhciBpbm5lckhUTUwgPSB0aGlzLmNvbnRhaW5lci5pbm5lckhUTUwucmVwbGFjZSgvJmx0O2JyJmd0Oy9nLCBcIlwiKTtcbiAgICAgIGlubmVySFRNTCA9IGlubmVySFRNTC5yZXBsYWNlKC88YnI+L2csIFwiXCIpO1xuICAgICAgaW5uZXJIVE1MID0gaW5uZXJIVE1MLnJlcGxhY2UoLyZuYnNwOy9nLCBcIlwiKTtcbiAgICAgIGlubmVySFRNTCA9IGlubmVySFRNTC5yZXBsYWNlKC8mbHQ7L2csIFwiPFwiKTtcbiAgICAgIGlubmVySFRNTCA9IGlubmVySFRNTC5yZXBsYWNlKC8mZ3Q7L2csIFwiPlwiKTtcbiAgICAgIGlubmVySFRNTCA9IGlubmVySFRNTC5yZXBsYWNlKC8mYW1wOy9nLCBcIiZcIik7XG4gICAgICB0aGlzLm9wdGlvbnMuZnJhZyA9IGlubmVySFRNTCB8fCBFTVBUWV9GUkFHX1NIQURFUjtcblxuICAgICAgaWYgKGlubmVySFRNTClcbiAgICAgICAgdGhpcy5jb250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IGludmlzaWJsZSBGcmFnbWVudCBoZWFkZXJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5mcmFnX2hlYWRlcilcbiAgICAgIHRoaXMub3B0aW9ucy5mcmFnX2hlYWRlciA9IFwiXCI7XG5cbiAgICAvLyBEZWZhdWx0IGludmlzaWJsZSBGcmFnbWVudCBmb290ZXJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5mcmFnX2Zvb3RlcilcbiAgICAgIHRoaXMub3B0aW9ucy5mcmFnX2Zvb3RlciA9IFwiXCI7XG5cbiAgICAvLyBMaXN0ZW4gdG8gaGFzaCBjaGFuZ2VzXG4gICAgaWYgKHRoaXMub3B0aW9ucy53YXRjaEhhc2gpXG4gICAgICBuZXcgSGFzaFdhdGNoKHRoaXMpO1xuXG4gICAgLy8gTG9hZCBVSVxuICAgIGlmICh0aGlzLm9wdGlvbnMubWVudSlcbiAgICAgIHRoaXMubWVudSA9IG5ldyBNZW51KHRoaXMpO1xuXG4gICAgLy8gU3VwcG9ydCBmb3IgbXVsdGlwbGUgYnVmZmVyc1xuICAgIGlmICh0aGlzLm9wdGlvbnMubXVsdGlwbGVCdWZmZXJzKVxuICAgICAgdGhpcy5idWZmZXJNYW5hZ2VyID0gbmV3IEJ1ZmZlck1hbmFnZXIodGhpcyk7XG5cbiAgICAvLyBMaXN0ZW4gdG8gZmlsZSBkcm9wc1xuICAgIGlmICh0aGlzLm9wdGlvbnMuZmlsZURyb3BzKVxuICAgICAgbmV3IEZpbGVEcm9wKHRoaXMpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pbmRlbnRVbml0ID09PSB1bmRlZmluZWQpXG4gICAgICB0aGlzLm9wdGlvbnMuaW5kZW50VW5pdCA9IDQ7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnRhYlNpemUgPT09IHVuZGVmaW5lZClcbiAgICAgIHRoaXMub3B0aW9ucy50YWJTaXplID0gNDtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuaW5kZW50V2l0aFRhYnMgPT09IHVuZGVmaW5lZClcbiAgICAgIHRoaXMub3B0aW9ucy5pbmRlbnRXaXRoVGFicyA9IGZhbHNlO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5saW5lV3JhcHBpbmcgPT09IHVuZGVmaW5lZClcbiAgICAgIHRoaXMub3B0aW9ucy5saW5lV3JhcHBpbmcgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5hdXRvZm9jdXMgPT09IHVuZGVmaW5lZClcbiAgICAgIHRoaXMub3B0aW9ucy5hdXRvZm9jdXMgPSB0cnVlO1xuXG4gICAgLy8gQ09SRSBlbGVtZW50c1xuICAgIHRoaXMuc2hhZGVyID0gbmV3IFNoYWRlcih0aGlzKTtcbiAgICB0aGlzLmVkaXRvciA9IGluaXRFZGl0b3IodGhpcyk7XG5cbiAgICB0aGlzLmhlbHBlcnMgPSBuZXcgSGVscGVycyh0aGlzKTtcbiAgICB0aGlzLmVycm9yc0Rpc3BsYXkgPSBuZXcgRXJyb3JzRGlzcGxheSh0aGlzKTtcbiAgICB0aGlzLnZpc3VhbERlYnVnZ2VyID0gbmV3IFZpc3VhbERlYnVnZ2VyKH
23459RoaXMpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5leHBvcnRJY29uKVxuICAgICAgdGhpcy5leHBvcnQgPSBuZXcgRXhwb3J0SWNvbih0aGlzKTtcblxuICAgIC8vIEVWRU5UU1xuICAgIHRoaXMuZWRpdG9yLm9uKFwiY2hhbmdlXCIsICgpID0+IHtcbiAgICAgIGlmICh0aGlzLmF1dG91cGRhdGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuY2FudmFzX2ZvbGxvdykge1xuICAgICAgdGhpcy5zaGFkZXIuZWwuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2FudmFzX2Zsb2F0KVxuICAgICAgICB0aGlzLnNoYWRlci5lbC5zdHlsZS5mbG9hdCA9IHRoaXMub3B0aW9ucy5jYW52YXNfZmxvYXQ7XG5cbiAgICAgIHRoaXMuZWRpdG9yLm9uKFwiY3Vyc29yQWN0aXZpdHlcIiwgKGNtKSA9PiB7XG4gICAgICAgIGxldCBoZWlnaHQgPVxuICAgICAgICAgIGNtLmhlaWdodEF0TGluZShjbS5nZXRDdXJzb3IoKS5saW5lICsgMSwgXCJsb2NhbFwiKSAtXG4gICAgICAgICAgdGhpcy5zaGFkZXIuZWwuY2xpZW50SGVpZ2h0O1xuICAgICAgICBpZiAoaGVpZ2h0IDwgMCkge1xuICAgICAgICAgIGhlaWdodCA9IDAuMDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNoYWRlci5lbC5zdHlsZS50b3AgPSBoZWlnaHQudG9TdHJpbmcoKSArIFwicHhcIjtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuZWRpdG9yLm9uKCdpbnB1dFJlYWQnLCAoY20sIGNoYW5nZSkgPT4ge1xuICAgICAgbGV0IGN1ciA9IGNtLmdldEN1cnNvcigpLFxuICAgICAgICAgIHRva2VuID0gY20uZ2V0VG9rZW5BdChjdXIpO1xuICAgICAgbGV0IGxpbmUgPSB0b2tlbi5zdHJpbmcudHJpbSgpO1xuICAgICAgICAgIFxuICAgICAgaWYgKGxpbmUuc3RhcnRzV2l0aCgnI2luY2x1ZGUnKSkge1xuICAgICAgICBsZXQgcGF0aCA9IGxpbmUuc3Vic3RyaW5nKDEwKTtcbiAgICAgICAgaWYgKHRoaXMubHlnaWFfZ2xvYiA9PT0gbnVsbCkge1xuICAgICAgICAgIGdldEpTT04oJ2h0dHBzOi8vbHlnaWEueHl6L2dsc2wuanNvbicsIChlcnIsIGRhdGEpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgdGhpcy5seWdpYV9nbG9iID0gZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZygnYXV0b2NvbXBsZXRlIGZvcicsIHBhdGgpO1xuXG4gICAgICAgIGxldCBzdGFydCA9IHRva2VuLnN0YXJ0O1xuICAgICAgICBsZXQgZW5kID0gY3VyLmNoO1xuICAgICAgICBsZXQgbGluZU4gPSBjdXIubGluZTtcblxuICAgICAgICBsZXQgcmVzdWx0ID0gW11cblxuICAgICAgICBpZiAodGhpcy5seWdpYV9nbG9iICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5seWdpYV9nbG9iLmZvckVhY2goICh3KSA9PiB7aWYgKHcuc3RhcnRzV2l0aChwYXRoKSkgcmVzdWx0LnB1c2goJyNpbmNsdWRlIFxcXCInICsgdyArICdcXFwiJyk7fSApO1xuICAgICAgICAgIHJlc3VsdC5zb3J0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBDb2RlTWlycm9yLnNob3dIaW50KGNtLCAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgcnRhID0ge1xuICAgICAgICAgICAgICBsaXN0OiByZXN1bHQsIFxuICAgICAgICAgICAgICBmcm9tOiBDb2RlTWlycm9yLlBvcyhsaW5lTiwgc3RhcnQpLFxuICAgICAgICAgICAgICB0bzogQ29kZU1pcnJvci5Qb3MobGluZU4sIGVuZClcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKHJ0YSk7XG4gICAgICAgICAgICByZXR1cm4gcnRhO1xuICAgICAgICAgIH0sIHtjb21wbGV0ZVNpbmdsZTogdHJ1ZSwgYWxpZ25XaXRoV29yZDogdHJ1ZX0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBJZiB0aGUgdXNlciBiYWlscyBmb3Igd2hhdGV2ZXIgcmVhc29uLCBoYXN0aWx5IHNob3ZlIHRoZSBjb250ZW50cyBvZlxuICAgIC8vIHRoZSBlZGl0b3IgaW50byBzb21lIGtpbmQgb2Ygc3RvcmFnZS4gVGhpcyBvdmVyd3JpdGVzIHdoYXRldmVyIHdhc1xuICAgIC8vIHRoZXJlIGJlZm9yZS4gTm90ZSB0aGF0IHRoZXJlIGlzIG5vdCByZWFsbHkgYSB3YXkgb2YgaGFuZGxpbmcgdW5sb2FkXG4gICAgLy8gd2l0aCBvdXIgb3duIFVJIGFuZCBsb2dpYywgc2luY2UgdGhpcyBhbGxvd3MgZm9yIHdpZGVzcHJlYWQgYWJ1c2VcbiAgICAvLyBvZiBub3JtYWwgYnJvd3NlciBmdW5jdGlvbmFsaXR5LlxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiYmVmb3JldW5sb2FkXCIsIChldmVudCkgPT4ge1xuICAgICAgbGV0IGNvbnRlbnQgPSB7fTtcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5idWZmZXJNYW5hZ2VyICYmXG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMuYnVmZmVyTWFuYWdlci5idWZmZXJzKS5sZW5ndGggIT09IDBcbiAgICAgICkge1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5idWZmZXJNYW5hZ2VyLmJ1ZmZlcnMpIHtcbiAgICAgICAgICBjb250ZW50W2tleV0gPSB0aGlzLmJ1ZmZlck1hbmFnZXIuYnVmZmVyc1trZXldLmdldFZhbHVlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRlbnRbbmV3IERhdGUoKS5nZXRUaW1lKCkudG9TdHJpbmcoKV0gPSB0aGlzLmVkaXRvci5nZXRWYWx1ZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLm1lbnUpIHtcbiAgICAgICAgTG9jYWxTdG9yYWdlLnNldEl0ZW0oXG4gICAgICAgICAgU1RPUkFHRV9MQVNUX0VESVRPUl9DT05URU5ULFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGNvbnRlbnQpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLm1lbnUpIHtcbiAgICAgIC8vIElmIHRoZXJlIGlzIHByZXZpdXMgY29udGVudCBsb2FkIGl0LlxuICAgICAgbGV0IG9sZENvbnRlbnQgPSBKU09OLnBhcnNlKFxuICAgICAgICBMb2NhbFN0b3JhZ2UuZ2V0SXRlbShTVE9SQUdFX0xBU1RfRURJVE9SX0NPTlRFTlQpXG4gICAgICApO1xuICAgICAgaWYgKG9sZENvbnRlbnQpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG9sZENvbnRlbnQpIHtcbiAgICAgICAgICB0aGlzLm9wZW4ob2xkQ29udGVudFtrZXldLCBrZXkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm5ldygpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm5ldygpO1xuICAgIH1cblxuICAgIC8vIGlmICh0aGlzLm9wdGlvbnMubWVudSB8fCB0aGlzLm9wdGlvbnMuZXhwb3J0SWNvbikge1xuICAgIC8vICAgLy8gc2V0dXAgQ3Jvc3NTdG9yYWdlIGNsaWVudFxuICAgIC8vICAgdGhpcy5zdG9yYWdlID0gbmV3IENyb3NzU3RvcmFnZUNsaWVudChcImh0dHBzOi8vb3BlbmZyYW1lLmlvL2h1Yi5odG1sXCIpO1xuICAgIC8vICAgdGhpcy5zdG9yYWdlLm9uQ29ubmVjdCgpLnRoZW4oKCkgPT4ge1xuICAgIC8vICAgICBjb25zb2xlLmxvZyhcIkNvbm5lY3RlZCB0byBPcGVuRnJhbWUgW29dXCIpO1xuICAgIC8vICAgfSk7XG4gICAgLy8gICAvLyB9KS
234595iaW5kKHRoaXMpO1xuICAgIC8vIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbmV3KCkge1xuICAgIHRoaXMuc2V0Q29udGVudChcbiAgICAgIHRoaXMub3B0aW9ucy5mcmFnIHx8IEVNUFRZX0ZSQUdfU0hBREVSLFxuICAgICAgbmV3IERhdGUoKS5nZXRUaW1lKCkudG9TdHJpbmcoKVxuICAgICk7XG4gICAgdGhpcy50cmlnZ2VyKFwibmV3X2NvbnRlbnRcIiwge30pO1xuICAgIHRoaXMub3B0aW9ucy5mcmFnID0gbnVsbDtcbiAgfVxuXG4gIHNldENvbnRlbnQoc2hhZGVyLCB0YWJOYW1lKSB7XG4gICAgLy8gSWYgdGhlIHN0cmluZyBpcyBDT0RFXG4gICAgaWYgKHRoaXMuc2hhZGVyICYmIHRoaXMuc2hhZGVyLmNhbnZhcykge1xuICAgICAgaWYgKHRoaXMuZGVidWdnaW5nKSB7XG4gICAgICAgIHRoaXMuZGVidWdnaW5nID0gZmFsc2U7XG4gICAgICAgIGZvY3VzQWxsKHRoaXMuZWRpdG9yKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2hhZGVyLmNhbnZhcy5sb2FkKFxuICAgICAgICB0aGlzLm9wdGlvbnMuZnJhZ19oZWFkZXIgKyBzaGFkZXIgKyB0aGlzLm9wdGlvbnMuZnJhZ19mb290ZXJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZWRpdG9yKSB7XG4gICAgICBpZiAodGFiTmFtZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuYnVmZmVyTWFuYWdlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuYnVmZmVyTWFuYWdlci5vcGVuKHRhYk5hbWUsIHNoYWRlcik7XG4gICAgICAgIHRoaXMuYnVmZmVyTWFuYWdlci5zZWxlY3QodGFiTmFtZSk7XG4gICAgICB9IFxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuZWRpdG9yLnNldFZhbHVlKHNoYWRlcik7XG4gICAgICAgIHRoaXMuZWRpdG9yLnNldFNpemUobnVsbCwgdGhpcy5lZGl0b3IuZ2V0RG9jKCkuaGVpZ2h0ICsgXCJweFwiKTtcbiAgICAgICAgdGhpcy5lZGl0b3Iuc2V0U2l6ZShudWxsLCBcImF1dG9cIik7XG4gICAgICAgIHRoaXMuZmlsZW5hbWUgPSB0YWJOYW1lO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmNoYW5nZSA9IHRydWU7XG4gIH1cblxuICBvcGVuKHNoYWRlciwgdGFiTmFtZSkge1xuICAgIGlmICh0eXBlb2Ygc2hhZGVyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgbGV0IGdlID0gdGhpcztcbiAgICAgIHJlYWRlci5vbmxvYWQgPSAoZSkgPT4ge1xuICAgICAgICBnZS5zZXRDb250ZW50KGUudGFyZ2V0LnJlc3VsdCwgc2hhZGVyLm5hbWUpO1xuICAgICAgfTtcbiAgICAgIHJlYWRlci5yZWFkQXNUZXh0KHNoYWRlcik7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc2hhZGVyID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBpZiAoL1xcLmZyYWckLy50ZXN0KHNoYWRlcikgfHwgL1xcLmZzJC8udGVzdChzaGFkZXIpKSB7XG4gICAgICAgIC8vIElmIHRoZSBzdHJpbmcgaXMgYW4gVVJMXG4gICAgICAgIHhoci5nZXQoc2hhZGVyLCAoZXJyb3IsIHJlc3BvbnNlLCBib2R5KSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yIGRvd25sb2FkaW5nIFwiLCBzaGFkZXIsIGVycm9yKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5zZXRDb250ZW50KGJvZHksIHRhYk5hbWUpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0Q29udGVudChzaGFkZXIsIHRhYk5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldENvbnRlbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZWRpdG9yLmdldFZhbHVlKCk7XG4gIH1cblxuICBnZXRBdXRob3IoKSB7XG4gICAgbGV0IGNvbnRlbnQgPSB0aGlzLmdldENvbnRlbnQoKTtcbiAgICBsZXQgcmVzdWx0ID0gY29udGVudC5tYXRjaChcbiAgICAgIC9cXC9cXC9cXHMqW0F8YV11dGhvclxccypbXFw6XT9cXHMqKFtcXHd8XFxzfFxcQHxcXCh8XFwpfFxcLXxcXF9dKikvaVxuICAgICk7XG4gICAgaWYgKHJlc3VsdCAmJiAhKHJlc3VsdFsxXSA9PT0gXCIgXCIgfHwgcmVzdWx0WzFdID09PSBcIlwiKSkge1xuICAgICAgbGV0IGF1dGhvciA9IHJlc3VsdFsxXS5yZXBsYWNlKC8oXFxyXFxufFxcbnxcXHIpL2dtLCBcIlwiKTtcbiAgICAgIHJldHVybiBhdXRob3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBcInVua25vd25cIjtcbiAgICB9XG4gIH1cblxuICBnZXRUaXRsZSgpIHtcbiAgICBsZXQgY29udGVudCA9IHRoaXMuZ2V0Q29udGVudCgpO1xuICAgIGxldCByZXN1bHQgPSBjb250ZW50Lm1hdGNoKFxuICAgICAgL1xcL1xcL1xccypbVHx0XWl0bGVcXHMqOlxccyooW1xcd3xcXHN8XFxAfFxcKHxcXCl8XFwtfFxcX10qKS9pXG4gICAgKTtcbiAgICBpZiAocmVzdWx0ICYmICEocmVzdWx0WzFdID09PSBcIiBcIiB8fCByZXN1bHRbMV0gPT09IFwiXCIpKSB7XG4gICAgICBsZXQgdGl0bGUgPSByZXN1bHRbMV0ucmVwbGFjZSgvKFxcclxcbnxcXG58XFxyKS9nbSwgXCJcIik7XG4gICAgICByZXR1cm4gdGl0bGU7XG4gICAgfSBlbHNlIGlmICh0aGlzLmJ1ZmZlck1hbmFnZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuYnVmZmVyTWFuYWdlci5jdXJyZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJucyBQcm9taXNlXG4gIGdldE9mVG9rZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoXCJhY2Nlc3NUb2tlblwiKTtcbiAgfVxuXG4gIGRvd25sb2FkKCkge1xuICAgIGxldCBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCk7XG4gICAgbGV0IG5hbWUgPSB0aGlzLmdldFRpdGxlKCk7XG4gICAgaWYgKG5hbWUgIT09IFwiXCIpIHtcbiAgICAgIG5hbWUgKz0gXCItXCI7XG4gICAgfVxuICAgIG5hbWUgKz0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBEb3dubG9hZCBjb2RlXG4gICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtjb250ZW50XSwgeyB0eXBlOiBcInRleHQvcGxhaW5cIiB9KTtcbiAgICBzYXZlQXMoYmxvYiwgbmFtZSArIFwiLmZyYWdcIik7XG4gICAgdGhpcy5lZGl0b3IuZG9jLm1hcmtDbGVhbigpO1xuICAgIHRoaXMuY2hhbmdlID0gZmFsc2U7XG4gIH1cblxuICB1cGRhdGUoKSB7XG4gICAgaWYgKHRoaXMuZGVidWdnaW5nKSB7XG4gICAgICB0aGlzLmRlYnVnZ2luZyA9IGZhbHNlO1xuICAgICAgZm9jdXNBbGwodGhpcy5lZGl0b3IpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnZpc3VhbERlYnVnZ2VyLnRlc3RpbmdSZXN1bHRzLmxlbmd0aCkgXG4gICAgICB0aGlzLnZpc3VhbERlYnVnZ2VyLmNsZWFuKCk7XG4gICAgXG4gICAgdGhpcy5zaGFkZXIuY2FudmFzLmxvYWQoXG4gICAgICB0aGlzLm9wdGlvbnMuZnJhZ19oZWFkZXIgK1xuICAgICAgICB0aGlzLmVkaXRvci5nZXRWYWx1ZSgpICtcbiAgICAgICAgdGhpcy5vcHRpb25zLmZyYWdfZm9vdGVyXG4gICAgKTtcbiAgfVxuXG4gIGNyZWF0ZUZvbnRMaW5rKCkge1xuICAgIHZhciBoZWFkID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJoZWFkXCIpWzBdO1xuICAgIHZhciBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImxpbmtcIik7XG4gICAgbGluay5ocmVmID0gXCJodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2ljb24/ZmFtaWx5PU1h
23459dGVyaWFsK0ljb25zXCI7XG4gICAgbGluay50eXBlID0gXCJ0ZXh0L2Nzc1wiO1xuICAgIGxpbmsucmVsID0gXCJzdHlsZXNoZWV0XCI7XG4gICAgbGluay5tZWRpYSA9IFwic2NyZWVuLHByaW50XCI7XG4gICAgaGVhZC5hcHBlbmRDaGlsZChsaW5rKTtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImhlYWRcIilbMF0uYXBwZW5kQ2hpbGQobGluayk7XG4gIH1cblxuICB0b2dnbGVQcmVzZW50YXRpb25XaW5kb3coZmxhZykge1xuICAgIHRoaXMucFdpbmRvd09wZW4gPSBmbGFnO1xuICAgIGlmIChmbGFnKVxuICAgICAgdGhpcy5zaGFkZXIub3BlbldpbmRvdygpO1xuICAgIGVsc2VcbiAgICAgIHRoaXMuc2hhZGVyLmNsb3NlV2luZG93KCk7XG4gIH1cblxuICBvbkNsb3NlUHJlc2VudGF0aW9uV2luZG93KCkge1xuICAgIHRoaXMucFdpbmRvd09wZW4gPSBmYWxzZTtcbiAgfVxufVxuXG53aW5kb3cuR2xzbEVkaXRvciA9IEdsc2xFZGl0b3I7XG5cbnZhciBHbHNsV2ViQ29tcG9uZW50ID0gZnVuY3Rpb24gKCkge307XG5HbHNsV2ViQ29tcG9uZW50LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSFRNTEVsZW1lbnQucHJvdG90eXBlKTtcbkdsc2xXZWJDb21wb25lbnQucHJvdG90eXBlLmNyZWF0ZWRDYWxsYmFjayA9IGZ1bmN0aW9uIGNyZWF0ZWRDYWxsYmFjaygpIHtcbiAgdmFyIG9wdGlvbnMgPSB7XG4gICAgY2FudmFzX3NpemU6IDE1MCxcbiAgICBjYW52YXNfZm9sbG93OiB0cnVlLFxuICAgIHRvb2x0aXBzOiB0cnVlLFxuICB9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGF0dHJpYnV0ZSA9IHRoaXMuYXR0cmlidXRlc1tpXTtcbiAgICBpZiAoYXR0cmlidXRlLnNwZWNpZmllZCkge1xuICAgICAgdmFyIHZhbHVlID0gYXR0cmlidXRlLnZhbHVlO1xuXG4gICAgICBpZiAodmFsdWUgPT09IFwidHJ1ZVwiKVxuICAgICAgICB2YWx1ZSA9IHRydWU7XG4gICAgICBlbHNlIGlmICh2YWx1ZSA9PT0gXCJmYWxzZVwiKVxuICAgICAgICB2YWx1ZSA9IGZhbHNlO1xuICAgICAgZWxzZSBpZiAocGFyc2VJbnQodmFsdWUpKVxuICAgICAgICB2YWx1ZSA9IHBhcnNlSW50KHZhbHVlKTtcblxuICAgICAgb3B0aW9uc1thdHRyaWJ1dGUubmFtZV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICB0aGlzLmdsc2xFZGl0b3IgPSBuZXcgR2xzbEVkaXRvcih0aGlzLCBvcHRpb25zKTtcbn07XG5cbmRvY3VtZW50LnJlZ2lzdGVyRWxlbWVudChcImdsc2wtZWRpdG9yXCIsIEdsc2xXZWJDb21wb25lbnQpO1xuIiwiLy8gSW1wb3J0IENvZGVNaXJyb3JcbmltcG9ydCBDb2RlTWlycm9yIGZyb20gJ2NvZGVtaXJyb3InO1xuXG4vLyBJbXBvcnQgQ29kZU1pcnJvciBhZGRvbnMgYW5kIG1vZHVsZXNcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9zZWFyY2gvc2VhcmNoJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9zZWFyY2gvc2VhcmNoY3Vyc29yJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9jb21tZW50L2NvbW1lbnQnO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2RpYWxvZy9kaWFsb2cnO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2VkaXQvbWF0Y2hicmFja2V0cyc7XG5pbXBvcnQgJ2NvZGVtaXJyb3IvYWRkb24vZWRpdC9jbG9zZWJyYWNrZXRzJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi93cmFwL2hhcmR3cmFwJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9mb2xkL2ZvbGRjb2RlJztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9mb2xkL2ZvbGRndXR0ZXInO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2ZvbGQvaW5kZW50LWZvbGQnO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2hpbnQvc2hvdy1oaW50JztcbmltcG9ydCAnY29kZW1pcnJvci9hZGRvbi9oaW50L2phdmFzY3JpcHQtaGludCc7XG5pbXBvcnQgJ2NvZGVtaXJyb3IvYWRkb24vZGlzcGxheS9ydWxlcnMnO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2Rpc3BsYXkvcGFuZWwnO1xuaW1wb3J0ICdjb2RlbWlycm9yL2FkZG9uL2hpbnQvc2hvdy1oaW50JztcbmltcG9ydCAnY29kZW1pcnJvci9tb2RlL2NsaWtlL2NsaWtlLmpzJztcblxuLy8gS2V5bWFwXG5pbXBvcnQgJ2NvZGVtaXJyb3Iva2V5bWFwL3N1YmxpbWUnO1xuXG5jb25zdCBVTkZPQ1VTX0NMQVNTID0gJ2dlX2VkaXRvci11bmZvY3VzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRFZGl0b3IgKG1haW4pIHtcbiAgICBpZiAobWFpbi5vcHRpb25zLmxpbmVOdW1iZXJzID09PSB1bmRlZmluZWQpXG4gICAgICAgIG1haW4ub3B0aW9ucy5saW5lTnVtYmVycyA9IHRydWU7XG5cbiAgICAvLyBDUkVBVEUgQU5EIFNUQVJUIENPREVNSVJST1JcbiAgICBsZXQgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBlbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2dlX2VkaXRvcicpO1xuXG4gICAgLy8gSWYgdGhlcmUgaXMgYSBtZW51IG9mZnNldCB0aGUgZWRpdG9yIHRvIGNvbWUgYWZ0ZXIgaXRcbiAgICBpZiAobWFpbi5tZW51KVxuICAgICAgICBlbC5zdHlsZS5wYWRkaW5nVG9wID0gKG1haW4ubWVudS5lbC5jbGllbnRIZWlnaHQgfHwgbWFpbi5tZW51LmVsLm9mZnNldEhlaWdodCB8fCBtYWluLm1lbnUuZWwuc2Nyb2xsSGVpZ2h0KSArICdweCc7XG5cbiAgICBtYWluLmNvbnRhaW5lci5hcHBlbmRDaGlsZChlbCk7XG5cbiAgICBmdW5jdGlvbiBmaWxsSW5jbHVkZShjbSwgb3B0aW9uKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSggKGFjY2VwdCkgPT4ge1xuICAgICAgICAgIHNldFRpbWVvdXQoICgpID0+IHtcbiAgICAgICAgICAgIGxldCBjdXIgPSBjbS5nZXRDdXJzb3IoKS4gXG4gICAgICAgICAgICAgICAgbGluZSA9IGNtLmdldExpbmUoY3VyLmxpbmUpLnRyaW0oKTtcbiAgICAgICAgICAgIHZhciBzdGFydCA9IGN1ci5jaCwgZW5kID0gY3VyLmNoO1xuXG4gICAgICAgICAgICBpZiAobGluZS5zdGFydHNXaXRoKCcjaW5jbHVkZSBcXFwibHlnaWEnKSkge1xuICAgICAgICAgICAgICAgIGxldCBwYXRoID0gbGluZS5zdWJzdHJpbmcoMTApO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmx5Z2lhX2dsb2IgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgIGdldEpTT04oJ2h0dHBzOi8vbHlnaWEueHl6L2dsc2wuanNvbicsIChlcnIsIGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVyciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgI
23459HRoaXMubHlnaWFfZ2xvYiA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYXV0b2NvbXBsZXRlIGZvcicsIHBhdGgpO1xuICAgICAgICBcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB0b2tlbi5zdGFydDtcbiAgICAgICAgICAgICAgICBsZXQgZW5kID0gY3VyLmNoO1xuICAgICAgICAgICAgICAgIGxldCBsaW5lTiA9IGN1ci5saW5lO1xuICAgICAgICBcbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0ID0gW11cbiAgICAgICAgXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubHlnaWFfZ2xvYiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgdGhpcy5seWdpYV9nbG9iLmZvckVhY2goICh3KSA9PiB7aWYgKHcuc3RhcnRzV2l0aChwYXRoKSkgcmVzdWx0LnB1c2goJyNpbmNsdWRlIFxcXCInICsgdyArICdcXFwiJyk7fSApO1xuICAgICAgICAgICAgICAgICAgcmVzdWx0LnNvcnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cobGluZU4sIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYWNjZXB0KHtsaXN0OiByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb206IENvZGVNaXJyb3IuUG9zKGN1ci5saW5lLCBzdGFydCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvOiBDb2RlTWlycm9yLlBvcyhjdXIubGluZSwgZW5kKX0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFjY2VwdChudWxsKVxuICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IGNtID0gQ29kZU1pcnJvcihlbCwge1xuICAgICAgICB2YWx1ZTogbWFpbi5vcHRpb25zLmZyYWcsXG4gICAgICAgIHZpZXdwb3J0TWFyZ2luOiBJbmZpbml0eSxcbiAgICAgICAgbGluZU51bWJlcnM6IG1haW4ub3B0aW9ucy5saW5lTnVtYmVycyxcbiAgICAgICAgbWF0Y2hCcmFja2V0czogdHJ1ZSxcbiAgICAgICAgbW9kZTogJ3gtc2hhZGVyL3gtZnJhZ21lbnQnLFxuICAgICAgICBrZXlNYXA6ICdzdWJsaW1lJyxcbiAgICAgICAgYXV0b0Nsb3NlQnJhY2tldHM6IHRydWUsXG4gICAgICAgIGV4dHJhS2V5czogeyAnQ3RybC1TcGFjZSc6ICdhdXRvY29tcGxldGUnIH0sXG4gICAgICAgIHNob3dDdXJzb3JXaGVuU2VsZWN0aW5nOiB0cnVlLFxuICAgICAgICB0aGVtZTogbWFpbi5vcHRpb25zLnRoZW1lLFxuICAgICAgICBkcmFnRHJvcDogZmFsc2UsXG4gICAgICAgIGluZGVudFVuaXQ6IG1haW4ub3B0aW9ucy5pbmRlbnRVbml0LFxuICAgICAgICB0YWJTaXplOiBtYWluLm9wdGlvbnMudGFiU2l6ZSxcbiAgICAgICAgaW5kZW50V2l0aFRhYnM6IG1haW4ub3B0aW9ucy5pbmRlbnRXaXRoVGFicyxcbiAgICAgICAgZ3V0dGVyczogbWFpbi5vcHRpb25zLmxpbmVOdW1iZXJzID8gWydDb2RlTWlycm9yLWxpbmVudW1iZXJzJywgJ2JyZWFrcG9pbnRzJ10gOiBmYWxzZSxcbiAgICAgICAgbGluZVdyYXBwaW5nOiBtYWluLm9wdGlvbnMubGluZVdyYXBwaW5nLFxuICAgICAgICBhdXRvZm9jdXM6IG1haW4ub3B0aW9ucy5hdXRvZm9jdXNcbiAgICB9KTtcblxuICAgIHJldHVybiBjbTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVuZm9jdXNMaW5lKGNtLCBsaW5lKSB7XG4gICAgaWYgKGxpbmUgPT09IG51bGwpIHtyZXR1cm47fVxuICAgIGNtLmdldERvYygpLmFkZExpbmVDbGFzcyhsaW5lLCAnZ3V0dGVyJywgVU5GT0NVU19DTEFTUyk7XG4gICAgY20uZ2V0RG9jKCkuYWRkTGluZUNsYXNzKGxpbmUsICd0ZXh0JywgVU5GT0NVU19DTEFTUyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bmZvY3VzQWxsKGNtKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGogPSBjbS5nZXREb2MoKS5saW5lQ291bnQoKTsgaSA8PSBqOyBpKyspXG4gICAgICAgIHVuZm9jdXNMaW5lKGNtLCBpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvY3VzTGluZShjbSwgbGluZSkge1xuICAgIGlmIChsaW5lID09PSBudWxsKSB7cmV0dXJuO31cbiAgICBjbS5nZXREb2MoKS5yZW1vdmVMaW5lQ2xhc3MobGluZSwgJ2d1dHRlcicsIFVORk9DVVNfQ0xBU1MpO1xuICAgIGNtLmdldERvYygpLnJlbW92ZUxpbmVDbGFzcyhsaW5lLCAndGV4dCcsIFVORk9DVVNfQ0xBU1MpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9jdXNBbGwoY20pIHtcbiAgICBmb3IgKGxldCBpID0gMCwgaiA9IGNtLmdldERvYygpLmxpbmVDb3VudCgpOyBpIDw9IGo7IGkrKylcbiAgICAgICAgZm9jdXNMaW5lKGNtLCBpKTtcbn1cbiIsImltcG9ydCBHbHNsQ2FudmFzIGZyb20gXCJnbHNsQ2FudmFzXCI7XG5pbXBvcnQgeyBzdWJzY3JpYmVJbnRlcmFjdGl2ZURvbSB9IGZyb20gXCIuLi90b29scy9pbnRlcmFjdGl2ZURvbVwiO1xuaW1wb3J0IE1lZGlhQ2FwdHVyZSBmcm9tIFwiLi4vdG9vbHMvbWVkaWFDYXB0dXJlXCI7XG5pbXBvcnQgTWVudUl0ZW0gZnJvbSBcIi4uL3VpL01lbnVJdGVtXCI7XG5pbXBvcnQgeyBzYXZlQXMgfSBmcm9tIFwiLi4vdG9vbHMvZG93bmxvYWRcIjtcblxudmFyIENPTlRST0xTX0NMQVNTTkFNRSA9IFwiZ2VfY29udHJvbFwiO1xudmFyIENPTlRST0xTX1BBTkVMX0NMQVNTTkFNRSA9IFwiZ2VfY29udHJvbF9wYW5lbFwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTaGFkZXIge1xuICBjb25zdHJ1Y3RvcihtYWluKSB7XG4gICAgdGhpcy5tYWluID0gbWFpbjtcbiAgICB0aGlzLm9wdGlvbnMgPSBtYWluLm9wdGlvbnM7XG4gICAgdGhpcy5mcmFnID0gXCJcIjtcblxuICAgIC8vIERPTSBDT05UQUlORVJcbiAgICB0aGlzLmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICB0aGlzLmVsLnNldEF0dHJpYnV0ZShcImNsYXNzXCIsIFwiZ2VfY2FudmFzX2NvbnRhaW5lclwiKTtcbiAgICAvLyBDUkVBVEUgQU5EIFNUQVJUIEdMU0xDQU5WQVNcbiAgICB0aGlzLmVsQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICB0aGlzLmVsQ2FudmFzLnNldEF0dHJpYnV0ZShcImNsYXNzXCIsIFwiZ2VfY2FudmFzXCIpO1xuICAgIHRoaXMuZWxDYW52YXMuc2V0QXR0cmlidXRlKFxuICAgICAgXCJkYXRhLWZyYWdtZW50XCIsXG4gICAgICB0aGlzLm9wdGlvbnMuZnJhZ19oZWFkZXIgKyB0aGlzLm9wdGlvbnMuZnJhZyArIHRoaXMub3B0aW9ucy5mcmFnX2Zvb3RlclxuICAgICk7XG4gICAgdGhpcy5lbC5hcHBlbmRDaGlsZCh0aGlzLmVsQ2FudmFzKTtcbiAgICBsZXQgZ2xzbGNhbnZhcyA9IG5ldyBHbHNsQ2FudmFzKHRoaXMuZWxDYW52YXMsIHtcbiAgICAgIHByZW11bHRpcGxpZWRBbHBoYTogZmFsc2UsXG4gICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRydWUsXG4gICAgICBiYWNrZ3JvdW5k
23459Q29sb3I6IFwicmdiYSgxLDEsMSwxKVwiLFxuICAgIH0pO1xuXG4gICAgbGV0IHdpZHRoID0gdGhpcy5vcHRpb25zLmNhbnZhc193aWR0aCB8fCB0aGlzLm9wdGlvbnMuY2FudmFzX3NpemUgfHwgXCIyNTBcIjtcbiAgICBsZXQgaGVpZ2h0ID1cbiAgICAgIHRoaXMub3B0aW9ucy5jYW52YXNfaGVpZ2h0IHx8IHRoaXMub3B0aW9ucy5jYW52YXNfc2l6ZSB8fCBcIjI1MFwiO1xuICAgIGdsc2xjYW52YXMuY2FudmFzLnN0eWxlLndpZHRoID0gd2lkdGggKyBcInB4XCI7XG4gICAgZ2xzbGNhbnZhcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgXCJweFwiO1xuICAgIGdsc2xjYW52YXMucmVzaXplKCk7XG5cbiAgICB0aGlzLmNhbnZhcyA9IGdsc2xjYW52YXM7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmltZ3MgJiYgdGhpcy5vcHRpb25zLmltZ3MubGVuZ3RoID4gMCkge1xuICAgICAgZm9yIChsZXQgaSBpbiB0aGlzLm9wdGlvbnMuaW1ncykge1xuICAgICAgICB0aGlzLmNhbnZhcy5zZXRVbmlmb3JtKFwidV90ZXhcIiArIGksIHRoaXMub3B0aW9ucy5pbWdzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNZWRpYSBDYXB0dXJlXG4gICAgdGhpcy5tZWRpYUNhcHR1cmUgPSBuZXcgTWVkaWFDYXB0dXJlKCk7XG4gICAgdGhpcy5tZWRpYUNhcHR1cmUuc2V0Q2FudmFzKHRoaXMuZWxDYW52YXMpO1xuICAgIHRoaXMuY2FudmFzLm9uKFwicmVuZGVyXCIsICgpID0+IHtcbiAgICAgIHRoaXMubWVkaWFDYXB0dXJlLmNvbXBsZXRlU2NyZWVuc2hvdCgpO1xuICAgIH0pO1xuXG4gICAgaWYgKG1haW4ub3B0aW9ucy5kaXNwbGF5TWVudSkge1xuICAgICAgLy8gQ09OVFJPTFNcbiAgICAgIHRoaXMuY29udHJvbHNDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwidWxcIik7XG4gICAgICB0aGlzLmNvbnRyb2xzQ29udGFpbmVyLmNsYXNzTmFtZSA9IENPTlRST0xTX0NMQVNTTkFNRTtcbiAgICAgIHRoaXMuY29udHJvbFBhbmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInVsXCIpO1xuICAgICAgdGhpcy5jb250cm9sUGFuZWwuY2xhc3NOYW1lID0gQ09OVFJPTFNfUEFORUxfQ0xBU1NOQU1FO1xuICAgICAgdGhpcy5jb250cm9sc0NvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmNvbnRyb2xQYW5lbCk7XG4gICAgICB0aGlzLmVsLmFwcGVuZENoaWxkKHRoaXMuY29udHJvbHNDb250YWluZXIpO1xuICAgICAgdGhpcy5jb250cm9scyA9IHt9O1xuICAgICAgLy8gcGxheS9zdG9wXG4gICAgICAvLyB0aGlzLmNvbnRyb2xzLnBsYXlQYXVzZSA9IG5ldyBNZW51SXRlbSh0aGlzLmNvbnRyb2xQYW5lbCwgJ2dlX2NvbnRyb2xfZWxlbWVudCcsICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+cGF1c2U8L2k+JywgKGV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmNvbnRyb2xzLnBsYXlQYXVzZSA9IG5ldyBNZW51SXRlbShcbiAgICAgICAgdGhpcy5jb250cm9sUGFuZWwsXG4gICAgICAgIFwiZ2VfY29udHJvbF9lbGVtZW50XCIsXG4gICAgICAgICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+cGF1c2U8L2k+JyxcbiAgICAgICAgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBpZiAoZ2xzbGNhbnZhcy5wYXVzZWQpIHtcbiAgICAgICAgICAgIGdsc2xjYW52YXMucGxheSgpO1xuICAgICAgICAgICAgLy8gdGhpcy5jb250cm9scy5wbGF5UGF1c2UubmFtZSA9ICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+cGF1c2U8L2k+JzsvLydQYXVzZSc7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xzLnBsYXlQYXVzZS5uYW1lID1cbiAgICAgICAgICAgICAgJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5wYXVzZTwvaT4nOyAvLydQYXVzZSc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsc2xjYW52YXMucGF1c2UoKTtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbHMucGxheVBhdXNlLm5hbWUgPVxuICAgICAgICAgICAgICAnPGkgY2xhc3M9XCJtYXRlcmlhbC1pY29uc1wiPnBsYXlfYXJyb3c8L2k+JzsgLy8nUGxheSc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgLy8gcmVjXG4gICAgICB0aGlzLmlzQ2FwdHVyaW5nID0gZmFsc2U7XG4gICAgICAvLyBsZXQgcmVjID0gbmV3IE1lbnVJdGVtKHRoaXMuY29udHJvbFBhbmVsLCAnZ2VfY29udHJvbF9lbGVtZW50JywgJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5maWJlcl9tYW51YWxfcmVjb3JkPC9pPicsIChldmVudCkgPT4ge1xuICAgICAgbGV0IHJlYyA9IG5ldyBNZW51SXRlbShcbiAgICAgICAgdGhpcy5jb250cm9sUGFuZWwsXG4gICAgICAgIFwiZ2VfY29udHJvbF9lbGVtZW50XCIsXG4gICAgICAgICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+JiN4RTA2MTs8L2k+JyxcbiAgICAgICAgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBpZiAodGhpcy5pc0NhcHR1cmluZykge1xuICAgICAgICAgICAgdGhpcy5zdG9wVmlkZW9DYXB0dXJlKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRWaWRlb0NhcHR1cmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICB0aGlzLmNvbnRyb2xzLnJlYyA9IHJlYztcbiAgICAgIHRoaXMuY29udHJvbHMucmVjLmJ1dHRvbi5zdHlsZS5jb2xvciA9IFwicmVkXCI7XG5cbiAgICAgIC8vIHByZXNlbnQgbW9kZSAob25seSBpZiB0aGVyZSBpcyBhIHByZXNlbnRhdGlvbi5odG1sIGZpbGUgdG8gcG9pbnQgdG8pXG4gICAgICAvLyB0aGlzLmNvbnRyb2xzLnByZXNlbnRhdGlvbk1vZGUgPSBuZXcgTWVudUl0ZW0odGhpcy5jb250cm9sUGFuZWwsICdnZV9jb250cm9sX2VsZW1lbnQnLCAnPGkgY2xhc3M9XCJtYXRlcmlhbC1pY29uc1wiPm9wZW5faW5fbmV3PC9pPicsIChldmVudCkgPT4ge1xuICAgICAgdGhpcy5jb250cm9scy5wcmVzZW50YXRpb25Nb2RlID0gbmV3IE1lbnVJdGVtKFxuICAgICAgICB0aGlzLmNvbnRyb2xQYW5lbCxcbiAgICAgICAgXCJnZV9jb250cm9sX2VsZW1lbnRcIixcbiAgICAgICAgJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5vcGVuX2luX25ldzwvaT4nLFxuICAgICAgICAoZXZlbnQpID0+IHtcbiAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGlmIChtYWluLnBXaW5kb3dPcGVuKSB7XG4gICAgICAgICAgICBtYWluLnRvZ2dsZVByZXNlbnRhdGlvbldpbmRvdyhmYWxzZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1haW4udG9nZ2xlUHJlc2VudGF0aW9uV2luZG93KHRydWUpO1xuICAgICAgICAgI
23459H1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgdGhpcy5lbENvbnRyb2wgPSB0aGlzLmVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoQ09OVFJPTFNfQ0xBU1NOQU1FKVswXTtcbiAgICAgIHRoaXMuZWxDb250cm9sLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZWVudGVyXCIsIChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLnNob3dDb250cm9scygpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmVsQ29udHJvbC5hZGRFdmVudExpc3RlbmVyKFwibW91c2VsZWF2ZVwiLCAoZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5oaWRlQ29udHJvbHMoKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5lbENhbnZhcy5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsIChldmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQub2Zmc2V0WSA+IHRoaXMuZWxDYW52YXMuY2xpZW50SGVpZ2h0ICogMC42Nikge1xuICAgICAgICAgIHRoaXMuc2hvd0NvbnRyb2xzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5oaWRlQ29udHJvbHMoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0aGlzLmhpZGVDb250cm9scygpO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT0gRVZFTlRTXG4gICAgLy8gRHJhZ2dhYmxlL3Jlc2l6YWJsZS9zbmFwcGFibGVcbiAgICBpZiAoXG4gICAgICBtYWluLm9wdGlvbnMuY2FudmFzX2RyYWdnYWJsZSB8fFxuICAgICAgbWFpbi5vcHRpb25zLmNhbnZhc19yZXNpemFibGUgfHxcbiAgICAgIG1haW4ub3B0aW9ucy5jYW52YXNfc25hcGFibGVcbiAgICApIHtcbiAgICAgIHN1YnNjcmliZUludGVyYWN0aXZlRG9tKHRoaXMuZWwsIHtcbiAgICAgICAgbW92ZTogbWFpbi5vcHRpb25zLmNhbnZhc19kcmFnZ2FibGUsXG4gICAgICAgIHJlc2l6ZTogbWFpbi5vcHRpb25zLmNhbnZhc19yZXNpemFibGUsXG4gICAgICAgIHNuYXA6IG1haW4ub3B0aW9ucy5jYW52YXNfc25hcGFibGUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKG1haW4ub3B0aW9ucy5jYW52YXNfc2l6ZSA9PT0gXCJoYWxmc2NyZWVuXCIpIHtcbiAgICAgICAgdGhpcy5lbC5zbmFwUmlnaHQoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5lbC5vbihcIm1vdmVcIiwgKGV2ZW50KSA9PiB7XG4gICAgICAgIGV2ZW50LmVsLnN0eWxlLndpZHRoID0gZXZlbnQuZWwuY2xpZW50V2lkdGggKyBcInB4XCI7XG4gICAgICAgIGV2ZW50LmVsLnN0eWxlLmhlaWdodCA9IGV2ZW50LmVsLmNsaWVudEhlaWdodCArIFwicHhcIjtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5lbC5vbihcInJlc2l6ZVwiLCAoZXZlbnQpID0+IHtcbiAgICAgICAgZ2xzbGNhbnZhcy5jYW52YXMuc3R5bGUud2lkdGggPSBldmVudC5lbC5jbGllbnRXaWR0aCArIFwicHhcIjtcbiAgICAgICAgZ2xzbGNhbnZhcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gZXZlbnQuZWwuY2xpZW50SGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICBnbHNsY2FudmFzLnJlc2l6ZSgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlcmUgaXMgYSBtZW51IG9mZnNldCB0aGUgZWRpdG9yIHRvIGNvbWUgYWZ0ZXIgaXRcbiAgICBpZiAobWFpbi5tZW51KSB7XG4gICAgICB0aGlzLmVsLnN0eWxlLnRvcCA9XG4gICAgICAgIChtYWluLm1lbnUuZWwuY2xpZW50SGVpZ2h0IHx8XG4gICAgICAgICAgbWFpbi5tZW51LmVsLm9mZnNldEhlaWdodCB8fFxuICAgICAgICAgIG1haW4ubWVudS5lbC5zY3JvbGxIZWlnaHQpICsgXCJweFwiO1xuICAgIH1cblxuICAgIC8vIEFkZCBhbGwgdGhpcyB0byB0aGUgbWFpbiBjb250YWluZXJcbiAgICBtYWluLmNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmVsKTtcbiAgICBnbHNsY2FudmFzLnJlc2l6ZSgpO1xuICB9XG5cbiAgaGlkZUNvbnRyb2xzKCkge1xuICAgIGlmICh0aGlzLmVsQ29udHJvbCAmJiB0aGlzLmVsQ29udHJvbC5jbGFzc05hbWUgPT09IENPTlRST0xTX0NMQVNTTkFNRSkge1xuICAgICAgdGhpcy5lbENvbnRyb2wuY2xhc3NOYW1lID1cbiAgICAgICAgQ09OVFJPTFNfQ0xBU1NOQU1FICsgXCIgXCIgKyBDT05UUk9MU19DTEFTU05BTUUgKyBcIl9oaWRkZW5cIjtcbiAgICB9XG4gIH1cblxuICBzaG93Q29udHJvbHMoKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5lbENvbnRyb2wgJiZcbiAgICAgIHRoaXMuZWxDb250cm9sLmNsYXNzTmFtZSA9PT1cbiAgICAgICAgQ09OVFJPTFNfQ0xBU1NOQU1FICsgXCIgXCIgKyBDT05UUk9MU19DTEFTU05BTUUgKyBcIl9oaWRkZW5cIlxuICAgICkge1xuICAgICAgdGhpcy5lbENvbnRyb2wuY2xhc3NOYW1lID0gQ09OVFJPTFNfQ0xBU1NOQU1FO1xuICAgIH1cbiAgfVxuXG4gIHJlcXVlc3RSZWRyYXcoKSB7XG4gICAgdGhpcy5jYW52YXMuZm9yY2VSZW5kZXIgPSB0cnVlO1xuICAgIHRoaXMuY2FudmFzLnJlbmRlcigpO1xuICB9XG5cbiAgc2NyZWVuc2hvdCgpIHtcbiAgICB0aGlzLnJlcXVlc3RSZWRyYXcoKTtcbiAgICByZXR1cm4gdGhpcy5tZWRpYUNhcHR1cmUuc2NyZWVuc2hvdCgpO1xuICB9XG5cbiAgc3RhcnRWaWRlb0NhcHR1cmUoKSB7XG4gICAgdGhpcy5yZXF1ZXN0UmVkcmF3KCk7XG4gICAgaWYgKHRoaXMubWVkaWFDYXB0dXJlLnN0YXJ0VmlkZW9DYXB0dXJlKCkpIHtcbiAgICAgIHRoaXMuaXNDYXB0dXJpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5jb250cm9scy5yZWMuYnV0dG9uLnN0eWxlLmNvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgLy8gdGhpcy5jb250cm9scy5yZWMubmFtZSA9ICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+c3RvcDwvaT4nO1xuICAgICAgdGhpcy5jb250cm9scy5yZWMubmFtZSA9ICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+JiN4RTA2MTs8L2k+JztcbiAgICB9XG4gIH1cblxuICBzdG9wVmlkZW9DYXB0dXJlKCkge1xuICAgIGlmICh0aGlzLmlzQ2FwdHVyaW5nKSB7XG4gICAgICB0aGlzLmlzQ2FwdHVyaW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmNvbnRyb2xzLnJlYy5idXR0b24uc3R5bGUuY29sb3IgPSBcInJlZFwiO1xuICAgICAgLy8gdGhpcy5jb250cm9scy5yZWMubmFtZSA9ICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+ZmliZXJfbWFudWFsX3JlY29yZDwvaT4nO1xuICAgICAgdGhpcy5jb250cm9scy5yZWMubmFtZSA9ICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+c3RvcDwvaT4nO1xuICAgICAgdGhpcy5tZWRpYUNhcHR1cmUuc3RvcFZpZGVvQ2FwdHVyZSgpLnRoZW4oKHZpZGVvKSA9PiB7XG4gICAgICAgI
23459HNhdmVBcyh2aWRlby5ibG9iLCBgJHtOdW1iZXIobmV3IERhdGUoKSl9LndlYm1gKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9wZW5XaW5kb3coKSB7XG4gICAgdGhpcy5vcmlnaW5hbFNpemUgPSB7XG4gICAgICB3aWR0aDogdGhpcy5jYW52YXMuY2FudmFzLmNsaWVudFdpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLmNhbnZhcy5jYW52YXMuY2xpZW50SGVpZ2h0LFxuICAgIH07XG4gICAgdGhpcy5wcmVzZW50YXRpb25XaW5kb3cgPSB3aW5kb3cub3BlbihcIlwiLCBcIl9ibGFua1wiLCBcInByZXNlbnRhdGlvbldpbmRvd1wiKTtcbiAgICB0aGlzLnNldFVwUHJlc2VudGF0aW9uV2luZG93KCk7XG4gIH1cblxuICBjbG9zZVdpbmRvdygpIHtcbiAgICBpZiAodGhpcy5wcmVzZW50YXRpb25XaW5kb3cpIHtcbiAgICAgIHRoaXMucHJlc2VudGF0aW9uV2luZG93LmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgc2V0Q2FudmFzU2l6ZSh3LCBoKSB7XG4gICAgdGhpcy5jYW52YXMuY2FudmFzLnN0eWxlLndpZHRoID0gdyArIFwicHhcIjtcbiAgICB0aGlzLmNhbnZhcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gaCArIFwicHhcIjtcbiAgfVxuXG4gIHNldFVwUHJlc2VudGF0aW9uV2luZG93KCkge1xuICAgIHRoaXMucHJlc2VudGF0aW9uV2luZG93LmRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMuY2FudmFzKTtcbiAgICB2YXIgZCA9IHRoaXMucHJlc2VudGF0aW9uV2luZG93LmRvY3VtZW50O1xuICAgIHZhciBkaXYgPSBkLmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgZGl2LmFwcGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoXCJQcm9qZWN0b3IgbW9kZVwiKSk7XG4gICAgdmFyIHNwYW4gPSB0aGlzLnByZXNlbnRhdGlvbldpbmRvdy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICBkaXYuYXBwZW5kQ2hpbGQoc3Bhbik7XG4gICAgc3Bhbi5hcHBlbmRDaGlsZChcbiAgICAgIGQuY3JlYXRlVGV4dE5vZGUoXG4gICAgICAgIFwiIC0gSWYgdGhlIGNhbnZhcyBkb2Vzbid0IHVwZGF0ZSwgZHJhZyB0aGlzIHdpbmRvdyBhbmQgcmV2ZWFsIHRoZSBlZGl0b3JcIlxuICAgICAgKVxuICAgICk7XG4gICAgZC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG5cbiAgICBkLnRpdGxlID0gXCJHTFNMIEVkaXRvclwiO1xuICAgIGQuYm9keS5zdHlsZS5wYWRkaW5nID0gXCIwXCI7XG4gICAgZC5ib2R5LnN0eWxlLm1hcmdpbiA9IFwiMFwiO1xuICAgIGQuYm9keS5zdHlsZS5iYWNrZ3JvdW5kID0gXCIjMTcxZTIyXCI7XG4gICAgZC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gXCJoaWRkZW5cIjtcblxuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICBkaXYuc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICBkaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiYSgwLCAwLCAwLCAwLjUpXCI7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgIGRpdi5zdHlsZS50b3AgPSBcIjBcIjtcbiAgICBkaXYuc3R5bGUubGVmdCA9IFwiMFwiO1xuICAgIGRpdi5zdHlsZS5yaWdodCA9IFwiMFwiO1xuICAgIGRpdi5zdHlsZS5wYWRkaW5nID0gXCIxNnB4XCI7XG4gICAgZGl2LnN0eWxlLmNvbG9yID0gXCIjZmZmZmZmXCI7XG4gICAgZGl2LnN0eWxlLmZvbnRTaXplID0gXCIxNHB4XCI7XG4gICAgZGl2LnN0eWxlLmZvbnRGYW1pbHkgPSBcIkhlbHZldGljYSwgR2VuZXZhLCBzYW5zLXNlcmlmXCI7XG4gICAgZGl2LnN0eWxlLmZvbnRXZWlnaHQgPSBcIjQwMFwiO1xuICAgIGRpdi5zdHlsZS5sZXR0ZXJTcGFjaW5nID0gXCIwLjFlbVwiO1xuICAgIGRpdi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgIGRpdi5zdHlsZS5vcGFjaXR5ID0gXCIxXCI7XG4gICAgZGl2LnN0eWxlLnpJbmRleCA9IFwiOTk5OVwiO1xuICAgIGRpdi5zdHlsZS5zZXRQcm9wZXJ0eShcIi13ZWJraXQtdHJhbnNpdGlvblwiLCBcIm9wYWNpdHkgMS41c1wiKTtcbiAgICBkaXYuc3R5bGUuc2V0UHJvcGVydHkoXCItbW96LXRyYW5zaXRpb25cIiwgXCJvcGFjaXR5IDEuNXNcIik7XG4gICAgZGl2LnN0eWxlLnNldFByb3BlcnR5KFwidHJhbnNpdGlvblwiLCBcIm9wYWNpdHkgMS41c1wiKTtcblxuICAgIHNwYW4uc3R5bGUuY29sb3IgPSBcInJnYmEoMjU1LCAyNTUsIDI1NSwgMC41KVwiO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBkaXYuc3R5bGUub3BhY2l0eSA9IDA7XG4gICAgfSwgNDAwMCk7XG5cbiAgICB0aGlzLnNldENhbnZhc1NpemUoXG4gICAgICB0aGlzLnByZXNlbnRhdGlvbldpbmRvdy5pbm5lcldpZHRoLFxuICAgICAgdGhpcy5wcmVzZW50YXRpb25XaW5kb3cuaW5uZXJIZWlnaHRcbiAgICApO1xuICAgIHRoaXMucHJlc2VudGF0aW9uV2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICBcInJlc2l6ZVwiLFxuICAgICAgdGhpcy5vblByZXNlbnRhdGlvbldpbmRvd1Jlc2l6ZS5iaW5kKHRoaXMpXG4gICAgKTtcbiAgICB0aGlzLnByZXNlbnRhdGlvbldpbmRvdy5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgXCJ1bmxvYWRcIixcbiAgICAgIHRoaXMub25QcmVzZW50YXRpb25XaW5kb3dDbG9zZS5iaW5kKHRoaXMpXG4gICAgKTtcbiAgfVxuXG4gIG9uUHJlc2VudGF0aW9uV2luZG93Q2xvc2UoKSB7XG4gICAgdGhpcy5lbC5hcHBlbmRDaGlsZCh0aGlzLmNhbnZhcy5jYW52YXMpO1xuICAgIHRoaXMuc2V0Q2FudmFzU2l6ZSh0aGlzLm9yaWdpbmFsU2l6ZS53aWR0aCwgdGhpcy5vcmlnaW5hbFNpemUuaGVpZ2h0KTtcbiAgICB0aGlzLmNhbnZhcy5yZXNpemUoKTtcblxuICAgIHRoaXMubWFpbi5vbkNsb3NlUHJlc2VudGF0aW9uV2luZG93KCk7XG4gICAgdGhpcy5tYWluLm1lbnUub25DbG9zZVByZXNlbnRhdGlvbldpbmRvdygpO1xuICAgIHRoaXMucHJlc2VudGF0aW9uV2luZG93ID0gbnVsbDtcbiAgfVxuXG4gIG9uUHJlc2VudGF0aW9uV2luZG93UmVzaXplKCkge1xuICAgIGlmICh0aGlzLnByZXNlbnRhdGlvbldpbmRvdykge1xuICAgICAgdGhpcy5zZXRDYW52YXNTaXplKFxuICAgICAgICB0aGlzLnByZXNlbnRhdGlvbldpbmRvdy5pbm5lcldpZHRoLFxuICAgICAgICB0aGlzLnByZXNlbnRhdGlvbldpbmRvdy5pbm5lckhlaWdodFxuICAgICAgKTtcbiAgICAgIHRoaXMuY2FudmFzLnJlc2l6ZSgpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8gSW1wb3J0IENvZGVNaXJyb3JcbmltcG9ydCBDb2RlTWlycm9yIGZyb20gJ2NvZGVtaXJyb3InO1xuaW1wb3J0ICdjb2RlbWlycm9yL21vZGUvY2xpa2UvY2xpa2UuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCdWZmZXJNYW5hZ2VyIHtcbiAgICBjb25zdHJ1Y3RvciAobWFpbikge1xuICAgICAgICB0aGlzLm1haW4gPSBtYWluO1xuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSB7fTtcbiAgICAgICAgdGhpcy50YWJzID0ge307XG4gICAgICAgI
23459HRoaXMuY3VycmVudCA9ICd1bnRpdGxlZCc7XG4gICAgfVxuXG4gICAgb3BlbiAobmFtZSwgY29udGVudCkge1xuICAgICAgICBpZiAoIXRoaXMuZWwpIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBET00gZWxlbWVudFxuICAgICAgICAgICAgdGhpcy5lbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3VsJyk7XG4gICAgICAgICAgICB0aGlzLmVsLmNsYXNzTmFtZSA9ICdnZV9wYW5lbCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5tYWluLmNoYW5nZSAmJiB0aGlzLmN1cnJlbnQgPT09ICd1bnRpdGxlZCcpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdPcGVuIEN1cnJlbnQgaW4gYSBkaWZmZXJlbnQgdGFiJyk7XG4gICAgICAgICAgICB0aGlzLm9wZW4odGhpcy5jdXJyZW50LCB0aGlzLm1haW4uZ2V0Q29udGVudCgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYnVmZmVyc1tuYW1lXSA9IENvZGVNaXJyb3IuRG9jKGNvbnRlbnQsICd4LXNoYWRlci94LWZyYWdtZW50Jyk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHRhYlxuICAgICAgICBsZXQgdGFiID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKTtcbiAgICAgICAgdGFiLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnZ2VfcGFuZWxfdGFiJyk7XG4gICAgICAgIHRhYi50ZXh0Q29udGVudCA9IG5hbWU7XG4gICAgICAgIENvZGVNaXJyb3Iub24odGFiLCAnY2xpY2snLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdChuYW1lKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGNsb3NlID0gdGFiLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKSk7XG4gICAgICAgIGNsb3NlLnRleHRDb250ZW50ID0gJ3gnO1xuICAgICAgICBjbG9zZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2dlX3BhbmVsX3RhYl9jbG9zZScpO1xuICAgICAgICBDb2RlTWlycm9yLm9uKGNsb3NlLCAnY2xpY2snLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKG5
23459hbWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmVsLmFwcGVuZENoaWxkKHRhYik7XG4gICAgICAgIHRoaXMudGFic1tuYW1lXSA9IHRhYjtcblxuICAgICAgICBpZiAodGhpcy5lbCAmJiAhdGhpcy5wYW5lbCAmJiB0aGlzLmdldExlbmd0aCgpID4gMSkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIFBhbmVsIENNIGVsZW1lbnRcbiAgICAgICAgICAgIHRoaXMucGFuZWwgPSB0aGlzLm1haW4uZWRpdG9yLmFkZFBhbmVsKHRoaXMuZWwsIHsgcG9zaXRpb246ICd0b3AnIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2VsZWN0IChuYW1lKSB7XG4gICAgICAgIGxldCBidWYgPSB0aGlzLmJ1ZmZlcnNbbmFtZV07XG5cbiAgICAgICAgaWYgKGJ1ZiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYnVmLmdldEVkaXRvcigpKSB7XG4gICAgICAgICAgICBidWYgPSBidWYubGlua2VkRG9jKHsgc2hhcmVkSGlzdDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgb2xkID0gdGhpcy5tYWluLmVkaXRvci5zd2FwRG9jKGJ1Zik7XG4gICAgICAgIGxldCBsaW5rZWQgPSBvbGQuaXRlckxpbmtlZERvY3MoZnVuY3Rpb24oZG9jKSB7XG4gICAgICAgICAgICBsaW5rZWQgPSBkb2M7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAobGlua2VkKSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGRvY3VtZW50IGluIGJ1ZmZlcnMgaXMgdGhlIG9uZSB0aGUgb3RoZXIgdmlldyBpcyBsb29raW5nIGF0XG4gICAgICAgICAgICBmb3IgKGxldCBidWZmZXJOYW1lIGluIHRoaXMuYnVmZmVycykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJ1ZmZlcnNbYnVmZmVyTmFtZV0gPT09IG9sZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlcnNbYnVmZmVyTmFtZV0gPSBsaW5rZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb2xkLnVubGlua0RvYyhsaW5rZWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1haW4ub3B0aW9ucy5hdXRvZm9jdXMpIHtcbiAgICAgICAgICAgIHRoaXMubWFpbi5lZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1haW4uc2V0Q29udGVudCh0aGlzLm1haW4uZ2V0Q29udGVudCgpKTtcblxuICAgICAgICBpZiAodGhpcy50YWJzW3RoaXMuY3VycmVudF0pIHtcbiAgICAgICAgICAgIHRoaXMudGFic1t0aGlzLmN1cnJlbnRdLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnZ2VfcGFuZWxfdGFiJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50YWJzW25hbWVdLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnZ2VfcGFuZWxfdGFiX2FjdGl2ZScpO1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuYW1lO1xuXG4gICAgICAgIHRoaXMubWFpbi5lZGl0b3Iuc2V0U2l6ZShudWxsLCAnYXV0bycpO1xuICAgICAgICB0aGlzLm1haW4uZWRpdG9yLmdldFdyYXBwZXJFbGVtZW50KCkuc3R5bGUuaGVpZ2h0ID0gJ2F1dG8nO1xuXG4gICAgICAgIHRoaXMubWFpbi50cmlnZ2VyKCduZXdfY29udGVudCcsIHt9KTtcbiAgICB9XG5cbiAgICBjbG9zZSAobmFtZSkge1xuICAgICAgICBsZXQgbmVlZENoYW5nZSA9IG5hbWUgPT09IHRoaXMuZ2V0Q3VycmVudCgpO1xuXG4gICAgICAgIHRoaXMuZWwucmVtb3ZlQ2hpbGQodGhpcy50YWJzW25hbWVdKTtcbiAgICAgICAgZGVsZXRlIHRoaXMudGFic1tuYW1lXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuYnVmZmVyc1tuYW1lXTtcblxuICAgICAgICBpZiAodGhpcy5nZXRMZW5ndGgoKSA9PT0gMSkge1xuICAgICAgICAgICAgdGhpcy5wYW5lbC5jbGVhcigpO1xuICAgICAgICAgICAgdGhpcy5wYW5lbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmVlZENoYW5nZSkge1xuICAgICAgICAgICAgZm9yIChsZXQgcHJvcCBpbiB0aGlzLnRhYnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdChwcm9wKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldEN1cnJlbnQgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50O1xuICAgIH1cblxuICAgIGdldExlbmd0aCAoKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLmJ1ZmZlcnMpLmxlbmd0aDtcbiAgICB9XG59XG4iLCIvKlxuT3JpZ2luYWw6IGh0dHBzOi8vZ2l0aHViLmNvbS90YW5ncmFtcy90YW5ncmFtLXBsYXkvYmxvYi9naC1wYWdlcy9zcmMvanMvYWRkb25zL3VpL0ZpbGVEcm9wLmpzXG5BdXRob3I6IExvdSBIdWFuZyAoQHNhaWtvZmlzaClcbiovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpbGVEcm9wIHtcbiAgICBjb25zdHJ1Y3RvciAobWFpbikge1xuICAgICAgICAvLyBTZXQgdXAgZHJhZy9kcm9wIGZpbGUgbGlzdGVuZXJzXG4gICAgICAgIG1haW4uY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbnRlcicsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgLy8gQ2hlY2sgdG8gbWFrZSBzdXJlIHRoYXQgZHJvcHBlZCBpdGVtcyBhcmUgZmlsZXMuXG4gICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIG90aGVyIGRyYWdzIChlLmcuIHRleHQgaW4gZWRpdG9yKVxuICAgICAgICAgICAgLy8gZnJvbSB0dXJuaW5nIG9uIHRoZSBmaWxlIGRyb3AgYXJlYS5cbiAgICAgICAgICAgIC8vIFNlZSBoZXJlOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY4NDgwNDMvaG93LWRvLWktZGV0ZWN0LWEtZmlsZS1pcy1iZWluZy1kcmFnZ2VkLXJhdGhlci10aGFuLWEtZHJhZ2dhYmxlLWVsZW1lbnQtb24tbXktcGFcbiAgICAgICAgICAgIC8vIFRlc3RlZCBpbiBDaHJvbWUsIEZpcmVmb3gsIFNhZmFyaSA4XG4gICAgICAgICAgICB2Y
23459XIgdHlwZXMgPSBldmVudC5kYXRhVHJhbnNmZXIudHlwZXM7XG4gICAgICAgICAgICBpZiAodHlwZXMgIT09IG51bGwgJiYgKCh0eXBlcy5pbmRleE9mKSA/ICh0eXBlcy5pbmRleE9mKCdGaWxlcycpICE9PSAtMSkgOiB0eXBlcy5jb250YWlucygnYXBwbGljYXRpb24veC1tb3otZmlsZScpKSkge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnY29weSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgIG1haW4uY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvLyBSZXF1aXJlZCB0byBwcmV2ZW50IGJyb3dzZXIgZnJvbSBuYXZpZ2F0aW5nIHRvIGEgZmlsZVxuICAgICAgICAgICAgLy8gaW5zdGVhZCBvZiByZWNlaXZpbmcgYSBkYXRhIHRyYW5zZmVyXG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9LCBmYWxzZSk7XG5cbiAgICAgICAgbWFpbi5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2xlYXZlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICBtYWluLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZSA9IGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlc1swXTtcbiAgICAgICAgICAgICAgICBtYWluLm9wZW4oZmlsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICB9XG59XG4iLCJleHBvcnQgZGVmYXVsdCBjbGFzcyBIYXNoV2F0Y2gge1xuICAgIGNvbnN0cnVjdG9yIChtYWluKSB7XG4gICAgICAgIHRoaXMubWFpbiA9IG1haW47XG4gICAgICAgIHRoaXMuY2hlY2soKTtcblxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2soKTtcbiAgICAgICAgfSwgZmFsc2UpO1xuICAgIH1cblxuICAgIGNoZWNrKCkge1xuICAgICAgICBpZiAod2luZG93LmxvY2F0aW9uLmhhc2ggIT09ICcnKSB7XG4gICAgICAgICAgICB0aGlzLm1haW4ub3B0aW9ucy5pbWdzID0gW107XG5cbiAgICAgICAgICAgIGxldCBoYXNoZXMgPSBsb2NhdGlvbi5oYXNoLnNwbGl0KCcmJyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIGluIGhhc2hlcykge1xuICAgICAgICAgICAgICAgIGxldCBleHQgPSBoYXNoZXNbaV0uc3Vic3RyKGhhc2hlc1tpXS5sYXN0SW5kZXhPZignLicpICsgMSk7XG4gICAgICAgICAgICAgICAgbGV0IHBhdGggPSBoYXNoZXNbaV07XG5cbiAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IGhhc2ggaWYgaXMgcHJlc2VudFxuICAgICAgICAgICAgICAgIGlmIChwYXRoLnNlYXJjaCgnIycpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgZmlsZW5hbWUgPSBwYXRoLnNwbGl0KCcvJykucG9wKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoZXh0ID09PSAnZnJhZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWluLm9wZW4ocGF0aCwgZmlsZW5hbWUucmVwbGFjZSgvXFwuW14vLl0rJC8sICcnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGV4dCA9PT0gJ3BuZycgfHwgZXh0ID09PSAnanBnJyB8fCBleHQgPT09ICdQTkcnIHx8IGV4dCA9PT0gJ0pQRycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWluLm9wdGlvbnMuaW1ncy5wdXNoKHBhdGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBxdWVyeSA9IHBhcnNlUXVlcnkod2luZG93LmxvY2F0aW9uLnNlYXJjaC5zbGljZSgxKSk7XG4gICAgICAgIGlmIChxdWVyeSkge1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2xvZycpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubWFpbi5idWZmZXJNYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbG9ncyA9IHF1ZXJ5LmxvZy5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSBpbiBsb2dzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWluLm9wZW4oJ2h0dHBzOi8vdGhlYm9va29mc2hhZGVycy5jb20vbG9nLycgKyBsb2dzW2ldICsgJy5mcmFnJywgbG9nc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1haW4ub3BlbignaHR0cHM6Ly90aGVib29rb2ZzaGFkZXJzLmNvbS9sb2cvJyArIHF1ZXJ5LmxvZyArICcuZnJhZycsIHF1ZXJ5LmxvZyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHF1ZXJ5W2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ3RydWUnIHx8IHZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA9PSAndHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHBhcnNlRmxvYXQodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHBhcnNlRmxvYXQodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgI
23459HRoaXMubWFpbi5vcHRpb25zW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUXVlcnkgKHFzdHIpIHtcbiAgICBsZXQgcXVlcnkgPSB7fTtcbiAgICBsZXQgYSA9IHFzdHIuc3BsaXQoJyYnKTtcbiAgICBmb3IgKGxldCBpIGluIGEpIHtcbiAgICAgICAgbGV0IGIgPSBhW2ldLnNwbGl0KCc9Jyk7XG4gICAgICAgIHF1ZXJ5W2RlY29kZVVSSUNvbXBvbmVudChiWzBdKV0gPSBkZWNvZGVVUklDb21wb25lbnQoYlsxXSk7XG4gICAgfVxuICAgIHJldHVybiBxdWVyeTtcbn1cbiIsIi8qXG5PcmlnaW5hbDogaHR0cHM6Ly9naXRodWIuY29tL3RhbmdyYW1zL3RhbmdyYW0tcGxheS9ibG9iL2doLXBhZ2VzL3NyYy9qcy9hZGRvbnMvTG9jYWxTdG9yYWdlLmpzXG5BdXRob3I6IExvdSBIdWFuZyAoQHNhaWtvZmlzaClcbiovXG5cbi8qKlxuICogIExvY2FsIHN0b3JhZ2VcbiAqXG4gKiAgUHJvdmlkZXMgYSBjb21tb24gaW50ZXJmYWNlIGZvciB0aGUgYXBwbGljYXRpb24gd2hlcmUgbW9kdWxlcyBjYW5cbiAqICByZXF1ZXN0IHN0b3JhZ2Ugb2YgdmFsdWVzIGFjcm9zcyBtdWx0aXBsZSB1c2VyIHNlc3Npb25zIHZpYSB0aGVcbiAqICBicm93c2VyJ3MgTG9jYWxTdG9yYWdlIEFQSS5cbiAqXG4gKiAgQnJvd3NlciBzdXBwb3J0IGlzIGdvb2QsIHNvIG5vIGZhbGxiYWNrcyBhcmUgaW1wbGVtZW50ZWQuXG4gKiAgVGhpcyBtb2R1bGUgbWFuYWdlcyBuYW1lc3BhY2luZyBmb3IgVGFuZ3JhbSBQbGF5IHRvIHByZXZlbnQgbmFtZVxuICogIGNvbGxpc2lvbnMgd2l0aCBvdGhlciBsaWJyYXJpZXMsIGJyb3dzZXIgZXh0ZW5zaW9ucywgZXRjLlxuICovXG5jb25zdCBMT0NBTF9TVE9SQUdFX1BSRUZJWCA9ICdnbHNsRWRpdG9yLSc7XG5cbmNvbnN0IExvY2FsU3RvcmFnZSA9IHtcbiAgICAvKipcbiAgICAgKiAgc2V0SXRlbSgpXG4gICAgICogIE5hbWVzcGFjZXMga2V5IG5hbWUgdG8gVGFuZ3JhbSBQbGF5IGFwcGxpY2F0aW9uIGFuZCBhZGRzXG4gICAgICogIHRoZSB2YWx1ZSB0byBMb2NhbFN0b3JhZ2UuXG4gICAgICovXG4gICAgc2V0SXRlbSAoa2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAod2luZG93LmxvY2FsU3RvcmFnZSkge1xuICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKExPQ0FMX1NUT1JBR0VfUFJFRklYICsga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogIHB1c2hJdGVtKClcbiAgICAgKiAgU3RvcmUgdmFsdWVzIGFzIGFuIGFycmF5LiBJZiB0aGUga2V5IGRvZXNuJ3QgZXhpc3QgYXMgYW4gb2JqZWN0LCBjcmVhdGUgaXQuXG4gICAgICogIE5vdGUgdGhhdCB0aGlzIG92ZXJ3cml0ZXMgYW4gb2xkIHZhbHVlIGlmIGl0IGlzIHByZXNlbnQgYW5kIG5vdCBhIEpTT04gb2JqZWN0IVxuICAgICAqICBJZiBpdCBleGlzdHMsIHJldHJlaXZlIGl0LCBzZXJpYWxpemUgaXQgaW50byBKU09OLCBwdXNoIHRoZSBuZXcgdmFsdWUsXG4gICAgICogIHJlLWVuY29kZSB0byBhIHN0cmluZyBhbmQgdGhlbiBzZXQgaXQgYmFjayBpbiBsb2NhbFN0b3JhZ2UuXG4gICAgICogIE5vIG90aGVyIGFycmF5IG1ldGhvZHMgYXJlIGltcGxlbWVudGVkLiBJZiB5b3UgbmVlZCB0byBkZWxldGUgaXRlbXMsIGV0Y1xuICAgICAqICB0aGVuIHJldHJpZXZlIHRoZSBzdHJpbmcgYXMgbm9ybWFsLCBkbyB0aGUgd29yayBpbiB5b3VyIHNjcmlwdCwgYW5kIHRoZW5cbiAgICAgKiAgc2V0IGl0IHRvIHRoZSBuZXcgc3RyaW5naWZpZWQgYXJyYXkgaW5zdGVhZCBvZiBwdXNoaW5nIGl0LlxuICAgICAqL1xuICAgIHB1c2hJdGVtIChrZXksIHZhbHVlKSB7XG4gICAgICAgIGxldCBzdG9yZWQ7XG4gICAgICAgIHN0b3JlZCA9IHRoaXMuZ2V0SXRlbShrZXkpO1xuICAgICAgICAvLyBJbiBjYXNlIHRoZXJlIGlzIGEgcHJldmlvdXNseSBzdG9yZWQgaXRlbSBoZXJlIHRoYXQgaXMgbm90XG4gICAgICAgIC8vIHBhcnNlYWJsZSBKU09OLCBkb24ndCBmYWlsXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzdG9yZWQgPSBKU09OLnBhcnNlKHN0b3JlZCk7XG4gICAgICAgICAgICBzdG9yZWQuYXJyID0gc3RvcmVkLmFyciB8fCBbXTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgc3RvcmVkID0geyBhcnI6IFtdIH07XG4gICAgICAgIH1cbiAgICAgICAgc3RvcmVkLmFyci5wdXNoKHZhbHVlKTtcbiAgICAgICAgdGhpcy5zZXRJdGVtKGtleSwgSlNPTi5zdHJpbmdpZnkoc3RvcmVkKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqICBnZXRJdGVtKClcbiAgICAgKiAgUmV0cmlldmVzIHZhbHVlIGZvciB0aGUgZ2l2ZW4ga2V5IG5hbWUgYW5kIGFwcGxpY2F0aW9uIG5hbWVzcGFjZS5cbiAgICAgKi9cbiAgICBnZXRJdGVtIChrZXkpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5sb2NhbFN0b3JhZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oTE9DQUxfU1RPUkFHRV9QUkVGSVggKyBrZXkpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqICByZW1vdmVJdGVtKClcbiAgICAgKiAgUmVtb3ZlcyBrZXktdmFsdWUgcGFpciB1bmRlciB0aGUgYXBwbGljYXRpb24gbmFtZXNwYWNlLlxuICAgICAqL1xuICAgIHJlbW92ZUl0ZW0gKGtleSkge1xuICAgICAgICBpZiAod2luZG93LmxvY2FsU3RvcmFnZSkge1xuICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKExPQ0FMX1NUT1JBR0VfUFJFRklYICsga2V5KTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiAgY2xlYXIoKVxuICAgICAqICBMb29wcyB0aHJvdWdoIGFsbCB2YWx1ZXMgaW4gbG9jYWxTdG9yYWdlIHVuZGVyIHRoZSBhcHBsaWNhdGlvblxuICAgICAqICBuYW1lc3BhY2UgYW5kIHJlbW92ZXMgdGhlbSwgcHJlc2VydmluZyBvdGhlciBrZXktdmFsdWUgcGFpcnMgaW5cbiAgICAgKiAgbG9jYWxTdG9yYWdlLlxuICAgICAqL1xuICAgIGNsZWFyICgpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5sb2NhbFN0b3JhZ2UpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiB3aW5kb3cubG9jYWxTdG9yYWdlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleS5pbmRleE9mKExPQ0FMX1NUT1JBR0VfUFJFRklYKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oTE9DQUxfU1RPUkFHRV9QUkVGSVggKyBrZXkpO1xuICAgICAgICAgICAgICAgI
23459H1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG59O1xuXG5leHBvcnQgZGVmYXVsdCBMb2NhbFN0b3JhZ2U7XG4iLCJleHBvcnQgZnVuY3Rpb24gZ2V0RG9tT3JpZ2luIChlbCkge1xuICAgIGNvbnN0IGJveCA9IChlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QpID8gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgOiB7IHRvcDogMCwgbGVmdDogMCB9O1xuICAgIGNvbnN0IGRvYyA9IGVsICYmIGVsLm93bmVyRG9jdW1lbnQ7XG4gICAgY29uc3QgYm9keSA9IGRvYy5ib2R5O1xuICAgIGNvbnN0IHdpbiA9IGRvYy5kZWZhdWx0VmlldyB8fCBkb2MucGFyZW50V2luZG93IHx8IHdpbmRvdztcbiAgICBjb25zdCBkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudCB8fCBib2R5LnBhcmVudE5vZGU7XG4gICAgY29uc3QgY2xpZW50VG9wID0gZG9jRWxlbS5jbGllbnRUb3AgfHwgYm9keS5jbGllbnRUb3AgfHwgMDsgLy8gYm9yZGVyIG9uIGh0bWwgb3IgYm9keSBvciBib3RoXG4gICAgY29uc3QgY2xpZW50TGVmdCA9IGRvY0VsZW0uY2xpZW50TGVmdCB8fCBib2R5LmNsaWVudExlZnQgfHwgMDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IGJveC5sZWZ0ICsgKHdpbi5wYWdlWE9mZnNldCB8fCBkb2NFbGVtLnNjcm9sbExlZnQpIC0gY2xpZW50TGVmdCxcbiAgICAgICAgdG9wOiBib3gudG9wICsgKHdpbi5wYWdlWU9mZnNldCB8fCBkb2NFbGVtLnNjcm9sbFRvcCkgLSBjbGllbnRUb3BcbiAgICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGV2aWNlUGl4ZWxSYXRpbyAoY3R4KSB7XG4gICAgbGV0IGRldmljZVBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuICAgIGxldCBiYWNraW5nU3RvcmVSYXRpbyA9IGN0eC53ZWJraXRCYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4Lm1vekJhY2tpbmdTdG9yZVBpeGVsUmF0aW8gfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgubXNCYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4Lm9CYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmJhY2tpbmdTdG9yZVBpeGVsUmF0aW8gfHwgMTtcbiAgICByZXR1cm4gZGV2aWNlUGl4ZWxSYXRpbyAvIGJhY2tpbmdTdG9yZVJhdGlvO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0SlNPTih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpO1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSAnanNvbic7XG4gICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHN0YXR1cyA9IHhoci5zdGF0dXM7XG4gICAgICBpZiAoc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgeGhyLnJlc3BvbnNlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGxiYWNrKHN0YXR1cywgeGhyLnJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG59O1xuIiwiXG5leHBvcnQgZnVuY3Rpb24gaXNDb21tZW50ZWQoY20sIG5MaW5lLCBtYXRjaCkge1xuICAgIGxldCB0b2tlbiA9IGNtLmdldFRva2VuQXQoeyBsaW5lOiBuTGluZSwgY2g6IG1hdGNoLmluZGV4IH0pO1xuICAgIGlmICh0b2tlbiAmJiB0b2tlbi50eXBlKSB7XG4gICAgICAgIHJldHVybiB0b2tlbi50eXBlID09PSAnY29tbWVudCc7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTGluZUFmdGVyTWFpbihjbSwgbkxpbmUpIHtcbiAgICBsZXQgdG90YWxMaW5lcyA9IGNtLmdldERvYygpLnNpemU7XG4gICAgbGV0IHZvaWRSRSA9IG5ldyBSZWdFeHAoJ3ZvaWQgbWFpblxcXFxzKlxcXFwoXFxcXHMqW3ZvaWRdKlxcXFwpJywgJ2knKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5MaW5lICYmIGkgPCB0b3RhbExpbmVzOyBpKyspIHtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IHVudGlsIGJlaW5nIGluc2lkZSB0aGUgbWFpbiBmdW5jdGlvblxuICAgICAgICBsZXQgdm9pZE1hdGNoID0gdm9pZFJFLmV4ZWMoY20uZ2V0TGluZShpKSk7XG4gICAgICAgIGlmICh2b2lkTWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZhcmlhYmxlVHlwZShjbSwgc1ZhcmlhYmxlKSB7XG4gICAgbGV0IG5MaW5lcyA9IGNtLmdldERvYygpLnNpemU7XG5cbiAgICAvLyBTaG93IGxpbmUgd2hlcmUgdGhlIHZhbHVlIG9mIHRoZSB2YXJpYWJsZSBpcyBiZWVuIGFzaWduZWRcbiAgICBsZXQgdW5pZm9ybVJFID0gbmV3IFJlZ0V4cCgnXFxcXHMqdW5pZm9ybVxcXFxzKyhmbG9hdHx2ZWMyfHZlYzN8dmVjNClcXFxccysnICsgc1ZhcmlhYmxlICsgJ1xcXFxzKjsnKTtcbiAgICBsZXQgdm9pZFJFID0gbmV3IFJlZ0V4cCgndm9pZCBtYWluXFxcXHMqXFxcXChcXFxccypbdm9pZF0qXFxcXCknLCAnaScpO1xuICAgIGxldCB2b2lkSU4gPSBmYWxzZTtcbiAgICBsZXQgY29uc3RydWN0UkUgPSBuZXcgUmVnRXhwKCcoZmxvYXR8dmVjXFxcXGQpXFxcXHMrKCcgKyBzVmFyaWFibGUgKyAnKVxcXFxzKls7XT8nLCAnaScpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbkxpbmVzOyBpKyspIHtcbiAgICAgICAgaWYgKCF2b2lkSU4pIHtcbiAgICAgICAgICAgIC8vIERvIG5vdCBzdGFydCB1bnRpbCBiZWluZyBpbnNpZGUgdGhlIG1haW4gZnVuY3Rpb25cbiAgICAgICAgICAgIGxldCB2b2lkTWF0Y2ggPSB2b2lkUkUuZXhlYyhjbS5nZXRMaW5lKGkpKTtcbiAgICAgICAgICAgIGlmICh2b2lkTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICB2b2lkSU4gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IHVuaWZvcm1NYXRjaCA9IHVuaWZvcm1SRS5leGVjKGNtLmdldExpbmUoaSkpO1xuICAgICAgICAgICAgICAgIGlmICh1bmlmb3JtTWF0Y2ggJiYgIWlzQ29tbWVudGVkKGNtLCBpLCB1bmlmb3JtTWF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgI
23459HJldHVybiB1bmlmb3JtTWF0Y2hbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbGV0IGNvbnN0cnVjdE1hdGNoID0gY29uc3RydWN0UkUuZXhlYyhjbS5nZXRMaW5lKGkpKTtcbiAgICAgICAgICAgIGlmIChjb25zdHJ1Y3RNYXRjaCAmJiBjb25zdHJ1Y3RNYXRjaFsxXSAmJiAhaXNDb21tZW50ZWQoY20sIGksIGNvbnN0cnVjdE1hdGNoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb25zdHJ1Y3RNYXRjaFsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJ25vbmUnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2hhZGVyRm9yVHlwZVZhckluTGluZShjbSwgc1R5cGUsIHNWYXJpYWJsZSwgbkxpbmUpIHtcbiAgICBsZXQgZnJhZyA9ICcnO1xuICAgIGxldCBvZmZzZXQgPSAxO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbkxpbmUgKyAxICYmIGkgPCBjbS5nZXREb2MoKS5zaXplOyBpKyspIHtcbiAgICAgICAgaWYgKGNtLmdldExpbmUoaSkpIHtcbiAgICAgICAgICAgIGZyYWcgKz0gY20uZ2V0TGluZShpKSArICdcXG4nO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnJhZyArPSAnXFx0Z2xfRnJhZ0NvbG9yID0gJztcbiAgICBpZiAoc1R5cGUgPT09ICdmbG9hdCcpIHtcbiAgICAgICAgZnJhZyArPSAndmVjNCh2ZWMzKCcgKyBzVmFyaWFibGUgKyAnKSwxLiknO1xuICAgIH1cbiAgICBlbHNlIGlmIChzVHlwZSA9PT0gJ3ZlYzInKSB7XG4gICAgICAgIGZyYWcgKz0gJ3ZlYzQodmVjMygnICsgc1ZhcmlhYmxlICsgJywwLiksMS4pJztcbiAgICB9XG4gICAgZWxzZSBpZiAoc1R5cGUgPT09ICd2ZWMzJykge1xuICAgICAgICBmcmFnICs9ICd2ZWM0KCcgKyBzVmFyaWFibGUgKyAnLDEuKSc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHNUeXBlID09PSAndmVjNCcpIHtcbiAgICAgICAgZnJhZyArPSBzVmFyaWFibGU7XG4gICAgfVxuICAgIGZyYWcgKz0gJztcXG59XFxuJztcblxuICAgIHJldHVybiBmcmFnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVzdWx0UmFuZ2UodGVzdFJlc3VsdHMpIHtcbiAgICBsZXQgbWluTVMgPSAnMTAwMDAwMDAuMCc7XG4gICAgbGV0IG1pbkxpbmUgPSAwO1xuICAgIGxldCBtYXhNUyA9ICcwLjAnO1xuICAgIGxldCBtYXhMaW5lID0gMDtcbiAgICBmb3IgKGxldCBpIGluIHRlc3RSZXN1bHRzKSB7XG4gICAgICAgIGlmICh0ZXN0UmVzdWx0c1tpXS5tcyA8IG1pbk1TKSB7XG4gICAgICAgICAgICBtaW5NUyA9IHRlc3RSZXN1bHRzW2ldLm1zO1xuICAgICAgICAgICAgbWluTGluZSA9IHRlc3RSZXN1bHRzW2ldLmxpbmU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRlc3RSZXN1bHRzW2ldLm1zID4gbWF4TVMpIHtcbiAgICAgICAgICAgIG1heE1TID0gdGVzdFJlc3VsdHNbaV0ubXM7XG4gICAgICAgICAgICBtYXhMaW5lID0gdGVzdFJlc3VsdHNbaV0ubGluZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBtaW46e2xpbmU6IG1pbkxpbmUsIG1zOiBtaW5NU30sIG1heDp7bGluZTogbWF4TGluZSwgbXM6IG1heE1TfSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWVkaWFuKHZhbHVlcykge1xuICAgIHZhbHVlcy5zb3J0KGZ1bmN0aW9uKGEsYikge3JldHVybiBhIC0gYjt9KTtcblxuICAgIHZhciBoYWxmID0gTWF0aC5mbG9vcih2YWx1ZXMubGVuZ3RoIC8gMik7XG5cbiAgICBpZih2YWx1ZXMubGVuZ3RoICUgMikge3JldHVybiB2YWx1ZXNbaGFsZl07fVxuICAgIGVsc2Uge3JldHVybiAodmFsdWVzW2hhbGYgLSAxXSArIHZhbHVlc1toYWxmXSkgLyAyLjA7fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVsdGFTdW0odGVzdFJlc3VsdHMpIHtcbiAgICBsZXQgdG90YWwgPSAwLjA7XG4gICAgZm9yIChsZXQgaSBpbiB0ZXN0UmVzdWx0cykge1xuICAgICAgICBpZiAodGVzdFJlc3VsdHNbaV0uZGVsdGEgPiAwKSB7XG4gICAgICAgICAgICB0b3RhbCArPSB0ZXN0UmVzdWx0c1tpXS5kZWx0YTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdG90YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRIaXRzKHRlc3RSZXN1bHRzKSB7XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBmb3IgKGxldCBpIGluIHRlc3RSZXN1bHRzKSB7XG4gICAgICAgIGlmICh0ZXN0UmVzdWx0c1tpXS5kZWx0YSA+IDApIHtcbiAgICAgICAgICAgIHRvdGFsKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIHNhdmVBcyhibG9iLCBmaWxlbmFtZSkge1xuICAgIGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgIGxpbmsuc2V0QXR0cmlidXRlKFwiZG93bmxvYWRcIiwgZmlsZW5hbWUpO1xuICAgIGxpbmsuc2V0QXR0cmlidXRlKFwiaHJlZlwiLCB1cmwpO1xuICAgIGxpbmsuY2xpY2soKTtcbn0iLCIvKlxuICogT3JpZ2luYWwgY29kZSBmcm9tOiBodHRwczovL3R3aXR0ZXIuY29tL2JsdXJzcGxpbmUgLyBodHRwczovL2dpdGh1Yi5jb20veno4NVxuICogU2VlIHBvc3QgQCBodHRwOi8vd3d3LmxhYjRnYW1lcy5uZXQveno4NS9ibG9nLzIwMTQvMTEvMTUvcmVzaXppbmctbW92aW5nLXNuYXBwaW5nLXdpbmRvd3Mtd2l0aC1qcy1jc3MvXG4gKi9cblxuaW1wb3J0IHsgc3Vic2NyaWJlTWl4aW4gfSBmcm9tICcuL21peGluJztcblxuLy8gVGhyZXNob2xkc1xudmFyIEZVTExTQ1JFRU5fTUFSR0lOUyA9IC0zMDtcbnZhciBNQVJHSU5TID0gMTA7XG5cbmZ1bmN0aW9uIHNldEJvdW5kcyhlbGVtZW50LCB4LCB5LCB3LCBoKSB7XG4gICAgZWxlbWVudC5zdHlsZS5sZWZ0ID0geCArICdweCc7XG4gICAgZWxlbWVudC5zdHlsZS50b3AgPSB5ICsgJ3B4JztcbiAgICBlbGVtZW50LnN0eWxlLndpZHRoID0gdyArICdweCc7XG4gICAgZWxlbWVudC5zdHlsZS5oZWlnaHQgPSBoICsgJ3B4Jztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN1YnNjcmliZUludGVyYWN0aXZlRG9tIChkb20sIG9wdGlvbnMpIHtcbiAgICBzdWJzY3JpYmVNaXhpbihkb20pO1xuXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgb3B0aW9ucy5yZXNpemUgPSBvcHRpb25zLnJlc2l6ZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5yZXNpemUgOiBmYWxzZTtcbiAgICBvcHRpb25zLm1vdmUgPSBvcHRpb25zLm1vdmUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubW92ZSA6IGZhbHNlO1xuICAgIG9wdGlvbnMuc25hcCA9IG9wdGlvbnMuc25hcCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5zbmFwIDogZmFsc2U7XG5cbiAgICAvLyBNaW5pbXVtIHJlc2l6YWJsZSBhcmVhXG4gICAgdmFyIG1pbldpZHRoID0gMTAwO1xuICAgIHZhciBtaW5IZWlnaHQgPSAxMDA7XG5cbiAgICAvLyBFbmQgb2Ygd2hhdCdzIGNvbmZpZ3VyYWJsZS5cbiAgICB2YXIgY2xpY2tlZCA9IG51bGw7XG4gICAgdmFyIG9uUmlnaHRFZGdlLCBvbkJvdHRvbUVkZ2UsIG9uTGVmdEVkZ2UsIG9uVG9wRWRnZTtcblxuICAgI
23459HZhciByaWdodFNjcmVlbkVkZ2UsIGJvdHRvbVNjcmVlbkVkZ2U7XG5cbiAgICB2YXIgcHJlU25hcHBlZDtcblxuICAgIHZhciBiLCB4LCB5O1xuXG4gICAgdmFyIHJlZHJhdyA9IGZhbHNlO1xuXG4gICAgdmFyIGdob3N0ZG9tID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZ2hvc3Rkb20uY2xhc3NOYW1lID0gJ2dob3N0ZG9tJztcblxuICAgIGlmIChvcHRpb25zLnNuYXApIHtcbiAgICAgICAgZG9tLnBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoZ2hvc3Rkb20pO1xuICAgIH1cblxuICAgIC8vIE1vdXNlIGV2ZW50c1xuICAgIGRvbS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbk1vdXNlRG93bik7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3VzZU1vdmUpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbk1vdXNlVXApO1xuXG4gICAgLy8gVG91Y2ggZXZlbnRzXG4gICAgZG9tLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBvblRvdWNoRG93biwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBvblRvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIG9uVG91Y2hFbmQsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG5cbiAgICBmdW5jdGlvbiBoaW50SGlkZSgpIHtcbiAgICAgICAgc2V0Qm91bmRzKGdob3N0ZG9tLCBiLmxlZnQsIGIudG9wLCBiLndpZHRoLCBiLmhlaWdodCk7XG4gICAgICAgIGdob3N0ZG9tLnN0eWxlLm9wYWNpdHkgPSAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uVG91Y2hEb3duIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgaWYgKGV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBvbkRvd24oZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Ub3VjaE1vdmUgKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBpZiAoZXZlbnQudG91Y2hlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIG9uTW92ZShldmVudC5jaGFuZ2VkVG91Y2hlc1swXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblRvdWNoRW5kIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgaWYgKGV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBvblVwKGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uTW91c2VEb3duIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgb25Eb3duKGV2ZW50KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbk1vdXNlTW92ZSAoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIG9uTW92ZShldmVudCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Nb3VzZVVwIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgb25VcChldmVudCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Eb3duIChldmVudCkge1xuICAgICAgICBjYWxjKGV2ZW50KTtcbiAgICAgICAgdmFyIGlzUmVzaXppbmcgPSBvcHRpb25zLnJlc2l6ZSAmJiAob25SaWdodEVkZ2UgfHwgb25Cb3R0b21FZGdlIHx8IG9uVG9wRWRnZSB8fCBvbkxlZnRFZGdlKTtcbiAgICAgICAgY2xpY2tlZCA9IHtcbiAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICB5OiB5LFxuICAgICAgICAgICAgY3g6IGV2ZW50LmNsaWVudFgsXG4gICAgICAgICAgICBjeTogZXZlbnQuY2xpZW50WSxcbiAgICAgICAgICAgIHc6IGIud2lkdGgsXG4gICAgICAgICAgICBoOiBiLmhlaWdodCxcbiAgICAgICAgICAgIGlzUmVzaXppbmc6IGlzUmVzaXppbmcsXG4gICAgICAgICAgICBpc01vdmluZzogIWlzUmVzaXppbmcgJiYgY2FuTW92ZSgpLFxuICAgICAgICAgICAgb25Ub3BFZGdlOiBvblRvcEVkZ2UsXG4gICAgICAgICAgICBvbkxlZnRFZGdlOiBvbkxlZnRFZGdlLFxuICAgICAgICAgICAgb25SaWdodEVkZ2U6IG9uUmlnaHRFZGdlLFxuICAgICAgICAgICAgb25Cb3R0b21FZGdlOiBvbkJvdHRvbUVkZ2VcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYW5Nb3ZlKCkge1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5tb3ZlICYmICh4ID4gMCAmJiB4IDwgYi53aWR0aCAmJi
23459B5ID4gMCAmJiB5IDwgYi5oZWlnaHQpOy8vICYmIHkgPCAzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxjIChldmVudCkge1xuICAgICAgICBiID0gZG9tLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB4ID0gZXZlbnQuY2xpZW50WCAtIGIubGVmdDtcbiAgICAgICAgeSA9IGV2ZW50LmNsaWVudFkgLSBiLnRvcDtcblxuICAgICAgICBvblRvcEVkZ2UgPSB5IDwgTUFSR0lOUztcbiAgICAgICAgb25MZWZ0RWRnZSA9IHggPCBNQVJHSU5TO1xuICAgICAgICBvblJpZ2h0RWRnZSA9IHggPj0gYi53aWR0aCAtIE1BUkdJTlM7XG4gICAgICAgIG9uQm90dG9tRWRnZSA9IHkgPj0gYi5oZWlnaHQgLSBNQVJHSU5TO1xuXG4gICAgICAgIHJpZ2h0U2NyZWVuRWRnZSA9IHdpbmRvdy5pbm5lcldpZHRoIC0gTUFSR0lOUztcbiAgICAgICAgYm90dG9tU2NyZWVuRWRnZSA9IHdpbmRvdy5pbm5lckhlaWdodCAtIE1BUkdJTlM7XG4gICAgfVxuXG4gICAgdmFyIGU7XG5cbiAgICBmdW5jdGlvbiBvbk1vdmUoZXZlbnQpIHtcbiAgICAgICAgY2FsYyhldmVudCk7XG4gICAgICAgIGUgPSBldmVudDtcbiAgICAgICAgcmVkcmF3ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhbmltYXRlKCkge1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYW5pbWF0ZSk7XG5cbiAgICAgICAgaWYgKCFyZWRyYXcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZWRyYXcgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY2xpY2tlZCAmJiBjbGlja2VkLmlzUmVzaXppbmcpIHtcbiAgICAgICAgICAgIGlmIChjbGlja2VkLm9uUmlnaHRFZGdlKSB7XG4gICAgICAgICAgICAgICAgZG9tLnN0eWxlLndpZHRoID0gTWF0aC5tYXgoeCwgbWluV2lkdGgpICsgJ3B4JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbGlja2VkLm9uQm90dG9tRWRnZSkge1xuICAgICAgICAgICAgICAgIGRvbS5zdHlsZS5oZWlnaHQgPSBNYXRoLm1heCh5LCBtaW5IZWlnaHQpICsgJ3B4JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNsaWNrZWQub25MZWZ0RWRnZSkge1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50V2lkdGggPSBNYXRoLm1heChjbGlja2VkLmN4IC0gZS5jbGllbnRYICsgY2xpY2tlZC53LCBtaW5XaWR0aCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRXaWR0aCA+IG1pbldpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbS5zdHlsZS53aWR0aCA9IGN1cnJlbnRXaWR0aCArICdweCc7XG4gICAgICAgICAgICAgICAgICAgIGRvbS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgncmlnaHQnKTtcbiAgICAgICAgICAgICAgICAgICAgZG9tLnN0eWxlLmxlZnQgPSBlLmNsaWVudFggKyAncHgnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNsaWNrZWQub25Ub3BFZGdlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRIZWlnaHQgPSBNYXRoLm1heChjbGlja2VkLmN5IC0gZS5jbGllbnRZICsgY2xpY2tlZC5oLCBtaW5IZWlnaHQpO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50SGVpZ2h0ID4gbWluSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbS5zdHlsZS5oZWlnaHQgPSBjdXJyZW50SGVpZ2h0ICsgJ3B4JztcbiAgICAgICAgICAgICAgICAgICAgZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCdib3R0b20nKTtcbiAgICAgICAgICAgICAgICAgICAgZG9tLnN0eWxlLnRvcCA9IGUuY2xpZW50WSArICdweCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoaW50SGlkZSgpO1xuICAgICAgICAgICAgZG9tLnRyaWdnZXIoJ3Jlc2l6ZScsIHsgZmluaXNoOiBmYWxzZSwgZWw6IGRvbSB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjbGlja2VkICYmIGNsaWNrZWQuaXNNb3ZpbmcpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnNuYXApIHtcbiAgICAgICAgICAgICAgICBpZiAoYi50b3AgPCBGVUxMU0NSRUVOX01BUkdJTlMgfHwgYi5sZWZ0IDwgRlVMTFNDUkVFTl9NQVJHSU5TIHx8IGIucmlnaHQgPiB3aW5kb3cuaW5uZXJXaWR0aCAtIEZVTExTQ1JFRU5fTUFSR0lOUyB8fCBiLmJvdHRvbSA+IHdpbmRvdy5pbm5lckhlaWdodCAtIEZVTExTQ1JFRU5fTUFSR0lOUykge1xuICAgICAgICAgICAgICAgICAgICBzZXRCb3VuZHMoZ2hvc3Rkb20sIDAsIDAsIHdpbmRvdy5pbm5lcldpZHRoLCB3aW5kb3cuaW5uZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBnaG9zdGRvbS5zdHlsZS5vcGFjaXR5ID0gMC4yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChiLnRvcCA8IE1BUkdJTlMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0Qm91bmRzKGdob3N0ZG9tLCAwLCAwLCB3aW5kb3cuaW5uZXJXaWR0aCwgd2luZG93LmlubmVySGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgICAgIGdob3N0ZG9tLnN0eWxlLm9wYWNpdHkgPSAwLjI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGIubGVmdCA8IE1BUkdJTlMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0Qm91bmRzKGdob3N0ZG9tLCAwLCAwLCB3aW5kb3cuaW5uZXJXaWR0aCAvIDIsIHdpbmRvdy5pbm5lckhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGdob3N0ZG9tLnN0eWxlLm9wYWNpdHkgPSAwLjI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGIucmlnaHQgPiByaWdodFNjcmVlbkVkZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0Qm91bmRzKGdob3N0ZG9tLCB3aW5kb3cuaW5uZXJXaWR0aCAvIDIsIDAsIHdpbmRvdy5pbm5lcldpZHRoIC8gMiwgd2luZG93LmlubmVySGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgZ2hvc3Rkb20uc3R5bGUub3BhY2l0eSA9IDAuMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoYi5ib3R0b20gPiBib3R0b21TY3JlZW5FZGdlKSB7XG4gICAgICAgICAgICAgICAgICAgI
23459HNldEJvdW5kcyhnaG9zdGRvbSwgMCwgd2luZG93LmlubmVySGVpZ2h0IC8gMiwgd2luZG93LmlubmVyV2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIC8gMik7XG4gICAgICAgICAgICAgICAgICAgIGdob3N0ZG9tLnN0eWxlLm9wYWNpdHkgPSAwLjI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBoaW50SGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmVTbmFwcGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEJvdW5kcyhkb20sXG4gICAgICAgICAgICAgICAgICAgICAgICBlLmNsaWVudFggLSBwcmVTbmFwcGVkLndpZHRoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuY2xpZW50WSAtIE1hdGgubWluKGNsaWNrZWQueSwgcHJlU25hcHBlZC5oZWlnaHQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlU25hcHBlZC53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZVNuYXBwZWQuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIG1vdmluZ1xuICAgICAgICAgICAgICAgIGRvbS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgncmlnaHQnKTtcbiAgICAgICAgICAgICAgICBkb20uc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2JvdHRvbScpO1xuICAgICAgICAgICAgICAgIGRvbS5zdHlsZS50b3AgPSAoZS5jbGllbnRZIC0gY2xpY2tlZC55KSArICdweCc7XG4gICAgICAgICAgICAgICAgZG9tLnN0eWxlLmxlZnQgPSAoZS5jbGllbnRYIC0gY2xpY2tlZC54KSArICdweCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgeCA9IChlLmNsaWVudFggLSBjbGlja2VkLngpO1xuICAgICAgICAgICAgICAgIGxldCB5ID0gKGUuY2xpZW50WSAtIGNsaWNrZWQueSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoeCA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgeCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHkgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh4ICsgZG9tLm9mZnNldFdpZHRoID4gd2luZG93LmlubmVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgeCA9IHdpbmRvdy5pbm5lcldpZHRoIC0gZG9tLm9mZnNldFdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh5ICsgZG9tLm9mZnNldEhlaWdodCA+IHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB5ID0gd2luZG93LmlubmVySGVpZ2h0IC0gZG9tLm9mZnNldEhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkb20uc3R5bGUucmVtb3ZlUHJvcGVydHkoJ3JpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCdib3R0b20nKTtcbiAgICAgICAgICAgICAgICBkb20uc3R5bGUubGVmdCA9IHggKyAncHgnO1xuICAgICAgICAgICAgICAgIGRvbS5zdHlsZS50b3AgPSB5ICsgJ3B4JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZG9tLnRyaWdnZXIoJ21vdmUnLCB7IGZpbmlzaDogZmFsc2UsIGVsOiBkb20gfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhpcyBjb2RlIGV4ZWN1dGVzIHdoZW4gbW91c2UgbW92ZXMgd2l0aG91dCBjbGlja2luZ1xuXG4gICAgICAgIC8vIHN0eWxlIGN1cnNvclxuICAgICAgICBpZiAob3B0aW9ucy5yZXNpemUgJiYgKG9uUmlnaHRFZGdlICYmIG9uQm90dG9tRWRnZSB8fCBvbkxlZnRFZGdlICYmIG9uVG9wRWRnZSkpIHtcbiAgICAgICAgICAgIGRvbS5zdHlsZS5jdXJzb3IgPSAnbndzZS1yZXNpemUnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9wdGlvbnMucmVzaXplICYmIChvblJpZ2h0RWRnZSAmJiBvblRvcEVkZ2UgfHwgb25Cb3R0b21FZGdlICYmIG9uTGVmdEVkZ2UpKSB7XG4gICAgICAgICAgICBkb20uc3R5bGUuY3Vyc29yID0gJ25lc3ctcmVzaXplJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLnJlc2l6ZSAmJiAob25SaWdodEVkZ2UgfHwgb25MZWZ0RWRnZSkpIHtcbiAgICAgICAgICAgIGRvbS5zdHlsZS5jdXJzb3IgPSAnZXctcmVzaXplJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLnJlc2l6ZSAmJiAob25Cb3R0b21FZGdlIHx8IG9uVG9wRWRnZSkpIHtcbiAgICAgICAgICAgIGRvbS5zdHlsZS5jdXJzb3IgPSAnbnMtcmVzaXplJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjYW5Nb3ZlKCkpIHtcbiAgICAgICAgICAgIGRvbS5zdHlsZS5jdXJzb3IgPSAnbW92ZSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkb20uc3R5bGUuY3Vyc29yID0gJ2RlZmF1bHQnO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFuaW1hdGUoKTtcblxuICAgIGZ1bmN0aW9uIG9uVXAoZSkge1xuICAgICAgICBjYWxjKGUpO1xuXG4gICAgICAgIGlmIChjbGlja2VkICYmIGNsaWNrZWQuaXNSZXNpemluZykge1xuICAgICAgICAgICAgZG9tLnRyaWdnZXIoJ3Jlc2l6ZScsIHsgZmluaXNoOiB0cnVlLCBlbDogZG9tIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc25hcCAmJiBjbGlja2VkICYmIGNsaWNrZWQuaXNNb3ZpbmcpIHtcbiAgICAgICAgICAgIC8vIFNuYXBcbiAgICAgICAgICAgIHZhciBzbmFwcGVkID0ge1xuICAgICAgICAgICAgICAgIHdpZHRoOiBiLndpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogYi5oZWlnaHRcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmIChiLnRvcCA8IEZVTExTQ1JFRU5fTUFSR0lOUyB8fCBiLmxlZnQgPCBGVUxMU0NSRUVOX01BUkdJTlMgfHwgYi5yaWdodCA+IHdpbmRvdy5pbm5lcldpZHRoIC0gRlVMTFNDUkVFTl9NQVJHSU5TIHx8IGIuYm90dG9tID4gd2luZG93LmlubmVySGVpZ2h0IC0gRlVMTFNDUkVFTl9NQVJHSU5TKSB7XG4gICAgICAgICAgICAgICAgc2V0Qm91bmRzKGRvbSwgMCwgMCwgd2luZG93LmlubmVyV2lkdGgsIHdpbmRvdy5pbm5lckhlaWdodCk7XG4gICAgICAgICAgICAgICAgcHJlU25hcHBlZCA9IHNuYXBwZWQ
234597XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChiLnRvcCA8IE1BUkdJTlMpIHtcbiAgICAgICAgICAgICAgICBzZXRCb3VuZHMoZG9tLCAwLCAwLCB3aW5kb3cuaW5uZXJXaWR0aCwgd2luZG93LmlubmVySGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgcHJlU25hcHBlZCA9IHNuYXBwZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChiLmxlZnQgPCBNQVJHSU5TKSB7XG4gICAgICAgICAgICAgICAgc2V0Qm91bmRzKGRvbSwgMCwgMCwgd2luZG93LmlubmVyV2lkdGggLyAyLCB3aW5kb3cuaW5uZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgIHByZVNuYXBwZWQgPSBzbmFwcGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoYi5yaWdodCA+IHJpZ2h0U2NyZWVuRWRnZSkge1xuICAgICAgICAgICAgICAgIHNldEJvdW5kcyhkb20sIHdpbmRvdy5pbm5lcldpZHRoIC8gMiwgMCwgd2luZG93LmlubmVyV2lkdGggLyAyLCB3aW5kb3cuaW5uZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgIHByZVNuYXBwZWQgPSBzbmFwcGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoYi5ib3R0b20gPiBib3R0b21TY3JlZW5FZGdlKSB7XG4gICAgICAgICAgICAgICAgc2V0Qm91bmRzKGRvbSwgMCwgd2luZG93LmlubmVySGVpZ2h0IC8gMiwgd2luZG93LmlubmVyV2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIC8gMik7XG4gICAgICAgICAgICAgICAgcHJlU25hcHBlZCA9IHNuYXBwZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVTbmFwcGVkID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhpbnRIaWRlKCk7XG4gICAgICAgICAgICBkb20udHJpZ2dlcignbW92ZScsIHsgZmluaXNoOiB0cnVlLCBlbDogZG9tIH0pO1xuICAgICAgICAgICAgZG9tLnRyaWdnZXIoJ3Jlc2l6ZScsIHsgZmluaXNoOiB0cnVlLCBlbDogZG9tIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNsaWNrZWQgPSBudWxsO1xuICAgIH1cblxuICAgIGRvbS5zbmFwUmlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzbmFwcGVkID0ge1xuICAgICAgICAgICAgd2lkdGg6IGRvbS53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogZG9tLmhlaWdodFxuICAgICAgICB9O1xuXG4gICAgICAgIHNldEJvdW5kcyhkb20sIHdpbmRvdy5pbm5lcldpZHRoIC8gMiwgMCwgd2luZG93LmlubmVyV2lkdGggLyAyLCB3aW5kb3cuaW5uZXJIZWlnaHQpO1xuICAgICAgICBwcmVTbmFwcGVkID0gc25hcHBlZDtcbiAgICAgICAgLy8gaGludEhpZGUoKTtcbiAgICAgICAgZG9tLnRyaWdnZXIoJ21vdmUnLCB7IGZpbmlzaDogdHJ1ZSwgZWw6IGRvbSB9KTtcbiAgICAgICAgZG9tLnRyaWdnZXIoJ3Jlc2l6ZScsIHsgZmluaXNoOiB0cnVlLCBlbDogZG9tIH0pO1xuICAgIH07XG5cbiAgICByZXR1cm4gZG9tO1xufVxuIiwiLyogZ2xvYmFsIE1lZGlhUmVjb3JkZXJcbkF1dGhvcjogQnJldHQgQ2FtcGVyIChAcHJvZmVzc29ybGVtZXphKVxuVVJMOiBodHRwczovL2dpdGh1Yi5jb20vdGFuZ3JhbXMvdGFuZ3JhbS9ibG9iL21hc3Rlci9zcmMvdXRpbHMvbWVkaWFfY2FwdHVyZS5qc1xuKi9cbmltcG9ydCB7Y3JlYXRlT2JqZWN0VVJMfSBmcm9tICcuL3VybHMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNZWRpYUNhcHR1cmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnF1ZXVlU2NyZWVuc2hvdCA9IG51bGw7XG4gICAgICAgIHRoaXMudmlkZW9DYXB0dXJlID0gbnVsbDtcbiAgICB9XG5cbiAgICBzZXRDYW52YXMgKGNhbnZhcykge1xuICAgICAgICB0aGlzLmNhbnZhcyA9IGNhbnZhcztcbiAgICB9XG5cbiAgICAvLyBUYWtlIGEgc2NyZWVuc2hvdCwgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBzY3JlZW5zaG90IGRhdGEgd2hlbiBhdmFpbGFibGVcbiAgICBzY3JlZW5zaG90ICgpIHtcbiAgICAgICAgaWYgKHRoaXMucXVldWVTY3JlZW5zaG90ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnF1ZXVlU2NyZWVuc2hvdC5wcm9taXNlOyAvLyBvbmx5IGNhcHR1cmUgb25lIHNjcmVlbnNob3QgYXQgYSB0aW1lXG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaWxsIHJlc29sdmUgb25jZSByZW5kZXJpbmcgaXMgY29tcGxldGUgYW5kIHJlbmRlciBidWZmZXIgaXMgY2FwdHVyZWRcbiAgICAgICAgdGhpcy5xdWV1ZVNjcmVlbnNob3QgPSB7fTtcbiAgICAgICAgdGhpcy5xdWV1ZVNjcmVlbnNob3QucHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucXVldWVTY3JlZW5zaG90LnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgdGhpcy5xdWV1ZVNjcmVlbnNob3QucmVqZWN0ID0gcmVqZWN0O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVldWVTY3JlZW5zaG90LnByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gQ2FsbGVkIGFmdGVyIHJlbmRlcmluZywgY2FwdHVyZXMgcmVuZGVyIGJ1ZmZlciBhbmQgcmVzb2x2ZXMgcHJvbWlzZSB3aXRoIHRoZSBpbWFnZSBkYXRhXG4gICAgY29tcGxldGVTY3JlZW5zaG90ICgpIHtcbiAgICAgICAgaWYgKHRoaXMucXVldWVTY3JlZW5zaG90ICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEdldCBkYXRhIFVSTCwgY29udmVydCB0byBibG9iXG4gICAgICAgICAgICAvLyBTdHJpcCBob3N0L21pbWV0eXBlL2V0Yy4sIGNvbnZlcnQgYmFzZTY0IHRvIGJpbmFyeSB3aXRob3V0IFVURi04IG1hbmdsaW5nXG4gICAgICAgICAgICAvLyBBZGFwdGVkIGZyb206IGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3VuY29uZWQvNDM3MDgyMlxuICAgICAgICAgICAgY29uc3QgdXJsID0gdGhpcy5jYW52YXMudG9EYXRhVVJMKCdpbWFnZS9wbmcnKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBhdG9iKHVybC5zbGljZSgyMikpO1xuICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgYnVmZmVyW2ldID0gZGF0YS5jaGFyQ29kZUF0KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtidWZmZXJdLCB7IHR5cGU6ICdpbWFnZS9wbmcnIH0pO1xuXG4gICAgICAgICAgICAvLyBSZXNvbHZlIHdpdGggc2NyZWVuc2hvdCBkYXRhXG4gICAgICAgICAgICB0aGlzLnF1ZXVlU2NyZWVuc2hvdC5yZXNvbHZlKHsgdXJsLCBibG9iLCB0eXBlOiAncG5nJyB9KTtcbiAgICAgICAgICAgI
23459HRoaXMucXVldWVTY3JlZW5zaG90ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFN0YXJ0cyBjYXB0dXJpbmcgYSB2aWRlbyBzdHJlYW0gZnJvbSB0aGUgY2FudmFzXG4gICAgc3RhcnRWaWRlb0NhcHR1cmUgKCkge1xuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5NZWRpYVJlY29yZGVyICE9PSAnZnVuY3Rpb24nIHx8ICF0aGlzLmNhbnZhcyB8fCB0eXBlb2YgdGhpcy5jYW52YXMuY2FwdHVyZVN0cmVhbSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ3dhcm46IFZpZGVvIGNhcHR1cmUgKENhbnZhcy5jYXB0dXJlU3RyZWFtIGFuZC9vciBNZWRpYVJlY29yZGVyIEFQSXMpIG5vdCBzdXBwb3J0ZWQgYnkgYnJvd3NlcicpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudmlkZW9DYXB0dXJlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnd2FybjogVmlkZW8gY2FwdHVyZSBhbHJlYWR5IGluIHByb2dyZXNzLCBjYWxsIFNjZW5lLnN0b3BWaWRlb0NhcHR1cmUoKSBmaXJzdCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RhcnQgYSBuZXcgY2FwdHVyZVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGNhcCA9IHRoaXMudmlkZW9DYXB0dXJlID0ge307XG4gICAgICAgICAgICBjYXAuY2h1bmtzID0gW107XG4gICAgICAgICAgICBjYXAuc3RyZWFtID0gdGhpcy5jYW52YXMuY2FwdHVyZVN0cmVhbSgpO1xuICAgICAgICAgICAgY2FwLm9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibScgfTsgLy8gVE9ETzogc3VwcG9ydCBvdGhlciBmb3JtYXQgb3B0aW9uc1xuICAgICAgICAgICAgY2FwLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcihjYXAuc3RyZWFtLCBjYXAub3B0aW9ucyk7XG4gICAgICAgICAgICBjYXAubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQuZGF0YS5zaXplID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjYXAuY2h1bmtzLnB1c2goZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gU3RvcHBlZCByZWNvcmRpbmc/IENyZWF0ZSB0aGUgZmluYWwgY2FwdHVyZSBmaWxlIGJsb2JcbiAgICAgICAgICAgICAgICBpZiAoY2FwLnJlc29sdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGJsb2IgPSBuZXcgQmxvYihjYXAuY2h1bmtzLCB7IHR5cGU6IGNhcC5vcHRpb25zLm1pbWVUeXBlIH0pO1xuICAgICAgICAgICAgICAgICAgICBsZXQgdXJsID0gY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEV4cGxpY2l0bHkgcmVtb3ZlIGFsbCBzdHJlYW0gdHJhY2tzLCBhbmQgc2V0IG9iamVjdHMgdG8gbnVsbFxuICAgICAgICAgICAgICAgICAgICBpZiAoY2FwLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRyYWNrcyA9IGNhcC5zdHJlYW0uZ2V0VHJhY2tzKCkgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFja3MuZm9yRWFjaCh0cmFjayA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcC5zdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FwLnN0cmVhbSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGNhcC5tZWRpYVJlY29yZGVyID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52aWRlb0NhcHR1cmUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhcC5yZXNvbHZlKHsgdXJsLCBibG9iLCB0eXBlOiAnd2VibScgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNhcC5tZWRpYVJlY29yZGVyLnN0YXJ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRoaXMudmlkZW9DYXB0dXJlID0gbnVsbDtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvcjogU2NlbmUgdmlkZW8gY2FwdHVyZSBmYWlsZWQnLCBlKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBTdG9wcyBjYXB0dXJpbmcgYSB2aWRlbyBzdHJlYW0gZnJvbSB0aGUgY2FudmFzLCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHZpZGVvIHdoZW4gYXZhaWxhYmxlXG4gICAgc3RvcFZpZGVvQ2FwdHVyZSAoKSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0NhcHR1cmUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCd3YXJuOiBObyBzY2VuZSB2aWRlbyBjYXB0dXJlIGluIHByb2dyZXNzLCBjYWxsIFNjZW5lLnN0YXJ0VmlkZW9DYXB0dXJlKCkgZmlyc3QnKTtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvbWlzZSB0aGF0IHdpbGwgcmVzb2x2ZSB3aGVuIGZpbmFsIHN0cmVhbSBpcyBhdmFpbGFibGVcbiAgICAgICAgdGhpcy52aWRlb0NhcHR1cmUucHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMudmlkZW9DYXB0dXJlLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgdGhpcy52aWRlb0NhcHR1cmUucmVqZWN0ID0gcmVqZWN0O1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdG9wIHJlY29yZGluZ1xuICAgICAgICB0aGlzLnZpZGVvQ2FwdHVyZS5tZWRpYVJlY29yZGVyLnN0b3AoKTtcblxuICAgICAgICByZXR1cm4gdGhpcy52aWRlb0NhcHR1cmUucHJvbWlzZTtcbiAgICB9XG59XG4iLCIvKlxuQWRkIGV2ZW50cyB0byBhIGNsYXNzIG9yIG9iamVjdDpcbiAgICBjbGFzcyBNeUNsYXNzIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICBzdWJzY3JpYmVNaXhpbih0aGlzKTsgLy8gQWRkIHRoZSBtaXhpbmcgZnVuY3Rpb25zIHRvIHRoZSBjbGFzc1xuICAgICAgICAgICAgLi4uXG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoJ3NvbWV0aGluZycsIHsgb3duZXI6IHRoaXMsIGNvbnRlbnQ6ICd0aGF0J30pOyAvLyB0cmlnZ2VyIGFuIGV2ZW50IHBhc3Npbmcgc29tZSBhcmd1bWVudHNcblxuU3Vic2NyaWJlIHRvIGV2ZW50cyBieSBkb2luZzpcbiAgICBteUNsYXNzLm9uKCdzb21ldGhpbmcnLCAoYXJncykgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhhcmdzKTtcbiAgICB9KTtcblxuVW5zdWJzY3JpYmUgdG8gZXZlbnRzIGJ5IGRvaW5nOlxuICAgIG15Q2xhc3Mub2ZmKCdzb21ldGhpbmcnKTtcblxub3IgbW9yZSBwcmVzaWNlbGx5OlxuICAgIG15Q2xhc3Mub2ZmKCdzb21ldGhpbmcnLCAoYXJncykgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhhcmdzKTtcbiAgICB9KTtcblxuVW5zdWJzY3JpYmUgdG8gYWxsIGV2ZW50cyBieTpcbiAgICBteUNsYXNzLm9mZkFsbCgpO1xuKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHN1YnNjcmliZU1peGluICh0YXJnZXQpIHtcbiAgICB2YXIgbGlzdGVuZXJzID0gbmV3IFNldCgpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24odGFyZ2V0LCB7XG5cbiAgICAgICAgb24gKHR5cGUsIGYpIHtcbiAgICAgICAgICAgIGxldCBsaXN0ZW5lciA9IHt9O1xuICAgICAgICAgICAgbGlzdGVuZXJbdHlwZV0gPSBmO1xuICAgICAgICAgICAgbGlzdGVuZXJzLmFkZChsaXN0ZW5lcik7XG4gICAgICAgI
23459H0sXG5cbiAgICAgICAgb2ZmICh0eXBlLCBmKSB7XG4gICAgICAgICAgICBpZiAoZikge1xuICAgICAgICAgICAgICAgIGxldCBsaXN0ZW5lciA9IHt9O1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyW3R5cGVdID0gZjtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGl0ZW0gb2YgbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhpdGVtKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVycy5kZWxldGUoaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIG9mZkFsbCAoKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMuY2xlYXIoKTtcbiAgICAgICAgfSxcblxuICAgICAgICB0cmlnZ2VyIChldmVudCwgLi4uZGF0YSkge1xuICAgICAgICAgICAgZm9yICh2YXIgbGlzdGVuZXIgb2YgbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcltldmVudF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJbZXZlbnRdKC4uLmRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBsaXN0U3Vic2NyaXB0aW9ucyAoKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpdGVtIG9mIGxpc3RlbmVycykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG4iLCJsZXQgX2NyZWF0ZU9iamVjdFVSTDtcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPYmplY3RVUkwgKHVybCkge1xuICAgIGlmIChfY3JlYXRlT2JqZWN0VVJMID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgX2NyZWF0ZU9iamVjdFVSTCA9ICh3aW5kb3cuVVJMICYmIHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKSB8fCAod2luZG93LndlYmtpdFVSTCAmJiB3aW5kb3cud2Via2l0VVJMLmNyZWF0ZU9iamVjdFVSTCk7XG4gICAgICAgIGlmICh0eXBlb2YgX2NyZWF0ZU9iamVjdFVSTCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgX2NyZWF0ZU9iamVjdFVSTCA9IG51bGw7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwgKG9yIHZlbmRvciBwcmVmaXgpIG5vdCBmb3VuZCwgdW5hYmxlIHRvIGNyZWF0ZSBsb2NhbCBibG9iIFVSTHMnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChfY3JlYXRlT2JqZWN0VVJMKSB7XG4gICAgICAgIHJldHVybiBfY3JlYXRlT2JqZWN0VVJMKHVybCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gdXJsO1xuICAgIH1cbn1cbiIsImV4cG9ydCBkZWZhdWx0IGNsYXNzIEVycm9yc0Rpc3BsYXkge1xuICAgIGNvbnN0cnVjdG9yKG1haW4pIHtcbiAgICAgICAgdGhpcy5tYWluID0gbWFpbjtcblxuICAgICAgICAvLyAgcHJpdmF0ZSB2YXJpYWJsZXNcbiAgICAgICAgdGhpcy53aWRnZXRzID0gW107XG5cbiAgICAgICAgLy8gRVZFTlRTXG4gICAgICAgIHRoaXMubWFpbi5zaGFkZXIuY2FudmFzLm9uKCdlcnJvcicsIChhcmcpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1haW4udmlzdWFsRGVidWdnZXIgJiYgdGhpcy5tYWluLnZpc3VhbERlYnVnZ2VyLnRlc3RpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFuKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRFcnJvcihhcmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLm1haW4uZWRpdG9yLm9uKCdjaGFuZ2VzJywgKGNtLCBjaGFuZ2VzT2JqcykgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMubWFpbi5zaGFkZXIuY2FudmFzLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNsZWFuKCkge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMud2lkZ2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5tYWluLmVkaXRvci5yZW1vdmVMaW5lV2lkZ2V0KHRoaXMud2lkZ2V0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53aWRnZXRzLmxlbmd0aCA9IDA7XG4gICAgfVxuXG4gICAgYWRkRXJyb3IoYXJncykge1xuICAgICAgICBsZXQgcmUgPSAvRVJST1I6XFxzK1xcZCs6KFxcZCspOlxccysoJy4qKS9nO1xuICAgICAgICBsZXQgbWF0Y2hlcyA9IHJlLmV4ZWMoYXJncy5lcnJvcik7XG4gICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICBsZXQgbnVtTGluZXMgPSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMubWFpbi5vcHRpb25zLmZyYWdfaGVhZGVyLmxlbmd0aCA+IDApXG4gICAgICAgICAgICAgICAgbnVtTGluZXMgKz0gKHRoaXMubWFpbi5vcHRpb25zLmZyYWdfaGVhZGVyLm1hdGNoKC9cXHI/XFxuL2cpIHx8ICcnKS5sZW5ndGg7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGxldCBsaW5lID0gcGFyc2VJbnQobWF0Y2hlc1sxXSkgLSBudW1MaW5lcztcbiAgICAgICAgICAgIGxldCBlciA9IG1hdGNoZXNbMl07XG4gICAgICAgICAgICBsZXQgbXNnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgICAgICAgIGxldCBpY29uID0gbXNnLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSk7XG4gICAgICAgICAgICBpY29uLmNsYXNzTmFtZSA9ICdnZS1lcnJvci1pY29uJztcbiAgICAgICAgICAgIGljb24uaW5uZXJIVE1MID0gJ3gnO1xuICAgICAgICAgICAgbXNnLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGVyKSk7XG4gICAgICAgICAgICBtc2cuY2xhc3NOYW1lID0gJ2dlLWVycm9yJztcbiAgICAgICAgICAgI
23459HRoaXMud2lkZ2V0cy5wdXNoKHRoaXMubWFpbi5lZGl0b3IuYWRkTGluZVdpZGdldChsaW5lLCBtc2cpKTsvLywgeyBjb3Zlckd1dHRlcjogZmFsc2UsIG5vSFNjcm9sbDogdHJ1ZSB9KSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgRXhwb3J0TW9kYWwgZnJvbSAnLi9tb2RhbHMvRXhwb3J0TW9kYWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFeHBvcnRJY29uIHtcbiAgICBjb25zdHJ1Y3RvciAobWFpbikge1xuICAgICAgICB0aGlzLm1haW4gPSBtYWluO1xuXG4gICAgICAgIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5lbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2dlX2V4cG9ydF9pY29uJyk7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gJ+KWsyc7XG4gICAgICAgIC8vIHRoaXMuZWwuaW5uZXJIVE1MID0gJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5tb3JlX3ZlcnQ8L2k+JztcbiAgICAgICAgdGhpcy5lbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKG1haW4uY2hhbmdlIHx8ICF0aGlzLm1vZGFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tb2RhbCA9IG5ldyBFeHBvcnRNb2RhbCgnZ2VfZXhwb3J0JywgeyBtYWluOiBtYWluIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tb2RhbC5wcmVzZW50TW9kYWwoZXZlbnQudGFyZ2V0Lm9mZnNldExlZnQsIGV2ZW50LnRhcmdldC5vZmZzZXRUb3ApO1xuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICB0aGlzLm1haW4uY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuZWwpO1xuICAgIH1cbn1cbiIsImltcG9ydCBDb2xvclBpY2tlciBmcm9tICcuL3BpY2tlcnMvQ29sb3JQaWNrZXInO1xuaW1wb3J0IFZlYzNQaWNrZXIgZnJvbSAnLi9waWNrZXJzL1ZlYzNQaWNrZXInO1xuaW1wb3J0IFZlYzJQaWNrZXIgZnJvbSAnLi9waWNrZXJzL1ZlYzJQaWNrZXInO1xuaW1wb3J0IEZsb2F0UGlja2VyIGZyb20gJy4vcGlja2Vycy9GbG9hdFBpY2tlcic7XG5cbmltcG9ydCBDb2xvciBmcm9tICcuL3BpY2tlcnMvdHlwZXMvQ29sb3InO1xuXG5pbXBvcnQgTW9kYWwgZnJvbSAnLi9tb2RhbHMvTW9kYWwnO1xuXG4vLyBSZXR1cm4gYWxsIHBhdHRlcm4gbWF0Y2hlcyB3aXRoIGNhcHR1cmVkIGdyb3Vwc1xuUmVnRXhwLnByb3RvdHlwZS5leGVjQWxsID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgbGV0IG1hdGNoID0gbnVsbDtcbiAgICBsZXQgbWF0Y2hlcyA9IFtdO1xuICAgIHdoaWxlIChtYXRjaCA9IHRoaXMuZXhlYyhzdHJpbmcpKSB7XG4gICAgICAgIGxldCBtYXRjaEFycmF
234595ID0gW107XG4gICAgICAgIGZvciAobGV0IGkgaW4gbWF0Y2gpIHtcbiAgICAgICAgICAgIGlmIChwYXJzZUludChpKSA9PSBpKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hBcnJheS5wdXNoKG1hdGNoW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtYXRjaEFycmF5LmluZGV4ID0gbWF0Y2guaW5kZXg7XG4gICAgICAgIG1hdGNoZXMucHVzaChtYXRjaEFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoZXM7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIZWxwZXJzIHtcbiAgICBjb25zdHJ1Y3RvciAobWFpbikge1xuICAgICAgICB0aGlzLm1haW4gPSBtYWluO1xuICAgICAgICB0aGlzLm1haW4uZGVidWdnaW5nID0gZmFsc2U7XG5cbiAgICAgICAgbGV0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUobWFpbi5lZGl0b3IuZ2V0V3JhcHBlckVsZW1lbnQoKSwgbnVsbCk7XG4gICAgICAgIGxldCBiZ0NvbG9yID0gbmV3IENvbG9yKHN0eWxlLmJhY2tncm91bmQgIT09ICcnID8gc3R5bGUuYmFja2dyb3VuZCA6IHN0eWxlLmJhY2tncm91bmRDb2xvcik7XG4gICAgICAgIGxldCBmZ0NvbG9yID0gbmV3IENvbG9yKHN0eWxlLmNvbG9yKTtcblxuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICBiZ0NvbG9yOiBiZ0NvbG9yLmdldFN0cmluZygncmdiJyksXG4gICAgICAgICAgICBmbkNvbG9yOiBmZ0NvbG9yLmdldFN0cmluZygncmdiJyksXG4gICAgICAgICAgICBkaW1Db2xvcjogJ3JnYigxMjcsIDEyNywgMTI3KScsXG4gICAgICAgICAgICBzZWxDb2xvcjogJ3JnYig0MCwgMTY4LCAxMDcpJyxcbiAgICAgICAgICAgIGxpbmtCdXR0b246IHRydWVcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBFVkVOVFNcbiAgICAgICAgbGV0IHdyYXBwZXIgPSB0aGlzLm1haW4uZWRpdG9yLmdldFdyYXBwZXJFbGVtZW50KCk7XG4gICAgICAgIHdyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGxldCBjdXJzb3IgPSB0aGlzLm1haW4uZWRpdG9yLmdldEN1cnNvcih0cnVlKTtcbiAgICAgICAgICAgIGxldCB0b2tlbiA9IHRoaXMubWFpbi5lZGl0b3IuZ2V0VG9rZW5BdChjdXJzb3IpO1xuICAgICAgICAgICAgaWYgKHRva2VuLnR5cGUgPT09ICd2YXJpYWJsZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW4udmlzdWFsRGVidWdnZXIuZGVidWcodG9rZW4uc3RyaW5nLCBjdXJzb3IubGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW4udXBkYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHdyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgLy8gYmFpbCBvdXQgaWYgd2Ugd2VyZSBkb2luZyBhIHNlbGVjdGlvbiBhbmQgbm90IGEgY2xpY2tcbiAgICAgICAgICAgIGlmICh0aGlzLm1haW4uZWRpdG9yLnNvbWV0aGluZ1NlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjdXJzb3IgPSB0aGlzLm1haW4uZWRpdG9yLmdldEN1cnNvcih0cnVlKTtcblxuICAgICAgICAgICAgLy8gc2VlIGlmIHRoZXJlIGlzIGEgbWF0Y2ggb24gdGhlIGN1cnNvciBjbGlja1xuICAgICAgICAgICAgbGV0IG1hdGNoID0gdGhpcy5nZXRNYXRjaChjdXJzb3IpO1xuICAgICAgICAgICAgbGV0IHRva2VuID0gdGhpcy5tYWluLmVkaXRvci5nZXRUb2tlbkF0KGN1cnNvcik7XG4gICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW4udmlzdWFsRGVidWdnZXIuY2xlYW4oZXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMubWFpbi51cGRhdGUoKTtcblxuICAgICAgICAgICAgICAgIC8vIFRvZ2dsZXMgdGhlIHRyYWNrcGFkIHRvIGJlIG9mZiBpZiBpdCdzIGFscmVhZHkgcHJlc2VudC5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5hY3RpdmVNb2RhbCAmJiB0aGlzLmFjdGl2ZU1vZGFsLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsLnJlbW92ZU1vZGFsKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gudHlwZSA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsID0gbmV3IENvbG9yUGlja2VyKG1hdGNoLnN0cmluZywgdGhpcy5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5zaG93QXQodGhpcy5tYWluLmVkaXRvcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlTW9kYWwub24oJ2NoYW5nZWQnLCAoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBuZXdDb2xvciA9IGNvbG9yLmdldFN0cmluZygndmVjJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogbWF0Y2guc3RhcnQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmQgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogbWF0Y2guZW5kIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaC5lbmQgPSBtYXRjaC5zdGFydCArIG5ld0NvbG9yLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWFpbi5lZGl0b3IucmVwbGFjZVJhbmdlKG5ld0NvbG9yLCBzdGFydCwgZW5kLCBgKyR7bWF0Y2gudHlwZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5vbignbGlua0J1dHRvbicsIChjb2xvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbCA9IG5ldyBWZWMzUGlja2VyKGNvbG9yLmdldFN0cmluZygndmVjJyksIHRoaXMucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsLnNob3dBdCh0aGlzLm1haW4uZWRpdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgI
23459HRoaXMuYWN0aXZlTW9kYWwub24oJ2NoYW5nZWQnLCAoZGlyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG5ld0RpciA9IGRpci5nZXRTdHJpbmcoJ3ZlYzMnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogbWF0Y2guc3RhcnQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZW5kID0geyBsaW5lOiBjdXJzb3IubGluZSwgY2g6IG1hdGNoLmVuZCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLmVuZCA9IG1hdGNoLnN0YXJ0ICsgbmV3RGlyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1haW4uZWRpdG9yLnJlcGxhY2VSYW5nZShuZXdEaXIsIHN0YXJ0LCBlbmQsIGArJHttYXRjaC50eXBlfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gudHlwZSA9PT0gJ3ZlYzMnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlTW9kYWwgPSBuZXcgVmVjM1BpY2tlcihtYXRjaC5zdHJpbmcsIHRoaXMucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlTW9kYWwuc2hvd0F0KHRoaXMubWFpbi5lZGl0b3IpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsLm9uKCdjaGFuZ2VkJywgKGRpcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG5ld0RpciA9IGRpci5nZXRTdHJpbmcoJ3ZlYzMnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydCA9IHsgbGluZTogY3Vyc29yLmxpbmUsIGNoOiBtYXRjaC5zdGFydCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVuZCA9IHsgbGluZTogY3Vyc29yLmxpbmUsIGNoOiBtYXRjaC5lbmQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLmVuZCA9IG1hdGNoLnN0YXJ0ICsgbmV3RGlyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWFpbi5lZGl0b3IucmVwbGFjZVJhbmdlKG5ld0Rpciwgc3RhcnQsIGVuZCwgYCske21hdGNoLnR5cGV9YCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChtYXRjaC50eXBlID09PSAndmVjMicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbCA9IG5ldyBWZWMyUGlja2VyKG1hdGNoLnN0cmluZywgdGhpcy5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5zaG93QXQodGhpcy5tYWluLmVkaXRvcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlTW9kYWwub24oJ2NoYW5nZWQnLCAocG9zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmV3cG9zID0gcG9zLmdldFN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0ID0geyBsaW5lOiBjdXJzb3IubGluZSwgY2g6IG1hdGNoLnN0YXJ0IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZW5kID0geyBsaW5lOiBjdXJzb3IubGluZSwgY2g6IG1hdGNoLmVuZCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2guZW5kID0gbWF0Y2guc3RhcnQgKyBuZXdwb3MubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWluLmVkaXRvci5yZXBsYWNlUmFuZ2UobmV3cG9zLCBzdGFydCwgZW5kLCBgKyR7bWF0Y2gudHlwZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1hdGNoLnR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlTW9kYWwgPSBuZXcgRmxvYXRQaWNrZXIobWF0Y2guc3RyaW5nLCB0aGlzLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsLnNob3dBdCh0aGlzLm1haW4uZWRpdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5vbignY2hhbmdlZCcsIChudW1iZXIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBuZXdOdW1iZXIgPSBudW1iZXIuZ2V0U3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogbWF0Y2guc3RhcnQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmQgPSB7IGxpbmU6IGN1cnNvci5saW5lLCBjaDogbWF0Y2guZW5kIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaC5lbmQgPSBtYXRjaC5zdGFydCArIG5ld051bWJlci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1haW4uZWRpdG9yLnJlcGxhY2VSYW5nZShuZXdOdW1iZXIsIHN0YXJ0LCBlbmQsIGArJHttYXRjaC50eXBlfWApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLm1haW4ub3B0aW9ucy50b29sdGlwcyAmJiAodG9rZW4udHlwZSA9PT0gJ2J1aWx0aW4nIHx8IHRva2VuLnR5cGUgPT09ICd2YXJpYWJsZS0zJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW4udmlzdWFsRGVidWdnZXIuY2xlYW4oZXZlbnQpO1xuICAgICAgICAgICAgICAgIGxldCBodG1sID0gJzxwPkxlYXJuIG1vcmUgYWJvdXQ6IDxhIGhyZWY9XCJodHRwczovL3RoZWJvb2tvZnNoYWRlcnMuY29tL2dsb3NzYXJ5Lz9zZWFyY2g9JyArIHRva2VuLnN0cmluZyArICdcIiB0YXJnZXQ9XCJfYmxhbmtcIj4nICsgdG9rZW4uc3RyaW5nICsgJzwvYT48L3A+JztcbiAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsID0gbmV3IE1vZGFsKCdnZV90b29sdGlwJywgeyBpbm5lckhUTUw6IGh0bWwgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5zaG93QXQodGhpcy5tYWluLmVkaXRvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0b2tlbi50eXBlID09PSAndmFyaWFibGUnKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWFpbi52aXN1YWxEZWJ1Z2dlcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1haW4udmlzdWFsRGVidWdnZXIuY2xlYW4oZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1haW4udmlzdWFsRGVidWdnZXIuaWx1bWluYXRlKHRva2VuLnN0cmluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRNYXRjaCAoY3Vyc29yKSB7XG4gICAgICAgIGxldCB0eXBlcyA9IFsnY29sb3InLCAndmVjMycgLCd2ZWMyJywgJ251bWJlciddO1xuICAgICAgICBsZXQgcnRhO1xuICAgICAgICBmb3IgKGxldCBpIGluIHR5cGVzKSB7XG4gICAgICAgICAgICBydGEgPSB0aGlzLmdldFR5cGVNYXRjaChjdXJzb3IsIHR5cGVzW2ldKTtcbiAgICAgICAgICAgIGlmIChydGEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcnRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgI
23459HJldHVybjtcbiAgICB9XG5cbiAgICBnZXRUeXBlTWF0Y2ggKGN1cnNvciwgdHlwZSkge1xuICAgICAgICBpZiAoIXR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmU7XG4gICAgICAgIHN3aXRjaCh0eXBlLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgIGNhc2UgJ2NvbG9yJzpcbiAgICAgICAgICAgICAgICByZSA9IC92ZWNbM3w0XVxcKFtcXGR8LnwsXFxzXSpcXCkvZztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3ZlYzMnOlxuICAgICAgICAgICAgICAgIHJlID0gL3ZlYzNcXChbLXxcXGR8LnwsXFxzXSpcXCkvZztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3ZlYzInOlxuICAgICAgICAgICAgICAgIHJlID0gL3ZlYzJcXChbLXxcXGR8LnwsXFxzXSpcXCkvZztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICAgICAgICAgICAgcmUgPSAvWy1dP1xcZCtcXC5cXGQrfFxcZCtcXC58XFwuXFxkKy9nO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdpbnZhbGlkIG1hdGNoIHNlbGVjdGlvbicpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbGluZSA9IHRoaXMubWFpbi5lZGl0b3IuZ2V0TGluZShjdXJzb3IubGluZSk7XG4gICAgICAgIGxldCBtYXRjaGVzID0gcmUuZXhlY0FsbChsaW5lKTtcblxuICAgICAgICBpZiAobWF0Y2hlcykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXRjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbCA9IG1hdGNoZXNbaV1bMF07XG4gICAgICAgICAgICAgICAgbGV0IGxlbiA9IHZhbC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0ID0gbWF0Y2hlc1tpXS5pbmRleDtcbiAgICAgICAgICAgICAgICBsZXQgZW5kID0gbWF0Y2hlc1tpXS5pbmRleCArIGxlbjtcbiAgICAgICAgICAgICAgICBpZiAoY3Vyc29yLmNoID49IHN0YXJ0ICYmIGN1cnNvci5jaCA8PSBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGVuZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZzogdmFsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG59XG4iLCJpbXBvcnQgTWVudUl0ZW0gZnJvbSAnLi9NZW51SXRlbSc7XG5pbXBvcnQgRXhwb3J0TW9kYWwgZnJvbSAnLi9tb2RhbHMvRXhwb3J0TW9kYWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNZW51IHtcbiAgICBjb25zdHJ1Y3RvciAobWFpbikge1xuICAgICAgICB0aGlzLm1haW4gPSBtYWluO1xuICAgICAgICB0aGlzLm1lbnVzID0ge307XG5cbiAgICAgICAgLy8gQ1JFQVRFIE1FTlUgQ29udGFpbmVyXG4gICAgICAgIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd1bCcpO1xuICAgICAgICB0aGlzLmVsLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnZ2VfbWVudV9iYXInKTtcblxuICAgICAgICAvLyBORVdcbiAgICAgICAgdGhpcy5tZW51cy5uZXcgPSBuZXcgTWVudUl0ZW0odGhpcy5lbCwgJ2dlX21lbnUnLCAnPGkgY2xhc3M9XCJtYXRlcmlhbC1pY29uc1wiPmFkZDwvaT4gTmV3JywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBtYWluLm5ldygpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBPUEVOXG4gICAgICAgIHRoaXMuZmlsZUlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcbiAgICAgICAgdGhpcy5maWxlSW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2ZpbGUnKTtcbiAgICAgICAgdGhpcy5maWxlSW5wdXQuc2V0QXR0cmlidXRlKCdhY2NlcHQnLCAndGV4dC94LXlhbWwnKTtcbiAgICAgICAgdGhpcy5maWxlSW5wdXQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgdGhpcy5maWxlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBtYWluLm9wZW4oZXZlbnQudGFyZ2V0LmZpbGVzWzBdKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubWVudXMub3BlbiA9IG5ldyBNZW51SXRlbSh0aGlzLmVsLCAnZ2VfbWVudScsICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+Zm9sZGVyX29wZW48L2k+ICBPcGVuJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmZpbGVJbnB1dC5jbGljaygpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyB0aGlzLm1lbnVzLmF1dG91cGRhdGUuYnV0dG9uLnN0eWxlLmNvbG9yID0gbWFpbi5hdXRvdXBkYXRlID8gJ3doaXRlJyA6ICdncmF5JztcblxuICAgICAgICAvLyBURVNUXG4gICAgICAgIHRoaXMubWVudXMudGVzdCA9IG5ldyBNZW51SXRlbSh0aGlzLmVsLCAnZ2VfbWVudScsICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+dGltZWxpbmU8L2k+IFRlc3QnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIG1haW4udmlzdWFsRGVidWdnZXIuY2hlY2soKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU0hBUkVcbiAgICAgICAgdGhpcy5tZW51cy5zaGFyZSA9IG5ldyBNZW51SXRlbSh0aGlzLmVsLCAnZ2VfbWVudScsICc8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCI+YXJyb3dfdXB3YXJkPC9pPiBFeHBvcnQnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChtYWluLmNoYW5nZSB8fCAhdGhpcy5leHBvcnRNb2RhbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwb3J0TW9kYWwgPSBuZXcgRXhwb3J0TW9kYWwoJ2dlX2V4cG9ydCcsIHsgbWFpbjogbWFpbiwgcG9zaXRpb246ICdmaXhlZCcgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBiYm94ID0gdGhpcy5tZW51cy5zaGFyZS5lbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgI
23459HRoaXMuZXhwb3J0TW9kYWwucHJlc2VudE1vZGFsKGJib3gubGVmdCAtIDUsIGJib3gudG9wICsgYmJveC5oZWlnaHQgKyA1KTtcbiAgICAgICAgfSk7XG5cblxuICAgICAgICAvLyBBVVRPVVBEQVRFXG4gICAgICAgIHRoaXMubWVudXMuYXV0b3VwZGF0ZSA9IG5ldyBNZW51SXRlbSh0aGlzLmVsLCAnZ2VfbWVudScsICcgPGkgY2xhc3M9XCJtYXRlcmlhbC1pY29uc1wiPmF1dG9yZW5ldzwvaT4gVXBkYXRlOiBPTicsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKG1haW4uYXV0b3VwZGF0ZSkge1xuICAgICAgICAgICAgICAgIG1haW4uYXV0b3VwZGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMubWVudXMuYXV0b3VwZGF0ZS5uYW1lID0gJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5hdXRvcmVuZXc8L2k+IFVwZGF0ZTogT0ZGJztcbiAgICAgICAgICAgICAgICAvLyB0aGlzLm1lbnVzLmF1dG91cGRhdGUuYnV0dG9uLnN0eWxlLmNvbG9yID0gJ2dyYXknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbWFpbi5hdXRvdXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBtYWluLnVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMubWVudXMuYXV0b3VwZGF0ZS5uYW1lID0gJzxpIGNsYXNzPVwibWF0ZXJpYWwtaWNvbnNcIj5hdXRvcmVuZXc8L2k+IFVwZGF0ZTogT04nO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMubWVudXMuYXV0b3VwZGF0ZS5idXR0b24uc3R5bGUuY29sb3IgPSAnd2hpdGUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBtYWluLmNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmVsKTtcbiAgICB9XG59XG4iLCJleHBvcnQgZGVmYXVsdCBjbGFzcyBNZW51SXRlbSB7XG4gICAgY29uc3RydWN0b3IgKGNvbnRhaW5lciwgY2xhc3NOYW1lLCBuYW1lLCBvbkNsaWNrKSB7XG4gICAgICAgIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpO1xuICAgICAgICB0aGlzLmJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpO1xuICAgICAgICB0aGlzLmJ1dHRvbi5jbGFzc05hbWUgPSBjbGFzc05hbWUgKyAnX2J1dHRvbic7XG4gICAgICAgIHRoaXMuZWwuYXBwZW5kQ2hpbGQodGhpcy5idXR0b24pO1xuICAgICAgICB0aGlzLmVsLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBjbGFzc05hbWUpO1xuICAgICAgICB0aGlzLmJ1dHRvbi5pbm5lckhUTUwgPSBuYW1lO1xuICAgICAgICB0aGlzLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgICAgICAgdGhpcy5oaWRkZW5DbGFzcyA9IGNsYXNzTmFtZSArICctLWhpZGRlbic7XG5cbiAgICAgICAgLy8gQXR0YWNoIGxpc3RlbmVycywgaW5jbHVkaW5nIHRob3NlIGZvciB0b29sdGlwIGJlaGF2aW9yXG4gICAgICAgIHRoaXMuYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25DbGljaywgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuZWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0IG5hbWUgKG5hbWUpIHtcbiAgICAgICAgdGhpcy5idXR0b24uaW5uZXJIVE1MID0gbmFtZTtcbiAgICB9XG5cbiAgICBoaWRlICgpIHtcbiAgICAgICAgdGhpcy5lbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgdGhpcy5jbGFzc05hbWUgKyAnICcgKyB0aGlzLmhpZGRlbkNsYXNzKTtcbiAgICB9XG5cbiAgICBzaG93ICgpIHtcbiAgICAgICAgdGhpcy5lbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgdGhpcy5jbGFzc05hbWUpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IGlzQ29tbWVudGVkLCBpc0xpbmVBZnRlck1haW4sIGdldFZhcmlhYmxlVHlwZSwgZ2V0U2hhZGVyRm9yVHlwZVZhckluTGluZSwgZ2V0UmVzdWx0UmFuZ2UsIGdldERlbHRhU3VtLCBnZXRIaXRzLCBnZXRNZWRpYW4gfSBmcm9tICcuLi90b29scy9kZWJ1Z2dpbmcnO1xuaW1wb3J0IHsgdW5mb2N1c0xpbmUsIGZvY3VzTGluZSwgdW5mb2N1c0FsbCwgZm9jdXNBbGwgfSBmcm9tICcuLi9jb3JlL0VkaXRvci5qcyc7XG5cbnZhciBtYWluR0UgPSB7fTtcbnZhciBOX1NBTVBMRVMgPSAzMDtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmlzdWFsRGVidWdnZXIge1xuICAgIGNvbnN0cnVjdG9yIChtYWluKSB7XG4gICAgICAgIHRoaXMubWFpbiA9IG1haW47XG4gICAgICAgIHRoaXMuYnJlYWtwb2ludCA9IG51bGw7XG4gICAgICAgIG1haW5HRSA9IG1haW47XG5cbiAgICAgICAgdGhpcy50ZXN0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMudGVzdGluZ0ZyYWcgPSAnJztcbiAgICAgICAgdGhpcy50ZXN0aW5nTGluZSA9IDA7XG4gICAgICAgIHRoaXMudGVzdGluZ1Jlc3VsdHMgPSBbXTtcbiAgICAgICAgdGhpcy50ZXN0aW5nU2FtcGxlcyA9IFtdO1xuXG4gICAgICAgIHRoaXMubWFpbi5lZGl0b3Iub24oJ2d1dHRlckNsaWNrJywgKGNtLCBuKSA9PiB7XG4gICAgICAgICAgICBsZXQgaW5mbyA9IGNtLmxpbmVJbmZvKG4pO1xuICAgICAgICAgICAgaWYgKGluZm8gJiYgaW5mby5ndXR0ZXJNYXJrZXJzICYmIGluZm8uZ3V0dGVyTWFya2Vycy5icmVha3BvaW50cykge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGZvciBhbiBhY3RpdmUgdmFyaWFibGUgKGEgdmFyaWFibGUgdGhhdCBoYXZlIGJlZW4gZGVjbGFyZSBvciBtb2RpZnkgaW4gdGhpcyBsaW5lKVxuICAgICAgICAgICAgICAgIGxldCB2YXJpYWJsZVJFID0gbmV3IFJlZ0V4cCgnXFxcXHMqW2Zsb2F0fHZlYzJ8dmVjM3x2ZWM0XT9cXFxccysoW1xcXFx3fFxcXFxfXSopW1xcXFwuXFxcXHddKj9cXFxccytbXFxcXCt8XFxcXC18XFxcXFxcXFx8XFxcXCpdP1xcXFw9JywgJ2knKTtcbiAgICAgICAgICAgICAgICBsZXQgbWF0Y2ggPSB2YXJpYWJsZVJFLmV4ZWMoaW5mby50ZXh0KTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1ZyhtYXRjaFsxXSwgaW5mby5saW5lKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5icmVha3BvaW50ID0gaW5mby5saW5lO1xuICAgICAgICAgICAgICAgI
23459H1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY2hlY2soKSB7XG4gICAgICAgIC8vIENsZWFuIHByZXZpdXMgcmVjb3Jkc1xuICAgICAgICB0aGlzLnRlc3RpbmdSZXN1bHRzID0gW107XG5cbiAgICAgICAgbGV0IGNtID0gdGhpcy5tYWluLmVkaXRvcjtcbiAgICAgICAgbGV0IG5MaW5lcyA9IGNtLmdldERvYygpLnNpemU7XG5cbiAgICAgICAgbGV0IG1haW5TdGFydHNBdCA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbkxpbmVzOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChpc0xpbmVBZnRlck1haW4oY20sIGkpKSB7XG4gICAgICAgICAgICAgICAgbWFpblN0YXJ0c0F0ID0gaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRlc3RMaW5lKG1haW5TdGFydHNBdCk7XG4gICAgfVxuXG4gICAgdGVzdExpbmUobkxpbmUpIHtcbiAgICAgICAgbGV0IGNtID0gbWFpbkdFLmVkaXRvcjtcbiAgICAgICAgbGV0IHZpc3VhbERlYnVnZ2VyID0gbWFpbkdFLnZpc3VhbERlYnVnZ2VyO1xuXG4gICAgICAgIC8vIElmIGlzIGRvbmUgdGVzdGluZy4uLlxuICAgICAgICBpZiAobkxpbmUgPj0gY20uZ2V0RG9jKCkuc2l6ZSkge1xuICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdGluZ0xpbmUgPSAwO1xuICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdGluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICBsZXQgcmVzdWx0cyA9IHZpc3VhbERlYnVnZ2VyLnRlc3RpbmdSZXN1bHRzO1xuICAgICAgICAgICAgbGV0IHJhbmdlID0gZ2V0UmVzdWx0UmFuZ2UocmVzdWx0cyk7XG4gICAgICAgICAgICBsZXQgc3VtID0gZ2V0RGVsdGFTdW0ocmVzdWx0cyk7XG4gICAgICAgICAgICBsZXQgaGl0cyA9IGdldEhpdHMocmVzdWx0cyk7XG5cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdUZXN0OiAnLHJhbmdlLm1heC5tcyArICdtcycsIHJlc3VsdHMpO1xuICAgICAgICAgICAgY20uY2xlYXJHdXR0ZXIoJ2JyZWFrcG9pbnRzJyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIGluIHJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgICBsZXQgcGN0ID0gKHJlc3VsdHNbaV0uZGVsdGEgLyBzdW0pICogMTAwO1xuICAgICAgICAgICAgICAgIGxldCBzaXplID0gKHJlc3VsdHNbaV0uZGVsdGEgLyBzdW0pICogMzA7XG4gICAgICAgICAgICAgICAgbGV0IG1hcmtlckhUTUwgPSAnPGRpdj4nICsgcmVzdWx0c1tpXS5tcy50b0ZpeGVkKDIpO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHRzW2ldLmRlbHRhID4gMC4pIHtcbiAgICAgICAgICAgICAgICAgICAgbWFya2VySFRNTCArPSAnPHNwYW4gY2xhc3M9XCJnZV9hc3NpbmdfbWFya2VyX3BjdCAnO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGN0ID4gKDEwMC4wIC8gaGl0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlckhUTUwgKz0gJ2dlX2Fzc2luZ19tYXJrZXJfc2xvd2VyJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtYXJrZXJIVE1MICs9ICdcIiBzdHlsZT1cIndpZHRoOiAnICsgc2l6ZS50b0ZpeGVkKDApICsgJ3B4O1wiIGRhdGE9XCInICsgcGN0LnRvRml4ZWQoMCkgKyAnJVwiPjwvc3Bhbj4nO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNtLnNldEd1dHRlck1hcmtlcihyZXN1bHRzW2ldLmxpbmUsICdicmVha3BvaW50cycsIG1ha2VNYXJrZXIobWFya2VySFRNTCArICc8L2Rpdj4nKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNMaW5lQWZ0ZXJNYWluKGNtLCBuTGluZSkpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBsaW5lIGlzIGluc2lkZSB0aGUgbWFpbiBmdW5jdGlvblxuICAgICAgICAgICAgbGV0IHNoYWRlciA9IG1haW5HRS5zaGFkZXIuY2FudmFzO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgYW4gYWN0aXZlIHZhcmlhYmxlIChhIHZhcmlhYmxlIHRoYXQgaGF2ZSBiZWVuIGRlY2xhcmUgb3IgbW9kaWZ5IGluIHRoaXMgbGluZSlcbiAgICAgICAgICAgIGxldCB2YXJpYWJsZVJFID0gbmV3IFJlZ0V4cCgnXFxcXHMqW2Zsb2F0fHZlYzJ8dmVjM3x2ZWM0XT9cXFxccysoW1xcXFx3fFxcXFxfXSopW1xcXFwuXFxcXHddKj9cXFxccytbXFxcXCt8XFxcXC18XFxcXFxcXFx8XFxcXCpdP1xcXFw9JywgJ2knKTtcbiAgICAgICAgICAgIGxldCBtYXRjaCA9IHZhcmlhYmxlUkUuZXhlYyhjbS5nZXRMaW5lKG5MaW5lKSk7XG4gICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBhbiBhY3RpdmUgdmFyaWFibGUsIGdldCB3aGF0IHR5cGUgaXNcbiAgICAgICAgICAgICAgICBsZXQgdmFyaWFibGUgPSBtYXRjaFsxXTtcbiAgICAgICAgICAgICAgICBsZXQgdHlwZSA9IGdldFZhcmlhYmxlVHlwZShjbSwgdmFyaWFibGUpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnbm9uZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgaXQgZmFpbHMgb24gZmluZGluZyB0aGUgdHlwZSBrZWVwIGdvaW5nIHdpdGggdGhlIHRlc3Qgb24gYW5vdGhlciBsaW5lXG4gICAgICAgICAgICAgICAgICAgIHZpc3VhbERlYnVnZ2VyLnRlc3RMaW5lKG5MaW5lICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBQcmVwYXJlXG4gICAgICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdGluZ0xpbmUgPSBuTGluZTtcbiAgICAgICAgICAgICAgICB2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nRnJhZyA9IGdldFNoYWRlckZvclR5cGVWYXJJbkxpbmUoY20sIHR5cGUsIHZhcmlhYmxlLCBuTGluZSk7XG4gICAgICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdGluZ1NhbXBsZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIHVuZm9jdXNBbGwoY20pO1xuICAgICAgICAgICAgICAgIGZvY3VzTGluZShjbSwgbkxpbmUpO1xuICAgICAgICAgICAgICAgIG1haW5HRS5kZWJ1Z2dpbmcgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgc2hhZGVyLnRlc3QodGhpcy5vblRlc3QsIHZpc3VhbERlYnVnZ2VyLnRlc3RpbmdGcmFnKTtcbiAgICAgICAgICAgI
23459H1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZpc3VhbERlYnVnZ2VyLnRlc3RMaW5lKG5MaW5lICsgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgbGluZSBpcyBub3QgaW5zaWRlIG1haW4gZnVuY3Rpb24sIHRlc3QgdGhlIG5leHQgb25lLi4uXG4gICAgICAgICAgICB2aXN1YWxEZWJ1Z2dlci50ZXN0TGluZShuTGluZSArIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25UZXN0ICh0YXJnZXQpIHtcbiAgICAgICAgbGV0IGNtID0gbWFpbkdFLmVkaXRvcjtcbiAgICAgICAgbGV0IHNoYWRlciA9IG1haW5HRS5zaGFkZXIuY2FudmFzO1xuICAgICAgICBsZXQgdmlzdWFsRGVidWdnZXIgPSBtYWluR0UudmlzdWFsRGVidWdnZXI7XG5cbiAgICAgICAgLy8gSWYgdGhlIHRlc3Qgc2hhZGVyIGNvbXBpbGVkLi4uXG4gICAgICAgIGlmICh0YXJnZXQud2FzVmFsaWQpIHtcbiAgICAgICAgICAgIC8vIGdldCBkYXRhLCBwcm9jZXNzIGFuZCBzdG9yZS5cbiAgICAgICAgICAgIGxldCBlbGFwc2VkTXMgPSB0YXJnZXQudGltZUVsYXBzZWRNcztcblxuICAgICAgICAgICAgaWYgKHZpc3VhbERlYnVnZ2VyLnRlc3RpbmdTYW1wbGVzLmxlbmd0aCA8IE5fU0FNUExFUyAtIDEpIHtcbiAgICAgICAgICAgICAgICB2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nU2FtcGxlcy5wdXNoKGVsYXBzZWRNcyk7XG4gICAgICAgICAgICAgICAgc2hhZGVyLnRlc3QodmlzdWFsRGVidWdnZXIub25UZXN0LCB2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nRnJhZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb2N1c0FsbChjbSk7XG4gICAgICAgICAgICAgICAgbWFpbkdFLmRlYnVnZ2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZpc3VhbERlYnVnZ2VyLnRlc3RpbmdTYW1wbGVzLnB1c2goZWxhcHNlZE1zKTtcbiAgICAgICAgICAgICAgICBlbGFwc2VkTXMgPSBnZXRNZWRpYW4odmlzdWFsRGVidWdnZXIudGVzdGluZ1NhbXBsZXMpO1xuXG4gICAgICAgICAgICAgICAgbGV0IHJhbmdlID0gZ2V0UmVzdWx0UmFuZ2UodmlzdWFsRGVidWdnZXIudGVzdGluZ1Jlc3VsdHMpO1xuICAgICAgICAgICAgICAgIGxldCBkZWx0YSA9IGVsYXBzZWRNcyAtIHJhbmdlLm1heC5tcztcbiAgICAgICAgICAgICAgICBpZiAodmlzdWFsRGVidWdnZXIudGVzdGluZ1Jlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbHRhID0gMC4wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nUmVzdWx0cy5wdXNoKHtsaW5lOnZpc3VhbERlYnVnZ2VyLnRlc3RpbmdMaW5lLCBtczp0YXJnZXQudGltZUVsYXBzZWRNcywgZGVsdGE6ZGVsdGF9KTtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnVGVzdGluZyBsaW5lOicsIHZpc3VhbERlYnVnZ2VyLnRlc3RpbmdMaW5lLCBlbGFwc2VkTXMsIGRlbHRhLCByYW5nZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgZ3V0dGVyIG1hcmtlclxuICAgICAgICAgICAgICAgIGNtLnNldEd1dHRlck1hcmtlcih2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nTGluZSxcbiAgICAgICAgICAgICAgICAgICAgJ2JyZWFrcG9pbnRzJyxcbiAgICAgICAgICAgICAgICAgICAgbWFrZU1hcmtlcihlbGFwc2VkTXMudG9GaXhlZCgyKSkpO1xuXG4gICAgICAgICAgICAgICAgLy8gVGVzdCBuZXh0IGxpbmVcbiAgICAgICAgICAgICAgICB2aXN1YWxEZWJ1Z2dlci50ZXN0TGluZSh2aXN1YWxEZWJ1Z2dlci50ZXN0aW5nTGluZSArIDEpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKHRhcmdldCk7XG4gICAgICAgICAgICAvLyBUZXN0IG5leHQgbGluZVxuICAgICAgICAgICAgdmlzdWFsRGVidWdnZXIudGVzdExpbmUodmlzdWFsRGVidWdnZXIudGVzdGluZ0xpbmUgKyAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRlYnVnICh2YXJpYWJsZSwgbkxpbmUpIHtcbiAgICAgICAgZm9jdXNBbGwodGhpcy5tYWluLmVkaXRvcik7XG4gICAgICAgIHRoaXMubWFpbi5kZWJ1Z2dpbmcgPSBmYWxzZTtcblxuICAgICAgICBpZiAoaXNMaW5lQWZ0ZXJNYWluKHRoaXMubWFpbi5lZGl0b3IsIG5MaW5lKSkge1xuICAgICAgICAgICAgdmFyIHR5cGUgPSBnZXRWYXJpYWJsZVR5cGUodGhpcy5tYWluLmVkaXRvciwgdmFyaWFibGUpO1xuICAgICAgICAgICAgaWYgKHR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5tYWluLnNoYWRlci5jYW52YXMubG9hZChnZXRTaGFkZXJGb3JUeXBlVmFySW5MaW5lKHRoaXMubWFpbi5lZGl0b3IsIHR5cGUsIHZhcmlhYmxlLCBuTGluZSkpO1xuICAgICAgICAgICAgICAgIHVuZm9jdXNBbGwodGhpcy5tYWluLmVkaXRvcik7XG4gICAgICAgICAgICAgICAgZm9jdXNMaW5lKHRoaXMubWFpbi5lZGl0b3IsIG5MaW5lKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW4uZGVidWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubWFpbi51cGRhdGUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlsdW1pbmF0ZSAodmFyaWFibGUpIHtcbiAgICAgICAgaWYgKHRoaXMubWFpbi5kZWJidWdpbmcgJiYgdGhpcy52YXJpYWJsZSA9PT0gdGhpcy52YXJpYWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMuY2xlYW4oKTtcblxuICAgICAgICBsZXQgY20gPSB0aGlzLm1haW4uZWRpdG9yO1xuXG4gICAgICAgIC8vIEhpZ2hsaWdodCBhbGwgY2FsbHMgdG8gYSB2YXJpYWJsZVxuICAgICAgICB0aGlzLm92ZXJsYXkgPSBzZWFyY2hPdmVybGF5KHZhcmlhYmxlLCB0cnVlKTtcbiAgICAgICAgY20uYWRkT3ZlcmxheSh0aGlzLm92ZXJsYXkpO1xuICAgICAgICBpZiAoY20uc2hvd01hdGNoZXNPblNjcm9sbGJhcikge1xuICAgICAgICAgICAgaWYgKHRoaXMuYW5ub3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFubm90YXRlLmNsZWFyKCk7IHRoaXMuYW5ub3RhdGUgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hbm5vdGF0ZSA9IGNtLnNob3dNYXRjaGVzT25TY3JvbGxiYXIodmFyaWFibGUsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xlYW4gKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudCAmJiBldmVudC50YXJnZXQgJiYgZXZlbnQudGFyZ2V0LmNsYXNzTmFtZSA9PT0gJ2dlX2Fzc2luZ19tYXJrZXInKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgI
23459H1cblxuICAgICAgICBsZXQgY20gPSB0aGlzLm1haW4uZWRpdG9yO1xuICAgICAgICBjbS5jbGVhckd1dHRlcignYnJlYWtwb2ludHMnKTtcbiAgICAgICAgaWYgKHRoaXMub3ZlcmxheSkge1xuICAgICAgICAgICAgY20ucmVtb3ZlT3ZlcmxheSh0aGlzLm92ZXJsYXksIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudHlwZSA9IG51bGw7XG4gICAgICAgIGlmICh0aGlzLm1haW4uZGViYnVnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLm1haW4uc2hhZGVyLmNhbnZhcy5sb2FkKHRoaXMubWFpbi5vcHRpb25zLmZyYWdfaGVhZGVyICsgdGhpcy5tYWluLmVkaXRvci5nZXRWYWx1ZSgpICsgdGhpcy5tYWluLm9wdGlvbnMuZnJhZ19mb290ZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWFpbi5kZWJidWdpbmcgPSBmYWxzZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VNYXJrZXIoaHRtbCwgZXh0cmFDbGFzcykge1xuICAgIGxldCBtYXJrZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBtYXJrZXIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdnZV9hc3NpbmdfbWFya2VyJyk7XG4gICAgbWFya2VyLmlubmVySFRNTCA9IGh0bWw7XG4gICAgcmV0dXJuIG1hcmtlcjtcbn1cblxuZnVuY3Rpb24gc2VhcmNoT3ZlcmxheShxdWVyeSwgY2FzZUluc2Vuc2l0aXZlKSB7XG4gICAgaWYgKHR5cGVvZiBxdWVyeSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcXVlcnkgPSBuZXcgUmVnRXhwKHF1ZXJ5LnJlcGxhY2UoL1tcXC1cXFtcXF1cXC9cXHtcXH1cXChcXClcXCpcXCtcXD9cXC5cXFxcXFxeXFwkXFx8XS9nLCAnXFxcXCQmJyksIGNhc2VJbnNlbnNpdGl2ZSA/ICdnaScgOiAnZycpO1xuICAgIH1cbiAgICBlbHNlIGlmICghcXVlcnkuZ2xvYmFsKSB7XG4gICAgICAgIHF1ZXJ5ID0gbmV3IFJlZ0V4cChxdWVyeS5zb3VyY2UsIHF1ZXJ5Lmlnbm9yZUNhc2UgPyAnZ2knIDogJ2cnKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0b2tlbjogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgICAgICBxdWVyeS5sYXN0SW5kZXggPSBzdHJlYW0ucG9zO1xuICAgICAgICAgICAgdmFyIG1hdGNoID0gcXVlcnkuZXhlYyhzdHJlYW0uc3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChtYXRjaCAmJiBtYXRjaC5pbmRleCA9PT0gc3RyZWFtLnBvcykge1xuICAgICAgICAgICAgICAgIHN0cmVhbS5wb3MgKz0gbWF0Y2hbMF0ubGVuZ3RoIHx8IDE7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdzZWFyY2hpbmcnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBzdHJlYW0ucG9zID0gbWF0Y2guaW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdHJlYW0uc2tpcFRvRW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufVxuIiwiaW1wb3J0IE1lbnVJdGVtIGZyb20gJy4uL01lbnVJdGVtJztcbmltcG9ydCBNb2RhbCBmcm9tICcuL01vZGFsJztcbi8vIGltcG9ydCB7IHNhdmVPblNlcnZlciwgY3JlYXRlT3BlbkZyYW1lQXJ0d29yayB9IGZyb20gJy4uLy4uL2lvL3NoYXJlJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRXhwb3J0TW9kYWwgZXh0ZW5kcyBNb2RhbCB7XG4gICAgY29uc3RydWN0b3IgKENTU19QUkVGSVgsIHByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoQ1NTX1BSRUZJWCwgcHJvcGVydGllcyk7XG4gICAgICAgIHRoaXMubWFpbiA9IHByb3BlcnRpZXMubWFpbjtcblxuICAgICAgICB0aGlzLnNhdmUgPSBuZXcgTWVudUl0ZW0odGhpcy5lbCwgJ2dlX3N1Yl9tZW51JywgJ0Rvd25sb2FkIGZpbGUnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMubWFpbi5kb3dubG9hZCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyB0aGlzLmNvZGVVUkwgPSBuZXcgTWVudUl0ZW0odGhpcy5lbCwgJ2dlX3N1Yl9tZW51JywgJ0NvZGUgVVJMLi4uJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIC8vICAgICBzYXZlT25TZXJ2ZXIodGhpcy5tYWluLCAoZXZlbnQpID0+IHtcbiAgICAgICAgLy8gICAgICAgICBwcm9tcHQoJ1VzZSB0aGlzIHVybCB0byBzaGFyZSB5b3VyIGNvZGUnLCAnaHR0cDovL3RoZWJvb2tvZnNoYWRlcnMuY29tL2VkaXQucGhwP2xvZz0nICsgZXZlbnQubmFtZSk7XG4gICAgICAgIC8vICAgICAgICAgdGhpcy5yZW1vdmVNb2RhbCgpO1xuICAgICAgICAvLyAgICAgfSk7XG4gICAgICAgIC8vIH0pO1xuXG4gICAgICAgIC8vIHRoaXMuc2hhZGVyVVJMID0gbmV3IE1lbnVJdGVtKHRoaXMuZWwsICdnZV9zdWJfbWVudScsICdBcnR3b3JrIFVSTC4uLicsIChldmVudCkgPT4ge1xuICAgICAgICAvLyAgICAgc2F2ZU9uU2VydmVyKHRoaXMubWFpbiwgKGV2ZW50KSA9PiB7XG4gICAgICAgIC8vICAgICAgICAgcHJvbXB0KCdVc2UgdGhpcyB1cmwgdG8gc2hhcmUgeW91ciBhcnR3b3JrJywgJ2h0dHA6Ly9wbGF5ZXIudGhlYm9va29mc2hhZGVycy5jb20vP2xvZz0nICsgZXZlbnQubmFtZSk7XG4gICAgICAgIC8vICAgICAgICAgdGhpcy5yZW1vdmVNb2RhbCgpO1xuICAgICAgICAvLyAgICAgfSk7XG4gICAgICAgIC8vIH0pO1xuXG4gICAgICAgIC8vIGxldCBzaGFyZU9GID0gbmV3IE1lbnVJdGVtKHRoaXMuZWwsICdnZV9zdWJfbWVudScsICdBcnR3b3JrIHRvIFtvXScsIChldmVudCkgPT4ge1xuICAgICAgICAvLyAgICAgc2hhcmVPRi5lbC5pbm5lckhUTUwgPSAnQXJ0d29yayB0byBbb106IGFkZGluZyB0byBjb2xsZWN0aW9uJztcbiAgICAgICAgLy8gICAgIHNhdmVPblNlcnZlcih0aGlzLm1haW4sIChldmVudCkgPT4ge1xuICAgICAgICAvLyAgICAgICAgIGNyZWF0ZU9wZW5GcmFtZUFydHdvcmsodGhpcy5tYWluLCBldmVudC5uYW1lLCBldmVudC51cmwsIChzdWNjZXNzKSA9PiB7XG4gICAgICAgIC8vICAgICAgICAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIC8vICAgICAgICAgICAgICAgICBzaGFyZU9GLmVsLmlubmVySFRNTCA9ICdBcnR3b3JrIHRvIFtvXTogYWRkZWQhJztcbiAgICAgICAgLy8gICAgICAgICAgICAgfVxuICAgICAgICAvLyAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgI
23459HNoYXJlT0YuZWwuaW5uZXJIVE1MID0gJ0FydHdvcmsgdG8gW29dOiBmYWlsZWQgOignO1xuICAgICAgICAvLyAgICAgICAgICAgICB9XG4gICAgICAgIC8vICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAvLyAgICAgICAgICAgICAgICAgc2hhcmVPRi5lbC5pbm5lckhUTUwgPSAnW29dJztcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTW9kYWwoKTtcbiAgICAgICAgLy8gICAgICAgICAgICAgfSwgNDAwMCk7XG4gICAgICAgIC8vICAgICAgICAgfSk7XG4gICAgICAgIC8vICAgICB9KTtcbiAgICAgICAgLy8gfSk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgc3Vic2NyaWJlTWl4aW4gfSBmcm9tICcuLi8uLi90b29scy9taXhpbic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1vZGFsIHtcbiAgICBjb25zdHJ1Y3RvciAoQ1NTX1BSRUZJWCwgcHJvcGVydGllcykge1xuICAgICAgICBzdWJzY3JpYmVNaXhpbih0aGlzKTtcbiAgICAgICAgdGhpcy5DU1NfUFJFRklYID0gQ1NTX1BSRUZJWDtcblxuICAgICAgICBwcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgZm9yIChsZXQgcHJvcCBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzW3Byb3BdID0gcHJvcGVydGllc1twcm9wXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5lbC5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAnX21vZGFsIGdlX21vZGFsJztcbiAgICAgICAgdGhpcy5lbC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLmJnQ29sb3I7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gdGhpcy5pbm5lckhUTUwgfHwgJyc7XG5cbiAgICAgICAgaWYgKHRoaXMuZWxlbWVudHMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5lbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuZWwuYXBwZW5kQ2hpbGQodGhpcy5lbGVtZW50c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGNsb3NlICgpIHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdjbG9zZScpO1xuICAgIH1cblxuICAgIHNob3dBdCAoY20pIHtcbiAgICAgICAgbGV0IGN1cnNvciA9IGNtLmN1cnNvckNvb3Jkcyh0cnVlLCAncGFnZScpO1xuICAgICAgICBsZXQgeCA9IGN1cnNvci5sZWZ0O1xuICAgICAgICBsZXQgeSA9IGN1cnNvci50b3A7XG5cbiAgICAgICAgeSArPSAzMDtcblxuICAgICAgICB0aGlzLnByZXNlbnRNb2RhbCh4LCB5KTtcbiAgICB9XG5cbiAgICBwcmVzZW50TW9kYWwgKHgsIHkpIHtcbiAgICAgICAgLy8gTGlzdGVuIGZvciBpbnRlcmFjdGlvbiBvdXRzaWRlIG9mIHRoZSBtb2RhbFxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uQ2xpY2tPdXRzaWRlSGFuZGxlciA9IGFkZEV2ZW50KGRvY3VtZW50LmJvZHksICdjbGljaycsIHRoaXMub25DbGlja091dHNpZGUsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbktleVByZXNzSGFuZGxlciA9IGFkZEV2ZW50KHdpbmRvdywgJ2tleWRvd24nLCB0aGlzLm9uS2V5UHJlc3MsIHRoaXMpO1xuICAgICAgICB9LCAwKTtcbiAgICAgICAgdGhpcy5pc1Zpc2libGUgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZWwuc3R5bGUubGVmdCA9IHggKyAncHgnO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLnRvcCA9IHkgKyAncHgnO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgIHRoaXMuZWwuc3R5bGUuaGVpZ2h0ID0gdGhpcy5oZWlnaHQgKyAncHgnO1xuXG4gICAgICAgIGlmICh0aGlzLnBvc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmVsLnN0eWxlLnBvc2l0aW9uID0gdGhpcy5wb3NpdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGhpcy5lbCk7XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdzaG93Jyk7XG4gICAgfVxuXG4gICAgZ2V0TW9kYWxDbGFzcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuQ1NTX1BSRUZJWCArICdtb2RhbCc7XG4gICAgfVxuXG4gICAgb25LZXlQcmVzcyAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVNb2RhbCgpO1xuICAgIH1cblxuICAgIG9uQ2xpY2tPdXRzaWRlIChldmVudCkge1xuICAgICAgICAvLyBIQUNLWSEhXG4gICAgICAgIC8vIEEgY2xpY2sgZXZlbnQgZmlyZXMgb24gdGhlIGJvZHkgYWZ0ZXIgbW91c2Vkb3duIC0gbW91c2Vtb3ZlLCBzaW11bHRhbmVvdXNseSB3aXRoXG4gICAgICAgIC8vIG1vdXNldXAuIFNvIGlmIHNvbWVvbmUgc3RhcnRlZCBhIG1vdXNlIGFjdGlvbiBpbnNpZGUgdGhlIG1vZGFsIGFuZCB0aGVuXG4gICAgICAgIC8vIG1vdXNldXAnZCBvdXRzaWRlIG9mIGl0LCBpdCBmaXJlcyBhIGNsaWNrIGV2ZW50IG9uIHRoZSBib2R5LCB0aHVzLCBjYXVzaW5nIHRoZVxuICAgICAgICAvLyBtb2RhbCB0byBkaXNhcHBlYXIgd2hlbiB0aGUgdXNlciBkb2VzIG5vdCBleHBlY3QgaXQgdG8sIHNpbmNlIHRoZSBtb3VzZSBkb3duIGV2ZW50XG4gICAgICAgIC8vIGRpZCBub3Qgc3RhcnQgb3V0c2lkZSB0aGUgbW9kYWwuXG4gICAgICAgIC8vIFRoZXJlIG1pZ2h0IGJlIChvciBzaG91bGQgYmUpIGEgYmV0dGVyIHdheSB0byB0cmFjayB0aGlzLCBidXQgcmlnaHQgbm93LCBqdXN0IGNhbmNlbFxuICAgICAgICAvLyB0aGUgZXZlbnQgaWYgdGhlIHRhcmdldCBlbmRzIHVwIGJlaW5nIG9uIHRoZSBib2R5IGRpcmVjdGx5IHJhdGhlciB0aGFuIG9uIG9uZSBvZiB0aGVcbiAgICAgICAgLy8gb3RoZXIgY2hpbGQgZWxlbWVudHMuXG4gICAgICAgIGlmIChldmVudC50YXJnZXQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBlbmQgdGhpcyBzcGVjaWZpYyBoYWNreSBwYXJ0XG4gICAgICAgIGxldCB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICAgI
23459HdoaWxlICh0YXJnZXQgIT09IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiAhdGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucyh0aGlzLmdldE1vZGFsQ2xhc3MoKSkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKHRoaXMuZ2V0TW9kYWxDbGFzcygpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTW9kYWwoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqICBSZW1vdmVzIG1vZGFsIGZyb20gRE9NIGFuZCBkZXN0cm95cyByZWxhdGVkIGV2ZW50IGxpc3RlbmVyc1xuICAgICAqL1xuICAgIHJlbW92ZU1vZGFsICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZWwgJiYgdGhpcy5lbC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5lbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVtb3ZlRXZlbnQoZG9jdW1lbnQuYm9keSwgJ2NsaWNrJywgdGhpcy5vbkNsaWNrT3V0c2lkZUhhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uQ2xpY2tPdXRzaWRlSGFuZGxlciA9IG51bGw7XG4gICAgICAgIHJlbW92ZUV2ZW50KHdpbmRvdywgJ2tleWRvd24nLCB0aGlzLm9uS2V5UHJlc3NIYW5kbGVyKTtcbiAgICAgICAgdGhpcy5vbktleVByZXNzSGFuZGxlciA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cbn1cblxuLyogRXZlbnQgaGFuZGxpbmcgKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRFdmVudCAoZWxlbWVudCwgZXZlbnQsIGNhbGxiYWNrLCBjYWxsZXIpIHtcbiAgICBsZXQgaGFuZGxlcjtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBjYWxsYmFjay5jYWxsKGNhbGxlciwgZSk7XG4gICAgfSwgZmFsc2UpO1xuICAgIHJldHVybiBoYW5kbGVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlRXZlbnQgKGVsZW1lbnQsIGV2ZW50LCBjYWxsYmFjaykge1xuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgY2FsbGJhY2ssIGZhbHNlKTtcbn1cbiIsIi8qXG5PcmlnaW5hbDogaHR0cHM6Ly9naXRodWIuY29tL3RhbmdyYW1zL3RhbmdyYW0tcGxheS9ibG9iL2doLXBhZ2VzL3NyYy9qcy9hZGRvbnMvdWkvd2lkZ2V0cy9Db2xvclBpY2tlck1vZGFsLmpzXG5BdXRob3I6IExvdSBIdWFuZyAoQHNhaWtvZmlzaClcbiovXG5cbmltcG9ydCBQaWNrZXIgZnJvbSAnLi9QaWNrZXInO1xuaW1wb3J0IENvbG9yIGZyb20gJy4vdHlwZXMvQ29sb3InO1xuaW1wb3J0IHsgYWRkRXZlbnQsIHJlbW92ZUV2ZW50IH0gZnJvbSAnLi9QaWNrZXInO1xuaW1wb3J0IHsgZ2V0RGV2aWNlUGl4ZWxSYXRpbyB9IGZyb20gJy4uLy4uL3Rvb2xzL2NvbW1vbic7XG5cbmltcG9ydCB7IHN1YnNjcmliZUludGVyYWN0aXZlRG9tIH0gZnJvbSAnLi4vLi4vdG9vbHMvaW50ZXJhY3RpdmVEb20nO1xuXG4vLyBTb21lIGNvbW1vbiB1c2UgdmFyaWFibGVzXG5sZXQgY3VycmVudFRhcmdldDtcbmxldCBjdXJyZW50VGFyZ2V0SGVpZ2h0ID0gMDtcbmxldCBkb21DYWNoZTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29sb3JQaWNrZXIgZXh0ZW5kcyBQaWNrZXIge1xuICAgIGNvbnN0cnVjdG9yIChjb2xvciA9ICd2ZWMzKDEuMCwwLjAsMC4wKScsIHByb3BlcnRpZXMgPSB7fSkge1xuICAgICAgICBzdXBlcignZ2VfY29sb3JwaWNrZXJfJywgcHJvcGVydGllcyk7XG5cbiAgICAgICAgdGhpcy53aWR0aCA9IDI1MDsgLy8gaW4gcGl4ZWxzXG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gMjUwOyAvLyBpbiBwaXhlbHNcblxuICAgICAgICB0aGlzLmRpc2MgPSB7IHdpZHRoOiAyMDAsIGhlaWdodDogMjAwIH07XG4gICAgICAgIHRoaXMuYmFybHVtID0geyB3aWR0aDogMjUsIGhlaWdodDogMjAwIH07XG5cbiAgICAgICAgdGhpcy5zZXRWYWx1ZShjb2xvcik7XG4gICAgICAgIHRoaXMuaW5pdCgpO1xuICAgIH1cblxuICAgIGluaXQoKSB7XG4gICAgICAgIGlmICghZG9tQ2FjaGUpIHtcbiAgICAgICAgICAgIGxldCBtb2RhbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgbGV0IHBhdGNoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsZXQgbWFwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsZXQgZGlzYyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgbGV0IGNvdmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsZXQgY3Vyc29yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsZXQgYmFyYmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIGxldCBiYXJ3aGl0ZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgbGV0IGJhcmx1bSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgbGV0IGJhcmN1cnNvcnMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIGxldCBsZWZ0Y3Vyc29yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsZXQgcmlnaHRjdXJzb3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgICAgICAgbW9kYWwuY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ21vZGFsIGdlX3BpY2tlcl9tb2RhbCc7XG4gICAgICAgICAgICBtb2RhbC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLmJnQ29sb3I7XG4gICAgICAgICAgICBwYXRjaC5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAncGF0Y2gnO1xuICAgICAgICAgICAgcGF0Y2guc3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5iZ0NvbG9yO1xuICAgICAgICAgICAgbWFwLmNsYXNzTmFtZSA9IHRoaXMuQ1NTX1BSRUZJWCArICdoc3YtbWFwJztcbiAgICAgICAgICAgIGRpc2MuY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ2Rpc2MnO1xuICAgICAgICAgICAgZGlzYy5zdHlsZS5iYWNrZ3JvdW5k
23459Q29sb3IgPSB0aGlzLmJnQ29sb3I7XG4gICAgICAgICAgICBjb3Zlci5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAnZGlzYy1jb3Zlcic7XG4gICAgICAgICAgICBjdXJzb3IuY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ2Rpc2MtY3Vyc29yJztcbiAgICAgICAgICAgIGJhcmJnLmNsYXNzTmFtZSA9IHRoaXMuQ1NTX1BSRUZJWCArICdiYXItYmcnO1xuICAgICAgICAgICAgYmFyd2hpdGUuY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ2Jhci13aGl0ZSc7XG4gICAgICAgICAgICBiYXJsdW0uY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ2Jhci1sdW1pbmFuY2UnO1xuICAgICAgICAgICAgYmFyY3Vyc29ycy5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAnYmFyLWN1cnNvcnMnO1xuICAgICAgICAgICAgbGVmdGN1cnNvci5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAnYmFyLWN1cnNvci1sZWZ0JztcbiAgICAgICAgICAgIHJpZ2h0Y3Vyc29yLmNsYXNzTmFtZSA9IHRoaXMuQ1NTX1BSRUZJWCArICdiYXItY3Vyc29yLXJpZ2h0JztcblxuICAgICAgICAgICAgbWFwLmlkID0gJ2NwLW1hcCc7XG4gICAgICAgICAgICBiYXJjdXJzb3JzLmlkID0gJ2NwLWJhcic7XG5cbiAgICAgICAgICAgIG1vZGFsLmFwcGVuZENoaWxkKHBhdGNoKTtcbiAgICAgICAgICAgIG1vZGFsLmFwcGVuZENoaWxkKG1hcCk7XG5cbiAgICAgICAgICAgIG1hcC5hcHBlbmRDaGlsZChkaXNjKTtcbiAgICAgICAgICAgIG1hcC5hcHBlbmRDaGlsZChjb3Zlcik7XG4gICAgICAgICAgICBtYXAuYXBwZW5kQ2hpbGQoY3Vyc29yKTtcbiAgICAgICAgICAgIG1hcC5hcHBlbmRDaGlsZChiYXJiZyk7XG4gICAgICAgICAgICBtYXAuYXBwZW5kQ2hpbGQoYmFyd2hpdGUpO1xuICAgICAgICAgICAgbWFwLmFwcGVuZENoaWxkKGJhcmx1bSk7XG4gICAgICAgICAgICBtYXAuYXBwZW5kQ2hpbGQoYmFyY3Vyc29ycyk7XG4gICAgICAgICAgICBiYXJjdXJzb3JzLmFwcGVuZENoaWxkKGxlZnRjdXJzb3IpO1xuICAgICAgICAgICAgYmFyY3Vyc29ycy5hcHBlbmRDaGlsZChyaWdodGN1cnNvcik7XG5cbiAgICAgICAgICAgIGRvbUNhY2hlID0gbW9kYWw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXR1cm5zIGEgY2xvbmUgb2YgdGhlIGNhY2hlZCBkb2N1bWVudCBmcmFnbWVudFxuICAgICAgICB0aGlzLmVsID0gZG9tQ2FjaGUuY2xvbmVOb2RlKHRydWUpO1xuICAgICAgICBzdWJzY3JpYmVJbnRlcmFjdGl2ZURvbSh0aGlzLmVsLCB7IG1vdmU6IHRydWUsIHJlc2l6ZTogZmFsc2UsIHNuYXA6IGZhbHNlIH0pO1xuXG4gICAgICAgIC8vIFRPRE86IEltcHJvdmUgdGhlc2UgcmVmZXJlbmNlc1xuICAgICAgICAvLyBUaGUgY2FjaGluZyBvZiByZWZlcmVuY2VzIGlzIGxpa2VseSB0byBiZSBpbXBvcnRhbnQgZm9yIHNwZWVkXG4gICAgICAgIHRoaXMuZG9tID0ge307XG4gICAgICAgIHRoaXMuZG9tLmhzdk1hcCA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmdlX2NvbG9ycGlja2VyX2hzdi1tYXAnKTtcbiAgICAgICAgdGhpcy5kb20uaHN2TWFwQ292ZXIgPSB0aGlzLmRvbS5oc3ZNYXAuY2hpbGRyZW5bMV07IC8vIHdlbGwuLi5cbiAgICAgICAgdGhpcy5kb20uaHN2TWFwQ3Vyc29yID0gdGhpcy5kb20uaHN2TWFwLmNoaWxkcmVuWzJdO1xuICAgICAgICB0aGlzLmRvbS5oc3ZCYXJCR0xheWVyID0gdGhpcy5kb20uaHN2TWFwLmNoaWxkcmVuWzNdO1xuICAgICAgICB0aGlzLmRvbS5oc3ZCYXJXaGl0ZUxheWVyID0gdGhpcy5kb20uaHN2TWFwLmNoaWxkcmVuWzRdO1xuICAgICAgICB0aGlzLmRvbS5oc3ZCYXJDdXJzb3JzID0gdGhpcy5kb20uaHN2TWFwLmNoaWxkcmVuWzZdO1xuICAgICAgICB0aGlzLmRvbS5oc3ZMZWZ0Q3Vyc29yID0gdGhpcy5kb20uaHN2QmFyQ3Vyc29ycy5jaGlsZHJlblswXTtcbiAgICAgICAgdGhpcy5kb20uaHN2UmlnaHRDdXJzb3IgPSB0aGlzLmRvbS5oc3ZCYXJDdXJzb3JzLmNoaWxkcmVuWzFdO1xuXG4gICAgICAgIHRoaXMuZG9tLmNvbG9yRGlzYyA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmdlX2NvbG9ycGlja2VyX2Rpc2MnKTtcbiAgICAgICAgdGhpcy5kb20ubHVtaW5hbmNlQmFyID0gdGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZ2VfY29sb3JwaWNrZXJfYmFyLWx1bWluYW5jZScpO1xuXG4gICAgICAgIGlmICh0aGlzLmxpbmtCdXR0b24pIHtcbiAgICAgICAgICAgIGxldCBsYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBsYnV0dG9uLmlubmVySFRNTCA9ICcrJztcbiAgICAgICAgICAgIGxidXR0b24uY2xhc3NOYW1lID0gdGhpcy5DU1NfUFJFRklYICsgJ2xpbmstYnV0dG9uJztcbiAgICAgICAgICAgIGxidXR0b24uc3R5bGUuY29sb3IgPSB0aGlzLmZnQ29sb3I7XG4gICAgICAgICAgICB0aGlzLmVsLmFwcGVuZENoaWxkKGxidXR0b24pO1xuXG4gICAgICAgICAgICBsYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlcignbGlua0J1dHRvbicsIHRoaXMudmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5saW5rQnV0dG9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlua0J1dHRvbih0aGlzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVNb2RhbCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkcmF3ICgpIHtcbiAgICAgICAgLy8gIFJlbmRlciBjb2xvciBwYXRjaFxuICAgICAgICBsZXQgcGF0Y2ggPSB0aGlzLmVsLnF1ZXJ5U2VsZWN0b3IoJy5nZV9jb2xvcnBpY2tlcl9wYXRjaCcpO1xuICAgICAgICBwYXRjaC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLnZhbHVlLmdldFN0cmluZygncmdiJyk7XG5cbiAgICAgICAgLy8gIFJlbmRlciBIU1YgcGlja2VyXG4gICAgICAgIGxldCBjb2xvciA9IHRoaXMudmFsdWUuY29sb3JzO1xuICAgICAgICBsZXQgY29sb3JEaXNjUmFkaXVzID0gdGhpcy5kb20uY29sb3JEaXNjLm9mZnNldEhlaWdodCAvID
23459I7XG4gICAgICAgIGxldCBwaTIgPSBNYXRoLlBJICogMjtcbiAgICAgICAgbGV0IHggPSBNYXRoLmNvcyhwaTIgLSBjb2xvci5oc3YuaCAqIHBpMik7XG4gICAgICAgIGxldCB5ID0gTWF0aC5zaW4ocGkyIC0gY29sb3IuaHN2LmggKiBwaTIpO1xuICAgICAgICBsZXQgciA9IGNvbG9yLmhzdi5zICogKGNvbG9yRGlzY1JhZGl1cyAtIDUpO1xuXG4gICAgICAgIHRoaXMuZG9tLmhzdk1hcENvdmVyLnN0eWxlLm9wYWNpdHkgPSAxIC0gY29sb3IuaHN2LnYgLyAyNTU7XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGZhc3RlciB2ZXJzaW9uLi4uXG4gICAgICAgIHRoaXMuZG9tLmhzdkJhcldoaXRlTGF5ZXIuc3R5bGUub3BhY2l0eSA9IDEgLSBjb2xvci5oc3YucztcbiAgICAgICAgdGhpcy5kb20uaHN2QmFyQkdMYXllci5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAncmdiKCcgK1xuICAgICAgICAgICAgY29sb3IuaHVlUkdCLnIgKyAnLCcgK1xuICAgICAgICAgICAgY29sb3IuaHVlUkdCLmcgKyAnLCcgK1xuICAgICAgICAgICAgY29sb3IuaHVlUkdCLmIgKyAnKSc7XG5cbiAgICAgICAgdGhpcy5kb20uaHN2TWFwQ3Vyc29yLnN0eWxlLmNzc1RleHQgPVxuICAgICAgICAgICAgJ2xlZnQ6ICcgKyAoeCAqIHIgKyBjb2xvckRpc2NSYWRpdXMpICsgJ3B4OycgK1xuICAgICAgICAgICAgJ3RvcDogJyArICh5ICogciArIGNvbG9yRGlzY1JhZGl1cykgKyAncHg7JyArXG4gICAgICAgICAgICAnYm9yZGVyLWNvbG9yOiAnICsgKGNvbG9yLmx1bWluYW5jZSA+IDAuMjIgPyAnIzMzMzsnIDogJyNkZGQnKTtcblxuICAgICAgICBpZiAoY29sb3IubHVtaW5hbmNlID4gMC4yMikge1xuICAgICAgICAgICAgdGhpcy5kb20uaHN2QmFyQ3Vyc29ycy5jbGFzc0xpc3QuYWRkKCdnZV9jb2xvcnBpY2tlcl9kYXJrJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRvbS5oc3ZCYXJDdXJzb3JzLmNsYXNzTGlzdC5yZW1vdmUoJ2dlX2NvbG9ycGlja2VyX2RhcmsnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRvbS5oc3ZMZWZ0Q3Vyc29yKSB7XG4gICAgICAgICAgICB0aGlzLmRvbS5oc3ZMZWZ0Q3Vyc29yLnN0eWxlLnRvcCA9IHRoaXMuZG9tLmhzdlJpZ2h0Q3Vyc29yLnN0eWxlLnRvcCA9ICgoMSAtIGNvbG9yLmhzdi52IC8gMjU1KSAqIGNvbG9yRGlzY1JhZGl1cyAqIDIpICsgJ3B4JztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByZXNlbnRNb2RhbCAoeCwgeSkge1xuICAgICAgICBzdXBlci5wcmVzZW50TW9kYWwoeCwgeSk7XG5cbiAgICAgICAgLy8gLy8gTGlzdGVuIGZvciBpbnRlcmFjdGlvbiBvbiB0aGUgSFNWIG1hcFxuICAgICAgICB0aGlzLm9uSHN2RG93bkhhbmRsZXIgPSBhZGRFdmVudCh0aGlzLmRvbS5oc3ZNYXAsICdtb3VzZWRvd24nLCB0aGlzLm9uSHN2RG93biwgdGhpcyk7XG5cbiAgICAgICAgbGV0IGNvbG9yRGlzYyA9IHRoaXMuZG9tLmNvbG9yRGlzYztcblxuICAgICAgICBpZiAoY29sb3JEaXNjLmdldENvbnRleHQpIHtcbiAgICAgICAgICAgIC8vIEhTViBjb2xvciB3aGVlbCB3aXRoIHdoaXRlIGNlbnRlclxuICAgICAgICAgICAgbGV0IGRpc2tDb250ZXh0ID0gY29sb3JEaXNjLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICBsZXQgcmF0aW8gPSBnZXREZXZpY2VQaXhlbFJhdGlvKGRpc2tDb250ZXh0KTtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHRoaXMuZGlzYy53aWR0aCAvIHJhdGlvO1xuICAgICAgICAgICAgbGV0IGhlaWdodCA9IHRoaXMuZGlzYy5oZWlnaHQgLyByYXRpbztcbiAgICAgICAgICAgIHRoaXMuZG9tLmNvbG9yRGlzYy53aWR0aCA9IHdpZHRoICogcmF0aW87XG4gICAgICAgICAgICB0aGlzLmRvbS5jb2xvckRpc2MuaGVpZ2h0ID0gaGVpZ2h0ICogcmF0aW87XG4gICAgICAgICAgICBkaXNrQ29udGV4dC5zY2FsZShyYXRpbywgcmF0aW8pO1xuXG4gICAgICAgICAgICBkcmF3RGlzayhcbiAgICAgICAgICAgICAgICBkaXNrQ29udGV4dCxcbiAgICAgICAgICAgICAgICBbd2lkdGggLyAyLCBoZWlnaHQgLyAyXSxcbiAgICAgICAgICAgICAgICBbd2lkdGggLyAyIC0gMSwgaGVpZ2h0IC8gMiAtIDFdLFxuICAgICAgICAgICAgICAgIDM2MCxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoY3R4LCBhbmdsZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZ3JhZGllbnQgPSBjdHguY3JlYXRlUmFkaWFsR3JhZGllbnQoMSwgMSwgMSwgMSwgMSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgwLCAnaHNsKCcgKyAoMzYwIC0gYW5nbG
23459UgKyAwKSArICcsIDEwMCUsIDUwJSknKTtcbiAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDEsICcjZmZmJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGdyYWRpZW50O1xuICAgICAgICAgICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIGdyYXkgYm9yZGVyXG4gICAgICAgICAgICBkcmF3Q2lyY2xlKFxuICAgICAgICAgICAgICAgIGRpc2tDb250ZXh0LFxuICAgICAgICAgICAgICAgIFt3aWR0aCAvIDIsIGhlaWdodCAvIDJdLFxuICAgICAgICAgICAgICAgIFt3aWR0aCAvIDIsIGhlaWdodCAvIDJdLFxuICAgICAgICAgICAgICAgIHRoaXMuYmdDb2xvciwvLyAnIzMwMzAzMCcsXG4gICAgICAgICAgICAgICAgMiAvIHJhdGlvXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBkcmF3IHRoZSBsdW1pbmFuY2VCYXIgYmFyXG4gICAgICAgICAgICBsZXQgY3R4ID0gdGhpcy5kb20ubHVtaW5hbmNlQmFyLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICB0aGlzLmRvbS5sdW1pbmFuY2VCYXIud2lkdGggPSB0aGlzLmJhcmx1bS53aWR0aDtcbiAgICAgICAgICAgIHRoaXMuZG9tLmx1bWluYW5jZUJhci5oZWlnaHQgPSB0aGlzLmJhcmx1bS5oZWlnaHQgKiByYXRpbztcbiAgICAgICAgICAgIGN0eC5zY2FsZShyYXRpbywgcmF0aW8pO1xuICAgICAgICAgICAgbGV0IGdyYWRpZW50ID0gY3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsIDAsIDAsIHRoaXMuYmFybHVtLmhlaWdodCAvIHJhdGlvKTtcblxuICAgICAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDAsICd0cmFuc3BhcmVudCcpO1xuICAgICAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDEsICdibGFjaycpO1xuXG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gZ3JhZGllbnQ7XG4gICAgICAgICAgICBjdHguZmlsbFJlY3QoMCwgMCwgMzAsIDIwMCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kcmF3KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIFVwZGF0ZXMgb25seSB0aGUgY29sb3IgdmFsdWUgb2YgdGhlIGNvbG9yIHBpY2tlclxuICAgICAqICBhbmQgdGhlIHZpZXcuIERlc2lnbmVkIHRvIGJlIGNhbGxlZCBieSBleHRlcm5hbCBtb2R1bGVzXG4gICAgICogIHNvIHRoYXQgaXQgY2FuIHVwZGF0ZSBpdHMgaW50ZXJuYWwgdmFsdWUgZnJvbSBhbiBvdXRzaWRlIHNvdXJjZS5cbiAgICAgKiAgRG9lcyBubyBET00gY3JlYXRpb24gJiBvdGhlciBpbml0aWFsaXphdGlvbiB3b3JrLlxuICAgICAqL1xuICAgIHNldFZhbHVlIChjb2xvcikge1xuICAgICAgICB0aGlzLnZhbHVlID0gbmV3IENvbG9yKGNvbG9yKTtcbiAgICB9XG5cbiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4gICAgLyogLS0tLSBIU1YtY2lyY2xlIGNvbG9yIHBpY2tlciAtLS0tLSAqL1xuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAgIC8vIEFjdGlvbnMgd2hlbiB1c2VyIG1vdXNlcyBkb3duIG9uIEhTViBjb2xvciBtYXBcbiAgICBvbkhzdkRvd24gKGV2ZW50KSB7XG4gICAgICAgIGxldCB0YXJnZXQgPSBldmVudC50YXJnZXQgfHwgZXZlbnQuc3JjRWxlbWVudDtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBjdXJyZW50VGFyZ2V0ID0gdGFyZ2V0LmlkID8gdGFyZ2V0IDogdGFyZ2V0LnBhcmVudE5vZGU7XG4gICAgICAgIGN1cnJlbnRUYXJnZXRIZWlnaHQgPSBjdXJyZW50VGFyZ2V0Lm9mZnNldEhlaWdodDsgLy8gYXMgZGlhbWV0ZXIgb2YgY2lyY2xlXG5cbiAgICAgICAgLy8gU3RhcnRzIGxpc3RlbmluZyBmb3IgbW91c2Vtb3ZlIGFuZCBtb3VzZXVwIGV2ZW50c1xuICAgICAgICB0aGlzLm9uSHN2TW92ZUhhbmRsZXIgPSBhZGRFdmVudCh0aGlzLmVsLCAnbW91c2Vtb3ZlJywgdGhpcy5vbkhzdk1vdmUsIHRoaXMpO1xuICAgICAgICB0aGlzLm9uSHN2VXBIYW5kbGVyID0gYWRkRXZlbnQod2luZG93LCAnbW91c2V1cCcsIHRoaXMub25Ic3ZVcCwgdGhpcyk7XG5cbiAgICAgICAgdGhpcy5vbkhzdk1vdmUoZXZlbnQpO1xuXG4gICAgICAgIC8vIEhpZGVzIG1vdXNlIGN1cnNvciBhbmQgYmVnaW5zIHJlbmRlcmluZyBsb29wXG4gICAgICAgIHRoaXMuZG9tLmhzdk1hcC5jbGFzc0xpc3QuYWRkKCdnZV9jb2xvcnBpY2tlcl9uby1jdXJzb3InKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5zdGFydCgpO1xuICAgIH1cblxuICAgIC8vIEFjdGlvbnMgd2hlbiB1c2VyIG1vdmVzIGFyb3VuZCBvbiBIU1YgY29sb3IgbWFwXG4gICAgb25Ic3ZNb3ZlIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICBsZXQgciwgeCwgeSwgaCwgcztcbiAgICAgICAgaWYgKGV2ZW50LnRhcmdldCA9PT0gdGhpcy5kb20uaHN2TWFwQ292ZXIgJiYgY3VycmVudFRhcmdldCA9PT0gdGhpcy5kb20uaHN2TWFwKSB7IC8vIHRoZSBjaXJjbGVcbiAgICAgICAgICAgIHIgPSBjdXJyZW50VGFyZ2V0SGVpZ2h0IC8gMixcbiAgICAgICAgICAgIHggPSBldmVudC5vZmZzZXRYIC0gcixcbiAgICAgICAgICAgIHkgPSBldmVudC5vZmZzZXRZIC0gcixcbiAgICAgICAgICAgIGggPSAoMzYwIC0gKChNYXRoLmF0YW4yKHksIHgpICogMTgwIC8gTWF0aC5QSSkgKyAoeSA8IDAgPyAzNjAgOiAwKSkpIC8gMzYwLFxuICAgICAgICAgICAgcyA9IChNYXRoLnNxcnQoKHggKiB4KSArICh5ICogeSkpIC8gcik7XG4gICAgICAgICAgICB0aGlzLnZhbHVlLnNldCh7IGgsIHMgfSwgJ2hzdicpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2ZW50LnRhcmdldCA9PT0gdGhpcy5kb20uaHN2QmFyQ3Vyc29ycyAmJiBjdXJyZW50VGFyZ2V0ID09PSB0aGlzLmRvbS5oc3ZCYXJDdXJzb3JzKSB7IC8vIHRoZSBsdW1pbmFuY2VCYXJcbiAgICAgICAgICAgIGxldCB2ID0gKGN1cnJlbnRUYXJnZXRIZWlnaHQgLSAoZXZlbnQub2Zmc2V0WSkpIC8gY3VycmVudFRhcmdldEhlaWdodDtcbiAgICAgICAgICAgI
23459HYgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCB2KSkgKiAyNTU7XG4gICAgICAgICAgICB0aGlzLnZhbHVlLnNldCh7IHY6IHYgfSwgJ2hzdicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50cmlnZ2VyKCdjaGFuZ2VkJywgdGhpcy52YWx1ZSk7XG4gICAgfVxuXG4gICAgLy8gQWN0aW9ucyB3aGVuIHVzZXIgbW91c2VzIHVwIG9uIEhTViBjb2xvciBtYXBcbiAgICBvbkhzdlVwIChldmVudCkge1xuICAgICAgICAvLyBTdG9wcyByZW5kZXJpbmcgYW5kIHJldHVybnMgbW91c2UgY3Vyc29yXG4gICAgICAgIHRoaXMucmVuZGVyZXIuc3RvcCgpO1xuICAgICAgICB0aGlzLmRvbS5oc3ZNYXAuY2xhc3NMaXN0LnJlbW92ZSgnZ2VfY29sb3JwaWNrZXJfbm8tY3Vyc29yJyk7XG4gICAgICAgIHRoaXMuZGVzdHJveUV2ZW50cygpO1xuICAgIH1cblxuICAgIC8vIERlc3Ryb3kgZXZlbnQgbGlzdGVuZXJzIHRoYXQgZXhpc3QgZHVyaW5nIG1vdXNlZG93biBjb2xvcnBpY2tlciBpbnRlcmFjdGlvblxuICAgIGRlc3Ryb3lFdmVudHMgKCkge1xuICAgICAgICByZW1vdmVFdmVudCh0aGlzLmVsLCAnbW91c2Vtb3ZlJywgdGhpcy5vbkhzdk1vdmVIYW5kbGVyKTtcbiAgICAgICAgdGhpcy5vbkhzdk1vdmVIYW5kbGVyID0gbnVsbDtcbiAgICAgICAgcmVtb3ZlRXZlbnQod2luZG93LCAnbW91c2V1cCcsIHRoaXMub25Ic3ZVcEhhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uSHN2VXBIYW5kbGVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBjbG9zZSAoKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveUV2ZW50cygpO1xuICAgICAgICByZW1vdmVFdmVudCh0aGlzLmRvbS5oc3ZNYXAsICdtb3VzZWRvd24nLCB0aGlzLm9uSHN2RG93bkhhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uSHN2RG93bkhhbmRsZXIgPSBudWxsO1xuICAgIH1cbn1cblxuLy8gZ2VuZXJpYyBmdW5jdGlvbiBmb3IgZHJhd2luZyBhIGNhbnZhcyBkaXNjXG5mdW5jdGlvbiBkcmF3RGlzayAoY3R4LCBjb29yZHMsIHJhZGl1cywgc3RlcHMsIGNvbG9yQ2FsbGJhY2spIHtcbiAgICBsZXQgeCA9IGNvb3Jkc1swXSB8fCBjb29yZHM7IC8vIGNvb3JkaW5hdGUgb24geC1heGlzXG4gICAgbGV0IHkgPSBjb29yZHNbMV0gfHwgY29vcmRzOyAvLyBjb29yZGluYXRlIG9uIHktYXhpc1xuICAgIGxldCBhID0gcmFkaXVzWzBdIHx8IHJhZGl1czsgLy8gcmFkaXVzIG9uIHgtYXhpc1xuICAgIGxldCBiID0gcmFkaXVzWzFdIHx8IHJhZGl1czsgLy8gcmFkaXVzIG9uIHktYXhpc1xuICAgIGxldCBhbmdsZSA9IDM2MDtcbiAgICBsZXQgY29lZiA9IE1hdGguUEkgLyAxODA7XG5cbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC50cmFuc2xhdGUoeCAtIGEsIHkgLSBiKTtcbiAgICBjdHguc2NhbGUoYSwgYik7XG5cbiAgICBzdGVwcyA9IChhbmdsZSAvIHN0ZXBzKSB8fCAzNjA7XG5cbiAgICBmb3IgKDsgYW5nbGUgPiAwIDsgYW5nbGUgLT0gc3RlcHMpIHtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBpZiAoc3RlcHMgIT09IDM2MCkge1xuICAgICAgICAgICAgY3R4Lm1vdmVUbygxLCAxKTsgLy8gc3Ryb2tlXG4gICAgICAgIH1cbiAgICAgICAgY3R4LmFyYygxLCAxLCAxLFxuICAgICAgICAgICAgKGFuZ2xlIC0gKHN0ZXBzIC8gMikgLSAxKSAqIGNvZWYsXG4gICAgICAgICAgICAoYW5nbGUgKyAoc3RlcHMgLyAyKSArIDEpICogY29lZik7XG5cbiAgICAgICAgaWYgKGNvbG9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNvbG9yQ2FsbGJhY2soY3R4LCBhbmdsZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gJ2JsYWNrJztcbiAgICAgICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cblxuZnVuY3Rpb24gZHJhd0NpcmNsZSAoY3R4LCBjb29yZHMsIHJhZGl1cywgY29sb3IsIHdpZHRoKSB7IC8vIHVzZXMgZHJhd0Rpc2tcbiAgICB3aWR0aCA9IHdpZHRoIHx8IDE7XG4gICAgcmFkaXVzID0gW1xuICAgICAgICAocmFkaXVzWzBdIHx8IHJhZGl1cykgLSB3aWR0aCAvIDIsXG4gICAgICAgIChyYWRpdXNbMV0gfHwgcmFkaXVzKSAtIHdpZHRoIC8gMlxuICAgIF07XG4gICAgZHJhd0Rpc2soY3R4LCBjb29yZHMsIHJhZGl1cywgMSwgZnVuY3Rpb24gKGN0eCwgYW5nbG
23459UpIHtcbiAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IHdpZHRoO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvciB8fCAnIzAwMCc7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9KTtcbn1cbiIsImltcG9ydCBQaWNrZXIgZnJvbSAnLi9QaWNrZXInO1xuaW1wb3J0IEZsb2F0IGZyb20gJy4vdHlwZXMvRmxvYXQnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGbG9hdFBpY2tlciBleHRlbmRzIFBpY2tlciB7XG4gICAgY29uc3RydWN0b3IgKG51bWJlciwgcHJvcGVydGllcykge1xuICAgICAgICBzdXBlcignZ2VfZmxvYXRwaWNrZXJfJywgcHJvcGVydGllcyk7XG5cbiAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMud2lkdGggfHwgMjUwO1xuICAgICAgICB0aGlzLmhlaWdodCA9IHRoaXMuaGVpZ2h0IHx8IDQwO1xuXG4gICAgICAgIHRoaXMucHJldk9mZnNldCA9IDA7XG4gICAgICAgIHRoaXMuc2NhbGUgPSAyO1xuXG4gICAgICAgIHRoaXMuc2V0VmFsdWUobnVtYmVyIHx8IDEpO1xuICAgICAgICB0aGlzLmNyZWF0ZSgpO1xuICAgIH1cblxuICAgIGRyYXcgKCkge1xuICAgICAgICB0aGlzLmN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuXG4gICAgICAgIC8vIGhvcml6b250YWwgbGluZVxuICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IHRoaXMuZGltQ29sb3I7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IDE7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5tb3ZlVG8oMCwgMC41ICsgdGhpcy5oZWlnaHQgKiAwLjUpO1xuICAgICAgICB0aGlzLmN0eC5saW5lVG8oMCArIHRoaXMud2lkdGgsIDAuNSArIHRoaXMuaGVpZ2h0ICogMC41KTtcbiAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpO1xuXG4gICAgICAgIC8vIHZlcnRpY2FsIGxpbmVcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSB0aGlzLmZuQ29sb3I7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IDE7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5tb3ZlVG8odGhpcy53aWR0aCAqIDAuNSwgMCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbyh0aGlzLndpZHRoICogMC41LCB0aGlzLmhlaWdodCk7XG4gICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcblxuICAgICAgICAvLyBUcmlhbmdsZSBsaW5lXG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHRoaXMub3ZlclBvaW50ID8gdGhpcy5zZWxDb2xvciA6IHRoaXMuZm5Db2xvcjtcbiAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4Lm1vdmVUbyh0aGlzLndpZHRoICogMC41LCA1KTtcbiAgICAgICAgdGhpcy5jdHgubGluZVRvKHRoaXMud2lkdGggKiAwLjQ4LCAwKTtcbiAgICAgICAgdGhpcy5jdHgubGluZVRvKHRoaXMud2lkdGggKiAwLjUyLCAwKTtcbiAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGwoKTtcblxuICAgICAgICBsZXQgdGltZXMgPSAzO1xuICAgICAgICBsZXQgdW5pdCA9IDQwO1xuICAgICAgICBsZXQgc3RlcCA9IHRoaXMud2lkdGggLyB1bml0O1xuICAgICAgICBsZXQgc2VjdGlvbnMgPSB1bml0ICogdGltZXM7XG5cbiAgICAgICAgbGV0IG9mZnNldFggPSB0aGlzLm9mZnNldFg7XG5cbiAgICAgICAgaWYgKE1hdGguYWJzKHRoaXMub2Zmc2V0WCAtIHRoaXMud2lkdGggKiAwLjUpID4gdGhpcy53aWR0aCAqIDAuNSkge1xuICAgICAgICAgICAgb2Zmc2V0WCA9ICh0aGlzLm9mZnNldFggLSB0aGlzLndpZHRoICogMC41KSAlICh0aGlzLndpZHRoICogMC41KSArIHRoaXMud2lkdGg7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IHRoaXMuZGltQ29sb3I7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlY3Rpb25zOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBsID0gKGkgJSAodW5pdCAvIDIpID09PSAwKSA/IHRoaXMuaGVpZ2h0ICogMC4zNSA6IChpICUgKHVuaXQgLyA0KSA9PT0gMCkgPyB0aGlzLmhlaWdodCAqIDAuMiA6IHRoaXMuaGVpZ2h0ICogMC4xO1xuICAgICAgICAgICAgdGhpcy5jdHgubW92ZVRvKGkgKiBzdGVwIC0gb2Zmc2V0WCwgdGhpcy5oZWlnaHQgKiAwLjUgLSBsKTtcbiAgICAgICAgICAgIHRoaXMuY3R4LmxpbmVUbyhpICogc3RlcCAtIG9mZnNldFgsIHRoaXMuaGVpZ2h0ICogMC41ICsgbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlKCk7XG5cbiAgICAgICAgbGV0IHZhbCA9IE1hdGgucm91bmQoKCh0aGlzLnZhbHVlIC0gdGhpcy5taW4pIC8gdGhpcy5yYW5nZSkgKiB0aGlzLndpZHRoKTtcblxuICAgICAgICAvLyBwb2ludFxuICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IHRoaXMub3ZlclBvaW50ID8gdGhpcy5zZWxDb2xvciA6IHRoaXMuZm5Db2xvcjtcbiAgICAgICAgdGhpcy5jdHgubGluZVdpZHRoID0gMTtcbiAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4Lm1vdmVUbyh0aGlzLm9mZnNldFggKyB2YWwsIHRoaXMuaGVpZ2h0ICogMC41KTtcbiAgICAgICAgdGhpcy5jdHgubGluZVRvKHRoaXMub2Zmc2V0WCArIHZhbCwgdGhpcy5oZWlnaHQpO1xuICAgICAgICB0aGlzLmN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlKCk7XG5cbiAgICAgICAgdGhpcy5vdmVyUG9pbnQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBvbk1vdXNlRG93biAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5wcmV2T2Zmc2V0ID0gZXZlbnQub2Zmc2V0WDtcbiAgICAgICAgc3VwZXIub25Nb3VzZURvd24oZXZlbnQpO1xuICAgIH1cblxuICAgIC8vIEFjdGlvbnMgd2hlbiB1c2VyIG1vdmVzIGFyb3VuZCBvbiBIU1YgY29sb3IgbWFwXG4gICAgb25Nb3VzZU1vdmUgKGV2ZW50KSB7XG4gICAgICAgIGxldCB4ID0gZXZlbnQub2Zmc2V0WDtcblxuICAgICAgICBsZXQgdmVsID0geCAtI
23459HRoaXMucHJldk9mZnNldDtcbiAgICAgICAgbGV0IG9mZnNldCA9IHRoaXMub2Zmc2V0WCAtIHZlbDtcblxuICAgICAgICBsZXQgY2VudGVyID0gdGhpcy53aWR0aCAvIHRoaXMuc2NhbGU7XG4gICAgICAgIHRoaXMuc2V0VmFsdWUob2Zmc2V0IC8gY2VudGVyKTtcbiAgICAgICAgdGhpcy5wcmV2T2Zmc2V0ID0geDtcblxuICAgICAgICAvLyBmaXJlICdjaGFuZ2VkJ1xuICAgICAgICB2YXIgbnVtYmVyID0gbmV3IEZsb2F0KHRoaXMuZ2V0VmFsdWUoKSk7XG4gICAgICAgIHRoaXMudHJpZ2dlcignY2hhbmdlZCcsIG51bWJlcik7XG4gICAgICAgIHRoaXMub3ZlclBvaW50ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBzZXRWYWx1ZSAodmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGNlbnRlciA9ICh0aGlzLndpZHRoIC8gdGhpcy5zY2FsZSk7XG4gICAgICAgIHRoaXMub2Zmc2V0WCA9IHRoaXMudmFsdWUgKiBjZW50ZXI7XG4gICAgfVxufVxuXG4iLCIvKlxuT3JpZ2luYWw6IGh0dHBzOi8vZ2l0aHViLmNvbS90YW5ncmFtcy90YW5ncmFtLXBsYXkvYmxvYi9naC1wYWdlcy9zcmMvanMvYWRkb25zL3VpL3dpZGdldHMvQ29sb3JQaWNrZXJNb2RhbC5qc1xuQXV0aG9yOiBMb3UgSHVhbmcgKEBzYWlrb2Zpc2gpXG4qL1xuXG5pbXBvcnQgeyBnZXREZXZpY2VQaXhlbFJhdGlvIH0gZnJvbSAnLi4vLi4vdG9vbHMvY29tbW9uJztcbmltcG9ydCB7IHN1YnNjcmliZU1peGluIH0gZnJvbSAnLi4vLi4vdG9vbHMvbWl4aW4nO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQaWNrZXIge1xuICAgIGNvbnN0cnVjdG9yIChDU1NfUFJFRklYLCBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHN1YnNjcmliZU1peGluKHRoaXMpO1xuICAgICAgICB0aGlzLkNTU19QUkVGSVggPSBDU1NfUFJFRklYO1xuXG4gICAgICAgIHRoaXMuYmdDb2xvciA9ICdyZ2IoNDYsIDQ4LCA1MSknO1xuICAgICAgICB0aGlzLmRpbUNvbG9yID0gJ3JnYigxMDAsIDEwMCwgMTAwKSc7XG4gICAgICAgIHRoaXMuZm5Db2xvciA9ICdyZ2IoMjMwLCAyMzAsIDIzMCknO1xuICAgICAgICB0aGlzLnNlbENvbG9yID0gJ3JnYigxMzMsIDIwNCwgMTk2KSc7XG5cbiAgICAgICAgcHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgIGZvciAobGV0IHByb3AgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpc1twcm9wXSA9IHByb3BlcnRpZXNbcHJvcF07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogIFRoaXMgaW5pdGlhbGl6ZXMgdGhlIHJlbmRlcmVyLiBJdCB1c2VzIHJlcXVlc3RBbmltYXRpb25GcmFtZSgpIHRvXG4gICAgICAgICAqICBzbW9vdGhseSByZW5kZXIgY2hhbmdlcyBpbiB0aGUgY29sb3IgcGlja2VyIGFzIHVzZXIgaW50ZXJhY3RzIHdpdGggaXQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnJlbmRlcmVyID0ge1xuICAgICAgICAgICAgLy8gU3RvcmVzIGEgcmVmZXJlbmNlIHRvIHRoZSBhbmltYXRpb24gcmVuZGVyaW5nIGxvb3AuXG4gICAgICAgICAgICBmcmFtZTogbnVsbCxcblxuICAgICAgICAgICAgZHJhd0ZyYW1lOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kcmF3KCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvLyBTdGFydHMgYW5pbWF0aW9uIHJlbmRlcmluZyBsb29wXG4gICAgICAgICAgICBzdGFydDogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuZHJhd0ZyYW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5mcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5yZW5kZXJlci5zdGFydCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvLyBTdG9wcyBhbmltYXRpb24gcmVuZGVyaW5nIGxvb3BcbiAgICAgICAgICAgIHN0b3A6ICgpID0+IHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5yZW5kZXJlci5mcmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaXNWaXNpYmxlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgY3JlYXRlICgpIHtcbiAgICAgICAgdGhpcy5lbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTmFtZSA9IHRoaXMuQ1NTX1BSRUZJWCArICdtb2RhbCBnZV9waWNrZXJfbW9kYWwnO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHRoaXMuYmdDb2xvcjtcblxuICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB0aGlzLmNhbnZhcy5jbGFzc05hbWUgPSB0aGlzLkNTU19QUkVGSVggKyAnY2FudmFzIGdlX3BpY2tlcl9jYW52YXMnO1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLmJnQ29sb3I7XG5cbiAgICAgICAgdGhpcy5lbC5hcHBlbmRDaGlsZCh0aGlzLmNhbnZhcyk7XG4gICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgICBsZXQgcmF0aW8gPSBnZXREZXZpY2VQaXhlbFJhdGlvKHRoaXMuY3R4KTtcbiAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoICogcmF0aW87XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogcmF0aW87XG4gICAgICAgIHRoaXMuY3R4LnNjYWxlKHJhdGlvLCByYXRpbyk7XG4gICAgfVxuXG4gICAgZHJhdyAoKSB7XG4gICAgICAgIC8vIHJlbmRlciBydXRpbmVcbiAgICB9XG5cbiAgICBjbG9zZSAoKSB7XG4gICAgICAgIC8vIENsb3NlIHJ1dGluZVxuICAgICAgICB0aGlzLmRlc3Ryb3lFdmVudHMoKTtcbiAgICAgICAgcmVtb3ZlRXZlbnQodGhpcy5lbCwgJ21vdXNlZG93bicsIHRoaXMub25Nb3VzZURvd25IYW5kbGVyKTtcbiAgICAgICAgdGhpcy5vbk1vdXNlRG93bkhhbmRsZXIgPSBudWxsO1xuICAgIH1cblxuICAgIGRlc3Ryb3lFdmVudHMgKCkge1xuICAgICAgICByZW1vdmVFdmVudCh0aGlzLmVsLCAnbW91c2Vtb3ZlJywgdGhpcy5vbk1vdXNlTW92ZUhhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uTW91c2VNb3ZlSGFuZGxlciA9IG51bGw7XG4gICAgICAgI
23459HJlbW92ZUV2ZW50KHdpbmRvdywgJ21vdXNldXAnLCB0aGlzLm9uTW91c2VVcEhhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uTW91c2VVcEhhbmRsZXIgPSBudWxsO1xuICAgIH1cblxuICAgIHNldFZhbHVlICh2YWx1ZSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgZ2V0VmFsdWUgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG5cbiAgICBzaG93QXQgKGNtKSB7XG4gICAgICAgIGxldCBjdXJzb3IgPSBjbS5jdXJzb3JDb29yZHModHJ1ZSwgJ3BhZ2UnKTtcbiAgICAgICAgbGV0IHggPSBjdXJzb3IubGVmdDtcbiAgICAgICAgbGV0IHkgPSBjdXJzb3IudG9wO1xuXG4gICAgICAgIHggLT0gdGhpcy53aWR0aCAqIDAuNTtcbiAgICAgICAgeSArPSAzMDtcblxuICAgICAgICAvLyAvLyBDaGVjayBpZiBkZXNpcmVkIHgsIHkgd2lsbCBiZSBvdXRzaWRlIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgLy8gLy8gRG8gbm90IGFsbG93IHRoZSBtb2RhbCB0byBkaXNhcHBlYXIgb2ZmIHRoZSBlZGdlIG9mIHRoZSB3aW5kb3cuXG4gICAgICAgIC8vIHggPSAoeCArIHRoaXMud2lkdGggPCB3aW5kb3cuaW5uZXJXaWR0aCkgPyB4IDogKHdpbmRvdy5pbm5lcldpZHRoIC0gMjAgLSB0aGlzLndpZHRoKTtcbiAgICAgICAgLy8geSA9ICh5ICsgdGhpcy5oZWlnaHQgPCB3aW5kb3cuaW5uZXJIZWlnaHQpID8geSA6ICh3aW5kb3cuaW5uZXJIZWlnaHQgLSAyMCAtIHRoaXMuaGVpZ2h0KTtcblxuICAgICAgICB0aGlzLnByZXNlbnRNb2RhbCh4LCB5KTtcbiAgICB9XG5cbiAgICBwcmVzZW50TW9kYWwgKHgsIHkpIHtcbiAgICAgICAgLy8gTGlzdGVuIGZvciBpbnRlcmFjdGlvbiBvdXRzaWRlIG9mIHRoZSBtb2RhbFxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uQ2xpY2tPdXRzaWRlSGFuZGxlciA9IGFkZEV2ZW50KGRvY3VtZW50LmJvZHksICdjbGljaycsIHRoaXMub25DbGlja091dHNpZGUsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbktleVByZXNzSGFuZGxlciA9IGFkZEV2ZW50KHdpbmRvdywgJ2tleWRvd24nLCB0aGlzLm9uS2V5UHJlc3MsIHRoaXMpO1xuICAgICAgICB9LCAwKTtcbiAgICAgICAgdGhpcy5pc1Zpc2libGUgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZWwuc3R5bGUubGVmdCA9IHggKyAncHgnO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLnRvcCA9IHkgKyAncHgnO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgIHRoaXMuZWwuc3R5bGUuaGVpZ2h0ID0gdGhpcy5oZWlnaHQgKyAncHgnO1xuICAgICAgICBkb2
23459N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuZWwpO1xuXG4gICAgICAgIHRoaXMub25Nb3VzZURvd25IYW5kbGVyID0gYWRkRXZlbnQodGhpcy5lbCwgJ21vdXNlZG93bicsIHRoaXMub25Nb3VzZURvd24sIHRoaXMpO1xuXG4gICAgICAgIHRoaXMucmVuZGVyZXIuZHJhd0ZyYW1lKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIFJlbW92ZXMgbW9kYWwgZnJvbSBET00gYW5kIGRlc3Ryb3lzIHJlbGF0ZWQgZXZlbnQgbGlzdGVuZXJzXG4gICAgICovXG4gICAgcmVtb3ZlTW9kYWwgKCkge1xuICAgICAgICBpZiAodGhpcy5lbCAmJiB0aGlzLmVsLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmVsKTtcbiAgICAgICAgfVxuICAgICAgICByZW1vdmVFdmVudChkb2N1bWVudC5ib2R5LCAnY2xpY2snLCB0aGlzLm9uQ2xpY2tPdXRzaWRlSGFuZGxlcik7XG4gICAgICAgIHRoaXMub25DbGlja091dHNpZGVIYW5kbGVyID0gbnVsbDtcbiAgICAgICAgcmVtb3ZlRXZlbnQod2luZG93LCAna2V5ZG93bicsIHRoaXMub25LZXlQcmVzc0hhbmRsZXIpO1xuICAgICAgICB0aGlzLm9uS2V5UHJlc3NIYW5kbGVyID0gbnVsbDtcblxuICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgIHRoaXMuaXNWaXNpYmxlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgb25LZXlQcmVzcyAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVNb2RhbCgpO1xuICAgIH1cblxuICAgIG9uQ2xpY2tPdXRzaWRlIChldmVudCkge1xuICAgICAgICAvLyBIQUNLWSEhXG4gICAgICAgIC8vIEEgY2xpY2sgZXZlbnQgZmlyZXMgb24gdGhlIGJvZHkgYWZ0ZXIgbW91c2Vkb3duIC0gbW91c2Vtb3ZlLCBzaW11bHRhbmVvdXNseSB3aXRoXG4gICAgICAgIC8vIG1vdXNldXAuIFNvIGlmIHNvbWVvbmUgc3RhcnRlZCBhIG1vdXNlIGFjdGlvbiBpbnNpZGUgdGhlIG1vZGFsIGFuZCB0aGVuXG4gICAgICAgIC8vIG1vdXNldXAnZCBvdXRzaWRlIG9mIGl0LCBpdCBmaXJlcyBhIGNsaWNrIGV2ZW50IG9uIHRoZSBib2R5LCB0aHVzLCBjYXVzaW5nIHRoZVxuICAgICAgICAvLyBtb2RhbCB0byBkaXNhcHBlYXIgd2hlbiB0aGUgdXNlciBkb2VzIG5vdCBleHBlY3QgaXQgdG8sIHNpbmNlIHRoZSBtb3VzZSBkb3duIGV2ZW50XG4gICAgICAgIC8vIGRpZCBub3Qgc3RhcnQgb3V0c2lkZSB0aGUgbW9kYWwuXG4gICAgICAgIC8vIFRoZXJlIG1pZ2h0IGJlIChvciBzaG91bGQgYmUpIGEgYmV0dGVyIHdheSB0byB0cmFjayB0aGlzLCBidXQgcmlnaHQgbm93LCBqdXN0IGNhbmNlbFxuICAgICAgICAvLyB0aGUgZXZlbnQgaWYgdGhlIHRhcmdldCBlbmRzIHVwIGJlaW5nIG9uIHRoZSBib2R5IGRpcmVjdGx5IHJhdGhlciB0aGFuIG9uIG9uZSBvZiB0aGVcbiAgICAgICAgLy8gb3RoZXIgY2hpbGQgZWxlbWVudHMuXG4gICAgICAgIGlmIChldmVudC50YXJnZXQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBlbmQgdGhpcyBzcGVjaWZpYyBoYWNreSBwYXJ0XG5cbiAgICAgICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgICB3aGlsZSAodGFyZ2V0ICE9PSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgIXRhcmdldC5jbGFzc0xpc3QuY29udGFpbnModGhpcy5DU1NfUFJFRklYICsgJ21vZGFsJykpIHtcbiAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKHRoaXMuQ1NTX1BSRUZJWCArICdtb2RhbCcpKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZU1vZGFsKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbk1vdXNlRG93biAoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAvLyBTdGFydHMgbGlzdGVuaW5nIGZvciBtb3VzZW1vdmUgYW5kIG1vdXNldXAgZXZlbnRzXG4gICAgICAgIHRoaXMub25Nb3VzZU1vdmVIYW5kbGVyID0gYWRkRXZlbnQodGhpcy5lbCwgJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUsIHRoaXMpO1xuICAgICAgICB0aGlzLm9uTW91c2VVcEhhbmRsZXIgPSBhZGRFdmVudCh3aW5kb3csICdtb3VzZXVwJywgdGhpcy5vbk1vdXNlVXAsIHRoaXMpO1xuXG4gICAgICAgIHRoaXMub25Nb3VzZU1vdmUoZXZlbnQpO1xuXG4gICAgICAgIHRoaXMucmVuZGVyZXIuc3RhcnQoKTtcbiAgICB9XG5cbiAgICBvbk1vdXNlTW92ZSAoZXZlbnQpIHtcbiAgICB9XG5cbiAgICBvbk1vdXNlVXAgKGV2ZW50KSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc3RvcCgpO1xuICAgICAgICB0aGlzLmRlc3Ryb3lFdmVudHMoKTtcbiAgICB9XG59XG5cbi8qIEV2ZW50IGhhbmRsaW5nICovXG5leHBvcnQgZnVuY3Rpb24gYWRkRXZlbnQgKGVsZW1lbnQsIGV2ZW50LCBjYWxsYmFjaywgY2FsbGVyKSB7XG4gICAgbGV0IGhhbmRsZXI7XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgY2FsbGJhY2suY2FsbChjYWxsZXIsIGUpO1xuICAgIH0sIGZhbHNlKTtcbiAgICByZXR1cm4gaGFuZGxlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUV2ZW50IChlbGVtZW50LCBldmVudCwgY2FsbGJhY2spIHtcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGNhbGxiYWNrLCBmYWxzZSk7XG59XG4iLCJpbXBvcnQgUGlja2VyIGZyb20gJy4vUGlja2VyJztcbmltcG9ydCBWZWN0b3IgZnJvbSAnLi90eXBlcy9WZWN0b3InO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWMyUGlja2VyIGV4dGVuZHMgUGlja2VyIHtcbiAgICBjb25zdHJ1Y3RvciAocG9zLCBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHN1cGVyKCdnZV92ZWMycGlja2VyXycsIHByb3BlcnRpZXMpO1xuXG4gICAgICAgIHRoaXMud2lkdGggPSB0aGlzLndpZHRoIHx8IDIwMDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLmhlaWdodCB8fCAyMDA7XG5cbiAgICAgICAgdGhpcy5taW4gPSB0aGlzLm1pbiB8fCAtMTtcbiAgICAgICAgdGhpcy5tYXggPSB0aGlzLm1heCB8fCAxO1xuICAgICAgICB0aGlzLnNpemUgPSB0aGlzLnNpemUgfHwgNjtcbiAgICAgICAgdGhpcy5yYW5nZSA9IHRoaXMubWF4IC0gdGhpcy5taW47XG4gICAgICAgI
23459HRoaXMub3ZlclBvaW50ID0gZmFsc2U7XG5cbiAgICAgICAgbGV0IGNlbnRlciA9ICgodGhpcy5yYW5nZSAvIDIpIC0gdGhpcy5tYXgpICogLTE7XG4gICAgICAgIHRoaXMuc2V0VmFsdWUocG9zIHx8IFtjZW50ZXIsY2VudGVyXSk7XG4gICAgICAgIHRoaXMuY3JlYXRlKCk7XG4gICAgfVxuXG4gICAgZHJhdyAoKSB7XG4gICAgICAgIHRoaXMuY3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cbiAgICAgICAgLy8gZnJhbWVcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSB0aGlzLmRpbUNvbG9yO1xuICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSAyO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2VSZWN0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcblxuICAgICAgICB0aGlzLmN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHgubGluZVdpZHRoID0gMC4yNTtcbiAgICAgICAgbGV0IHNlY3Rpb25zID0gMjA7XG4gICAgICAgIGxldCBzdGVwID0gdGhpcy53aWR0aCAvIHNlY3Rpb25zO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlY3Rpb25zOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuY3R4Lm1vdmVUbyhpICogc3RlcCwgMCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5saW5lVG8oaSAqIHN0ZXAsIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuY3R4Lm1vdmVUbygwLCBpICogc3RlcCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5saW5lVG8odGhpcy53aWR0aCwgaSAqIHN0ZXApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpO1xuXG4gICAgICAgIC8vIGhvcml6b250YWwgbGluZVxuICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IHRoaXMuZGltQ29sb3I7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IDEuMDtcbiAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4Lm1vdmVUbygwLCAwLjUgKyB0aGlzLmhlaWdodCAqIDAuNSk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbyh0aGlzLndpZHRoLCAwLjUgKyB0aGlzLmhlaWdodCAqIDAuNSk7XG4gICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcblxuICAgICAgICAvLyB2ZXJ0aWNhbCBsaW5lXG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5tb3ZlVG8oMC41ICsgdGhpcy53aWR0aCAqIDAuNSwgMCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbygwLjUgKyB0aGlzLndpZHRoICogMC41LCB0aGlzLmhlaWdodCk7XG4gICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcblxuICAgICAgICAvLyAvLyBUcmlhbmdsZSBsaW5lXG4gICAgICAgIC8vIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHRoaXMuZGltQ29sb3I7XG4gICAgICAgIC8vIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5tb3ZlVG8odGhpcy53aWR0aCAqIDAuNSwgNSk7XG4gICAgICAgIC8vIHRoaXMuY3R4LmxpbmVUbyh0aGlzLndpZHRoICogMC40OCwgMCk7XG4gICAgICAgIC8vIHRoaXMuY3R4LmxpbmVUbyh0aGlzLndpZHRoICogMC41MiwgMCk7XG4gICAgICAgIC8vIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5maWxsKCk7XG5cbiAgICAgICAgbGV0IHggPSBNYXRoLnJvdW5kKCgodGhpcy52YWx1ZS54IC0gdGhpcy5taW4pIC8gdGhpcy5yYW5nZSkgKiB0aGlzLndpZHRoKTtcbiAgICAgICAgbGV0IHkgPSBNYXRoLnJvdW5kKCgoMSAtICh0aGlzLnZhbHVlLnkgLSB0aGlzLm1pbikgLyB0aGlzLnJhbmdlKSkgKiB0aGlzLmhlaWdodCk7XG5cbiAgICAgICAgbGV0IGhhbGYgPSB0aGlzLnNpemUgLyAyO1xuXG4gICAgICAgIGlmICh4IDwgaGFsZikge1xuICAgICAgICAgICAgeCA9IGhhbGY7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHggPiB0aGlzLndpZHRoIC0gaGFsZikge1xuICAgICAgICAgICAgeCA9IHRoaXMud2lkdGggLSBoYWxmO1xuICAgICAgICB9XG4gICAgICAgIGlmICh5IDwgaGFsZikge1xuICAgICAgICAgICAgeSA9IGhhbGY7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHkgPiB0aGlzLmhlaWdodCAtIGhhbGYpIHtcbiAgICAgICAgICAgIHkgPSB0aGlzLmhlaWdodCAtIGhhbGY7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwb2ludFxuICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSB0aGlzLm92ZXJQb2ludCA/IHRoaXMuc2VsQ29sb3IgOiB0aGlzLmZuQ29sb3I7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBsZXQgcmFkaXVzID0gdGhpcy5vdmVyUG9pbnQgPyA0IDogMjtcbiAgICAgICAgdGhpcy5jdHguYXJjKHgsIHksIHJhZGl1cywgMCwgMiAqIE1hdGguUEksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jdHguZmlsbCgpO1xuXG4gICAgICAgIHRoaXMuY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgdGhpcy5vdmVyUG9pbnQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBBY3Rpb25zIHdoZW4gdXNlciBtb3ZlcyBhcm91bmQgb24gSFNWIGNvbG9yIG1hcFxuICAgIG9uTW91c2VNb3ZlIChldmVudCkge1xuICAgICAgICBsZXQgeCA9IGV2ZW50Lm9mZnNldFg7XG4gICAgICAgIGxldCB5ID0gZXZlbnQub2Zmc2V0WTtcblxuICAgICAgICB0aGlzLnZhbHVlLnggPSAoKHRoaXMucmFuZ2UgLyB0aGlzLndpZHRoKSAqIHgpIC0gKHRoaXMucmFuZ2UgLSB0aGlzLm1heCk7XG4gICAgICAgIHRoaXMudmFsdWUueSA9ICgoKHRoaXMucmFuZ2UgLyB0aGlzLmhlaWdodCkgKiB5KSAtICh0aGlzLnJhbmdlIC0gdGhpcy5tYXgpKSAqIC0xO1xuXG4gICAgICAgIC8vIGZpcmUgJ2NoYW5nZWQnXG4gICAgICAgIHRoaXMudHJpZ2dlcignY2hhbmdlZCcsIHRoaXMudmFsdWUpO1xuICAgICAgICB0aGlzLm92ZXJQb2ludCA9IHRydWU7XG4gICAgfVxuXG4gICAgc2V0VmFsdWUgKHBvcykge1xuICAgICAgICB0aGlzLnZhbHVlID0gbmV3IFZlY3Rvcihwb3MpO1xuICAgIH1cbn1cbiIsImltcG9ydCBQaWNrZXIgZnJvbSAnLi9QaWNrZXInO1xuaW1wb3J0IFZlY3RvciBmcm9tICcuL3R5cGVzL1ZlY3Rvcic7XG5pbXBvcnQgTWF0cml4IGZyb20gJy4vdHlwZXMvTWF0cml4JztcbmltcG9ydCB7
23459IGFkZEV2ZW50LCByZW1vdmVFdmVudCB9IGZyb20gJy4vUGlja2VyJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmVjM1BpY2tlciBleHRlbmRzIFBpY2tlciB7XG4gICAgY29uc3RydWN0b3IgKGRpciwgcHJvcGVydGllcykge1xuICAgICAgICBzdXBlcignZ2VfdmVjM3BpY2tlcl8nLCBwcm9wZXJ0aWVzKTtcblxuICAgICAgICB0aGlzLndpZHRoID0gdGhpcy53aWR0aCB8fCAyMDA7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy53aWR0aCB8fCAyMDA7XG4gICAgICAgIHRoaXMuc2NhbGUgPSA1MDtcblxuICAgICAgICB0aGlzLnNldFZhbHVlKGRpciB8fCBbMCwgMCwgMV0pO1xuICAgICAgICB0aGlzLmNyZWF0ZSgpO1xuXG4gICAgICAgIHRoaXMuY2FtZXJhID0gbmV3IE1hdHJpeCgpO1xuICAgICAgICB0aGlzLnNoYXBlcyA9IFtdO1xuICAgICAgICB0aGlzLmNlbnRlciA9IFswLCAwLCAwXTtcblxuICAgICAgICB0aGlzLnNoYXBlcy5wdXNoKHtcbiAgICAgICAgICAgIGVkZ2VDb2xvdXI6IHRoaXMuZGltQ29sb3IsXG4gICAgICAgICAgICBub2RlczogW1t0aGlzLndpZHRoIC8gMiAtIDUwLCB0aGlzLmhlaWdodCAvIDIsIDEwMF0sIFt0aGlzLndpZHRoIC8gMiArIDUwLCB0aGlzLmhlaWdodCAvIDIsIDEwMF0sXG4gICAgICAgICAgICAgICAgW3RoaXMud2lkdGggLyAyLCB0aGlzLmhlaWdodCAvIDIgLSA1MCwgMTAwXSwgW3RoaXMud2lkdGggLyAyLCB0aGlzLmhlaWdodCAvIDIgKyA1MCwgMTAwXSxcbiAgICAgICAgICAgICAgICBbdGhpcy53aWR0aCAvIDIsIHRoaXMuaGVpZ2h0IC8gMiwgNTBdLCBbdGhpcy53aWR0aCAvIDIsIHRoaXMuaGVpZ2h0IC8gMiwgMTUwXV0sXG4gICAgICAgICAgICBlZGdlczogW1swLDFdLCBbMiwzXSwgWzQsNV1dXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuc2hhcGVzLnB1c2goe1xuICAgICAgICAgICAgdGV4dENvbG91cjogdGhpcy5mbkNvbG9yLFxuICAgICAgICAgICAgbm9kZXM6IFtbdGhpcy53aWR0aCAvIDIgKyA2OCwgdGhpcy5oZWlnaHQgLyAyLCAxMDBdLCBbdGhpcy53aWR0aCAvIDIgLSA2OCwgdGhpcy5oZWlnaHQgLyAyLCAxMDBdLFxuICAgICAgICAgICAgICAgIFt0aGlzLndpZHRoIC8gMiwgdGhpcy5oZWlnaHQgLyAyICsgNjgsIDEwMF0sIFt0aGlzLndpZHRoIC8gMiwgdGhpcy5oZWlnaHQgLyAyIC0gNjgsIDEwMF0sXG4gICAgICAgICAgICAgICAgW3RoaXMud2lkdGggLyAyLCB0aGlzLmhlaWdodCAvIDIsIDE2OF0sIFt0aGlzLndpZHRoIC8gMiwgdGhpcy5oZWlnaHQgLyAyLCAzMl1dLFxuICAgICAgICAgICAgdGV4dDogWyd4JywgJy14JywgJ3knLCAnLXknLCAneicsICcteiddXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuc2V0Q2VudGVyKHRoaXMud2lkdGggLyAyLCB0aGlzLmhlaWdodCAvIDIsIDEwMCk7XG5cbiAgICAgICAgLy8gTW91c2UgZXZlbnRzXG4gICAgICAgIHRoaXMuZHJhZ09mZnNldCA9IFswLCAwXTtcbiAgICAgICAgdGhpcy5vdmVyUG9pbnQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBzZXRDZW50ZXIgKHgsIHksIHopIHtcbiAgICAgICAgZm9yIChsZXQgcyBpbiB0aGlzLnNoYXBlcykge1xuICAgICAgICAgICAgbGV0IHNoYXBlID0gdGhpcy5zaGFwZXNbc107XG5cbiAgICAgICAgICAgIGZvciAobGV0IG4gaW4gc2hhcGUubm9kZXMpIHtcbiAgICAgICAgICAgICAgICBzaGFwZS5ub2Rlc1tuXVswXSAtPSB4O1xuICAgICAgICAgICAgICAgIHNoYXBlLm5vZGVzW25dWzFdIC09IHk7XG4gICAgICAgICAgICAgICAgc2hhcGUubm9kZXNbbl1bMl0gLT0gejtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNlbnRlciA9IFt4LCB5LCB6XTtcbiAgICB9XG5cbiAgICB2aWV3RnJvbUNhbWVyYSAobm9kZSkge1xuICAgICAgICBsZXQgQSA9IHRoaXMuY2FtZXJhLmdldE11bHQobm9kZSk7XG4gICAgICAgIEEuYWRkKHRoaXMuY2VudGVyKTtcbiAgICAgICAgcmV0dXJuIFtBLngsIHRoaXMuaGVpZ2h0IC0gQS55XTtcbiAgICB9XG5cbiAgICBkcmF3ICgpIHtcbiAgICAgICAgdGhpcy5jdHguY2xlYXJSZWN0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcblxuICAgICAgICBmb3IgKGxldCBzIGluIHRoaXMuc2hhcGVzKSB7XG4gICAgICAgICAgICBsZXQgc2hhcGUgPSB0aGlzLnNoYXBlc1tzXTtcbiAgICAgICAgICAgIGlmIChzaGFwZS5lZGdlQ29sb3VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmF3U2hhcGVFZGdlcyhzaGFwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hhcGUubm9kZUNvbG91cikge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhd1NoYXBlTm9kZXMoc2hhcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNoYXBlLnRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYXdTaGFwZVRleHQoc2hhcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kcmF3U2hhcGVFZGdlcyh7XG4gICAgICAgICAgICBlZGdlQ29sb3VyOiB0aGlzLmZuQ29sb3IsXG4gICAgICAgICAgICBub2RlczogW1swLDAsMF0sIHRoaXMucG9pbnRdLFxuICAgICAgICAgICAgZWRnZXM6IFtbMCwxXV1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5kcmF3U2hhcGVOb2Rlcyh7XG4gICAgICAgICAgICBub2RlQ29sb3VyOiB0aGlzLm92ZXJQb2ludCA/IHRoaXMuc2VsQ29sb3IgOiB0aGlzLmZuQ29sb3IsXG4gICAgICAgICAgICBub2RlUmFkaXVzOiB0aGlzLm92ZXJQb2ludCA/IDQgOiAyLFxuICAgICAgICAgICAgbm9kZXM6IFt0aGlzLnBvaW50XVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBkcmF3U2hhcGVFZGdlcyAoc2hhcGUpIHtcbiAgICAgICAgbGV0IG5vZGVzID0gc2hhcGUubm9kZXM7XG5cbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBzaGFwZS5lZGdlQ29sb3VyO1xuICAgICAgICBmb3IgKGxldCBlIGluIHNoYXBlLmVkZ2VzKSB7XG4gICAgICAgICAgICBsZXQgY29vcmQgPSB0aGlzLnZpZXdGcm9tQ2FtZXJhKG5vZGVzW3NoYXBlLmVkZ2VzW2VdWzBdXSk7XG4gICAgICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSAxO1xuICAgICAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5tb3ZlVG8oY29vcmRbMF0sIGNvb3JkWzFdKTtcbiAgICAgICAgICAgIGNvb3JkID0gdGh
23459pcy52aWV3RnJvbUNhbWVyYShub2Rlc1tzaGFwZS5lZGdlc1tlXVsxXV0pO1xuICAgICAgICAgICAgdGhpcy5jdHgubGluZVRvKGNvb3JkWzBdLCBjb29yZFsxXSk7XG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRyYXdTaGFwZU5vZGVzIChzaGFwZSkge1xuICAgICAgICBsZXQgcmFkaXVzID0gc2hhcGUubm9kZVJhZGl1cyB8fCA0O1xuICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSBzaGFwZS5ub2RlQ29sb3VyO1xuICAgICAgICBmb3IgKGxldCBuIGluIHNoYXBlLm5vZGVzKSB7XG4gICAgICAgICAgICBsZXQgY29vcmQgPSB0aGlzLnZpZXdGcm9tQ2FtZXJhKHNoYXBlLm5vZGVzW25dKTtcbiAgICAgICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgdGhpcy5jdHguYXJjKGNvb3JkWzBdLCBjb29yZFsxXSwgcmFkaXVzLCAwICwgMiAqIE1hdGguUEksIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuY3R4LmZpbGwoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRyYXdTaGFwZVRleHQgKHNoYXBlKSB7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHNoYXBlLnRleHRDb2xvdXI7XG4gICAgICAgIGZvciAobGV0IG4gaW4gc2hhcGUubm9kZXMpIHtcbiAgICAgICAgICAgIGxldCBjb29yZCA9IHRoaXMudmlld0Zyb21DYW1lcmEoc2hhcGUubm9kZXNbbl0pO1xuICAgICAgICAgICAgdGhpcy5jdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgICAgICB0aGlzLmN0eC5maWxsVGV4dChzaGFwZS50ZXh0W25dLCBjb29yZFswXSwgY29vcmRbMV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25Nb3VzZURvd24gKGV2ZW50KSB7XG4gICAgICAgIGxldCBtb3VzZSA9IFtldmVudC5vZmZzZXRYLCBldmVudC5vZmZzZXRZXTtcbiAgICAgICAgdGhpcy5kcmFnT2Zmc2V0ID0gbW91c2U7XG5cbiAgICAgICAgbGV0IHBvcyA9IG5ldyBWZWN0b3IodGhpcy52aWV3RnJvbUNhbWVyYSh0aGlzLnBvaW50KSk7XG4gICAgICAgIGxldCBkaWZmID0gcG9zLmdldFN1Yihtb3VzZSk7XG4gICAgICAgIHRoaXMub3ZlclBvaW50ID0gZGlmZi5nZXRMZW5ndGgoKSA8IDEwO1xuXG4gICAgICAgIHN1cGVyLm9uTW91c2VEb3duKGV2ZW50KTtcbiAgICAgICAgdGhpcy5vbk1vdXNlVXBIYW5kbGVyID0gYWRkRXZlbnQodGhpcy5lbCwgJ2RibGNsaWNrJywgdGhpcy5vbkRiQ2xpY2ssIHRoaXMpO1xuICAgIH1cblxuICAgIC8vIEFjdGlvbnMgd2hlbiB1c2VyIG1vdmVzIGFyb3VuZCBvbiBIU1YgY29sb3IgbWFwXG4gICAgb25Nb3VzZU1vdmUgKGV2ZW50KSB7XG4gICAgICAgIGxldCB4ID0gZXZlbnQub2Zmc2V0WDtcbiAgICAgICAgbGV0IHkgPSBldmVudC5vZmZzZXRZO1xuXG4gICAgICAgIHZhciBkeCA9IDAuMDEgKiAoeCAtIHRoaXMuZHJhZ09mZnNldFswXSk7XG4gICAgICAgIHZhciBkeSA9IDAuMDEgKiAoeSAtIHRoaXMuZHJhZ09mZnNldFsxXSk7XG5cbiAgICAgICAgaWYgKHRoaXMub3ZlclBvaW50KSB7XG4gICAgICAgICAgICBsZXQgaW52TSA9IHRoaXMuY2FtZXJhLmdldEludigpO1xuICAgICAgICAgICAgbGV0IHZlbCA9IGludk0uZ2V0TXVsdChbZHgsIC1keSwgMC4wXSk7XG4gICAgICAgICAgICB2ZWwubXVsdCgyKTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUuYWRkKHZlbCk7XG4gICAgICAgICAgICB0aGlzLnBvaW50ID0gW3RoaXMudmFsdWUueCAqIHRoaXMuc2NhbGUsIHRoaXMudmFsdWUueSAqIHRoaXMuc2NhbGUsIHRoaXMudmFsdWUueiAqIHRoaXMuc2NhbGVdO1xuICAgICAgICAgICAgLy8gZmlyZSAnY2hhbmdlZCdcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlcignY2hhbmdlZCcsIHRoaXMudmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jYW1lcmEucm90YXRlWChkeSk7XG4gICAgICAgICAgICB0aGlzLmNhbWVyYS5yb3RhdGVZKGR4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZHJhZ09mZnNldCA9IFt4LCB5XTtcbiAgICB9XG5cbiAgICBvbkRiQ2xpY2sgKGV2ZW50KSB7XG4gICAgICAgIGxldCBtb3VzZSA9IG5ldyBWZWN0b3IoW2V2ZW50Lm9mZnNldFgsIGV2ZW50Lm9mZnNldFldKTtcbiAgICAgICAgbGV0IGF4aXMgPSB7XG4gICAgICAgICAgICB4OiBbNjgsIDAsIDBdLFxuICAgICAgICAgICAgbmVnWDogWy02OCwgMCwgMF0sXG4gICAgICAgICAgICB5OiBbMCwgNjgsIDEwMF0sXG4gICAgICAgICAgICBuZWdZOiBbMCwgLTY4LCAwXVxuICAgICAgICB9O1xuICAgICAgICBsZXQgc2VsZWN0ZWQgPSAnJztcbiAgICAgICAgZm9yIChsZXQgaSBpbiBheGlzKSB7XG4gICAgICAgICAgICBsZXQgcG9zID0gbmV3IFZlY3Rvcih0aGlzLnZpZXdGcm9tQ2FtZXJhKGF4aXNbaV0pKTtcbiAgICAgICAgICAgIGxldCBkaWZmID0gcG9zLmdldFN1Yihtb3VzZSk7XG4gICAgICAgICAgICBpZiAoZGlmZi5nZXRMZW5ndGgoKSA8IDEwKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQgPSBpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FtZXJhID0gbmV3IE1hdHJpeCgpO1xuXG4gICAgICAgIGlmIChzZWxlY3RlZCA9PT0gJ3gnKSB7XG4gICAgICAgICAgICB0aGlzLmNhbWVyYS5yb3RhdGVZKC0xLjU3MDc5NjMyNjc5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChzZWxlY3RlZCA9PT0gJ25lZ1gnKSB7XG4gICAgICAgICAgICB0aGlzLmNhbWVyYS5yb3RhdGVZKDEuNTcwNzk2MzI2NzkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNlbGVjdGVkID09PSAneScpIHtcbiAgICAgICAgICAgIHRoaXMuY2FtZXJhLnJvdGF0ZVgoLTEuNTcwNzk2MzI2NzkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNlbGVjdGVkID09PSAnbmVnWScpIHtcbiAgICAgICAgICAgIHRoaXMuY2FtZXJhLnJvdGF0ZVgoMS41NzA3OTYzMjY3OSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRyYXcoKTtcbiAgICB9XG5cbiAgICBkZXN0cm95RXZlbnRzICgpIHtcbiAgICAgICAgc3VwZXIuZGVzdHJveUV2ZW50cygpO1xuICAgICAgICByZW1vdmVFdmVudCh0aGlzLmVsLCAnZGJsY2xpY2snLCB0aGlzLm9uRGJDbGljayk7XG4gICAgICAgI
23459HRoaXMub25Nb3VzZU1vdmVIYW5kbGVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBzZXRWYWx1ZSAoZGlyKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBuZXcgVmVjdG9yKGRpcik7XG4gICAgICAgIHRoaXMucG9pbnQgPSBbdGhpcy52YWx1ZS54ICogdGhpcy5zY2FsZSwgdGhpcy52YWx1ZS55ICogdGhpcy5zY2FsZSwgdGhpcy52YWx1ZS56ICogdGhpcy5zY2FsZV07XG4gICAgfVxufVxuIiwiaW1wb3J0IENvbG9yQ29udmVydGVyIGZyb20gJy4vQ29sb3JDb252ZXJ0ZXInO1xuaW1wb3J0IHsgZ2V0Q29sb3JBc1JHQiwgZ2V0VmFsdWVSYW5nZXMsIGdldEx1bWluYW5jZSwgbGltaXRWYWx1ZSB9IGZyb20gJy4vQ29sb3JDb252ZXJ0ZXInO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xvciB7XG4gICAgY29uc3RydWN0b3IgKGNvbG9yKSB7XG4gICAgICAgIHRoaXMuY29sb3JzID0ge307XG4gICAgICAgIHRoaXMuc2V0KGNvbG9yKTtcbiAgICB9XG5cbiAgICBzZXQgKGNvbG9yLCB0eXBlKSB7IC8vIGNvbG9yIG9ubHkgZnVsbCByYW5nZVxuICAgICAgICBpZiAodHlwZW9mIGNvbG9yID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgdHlwZSA9IHR5cGUgPyB0eXBlIDogJ3JnYic7XG4gICAgICAgICAgICB0aGlzLmNvbG9yc1t0eXBlXSA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgbiA9IDM7IG4tLTspIHtcbiAgICAgICAgICAgICAgICBsZXQgbSA9IHR5cGVbbl0gfHwgdHlwZS5jaGFyQXQobik7IC8vIElFN1xuICAgICAgICAgICAgICAgIHRoaXMuY29sb3JzW3R5cGVdW21dID0gY29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGNvbG9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbGV0IHBhcnRzID0gY29sb3IucmVwbGFjZSgvKD86I3xcXCl8JSkvZywgJycpLnNwbGl0KCcoJyk7XG4gICAgICAgICAgICBpZiAocGFydHNbMV0pIHtcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWVzID0gKHBhcnRzWzFdIHx8ICcnKS5zcGxpdCgvLFxccyovKTtcbiAgICAgICAgICAgICAgICB0eXBlID0gdHlwZSA/IHR5cGUgOiAocGFydHNbMV0gPyBwYXJ0c1swXS5zdWJzdHIoMCwgMykgOiAncmdiJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXQodmFsdWVzLCB0eXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0KGdldENvbG9yQXNSR0IoY29sb3IpLCAncmdiJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29sb3IpIHtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9yKSkge1xuICAgICAgICAgICAgICAgIGxldCBtID0gJyc7XG4gICAgICAgICAgICAgICAgdHlwZSA9IHR5cGUgfHwgJ3JnYic7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yc1t0eXBlXSA9IHRoaXMuY29sb3JzW3R5cGVdIHx8IHt9O1xuICAgICAgICAgICAgICAgIGZvciAobGV0IG4gPSAzOyBuLS07KSB7XG4gICAgICAgICAgICAgICAgICAgIG0gPSB0eXBlW25dIHx8IHR5cGUuY2hhckF0KG4pOyAvLyBJRTdcbiAgICAgICAgICAgICAgICAgICAgbGV0IGkgPSBjb2xvci5sZW5ndGggPj0gMyA/IG4gOiAwO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yc1t0eXBlXVttXSA9IHBhcnNlRmxvYXQoY29sb3JbaV0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjb2xvci5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2xvcnMuYWxwaGEgPSBwYXJzZUZsb2F0KGNvbG9yWzNdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgbiBpbiBjb2xvcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yc1t0eXBlXVtuXSA9IGxpbWl0VmFsdWUoY29sb3Jbbl0gLyBnZXRWYWx1ZVJhbmdlcyh0eXBlKVtuXVsxXSwgMCwgMSkgKiBnZXRWYWx1ZVJhbmdlcyh0eXBlKVtuXVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlICE9PSAncmdiJykge1xuICAgICAgICAgICAgdmFyIGNvbnZlcnQgPSBDb2xvckNvbnZlcnRlcjtcbiAgICAgICAgICAgIHRoaXMuY29sb3JzLnJnYiA9IGNvbnZlcnRbdHlwZSArICcycmdiJ10odGhpcy5jb2xvcnNbdHlwZV0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udmVydCh0eXBlKTtcbiAgICAgICAgdGhpcy5jb2xvcnMuaHVlUkdCID0gQ29sb3JDb252ZXJ0ZXIuaHVlMlJHQih0aGlzLmNvbG9ycy5oc3YuaCk7XG4gICAgICAgIHRoaXMuY29sb3JzLmx1bWluYW5jZSA9IGdldEx1bWluYW5jZSh0aGlzLmNvbG9ycy5yZ2IpO1xuICAgIH1cblxuICAgIGNvbnZlcnQgKHR5cGUpIHtcbiAgICAgICAgbGV0IGNvbnZlcnQgPSBDb2xvckNvbnZlcnRlcixcbiAgICAgICAgICAgIHJhbmdlcyA9IGdldFZhbHVlUmFuZ2VzKCksXG4gICAgICAgICAgICBleGNlcHRpb25zID0geyBoc2w6ICdoc3YnLCBjbXlrOiAnY215JywgcmdiOiB0eXBlIH07XG5cbiAgICAgICAgaWYgKHR5cGUgIT09ICdhbHBoYScpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHR5cCBpbiByYW5nZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXJhbmdlc1t0eXBdW3R5cF0pIHsgLy8gbm8gYWxwaGF8SEVYXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlICE9PSB0eXAgJiYgdHlwICE9PSAnWFlaJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZyb20gPSBleGNlcHRpb25zW3R5cF0gfHwgJ3JnYic7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yc1t0eXBdID0gY29udmVydFtmcm9tICsgJzInICsgdHlwXSh0aGlzLmNvbG9yc1tmcm9tXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXQgKHR5cGUpIHtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdyZ2InKSB7XG4gICAgICAgICAgICB2Y
23459XIgY29udmVydCA9IENvbG9yQ29udmVydGVyO1xuICAgICAgICAgICAgdGhpcy5jb2xvcnNbdHlwZV0gPSBjb252ZXJ0WydyZ2IyJyArIHR5cGVdKHRoaXMuY29sb3JzWydyZ2InXSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2xvcnNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2xvcnNbJ3JnYiddO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0U3RyaW5nICh0eXBlKSB7XG4gICAgICAgIGlmICh0eXBlID09PSAnSEVYJykge1xuICAgICAgICAgICAgdmFyIGNvbnZlcnQgPSBDb2xvckNvbnZlcnRlcjtcbiAgICAgICAgICAgIHJldHVybiBjb252ZXJ0WydyZ2IyJyArIHR5cGVdKHRoaXMuY29sb3JzWydyZ2InXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSB0aGlzLmdldCh0eXBlKTtcbiAgICAgICAgICAgIGxldCBzdHIgPSB0eXBlLFxuICAgICAgICAgICAgICAgIG0gPSAnJztcbiAgICAgICAgICAgIGlmICh0eXBlID09PSAndmVjJykge1xuICAgICAgICAgICAgICAgIHN0ciArPSB0aGlzLmNvbG9ycy5hbHBoYSA/IDQgOiAzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RyICs9ICcoJztcbiAgICAgICAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgMzsgbisrKSB7XG4gICAgICAgICAgICAgICAgbSA9IHR5cGVbbl0gfHwgdHlwZS5jaGFyQXQobik7IC8vIElFN1xuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAndmVjJykge1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gKGNvbG9yW21dKS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IE1hdGguZmxvb3IoY29sb3JbbV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobiAhPT0gMikge1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gJywnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuY29sb3JzLmFscGhhKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9ICcsJyArICh0aGlzLmNvbG9ycy5hbHBoYSkudG9GaXhlZCgzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdHIgKz0gJyknO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdW5pZm9ybVR5cGUgKCkge1xuICAgICAgICBpZiAodGhpcy5jb2xvcnMuYWxwaGEpIHtcbiAgICAgICAgICAgIHJldHVybiAndmVjNCc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICd2ZWMzJztcbiAgICB9XG5cbiAgICB1bmlmb3JtVmFsdWUgKCkge1xuICAgICAgICB2Y
23459XIgdmVjID0gdGhpcy5nZXQoJ3ZlYycpO1xuICAgICAgICB2YXIgYXJyID0gW3ZlYy52LCB2ZWMuZSwgdmVjLmNdO1xuICAgICAgICBpZiAodGhpcy5jb2xvcnMuYWxwaGEpIHtcbiAgICAgICAgICAgIGFyci5wdXNoKHRoaXMuY29sb3JzLmFscGhhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH1cblxuICAgIHVuaWZvcm1NZXRob2QgKHR5cGUpIHtcbiAgICAgICAgaWYgKHRoaXMuY29sb3JzLmFscGhhKSB7XG4gICAgICAgICAgICByZXR1cm4gJzRmJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJzNmJztcbiAgICB9XG59XG4iLCJ2YXIgdmFsdWVSYW5nZXMgPSB7XG4gICAgcmdiOiB7IHI6IFswLCAyNTVdLCBnOiBbMCwgMjU1XSwgYjogWzAsIDI1NV0gfSxcbiAgICBoc3Y6IHsgaDogWzAsIDFdLCBzOiBbMCwgMV0sIHY6IFswLCAyNTVdIH0sXG4gICAgaHNsOiB7IGg6IFswLCAzNjBdLCBzOiBbMCwgMTAwXSwgbDogWzAsIDEwMF0gfSxcbiAgICBjbXk6IHsgYzogWzAsIDEwMF0sIG06IFswLCAxMDBdLCB5OiBbMCwgMTAwXSB9LFxuICAgIGNteWs6IHsgYzogWzAsIDEwMF0sIG06IFswLCAxMDBdLCB5OiBbMCwgMTAwXSwgazogWzAsIDEwMF0gfSxcbiAgICBMYWI6IHsgTDogWzAsIDEwMF0sIGE6IFstMTI4LCAxMjddLCBiOiBbLTEyOCwgMTI3XSB9LFxuICAgIFhZWjogeyBYOiBbMCwgMTAwXSwgWTogWzAsIDEwMF0sIFo6IFswLCAxMDBdIH0sXG4gICAgdmVjOiB7IHY6IFswLCAxXSwgZTogWzAsIDFdLCBjOiBbMCwgMV0gfSxcbiAgICBhbHBoYTogeyBhbHBoYTogWzAsIDFdIH0sXG4gICAgSEVYOiB7IEhFWDogWzAsIDE2Nzc3MjE1XSB9IC8vIG1heWJlIHdlIGRvbid0IG5lZWQgdGhpc1xufTtcblxuLy8gaHR0cDovL3d3dy5icnVjZWxpbmRibG9vbS5jb20vaW5kZXguaHRtbD9FcW5fUkdCX1hZWl9NYXRyaXguaHRtbCBmb3IgbW9yZVxudmFyIFhZWk1hdHJpeCA9IHsgLy8gT2JzZXJ2ZXIgPSAywrAgKENJRSAxOTMxKSwgSWxsdW1pbmFudCA9IEQ2NVxuICAgIFg6IFswLjQxMjQ1NjQsIDAuMzU3NTc2MSwgMC4xODA0Mzc1XSxcbiAgICBZOiBbMC4yMTI2NzI5LCAwLjcxNTE1MjIsIDAuMDcyMTc1MF0sXG4gICAgWjogWzAuMDE5MzMzOSwgMC4xMTkxOTIwLCAwLjk1MDMwNDFdLFxuICAgIFI6IFszLjI0MDQ1NDIsIC0xLjUzNzEzODUsIC0wLjQ5ODUzMTRdLFxuICAgIEc6IFstMC45NjkyNjYwLCAxLjg3NjAxMDgsIDAuMDQxNTU2MF0sXG4gICAgQjogWzAuMDU1NjQzNCwgLTAuMjA0MDI1OSwgMS4wNTcyMjUyXVxufTtcblxudmFyIFhZWlJlZmVyZW5jZSA9IHtcbiAgICBYOiBYWVpNYXRyaXguWFswXSArIFhZWk1hdHJpeC5YWzFdICsgWFlaTWF0cml4LlhbMl0sXG4gICAgWTogWFlaTWF0cml4LllbMF0gKyBYWVpNYXRyaXguWVsxXSArIFhZWk1hdHJpeC5ZWzJdLFxuICAgIFo6IFhZWk1hdHJpeC5aWzBdICsgWFlaTWF0cml4LlpbMV0gKyBYWVpNYXRyaXguWlsyXVxufTtcblxudmFyIGx1bWluYW5jZSA9IHsgcjogMC4yMTI2LCBnOiAwLjcxNTIsIGI6IDAuMDcyMiB9OyAvLyBXM0MgMi4wXG5cbnZhciBfY29sb3JzO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xvckNvbnZlcnRlciB7XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFZFQyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cbiAgICBzdGF0aWMgdmVjMnJnYiAodmVjKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByOiB2ZWMudiAqIHZhbHVlUmFuZ2VzWydyZ2InXVsnciddWzFdLFxuICAgICAgICAgICAgZzogdmVjLmUgKiB2YWx1ZVJhbmdlc1sncmdiJ11bJ2cnXVsxXSxcbiAgICAgICAgICAgIGI6IHZlYy5jICogdmFsdWVSYW5nZXNbJ3JnYiddWydiJ11bMV1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBzdGF0aWMgcmdiMnZlYyAocmdiKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2OiByZ2IuciAvIHZhbHVlUmFuZ2VzWydyZ2InXVsnciddWzFdLFxuICAgICAgICAgICAgZTogcmdiLmcgLyB2YWx1ZVJhbmdlc1sncmdiJ11bJ2cnXVsxXSxcbiAgICAgICAgICAgIGM6IHJnYi5iIC8gdmFsdWVSYW5nZXNbJ3JnYiddWydiJ11bMV1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gSEVYIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgc3RhdGljIFJHQjJIRVggKHJnYikge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgKHJnYi5yIDwgMTYgPyAnMCcgOiAnJykgKyByZ2Iuci50b1N0cmluZygxNikgK1xuICAgICAgICAgICAgKHJnYi5nIDwgMTYgPyAnMCcgOiAnJykgKyByZ2IuZy50b1N0cmluZygxNikgK1xuICAgICAgICAgICAgKHJnYi5iIDwgMTYgPyAnMCcgOiAnJykgKyByZ2IuYi50b1N0cmluZygxNilcbiAgICAgICAgKS50b1VwcGVyQ2FzZSgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBIRVgycmdiIChIRVgpIHtcbiAgICAgICAgSEVYID0gSEVYLnNwbGl0KCcnKTsgLy8gSUU3XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByOiBwYXJzZUludChIRVhbMF0gKyBIRVhbSEVYWzNdID8gMSA6IDBdLCAxNikgLyAyNTUsXG4gICAgICAgICAgICBnOiBwYXJzZUludChIRVhbSEVYWzNdID8gMiA6IDFdICsgKEhFWFszXSB8fCBIRVhbMV0pLCAxNikgLyAyNTUsXG4gICAgICAgICAgICBiOiBwYXJzZUludCgoSEVYWzRdIHx8IEhFWFsyXSkgKyAoSEVYWzVdIHx8IEhFWFsyXSksIDE2KSAvIDI1NVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBIVUUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbiAgICBzdGF0aWMgaHVlMlJHQiAoaHVlKSB7XG4gICAgICAgIHZhciBoID0gaHVlICogNixcbiAgICAgICAgICAgIC8vIG1vZCA9IH5+aCAlIDYsIC8vIE1hdGguZmxvb3IoaCkgLT4gZmFzdGVyIGluIG1vc3QgYnJvd3NlcnNcbiAgICAgICAgICAgIG1vZCA9IE1hdGguZmxvb3IoaCksXG4gICAgICAgICAgICBpID0gaCA9PT0gNiA/IDAgOiAoaCAtIG1vZCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByOiBNYXRoLnJvdW5kKFsxLCAxIC0gaSwgMCwgMCwgaSwgMV1bbW9kXSAqIDI1NSksXG4gICAgICAgICAgICBnOiBNYXRoLnJvdW5kKFtpLCAxLCAxLCAxIC0gaSwgMCwgMF1bbW9kXSAqIDI1NSksXG4gICAgICAgICAgICBiOiBNYXRoLnJvdW5kKFswLCAwLCBpLCAxLCAxLCAxIC0gaV1bbW9kXSAqIDI1NSlcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gSFNWIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgc3RhdGljIHJnYjJoc3YgKHJnYikgeyAvLyBmYXN0ZXJcbiAgICAgICAgdmFyIHIgPSByZ2IucixcbiAgICAgICAgICAgIGcgPSByZ2IuZyxcbiAgICAgICAgICAgIGIgPSByZ2IuYi
23459xcbiAgICAgICAgICAgIGsgPSAwLFxuICAgICAgICAgICAgY2hyb21hLFxuICAgICAgICAgICAgbWluLFxuICAgICAgICAgICAgcztcblxuICAgICAgICBpZiAoZyA8IGIpIHtcbiAgICAgICAgICAgIGcgPSBiICsgKGIgPSBnLCAwKTtcbiAgICAgICAgICAgIGsgPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBtaW4gPSBiO1xuICAgICAgICBpZiAociA8IGcpIHtcbiAgICAgICAgICAgIHIgPSBnICsgKGcgPSByLCAwKTtcbiAgICAgICAgICAgIGsgPSAtMiAvIDYgLSBrO1xuICAgICAgICAgICAgbWluID0gTWF0aC5taW4oZywgYik7IC8vIGcgPCBiID8gZyA6IGI7ID8/P1xuICAgICAgICB9XG4gICAgICAgIGNocm9tYSA9IHIgLSBtaW47XG4gICAgICAgIHMgPSByID8gKGNocm9tYSAvIHIpIDogMDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGg6IHMgPCAxZS0xNSA/ICgoX2NvbG9ycyAmJiBfY29sb3JzLmhzbCAmJiBfY29sb3JzLmhzbC5oKSB8fCAwKSA6XG4gICAgICAgICAgICAgICAgY2hyb21hID8gTWF0aC5hYnMoayArIChnIC0gYikgLyAoNiAqIGNocm9tYSkpIDogMCxcbiAgICAgICAgICAgIHM6IHIgPyAoY2hyb21hIC8gcikgOiAoKF9jb2xvcnMgJiYgX2NvbG9ycy5oc3YgJiYgX2NvbG9ycy5oc3YucykgfHwgMCksIC8vID8/X2NvbG9ycy5oc3YucyB8fCAwXG4gICAgICAgICAgICB2OiByXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIGhzdjJyZ2IgKGhzdikge1xuICAgICAgICB2YXIgaCA9IGhzdi5oICogNixcbiAgICAgICAgICAgIHMgPSBoc3YucyxcbiAgICAgICAgICAgIHYgPSBoc3YudixcbiAgICAgICAgICAgIC8vIGkgPSB+fmgsIC8vIE1hdGguZmxvb3IoaCkgLT4gZmFzdGVyIGluIG1vc3QgYnJvd3NlcnNcbiAgICAgICAgICAgIGkgPSBNYXRoLmZsb29yKGgpLFxuICAgICAgICAgICAgZiA9IGggLSBpLFxuICAgICAgICAgICAgcCA9IHYgKiAoMSAtIHMpLFxuICAgICAgICAgICAgcSA9IHYgKiAoMSAtIGYgKiBzKSxcbiAgICAgICAgICAgIHQgPSB2ICogKDEgLSAoMSAtIGYpICogcyksXG4gICAgICAgICAgICBtb2QgPSBpICUgNjtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcjogW3YsIHEsIHAsIHAsIHQsIHZdW21vZF0sXG4gICAgICAgICAgICBnOiBbdCwgdiwgdiwgcSwgcCwgcF1bbW9kXSxcbiAgICAgICAgICAgIGI6IFtwLCBwLCB0LCB2LCB2LCBxXVttb2RdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIEhTTCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIHN0YXRpYyBoc3YyaHNsIChoc3YpIHtcbiAgICAgICAgdmFyIGwgPSAoMiAtIGhzdi5zKSAqIGhzdi52LFxuICAgICAgICAgICAgcyA9IGhzdi5zICogaHN2LnY7XG5cbiAgICAgICAgcyA9ICFoc3YucyA/IDAgOiBsIDwgMSA/IChsID8gcyAvIGwgOiAwKSA6IHMgLyAoMiAtIGwpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoOiBoc3YuaCxcbiAgICAgICAgICAgIHM6ICFoc3YudiAmJiAhcyA/ICgoX2NvbG9ycyAmJiBfY29sb3JzLmhzbCAmJiBfY29sb3JzLmhzbC5zKSB8fCAwKSA6IHMsIC8vID8/P1xuICAgICAgICAgICAgbDogbCAvIDJcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBzdGF0aWMgcmdiMmhzbCAocmdiLCBkZXBlbmRlbnQpIHsgLy8gbm90IHVzZWQgaW4gQ29sb3JcbiAgICAgICAgdmFyIGhzdiA9IENvbG9yQ29udmVydGVyLnJnYjJoc3YocmdiKTtcblxuICAgICAgICByZXR1cm4gQ29sb3JDb252ZXJ0ZXIuaHN2MmhzbChkZXBlbmRlbnQgPyBoc3YgOiAoX2NvbG9ycy5oc3YgPSBoc3YpKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaHNsMnJnYiAoaHNsKSB7XG4gICAgICAgIHZhciBoID0gaHNsLmggKiA2LFxuICAgICAgICAgICAgcyA9IGhzbC5zLFxuICAgICAgICAgICAgbCA9IGhzbC5sLFxuICAgICAgICAgICAgdiA9IGwgPCAwLjUgPyBsICogKDEgKyBzKSA6IChsICsgcykgLSAocyAqIGwpLFxuICAgICAgICAgICAgbSA9IGwgKyBsIC0gdixcbiAgICAgICAgICAgIHN2ID0gdiA/ICgodiAtIG0pIC8gdikgOiAwLFxuICAgICAgICAgICAgLy8gc2V4dGFudCA9IH5+aCwgLy8gTWF0aC5mbG9vcihoKSAtPiBmYXN0ZXIgaW4gbW9zdCBicm93c2Vyc1xuICAgICAgICAgICAgc2V4dGFudCA9IE1hdGguZmxvb3IoaCksXG4gICAgICAgICAgICBmcmFjdCA9IGggLSBzZXh0YW50LFxuICAgICAgICAgICAgdnNmID0gdiAqIHN2ICogZnJhY3QsXG4gICAgICAgICAgICB0ID0gbSArIHZzZixcbiAgICAgICAgICAgIHEgPSB2IC0gdnNmLFxuICAgICAgICAgICAgbW9kID0gc2V4dGFudCAlIDY7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHI6IFt2LCBxLCBtLCBtLCB0LCB2XVttb2RdLFxuICAgICAgICAgICAgZzogW3QsIHYsIHYsIHEsIG0sIG1dW21vZF0sXG4gICAgICAgICAgICBiOiBbbSwgbSwgdCwgdiwgdiwgcV1bbW9kXVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDTVlLIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuICAgIC8vIFF1b3RlIGZyb20gV2lraXBlZGlhOlxuICAgIC8vICdTaW5jZSBSR0IgYW5kIENNWUsgc3BhY2VzIGFyZSBib3RoIGRldmljZS1kZXBlbmRlbnQgc3BhY2VzLCB0aGVyZSBpcyBub1xuICAgIC8vIHNpbXBsZSBvciBnZW5lcmFsIGNvbnZlcnNpb24gZm9ybXVsYSB0aGF0IGNvbnZlcnRzIGJldHdlZW4gdGhlbS5cbiAgICAvLyBDb252ZXJzaW9ucyBhcmUgZ2VuZXJhbGx5IGRvbmUgdGhyb3VnaCBjb2xvciBtYW5hZ2VtZW50IHN5c3RlbXMsIHVzaW5nXG4gICAgLy8gY29sb3IgcHJvZmlsZXMgdGhhdCBkZXNjcmliZSB0aGUgc3BhY2VzIGJlaW5nIGNvbnZlcnRlZC4gTmV2ZXJ0aGVsZXNzLCB0aGVcbiAgICAvLyBjb252ZXJzaW9ucyBjYW5ub3QgYmUgZXhhY3QsIHNpbmNlIHRoZXNlIHNwYWNlcyBoYXZlIHZlcnkgZGlmZmVyZW50IGdhbXV0cy4nXG4gICAgLy8gVHJhbnNsYXRpb246IHRoZSBmb2xsb3dpbmcgYXJlIGp1c3Qgc2ltcGxlIFJHQiB0byBDTVkoSykgYW5kIHZpc2EgdmVyc2EgY29udmVyc2lvbiBmdW5jdGlvbnMuXG5cbiAgICBzdGF0aWMgcmdiMmNteSAocmdiKSB7XG4gICAgICAgI
23459HJldHVybiB7XG4gICAgICAgICAgICBjOiAxIC0gcmdiLnIsXG4gICAgICAgICAgICBtOiAxIC0gcmdiLmcsXG4gICAgICAgICAgICB5OiAxIC0gcmdiLmJcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY215MmNteWsgKGNteSkge1xuICAgICAgICB2YXIgayA9IE1hdGgubWluKE1hdGgubWluKGNteS5jLCBjbXkubSksIGNteS55KSxcbiAgICAgICAgICAgIHQgPSAxIC0gayB8fCAxZS0yMDtcblxuICAgICAgICByZXR1cm4geyAvLyByZWd1bGFyXG4gICAgICAgICAgICBjOiAoY215LmMgLSBrKSAvIHQsXG4gICAgICAgICAgICBtOiAoY215Lm0gLSBrKSAvIHQsXG4gICAgICAgICAgICB5OiAoY215LnkgLSBrKSAvIHQsXG4gICAgICAgICAgICBrOiBrXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIGNteWsyY215IChjbXlrKSB7XG4gICAgICAgIHZhciBrID0gY215ay5rO1xuXG4gICAgICAgIHJldHVybiB7IC8vIHJlZ3VsYXJcbiAgICAgICAgICAgIGM6IGNteWsuYyAqICgxIC0gaykgKyBrLFxuICAgICAgICAgICAgbTogY215ay5tICogKDEgLSBrKSArIGssXG4gICAgICAgICAgICB5OiBjbXlrLnkgKiAoMSAtIGspICsga1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyBjbXkycmdiIChjbXkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHI6IDEgLSBjbXkuYyxcbiAgICAgICAgICAgIGc6IDEgLSBjbXkubSxcbiAgICAgICAgICAgIGI6IDEgLSBjbXkueVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyByZ2IyY215ayAocmdiKSB7XG4gICAgICAgIHZhciBjbXkgPSBDb2xvckNvbnZlcnRlci5yZ2IyY215KHJnYik7IC8vIGRvcHBlbHQ/P1xuICAgICAgICByZXR1cm4gQ29sb3JDb252ZXJ0ZXIuY215MmNteWsoY215KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY215azJyZ2IgKGNteWspIHtcbiAgICAgICAgdmFyIGNteSA9IENvbG9yQ29udmVydGVyLmNteWsyY215KGNteWspOyAvLyBkb3BwZWx0Pz9cbiAgICAgICAgcmV0dXJuIENvbG9yQ29udmVydGVyLmNteTJyZ2IoY215KTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gTEFCIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgc3RhdGljIFhZWjJyZ2IgKFhZWikge1xuICAgICAgICB2Y
23459XIgTSA9IFhZWk1hdHJpeCxcbiAgICAgICAgICAgIFggPSBYWVouWCxcbiAgICAgICAgICAgIFkgPSBYWVouWSxcbiAgICAgICAgICAgIFogPSBYWVouWixcbiAgICAgICAgICAgIHIgPSBYICogTS5SWzBdICsgWSAqIE0uUlsxXSArIFogKiBNLlJbMl0sXG4gICAgICAgICAgICBnID0gWCAqIE0uR1swXSArIFkgKiBNLkdbMV0gKyBaICogTS5HWzJdLFxuICAgICAgICAgICAgYiA9IFggKiBNLkJbMF0gKyBZICogTS5CWzFdICsgWiAqIE0uQlsyXSxcbiAgICAgICAgICAgIE4gPSAxIC8gMi40O1xuXG4gICAgICAgIE0gPSAwLjAwMzEzMDg7XG5cbiAgICAgICAgciA9IChyID4gTSA/IDEuMDU1ICogTWF0aC5wb3cociwgTikgLSAwLjA1NSA6IDEyLjkyICogcik7XG4gICAgICAgIGcgPSAoZyA+IE0gPyAxLjA1NSAqIE1hdGgucG93KGcsIE4pIC0gMC4wNTUgOiAxMi45MiAqIGcpO1xuICAgICAgICBiID0gKGIgPiBNID8gMS4wNTUgKiBNYXRoLnBvdyhiLCBOKSAtIDAuMDU1IDogMTIuOTIgKiBiKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcjogbGltaXRWYWx1ZShyLCAwLCAxKSxcbiAgICAgICAgICAgIGc6IGxpbWl0VmFsdWUoZywgMCwgMSksXG4gICAgICAgICAgICBiOiBsaW1pdFZhbHVlKGIsIDAsIDEpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIHJnYjJYWVogKHJnYikge1xuICAgICAgICB2YXIgTSA9IFhZWk1hdHJpeCxcbiAgICAgICAgICAgIHIgPSByZ2IucixcbiAgICAgICAgICAgIGcgPSByZ2IuZyxcbiAgICAgICAgICAgIGIgPSByZ2IuYixcbiAgICAgICAgICAgIE4gPSAwLjA0MDQ1O1xuXG4gICAgICAgIHIgPSAociA+IE4gPyBNYXRoLnBvdygociArIDAuMDU1KSAvIDEuMDU1LCAyLjQpIDogciAvIDEyLjkyKTtcbiAgICAgICAgZyA9IChnID4gTiA/IE1hdGgucG93KChnICsgMC4wNTUpIC8gMS4wNTUsIDIuNCkgOiBnIC8gMTIuOTIpO1xuICAgICAgICBiID0gKGIgPiBOID8gTWF0aC5wb3coKGIgKyAwLjA1NSkgLyAxLjA1NSwgMi40KSA6IGIgLyAxMi45Mik7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFg6IHIgKiBNLlhbMF0gKyBnICogTS5YWzFdICsgYiAqIE0uWFsyXSxcbiAgICAgICAgICAgIFk6IHIgKiBNLllbMF0gKyBnICogTS5ZWzFdICsgYiAqIE0uWVsyXSxcbiAgICAgICAgICAgIFo6IHIgKiBNLlpbMF0gKyBnICogTS5aWzFdICsgYiAqIE0uWlsyXVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyBYWVoyTGFiIChYWVopIHtcbiAgICAgICAgdmFyIFIgPSBYWVpSZWZlcmVuY2UsXG4gICAgICAgICAgICBYID0gWFlaLlggLyBSLlgsXG4gICAgICAgICAgICBZID0gWFlaLlkgLyBSLlksXG4gICAgICAgICAgICBaID0gWFlaLlogLyBSLlosXG4gICAgICAgICAgICBOID0gMTYgLyAxMTYsXG4gICAgICAgICAgICBNID0gMSAvIDMsXG4gICAgICAgICAgICBLID0gMC4wMDg4NTYsXG4gICAgICAgICAgICBMID0gNy43ODcwMzc7XG5cbiAgICAgICAgWCA9IFggPiBLID8gTWF0aC5wb3coWCwgTSkgOiAoTCAqIFgpICsgTjtcbiAgICAgICAgWSA9IFkgPiBLID8gTWF0aC5wb3coWSwgTSkgOiAoTCAqIFkpICsgTjtcbiAgICAgICAgWiA9IFogPiBLID8gTWF0aC5wb3coWiwgTSkgOiAoTCAqIFopICsgTjtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgTDogKDExNiAqIFkpIC0gMTYsXG4gICAgICAgICAgICBhOiA1MDAgKiAoWCAtIFkpLFxuICAgICAgICAgICAgYjogMjAwICogKFkgLSBaKVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyBMYWIyWFlaIChMYWIpIHtcbiAgICAgICAgdmFyIFIgPSBYWVpSZWZlcmVuY2UsXG4gICAgICAgICAgICBZID0gKExhYi5MICsgMTYpIC8gMTE2LFxuICAgICAgICAgICAgWCA9IExhYi5hIC8gNTAwICsgWSxcbiAgICAgICAgICAgIFogPSBZIC0gTGFiLmIgLyAyMDAsXG4gICAgICAgICAgICBYMyA9IE1hdGgucG93KFgsIDMpLFxuICAgICAgICAgICAgWTMgPSBNYXRoLnBvdyhZLCAzKSxcbiAgICAgICAgICAgIFozID0gTWF0aC5wb3coWiwgMyksXG4gICAgICAgICAgICBOID0gMTYgLyAxMTYsXG4gICAgICAgICAgICBLID0gMC4wMDg4NTYsXG4gICAgICAgICAgICBMID0gNy43ODcwMzc7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFg6IChYMyA+IEsgPyBYMyA6IChYIC0gTikgLyBMKSAqIFIuWCxcbiAgICAgICAgICAgIFk6IChZMyA+IEsgPyBZMyA6IChZIC0gTikgLyBMKSAqIFIuWSxcbiAgICAgICAgICAgIFo6IChaMyA+IEsgPyBaMyA6IChaIC0gTikgLyBMKSAqIFIuWlxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyByZ2IyTGFiIChyZ2IpIHtcbiAgICAgICAgdmFyIFhZWiA9IENvbG9yQ29udmVydGVyLnJnYjJYWVoocmdiKTtcblxuICAgICAgICByZXR1cm4gQ29sb3JDb252ZXJ0ZXIuWFlaMkxhYihYWVopO1xuICAgIH1cblxuICAgIHN0YXRpYyBMYWIycmdiIChMYWIpIHtcbiAgICAgICAgdmFyIFhZWiA9IENvbG9yQ29udmVydGVyLkxhYjJYWVooTGFiKTtcblxuICAgICAgICByZXR1cm4gQ29sb3JDb252ZXJ0ZXIuWFlaMnJnYihYWVopO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbWl0VmFsdWUodmFsdWUsIG1pbiwgbWF4KSB7XG4gICAgLy8gcmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB2YWx1ZSkpOyAvLyBmYXN0ZXI/P1xuICAgIHJldHVybiAodmFsdWUgPiBtYXggPyBtYXggOiB2YWx1ZSA8IG1pbiA/IG1pbiA6IHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEx1bWluYW5jZShyZ2IsIG5vcm1hbGl6ZWQpIHtcbiAgICB2YXIgZGl2ID0gbm9ybWFsaXplZCA/IDEgOiAyNTUsXG4gICAgICAgIFJHQiA9IFtyZ2IuciAvIGRpdiwgcmdiLmcgLyBkaXYsIHJnYi5iIC8gZGl2XTtcblxuICAgIGZvciAodmFyIGkgPSBSR0IubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIFJHQltpXSA9IFJHQltpXSA8PSAwLjAzOTI4ID8gUkdCW2ldIC8gMTIuOTIgOiBNYXRoLnBvdygoKFJHQltpXSArIDAuMDU1KSAvIDEuMDU1KSwgMi40KTtcbiAgICB9XG4gICAgcmV0dXJuICgobHVtaW5hbmNlLnIgKiBSR0JbMF0pICsgKGx1bWluYW5jZS5nICogUkdCWzFdKSArIChsdW1pbmFuY2UuYiAqIFJHQlsyXSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29sb3JBc1JHQiAoY29sb3IpIHtcbiAgICAvLyBDcmVhdGUgYSB0ZXN0IGVsZW1lbnQgdG8gYXBwbHkgYSBDU1MgY29sb3IgYW5kIHJldHJpZXZlXG4gICAgLy8gYSBub3JtYWxpem
23459VkIHZhbHVlIGZyb20uXG4gICAgbGV0IHRlc3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB0ZXN0LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGNvbG9yO1xuXG4gICAgLy8gQ2hyb21lIHJlcXVpcmVzIHRoZSBlbGVtZW50IHRvIGJlIGluIERPTSBmb3Igc3R5bGVzIHRvIGJlIGNvbXB1dGVkLlxuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGVzdCk7XG5cbiAgICAvLyBHZXQgdGhlIGNvbXB1dGVkIHN0eWxlIGZyb20gdGhlIGJyb3dzZXIsIGluIHRoZSBmb3JtYXQgb2ZcbiAgICAvLyByZ2IoeCwgeCwgeClcbiAgICBsZXQgbm9ybWFsaXplZCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRlc3QpLmJhY2tncm91bmRDb2xvcjtcblxuICAgIC8vIEluIGNlcnRhaW4gY2FzZXMgZ2V0Q29tcHV0ZWRTdHlsZSgpIG1heSByZXR1cm5cbiAgICAvLyAndHJhbnNwYXJlbnQnIGFzIGEgdmFsdWUsIHdoaWNoIGlzIHVzZWxlc3MoPykgZm9yIHRoZSBjdXJyZW50XG4gICAgLy8gY29sb3IgcGlja2VyLiBBY2NvcmRpbmcgdG8gc3BlY2lmaWNhdGlvbnMsIHRyYW5zcGFyZW50XG4gICAgLy8gaXMgYSBibGFjayB3aXRoIDAgYWxwaGEgLSByZ2JhKDAsIDAsIDAsIDApIC0gYnV0IGJlY2F1c2VcbiAgICAvLyB0aGUgcGlja2VyIGRvZXMgbm90IGN1cnJlbnRseSBoYW5kbGUgYWxwaGEsIHdlIHJldHVybiB0aGVcbiAgICAvLyBibGFjayB2YWx1ZS5cbiAgICBpZiAobm9ybWFsaXplZCA9PT0gJ3RyYW5zcGFyZW50Jykge1xuICAgICAgICBub3JtYWxpemVkID0gJ3JnYigwLCAwLCAwKSc7XG4gICAgfVxuXG4gICAgLy8gR2FyYmFnZSBjb2xsZWN0aW9uXG4gICAgdGVzdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRlc3QpO1xuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWx1ZVJhbmdlcyh0eXBlKSB7XG4gICAgaWYgKCF0eXBlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZVJhbmdlcztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB2YWx1ZVJhbmdlc1t0eXBlXTtcbiAgICB9XG59XG4iLCJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZsb2F0IHtcbiAgICBjb25zdHJ1Y3RvciAodmFsdWUpIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgIH1cblxuICAgIGdldFN0cmluZyAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlLnRvRml4ZWQoMyk7XG4gICAgfVxuXG4gICAgdW5pZm9ybVR5cGUgKCkge1xuICAgICAgICByZXR1cm4gJ2Zsb2F0JztcbiAgICB9XG5cbiAgICB1bmlmb3JtVmFsdWUgKCkge1xuICAgICAgICByZXR1cm4gW3RoaXMudmFsdWVdO1xuICAgIH1cblxuICAgIHVuaWZvcm1NZXRob2QgKCkge1xuICAgICAgICByZXR1cm4gJzFmJztcbiAgICB9XG59XG4iLCJpbXBvcnQgVmVjdG9yIGZyb20gJy4vVmVjdG9yJztcblxuLy8gVE9ETzpcbi8vICAgICAgLSBnZW5lcmFsaXplIHRoaXMgZm9yIG1hdDIsIG1hdDMgYW5kIG1hdDRcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWF0cml4IHtcbiAgICBjb25zdHJ1Y3RvcihtLCB0eXBlKSB7XG4gICAgICAgIHRoaXMuZGltID0gMztcbiAgICAgICAgdGhpcy52YWx1ZSA9IFtcbiAgICAgICAgICAgIFsxLCAwLCAwXSxcbiAgICAgICAgICAgIFswLCAxLCAwXSxcbiAgICAgICAgICAgIFswLCAwLCAxXV07XG4gICAgICAgIGlmIChtKSB7XG4gICAgICAgICAgICB0aGlzLnNldChtLCB0eXBlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldCAobSwgdHlwZSkge1xuICAgICAgICBpZiAobS52YWx1ZVswXVswXSkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IG0udmFsdWU7XG4gICAgICAgICAgICB0aGlzLmRpbSA9IG0uZGltO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG1bMF1bMF0pIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBtO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcm90YXRlWCAodGhldGEpIHtcbiAgICAgICAgbGV0IGMgPSBNYXRoLmNvcyh0aGV0YSk7XG4gICAgICAgIGxldCBzID0gTWF0aC5zaW4odGhldGEpO1xuICAgICAgICBsZXQgVCA9IFtcbiAgICAgICAgICAgIFsxLCAwLCAwXSxcbiAgICAgICAgICAgIFswLCBjLCAtc10sXG4gICAgICAgICAgICBbMCwgcywgY11dO1xuXG4gICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLmdldFRyYW5zZm9ybShUKTtcbiAgICB9XG5cbiAgICByb3RhdGVZICh0aGV0YSkge1xuICAgICAgICBsZXQgYyA9IE1hdGguY29zKHRoZXRhKTtcbiAgICAgICAgbGV0IHMgPSBNYXRoLnNpbih0aGV0YSk7XG4gICAgICAgIGxldCBUID0gW1xuICAgICAgICAgICAgW2MsIDAsIHNdLFxuICAgICAgICAgICAgWzAsIDEsIDBdLFxuICAgICAgICAgICAgWy1zLCAwLCBjXV07XG5cbiAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMuZ2V0VHJhbnNmb3JtKFQpO1xuICAgIH1cblxuICAgIGdldE11bHQgKHYpIHtcbiAgICAgICAgaWYgKHZbMF1bMF0gfHwgKHYudmFsdWUgJiYgdi52YWx1ZVswXVswXSkpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IHdoYXQgSWYgdiBpcyBhIG1hdHJpeFxuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RPRE86IHdoYXQgSWYgdiBpcyBhIG1hdHJpeCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gSWYgdiBpcyBhIHZlY3RvclxuICAgICAgICAgICAgbGV0IEEgPSBuZXcgVmVjdG9yKHYpO1xuICAgICAgICAgICAgbGV0IEIgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgQS5kaW07IGkrKykge1xuICAgICAgICAgICAgICAgIEIucHVzaChBLnZhbHVlWzBdICogdGhpcy52YWx1ZVtpXVswXSArIEEudmFsdWVbMV0gKiB0aGlzLnZhbHVlW2ldWzFdICsgQS52YWx1ZVsyXSAqIHRoaXMudmFsdWVbaV1bMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWN0b3IoQik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRUcmFuc2Zvcm0gKG0pIHtcbiAgICAgICAgbGV0IG5ld01hdHJpeCA9IFtdO1xuICAgICAgICBmb3IgKGxldCByb3cgaW4gbSkge1xuICAgICAgICAgICAgbGV0IHQgPSBtW3Jvd107XG4gICAgICAgICAgICBsZXQgbm
23459V3Um93ID0gW107XG4gICAgICAgICAgICBuZXdSb3cucHVzaCh0WzBdICogdGhpcy52YWx1ZVswXVswXSArIHRbMV0gKiB0aGlzLnZhbHVlWzFdWzBdICsgdFsyXSAqIHRoaXMudmFsdWVbMl1bMF0pO1xuICAgICAgICAgICAgbmV3Um93LnB1c2godFswXSAqIHRoaXMudmFsdWVbMF1bMV0gKyB0WzFdICogdGhpcy52YWx1ZVsxXVsxXSArIHRbMl0gKiB0aGlzLnZhbHVlWzJdWzFdKTtcbiAgICAgICAgICAgIG5ld1Jvdy5wdXNoKHRbMF0gKiB0aGlzLnZhbHVlWzBdWzJdICsgdFsxXSAqIHRoaXMudmFsdWVbMV1bMl0gKyB0WzJdICogdGhpcy52YWx1ZVsyXVsyXSk7XG4gICAgICAgICAgICBuZXdNYXRyaXgucHVzaChuZXdSb3cpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdNYXRyaXg7XG4gICAgfVxuXG4gICAgZ2V0SW52KCkge1xuICAgICAgICBsZXQgTSA9IG5ldyBNYXRyaXgoKTtcbiAgICAgICAgbGV0IGRldGVybWluYW50ID0gdGhpcy52YWx1ZVswXVswXSAqICh0aGlzLnZhbHVlWzFdWzFdICogdGhpcy52YWx1ZVsyXVsyXSAtIHRoaXMudmFsdWVbMl1bMV0gKiB0aGlzLnZhbHVlWzFdWzJdKSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVswXVsxXSAqICh0aGlzLnZhbHVlWzFdWzBdICogdGhpcy52YWx1ZVsyXVsyXSAtIHRoaXMudmFsdWVbMV1bMl0gKiB0aGlzLnZhbHVlWzJdWzBdKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVswXVsyXSAqICh0aGlzLnZhbHVlWzFdWzBdICogdGhpcy52YWx1ZVsyXVsxXSAtIHRoaXMudmFsdWVbMV1bMV0gKiB0aGlzLnZhbHVlWzJdWzBdKTtcbiAgICAgICAgbGV0IGludmRldCA9IDEgLyBkZXRlcm1pbmFudDtcbiAgICAgICAgTS52YWx1ZVswXVswXSA9ICh0aGlzLnZhbHVlWzFdWzFdICogdGhpcy52YWx1ZVsyXVsyXSAtIHRoaXMudmFsdWVbMl1bMV0gKiB0aGlzLnZhbHVlWzFdWzJdKSAqIGludmRldDtcbiAgICAgICAgTS52YWx1ZVswXVsxXSA9IC0odGhpcy52YWx1ZVswXVsxXSAqIHRoaXMudmFsdWVbMl1bMl0gLSB0aGlzLnZhbHVlWzBdWzJdICogdGhpcy52YWx1ZVsyXVsxXSkgKiBpbnZkZXQ7XG4gICAgICAgIE0udmFsdWVbMF1bMl0gPSAodGhpcy52YWx1ZVswXVsxXSAqIHRoaXMudmFsdWVbMV1bMl0gLSB0aGlzLnZhbHVlWzBdWzJdICogdGhpcy52YWx1ZVsxXVsxXSkgKiBpbnZkZXQ7XG4gICAgICAgIE0udmFsdWVbMV1bMF0gPSAtKHRoaXMudmFsdWVbMV1bMF0gKiB0aGlzLnZhbHVlWzJdWzJdIC0gdGhpcy52YWx1ZVsxXVsyXSAqIHRoaXMudmFsdWVbMl1bMF0pICogaW52ZGV0O1xuICAgICAgICBNLnZhbHVlWzFdWzFdID0gKHRoaXMudmFsdWVbMF1bMF0gKiB0aGlzLnZhbHVlWzJdWzJdIC0gdGhpcy52YWx1ZVswXVsyXSAqIHRoaXMudmFsdWVbMl1bMF0pICogaW52ZGV0O1xuICAgICAgICBNLnZhbHVlWzFdWzJdID0gLSh0aGlzLnZhbHVlWzBdWzBdICogdGhpcy52YWx1ZVsxXVsyXSAtIHRoaXMudmFsdWVbMV1bMF0gKiB0aGlzLnZhbHVlWzBdWzJdKSAqIGludmRldDtcbiAgICAgICAgTS52YWx1ZVsyXVswXSA9ICh0aGlzLnZhbHVlWzFdWzBdICogdGhpcy52YWx1ZVsyXVsxXSAtIHRoaXMudmFsdWVbMl1bMF0gKiB0aGlzLnZhbHVlWzFdWzFdKSAqIGludmRldDtcbiAgICAgICAgTS52YWx1ZVsyXVsxXSA9IC0odGhpcy52YWx1ZVswXVswXSAqIHRoaXMudmFsdWVbMl1bMV0gLSB0aGlzLnZhbHVlWzJdWzBdICogdGhpcy52YWx1ZVswXVsxXSkgKiBpbnZkZXQ7XG4gICAgICAgIE0udmFsdWVbMl1bMl0gPSAodGhpcy52YWx1ZVswXVswXSAqIHRoaXMudmFsdWVbMV1bMV0gLSB0aGlzLnZhbHVlWzFdWzBdICogdGhpcy52YWx1ZVswXVsxXSkgKiBpbnZkZXQ7XG4gICAgICAgIHJldHVybiBNO1xuICAgIH1cbn1cbiIsImV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlY3RvciB7XG4gICAgY29uc3RydWN0b3IgKHZlYywgdHlwZSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gWzAsMF07XG4gICAgICAgIHRoaXMuZGltID0gMjtcbiAgICAgICAgdGhpcy5zZXQodmVjLCB0eXBlKTtcbiAgICB9XG5cbiAgICBzZXQgKHZlYywgdHlwZSkge1xuICAgICAgICBpZiAodHlwZW9mIHZlYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHR5cGUgPSB0eXBlIHx8ICd2ZWMyJztcbiAgICAgICAgICAgIHRoaXMuc2V0KFt2ZWNdLCB0eXBlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmVjID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbGV0IHBhcnRzID0gdmVjLnJlcGxhY2UoLyg/OiN8XFwpfFxcXXwlKS9nLCAnJykuc3BsaXQoJygnKTtcbiAgICAgICAgICAgIGxldCBzdHJWYWx1ZXMgPSAocGFydHNbMV0gfHwgcGFydHNbMF0ucmVwbGFjZSgvKFxcWykvZywgJycpKS5zcGxpdCgvLFxccyovKTtcbiAgICAgICAgICAgIHR5cGUgPSB0eXBlIHx8IChwYXJ0c1sxXSA/IHBhcnRzWzBdLnN1YnN0cigwLCA0KSA6ICd2ZWMnICsgc3RyVmFsdWVzLmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgdmFsdWVzID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpIGluIHN0clZhbHVlcykge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHBhcnNlRmxvYXQoc3RyVmFsdWVzW2ldKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldCh2YWx1ZXMsIHR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHZlYykge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmVjKSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5kaW0gPSB0eXBlID8gTnVtYmVyKHR5cGUuc3Vic3RyKDMsIDQpKSA6IHZlYy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgbGV0IGZpbGxlciA9IHZlYy5sZW5ndGggPT09IDEgPyB2ZWNbMF0gOiAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kaW07IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZhbHVlLnB1c2godmVjW2ldIHx8IGZpbGxlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodmVjLmRpbSkge1xuICAgICAgICAgICAgICAgI
23459HRoaXMudmFsdWUgPSB2ZWMudmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5kaW0gPSB2ZWMuZGltO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0IHggKHYpIHtcbiAgICAgICAgdGhpcy52YWx1ZVswXSA9IHY7XG4gICAgfVxuXG4gICAgc2V0IHkgKHYpIHtcbiAgICAgICAgdGhpcy52YWx1ZVsxXSA9IHY7XG4gICAgfVxuXG4gICAgc2V0IHogKHYpIHtcbiAgICAgICAgaWYgKHRoaXMuZGltIDwgMykge1xuICAgICAgICAgICAgd2hpbGUgKHRoaXMuZGltIDwgMykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUucHVzaCgwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGltID0gMztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZhbHVlWzJdID0gdjtcbiAgICB9XG5cbiAgICBzZXQgdyAodikge1xuICAgICAgICBpZiAodGhpcy5kaW0gPCA0KSB7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5kaW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZS5wdXNoKDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kaW0gPSA0O1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudmFsdWVbM10gPSB2O1xuICAgIH1cblxuICAgIGdldCB4ICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVbMF0gfHwgMC4wO1xuICAgIH1cblxuICAgIGdldCB5ICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVbMV0gfHwgMC4wO1xuICAgIH1cblxuICAgIGdldCB6ICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVbMl0gfHwgMC4wIDtcbiAgICB9XG5cbiAgICBnZXQgdyAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlWzNdIHx8IDAuMDtcbiAgICB9XG5cbiAgICBnZXRTdHJpbmcodHlwZSkge1xuICAgICAgICB0eXBlID0gdHlwZSB8fCAndmVjJyArIHRoaXMuZGltO1xuXG4gICAgICAgIGxldCBsZW4gPSB0aGlzLmRpbTtcbiAgICAgICAgbGV0IHN0ciA9ICcnO1xuICAgICAgICBsZXQgaGVhZCA9IHR5cGUgKyAnKCc7XG4gICAgICAgIGxldCBlbmQgPSAnKSc7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgIGhlYWQgPSAnWyc7XG4gICAgICAgICAgICBlbmQgPSAnXSc7XG4gICAgICAgICAgICBsZW4gPSB0aGlzLmRpbTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxlbiA9IE51bWJlcih0eXBlLnN1YnN0cigzLCA0KSk7XG4gICAgICAgIH1cblxuICAgICAgICBzdHIgPSBoZWFkO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBzdHIgKz0gdGhpcy52YWx1ZVtpXS50b0ZpeGVkKDMpO1xuICAgICAgICAgICAgaWYgKGkgIT09IGxlbiAtIDEpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gJywnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHIgKz0gZW5kO1xuICAgIH1cblxuICAgIHVuaWZvcm1UeXBlICgpIHtcbiAgICAgICAgcmV0dXJuICd2ZWMnICsgdGhpcy5kaW07XG4gICAgfVxuXG4gICAgdW5pZm9ybVZhbHVlICgpIHtcbiAgICAgICAgdmFyIGFyciA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZGltOyBpKyspIHtcbiAgICAgICAgICAgIGFyci5wdXNoKHRoaXMudmFsdWVbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfVxuXG4gICAgdW5pZm9ybU1ldGhvZCAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpbSArICdmJztcbiAgICB9XG5cbiAgICAvLyBWRUNUT1IgT1BFUkFUSU9OU1xuXG4gICAgYWRkICh2KSB7XG4gICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kaW07IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVbaV0gPSB0aGlzLnZhbHVlW2ldICsgdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxldCBBID0gbmV3IFZlY3Rvcih2KTtcbiAgICAgICAgICAgIGxldCBsaW0gPSBNYXRoLm1pbih0aGlzLmRpbSwgQS5kaW0pO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW07IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVbaV0gPSB0aGlzLnZhbHVlW2ldICsgQS52YWx1ZVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN1YiAodikge1xuICAgICAgICBpZiAodHlwZW9mIHYgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZGltOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlW2ldID0gdGhpcy52YWx1ZVtpXSAtIHY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZXQgQSA9IG5ldyBWZWN0b3Iodik7XG4gICAgICAgICAgICBsZXQgbGltID0gTWF0aC5taW4odGhpcy5kaW0sIEEuZGltKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGltOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlW2ldID0gdGhpcy52YWx1ZVtpXSAtIEEudmFsdWVbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBtdWx0ICh2KSB7XG4gICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIC8vIE11bGl0cGx5IGJ5IHNjYWxhclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRpbTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZVtpXSA9IHRoaXMudmFsdWVbaV0gKiB2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gTXVsdGlwbHkgdHdvIHZlY3RvcnNcbiAgICAgICAgICAgIGxldCBBID0gbmV3IFZlY3Rvcih2KTtcbiAgICAgICAgICAgIGxldCBsaW0gPSBNYXRoLm1pbih0aGlzLmRpbSwgQS5kaW0pO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW07IGkrKykge1xuICAgICAgICAgICAgICAgI
23459HRoaXMudmFsdWVbaV0gPSB0aGlzLnZhbHVlW2ldICogQS52YWx1ZVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRpdiAodikge1xuICAgICAgICBpZiAodHlwZW9mIHYgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAvLyBNdWxpdHBseSBieSBzY2FsYXJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kaW07IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVbaV0gPSB0aGlzLnZhbHVlW2ldIC8gdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIE11bHRpcGx5IHR3byB2ZWN0b3JzXG4gICAgICAgICAgICBsZXQgQSA9IG5ldyBWZWN0b3Iodik7XG4gICAgICAgICAgICBsZXQgbGltID0gTWF0aC5taW4odGhpcy5kaW0sIEEuZGltKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGltOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlW2ldID0gdGhpcy52YWx1ZVtpXSAvIEEudmFsdWVbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBub3JtYWxpemUgKCkge1xuICAgICAgICBsZXQgbCA9IHRoaXMuZ2V0TGVuZ3RoKCk7XG4gICAgICAgIHRoaXMuZGl2KGwpO1xuICAgIH1cblxuICAgIGdldEFkZCAodikge1xuICAgICAgICB2YXIgQSA9IG5ldyBWZWN0b3IodGhpcyk7XG4gICAgICAgIEEuYWRkKHYpO1xuICAgICAgICByZXR1cm4gQTtcbiAgICB9XG5cbiAgICBnZXRTdWIgKHYpIHtcbiAgICAgICAgdmFyIEEgPSBuZXcgVmVjdG9yKHRoaXMpO1xuICAgICAgICBBLnN1Yih2KTtcbiAgICAgICAgcmV0dXJuIEE7XG4gICAgfVxuXG4gICAgZ2V0TXVsdCAodikge1xuICAgICAgICB2Y
23459XIgQSA9IG5ldyBWZWN0b3IodGhpcyk7XG4gICAgICAgIEEubXVsdCh2KTtcbiAgICAgICAgcmV0dXJuIEE7XG4gICAgfVxuXG4gICAgZ2V0RGl2ICh2KSB7XG4gICAgICAgIHZhciBBID0gbmV3IFZlY3Rvcih0aGlzKTtcbiAgICAgICAgQS5kaXYodik7XG4gICAgICAgIHJldHVybiBBO1xuICAgIH1cblxuICAgIGdldExlbmd0aFNxICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZGltID09PSAyKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMudmFsdWVbMF0gKiB0aGlzLnZhbHVlWzBdICsgdGhpcy52YWx1ZVsxXSAqIHRoaXMudmFsdWVbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLnZhbHVlWzBdICogdGhpcy52YWx1ZVswXSArIHRoaXMudmFsdWVbMV0gKiB0aGlzLnZhbHVlWzFdICsgdGhpcy52YWx1ZVsyXSAqIHRoaXMudmFsdWVbMl0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0TGVuZ3RoICgpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmdldExlbmd0aFNxKCkpO1xuICAgIH1cbn1cbiJdfQ==

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.