UNPKG

2.19 MBJavaScriptView Raw
1/*! onsenui v2.0.4 - 2016-11-04 */
2if (!window.CustomEvent) {
3 (function() {
4 var CustomEvent;
5
6 CustomEvent = function(event, params) {
7 var evt;
8 params = params || {
9 bubbles: false,
10 cancelable: false,
11 detail: undefined
12 };
13 evt = document.createEvent("CustomEvent");
14 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
15 return evt;
16 };
17
18 CustomEvent.prototype = window.Event.prototype;
19
20 window.CustomEvent = CustomEvent;
21 })();
22}
23
24/**
25 * @license
26 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
27 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
28 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
29 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
30 * Code distributed by Google as part of the polymer project is also
31 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
32 */
33// @version 0.7.22
34if (typeof WeakMap === "undefined") {
35 (function() {
36 var defineProperty = Object.defineProperty;
37 var counter = Date.now() % 1e9;
38 var WeakMap = function() {
39 this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
40 };
41 WeakMap.prototype = {
42 set: function(key, value) {
43 var entry = key[this.name];
44 if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
45 value: [ key, value ],
46 writable: true
47 });
48 return this;
49 },
50 get: function(key) {
51 var entry;
52 return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
53 },
54 "delete": function(key) {
55 var entry = key[this.name];
56 if (!entry || entry[0] !== key) return false;
57 entry[0] = entry[1] = undefined;
58 return true;
59 },
60 has: function(key) {
61 var entry = key[this.name];
62 if (!entry) return false;
63 return entry[0] === key;
64 }
65 };
66 window.WeakMap = WeakMap;
67 })();
68}
69
70(function(global) {
71 if (global.JsMutationObserver) {
72 return;
73 }
74 var registrationsTable = new WeakMap();
75 var setImmediate;
76 if (/Trident|Edge/.test(navigator.userAgent)) {
77 setImmediate = setTimeout;
78 } else if (window.setImmediate) {
79 setImmediate = window.setImmediate;
80 } else {
81 var setImmediateQueue = [];
82 var sentinel = String(Math.random());
83 window.addEventListener("message", function(e) {
84 if (e.data === sentinel) {
85 var queue = setImmediateQueue;
86 setImmediateQueue = [];
87 queue.forEach(function(func) {
88 func();
89 });
90 }
91 });
92 setImmediate = function(func) {
93 setImmediateQueue.push(func);
94 window.postMessage(sentinel, "*");
95 };
96 }
97 var isScheduled = false;
98 var scheduledObservers = [];
99 function scheduleCallback(observer) {
100 scheduledObservers.push(observer);
101 if (!isScheduled) {
102 isScheduled = true;
103 setImmediate(dispatchCallbacks);
104 }
105 }
106 function wrapIfNeeded(node) {
107 return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
108 }
109 function dispatchCallbacks() {
110 isScheduled = false;
111 var observers = scheduledObservers;
112 scheduledObservers = [];
113 observers.sort(function(o1, o2) {
114 return o1.uid_ - o2.uid_;
115 });
116 var anyNonEmpty = false;
117 observers.forEach(function(observer) {
118 var queue = observer.takeRecords();
119 removeTransientObserversFor(observer);
120 if (queue.length) {
121 observer.callback_(queue, observer);
122 anyNonEmpty = true;
123 }
124 });
125 if (anyNonEmpty) dispatchCallbacks();
126 }
127 function removeTransientObserversFor(observer) {
128 observer.nodes_.forEach(function(node) {
129 var registrations = registrationsTable.get(node);
130 if (!registrations) return;
131 registrations.forEach(function(registration) {
132 if (registration.observer === observer) registration.removeTransientObservers();
133 });
134 });
135 }
136 function forEachAncestorAndObserverEnqueueRecord(target, callback) {
137 for (var node = target; node; node = node.parentNode) {
138 var registrations = registrationsTable.get(node);
139 if (registrations) {
140 for (var j = 0; j < registrations.length; j++) {
141 var registration = registrations[j];
142 var options = registration.options;
143 if (node !== target && !options.subtree) continue;
144 var record = callback(options);
145 if (record) registration.enqueue(record);
146 }
147 }
148 }
149 }
150 var uidCounter = 0;
151 function JsMutationObserver(callback) {
152 this.callback_ = callback;
153 this.nodes_ = [];
154 this.records_ = [];
155 this.uid_ = ++uidCounter;
156 }
157 JsMutationObserver.prototype = {
158 observe: function(target, options) {
159 target = wrapIfNeeded(target);
160 if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
161 throw new SyntaxError();
162 }
163 var registrations = registrationsTable.get(target);
164 if (!registrations) registrationsTable.set(target, registrations = []);
165 var registration;
166 for (var i = 0; i < registrations.length; i++) {
167 if (registrations[i].observer === this) {
168 registration = registrations[i];
169 registration.removeListeners();
170 registration.options = options;
171 break;
172 }
173 }
174 if (!registration) {
175 registration = new Registration(this, target, options);
176 registrations.push(registration);
177 this.nodes_.push(target);
178 }
179 registration.addListeners();
180 },
181 disconnect: function() {
182 this.nodes_.forEach(function(node) {
183 var registrations = registrationsTable.get(node);
184 for (var i = 0; i < registrations.length; i++) {
185 var registration = registrations[i];
186 if (registration.observer === this) {
187 registration.removeListeners();
188 registrations.splice(i, 1);
189 break;
190 }
191 }
192 }, this);
193 this.records_ = [];
194 },
195 takeRecords: function() {
196 var copyOfRecords = this.records_;
197 this.records_ = [];
198 return copyOfRecords;
199 }
200 };
201 function MutationRecord(type, target) {
202 this.type = type;
203 this.target = target;
204 this.addedNodes = [];
205 this.removedNodes = [];
206 this.previousSibling = null;
207 this.nextSibling = null;
208 this.attributeName = null;
209 this.attributeNamespace = null;
210 this.oldValue = null;
211 }
212 function copyMutationRecord(original) {
213 var record = new MutationRecord(original.type, original.target);
214 record.addedNodes = original.addedNodes.slice();
215 record.removedNodes = original.removedNodes.slice();
216 record.previousSibling = original.previousSibling;
217 record.nextSibling = original.nextSibling;
218 record.attributeName = original.attributeName;
219 record.attributeNamespace = original.attributeNamespace;
220 record.oldValue = original.oldValue;
221 return record;
222 }
223 var currentRecord, recordWithOldValue;
224 function getRecord(type, target) {
225 return currentRecord = new MutationRecord(type, target);
226 }
227 function getRecordWithOldValue(oldValue) {
228 if (recordWithOldValue) return recordWithOldValue;
229 recordWithOldValue = copyMutationRecord(currentRecord);
230 recordWithOldValue.oldValue = oldValue;
231 return recordWithOldValue;
232 }
233 function clearRecords() {
234 currentRecord = recordWithOldValue = undefined;
235 }
236 function recordRepresentsCurrentMutation(record) {
237 return record === recordWithOldValue || record === currentRecord;
238 }
239 function selectRecord(lastRecord, newRecord) {
240 if (lastRecord === newRecord) return lastRecord;
241 if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
242 return null;
243 }
244 function Registration(observer, target, options) {
245 this.observer = observer;
246 this.target = target;
247 this.options = options;
248 this.transientObservedNodes = [];
249 }
250 Registration.prototype = {
251 enqueue: function(record) {
252 var records = this.observer.records_;
253 var length = records.length;
254 if (records.length > 0) {
255 var lastRecord = records[length - 1];
256 var recordToReplaceLast = selectRecord(lastRecord, record);
257 if (recordToReplaceLast) {
258 records[length - 1] = recordToReplaceLast;
259 return;
260 }
261 } else {
262 scheduleCallback(this.observer);
263 }
264 records[length] = record;
265 },
266 addListeners: function() {
267 this.addListeners_(this.target);
268 },
269 addListeners_: function(node) {
270 var options = this.options;
271 if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
272 if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
273 if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
274 if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
275 },
276 removeListeners: function() {
277 this.removeListeners_(this.target);
278 },
279 removeListeners_: function(node) {
280 var options = this.options;
281 if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
282 if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
283 if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
284 if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
285 },
286 addTransientObserver: function(node) {
287 if (node === this.target) return;
288 this.addListeners_(node);
289 this.transientObservedNodes.push(node);
290 var registrations = registrationsTable.get(node);
291 if (!registrations) registrationsTable.set(node, registrations = []);
292 registrations.push(this);
293 },
294 removeTransientObservers: function() {
295 var transientObservedNodes = this.transientObservedNodes;
296 this.transientObservedNodes = [];
297 transientObservedNodes.forEach(function(node) {
298 this.removeListeners_(node);
299 var registrations = registrationsTable.get(node);
300 for (var i = 0; i < registrations.length; i++) {
301 if (registrations[i] === this) {
302 registrations.splice(i, 1);
303 break;
304 }
305 }
306 }, this);
307 },
308 handleEvent: function(e) {
309 e.stopImmediatePropagation();
310 switch (e.type) {
311 case "DOMAttrModified":
312 var name = e.attrName;
313 var namespace = e.relatedNode.namespaceURI;
314 var target = e.target;
315 var record = new getRecord("attributes", target);
316 record.attributeName = name;
317 record.attributeNamespace = namespace;
318 var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
319 forEachAncestorAndObserverEnqueueRecord(target, function(options) {
320 if (!options.attributes) return;
321 if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
322 return;
323 }
324 if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
325 return record;
326 });
327 break;
328
329 case "DOMCharacterDataModified":
330 var target = e.target;
331 var record = getRecord("characterData", target);
332 var oldValue = e.prevValue;
333 forEachAncestorAndObserverEnqueueRecord(target, function(options) {
334 if (!options.characterData) return;
335 if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
336 return record;
337 });
338 break;
339
340 case "DOMNodeRemoved":
341 this.addTransientObserver(e.target);
342
343 case "DOMNodeInserted":
344 var changedNode = e.target;
345 var addedNodes, removedNodes;
346 if (e.type === "DOMNodeInserted") {
347 addedNodes = [ changedNode ];
348 removedNodes = [];
349 } else {
350 addedNodes = [];
351 removedNodes = [ changedNode ];
352 }
353 var previousSibling = changedNode.previousSibling;
354 var nextSibling = changedNode.nextSibling;
355 var record = getRecord("childList", e.target.parentNode);
356 record.addedNodes = addedNodes;
357 record.removedNodes = removedNodes;
358 record.previousSibling = previousSibling;
359 record.nextSibling = nextSibling;
360 forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
361 if (!options.childList) return;
362 return record;
363 });
364 }
365 clearRecords();
366 }
367 };
368 global.JsMutationObserver = JsMutationObserver;
369 if (!global.MutationObserver) {
370 global.MutationObserver = JsMutationObserver;
371 JsMutationObserver._isPolyfilled = true;
372 }
373})(self);
374/*
375Copyright 2013-2015 ASIAL CORPORATION
376
377Licensed under the Apache License, Version 2.0 (the "License");
378you may not use this file except in compliance with the License.
379You may obtain a copy of the License at
380
381 http://www.apache.org/licenses/LICENSE-2.0
382
383Unless required by applicable law or agreed to in writing, software
384distributed under the License is distributed on an "AS IS" BASIS,
385WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
386See the License for the specific language governing permissions and
387limitations under the License.
388
389*/
390
391
392/**
393 * Minimal animation library for managing css transition on mobile browsers.
394 */
395window.animit = (function(){
396 'use strict';
397
398 var TIMEOUT_RATIO = 1.4;
399
400 var util = {
401 };
402
403 // capitalize string
404 util.capitalize = function(str) {
405 return str.charAt(0).toUpperCase() + str.slice(1);
406 };
407
408 /**
409 * @param {Object} params
410 * @param {String} params.property
411 * @param {Float} params.duration
412 * @param {String} params.timing
413 */
414 util.buildTransitionValue = function(params) {
415 params.property = params.property || 'all';
416 params.duration = params.duration || 0.4;
417 params.timing = params.timing || 'linear';
418
419 var props = params.property.split(/ +/);
420
421 return props.map(function(prop) {
422 return prop + ' ' + params.duration + 's ' + params.timing;
423 }).join(', ');
424 };
425
426 /**
427 * Add an event handler on "transitionend" event.
428 */
429 util.onceOnTransitionEnd = function(element, callback) {
430 if (!element) {
431 return function() {};
432 }
433
434 var fn = function(event) {
435 if (element == event.target) {
436 event.stopPropagation();
437 removeListeners();
438
439 callback();
440 }
441 };
442
443 var removeListeners = function() {
444 util._transitionEndEvents.forEach(function(eventName) {
445 element.removeEventListener(eventName, fn, false);
446 });
447 };
448
449 util._transitionEndEvents.forEach(function(eventName) {
450 element.addEventListener(eventName, fn, false);
451 });
452
453 return removeListeners;
454 };
455
456 util._transitionEndEvents = (function() {
457
458 if ('ontransitionend' in window) {
459 return ['transitionend'];
460 }
461
462 if ('onwebkittransitionend' in window) {
463 return ['webkitTransitionEnd'];
464 }
465
466 if (util.vendorPrefix === 'webkit' || util.vendorPrefix === 'o' || util.vendorPrefix === 'moz' || util.vendorPrefix === 'ms') {
467 return [util.vendorPrefix + 'TransitionEnd', 'transitionend'];
468 }
469
470 return [];
471 })();
472
473 util._cssPropertyDict = (function() {
474 var styles = window.getComputedStyle(document.documentElement, '');
475 var dict = {};
476 var a = 'A'.charCodeAt(0);
477 var z = 'z'.charCodeAt(0);
478
479 var upper = function(s) {
480 return s.substr(1).toUpperCase();
481 };
482
483 for (var i = 0; i < styles.length; i++) {
484
485 var key = styles[i]
486 .replace(/^[\-]+/, '')
487 .replace(/[\-][a-z]/g, upper)
488 .replace(/^moz/, 'Moz');
489
490 if (a <= key.charCodeAt(0) && z >= key.charCodeAt(0)) {
491 if (key !== 'cssText' && key !== 'parentText') {
492 dict[key] = true;
493 }
494 }
495 }
496
497 return dict;
498 })();
499
500 util.hasCssProperty = function(name) {
501 return name in util._cssPropertyDict;
502 };
503
504 /**
505 * Vendor prefix for css property.
506 */
507 util.vendorPrefix = (function() {
508 var styles = window.getComputedStyle(document.documentElement, ''),
509 pre = (Array.prototype.slice
510 .call(styles)
511 .join('')
512 .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
513 )[1];
514 return pre;
515 })();
516
517 util.forceLayoutAtOnce = function(elements, callback) {
518 this.batchImmediate(function() {
519 elements.forEach(function(element) {
520 // force layout
521 element.offsetHeight;
522 });
523 callback();
524 });
525 };
526
527 util.batchImmediate = (function() {
528 var callbacks = [];
529
530 return function(callback) {
531 if (callbacks.length === 0) {
532 setImmediate(function() {
533 var concreateCallbacks = callbacks.slice(0);
534 callbacks = [];
535 concreateCallbacks.forEach(function(callback) {
536 callback();
537 });
538 });
539 }
540
541 callbacks.push(callback);
542 };
543 })();
544
545 util.batchAnimationFrame = (function() {
546 var callbacks = [];
547
548 var raf = window.requestAnimationFrame ||
549 window.webkitRequestAnimationFrame ||
550 window.mozRequestAnimationFrame ||
551 window.oRequestAnimationFrame ||
552 window.msRequestAnimationFrame ||
553 function(callback) {
554 setTimeout(callback, 1000 / 60);
555 };
556
557 return function(callback) {
558 if (callbacks.length === 0) {
559 raf(function() {
560 var concreateCallbacks = callbacks.slice(0);
561 callbacks = [];
562 concreateCallbacks.forEach(function(callback) {
563 callback();
564 });
565 });
566 }
567
568 callbacks.push(callback);
569 };
570 })();
571
572 util.transitionPropertyName = (function() {
573 if (util.hasCssProperty('transitionDuration')) {
574 return 'transition';
575 }
576
577 if (util.hasCssProperty(util.vendorPrefix + 'TransitionDuration')) {
578 return util.vendorPrefix + 'Transition';
579 }
580
581 throw new Error('Invalid state');
582 })();
583
584
585 /**
586 * @param {HTMLElement} element
587 */
588 var Animit = function(element) {
589 if (!(this instanceof Animit)) {
590 return new Animit(element);
591 }
592
593 if (element instanceof HTMLElement) {
594 this.elements = [element];
595 } else if (Object.prototype.toString.call(element) === '[object Array]') {
596 this.elements = element;
597
598 } else {
599 throw new Error('First argument must be an array or an instance of HTMLElement.');
600 }
601
602 this.transitionQueue = [];
603 this.lastStyleAttributeDict = [];
604 };
605
606 Animit.prototype = {
607
608 /**
609 * @property {Array}
610 */
611 transitionQueue: undefined,
612
613 /**
614 * @property {Array}
615 */
616 elements: undefined,
617
618 /**
619 * Start animation sequence with passed animations.
620 *
621 * @param {Function} callback
622 */
623 play: function(callback) {
624 if (typeof callback === 'function') {
625 this.transitionQueue.push(function(done) {
626 callback();
627 done();
628 });
629 }
630
631 this.startAnimation();
632
633 return this;
634 },
635
636 /**
637 * Queue transition animations or other function.
638 *
639 * e.g. animit(elt).queue({color: 'red'})
640 * e.g. animit(elt).queue({color: 'red'}, {duration: 0.4})
641 * e.g. animit(elt).queue({css: {color: 'red'}, duration: 0.2})
642 *
643 * @param {Object|Animit.Transition|Function} transition
644 * @param {Object} [options]
645 */
646 queue: function(transition, options) {
647 var queue = this.transitionQueue;
648
649 if (transition && options) {
650 options.css = transition;
651 transition = new Animit.Transition(options);
652 }
653
654 if (!(transition instanceof Function || transition instanceof Animit.Transition)) {
655 if (transition.css) {
656 transition = new Animit.Transition(transition);
657 } else {
658 transition = new Animit.Transition({
659 css: transition
660 });
661 }
662 }
663
664 if (transition instanceof Function) {
665 queue.push(transition);
666 } else if (transition instanceof Animit.Transition) {
667 queue.push(transition.build());
668 } else {
669 throw new Error('Invalid arguments');
670 }
671
672 return this;
673 },
674
675 /**
676 * Queue transition animations.
677 *
678 * @param {Float} seconds
679 */
680 wait: function(seconds) {
681 if (seconds > 0) {
682 this.transitionQueue.push(function(done) {
683 setTimeout(done, 1000 * seconds);
684 });
685 }
686
687 return this;
688 },
689
690 saveStyle: function() {
691
692 this.transitionQueue.push(function(done) {
693 this.elements.forEach(function(element, index) {
694 var css = this.lastStyleAttributeDict[index] = {};
695
696 for (var i = 0; i < element.style.length; i++) {
697 css[element.style[i]] = element.style[element.style[i]];
698 }
699 }.bind(this));
700 done();
701 }.bind(this));
702
703 return this;
704 },
705
706 /**
707 * Restore element's style.
708 *
709 * @param {Object} [options]
710 * @param {Float} [options.duration]
711 * @param {String} [options.timing]
712 * @param {String} [options.transition]
713 */
714 restoreStyle: function(options) {
715 options = options || {};
716 var self = this;
717
718 if (options.transition && !options.duration) {
719 throw new Error('"options.duration" is required when "options.transition" is enabled.');
720 }
721
722 var transitionName = util.transitionPropertyName;
723
724 if (options.transition || (options.duration && options.duration > 0)) {
725 var transitionValue = options.transition || ('all ' + options.duration + 's ' + (options.timing || 'linear'));
726
727 this.transitionQueue.push(function(done) {
728 var elements = this.elements;
729 var timeoutId;
730
731 var clearTransition = function() {
732 elements.forEach(function(element) {
733 element.style[transitionName] = '';
734 });
735 };
736
737 // add "transitionend" event handler
738 var removeListeners = util.onceOnTransitionEnd(elements[0], function() {
739 clearTimeout(timeoutId);
740 clearTransition();
741 done();
742 });
743
744 // for fail safe.
745 timeoutId = setTimeout(function() {
746 removeListeners();
747 clearTransition();
748 done();
749 }, options.duration * 1000 * TIMEOUT_RATIO);
750
751 // transition and style settings
752 elements.forEach(function(element, index) {
753
754 var css = self.lastStyleAttributeDict[index];
755
756 if (!css) {
757 throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.');
758 }
759
760 self.lastStyleAttributeDict[index] = undefined;
761
762 var name;
763 for (var i = 0, len = element.style.length; i < len; i++) {
764 name = element.style[i];
765 if (css[name] === undefined) {
766 css[name] = '';
767 }
768 }
769
770 element.style[transitionName] = transitionValue;
771
772 Object.keys(css).forEach(function(key) {
773 if (key !== transitionName) {
774 element.style[key] = css[key];
775 }
776 });
777
778 element.style[transitionName] = transitionValue;
779 });
780 });
781 } else {
782 this.transitionQueue.push(function(done) {
783 reset();
784 done();
785 });
786 }
787
788 return this;
789
790 function reset() {
791 // Clear transition animation settings.
792 self.elements.forEach(function(element, index) {
793 element.style[transitionName] = 'none';
794
795 var css = self.lastStyleAttributeDict[index];
796
797 if (!css) {
798 throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.');
799 }
800
801 self.lastStyleAttributeDict[index] = undefined;
802
803 for (var i = 0, name = ''; i < element.style.length; i++) {
804 name = element.style[i];
805 if (typeof css[element.style[i]] === 'undefined') {
806 css[element.style[i]] = '';
807 }
808 }
809
810 Object.keys(css).forEach(function(key) {
811 element.style[key] = css[key];
812 });
813
814 });
815 }
816 },
817
818 /**
819 * Start animation sequence.
820 */
821 startAnimation: function() {
822 this._dequeueTransition();
823
824 return this;
825 },
826
827 _dequeueTransition: function() {
828 var transition = this.transitionQueue.shift();
829 if (this._currentTransition) {
830 throw new Error('Current transition exists.');
831 }
832 this._currentTransition = transition;
833 var self = this;
834 var called = false;
835
836 var done = function() {
837 if (!called) {
838 called = true;
839 self._currentTransition = undefined;
840 self._dequeueTransition();
841 } else {
842 throw new Error('Invalid state: This callback is called twice.');
843 }
844 };
845
846 if (transition) {
847 transition.call(this, done);
848 }
849 }
850
851 };
852
853 /**
854 * @param {Animit} arguments
855 */
856 Animit.runAll = function(/* arguments... */) {
857 for (var i = 0; i < arguments.length; i++) {
858 arguments[i].play();
859 }
860 };
861
862
863 /**
864 * @param {Object} options
865 * @param {Float} [options.duration]
866 * @param {String} [options.property]
867 * @param {String} [options.timing]
868 */
869 Animit.Transition = function(options) {
870 this.options = options || {};
871 this.options.duration = this.options.duration || 0;
872 this.options.timing = this.options.timing || 'linear';
873 this.options.css = this.options.css || {};
874 this.options.property = this.options.property || 'all';
875 };
876
877 Animit.Transition.prototype = {
878
879 /**
880 * @param {HTMLElement} element
881 * @return {Function}
882 */
883 build: function() {
884
885 if (Object.keys(this.options.css).length === 0) {
886 throw new Error('options.css is required.');
887 }
888
889 var css = createActualCssProps(this.options.css);
890
891 if (this.options.duration > 0) {
892 var transitionValue = util.buildTransitionValue(this.options);
893 var self = this;
894
895 return function(callback) {
896 var elements = this.elements;
897 var timeout = self.options.duration * 1000 * TIMEOUT_RATIO;
898 var timeoutId;
899
900 var removeListeners = util.onceOnTransitionEnd(elements[0], function() {
901 clearTimeout(timeoutId);
902 callback();
903 });
904
905 timeoutId = setTimeout(function() {
906 removeListeners();
907 callback();
908 }, timeout);
909
910 elements.forEach(function(element) {
911 element.style[util.transitionPropertyName] = transitionValue;
912
913 Object.keys(css).forEach(function(name) {
914 element.style[name] = css[name];
915 });
916 });
917
918 };
919 }
920
921 if (this.options.duration <= 0) {
922 return function(callback) {
923 var elements = this.elements;
924
925 elements.forEach(function(element) {
926 element.style[util.transitionPropertyName] = '';
927
928 Object.keys(css).forEach(function(name) {
929 element.style[name] = css[name];
930 });
931 });
932
933 if (elements.length > 0) {
934 util.forceLayoutAtOnce(elements, function() {
935 util.batchAnimationFrame(callback);
936 });
937 } else {
938 util.batchAnimationFrame(callback);
939 }
940 };
941 }
942
943 function createActualCssProps(css) {
944 var result = {};
945
946 Object.keys(css).forEach(function(name) {
947 var value = css[name];
948
949 if (util.hasCssProperty(name)) {
950 result[name] = value;
951 return;
952 }
953
954 var prefixed = util.vendorPrefix + util.capitalize(name);
955 if (util.hasCssProperty(prefixed)) {
956 result[prefixed] = value;
957 } else {
958 result[prefixed] = value;
959 result[name] = value;
960 }
961 });
962
963 return result;
964 }
965
966 }
967 };
968
969
970 return Animit;
971})();
972
973/*
974 * childNode.remove method polyfill for IE.
975 * https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
976 */
977
978(function() {
979 if (!('remove' in Element.prototype)) {
980 Element.prototype.remove = function() {
981 if (this.parentNode) {
982 this.parentNode.removeChild(this);
983 }
984 };
985 }
986})();
987
988/*
989 * classList.js: Cross-browser full element.classList implementation.
990 * 1.1.20150312
991 *
992 * By Eli Grey, http://eligrey.com
993 * License: Dedicated to the public domain.
994 * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md
995 */
996
997/*global self, document, DOMException */
998
999/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
1000
1001if ("document" in self) {
1002
1003// Full polyfill for browsers with no classList support
1004// Including IE < Edge missing SVGElement.classList
1005if (!("classList" in document.createElement("_"))
1006 || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
1007
1008(function (view) {
1009
1010"use strict";
1011
1012if (!('Element' in view)) return;
1013
1014var
1015 classListProp = "classList"
1016 , protoProp = "prototype"
1017 , elemCtrProto = view.Element[protoProp]
1018 , objCtr = Object
1019 , strTrim = String[protoProp].trim || function () {
1020 return this.replace(/^\s+|\s+$/g, "");
1021 }
1022 , arrIndexOf = Array[protoProp].indexOf || function (item) {
1023 var
1024 i = 0
1025 , len = this.length
1026 ;
1027 for (; i < len; i++) {
1028 if (i in this && this[i] === item) {
1029 return i;
1030 }
1031 }
1032 return -1;
1033 }
1034 // Vendors: please allow content code to instantiate DOMExceptions
1035 , DOMEx = function (type, message) {
1036 this.name = type;
1037 this.code = DOMException[type];
1038 this.message = message;
1039 }
1040 , checkTokenAndGetIndex = function (classList, token) {
1041 if (token === "") {
1042 throw new DOMEx(
1043 "SYNTAX_ERR"
1044 , "An invalid or illegal string was specified"
1045 );
1046 }
1047 if (/\s/.test(token)) {
1048 throw new DOMEx(
1049 "INVALID_CHARACTER_ERR"
1050 , "String contains an invalid character"
1051 );
1052 }
1053 return arrIndexOf.call(classList, token);
1054 }
1055 , ClassList = function (elem) {
1056 var
1057 trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
1058 , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
1059 , i = 0
1060 , len = classes.length
1061 ;
1062 for (; i < len; i++) {
1063 this.push(classes[i]);
1064 }
1065 this._updateClassName = function () {
1066 elem.setAttribute("class", this.toString());
1067 };
1068 }
1069 , classListProto = ClassList[protoProp] = []
1070 , classListGetter = function () {
1071 return new ClassList(this);
1072 }
1073;
1074// Most DOMException implementations don't allow calling DOMException's toString()
1075// on non-DOMExceptions. Error's toString() is sufficient here.
1076DOMEx[protoProp] = Error[protoProp];
1077classListProto.item = function (i) {
1078 return this[i] || null;
1079};
1080classListProto.contains = function (token) {
1081 token += "";
1082 return checkTokenAndGetIndex(this, token) !== -1;
1083};
1084classListProto.add = function () {
1085 var
1086 tokens = arguments
1087 , i = 0
1088 , l = tokens.length
1089 , token
1090 , updated = false
1091 ;
1092 do {
1093 token = tokens[i] + "";
1094 if (checkTokenAndGetIndex(this, token) === -1) {
1095 this.push(token);
1096 updated = true;
1097 }
1098 }
1099 while (++i < l);
1100
1101 if (updated) {
1102 this._updateClassName();
1103 }
1104};
1105classListProto.remove = function () {
1106 var
1107 tokens = arguments
1108 , i = 0
1109 , l = tokens.length
1110 , token
1111 , updated = false
1112 , index
1113 ;
1114 do {
1115 token = tokens[i] + "";
1116 index = checkTokenAndGetIndex(this, token);
1117 while (index !== -1) {
1118 this.splice(index, 1);
1119 updated = true;
1120 index = checkTokenAndGetIndex(this, token);
1121 }
1122 }
1123 while (++i < l);
1124
1125 if (updated) {
1126 this._updateClassName();
1127 }
1128};
1129classListProto.toggle = function (token, force) {
1130 token += "";
1131
1132 var
1133 result = this.contains(token)
1134 , method = result ?
1135 force !== true && "remove"
1136 :
1137 force !== false && "add"
1138 ;
1139
1140 if (method) {
1141 this[method](token);
1142 }
1143
1144 if (force === true || force === false) {
1145 return force;
1146 } else {
1147 return !result;
1148 }
1149};
1150classListProto.toString = function () {
1151 return this.join(" ");
1152};
1153
1154if (objCtr.defineProperty) {
1155 var classListPropDesc = {
1156 get: classListGetter
1157 , enumerable: true
1158 , configurable: true
1159 };
1160 try {
1161 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
1162 } catch (ex) { // IE 8 doesn't support enumerable:true
1163 if (ex.number === -0x7FF5EC54) {
1164 classListPropDesc.enumerable = false;
1165 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
1166 }
1167 }
1168} else if (objCtr[protoProp].__defineGetter__) {
1169 elemCtrProto.__defineGetter__(classListProp, classListGetter);
1170}
1171
1172}(self));
1173
1174} else {
1175// There is full or partial native classList support, so just check if we need
1176// to normalize the add/remove and toggle APIs.
1177
1178(function () {
1179 "use strict";
1180
1181 var testElement = document.createElement("_");
1182
1183 testElement.classList.add("c1", "c2");
1184
1185 // Polyfill for IE 10/11 and Firefox <26, where classList.add and
1186 // classList.remove exist but support only one argument at a time.
1187 if (!testElement.classList.contains("c2")) {
1188 var createMethod = function(method) {
1189 var original = DOMTokenList.prototype[method];
1190
1191 DOMTokenList.prototype[method] = function(token) {
1192 var i, len = arguments.length;
1193
1194 for (i = 0; i < len; i++) {
1195 token = arguments[i];
1196 original.call(this, token);
1197 }
1198 };
1199 };
1200 createMethod('add');
1201 createMethod('remove');
1202 }
1203
1204 testElement.classList.toggle("c3", false);
1205
1206 // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
1207 // support the second argument.
1208 if (testElement.classList.contains("c3")) {
1209 var _toggle = DOMTokenList.prototype.toggle;
1210
1211 DOMTokenList.prototype.toggle = function(token, force) {
1212 if (1 in arguments && !this.contains(token) === !force) {
1213 return force;
1214 } else {
1215 return _toggle.call(this, token);
1216 }
1217 };
1218
1219 }
1220
1221 testElement = null;
1222}());
1223
1224}
1225
1226}
1227
1228
1229/*!
1230
1231Copyright (C) 2014-2016 by Andrea Giammarchi - @WebReflection
1232
1233Permission is hereby granted, free of charge, to any person obtaining a copy
1234of this software and associated documentation files (the "Software"), to deal
1235in the Software without restriction, including without limitation the rights
1236to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1237copies of the Software, and to permit persons to whom the Software is
1238furnished to do so, subject to the following conditions:
1239
1240The above copyright notice and this permission notice shall be included in
1241all copies or substantial portions of the Software.
1242
1243THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1244IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1245FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1246AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1247LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1248OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1249THE SOFTWARE.
1250
1251*/
1252
1253if ('customElements' in window) {
1254 window.customElements.define = undefined;
1255}
1256
1257(function(window){'use strict';
1258
1259 // DO NOT USE THIS FILE DIRECTLY, IT WON'T WORK
1260 // THIS IS A PROJECT BASED ON A BUILD SYSTEM
1261 // THIS FILE IS JUST WRAPPED UP RESULTING IN
1262 // build/document-register-element.js
1263 // and its .max.js counter part
1264
1265 var
1266 document = window.document,
1267 Object = window.Object
1268 ;
1269
1270 var htmlClass = (function (info) {
1271 // (C) Andrea Giammarchi - @WebReflection - MIT Style
1272 var
1273 catchClass = /^[A-Z]+[a-z]/,
1274 filterBy = function (re) {
1275 var arr = [], tag;
1276 for (tag in register) {
1277 if (re.test(tag)) arr.push(tag);
1278 }
1279 return arr;
1280 },
1281 add = function (Class, tag) {
1282 tag = tag.toLowerCase();
1283 if (!(tag in register)) {
1284 register[Class] = (register[Class] || []).concat(tag);
1285 register[tag] = (register[tag.toUpperCase()] = Class);
1286 }
1287 },
1288 register = (Object.create || Object)(null),
1289 htmlClass = {},
1290 i, section, tags, Class
1291 ;
1292 for (section in info) {
1293 for (Class in info[section]) {
1294 tags = info[section][Class];
1295 register[Class] = tags;
1296 for (i = 0; i < tags.length; i++) {
1297 register[tags[i].toLowerCase()] =
1298 register[tags[i].toUpperCase()] = Class;
1299 }
1300 }
1301 }
1302 htmlClass.get = function get(tagOrClass) {
1303 return typeof tagOrClass === 'string' ?
1304 (register[tagOrClass] || (catchClass.test(tagOrClass) ? [] : '')) :
1305 filterBy(tagOrClass);
1306 };
1307 htmlClass.set = function set(tag, Class) {
1308 return (catchClass.test(tag) ?
1309 add(tag, Class) :
1310 add(Class, tag)
1311 ), htmlClass;
1312 };
1313 return htmlClass;
1314 }({
1315 "collections": {
1316 "HTMLAllCollection": [
1317 "all"
1318 ],
1319 "HTMLCollection": [
1320 "forms"
1321 ],
1322 "HTMLFormControlsCollection": [
1323 "elements"
1324 ],
1325 "HTMLOptionsCollection": [
1326 "options"
1327 ]
1328 },
1329 "elements": {
1330 "Element": [
1331 "element"
1332 ],
1333 "HTMLAnchorElement": [
1334 "a"
1335 ],
1336 "HTMLAppletElement": [
1337 "applet"
1338 ],
1339 "HTMLAreaElement": [
1340 "area"
1341 ],
1342 "HTMLAttachmentElement": [
1343 "attachment"
1344 ],
1345 "HTMLAudioElement": [
1346 "audio"
1347 ],
1348 "HTMLBRElement": [
1349 "br"
1350 ],
1351 "HTMLBaseElement": [
1352 "base"
1353 ],
1354 "HTMLBodyElement": [
1355 "body"
1356 ],
1357 "HTMLButtonElement": [
1358 "button"
1359 ],
1360 "HTMLCanvasElement": [
1361 "canvas"
1362 ],
1363 "HTMLContentElement": [
1364 "content"
1365 ],
1366 "HTMLDListElement": [
1367 "dl"
1368 ],
1369 "HTMLDataElement": [
1370 "data"
1371 ],
1372 "HTMLDataListElement": [
1373 "datalist"
1374 ],
1375 "HTMLDetailsElement": [
1376 "details"
1377 ],
1378 "HTMLDialogElement": [
1379 "dialog"
1380 ],
1381 "HTMLDirectoryElement": [
1382 "dir"
1383 ],
1384 "HTMLDivElement": [
1385 "div"
1386 ],
1387 "HTMLDocument": [
1388 "document"
1389 ],
1390 "HTMLElement": [
1391 "element",
1392 "abbr",
1393 "address",
1394 "article",
1395 "aside",
1396 "b",
1397 "bdi",
1398 "bdo",
1399 "cite",
1400 "code",
1401 "command",
1402 "dd",
1403 "dfn",
1404 "dt",
1405 "em",
1406 "figcaption",
1407 "figure",
1408 "footer",
1409 "header",
1410 "i",
1411 "kbd",
1412 "mark",
1413 "nav",
1414 "noscript",
1415 "rp",
1416 "rt",
1417 "ruby",
1418 "s",
1419 "samp",
1420 "section",
1421 "small",
1422 "strong",
1423 "sub",
1424 "summary",
1425 "sup",
1426 "u",
1427 "var",
1428 "wbr"
1429 ],
1430 "HTMLEmbedElement": [
1431 "embed"
1432 ],
1433 "HTMLFieldSetElement": [
1434 "fieldset"
1435 ],
1436 "HTMLFontElement": [
1437 "font"
1438 ],
1439 "HTMLFormElement": [
1440 "form"
1441 ],
1442 "HTMLFrameElement": [
1443 "frame"
1444 ],
1445 "HTMLFrameSetElement": [
1446 "frameset"
1447 ],
1448 "HTMLHRElement": [
1449 "hr"
1450 ],
1451 "HTMLHeadElement": [
1452 "head"
1453 ],
1454 "HTMLHeadingElement": [
1455 "h1",
1456 "h2",
1457 "h3",
1458 "h4",
1459 "h5",
1460 "h6"
1461 ],
1462 "HTMLHtmlElement": [
1463 "html"
1464 ],
1465 "HTMLIFrameElement": [
1466 "iframe"
1467 ],
1468 "HTMLImageElement": [
1469 "img"
1470 ],
1471 "HTMLInputElement": [
1472 "input"
1473 ],
1474 "HTMLKeygenElement": [
1475 "keygen"
1476 ],
1477 "HTMLLIElement": [
1478 "li"
1479 ],
1480 "HTMLLabelElement": [
1481 "label"
1482 ],
1483 "HTMLLegendElement": [
1484 "legend"
1485 ],
1486 "HTMLLinkElement": [
1487 "link"
1488 ],
1489 "HTMLMapElement": [
1490 "map"
1491 ],
1492 "HTMLMarqueeElement": [
1493 "marquee"
1494 ],
1495 "HTMLMediaElement": [
1496 "media"
1497 ],
1498 "HTMLMenuElement": [
1499 "menu"
1500 ],
1501 "HTMLMenuItemElement": [
1502 "menuitem"
1503 ],
1504 "HTMLMetaElement": [
1505 "meta"
1506 ],
1507 "HTMLMeterElement": [
1508 "meter"
1509 ],
1510 "HTMLModElement": [
1511 "del",
1512 "ins"
1513 ],
1514 "HTMLOListElement": [
1515 "ol"
1516 ],
1517 "HTMLObjectElement": [
1518 "object"
1519 ],
1520 "HTMLOptGroupElement": [
1521 "optgroup"
1522 ],
1523 "HTMLOptionElement": [
1524 "option"
1525 ],
1526 "HTMLOutputElement": [
1527 "output"
1528 ],
1529 "HTMLParagraphElement": [
1530 "p"
1531 ],
1532 "HTMLParamElement": [
1533 "param"
1534 ],
1535 "HTMLPictureElement": [
1536 "picture"
1537 ],
1538 "HTMLPreElement": [
1539 "pre"
1540 ],
1541 "HTMLProgressElement": [
1542 "progress"
1543 ],
1544 "HTMLQuoteElement": [
1545 "blockquote",
1546 "q",
1547 "quote"
1548 ],
1549 "HTMLScriptElement": [
1550 "script"
1551 ],
1552 "HTMLSelectElement": [
1553 "select"
1554 ],
1555 "HTMLShadowElement": [
1556 "shadow"
1557 ],
1558 "HTMLSlotElement": [
1559 "slot"
1560 ],
1561 "HTMLSourceElement": [
1562 "source"
1563 ],
1564 "HTMLSpanElement": [
1565 "span"
1566 ],
1567 "HTMLStyleElement": [
1568 "style"
1569 ],
1570 "HTMLTableCaptionElement": [
1571 "caption"
1572 ],
1573 "HTMLTableCellElement": [
1574 "td",
1575 "th"
1576 ],
1577 "HTMLTableColElement": [
1578 "col",
1579 "colgroup"
1580 ],
1581 "HTMLTableElement": [
1582 "table"
1583 ],
1584 "HTMLTableRowElement": [
1585 "tr"
1586 ],
1587 "HTMLTableSectionElement": [
1588 "thead",
1589 "tbody",
1590 "tfoot"
1591 ],
1592 "HTMLTemplateElement": [
1593 "template"
1594 ],
1595 "HTMLTextAreaElement": [
1596 "textarea"
1597 ],
1598 "HTMLTimeElement": [
1599 "time"
1600 ],
1601 "HTMLTitleElement": [
1602 "title"
1603 ],
1604 "HTMLTrackElement": [
1605 "track"
1606 ],
1607 "HTMLUListElement": [
1608 "ul"
1609 ],
1610 "HTMLUnknownElement": [
1611 "unknown",
1612 "vhgroupv",
1613 "vkeygen"
1614 ],
1615 "HTMLVideoElement": [
1616 "video"
1617 ]
1618 },
1619 "nodes": {
1620 "Attr": [
1621 "node"
1622 ],
1623 "Audio": [
1624 "audio"
1625 ],
1626 "CDATASection": [
1627 "node"
1628 ],
1629 "CharacterData": [
1630 "node"
1631 ],
1632 "Comment": [
1633 "#comment"
1634 ],
1635 "Document": [
1636 "#document"
1637 ],
1638 "DocumentFragment": [
1639 "#document-fragment"
1640 ],
1641 "DocumentType": [
1642 "node"
1643 ],
1644 "HTMLDocument": [
1645 "#document"
1646 ],
1647 "Image": [
1648 "img"
1649 ],
1650 "Option": [
1651 "option"
1652 ],
1653 "ProcessingInstruction": [
1654 "node"
1655 ],
1656 "ShadowRoot": [
1657 "#shadow-root"
1658 ],
1659 "Text": [
1660 "#text"
1661 ],
1662 "XMLDocument": [
1663 "xml"
1664 ]
1665 }
1666 }));
1667
1668
1669 var
1670 // V0 polyfill entry
1671 REGISTER_ELEMENT = 'registerElement',
1672
1673 // IE < 11 only + old WebKit for attributes + feature detection
1674 EXPANDO_UID = '__' + REGISTER_ELEMENT + (window.Math.random() * 10e4 >> 0),
1675
1676 // shortcuts and costants
1677 ADD_EVENT_LISTENER = 'addEventListener',
1678 ATTACHED = 'attached',
1679 CALLBACK = 'Callback',
1680 DETACHED = 'detached',
1681 EXTENDS = 'extends',
1682
1683 ATTRIBUTE_CHANGED_CALLBACK = 'attributeChanged' + CALLBACK,
1684 ATTACHED_CALLBACK = ATTACHED + CALLBACK,
1685 CONNECTED_CALLBACK = 'connected' + CALLBACK,
1686 DISCONNECTED_CALLBACK = 'disconnected' + CALLBACK,
1687 CREATED_CALLBACK = 'created' + CALLBACK,
1688 DETACHED_CALLBACK = DETACHED + CALLBACK,
1689
1690 ADDITION = 'ADDITION',
1691 MODIFICATION = 'MODIFICATION',
1692 REMOVAL = 'REMOVAL',
1693
1694 DOM_ATTR_MODIFIED = 'DOMAttrModified',
1695 DOM_CONTENT_LOADED = 'DOMContentLoaded',
1696 DOM_SUBTREE_MODIFIED = 'DOMSubtreeModified',
1697
1698 PREFIX_TAG = '<',
1699 PREFIX_IS = '=',
1700
1701 // valid and invalid node names
1702 validName = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,
1703 invalidNames = [
1704 'ANNOTATION-XML',
1705 'COLOR-PROFILE',
1706 'FONT-FACE',
1707 'FONT-FACE-SRC',
1708 'FONT-FACE-URI',
1709 'FONT-FACE-FORMAT',
1710 'FONT-FACE-NAME',
1711 'MISSING-GLYPH'
1712 ],
1713
1714 // registered types and their prototypes
1715 types = [],
1716 protos = [],
1717
1718 // to query subnodes
1719 query = '',
1720
1721 // html shortcut used to feature detect
1722 documentElement = document.documentElement,
1723
1724 // ES5 inline helpers || basic patches
1725 indexOf = types.indexOf || function (v) {
1726 for(var i = this.length; i-- && this[i] !== v;){}
1727 return i;
1728 },
1729
1730 // other helpers / shortcuts
1731 OP = Object.prototype,
1732 hOP = OP.hasOwnProperty,
1733 iPO = OP.isPrototypeOf,
1734
1735 defineProperty = Object.defineProperty,
1736 empty = [],
1737 gOPD = Object.getOwnPropertyDescriptor,
1738 gOPN = Object.getOwnPropertyNames,
1739 gPO = Object.getPrototypeOf,
1740 sPO = Object.setPrototypeOf,
1741
1742 // jshint proto: true
1743 hasProto = !!Object.__proto__,
1744
1745 // V1 helpers
1746 fixGetClass = false,
1747 DRECEV1 = '__dreCEv1',
1748 customElements = window.customElements,
1749 usableCustomElements = !!(
1750 customElements &&
1751 customElements.define &&
1752 customElements.get &&
1753 customElements.whenDefined
1754 ),
1755 Dict = Object.create || Object,
1756 Map = window.Map || function Map() {
1757 var K = [], V = [], i;
1758 return {
1759 get: function (k) {
1760 return V[indexOf.call(K, k)];
1761 },
1762 set: function (k, v) {
1763 i = indexOf.call(K, k);
1764 if (i < 0) V[K.push(k) - 1] = v;
1765 else V[i] = v;
1766 }
1767 };
1768 },
1769 Promise = window.Promise || function (fn) {
1770 var
1771 notify = [],
1772 done = false,
1773 p = {
1774 'catch': function () {
1775 return p;
1776 },
1777 'then': function (cb) {
1778 notify.push(cb);
1779 if (done) setTimeout(resolve, 1);
1780 return p;
1781 }
1782 }
1783 ;
1784 function resolve(value) {
1785 done = true;
1786 while (notify.length) notify.shift()(value);
1787 }
1788 fn(resolve);
1789 return p;
1790 },
1791 justCreated = false,
1792 constructors = Dict(null),
1793 waitingList = Dict(null),
1794 nodeNames = new Map(),
1795 secondArgument = String,
1796
1797 // used to create unique instances
1798 create = Object.create || function Bridge(proto) {
1799 // silly broken polyfill probably ever used but short enough to work
1800 return proto ? ((Bridge.prototype = proto), new Bridge()) : this;
1801 },
1802
1803 // will set the prototype if possible
1804 // or copy over all properties
1805 setPrototype = sPO || (
1806 hasProto ?
1807 function (o, p) {
1808 o.__proto__ = p;
1809 return o;
1810 } : (
1811 (gOPN && gOPD) ?
1812 (function(){
1813 function setProperties(o, p) {
1814 for (var
1815 key,
1816 names = gOPN(p),
1817 i = 0, length = names.length;
1818 i < length; i++
1819 ) {
1820 key = names[i];
1821 if (!hOP.call(o, key)) {
1822 defineProperty(o, key, gOPD(p, key));
1823 }
1824 }
1825 }
1826 return function (o, p) {
1827 do {
1828 setProperties(o, p);
1829 } while ((p = gPO(p)) && !iPO.call(p, o));
1830 return o;
1831 };
1832 }()) :
1833 function (o, p) {
1834 for (var key in p) {
1835 o[key] = p[key];
1836 }
1837 return o;
1838 }
1839 )),
1840
1841 // DOM shortcuts and helpers, if any
1842
1843 MutationObserver = window.MutationObserver ||
1844 window.WebKitMutationObserver,
1845
1846 HTMLElementPrototype = (
1847 window.HTMLElement ||
1848 window.Element ||
1849 window.Node
1850 ).prototype,
1851
1852 IE8 = !iPO.call(HTMLElementPrototype, documentElement),
1853
1854 safeProperty = IE8 ? function (o, k, d) {
1855 o[k] = d.value;
1856 return o;
1857 } : defineProperty,
1858
1859 isValidNode = IE8 ?
1860 function (node) {
1861 return node.nodeType === 1;
1862 } :
1863 function (node) {
1864 return iPO.call(HTMLElementPrototype, node);
1865 },
1866
1867 targets = IE8 && [],
1868
1869 attachShadow = HTMLElementPrototype.attachShadow,
1870 cloneNode = HTMLElementPrototype.cloneNode,
1871 dispatchEvent = HTMLElementPrototype.dispatchEvent,
1872 getAttribute = HTMLElementPrototype.getAttribute,
1873 hasAttribute = HTMLElementPrototype.hasAttribute,
1874 removeAttribute = HTMLElementPrototype.removeAttribute,
1875 setAttribute = HTMLElementPrototype.setAttribute,
1876
1877 // replaced later on
1878 createElement = document.createElement,
1879 patchedCreateElement = createElement,
1880
1881 // shared observer for all attributes
1882 attributesObserver = MutationObserver && {
1883 attributes: true,
1884 characterData: true,
1885 attributeOldValue: true
1886 },
1887
1888 // useful to detect only if there's no MutationObserver
1889 DOMAttrModified = MutationObserver || function(e) {
1890 doesNotSupportDOMAttrModified = false;
1891 documentElement.removeEventListener(
1892 DOM_ATTR_MODIFIED,
1893 DOMAttrModified
1894 );
1895 },
1896
1897 // will both be used to make DOMNodeInserted asynchronous
1898 asapQueue,
1899 asapTimer = 0,
1900
1901 // internal flags
1902 setListener = false,
1903 doesNotSupportDOMAttrModified = true,
1904 dropDomContentLoaded = true,
1905
1906 // needed for the innerHTML helper
1907 notFromInnerHTMLHelper = true,
1908
1909 // optionally defined later on
1910 onSubtreeModified,
1911 callDOMAttrModified,
1912 getAttributesMirror,
1913 observer,
1914 observe,
1915
1916 // based on setting prototype capability
1917 // will check proto or the expando attribute
1918 // in order to setup the node once
1919 patchIfNotAlready,
1920 patch
1921 ;
1922
1923 // only if needed
1924 if (!(REGISTER_ELEMENT in document)) {
1925
1926 if (sPO || hasProto) {
1927 patchIfNotAlready = function (node, proto) {
1928 if (!iPO.call(proto, node)) {
1929 setupNode(node, proto);
1930 }
1931 };
1932 patch = setupNode;
1933 } else {
1934 patchIfNotAlready = function (node, proto) {
1935 if (!node[EXPANDO_UID]) {
1936 node[EXPANDO_UID] = Object(true);
1937 setupNode(node, proto);
1938 }
1939 };
1940 patch = patchIfNotAlready;
1941 }
1942
1943 if (IE8) {
1944 doesNotSupportDOMAttrModified = false;
1945 (function (){
1946 var
1947 descriptor = gOPD(HTMLElementPrototype, ADD_EVENT_LISTENER),
1948 addEventListener = descriptor.value,
1949 patchedRemoveAttribute = function (name) {
1950 var e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true});
1951 e.attrName = name;
1952 e.prevValue = getAttribute.call(this, name);
1953 e.newValue = null;
1954 e[REMOVAL] = e.attrChange = 2;
1955 removeAttribute.call(this, name);
1956 dispatchEvent.call(this, e);
1957 },
1958 patchedSetAttribute = function (name, value) {
1959 var
1960 had = hasAttribute.call(this, name),
1961 old = had && getAttribute.call(this, name),
1962 e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true})
1963 ;
1964 setAttribute.call(this, name, value);
1965 e.attrName = name;
1966 e.prevValue = had ? old : null;
1967 e.newValue = value;
1968 if (had) {
1969 e[MODIFICATION] = e.attrChange = 1;
1970 } else {
1971 e[ADDITION] = e.attrChange = 0;
1972 }
1973 dispatchEvent.call(this, e);
1974 },
1975 onPropertyChange = function (e) {
1976 // jshint eqnull:true
1977 var
1978 node = e.currentTarget,
1979 superSecret = node[EXPANDO_UID],
1980 propertyName = e.propertyName,
1981 event
1982 ;
1983 if (superSecret.hasOwnProperty(propertyName)) {
1984 superSecret = superSecret[propertyName];
1985 event = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true});
1986 event.attrName = superSecret.name;
1987 event.prevValue = superSecret.value || null;
1988 event.newValue = (superSecret.value = node[propertyName] || null);
1989 if (event.prevValue == null) {
1990 event[ADDITION] = event.attrChange = 0;
1991 } else {
1992 event[MODIFICATION] = event.attrChange = 1;
1993 }
1994 dispatchEvent.call(node, event);
1995 }
1996 }
1997 ;
1998 descriptor.value = function (type, handler, capture) {
1999 if (
2000 type === DOM_ATTR_MODIFIED &&
2001 this[ATTRIBUTE_CHANGED_CALLBACK] &&
2002 this.setAttribute !== patchedSetAttribute
2003 ) {
2004 this[EXPANDO_UID] = {
2005 className: {
2006 name: 'class',
2007 value: this.className
2008 }
2009 };
2010 this.setAttribute = patchedSetAttribute;
2011 this.removeAttribute = patchedRemoveAttribute;
2012 addEventListener.call(this, 'propertychange', onPropertyChange);
2013 }
2014 addEventListener.call(this, type, handler, capture);
2015 };
2016 defineProperty(HTMLElementPrototype, ADD_EVENT_LISTENER, descriptor);
2017 }());
2018 } else if (!MutationObserver) {
2019 documentElement[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, DOMAttrModified);
2020 documentElement.setAttribute(EXPANDO_UID, 1);
2021 documentElement.removeAttribute(EXPANDO_UID);
2022 if (doesNotSupportDOMAttrModified) {
2023 onSubtreeModified = function (e) {
2024 var
2025 node = this,
2026 oldAttributes,
2027 newAttributes,
2028 key
2029 ;
2030 if (node === e.target) {
2031 oldAttributes = node[EXPANDO_UID];
2032 node[EXPANDO_UID] = (newAttributes = getAttributesMirror(node));
2033 for (key in newAttributes) {
2034 if (!(key in oldAttributes)) {
2035 // attribute was added
2036 return callDOMAttrModified(
2037 0,
2038 node,
2039 key,
2040 oldAttributes[key],
2041 newAttributes[key],
2042 ADDITION
2043 );
2044 } else if (newAttributes[key] !== oldAttributes[key]) {
2045 // attribute was changed
2046 return callDOMAttrModified(
2047 1,
2048 node,
2049 key,
2050 oldAttributes[key],
2051 newAttributes[key],
2052 MODIFICATION
2053 );
2054 }
2055 }
2056 // checking if it has been removed
2057 for (key in oldAttributes) {
2058 if (!(key in newAttributes)) {
2059 // attribute removed
2060 return callDOMAttrModified(
2061 2,
2062 node,
2063 key,
2064 oldAttributes[key],
2065 newAttributes[key],
2066 REMOVAL
2067 );
2068 }
2069 }
2070 }
2071 };
2072 callDOMAttrModified = function (
2073 attrChange,
2074 currentTarget,
2075 attrName,
2076 prevValue,
2077 newValue,
2078 action
2079 ) {
2080 var e = {
2081 attrChange: attrChange,
2082 currentTarget: currentTarget,
2083 attrName: attrName,
2084 prevValue: prevValue,
2085 newValue: newValue
2086 };
2087 e[action] = attrChange;
2088 onDOMAttrModified(e);
2089 };
2090 getAttributesMirror = function (node) {
2091 for (var
2092 attr, name,
2093 result = {},
2094 attributes = node.attributes,
2095 i = 0, length = attributes.length;
2096 i < length; i++
2097 ) {
2098 attr = attributes[i];
2099 name = attr.name;
2100 if (name !== 'setAttribute') {
2101 result[name] = attr.value;
2102 }
2103 }
2104 return result;
2105 };
2106 }
2107 }
2108
2109 // set as enumerable, writable and configurable
2110 document[REGISTER_ELEMENT] = function registerElement(type, options) {
2111 upperType = type.toUpperCase();
2112 if (!setListener) {
2113 // only first time document.registerElement is used
2114 // we need to set this listener
2115 // setting it by default might slow down for no reason
2116 setListener = true;
2117 if (MutationObserver) {
2118 observer = (function(attached, detached){
2119 function checkEmAll(list, callback) {
2120 for (var i = 0, length = list.length; i < length; callback(list[i++])){}
2121 }
2122 return new MutationObserver(function (records) {
2123 for (var
2124 current, node, newValue,
2125 i = 0, length = records.length; i < length; i++
2126 ) {
2127 current = records[i];
2128 if (current.type === 'childList') {
2129 checkEmAll(current.addedNodes, attached);
2130 checkEmAll(current.removedNodes, detached);
2131 } else {
2132 node = current.target;
2133 if (notFromInnerHTMLHelper &&
2134 node[ATTRIBUTE_CHANGED_CALLBACK] &&
2135 current.attributeName !== 'style') {
2136 newValue = getAttribute.call(node, current.attributeName);
2137 if (newValue !== current.oldValue) {
2138 node[ATTRIBUTE_CHANGED_CALLBACK](
2139 current.attributeName,
2140 current.oldValue,
2141 newValue
2142 );
2143 }
2144 }
2145 }
2146 }
2147 });
2148 }(executeAction(ATTACHED), executeAction(DETACHED)));
2149 observe = function (node) {
2150 observer.observe(
2151 node,
2152 {
2153 childList: true,
2154 subtree: true
2155 }
2156 );
2157 return node;
2158 };
2159 observe(document);
2160 if (attachShadow) {
2161 HTMLElementPrototype.attachShadow = function () {
2162 return observe(attachShadow.apply(this, arguments));
2163 };
2164 }
2165 } else {
2166 asapQueue = [];
2167 document[ADD_EVENT_LISTENER]('DOMNodeInserted', onDOMNode(ATTACHED));
2168 document[ADD_EVENT_LISTENER]('DOMNodeRemoved', onDOMNode(DETACHED));
2169 }
2170
2171 document[ADD_EVENT_LISTENER](DOM_CONTENT_LOADED, onReadyStateChange);
2172 document[ADD_EVENT_LISTENER]('readystatechange', onReadyStateChange);
2173
2174 HTMLElementPrototype.cloneNode = function (deep) {
2175 var
2176 node = cloneNode.call(this, !!deep),
2177 i = getTypeIndex(node)
2178 ;
2179 if (-1 < i) patch(node, protos[i]);
2180 if (deep) loopAndSetup(node.querySelectorAll(query));
2181 return node;
2182 };
2183 }
2184
2185 if (-2 < (
2186 indexOf.call(types, PREFIX_IS + upperType) +
2187 indexOf.call(types, PREFIX_TAG + upperType)
2188 )) {
2189 throwTypeError(type);
2190 }
2191
2192 if (!validName.test(upperType) || -1 < indexOf.call(invalidNames, upperType)) {
2193 throw new Error('The type ' + type + ' is invalid');
2194 }
2195
2196 var
2197 constructor = function () {
2198 return extending ?
2199 document.createElement(nodeName, upperType) :
2200 document.createElement(nodeName);
2201 },
2202 opt = options || OP,
2203 extending = hOP.call(opt, EXTENDS),
2204 nodeName = extending ? options[EXTENDS].toUpperCase() : upperType,
2205 upperType,
2206 i
2207 ;
2208
2209 if (extending && -1 < (
2210 indexOf.call(types, PREFIX_TAG + nodeName)
2211 )) {
2212 throwTypeError(nodeName);
2213 }
2214
2215 i = types.push((extending ? PREFIX_IS : PREFIX_TAG) + upperType) - 1;
2216
2217 query = query.concat(
2218 query.length ? ',' : '',
2219 extending ? nodeName + '[is="' + type.toLowerCase() + '"]' : nodeName
2220 );
2221
2222 constructor.prototype = (
2223 protos[i] = hOP.call(opt, 'prototype') ?
2224 opt.prototype :
2225 create(HTMLElementPrototype)
2226 );
2227
2228 loopAndVerify(
2229 document.querySelectorAll(query),
2230 ATTACHED
2231 );
2232
2233 return constructor;
2234 };
2235
2236 document.createElement = (patchedCreateElement = function (localName, typeExtension) {
2237 var
2238 is = getIs(typeExtension),
2239 node = is ?
2240 createElement.call(document, localName, secondArgument(is)) :
2241 createElement.call(document, localName),
2242 name = '' + localName,
2243 i = indexOf.call(
2244 types,
2245 (is ? PREFIX_IS : PREFIX_TAG) +
2246 (is || name).toUpperCase()
2247 ),
2248 setup = -1 < i
2249 ;
2250 if (is) {
2251 node.setAttribute('is', is = is.toLowerCase());
2252 if (setup) {
2253 setup = isInQSA(name.toUpperCase(), is);
2254 }
2255 }
2256 notFromInnerHTMLHelper = !document.createElement.innerHTMLHelper;
2257 if (setup) patch(node, protos[i]);
2258 return node;
2259 });
2260
2261 }
2262
2263 function ASAP() {
2264 var queue = asapQueue.splice(0, asapQueue.length);
2265 asapTimer = 0;
2266 while (queue.length) {
2267 queue.shift().call(
2268 null, queue.shift()
2269 );
2270 }
2271 }
2272
2273 function loopAndVerify(list, action) {
2274 for (var i = 0, length = list.length; i < length; i++) {
2275 verifyAndSetupAndAction(list[i], action);
2276 }
2277 }
2278
2279 function loopAndSetup(list) {
2280 for (var i = 0, length = list.length, node; i < length; i++) {
2281 node = list[i];
2282 patch(node, protos[getTypeIndex(node)]);
2283 }
2284 }
2285
2286 function executeAction(action) {
2287 return function (node) {
2288 if (isValidNode(node)) {
2289 verifyAndSetupAndAction(node, action);
2290 loopAndVerify(
2291 node.querySelectorAll(query),
2292 action
2293 );
2294 }
2295 };
2296 }
2297
2298 function getTypeIndex(target) {
2299 var
2300 is = getAttribute.call(target, 'is'),
2301 nodeName = target.nodeName.toUpperCase(),
2302 i = indexOf.call(
2303 types,
2304 is ?
2305 PREFIX_IS + is.toUpperCase() :
2306 PREFIX_TAG + nodeName
2307 )
2308 ;
2309 return is && -1 < i && !isInQSA(nodeName, is) ? -1 : i;
2310 }
2311
2312 function isInQSA(name, type) {
2313 return -1 < query.indexOf(name + '[is="' + type + '"]');
2314 }
2315
2316 function onDOMAttrModified(e) {
2317 var
2318 node = e.currentTarget,
2319 attrChange = e.attrChange,
2320 attrName = e.attrName,
2321 target = e.target,
2322 addition = e[ADDITION] || 2,
2323 removal = e[REMOVAL] || 3
2324 ;
2325 if (notFromInnerHTMLHelper &&
2326 (!target || target === node) &&
2327 node[ATTRIBUTE_CHANGED_CALLBACK] &&
2328 attrName !== 'style' && (
2329 e.prevValue !== e.newValue ||
2330 // IE9, IE10, and Opera 12 gotcha
2331 e.newValue === '' && (
2332 attrChange === addition ||
2333 attrChange === removal
2334 )
2335 )) {
2336 node[ATTRIBUTE_CHANGED_CALLBACK](
2337 attrName,
2338 attrChange === addition ? null : e.prevValue,
2339 attrChange === removal ? null : e.newValue
2340 );
2341 }
2342 }
2343
2344 function onDOMNode(action) {
2345 var executor = executeAction(action);
2346 return function (e) {
2347 asapQueue.push(executor, e.target);
2348 if (asapTimer) clearTimeout(asapTimer);
2349 asapTimer = setTimeout(ASAP, 1);
2350 };
2351 }
2352
2353 function onReadyStateChange(e) {
2354 if (dropDomContentLoaded) {
2355 dropDomContentLoaded = false;
2356 e.currentTarget.removeEventListener(DOM_CONTENT_LOADED, onReadyStateChange);
2357 }
2358 loopAndVerify(
2359 (e.target || document).querySelectorAll(query),
2360 e.detail === DETACHED ? DETACHED : ATTACHED
2361 );
2362 if (IE8) purge();
2363 }
2364
2365 function patchedSetAttribute(name, value) {
2366 // jshint validthis:true
2367 var self = this;
2368 setAttribute.call(self, name, value);
2369 onSubtreeModified.call(self, {target: self});
2370 }
2371
2372 function setupNode(node, proto) {
2373 setPrototype(node, proto);
2374 if (observer) {
2375 observer.observe(node, attributesObserver);
2376 } else {
2377 if (doesNotSupportDOMAttrModified) {
2378 node.setAttribute = patchedSetAttribute;
2379 node[EXPANDO_UID] = getAttributesMirror(node);
2380 node[ADD_EVENT_LISTENER](DOM_SUBTREE_MODIFIED, onSubtreeModified);
2381 }
2382 node[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, onDOMAttrModified);
2383 }
2384 if (node[CREATED_CALLBACK] && notFromInnerHTMLHelper) {
2385 node.created = true;
2386 node[CREATED_CALLBACK]();
2387 node.created = false;
2388 }
2389 }
2390
2391 function purge() {
2392 for (var
2393 node,
2394 i = 0,
2395 length = targets.length;
2396 i < length; i++
2397 ) {
2398 node = targets[i];
2399 if (!documentElement.contains(node)) {
2400 length--;
2401 targets.splice(i--, 1);
2402 verifyAndSetupAndAction(node, DETACHED);
2403 }
2404 }
2405 }
2406
2407 function throwTypeError(type) {
2408 throw new Error('A ' + type + ' type is already registered');
2409 }
2410
2411 function verifyAndSetupAndAction(node, action) {
2412 var
2413 fn,
2414 i = getTypeIndex(node)
2415 ;
2416 if (-1 < i) {
2417 patchIfNotAlready(node, protos[i]);
2418 i = 0;
2419 if (action === ATTACHED && !node[ATTACHED]) {
2420 node[DETACHED] = false;
2421 node[ATTACHED] = true;
2422 i = 1;
2423 if (IE8 && indexOf.call(targets, node) < 0) {
2424 targets.push(node);
2425 }
2426 } else if (action === DETACHED && !node[DETACHED]) {
2427 node[ATTACHED] = false;
2428 node[DETACHED] = true;
2429 i = 1;
2430 }
2431 if (i && (fn = node[action + CALLBACK])) fn.call(node);
2432 }
2433 }
2434
2435
2436
2437 // V1 in da House!
2438 function CustomElementRegistry() {}
2439
2440 CustomElementRegistry.prototype = {
2441 constructor: CustomElementRegistry,
2442 // a workaround for the stubborn WebKit
2443 define: usableCustomElements ?
2444 function (name, Class, options) {
2445 if (options) {
2446 CERDefine(name, Class, options);
2447 } else {
2448 var NAME = name.toUpperCase();
2449 constructors[NAME] = {
2450 constructor: Class,
2451 create: [NAME]
2452 };
2453 nodeNames.set(Class, NAME);
2454 customElements.define(name, Class);
2455 }
2456 } :
2457 CERDefine,
2458 get: usableCustomElements ?
2459 function (name) {
2460 return customElements.get(name) || get(name);
2461 } :
2462 get,
2463 whenDefined: usableCustomElements ?
2464 function (name) {
2465 return Promise.race([
2466 customElements.whenDefined(name),
2467 whenDefined(name)
2468 ]);
2469 } :
2470 whenDefined
2471 };
2472
2473 function CERDefine(name, Class, options) {
2474 var
2475 is = options && options[EXTENDS] || '',
2476 CProto = Class.prototype,
2477 proto = create(CProto),
2478 attributes = Class.observedAttributes || empty,
2479 definition = {prototype: proto}
2480 ;
2481 // TODO: is this needed at all since it's inherited?
2482 // defineProperty(proto, 'constructor', {value: Class});
2483 safeProperty(proto, CREATED_CALLBACK, {
2484 value: function () {
2485 if (justCreated) justCreated = false;
2486 else if (!this[DRECEV1]) {
2487 this[DRECEV1] = true;
2488 new Class(this);
2489 if (CProto[CREATED_CALLBACK])
2490 CProto[CREATED_CALLBACK].call(this);
2491 var info = constructors[nodeNames.get(Class)];
2492 if (!usableCustomElements || info.create.length > 1) {
2493 notifyAttributes(this);
2494 }
2495 }
2496 }
2497 });
2498 safeProperty(proto, ATTRIBUTE_CHANGED_CALLBACK, {
2499 value: function (name) {
2500 if (-1 < indexOf.call(attributes, name))
2501 CProto[ATTRIBUTE_CHANGED_CALLBACK].apply(this, arguments);
2502 }
2503 });
2504 if (CProto[CONNECTED_CALLBACK]) {
2505 safeProperty(proto, ATTACHED_CALLBACK, {
2506 value: CProto[CONNECTED_CALLBACK]
2507 });
2508 }
2509 if (CProto[DISCONNECTED_CALLBACK]) {
2510 safeProperty(proto, DETACHED_CALLBACK, {
2511 value: CProto[DISCONNECTED_CALLBACK]
2512 });
2513 }
2514 if (is) definition[EXTENDS] = is;
2515 name = name.toUpperCase();
2516 constructors[name] = {
2517 constructor: Class,
2518 create: is ? [is, secondArgument(name)] : [name]
2519 };
2520 nodeNames.set(Class, name);
2521 document[REGISTER_ELEMENT](name.toLowerCase(), definition);
2522 whenDefined(name);
2523 waitingList[name].r();
2524 }
2525
2526 function get(name) {
2527 var info = constructors[name.toUpperCase()];
2528 return info && info.constructor;
2529 }
2530
2531 function getIs(options) {
2532 return typeof options === 'string' ?
2533 options : (options && options.is || '');
2534 }
2535
2536 function notifyAttributes(self) {
2537 var
2538 callback = self[ATTRIBUTE_CHANGED_CALLBACK],
2539 attributes = callback ? self.attributes : empty,
2540 i = attributes.length,
2541 attribute
2542 ;
2543 while (i--) {
2544 attribute = attributes[i]; // || attributes.item(i);
2545 callback.call(
2546 self,
2547 attribute.name || attribute.nodeName,
2548 null,
2549 attribute.value || attribute.nodeValue
2550 );
2551 }
2552 }
2553
2554 function whenDefined(name) {
2555 name = name.toUpperCase();
2556 if (!(name in waitingList)) {
2557 waitingList[name] = {};
2558 waitingList[name].p = new Promise(function (resolve) {
2559 waitingList[name].r = resolve;
2560 });
2561 }
2562 return waitingList[name].p;
2563 }
2564
2565 function polyfillV1() {
2566 if (customElements) delete window.customElements;
2567 defineProperty(window, 'customElements', {
2568 configurable: true,
2569 value: new CustomElementRegistry()
2570 });
2571 defineProperty(window, 'CustomElementRegistry', {
2572 configurable: true,
2573 value: CustomElementRegistry
2574 });
2575 for (var
2576 patchClass = function (name) {
2577 var Class = window[name];
2578 if (Class) {
2579 window[name] = function CustomElementsV1(self) {
2580 var info, isNative;
2581 if (!self) self = this;
2582 if (!self[DRECEV1]) {
2583 justCreated = true;
2584 info = constructors[nodeNames.get(self.constructor)];
2585 isNative = usableCustomElements && info.create.length === 1;
2586 self = isNative ?
2587 Reflect.construct(Class, empty, info.constructor) :
2588 document.createElement.apply(document, info.create);
2589 self[DRECEV1] = true;
2590 justCreated = false;
2591 if (!isNative) notifyAttributes(self);
2592 }
2593 return self;
2594 };
2595 window[name].prototype = Class.prototype;
2596 try {
2597 Class.prototype.constructor = window[name];
2598 } catch(WebKit) {
2599 fixGetClass = true;
2600 defineProperty(Class, DRECEV1, {value: window[name]});
2601 }
2602 }
2603 },
2604 Classes = htmlClass.get(/^HTML[A-Z]*[a-z]/),
2605 i = Classes.length;
2606 i--;
2607 patchClass(Classes[i])
2608 ) {}
2609 (document.createElement = function (name, options) {
2610 var is = getIs(options);
2611 return is ?
2612 patchedCreateElement.call(this, name, secondArgument(is)) :
2613 patchedCreateElement.call(this, name);
2614 });
2615 }
2616
2617 // if customElements is not there at all
2618 if (!customElements) polyfillV1();
2619 else {
2620 // if available test extends work as expected
2621 try {
2622 (function (DRE, options, name) {
2623 options[EXTENDS] = 'a';
2624 DRE.prototype = create(HTMLAnchorElement.prototype);
2625 DRE.prototype.constructor = DRE;
2626 window.customElements.define(name, DRE, options);
2627 if (
2628 getAttribute.call(document.createElement('a', {is: name}), 'is') !== name ||
2629 (usableCustomElements && getAttribute.call(new DRE(), 'is') !== name)
2630 ) {
2631 throw options;
2632 }
2633 }(
2634 function DRE() {
2635 return Reflect.construct(HTMLAnchorElement, [], DRE);
2636 },
2637 {},
2638 'document-register-element-a'
2639 ));
2640 } catch(o_O) {
2641 // or force the polyfill if not
2642 // and keep internal original reference
2643 polyfillV1();
2644 }
2645 }
2646
2647 try {
2648 createElement.call(document, 'a', 'a');
2649 } catch(FireFox) {
2650 secondArgument = function (is) {
2651 return {is: is};
2652 };
2653 }
2654
2655}(window));
2656
2657;(function () {
2658 'use strict';
2659
2660 /**
2661 * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
2662 *
2663 * @codingstandard ftlabs-jsv2
2664 * @copyright The Financial Times Limited [All Rights Reserved]
2665 * @license MIT License (see LICENSE.txt)
2666 */
2667
2668 /*jslint browser:true, node:true*/
2669 /*global define, Event, Node*/
2670
2671
2672 /**
2673 * Instantiate fast-clicking listeners on the specified layer.
2674 *
2675 * @constructor
2676 * @param {Element} layer The layer to listen on
2677 * @param {Object} [options={}] The options to override the defaults
2678 */
2679 function FastClick(layer, options) {
2680 var oldOnClick;
2681
2682 options = options || {};
2683
2684 /**
2685 * Whether a click is currently being tracked.
2686 *
2687 * @type boolean
2688 */
2689 this.trackingClick = false;
2690
2691
2692 /**
2693 * Timestamp for when click tracking started.
2694 *
2695 * @type number
2696 */
2697 this.trackingClickStart = 0;
2698
2699
2700 /**
2701 * The element being tracked for a click.
2702 *
2703 * @type EventTarget
2704 */
2705 this.targetElement = null;
2706
2707
2708 /**
2709 * X-coordinate of touch start event.
2710 *
2711 * @type number
2712 */
2713 this.touchStartX = 0;
2714
2715
2716 /**
2717 * Y-coordinate of touch start event.
2718 *
2719 * @type number
2720 */
2721 this.touchStartY = 0;
2722
2723
2724 /**
2725 * ID of the last touch, retrieved from Touch.identifier.
2726 *
2727 * @type number
2728 */
2729 this.lastTouchIdentifier = 0;
2730
2731
2732 /**
2733 * Touchmove boundary, beyond which a click will be cancelled.
2734 *
2735 * @type number
2736 */
2737 this.touchBoundary = options.touchBoundary || 10;
2738
2739
2740 /**
2741 * The FastClick layer.
2742 *
2743 * @type Element
2744 */
2745 this.layer = layer;
2746
2747 /**
2748 * The minimum time between tap(touchstart and touchend) events
2749 *
2750 * @type number
2751 */
2752 this.tapDelay = options.tapDelay || 200;
2753
2754 /**
2755 * The maximum time for a tap
2756 *
2757 * @type number
2758 */
2759 this.tapTimeout = options.tapTimeout || 700;
2760
2761 if (FastClick.notNeeded(layer)) {
2762 return;
2763 }
2764
2765 // Some old versions of Android don't have Function.prototype.bind
2766 function bind(method, context) {
2767 return function() { return method.apply(context, arguments); };
2768 }
2769
2770
2771 var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
2772 var context = this;
2773 for (var i = 0, l = methods.length; i < l; i++) {
2774 context[methods[i]] = bind(context[methods[i]], context);
2775 }
2776
2777 // Set up event handlers as required
2778 if (deviceIsAndroid) {
2779 layer.addEventListener('mouseover', this.onMouse, true);
2780 layer.addEventListener('mousedown', this.onMouse, true);
2781 layer.addEventListener('mouseup', this.onMouse, true);
2782 }
2783
2784 layer.addEventListener('click', this.onClick, true);
2785 layer.addEventListener('touchstart', this.onTouchStart, false);
2786 layer.addEventListener('touchmove', this.onTouchMove, false);
2787 layer.addEventListener('touchend', this.onTouchEnd, false);
2788 layer.addEventListener('touchcancel', this.onTouchCancel, false);
2789
2790 // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
2791 // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
2792 // layer when they are cancelled.
2793 if (!Event.prototype.stopImmediatePropagation) {
2794 layer.removeEventListener = function(type, callback, capture) {
2795 var rmv = Node.prototype.removeEventListener;
2796 if (type === 'click') {
2797 rmv.call(layer, type, callback.hijacked || callback, capture);
2798 } else {
2799 rmv.call(layer, type, callback, capture);
2800 }
2801 };
2802
2803 layer.addEventListener = function(type, callback, capture) {
2804 var adv = Node.prototype.addEventListener;
2805 if (type === 'click') {
2806 adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
2807 if (!event.propagationStopped) {
2808 callback(event);
2809 }
2810 }), capture);
2811 } else {
2812 adv.call(layer, type, callback, capture);
2813 }
2814 };
2815 }
2816
2817 // If a handler is already declared in the element's onclick attribute, it will be fired before
2818 // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
2819 // adding it as listener.
2820 if (typeof layer.onclick === 'function') {
2821
2822 // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
2823 // - the old one won't work if passed to addEventListener directly.
2824 oldOnClick = layer.onclick;
2825 layer.addEventListener('click', function(event) {
2826 oldOnClick(event);
2827 }, false);
2828 layer.onclick = null;
2829 }
2830 }
2831
2832 /**
2833 * Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
2834 *
2835 * @type boolean
2836 */
2837 var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
2838
2839 /**
2840 * Android requires exceptions.
2841 *
2842 * @type boolean
2843 */
2844 var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
2845
2846
2847 /**
2848 * iOS requires exceptions.
2849 *
2850 * @type boolean
2851 */
2852 var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
2853
2854
2855 /**
2856 * iOS 4 requires an exception for select elements.
2857 *
2858 * @type boolean
2859 */
2860 var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
2861
2862
2863 /**
2864 * iOS 6.0-7.* requires the target element to be manually derived
2865 *
2866 * @type boolean
2867 */
2868 var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);
2869
2870 /**
2871 * BlackBerry requires exceptions.
2872 *
2873 * @type boolean
2874 */
2875 var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
2876
2877 /**
2878 * Determine whether a given element requires a native click.
2879 *
2880 * @param {EventTarget|Element} target Target DOM element
2881 * @returns {boolean} Returns true if the element needs a native click
2882 */
2883 FastClick.prototype.needsClick = function(target) {
2884 switch (target.nodeName.toLowerCase()) {
2885
2886 // Don't send a synthetic click to disabled inputs (issue #62)
2887 case 'button':
2888 case 'select':
2889 case 'textarea':
2890 if (target.disabled) {
2891 return true;
2892 }
2893
2894 break;
2895 case 'input':
2896
2897 // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
2898 if ((deviceIsIOS && target.type === 'file') || target.disabled) {
2899 return true;
2900 }
2901
2902 break;
2903 case 'label':
2904 case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
2905 case 'video':
2906 return true;
2907 }
2908
2909 return (/\bneedsclick\b/).test(target.className);
2910 };
2911
2912
2913 /**
2914 * Determine whether a given element requires a call to focus to simulate click into element.
2915 *
2916 * @param {EventTarget|Element} target Target DOM element
2917 * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
2918 */
2919 FastClick.prototype.needsFocus = function(target) {
2920 switch (target.nodeName.toLowerCase()) {
2921 case 'textarea':
2922 return true;
2923 case 'select':
2924 return !deviceIsAndroid;
2925 case 'input':
2926 switch (target.type) {
2927 case 'button':
2928 case 'checkbox':
2929 case 'file':
2930 case 'image':
2931 case 'radio':
2932 case 'submit':
2933 return false;
2934 }
2935
2936 // No point in attempting to focus disabled inputs
2937 return !target.disabled && !target.readOnly;
2938 default:
2939 return (/\bneedsfocus\b/).test(target.className);
2940 }
2941 };
2942
2943
2944 /**
2945 * Send a click event to the specified element.
2946 *
2947 * @param {EventTarget|Element} targetElement
2948 * @param {Event} event
2949 */
2950 FastClick.prototype.sendClick = function(targetElement, event) {
2951 var clickEvent, touch;
2952
2953 // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
2954 if (document.activeElement && document.activeElement !== targetElement) {
2955 document.activeElement.blur();
2956 }
2957
2958 touch = event.changedTouches[0];
2959
2960 // Synthesize a click event, with an extra attribute so it can be tracked
2961 clickEvent = document.createEvent('MouseEvents');
2962 clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
2963 clickEvent.forwardedTouchEvent = true;
2964 targetElement.dispatchEvent(clickEvent);
2965 };
2966
2967 FastClick.prototype.determineEventType = function(targetElement) {
2968
2969 //Issue #159: Android Chrome Select Box does not open with a synthetic click event
2970 if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
2971 return 'mousedown';
2972 }
2973
2974 return 'click';
2975 };
2976
2977
2978 /**
2979 * @param {EventTarget|Element} targetElement
2980 */
2981 FastClick.prototype.focus = function(targetElement) {
2982 var length;
2983
2984 // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
2985 if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
2986 length = targetElement.value.length;
2987 targetElement.setSelectionRange(length, length);
2988 } else {
2989 targetElement.focus();
2990 }
2991 };
2992
2993
2994 /**
2995 * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
2996 *
2997 * @param {EventTarget|Element} targetElement
2998 */
2999 FastClick.prototype.updateScrollParent = function(targetElement) {
3000 var scrollParent, parentElement;
3001
3002 scrollParent = targetElement.fastClickScrollParent;
3003
3004 // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
3005 // target element was moved to another parent.
3006 if (!scrollParent || !scrollParent.contains(targetElement)) {
3007 parentElement = targetElement;
3008 do {
3009 if (parentElement.scrollHeight > parentElement.offsetHeight) {
3010 scrollParent = parentElement;
3011 targetElement.fastClickScrollParent = parentElement;
3012 break;
3013 }
3014
3015 parentElement = parentElement.parentElement;
3016 } while (parentElement);
3017 }
3018
3019 // Always update the scroll top tracker if possible.
3020 if (scrollParent) {
3021 scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
3022 }
3023 };
3024
3025
3026 /**
3027 * @param {EventTarget} targetElement
3028 * @returns {Element|EventTarget}
3029 */
3030 FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
3031
3032 // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
3033 if (eventTarget.nodeType === Node.TEXT_NODE) {
3034 return eventTarget.parentNode;
3035 }
3036
3037 return eventTarget;
3038 };
3039
3040
3041 /**
3042 * On touch start, record the position and scroll offset.
3043 *
3044 * @param {Event} event
3045 * @returns {boolean}
3046 */
3047 FastClick.prototype.onTouchStart = function(event) {
3048 var targetElement, touch, selection;
3049
3050 // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
3051 if (event.targetTouches.length > 1) {
3052 return true;
3053 }
3054
3055 targetElement = this.getTargetElementFromEventTarget(event.target);
3056 touch = event.targetTouches[0];
3057
3058 // Ignore touches on contenteditable elements to prevent conflict with text selection.
3059 // (For details: https://github.com/ftlabs/fastclick/pull/211 )
3060 if (targetElement.isContentEditable) {
3061 return true;
3062 }
3063
3064 if (deviceIsIOS) {
3065
3066 // Only trusted events will deselect text on iOS (issue #49)
3067 selection = window.getSelection();
3068 if (selection.rangeCount && !selection.isCollapsed) {
3069 return true;
3070 }
3071
3072 if (!deviceIsIOS4) {
3073
3074 // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
3075 // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
3076 // with the same identifier as the touch event that previously triggered the click that triggered the alert.
3077 // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
3078 // immediately preceding touch event (issue #52), so this fix is unavailable on that platform.
3079 // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
3080 // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
3081 // random integers, it's safe to to continue if the identifier is 0 here.
3082 if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
3083 event.preventDefault();
3084 return false;
3085 }
3086
3087 this.lastTouchIdentifier = touch.identifier;
3088
3089 // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
3090 // 1) the user does a fling scroll on the scrollable layer
3091 // 2) the user stops the fling scroll with another tap
3092 // then the event.target of the last 'touchend' event will be the element that was under the user's finger
3093 // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
3094 // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
3095 this.updateScrollParent(targetElement);
3096 }
3097 }
3098
3099 this.trackingClick = true;
3100 this.trackingClickStart = event.timeStamp;
3101 this.targetElement = targetElement;
3102
3103 this.touchStartX = touch.pageX;
3104 this.touchStartY = touch.pageY;
3105
3106 // Prevent phantom clicks on fast double-tap (issue #36)
3107 if ((event.timeStamp - this.lastClickTime) < this.tapDelay && (event.timeStamp - this.lastClickTime) > -1) {
3108 event.preventDefault();
3109 }
3110
3111 return true;
3112 };
3113
3114
3115 /**
3116 * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
3117 *
3118 * @param {Event} event
3119 * @returns {boolean}
3120 */
3121 FastClick.prototype.touchHasMoved = function(event) {
3122 var touch = event.changedTouches[0], boundary = this.touchBoundary;
3123
3124 if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
3125 return true;
3126 }
3127
3128 return false;
3129 };
3130
3131
3132 /**
3133 * Update the last position.
3134 *
3135 * @param {Event} event
3136 * @returns {boolean}
3137 */
3138 FastClick.prototype.onTouchMove = function(event) {
3139 if (!this.trackingClick) {
3140 return true;
3141 }
3142
3143 // If the touch has moved, cancel the click tracking
3144 if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
3145 this.trackingClick = false;
3146 this.targetElement = null;
3147 }
3148
3149 return true;
3150 };
3151
3152
3153 /**
3154 * Attempt to find the labelled control for the given label element.
3155 *
3156 * @param {EventTarget|HTMLLabelElement} labelElement
3157 * @returns {Element|null}
3158 */
3159 FastClick.prototype.findControl = function(labelElement) {
3160
3161 // Fast path for newer browsers supporting the HTML5 control attribute
3162 if (labelElement.control !== undefined) {
3163 return labelElement.control;
3164 }
3165
3166 // All browsers under test that support touch events also support the HTML5 htmlFor attribute
3167 if (labelElement.htmlFor) {
3168 return document.getElementById(labelElement.htmlFor);
3169 }
3170
3171 // If no for attribute exists, attempt to retrieve the first labellable descendant element
3172 // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
3173 return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
3174 };
3175
3176
3177 /**
3178 * On touch end, determine whether to send a click event at once.
3179 *
3180 * @param {Event} event
3181 * @returns {boolean}
3182 */
3183 FastClick.prototype.onTouchEnd = function(event) {
3184 var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
3185
3186 if (!this.trackingClick) {
3187 return true;
3188 }
3189
3190 // Prevent phantom clicks on fast double-tap (issue #36)
3191 if ((event.timeStamp - this.lastClickTime) < this.tapDelay && (event.timeStamp - this.lastClickTime) > -1) {
3192 this.cancelNextClick = true;
3193 return true;
3194 }
3195
3196 if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
3197 return true;
3198 }
3199
3200 // Reset to prevent wrong click cancel on input (issue #156).
3201 this.cancelNextClick = false;
3202
3203 this.lastClickTime = event.timeStamp;
3204
3205 trackingClickStart = this.trackingClickStart;
3206 this.trackingClick = false;
3207 this.trackingClickStart = 0;
3208
3209 // On some iOS devices, the targetElement supplied with the event is invalid if the layer
3210 // is performing a transition or scroll, and has to be re-detected manually. Note that
3211 // for this to function correctly, it must be called *after* the event target is checked!
3212 // See issue #57; also filed as rdar://13048589 .
3213 if (deviceIsIOSWithBadTarget) {
3214 touch = event.changedTouches[0];
3215
3216 // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
3217 targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
3218 targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
3219 }
3220
3221 targetTagName = targetElement.tagName.toLowerCase();
3222 if (targetTagName === 'label') {
3223 forElement = this.findControl(targetElement);
3224 if (forElement) {
3225 this.focus(targetElement);
3226 if (deviceIsAndroid) {
3227 return false;
3228 }
3229
3230 targetElement = forElement;
3231 }
3232 } else if (this.needsFocus(targetElement)) {
3233
3234 // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
3235 // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
3236 if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
3237 this.targetElement = null;
3238 return false;
3239 }
3240
3241 this.focus(targetElement);
3242 this.sendClick(targetElement, event);
3243
3244 // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
3245 // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
3246 if (!deviceIsIOS || targetTagName !== 'select') {
3247 this.targetElement = null;
3248 event.preventDefault();
3249 }
3250
3251 return false;
3252 }
3253
3254 if (deviceIsIOS && !deviceIsIOS4) {
3255
3256 // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
3257 // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
3258 scrollParent = targetElement.fastClickScrollParent;
3259 if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
3260 return true;
3261 }
3262 }
3263
3264 // Prevent the actual click from going though - unless the target node is marked as requiring
3265 // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
3266 if (!this.needsClick(targetElement)) {
3267 event.preventDefault();
3268 this.sendClick(targetElement, event);
3269 }
3270
3271 return false;
3272 };
3273
3274
3275 /**
3276 * On touch cancel, stop tracking the click.
3277 *
3278 * @returns {void}
3279 */
3280 FastClick.prototype.onTouchCancel = function() {
3281 this.trackingClick = false;
3282 this.targetElement = null;
3283 };
3284
3285
3286 /**
3287 * Determine mouse events which should be permitted.
3288 *
3289 * @param {Event} event
3290 * @returns {boolean}
3291 */
3292 FastClick.prototype.onMouse = function(event) {
3293
3294 // If a target element was never set (because a touch event was never fired) allow the event
3295 if (!this.targetElement) {
3296 return true;
3297 }
3298
3299 if (event.forwardedTouchEvent) {
3300 return true;
3301 }
3302
3303 // Programmatically generated events targeting a specific element should be permitted
3304 if (!event.cancelable) {
3305 return true;
3306 }
3307
3308 // Derive and check the target element to see whether the mouse event needs to be permitted;
3309 // unless explicitly enabled, prevent non-touch click events from triggering actions,
3310 // to prevent ghost/doubleclicks.
3311 if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
3312
3313 // Prevent any user-added listeners declared on FastClick element from being fired.
3314 if (event.stopImmediatePropagation) {
3315 event.stopImmediatePropagation();
3316 } else {
3317
3318 // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
3319 event.propagationStopped = true;
3320 }
3321
3322 // Cancel the event
3323 event.stopPropagation();
3324 event.preventDefault();
3325
3326 return false;
3327 }
3328
3329 // If the mouse event is permitted, return true for the action to go through.
3330 return true;
3331 };
3332
3333
3334 /**
3335 * On actual clicks, determine whether this is a touch-generated click, a click action occurring
3336 * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
3337 * an actual click which should be permitted.
3338 *
3339 * @param {Event} event
3340 * @returns {boolean}
3341 */
3342 FastClick.prototype.onClick = function(event) {
3343 var permitted;
3344
3345 // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
3346 if (this.trackingClick) {
3347 this.targetElement = null;
3348 this.trackingClick = false;
3349 return true;
3350 }
3351
3352 // Very odd behavior on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
3353 if (event.target.type === 'submit' && event.detail === 0) {
3354 return true;
3355 }
3356
3357 permitted = this.onMouse(event);
3358
3359 // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
3360 if (!permitted) {
3361 this.targetElement = null;
3362 }
3363
3364 // If clicks are permitted, return true for the action to go through.
3365 return permitted;
3366 };
3367
3368
3369 /**
3370 * Remove all FastClick's event listeners.
3371 *
3372 * @returns {void}
3373 */
3374 FastClick.prototype.destroy = function() {
3375 var layer = this.layer;
3376
3377 if (deviceIsAndroid) {
3378 layer.removeEventListener('mouseover', this.onMouse, true);
3379 layer.removeEventListener('mousedown', this.onMouse, true);
3380 layer.removeEventListener('mouseup', this.onMouse, true);
3381 }
3382
3383 layer.removeEventListener('click', this.onClick, true);
3384 layer.removeEventListener('touchstart', this.onTouchStart, false);
3385 layer.removeEventListener('touchmove', this.onTouchMove, false);
3386 layer.removeEventListener('touchend', this.onTouchEnd, false);
3387 layer.removeEventListener('touchcancel', this.onTouchCancel, false);
3388 };
3389
3390
3391 /**
3392 * Check whether FastClick is needed.
3393 *
3394 * @param {Element} layer The layer to listen on
3395 */
3396 FastClick.notNeeded = function(layer) {
3397 var metaViewport;
3398 var chromeVersion;
3399 var blackberryVersion;
3400 var firefoxVersion;
3401
3402 // Devices that don't support touch don't need FastClick
3403 if (typeof window.ontouchstart === 'undefined') {
3404 return true;
3405 }
3406
3407 // Chrome version - zero for other browsers
3408 chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
3409
3410 if (chromeVersion) {
3411
3412 if (deviceIsAndroid) {
3413 metaViewport = document.querySelector('meta[name=viewport]');
3414
3415 if (metaViewport) {
3416 // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
3417 if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
3418 return true;
3419 }
3420 // Chrome 32 and above with width=device-width or less don't need FastClick
3421 if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
3422 return true;
3423 }
3424 }
3425
3426 // Chrome desktop doesn't need FastClick (issue #15)
3427 } else {
3428 return true;
3429 }
3430 }
3431
3432 if (deviceIsBlackBerry10) {
3433 blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
3434
3435 // BlackBerry 10.3+ does not require Fastclick library.
3436 // https://github.com/ftlabs/fastclick/issues/251
3437 if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
3438 metaViewport = document.querySelector('meta[name=viewport]');
3439
3440 if (metaViewport) {
3441 // user-scalable=no eliminates click delay.
3442 if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
3443 return true;
3444 }
3445 // width=device-width (or less than device-width) eliminates click delay.
3446 if (document.documentElement.scrollWidth <= window.outerWidth) {
3447 return true;
3448 }
3449 }
3450 }
3451 }
3452
3453 // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
3454 if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
3455 return true;
3456 }
3457
3458 // Firefox version - zero for other browsers
3459 firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
3460
3461 if (firefoxVersion >= 27) {
3462 // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896
3463
3464 metaViewport = document.querySelector('meta[name=viewport]');
3465 if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
3466 return true;
3467 }
3468 }
3469
3470 // IE11: prefixed -ms-touch-action is no longer supported and it's recommended to use non-prefixed version
3471 // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
3472 if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
3473 return true;
3474 }
3475
3476 return false;
3477 };
3478
3479
3480 /**
3481 * Factory method for creating a FastClick object
3482 *
3483 * @param {Element} layer The layer to listen on
3484 * @param {Object} [options={}] The options to override the defaults
3485 */
3486 FastClick.attach = function(layer, options) {
3487 return new FastClick(layer, options);
3488 };
3489
3490 window.FastClick = FastClick;
3491}());
3492
3493// see https://github.com/WebReflection/document-register-element/issues/21#issuecomment-102020311
3494var innerHTML = (function (document) {
3495
3496 var
3497 EXTENDS = 'extends',
3498 register = document.registerElement,
3499 div = document.createElement('div'),
3500 dre = 'document-register-element',
3501 innerHTML = register.innerHTML,
3502 initialize,
3503 registered
3504 ;
3505
3506 // avoid duplicated wrappers
3507 if (innerHTML) return innerHTML;
3508
3509 try {
3510
3511 // feature detect the problem
3512 register.call(
3513 document,
3514 dre,
3515 {prototype: Object.create(
3516 HTMLElement.prototype,
3517 {createdCallback: {value: Object}}
3518 )}
3519 );
3520
3521 div.innerHTML = '<' + dre + '></' + dre + '>';
3522
3523 // if natively supported, nothing to do
3524 if ('createdCallback' in div.querySelector(dre)) {
3525 // return just an innerHTML wrap
3526 return (register.innerHTML = function (el, html) {
3527 el.innerHTML = html;
3528 return el;
3529 });
3530 }
3531
3532 } catch(meh) {}
3533
3534 // in other cases
3535 registered = [];
3536 initialize = function (el) {
3537 if (
3538 'createdCallback' in el ||
3539 'attachedCallback' in el ||
3540 'detachedCallback' in el ||
3541 'attributeChangedCallback' in el
3542 ) return;
3543 document.createElement.innerHTMLHelper = true;
3544 for (var
3545 parentNode = el.parentNode,
3546 type = el.getAttribute('is'),
3547 name = el.nodeName,
3548 node = document.createElement.apply(
3549 document,
3550 type ? [name, type] : [name]
3551 ),
3552 attributes = el.attributes,
3553 i = 0,
3554 length = attributes.length,
3555 attr, fc;
3556 i < length; i++
3557 ) {
3558 attr = attributes[i];
3559 node.setAttribute(attr.name, attr.value);
3560 }
3561 if (node.createdCallback) {
3562 node.created = true;
3563 node.createdCallback();
3564 node.created = false;
3565 }
3566 while ((fc = el.firstChild)) node.appendChild(fc);
3567 document.createElement.innerHTMLHelper = false;
3568 if (parentNode) parentNode.replaceChild(node, el);
3569 };
3570 // augment the document.registerElement method
3571 return ((document.registerElement = function registerElement(type, options) {
3572 var name = (options[EXTENDS] ?
3573 (options[EXTENDS] + '[is="' + type + '"]') : type
3574 ).toLowerCase();
3575 if (registered.indexOf(name) < 0) registered.push(name);
3576 return register.apply(document, arguments);
3577 }).innerHTML = function (el, html) {
3578 el.innerHTML = html;
3579 for (var
3580 nodes = el.querySelectorAll(registered.join(',')),
3581 i = nodes.length; i--; initialize(nodes[i])
3582 ) {}
3583 return el;
3584 });
3585}(document));
3586/**
3587 * MicroEvent - to make any js object an event emitter (server or browser)
3588 *
3589 * - pure javascript - server compatible, browser compatible
3590 * - dont rely on the browser doms
3591 * - super simple - you get it immediately, no mystery, no magic involved
3592 *
3593 * - create a MicroEventDebug with goodies to debug
3594 * - make it safer to use
3595*/
3596
3597/** NOTE: This library is customized for Onsen UI. */
3598
3599var MicroEvent = function(){};
3600MicroEvent.prototype = {
3601 on : function(event, fct){
3602 this._events = this._events || {};
3603 this._events[event] = this._events[event] || [];
3604 this._events[event].push(fct);
3605 },
3606 once : function(event, fct){
3607 var self = this;
3608 var wrapper = function() {
3609 self.off(event, wrapper);
3610 return fct.apply(null, arguments);
3611 };
3612 this.on(event, wrapper);
3613 },
3614 off : function(event, fct){
3615 this._events = this._events || {};
3616 if( event in this._events === false ) return;
3617
3618 this._events[event] = this._events[event]
3619 .filter(function(_fct) {
3620 if (fct) {
3621 return fct !== _fct;
3622 }
3623 else {
3624 return false;
3625 }
3626 });
3627 },
3628 emit : function(event /* , args... */){
3629 this._events = this._events || {};
3630 if( event in this._events === false ) return;
3631 for(var i = 0; i < this._events[event].length; i++){
3632 this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
3633 }
3634 }
3635};
3636
3637/**
3638 * mixin will delegate all MicroEvent.js function in the destination object
3639 *
3640 * - require('MicroEvent').mixin(Foobar) will make Foobar able to use MicroEvent
3641 *
3642 * @param {Object} the object which will support MicroEvent
3643*/
3644MicroEvent.mixin = function(destObject){
3645 var props = ['on', 'once', 'off', 'emit'];
3646 for(var i = 0; i < props.length; i ++){
3647 if( typeof destObject === 'function' ){
3648 destObject.prototype[props[i]] = MicroEvent.prototype[props[i]];
3649 }else{
3650 destObject[props[i]] = MicroEvent.prototype[props[i]];
3651 }
3652 }
3653}
3654
3655// export in common js
3656if( typeof module !== "undefined" && ('exports' in module)){
3657 module.exports = MicroEvent;
3658}
3659
3660window.MicroEvent = MicroEvent;
3661
3662(function (root) {
3663
3664 // Store setTimeout reference so promise-polyfill will be unaffected by
3665 // other code modifying setTimeout (like sinon.useFakeTimers())
3666 var setTimeoutFunc = setTimeout;
3667
3668 function noop() {}
3669
3670 // Polyfill for Function.prototype.bind
3671 function bind(fn, thisArg) {
3672 return function () {
3673 fn.apply(thisArg, arguments);
3674 };
3675 }
3676
3677 function Promise(fn) {
3678 if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
3679 if (typeof fn !== 'function') throw new TypeError('not a function');
3680 this._state = 0;
3681 this._handled = false;
3682 this._value = undefined;
3683 this._deferreds = [];
3684
3685 doResolve(fn, this);
3686 }
3687
3688 function handle(self, deferred) {
3689 while (self._state === 3) {
3690 self = self._value;
3691 }
3692 if (self._state === 0) {
3693 self._deferreds.push(deferred);
3694 return;
3695 }
3696 self._handled = true;
3697 Promise._immediateFn(function () {
3698 var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
3699 if (cb === null) {
3700 (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
3701 return;
3702 }
3703 var ret;
3704 try {
3705 ret = cb(self._value);
3706 } catch (e) {
3707 reject(deferred.promise, e);
3708 return;
3709 }
3710 resolve(deferred.promise, ret);
3711 });
3712 }
3713
3714 function resolve(self, newValue) {
3715 try {
3716 // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
3717 if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
3718 if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
3719 var then = newValue.then;
3720 if (newValue instanceof Promise) {
3721 self._state = 3;
3722 self._value = newValue;
3723 finale(self);
3724 return;
3725 } else if (typeof then === 'function') {
3726 doResolve(bind(then, newValue), self);
3727 return;
3728 }
3729 }
3730 self._state = 1;
3731 self._value = newValue;
3732 finale(self);
3733 } catch (e) {
3734 reject(self, e);
3735 }
3736 }
3737
3738 function reject(self, newValue) {
3739 self._state = 2;
3740 self._value = newValue;
3741 finale(self);
3742 }
3743
3744 function finale(self) {
3745 if (self._state === 2 && self._deferreds.length === 0) {
3746 Promise._immediateFn(function() {
3747 if (!self._handled) {
3748 Promise._unhandledRejectionFn(self._value);
3749 }
3750 });
3751 }
3752
3753 for (var i = 0, len = self._deferreds.length; i < len; i++) {
3754 handle(self, self._deferreds[i]);
3755 }
3756 self._deferreds = null;
3757 }
3758
3759 function Handler(onFulfilled, onRejected, promise) {
3760 this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
3761 this.onRejected = typeof onRejected === 'function' ? onRejected : null;
3762 this.promise = promise;
3763 }
3764
3765 /**
3766 * Take a potentially misbehaving resolver function and make sure
3767 * onFulfilled and onRejected are only called once.
3768 *
3769 * Makes no guarantees about asynchrony.
3770 */
3771 function doResolve(fn, self) {
3772 var done = false;
3773 try {
3774 fn(function (value) {
3775 if (done) return;
3776 done = true;
3777 resolve(self, value);
3778 }, function (reason) {
3779 if (done) return;
3780 done = true;
3781 reject(self, reason);
3782 });
3783 } catch (ex) {
3784 if (done) return;
3785 done = true;
3786 reject(self, ex);
3787 }
3788 }
3789
3790 Promise.prototype['catch'] = function (onRejected) {
3791 return this.then(null, onRejected);
3792 };
3793
3794 Promise.prototype.then = function (onFulfilled, onRejected) {
3795 var prom = new (this.constructor)(noop);
3796
3797 handle(this, new Handler(onFulfilled, onRejected, prom));
3798 return prom;
3799 };
3800
3801 Promise.all = function (arr) {
3802 var args = Array.prototype.slice.call(arr);
3803
3804 return new Promise(function (resolve, reject) {
3805 if (args.length === 0) return resolve([]);
3806 var remaining = args.length;
3807
3808 function res(i, val) {
3809 try {
3810 if (val && (typeof val === 'object' || typeof val === 'function')) {
3811 var then = val.then;
3812 if (typeof then === 'function') {
3813 then.call(val, function (val) {
3814 res(i, val);
3815 }, reject);
3816 return;
3817 }
3818 }
3819 args[i] = val;
3820 if (--remaining === 0) {
3821 resolve(args);
3822 }
3823 } catch (ex) {
3824 reject(ex);
3825 }
3826 }
3827
3828 for (var i = 0; i < args.length; i++) {
3829 res(i, args[i]);
3830 }
3831 });
3832 };
3833
3834 Promise.resolve = function (value) {
3835 if (value && typeof value === 'object' && value.constructor === Promise) {
3836 return value;
3837 }
3838
3839 return new Promise(function (resolve) {
3840 resolve(value);
3841 });
3842 };
3843
3844 Promise.reject = function (value) {
3845 return new Promise(function (resolve, reject) {
3846 reject(value);
3847 });
3848 };
3849
3850 Promise.race = function (values) {
3851 return new Promise(function (resolve, reject) {
3852 for (var i = 0, len = values.length; i < len; i++) {
3853 values[i].then(resolve, reject);
3854 }
3855 });
3856 };
3857
3858 // Use polyfill for setImmediate for performance gains
3859 Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
3860 function (fn) {
3861 setTimeoutFunc(fn, 0);
3862 };
3863
3864 Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
3865 if (typeof console !== 'undefined' && console) {
3866 console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
3867 }
3868 };
3869
3870 /**
3871 * Set the immediate function to execute callbacks
3872 * @param fn {function} Function to execute
3873 * @deprecated
3874 */
3875 Promise._setImmediateFn = function _setImmediateFn(fn) {
3876 Promise._immediateFn = fn;
3877 };
3878
3879 /**
3880 * Change the function to execute on unhandled rejection
3881 * @param {function} fn Function to execute on unhandled rejection
3882 * @deprecated
3883 */
3884 Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
3885 Promise._unhandledRejectionFn = fn;
3886 };
3887
3888 if (!window.Promise) {
3889 window.Promise = Promise;
3890 }
3891})(this);
3892
3893/*
3894Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola
3895
3896Permission is hereby granted, free of charge, to any person obtaining
3897a copy of this software and associated documentation files (the
3898"Software"), to deal in the Software without restriction, including
3899without limitation the rights to use, copy, modify, merge, publish,
3900distribute, sublicense, and/or sell copies of the Software, and to
3901permit persons to whom the Software is furnished to do so, subject to
3902the following conditions:
3903
3904The above copyright notice and this permission notice shall be
3905included in all copies or substantial portions of the Software.
3906
3907THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3908EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3909MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3910NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
3911LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
3912OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
3913WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3914
3915*/
3916(function (global, undefined) {
3917 "use strict";
3918
3919 if (global.setImmediate) {
3920 return;
3921 }
3922
3923 var nextHandle = 1; // Spec says greater than zero
3924 var tasksByHandle = {};
3925 var currentlyRunningATask = false;
3926 var doc = global.document;
3927 var setImmediate;
3928
3929 function addFromSetImmediateArguments(args) {
3930 tasksByHandle[nextHandle] = partiallyApplied.apply(undefined, args);
3931 return nextHandle++;
3932 }
3933
3934 // This function accepts the same arguments as setImmediate, but
3935 // returns a function that requires no arguments.
3936 function partiallyApplied(handler) {
3937 var args = [].slice.call(arguments, 1);
3938 return function() {
3939 if (typeof handler === "function") {
3940 handler.apply(undefined, args);
3941 } else {
3942 (new Function("" + handler))();
3943 }
3944 };
3945 }
3946
3947 function runIfPresent(handle) {
3948 // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
3949 // So if we're currently running a task, we'll need to delay this invocation.
3950 if (currentlyRunningATask) {
3951 // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
3952 // "too much recursion" error.
3953 setTimeout(partiallyApplied(runIfPresent, handle), 0);
3954 } else {
3955 var task = tasksByHandle[handle];
3956 if (task) {
3957 currentlyRunningATask = true;
3958 try {
3959 task();
3960 } finally {
3961 clearImmediate(handle);
3962 currentlyRunningATask = false;
3963 }
3964 }
3965 }
3966 }
3967
3968 function clearImmediate(handle) {
3969 delete tasksByHandle[handle];
3970 }
3971
3972 function installNextTickImplementation() {
3973 setImmediate = function() {
3974 var handle = addFromSetImmediateArguments(arguments);
3975 process.nextTick(partiallyApplied(runIfPresent, handle));
3976 return handle;
3977 };
3978 }
3979
3980 function canUsePostMessage() {
3981 // The test against `importScripts` prevents this implementation from being installed inside a web worker,
3982 // where `global.postMessage` means something completely different and can't be used for this purpose.
3983 if (global.postMessage && !global.importScripts) {
3984 var postMessageIsAsynchronous = true;
3985 var oldOnMessage = global.onmessage;
3986 global.onmessage = function() {
3987 postMessageIsAsynchronous = false;
3988 };
3989 global.postMessage("", "*");
3990 global.onmessage = oldOnMessage;
3991 return postMessageIsAsynchronous;
3992 }
3993 }
3994
3995 function installPostMessageImplementation() {
3996 // Installs an event handler on `global` for the `message` event: see
3997 // * https://developer.mozilla.org/en/DOM/window.postMessage
3998 // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
3999
4000 var messagePrefix = "setImmediate$" + Math.random() + "$";
4001 var onGlobalMessage = function(event) {
4002 if (event.source === global &&
4003 typeof event.data === "string" &&
4004 event.data.indexOf(messagePrefix) === 0) {
4005 runIfPresent(+event.data.slice(messagePrefix.length));
4006 }
4007 };
4008
4009 if (global.addEventListener) {
4010 global.addEventListener("message", onGlobalMessage, false);
4011 } else {
4012 global.attachEvent("onmessage", onGlobalMessage);
4013 }
4014
4015 setImmediate = function() {
4016 var handle = addFromSetImmediateArguments(arguments);
4017 global.postMessage(messagePrefix + handle, "*");
4018 return handle;
4019 };
4020 }
4021
4022 function installMessageChannelImplementation() {
4023 var channel = new MessageChannel();
4024 channel.port1.onmessage = function(event) {
4025 var handle = event.data;
4026 runIfPresent(handle);
4027 };
4028
4029 setImmediate = function() {
4030 var handle = addFromSetImmediateArguments(arguments);
4031 channel.port2.postMessage(handle);
4032 return handle;
4033 };
4034 }
4035
4036 function installReadyStateChangeImplementation() {
4037 var html = doc.documentElement;
4038 setImmediate = function() {
4039 var handle = addFromSetImmediateArguments(arguments);
4040 // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
4041 // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
4042 var script = doc.createElement("script");
4043 script.onreadystatechange = function () {
4044 runIfPresent(handle);
4045 script.onreadystatechange = null;
4046 html.removeChild(script);
4047 script = null;
4048 };
4049 html.appendChild(script);
4050 return handle;
4051 };
4052 }
4053
4054 function installSetTimeoutImplementation() {
4055 setImmediate = function() {
4056 var handle = addFromSetImmediateArguments(arguments);
4057 setTimeout(partiallyApplied(runIfPresent, handle), 0);
4058 return handle;
4059 };
4060 }
4061
4062 // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
4063 var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
4064 attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
4065
4066 // Don't get fooled by e.g. browserify environments.
4067 if ({}.toString.call(global.process) === "[object process]") {
4068 // For Node.js before 0.9
4069 installNextTickImplementation();
4070
4071 } else if (canUsePostMessage()) {
4072 // For non-IE10 modern browsers
4073 installPostMessageImplementation();
4074
4075 } else if (global.MessageChannel) {
4076 // For web workers, where supported
4077 installMessageChannelImplementation();
4078
4079 } else if (doc && "onreadystatechange" in doc.createElement("script")) {
4080 // For IE 6–8
4081 installReadyStateChangeImplementation();
4082
4083 } else {
4084 // For older browsers
4085 installSetTimeoutImplementation();
4086 }
4087
4088 attachTo.setImmediate = setImmediate;
4089 attachTo.clearImmediate = clearImmediate;
4090}(function() {return this;}()));
4091
4092(function() {
4093 function Viewport() {
4094
4095 this.PRE_IOS7_VIEWPORT = "initial-scale=1, maximum-scale=1, user-scalable=no";
4096 this.IOS7_VIEWPORT = "initial-scale=1, maximum-scale=1, user-scalable=no";
4097 this.DEFAULT_VIEWPORT = "initial-scale=1, maximum-scale=1, user-scalable=no";
4098
4099 this.ensureViewportElement();
4100 this.platform = {};
4101 this.platform.name = this.getPlatformName();
4102 this.platform.version = this.getPlatformVersion();
4103
4104 return this;
4105 };
4106
4107 Viewport.prototype.ensureViewportElement = function(){
4108 this.viewportElement = document.querySelector('meta[name=viewport]');
4109 if(!this.viewportElement){
4110 this.viewportElement = document.createElement('meta');
4111 this.viewportElement.name = "viewport";
4112 document.head.appendChild(this.viewportElement);
4113 }
4114 },
4115
4116 Viewport.prototype.setup = function() {
4117 if (!this.viewportElement) {
4118 return;
4119 }
4120
4121 if (this.viewportElement.getAttribute('data-no-adjust') == "true") {
4122 return;
4123 }
4124
4125 if (!this.viewportElement.getAttribute('content')) {
4126 if (this.platform.name == 'ios') {
4127 if (this.platform.version >= 7 && isWebView()) {
4128 this.viewportElement.setAttribute('content', this.IOS7_VIEWPORT);
4129 } else {
4130 this.viewportElement.setAttribute('content', this.PRE_IOS7_VIEWPORT);
4131 }
4132 } else {
4133 this.viewportElement.setAttribute('content', this.DEFAULT_VIEWPORT);
4134 }
4135 }
4136
4137 function isWebView() {
4138 return !!(window.cordova || window.phonegap || window.PhoneGap);
4139 }
4140 };
4141
4142 Viewport.prototype.getPlatformName = function() {
4143 if (navigator.userAgent.match(/Android/i)) {
4144 return "android";
4145 }
4146
4147 if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
4148 return "ios";
4149 }
4150
4151 // unknown
4152 return undefined;
4153 };
4154
4155 Viewport.prototype.getPlatformVersion = function() {
4156 var start = window.navigator.userAgent.indexOf('OS ');
4157 return window.Number(window.navigator.userAgent.substr(start + 3, 3).replace('_', '.'));
4158 };
4159
4160 window.Viewport = Viewport;
4161})();
4162
4163// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4164// JavaScript Dynamic Content shim for Windows Store apps
4165(function () {
4166
4167 if (window.MSApp && MSApp.execUnsafeLocalFunction) {
4168
4169 // Some nodes will have an "attributes" property which shadows the Node.prototype.attributes property
4170 // and means we don't actually see the attributes of the Node (interestingly the VS debug console
4171 // appears to suffer from the same issue).
4172 //
4173 var Element_setAttribute = Object.getOwnPropertyDescriptor(Element.prototype, "setAttribute").value;
4174 var Element_removeAttribute = Object.getOwnPropertyDescriptor(Element.prototype, "removeAttribute").value;
4175 var HTMLElement_insertAdjacentHTMLPropertyDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "insertAdjacentHTML");
4176 var Node_get_attributes = Object.getOwnPropertyDescriptor(Node.prototype, "attributes").get;
4177 var Node_get_childNodes = Object.getOwnPropertyDescriptor(Node.prototype, "childNodes").get;
4178 var detectionDiv = document.createElement("div");
4179
4180 function getAttributes(element) {
4181 return Node_get_attributes.call(element);
4182 }
4183
4184 function setAttribute(element, attribute, value) {
4185 try {
4186 Element_setAttribute.call(element, attribute, value);
4187 } catch (e) {
4188 // ignore
4189 }
4190 }
4191
4192 function removeAttribute(element, attribute) {
4193 Element_removeAttribute.call(element, attribute);
4194 }
4195
4196 function childNodes(element) {
4197 return Node_get_childNodes.call(element);
4198 }
4199
4200 function empty(element) {
4201 while (element.childNodes.length) {
4202 element.removeChild(element.lastChild);
4203 }
4204 }
4205
4206 function insertAdjacentHTML(element, position, html) {
4207 HTMLElement_insertAdjacentHTMLPropertyDescriptor.value.call(element, position, html);
4208 }
4209
4210 function inUnsafeMode() {
4211 var isUnsafe = true;
4212 try {
4213 detectionDiv.innerHTML = "<test/>";
4214 }
4215 catch (ex) {
4216 isUnsafe = false;
4217 }
4218
4219 return isUnsafe;
4220 }
4221
4222 function cleanse(html, targetElement) {
4223 var cleaner = document.implementation.createHTMLDocument("cleaner");
4224 empty(cleaner.documentElement);
4225 MSApp.execUnsafeLocalFunction(function () {
4226 insertAdjacentHTML(cleaner.documentElement, "afterbegin", html);
4227 });
4228
4229 var scripts = cleaner.documentElement.querySelectorAll("script");
4230 Array.prototype.forEach.call(scripts, function (script) {
4231 switch (script.type.toLowerCase()) {
4232 case "":
4233 script.type = "text/inert";
4234 break;
4235 case "text/javascript":
4236 case "text/ecmascript":
4237 case "text/x-javascript":
4238 case "text/jscript":
4239 case "text/livescript":
4240 case "text/javascript1.1":
4241 case "text/javascript1.2":
4242 case "text/javascript1.3":
4243 script.type = "text/inert-" + script.type.slice("text/".length);
4244 break;
4245 case "application/javascript":
4246 case "application/ecmascript":
4247 case "application/x-javascript":
4248 script.type = "application/inert-" + script.type.slice("application/".length);
4249 break;
4250
4251 default:
4252 break;
4253 }
4254 });
4255
4256 function cleanseAttributes(element) {
4257 var attributes = getAttributes(element);
4258 if (attributes && attributes.length) {
4259 // because the attributes collection is live it is simpler to queue up the renames
4260 var events;
4261 for (var i = 0, len = attributes.length; i < len; i++) {
4262 var attribute = attributes[i];
4263 var name = attribute.name;
4264 if ((name[0] === "o" || name[0] === "O") &&
4265 (name[1] === "n" || name[1] === "N")) {
4266 events = events || [];
4267 events.push({ name: attribute.name, value: attribute.value });
4268 }
4269 }
4270 if (events) {
4271 for (var i = 0, len = events.length; i < len; i++) {
4272 var attribute = events[i];
4273 removeAttribute(element, attribute.name);
4274 setAttribute(element, "x-" + attribute.name, attribute.value);
4275 }
4276 }
4277 }
4278 var children = childNodes(element);
4279 for (var i = 0, len = children.length; i < len; i++) {
4280 cleanseAttributes(children[i]);
4281 }
4282 }
4283 cleanseAttributes(cleaner.documentElement);
4284
4285 var cleanedNodes = [];
4286
4287 if (targetElement.tagName === 'HTML') {
4288 cleanedNodes = Array.prototype.slice.call(document.adoptNode(cleaner.documentElement).childNodes);
4289 } else {
4290 if (cleaner.head) {
4291 cleanedNodes = cleanedNodes.concat(Array.prototype.slice.call(document.adoptNode(cleaner.head).childNodes));
4292 }
4293 if (cleaner.body) {
4294 cleanedNodes = cleanedNodes.concat(Array.prototype.slice.call(document.adoptNode(cleaner.body).childNodes));
4295 }
4296 }
4297
4298 return cleanedNodes;
4299 }
4300
4301 function cleansePropertySetter(property, setter) {
4302 var propertyDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, property);
4303 var originalSetter = propertyDescriptor.set;
4304 Object.defineProperty(HTMLElement.prototype, property, {
4305 get: propertyDescriptor.get,
4306 set: function (value) {
4307 if(window.WinJS && window.WinJS._execUnsafe && inUnsafeMode()) {
4308 originalSetter.call(this, value);
4309 } else {
4310 var that = this;
4311 var nodes = cleanse(value, that);
4312 MSApp.execUnsafeLocalFunction(function () {
4313 setter(propertyDescriptor, that, nodes);
4314 });
4315 }
4316 },
4317 enumerable: propertyDescriptor.enumerable,
4318 configurable: propertyDescriptor.configurable,
4319 });
4320 }
4321 cleansePropertySetter("innerHTML", function (propertyDescriptor, target, elements) {
4322 empty(target);
4323 for (var i = 0, len = elements.length; i < len; i++) {
4324 target.appendChild(elements[i]);
4325 }
4326 });
4327 cleansePropertySetter("outerHTML", function (propertyDescriptor, target, elements) {
4328 for (var i = 0, len = elements.length; i < len; i++) {
4329 target.insertAdjacentElement("afterend", elements[i]);
4330 }
4331 target.parentNode.removeChild(target);
4332 });
4333
4334 }
4335
4336}());
4337(function (global, factory) {
4338 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4339 typeof define === 'function' && define.amd ? define(factory) :
4340 (global.ons = factory());
4341}(this, (function () { 'use strict';
4342
4343/*
4344Copyright 2013-2015 ASIAL CORPORATION
4345
4346Licensed under the Apache License, Version 2.0 (the "License");
4347you may not use this file except in compliance with the License.
4348You may obtain a copy of the License at
4349
4350 http://www.apache.org/licenses/LICENSE-2.0
4351
4352Unless required by applicable law or agreed to in writing, software
4353distributed under the License is distributed on an "AS IS" BASIS,
4354WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4355See the License for the specific language governing permissions and
4356limitations under the License.
4357
4358*/
4359
4360var unwrap = function unwrap(string) {
4361 return string.slice(1, -1);
4362};
4363var isObjectString = function isObjectString(string) {
4364 return string.startsWith('{') && string.endsWith('}');
4365};
4366var isArrayString = function isArrayString(string) {
4367 return string.startsWith('[') && string.endsWith(']');
4368};
4369var isQuotedString = function isQuotedString(string) {
4370 return string.startsWith('\'') && string.endsWith('\'') || string.startsWith('"') && string.endsWith('"');
4371};
4372
4373var error$1 = function error$1(token, string, originalString) {
4374 throw new Error('Unexpected token \'' + token + '\' at position ' + (originalString.length - string.length - 1) + ' in string: \'' + originalString + '\'');
4375};
4376
4377var processToken = function processToken(token, string, originalString) {
4378 if (token === 'true' || token === 'false') {
4379 return token === 'true';
4380 } else if (isQuotedString(token)) {
4381 return unwrap(token);
4382 } else if (!isNaN(token)) {
4383 return +token;
4384 } else if (isObjectString(token)) {
4385 return parseObject(unwrap(token));
4386 } else if (isArrayString(token)) {
4387 return parseArray(unwrap(token));
4388 } else {
4389 error$1(token, string, originalString);
4390 }
4391};
4392
4393var nextToken = function nextToken(string) {
4394 string = string.trimLeft();
4395 var limit = string.length;
4396
4397 if (string[0] === ':' || string[0] === ',') {
4398
4399 limit = 1;
4400 } else if (string[0] === '{' || string[0] === '[') {
4401
4402 var c = string.charCodeAt(0);
4403 var nestedObject = 1;
4404 for (var i = 1; i < string.length; i++) {
4405 if (string.charCodeAt(i) === c) {
4406 nestedObject++;
4407 } else if (string.charCodeAt(i) === c + 2) {
4408 nestedObject--;
4409 if (nestedObject === 0) {
4410 limit = i + 1;
4411 break;
4412 }
4413 }
4414 }
4415 } else if (string[0] === '\'' || string[0] === '\"') {
4416
4417 for (var _i = 1; _i < string.length; _i++) {
4418 if (string[_i] === string[0]) {
4419 limit = _i + 1;
4420 break;
4421 }
4422 }
4423 } else {
4424
4425 for (var _i2 = 1; _i2 < string.length; _i2++) {
4426 if ([' ', ',', ':'].indexOf(string[_i2]) !== -1) {
4427 limit = _i2;
4428 break;
4429 }
4430 }
4431 }
4432
4433 return string.slice(0, limit);
4434};
4435
4436var parseObject = function parseObject(string) {
4437 var isValidKey = function isValidKey(key) {
4438 return (/^[A-Z_\$][A-Z0-9_\$]*$/i.test(key)
4439 );
4440 };
4441
4442 string = string.trim();
4443 var originalString = string;
4444 var object = {};
4445 var readingKey = true,
4446 key = void 0,
4447 previousToken = void 0,
4448 token = void 0;
4449
4450 while (string.length > 0) {
4451 previousToken = token;
4452 token = nextToken(string);
4453 string = string.slice(token.length, string.length).trimLeft();
4454
4455 if (token === ':' && (!readingKey || !previousToken || previousToken === ',') || token === ',' && readingKey || token !== ':' && token !== ',' && previousToken && previousToken !== ',' && previousToken !== ':') {
4456 error$1(token, string, originalString);
4457 } else if (token === ':' && readingKey && previousToken) {
4458 if (isValidKey(previousToken)) {
4459 key = previousToken;
4460 readingKey = false;
4461 } else {
4462 throw new Error('Invalid key token \'' + previousToken + '\' at position 0 in string: \'' + originalString + '\'');
4463 }
4464 } else if (token === ',' && !readingKey && previousToken) {
4465 object[key] = processToken(previousToken, string, originalString);
4466 readingKey = true;
4467 }
4468 }
4469
4470 if (token) {
4471 object[key] = processToken(token, string, originalString);
4472 }
4473
4474 return object;
4475};
4476
4477var parseArray = function parseArray(string) {
4478 string = string.trim();
4479 var originalString = string;
4480 var array = [];
4481 var previousToken = void 0,
4482 token = void 0;
4483
4484 while (string.length > 0) {
4485 previousToken = token;
4486 token = nextToken(string);
4487 string = string.slice(token.length, string.length).trimLeft();
4488
4489 if (token === ',' && (!previousToken || previousToken === ',')) {
4490 error$1(token, string, originalString);
4491 } else if (token === ',') {
4492 array.push(processToken(previousToken, string, originalString));
4493 }
4494 }
4495
4496 if (token) {
4497 if (token !== ',') {
4498 array.push(processToken(token, string, originalString));
4499 } else {
4500 error$1(token, string, originalString);
4501 }
4502 }
4503
4504 return array;
4505};
4506
4507var parse = function parse(string) {
4508 string = string.trim();
4509
4510 if (isObjectString(string)) {
4511 return parseObject(unwrap(string));
4512 } else if (isArrayString(string)) {
4513 return parseArray(unwrap(string));
4514 } else {
4515 throw new Error('Provided string must be object or array like: ' + string);
4516 }
4517};
4518
4519var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
4520 return typeof obj;
4521} : function (obj) {
4522 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
4523};
4524
4525
4526
4527
4528
4529var asyncGenerator = function () {
4530 function AwaitValue(value) {
4531 this.value = value;
4532 }
4533
4534 function AsyncGenerator(gen) {
4535 var front, back;
4536
4537 function send(key, arg) {
4538 return new Promise(function (resolve, reject) {
4539 var request = {
4540 key: key,
4541 arg: arg,
4542 resolve: resolve,
4543 reject: reject,
4544 next: null
4545 };
4546
4547 if (back) {
4548 back = back.next = request;
4549 } else {
4550 front = back = request;
4551 resume(key, arg);
4552 }
4553 });
4554 }
4555
4556 function resume(key, arg) {
4557 try {
4558 var result = gen[key](arg);
4559 var value = result.value;
4560
4561 if (value instanceof AwaitValue) {
4562 Promise.resolve(value.value).then(function (arg) {
4563 resume("next", arg);
4564 }, function (arg) {
4565 resume("throw", arg);
4566 });
4567 } else {
4568 settle(result.done ? "return" : "normal", result.value);
4569 }
4570 } catch (err) {
4571 settle("throw", err);
4572 }
4573 }
4574
4575 function settle(type, value) {
4576 switch (type) {
4577 case "return":
4578 front.resolve({
4579 value: value,
4580 done: true
4581 });
4582 break;
4583
4584 case "throw":
4585 front.reject(value);
4586 break;
4587
4588 default:
4589 front.resolve({
4590 value: value,
4591 done: false
4592 });
4593 break;
4594 }
4595
4596 front = front.next;
4597
4598 if (front) {
4599 resume(front.key, front.arg);
4600 } else {
4601 back = null;
4602 }
4603 }
4604
4605 this._invoke = send;
4606
4607 if (typeof gen.return !== "function") {
4608 this.return = undefined;
4609 }
4610 }
4611
4612 if (typeof Symbol === "function" && Symbol.asyncIterator) {
4613 AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
4614 return this;
4615 };
4616 }
4617
4618 AsyncGenerator.prototype.next = function (arg) {
4619 return this._invoke("next", arg);
4620 };
4621
4622 AsyncGenerator.prototype.throw = function (arg) {
4623 return this._invoke("throw", arg);
4624 };
4625
4626 AsyncGenerator.prototype.return = function (arg) {
4627 return this._invoke("return", arg);
4628 };
4629
4630 return {
4631 wrap: function (fn) {
4632 return function () {
4633 return new AsyncGenerator(fn.apply(this, arguments));
4634 };
4635 },
4636 await: function (value) {
4637 return new AwaitValue(value);
4638 }
4639 };
4640}();
4641
4642
4643
4644
4645
4646var classCallCheck = function (instance, Constructor) {
4647 if (!(instance instanceof Constructor)) {
4648 throw new TypeError("Cannot call a class as a function");
4649 }
4650};
4651
4652var createClass = function () {
4653 function defineProperties(target, props) {
4654 for (var i = 0; i < props.length; i++) {
4655 var descriptor = props[i];
4656 descriptor.enumerable = descriptor.enumerable || false;
4657 descriptor.configurable = true;
4658 if ("value" in descriptor) descriptor.writable = true;
4659 Object.defineProperty(target, descriptor.key, descriptor);
4660 }
4661 }
4662
4663 return function (Constructor, protoProps, staticProps) {
4664 if (protoProps) defineProperties(Constructor.prototype, protoProps);
4665 if (staticProps) defineProperties(Constructor, staticProps);
4666 return Constructor;
4667 };
4668}();
4669
4670
4671
4672
4673
4674
4675
4676var _extends = Object.assign || function (target) {
4677 for (var i = 1; i < arguments.length; i++) {
4678 var source = arguments[i];
4679
4680 for (var key in source) {
4681 if (Object.prototype.hasOwnProperty.call(source, key)) {
4682 target[key] = source[key];
4683 }
4684 }
4685 }
4686
4687 return target;
4688};
4689
4690var get$1 = function get$1(object, property, receiver) {
4691 if (object === null) object = Function.prototype;
4692 var desc = Object.getOwnPropertyDescriptor(object, property);
4693
4694 if (desc === undefined) {
4695 var parent = Object.getPrototypeOf(object);
4696
4697 if (parent === null) {
4698 return undefined;
4699 } else {
4700 return get$1(parent, property, receiver);
4701 }
4702 } else if ("value" in desc) {
4703 return desc.value;
4704 } else {
4705 var getter = desc.get;
4706
4707 if (getter === undefined) {
4708 return undefined;
4709 }
4710
4711 return getter.call(receiver);
4712 }
4713};
4714
4715var inherits = function (subClass, superClass) {
4716 if (typeof superClass !== "function" && superClass !== null) {
4717 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
4718 }
4719
4720 subClass.prototype = Object.create(superClass && superClass.prototype, {
4721 constructor: {
4722 value: subClass,
4723 enumerable: false,
4724 writable: true,
4725 configurable: true
4726 }
4727 });
4728 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
4729};
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741var possibleConstructorReturn = function (self, call) {
4742 if (!self) {
4743 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
4744 }
4745
4746 return call && (typeof call === "object" || typeof call === "function") ? call : self;
4747};
4748
4749
4750
4751var set$1 = function set$1(object, property, value, receiver) {
4752 var desc = Object.getOwnPropertyDescriptor(object, property);
4753
4754 if (desc === undefined) {
4755 var parent = Object.getPrototypeOf(object);
4756
4757 if (parent !== null) {
4758 set$1(parent, property, value, receiver);
4759 }
4760 } else if ("value" in desc && desc.writable) {
4761 desc.value = value;
4762 } else {
4763 var setter = desc.set;
4764
4765 if (setter !== undefined) {
4766 setter.call(receiver, value);
4767 }
4768 }
4769
4770 return value;
4771};
4772
4773/*
4774Copyright 2013-2015 ASIAL CORPORATION
4775
4776Licensed under the Apache License, Version 2.0 (the "License");
4777you may not use this file except in compliance with the License.
4778You may obtain a copy of the License at
4779
4780 http://www.apache.org/licenses/LICENSE-2.0
4781
4782Unless required by applicable law or agreed to in writing, software
4783distributed under the License is distributed on an "AS IS" BASIS,
4784WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4785See the License for the specific language governing permissions and
4786limitations under the License.
4787
4788*/
4789
4790var util = {};
4791
4792/**
4793 * @param {String/Function} query dot class name or node name or matcher function.
4794 * @return {Function}
4795 */
4796util.prepareQuery = function (query) {
4797 return query instanceof Function ? query : function (element) {
4798 return util.match(element, query);
4799 };
4800};
4801
4802/**
4803 * @param {Element} element
4804 * @param {String/Function} query dot class name or node name.
4805 * @return {Boolean}
4806 */
4807util.match = function (element, query) {
4808 if (query[0] === '.') {
4809 return element.classList.contains(query.slice(1));
4810 }
4811 return element.nodeName.toLowerCase() === query;
4812};
4813
4814/**
4815 * @param {Element} element
4816 * @param {String/Function} query dot class name or node name or matcher function.
4817 * @return {HTMLElement/null}
4818 */
4819util.findChild = function (element, query) {
4820 var match = util.prepareQuery(query);
4821
4822 for (var i = 0; i < element.children.length; i++) {
4823 var node = element.children[i];
4824 if (match(node)) {
4825 return node;
4826 }
4827 }
4828 return null;
4829};
4830
4831/**
4832 * @param {Element} element
4833 * @param {String/Function} query dot class name or node name or matcher function.
4834 * @return {HTMLElement/null}
4835 */
4836util.findParent = function (element, query) {
4837 var match = util.prepareQuery(query);
4838
4839 var parent = element.parentNode;
4840 for (;;) {
4841 if (!parent || parent === document) {
4842 return null;
4843 }
4844 if (match(parent)) {
4845 return parent;
4846 }
4847 parent = parent.parentNode;
4848 }
4849};
4850
4851/**
4852 * @param {Element} element
4853 * @return {boolean}
4854 */
4855util.isAttached = function (element) {
4856 while (document.documentElement !== element) {
4857 if (!element) {
4858 return false;
4859 }
4860 element = element.parentNode;
4861 }
4862 return true;
4863};
4864
4865/**
4866 * @param {Element} element
4867 * @return {boolean}
4868 */
4869util.hasAnyComponentAsParent = function (element) {
4870 while (element && document.documentElement !== element) {
4871 element = element.parentNode;
4872 if (element && element.nodeName.toLowerCase().match(/(ons-navigator|ons-tabbar|ons-sliding-menu|ons-split-view)/)) {
4873 return true;
4874 }
4875 }
4876 return false;
4877};
4878
4879/**
4880 * @param {Element} element
4881 * @param {String} action to propagate
4882 */
4883util.propagateAction = function (element, action) {
4884 for (var i = 0; i < element.childNodes.length; i++) {
4885 var child = element.childNodes[i];
4886 if (child[action] instanceof Function) {
4887 child[action]();
4888 } else {
4889 util.propagateAction(child, action);
4890 }
4891 }
4892};
4893
4894/**
4895 * @param {String} selector - tag and class only
4896 * @param {Object} style
4897 * @param {Element}
4898 */
4899util.create = function () {
4900 var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
4901 var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4902
4903 var classList = selector.split('.');
4904 var element = document.createElement(classList.shift() || 'div');
4905
4906 if (classList.length) {
4907 element.className = classList.join(' ');
4908 }
4909
4910 util.extend(element.style, style);
4911
4912 return element;
4913};
4914
4915/**
4916 * @param {String} html
4917 * @return {Element}
4918 */
4919util.createElement = function (html) {
4920 var wrapper = document.createElement('div');
4921 innerHTML(wrapper, html);
4922
4923 if (wrapper.children.length > 1) {
4924 throw new Error('"html" must be one wrapper element.');
4925 }
4926
4927 return wrapper.children[0];
4928};
4929
4930/**
4931 * @param {String} html
4932 * @return {HTMLFragment}
4933 */
4934util.createFragment = function (html) {
4935 var wrapper = document.createElement('div');
4936 innerHTML(wrapper, html);
4937 var fragment = document.createDocumentFragment();
4938
4939 while (wrapper.firstChild) {
4940 fragment.appendChild(wrapper.firstChild);
4941 }
4942
4943 return fragment;
4944};
4945
4946/*
4947 * @param {Object} dst Destination object.
4948 * @param {...Object} src Source object(s).
4949 * @returns {Object} Reference to `dst`.
4950 */
4951util.extend = function (dst) {
4952 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
4953 args[_key - 1] = arguments[_key];
4954 }
4955
4956 for (var i = 0; i < args.length; i++) {
4957 if (args[i]) {
4958 var keys = Object.keys(args[i]);
4959 for (var j = 0; j < keys.length; j++) {
4960 var key = keys[j];
4961 dst[key] = args[i][key];
4962 }
4963 }
4964 }
4965
4966 return dst;
4967};
4968
4969/**
4970 * @param {Object} arrayLike
4971 * @return {Array}
4972 */
4973util.arrayFrom = function (arrayLike) {
4974 return Array.prototype.slice.apply(arrayLike);
4975};
4976
4977/**
4978 * @param {String} jsonString
4979 * @param {Object} [failSafe]
4980 * @return {Object}
4981 */
4982util.parseJSONObjectSafely = function (jsonString) {
4983 var failSafe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4984
4985 try {
4986 var result = JSON.parse('' + jsonString);
4987 if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) {
4988 return result;
4989 }
4990 } catch (e) {
4991 return failSafe;
4992 }
4993 return failSafe;
4994};
4995
4996/**
4997 * @param {String} path - path such as 'myApp.controllers.data.loadData'
4998 * @return {Any} - whatever is located at that path
4999 */
5000util.findFromPath = function (path) {
5001 path = path.split('.');
5002 var el = window,
5003 key;
5004 while (key = path.shift()) {
5005 // eslint-disable-line no-cond-assign
5006 el = el[key];
5007 }
5008 return el;
5009};
5010
5011/**
5012 * @param {Element} element
5013 * @param {String} eventName
5014 * @param {Object} [detail]
5015 * @return {CustomEvent}
5016 */
5017util.triggerElementEvent = function (target, eventName) {
5018 var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
5019
5020
5021 var event = new CustomEvent(eventName, {
5022 bubbles: true,
5023 cancelable: true,
5024 detail: detail
5025 });
5026
5027 Object.keys(detail).forEach(function (key) {
5028 event[key] = detail[key];
5029 });
5030
5031 target.dispatchEvent(event);
5032
5033 return event;
5034};
5035
5036/**
5037 * @param {Element} target
5038 * @param {String} modifierName
5039 * @return {Boolean}
5040 */
5041util.hasModifier = function (target, modifierName) {
5042 if (!target.hasAttribute('modifier')) {
5043 return false;
5044 }
5045 return target.getAttribute('modifier').split(/\s+/).some(function (e) {
5046 return e === modifierName;
5047 });
5048};
5049
5050/**
5051 * @param {Element} target
5052 * @param {String} modifierName
5053 * @return {Boolean} Whether it was added or not.
5054 */
5055util.addModifier = function (target, modifierName) {
5056 if (util.hasModifier(target, modifierName)) {
5057 return false;
5058 }
5059
5060 modifierName = modifierName.trim();
5061 var modifierAttribute = target.getAttribute('modifier') || '';
5062 target.setAttribute('modifier', (modifierAttribute + ' ' + modifierName).trim());
5063 return true;
5064};
5065
5066/**
5067 * @param {Element} target
5068 * @param {String} modifierName
5069 * @return {Boolean} Whether it was found or not.
5070 */
5071util.removeModifier = function (target, modifierName) {
5072 if (!target.getAttribute('modifier')) {
5073 return false;
5074 }
5075
5076 var modifiers = target.getAttribute('modifier').split(/\s+/);
5077
5078 var newModifiers = modifiers.filter(function (item) {
5079 return item && item !== modifierName;
5080 });
5081 target.setAttribute('modifier', newModifiers.join(' '));
5082
5083 return modifiers.length !== newModifiers.length;
5084};
5085
5086util.updateParentPosition = function (el) {
5087 if (!el._parentUpdated && el.parentElement) {
5088 if (window.getComputedStyle(el.parentElement).getPropertyValue('position') === 'static') {
5089 el.parentElement.style.position = 'relative';
5090 }
5091 el._parentUpdated = true;
5092 }
5093};
5094
5095util.toggleAttribute = function (element, name, enable) {
5096 if (enable) {
5097 element.setAttribute(name, '');
5098 } else {
5099 element.removeAttribute(name);
5100 }
5101};
5102
5103util.bindListeners = function (element, listenerNames) {
5104 listenerNames.forEach(function (name) {
5105 var boundName = name.replace(/^_[a-z]/, '_bound' + name[1].toUpperCase());
5106 element[boundName] = element[boundName] || element[name].bind(element);
5107 });
5108};
5109
5110util.each = function (obj, f) {
5111 return Object.keys(obj).forEach(function (key) {
5112 return f(key, obj[key]);
5113 });
5114};
5115
5116/**
5117 * @param {Element} target
5118 */
5119util.updateRipple = function (target) {
5120 var rippleElement = util.findChild(target, 'ons-ripple');
5121
5122 if (target.hasAttribute('ripple')) {
5123 if (!rippleElement) {
5124 target.insertBefore(document.createElement('ons-ripple'), target.firstChild);
5125 }
5126 } else if (rippleElement) {
5127 rippleElement.remove();
5128 }
5129};
5130
5131/**
5132 * @param {String}
5133 * @return {Object}
5134 */
5135util.animationOptionsParse = parse;
5136
5137/**
5138 * @param {*} value
5139 */
5140util.isInteger = function (value) {
5141 return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
5142};
5143
5144/**
5145 * @return {Obejct} Deferred promise.
5146 */
5147util.defer = function () {
5148 var deferred = {};
5149 deferred.promise = new Promise(function (resolve, reject) {
5150 deferred.resolve = resolve;
5151 deferred.reject = reject;
5152 });
5153 return deferred;
5154};
5155
5156/*
5157 * Gesture detector library that forked from github.com/EightMedia/hammer.js.
5158 */
5159
5160var Event$1;
5161var Utils;
5162var Detection;
5163var PointerEvent;
5164
5165/**
5166 * @object ons.GestureDetector
5167 * @category gesture
5168 * @description
5169 * [en]Utility class for gesture detection.[/en]
5170 * [ja]ジェスチャを検知するためのユーティリティクラスです。[/ja]
5171 */
5172
5173/**
5174 * @method constructor
5175 * @signature constructor(element[, options])
5176 * @description
5177 * [en]Create a new GestureDetector instance.[/en]
5178 * [ja]GestureDetectorのインスタンスを生成します。[/ja]
5179 * @param {Element} element
5180 * [en]Name of the event.[/en]
5181 * [ja]ジェスチャを検知するDOM要素を指定します。[/ja]
5182 * @param {Object} [options]
5183 * [en]Options object.[/en]
5184 * [ja]オプションを指定します。[/ja]
5185 * @return {ons.GestureDetector.Instance}
5186 */
5187var GestureDetector = function GestureDetector(element, options) {
5188 return new GestureDetector.Instance(element, options || {});
5189};
5190
5191/**
5192 * default settings.
5193 * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled
5194 * by setting it's name (like `swipe`) to false.
5195 * You can set the defaults for all instances by changing this object before creating an instance.
5196 * @example
5197 * ````
5198 * GestureDetector.defaults.drag = false;
5199 * GestureDetector.defaults.behavior.touchAction = 'pan-y';
5200 * delete GestureDetector.defaults.behavior.userSelect;
5201 * ````
5202 * @property defaults
5203 * @type {Object}
5204 */
5205GestureDetector.defaults = {
5206 behavior: {
5207 // userSelect: 'none', // Also disables selection in `input` children
5208 touchAction: 'pan-y',
5209 touchCallout: 'none',
5210 contentZooming: 'none',
5211 userDrag: 'none',
5212 tapHighlightColor: 'rgba(0,0,0,0)'
5213 }
5214};
5215
5216/**
5217 * GestureDetector document where the base events are added at
5218 * @property DOCUMENT
5219 * @type {HTMLElement}
5220 * @default window.document
5221 */
5222GestureDetector.DOCUMENT = document;
5223
5224/**
5225 * detect support for pointer events
5226 * @property HAS_POINTEREVENTS
5227 * @type {Boolean}
5228 */
5229GestureDetector.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;
5230
5231/**
5232 * detect support for touch events
5233 * @property HAS_TOUCHEVENTS
5234 * @type {Boolean}
5235 */
5236GestureDetector.HAS_TOUCHEVENTS = 'ontouchstart' in window;
5237
5238/**
5239 * detect mobile browsers
5240 * @property IS_MOBILE
5241 * @type {Boolean}
5242 */
5243GestureDetector.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent);
5244
5245/**
5246 * detect if we want to support mouseevents at all
5247 * @property NO_MOUSEEVENTS
5248 * @type {Boolean}
5249 */
5250GestureDetector.NO_MOUSEEVENTS = GestureDetector.HAS_TOUCHEVENTS && GestureDetector.IS_MOBILE || GestureDetector.HAS_POINTEREVENTS;
5251
5252/**
5253 * interval in which GestureDetector recalculates current velocity/direction/angle in ms
5254 * @property CALCULATE_INTERVAL
5255 * @type {Number}
5256 * @default 25
5257 */
5258GestureDetector.CALCULATE_INTERVAL = 25;
5259
5260/**
5261 * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup`
5262 * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`)
5263 * @property EVENT_TYPES
5264 * @private
5265 * @writeOnce
5266 * @type {Object}
5267 */
5268var EVENT_TYPES = {};
5269
5270/**
5271 * direction strings, for safe comparisons
5272 * @property DIRECTION_DOWN|LEFT|UP|RIGHT
5273 * @final
5274 * @type {String}
5275 * @default 'down' 'left' 'up' 'right'
5276 */
5277var DIRECTION_DOWN = GestureDetector.DIRECTION_DOWN = 'down';
5278var DIRECTION_LEFT = GestureDetector.DIRECTION_LEFT = 'left';
5279var DIRECTION_UP = GestureDetector.DIRECTION_UP = 'up';
5280var DIRECTION_RIGHT = GestureDetector.DIRECTION_RIGHT = 'right';
5281
5282/**
5283 * pointertype strings, for safe comparisons
5284 * @property POINTER_MOUSE|TOUCH|PEN
5285 * @final
5286 * @type {String}
5287 * @default 'mouse' 'touch' 'pen'
5288 */
5289var POINTER_MOUSE = GestureDetector.POINTER_MOUSE = 'mouse';
5290var POINTER_TOUCH = GestureDetector.POINTER_TOUCH = 'touch';
5291var POINTER_PEN = GestureDetector.POINTER_PEN = 'pen';
5292
5293/**
5294 * eventtypes
5295 * @property EVENT_START|MOVE|END|RELEASE|TOUCH
5296 * @final
5297 * @type {String}
5298 * @default 'start' 'change' 'move' 'end' 'release' 'touch'
5299 */
5300var EVENT_START = GestureDetector.EVENT_START = 'start';
5301var EVENT_MOVE = GestureDetector.EVENT_MOVE = 'move';
5302var EVENT_END = GestureDetector.EVENT_END = 'end';
5303var EVENT_RELEASE = GestureDetector.EVENT_RELEASE = 'release';
5304var EVENT_TOUCH = GestureDetector.EVENT_TOUCH = 'touch';
5305
5306/**
5307 * if the window events are set...
5308 * @property READY
5309 * @writeOnce
5310 * @type {Boolean}
5311 * @default false
5312 */
5313GestureDetector.READY = false;
5314
5315/**
5316 * plugins namespace
5317 * @property plugins
5318 * @type {Object}
5319 */
5320GestureDetector.plugins = GestureDetector.plugins || {};
5321
5322/**
5323 * gestures namespace
5324 * see `/gestures` for the definitions
5325 * @property gestures
5326 * @type {Object}
5327 */
5328GestureDetector.gestures = GestureDetector.gestures || {};
5329
5330/**
5331 * setup events to detect gestures on the document
5332 * this function is called when creating an new instance
5333 * @private
5334 */
5335function setup() {
5336 if (GestureDetector.READY) {
5337 return;
5338 }
5339
5340 // find what eventtypes we add listeners to
5341 Event$1.determineEventTypes();
5342
5343 // Register all gestures inside GestureDetector.gestures
5344 Utils.each(GestureDetector.gestures, function (gesture) {
5345 Detection.register(gesture);
5346 });
5347
5348 // Add touch events on the document
5349 Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_MOVE, Detection.detect);
5350 Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_END, Detection.detect);
5351
5352 // GestureDetector is ready...!
5353 GestureDetector.READY = true;
5354}
5355
5356/**
5357 * @module GestureDetector
5358 *
5359 * @class Utils
5360 * @static
5361 */
5362Utils = GestureDetector.utils = {
5363 /**
5364 * extend method, could also be used for cloning when `dest` is an empty object.
5365 * changes the dest object
5366 * @param {Object} dest
5367 * @param {Object} src
5368 * @param {Boolean} [merge=false] do a merge
5369 * @return {Object} dest
5370 */
5371 extend: function extend(dest, src, merge) {
5372 for (var key in src) {
5373 if (src.hasOwnProperty(key) && (dest[key] === undefined || !merge)) {
5374 dest[key] = src[key];
5375 }
5376 }
5377 return dest;
5378 },
5379
5380 /**
5381 * simple addEventListener wrapper
5382 * @param {HTMLElement} element
5383 * @param {String} type
5384 * @param {Function} handler
5385 */
5386 on: function on(element, type, handler) {
5387 element.addEventListener(type, handler, false);
5388 },
5389
5390 /**
5391 * simple removeEventListener wrapper
5392 * @param {HTMLElement} element
5393 * @param {String} type
5394 * @param {Function} handler
5395 */
5396 off: function off(element, type, handler) {
5397 element.removeEventListener(type, handler, false);
5398 },
5399
5400 /**
5401 * forEach over arrays and objects
5402 * @param {Object|Array} obj
5403 * @param {Function} iterator
5404 * @param {any} iterator.item
5405 * @param {Number} iterator.index
5406 * @param {Object|Array} iterator.obj the source object
5407 * @param {Object} context value to use as `this` in the iterator
5408 */
5409 each: function each(obj, iterator, context) {
5410 var i, len;
5411
5412 // native forEach on arrays
5413 if ('forEach' in obj) {
5414 obj.forEach(iterator, context);
5415 // arrays
5416 } else if (obj.length !== undefined) {
5417 for (i = 0, len = obj.length; i < len; i++) {
5418 if (iterator.call(context, obj[i], i, obj) === false) {
5419 return;
5420 }
5421 }
5422 // objects
5423 } else {
5424 for (i in obj) {
5425 if (obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj) === false) {
5426 return;
5427 }
5428 }
5429 }
5430 },
5431
5432 /**
5433 * find if a string contains the string using indexOf
5434 * @param {String} src
5435 * @param {String} find
5436 * @return {Boolean} found
5437 */
5438 inStr: function inStr(src, find) {
5439 return src.indexOf(find) > -1;
5440 },
5441
5442 /**
5443 * find if a array contains the object using indexOf or a simple polyfill
5444 * @param {String} src
5445 * @param {String} find
5446 * @return {Boolean|Number} false when not found, or the index
5447 */
5448 inArray: function inArray(src, find) {
5449 if (src.indexOf) {
5450 var index = src.indexOf(find);
5451 return index === -1 ? false : index;
5452 } else {
5453 for (var i = 0, len = src.length; i < len; i++) {
5454 if (src[i] === find) {
5455 return i;
5456 }
5457 }
5458 return false;
5459 }
5460 },
5461
5462 /**
5463 * convert an array-like object (`arguments`, `touchlist`) to an array
5464 * @param {Object} obj
5465 * @return {Array}
5466 */
5467 toArray: function toArray(obj) {
5468 return Array.prototype.slice.call(obj, 0);
5469 },
5470
5471 /**
5472 * find if a node is in the given parent
5473 * @param {HTMLElement} node
5474 * @param {HTMLElement} parent
5475 * @return {Boolean} found
5476 */
5477 hasParent: function hasParent(node, parent) {
5478 while (node) {
5479 if (node == parent) {
5480 return true;
5481 }
5482 node = node.parentNode;
5483 }
5484 return false;
5485 },
5486
5487 /**
5488 * get the center of all the touches
5489 * @param {Array} touches
5490 * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties
5491 */
5492 getCenter: function getCenter(touches) {
5493 var pageX = [],
5494 pageY = [],
5495 clientX = [],
5496 clientY = [],
5497 min = Math.min,
5498 max = Math.max;
5499
5500 // no need to loop when only one touch
5501 if (touches.length === 1) {
5502 return {
5503 pageX: touches[0].pageX,
5504 pageY: touches[0].pageY,
5505 clientX: touches[0].clientX,
5506 clientY: touches[0].clientY
5507 };
5508 }
5509
5510 Utils.each(touches, function (touch) {
5511 pageX.push(touch.pageX);
5512 pageY.push(touch.pageY);
5513 clientX.push(touch.clientX);
5514 clientY.push(touch.clientY);
5515 });
5516
5517 return {
5518 pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2,
5519 pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2,
5520 clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2,
5521 clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2
5522 };
5523 },
5524
5525 /**
5526 * calculate the velocity between two points. unit is in px per ms.
5527 * @param {Number} deltaTime
5528 * @param {Number} deltaX
5529 * @param {Number} deltaY
5530 * @return {Object} velocity `x` and `y`
5531 */
5532 getVelocity: function getVelocity(deltaTime, deltaX, deltaY) {
5533 return {
5534 x: Math.abs(deltaX / deltaTime) || 0,
5535 y: Math.abs(deltaY / deltaTime) || 0
5536 };
5537 },
5538
5539 /**
5540 * calculate the angle between two coordinates
5541 * @param {Touch} touch1
5542 * @param {Touch} touch2
5543 * @return {Number} angle
5544 */
5545 getAngle: function getAngle(touch1, touch2) {
5546 var x = touch2.clientX - touch1.clientX,
5547 y = touch2.clientY - touch1.clientY;
5548
5549 return Math.atan2(y, x) * 180 / Math.PI;
5550 },
5551
5552 /**
5553 * do a small comparison to get the direction between two touches.
5554 * @param {Touch} touch1
5555 * @param {Touch} touch2
5556 * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN`
5557 */
5558 getDirection: function getDirection(touch1, touch2) {
5559 var x = Math.abs(touch1.clientX - touch2.clientX),
5560 y = Math.abs(touch1.clientY - touch2.clientY);
5561
5562 if (x >= y) {
5563 return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
5564 }
5565 return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN;
5566 },
5567
5568 /**
5569 * calculate the distance between two touches
5570 * @param {Touch}touch1
5571 * @param {Touch} touch2
5572 * @return {Number} distance
5573 */
5574 getDistance: function getDistance(touch1, touch2) {
5575 var x = touch2.clientX - touch1.clientX,
5576 y = touch2.clientY - touch1.clientY;
5577
5578 return Math.sqrt(x * x + y * y);
5579 },
5580
5581 /**
5582 * calculate the scale factor between two touchLists
5583 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
5584 * @param {Array} start array of touches
5585 * @param {Array} end array of touches
5586 * @return {Number} scale
5587 */
5588 getScale: function getScale(start, end) {
5589 // need two fingers...
5590 if (start.length >= 2 && end.length >= 2) {
5591 return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]);
5592 }
5593 return 1;
5594 },
5595
5596 /**
5597 * calculate the rotation degrees between two touchLists
5598 * @param {Array} start array of touches
5599 * @param {Array} end array of touches
5600 * @return {Number} rotation
5601 */
5602 getRotation: function getRotation(start, end) {
5603 // need two fingers
5604 if (start.length >= 2 && end.length >= 2) {
5605 return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]);
5606 }
5607 return 0;
5608 },
5609
5610 /**
5611 * find out if the direction is vertical *
5612 * @param {String} direction matches `DIRECTION_UP|DOWN`
5613 * @return {Boolean} is_vertical
5614 */
5615 isVertical: function isVertical(direction) {
5616 return direction == DIRECTION_UP || direction == DIRECTION_DOWN;
5617 },
5618
5619 /**
5620 * set css properties with their prefixes
5621 * @param {HTMLElement} element
5622 * @param {String} prop
5623 * @param {String} value
5624 * @param {Boolean} [toggle=true]
5625 * @return {Boolean}
5626 */
5627 setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) {
5628 var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms'];
5629 prop = Utils.toCamelCase(prop);
5630
5631 for (var i = 0; i < prefixes.length; i++) {
5632 var p = prop;
5633 // prefixes
5634 if (prefixes[i]) {
5635 p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1);
5636 }
5637
5638 // test the style
5639 if (p in element.style) {
5640 element.style[p] = (toggle === null || toggle) && value || '';
5641 break;
5642 }
5643 }
5644 },
5645
5646 /**
5647 * toggle browser default behavior by setting css properties.
5648 * `userSelect='none'` also sets `element.onselectstart` to false
5649 * `userDrag='none'` also sets `element.ondragstart` to false
5650 *
5651 * @param {HtmlElement} element
5652 * @param {Object} props
5653 * @param {Boolean} [toggle=true]
5654 */
5655 toggleBehavior: function toggleBehavior(element, props, toggle) {
5656 if (!props || !element || !element.style) {
5657 return;
5658 }
5659
5660 // set the css properties
5661 Utils.each(props, function (value, prop) {
5662 Utils.setPrefixedCss(element, prop, value, toggle);
5663 });
5664
5665 var falseFn = toggle && function () {
5666 return false;
5667 };
5668
5669 // also the disable onselectstart
5670 if (props.userSelect == 'none') {
5671 element.onselectstart = falseFn;
5672 }
5673 // and disable ondragstart
5674 if (props.userDrag == 'none') {
5675 element.ondragstart = falseFn;
5676 }
5677 },
5678
5679 /**
5680 * convert a string with underscores to camelCase
5681 * so prevent_default becomes preventDefault
5682 * @param {String} str
5683 * @return {String} camelCaseStr
5684 */
5685 toCamelCase: function toCamelCase(str) {
5686 return str.replace(/[_-]([a-z])/g, function (s) {
5687 return s[1].toUpperCase();
5688 });
5689 }
5690};
5691
5692/**
5693 * @module GestureDetector
5694 */
5695/**
5696 * @class Event
5697 * @static
5698 */
5699Event$1 = GestureDetector.event = {
5700 /**
5701 * when touch events have been fired, this is true
5702 * this is used to stop mouse events
5703 * @property prevent_mouseevents
5704 * @private
5705 * @type {Boolean}
5706 */
5707 preventMouseEvents: false,
5708
5709 /**
5710 * if EVENT_START has been fired
5711 * @property started
5712 * @private
5713 * @type {Boolean}
5714 */
5715 started: false,
5716
5717 /**
5718 * when the mouse is hold down, this is true
5719 * @property should_detect
5720 * @private
5721 * @type {Boolean}
5722 */
5723 shouldDetect: false,
5724
5725 /**
5726 * simple event binder with a hook and support for multiple types
5727 * @param {HTMLElement} element
5728 * @param {String} type
5729 * @param {Function} handler
5730 * @param {Function} [hook]
5731 * @param {Object} hook.type
5732 */
5733 on: function on(element, type, handler, hook) {
5734 var types = type.split(' ');
5735 Utils.each(types, function (type) {
5736 Utils.on(element, type, handler);
5737 hook && hook(type);
5738 });
5739 },
5740
5741 /**
5742 * simple event unbinder with a hook and support for multiple types
5743 * @param {HTMLElement} element
5744 * @param {String} type
5745 * @param {Function} handler
5746 * @param {Function} [hook]
5747 * @param {Object} hook.type
5748 */
5749 off: function off(element, type, handler, hook) {
5750 var types = type.split(' ');
5751 Utils.each(types, function (type) {
5752 Utils.off(element, type, handler);
5753 hook && hook(type);
5754 });
5755 },
5756
5757 /**
5758 * the core touch event handler.
5759 * this finds out if we should to detect gestures
5760 * @param {HTMLElement} element
5761 * @param {String} eventType matches `EVENT_START|MOVE|END`
5762 * @param {Function} handler
5763 * @return onTouchHandler {Function} the core event handler
5764 */
5765 onTouch: function onTouch(element, eventType, handler) {
5766 var self = this;
5767
5768 var onTouchHandler = function onTouchHandler(ev) {
5769 var srcType = ev.type.toLowerCase(),
5770 isPointer = GestureDetector.HAS_POINTEREVENTS,
5771 isMouse = Utils.inStr(srcType, 'mouse'),
5772 triggerType;
5773
5774 // if we are in a mouseevent, but there has been a touchevent triggered in this session
5775 // we want to do nothing. simply break out of the event.
5776 if (isMouse && self.preventMouseEvents) {
5777 return;
5778
5779 // mousebutton must be down
5780 } else if (isMouse && eventType == EVENT_START && ev.button === 0) {
5781 self.preventMouseEvents = false;
5782 self.shouldDetect = true;
5783 } else if (isPointer && eventType == EVENT_START) {
5784 self.shouldDetect = ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev);
5785 // just a valid start event, but no mouse
5786 } else if (!isMouse && eventType == EVENT_START) {
5787 self.preventMouseEvents = true;
5788 self.shouldDetect = true;
5789 }
5790
5791 // update the pointer event before entering the detection
5792 if (isPointer && eventType != EVENT_END) {
5793 PointerEvent.updatePointer(eventType, ev);
5794 }
5795
5796 // we are in a touch/down state, so allowed detection of gestures
5797 if (self.shouldDetect) {
5798 triggerType = self.doDetect.call(self, ev, eventType, element, handler);
5799 }
5800
5801 // ...and we are done with the detection
5802 // so reset everything to start each detection totally fresh
5803 if (triggerType == EVENT_END) {
5804 self.preventMouseEvents = false;
5805 self.shouldDetect = false;
5806 PointerEvent.reset();
5807 // update the pointerevent object after the detection
5808 }
5809
5810 if (isPointer && eventType == EVENT_END) {
5811 PointerEvent.updatePointer(eventType, ev);
5812 }
5813 };
5814
5815 this.on(element, EVENT_TYPES[eventType], onTouchHandler);
5816 return onTouchHandler;
5817 },
5818
5819 /**
5820 * the core detection method
5821 * this finds out what GestureDetector-touch-events to trigger
5822 * @param {Object} ev
5823 * @param {String} eventType matches `EVENT_START|MOVE|END`
5824 * @param {HTMLElement} element
5825 * @param {Function} handler
5826 * @return {String} triggerType matches `EVENT_START|MOVE|END`
5827 */
5828 doDetect: function doDetect(ev, eventType, element, handler) {
5829 var touchList = this.getTouchList(ev, eventType);
5830 var touchListLength = touchList.length;
5831 var triggerType = eventType;
5832 var triggerChange = touchList.trigger; // used by fakeMultitouch plugin
5833 var changedLength = touchListLength;
5834
5835 // at each touchstart-like event we want also want to trigger a TOUCH event...
5836 if (eventType == EVENT_START) {
5837 triggerChange = EVENT_TOUCH;
5838 // ...the same for a touchend-like event
5839 } else if (eventType == EVENT_END) {
5840 triggerChange = EVENT_RELEASE;
5841
5842 // keep track of how many touches have been removed
5843 changedLength = touchList.length - (ev.changedTouches ? ev.changedTouches.length : 1);
5844 }
5845
5846 // after there are still touches on the screen,
5847 // we just want to trigger a MOVE event. so change the START or END to a MOVE
5848 // but only after detection has been started, the first time we actually want a START
5849 if (changedLength > 0 && this.started) {
5850 triggerType = EVENT_MOVE;
5851 }
5852
5853 // detection has been started, we keep track of this, see above
5854 this.started = true;
5855
5856 // generate some event data, some basic information
5857 var evData = this.collectEventData(element, triggerType, touchList, ev);
5858
5859 // trigger the triggerType event before the change (TOUCH, RELEASE) events
5860 // but the END event should be at last
5861 if (eventType != EVENT_END) {
5862 handler.call(Detection, evData);
5863 }
5864
5865 // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed
5866 if (triggerChange) {
5867 evData.changedLength = changedLength;
5868 evData.eventType = triggerChange;
5869
5870 handler.call(Detection, evData);
5871
5872 evData.eventType = triggerType;
5873 delete evData.changedLength;
5874 }
5875
5876 // trigger the END event
5877 if (triggerType == EVENT_END) {
5878 handler.call(Detection, evData);
5879
5880 // ...and we are done with the detection
5881 // so reset everything to start each detection totally fresh
5882 this.started = false;
5883 }
5884
5885 return triggerType;
5886 },
5887
5888 /**
5889 * we have different events for each device/browser
5890 * determine what we need and set them in the EVENT_TYPES constant
5891 * the `onTouch` method is bind to these properties.
5892 * @return {Object} events
5893 */
5894 determineEventTypes: function determineEventTypes() {
5895 var types;
5896 if (GestureDetector.HAS_POINTEREVENTS) {
5897 if (window.PointerEvent) {
5898 types = ['pointerdown', 'pointermove', 'pointerup pointercancel lostpointercapture'];
5899 } else {
5900 types = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp MSPointerCancel MSLostPointerCapture'];
5901 }
5902 } else if (GestureDetector.NO_MOUSEEVENTS) {
5903 types = ['touchstart', 'touchmove', 'touchend touchcancel'];
5904 } else {
5905 types = ['touchstart mousedown', 'touchmove mousemove', 'touchend touchcancel mouseup'];
5906 }
5907
5908 EVENT_TYPES[EVENT_START] = types[0];
5909 EVENT_TYPES[EVENT_MOVE] = types[1];
5910 EVENT_TYPES[EVENT_END] = types[2];
5911 return EVENT_TYPES;
5912 },
5913
5914 /**
5915 * create touchList depending on the event
5916 * @param {Object} ev
5917 * @param {String} eventType
5918 * @return {Array} touches
5919 */
5920 getTouchList: function getTouchList(ev, eventType) {
5921 // get the fake pointerEvent touchlist
5922 if (GestureDetector.HAS_POINTEREVENTS) {
5923 return PointerEvent.getTouchList();
5924 }
5925
5926 // get the touchlist
5927 if (ev.touches) {
5928 if (eventType == EVENT_MOVE) {
5929 return ev.touches;
5930 }
5931
5932 var identifiers = [];
5933 var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches));
5934 var touchList = [];
5935
5936 Utils.each(concat, function (touch) {
5937 if (Utils.inArray(identifiers, touch.identifier) === false) {
5938 touchList.push(touch);
5939 }
5940 identifiers.push(touch.identifier);
5941 });
5942
5943 return touchList;
5944 }
5945
5946 // make fake touchList from mouse position
5947 ev.identifier = 1;
5948 return [ev];
5949 },
5950
5951 /**
5952 * collect basic event data
5953 * @param {HTMLElement} element
5954 * @param {String} eventType matches `EVENT_START|MOVE|END`
5955 * @param {Array} touches
5956 * @param {Object} ev
5957 * @return {Object} ev
5958 */
5959 collectEventData: function collectEventData(element, eventType, touches, ev) {
5960 // find out pointerType
5961 var pointerType = POINTER_TOUCH;
5962 if (Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) {
5963 pointerType = POINTER_MOUSE;
5964 } else if (PointerEvent.matchType(POINTER_PEN, ev)) {
5965 pointerType = POINTER_PEN;
5966 }
5967
5968 return {
5969 center: Utils.getCenter(touches),
5970 timeStamp: Date.now(),
5971 target: ev.target,
5972 touches: touches,
5973 eventType: eventType,
5974 pointerType: pointerType,
5975 srcEvent: ev,
5976
5977 /**
5978 * prevent the browser default actions
5979 * mostly used to disable scrolling of the browser
5980 */
5981 preventDefault: function preventDefault() {
5982 var srcEvent = this.srcEvent;
5983 srcEvent.preventManipulation && srcEvent.preventManipulation();
5984 srcEvent.preventDefault && srcEvent.preventDefault();
5985 },
5986
5987 /**
5988 * stop bubbling the event up to its parents
5989 */
5990 stopPropagation: function stopPropagation() {
5991 this.srcEvent.stopPropagation();
5992 },
5993
5994 /**
5995 * immediately stop gesture detection
5996 * might be useful after a swipe was detected
5997 * @return {*}
5998 */
5999 stopDetect: function stopDetect() {
6000 return Detection.stopDetect();
6001 }
6002 };
6003 }
6004};
6005
6006/**
6007 * @module GestureDetector
6008 *
6009 * @class PointerEvent
6010 * @static
6011 */
6012PointerEvent = GestureDetector.PointerEvent = {
6013 /**
6014 * holds all pointers, by `identifier`
6015 * @property pointers
6016 * @type {Object}
6017 */
6018 pointers: {},
6019
6020 /**
6021 * get the pointers as an array
6022 * @return {Array} touchlist
6023 */
6024 getTouchList: function getTouchList() {
6025 var touchlist = [];
6026 // we can use forEach since pointerEvents only is in IE10
6027 Utils.each(this.pointers, function (pointer) {
6028 touchlist.push(pointer);
6029 });
6030 return touchlist;
6031 },
6032
6033 /**
6034 * update the position of a pointer
6035 * @param {String} eventType matches `EVENT_START|MOVE|END`
6036 * @param {Object} pointerEvent
6037 */
6038 updatePointer: function updatePointer(eventType, pointerEvent) {
6039 if (eventType == EVENT_END || eventType != EVENT_END && pointerEvent.buttons !== 1) {
6040 delete this.pointers[pointerEvent.pointerId];
6041 } else {
6042 pointerEvent.identifier = pointerEvent.pointerId;
6043 this.pointers[pointerEvent.pointerId] = pointerEvent;
6044 }
6045 },
6046
6047 /**
6048 * check if ev matches pointertype
6049 * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN`
6050 * @param {PointerEvent} ev
6051 */
6052 matchType: function matchType(pointerType, ev) {
6053 if (!ev.pointerType) {
6054 return false;
6055 }
6056
6057 var pt = ev.pointerType,
6058 types = {};
6059
6060 types[POINTER_MOUSE] = pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE);
6061 types[POINTER_TOUCH] = pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH);
6062 types[POINTER_PEN] = pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN);
6063 return types[pointerType];
6064 },
6065
6066 /**
6067 * reset the stored pointers
6068 */
6069 reset: function resetList() {
6070 this.pointers = {};
6071 }
6072};
6073
6074/**
6075 * @module GestureDetector
6076 *
6077 * @class Detection
6078 * @static
6079 */
6080Detection = GestureDetector.detection = {
6081 // contains all registered GestureDetector.gestures in the correct order
6082 gestures: [],
6083
6084 // data of the current GestureDetector.gesture detection session
6085 current: null,
6086
6087 // the previous GestureDetector.gesture session data
6088 // is a full clone of the previous gesture.current object
6089 previous: null,
6090
6091 // when this becomes true, no gestures are fired
6092 stopped: false,
6093
6094 /**
6095 * start GestureDetector.gesture detection
6096 * @param {GestureDetector.Instance} inst
6097 * @param {Object} eventData
6098 */
6099 startDetect: function startDetect(inst, eventData) {
6100 // already busy with a GestureDetector.gesture detection on an element
6101 if (this.current) {
6102 return;
6103 }
6104
6105 this.stopped = false;
6106
6107 // holds current session
6108 this.current = {
6109 inst: inst, // reference to GestureDetectorInstance we're working for
6110 startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc
6111 lastEvent: false, // last eventData
6112 lastCalcEvent: false, // last eventData for calculations.
6113 futureCalcEvent: false, // last eventData for calculations.
6114 lastCalcData: {}, // last lastCalcData
6115 name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc
6116 };
6117
6118 this.detect(eventData);
6119 },
6120
6121 /**
6122 * GestureDetector.gesture detection
6123 * @param {Object} eventData
6124 * @return {any}
6125 */
6126 detect: function detect(eventData) {
6127 if (!this.current || this.stopped) {
6128 return;
6129 }
6130
6131 // extend event data with calculations about scale, distance etc
6132 eventData = this.extendEventData(eventData);
6133
6134 // GestureDetector instance and instance options
6135 var inst = this.current.inst,
6136 instOptions = inst.options;
6137
6138 // call GestureDetector.gesture handlers
6139 Utils.each(this.gestures, function triggerGesture(gesture) {
6140 // only when the instance options have enabled this gesture
6141 if (!this.stopped && inst.enabled && instOptions[gesture.name]) {
6142 gesture.handler.call(gesture, eventData, inst);
6143 }
6144 }, this);
6145
6146 // store as previous event event
6147 if (this.current) {
6148 this.current.lastEvent = eventData;
6149 }
6150
6151 if (eventData.eventType == EVENT_END) {
6152 this.stopDetect();
6153 }
6154
6155 return eventData; // eslint-disable-line consistent-return
6156 },
6157
6158 /**
6159 * clear the GestureDetector.gesture vars
6160 * this is called on endDetect, but can also be used when a final GestureDetector.gesture has been detected
6161 * to stop other GestureDetector.gestures from being fired
6162 */
6163 stopDetect: function stopDetect() {
6164 // clone current data to the store as the previous gesture
6165 // used for the double tap gesture, since this is an other gesture detect session
6166 this.previous = Utils.extend({}, this.current);
6167
6168 // reset the current
6169 this.current = null;
6170 this.stopped = true;
6171 },
6172
6173 /**
6174 * calculate velocity, angle and direction
6175 * @param {Object} ev
6176 * @param {Object} center
6177 * @param {Number} deltaTime
6178 * @param {Number} deltaX
6179 * @param {Number} deltaY
6180 */
6181 getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) {
6182 var cur = this.current,
6183 recalc = false,
6184 calcEv = cur.lastCalcEvent,
6185 calcData = cur.lastCalcData;
6186
6187 if (calcEv && ev.timeStamp - calcEv.timeStamp > GestureDetector.CALCULATE_INTERVAL) {
6188 center = calcEv.center;
6189 deltaTime = ev.timeStamp - calcEv.timeStamp;
6190 deltaX = ev.center.clientX - calcEv.center.clientX;
6191 deltaY = ev.center.clientY - calcEv.center.clientY;
6192 recalc = true;
6193 }
6194
6195 if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
6196 cur.futureCalcEvent = ev;
6197 }
6198
6199 if (!cur.lastCalcEvent || recalc) {
6200 calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY);
6201 calcData.angle = Utils.getAngle(center, ev.center);
6202 calcData.direction = Utils.getDirection(center, ev.center);
6203
6204 cur.lastCalcEvent = cur.futureCalcEvent || ev;
6205 cur.futureCalcEvent = ev;
6206 }
6207
6208 ev.velocityX = calcData.velocity.x;
6209 ev.velocityY = calcData.velocity.y;
6210 ev.interimAngle = calcData.angle;
6211 ev.interimDirection = calcData.direction;
6212 },
6213
6214 /**
6215 * extend eventData for GestureDetector.gestures
6216 * @param {Object} ev
6217 * @return {Object} ev
6218 */
6219 extendEventData: function extendEventData(ev) {
6220 var cur = this.current,
6221 startEv = cur.startEvent,
6222 lastEv = cur.lastEvent || startEv;
6223
6224 // update the start touchlist to calculate the scale/rotation
6225 if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
6226 startEv.touches = [];
6227 Utils.each(ev.touches, function (touch) {
6228 startEv.touches.push({
6229 clientX: touch.clientX,
6230 clientY: touch.clientY
6231 });
6232 });
6233 }
6234
6235 var deltaTime = ev.timeStamp - startEv.timeStamp,
6236 deltaX = ev.center.clientX - startEv.center.clientX,
6237 deltaY = ev.center.clientY - startEv.center.clientY;
6238
6239 this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY);
6240
6241 Utils.extend(ev, {
6242 startEvent: startEv,
6243
6244 deltaTime: deltaTime,
6245 deltaX: deltaX,
6246 deltaY: deltaY,
6247
6248 distance: Utils.getDistance(startEv.center, ev.center),
6249 angle: Utils.getAngle(startEv.center, ev.center),
6250 direction: Utils.getDirection(startEv.center, ev.center),
6251 scale: Utils.getScale(startEv.touches, ev.touches),
6252 rotation: Utils.getRotation(startEv.touches, ev.touches)
6253 });
6254
6255 return ev;
6256 },
6257
6258 /**
6259 * register new gesture
6260 * @param {Object} gesture object, see `gestures/` for documentation
6261 * @return {Array} gestures
6262 */
6263 register: function register(gesture) {
6264 // add an enable gesture options if there is no given
6265 var options = gesture.defaults || {};
6266 if (options[gesture.name] === undefined) {
6267 options[gesture.name] = true;
6268 }
6269
6270 // extend GestureDetector default options with the GestureDetector.gesture options
6271 Utils.extend(GestureDetector.defaults, options, true);
6272
6273 // set its index
6274 gesture.index = gesture.index || 1000;
6275
6276 // add GestureDetector.gesture to the list
6277 this.gestures.push(gesture);
6278
6279 // sort the list by index
6280 this.gestures.sort(function (a, b) {
6281 if (a.index < b.index) {
6282 return -1;
6283 }
6284 if (a.index > b.index) {
6285 return 1;
6286 }
6287 return 0;
6288 });
6289
6290 return this.gestures;
6291 }
6292};
6293
6294/**
6295 * @module GestureDetector
6296 */
6297
6298/**
6299 * create new GestureDetector instance
6300 * all methods should return the instance itself, so it is chainable.
6301 *
6302 * @class Instance
6303 * @constructor
6304 * @param {HTMLElement} element
6305 * @param {Object} [options={}] options are merged with `GestureDetector.defaults`
6306 * @return {GestureDetector.Instance}
6307 */
6308GestureDetector.Instance = function (element, options) {
6309 var self = this;
6310
6311 // setup GestureDetectorJS window events and register all gestures
6312 // this also sets up the default options
6313 setup();
6314
6315 /**
6316 * @property element
6317 * @type {HTMLElement}
6318 */
6319 this.element = element;
6320
6321 /**
6322 * @property enabled
6323 * @type {Boolean}
6324 * @protected
6325 */
6326 this.enabled = true;
6327
6328 /**
6329 * options, merged with the defaults
6330 * options with an _ are converted to camelCase
6331 * @property options
6332 * @type {Object}
6333 */
6334 Utils.each(options, function (value, name) {
6335 delete options[name];
6336 options[Utils.toCamelCase(name)] = value;
6337 });
6338
6339 this.options = Utils.extend(Utils.extend({}, GestureDetector.defaults), options || {});
6340
6341 // add some css to the element to prevent the browser from doing its native behavior
6342 if (this.options.behavior) {
6343 Utils.toggleBehavior(this.element, this.options.behavior, true);
6344 }
6345
6346 /**
6347 * event start handler on the element to start the detection
6348 * @property eventStartHandler
6349 * @type {Object}
6350 */
6351 this.eventStartHandler = Event$1.onTouch(element, EVENT_START, function (ev) {
6352 if (self.enabled && ev.eventType == EVENT_START) {
6353 Detection.startDetect(self, ev);
6354 } else if (ev.eventType == EVENT_TOUCH) {
6355 Detection.detect(ev);
6356 }
6357 });
6358
6359 /**
6360 * keep a list of user event handlers which needs to be removed when calling 'dispose'
6361 * @property eventHandlers
6362 * @type {Array}
6363 */
6364 this.eventHandlers = [];
6365};
6366
6367GestureDetector.Instance.prototype = {
6368 /**
6369 * @method on
6370 * @signature on(gestures, handler)
6371 * @description
6372 * [en]Adds an event handler for a gesture. Available gestures are: drag, dragleft, dragright, dragup, dragdown, hold, release, swipe, swipeleft, swiperight, swipeup, swipedown, tap, doubletap, touch, transform, pinch, pinchin, pinchout and rotate. [/en]
6373 * [ja]ジェスチャに対するイベントハンドラを追加します。指定できるジェスチャ名は、drag dragleft dragright dragup dragdown hold release swipe swipeleft swiperight swipeup swipedown tap doubletap touch transform pinch pinchin pinchout rotate です。[/ja]
6374 * @param {String} gestures
6375 * [en]A space separated list of gestures.[/en]
6376 * [ja]検知するジェスチャ名を指定します。スペースで複数指定することができます。[/ja]
6377 * @param {Function} handler
6378 * [en]An event handling function.[/en]
6379 * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja]
6380 */
6381 on: function onEvent(gestures, handler) {
6382 var self = this;
6383 Event$1.on(self.element, gestures, handler, function (type) {
6384 self.eventHandlers.push({ gesture: type, handler: handler });
6385 });
6386 return self;
6387 },
6388
6389 /**
6390 * @method off
6391 * @signature off(gestures, handler)
6392 * @description
6393 * [en]Remove an event listener.[/en]
6394 * [ja]イベントリスナーを削除します。[/ja]
6395 * @param {String} gestures
6396 * [en]A space separated list of gestures.[/en]
6397 * [ja]ジェスチャ名を指定します。スペースで複数指定することができます。[/ja]
6398 * @param {Function} handler
6399 * [en]An event handling function.[/en]
6400 * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja]
6401 */
6402 off: function offEvent(gestures, handler) {
6403 var self = this;
6404
6405 Event$1.off(self.element, gestures, handler, function (type) {
6406 var index = Utils.inArray({ gesture: type, handler: handler });
6407 if (index !== false) {
6408 self.eventHandlers.splice(index, 1);
6409 }
6410 });
6411 return self;
6412 },
6413
6414 /**
6415 * trigger gesture event
6416 * @method trigger
6417 * @signature trigger(gesture, eventData)
6418 * @param {String} gesture
6419 * @param {Object} [eventData]
6420 */
6421 trigger: function triggerEvent(gesture, eventData) {
6422 // optional
6423 if (!eventData) {
6424 eventData = {};
6425 }
6426
6427 // create DOM event
6428 var event = GestureDetector.DOCUMENT.createEvent('Event');
6429 event.initEvent(gesture, true, true);
6430 event.gesture = eventData;
6431
6432 // trigger on the target if it is in the instance element,
6433 // this is for event delegation tricks
6434 var element = this.element;
6435 if (Utils.hasParent(eventData.target, element)) {
6436 element = eventData.target;
6437 }
6438
6439 element.dispatchEvent(event);
6440 return this;
6441 },
6442
6443 /**
6444 * @method enable
6445 * @signature enable(state)
6446 * @description
6447 * [en]Enable or disable gesture detection.[/en]
6448 * [ja]ジェスチャ検知を有効化/無効化します。[/ja]
6449 * @param {Boolean} state
6450 * [en]Specify if it should be enabled or not.[/en]
6451 * [ja]有効にするかどうかを指定します。[/ja]
6452 */
6453 enable: function enable(state) {
6454 this.enabled = state;
6455 return this;
6456 },
6457
6458 /**
6459 * @method dispose
6460 * @signature dispose()
6461 * @description
6462 * [en]Remove and destroy all event handlers for this instance.[/en]
6463 * [ja]このインスタンスでのジェスチャの検知や、イベントハンドラを全て解除して廃棄します。[/ja]
6464 */
6465 dispose: function dispose() {
6466 var i, eh;
6467
6468 // undo all changes made by stop_browser_behavior
6469 Utils.toggleBehavior(this.element, this.options.behavior, false);
6470
6471 // unbind all custom event handlers
6472 for (i = -1; eh = this.eventHandlers[++i];) {
6473 // eslint-disable-line no-cond-assign
6474 Utils.off(this.element, eh.gesture, eh.handler);
6475 }
6476
6477 this.eventHandlers = [];
6478
6479 // unbind the start event listener
6480 Event$1.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler);
6481
6482 return null;
6483 }
6484};
6485
6486/**
6487 * @module gestures
6488 */
6489/**
6490 * Move with x fingers (default 1) around on the page.
6491 * Preventing the default browser behavior is a good way to improve feel and working.
6492 * ````
6493 * GestureDetectortime.on("drag", function(ev) {
6494 * console.log(ev);
6495 * ev.gesture.preventDefault();
6496 * });
6497 * ````
6498 *
6499 * @class Drag
6500 * @static
6501 */
6502/**
6503 * @event drag
6504 * @param {Object} ev
6505 */
6506/**
6507 * @event dragstart
6508 * @param {Object} ev
6509 */
6510/**
6511 * @event dragend
6512 * @param {Object} ev
6513 */
6514/**
6515 * @event drapleft
6516 * @param {Object} ev
6517 */
6518/**
6519 * @event dragright
6520 * @param {Object} ev
6521 */
6522/**
6523 * @event dragup
6524 * @param {Object} ev
6525 */
6526/**
6527 * @event dragdown
6528 * @param {Object} ev
6529 */
6530
6531/**
6532 * @param {String} name
6533 */
6534(function (name) {
6535 var triggered = false;
6536
6537 function dragGesture(ev, inst) {
6538 var cur = Detection.current;
6539
6540 // max touches
6541 if (inst.options.dragMaxTouches > 0 && ev.touches.length > inst.options.dragMaxTouches) {
6542 return;
6543 }
6544
6545 switch (ev.eventType) {
6546 case EVENT_START:
6547 triggered = false;
6548 break;
6549
6550 case EVENT_MOVE:
6551 // when the distance we moved is too small we skip this gesture
6552 // or we can be already in dragging
6553 if (ev.distance < inst.options.dragMinDistance && cur.name != name) {
6554 return;
6555 }
6556
6557 var startCenter = cur.startEvent.center;
6558
6559 // we are dragging!
6560 if (cur.name != name) {
6561 cur.name = name;
6562 if (inst.options.dragDistanceCorrection && ev.distance > 0) {
6563 // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center.
6564 // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0.
6565 // It might be useful to save the original start point somewhere
6566 var factor = Math.abs(inst.options.dragMinDistance / ev.distance);
6567 startCenter.pageX += ev.deltaX * factor;
6568 startCenter.pageY += ev.deltaY * factor;
6569 startCenter.clientX += ev.deltaX * factor;
6570 startCenter.clientY += ev.deltaY * factor;
6571
6572 // recalculate event data using new start point
6573 ev = Detection.extendEventData(ev);
6574 }
6575 }
6576
6577 // lock drag to axis?
6578 if (cur.lastEvent.dragLockToAxis || inst.options.dragLockToAxis && inst.options.dragLockMinDistance <= ev.distance) {
6579 ev.dragLockToAxis = true;
6580 }
6581
6582 // keep direction on the axis that the drag gesture started on
6583 var lastDirection = cur.lastEvent.direction;
6584 if (ev.dragLockToAxis && lastDirection !== ev.direction) {
6585 if (Utils.isVertical(lastDirection)) {
6586 ev.direction = ev.deltaY < 0 ? DIRECTION_UP : DIRECTION_DOWN;
6587 } else {
6588 ev.direction = ev.deltaX < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
6589 }
6590 }
6591
6592 // first time, trigger dragstart event
6593 if (!triggered) {
6594 inst.trigger(name + 'start', ev);
6595 triggered = true;
6596 }
6597
6598 // trigger events
6599 inst.trigger(name, ev);
6600 inst.trigger(name + ev.direction, ev);
6601
6602 var isVertical = Utils.isVertical(ev.direction);
6603
6604 // block the browser events
6605 if (inst.options.dragBlockVertical && isVertical || inst.options.dragBlockHorizontal && !isVertical) {
6606 ev.preventDefault();
6607 }
6608 break;
6609
6610 case EVENT_RELEASE:
6611 if (triggered && ev.changedLength <= inst.options.dragMaxTouches) {
6612 inst.trigger(name + 'end', ev);
6613 triggered = false;
6614 }
6615 break;
6616
6617 case EVENT_END:
6618 triggered = false;
6619 break;
6620 }
6621 }
6622
6623 GestureDetector.gestures.Drag = {
6624 name: name,
6625 index: 50,
6626 handler: dragGesture,
6627 defaults: {
6628 /**
6629 * minimal movement that have to be made before the drag event gets triggered
6630 * @property dragMinDistance
6631 * @type {Number}
6632 * @default 10
6633 */
6634 dragMinDistance: 10,
6635
6636 /**
6637 * Set dragDistanceCorrection to true to make the starting point of the drag
6638 * be calculated from where the drag was triggered, not from where the touch started.
6639 * Useful to avoid a jerk-starting drag, which can make fine-adjustments
6640 * through dragging difficult, and be visually unappealing.
6641 * @property dragDistanceCorrection
6642 * @type {Boolean}
6643 * @default true
6644 */
6645 dragDistanceCorrection: true,
6646
6647 /**
6648 * set 0 for unlimited, but this can conflict with transform
6649 * @property dragMaxTouches
6650 * @type {Number}
6651 * @default 1
6652 */
6653 dragMaxTouches: 1,
6654
6655 /**
6656 * prevent default browser behavior when dragging occurs
6657 * be careful with it, it makes the element a blocking element
6658 * when you are using the drag gesture, it is a good practice to set this true
6659 * @property dragBlockHorizontal
6660 * @type {Boolean}
6661 * @default false
6662 */
6663 dragBlockHorizontal: false,
6664
6665 /**
6666 * same as `dragBlockHorizontal`, but for vertical movement
6667 * @property dragBlockVertical
6668 * @type {Boolean}
6669 * @default false
6670 */
6671 dragBlockVertical: false,
6672
6673 /**
6674 * dragLockToAxis keeps the drag gesture on the axis that it started on,
6675 * It disallows vertical directions if the initial direction was horizontal, and vice versa.
6676 * @property dragLockToAxis
6677 * @type {Boolean}
6678 * @default false
6679 */
6680 dragLockToAxis: false,
6681
6682 /**
6683 * drag lock only kicks in when distance > dragLockMinDistance
6684 * This way, locking occurs only when the distance has become large enough to reliably determine the direction
6685 * @property dragLockMinDistance
6686 * @type {Number}
6687 * @default 25
6688 */
6689 dragLockMinDistance: 25
6690 }
6691 };
6692})('drag');
6693
6694/**
6695 * @module gestures
6696 */
6697/**
6698 * trigger a simple gesture event, so you can do anything in your handler.
6699 * only usable if you know what your doing...
6700 *
6701 * @class Gesture
6702 * @static
6703 */
6704/**
6705 * @event gesture
6706 * @param {Object} ev
6707 */
6708GestureDetector.gestures.Gesture = {
6709 name: 'gesture',
6710 index: 1337,
6711 handler: function releaseGesture(ev, inst) {
6712 inst.trigger(this.name, ev);
6713 }
6714};
6715
6716/**
6717 * @module gestures
6718 */
6719/**
6720 * Touch stays at the same place for x time
6721 *
6722 * @class Hold
6723 * @static
6724 */
6725/**
6726 * @event hold
6727 * @param {Object} ev
6728 */
6729
6730/**
6731 * @param {String} name
6732 */
6733(function (name) {
6734 var timer;
6735
6736 function holdGesture(ev, inst) {
6737 var options = inst.options,
6738 current = Detection.current;
6739
6740 switch (ev.eventType) {
6741 case EVENT_START:
6742 clearTimeout(timer);
6743
6744 // set the gesture so we can check in the timeout if it still is
6745 current.name = name;
6746
6747 // set timer and if after the timeout it still is hold,
6748 // we trigger the hold event
6749 timer = setTimeout(function () {
6750 if (current && current.name == name) {
6751 inst.trigger(name, ev);
6752 }
6753 }, options.holdTimeout);
6754 break;
6755
6756 case EVENT_MOVE:
6757 if (ev.distance > options.holdThreshold) {
6758 clearTimeout(timer);
6759 }
6760 break;
6761
6762 case EVENT_RELEASE:
6763 clearTimeout(timer);
6764 break;
6765 }
6766 }
6767
6768 GestureDetector.gestures.Hold = {
6769 name: name,
6770 index: 10,
6771 defaults: {
6772 /**
6773 * @property holdTimeout
6774 * @type {Number}
6775 * @default 500
6776 */
6777 holdTimeout: 500,
6778
6779 /**
6780 * movement allowed while holding
6781 * @property holdThreshold
6782 * @type {Number}
6783 * @default 2
6784 */
6785 holdThreshold: 2
6786 },
6787 handler: holdGesture
6788 };
6789})('hold');
6790
6791/**
6792 * @module gestures
6793 */
6794/**
6795 * when a touch is being released from the page
6796 *
6797 * @class Release
6798 * @static
6799 */
6800/**
6801 * @event release
6802 * @param {Object} ev
6803 */
6804GestureDetector.gestures.Release = {
6805 name: 'release',
6806 index: Infinity,
6807 handler: function releaseGesture(ev, inst) {
6808 if (ev.eventType == EVENT_RELEASE) {
6809 inst.trigger(this.name, ev);
6810 }
6811 }
6812};
6813
6814/**
6815 * @module gestures
6816 */
6817/**
6818 * triggers swipe events when the end velocity is above the threshold
6819 * for best usage, set `preventDefault` (on the drag gesture) to `true`
6820 * ````
6821 * GestureDetectortime.on("dragleft swipeleft", function(ev) {
6822 * console.log(ev);
6823 * ev.gesture.preventDefault();
6824 * });
6825 * ````
6826 *
6827 * @class Swipe
6828 * @static
6829 */
6830/**
6831 * @event swipe
6832 * @param {Object} ev
6833 */
6834/**
6835 * @event swipeleft
6836 * @param {Object} ev
6837 */
6838/**
6839 * @event swiperight
6840 * @param {Object} ev
6841 */
6842/**
6843 * @event swipeup
6844 * @param {Object} ev
6845 */
6846/**
6847 * @event swipedown
6848 * @param {Object} ev
6849 */
6850GestureDetector.gestures.Swipe = {
6851 name: 'swipe',
6852 index: 40,
6853 defaults: {
6854 /**
6855 * @property swipeMinTouches
6856 * @type {Number}
6857 * @default 1
6858 */
6859 swipeMinTouches: 1,
6860
6861 /**
6862 * @property swipeMaxTouches
6863 * @type {Number}
6864 * @default 1
6865 */
6866 swipeMaxTouches: 1,
6867
6868 /**
6869 * horizontal swipe velocity
6870 * @property swipeVelocityX
6871 * @type {Number}
6872 * @default 0.6
6873 */
6874 swipeVelocityX: 0.6,
6875
6876 /**
6877 * vertical swipe velocity
6878 * @property swipeVelocityY
6879 * @type {Number}
6880 * @default 0.6
6881 */
6882 swipeVelocityY: 0.6
6883 },
6884
6885 handler: function swipeGesture(ev, inst) {
6886 if (ev.eventType == EVENT_RELEASE) {
6887 var touches = ev.touches.length,
6888 options = inst.options;
6889
6890 // max touches
6891 if (touches < options.swipeMinTouches || touches > options.swipeMaxTouches) {
6892 return;
6893 }
6894
6895 // when the distance we moved is too small we skip this gesture
6896 // or we can be already in dragging
6897 if (ev.velocityX > options.swipeVelocityX || ev.velocityY > options.swipeVelocityY) {
6898 // trigger swipe events
6899 inst.trigger(this.name, ev);
6900 inst.trigger(this.name + ev.direction, ev);
6901 }
6902 }
6903 }
6904};
6905
6906/**
6907 * @module gestures
6908 */
6909/**
6910 * Single tap and a double tap on a place
6911 *
6912 * @class Tap
6913 * @static
6914 */
6915/**
6916 * @event tap
6917 * @param {Object} ev
6918 */
6919/**
6920 * @event doubletap
6921 * @param {Object} ev
6922 */
6923
6924/**
6925 * @param {String} name
6926 */
6927(function (name) {
6928 var hasMoved = false;
6929
6930 function tapGesture(ev, inst) {
6931 var options = inst.options,
6932 current = Detection.current,
6933 prev = Detection.previous,
6934 sincePrev,
6935 didDoubleTap;
6936
6937 switch (ev.eventType) {
6938 case EVENT_START:
6939 hasMoved = false;
6940 break;
6941
6942 case EVENT_MOVE:
6943 hasMoved = hasMoved || ev.distance > options.tapMaxDistance;
6944 break;
6945
6946 case EVENT_END:
6947 if (!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) {
6948 // previous gesture, for the double tap since these are two different gesture detections
6949 sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp;
6950 didDoubleTap = false;
6951
6952 // check if double tap
6953 if (prev && prev.name == name && sincePrev && sincePrev < options.doubleTapInterval && ev.distance < options.doubleTapDistance) {
6954 inst.trigger('doubletap', ev);
6955 didDoubleTap = true;
6956 }
6957
6958 // do a single tap
6959 if (!didDoubleTap || options.tapAlways) {
6960 current.name = name;
6961 inst.trigger(current.name, ev);
6962 }
6963 }
6964 break;
6965 }
6966 }
6967
6968 GestureDetector.gestures.Tap = {
6969 name: name,
6970 index: 100,
6971 handler: tapGesture,
6972 defaults: {
6973 /**
6974 * max time of a tap, this is for the slow tappers
6975 * @property tapMaxTime
6976 * @type {Number}
6977 * @default 250
6978 */
6979 tapMaxTime: 250,
6980
6981 /**
6982 * max distance of movement of a tap, this is for the slow tappers
6983 * @property tapMaxDistance
6984 * @type {Number}
6985 * @default 10
6986 */
6987 tapMaxDistance: 10,
6988
6989 /**
6990 * always trigger the `tap` event, even while double-tapping
6991 * @property tapAlways
6992 * @type {Boolean}
6993 * @default true
6994 */
6995 tapAlways: true,
6996
6997 /**
6998 * max distance between two taps
6999 * @property doubleTapDistance
7000 * @type {Number}
7001 * @default 20
7002 */
7003 doubleTapDistance: 20,
7004
7005 /**
7006 * max time between two taps
7007 * @property doubleTapInterval
7008 * @type {Number}
7009 * @default 300
7010 */
7011 doubleTapInterval: 300
7012 }
7013 };
7014})('tap');
7015
7016/**
7017 * @module gestures
7018 */
7019/**
7020 * when a touch is being touched at the page
7021 *
7022 * @class Touch
7023 * @static
7024 */
7025/**
7026 * @event touch
7027 * @param {Object} ev
7028 */
7029GestureDetector.gestures.Touch = {
7030 name: 'touch',
7031 index: -Infinity,
7032 defaults: {
7033 /**
7034 * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page,
7035 * but it improves gestures like transforming and dragging.
7036 * be careful with using this, it can be very annoying for users to be stuck on the page
7037 * @property preventDefault
7038 * @type {Boolean}
7039 * @default false
7040 */
7041 preventDefault: false,
7042
7043 /**
7044 * disable mouse events, so only touch (or pen!) input triggers events
7045 * @property preventMouse
7046 * @type {Boolean}
7047 * @default false
7048 */
7049 preventMouse: false
7050 },
7051 handler: function touchGesture(ev, inst) {
7052 if (inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) {
7053 ev.stopDetect();
7054 return;
7055 }
7056
7057 if (inst.options.preventDefault) {
7058 ev.preventDefault();
7059 }
7060
7061 if (ev.eventType == EVENT_TOUCH) {
7062 inst.trigger('touch', ev);
7063 }
7064 }
7065};
7066
7067/**
7068 * @module gestures
7069 */
7070/**
7071 * User want to scale or rotate with 2 fingers
7072 * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the
7073 * `preventDefault` option.
7074 *
7075 * @class Transform
7076 * @static
7077 */
7078/**
7079 * @event transform
7080 * @param {Object} ev
7081 */
7082/**
7083 * @event transformstart
7084 * @param {Object} ev
7085 */
7086/**
7087 * @event transformend
7088 * @param {Object} ev
7089 */
7090/**
7091 * @event pinchin
7092 * @param {Object} ev
7093 */
7094/**
7095 * @event pinchout
7096 * @param {Object} ev
7097 */
7098/**
7099 * @event rotate
7100 * @param {Object} ev
7101 */
7102
7103/**
7104 * @param {String} name
7105 */
7106(function (name) {
7107 var triggered = false;
7108
7109 function transformGesture(ev, inst) {
7110 switch (ev.eventType) {
7111 case EVENT_START:
7112 triggered = false;
7113 break;
7114
7115 case EVENT_MOVE:
7116 // at least multitouch
7117 if (ev.touches.length < 2) {
7118 return;
7119 }
7120
7121 var scaleThreshold = Math.abs(1 - ev.scale);
7122 var rotationThreshold = Math.abs(ev.rotation);
7123
7124 // when the distance we moved is too small we skip this gesture
7125 // or we can be already in dragging
7126 if (scaleThreshold < inst.options.transformMinScale && rotationThreshold < inst.options.transformMinRotation) {
7127 return;
7128 }
7129
7130 // we are transforming!
7131 Detection.current.name = name;
7132
7133 // first time, trigger dragstart event
7134 if (!triggered) {
7135 inst.trigger(name + 'start', ev);
7136 triggered = true;
7137 }
7138
7139 inst.trigger(name, ev); // basic transform event
7140
7141 // trigger rotate event
7142 if (rotationThreshold > inst.options.transformMinRotation) {
7143 inst.trigger('rotate', ev);
7144 }
7145
7146 // trigger pinch event
7147 if (scaleThreshold > inst.options.transformMinScale) {
7148 inst.trigger('pinch', ev);
7149 inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev);
7150 }
7151 break;
7152
7153 case EVENT_RELEASE:
7154 if (triggered && ev.changedLength < 2) {
7155 inst.trigger(name + 'end', ev);
7156 triggered = false;
7157 }
7158 break;
7159 }
7160 }
7161
7162 GestureDetector.gestures.Transform = {
7163 name: name,
7164 index: 45,
7165 defaults: {
7166 /**
7167 * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
7168 * @property transformMinScale
7169 * @type {Number}
7170 * @default 0.01
7171 */
7172 transformMinScale: 0.01,
7173
7174 /**
7175 * rotation in degrees
7176 * @property transformMinRotation
7177 * @type {Number}
7178 * @default 1
7179 */
7180 transformMinRotation: 1
7181 },
7182
7183 handler: transformGesture
7184 };
7185})('transform');
7186
7187/*
7188Copyright 2013-2015 ASIAL CORPORATION
7189
7190Licensed under the Apache License, Version 2.0 (the "License");
7191you may not use this file except in compliance with the License.
7192You may obtain a copy of the License at
7193
7194 http://www.apache.org/licenses/LICENSE-2.0
7195
7196Unless required by applicable law or agreed to in writing, software
7197distributed under the License is distributed on an "AS IS" BASIS,
7198WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7199See the License for the specific language governing permissions and
7200limitations under the License.
7201
7202*/
7203
7204/**
7205 * @object ons.platform
7206 * @category util
7207 * @description
7208 * [en]Utility methods to detect current platform.[/en]
7209 * [ja]現在実行されているプラットフォームを検知するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
7210 */
7211var Platform = function () {
7212
7213 /**
7214 * All elements will be rendered as if the app was running on this platform.
7215 * @type {String}
7216 */
7217 function Platform() {
7218 classCallCheck(this, Platform);
7219
7220 this._renderPlatform = null;
7221 }
7222
7223 /**
7224 * @method select
7225 * @signature select(platform)
7226 * @param {string} platform Name of the platform.
7227 * [en]Possible values are: "opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios" or "wp".[/en]
7228 * [ja]"opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios", "wp"のいずれかを指定します。[/ja]
7229 * @description
7230 * [en]Sets the platform used to render the elements. Useful for testing.[/en]
7231 * [ja]要素を描画するために利用するプラットフォーム名を設定します。テストに便利です。[/ja]
7232 */
7233
7234
7235 createClass(Platform, [{
7236 key: 'select',
7237 value: function select(platform) {
7238 if (typeof platform === 'string') {
7239 this._renderPlatform = platform.trim().toLowerCase();
7240 }
7241 }
7242
7243 /**
7244 * @method isWebView
7245 * @signature isWebView()
7246 * @description
7247 * [en]Returns whether app is running in Cordova.[/en]
7248 * [ja]Cordova内で実行されているかどうかを返します。[/ja]
7249 * @return {Boolean}
7250 */
7251
7252 }, {
7253 key: 'isWebView',
7254 value: function isWebView() {
7255 if (document.readyState === 'loading' || document.readyState == 'uninitialized') {
7256 throw new Error('isWebView() method is available after dom contents loaded.');
7257 }
7258
7259 return !!(window.cordova || window.phonegap || window.PhoneGap);
7260 }
7261
7262 /**
7263 * @method isIOS
7264 * @signature isIOS()
7265 * @description
7266 * [en]Returns whether the OS is iOS.[/en]
7267 * [ja]iOS上で実行されているかどうかを返します。[/ja]
7268 * @return {Boolean}
7269 */
7270
7271 }, {
7272 key: 'isIOS',
7273 value: function isIOS() {
7274 if (this._renderPlatform) {
7275 return this._renderPlatform === 'ios';
7276 } else if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
7277 return (/iOS/i.test(device.platform)
7278 );
7279 } else {
7280 return (/iPhone|iPad|iPod/i.test(navigator.userAgent)
7281 );
7282 }
7283 }
7284
7285 /**
7286 * @method isAndroid
7287 * @signature isAndroid()
7288 * @description
7289 * [en]Returns whether the OS is Android.[/en]
7290 * [ja]Android上で実行されているかどうかを返します。[/ja]
7291 * @return {Boolean}
7292 */
7293
7294 }, {
7295 key: 'isAndroid',
7296 value: function isAndroid() {
7297 if (this._renderPlatform) {
7298 return this._renderPlatform === 'android';
7299 } else if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
7300 return (/Android/i.test(device.platform)
7301 );
7302 } else {
7303 return (/Android/i.test(navigator.userAgent)
7304 );
7305 }
7306 }
7307
7308 /**
7309 * @method isAndroidPhone
7310 * @signature isAndroidPhone()
7311 * @description
7312 * [en]Returns whether the device is Android phone.[/en]
7313 * [ja]Android携帯上で実行されているかどうかを返します。[/ja]
7314 * @return {Boolean}
7315 */
7316
7317 }, {
7318 key: 'isAndroidPhone',
7319 value: function isAndroidPhone() {
7320 return (/Android/i.test(navigator.userAgent) && /Mobile/i.test(navigator.userAgent)
7321 );
7322 }
7323
7324 /**
7325 * @method isAndroidTablet
7326 * @signature isAndroidTablet()
7327 * @description
7328 * [en]Returns whether the device is Android tablet.[/en]
7329 * [ja]Androidタブレット上で実行されているかどうかを返します。[/ja]
7330 * @return {Boolean}
7331 */
7332
7333 }, {
7334 key: 'isAndroidTablet',
7335 value: function isAndroidTablet() {
7336 return (/Android/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent)
7337 );
7338 }
7339
7340 /**
7341 * @return {Boolean}
7342 */
7343
7344 }, {
7345 key: 'isWP',
7346 value: function isWP() {
7347 if (this._renderPlatform) {
7348 return this._renderPlatform === 'wp';
7349 } else if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
7350 return (/Win32NT|WinCE/i.test(device.platform)
7351 );
7352 } else {
7353 return (/Windows Phone|IEMobile|WPDesktop/i.test(navigator.userAgent)
7354 );
7355 }
7356 }
7357
7358 /**
7359 * @methos isIPhone
7360 * @signature isIPhone()
7361 * @description
7362 * [en]Returns whether the device is iPhone.[/en]
7363 * [ja]iPhone上で実行されているかどうかを返します。[/ja]
7364 * @return {Boolean}
7365 */
7366
7367 }, {
7368 key: 'isIPhone',
7369 value: function isIPhone() {
7370 return (/iPhone/i.test(navigator.userAgent)
7371 );
7372 }
7373
7374 /**
7375 * @method isIPad
7376 * @signature isIPad()
7377 * @description
7378 * [en]Returns whether the device is iPad.[/en]
7379 * [ja]iPad上で実行されているかどうかを返します。[/ja]
7380 * @return {Boolean}
7381 */
7382
7383 }, {
7384 key: 'isIPad',
7385 value: function isIPad() {
7386 return (/iPad/i.test(navigator.userAgent)
7387 );
7388 }
7389
7390 /**
7391 * @return {Boolean}
7392 */
7393
7394 }, {
7395 key: 'isIPod',
7396 value: function isIPod() {
7397 return (/iPod/i.test(navigator.userAgent)
7398 );
7399 }
7400
7401 /**
7402 * @method isBlackBerry
7403 * @signature isBlackBerry()
7404 * @description
7405 * [en]Returns whether the device is BlackBerry.[/en]
7406 * [ja]BlackBerry上で実行されているかどうかを返します。[/ja]
7407 * @return {Boolean}
7408 */
7409
7410 }, {
7411 key: 'isBlackBerry',
7412 value: function isBlackBerry() {
7413 if (this._renderPlatform) {
7414 return this._renderPlatform === 'blackberry';
7415 } else if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
7416 return (/BlackBerry/i.test(device.platform)
7417 );
7418 } else {
7419 return (/BlackBerry|RIM Tablet OS|BB10/i.test(navigator.userAgent)
7420 );
7421 }
7422 }
7423
7424 /**
7425 * @method isOpera
7426 * @signature isOpera()
7427 * @description
7428 * [en]Returns whether the browser is Opera.[/en]
7429 * [ja]Opera上で実行されているかどうかを返します。[/ja]
7430 * @return {Boolean}
7431 */
7432
7433 }, {
7434 key: 'isOpera',
7435 value: function isOpera() {
7436 if (this._renderPlatform) {
7437 return this._renderPlatform === 'opera';
7438 } else {
7439 return !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
7440 }
7441 }
7442
7443 /**
7444 * @method isFirefox
7445 * @signature isFirefox()
7446 * @description
7447 * [en]Returns whether the browser is Firefox.[/en]
7448 * [ja]Firefox上で実行されているかどうかを返します。[/ja]
7449 * @return {Boolean}
7450 */
7451
7452 }, {
7453 key: 'isFirefox',
7454 value: function isFirefox() {
7455 if (this._renderPlatform) {
7456 return this._renderPlatform === 'firefox';
7457 } else {
7458 return typeof InstallTrigger !== 'undefined';
7459 }
7460 }
7461
7462 /**
7463 * @method isSafari
7464 * @signature isSafari()
7465 * @description
7466 * [en]Returns whether the browser is Safari.[/en]
7467 * [ja]Safari上で実行されているかどうかを返します。[/ja]
7468 * @return {Boolean}
7469 */
7470
7471 }, {
7472 key: 'isSafari',
7473 value: function isSafari() {
7474 if (this._renderPlatform) {
7475 return this._renderPlatform === 'safari';
7476 } else {
7477 return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
7478 }
7479 }
7480
7481 /**
7482 * @method isChrome
7483 * @signature isChrome()
7484 * @description
7485 * [en]Returns whether the browser is Chrome.[/en]
7486 * [ja]Chrome上で実行されているかどうかを返します。[/ja]
7487 * @return {Boolean}
7488 */
7489
7490 }, {
7491 key: 'isChrome',
7492 value: function isChrome() {
7493 if (this._renderPlatform) {
7494 return this._renderPlatform === 'chrome';
7495 } else {
7496 return !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) && !(navigator.userAgent.indexOf(' Edge/') >= 0);
7497 }
7498 }
7499
7500 /**
7501 * @method isIE
7502 * @signature isIE()
7503 * @description
7504 * [en]Returns whether the browser is Internet Explorer.[/en]
7505 * [ja]Internet Explorer上で実行されているかどうかを返します。[/ja]
7506 * @return {Boolean}
7507 */
7508
7509 }, {
7510 key: 'isIE',
7511 value: function isIE() {
7512 if (this._renderPlatform) {
7513 return this._renderPlatform === 'ie';
7514 } else {
7515 return false || !!document.documentMode;
7516 }
7517 }
7518
7519 /**
7520 * @method isEdge
7521 * @signature isEdge()
7522 * @description
7523 * [en]Returns whether the browser is Edge.[/en]
7524 * [ja]Edge上で実行されているかどうかを返します。[/ja]
7525 * @return {Boolean}
7526 */
7527
7528 }, {
7529 key: 'isEdge',
7530 value: function isEdge() {
7531 if (this._renderPlatform) {
7532 return this._renderPlatform === 'edge';
7533 } else {
7534 return navigator.userAgent.indexOf(' Edge/') >= 0;
7535 }
7536 }
7537
7538 /**
7539 * @method isIOS7above
7540 * @signature isIOS7above()
7541 * @description
7542 * [en]Returns whether the iOS version is 7 or above.[/en]
7543 * [ja]iOS7以上で実行されているかどうかを返します。[/ja]
7544 * @return {Boolean}
7545 */
7546
7547 }, {
7548 key: 'isIOS7above',
7549 value: function isIOS7above() {
7550 if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
7551 return (/iOS/i.test(device.platform) && parseInt(device.version.split('.')[0]) >= 7
7552 );
7553 } else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
7554 var ver = (navigator.userAgent.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || [''])[0].replace(/_/g, '.');
7555 return parseInt(ver.split('.')[0]) >= 7;
7556 }
7557 return false;
7558 }
7559
7560 /**
7561 * @return {String}
7562 */
7563
7564 }, {
7565 key: 'getMobileOS',
7566 value: function getMobileOS() {
7567 if (this.isAndroid()) {
7568 return 'android';
7569 } else if (this.isIOS()) {
7570 return 'ios';
7571 } else if (this.isWP()) {
7572 return 'wp';
7573 } else {
7574 return 'other';
7575 }
7576 }
7577
7578 /**
7579 * @return {String}
7580 */
7581
7582 }, {
7583 key: 'getIOSDevice',
7584 value: function getIOSDevice() {
7585 if (this.isIPhone()) {
7586 return 'iphone';
7587 } else if (this.isIPad()) {
7588 return 'ipad';
7589 } else if (this.isIPod()) {
7590 return 'ipod';
7591 } else {
7592 return 'na';
7593 }
7594 }
7595 }]);
7596 return Platform;
7597}();
7598
7599var platform = new Platform();
7600
7601/*
7602Copyright 2013-2015 ASIAL CORPORATION
7603
7604Licensed under the Apache License, Version 2.0 (the "License");
7605you may not use this file except in compliance with the License.
7606You may obtain a copy of the License at
7607
7608 http://www.apache.org/licenses/LICENSE-2.0
7609
7610Unless required by applicable law or agreed to in writing, software
7611distributed under the License is distributed on an "AS IS" BASIS,
7612WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7613See the License for the specific language governing permissions and
7614limitations under the License.
7615
7616*/
7617var readyMap = new WeakMap();
7618var queueMap = new WeakMap();
7619
7620function isContentReady(element) {
7621 if (element.childNodes.length > 0) {
7622 setContentReady(element);
7623 }
7624 return readyMap.has(element);
7625}
7626
7627function setContentReady(element) {
7628 readyMap.set(element, true);
7629}
7630
7631function addCallback(element, fn) {
7632 if (!queueMap.has(element)) {
7633 queueMap.set(element, []);
7634 }
7635 queueMap.get(element).push(fn);
7636}
7637
7638function consumeQueue(element) {
7639 var callbacks = queueMap.get(element, []) || [];
7640 queueMap.delete(element);
7641 callbacks.forEach(function (callback) {
7642 return callback();
7643 });
7644}
7645
7646function contentReady(element) {
7647 var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
7648
7649 addCallback(element, fn);
7650
7651 if (isContentReady(element)) {
7652 consumeQueue(element);
7653 return;
7654 }
7655
7656 var observer = new MutationObserver(function (changes) {
7657 setContentReady(element);
7658 consumeQueue(element);
7659 });
7660 observer.observe(element, { childList: true, characterData: true });
7661
7662 // failback for elements has empty content.
7663 setImmediate(function () {
7664 setContentReady(element);
7665 consumeQueue(element);
7666 });
7667}
7668
7669/*
7670Copyright 2013-2015 ASIAL CORPORATION
7671
7672Licensed under the Apache License, Version 2.0 (the "License");
7673you may not use this file except in compliance with the License.
7674You may obtain a copy of the License at
7675
7676 http://www.apache.org/licenses/LICENSE-2.0
7677
7678Unless required by applicable law or agreed to in writing, software
7679distributed under the License is distributed on an "AS IS" BASIS,
7680WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7681See the License for the specific language governing permissions and
7682limitations under the License.
7683
7684*/
7685
7686/**
7687 * @object ons.notification
7688 * @category dialog
7689 * @tutorial vanilla/Reference/dialog
7690 * @description
7691 * [en]
7692 * Utility methods to create different kinds of alert dialogs. There are three methods available:
7693 *
7694 * * `ons.notification.alert()`
7695 * * `ons.notification.confirm()`
7696 * * `ons.notification.prompt()`
7697 *
7698 * It will automatically display a Material Design dialog on Android devices.
7699 * [/en]
7700 * [ja]いくつかの種類のアラートダイアログを作成するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
7701 * @example
7702 * ons.notification.alert('Hello, world!');
7703 *
7704 * ons.notification.confirm('Are you ready?')
7705 * .then(
7706 * function(answer) {
7707 * if (answer === 1) {
7708 * ons.notification.alert('Let\'s go!');
7709 * }
7710 * }
7711 * );
7712 *
7713 * ons.notification.prompt('How old are ?')
7714 * .then(
7715 * function(age) {
7716 * ons.notification.alert('You are ' + age + ' years old.');
7717 * }
7718 * );
7719 */
7720var notification = {};
7721
7722notification._createAlertDialog = function (options) {
7723 // Prompt input string
7724 var inputString = '';
7725 if (options.isPrompt) {
7726 inputString = '\n <input\n class="text-input text-input--underbar"\n type="' + (options.inputType || 'text') + '"\n placeholder="' + (options.placeholder || '') + '"\n value="' + (options.defaultValue || '') + '"\n style="width: 100%; margin-top: 10px;"\n />\n ';
7727 }
7728
7729 // Buttons string
7730 var buttons = '';
7731 options.buttonLabels.forEach(function (label, index) {
7732 buttons += '\n <button class="\n alert-dialog-button\n ' + (index === options.primaryButtonIndex ? ' alert-dialog-button--primal' : '') + '\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-button--one' : '') + '\n ">\n ' + label + '\n </button>\n ';
7733 });
7734
7735 // Dialog Element
7736 var el = {};
7737 var _destroyDialog = function _destroyDialog() {
7738 if (el.dialog.onDialogCancel) {
7739 el.dialog.removeEventListener('dialog-cancel', el.dialog.onDialogCancel);
7740 }
7741
7742 Object.keys(el).forEach(function (key) {
7743 return delete el[key];
7744 });
7745 el = null;
7746
7747 if (options.destroy instanceof Function) {
7748 options.destroy();
7749 }
7750 };
7751
7752 el.dialog = document.createElement('ons-alert-dialog');
7753 innerHTML(el.dialog, '\n <div class="alert-dialog-mask"></div>\n <div class="alert-dialog">\n <div class="alert-dialog-container">\n <div class="alert-dialog-title">\n ' + (options.title || '') + '\n </div>\n <div class="alert-dialog-content">\n ' + (options.message || options.messageHTML) + '\n ' + inputString + '\n </div>\n <div class="\n alert-dialog-footer\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-footer--one' : '') + '\n ">\n ' + buttons + '\n </div>\n </div>\n </div>\n ');
7754 contentReady(el.dialog);
7755
7756 // Set attributes
7757 ['id', 'class', 'animation'].forEach(function (a) {
7758 return options.hasOwnProperty(a) && el.dialog.setAttribute(a, options[a]);
7759 });
7760 if (options.modifier) {
7761 util.addModifier(el.dialog, options.modifier);
7762 }
7763
7764 var deferred = util.defer();
7765
7766 // Prompt events
7767 if (options.isPrompt && options.submitOnEnter) {
7768 el.input = el.dialog.querySelector('.text-input');
7769 el.input.onkeypress = function (event) {
7770 if (event.keyCode === 13) {
7771 el.dialog.hide().then(function () {
7772 var resolveValue = el.input.value;
7773 _destroyDialog();
7774 options.callback(resolveValue);
7775 deferred.resolve(resolveValue);
7776 });
7777 }
7778 };
7779 }
7780
7781 // Button events
7782 el.footer = el.dialog.querySelector('.alert-dialog-footer');
7783 util.arrayFrom(el.dialog.querySelectorAll('.alert-dialog-button')).forEach(function (buttonElement, index) {
7784 buttonElement.onclick = function () {
7785 el.dialog.hide().then(function () {
7786 var resolveValue = options.isPrompt ? el.input.value : index;
7787 el.dialog.remove();
7788 _destroyDialog();
7789 options.callback(resolveValue);
7790 deferred.resolve(resolveValue);
7791 });
7792 };
7793
7794 el.footer.appendChild(buttonElement);
7795 });
7796
7797 // Cancel events
7798 if (options.cancelable) {
7799 el.dialog.cancelable = true;
7800 el.dialog.onDialogCancel = function () {
7801 setImmediate(function () {
7802 el.dialog.remove();
7803 _destroyDialog();
7804 });
7805 var resolveValue = options.isPrompt ? null : -1;
7806 options.callback(resolveValue);
7807 deferred.reject(resolveValue);
7808 };
7809 el.dialog.addEventListener('dialog-cancel', el.dialog.onDialogCancel, false);
7810 }
7811
7812 // Show dialog
7813 document.body.appendChild(el.dialog);
7814 options.compile(el.dialog);
7815 setImmediate(function () {
7816 el.dialog.show().then(function () {
7817 if (el.input && options.isPrompt && options.autofocus) {
7818 el.input.focus();
7819 }
7820 });
7821 });
7822
7823 return deferred.promise;
7824};
7825
7826var _normalizeArguments = function _normalizeArguments(message) {
7827 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7828 var defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
7829
7830 typeof message === 'string' ? options.message = message : options = message;
7831 if (!options.message && !options.messageHTML) {
7832 throw new Error('Alert dialog must contain a message.');
7833 }
7834
7835 if (options.hasOwnProperty('buttonLabels') || options.hasOwnProperty('buttonLabel')) {
7836 options.buttonLabels = options.buttonLabels || options.buttonLabel;
7837 if (!Array.isArray(options.buttonLabels)) {
7838 options.buttonLabels = [options.buttonLabels || ''];
7839 }
7840 }
7841
7842 return util.extend({
7843 compile: function compile(param) {
7844 return param;
7845 },
7846 callback: function callback(param) {
7847 return param;
7848 },
7849 buttonLabels: ['OK'],
7850 primaryButtonIndex: 0,
7851 animation: 'default',
7852 cancelable: false
7853 }, defaults, options);
7854};
7855
7856/**
7857 * @method alert
7858 * @signature alert(message [, options] | options)
7859 * @return {Promise}
7860 * [en]Will resolve when the dialog is closed.[/en]
7861 * [ja][/ja]
7862 * @param {String} message
7863 * [en]Alert message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
7864 * [ja][/ja]
7865 * @param {Object} options
7866 * [en]Parameter object.[/en]
7867 * [ja]オプションを指定するオブジェクトです。[/ja]
7868 * @param {String} [options.message]
7869 * [en]Alert message.[/en]
7870 * [ja]アラートダイアログに表示する文字列を指定します。[/ja]
7871 * @param {String} [options.messageHTML]
7872 * [en]Alert message in HTML.[/en]
7873 * [ja]アラートダイアログに表示するHTMLを指定します。[/ja]
7874 * @param {String | Array} [options.buttonLabels]
7875 * [en]Labels for the buttons. Default is `"OK"`.[/en]
7876 * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
7877 * @param {Number} [options.primaryButtonIndex]
7878 * [en]Index of primary button. Default is `0`.[/en]
7879 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
7880 * @param {Boolean} [options.cancelable]
7881 * [en]Whether the dialog is cancelable or not. Default is `false`. If the dialog is cancelable it can be closed by clicking the background or pressing the Android back button.[/en]
7882 * [ja]ダイアログがキャンセル可能かどうかを指定します。[/ja]
7883 * @param {String} [options.animation]
7884 * [en]Animation name. Available animations are `none` and `fade`. Default is `fade`.[/en]
7885 * [ja]アラートダイアログを表示する際のアニメーション名を指定します。"none", "fade"のいずれかを指定できます。[/ja]
7886 * @param {String} [options.id]
7887 * [en]The `<ons-alert-dialog>` element's ID.[/en]
7888 * [ja]ons-alert-dialog要素のID。[/ja]
7889 * @param {String} [options.class]
7890 * [en]The `<ons-alert-dialog>` element's class.[/en]
7891 * [ja]ons-alert-dialog要素のclass。[/ja]
7892 * @param {String} [options.title]
7893 * [en]Dialog title. Default is `"Alert"`.[/en]
7894 * [ja]アラートダイアログの上部に表示するタイトルを指定します。"Alert"がデフォルトです。[/ja]
7895 * @param {String} [options.modifier]
7896 * [en]Modifier for the dialog.[/en]
7897 * [ja]アラートダイアログのmodifier属性の値を指定します。[/ja]
7898 * @param {Function} [options.callback]
7899 * [en]Function that executes after dialog has been closed.[/en]
7900 * [ja]アラートダイアログが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja]
7901 * @description
7902 * [en]
7903 * Display an alert dialog to show the user a message.
7904 *
7905 * The content of the message can be either simple text or HTML.
7906 *
7907 * It can be called in the following ways:
7908 *
7909 * ```
7910 * ons.notification.alert(message, options);
7911 * ons.notification.alert(options);
7912 * ```
7913 *
7914 * Must specify either `message` or `messageHTML`.
7915 * [/en]
7916 * [ja]
7917 * ユーザーへメッセージを見せるためのアラートダイアログを表示します。
7918 * 表示するメッセージは、テキストかもしくはHTMLを指定できます。
7919 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
7920 * [/ja]
7921 */
7922notification.alert = function (message, options) {
7923 options = _normalizeArguments(message, options, {
7924 title: 'Alert'
7925 });
7926
7927 return notification._createAlertDialog(options);
7928};
7929
7930/**
7931 * @method confirm
7932 * @signature confirm(message [, options] | options)
7933 * @return {Promise}
7934 * [en]Will resolve to the index of the button that was pressed.[/en]
7935 * [ja][/ja]
7936 * @param {String} message
7937 * [en]Alert message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
7938 * [ja][/ja]
7939 * @param {Object} options
7940 * [en]Parameter object.[/en]
7941 * @param {Array} [options.buttonLabels]
7942 * [en]Labels for the buttons. Default is `["Cancel", "OK"]`.[/en]
7943 * [ja]ボタンのラベルの配列を指定します。["Cancel", "OK"]がデフォルトです。[/ja]
7944 * @param {Number} [options.primaryButtonIndex]
7945 * [en]Index of primary button. Default is `1`.[/en]
7946 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 1 です。[/ja]
7947 * @description
7948 * [en]
7949 * Display a dialog to ask the user for confirmation. Extends `alert()` parameters.
7950 * The default button labels are `"Cancel"` and `"OK"` but they can be customized.
7951 *
7952 * It can be called in the following ways:
7953 *
7954 * ```
7955 * ons.notification.confirm(message, options);
7956 * ons.notification.confirm(options);
7957 * ```
7958 *
7959 * Must specify either `message` or `messageHTML`.
7960 * [/en]
7961 * [ja]
7962 * ユーザに確認を促すダイアログを表示します。
7963 * デオルとのボタンラベルは、"Cancel"と"OK"ですが、これはこのメソッドの引数でカスタマイズできます。
7964 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
7965 * [/ja]
7966 */
7967notification.confirm = function (message, options) {
7968 options = _normalizeArguments(message, options, {
7969 buttonLabels: ['Cancel', 'OK'],
7970 primaryButtonIndex: 1,
7971 title: 'Confirm'
7972 });
7973
7974 return notification._createAlertDialog(options);
7975};
7976
7977/**
7978 * @method prompt
7979 * @signature prompt(message [, options] | options)
7980 * @param {String} message
7981 * [en]Alert message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
7982 * [ja][/ja]
7983 * @return {Promise}
7984 * [en]Will resolve to the input value when the dialog is closed.[/en]
7985 * [ja][/ja]
7986 * @param {Object} options
7987 * [en]Parameter object.[/en]
7988 * [ja]オプションを指定するオブジェクトです。[/ja]
7989 * @param {String | Array} [options.buttonLabels]
7990 * [en]Labels for the buttons. Default is `"OK"`.[/en]
7991 * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
7992 * @param {Number} [options.primaryButtonIndex]
7993 * [en]Index of primary button. Default is `0`.[/en]
7994 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
7995 * @param {String} [options.placeholder]
7996 * [en]Placeholder for the text input.[/en]
7997 * [ja]テキスト欄のプレースホルダに表示するテキストを指定します。[/ja]
7998 * @param {String} [options.defaultValue]
7999 * [en]Default value for the text input.[/en]
8000 * [ja]テキスト欄のデフォルトの値を指定します。[/ja]
8001 * @param {String} [options.inputType]
8002 * [en]Type of the input element (`password`, `date`...). Default is `text`.[/en]
8003 * [ja][/ja]
8004 * @param {Boolean} [options.autofocus]
8005 * [en]Autofocus the input element. Default is `true`.[/en]
8006 * [ja]input要素に自動的にフォーカスするかどうかを指定します。デフォルトはtrueです。[/ja]
8007 * @param {Boolean} [options.submitOnEnter]
8008 * [en]Submit automatically when enter is pressed. Default is `true`.[/en]
8009 * [ja]Enterが押された際にそのformをsubmitするかどうかを指定します。デフォルトはtrueです。[/ja]
8010 * @description
8011 * [en]
8012 * Display a dialog with a prompt to ask the user a question. Extends `alert()` parameters.
8013 *
8014 * It can be called in the following ways:
8015 *
8016 * ```
8017 * ons.notification.prompt(message, options);
8018 * ons.notification.prompt(options);
8019 * ```
8020 *
8021 * Must specify either `message` or `messageHTML`.
8022 * [/en]
8023 * [ja]
8024 * ユーザーに入力を促すダイアログを表示します。
8025 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
8026 * [/ja]
8027 */
8028notification.prompt = function (message, options) {
8029 options = _normalizeArguments(message, options, {
8030 title: 'Alert',
8031 isPrompt: true,
8032 autofocus: true,
8033 submitOnEnter: true
8034 });
8035
8036 return notification._createAlertDialog(options);
8037};
8038
8039/*
8040Copyright 2013-2015 ASIAL CORPORATION
8041
8042Licensed under the Apache License, Version 2.0 (the "License");
8043you may not use this file except in compliance with the License.
8044You may obtain a copy of the License at
8045
8046 http://www.apache.org/licenses/LICENSE-2.0
8047
8048Unless required by applicable law or agreed to in writing, software
8049distributed under the License is distributed on an "AS IS" BASIS,
8050WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8051See the License for the specific language governing permissions and
8052limitations under the License.
8053
8054*/
8055
8056var pageAttributeExpression = {
8057 _variables: {},
8058
8059 /**
8060 * Define a variable.
8061 *
8062 * @param {String} name Name of the variable
8063 * @param {String|Function} value Value of the variable. Can be a string or a function. The function must return a string.
8064 * @param {Boolean} overwrite If this value is false, an error will be thrown when trying to define a variable that has already been defined.
8065 */
8066 defineVariable: function defineVariable(name, value) {
8067 var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
8068
8069 if (typeof name !== 'string') {
8070 throw new Error('Variable name must be a string.');
8071 } else if (typeof value !== 'string' && typeof value !== 'function') {
8072 throw new Error('Variable value must be a string or a function.');
8073 } else if (this._variables.hasOwnProperty(name) && !overwrite) {
8074 throw new Error('"' + name + '" is already defined.');
8075 }
8076 this._variables[name] = value;
8077 },
8078
8079 /**
8080 * Get a variable.
8081 *
8082 * @param {String} name Name of the variable.
8083 * @return {String|Function|null}
8084 */
8085 getVariable: function getVariable(name) {
8086 if (!this._variables.hasOwnProperty(name)) {
8087 return null;
8088 }
8089
8090 return this._variables[name];
8091 },
8092
8093 /**
8094 * Remove a variable.
8095 *
8096 * @param {String} name Name of the varaible.
8097 */
8098 removeVariable: function removeVariable(name) {
8099 delete this._variables[name];
8100 },
8101
8102 /**
8103 * Get all variables.
8104 *
8105 * @return {Object}
8106 */
8107 getAllVariables: function getAllVariables() {
8108 return this._variables;
8109 },
8110 _parsePart: function _parsePart(part) {
8111 var c = void 0,
8112 inInterpolation = false,
8113 currentIndex = 0;
8114
8115 var tokens = [];
8116
8117 if (part.length === 0) {
8118 throw new Error('Unable to parse empty string.');
8119 }
8120
8121 for (var i = 0; i < part.length; i++) {
8122 c = part.charAt(i);
8123
8124 if (c === '$' && part.charAt(i + 1) === '{') {
8125 if (inInterpolation) {
8126 throw new Error('Nested interpolation not supported.');
8127 }
8128
8129 var token = part.substring(currentIndex, i);
8130 if (token.length > 0) {
8131 tokens.push(part.substring(currentIndex, i));
8132 }
8133
8134 currentIndex = i;
8135 inInterpolation = true;
8136 } else if (c === '}') {
8137 if (!inInterpolation) {
8138 throw new Error('} must be preceeded by ${');
8139 }
8140
8141 var _token = part.substring(currentIndex, i + 1);
8142 if (_token.length > 0) {
8143 tokens.push(part.substring(currentIndex, i + 1));
8144 }
8145
8146 currentIndex = i + 1;
8147 inInterpolation = false;
8148 }
8149 }
8150
8151 if (inInterpolation) {
8152 throw new Error('Unterminated interpolation.');
8153 }
8154
8155 tokens.push(part.substring(currentIndex, part.length));
8156
8157 return tokens;
8158 },
8159 _replaceToken: function _replaceToken(token) {
8160 var re = /^\${(.*?)}$/,
8161 match = token.match(re);
8162
8163 if (match) {
8164 var name = match[1].trim();
8165 var variable = this.getVariable(name);
8166
8167 if (variable === null) {
8168 throw new Error('Variable "' + name + '" does not exist.');
8169 } else if (typeof variable === 'string') {
8170 return variable;
8171 } else {
8172 var rv = variable();
8173
8174 if (typeof rv !== 'string') {
8175 throw new Error('Must return a string.');
8176 }
8177
8178 return rv;
8179 }
8180 } else {
8181 return token;
8182 }
8183 },
8184 _replaceTokens: function _replaceTokens(tokens) {
8185 return tokens.map(this._replaceToken.bind(this));
8186 },
8187 _parseExpression: function _parseExpression(expression) {
8188 return expression.split(',').map(function (part) {
8189 return part.trim();
8190 }).map(this._parsePart.bind(this)).map(this._replaceTokens.bind(this)).map(function (part) {
8191 return part.join('');
8192 });
8193 },
8194
8195 /**
8196 * Evaluate an expression.
8197 *
8198 * @param {String} expression An page attribute expression.
8199 * @return {Array}
8200 */
8201 evaluate: function evaluate(expression) {
8202 if (!expression) {
8203 return [];
8204 }
8205
8206 return this._parseExpression(expression);
8207 }
8208};
8209
8210// Define default variables.
8211pageAttributeExpression.defineVariable('mobileOS', platform.getMobileOS());
8212pageAttributeExpression.defineVariable('iOSDevice', platform.getIOSDevice());
8213pageAttributeExpression.defineVariable('runtime', function () {
8214 return platform.isWebView() ? 'cordova' : 'browser';
8215});
8216
8217/*
8218Copyright 2013-2015 ASIAL CORPORATION
8219
8220Licensed under the Apache License, Version 2.0 (the "License");
8221you may not use this file except in compliance with the License.
8222You may obtain a copy of the License at
8223
8224 http://www.apache.org/licenses/LICENSE-2.0
8225
8226Unless required by applicable law or agreed to in writing, software
8227distributed under the License is distributed on an "AS IS" BASIS,
8228WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8229See the License for the specific language governing permissions and
8230limitations under the License.
8231
8232*/
8233
8234var internal$1 = {};
8235
8236internal$1.config = {
8237 autoStatusBarFill: true,
8238 animationsDisabled: false
8239};
8240
8241internal$1.nullElement = window.document.createElement('div');
8242
8243/**
8244 * @return {Boolean}
8245 */
8246internal$1.isEnabledAutoStatusBarFill = function () {
8247 return !!internal$1.config.autoStatusBarFill;
8248};
8249
8250/**
8251 * @param {String} html
8252 * @return {String}
8253 */
8254internal$1.normalizePageHTML = function (html) {
8255 html = ('' + html).trim();
8256
8257 if (!html.match(/^<ons-page/)) {
8258 html = '<ons-page _muted>' + html + '</ons-page>';
8259 }
8260
8261 return html;
8262};
8263
8264internal$1.waitDOMContentLoaded = function (callback) {
8265 if (window.document.readyState === 'loading' || window.document.readyState == 'uninitialized') {
8266 window.document.addEventListener('DOMContentLoaded', callback);
8267 } else {
8268 setImmediate(callback);
8269 }
8270};
8271
8272internal$1.autoStatusBarFill = function (action) {
8273 var onReady = function onReady() {
8274 if (internal$1.shouldFillStatusBar()) {
8275 action();
8276 }
8277 document.removeEventListener('deviceready', onReady);
8278 document.removeEventListener('DOMContentLoaded', onReady);
8279 };
8280
8281 if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object') {
8282 document.addEventListener('deviceready', onReady);
8283 } else if (['complete', 'interactive'].indexOf(document.readyState) === -1) {
8284 document.addEventListener('DOMContentLoaded', function () {
8285 onReady();
8286 });
8287 } else {
8288 onReady();
8289 }
8290};
8291
8292internal$1.shouldFillStatusBar = function () {
8293 return internal$1.isEnabledAutoStatusBarFill() && platform.isWebView() && platform.isIOS7above();
8294};
8295
8296internal$1.templateStore = {
8297 _storage: {},
8298
8299 /**
8300 * @param {String} key
8301 * @return {String/null} template
8302 */
8303 get: function get(key) {
8304 return internal$1.templateStore._storage[key] || null;
8305 },
8306
8307
8308 /**
8309 * @param {String} key
8310 * @param {String} template
8311 */
8312 set: function set(key, template) {
8313 internal$1.templateStore._storage[key] = template;
8314 }
8315};
8316
8317window.document.addEventListener('_templateloaded', function (e) {
8318 if (e.target.nodeName.toLowerCase() === 'ons-template') {
8319 internal$1.templateStore.set(e.templateId, e.template);
8320 }
8321}, false);
8322
8323window.document.addEventListener('DOMContentLoaded', function () {
8324 register('script[type="text/ons-template"]');
8325 register('script[type="text/template"]');
8326 register('script[type="text/ng-template"]');
8327
8328 function register(query) {
8329 var templates = window.document.querySelectorAll(query);
8330 for (var i = 0; i < templates.length; i++) {
8331 internal$1.templateStore.set(templates[i].getAttribute('id'), templates[i].textContent);
8332 }
8333 }
8334}, false);
8335
8336/**
8337 * @param {String} page
8338 * @return {Promise}
8339 */
8340internal$1.getTemplateHTMLAsync = function (page) {
8341 return new Promise(function (resolve, reject) {
8342 setImmediate(function () {
8343 var cache = internal$1.templateStore.get(page);
8344
8345 if (cache) {
8346 var html = typeof cache === 'string' ? cache : cache[1];
8347 resolve(html);
8348 } else {
8349 (function () {
8350 var xhr = new XMLHttpRequest();
8351 xhr.open('GET', page, true);
8352 xhr.onload = function (response) {
8353 var html = xhr.responseText;
8354 if (xhr.status >= 400 && xhr.status < 600) {
8355 reject(html);
8356 } else {
8357 resolve(html);
8358 }
8359 };
8360 xhr.onerror = function () {
8361 throw new Error('The page is not found: ' + page);
8362 };
8363 xhr.send(null);
8364 })();
8365 }
8366 });
8367 });
8368};
8369
8370/**
8371 * @param {String} page
8372 * @return {Promise}
8373 */
8374internal$1.getPageHTMLAsync = function (page) {
8375 var pages = pageAttributeExpression.evaluate(page);
8376
8377 var getPage = function getPage(page) {
8378 if (typeof page !== 'string') {
8379 return Promise.reject('Must specify a page.');
8380 }
8381
8382 return internal$1.getTemplateHTMLAsync(page).then(function (html) {
8383 return internal$1.normalizePageHTML(html);
8384 }, function (error) {
8385 if (pages.length === 0) {
8386 return Promise.reject(error);
8387 }
8388
8389 return getPage(pages.shift());
8390 }).then(function (html) {
8391 return internal$1.normalizePageHTML(html);
8392 });
8393 };
8394
8395 return getPage(pages.shift());
8396};
8397
8398/*
8399Copyright 2013-2015 ASIAL CORPORATION
8400
8401Licensed under the Apache License, Version 2.0 (the "License");
8402you may not use this file except in compliance with the License.
8403You may obtain a copy of the License at
8404
8405 http://www.apache.org/licenses/LICENSE-2.0
8406
8407Unless required by applicable law or agreed to in writing, software
8408distributed under the License is distributed on an "AS IS" BASIS,
8409WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8410See the License for the specific language governing permissions and
8411limitations under the License.
8412
8413*/
8414
8415var AnimatorFactory = function () {
8416
8417 /**
8418 * @param {Object} opts
8419 * @param {Object} opts.animators The dictionary for animator classes
8420 * @param {Function} opts.baseClass The base class of animators
8421 * @param {String} [opts.baseClassName] The name of the base class of animators
8422 * @param {String} [opts.defaultAnimation] The default animation name
8423 * @param {Object} [opts.defaultAnimationOptions] The default animation options
8424 */
8425 function AnimatorFactory(opts) {
8426 classCallCheck(this, AnimatorFactory);
8427
8428 this._animators = opts.animators;
8429 this._baseClass = opts.baseClass;
8430 this._baseClassName = opts.baseClassName || opts.baseClass.name;
8431 this._animation = opts.defaultAnimation || 'default';
8432 this._animationOptions = opts.defaultAnimationOptions || {};
8433
8434 if (!this._animators[this._animation]) {
8435 throw new Error('No such animation: ' + this._animation);
8436 }
8437 }
8438
8439 /**
8440 * @param {String} jsonString
8441 * @return {Object/null}
8442 */
8443
8444
8445 createClass(AnimatorFactory, [{
8446 key: 'setAnimationOptions',
8447
8448
8449 /**
8450 * @param {Object} options
8451 */
8452 value: function setAnimationOptions(options) {
8453 this._animationOptions = options;
8454 }
8455
8456 /**
8457 * @param {Object} options
8458 * @param {String} [options.animation] The animation name
8459 * @param {Object} [options.animationOptions] The animation options
8460 * @param {Object} defaultAnimator The default animator instance
8461 * @return {Object} An animator instance
8462 */
8463
8464 }, {
8465 key: 'newAnimator',
8466 value: function newAnimator() {
8467 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8468 var defaultAnimator = arguments[1];
8469
8470
8471 var animator = null;
8472
8473 if (options.animation instanceof this._baseClass) {
8474 return options.animation;
8475 }
8476
8477 var Animator = null;
8478
8479 if (typeof options.animation === 'string') {
8480 Animator = this._animators[options.animation];
8481 }
8482
8483 if (!Animator && defaultAnimator) {
8484 animator = defaultAnimator;
8485 } else {
8486 Animator = Animator || this._animators[this._animation];
8487
8488 var animationOpts = util.extend({}, this._animationOptions, options.animationOptions || {}, internal$1.config.animationsDisabled ? { duration: 0, delay: 0 } : {});
8489
8490 animator = new Animator(animationOpts);
8491
8492 if (typeof animator === 'function') {
8493 animator = new animator(animationOpts); // eslint-disable-line new-cap
8494 }
8495 }
8496
8497 if (!(animator instanceof this._baseClass)) {
8498 throw new Error('"animator" is not an instance of ' + this._baseClassName + '.');
8499 }
8500
8501 return animator;
8502 }
8503 }], [{
8504 key: 'parseAnimationOptionsString',
8505 value: function parseAnimationOptionsString(jsonString) {
8506 try {
8507 if (typeof jsonString === 'string') {
8508 var result = util.animationOptionsParse(jsonString);
8509 if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) {
8510 return result;
8511 } else {
8512 console.error('"animation-options" attribute must be a JSON object string: ' + jsonString);
8513 }
8514 }
8515 return {};
8516 } catch (e) {
8517 console.error('"animation-options" attribute must be a JSON object string: ' + jsonString);
8518 return {};
8519 }
8520 }
8521 }]);
8522 return AnimatorFactory;
8523}();
8524
8525/*
8526Copyright 2013-2015 ASIAL CORPORATION
8527
8528Licensed under the Apache License, Version 2.0 (the "License");
8529you may not use this file except in compliance with the License.
8530You may obtain a copy of the License at
8531
8532 http://www.apache.org/licenses/LICENSE-2.0
8533
8534Unless required by applicable law or agreed to in writing, software
8535distributed under the License is distributed on an "AS IS" BASIS,
8536WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8537See the License for the specific language governing permissions and
8538limitations under the License.
8539
8540*/
8541
8542var ModifierUtil = function () {
8543 function ModifierUtil() {
8544 classCallCheck(this, ModifierUtil);
8545 }
8546
8547 createClass(ModifierUtil, null, [{
8548 key: 'diff',
8549
8550 /**
8551 * @param {String} last
8552 * @param {String} current
8553 */
8554 value: function diff(last, current) {
8555 last = makeDict(('' + last).trim());
8556 current = makeDict(('' + current).trim());
8557
8558 var removed = Object.keys(last).reduce(function (result, token) {
8559 if (!current[token]) {
8560 result.push(token);
8561 }
8562 return result;
8563 }, []);
8564
8565 var added = Object.keys(current).reduce(function (result, token) {
8566 if (!last[token]) {
8567 result.push(token);
8568 }
8569 return result;
8570 }, []);
8571
8572 return { added: added, removed: removed };
8573
8574 function makeDict(modifier) {
8575 var dict = {};
8576 ModifierUtil.split(modifier).forEach(function (token) {
8577 return dict[token] = token;
8578 });
8579 return dict;
8580 }
8581 }
8582
8583 /**
8584 * @param {Object} diff
8585 * @param {Object} classList
8586 * @param {String} template
8587 */
8588
8589 }, {
8590 key: 'applyDiffToClassList',
8591 value: function applyDiffToClassList(diff, classList, template) {
8592 diff.added.map(function (modifier) {
8593 return template.replace(/\*/g, modifier);
8594 }).forEach(function (klass) {
8595 return classList.add(klass);
8596 });
8597
8598 diff.removed.map(function (modifier) {
8599 return template.replace(/\*/g, modifier);
8600 }).forEach(function (klass) {
8601 return classList.remove(klass);
8602 });
8603 }
8604
8605 /**
8606 * @param {Object} diff
8607 * @param {HTMLElement} element
8608 * @param {Object} scheme
8609 */
8610
8611 }, {
8612 key: 'applyDiffToElement',
8613 value: function applyDiffToElement(diff, element, scheme) {
8614 var matches = function matches(e, s) {
8615 return (e.matches || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector).call(e, s);
8616 };
8617 for (var selector in scheme) {
8618 if (scheme.hasOwnProperty(selector)) {
8619 var targetElements = !selector || matches(element, selector) ? [element] : element.querySelectorAll(selector);
8620 for (var i = 0; i < targetElements.length; i++) {
8621 ModifierUtil.applyDiffToClassList(diff, targetElements[i].classList, scheme[selector]);
8622 }
8623 }
8624 }
8625 }
8626
8627 /**
8628 * @param {String} last
8629 * @param {String} current
8630 * @param {HTMLElement} element
8631 * @param {Object} scheme
8632 */
8633
8634 }, {
8635 key: 'onModifierChanged',
8636 value: function onModifierChanged(last, current, element, scheme) {
8637 return ModifierUtil.applyDiffToElement(ModifierUtil.diff(last, current), element, scheme);
8638 }
8639
8640 /**
8641 * @param {HTMLElement} element
8642 * @param {Object} scheme
8643 */
8644
8645 }, {
8646 key: 'initModifier',
8647 value: function initModifier(element, scheme) {
8648 var modifier = element.getAttribute('modifier');
8649 if (typeof modifier !== 'string') {
8650 return;
8651 }
8652
8653 ModifierUtil.applyDiffToElement({
8654 removed: [],
8655 added: ModifierUtil.split(modifier)
8656 }, element, scheme);
8657 }
8658 }, {
8659 key: 'split',
8660 value: function split(modifier) {
8661 if (typeof modifier !== 'string') {
8662 return [];
8663 }
8664
8665 return modifier.trim().split(/ +/).filter(function (token) {
8666 return token !== '';
8667 });
8668 }
8669 }]);
8670 return ModifierUtil;
8671}();
8672
8673/*
8674Copyright 2013-2015 ASIAL CORPORATION
8675
8676Licensed under the Apache License, Version 2.0 (the "License");
8677you may not use this file except in compliance with the License.
8678You may obtain a copy of the License at
8679
8680 http://www.apache.org/licenses/LICENSE-2.0
8681
8682Unless required by applicable law or agreed to in writing, software
8683distributed under the License is distributed on an "AS IS" BASIS,
8684WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8685See the License for the specific language governing permissions and
8686limitations under the License.
8687
8688*/
8689
8690var LazyRepeatDelegate = function () {
8691 function LazyRepeatDelegate(userDelegate) {
8692 var templateElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
8693 classCallCheck(this, LazyRepeatDelegate);
8694
8695 if ((typeof userDelegate === 'undefined' ? 'undefined' : _typeof(userDelegate)) !== 'object' || userDelegate === null) {
8696 throw Error('"delegate" parameter must be an object.');
8697 }
8698 this._userDelegate = userDelegate;
8699
8700 if (!(templateElement instanceof Element) && templateElement !== null) {
8701 throw Error('"templateElement" parameter must be an instance of Element or null.');
8702 }
8703 this._templateElement = templateElement;
8704 }
8705
8706 createClass(LazyRepeatDelegate, [{
8707 key: 'hasRenderFunction',
8708
8709
8710 /**
8711 * @return {Boolean}
8712 */
8713 value: function hasRenderFunction() {
8714 return this._userDelegate._render instanceof Function;
8715 }
8716
8717 /**
8718 * @return {void}
8719 */
8720
8721 }, {
8722 key: '_render',
8723 value: function _render(items, height) {
8724 this._userDelegate._render(items, height);
8725 }
8726
8727 /**
8728 * @param {Number} index
8729 * @param {Element} parent
8730 * @param {Function} done A function that take item object as parameter.
8731 */
8732
8733 }, {
8734 key: 'loadItemElement',
8735 value: function loadItemElement(index, parent, done) {
8736 if (this._userDelegate.loadItemElement instanceof Function) {
8737 this._userDelegate.loadItemElement(index, parent, function (element) {
8738 return done({ element: element });
8739 });
8740 } else {
8741 var element = this._userDelegate.createItemContent(index, this._templateElement);
8742 if (!(element instanceof Element)) {
8743 throw Error('createItemContent() must return an instance of Element.');
8744 }
8745 parent.appendChild(element);
8746 done({ element: element });
8747 }
8748 }
8749
8750 /**
8751 * @return {Number}
8752 */
8753
8754 }, {
8755 key: 'countItems',
8756 value: function countItems() {
8757 var count = this._userDelegate.countItems();
8758 if (typeof count !== 'number') {
8759 throw Error('countItems() must return a number.');
8760 }
8761 return count;
8762 }
8763
8764 /**
8765 * @param {Number} index
8766 * @param {Object} item
8767 * @param {Element} item.element
8768 */
8769
8770 }, {
8771 key: 'updateItem',
8772 value: function updateItem(index, item) {
8773 if (this._userDelegate.updateItemContent instanceof Function) {
8774 this._userDelegate.updateItemContent(index, item);
8775 }
8776 }
8777
8778 /**
8779 * @return {Number}
8780 */
8781
8782 }, {
8783 key: 'calculateItemHeight',
8784 value: function calculateItemHeight(index) {
8785 if (this._userDelegate.calculateItemHeight instanceof Function) {
8786 var height = this._userDelegate.calculateItemHeight(index);
8787
8788 if (typeof height !== 'number') {
8789 throw Error('calculateItemHeight() must return a number.');
8790 }
8791
8792 return height;
8793 }
8794
8795 return 0;
8796 }
8797
8798 /**
8799 * @param {Number} index
8800 * @param {Object} item
8801 */
8802
8803 }, {
8804 key: 'destroyItem',
8805 value: function destroyItem(index, item) {
8806 if (this._userDelegate.destroyItem instanceof Function) {
8807 this._userDelegate.destroyItem(index, item);
8808 }
8809 }
8810
8811 /**
8812 * @return {void}
8813 */
8814
8815 }, {
8816 key: 'destroy',
8817 value: function destroy() {
8818 if (this._userDelegate.destroy instanceof Function) {
8819 this._userDelegate.destroy();
8820 }
8821
8822 this._userDelegate = this._templateElement = null;
8823 }
8824 }, {
8825 key: 'itemHeight',
8826 get: function get() {
8827 return this._userDelegate.itemHeight;
8828 }
8829 }]);
8830 return LazyRepeatDelegate;
8831}();
8832
8833/**
8834 * This class provide core functions for ons-lazy-repeat.
8835 */
8836var LazyRepeatProvider = function () {
8837
8838 /**
8839 * @param {Element} wrapperElement
8840 * @param {LazyRepeatDelegate} delegate
8841 */
8842 function LazyRepeatProvider(wrapperElement, delegate) {
8843 classCallCheck(this, LazyRepeatProvider);
8844
8845 if (!(delegate instanceof LazyRepeatDelegate)) {
8846 throw Error('"delegate" parameter must be an instance of LazyRepeatDelegate.');
8847 }
8848
8849 this._wrapperElement = wrapperElement;
8850 this._delegate = delegate;
8851
8852 if (wrapperElement.tagName.toLowerCase() === 'ons-list') {
8853 wrapperElement.classList.add('lazy-list');
8854 }
8855
8856 this._pageContent = this._findPageContentElement(wrapperElement);
8857
8858 if (!this._pageContent) {
8859 throw new Error('ons-lazy-repeat must be a descendant of an <ons-page> or an element.');
8860 }
8861
8862 this._topPositions = [];
8863 this._renderedItems = {};
8864
8865 if (!this._delegate.itemHeight && !this._delegate.calculateItemHeight(0)) {
8866 this._unknownItemHeight = true;
8867 }
8868 this._addEventListeners();
8869 this._onChange();
8870 }
8871
8872 createClass(LazyRepeatProvider, [{
8873 key: '_findPageContentElement',
8874 value: function _findPageContentElement(wrapperElement) {
8875 var pageContent = util.findParent(wrapperElement, '.page__content');
8876
8877 if (pageContent) {
8878 return pageContent;
8879 }
8880
8881 var page = util.findParent(wrapperElement, 'ons-page');
8882 if (page) {
8883 var content = util.findChild(page, '.content');
8884 if (content) {
8885 return content;
8886 }
8887 }
8888
8889 return null;
8890 }
8891 }, {
8892 key: '_checkItemHeight',
8893 value: function _checkItemHeight(callback) {
8894 var _this = this;
8895
8896 this._delegate.loadItemElement(0, this._wrapperElement, function (item) {
8897 if (!_this._unknownItemHeight) {
8898 throw Error('Invalid state');
8899 }
8900
8901 var done = function done() {
8902 _this._wrapperElement.removeChild(item.element);
8903 delete _this._unknownItemHeight;
8904 callback();
8905 };
8906
8907 _this._itemHeight = item.element.offsetHeight;
8908
8909 if (_this._itemHeight > 0) {
8910 done();
8911 return;
8912 }
8913
8914 // retry to measure offset height
8915 // dirty fix for angular2 directive
8916 var lastVisibility = _this._wrapperElement.style.visibility;
8917 _this._wrapperElement.style.visibility = 'hidden';
8918 item.element.style.visibility = 'hidden';
8919
8920 setImmediate(function () {
8921 _this._itemHeight = item.element.offsetHeight;
8922 if (_this._itemHeight == 0) {
8923 throw Error('Invalid state: this._itemHeight must be greater than zero.');
8924 }
8925 _this._wrapperElement.style.visibility = lastVisibility;
8926 done();
8927 });
8928 });
8929 }
8930 }, {
8931 key: '_countItems',
8932 value: function _countItems() {
8933 return this._delegate.countItems();
8934 }
8935 }, {
8936 key: '_getItemHeight',
8937 value: function _getItemHeight(i) {
8938 return this.staticItemHeight || this._delegate.calculateItemHeight(i);
8939 }
8940 }, {
8941 key: '_onChange',
8942 value: function _onChange() {
8943 this._render();
8944 }
8945 }, {
8946 key: 'refresh',
8947 value: function refresh() {
8948 this._removeAllElements();
8949 this._onChange();
8950 }
8951 }, {
8952 key: '_render',
8953 value: function _render() {
8954 var _this2 = this;
8955
8956 if (this._unknownItemHeight) {
8957 return this._checkItemHeight(this._render.bind(this));
8958 }
8959
8960 var items = this._getItemsInView();
8961
8962 if (this._delegate.hasRenderFunction && this._delegate.hasRenderFunction()) {
8963 this._delegate._render(items, this._listHeight);
8964 return null;
8965 }
8966
8967 var keep = {};
8968
8969 items.forEach(function (item) {
8970 _this2._renderElement(item);
8971 keep[item.index] = true;
8972 });
8973
8974 Object.keys(this._renderedItems).forEach(function (key) {
8975 return keep[key] || _this2._removeElement(key);
8976 });
8977
8978 this._wrapperElement.style.height = this._listHeight + 'px';
8979 }
8980
8981 /**
8982 * @param {Object} item
8983 * @param {Number} item.index
8984 * @param {Number} item.top
8985 */
8986
8987 }, {
8988 key: '_renderElement',
8989 value: function _renderElement(_ref) {
8990 var _this3 = this;
8991
8992 var index = _ref.index,
8993 top = _ref.top;
8994
8995 var item = this._renderedItems[index];
8996 if (item) {
8997 this._delegate.updateItem(index, item); // update if it exists
8998 item.element.style.top = top + 'px';
8999 return;
9000 }
9001
9002 this._delegate.loadItemElement(index, this._wrapperElement, function (item) {
9003 util.extend(item.element.style, {
9004 position: 'absolute',
9005 top: top + 'px',
9006 left: 0,
9007 right: 0
9008 });
9009
9010 _this3._renderedItems[index] = item;
9011 });
9012 }
9013
9014 /**
9015 * @param {Number} index
9016 */
9017
9018 }, {
9019 key: '_removeElement',
9020 value: function _removeElement(index) {
9021 var item = this._renderedItems[index];
9022
9023 this._delegate.destroyItem(index, item);
9024
9025 if (item.element.parentElement) {
9026 item.element.parentElement.removeChild(item.element);
9027 }
9028
9029 delete this._renderedItems[index];
9030 }
9031 }, {
9032 key: '_removeAllElements',
9033 value: function _removeAllElements() {
9034 var _this4 = this;
9035
9036 Object.keys(this._renderedItems).forEach(function (key) {
9037 return _this4._removeElement(key);
9038 });
9039 }
9040 }, {
9041 key: '_calculateStartIndex',
9042 value: function _calculateStartIndex(current) {
9043 var start = 0;
9044 var end = this._itemCount - 1;
9045
9046 if (this.staticItemHeight) {
9047 return parseInt(-current / this.staticItemHeight);
9048 }
9049
9050 // Binary search for index at top of screen so we can speed up rendering.
9051 for (;;) {
9052 var middle = Math.floor((start + end) / 2);
9053 var value = current + this._topPositions[middle];
9054
9055 if (end < start) {
9056 return 0;
9057 } else if (value <= 0 && value + this._getItemHeight(middle) > 0) {
9058 return middle;
9059 } else if (isNaN(value) || value >= 0) {
9060 end = middle - 1;
9061 } else {
9062 start = middle + 1;
9063 }
9064 }
9065 }
9066 }, {
9067 key: '_recalculateTopPositions',
9068 value: function _recalculateTopPositions() {
9069 var l = Math.min(this._topPositions.length, this._itemCount);
9070 this._topPositions[0] = 0;
9071 for (var i = 1, _l; i < _l; i++) {
9072 this._topPositions[i] = this._topPositions[i - 1] + this._getItemHeight(i);
9073 }
9074 }
9075 }, {
9076 key: '_getItemsInView',
9077 value: function _getItemsInView() {
9078 var offset = this._wrapperElement.getBoundingClientRect().top;
9079 var limit = 4 * window.innerHeight - offset;
9080 var count = this._countItems();
9081
9082 if (count !== this._itemCount) {
9083 this._itemCount = count;
9084 this._recalculateTopPositions();
9085 }
9086
9087 var i = Math.max(0, this._calculateStartIndex(offset) - 30);
9088
9089 var items = [];
9090 for (var top = this._topPositions[i]; i < count && top < limit; i++) {
9091 if (i >= this._topPositions.length) {
9092 // perf optimization
9093 this._topPositions.length += 100;
9094 }
9095
9096 this._topPositions[i] = top;
9097 items.push({ top: top, index: i });
9098 top += this._getItemHeight(i);
9099 }
9100 this._listHeight = top;
9101
9102 return items;
9103 }
9104 }, {
9105 key: '_debounce',
9106 value: function _debounce(func, wait, immediate) {
9107 var timeout = void 0;
9108 return function () {
9109 var _this5 = this,
9110 _arguments = arguments;
9111
9112 var callNow = immediate && !timeout;
9113 clearTimeout(timeout);
9114 if (callNow) {
9115 func.apply(this, arguments);
9116 } else {
9117 timeout = setTimeout(function () {
9118 timeout = null;
9119 func.apply(_this5, _arguments);
9120 }, wait);
9121 }
9122 };
9123 }
9124 }, {
9125 key: '_doubleFireOnTouchend',
9126 value: function _doubleFireOnTouchend() {
9127 this._render();
9128 this._debounce(this._render.bind(this), 100);
9129 }
9130 }, {
9131 key: '_addEventListeners',
9132 value: function _addEventListeners() {
9133 util.bindListeners(this, ['_onChange', '_doubleFireOnTouchend']);
9134
9135 if (platform.isIOS()) {
9136 this._boundOnChange = this._debounce(this._boundOnChange, 30);
9137 }
9138
9139 this._pageContent.addEventListener('scroll', this._boundOnChange, true);
9140
9141 if (platform.isIOS()) {
9142 this._pageContent.addEventListener('touchmove', this._boundOnChange, true);
9143 this._pageContent.addEventListener('touchend', this._boundDoubleFireOnTouchend, true);
9144 }
9145
9146 window.document.addEventListener('resize', this._boundOnChange, true);
9147 }
9148 }, {
9149 key: '_removeEventListeners',
9150 value: function _removeEventListeners() {
9151 this._pageContent.removeEventListener('scroll', this._boundOnChange, true);
9152
9153 if (platform.isIOS()) {
9154 this._pageContent.removeEventListener('touchmove', this._boundOnChange, true);
9155 this._pageContent.removeEventListener('touchend', this._boundDoubleFireOnTouchend, true);
9156 }
9157
9158 window.document.removeEventListener('resize', this._boundOnChange, true);
9159 }
9160 }, {
9161 key: 'destroy',
9162 value: function destroy() {
9163 this._removeAllElements();
9164 this._delegate.destroy();
9165 this._parentElement = this._delegate = this._renderedItems = null;
9166 this._removeEventListeners();
9167 }
9168 }, {
9169 key: 'staticItemHeight',
9170 get: function get() {
9171 return this._delegate.itemHeight || this._itemHeight;
9172 }
9173 }]);
9174 return LazyRepeatProvider;
9175}();
9176
9177/*
9178Copyright 2013-2015 ASIAL CORPORATION
9179
9180Licensed under the Apache License, Version 2.0 (the "License");
9181you may not use this file except in compliance with the License.
9182You may obtain a copy of the License at
9183
9184 http://www.apache.org/licenses/LICENSE-2.0
9185
9186Unless required by applicable law or agreed to in writing, software
9187distributed under the License is distributed on an "AS IS" BASIS,
9188WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9189See the License for the specific language governing permissions and
9190limitations under the License.
9191
9192*/
9193internal$1.AnimatorFactory = AnimatorFactory;
9194internal$1.ModifierUtil = ModifierUtil;
9195internal$1.LazyRepeatProvider = LazyRepeatProvider;
9196internal$1.LazyRepeatDelegate = LazyRepeatDelegate;
9197
9198/*
9199Copyright 2013-2015 ASIAL CORPORATION
9200
9201Licensed under the Apache License, Version 2.0 (the "License");
9202you may not use this file except in compliance with the License.
9203You may obtain a copy of the License at
9204
9205 http://www.apache.org/licenses/LICENSE-2.0
9206
9207Unless required by applicable law or agreed to in writing, software
9208distributed under the License is distributed on an "AS IS" BASIS,
9209WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9210See the License for the specific language governing permissions and
9211limitations under the License.
9212
9213*/
9214
9215var create = function create() {
9216
9217 /**
9218 * @object ons.orientation
9219 * @category util
9220 * @description
9221 * [en]Utility methods for orientation detection.[/en]
9222 * [ja]画面のオリエンテーション検知のためのユーティリティメソッドを収めているオブジェクトです。[/ja]
9223 */
9224 var obj = {
9225 /**
9226 * @event change
9227 * @description
9228 * [en]Fired when the device orientation changes.[/en]
9229 * [ja]デバイスのオリエンテーションが変化した際に発火します。[/ja]
9230 * @param {Object} event
9231 * [en]Event object.[/en]
9232 * [ja]イベントオブジェクトです。[/ja]
9233 * @param {Boolean} event.isPortrait
9234 * [en]Will be true if the current orientation is portrait mode.[/en]
9235 * [ja]現在のオリエンテーションがportraitの場合にtrueを返します。[/ja]
9236 */
9237
9238 /**
9239 * @method on
9240 * @signature on(eventName, listener)
9241 * @description
9242 * [en]Add an event listener.[/en]
9243 * [ja]イベントリスナーを追加します。[/ja]
9244 * @param {String} eventName
9245 * [en]Name of the event.[/en]
9246 * [ja]イベント名を指定します。[/ja]
9247 * @param {Function} listener
9248 * [en]Function to execute when the event is triggered.[/en]
9249 * [ja]このイベントが発火された際に呼び出される関数オブジェクトを指定します。[/ja]
9250 */
9251
9252 /**
9253 * @method once
9254 * @signature once(eventName, listener)
9255 * @description
9256 * [en]Add an event listener that's only triggered once.[/en]
9257 * [ja]一度だけ呼び出されるイベントリスナーを追加します。[/ja]
9258 * @param {String} eventName
9259 * [en]Name of the event.[/en]
9260 * [ja]イベント名を指定します。[/ja]
9261 * @param {Function} listener
9262 * [en]Function to execute when the event is triggered.[/en]
9263 * [ja]イベントが発火した際に呼び出される関数オブジェクトを指定します。[/ja]
9264 */
9265
9266 /**
9267 * @method off
9268 * @signature off(eventName, [listener])
9269 * @description
9270 * [en]Remove an event listener. If the listener is not specified all listeners for the event type will be removed.[/en]
9271 * [ja]イベントリスナーを削除します。もしイベントリスナーを指定しなかった場合には、そのイベントに紐づく全てのイベントリスナーが削除されます。[/ja]
9272 * @param {String} eventName
9273 * [en]Name of the event.[/en]
9274 * [ja]イベント名を指定します。[/ja]
9275 * @param {Function} listener
9276 * [en]Function to execute when the event is triggered.[/en]
9277 * [ja]削除するイベントリスナーを指定します。[/ja]
9278 */
9279
9280 // actual implementation to detect if whether current screen is portrait or not
9281 _isPortrait: false,
9282
9283 /**
9284 * @method isPortrait
9285 * @signature isPortrait()
9286 * @return {Boolean}
9287 * [en]Will be true if the current orientation is portrait mode.[/en]
9288 * [ja]オリエンテーションがportraitモードの場合にtrueになります。[/ja]
9289 * @description
9290 * [en]Returns whether the current screen orientation is portrait or not.[/en]
9291 * [ja]オリエンテーションがportraitモードかどうかを返します。[/ja]
9292 */
9293 isPortrait: function isPortrait() {
9294 return this._isPortrait();
9295 },
9296
9297 /**
9298 * @method isLandscape
9299 * @signature isLandscape()
9300 * @return {Boolean}
9301 * [en]Will be true if the current orientation is landscape mode.[/en]
9302 * [ja]オリエンテーションがlandscapeモードの場合にtrueになります。[/ja]
9303 * @description
9304 * [en]Returns whether the current screen orientation is landscape or not.[/en]
9305 * [ja]オリエンテーションがlandscapeモードかどうかを返します。[/ja]
9306 */
9307 isLandscape: function isLandscape() {
9308 return !this.isPortrait();
9309 },
9310
9311 _init: function _init() {
9312 document.addEventListener('DOMContentLoaded', this._onDOMContentLoaded.bind(this), false);
9313
9314 if ('orientation' in window) {
9315 window.addEventListener('orientationchange', this._onOrientationChange.bind(this), false);
9316 } else {
9317 window.addEventListener('resize', this._onResize.bind(this), false);
9318 }
9319
9320 this._isPortrait = function () {
9321 return window.innerHeight > window.innerWidth;
9322 };
9323
9324 return this;
9325 },
9326
9327 _onDOMContentLoaded: function _onDOMContentLoaded() {
9328 this._installIsPortraitImplementation();
9329 this.emit('change', { isPortrait: this.isPortrait() });
9330 },
9331
9332 _installIsPortraitImplementation: function _installIsPortraitImplementation() {
9333 var isPortrait = window.innerWidth < window.innerHeight;
9334
9335 if (!('orientation' in window)) {
9336 this._isPortrait = function () {
9337 return window.innerHeight > window.innerWidth;
9338 };
9339 } else if (window.orientation % 180 === 0) {
9340 this._isPortrait = function () {
9341 return Math.abs(window.orientation % 180) === 0 ? isPortrait : !isPortrait;
9342 };
9343 } else {
9344 this._isPortrait = function () {
9345 return Math.abs(window.orientation % 180) === 90 ? isPortrait : !isPortrait;
9346 };
9347 }
9348 },
9349
9350 _onOrientationChange: function _onOrientationChange() {
9351 var _this = this;
9352
9353 var isPortrait = this._isPortrait();
9354
9355 // Wait for the dimensions to change because
9356 // of Android inconsistency.
9357 var nIter = 0;
9358 var interval = setInterval(function () {
9359 nIter++;
9360
9361 var w = window.innerWidth;
9362 var h = window.innerHeight;
9363
9364 if (isPortrait && w <= h || !isPortrait && w >= h) {
9365 _this.emit('change', { isPortrait: isPortrait });
9366 clearInterval(interval);
9367 } else if (nIter === 50) {
9368 _this.emit('change', { isPortrait: isPortrait });
9369 clearInterval(interval);
9370 }
9371 }, 20);
9372 },
9373
9374 // Run on not mobile browser.
9375 _onResize: function _onResize() {
9376 this.emit('change', { isPortrait: this.isPortrait() });
9377 }
9378 };
9379
9380 MicroEvent.mixin(obj);
9381
9382 return obj;
9383};
9384
9385var orientation = create()._init();
9386
9387/*
9388Copyright 2013-2015 ASIAL CORPORATION
9389
9390Licensed under the Apache License, Version 2.0 (the "License");
9391you may not use this file except in compliance with the License.
9392You may obtain a copy of the License at
9393
9394 http://www.apache.org/licenses/LICENSE-2.0
9395
9396Unless required by applicable law or agreed to in writing, software
9397distributed under the License is distributed on an "AS IS" BASIS,
9398WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9399See the License for the specific language governing permissions and
9400limitations under the License.
9401
9402*/
9403
9404var softwareKeyboard = new MicroEvent();
9405softwareKeyboard._visible = false;
9406
9407var onShow = function onShow() {
9408 softwareKeyboard._visible = true;
9409 softwareKeyboard.emit('show');
9410};
9411
9412var onHide = function onHide() {
9413 softwareKeyboard._visible = false;
9414 softwareKeyboard.emit('hide');
9415};
9416
9417var bindEvents = function bindEvents() {
9418 if (typeof Keyboard !== 'undefined') {
9419 // https://github.com/martinmose/cordova-keyboard/blob/95f3da3a38d8f8e1fa41fbf40145352c13535a00/README.md
9420 Keyboard.onshow = onShow;
9421 Keyboard.onhide = onHide;
9422 softwareKeyboard.emit('init', { visible: Keyboard.isVisible });
9423
9424 return true;
9425 } else if (typeof cordova.plugins !== 'undefined' && typeof cordova.plugins.Keyboard !== 'undefined') {
9426 // https://github.com/driftyco/ionic-plugins-keyboard/blob/ca27ecf/README.md
9427 window.addEventListener('native.keyboardshow', onShow);
9428 window.addEventListener('native.keyboardhide', onHide);
9429 softwareKeyboard.emit('init', { visible: cordova.plugins.Keyboard.isVisible });
9430
9431 return true;
9432 }
9433
9434 return false;
9435};
9436
9437var noPluginError = function noPluginError() {
9438 console.warn('ons-keyboard: Cordova Keyboard plugin is not present.');
9439};
9440
9441document.addEventListener('deviceready', function () {
9442 if (!bindEvents()) {
9443 if (document.querySelector('[ons-keyboard-active]') || document.querySelector('[ons-keyboard-inactive]')) {
9444 noPluginError();
9445 }
9446
9447 softwareKeyboard.on = noPluginError;
9448 }
9449});
9450
9451/*
9452Copyright 2013-2015 ASIAL CORPORATION
9453
9454Licensed under the Apache License, Version 2.0 (the "License");
9455you may not use this file except in compliance with the License.
9456You may obtain a copy of the License at
9457
9458 http://www.apache.org/licenses/LICENSE-2.0
9459
9460Unless required by applicable law or agreed to in writing, software
9461distributed under the License is distributed on an "AS IS" BASIS,
9462WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9463See the License for the specific language governing permissions and
9464limitations under the License.
9465
9466*/
9467
9468var util$2 = {
9469 _ready: false,
9470
9471 _domContentLoaded: false,
9472
9473 _onDOMContentLoaded: function _onDOMContentLoaded() {
9474 util$2._domContentLoaded = true;
9475
9476 if (platform.isWebView()) {
9477 window.document.addEventListener('deviceready', function () {
9478 util$2._ready = true;
9479 }, false);
9480 } else {
9481 util$2._ready = true;
9482 }
9483 },
9484
9485 addBackButtonListener: function addBackButtonListener(fn) {
9486 if (!this._domContentLoaded) {
9487 throw new Error('This method is available after DOMContentLoaded');
9488 }
9489
9490 if (this._ready) {
9491 window.document.addEventListener('backbutton', fn, false);
9492 } else {
9493 window.document.addEventListener('deviceready', function () {
9494 window.document.addEventListener('backbutton', fn, false);
9495 });
9496 }
9497 },
9498
9499 removeBackButtonListener: function removeBackButtonListener(fn) {
9500 if (!this._domContentLoaded) {
9501 throw new Error('This method is available after DOMContentLoaded');
9502 }
9503
9504 if (this._ready) {
9505 window.document.removeEventListener('backbutton', fn, false);
9506 } else {
9507 window.document.addEventListener('deviceready', function () {
9508 window.document.removeEventListener('backbutton', fn, false);
9509 });
9510 }
9511 }
9512};
9513window.addEventListener('DOMContentLoaded', function () {
9514 return util$2._onDOMContentLoaded();
9515}, false);
9516
9517var HandlerRepository = {
9518 _store: {},
9519
9520 _genId: function () {
9521 var i = 0;
9522 return function () {
9523 return i++;
9524 };
9525 }(),
9526
9527 set: function set(element, handler) {
9528 if (element.dataset.deviceBackButtonHandlerId) {
9529 this.remove(element);
9530 }
9531 var id = element.dataset.deviceBackButtonHandlerId = HandlerRepository._genId();
9532 this._store[id] = handler;
9533 },
9534
9535 remove: function remove(element) {
9536 if (element.dataset.deviceBackButtonHandlerId) {
9537 delete this._store[element.dataset.deviceBackButtonHandlerId];
9538 delete element.dataset.deviceBackButtonHandlerId;
9539 }
9540 },
9541
9542 get: function get(element) {
9543 if (!element.dataset.deviceBackButtonHandlerId) {
9544 return undefined;
9545 }
9546
9547 var id = element.dataset.deviceBackButtonHandlerId;
9548
9549 if (!this._store[id]) {
9550 throw new Error();
9551 }
9552
9553 return this._store[id];
9554 },
9555
9556 has: function has(element) {
9557 if (!element.dataset) {
9558 return false;
9559 }
9560
9561 var id = element.dataset.deviceBackButtonHandlerId;
9562
9563 return !!this._store[id];
9564 }
9565};
9566
9567var DeviceBackButtonDispatcher = function () {
9568 function DeviceBackButtonDispatcher() {
9569 classCallCheck(this, DeviceBackButtonDispatcher);
9570
9571 this._isEnabled = false;
9572 this._boundCallback = this._callback.bind(this);
9573 }
9574
9575 /**
9576 * Enable to handle 'backbutton' events.
9577 */
9578
9579
9580 createClass(DeviceBackButtonDispatcher, [{
9581 key: 'enable',
9582 value: function enable() {
9583 if (!this._isEnabled) {
9584 util$2.addBackButtonListener(this._boundCallback);
9585 this._isEnabled = true;
9586 }
9587 }
9588
9589 /**
9590 * Disable to handle 'backbutton' events.
9591 */
9592
9593 }, {
9594 key: 'disable',
9595 value: function disable() {
9596 if (this._isEnabled) {
9597 util$2.removeBackButtonListener(this._boundCallback);
9598 this._isEnabled = false;
9599 }
9600 }
9601
9602 /**
9603 * Fire a 'backbutton' event manually.
9604 */
9605
9606 }, {
9607 key: 'fireDeviceBackButtonEvent',
9608 value: function fireDeviceBackButtonEvent() {
9609 var event = document.createEvent('Event');
9610 event.initEvent('backbutton', true, true);
9611 document.dispatchEvent(event);
9612 }
9613 }, {
9614 key: '_callback',
9615 value: function _callback() {
9616 this._dispatchDeviceBackButtonEvent();
9617 }
9618
9619 /**
9620 * @param {HTMLElement} element
9621 * @param {Function} callback
9622 */
9623
9624 }, {
9625 key: 'createHandler',
9626 value: function createHandler(element, callback) {
9627 if (!(element instanceof HTMLElement)) {
9628 throw new Error('element must be an instance of HTMLElement');
9629 }
9630
9631 if (!(callback instanceof Function)) {
9632 throw new Error('callback must be an instance of Function');
9633 }
9634
9635 var handler = {
9636 _callback: callback,
9637 _element: element,
9638
9639 disable: function disable() {
9640 HandlerRepository.remove(element);
9641 },
9642
9643 setListener: function setListener(callback) {
9644 this._callback = callback;
9645 },
9646
9647 enable: function enable() {
9648 HandlerRepository.set(element, this);
9649 },
9650
9651 isEnabled: function isEnabled() {
9652 return HandlerRepository.get(element) === this;
9653 },
9654
9655 destroy: function destroy() {
9656 HandlerRepository.remove(element);
9657 this._callback = this._element = null;
9658 }
9659 };
9660
9661 handler.enable();
9662
9663 return handler;
9664 }
9665 }, {
9666 key: '_dispatchDeviceBackButtonEvent',
9667 value: function _dispatchDeviceBackButtonEvent() {
9668 var tree = this._captureTree();
9669
9670 var element = this._findHandlerLeafElement(tree);
9671
9672 var handler = HandlerRepository.get(element);
9673 handler._callback(createEvent(element));
9674
9675 function createEvent(element) {
9676 return {
9677 _element: element,
9678 callParentHandler: function callParentHandler() {
9679 var parent = this._element.parentNode;
9680
9681 while (parent) {
9682 handler = HandlerRepository.get(parent);
9683 if (handler) {
9684 return handler._callback(createEvent(parent));
9685 }
9686 parent = parent.parentNode;
9687 }
9688 }
9689 };
9690 }
9691 }
9692
9693 /**
9694 * @return {Object}
9695 */
9696
9697 }, {
9698 key: '_captureTree',
9699 value: function _captureTree() {
9700 return createTree(document.body);
9701
9702 function createTree(element) {
9703 return {
9704 element: element,
9705 children: Array.prototype.concat.apply([], arrayOf(element.children).map(function (childElement) {
9706
9707 if (childElement.style.display === 'none') {
9708 return [];
9709 }
9710
9711 if (childElement.children.length === 0 && !HandlerRepository.has(childElement)) {
9712 return [];
9713 }
9714
9715 var result = createTree(childElement);
9716
9717 if (result.children.length === 0 && !HandlerRepository.has(result.element)) {
9718 return [];
9719 }
9720
9721 return [result];
9722 }))
9723 };
9724 }
9725
9726 function arrayOf(target) {
9727 var result = [];
9728 for (var i = 0; i < target.length; i++) {
9729 result.push(target[i]);
9730 }
9731 return result;
9732 }
9733 }
9734
9735 /**
9736 * @param {Object} tree
9737 * @return {HTMLElement}
9738 */
9739
9740 }, {
9741 key: '_findHandlerLeafElement',
9742 value: function _findHandlerLeafElement(tree) {
9743 return find(tree);
9744
9745 function find(node) {
9746 if (node.children.length === 0) {
9747 return node.element;
9748 }
9749
9750 if (node.children.length === 1) {
9751 return find(node.children[0]);
9752 }
9753
9754 return node.children.map(function (childNode) {
9755 return childNode.element;
9756 }).reduce(function (left, right) {
9757 if (!left) {
9758 return right;
9759 }
9760
9761 var leftZ = parseInt(window.getComputedStyle(left, '').zIndex, 10);
9762 var rightZ = parseInt(window.getComputedStyle(right, '').zIndex, 10);
9763
9764 if (!isNaN(leftZ) && !isNaN(rightZ)) {
9765 return leftZ > rightZ ? left : right;
9766 }
9767
9768 throw new Error('Capturing backbutton-handler is failure.');
9769 }, null);
9770 }
9771 }
9772 }]);
9773 return DeviceBackButtonDispatcher;
9774}();
9775
9776var deviceBackButtonDispatcher = new DeviceBackButtonDispatcher();
9777
9778/*
9779Copyright 2013-2015 ASIAL CORPORATION
9780
9781Licensed under the Apache License, Version 2.0 (the "License");
9782you may not use this file except in compliance with the License.
9783You may obtain a copy of the License at
9784
9785 http://www.apache.org/licenses/LICENSE-2.0
9786
9787Unless required by applicable law or agreed to in writing, software
9788distributed under the License is distributed on an "AS IS" BASIS,
9789WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9790See the License for the specific language governing permissions and
9791limitations under the License.
9792
9793*/
9794
9795var autoStyleEnabled = true;
9796
9797// Modifiers
9798var modifiersMap = {
9799 'quiet': 'material--flat',
9800 'light': 'material--flat',
9801 'outline': 'material--flat',
9802 'cta': '',
9803 'large--quiet': 'material--flat large',
9804 'large--cta': 'large',
9805 'noborder': '',
9806 'chevron': '',
9807 'tappable': ''
9808};
9809
9810var platforms = {};
9811
9812platforms.android = function (element) {
9813
9814 if (!/ons-fab|ons-speed-dial|ons-progress/.test(element.tagName.toLowerCase()) && !/material/.test(element.getAttribute('modifier'))) {
9815
9816 var oldModifier = element.getAttribute('modifier') || '';
9817
9818 var newModifier = oldModifier.trim().split(/\s+/).map(function (e) {
9819 return modifiersMap.hasOwnProperty(e) ? modifiersMap[e] : e;
9820 });
9821 newModifier.unshift('material');
9822
9823 element.setAttribute('modifier', newModifier.join(' ').trim());
9824 }
9825
9826 // Effects
9827 if (/ons-button|ons-list-item|ons-fab|ons-speed-dial|ons-tab$/.test(element.tagName.toLowerCase()) && !element.hasAttribute('ripple') && !util.findChild(element, 'ons-ripple')) {
9828
9829 if (element.tagName.toLowerCase() === 'ons-list-item') {
9830 if (element.hasAttribute('tappable')) {
9831 element.setAttribute('ripple', '');
9832 element.removeAttribute('tappable');
9833 }
9834 } else {
9835 element.setAttribute('ripple', '');
9836 }
9837 }
9838};
9839
9840platforms.ios = function (element) {
9841
9842 // Modifiers
9843 if (/material/.test(element.getAttribute('modifier'))) {
9844 util.removeModifier(element, 'material');
9845
9846 if (util.removeModifier(element, 'material--flat')) {
9847 util.addModifier(element, util.removeModifier(element, 'large') ? 'large--quiet' : 'quiet');
9848 }
9849
9850 if (!element.getAttribute('modifier')) {
9851 element.removeAttribute('modifier');
9852 }
9853 }
9854
9855 // Effects
9856 if (element.hasAttribute('ripple')) {
9857 if (element.tagName.toLowerCase() === 'ons-list-item') {
9858 element.setAttribute('tappable', '');
9859 }
9860
9861 element.removeAttribute('ripple');
9862 }
9863};
9864
9865var unlocked = {
9866 android: true
9867};
9868
9869var prepareAutoStyle = function prepareAutoStyle(element, force) {
9870 if (autoStyleEnabled && !element.hasAttribute('disable-auto-styling')) {
9871 var mobileOS = platform.getMobileOS();
9872 if (platforms.hasOwnProperty(mobileOS) && (unlocked.hasOwnProperty(mobileOS) || force)) {
9873 platforms[mobileOS](element);
9874 }
9875 }
9876};
9877
9878var autoStyle = {
9879 isEnabled: function isEnabled() {
9880 return autoStyleEnabled;
9881 },
9882 enable: function enable() {
9883 return autoStyleEnabled = true;
9884 },
9885 disable: function disable() {
9886 return autoStyleEnabled = false;
9887 },
9888 prepare: prepareAutoStyle
9889};
9890
9891/*
9892Copyright 2013-2015 ASIAL CORPORATION
9893
9894Licensed under the Apache License, Version 2.0 (the "License");
9895you may not use this file except in compliance with the License.
9896You may obtain a copy of the License at
9897
9898 http://www.apache.org/licenses/LICENSE-2.0
9899
9900Unless required by applicable law or agreed to in writing, software
9901distributed under the License is distributed on an "AS IS" BASIS,
9902WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9903See the License for the specific language governing permissions and
9904limitations under the License.
9905
9906*/
9907
9908var generateId = function () {
9909 var i = 0;
9910 return function () {
9911 return i++;
9912 };
9913}();
9914
9915/**
9916 * Door locking system.
9917 *
9918 * @param {Object} [options]
9919 * @param {Function} [options.log]
9920 */
9921
9922var DoorLock = function () {
9923 function DoorLock() {
9924 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
9925 classCallCheck(this, DoorLock);
9926
9927 this._lockList = [];
9928 this._waitList = [];
9929 this._log = options.log || function () {};
9930 }
9931
9932 /**
9933 * Register a lock.
9934 *
9935 * @return {Function} Callback for unlocking.
9936 */
9937
9938
9939 createClass(DoorLock, [{
9940 key: 'lock',
9941 value: function lock() {
9942 var _this = this;
9943
9944 var unlock = function unlock() {
9945 _this._unlock(unlock);
9946 };
9947 unlock.id = generateId();
9948 this._lockList.push(unlock);
9949 this._log('lock: ' + unlock.id);
9950
9951 return unlock;
9952 }
9953 }, {
9954 key: '_unlock',
9955 value: function _unlock(fn) {
9956 var index = this._lockList.indexOf(fn);
9957 if (index === -1) {
9958 throw new Error('This function is not registered in the lock list.');
9959 }
9960
9961 this._lockList.splice(index, 1);
9962 this._log('unlock: ' + fn.id);
9963
9964 this._tryToFreeWaitList();
9965 }
9966 }, {
9967 key: '_tryToFreeWaitList',
9968 value: function _tryToFreeWaitList() {
9969 while (!this.isLocked() && this._waitList.length > 0) {
9970 this._waitList.shift()();
9971 }
9972 }
9973
9974 /**
9975 * Register a callback for waiting unlocked door.
9976 *
9977 * @params {Function} callback Callback on unlocking the door completely.
9978 */
9979
9980 }, {
9981 key: 'waitUnlock',
9982 value: function waitUnlock(callback) {
9983 if (!(callback instanceof Function)) {
9984 throw new Error('The callback param must be a function.');
9985 }
9986
9987 if (this.isLocked()) {
9988 this._waitList.push(callback);
9989 } else {
9990 callback();
9991 }
9992 }
9993
9994 /**
9995 * @return {Boolean}
9996 */
9997
9998 }, {
9999 key: 'isLocked',
10000 value: function isLocked() {
10001 return this._lockList.length > 0;
10002 }
10003 }]);
10004 return DoorLock;
10005}();
10006
10007/*
10008Copyright 2013-2015 ASIAL CORPORATION
10009
10010Licensed under the Apache License, Version 2.0 (the "License");
10011you may not use this file except in compliance with the License.
10012You may obtain a copy of the License at
10013
10014 http://www.apache.org/licenses/LICENSE-2.0
10015
10016Unless required by applicable law or agreed to in writing, software
10017distributed under the License is distributed on an "AS IS" BASIS,
10018WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10019See the License for the specific language governing permissions and
10020limitations under the License.
10021
10022*/
10023// Default implementation for global PageLoader.
10024function loadPage$1(_ref, done) {
10025 var page = _ref.page,
10026 parent = _ref.parent,
10027 _ref$params = _ref.params,
10028 params = _ref$params === undefined ? {} : _ref$params,
10029 replace = _ref.replace;
10030
10031 internal$1.getPageHTMLAsync(page).then(function (html) {
10032 if (replace) {
10033 util.propagateAction(parent, '_destroy');
10034 parent.innerHTML = '';
10035 }
10036
10037 var element = util.createElement(html.trim());
10038 parent.appendChild(element);
10039
10040 done({
10041 element: element,
10042 unload: function unload() {
10043 return element.remove();
10044 }
10045 });
10046 });
10047}
10048
10049var PageLoader = function () {
10050 /**
10051 * @param {Function} [fn] Returns an object that has "element" property and "unload" function.
10052 */
10053 function PageLoader(fn) {
10054 classCallCheck(this, PageLoader);
10055
10056 this._loader = fn instanceof Function ? fn : loadPage$1;
10057 }
10058
10059 /**
10060 * Set internal loader implementation.
10061 */
10062
10063
10064 createClass(PageLoader, [{
10065 key: 'load',
10066
10067
10068 /**
10069 * @param {any} options.page
10070 * @param {Element} options.parent A location to load page.
10071 * @param {Object} [options.params] Extra parameters for ons-page.
10072 * @param {Boolean} [options.replace] Remove the previous content.
10073 * @param {Function} done Take an object that has "element" property and "unload" function.
10074 */
10075 value: function load(_ref2, done) {
10076 var page = _ref2.page,
10077 parent = _ref2.parent,
10078 _ref2$params = _ref2.params,
10079 params = _ref2$params === undefined ? {} : _ref2$params,
10080 replace = _ref2.replace;
10081
10082 this._loader({ page: page, parent: parent, params: params, replace: replace }, function (result) {
10083 if (!(result.element instanceof Element)) {
10084 throw Error('target.element must be an instance of Element.');
10085 }
10086
10087 if (!(result.unload instanceof Function)) {
10088 throw Error('target.unload must be an instance of Function.');
10089 }
10090
10091 done(result);
10092 }, params);
10093 }
10094 }, {
10095 key: 'internalLoader',
10096 set: function set(fn) {
10097 if (!(fn instanceof Function)) {
10098 throw Error('First parameter must be an instance of Function');
10099 }
10100 this._loader = fn;
10101 },
10102 get: function get() {
10103 return this._loader;
10104 }
10105 }]);
10106 return PageLoader;
10107}();
10108
10109var defaultPageLoader = new PageLoader();
10110
10111var instantPageLoader = new PageLoader(function (_ref3, done) {
10112 var page = _ref3.page,
10113 parent = _ref3.parent,
10114 _ref3$params = _ref3.params,
10115 params = _ref3$params === undefined ? {} : _ref3$params,
10116 replace = _ref3.replace;
10117
10118 if (replace) {
10119 util.propagateAction(parent, '_destroy');
10120 parent.innerHTML = '';
10121 }
10122
10123 var element = util.createElement(page.trim());
10124 parent.appendChild(element);
10125
10126 done({
10127 element: element,
10128 unload: function unload() {
10129 return element.remove();
10130 }
10131 });
10132});
10133
10134/*
10135Copyright 2013-2015 ASIAL CORPORATION
10136
10137Licensed under the Apache License, Version 2.0 (the "License");
10138you may not use this file except in compliance with the License.
10139You may obtain a copy of the License at
10140
10141 http://www.apache.org/licenses/LICENSE-2.0
10142
10143Unless required by applicable law or agreed to in writing, software
10144distributed under the License is distributed on an "AS IS" BASIS,
10145WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10146See the License for the specific language governing permissions and
10147limitations under the License.
10148
10149*/
10150
10151/**
10152 * @object ons
10153 * @category util
10154 * @description
10155 * [ja]Onsen UIで利用できるグローバルなオブジェクトです。[/ja]
10156 * [en]A global object that's used in Onsen UI. [/en]
10157 */
10158var ons$1 = {};
10159
10160ons$1._util = util;
10161ons$1._deviceBackButtonDispatcher = deviceBackButtonDispatcher;
10162ons$1._internal = internal$1;
10163ons$1.GestureDetector = GestureDetector;
10164ons$1.platform = platform;
10165ons$1.softwareKeyboard = softwareKeyboard;
10166ons$1.pageAttributeExpression = pageAttributeExpression;
10167ons$1.orientation = orientation;
10168ons$1.notification = notification;
10169ons$1._animationOptionsParser = parse;
10170ons$1._autoStyle = autoStyle;
10171ons$1._DoorLock = DoorLock;
10172ons$1._contentReady = contentReady;
10173ons$1.defaultPageLoader = defaultPageLoader;
10174ons$1.PageLoader = PageLoader;
10175
10176ons$1._readyLock = new DoorLock();
10177
10178ons$1.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]);
10179
10180waitDeviceReady();
10181
10182/**
10183 * @method isReady
10184 * @signature isReady()
10185 * @return {Boolean}
10186 * [en]Will be true if Onsen UI is initialized.[/en]
10187 * [ja]初期化されているかどうかを返します。[/ja]
10188 * @description
10189 * [en]Returns true if Onsen UI is initialized.[/en]
10190 * [ja]Onsen UIがすでに初期化されているかどうかを返すメソッドです。[/ja]
10191 */
10192ons$1.isReady = function () {
10193 return !ons$1._readyLock.isLocked();
10194};
10195
10196/**
10197 * @method isWebView
10198 * @signature isWebView()
10199 * @return {Boolean}
10200 * [en]Will be true if the app is running in Cordova.[/en]
10201 * [ja]Cordovaで実行されている場合にtrueになります。[/ja]
10202 * @description
10203 * [en]Returns true if running inside Cordova.[/en]
10204 * [ja]Cordovaで実行されているかどうかを返すメソッドです。[/ja]
10205 */
10206ons$1.isWebView = ons$1.platform.isWebView;
10207
10208/**
10209 * @method ready
10210 * @signature ready(callback)
10211 * @description
10212 * [ja]アプリの初期化に利用するメソッドです。渡された関数は、Onsen UIの初期化が終了している時点で必ず呼ばれます。[/ja]
10213 * [en]Method used to wait for app initialization. The callback will not be executed until Onsen UI has been completely initialized.[/en]
10214 * @param {Function} callback
10215 * [en]Function that executes after Onsen UI has been initialized.[/en]
10216 * [ja]Onsen UIが初期化が完了した後に呼び出される関数オブジェクトを指定します。[/ja]
10217 */
10218ons$1.ready = function (callback) {
10219 if (ons$1.isReady()) {
10220 callback();
10221 } else {
10222 ons$1._readyLock.waitUnlock(callback);
10223 }
10224};
10225
10226/**
10227 * @method setDefaultDeviceBackButtonListener
10228 * @signature setDefaultDeviceBackButtonListener(listener)
10229 * @param {Function} listener
10230 * [en]Function that executes when device back button is pressed.[/en]
10231 * [ja]デバイスのバックボタンが押された時に実行される関数オブジェクトを指定します。[/ja]
10232 * @description
10233 * [en]Set default handler for device back button.[/en]
10234 * [ja]デバイスのバックボタンのためのデフォルトのハンドラを設定します。[/ja]
10235 */
10236ons$1.setDefaultDeviceBackButtonListener = function (listener) {
10237 ons$1._defaultDeviceBackButtonHandler.setListener(listener);
10238};
10239
10240/**
10241 * @method disableDeviceBackButtonHandler
10242 * @signature disableDeviceBackButtonHandler()
10243 * @description
10244 * [en]Disable device back button event handler.[/en]
10245 * [ja]デバイスのバックボタンのイベントを受け付けないようにします。[/ja]
10246 */
10247ons$1.disableDeviceBackButtonHandler = function () {
10248 ons$1._deviceBackButtonDispatcher.disable();
10249};
10250
10251/**
10252 * @method enableDeviceBackButtonHandler
10253 * @signature enableDeviceBackButtonHandler()
10254 * @description
10255 * [en]Enable device back button event handler.[/en]
10256 * [ja]デバイスのバックボタンのイベントを受け付けるようにします。[/ja]
10257 */
10258ons$1.enableDeviceBackButtonHandler = function () {
10259 ons$1._deviceBackButtonDispatcher.enable();
10260};
10261
10262/**
10263 * @method enableAutoStatusBarFill
10264 * @signature enableAutoStatusBarFill()
10265 * @description
10266 * [en]Enable status bar fill feature on iOS7 and above.[/en]
10267 * [ja]iOS7以上で、ステータスバー部分の高さを自動的に埋める処理を有効にします。[/ja]
10268 */
10269ons$1.enableAutoStatusBarFill = function () {
10270 if (ons$1.isReady()) {
10271 throw new Error('This method must be called before ons.isReady() is true.');
10272 }
10273 ons$1._internal.config.autoStatusBarFill = true;
10274};
10275
10276/**
10277 * @method disableAutoStatusBarFill
10278 * @signature disableAutoStatusBarFill()
10279 * @description
10280 * [en]Disable status bar fill feature on iOS7 and above.[/en]
10281 * [ja]iOS7以上で、ステータスバー部分の高さを自動的に埋める処理を無効にします。[/ja]
10282 */
10283ons$1.disableAutoStatusBarFill = function () {
10284 if (ons$1.isReady()) {
10285 throw new Error('This method must be called before ons.isReady() is true.');
10286 }
10287 ons$1._internal.config.autoStatusBarFill = false;
10288};
10289
10290/**
10291 * @method disableAnimations
10292 * @signature disableAnimations()
10293 * @description
10294 * [en]Disable all animations. Could be handy for testing and older devices.[/en]
10295 * [ja]アニメーションを全て無効にします。テストの際に便利です。[/ja]
10296 */
10297ons$1.disableAnimations = function () {
10298 ons$1._internal.config.animationsDisabled = true;
10299};
10300
10301/**
10302 * @method enableAnimations
10303 * @signature enableAnimations()
10304 * @description
10305 * [en]Enable animations (default).[/en]
10306 * [ja]アニメーションを有効にします。[/ja]
10307 */
10308ons$1.enableAnimations = function () {
10309 ons$1._internal.config.animationsDisabled = false;
10310};
10311
10312/**
10313 * @method disableAutoStyling
10314 * @signature disableAutoStyling()
10315 * @description
10316 * [en]Disable automatic styling.[/en]
10317 * [ja][/ja]
10318 */
10319ons$1.disableAutoStyling = ons$1._autoStyle.disable;
10320
10321/**
10322 * @method enableAutoStyling
10323 * @signature enableAutoStyling()
10324 * @description
10325 * [en]Enable automatic styling based on OS (default).[/en]
10326 * [ja][/ja]
10327 */
10328ons$1.enableAutoStyling = ons$1._autoStyle.enable;
10329
10330/**
10331 * @method forcePlatformStyling
10332 * @signature forcePlatformStyling(platform)
10333 * @description
10334 * [en]Refresh styling for the given platform.[/en]
10335 * [ja][/ja]
10336 * @param {string} platform New platform to style the elements.
10337 */
10338ons$1.forcePlatformStyling = function (newPlatform) {
10339 ons$1.enableAutoStyling();
10340 ons$1.platform.select(newPlatform || 'ios');
10341
10342 ons$1._util.arrayFrom(document.querySelectorAll('*')).forEach(function (element) {
10343 if (element.tagName.toLowerCase() === 'ons-if') {
10344 element._platformUpdate();
10345 } else if (element.tagName.match(/^ons-/i)) {
10346 ons$1._autoStyle.prepare(element, true);
10347 if (element.tagName.toLowerCase() === 'ons-tabbar') {
10348 element._updatePosition();
10349 }
10350 }
10351 });
10352};
10353
10354/**
10355 * @param {String} page
10356 * @param {Object} [options]
10357 * @param {Function} [options.link]
10358 * @return {Promise}
10359 */
10360ons$1._createPopoverOriginal = function (page) {
10361 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10362
10363
10364 if (!page) {
10365 throw new Error('Page url must be defined.');
10366 }
10367
10368 return ons$1._internal.getPageHTMLAsync(page).then(function (html) {
10369 html = html.match(/<ons-popover/gi) ? '<div>' + html + '</div>' : '<ons-popover>' + html + '</ons-popover>';
10370 var div = ons$1._util.createElement('<div>' + html + '</div>');
10371
10372 var popover = div.querySelector('ons-popover');
10373 document.body.appendChild(popover);
10374
10375 if (options.link instanceof Function) {
10376 options.link(popover);
10377 }
10378
10379 return popover;
10380 });
10381};
10382
10383/**
10384 * @method createPopover
10385 * @signature createPopover(page, [options])
10386 * @param {String} page
10387 * [en]Page name. Can be either an HTML file or an <ons-template> containing a <ons-dialog> component.[/en]
10388 * [ja]pageのURLか、もしくはons-templateで宣言したテンプレートのid属性の値を指定できます。[/ja]
10389 * @param {Object} [options]
10390 * [en]Parameter object.[/en]
10391 * [ja]オプションを指定するオブジェクト。[/ja]
10392 * @param {Object} [options.parentScope]
10393 * [en]Parent scope of the dialog. Used to bind models and access scope methods from the dialog.[/en]
10394 * [ja]ダイアログ内で利用する親スコープを指定します。ダイアログからモデルやスコープのメソッドにアクセスするのに使います。このパラメータはAngularJSバインディングでのみ利用できます。[/ja]
10395 * @return {Promise}
10396 * [en]Promise object that resolves to the popover component object.[/en]
10397 * [ja]ポップオーバーのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
10398 * @description
10399 * [en]Create a popover instance from a template.[/en]
10400 * [ja]テンプレートからポップオーバーのインスタンスを生成します。[/ja]
10401 */
10402ons$1.createPopover = ons$1._createPopoverOriginal;
10403
10404/**
10405 * @param {String} page
10406 * @param {Object} [options]
10407 * @param {Function} [options.link]
10408 * @return {Promise}
10409 */
10410ons$1._createDialogOriginal = function (page) {
10411 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10412
10413
10414 if (!page) {
10415 throw new Error('Page url must be defined.');
10416 }
10417
10418 return ons$1._internal.getPageHTMLAsync(page).then(function (html) {
10419 html = html.match(/<ons-dialog/gi) ? '<div>' + html + '</div>' : '<ons-dialog>' + html + '</ons-dialog>';
10420 var div = ons$1._util.createElement('<div>' + html + '</div>');
10421
10422 var dialog = div.querySelector('ons-dialog');
10423 document.body.appendChild(dialog);
10424
10425 if (options.link instanceof Function) {
10426 options.link(dialog);
10427 }
10428
10429 return dialog;
10430 });
10431};
10432
10433/**
10434 * @method createDialog
10435 * @signature createDialog(page, [options])
10436 * @param {String} page
10437 * [en]Page name. Can be either an HTML file or an <ons-template> containing a <ons-dialog> component.[/en]
10438 * [ja]pageのURLか、もしくはons-templateで宣言したテンプレートのid属性の値を指定できます。[/ja]
10439 * @param {Object} [options]
10440 * [en]Parameter object.[/en]
10441 * [ja]オプションを指定するオブジェクト。[/ja]
10442 * @return {Promise}
10443 * [en]Promise object that resolves to the dialog component object.[/en]
10444 * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
10445 * @description
10446 * [en]Create a dialog instance from a template.[/en]
10447 * [ja]テンプレートからダイアログのインスタンスを生成します。[/ja]
10448 */
10449ons$1.createDialog = ons$1._createDialogOriginal;
10450
10451/**
10452 * @param {String} page
10453 * @param {Object} [options]
10454 * @param {Function} [options.link]
10455 * @return {Promise}
10456 */
10457ons$1._createAlertDialogOriginal = function (page) {
10458 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10459
10460
10461 if (!page) {
10462 throw new Error('Page url must be defined.');
10463 }
10464
10465 return ons$1._internal.getPageHTMLAsync(page).then(function (html) {
10466 html = html.match(/<ons-alert-dialog/gi) ? '<div>' + html + '</div>' : '<ons-alert-dialog>' + html + '</ons-alert-dialog>';
10467 var div = ons$1._util.createElement('<div>' + html + '</div>');
10468
10469 var alertDialog = div.querySelector('ons-alert-dialog');
10470 document.body.appendChild(alertDialog);
10471
10472 if (options.link instanceof Function) {
10473 options.link(alertDialog);
10474 }
10475
10476 return alertDialog;
10477 });
10478};
10479
10480/**
10481 * @method createAlertDialog
10482 * @signature createAlertDialog(page, [options])
10483 * @param {String} page
10484 * [en]Page name. Can be either an HTML file or an <ons-template> containing a <ons-alert-dialog> component.[/en]
10485 * [ja]pageのURLか、もしくはons-templateで宣言したテンプレートのid属性の値を指定できます。[/ja]
10486 * @param {Object} [options]
10487 * [en]Parameter object.[/en]
10488 * [ja]オプションを指定するオブジェクト。[/ja]
10489 * @return {Promise}
10490 * [en]Promise object that resolves to the alert dialog component object.[/en]
10491 * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja]
10492 * @description
10493 * [en]Create a alert dialog instance from a template.[/en]
10494 * [ja]テンプレートからアラートダイアログのインスタンスを生成します。[/ja]
10495 */
10496ons$1.createAlertDialog = ons$1._createAlertDialogOriginal;
10497
10498/**
10499 * @param {String} page
10500 * @param {Function} link
10501 */
10502ons$1._resolveLoadingPlaceholderOriginal = function (page, link) {
10503 var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]'));
10504
10505 if (elements.length > 0) {
10506 elements.filter(function (element) {
10507 return !element.getAttribute('page');
10508 }).forEach(function (element) {
10509 element.setAttribute('ons-loading-placeholder', page);
10510 ons$1._resolveLoadingPlaceholder(element, page, link);
10511 });
10512 } else {
10513 throw new Error('No ons-loading-placeholder exists.');
10514 }
10515};
10516
10517/**
10518 * @method resolveLoadingPlaceholder
10519 * @signature resolveLoadingPlaceholder(page)
10520 * @param {String} page
10521 * [en]Page name. Can be either an HTML file or an <ons-template> element.[/en]
10522 * [ja]pageのURLか、もしくはons-templateで宣言したテンプレートのid属性の値を指定できます。[/ja]
10523 * @description
10524 * [en]If no page is defined for the `ons-loading-placeholder` attribute it will wait for this method being called before loading the page.[/en]
10525 * [ja]ons-loading-placeholderの属性値としてページが指定されていない場合は、ページロード前に呼ばれるons.resolveLoadingPlaceholder処理が行われるまで表示されません。[/ja]
10526 */
10527ons$1.resolveLoadingPlaceholder = ons$1._resolveLoadingPlaceholderOriginal;
10528
10529ons$1._setupLoadingPlaceHolders = function () {
10530 ons$1.ready(function () {
10531 var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]'));
10532
10533 elements.forEach(function (element) {
10534 var page = element.getAttribute('ons-loading-placeholder');
10535 if (typeof page === 'string') {
10536 ons$1._resolveLoadingPlaceholder(element, page);
10537 }
10538 });
10539 });
10540};
10541
10542ons$1._resolveLoadingPlaceholder = function (element, page, link) {
10543 link = link || function (element, done) {
10544 done();
10545 };
10546 ons$1._internal.getPageHTMLAsync(page).then(function (html) {
10547
10548 while (element.firstChild) {
10549 element.removeChild(element.firstChild);
10550 }
10551
10552 var contentElement = ons$1._util.createElement('<div>' + html + '</div>');
10553 contentElement.style.display = 'none';
10554
10555 element.appendChild(contentElement);
10556
10557 link(contentElement, function () {
10558 contentElement.style.display = '';
10559 });
10560 }).catch(function (error) {
10561 throw new Error('Unabled to resolve placeholder: ' + error);
10562 });
10563};
10564
10565function waitDeviceReady() {
10566 var unlockDeviceReady = ons$1._readyLock.lock();
10567 window.addEventListener('DOMContentLoaded', function () {
10568 if (ons$1.isWebView()) {
10569 window.document.addEventListener('deviceready', unlockDeviceReady, false);
10570 } else {
10571 unlockDeviceReady();
10572 }
10573 }, false);
10574}
10575
10576window._superSecretOns = ons$1;
10577
10578/*
10579Copyright 2013-2015 ASIAL CORPORATION
10580
10581Licensed under the Apache License, Version 2.0 (the "License");
10582you may not use this file except in compliance with the License.
10583You may obtain a copy of the License at
10584
10585 http://www.apache.org/licenses/LICENSE-2.0
10586
10587Unless required by applicable law or agreed to in writing, software
10588distributed under the License is distributed on an "AS IS" BASIS,
10589WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10590See the License for the specific language governing permissions and
10591limitations under the License.
10592
10593*/
10594
10595function getElementClass() {
10596 if (typeof HTMLElement !== 'function') {
10597 // case of Safari
10598 var _BaseElement = function _BaseElement() {};
10599 _BaseElement.prototype = document.createElement('div');
10600 return _BaseElement;
10601 } else {
10602 return HTMLElement;
10603 }
10604}
10605
10606var BaseElement = function (_getElementClass) {
10607 inherits(BaseElement, _getElementClass);
10608
10609 function BaseElement(self) {
10610 var _this, _ret;
10611
10612 classCallCheck(this, BaseElement);
10613
10614 self = (_this = possibleConstructorReturn(this, (BaseElement.__proto__ || Object.getPrototypeOf(BaseElement)).call(this, self)), _this);
10615 self.init();
10616 return _ret = self, possibleConstructorReturn(_this, _ret);
10617 }
10618
10619 createClass(BaseElement, [{
10620 key: 'init',
10621 value: function init() {}
10622 }]);
10623 return BaseElement;
10624}(getElementClass());
10625
10626/*
10627Copyright 2013-2015 ASIAL CORPORATION
10628
10629Licensed under the Apache License, Version 2.0 (the "License");
10630you may not use this file except in compliance with the License.
10631You may obtain a copy of the License at
10632
10633 http://www.apache.org/licenses/LICENSE-2.0
10634
10635Unless required by applicable law or agreed to in writing, software
10636distributed under the License is distributed on an "AS IS" BASIS,
10637WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10638See the License for the specific language governing permissions and
10639limitations under the License.
10640
10641*/
10642
10643/**
10644 * @element ons-template
10645 * @category util
10646 * @description
10647 * [en]
10648 * Define a separate HTML fragment and use as a template.
10649 *
10650 * These templates can be loaded as pages in `<ons-navigator>`, `<ons-tabbar>` and `<ons-splitter>`. They can also be used to generate dialogs.
10651 * [/en]
10652 * [ja]テンプレートとして使用するためのHTMLフラグメントを定義します。この要素でHTMLを宣言すると、id属性に指定した名前をpageのURLとしてons-navigatorなどのコンポーネントから参照できます。[/ja]
10653 * @guide templates
10654 * [en]Defining multiple pages in single html[/en]
10655 * [ja]複数のページを1つのHTMLに記述する[/ja]
10656 * @seealso ons-navigator
10657 * [en]The `<ons-navigator>` component enables stack based navigation.[/en]
10658 * [ja][/ja]
10659 * @seealso ons-tabbar
10660 * [en]The `<ons-tabbar>` component is used to add tab navigation.[/en]
10661 * [ja][/ja]
10662 * @seealso ons-splitter
10663 * [en]The `<ons-splitter>` component can be used to create a draggable menu or column based layout.[/en]
10664 * [ja][/ja]
10665 * @example
10666 * <ons-template id="foobar.html">
10667 * <ons-page>
10668 * Page content
10669 * </ons-page>
10670 * </ons-template>
10671 *
10672 * <ons-navigator page="foobar.html">
10673 * </ons-navigator>
10674 */
10675
10676var TemplateElement = function (_BaseElement) {
10677 inherits(TemplateElement, _BaseElement);
10678
10679 function TemplateElement() {
10680 classCallCheck(this, TemplateElement);
10681 return possibleConstructorReturn(this, (TemplateElement.__proto__ || Object.getPrototypeOf(TemplateElement)).apply(this, arguments));
10682 }
10683
10684 createClass(TemplateElement, [{
10685 key: 'init',
10686
10687
10688 /**
10689 * @property template
10690 * @type {String}
10691 * @description
10692 * [en]Template content. This property can not be used with AngularJS bindings.[/en]
10693 * [ja][/ja]
10694 */
10695
10696 value: function init() {
10697 this.template = this.innerHTML;
10698
10699 while (this.firstChild) {
10700 this.removeChild(this.firstChild);
10701 }
10702 }
10703 }, {
10704 key: 'connectedCallback',
10705 value: function connectedCallback() {
10706 var event = new CustomEvent('_templateloaded', { bubbles: true, cancelable: true });
10707 event.template = this.template;
10708 event.templateId = this.getAttribute('id');
10709
10710 this.dispatchEvent(event);
10711 }
10712 }]);
10713 return TemplateElement;
10714}(BaseElement);
10715
10716customElements.define('ons-template', TemplateElement);
10717
10718/*
10719Copyright 2013-2015 ASIAL CORPORATION
10720
10721Licensed under the Apache License, Version 2.0 (the "License");
10722you may not use this file except in compliance with the License.
10723You may obtain a copy of the License at
10724
10725 http://www.apache.org/licenses/LICENSE-2.0
10726
10727Unless required by applicable law or agreed to in writing, software
10728distributed under the License is distributed on an "AS IS" BASIS,
10729WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10730See the License for the specific language governing permissions and
10731limitations under the License.
10732
10733*/
10734
10735/**
10736 * @element ons-if
10737 * @category conditional
10738 * @tutorial vanilla/Reference/if
10739 * @description
10740 * [en]
10741 * Conditionally display content depending on the platform, device orientation or both.
10742 *
10743 * Sometimes it is useful to conditionally hide or show certain components based on platform. When running on iOS the `<ons-if>` element can be used to hide the `<ons-fab>` element.
10744 * [/en]
10745 * [ja][/ja]
10746 * @guide cross-platform-styling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
10747 * @example
10748 * <ons-page>
10749 * <ons-if orientation="landscape">
10750 * Landscape view!
10751 * </ons-if>
10752 * <ons-if platform="android">
10753 * This is Android.
10754 * </ons-if>
10755 * <ons-if platform="ios other">
10756 * This is not Android.
10757 * </ons-if>
10758 * </ons-page>
10759 */
10760
10761var IfElement = function (_BaseElement) {
10762 inherits(IfElement, _BaseElement);
10763
10764 function IfElement() {
10765 classCallCheck(this, IfElement);
10766 return possibleConstructorReturn(this, (IfElement.__proto__ || Object.getPrototypeOf(IfElement)).apply(this, arguments));
10767 }
10768
10769 createClass(IfElement, [{
10770 key: 'init',
10771
10772
10773 /**
10774 * @attribute platform
10775 * @initonly
10776 * @type {string}
10777 * @description
10778 * [en]Space-separated platform names. Possible values are `"ios"`, `"android"`, `"windows"` and `"other"`.[/en]
10779 * [ja][/ja]
10780 */
10781
10782 /**
10783 * @attribute orientation
10784 * @type {string}
10785 * @description
10786 * [en]Either `"portrait"` or `"landscape"`.[/en]
10787 * [ja]portraitもしくはlandscapeを指定します[/ja]
10788 */
10789
10790 value: function init() {
10791 var _this2 = this;
10792
10793 contentReady(this, function () {
10794 if (platform._renderPlatform !== null) {
10795 _this2._platformUpdate();
10796 } else if (!_this2._isAllowedPlatform()) {
10797 while (_this2.childNodes[0]) {
10798 _this2.childNodes[0].remove();
10799 }
10800 _this2._platformUpdate();
10801 }
10802 });
10803
10804 this._onOrientationChange();
10805 }
10806 }, {
10807 key: 'connectedCallback',
10808 value: function connectedCallback() {
10809 orientation.on('change', this._onOrientationChange.bind(this));
10810 }
10811 }, {
10812 key: 'attributeChangedCallback',
10813 value: function attributeChangedCallback(name) {
10814 if (name === 'orientation') {
10815 this._onOrientationChange();
10816 }
10817 }
10818 }, {
10819 key: 'disconnectedCallback',
10820 value: function disconnectedCallback() {
10821 orientation.off('change', this._onOrientationChange);
10822 }
10823 }, {
10824 key: '_platformUpdate',
10825 value: function _platformUpdate() {
10826 this.style.display = this._isAllowedPlatform() ? '' : 'none';
10827 }
10828 }, {
10829 key: '_isAllowedPlatform',
10830 value: function _isAllowedPlatform() {
10831 return !this.getAttribute('platform') || this.getAttribute('platform').split(/\s+/).indexOf(platform.getMobileOS()) >= 0;
10832 }
10833 }, {
10834 key: '_onOrientationChange',
10835 value: function _onOrientationChange() {
10836 if (this.hasAttribute('orientation') && this._isAllowedPlatform()) {
10837 var conditionalOrientation = this.getAttribute('orientation').toLowerCase();
10838 var currentOrientation = orientation.isPortrait() ? 'portrait' : 'landscape';
10839
10840 this.style.display = conditionalOrientation === currentOrientation ? '' : 'none';
10841 }
10842 }
10843 }], [{
10844 key: 'observedAttributes',
10845 get: function get() {
10846 return ['orientation'];
10847 }
10848 }]);
10849 return IfElement;
10850}(BaseElement);
10851
10852customElements.define('ons-if', IfElement);
10853
10854/*
10855Copyright 2013-2015 ASIAL CORPORATION
10856
10857Licensed under the Apache License, Version 2.0 (the "License");
10858you may not use this file except in compliance with the License.
10859You may obtain a copy of the License at
10860
10861 http://www.apache.org/licenses/LICENSE-2.0
10862
10863Unless required by applicable law or agreed to in writing, software
10864distributed under the License is distributed on an "AS IS" BASIS,
10865WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10866See the License for the specific language governing permissions and
10867limitations under the License.
10868
10869*/
10870
10871var AlertDialogAnimator = function () {
10872 function AlertDialogAnimator() {
10873 var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
10874 _ref$timing = _ref.timing,
10875 timing = _ref$timing === undefined ? 'linear' : _ref$timing,
10876 _ref$delay = _ref.delay,
10877 delay = _ref$delay === undefined ? 0 : _ref$delay,
10878 _ref$duration = _ref.duration,
10879 duration = _ref$duration === undefined ? 0.2 : _ref$duration;
10880
10881 classCallCheck(this, AlertDialogAnimator);
10882
10883 this.timing = timing;
10884 this.delay = delay;
10885 this.duration = duration;
10886 }
10887
10888 /**
10889 * @param {HTMLElement} dialog
10890 * @param {Function} done
10891 */
10892
10893
10894 createClass(AlertDialogAnimator, [{
10895 key: 'show',
10896 value: function show(dialog, done) {
10897 done();
10898 }
10899
10900 /**
10901 * @param {HTMLElement} dialog
10902 * @param {Function} done
10903 */
10904
10905 }, {
10906 key: 'hide',
10907 value: function hide(dialog, done) {
10908 done();
10909 }
10910 }]);
10911 return AlertDialogAnimator;
10912}();
10913
10914/**
10915 * Android style animator for alert dialog.
10916 */
10917var AndroidAlertDialogAnimator = function (_AlertDialogAnimator) {
10918 inherits(AndroidAlertDialogAnimator, _AlertDialogAnimator);
10919
10920 function AndroidAlertDialogAnimator() {
10921 var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
10922 _ref2$timing = _ref2.timing,
10923 timing = _ref2$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref2$timing,
10924 _ref2$duration = _ref2.duration,
10925 duration = _ref2$duration === undefined ? 0.2 : _ref2$duration,
10926 _ref2$delay = _ref2.delay,
10927 delay = _ref2$delay === undefined ? 0 : _ref2$delay;
10928
10929 classCallCheck(this, AndroidAlertDialogAnimator);
10930 return possibleConstructorReturn(this, (AndroidAlertDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay }));
10931 }
10932
10933 /**
10934 * @param {Object} dialog
10935 * @param {Function} callback
10936 */
10937
10938
10939 createClass(AndroidAlertDialogAnimator, [{
10940 key: 'show',
10941 value: function show(dialog, callback) {
10942 callback = callback ? callback : function () {};
10943
10944 animit.runAll(animit(dialog._mask).queue({
10945 opacity: 0
10946 }).wait(this.delay).queue({
10947 opacity: 1.0
10948 }, {
10949 duration: this.duration,
10950 timing: this.timing
10951 }), animit(dialog._dialog).saveStyle().queue({
10952 css: {
10953 transform: 'translate3d(-50%, -50%, 0) scale3d(0.9, 0.9, 1.0)',
10954 opacity: 0.0
10955 },
10956 duration: 0
10957 }).wait(this.delay).queue({
10958 css: {
10959 transform: 'translate3d(-50%, -50%, 0) scale3d(1.0, 1.0, 1.0)',
10960 opacity: 1.0
10961 },
10962 duration: this.duration,
10963 timing: this.timing
10964 }).restoreStyle().queue(function (done) {
10965 callback();
10966 done();
10967 }));
10968 }
10969
10970 /**
10971 * @param {Object} dialog
10972 * @param {Function} callback
10973 */
10974
10975 }, {
10976 key: 'hide',
10977 value: function hide(dialog, callback) {
10978 callback = callback ? callback : function () {};
10979
10980 animit.runAll(animit(dialog._mask).queue({
10981 opacity: 1.0
10982 }).wait(this.delay).queue({
10983 opacity: 0
10984 }, {
10985 duration: this.duration,
10986 timing: this.timing
10987 }), animit(dialog._dialog).saveStyle().queue({
10988 css: {
10989 transform: 'translate3d(-50%, -50%, 0) scale3d(1.0, 1.0, 1.0)',
10990 opacity: 1.0
10991 },
10992 duration: 0
10993 }).wait(this.delay).queue({
10994 css: {
10995 transform: 'translate3d(-50%, -50%, 0) scale3d(0.9, 0.9, 1.0)',
10996 opacity: 0.0
10997 },
10998 duration: this.duration,
10999 timing: this.timing
11000 }).restoreStyle().queue(function (done) {
11001 callback();
11002 done();
11003 }));
11004 }
11005 }]);
11006 return AndroidAlertDialogAnimator;
11007}(AlertDialogAnimator);
11008
11009/**
11010 * iOS style animator for alert dialog.
11011 */
11012var IOSAlertDialogAnimator = function (_AlertDialogAnimator2) {
11013 inherits(IOSAlertDialogAnimator, _AlertDialogAnimator2);
11014
11015 function IOSAlertDialogAnimator() {
11016 var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
11017 _ref3$timing = _ref3.timing,
11018 timing = _ref3$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref3$timing,
11019 _ref3$duration = _ref3.duration,
11020 duration = _ref3$duration === undefined ? 0.2 : _ref3$duration,
11021 _ref3$delay = _ref3.delay,
11022 delay = _ref3$delay === undefined ? 0 : _ref3$delay;
11023
11024 classCallCheck(this, IOSAlertDialogAnimator);
11025 return possibleConstructorReturn(this, (IOSAlertDialogAnimator.__proto__ || Object.getPrototypeOf(IOSAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay }));
11026 }
11027
11028 /*
11029 * @param {Object} dialog
11030 * @param {Function} callback
11031 */
11032
11033
11034 createClass(IOSAlertDialogAnimator, [{
11035 key: 'show',
11036 value: function show(dialog, callback) {
11037 callback = callback ? callback : function () {};
11038
11039 animit.runAll(animit(dialog._mask).queue({
11040 opacity: 0
11041 }).wait(this.delay).queue({
11042 opacity: 1.0
11043 }, {
11044 duration: this.duration,
11045 timing: this.timing
11046 }), animit(dialog._dialog).saveStyle().queue({
11047 css: {
11048 transform: 'translate3d(-50%, -50%, 0) scale3d(1.3, 1.3, 1.0)',
11049 opacity: 0.0
11050 },
11051 duration: 0
11052 }).wait(this.delay).queue({
11053 css: {
11054 transform: 'translate3d(-50%, -50%, 0) scale3d(1.0, 1.0, 1.0)',
11055 opacity: 1.0
11056 },
11057 duration: this.duration,
11058 timing: this.timing
11059 }).restoreStyle().queue(function (done) {
11060 callback();
11061 done();
11062 }));
11063 }
11064
11065 /**
11066 * @param {Object} dialog
11067 * @param {Function} callback
11068 */
11069
11070 }, {
11071 key: 'hide',
11072 value: function hide(dialog, callback) {
11073 callback = callback ? callback : function () {};
11074
11075 animit.runAll(animit(dialog._mask).queue({
11076 opacity: 1.0
11077 }).wait(this.delay).queue({
11078 opacity: 0
11079 }, {
11080 duration: this.duration,
11081 timing: this.timing
11082 }), animit(dialog._dialog).saveStyle().queue({
11083 css: {
11084 opacity: 1.0
11085 },
11086 duration: 0
11087 }).wait(this.delay).queue({
11088 css: {
11089 opacity: 0.0
11090 },
11091 duration: this.duration,
11092 timing: this.timing
11093 }).restoreStyle().queue(function (done) {
11094 callback();
11095 done();
11096 }));
11097 }
11098 }]);
11099 return IOSAlertDialogAnimator;
11100}(AlertDialogAnimator);
11101
11102/*
11103Copyright 2013-2015 ASIAL CORPORATION
11104
11105Licensed under the Apache License, Version 2.0 (the "License");
11106you may not use this file except in compliance with the License.
11107You may obtain a copy of the License at
11108
11109 http://www.apache.org/licenses/LICENSE-2.0
11110
11111Unless required by applicable law or agreed to in writing, software
11112distributed under the License is distributed on an "AS IS" BASIS,
11113WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11114See the License for the specific language governing permissions and
11115limitations under the License.
11116
11117*/
11118
11119var scheme = {
11120 '.alert-dialog': 'alert-dialog--*',
11121 '.alert-dialog-container': 'alert-dialog-container--*',
11122 '.alert-dialog-title': 'alert-dialog-title--*',
11123 '.alert-dialog-content': 'alert-dialog-content--*',
11124 '.alert-dialog-footer': 'alert-dialog-footer--*',
11125 '.alert-dialog-button': 'alert-dialog-button--*',
11126 '.alert-dialog-footer--one': 'alert-dialog-footer--one--*',
11127 '.alert-dialog-button--one': 'alert-dialog-button--one--*',
11128 '.alert-dialog-button--primal': 'alert-dialog-button--primal--*',
11129 '.alert-dialog-mask': 'alert-dialog-mask--*',
11130 '.text-input': 'text-input--*'
11131};
11132
11133var _animatorDict = {
11134 'none': AlertDialogAnimator,
11135 'default': function _default() {
11136 return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator;
11137 },
11138 'fade': function fade() {
11139 return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator;
11140 }
11141};
11142
11143/**
11144 * @element ons-alert-dialog
11145 * @category dialog
11146 * @description
11147 * [en]
11148 * Alert dialog that is displayed on top of the current screen. Useful for displaying questions, warnings or error messages to the user. The title, content and buttons can be easily customized and it will automatically switch style based on the platform.
11149 *
11150 * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createAlertDialog(template)` utility function and the `<ons-template>` tag.
11151 * [/en]
11152 * [ja][/ja]
11153 * @codepen Qwwxyp
11154 * @tutorial vanilla/Reference/dialog
11155 * @modifier material
11156 * [en]Material Design style[/en]
11157 * [ja][/ja]
11158 * @guide dialogs
11159 * [en]Dialog components[/en]
11160 * [ja]Dialog components[/ja]
11161 * @seealso ons-dialog
11162 * [en]ons-dialog component[/en]
11163 * [ja]ons-dialogコンポーネント[/ja]
11164 * @seealso ons-popover
11165 * [en]ons-popover component[/en]
11166 * [ja]ons-dialogコンポーネント[/ja]
11167 * @seealso ons.notification
11168 * [en]Using ons.notification utility functions.[/en]
11169 * [ja]アラートダイアログを表示するには、ons.notificationオブジェクトのメソッドを使うこともできます。[/ja]
11170 * @example
11171 * <ons-alert-dialog id="alert-dialog">
11172 * <div class="alert-dialog-title">Warning!</div>
11173 * <div class="alert-dialog-content">
11174 * An error has occurred!
11175 * </div>
11176 * <div class="alert-dialog-footer">
11177 * <button id="alert-dialog-button" class="alert-dialog-button">OK</button>
11178 * </div>
11179 * </ons-alert-dialog>
11180 * <script>
11181 * document.getElementById('alert-dialog').show();
11182 * </script>
11183 */
11184
11185var AlertDialogElement = function (_BaseElement) {
11186 inherits(AlertDialogElement, _BaseElement);
11187
11188 function AlertDialogElement() {
11189 classCallCheck(this, AlertDialogElement);
11190 return possibleConstructorReturn(this, (AlertDialogElement.__proto__ || Object.getPrototypeOf(AlertDialogElement)).apply(this, arguments));
11191 }
11192
11193 createClass(AlertDialogElement, [{
11194 key: 'init',
11195
11196
11197 /**
11198 * @event preshow
11199 * @description
11200 * [en]Fired just before the alert dialog is displayed.[/en]
11201 * [ja]アラートダイアログが表示される直前に発火します。[/ja]
11202 * @param {Object} event [en]Event object.[/en]
11203 * @param {Object} event.alertDialog
11204 * [en]Alert dialog object.[/en]
11205 * [ja]アラートダイアログのオブジェクト。[/ja]
11206 * @param {Function} event.cancel
11207 * [en]Execute to stop the dialog from showing.[/en]
11208 * [ja]この関数を実行すると、アラートダイアログの表示を止めます。[/ja]
11209 */
11210
11211 /**
11212 * @event postshow
11213 * @description
11214 * [en]Fired just after the alert dialog is displayed.[/en]
11215 * [ja]アラートダイアログが表示された直後に発火します。[/ja]
11216 * @param {Object} event [en]Event object.[/en]
11217 * @param {Object} event.alertDialog
11218 * [en]Alert dialog object.[/en]
11219 * [ja]アラートダイアログのオブジェクト。[/ja]
11220 */
11221
11222 /**
11223 * @event prehide
11224 * @description
11225 * [en]Fired just before the alert dialog is hidden.[/en]
11226 * [ja]アラートダイアログが隠れる直前に発火します。[/ja]
11227 * @param {Object} event [en]Event object.[/en]
11228 * @param {Object} event.alertDialog
11229 * [en]Alert dialog object.[/en]
11230 * [ja]アラートダイアログのオブジェクト。[/ja]
11231 * @param {Function} event.cancel
11232 * [en]Execute to stop the dialog from hiding.[/en]
11233 * [ja]この関数を実行すると、アラートダイアログが閉じようとするのを止めます。[/ja]
11234 */
11235
11236 /**
11237 * @event posthide
11238 * @description
11239 * [en]Fired just after the alert dialog is hidden.[/en]
11240 * [ja]アラートダイアログが隠れた後に発火します。[/ja]
11241 * @param {Object} event [en]Event object.[/en]
11242 * @param {Object} event.alertDialog
11243 * [en]Alert dialog object.[/en]
11244 * [ja]アラートダイアログのオブジェクト。[/ja]
11245 */
11246
11247 /**
11248 * @attribute modifier
11249 * @type {String}
11250 * @description
11251 * [en]The appearance of the dialog.[/en]
11252 * [ja]ダイアログの見た目を指定します。[/ja]
11253 */
11254
11255 /**
11256 * @attribute cancelable
11257 * @description
11258 * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
11259 * [ja][/ja]
11260 */
11261
11262 /**
11263 * @attribute disabled
11264 * @description
11265 * [en]If this attribute is set the dialog is disabled.[/en]
11266 * [ja]この属性がある時、アラートダイアログはdisabled状態になります。[/ja]
11267 */
11268
11269 /**
11270 * @attribute animation
11271 * @type {String}
11272 * @default default
11273 * @description
11274 * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en]
11275 * [ja]ダイアログを表示する際のアニメーション名を指定します。デフォルトでは"none"か"default"が指定できます。[/ja]
11276 */
11277
11278 /**
11279 * @attribute animation-options
11280 * @type {Expression}
11281 * @description
11282 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
11283 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
11284 */
11285
11286 /**
11287 * @attribute mask-color
11288 * @type {String}
11289 * @default rgba(0, 0, 0, 0.2)
11290 * @description
11291 * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)".[/en]
11292 * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
11293 */
11294
11295 value: function init() {
11296 var _this2 = this;
11297
11298 contentReady(this, function () {
11299 return _this2._compile();
11300 });
11301
11302 this._visible = false;
11303 this._doorLock = new DoorLock();
11304 this._boundCancel = this._cancel.bind(this);
11305
11306 this._updateAnimatorFactory();
11307 }
11308
11309 /**
11310 * @return {Element}
11311 */
11312
11313 }, {
11314 key: '_updateAnimatorFactory',
11315 value: function _updateAnimatorFactory() {
11316 this._animatorFactory = new AnimatorFactory({
11317 animators: _animatorDict,
11318 baseClass: AlertDialogAnimator,
11319 baseClassName: 'AlertDialogAnimator',
11320 defaultAnimation: this.getAttribute('animation')
11321 });
11322 }
11323 }, {
11324 key: '_compile',
11325 value: function _compile() {
11326 autoStyle.prepare(this);
11327
11328 this.style.display = 'none';
11329
11330 /**
11331 * Expected result after compile:
11332 *
11333 * <ons-alert-dialog style="none">
11334 * <div class="alert-dialog-mask"></div>
11335 * <div class="alert-dialog">
11336 * <div class="alert-dialog-container">...</div>
11337 * </div>
11338 * </ons-alert-dialog>
11339 */
11340
11341 var content = document.createDocumentFragment();
11342
11343 if (!this._mask && !this._dialog) {
11344 while (this.firstChild) {
11345 content.appendChild(this.firstChild);
11346 }
11347 }
11348
11349 if (!this._mask) {
11350 var mask = document.createElement('div');
11351 mask.classList.add('alert-dialog-mask');
11352 this.insertBefore(mask, this.children[0]);
11353 }
11354
11355 if (!this._dialog) {
11356 var dialog = document.createElement('div');
11357 dialog.classList.add('alert-dialog');
11358 this.insertBefore(dialog, null);
11359 }
11360
11361 if (!util.findChild(this._dialog, '.alert-dialog-container')) {
11362 var container = document.createElement('div');
11363 container.classList.add('alert-dialog-container');
11364 this._dialog.appendChild(container);
11365 }
11366
11367 this._dialog.children[0].appendChild(content);
11368
11369 this._dialog.style.zIndex = 20001;
11370 this._mask.style.zIndex = 20000;
11371
11372 if (this.getAttribute('mask-color')) {
11373 this._mask.style.backgroundColor = this.getAttribute('mask-color');
11374 }
11375
11376 ModifierUtil.initModifier(this, scheme);
11377 }
11378
11379 /**
11380 * @property disabled
11381 * @type {Boolean}
11382 * @description
11383 * [en]Whether the element is disabled or not.[/en]
11384 * [ja]無効化されている場合に`true`。[/ja]
11385 */
11386
11387 }, {
11388 key: 'show',
11389
11390
11391 /**
11392 * @method show
11393 * @signature show([options])
11394 * @param {Object} [options]
11395 * [en]Parameter object.[/en]
11396 * [ja]オプションを指定するオブジェクトです。[/ja]
11397 * @param {String} [options.animation]
11398 * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en]
11399 * [ja]アニメーション名を指定します。指定できるのは、"fade", "none"のいずれかです。[/ja]
11400 * @param {String} [options.animationOptions]
11401 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
11402 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja]
11403 * @param {Function} [options.callback]
11404 * [en]Function to execute after the dialog has been revealed.[/en]
11405 * [ja]ダイアログが表示され終わった時に呼び出されるコールバックを指定します。[/ja]
11406 * @description
11407 * [en]Show the alert dialog.[/en]
11408 * [ja]ダイアログを表示します。[/ja]
11409 * @return {Promise}
11410 * [en]A `Promise` object that resolves to the displayed element.[/en]
11411 * [ja][/ja]
11412 */
11413 value: function show() {
11414 var _this3 = this;
11415
11416 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
11417
11418 var _cancel2 = false;
11419 var callback = options.callback || function () {};
11420
11421 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
11422
11423 util.triggerElementEvent(this, 'preshow', {
11424 alertDialog: this,
11425 cancel: function cancel() {
11426 _cancel2 = true;
11427 }
11428 });
11429
11430 if (!_cancel2) {
11431 var _ret = function () {
11432 var tryShow = function tryShow() {
11433 var unlock = _this3._doorLock.lock();
11434 var animator = _this3._animatorFactory.newAnimator(options);
11435
11436 _this3.style.display = 'block';
11437 _this3._mask.style.opacity = '1';
11438
11439 return new Promise(function (resolve) {
11440 contentReady(_this3, function () {
11441 animator.show(_this3, function () {
11442 _this3._visible = true;
11443 unlock();
11444
11445 util.triggerElementEvent(_this3, 'postshow', { alertDialog: _this3 });
11446
11447 callback();
11448 resolve(_this3);
11449 });
11450 });
11451 });
11452 };
11453
11454 return {
11455 v: new Promise(function (resolve) {
11456 _this3._doorLock.waitUnlock(function () {
11457 return resolve(tryShow());
11458 });
11459 })
11460 };
11461 }();
11462
11463 if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
11464 } else {
11465 return Promise.reject('Canceled in preshow event.');
11466 }
11467 }
11468
11469 /**
11470 * @method hide
11471 * @signature hide([options])
11472 * @param {Object} [options]
11473 * [en]Parameter object.[/en]
11474 * [ja]オプションを指定するオブジェクト。[/ja]
11475 * @param {String} [options.animation]
11476 * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en]
11477 * [ja]アニメーション名を指定します。"fade", "none"のいずれかを指定します。[/ja]
11478 * @param {String} [options.animationOptions]
11479 * [en]Specify the animation's duration, delay and timing. E.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code>[/en]
11480 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja]
11481 * @param {Function} [options.callback]
11482 * [en]Function to execute after the dialog has been hidden.[/en]
11483 * [ja]このダイアログが閉じた時に呼び出されるコールバックを指定します。[/ja]
11484 * @description
11485 * [en]Hide the alert dialog.[/en]
11486 * [ja]ダイアログを閉じます。[/ja]
11487 * @return {Promise}
11488 * [en]Resolves to the hidden element[/en]
11489 * [ja][/ja]
11490 */
11491
11492 }, {
11493 key: 'hide',
11494 value: function hide() {
11495 var _this4 = this;
11496
11497 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
11498
11499 var _cancel3 = false;
11500 var callback = options.callback || function () {};
11501
11502 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
11503
11504 util.triggerElementEvent(this, 'prehide', {
11505 alertDialog: this,
11506 cancel: function cancel() {
11507 _cancel3 = true;
11508 }
11509 });
11510
11511 if (!_cancel3) {
11512 var _ret2 = function () {
11513 var tryHide = function tryHide() {
11514 var unlock = _this4._doorLock.lock();
11515 var animator = _this4._animatorFactory.newAnimator(options);
11516
11517 return new Promise(function (resolve) {
11518 contentReady(_this4, function () {
11519 animator.hide(_this4, function () {
11520 _this4.style.display = 'none';
11521 _this4._visible = false;
11522 unlock();
11523
11524 util.triggerElementEvent(_this4, 'posthide', { alertDialog: _this4 });
11525
11526 callback();
11527 resolve(_this4);
11528 });
11529 });
11530 });
11531 };
11532
11533 return {
11534 v: new Promise(function (resolve) {
11535 _this4._doorLock.waitUnlock(function () {
11536 return resolve(tryHide());
11537 });
11538 })
11539 };
11540 }();
11541
11542 if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === "object") return _ret2.v;
11543 } else {
11544 return Promise.reject('Canceled in prehide event.');
11545 }
11546 }
11547
11548 /**
11549 * @property visible
11550 * @readonly
11551 * @type {Boolean}
11552 * @description
11553 * [en]Whether the dialog is visible or not.[/en]
11554 * [ja]要素が見える場合に`true`。[/ja]
11555 */
11556
11557 }, {
11558 key: '_cancel',
11559 value: function _cancel() {
11560 var _this5 = this;
11561
11562 if (this.cancelable && !this._running) {
11563 this._running = true;
11564 this.hide().then(function () {
11565 _this5._running = false;
11566 util.triggerElementEvent(_this5, 'dialog-cancel');
11567 }, function () {
11568 return _this5._running = false;
11569 });
11570 }
11571 }
11572 }, {
11573 key: 'connectedCallback',
11574 value: function connectedCallback() {
11575 var _this6 = this;
11576
11577 this.onDeviceBackButton = function (e) {
11578 return _this6.cancelable ? _this6._cancel() : e.callParentHandler();
11579 };
11580
11581 contentReady(this, function () {
11582 _this6._mask.addEventListener('click', _this6._boundCancel, false);
11583 });
11584 }
11585 }, {
11586 key: 'disconnectedCallback',
11587 value: function disconnectedCallback() {
11588 this._backButtonHandler.destroy();
11589 this._backButtonHandler = null;
11590
11591 this._mask.removeEventListener('click', this._boundCancel.bind(this), false);
11592 }
11593 }, {
11594 key: 'attributeChangedCallback',
11595 value: function attributeChangedCallback(name, last, current) {
11596 if (name === 'modifier') {
11597 return ModifierUtil.onModifierChanged(last, current, this, scheme);
11598 } else if (name === 'animation') {
11599 this._updateAnimatorFactory();
11600 }
11601 }
11602
11603 /**
11604 * @param {String} name
11605 * @param {DialogAnimator} Animator
11606 */
11607
11608 }, {
11609 key: '_mask',
11610 get: function get() {
11611 return util.findChild(this, '.alert-dialog-mask');
11612 }
11613
11614 /**
11615 * @return {Element}
11616 */
11617
11618 }, {
11619 key: '_dialog',
11620 get: function get() {
11621 return util.findChild(this, '.alert-dialog');
11622 }
11623
11624 /**
11625 * @return {Element}
11626 */
11627
11628 }, {
11629 key: '_titleElement',
11630 get: function get() {
11631 return util.findChild(this._dialog.children[0], '.alert-dialog-title');
11632 }
11633
11634 /**
11635 * @return {Element}
11636 */
11637
11638 }, {
11639 key: '_contentElement',
11640 get: function get() {
11641 return util.findChild(this._dialog.children[0], '.alert-dialog-content');
11642 }
11643 }, {
11644 key: 'disabled',
11645 set: function set(value) {
11646 return util.toggleAttribute(this, 'disabled', value);
11647 },
11648 get: function get() {
11649 return this.hasAttribute('disabled');
11650 }
11651
11652 /**
11653 * @property cancelable
11654 * @type {Boolean}
11655 * @description
11656 * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
11657 * [ja][/ja]
11658 */
11659
11660 }, {
11661 key: 'cancelable',
11662 set: function set(value) {
11663 return util.toggleAttribute(this, 'cancelable', value);
11664 },
11665 get: function get() {
11666 return this.hasAttribute('cancelable');
11667 }
11668 }, {
11669 key: 'visible',
11670 get: function get() {
11671 return this._visible;
11672 }
11673
11674 /**
11675 * @property onDeviceBackButton
11676 * @type {Object}
11677 * @description
11678 * [en]Back-button handler.[/en]
11679 * [ja]バックボタンハンドラ。[/ja]
11680 */
11681
11682 }, {
11683 key: 'onDeviceBackButton',
11684 get: function get() {
11685 return this._backButtonHandler;
11686 },
11687 set: function set(callback) {
11688 if (this._backButtonHandler) {
11689 this._backButtonHandler.destroy();
11690 }
11691
11692 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
11693 }
11694 }], [{
11695 key: 'registerAnimator',
11696 value: function registerAnimator(name, Animator) {
11697 if (!(Animator.prototype instanceof AlertDialogAnimator)) {
11698 throw new Error('"Animator" param must inherit OnsAlertDialogElement.AlertDialogAnimator');
11699 }
11700 _animatorDict[name] = Animator;
11701 }
11702 }, {
11703 key: 'observedAttributes',
11704 get: function get() {
11705 return ['modifier', 'animation'];
11706 }
11707 }, {
11708 key: 'AlertDialogAnimator',
11709 get: function get() {
11710 return AlertDialogAnimator;
11711 }
11712 }]);
11713 return AlertDialogElement;
11714}(BaseElement);
11715
11716customElements.define('ons-alert-dialog', AlertDialogElement);
11717
11718/*
11719Copyright 2013-2015 ASIAL CORPORATION
11720
11721Licensed under the Apache License, Version 2.0 (the "License");
11722you may not use this file except in compliance with the License.
11723You may obtain a copy of the License at
11724
11725 http://www.apache.org/licenses/LICENSE-2.0
11726
11727Unless required by applicable law or agreed to in writing, software
11728distributed under the License is distributed on an "AS IS" BASIS,
11729WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11730See the License for the specific language governing permissions and
11731limitations under the License.
11732
11733*/
11734
11735var scheme$1 = {
11736 '': 'back-button--*',
11737 '.back-button__icon': 'back-button--*__icon',
11738 '.back-button__label': 'back-button--*__label'
11739};
11740
11741/**
11742 * @element ons-back-button
11743 * @category navigation
11744 * @description
11745 * [en]
11746 * Back button component for `<ons-toolbar>`. Put it in the left part of the `<ons-toolbar>`.
11747 *
11748 * It will find the parent `<ons-navigator>` element and pop a page when clicked. This behavior can be overriden by specifying the `onClick` property.
11749 * [/en]
11750 * [ja][/ja]
11751 * @codepen aHmGL
11752 * @tutorial vanilla/Reference/navigator
11753 * @modifier material
11754 * [en]Material Design style[/en]
11755 * [ja][/ja]
11756 * @seealso ons-toolbar
11757 * [en]ons-toolbar component[/en]
11758 * [ja]ons-toolbarコンポーネント[/ja]
11759 * @seealso ons-navigator
11760 * [en]ons-navigator component[/en]
11761 * [ja]ons-navigatorコンポーネント[/ja]
11762 * @example
11763 * <ons-toolbar>
11764 * <div class="left">
11765 * <ons-back-button>Back</ons-back-button>
11766 * </div>
11767 * <div class="center">
11768 * Title
11769 * <div>
11770 * </ons-toolbar>
11771 */
11772
11773var BackButtonElement = function (_BaseElement) {
11774 inherits(BackButtonElement, _BaseElement);
11775
11776 function BackButtonElement() {
11777 classCallCheck(this, BackButtonElement);
11778 return possibleConstructorReturn(this, (BackButtonElement.__proto__ || Object.getPrototypeOf(BackButtonElement)).apply(this, arguments));
11779 }
11780
11781 createClass(BackButtonElement, [{
11782 key: 'init',
11783
11784 /**
11785 * @attribute modifier
11786 * @type {String}
11787 * @description
11788 * [en]The appearance of the back button.[/en]
11789 * [ja]バックボタンの見た目を指定します。[/ja]
11790 */
11791
11792 value: function init() {
11793 var _this2 = this;
11794
11795 contentReady(this, function () {
11796 _this2._compile();
11797 });
11798
11799 this._options = {};
11800 this._boundOnClick = this._onClick.bind(this);
11801 }
11802 }, {
11803 key: '_compile',
11804 value: function _compile() {
11805 autoStyle.prepare(this);
11806
11807 this.classList.add('back-button');
11808
11809 if (!util.findChild(this, '.back-button__label')) {
11810 var label = util.create('span.back-button__label');
11811
11812 while (this.childNodes[0]) {
11813 label.appendChild(this.childNodes[0]);
11814 }
11815 this.appendChild(label);
11816 }
11817
11818 if (!util.findChild(this, '.back-button__icon')) {
11819 var icon = util.create('span.back-button__icon');
11820
11821 this.insertBefore(icon, this.children[0]);
11822 }
11823
11824 ModifierUtil.initModifier(this, scheme$1);
11825 }
11826
11827 /**
11828 * @property options
11829 * @type {Object}
11830 * @description
11831 * [en]Options object.[/en]
11832 * [ja]オプションを指定するオブジェクト。[/ja]
11833 */
11834
11835 /**
11836 * @property options.animation
11837 * @type {String}
11838 * @description
11839 * [en]Animation name. Available animations are "slide", "lift", "fade" and "none".
11840 * These are platform based animations. For fixed animations, add "-ios" or "-md"
11841 * suffix to the animation name. E.g. "lift-ios", "lift-md". Defaults values are "slide-ios" and "fade-md".
11842 * [/en]
11843 * [ja][/ja]
11844 */
11845
11846 /**
11847 * @property options.animationOptions
11848 * @type {String}
11849 * @description
11850 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en]
11851 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
11852 */
11853
11854 /**
11855 * @property options.callback
11856 * @type {String}
11857 * @description
11858 * [en]Function that is called when the transition has ended.[/en]
11859 * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
11860 */
11861
11862 /**
11863 * @property options.refresh
11864 * @description
11865 * [en]The previous page will be refreshed (destroyed and created again) before popPage action.[/en]
11866 * [ja]popPageする前に、前にあるページを生成しなおして更新する場合にtrueを指定します。[/ja]
11867 */
11868
11869 }, {
11870 key: '_onClick',
11871
11872
11873 /**
11874 * @property onClick
11875 * @type {Function}
11876 * @description
11877 * [en]Used to override the default back button behavior.[/en]
11878 * [ja][/ja]
11879 */
11880 value: function _onClick() {
11881 if (this.onClick) {
11882 this.onClick.apply(this);
11883 } else {
11884 var navigator = util.findParent(this, 'ons-navigator');
11885 if (navigator) {
11886 navigator.popPage(this.options);
11887 }
11888 }
11889 }
11890 }, {
11891 key: 'connectedCallback',
11892 value: function connectedCallback() {
11893 this.addEventListener('click', this._boundOnClick, false);
11894 }
11895 }, {
11896 key: 'attributeChangedCallback',
11897 value: function attributeChangedCallback(name, last, current) {
11898 if (name === 'modifier') {
11899 return ModifierUtil.onModifierChanged(last, current, this, scheme$1);
11900 }
11901 }
11902 }, {
11903 key: 'disconnectedCallback',
11904 value: function disconnectedCallback() {
11905 this.removeEventListener('click', this._boundOnClick, false);
11906 }
11907 }, {
11908 key: 'show',
11909 value: function show() {
11910 this.style.display = 'inline-block';
11911 }
11912 }, {
11913 key: 'hide',
11914 value: function hide() {
11915 this.style.display = 'none';
11916 }
11917 }, {
11918 key: 'options',
11919 get: function get() {
11920 return this._options;
11921 },
11922 set: function set(object) {
11923 this._options = object;
11924 }
11925 }], [{
11926 key: 'observedAttributes',
11927 get: function get() {
11928 return ['modifier'];
11929 }
11930 }]);
11931 return BackButtonElement;
11932}(BaseElement);
11933
11934customElements.define('ons-back-button', BackButtonElement);
11935
11936/*
11937Copyright 2013-2015 ASIAL CORPORATION
11938
11939Licensed under the Apache License, Version 2.0 (the "License");
11940you may not use this file except in compliance with the License.
11941You may obtain a copy of the License at
11942
11943 http://www.apache.org/licenses/LICENSE-2.0
11944
11945Unless required by applicable law or agreed to in writing, software
11946distributed under the License is distributed on an "AS IS" BASIS,
11947WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11948See the License for the specific language governing permissions and
11949limitations under the License.
11950
11951*/
11952
11953var scheme$2 = { '': 'bottom-bar--*' };
11954
11955/**
11956 * @element ons-bottom-toolbar
11957 * @category page
11958 * @description
11959 * [en]Toolbar component that is positioned at the bottom of the page.[/en]
11960 * [ja]ページ下部に配置されるツールバー用コンポーネントです。[/ja]
11961 * @modifier transparent
11962 * [en]Make the toolbar transparent.[/en]
11963 * [ja]ツールバーの背景を透明にして表示します。[/ja]
11964 * @seealso ons-toolbar [en]ons-toolbar component[/en][ja]ons-toolbarコンポーネント[/ja]
11965 * @example
11966 * <ons-bottom-toolbar>
11967 * Content
11968 * </ons-bottom-toolbar>
11969 */
11970
11971var BottomToolbarElement = function (_BaseElement) {
11972 inherits(BottomToolbarElement, _BaseElement);
11973
11974 function BottomToolbarElement() {
11975 classCallCheck(this, BottomToolbarElement);
11976 return possibleConstructorReturn(this, (BottomToolbarElement.__proto__ || Object.getPrototypeOf(BottomToolbarElement)).apply(this, arguments));
11977 }
11978
11979 createClass(BottomToolbarElement, [{
11980 key: 'init',
11981
11982 /**
11983 * @attribute modifier
11984 * @type {String}
11985 * @description
11986 * [en]The appearance of the toolbar.[/en]
11987 * [ja]ツールバーの見た目の表現を指定します。[/ja]
11988 */
11989
11990 value: function init() {
11991 this.classList.add('bottom-bar');
11992 ModifierUtil.initModifier(this, scheme$2);
11993 }
11994 }, {
11995 key: 'connectedCallback',
11996 value: function connectedCallback() {
11997 if (util.match(this.parentNode, 'ons-page')) {
11998 this.parentNode.classList.add('page-with-bottom-toolbar');
11999 }
12000 }
12001 }, {
12002 key: 'attributeChangedCallback',
12003 value: function attributeChangedCallback(name, last, current) {
12004 if (name === 'modifier') {
12005 ModifierUtil.onModifierChanged(last, current, this, scheme$2);
12006 }
12007 }
12008 }], [{
12009 key: 'observedAttributes',
12010 get: function get() {
12011 return ['modifier'];
12012 }
12013 }]);
12014 return BottomToolbarElement;
12015}(BaseElement);
12016
12017customElements.define('ons-bottom-toolbar', BottomToolbarElement);
12018
12019/*
12020Copyright 2013-2015 ASIAL CORPORATION
12021
12022Licensed under the Apache License, Version 2.0 (the "License");
12023you may not use this file except in compliance with the License.
12024You may obtain a copy of the License at
12025
12026 http://www.apache.org/licenses/LICENSE-2.0
12027
12028Unless required by applicable law or agreed to in writing, software
12029distributed under the License is distributed on an "AS IS" BASIS,
12030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12031See the License for the specific language governing permissions and
12032limitations under the License.
12033
12034*/
12035
12036var scheme$3 = { '': 'button--*' };
12037
12038/**
12039 * @element ons-button
12040 * @category form
12041 * @modifier outline
12042 * [en]Button with outline and transparent background[/en]
12043 * [ja]アウトラインを持ったボタンを表示します。[/ja]
12044 * @modifier light
12045 * [en]Button that doesn't stand out.[/en]
12046 * [ja]目立たないボタンを表示します。[/ja]
12047 * @modifier quiet
12048 * [en]Button with no outline and or background..[/en]
12049 * [ja]枠線や背景が無い文字だけのボタンを表示します。[/ja]
12050 * @modifier cta
12051 * [en]Button that really stands out.[/en]
12052 * [ja]目立つボタンを表示します。[/ja]
12053 * @modifier large
12054 * [en]Large button that covers the width of the screen.[/en]
12055 * [ja]横いっぱいに広がる大きなボタンを表示します。[/ja]
12056 * @modifier large--quiet
12057 * [en]Large quiet button.[/en]
12058 * [ja]横いっぱいに広がるquietボタンを表示します。[/ja]
12059 * @modifier large--cta
12060 * [en]Large call to action button.[/en]
12061 * [ja]横いっぱいに広がるctaボタンを表示します。[/ja]
12062 * @modifier material
12063 * [en]Material Design button[/en]
12064 * [ja]マテリアルデザインのボタン[/ja]
12065 * @modifier material--flat
12066 * [en]Material Design flat button[/en]
12067 * [ja]マテリアルデザインのフラットボタン[/ja]
12068 * @description
12069 * [en]
12070 * Button component. If you want to place a button in a toolbar, use `<ons-toolbar-button>` or `<ons-back-button>` instead.
12071 *
12072 * Will automatically display as a Material Design button with a ripple effect on Android.
12073 * [/en]
12074 * [ja]ボタン用コンポーネント。ツールバーにボタンを設置する場合は、ons-toolbar-buttonもしくはons-back-buttonコンポーネントを使用します。[/ja]
12075 * @codepen hLayx
12076 * @tutorial vanilla/Reference/button
12077 * @guide Button [en]Guide for `<ons-button>`[/en][ja]<ons-button>の使い方[/ja]
12078 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
12079 * @guide cross-platform-styling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
12080 * @example
12081 * <ons-button modifier="large--cta">
12082 * Tap Me
12083 * </ons-button>
12084 */
12085
12086var ButtonElement = function (_BaseElement) {
12087 inherits(ButtonElement, _BaseElement);
12088
12089 function ButtonElement() {
12090 classCallCheck(this, ButtonElement);
12091 return possibleConstructorReturn(this, (ButtonElement.__proto__ || Object.getPrototypeOf(ButtonElement)).apply(this, arguments));
12092 }
12093
12094 createClass(ButtonElement, [{
12095 key: 'init',
12096
12097
12098 /**
12099 * @attribute modifier
12100 * @type {String}
12101 * @description
12102 * [en]The appearance of the button.[/en]
12103 * [ja]ボタンの表現を指定します。[/ja]
12104 */
12105
12106 /**
12107 * @attribute ripple
12108 * @description
12109 * [en]If this attribute is defined, the button will have a ripple effect.[/en]
12110 * [ja][/ja]
12111 */
12112
12113 /**
12114 * @attribute disabled
12115 * @description
12116 * [en]Specify if button should be disabled.[/en]
12117 * [ja]ボタンを無効化する場合は指定します。[/ja]
12118 */
12119
12120 value: function init() {
12121 this._compile();
12122 }
12123 }, {
12124 key: 'attributeChangedCallback',
12125 value: function attributeChangedCallback(name, last, current) {
12126 switch (name) {
12127 case 'modifier':
12128 ModifierUtil.onModifierChanged(last, current, this, scheme$3);
12129 break;
12130 case 'ripple':
12131 this._updateRipple();
12132 }
12133 }
12134
12135 /**
12136 * @property disabled
12137 * @type {Boolean}
12138 * @description
12139 * [en]Whether the button is disabled or not.[/en]
12140 * [ja]無効化されている場合に`true`。[/ja]
12141 */
12142
12143 }, {
12144 key: '_compile',
12145 value: function _compile() {
12146 autoStyle.prepare(this);
12147
12148 this.classList.add('button');
12149
12150 this._updateRipple();
12151
12152 ModifierUtil.initModifier(this, scheme$3);
12153 }
12154 }, {
12155 key: '_updateRipple',
12156 value: function _updateRipple() {
12157 util.updateRipple(this);
12158 }
12159 }, {
12160 key: 'disabled',
12161 set: function set(value) {
12162 return util.toggleAttribute(this, 'disabled', value);
12163 },
12164 get: function get() {
12165 return this.hasAttribute('disabled');
12166 }
12167 }], [{
12168 key: 'observedAttributes',
12169 get: function get() {
12170 return ['modifier', 'ripple'];
12171 }
12172 }]);
12173 return ButtonElement;
12174}(BaseElement);
12175
12176customElements.define('ons-button', ButtonElement);
12177
12178/*
12179Copyright 2013-2015 ASIAL CORPORATION
12180
12181Licensed under the Apache License, Version 2.0 (the "License");
12182you may not use this file except in compliance with the License.
12183You may obtain a copy of the License at
12184
12185 http://www.apache.org/licenses/LICENSE-2.0
12186
12187Unless required by applicable law or agreed to in writing, software
12188distributed under the License is distributed on an "AS IS" BASIS,
12189WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12190See the License for the specific language governing permissions and
12191limitations under the License.
12192
12193*/
12194
12195var scheme$4 = { '': 'carousel-item--*' };
12196
12197/**
12198 * @element ons-carousel-item
12199 * @category carousel
12200 * @description
12201 * [en]
12202 * Carousel item component. Used as a child of the `<ons-carousel>` element.
12203 * [/en]
12204 * [ja][/ja]
12205 * @codepen xbbzOQ
12206 * @tutorial vanilla/Reference/carousel
12207 * @seealso ons-carousel
12208 * [en]`<ons-carousel>` components[/en]
12209 * [ja]<ons-carousel>コンポーネント[/ja]
12210 * @example
12211 * <ons-carousel style="width: 100%; height: 200px">
12212 * <ons-carousel-item>
12213 * ...
12214 * </ons-carousel-item>
12215 * <ons-carousel-item>
12216 * ...
12217 * </ons-carousel-item>
12218 * </ons-carousel>
12219 */
12220
12221var CarouselItemElement = function (_BaseElement) {
12222 inherits(CarouselItemElement, _BaseElement);
12223
12224 function CarouselItemElement() {
12225 classCallCheck(this, CarouselItemElement);
12226 return possibleConstructorReturn(this, (CarouselItemElement.__proto__ || Object.getPrototypeOf(CarouselItemElement)).apply(this, arguments));
12227 }
12228
12229 createClass(CarouselItemElement, [{
12230 key: 'init',
12231 value: function init() {
12232 this.style.width = '100%';
12233 ModifierUtil.initModifier(this, scheme$4);
12234 }
12235 }, {
12236 key: 'attributeChangedCallback',
12237 value: function attributeChangedCallback(name, last, current) {
12238 if (name === 'modifier') {
12239 return ModifierUtil.onModifierChanged(last, current, this, scheme$4);
12240 }
12241 }
12242 }], [{
12243 key: 'observedAttributes',
12244 get: function get() {
12245 return ['modifier'];
12246 }
12247 }]);
12248 return CarouselItemElement;
12249}(BaseElement);
12250
12251customElements.define('ons-carousel-item', CarouselItemElement);
12252
12253/*
12254Copyright 2013-2015 ASIAL CORPORATION
12255
12256Licensed under the Apache License, Version 2.0 (the "License");
12257you may not use this file except in compliance with the License.
12258You may obtain a copy of the License at
12259
12260 http://www.apache.org/licenses/LICENSE-2.0
12261
12262Unless required by applicable law or agreed to in writing, software
12263distributed under the License is distributed on an "AS IS" BASIS,
12264WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12265See the License for the specific language governing permissions and
12266limitations under the License.
12267
12268*/
12269
12270var VerticalModeTrait = {
12271
12272 _getScrollDelta: function _getScrollDelta(event) {
12273 return event.gesture.deltaY;
12274 },
12275
12276 _getScrollVelocity: function _getScrollVelocity(event) {
12277 return event.gesture.velocityY;
12278 },
12279
12280 _getElementSize: function _getElementSize() {
12281 if (!this._currentElementSize) {
12282 this._currentElementSize = this.getBoundingClientRect().height;
12283 }
12284
12285 return this._currentElementSize;
12286 },
12287
12288 _generateScrollTransform: function _generateScrollTransform(scroll) {
12289 return 'translate3d(0px, ' + -scroll + 'px, 0px)';
12290 },
12291
12292 _updateDimensionData: function _updateDimensionData() {
12293 this._style = window.getComputedStyle(this);
12294 this._dimensions = this.getBoundingClientRect();
12295 },
12296
12297 _updateOffset: function _updateOffset() {
12298 if (this.centered) {
12299 var height = (this._dimensions.height || 0) - parseInt(this._style.paddingTop, 10) - parseInt(this._style.paddingBottom, 10);
12300 this._offset = -(height - this._getCarouselItemSize()) / 2;
12301 }
12302 },
12303
12304 _layoutCarouselItems: function _layoutCarouselItems() {
12305 var children = this._getCarouselItemElements();
12306
12307 var sizeAttr = this._getCarouselItemSizeAttr();
12308 var sizeInfo = this._decomposeSizeString(sizeAttr);
12309
12310 for (var i = 0; i < children.length; i++) {
12311 children[i].style.position = 'absolute';
12312 children[i].style.height = sizeAttr;
12313 children[i].style.visibility = 'visible';
12314 children[i].style.top = i * sizeInfo.number + sizeInfo.unit;
12315 }
12316 },
12317
12318 _setup: function _setup() {
12319 this._updateDimensionData();
12320 this._updateOffset();
12321 this._layoutCarouselItems();
12322 }
12323};
12324
12325var HorizontalModeTrait = {
12326
12327 _getScrollDelta: function _getScrollDelta(event) {
12328 return event.gesture.deltaX;
12329 },
12330
12331 _getScrollVelocity: function _getScrollVelocity(event) {
12332 return event.gesture.velocityX;
12333 },
12334
12335 _getElementSize: function _getElementSize() {
12336 if (!this._currentElementSize) {
12337 this._currentElementSize = this.getBoundingClientRect().width;
12338 }
12339
12340 return this._currentElementSize;
12341 },
12342
12343 _generateScrollTransform: function _generateScrollTransform(scroll) {
12344 return 'translate3d(' + -scroll + 'px, 0px, 0px)';
12345 },
12346
12347 _updateDimensionData: function _updateDimensionData() {
12348 this._style = window.getComputedStyle(this);
12349 this._dimensions = this.getBoundingClientRect();
12350 },
12351
12352 _updateOffset: function _updateOffset() {
12353 if (this.centered) {
12354 var width = (this._dimensions.width || 0) - parseInt(this._style.paddingLeft, 10) - parseInt(this._style.paddingRight, 10);
12355 this._offset = -(width - this._getCarouselItemSize()) / 2;
12356 }
12357 },
12358
12359 _layoutCarouselItems: function _layoutCarouselItems() {
12360 var children = this._getCarouselItemElements();
12361
12362 var sizeAttr = this._getCarouselItemSizeAttr();
12363 var sizeInfo = this._decomposeSizeString(sizeAttr);
12364
12365 for (var i = 0; i < children.length; i++) {
12366 children[i].style.position = 'absolute';
12367 children[i].style.width = sizeAttr;
12368 children[i].style.visibility = 'visible';
12369 children[i].style.left = i * sizeInfo.number + sizeInfo.unit;
12370 }
12371 },
12372
12373 _setup: function _setup() {
12374 this._updateDimensionData();
12375 this._updateOffset();
12376 this._layoutCarouselItems();
12377 }
12378};
12379
12380/**
12381 * @element ons-carousel
12382 * @category carousel
12383 * @description
12384 * [en]
12385 * Carousel component. A carousel can be used to display several items in the same space.
12386 *
12387 * The component supports displaying content both horizontally and vertically. The user can scroll through the items by dragging and it can also be controller programmatically.
12388 * [/en]
12389 * [ja][/ja]
12390 * @codepen xbbzOQ
12391 * @tutorial vanilla/Reference/carousel
12392 * @seealso ons-carousel-item
12393 * [en]`<ons-carousel-item>` component[/en]
12394 * [ja]ons-carousel-itemコンポーネント[/ja]
12395 * @example
12396 * <ons-carousel style="width: 100%; height: 200px">
12397 * <ons-carousel-item>
12398 * ...
12399 * </ons-carousel-item>
12400 * <ons-carousel-item>
12401 * ...
12402 * </ons-carousel-item>
12403 * </ons-carousel>
12404 */
12405
12406var CarouselElement = function (_BaseElement) {
12407 inherits(CarouselElement, _BaseElement);
12408
12409 function CarouselElement() {
12410 classCallCheck(this, CarouselElement);
12411 return possibleConstructorReturn(this, (CarouselElement.__proto__ || Object.getPrototypeOf(CarouselElement)).apply(this, arguments));
12412 }
12413
12414 createClass(CarouselElement, [{
12415 key: 'init',
12416
12417
12418 /**
12419 * @event postchange
12420 * @description
12421 * [en]Fired just after the current carousel item has changed.[/en]
12422 * [ja]現在表示しているカルーセルの要素が変わった時に発火します。[/ja]
12423 * @param {Object} event
12424 * [en]Event object.[/en]
12425 * [ja]イベントオブジェクトです。[/ja]
12426 * @param {Object} event.carousel
12427 * [en]Carousel object.[/en]
12428 * [ja]イベントが発火したCarouselオブジェクトです。[/ja]
12429 * @param {Number} event.activeIndex
12430 * [en]Current active index.[/en]
12431 * [ja]現在アクティブになっている要素のインデックス。[/ja]
12432 * @param {Number} event.lastActiveIndex
12433 * [en]Previous active index.[/en]
12434 * [ja]以前アクティブだった要素のインデックス。[/ja]
12435 */
12436
12437 /**
12438 * @event refresh
12439 * @description
12440 * [en]Fired when the carousel has been refreshed.[/en]
12441 * [ja]カルーセルが更新された時に発火します。[/ja]
12442 * @param {Object} event
12443 * [en]Event object.[/en]
12444 * [ja]イベントオブジェクトです。[/ja]
12445 * @param {Object} event.carousel
12446 * [en]Carousel object.[/en]
12447 * [ja]イベントが発火したCarouselオブジェクトです。[/ja]
12448 */
12449
12450 /**
12451 * @event overscroll
12452 * @description
12453 * [en]Fired when the carousel has been overscrolled.[/en]
12454 * [ja]カルーセルがオーバースクロールした時に発火します。[/ja]
12455 * @param {Object} event
12456 * [en]Event object.[/en]
12457 * [ja]イベントオブジェクトです。[/ja]
12458 * @param {Object} event.carousel
12459 * [en]Fired when the carousel has been refreshed.[/en]
12460 * [ja]カルーセルが更新された時に発火します。[/ja]
12461 * @param {Number} event.activeIndex
12462 * [en]Current active index.[/en]
12463 * [ja]現在アクティブになっている要素のインデックス。[/ja]
12464 * @param {String} event.direction
12465 * [en]Can be one of either "up", "down", "left" or "right".[/en]
12466 * [ja]オーバースクロールされた方向が得られます。"up", "down", "left", "right"のいずれかの方向が渡されます。[/ja]
12467 * @param {Function} event.waitToReturn
12468 * [en]Takes a <code>Promise</code> object as an argument. The carousel will not scroll back until the promise has been resolved or rejected.[/en]
12469 * [ja]この関数はPromiseオブジェクトを引数として受け取ります。渡したPromiseオブジェクトがresolveされるかrejectされるまで、カルーセルはスクロールバックしません。[/ja]
12470 */
12471
12472 /**
12473 * @attribute direction
12474 * @type {String}
12475 * @description
12476 * [en]The direction of the carousel. Can be either "horizontal" or "vertical". Default is "horizontal".[/en]
12477 * [ja]カルーセルの方向を指定します。"horizontal"か"vertical"を指定できます。"horizontal"がデフォルト値です。[/ja]
12478 */
12479
12480 /**
12481 * @attribute fullscreen
12482 * @description
12483 * [en]If this attribute is set the carousel will cover the whole screen.[/en]
12484 * [ja]この属性があると、absoluteポジションを使ってカルーセルが自動的に画面いっぱいに広がります。[/ja]
12485 */
12486
12487 /**
12488 * @attribute overscrollable
12489 * @description
12490 * [en]If this attribute is set the carousel will be scrollable over the edge. It will bounce back when released.[/en]
12491 * [ja]この属性がある時、タッチやドラッグで端までスクロールした時に、バウンドするような効果が当たります。[/ja]
12492 */
12493
12494 /**
12495 * @attribute centered
12496 * @description
12497 * [en]If this attribute is set the carousel then the selected item will be in the center of the carousel instead of the beginning. Useful only when the items are smaller than the carousel. [/en]
12498 * [ja]この属性がある時、選んでいるons-carousel-itemはカルーセルの真ん中へ行きます。項目がカルーセルよりも小さい場合にのみ、これは便利です。[/ja]
12499 */
12500
12501 /**
12502 * @attribute item-width
12503 * @type {String}
12504 * @description
12505 * [en]ons-carousel-item's width. Only works when the direction is set to "horizontal".[/en]
12506 * [ja]ons-carousel-itemの幅を指定します。この属性は、direction属性に"horizontal"を指定した時のみ有効になります。[/ja]
12507 */
12508
12509 /**
12510 * @attribute item-height
12511 * @type {String}
12512 * @description
12513 * [en]ons-carousel-item's height. Only works when the direction is set to "vertical".[/en]
12514 * [ja]ons-carousel-itemの高さを指定します。この属性は、direction属性に"vertical"を指定した時のみ有効になります。[/ja]
12515 */
12516
12517 /**
12518 * @attribute auto-scroll
12519 * @description
12520 * [en]If this attribute is set the carousel will be automatically scrolled to the closest item border when released.[/en]
12521 * [ja]この属性がある時、一番近いcarousel-itemの境界まで自動的にスクロールするようになります。[/ja]
12522 */
12523
12524 /**
12525 * @attribute auto-scroll-ratio
12526 * @type {Number}
12527 * @description
12528 * [en]A number between 0.0 and 1.0 that specifies how much the user must drag the carousel in order for it to auto scroll to the next item.[/en]
12529 * [ja]0.0から1.0までの値を指定します。カルーセルの要素をどれぐらいの割合までドラッグすると次の要素に自動的にスクロールするかを指定します。[/ja]
12530 */
12531
12532 /**
12533 * @attribute swipeable
12534 * @description
12535 * [en]If this attribute is set the carousel can be scrolled by drag or swipe.[/en]
12536 * [ja]この属性がある時、カルーセルをスワイプやドラッグで移動できるようになります。[/ja]
12537 */
12538
12539 /**
12540 * @attribute disabled
12541 * @description
12542 * [en]If this attribute is set the carousel is disabled.[/en]
12543 * [ja]この属性がある時、dragやtouchやswipeを受け付けなくなります。[/ja]
12544 */
12545
12546 /**
12547 * @attribute initial-index
12548 * @initonly
12549 * @type {Number}
12550 * @description
12551 * [en]Specify the index of the ons-carousel-item to show initially. Default is 0.[/en]
12552 * [ja]最初に表示するons-carousel-itemを0始まりのインデックスで指定します。デフォルト値は 0 です。[/ja]
12553 */
12554
12555 /**
12556 * @attribute auto-refresh
12557 * @description
12558 * [en]When this attribute is set the carousel will automatically refresh when the number of child nodes change.[/en]
12559 * [ja]この属性がある時、子要素の数が変わるとカルーセルは自動的に更新されるようになります。[/ja]
12560 */
12561
12562 /**
12563 * @attribute animation-options
12564 * @type {Expression}
12565 * @description
12566 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
12567 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
12568 */
12569
12570 value: function init() {
12571 this._doorLock = new DoorLock();
12572 this._scroll = 0;
12573 this._offset = 0;
12574 this._lastActiveIndex = 0;
12575
12576 this._boundOnDrag = this._onDrag.bind(this);
12577 this._boundOnDragEnd = this._onDragEnd.bind(this);
12578 this._boundOnResize = this._onResize.bind(this);
12579
12580 this._mixin(this._isVertical() ? VerticalModeTrait : HorizontalModeTrait);
12581 }
12582 }, {
12583 key: '_onResize',
12584 value: function _onResize() {
12585 var i = this._scroll / this._currentElementSize;
12586 delete this._currentElementSize;
12587 this.setActiveIndex(i);
12588 }
12589 }, {
12590 key: '_onDirectionChange',
12591 value: function _onDirectionChange() {
12592 if (this._isVertical()) {
12593 this.style.overflowX = 'auto';
12594 this.style.overflowY = '';
12595 } else {
12596 this.style.overflowX = '';
12597 this.style.overflowY = 'auto';
12598 }
12599
12600 this.refresh();
12601 }
12602 }, {
12603 key: '_saveLastState',
12604 value: function _saveLastState() {
12605 this._lastState = {
12606 elementSize: this._getCarouselItemSize(),
12607 carouselElementCount: this.itemCount,
12608 width: this._getCarouselItemSize() * this.itemCount
12609 };
12610 }
12611
12612 /**
12613 * @return {Number}
12614 */
12615
12616 }, {
12617 key: '_getCarouselItemSize',
12618 value: function _getCarouselItemSize() {
12619 var sizeAttr = this._getCarouselItemSizeAttr();
12620 var sizeInfo = this._decomposeSizeString(sizeAttr);
12621 var elementSize = this._getElementSize();
12622
12623 if (sizeInfo.unit === '%') {
12624 return Math.round(sizeInfo.number / 100 * elementSize);
12625 } else if (sizeInfo.unit === 'px') {
12626 return sizeInfo.number;
12627 } else {
12628 throw new Error('Invalid state');
12629 }
12630 }
12631
12632 /**
12633 * @return {Number}
12634 */
12635
12636 }, {
12637 key: '_getInitialIndex',
12638 value: function _getInitialIndex() {
12639 var index = parseInt(this.getAttribute('initial-index'), 10);
12640
12641 if (typeof index === 'number' && !isNaN(index)) {
12642 return Math.max(Math.min(index, this.itemCount - 1), 0);
12643 } else {
12644 return 0;
12645 }
12646 }
12647
12648 /**
12649 * @return {String}
12650 */
12651
12652 }, {
12653 key: '_getCarouselItemSizeAttr',
12654 value: function _getCarouselItemSizeAttr() {
12655 var attrName = 'item-' + (this._isVertical() ? 'height' : 'width');
12656 var itemSizeAttr = ('' + this.getAttribute(attrName)).trim();
12657
12658 return itemSizeAttr.match(/^\d+(px|%)$/) ? itemSizeAttr : '100%';
12659 }
12660
12661 /**
12662 * @return {Object}
12663 */
12664
12665 }, {
12666 key: '_decomposeSizeString',
12667 value: function _decomposeSizeString(size) {
12668 var matches = size.match(/^(\d+)(px|%)/);
12669
12670 return {
12671 number: parseInt(matches[1], 10),
12672 unit: matches[2]
12673 };
12674 }
12675 }, {
12676 key: '_setupInitialIndex',
12677 value: function _setupInitialIndex() {
12678 this._scroll = (this._offset || 0) + this._getCarouselItemSize() * this._getInitialIndex();
12679 this._lastActiveIndex = this._getInitialIndex();
12680 this._scrollTo(this._scroll);
12681 }
12682
12683 /**
12684 * @method setActiveIndex
12685 * @signature setActiveIndex(index, [options])
12686 * @param {Number} index
12687 * [en]The index that the carousel should be set to.[/en]
12688 * [ja]carousel要素のインデックスを指定します。[/ja]
12689 * @param {Object} [options]
12690 * [en]Parameter object.[/en]
12691 * [ja][/ja]
12692 * @param {Function} [options.callback]
12693 * [en]A function that will be called after the animation is finished.[/en]
12694 * [ja][/ja]
12695 * @param {String} [options.animation]
12696 * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
12697 * [ja][/ja]
12698 * @param {Object} [options.animationOptions]
12699 * [en]An object that can be used to specify duration, delay and timing function of the animation.[/en]
12700 * [ja][/ja]
12701 * @description
12702 * [en]Specify the index of the `<ons-carousel-item>` to show.[/en]
12703 * [ja]表示するons-carousel-itemをindexで指定します。[/ja]
12704 * @return {Promise}
12705 * [en]Resolves to the carousel element.[/en]
12706 * [ja][/ja]
12707 */
12708
12709 }, {
12710 key: 'setActiveIndex',
12711 value: function setActiveIndex(index) {
12712 var _this2 = this;
12713
12714 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
12715
12716 if (options && (typeof options === 'undefined' ? 'undefined' : _typeof(options)) != 'object') {
12717 throw new Error('options must be an object. You supplied ' + options);
12718 }
12719
12720 options.animationOptions = util.extend({ duration: 0.3, timing: 'cubic-bezier(.1, .7, .1, 1)' }, options.animationOptions || {}, this.hasAttribute('animation-options') ? util.animationOptionsParse(this.getAttribute('animation-options')) : {});
12721
12722 index = Math.max(0, Math.min(index, this.itemCount - 1));
12723 var scroll = (this._offset || 0) + this._getCarouselItemSize() * index;
12724 var max = this._calculateMaxScroll();
12725
12726 this._scroll = Math.max(0, Math.min(max, scroll));
12727 return this._scrollTo(this._scroll, options).then(function () {
12728 _this2._tryFirePostChangeEvent();
12729 return _this2;
12730 });
12731 }
12732
12733 /**
12734 * @method getActiveIndex
12735 * @signature getActiveIndex()
12736 * @return {Number}
12737 * [en]The current carousel item index.[/en]
12738 * [ja]現在表示しているカルーセル要素のインデックスが返されます。[/ja]
12739 * @description
12740 * [en]Returns the index of the currently visible `<ons-carousel-item>`.[/en]
12741 * [ja]現在表示されているons-carousel-item要素のインデックスを返します。[/ja]
12742 */
12743
12744 }, {
12745 key: 'getActiveIndex',
12746 value: function getActiveIndex() {
12747 var scroll = this._scroll - (this._offset || 0);
12748 var count = this.itemCount;
12749 var size = this._getCarouselItemSize();
12750
12751 if (scroll < 0) {
12752 return 0;
12753 }
12754
12755 var i = void 0;
12756 for (i = 0; i < count; i++) {
12757 if (size * i <= scroll && size * (i + 1) > scroll) {
12758 return i;
12759 }
12760 }
12761
12762 // max carousel index
12763 return i;
12764 }
12765
12766 /**
12767 * @method next
12768 * @signature next([options])
12769 * @param {Object} [options]
12770 * [en]Parameter object.[/en]
12771 * [ja][/ja]
12772 * @param {Function} [options.callback]
12773 * [en]A function that will be executed after the animation has finished.[/en]
12774 * [ja][/ja]
12775 * @param {String} [options.animation]
12776 * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
12777 * [ja][/ja]
12778 * @param {Object} [options.animationOptions]
12779 * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
12780 * [ja][/ja]
12781 * @return {Promise}
12782 * [en]Resolves to the carousel element[/en]
12783 * [ja][/ja]
12784 * @description
12785 * [en]Show next `<ons-carousel-item>`.[/en]
12786 * [ja]次のons-carousel-itemを表示します。[/ja]
12787 */
12788
12789 }, {
12790 key: 'next',
12791 value: function next(options) {
12792 return this.setActiveIndex(this.getActiveIndex() + 1, options);
12793 }
12794
12795 /**
12796 * @method prev
12797 * @signature prev([options])
12798 * @param {Object} [options]
12799 * [en]Parameter object.[/en]
12800 * [ja][/ja]
12801 * @param {Function} [options.callback]
12802 * [en]A function that will be executed after the animation has finished.[/en]
12803 * [ja][/ja]
12804 * @param {String} [options.animation]
12805 * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
12806 * [ja][/ja]
12807 * @param {Object} [options.animationOptions]
12808 * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
12809 * [ja][/ja]
12810 * @return {Promise}
12811 * [en]Resolves to the carousel element[/en]
12812 * [ja][/ja]
12813 * @description
12814 * [en]Show previous `<ons-carousel-item>`.[/en]
12815 * [ja]前のons-carousel-itemを表示します。[/ja]
12816 */
12817
12818 }, {
12819 key: 'prev',
12820 value: function prev(options) {
12821 return this.setActiveIndex(this.getActiveIndex() - 1, options);
12822 }
12823
12824 /**
12825 * @return {Boolean}
12826 */
12827
12828 }, {
12829 key: '_isEnabledChangeEvent',
12830 value: function _isEnabledChangeEvent() {
12831 var elementSize = this._getElementSize();
12832 var carouselItemSize = this._getCarouselItemSize();
12833
12834 return this.autoScroll && Math.abs(elementSize - carouselItemSize) < 0.5;
12835 }
12836
12837 /**
12838 * @return {Boolean}
12839 */
12840
12841 }, {
12842 key: '_isVertical',
12843 value: function _isVertical() {
12844 return this.getAttribute('direction') === 'vertical';
12845 }
12846 }, {
12847 key: '_prepareEventListeners',
12848 value: function _prepareEventListeners() {
12849 var _this3 = this;
12850
12851 this._gestureDetector = new GestureDetector(this, {
12852 dragMinDistance: 1,
12853 dragLockToAxis: true
12854 });
12855 this._mutationObserver = new MutationObserver(function () {
12856 return _this3.refresh();
12857 });
12858
12859 this._updateSwipeable();
12860 this._updateAutoRefresh();
12861
12862 window.addEventListener('resize', this._boundOnResize, true);
12863 }
12864 }, {
12865 key: '_removeEventListeners',
12866 value: function _removeEventListeners() {
12867 this._gestureDetector.dispose();
12868 this._gestureDetector = null;
12869
12870 this._mutationObserver.disconnect();
12871 this._mutationObserver = null;
12872
12873 window.removeEventListener('resize', this._boundOnResize, true);
12874 }
12875 }, {
12876 key: '_updateSwipeable',
12877 value: function _updateSwipeable() {
12878 if (this._gestureDetector) {
12879 if (this.swipeable) {
12880 this._gestureDetector.on('drag dragleft dragright dragup dragdown swipe swipeleft swiperight swipeup swipedown', this._boundOnDrag);
12881 this._gestureDetector.on('dragend', this._boundOnDragEnd);
12882 } else {
12883 this._gestureDetector.off('drag dragleft dragright dragup dragdown swipe swipeleft swiperight swipeup swipedown', this._boundOnDrag);
12884 this._gestureDetector.off('dragend', this._boundOnDragEnd);
12885 }
12886 }
12887 }
12888 }, {
12889 key: '_updateAutoRefresh',
12890 value: function _updateAutoRefresh() {
12891 if (this._mutationObserver) {
12892 if (this.hasAttribute('auto-refresh')) {
12893 this._mutationObserver.observe(this, { childList: true });
12894 } else {
12895 this._mutationObserver.disconnect();
12896 }
12897 }
12898 }
12899 }, {
12900 key: '_tryFirePostChangeEvent',
12901 value: function _tryFirePostChangeEvent() {
12902 var currentIndex = this.getActiveIndex();
12903
12904 if (this._lastActiveIndex !== currentIndex) {
12905 var lastActiveIndex = this._lastActiveIndex;
12906 this._lastActiveIndex = currentIndex;
12907
12908 util.triggerElementEvent(this, 'postchange', {
12909 carousel: this,
12910 activeIndex: currentIndex,
12911 lastActiveIndex: lastActiveIndex
12912 });
12913 }
12914 }
12915 }, {
12916 key: '_isWrongDirection',
12917 value: function _isWrongDirection(d) {
12918 // this._lastDragDirection = d;
12919 return this._isVertical() ? d === 'left' || d === 'right' : d === 'up' || d === 'down';
12920 }
12921 }, {
12922 key: '_onDrag',
12923 value: function _onDrag(event) {
12924 if (this._isWrongDirection(event.gesture.direction)) {
12925 return;
12926 }
12927
12928 event.stopPropagation();
12929
12930 this._lastDragEvent = event;
12931
12932 var scroll = this._scroll - this._getScrollDelta(event);
12933 this._scrollTo(scroll);
12934 event.gesture.preventDefault();
12935
12936 this._tryFirePostChangeEvent();
12937 }
12938 }, {
12939 key: '_onDragEnd',
12940 value: function _onDragEnd(event) {
12941 var _this4 = this;
12942
12943 if (!this._lastDragEvent) {
12944 return;
12945 }
12946 this._currentElementSize = undefined;
12947 this._scroll = this._scroll - this._getScrollDelta(event);
12948
12949 // if (!this._isWrongDirection(this._lastDragDirection) && this._getScrollDelta(event) !== 0) {
12950 // event.stopPropagation();
12951 // }
12952
12953 if (this._isOverScroll(this._scroll)) {
12954 var waitForAction = false;
12955 util.triggerElementEvent(this, 'overscroll', {
12956 carousel: this,
12957 activeIndex: this.getActiveIndex(),
12958 direction: this._getOverScrollDirection(),
12959 waitToReturn: function waitToReturn(promise) {
12960 waitForAction = true;
12961 promise.then(function () {
12962 return _this4._scrollToKillOverScroll();
12963 });
12964 }
12965 });
12966
12967 if (!waitForAction) {
12968 this._scrollToKillOverScroll();
12969 }
12970 } else {
12971 this._startMomentumScroll();
12972 }
12973 this._lastDragEvent = null;
12974
12975 event.gesture.preventDefault();
12976 }
12977
12978 /**
12979 * @param {Object} trait
12980 */
12981
12982 }, {
12983 key: '_mixin',
12984 value: function _mixin(trait) {
12985 Object.keys(trait).forEach(function (key) {
12986 this[key] = trait[key];
12987 }.bind(this));
12988 }
12989 }, {
12990 key: '_startMomentumScroll',
12991 value: function _startMomentumScroll() {
12992 if (this._lastDragEvent) {
12993 var velocity = this._getScrollVelocity(this._lastDragEvent);
12994 var duration = 0.3;
12995 var scrollDelta = duration * 100 * velocity;
12996 var scroll = this._normalizeScrollPosition(this._scroll + (this._getScrollDelta(this._lastDragEvent) > 0 ? -scrollDelta : scrollDelta));
12997
12998 this._scroll = scroll;
12999
13000 animit(this._getCarouselItemElements()).queue({
13001 transform: this._generateScrollTransform(this._scroll)
13002 }, {
13003 duration: duration,
13004 timing: 'cubic-bezier(.1, .7, .1, 1)'
13005 }).queue(function (done) {
13006 done();
13007 this._tryFirePostChangeEvent();
13008 }.bind(this)).play();
13009 }
13010 }
13011 }, {
13012 key: '_normalizeScrollPosition',
13013 value: function _normalizeScrollPosition(scroll) {
13014 var max = this._calculateMaxScroll();
13015
13016 if (!this.autoScroll) {
13017 return Math.max(0, Math.min(max, scroll));
13018 }
13019 var arr = [];
13020 var size = this._getCarouselItemSize();
13021 var nbrOfItems = this.itemCount;
13022
13023 for (var i = 0; i < nbrOfItems; i++) {
13024 if (i * size + this._offset < max) {
13025 arr.push(i * size + this._offset);
13026 }
13027 }
13028 arr.push(max);
13029
13030 arr.sort(function (left, right) {
13031 left = Math.abs(left - scroll);
13032 right = Math.abs(right - scroll);
13033
13034 return left - right;
13035 });
13036
13037 arr = arr.filter(function (item, pos) {
13038 return !pos || item != arr[pos - 1];
13039 });
13040
13041 var lastScroll = this._lastActiveIndex * size + this._offset;
13042 var scrollRatio = Math.abs(scroll - lastScroll) / size;
13043 var result = arr[0];
13044
13045 if (scrollRatio <= this.autoScrollRatio) {
13046 result = lastScroll;
13047 } else if (scrollRatio < 1.0) {
13048 if (arr[0] === lastScroll && arr.length > 1) {
13049 result = arr[1];
13050 }
13051 }
13052
13053 return Math.max(0, Math.min(max, result));
13054 }
13055
13056 /**
13057 * @return {Array}
13058 */
13059
13060 }, {
13061 key: '_getCarouselItemElements',
13062 value: function _getCarouselItemElements() {
13063 return util.arrayFrom(this.children).filter(function (child) {
13064 return child.nodeName.toLowerCase() === 'ons-carousel-item';
13065 });
13066 }
13067
13068 /**
13069 * @param {Number} scroll
13070 * @param {Object} [options]
13071 * @return {Promise} Resolves to the carousel element
13072 */
13073
13074 }, {
13075 key: '_scrollTo',
13076 value: function _scrollTo(scroll) {
13077 var _this5 = this;
13078
13079 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
13080
13081 var isOverscrollable = this.overscrollable;
13082
13083 var normalizeScroll = function normalizeScroll(scroll) {
13084 var ratio = 0.35;
13085
13086 if (scroll < 0) {
13087 return isOverscrollable ? Math.round(scroll * ratio) : 0;
13088 }
13089
13090 var maxScroll = _this5._calculateMaxScroll();
13091 if (maxScroll < scroll) {
13092 return isOverscrollable ? maxScroll + Math.round((scroll - maxScroll) * ratio) : maxScroll;
13093 }
13094
13095 return scroll;
13096 };
13097
13098 return new Promise(function (resolve) {
13099 animit(_this5._getCarouselItemElements()).queue({
13100 transform: _this5._generateScrollTransform(normalizeScroll(scroll))
13101 }, options.animation !== 'none' ? options.animationOptions : {}).play(function () {
13102 if (options.callback instanceof Function) {
13103 options.callback();
13104 }
13105 resolve();
13106 });
13107 });
13108 }
13109 }, {
13110 key: '_calculateMaxScroll',
13111 value: function _calculateMaxScroll() {
13112 var max = this.itemCount * this._getCarouselItemSize() - this._getElementSize();
13113 return Math.ceil(max < 0 ? 0 : max); // Need to return an integer value.
13114 }
13115 }, {
13116 key: '_isOverScroll',
13117 value: function _isOverScroll(scroll) {
13118 if (scroll < 0 || scroll > this._calculateMaxScroll()) {
13119 return true;
13120 }
13121 return false;
13122 }
13123 }, {
13124 key: '_getOverScrollDirection',
13125 value: function _getOverScrollDirection() {
13126 if (this._isVertical()) {
13127 return this._scroll <= 0 ? 'up' : 'down';
13128 } else {
13129 return this._scroll <= 0 ? 'left' : 'right';
13130 }
13131 }
13132 }, {
13133 key: '_scrollToKillOverScroll',
13134 value: function _scrollToKillOverScroll() {
13135 var duration = 0.4;
13136
13137 if (this._scroll < 0) {
13138 animit(this._getCarouselItemElements()).queue({
13139 transform: this._generateScrollTransform(0)
13140 }, {
13141 duration: duration,
13142 timing: 'cubic-bezier(.1, .4, .1, 1)'
13143 }).queue(function (done) {
13144 done();
13145 this._tryFirePostChangeEvent();
13146 }.bind(this)).play();
13147 this._scroll = 0;
13148 return;
13149 }
13150
13151 var maxScroll = this._calculateMaxScroll();
13152
13153 if (maxScroll < this._scroll) {
13154 animit(this._getCarouselItemElements()).queue({
13155 transform: this._generateScrollTransform(maxScroll)
13156 }, {
13157 duration: duration,
13158 timing: 'cubic-bezier(.1, .4, .1, 1)'
13159 }).queue(function (done) {
13160 done();
13161 this._tryFirePostChangeEvent();
13162 }.bind(this)).play();
13163 this._scroll = maxScroll;
13164 return;
13165 }
13166
13167 return;
13168 }
13169
13170 /**
13171 * @property itemCount
13172 * @readonly
13173 * @type {Number}
13174 * @description
13175 * [en]The number of carousel items.[/en]
13176 * [ja]カルーセル要素の数です。[/ja]
13177 */
13178
13179 }, {
13180 key: 'refresh',
13181
13182
13183 /**
13184 * @method refresh
13185 * @signature refresh()
13186 * @description
13187 * [en]Update the layout of the carousel. Used when adding `<ons-carousel-items>` dynamically or to automatically adjust the size.[/en]
13188 * [ja]レイアウトや内部の状態を最新のものに更新します。ons-carousel-itemを動的に増やしたり、ons-carouselの大きさを動的に変える際に利用します。[/ja]
13189 */
13190 value: function refresh() {
13191 // Bug fix
13192 if (this._getCarouselItemSize() === 0) {
13193 return;
13194 }
13195
13196 this._mixin(this._isVertical() ? VerticalModeTrait : HorizontalModeTrait);
13197 this._setup();
13198
13199 if (this._lastState && this._lastState.width > 0) {
13200 var scroll = this._scroll; // - this._offset;
13201
13202 if (this._isOverScroll(scroll)) {
13203 this._scrollToKillOverScroll();
13204 } else {
13205 if (this.autoScroll) {
13206 scroll = this._normalizeScrollPosition(scroll);
13207 }
13208
13209 this._scrollTo(scroll);
13210 }
13211 }
13212
13213 this._saveLastState();
13214
13215 util.triggerElementEvent(this, 'refresh', { carousel: this });
13216 }
13217
13218 /**
13219 * @method first
13220 * @signature first()
13221 * @param {Object} [options]
13222 * [en]Parameter object.[/en]
13223 * [ja][/ja]
13224 * @param {Function} [options.callback]
13225 * [en]A function that will be executed after the animation has finished.[/en]
13226 * [ja][/ja]
13227 * @param {String} [options.animation]
13228 * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
13229 * [ja][/ja]
13230 * @param {Object} [options.animationOptions]
13231 * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
13232 * [ja][/ja]
13233 * @return {Promise}
13234 * [en]Resolves to the carousel element[/en]
13235 * [ja][/ja]
13236 * @description
13237 * [en]Show first `<ons-carousel-item>`.[/en]
13238 * [ja]最初のons-carousel-itemを表示します。[/ja]
13239 */
13240
13241 }, {
13242 key: 'first',
13243 value: function first(options) {
13244 return this.setActiveIndex(0, options);
13245 }
13246
13247 /**
13248 * @method last
13249 * @signature last()
13250 * @param {Object} [options]
13251 * [en]Parameter object.[/en]
13252 * [ja][/ja]
13253 * @param {Function} [options.callback]
13254 * [en]A function that will be executed after the animation has finished.[/en]
13255 * [ja][/ja]
13256 * @param {String} [options.animation]
13257 * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en]
13258 * [ja][/ja]
13259 * @param {Object} [options.animationOptions]
13260 * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en]
13261 * [ja][/ja]
13262 * @return {Promise}
13263 * [en]Resolves to the carousel element[/en]
13264 * [ja]Resolves to the carousel element[/ja]
13265 * @description
13266 * [en]Show last ons-carousel item.[/en]
13267 * [ja]最後のons-carousel-itemを表示します。[/ja]
13268 */
13269
13270 }, {
13271 key: 'last',
13272 value: function last(options) {
13273 this.setActiveIndex(Math.max(this.itemCount - 1, 0), options);
13274 }
13275 }, {
13276 key: 'connectedCallback',
13277 value: function connectedCallback() {
13278 var _this6 = this;
13279
13280 this._prepareEventListeners();
13281
13282 this._setup();
13283 this._setupInitialIndex();
13284
13285 this._saveLastState();
13286
13287 // Fix rendering glitch on Android 4.1
13288 if (this.offsetHeight === 0) {
13289 setImmediate(function () {
13290 return _this6.refresh();
13291 });
13292 }
13293 }
13294 }, {
13295 key: 'attributeChangedCallback',
13296 value: function attributeChangedCallback(name, last, current) {
13297 switch (name) {
13298 case 'swipeable':
13299 this._updateSwipeable();
13300 break;
13301 case 'auto-refresh':
13302 this._updateAutoRefresh();
13303 break;
13304 case 'direction':
13305 this._onDirectionChange();
13306 }
13307 }
13308 }, {
13309 key: 'disconnectedCallback',
13310 value: function disconnectedCallback() {
13311 this._removeEventListeners();
13312 }
13313
13314 /**
13315 * @property autoScrollRatio
13316 * @type {Number}
13317 * @description
13318 * [en]The current auto scroll ratio. [/en]
13319 * [ja]現在のオートスクロールのratio値。[/ja]
13320 */
13321
13322 }, {
13323 key: 'itemCount',
13324 get: function get() {
13325 return this._getCarouselItemElements().length;
13326 }
13327 }, {
13328 key: 'autoScrollRatio',
13329 get: function get() {
13330 var attr = this.getAttribute('auto-scroll-ratio');
13331
13332 if (!attr) {
13333 return 0.5;
13334 }
13335
13336 var scrollRatio = parseFloat(attr);
13337 if (scrollRatio < 0.0 || scrollRatio > 1.0) {
13338 throw new Error('Invalid ratio.');
13339 }
13340
13341 return isNaN(scrollRatio) ? 0.5 : scrollRatio;
13342 },
13343 set: function set(ratio) {
13344 if (ratio < 0.0 || ratio > 1.0) {
13345 throw new Error('Invalid ratio.');
13346 }
13347
13348 this.setAttribute('auto-scroll-ratio', ratio);
13349 }
13350
13351 /**
13352 * @property swipeable
13353 * @type {Boolean}
13354 * @description
13355 * [en]true if the carousel is swipeable.[/en]
13356 * [ja]swipeableであればtrueを返します。[/ja]
13357 */
13358
13359 }, {
13360 key: 'swipeable',
13361 get: function get() {
13362 return this.hasAttribute('swipeable');
13363 },
13364 set: function set(value) {
13365 return util.toggleAttribute(this, 'swipeable', value);
13366 }
13367
13368 /**
13369 * @property autoScroll
13370 * @type {Boolean}
13371 * @description
13372 * [en]true if auto scroll is enabled.[/en]
13373 * [ja]オートスクロールが有効であればtrueを返します。[/ja]
13374 */
13375
13376 }, {
13377 key: 'autoScroll',
13378 get: function get() {
13379 return this.hasAttribute('auto-scroll');
13380 },
13381 set: function set(value) {
13382 return util.toggleAttribute(this, 'auto-scroll', value);
13383 }
13384
13385 /**
13386 * @property disabled
13387 * @type {Boolean}
13388 * @description
13389 * [en]Whether the carousel is disabled or not.[/en]
13390 * [ja]無効化されている場合に`true`。[/ja]
13391 */
13392
13393 }, {
13394 key: 'disabled',
13395 get: function get() {
13396 return this.hasAttribute('disabled');
13397 },
13398 set: function set(value) {
13399 return util.toggleAttribute(this, 'disabled', value);
13400 }
13401
13402 /**
13403 * @property overscrollable
13404 * @type {Boolean}
13405 * @description
13406 * [en]Whether the carousel is overscrollable or not.[/en]
13407 * [ja]overscrollできればtrueを返します。[/ja]
13408 */
13409
13410 }, {
13411 key: 'overscrollable',
13412 get: function get() {
13413 return this.hasAttribute('overscrollable');
13414 },
13415 set: function set(value) {
13416 return util.toggleAttribute(this, 'overscrollable', value);
13417 }
13418
13419 /**
13420 * @property centered
13421 * @type {Boolean}
13422 * @description
13423 * [en]Whether the carousel is centered or not.[/en]
13424 * [ja]centered状態になっていればtrueを返します。[/ja]
13425 */
13426
13427 }, {
13428 key: 'centered',
13429 get: function get() {
13430 return this.hasAttribute('centered');
13431 },
13432 set: function set(value) {
13433 return util.toggleAttribute(this, 'centered', value);
13434 }
13435 }], [{
13436 key: 'observedAttributes',
13437 get: function get() {
13438 return ['swipeable', 'auto-refresh', 'direction'];
13439 }
13440 }]);
13441 return CarouselElement;
13442}(BaseElement);
13443
13444customElements.define('ons-carousel', CarouselElement);
13445
13446/*
13447Copyright 2013-2015 ASIAL CORPORATION
13448
13449Licensed under the Apache License, Version 2.0 (the "License");
13450you may not use this file except in compliance with the License.
13451You may obtain a copy of the License at
13452
13453 http://www.apache.org/licenses/LICENSE-2.0
13454
13455Unless required by applicable law or agreed to in writing, software
13456distributed under the License is distributed on an "AS IS" BASIS,
13457WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13458See the License for the specific language governing permissions and
13459limitations under the License.
13460
13461*/
13462
13463/**
13464 * @element ons-col
13465 * @category grid
13466 * @description
13467 * [en]Represents a column in the grid system. Use with `<ons-row>` to layout components.[/en]
13468 * [ja]グリッドシステムにて列を定義します。ons-rowとともに使用し、コンポーネントのレイアウトに利用します。[/ja]
13469 * @note
13470 * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-column, they may not be displayed correctly. You can use only one alignment.[/en]
13471 * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-columnを組み合わせた場合に描画が崩れる場合があります。[/ja]
13472 * @codepen GgujC {wide}
13473 * @guide layouting [en]Layouting guide[/en][ja]レイアウト機能[/ja]
13474 * @seealso ons-row
13475 * [en]The `<ons-row>` component is the parent of `<ons-col>`.[/en]
13476 * [ja]ons-rowコンポーネント[/ja]
13477 * @example
13478 * <ons-row>
13479 * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col>
13480 * <ons-col>Text</ons-col>
13481 * </ons-row>
13482 */
13483
13484/**
13485 * @attribute vertical-align
13486 * @type {String}
13487 * @description
13488 * [en]Vertical alignment of the column. Valid values are "top", "center", and "bottom".[/en]
13489 * [ja]縦の配置を指定する。"top", "center", "bottom"のいずれかを指定します。[/ja]
13490 */
13491
13492/**
13493 * @attribute width
13494 * @type {String}
13495 * @description
13496 * [en]The width of the column. Valid values are css width values ("10%", "50px").[/en]
13497 * [ja]カラムの横幅を指定する。パーセントもしくはピクセルで指定します(10%や50px)。[/ja]
13498 */
13499
13500var ColElement = function (_BaseElement) {
13501 inherits(ColElement, _BaseElement);
13502
13503 function ColElement() {
13504 classCallCheck(this, ColElement);
13505 return possibleConstructorReturn(this, (ColElement.__proto__ || Object.getPrototypeOf(ColElement)).apply(this, arguments));
13506 }
13507
13508 createClass(ColElement, [{
13509 key: 'init',
13510 value: function init() {
13511 if (this.getAttribute('width')) {
13512 this._updateWidth();
13513 }
13514 }
13515 }, {
13516 key: 'attributeChangedCallback',
13517 value: function attributeChangedCallback(name, last, current) {
13518 if (name === 'width') {
13519 this._updateWidth();
13520 }
13521 }
13522 }, {
13523 key: '_updateWidth',
13524 value: function _updateWidth() {
13525 var width = this.getAttribute('width');
13526 if (typeof width === 'string') {
13527 width = ('' + width).trim();
13528 width = width.match(/^\d+$/) ? width + '%' : width;
13529
13530 this.style.webkitBoxFlex = '0';
13531 this.style.webkitFlex = '0 0 ' + width;
13532 this.style.mozBoxFlex = '0';
13533 this.style.mozFlex = '0 0 ' + width;
13534 this.style.msFlex = '0 0 ' + width;
13535 this.style.flex = '0 0 ' + width;
13536 this.style.maxWidth = width;
13537 }
13538 }
13539 }], [{
13540 key: 'observedAttributes',
13541 get: function get() {
13542 return ['width'];
13543 }
13544 }]);
13545 return ColElement;
13546}(BaseElement);
13547
13548customElements.define('ons-col', ColElement);
13549
13550/*
13551Copyright 2013-2015 ASIAL CORPORATION
13552
13553Licensed under the Apache License, Version 2.0 (the "License");
13554you may not use this file except in compliance with the License.
13555You may obtain a copy of the License at
13556
13557 http://www.apache.org/licenses/LICENSE-2.0
13558
13559Unless required by applicable law or agreed to in writing, software
13560distributed under the License is distributed on an "AS IS" BASIS,
13561WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13562See the License for the specific language governing permissions and
13563limitations under the License.
13564
13565*/
13566
13567var DialogAnimator = function () {
13568 function DialogAnimator() {
13569 var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
13570 _ref$timing = _ref.timing,
13571 timing = _ref$timing === undefined ? 'linear' : _ref$timing,
13572 _ref$delay = _ref.delay,
13573 delay = _ref$delay === undefined ? 0 : _ref$delay,
13574 _ref$duration = _ref.duration,
13575 duration = _ref$duration === undefined ? 0.2 : _ref$duration;
13576
13577 classCallCheck(this, DialogAnimator);
13578
13579 this.timing = timing;
13580 this.delay = delay;
13581 this.duration = duration;
13582 }
13583
13584 /**
13585 * @param {HTMLElement} dialog
13586 * @param {Function} done
13587 */
13588
13589
13590 createClass(DialogAnimator, [{
13591 key: 'show',
13592 value: function show(dialog, done) {
13593 done();
13594 }
13595
13596 /**
13597 * @param {HTMLElement} dialog
13598 * @param {Function} done
13599 */
13600
13601 }, {
13602 key: 'hide',
13603 value: function hide(dialog, done) {
13604 done();
13605 }
13606 }]);
13607 return DialogAnimator;
13608}();
13609
13610/**
13611 * Android style animator for dialog.
13612 */
13613var AndroidDialogAnimator = function (_DialogAnimator) {
13614 inherits(AndroidDialogAnimator, _DialogAnimator);
13615
13616 function AndroidDialogAnimator() {
13617 var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
13618 _ref2$timing = _ref2.timing,
13619 timing = _ref2$timing === undefined ? 'ease-in-out' : _ref2$timing,
13620 _ref2$delay = _ref2.delay,
13621 delay = _ref2$delay === undefined ? 0 : _ref2$delay,
13622 _ref2$duration = _ref2.duration,
13623 duration = _ref2$duration === undefined ? 0.3 : _ref2$duration;
13624
13625 classCallCheck(this, AndroidDialogAnimator);
13626 return possibleConstructorReturn(this, (AndroidDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
13627 }
13628
13629 /**
13630 * @param {Object} dialog
13631 * @param {Function} callback
13632 */
13633
13634
13635 createClass(AndroidDialogAnimator, [{
13636 key: 'show',
13637 value: function show(dialog, callback) {
13638 callback = callback ? callback : function () {};
13639
13640 animit.runAll(animit(dialog._mask).queue({
13641 opacity: 0
13642 }).wait(this.delay).queue({
13643 opacity: 1.0
13644 }, {
13645 duration: this.duration,
13646 timing: this.timing
13647 }), animit(dialog._dialog).saveStyle().queue({
13648 css: {
13649 transform: 'translate3d(-50%, -60%, 0)',
13650 opacity: 0.0
13651 },
13652 duration: 0
13653 }).wait(this.delay).queue({
13654 css: {
13655 transform: 'translate3d(-50%, -50%, 0)',
13656 opacity: 1.0
13657 },
13658 duration: this.duration,
13659 timing: this.timing
13660 }).restoreStyle().queue(function (done) {
13661 callback();
13662 done();
13663 }));
13664 }
13665
13666 /**
13667 * @param {Object} dialog
13668 * @param {Function} callback
13669 */
13670
13671 }, {
13672 key: 'hide',
13673 value: function hide(dialog, callback) {
13674 callback = callback ? callback : function () {};
13675
13676 animit.runAll(animit(dialog._mask).queue({
13677 opacity: 1.0
13678 }).wait(this.delay).queue({
13679 opacity: 0
13680 }, {
13681 duration: this.duration,
13682 timing: this.timing
13683 }), animit(dialog._dialog).saveStyle().queue({
13684 css: {
13685 transform: 'translate3d(-50%, -50%, 0)',
13686 opacity: 1.0
13687 },
13688 duration: 0
13689 }).wait(this.delay).queue({
13690 css: {
13691 transform: 'translate3d(-50%, -60%, 0)',
13692 opacity: 0.0
13693 },
13694 duration: this.duration,
13695 timing: this.timing
13696 }).restoreStyle().queue(function (done) {
13697 callback();
13698 done();
13699 }));
13700 }
13701 }]);
13702 return AndroidDialogAnimator;
13703}(DialogAnimator);
13704
13705/**
13706 * iOS style animator for dialog.
13707 */
13708var IOSDialogAnimator = function (_DialogAnimator2) {
13709 inherits(IOSDialogAnimator, _DialogAnimator2);
13710
13711 function IOSDialogAnimator() {
13712 var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
13713 _ref3$timing = _ref3.timing,
13714 timing = _ref3$timing === undefined ? 'ease-in-out' : _ref3$timing,
13715 _ref3$delay = _ref3.delay,
13716 delay = _ref3$delay === undefined ? 0 : _ref3$delay,
13717 _ref3$duration = _ref3.duration,
13718 duration = _ref3$duration === undefined ? 0.3 : _ref3$duration;
13719
13720 classCallCheck(this, IOSDialogAnimator);
13721 return possibleConstructorReturn(this, (IOSDialogAnimator.__proto__ || Object.getPrototypeOf(IOSDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
13722 }
13723
13724 /**
13725 * @param {Object} dialog
13726 * @param {Function} callback
13727 */
13728
13729
13730 createClass(IOSDialogAnimator, [{
13731 key: 'show',
13732 value: function show(dialog, callback) {
13733 callback = callback ? callback : function () {};
13734
13735 animit.runAll(animit(dialog._mask).queue({
13736 opacity: 0
13737 }).wait(this.delay).queue({
13738 opacity: 1.0
13739 }, {
13740 duration: this.duration,
13741 timing: this.timing
13742 }), animit(dialog._dialog).saveStyle().queue({
13743 css: {
13744 transform: 'translate3d(-50%, 300%, 0)'
13745 },
13746 duration: 0
13747 }).wait(this.delay).queue({
13748 css: {
13749 transform: 'translate3d(-50%, -50%, 0)'
13750 },
13751 duration: this.duration,
13752 timing: this.timing
13753 }).restoreStyle().queue(function (done) {
13754 callback();
13755 done();
13756 }));
13757 }
13758
13759 /**
13760 * @param {Object} dialog
13761 * @param {Function} callback
13762 */
13763
13764 }, {
13765 key: 'hide',
13766 value: function hide(dialog, callback) {
13767 callback = callback ? callback : function () {};
13768
13769 animit.runAll(animit(dialog._mask).queue({
13770 opacity: 1.0
13771 }).wait(this.delay).queue({
13772 opacity: 0
13773 }, {
13774 duration: this.duration,
13775 timing: this.timing
13776 }), animit(dialog._dialog).saveStyle().queue({
13777 css: {
13778 transform: 'translate3d(-50%, -50%, 0)'
13779 },
13780 duration: 0
13781 }).wait(this.delay).queue({
13782 css: {
13783 transform: 'translate3d(-50%, 300%, 0)'
13784 },
13785 duration: this.duration,
13786 timing: this.timing
13787 }).restoreStyle().queue(function (done) {
13788 callback();
13789 done();
13790 }));
13791 }
13792 }]);
13793 return IOSDialogAnimator;
13794}(DialogAnimator);
13795
13796/**
13797 * Slide animator for dialog.
13798 */
13799var SlideDialogAnimator = function (_DialogAnimator3) {
13800 inherits(SlideDialogAnimator, _DialogAnimator3);
13801
13802 function SlideDialogAnimator() {
13803 var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
13804 _ref4$timing = _ref4.timing,
13805 timing = _ref4$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref4$timing,
13806 _ref4$delay = _ref4.delay,
13807 delay = _ref4$delay === undefined ? 0 : _ref4$delay,
13808 _ref4$duration = _ref4.duration,
13809 duration = _ref4$duration === undefined ? 0.2 : _ref4$duration;
13810
13811 classCallCheck(this, SlideDialogAnimator);
13812 return possibleConstructorReturn(this, (SlideDialogAnimator.__proto__ || Object.getPrototypeOf(SlideDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration }));
13813 }
13814
13815 /**
13816 * @param {Object} dialog
13817 * @param {Function} callback
13818 */
13819
13820
13821 createClass(SlideDialogAnimator, [{
13822 key: 'show',
13823 value: function show(dialog, callback) {
13824 callback = callback ? callback : function () {};
13825
13826 animit.runAll(animit(dialog._mask).queue({
13827 opacity: 0
13828 }).wait(this.delay).queue({
13829 opacity: 1.0
13830 }, {
13831 duration: this.duration,
13832 timing: this.timing
13833 }), animit(dialog._dialog).saveStyle().queue({
13834 css: {
13835 transform: 'translate3D(-50%, -350%, 0)'
13836 },
13837 duration: 0
13838 }).wait(this.delay).queue({
13839 css: {
13840 transform: 'translate3D(-50%, -50%, 0)'
13841 },
13842 duration: this.duration,
13843 timing: this.timing
13844 }).restoreStyle().queue(function (done) {
13845 callback();
13846 done();
13847 }));
13848 }
13849
13850 /**
13851 * @param {Object} dialog
13852 * @param {Function} callback
13853 */
13854
13855 }, {
13856 key: 'hide',
13857 value: function hide(dialog, callback) {
13858 callback = callback ? callback : function () {};
13859
13860 animit.runAll(animit(dialog._mask).queue({
13861 opacity: 1.0
13862 }).wait(this.delay).queue({
13863 opacity: 0
13864 }, {
13865 duration: this.duration,
13866 timing: this.timing
13867 }), animit(dialog._dialog).saveStyle().queue({
13868 css: {
13869 transform: 'translate3D(-50%, -50%, 0)'
13870 },
13871 duration: 0
13872 }).wait(this.delay).queue({
13873 css: {
13874 transform: 'translate3D(-50%, -350%, 0)'
13875 },
13876 duration: this.duration,
13877 timing: this.timing
13878 }).restoreStyle().queue(function (done) {
13879 callback();
13880 done();
13881 }));
13882 }
13883 }]);
13884 return SlideDialogAnimator;
13885}(DialogAnimator);
13886
13887/*
13888Copyright 2013-2015 ASIAL CORPORATION
13889
13890Licensed under the Apache License, Version 2.0 (the "License");
13891you may not use this file except in compliance with the License.
13892You may obtain a copy of the License at
13893
13894 http://www.apache.org/licenses/LICENSE-2.0
13895
13896Unless required by applicable law or agreed to in writing, software
13897distributed under the License is distributed on an "AS IS" BASIS,
13898WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13899See the License for the specific language governing permissions and
13900limitations under the License.
13901
13902*/
13903
13904var scheme$5 = {
13905 '.dialog': 'dialog--*',
13906 '.dialog-container': 'dialog-container--*',
13907 '.dialog-mask': 'dialog-mask--*'
13908};
13909
13910var _animatorDict$1 = {
13911 'default': function _default() {
13912 return platform.isAndroid() ? AndroidDialogAnimator : IOSDialogAnimator;
13913 },
13914 'slide': SlideDialogAnimator,
13915 'none': DialogAnimator
13916};
13917
13918/**
13919 * @element ons-dialog
13920 * @category dialog
13921 * @description
13922 * [en]
13923 * Dialog that is displayed on top of current screen. As opposed to the `<ons-alert-dialog>` element, this component can contain any kind of content.
13924 *
13925 * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createDialog(template)` utility function and the `<ons-template>` tag.
13926 *
13927 * The dialog is useful for displaying menus, additional information or to ask the user to make a decision.
13928 *
13929 * It will automatically be displayed as Material Design when running on an Android device.
13930 * [/en]
13931 * [ja][/ja]
13932 * @modifier material
13933 * [en]Display a Material Design dialog.[/en]
13934 * [ja]マテリアルデザインのダイアログを表示します。[/ja]
13935 * @codepen zxxaGa
13936 * @tutorial vanilla/Reference/dialog
13937 * @guide dialogs
13938 * [en]Dialog components[/en]
13939 * [ja]Dialog components[/ja]
13940 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
13941 * @seealso ons-alert-dialog
13942 * [en]`<ons-alert-dialog>` component[/en]
13943 * [ja]ons-alert-dialogコンポーネント[/ja]
13944 * @seealso ons-popover
13945 * [en]`<ons-popover>` component[/en]
13946 * [ja]ons-popoverコンポーネント[/ja]
13947 * @seealso ons-modal
13948 * [en]`<ons-modal>` component[/en]
13949 * [ja]ons-modalコンポーネント[/ja]
13950 * @example
13951 * <ons-dialog id="dialog">
13952 * <p>This is a dialog!</p>
13953 * </ons-dialog>
13954 *
13955 * <script>
13956 * document.getElementById('dialog').show();
13957 * </script>
13958 */
13959
13960var DialogElement = function (_BaseElement) {
13961 inherits(DialogElement, _BaseElement);
13962
13963 function DialogElement() {
13964 classCallCheck(this, DialogElement);
13965 return possibleConstructorReturn(this, (DialogElement.__proto__ || Object.getPrototypeOf(DialogElement)).apply(this, arguments));
13966 }
13967
13968 createClass(DialogElement, [{
13969 key: 'init',
13970 value: function init() {
13971 var _this2 = this;
13972
13973 contentReady(this, function () {
13974 return _this2._compile();
13975 });
13976
13977 this._visible = false;
13978 this._doorLock = new DoorLock();
13979 this._boundCancel = this._cancel.bind(this);
13980
13981 this._updateAnimatorFactory();
13982 }
13983 }, {
13984 key: '_updateAnimatorFactory',
13985 value: function _updateAnimatorFactory() {
13986 this._animatorFactory = new AnimatorFactory({
13987 animators: _animatorDict$1,
13988 baseClass: DialogAnimator,
13989 baseClassName: 'DialogAnimator',
13990 defaultAnimation: this.getAttribute('animation')
13991 });
13992 }
13993 }, {
13994 key: '_compile',
13995 value: function _compile() {
13996 autoStyle.prepare(this);
13997
13998 this.style.display = 'none';
13999
14000 /* Expected result:
14001 * <ons-dialog>
14002 * <div class="dialog-mask"></div>
14003 * <div class="dialog">
14004 * <div class="dialog-container">...</div>
14005 * </div>
14006 * </ons-dialog>
14007 */
14008
14009 if (!this._dialog) {
14010 var dialog = document.createElement('div');
14011 dialog.classList.add('dialog');
14012
14013 var container = document.createElement('div');
14014 dialog.classList.add('dialog-container');
14015
14016 dialog.appendChild(container);
14017
14018 while (this.firstChild) {
14019 container.appendChild(this.firstChild);
14020 }
14021
14022 this.appendChild(dialog);
14023 }
14024
14025 if (!this._mask) {
14026 var mask = document.createElement('div');
14027 mask.classList.add('dialog-mask');
14028 this.insertBefore(mask, this.firstChild);
14029 }
14030
14031 this._dialog.style.zIndex = 20001;
14032 this._mask.style.zIndex = 20000;
14033
14034 this.setAttribute('status-bar-fill', '');
14035
14036 ModifierUtil.initModifier(this, scheme$5);
14037 }
14038
14039 /**
14040 * @property onDeviceBackButton
14041 * @type {Object}
14042 * @description
14043 * [en]Back-button handler.[/en]
14044 * [ja]バックボタンハンドラ。[/ja]
14045 */
14046
14047 }, {
14048 key: '_cancel',
14049 value: function _cancel() {
14050 var _this3 = this;
14051
14052 if (this.cancelable && !this._running) {
14053 this._running = true;
14054 this.hide().then(function () {
14055 _this3._running = false;
14056 util.triggerElementEvent(_this3, 'dialog-cancel');
14057 }, function () {
14058 return _this3._running = false;
14059 });
14060 }
14061 }
14062
14063 /**
14064 * @method show
14065 * @signature show([options])
14066 * @param {Object} [options]
14067 * [en]Parameter object.[/en]
14068 * [ja]オプションを指定するオブジェクト。[/ja]
14069 * @param {String} [options.animation]
14070 * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
14071 * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定します。[/ja]
14072 * @param {String} [options.animationOptions]
14073 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
14074 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
14075 * @param {Function} [options.callback]
14076 * [en]This function is called after the dialog has been revealed.[/en]
14077 * [ja]ダイアログが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
14078 * @description
14079 * [en]Show the dialog.[/en]
14080 * [ja]ダイアログを開きます。[/ja]
14081 * @return {Promise} Resolves to the displayed element.
14082 */
14083
14084 }, {
14085 key: 'show',
14086 value: function show() {
14087 var _this4 = this;
14088
14089 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14090
14091 var _cancel2 = false;
14092 var callback = options.callback || function () {};
14093
14094 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
14095
14096 util.triggerElementEvent(this, 'preshow', {
14097 dialog: this,
14098 cancel: function cancel() {
14099 _cancel2 = true;
14100 }
14101 });
14102
14103 if (!_cancel2) {
14104 var _ret = function () {
14105 var tryShow = function tryShow() {
14106 var unlock = _this4._doorLock.lock();
14107 var animator = _this4._animatorFactory.newAnimator(options);
14108
14109 _this4.style.display = 'block';
14110 _this4._mask.style.opacity = '1';
14111
14112 return new Promise(function (resolve) {
14113 contentReady(_this4, function () {
14114 animator.show(_this4, function () {
14115 _this4._visible = true;
14116 unlock();
14117
14118 util.triggerElementEvent(_this4, 'postshow', { dialog: _this4 });
14119
14120 callback();
14121 resolve(_this4);
14122 });
14123 });
14124 });
14125 };
14126
14127 return {
14128 v: new Promise(function (resolve) {
14129 _this4._doorLock.waitUnlock(function () {
14130 return resolve(tryShow());
14131 });
14132 })
14133 };
14134 }();
14135
14136 if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
14137 } else {
14138 return Promise.reject('Canceled in preshow event.');
14139 }
14140 }
14141
14142 /**
14143 * @method hide
14144 * @signature hide([options])
14145 * @param {Object} [options]
14146 * [en]Parameter object.[/en]
14147 * [ja]オプションを指定するオブジェクト。[/ja]
14148 * @param {String} [options.animation]
14149 * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en]
14150 * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定できます。[/ja]
14151 * @param {String} [options.animationOptions]
14152 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
14153 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/ja]
14154 * @param {Function} [options.callback]
14155 * [en]This functions is called after the dialog has been hidden.[/en]
14156 * [ja]ダイアログが隠れた後に呼び出される関数オブジェクトを指定します。[/ja]
14157 * @description
14158 * [en]Hide the dialog.[/en]
14159 * [ja]ダイアログを閉じます。[/ja]
14160 * @return {Promise}
14161 * [en]Resolves to the hidden element[/en]
14162 * [ja][/ja]
14163 */
14164
14165 }, {
14166 key: 'hide',
14167 value: function hide() {
14168 var _this5 = this;
14169
14170 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14171
14172 var _cancel3 = false;
14173 var callback = options.callback || function () {};
14174
14175 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
14176
14177 util.triggerElementEvent(this, 'prehide', {
14178 dialog: this,
14179 cancel: function cancel() {
14180 _cancel3 = true;
14181 }
14182 });
14183
14184 if (!_cancel3) {
14185 var _ret2 = function () {
14186 var tryHide = function tryHide() {
14187 var unlock = _this5._doorLock.lock();
14188 var animator = _this5._animatorFactory.newAnimator(options);
14189
14190 return new Promise(function (resolve) {
14191 contentReady(_this5, function () {
14192 animator.hide(_this5, function () {
14193 _this5.style.display = 'none';
14194 _this5._visible = false;
14195 unlock();
14196
14197 util.triggerElementEvent(_this5, 'posthide', { dialog: _this5 });
14198
14199 callback();
14200 resolve(_this5);
14201 });
14202 });
14203 });
14204 };
14205
14206 return {
14207 v: new Promise(function (resolve) {
14208 _this5._doorLock.waitUnlock(function () {
14209 return resolve(tryHide());
14210 });
14211 })
14212 };
14213 }();
14214
14215 if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === "object") return _ret2.v;
14216 } else {
14217 return Promise.reject('Canceled in prehide event.');
14218 }
14219 }
14220
14221 /**
14222 * @property visible
14223 * @readonly
14224 * @type {Boolean}
14225 * @description
14226 * [en]Whether the dialog is visible or not.[/en]
14227 * [ja]要素が見える場合に`true`。[/ja]
14228 */
14229
14230 }, {
14231 key: 'connectedCallback',
14232 value: function connectedCallback() {
14233 var _this6 = this;
14234
14235 this.onDeviceBackButton = function (e) {
14236 return _this6.cancelable ? _this6._cancel() : e.callParentHandler();
14237 };
14238
14239 contentReady(this, function () {
14240 _this6._mask.addEventListener('click', _this6._boundCancel, false);
14241 });
14242 }
14243 }, {
14244 key: 'disconnectedCallback',
14245 value: function disconnectedCallback() {
14246 this._backButtonHandler.destroy();
14247 this._backButtonHandler = null;
14248
14249 this._mask.removeEventListener('click', this._boundCancel.bind(this), false);
14250 }
14251 }, {
14252 key: 'attributeChangedCallback',
14253 value: function attributeChangedCallback(name, last, current) {
14254 if (name === 'modifier') {
14255 return ModifierUtil.onModifierChanged(last, current, this, scheme$5);
14256 } else if (name === 'animation') {
14257 this._updateAnimatorFactory();
14258 }
14259 }
14260
14261 /**
14262 * @param {String} name
14263 * @param {DialogAnimator} Animator
14264 */
14265
14266 }, {
14267 key: '_mask',
14268
14269
14270 /**
14271 * @event preshow
14272 * @description
14273 * [en]Fired just before the dialog is displayed.[/en]
14274 * [ja]ダイアログが表示される直前に発火します。[/ja]
14275 * @param {Object} event [en]Event object.[/en]
14276 * @param {Object} event.dialog
14277 * [en]Component object.[/en]
14278 * [ja]コンポーネントのオブジェクト。[/ja]
14279 * @param {Function} event.cancel
14280 * [en]Execute this function to stop the dialog from being shown.[/en]
14281 * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja]
14282 */
14283
14284 /**
14285 * @event postshow
14286 * @description
14287 * [en]Fired just after the dialog is displayed.[/en]
14288 * [ja]ダイアログが表示された直後に発火します。[/ja]
14289 * @param {Object} event [en]Event object.[/en]
14290 * @param {Object} event.dialog
14291 * [en]Component object.[/en]
14292 * [ja]コンポーネントのオブジェクト。[/ja]
14293 */
14294
14295 /**
14296 * @event prehide
14297 * @description
14298 * [en]Fired just before the dialog is hidden.[/en]
14299 * [ja]ダイアログが隠れる直前に発火します。[/ja]
14300 * @param {Object} event [en]Event object.[/en]
14301 * @param {Object} event.dialog
14302 * [en]Component object.[/en]
14303 * [ja]コンポーネントのオブジェクト。[/ja]
14304 * @param {Function} event.cancel
14305 * [en]Execute this function to stop the dialog from being hidden.[/en]
14306 * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja]
14307 */
14308
14309 /**
14310 * @event posthide
14311 * @description
14312 * [en]Fired just after the dialog is hidden.[/en]
14313 * [ja]ダイアログが隠れた後に発火します。[/ja]
14314 * @param {Object} event [en]Event object.[/en]
14315 * @param {Object} event.dialog
14316 * [en]Component object.[/en]
14317 * [ja]コンポーネントのオブジェクト。[/ja]
14318 */
14319
14320 /**
14321 * @attribute modifier
14322 * @type {String}
14323 * @description
14324 * [en]The appearance of the dialog.[/en]
14325 * [ja]ダイアログの表現を指定します。[/ja]
14326 */
14327
14328 /**
14329 * @attribute cancelable
14330 * @description
14331 * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
14332 * [ja][/ja]
14333 */
14334
14335 /**
14336 * @attribute disabled
14337 * @description
14338 * [en]If this attribute is set the dialog is disabled.[/en]
14339 * [ja]この属性がある時、ダイアログはdisabled状態になります。[/ja]
14340 */
14341
14342 /**
14343 * @attribute animation
14344 * @type {String}
14345 * @default default
14346 * @description
14347 * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en]
14348 * [ja]ダイアログを表示する際のアニメーション名を指定します。"none"もしくは"default"を指定できます。[/ja]
14349 */
14350
14351 /**
14352 * @attribute animation-options
14353 * @type {Expression}
14354 * @description
14355 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
14356 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja]
14357 */
14358
14359 /**
14360 * @attribute mask-color
14361 * @type {String}
14362 * @default rgba(0, 0, 0, 0.2)
14363 * @description
14364 * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en]
14365 * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
14366 */
14367
14368 get: function get() {
14369 return util.findChild(this, '.dialog-mask');
14370 }
14371 }, {
14372 key: '_dialog',
14373 get: function get() {
14374 return util.findChild(this, '.dialog');
14375 }
14376 }, {
14377 key: 'onDeviceBackButton',
14378 get: function get() {
14379 return this._backButtonHandler;
14380 },
14381 set: function set(callback) {
14382 if (this._backButtonHandler) {
14383 this._backButtonHandler.destroy();
14384 }
14385
14386 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
14387 }
14388 }, {
14389 key: 'visible',
14390 get: function get() {
14391 return this._visible;
14392 }
14393
14394 /**
14395 * @property disabled
14396 * @type {Boolean}
14397 * @description
14398 * [en]Whether the dialog is disabled or not.[/en]
14399 * [ja]無効化されている場合に`true`。[/ja]
14400 */
14401
14402 }, {
14403 key: 'disabled',
14404 set: function set(value) {
14405 return util.toggleAttribute(this, 'disabled', value);
14406 },
14407 get: function get() {
14408 return this.hasAttribute('disabled');
14409 }
14410
14411 /**
14412 * @property cancelable
14413 * @type {Boolean}
14414 * @description
14415 * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en]
14416 * [ja][/ja]
14417 */
14418
14419 }, {
14420 key: 'cancelable',
14421 set: function set(value) {
14422 return util.toggleAttribute(this, 'cancelable', value);
14423 },
14424 get: function get() {
14425 return this.hasAttribute('cancelable');
14426 }
14427 }], [{
14428 key: 'registerAnimator',
14429 value: function registerAnimator(name, Animator) {
14430 if (!(Animator.prototype instanceof DialogAnimator)) {
14431 throw new Error('"Animator" param must inherit OnsDialogElement.DialogAnimator');
14432 }
14433 _animatorDict$1[name] = Animator;
14434 }
14435 }, {
14436 key: 'observedAttributes',
14437 get: function get() {
14438 return ['modifier', 'animation'];
14439 }
14440 }, {
14441 key: 'DialogAnimator',
14442 get: function get() {
14443 return DialogAnimator;
14444 }
14445 }]);
14446 return DialogElement;
14447}(BaseElement);
14448
14449customElements.define('ons-dialog', DialogElement);
14450
14451/*
14452Copyright 2013-2015 ASIAL CORPORATION
14453Licensed under the Apache License, Version 2.0 (the "License");
14454you may not use this file except in compliance with the License.
14455You may obtain a copy of the License at
14456 http://www.apache.org/licenses/LICENSE-2.0
14457Unless required by applicable law or agreed to in writing, software
14458distributed under the License is distributed on an "AS IS" BASIS,
14459WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14460See the License for the specific language governing permissions and
14461limitations under the License.
14462*/
14463
14464var scheme$6 = {
14465 '': 'fab--*'
14466};
14467
14468/**
14469 * @element ons-fab
14470 * @category form
14471 * @description
14472 * [en]
14473 * The Floating action button is a circular button defined in the [Material Design specification](https://www.google.com/design/spec/components/buttons-floating-action-button.html). They are often used to promote the primary action of the app.
14474 *
14475 * It can be displayed either as an inline element or in one of the corners. Normally it will be positioned in the lower right corner of the screen.
14476 * [/en]
14477 * [ja][/ja]
14478 * @tutorial vanilla/Reference/fab
14479 * @guide cross-platform-styling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
14480 * @seealso ons-speed-dial
14481 * [en]The `<ons-speed-dial>` component is a Floating action button that displays a menu when tapped.[/en]
14482 * [ja][/ja]
14483 */
14484
14485var FabElement = function (_BaseElement) {
14486 inherits(FabElement, _BaseElement);
14487
14488 function FabElement() {
14489 classCallCheck(this, FabElement);
14490 return possibleConstructorReturn(this, (FabElement.__proto__ || Object.getPrototypeOf(FabElement)).apply(this, arguments));
14491 }
14492
14493 createClass(FabElement, [{
14494 key: 'init',
14495
14496
14497 /**
14498 * @attribute modifier
14499 * @type {String}
14500 * @description
14501 * [en]The appearance of the button.[/en]
14502 * [ja]ボタンの表現を指定します。[/ja]
14503 */
14504
14505 /**
14506 * @attribute ripple
14507 * @description
14508 * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en]
14509 * [ja][/ja]
14510 */
14511
14512 /**
14513 * @attribute position
14514 * @type {String}
14515 * @description
14516 * [en]The position of the button. Should be a string like `"bottom right"` or `"top left"`. If this attribute is not defined it will be displayed as an inline element.[/en]
14517 * [ja][/ja]
14518 */
14519
14520 /**
14521 * @attribute disabled
14522 * @description
14523 * [en]Specify if button should be disabled.[/en]
14524 * [ja]ボタンを無効化する場合は指定します。[/ja]
14525 */
14526
14527 value: function init() {
14528 var _this2 = this;
14529
14530 contentReady(this, function () {
14531 _this2._compile();
14532 });
14533 }
14534 }, {
14535 key: '_compile',
14536 value: function _compile() {
14537 var _this3 = this;
14538
14539 autoStyle.prepare(this);
14540
14541 this.classList.add('fab');
14542
14543 if (!util.findChild(this, '.fab__icon')) {
14544 (function () {
14545 var content = document.createElement('span');
14546 content.classList.add('fab__icon');
14547
14548 util.arrayFrom(_this3.childNodes).forEach(function (element) {
14549 if (!element.tagName || element.tagName.toLowerCase() !== 'ons-ripple') {
14550 content.appendChild(element);
14551 }
14552 });
14553 _this3.appendChild(content);
14554 })();
14555 }
14556
14557 this._updateRipple();
14558
14559 ModifierUtil.initModifier(this, scheme$6);
14560
14561 this._updatePosition();
14562
14563 this.show();
14564 }
14565 }, {
14566 key: 'attributeChangedCallback',
14567 value: function attributeChangedCallback(name, last, current) {
14568 switch (name) {
14569 case 'modifier':
14570 ModifierUtil.onModifierChanged(last, current, this, scheme$6);
14571 break;
14572 case 'ripple':
14573 this._updateRipple();
14574 break;
14575 case 'position':
14576 this._updatePosition();
14577 }
14578 }
14579 }, {
14580 key: '_show',
14581 value: function _show() {
14582 this.show();
14583 }
14584 }, {
14585 key: '_hide',
14586 value: function _hide() {
14587 this.hide();
14588 }
14589 }, {
14590 key: '_updateRipple',
14591 value: function _updateRipple() {
14592 util.updateRipple(this);
14593 }
14594 }, {
14595 key: '_updatePosition',
14596 value: function _updatePosition() {
14597 var position = this.getAttribute('position');
14598 this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center');
14599 switch (position) {
14600 case 'top right':
14601 case 'right top':
14602 this.classList.add('fab--top__right');
14603 break;
14604 case 'top left':
14605 case 'left top':
14606 this.classList.add('fab--top__left');
14607 break;
14608 case 'bottom right':
14609 case 'right bottom':
14610 this.classList.add('fab--bottom__right');
14611 break;
14612 case 'bottom left':
14613 case 'left bottom':
14614 this.classList.add('fab--bottom__left');
14615 break;
14616 case 'center top':
14617 case 'top center':
14618 this.classList.add('fab--top__center');
14619 break;
14620 case 'center bottom':
14621 case 'bottom center':
14622 this.classList.add('fab--bottom__center');
14623 break;
14624 default:
14625 break;
14626 }
14627 }
14628
14629 /**
14630 * @method show
14631 * @signature show()
14632 * @description
14633 * [en]Show the floating action button.[/en]
14634 * [ja][/ja]
14635 */
14636
14637 }, {
14638 key: 'show',
14639 value: function show() {
14640 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14641
14642 this.style.transform = 'scale(1)';
14643 this.style.webkitTransform = 'scale(1)';
14644 }
14645
14646 /**
14647 * @method hide
14648 * @signature hide()
14649 * @description
14650 * [en]Hide the floating action button.[/en]
14651 * [ja][/ja]
14652 */
14653
14654 }, {
14655 key: 'hide',
14656 value: function hide() {
14657 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14658
14659 this.style.transform = 'scale(0)';
14660 this.style.webkitTransform = 'scale(0)';
14661 }
14662
14663 /**
14664 * @property disabled
14665 * @type {Boolean}
14666 * @description
14667 * [en]Whether the element is disabled or not.[/en]
14668 * [ja]無効化されている場合に`true`。[/ja]
14669 */
14670
14671 }, {
14672 key: 'toggle',
14673
14674
14675 /**
14676 * @method toggle
14677 * @signature toggle()
14678 * @description
14679 * [en]Toggle the visibility of the button.[/en]
14680 * [ja][/ja]
14681 */
14682 value: function toggle() {
14683 this.visible ? this.hide() : this.show();
14684 }
14685 }, {
14686 key: 'disabled',
14687 set: function set(value) {
14688 return util.toggleAttribute(this, 'disabled', value);
14689 },
14690 get: function get() {
14691 return this.hasAttribute('disabled');
14692 }
14693
14694 /**
14695 * @property visible
14696 * @readonly
14697 * @type {Boolean}
14698 * @description
14699 * [en]Whether the element is visible or not.[/en]
14700 * [ja]要素が見える場合に`true`。[/ja]
14701 */
14702
14703 }, {
14704 key: 'visible',
14705 get: function get() {
14706 return this.style.transform === 'scale(1)' && this.style.display !== 'none';
14707 }
14708 }], [{
14709 key: 'observedAttributes',
14710 get: function get() {
14711 return ['modifier', 'ripple', 'position'];
14712 }
14713 }]);
14714 return FabElement;
14715}(BaseElement);
14716
14717customElements.define('ons-fab', FabElement);
14718
14719/*
14720Copyright 2013-2015 ASIAL CORPORATION
14721
14722Licensed under the Apache License, Version 2.0 (the "License");
14723you may not use this file except in compliance with the License.
14724You may obtain a copy of the License at
14725
14726 http://www.apache.org/licenses/LICENSE-2.0
14727
14728Unless required by applicable law or agreed to in writing, software
14729distributed under the License is distributed on an "AS IS" BASIS,
14730WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14731See the License for the specific language governing permissions and
14732limitations under the License.
14733
14734*/
14735
14736/**
14737 * @element ons-gesture-detector
14738 * @category gesture
14739 * @description
14740 * [en]
14741 * Component to detect finger gestures within the wrapped element. Following gestures are supported:
14742 * - Drag gestures: `drag`, `dragleft`, `dragright`, `dragup`, `dragdown`
14743 * - Hold gestures: `hold`, `release`
14744 * - Swipe gestures: `swipe`, `swipeleft`, `swiperight`, `swipeup`, `swipedown`
14745 * - Tap gestures: `tap`, `doubletap`
14746 * - Pinch gestures: `pinch`, `pinchin`, `pinchout`
14747 * - Other gestures: `touch`, `transform`, `rotate`
14748 * [/en]
14749 * [ja]要素内のジェスチャー操作を検知します。詳しくはガイドを参照してください。[/ja]
14750 * @guide gesture-detector
14751 * [en]Detecting finger gestures[/en]
14752 * [ja]ジェスチャー操作の検知[/ja]
14753 * @example
14754 * <ons-gesture-detector>
14755 * <div id="detect-area" style="width: 100px; height: 100px;">
14756 * Swipe Here
14757 * </div>
14758 * </ons-gesture-detector>
14759 *
14760 * <script>
14761 * document.addEventListener('swipeleft', function(event) {
14762 * if (event.target.matches('#detect-area')) {
14763 * console.log('Swipe left is detected.');
14764 * }
14765 * });
14766 * </script>
14767 */
14768
14769var GestureDetectorElement = function (_BaseElement) {
14770 inherits(GestureDetectorElement, _BaseElement);
14771
14772 function GestureDetectorElement() {
14773 classCallCheck(this, GestureDetectorElement);
14774 return possibleConstructorReturn(this, (GestureDetectorElement.__proto__ || Object.getPrototypeOf(GestureDetectorElement)).apply(this, arguments));
14775 }
14776
14777 createClass(GestureDetectorElement, [{
14778 key: 'init',
14779 value: function init() {
14780 this._gestureDetector = new GestureDetector(this);
14781 }
14782 }]);
14783 return GestureDetectorElement;
14784}(BaseElement);
14785
14786customElements.define('ons-gesture-detector', GestureDetectorElement);
14787
14788/*
14789Copyright 2013-2015 ASIAL CORPORATION
14790
14791Licensed under the Apache License, Version 2.0 (the "License");
14792you may not use this file except in compliance with the License.
14793You may obtain a copy of the License at
14794
14795 http://www.apache.org/licenses/LICENSE-2.0
14796
14797Unless required by applicable law or agreed to in writing, software
14798distributed under the License is distributed on an "AS IS" BASIS,
14799WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14800See the License for the specific language governing permissions and
14801limitations under the License.
14802
14803*/
14804
14805/**
14806 * @element ons-icon
14807 * @category visual
14808 * @description
14809 * [en]
14810 * Displays an icon. The following icon suites are available:
14811 *
14812 * * [Font Awesome](https://fortawesome.github.io/Font-Awesome/)
14813 * * [Ionicons](http://ionicons.com/)
14814 * * [Material Design Iconic Font](http://zavoloklom.github.io/material-design-iconic-font/)
14815 * [/en]
14816 * [ja][/ja]
14817 * @codepen xAhvg
14818 * @tutorial vanilla/Reference/icon
14819 * @guide cross-platform-styling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
14820 * @example
14821 * <ons-icon
14822 * icon="md-car"
14823 * size="20px"
14824 * style="color: red">
14825 * </ons-icon>
14826 *
14827 * <ons-button>
14828 * <ons-icon icon="md-car"></ons-icon>
14829 * Car
14830 * </ons-button>
14831 */
14832
14833var IconElement = function (_BaseElement) {
14834 inherits(IconElement, _BaseElement);
14835
14836 function IconElement() {
14837 classCallCheck(this, IconElement);
14838 return possibleConstructorReturn(this, (IconElement.__proto__ || Object.getPrototypeOf(IconElement)).apply(this, arguments));
14839 }
14840
14841 createClass(IconElement, [{
14842 key: 'init',
14843
14844
14845 /**
14846 * @attribute icon
14847 * @type {String}
14848 * @description
14849 * [en]
14850 * The icon name. `"md-"` prefix for Material Icons, `"fa-"` for Font Awesome and `"ion-"` prefix for Ionicons.
14851 *
14852 * See all available icons on their respective sites:
14853 *
14854 * * [Font Awesome](https://fortawesome.github.io/Font-Awesome/)
14855 * * [Ionicons](http://ionicons.com)
14856 * * [Material Design Iconic Font](http://zavoloklom.github.io/material-design-iconic-font/)
14857 *
14858 * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix.
14859 *
14860 * The code:
14861 *
14862 * ```
14863 * <ons-icon
14864 * icon="ion-edit, material:md-edit">
14865 * </ons-icon>
14866 * ```
14867 *
14868 * will display `"md-edit"` for Material Design and `"ion-edit"` as the default icon.
14869 * [/en]
14870 * [ja][/ja]
14871 */
14872
14873 /**
14874 * @attribute size
14875 * @type {String}
14876 * @description
14877 * [en]
14878 * The sizes of the icon. Valid values are lg, 2x, 3x, 4x, 5x, or in the size in pixels.
14879 * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix.
14880 *
14881 * The code:
14882 *
14883 * ```
14884 * <ons-icon
14885 * icon="ion-edit"
14886 * size="32px, material:24px">
14887 * </ons-icon>
14888 * ```
14889 *
14890 * will render as a `24px` icon if the `"material"` modifier is present and `32px` otherwise.
14891 * [/en]
14892 * [ja][/ja]
14893 */
14894
14895 /**
14896 * @attribute rotate
14897 * @type {Number}
14898 * @description
14899 * [en]Number of degrees to rotate the icon. Valid values are 90, 180 and 270.[/en]
14900 * [ja]アイコンを回転して表示します。90, 180, 270から指定できます。[/ja]
14901 */
14902
14903 /**
14904 * @attribute fixed-width
14905 * @type {Boolean}
14906 * @default false
14907 * @description
14908 * [en]When used in a list, you want the icons to have the same width so that they align vertically by defining this attribute.[/en]
14909 * [ja][/ja]
14910 */
14911
14912 /**
14913 * @attribute spin
14914 * @description
14915 * [en]Specify whether the icon should be spinning.[/en]
14916 * [ja]アイコンを回転するかどうかを指定します。[/ja]
14917 */
14918
14919 value: function init() {
14920 this._compile();
14921 }
14922 }, {
14923 key: 'attributeChangedCallback',
14924 value: function attributeChangedCallback(name, last, current) {
14925 if (['icon', 'size', 'modifier'].indexOf(name) !== -1) {
14926 this._update();
14927 }
14928 }
14929 }, {
14930 key: '_compile',
14931 value: function _compile() {
14932 autoStyle.prepare(this);
14933 this._update();
14934 }
14935 }, {
14936 key: '_update',
14937 value: function _update() {
14938 var _this2 = this;
14939
14940 this._cleanClassAttribute();
14941
14942 var _buildClassAndStyle2 = this._buildClassAndStyle(this._getAttribute('icon'), this._getAttribute('size')),
14943 classList = _buildClassAndStyle2.classList,
14944 style = _buildClassAndStyle2.style;
14945
14946 util.extend(this.style, style);
14947
14948 classList.forEach(function (className) {
14949 return _this2.classList.add(className);
14950 });
14951 }
14952 }, {
14953 key: '_getAttribute',
14954 value: function _getAttribute(attr) {
14955 var parts = (this.getAttribute(attr) || '').split(/\s*,\s*/);
14956 var def = parts[0];
14957 var md = parts[1];
14958 md = (md || '').split(/\s*:\s*/);
14959 return (util.hasModifier(this, md[0]) ? md[1] : def) || '';
14960 }
14961
14962 /**
14963 * Remove unneeded class value.
14964 */
14965
14966 }, {
14967 key: '_cleanClassAttribute',
14968 value: function _cleanClassAttribute() {
14969 var _this3 = this;
14970
14971 util.arrayFrom(this.classList).filter(function (className) {
14972 return (/^(fa$|fa-|ion-|zmdi-)/.test(className)
14973 );
14974 }).forEach(function (className) {
14975 return _this3.classList.remove(className);
14976 });
14977
14978 this.classList.remove('zmdi');
14979 this.classList.remove('ons-icon--ion');
14980 }
14981 }, {
14982 key: '_buildClassAndStyle',
14983 value: function _buildClassAndStyle(iconName, size) {
14984 var classList = ['ons-icon'];
14985 var style = {};
14986
14987 // Icon
14988 if (iconName.indexOf('ion-') === 0) {
14989 classList.push(iconName);
14990 classList.push('ons-icon--ion');
14991 } else if (iconName.indexOf('fa-') === 0) {
14992 classList.push(iconName);
14993 classList.push('fa');
14994 } else if (iconName.indexOf('md-') === 0) {
14995 classList.push('zmdi');
14996 classList.push('zmdi-' + iconName.split(/\-(.+)?/)[1]);
14997 } else {
14998 classList.push('fa');
14999 classList.push('fa-' + iconName);
15000 }
15001
15002 // Size
15003 if (size.match(/^[1-5]x|lg$/)) {
15004 classList.push('fa-' + size);
15005 this.style.removeProperty('font-size');
15006 } else {
15007 style.fontSize = size;
15008 }
15009
15010 return {
15011 classList: classList,
15012 style: style
15013 };
15014 }
15015 }], [{
15016 key: 'observedAttributes',
15017 get: function get() {
15018 return ['icon', 'size', 'modifier'];
15019 }
15020 }]);
15021 return IconElement;
15022}(BaseElement);
15023
15024customElements.define('ons-icon', IconElement);
15025
15026/*
15027Copyright 2013-2015 ASIAL CORPORATION
15028Licensed under the Apache License, Version 2.0 (the "License");
15029you may not use this file except in compliance with the License.
15030You may obtain a copy of the License at
15031 http://www.apache.org/licenses/LICENSE-2.0
15032Unless required by applicable law or agreed to in writing, software
15033distributed under the License is distributed on an "AS IS" BASIS,
15034WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15035See the License for the specific language governing permissions and
15036limitations under the License.
15037*/
15038
15039/**
15040 * @element ons-lazy-repeat
15041 * @category list
15042 * @description
15043 * [en]
15044 * Using this component a list with millions of items can be rendered without a drop in performance.
15045 * It does that by "lazily" loading elements into the DOM when they come into view and
15046 * removing items from the DOM when they are not visible.
15047 * [/en]
15048 * [ja]
15049 * このコンポーネント内で描画されるアイテムのDOM要素の読み込みは、画面に見えそうになった時まで自動的に遅延され、
15050 * 画面から見えなくなった場合にはその要素は動的にアンロードされます。
15051 * このコンポーネントを使うことで、パフォーマンスを劣化させること無しに巨大な数の要素を描画できます。
15052 * [/ja]
15053 * @codepen QwrGBm
15054 * @tutorial vanilla/Reference/lazy-repeat
15055 * @seealso ons-list
15056 * [en]The `<ons-list>` element is used to render a list.[/en]
15057 * [ja]`<ons-list>`要素はリストを描画するのに使われます。[/ja]
15058 * @guide infinite-scroll
15059 * [en]Loading more items on infinite scroll[/en]
15060 * [ja]Loading more items on infinite scroll[/ja]
15061 * @example
15062 * <script>
15063 * window.addEventListener('load', function() {
15064 * var lazyRepeat = document.querySelector('#list');
15065 * lazyRepeat.delegate = {
15066 * createItemContent: function(i, template) {
15067 * var dom = template.cloneNode(true);
15068 * dom.innerText = i;
15069 *
15070 * return dom;
15071 * },
15072 * countItems: function() {
15073 * return 10000000;
15074 * },
15075 * destroyItem: function(index, item) {
15076 * console.log('Destroyed item with index: ' + index);
15077 * }
15078 * };
15079 * });
15080 * </script>
15081 *
15082 * <ons-list id="list">
15083 * <ons-lazy-repeat>
15084 * <ons-list-item></ons-list-item>
15085 * </ons-lazy-repeat>
15086 * </ons-list>
15087 */
15088
15089var LazyRepeatElement = function (_BaseElement) {
15090 inherits(LazyRepeatElement, _BaseElement);
15091
15092 function LazyRepeatElement() {
15093 classCallCheck(this, LazyRepeatElement);
15094 return possibleConstructorReturn(this, (LazyRepeatElement.__proto__ || Object.getPrototypeOf(LazyRepeatElement)).apply(this, arguments));
15095 }
15096
15097 createClass(LazyRepeatElement, [{
15098 key: 'connectedCallback',
15099 value: function connectedCallback() {
15100 util.updateParentPosition(this);
15101
15102 // not very good idea and also not documented
15103 if (this.hasAttribute('delegate')) {
15104 this.delegate = window[this.getAttribute('delegate')];
15105 }
15106 }
15107
15108 /**
15109 * @property delegate
15110 * @type {Object}
15111 * @description
15112 * [en]Specify a delegate object to load and unload item elements.[/en]
15113 * [ja]要素のロード、アンロードなどの処理を委譲するオブジェクトを指定します。[/ja]
15114 */
15115
15116 /**
15117 * @property delegate.createItemContent
15118 * @type {Function}
15119 * @description
15120 * [en]
15121 * This function should return a `HTMLElement`.
15122 *
15123 * To help rendering the element, the current index and a template is supplied as arguments. The template is the initial content of the `<ons-lazy-repeat>` element.
15124 * [/en]
15125 * [ja]
15126 * この関数は`HTMLElement`を返してください。
15127 * 要素を生成しやすくするために、現在のアイテムのインデックスとテンプレートが引数に渡されます。
15128 * このテンプレートは、`<ons-lazy-repeat>`要素のコンテンツが渡されます。
15129 * [/ja]
15130 */
15131
15132 /**
15133 * @property delegate.countItems
15134 * @type {Function}
15135 * @description
15136 * [en]Should return the number of items in the list.[/en]
15137 * [ja]リスト内のアイテム数を返してください。[/ja]
15138 */
15139
15140 /**
15141 * @property delegate.calculateItemHeight
15142 * @type {Function}
15143 * @description
15144 * [en]
15145 * Should return the height of an item. The index is provided as an argument.
15146 *
15147 * This is important when rendering lists where the items have different height.
15148 *
15149 * The function is optional and if it isn't present the height of the first item will be automatically calculated and used for all other items.
15150 * [/en]
15151 * [ja]
15152 * アイテムの高さ(ピクセル)を返してください。アイテムのインデックス値は引数で渡されます。
15153 * この関数は、それぞれのアイムが違った高さを持つリストをレンダリングする際に重要です。
15154 * この関数はオプショナルです。もしこの関数が無い場合には、
15155 * 最初のアイテムの高さが他のすべてのアイテムの高さとして利用されます。
15156 * [/ja]
15157 */
15158
15159 /**
15160 * @property delegate.destroyItem
15161 * @type {Function}
15162 * @description
15163 * [en]
15164 * This function is used called when an item is removed from the DOM. The index and DOM element is provided as arguments.
15165 *
15166 * The function is optional but may be important in order to avoid memory leaks.
15167 * [/en]
15168 * [ja]
15169 * この関数は、あるアイテムがDOMツリーから除かれた時に呼び出されます。
15170 * アイテムのインデックス値とDOM要素が引数として渡されます。
15171 * この関数はオプショナルですが、各アイテムの後処理が必要な場合にはメモリーリークを避けるために重要です。
15172 * [/ja]
15173 */
15174
15175 }, {
15176 key: 'refresh',
15177
15178
15179 /**
15180 * @method refresh
15181 * @signature refresh()
15182 * @description
15183 * [en]Refresh the list. Use this method when the data has changed.[/en]
15184 * [ja]リストを更新します。もしデータが変わった場合にはこのメソッドを使ってください。[/ja]
15185 */
15186 value: function refresh() {
15187 this._lazyRepeatProvider && this._lazyRepeatProvider.refresh();
15188 }
15189 }, {
15190 key: 'attributeChangedCallback',
15191 value: function attributeChangedCallback(name, last, current) {}
15192 }, {
15193 key: 'disconnectedCallback',
15194 value: function disconnectedCallback() {
15195 if (this._lazyRepeatProvider) {
15196 this._lazyRepeatProvider.destroy();
15197 this._lazyRepeatProvider = null;
15198 }
15199 }
15200 }, {
15201 key: 'delegate',
15202 set: function set(userDelegate) {
15203 this._lazyRepeatProvider && this._lazyRepeatProvider.destroy();
15204
15205 if (!this._templateElement && this.children[0]) {
15206 this._templateElement = this.removeChild(this.children[0]);
15207 }
15208
15209 var delegate = new LazyRepeatDelegate(userDelegate, this._templateElement || null);
15210 this._lazyRepeatProvider = new LazyRepeatProvider(this.parentElement, delegate);
15211 },
15212 get: function get() {
15213 throw new Error('This property can only be used to set the delegate object.');
15214 }
15215 }]);
15216 return LazyRepeatElement;
15217}(BaseElement);
15218
15219customElements.define('ons-lazy-repeat', LazyRepeatElement);
15220
15221/*
15222Copyright 2013-2015 ASIAL CORPORATION
15223
15224Licensed under the Apache License, Version 2.0 (the "License");
15225you may not use this file except in compliance with the License.
15226You may obtain a copy of the License at
15227
15228 http://www.apache.org/licenses/LICENSE-2.0
15229
15230Unless required by applicable law or agreed to in writing, software
15231distributed under the License is distributed on an "AS IS" BASIS,
15232WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15233See the License for the specific language governing permissions and
15234limitations under the License.
15235
15236*/
15237
15238var scheme$7 = { '': 'list__header--*' };
15239
15240/**
15241 * @element ons-list-header
15242 * @category list
15243 * @description
15244 * [en]Header element for list items. Must be put inside the `<ons-list>` component.[/en]
15245 * [ja]リスト要素に使用するヘッダー用コンポーネント。ons-listと共に使用します。[/ja]
15246 * @seealso ons-list
15247 * [en]The `<ons-list>` component[/en]
15248 * [ja]ons-listコンポーネント[/ja]
15249 * @seealso ons-list-item
15250 * [en]The `<ons-list-item>` component[/en]
15251 * [ja]ons-list-itemコンポーネント[/ja]
15252 * @guide lists [en]Using lists[/en][ja]リストを使う[/ja]
15253 * @codepen yxcCt
15254 * @tutorial vanilla/Reference/list
15255 * @modifier material
15256 * [en]Display a Material Design list header.[/en]
15257 * [ja][/ja]
15258 * @example
15259 * <ons-list>
15260 * <ons-list-header>Header Text</ons-list-header>
15261 * <ons-list-item>Item</ons-list-item>
15262 * <ons-list-item>Item</ons-list-item>
15263 * </ons-list>
15264 */
15265
15266var ListHeaderElement = function (_BaseElement) {
15267 inherits(ListHeaderElement, _BaseElement);
15268
15269 function ListHeaderElement() {
15270 classCallCheck(this, ListHeaderElement);
15271 return possibleConstructorReturn(this, (ListHeaderElement.__proto__ || Object.getPrototypeOf(ListHeaderElement)).apply(this, arguments));
15272 }
15273
15274 createClass(ListHeaderElement, [{
15275 key: 'init',
15276
15277
15278 /**
15279 * @attribute modifier
15280 * @type {String}
15281 * @description
15282 * [en]The appearance of the list header.[/en]
15283 * [ja]ヘッダーの表現を指定します。[/ja]
15284 */
15285
15286 value: function init() {
15287 this._compile();
15288 }
15289 }, {
15290 key: '_compile',
15291 value: function _compile() {
15292 autoStyle.prepare(this);
15293 this.classList.add('list__header');
15294 ModifierUtil.initModifier(this, scheme$7);
15295 }
15296 }, {
15297 key: 'attributeChangedCallback',
15298 value: function attributeChangedCallback(name, last, current) {
15299 if (name === 'modifier') {
15300 return ModifierUtil.onModifierChanged(last, current, this, scheme$7);
15301 }
15302 }
15303 }], [{
15304 key: 'observedAttributes',
15305 get: function get() {
15306 return ['modifier'];
15307 }
15308 }]);
15309 return ListHeaderElement;
15310}(BaseElement);
15311
15312customElements.define('ons-list-header', ListHeaderElement);
15313
15314/*
15315Copyright 2013-2015 ASIAL CORPORATION
15316
15317Licensed under the Apache License, Version 2.0 (the "License");
15318you may not use this file except in compliance with the License.
15319You may obtain a copy of the License at
15320
15321 http://www.apache.org/licenses/LICENSE-2.0
15322
15323Unless required by applicable law or agreed to in writing, software
15324distributed under the License is distributed on an "AS IS" BASIS,
15325WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15326See the License for the specific language governing permissions and
15327limitations under the License.
15328
15329*/
15330
15331var scheme$8 = {
15332 '.list__item': 'list__item--*',
15333 '.list__item__left': 'list__item--*__left',
15334 '.list__item__center': 'list__item--*__center',
15335 '.list__item__right': 'list__item--*__right',
15336 '.list__item__label': 'list__item--*__label',
15337 '.list__item__title': 'list__item--*__title',
15338 '.list__item__subtitle': 'list__item--*__subtitle',
15339 '.list__item__thumbnail': 'list__item--*__thumbnail',
15340 '.list__item__icon': 'list__item--*__icon'
15341};
15342
15343/**
15344 * @element ons-list-item
15345 * @category list
15346 * @modifier tappable
15347 * [en]Make the list item change appearance when it's tapped. On iOS it is better to use the "tappable" and "tap-background-color" attribute for better behavior when scrolling.[/en]
15348 * [ja]タップやクリックした時に効果が表示されるようになります。[/ja]
15349 * @modifier chevron
15350 * [en]Display a chevron at the right end of the list item and make it change appearance when tapped. The chevron is not displayed in Material Design.[/en]
15351 * [ja][/ja]
15352 * @modifier longdivider
15353 * [en]Displays a long horizontal divider between items.[/en]
15354 * [ja][/ja]
15355 * @modifier nodivider
15356 * [en]Removes the divider between list items.[/en]
15357 * [ja][/ja]
15358 * @modifier material
15359 * [en]Display a Material Design list item.[/en]
15360 * [ja][/ja]
15361 * @description
15362 * [en]
15363 * Component that represents each item in the list. Must be put inside the `<ons-list>` component.
15364 *
15365 * The list item is composed of three parts that are represented with the `left`, `center` and `right` classes. These classes can be used to ensure that the content of the list items is properly aligned.
15366 *
15367 * ```
15368 * <ons-list-item>
15369 * <div class="left">Left</div>
15370 * <div class="center">Center</div>
15371 * <div class="right">Right</div>
15372 * </ons-list-item>
15373 * ```
15374 *
15375 * There is also a number of classes (prefixed with `list__item__*`) that help when putting things like icons and thumbnails into the list items.
15376 * [/en]
15377 * [ja][/ja]
15378 * @seealso ons-list
15379 * [en]ons-list component[/en]
15380 * [ja]ons-listコンポーネント[/ja]
15381 * @seealso ons-list-header
15382 * [en]ons-list-header component[/en]
15383 * [ja]ons-list-headerコンポーネント[/ja]
15384 * @guide lists
15385 * [en]Using lists[/en]
15386 * [ja]リストを使う[/ja]
15387 * @codepen yxcCt
15388 * @tutorial vanilla/Reference/list
15389 * @example
15390 * <ons-list-item>
15391 * <div class="left">
15392 * <ons-icon icon="md-face" class="list__item__icon"></ons-icon>
15393 * </div>
15394 * <div class="center">
15395 * <div class="list__item__title">Title</div>
15396 * <div class="list__item__subtitle">Subtitle</div>
15397 * </div>
15398 * <div class="right">
15399 * <ons-switch></ons-switch>
15400 * </div>
15401 * </ons-list-item>
15402 */
15403
15404var ListItemElement = function (_BaseElement) {
15405 inherits(ListItemElement, _BaseElement);
15406
15407 function ListItemElement() {
15408 classCallCheck(this, ListItemElement);
15409 return possibleConstructorReturn(this, (ListItemElement.__proto__ || Object.getPrototypeOf(ListItemElement)).apply(this, arguments));
15410 }
15411
15412 createClass(ListItemElement, [{
15413 key: 'init',
15414
15415
15416 /**
15417 * @attribute modifier
15418 * @type {String}
15419 * @description
15420 * [en]The appearance of the list item.[/en]
15421 * [ja]各要素の表現を指定します。[/ja]
15422 */
15423
15424 /**
15425 * @attribute lock-on-drag
15426 * @type {String}
15427 * @description
15428 * [en]Prevent vertical scrolling when the user drags horizontally.[/en]
15429 * [ja]この属性があると、ユーザーがこの要素を横方向にドラッグしている時に、縦方向のスクロールが起きないようになります。[/ja]
15430 */
15431
15432 /**
15433 * @attribute tappable
15434 * @type {Boolean}
15435 * @description
15436 * [en]Makes the element react to taps.[/en]
15437 * [ja][/ja]
15438 */
15439
15440 /**
15441 * @attribute tap-background-color
15442 * @type {Color}
15443 * @description
15444 * [en] Changes the background color when tapped. For this to work, the attribute "tappable" needs to be set. The default color is "#d9d9d9". It will display as a ripple effect on Android.[/en]
15445 * [ja][/ja]
15446 */
15447
15448 value: function init() {
15449 var _this2 = this;
15450
15451 contentReady(this, function () {
15452 _this2._compile();
15453 });
15454 }
15455 }, {
15456 key: '_compile',
15457 value: function _compile() {
15458 this.classList.add('list__item');
15459
15460 var left = void 0,
15461 center = void 0,
15462 right = void 0;
15463
15464 for (var i = 0; i < this.children.length; i++) {
15465 var el = this.children[i];
15466
15467 if (el.classList.contains('left')) {
15468 el.classList.add('list__item__left');
15469 left = el;
15470 } else if (el.classList.contains('center')) {
15471 center = el;
15472 } else if (el.classList.contains('right')) {
15473 el.classList.add('list__item__right');
15474 right = el;
15475 }
15476 }
15477
15478 if (!center) {
15479 center = document.createElement('div');
15480
15481 if (!left && !right) {
15482 while (this.childNodes[0]) {
15483 center.appendChild(this.childNodes[0]);
15484 }
15485 } else {
15486 for (var _i = this.childNodes.length - 1; _i >= 0; _i--) {
15487 var _el = this.childNodes[_i];
15488 if (_el !== left && _el !== right) {
15489 center.insertBefore(_el, center.firstChild);
15490 }
15491 }
15492 }
15493
15494 this.insertBefore(center, right || null);
15495 }
15496
15497 center.classList.add('center');
15498 center.classList.add('list__item__center');
15499
15500 this._updateRipple();
15501
15502 ModifierUtil.initModifier(this, scheme$8);
15503
15504 autoStyle.prepare(this);
15505 }
15506 }, {
15507 key: 'attributeChangedCallback',
15508 value: function attributeChangedCallback(name, last, current) {
15509 switch (name) {
15510 case 'modifier':
15511 ModifierUtil.onModifierChanged(last, current, this, scheme$8);
15512 break;
15513 case 'ripple':
15514 this._updateRipple();
15515 }
15516 }
15517 }, {
15518 key: 'connectedCallback',
15519 value: function connectedCallback() {
15520 this.addEventListener('drag', this._onDrag);
15521 this.addEventListener('touchstart', this._onTouch);
15522 this.addEventListener('mousedown', this._onTouch);
15523 this.addEventListener('touchend', this._onRelease);
15524 this.addEventListener('touchmove', this._onRelease);
15525 this.addEventListener('touchcancel', this._onRelease);
15526 this.addEventListener('mouseup', this._onRelease);
15527 this.addEventListener('mouseout', this._onRelease);
15528 this.addEventListener('touchleave', this._onRelease);
15529
15530 this._originalBackgroundColor = this.style.backgroundColor;
15531
15532 this.tapped = false;
15533 }
15534 }, {
15535 key: 'disconnectedCallback',
15536 value: function disconnectedCallback() {
15537 this.removeEventListener('drag', this._onDrag);
15538 this.removeEventListener('touchstart', this._onTouch);
15539 this.removeEventListener('mousedown', this._onTouch);
15540 this.removeEventListener('touchend', this._onRelease);
15541 this.removeEventListener('touchmove', this._onRelease);
15542 this.removeEventListener('touchcancel', this._onRelease);
15543 this.removeEventListener('mouseup', this._onRelease);
15544 this.removeEventListener('mouseout', this._onRelease);
15545 this.removeEventListener('touchleave', this._onRelease);
15546 }
15547 }, {
15548 key: '_updateRipple',
15549 value: function _updateRipple() {
15550 util.updateRipple(this);
15551 }
15552 }, {
15553 key: '_onDrag',
15554 value: function _onDrag(event) {
15555 var gesture = event.gesture;
15556 // Prevent vertical scrolling if the users pans left or right.
15557 if (this._shouldLockOnDrag() && ['left', 'right'].indexOf(gesture.direction) > -1) {
15558 gesture.preventDefault();
15559 }
15560 }
15561 }, {
15562 key: '_onTouch',
15563 value: function _onTouch() {
15564 if (this.tapped) {
15565 return;
15566 }
15567
15568 this.tapped = true;
15569
15570 this.style.transition = this._transition;
15571 this.style.webkitTransition = this._transition;
15572 this.style.MozTransition = this._transition;
15573
15574 if (this._tappable) {
15575 if (this.style.backgroundColor) {
15576 this._originalBackgroundColor = this.style.backgroundColor;
15577 }
15578
15579 this.style.backgroundColor = this._tapBackgroundColor;
15580 this.style.boxShadow = '0px -1px 0px 0px ' + this._tapBackgroundColor;
15581 }
15582 }
15583 }, {
15584 key: '_onRelease',
15585 value: function _onRelease() {
15586 this.tapped = false;
15587
15588 this.style.transition = '';
15589 this.style.webkitTransition = '';
15590 this.style.MozTransition = '';
15591
15592 this.style.backgroundColor = this._originalBackgroundColor || '';
15593 this.style.boxShadow = '';
15594 }
15595 }, {
15596 key: '_shouldLockOnDrag',
15597 value: function _shouldLockOnDrag() {
15598 return this.hasAttribute('lock-on-drag');
15599 }
15600 }, {
15601 key: '_transition',
15602 get: function get() {
15603 return 'background-color 0.0s linear 0.02s, box-shadow 0.0s linear 0.02s';
15604 }
15605 }, {
15606 key: '_tappable',
15607 get: function get() {
15608 return this.hasAttribute('tappable');
15609 }
15610 }, {
15611 key: '_tapBackgroundColor',
15612 get: function get() {
15613 return this.getAttribute('tap-background-color') || '#d9d9d9';
15614 }
15615 }], [{
15616 key: 'observedAttributes',
15617 get: function get() {
15618 return ['modifier', 'ripple'];
15619 }
15620 }]);
15621 return ListItemElement;
15622}(BaseElement);
15623
15624customElements.define('ons-list-item', ListItemElement);
15625
15626/*
15627Copyright 2013-2015 ASIAL CORPORATION
15628
15629Licensed under the Apache License, Version 2.0 (the "License");
15630you may not use this file except in compliance with the License.
15631You may obtain a copy of the License at
15632
15633 http://www.apache.org/licenses/LICENSE-2.0
15634
15635Unless required by applicable law or agreed to in writing, software
15636distributed under the License is distributed on an "AS IS" BASIS,
15637WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15638See the License for the specific language governing permissions and
15639limitations under the License.
15640
15641*/
15642
15643var scheme$9 = { '': 'list--*' };
15644
15645/**
15646 * @element ons-list
15647 * @category list
15648 * @modifier inset
15649 * [en]Inset list that doesn't cover the whole width of the parent.[/en]
15650 * [ja]親要素の画面いっぱいに広がらないリストを表示します。[/ja]
15651 * @modifier noborder
15652 * [en]A list with no borders at the top and bottom.[/en]
15653 * [ja]リストの上下のボーダーが無いリストを表示します。[/ja]
15654 * @description
15655 * [en]Component to define a list, and the container for ons-list-item(s).[/en]
15656 * [ja]リストを表現するためのコンポーネント。ons-list-itemのコンテナとして使用します。[/ja]
15657 * @seealso ons-list-item
15658 * [en]ons-list-item component[/en]
15659 * [ja]ons-list-itemコンポーネント[/ja]
15660 * @seealso ons-list-header
15661 * [en]ons-list-header component[/en]
15662 * [ja]ons-list-headerコンポーネント[/ja]
15663 * @seealso ons-lazy-repeat
15664 * [en]ons-lazy-repeat component[/en]
15665 * [ja]ons-lazy-repeatコンポーネント[/ja]
15666 * @guide lists
15667 * [en]Using lists[/en]
15668 * [ja]リストを使う[/ja]
15669 * @guide infinite-scroll
15670 * [en]Loading more items on infinite scroll[/en]
15671 * [ja]Loading more items on infinite scroll[/ja]
15672 * @codepen yxcCt
15673 * @tutorial vanilla/Reference/list
15674 * @example
15675 * <ons-list>
15676 * <ons-list-header>Header Text</ons-list-header>
15677 * <ons-list-item>Item</ons-list-item>
15678 * <ons-list-item>Item</ons-list-item>
15679 * </ons-list>
15680 */
15681
15682var ListElement = function (_BaseElement) {
15683 inherits(ListElement, _BaseElement);
15684
15685 function ListElement() {
15686 classCallCheck(this, ListElement);
15687 return possibleConstructorReturn(this, (ListElement.__proto__ || Object.getPrototypeOf(ListElement)).apply(this, arguments));
15688 }
15689
15690 createClass(ListElement, [{
15691 key: 'init',
15692
15693
15694 /**
15695 * @attribute modifier
15696 * @type {String}
15697 * @description
15698 * [en]The appearance of the list.[/en]
15699 * [ja]リストの表現を指定します。[/ja]
15700 */
15701
15702 value: function init() {
15703 this._compile();
15704 }
15705 }, {
15706 key: '_compile',
15707 value: function _compile() {
15708 autoStyle.prepare(this);
15709 this.classList.add('list');
15710 ModifierUtil.initModifier(this, scheme$9);
15711 }
15712 }, {
15713 key: 'attributeChangedCallback',
15714 value: function attributeChangedCallback(name, last, current) {
15715 if (name === 'modifier') {
15716 return ModifierUtil.onModifierChanged(last, current, this, scheme$9);
15717 }
15718 }
15719 }], [{
15720 key: 'observedAttributes',
15721 get: function get() {
15722 return ['modifier'];
15723 }
15724 }]);
15725 return ListElement;
15726}(BaseElement);
15727
15728customElements.define('ons-list', ListElement);
15729
15730/*
15731Copyright 2013-2015 ASIAL CORPORATION
15732Licensed under the Apache License, Version 2.0 (the "License");
15733you may not use this file except in compliance with the License.
15734You may obtain a copy of the License at
15735 http://www.apache.org/licenses/LICENSE-2.0
15736Unless required by applicable law or agreed to in writing, software
15737distributed under the License is distributed on an "AS IS" BASIS,
15738WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15739See the License for the specific language governing permissions and
15740limitations under the License.
15741*/
15742
15743var scheme$10 = {
15744 '.text-input': 'text-input--*',
15745 '.text-input__label': 'text-input--*__label',
15746 '.radio-button': 'radio-button--*',
15747 '.radio-button__input': 'radio-button--*__input',
15748 '.radio-button__checkmark': 'radio-button--*__checkmark',
15749 '.checkbox': 'checkbox--*',
15750 '.checkbox__input': 'checkbox--*__input',
15751 '.checkbox__checkmark': 'checkbox--*__checkmark'
15752};
15753
15754var INPUT_ATTRIBUTES = ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'disabled', 'inputmode', 'max', 'maxlength', 'min', 'minlength', 'name', 'pattern', 'placeholder', 'readonly', 'size', 'step', 'type', 'validator', 'value'];
15755
15756/**
15757 * @element ons-input
15758 * @category form
15759 * @modifier material
15760 * [en]Displays a Material Design input.[/en]
15761 * [ja][/ja]
15762 * @modifier underbar
15763 * [en]Displays a horizontal line underneath a text input.[/en]
15764 * [ja][/ja]
15765 * @description
15766 * [en]
15767 * An input element. The `type` attribute can be used to change the input type. All text input types as well as `checkbox` and `radio` are supported.
15768 *
15769 * The component will automatically render as a Material Design input on Android devices.
15770 *
15771 * Most attributes that can be used for a normal `<input>` element can also be used on the `<ons-input>` element.
15772 * [/en]
15773 * [ja][/ja]
15774 * @codepen ojQxLj
15775 * @tutorial vanilla/Reference/input
15776 * @seealso ons-range
15777 * [en]The `<ons-range>` element is used to display a range slider.[/en]
15778 * [ja][/ja]
15779 * @seealso ons-switch
15780 * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en]
15781 * [ja][/ja]
15782 * @guide adding-page-content
15783 * [en]Using form components[/en]
15784 * [ja]フォームを使う[/ja]
15785 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
15786 * @example
15787 * <ons-input placeholder="Username" float></ons-input>
15788 * <ons-input type="checkbox" checked></ons-input>
15789 */
15790
15791var InputElement = function (_BaseElement) {
15792 inherits(InputElement, _BaseElement);
15793
15794 function InputElement() {
15795 classCallCheck(this, InputElement);
15796 return possibleConstructorReturn(this, (InputElement.__proto__ || Object.getPrototypeOf(InputElement)).apply(this, arguments));
15797 }
15798
15799 createClass(InputElement, [{
15800 key: 'init',
15801
15802
15803 /**
15804 * @attribute placeholder
15805 * @type {String}
15806 * @description
15807 * [en]Placeholder text. In Material Design, this placeholder will be a floating label.[/en]
15808 * [ja][/ja]
15809 */
15810
15811 /**
15812 * @attribute float
15813 * @description
15814 * [en]If this attribute is present, the placeholder will be animated in Material Design.[/en]
15815 * [ja]この属性が設定された時、ラベルはアニメーションするようになります。[/ja]
15816 */
15817
15818 /**
15819 * @attribute type
15820 * @type {String}
15821 * @description
15822 * [en]
15823 * Specify the input type. This is the same as the "type" attribute for normal inputs. However, for "range" you should instead use <ons-range> element.
15824 *
15825 * Please take a look at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-type) for an exhaustive list of possible values. Depending on the platform and browser version some of these might not work.
15826 * [/en]
15827 * [ja][/ja]
15828 */
15829
15830 /**
15831 * @attribute input-id
15832 * @type {String}
15833 * @description
15834 * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using <label for="..."> elements.[/en]
15835 * [ja][/ja]
15836 */
15837
15838 /**
15839 * @attribute content-left
15840 * @description
15841 * [en]The HTML content of `<ons-input>` is placed before the actual input as a label. Omit this to display it after the input.[/en]
15842 * [ja][/ja]
15843 */
15844
15845 value: function init() {
15846 var _this2 = this;
15847
15848 contentReady(this, function () {
15849 _this2._compile();
15850 _this2.attributeChangedCallback('checked', null, _this2.getAttribute('checked'));
15851 });
15852
15853 this._boundOnInput = this._onInput.bind(this);
15854 this._boundOnFocusin = this._onFocusin.bind(this);
15855 this._boundDelegateEvent = this._delegateEvent.bind(this);
15856 }
15857 }, {
15858 key: '_compile',
15859 value: function _compile() {
15860 autoStyle.prepare(this);
15861
15862 if (this.children.length !== 0) {
15863 return;
15864 }
15865
15866 var helper = document.createElement('span');
15867 helper.classList.add('_helper');
15868
15869 var container = document.createElement('label');
15870 container.appendChild(document.createElement('input'));
15871 container.appendChild(helper);
15872
15873 var label = document.createElement('span');
15874 label.classList.add('input-label');
15875
15876 util.arrayFrom(this.childNodes).forEach(function (element) {
15877 return label.appendChild(element);
15878 });
15879 this.hasAttribute('content-left') ? container.insertBefore(label, container.firstChild) : container.appendChild(label);
15880
15881 this.appendChild(container);
15882
15883 switch (this.getAttribute('type')) {
15884 case 'checkbox':
15885 this.classList.add('checkbox');
15886 this._input.classList.add('checkbox__input');
15887 this._helper.classList.add('checkbox__checkmark');
15888 this._updateBoundAttributes();
15889 break;
15890
15891 case 'radio':
15892 this.classList.add('radio-button');
15893 this._input.classList.add('radio-button__input');
15894 this._helper.classList.add('radio-button__checkmark');
15895 this._updateBoundAttributes();
15896 break;
15897
15898 default:
15899 this._input.classList.add('text-input');
15900 this._helper.classList.add('text-input__label');
15901 this._input.parentElement.classList.add('text-input__container');
15902
15903 this._updateLabel();
15904 this._updateBoundAttributes();
15905 this._updateLabelClass();
15906 break;
15907 }
15908
15909 if (this.hasAttribute('input-id')) {
15910 this._input.id = this.getAttribute('input-id');
15911 }
15912
15913 ModifierUtil.initModifier(this, scheme$10);
15914 }
15915 }, {
15916 key: 'attributeChangedCallback',
15917 value: function attributeChangedCallback(name, last, current) {
15918 var _this3 = this;
15919
15920 if (name === 'modifier') {
15921 return contentReady(this, function () {
15922 return ModifierUtil.onModifierChanged(last, current, _this3, scheme$10);
15923 });
15924 } else if (name === 'placeholder') {
15925 return contentReady(this, function () {
15926 return _this3._updateLabel();
15927 });
15928 }if (name === 'input-id') {
15929 contentReady(this, function () {
15930 return _this3._input.id = current;
15931 });
15932 }if (name === 'checked') {
15933 this.checked = current !== null;
15934 } else if (INPUT_ATTRIBUTES.indexOf(name) >= 0) {
15935 return contentReady(this, function () {
15936 return _this3._updateBoundAttributes();
15937 });
15938 }
15939 }
15940 }, {
15941 key: 'connectedCallback',
15942 value: function connectedCallback() {
15943 var _this4 = this;
15944
15945 contentReady(this, function () {
15946 if (_this4._input.type !== 'checkbox' && _this4._input.type !== 'radio') {
15947 _this4._input.addEventListener('input', _this4._boundOnInput);
15948 _this4._input.addEventListener('focusin', _this4._boundOnFocusin);
15949 _this4._input.addEventListener('focusout', _this4._boundOnFocusout);
15950 }
15951
15952 _this4._input.addEventListener('focus', _this4._boundDelegateEvent);
15953 _this4._input.addEventListener('blur', _this4._boundDelegateEvent);
15954 });
15955 }
15956 }, {
15957 key: 'disconnectedCallback',
15958 value: function disconnectedCallback() {
15959 var _this5 = this;
15960
15961 contentReady(this, function () {
15962 _this5._input.removeEventListener('input', _this5._boundOnInput);
15963 _this5._input.removeEventListener('focusin', _this5._boundOnFocusin);
15964 _this5._input.removeEventListener('focus', _this5._boundDelegateEvent);
15965 _this5._input.removeEventListener('blur', _this5._boundDelegateEvent);
15966 });
15967 }
15968 }, {
15969 key: '_setLabel',
15970 value: function _setLabel(value) {
15971 if (typeof this._helper.textContent !== 'undefined') {
15972 this._helper.textContent = value;
15973 } else {
15974 this._helper.innerText = value;
15975 }
15976 }
15977 }, {
15978 key: '_updateLabel',
15979 value: function _updateLabel() {
15980 this._setLabel(this.hasAttribute('placeholder') ? this.getAttribute('placeholder') : '');
15981 }
15982 }, {
15983 key: '_updateBoundAttributes',
15984 value: function _updateBoundAttributes() {
15985 var _this6 = this;
15986
15987 INPUT_ATTRIBUTES.forEach(function (attr) {
15988 if (_this6.hasAttribute(attr)) {
15989 _this6._input.setAttribute(attr, _this6.getAttribute(attr));
15990 } else {
15991 _this6._input.removeAttribute(attr);
15992 }
15993 });
15994 }
15995 }, {
15996 key: '_updateLabelClass',
15997 value: function _updateLabelClass() {
15998 if (this.value === '') {
15999 this._helper.classList.remove('text-input--material__label--active');
16000 } else if (['checkbox', 'radio'].indexOf(this.getAttribute('type')) === -1) {
16001 this._helper.classList.add('text-input--material__label--active');
16002 }
16003 }
16004 }, {
16005 key: '_delegateEvent',
16006 value: function _delegateEvent(event) {
16007 var e = new CustomEvent(event.type, {
16008 bubbles: false,
16009 cancelable: true
16010 });
16011
16012 return this.dispatchEvent(e);
16013 }
16014 }, {
16015 key: '_onInput',
16016 value: function _onInput(event) {
16017 this._updateLabelClass();
16018 }
16019 }, {
16020 key: '_onFocusin',
16021 value: function _onFocusin(event) {
16022 this._updateLabelClass();
16023 }
16024 }, {
16025 key: '_input',
16026 get: function get() {
16027 return this.querySelector('input');
16028 }
16029 }, {
16030 key: '_helper',
16031 get: function get() {
16032 return this.querySelector('._helper');
16033 }
16034
16035 /**
16036 * @property value
16037 * @type {String}
16038 * @description
16039 * [en]The current value of the input.[/en]
16040 * [ja][/ja]
16041 */
16042
16043 }, {
16044 key: 'value',
16045 get: function get() {
16046 return this._input === null ? this.getAttribute('value') : this._input.value;
16047 },
16048 set: function set(val) {
16049 var _this7 = this;
16050
16051 contentReady(this, function () {
16052 _this7._input.value = val;
16053 _this7._onInput();
16054 });
16055 }
16056
16057 /**
16058 * @property checked
16059 * @type {Boolean}
16060 * @description
16061 * [en]Whether the input is checked or not. Only works for `radio` and `checkbox` type inputs.[/en]
16062 * [ja][/ja]
16063 */
16064
16065 }, {
16066 key: 'checked',
16067 get: function get() {
16068 return this._input.checked;
16069 },
16070 set: function set(val) {
16071 var _this8 = this;
16072
16073 contentReady(this, function () {
16074 _this8._input.checked = val;
16075 });
16076 }
16077
16078 /**
16079 * @property disabled
16080 * @type {Boolean}
16081 * @description
16082 * [en]Whether the input is disabled or not.[/en]
16083 * [ja]無効化されている場合に`true`。[/ja]
16084 */
16085
16086 }, {
16087 key: 'disabled',
16088 set: function set(value) {
16089 return util.toggleAttribute(this, 'disabled', value);
16090 },
16091 get: function get() {
16092 return this.hasAttribute('disabled');
16093 }
16094 }, {
16095 key: '_isTextInput',
16096 get: function get() {
16097 return this.type !== 'radio' && this.type !== 'checkbox';
16098 }
16099 }, {
16100 key: 'type',
16101 get: function get() {
16102 return this.getAttribute('type');
16103 }
16104 }], [{
16105 key: 'observedAttributes',
16106 get: function get() {
16107 return ['modifier', 'placeholder', 'input-id', 'checked'].concat(INPUT_ATTRIBUTES);
16108 }
16109 }]);
16110 return InputElement;
16111}(BaseElement);
16112
16113customElements.define('ons-input', InputElement);
16114
16115/*
16116Copyright 2013-2015 ASIAL CORPORATION
16117
16118Licensed under the Apache License, Version 2.0 (the "License");
16119you may not use this file except in compliance with the License.
16120You may obtain a copy of the License at
16121
16122 http://www.apache.org/licenses/LICENSE-2.0
16123
16124Unless required by applicable law or agreed to in writing, software
16125distributed under the License is distributed on an "AS IS" BASIS,
16126WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16127See the License for the specific language governing permissions and
16128limitations under the License.
16129
16130*/
16131
16132var ModalAnimator = function () {
16133
16134 /**
16135 * @param {Object} options
16136 * @param {String} options.timing
16137 * @param {Number} options.duration
16138 * @param {Number} options.delay
16139 */
16140 function ModalAnimator() {
16141 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16142 classCallCheck(this, ModalAnimator);
16143
16144 this.delay = 0;
16145 this.duration = 0.2;
16146
16147 this.timing = options.timing || this.timing;
16148 this.duration = options.duration !== undefined ? options.duration : this.duration;
16149 this.delay = options.delay !== undefined ? options.delay : this.delay;
16150 }
16151
16152 /**
16153 * @param {HTMLElement} modal
16154 * @param {Function} callback
16155 */
16156
16157
16158 createClass(ModalAnimator, [{
16159 key: "show",
16160 value: function show(modal, callback) {
16161 callback();
16162 }
16163
16164 /**
16165 * @param {HTMLElement} modal
16166 * @param {Function} callback
16167 */
16168
16169 }, {
16170 key: "hide",
16171 value: function hide(modal, callback) {
16172 callback();
16173 }
16174 }]);
16175 return ModalAnimator;
16176}();
16177
16178/*
16179Copyright 2013-2015 ASIAL CORPORATION
16180
16181Licensed under the Apache License, Version 2.0 (the "License");
16182you may not use this file except in compliance with the License.
16183You may obtain a copy of the License at
16184
16185 http://www.apache.org/licenses/LICENSE-2.0
16186
16187Unless required by applicable law or agreed to in writing, software
16188distributed under the License is distributed on an "AS IS" BASIS,
16189WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16190See the License for the specific language governing permissions and
16191limitations under the License.
16192
16193*/
16194
16195/**
16196 * iOS style animator for dialog.
16197 */
16198
16199var FadeModalAnimator = function (_ModalAnimator) {
16200 inherits(FadeModalAnimator, _ModalAnimator);
16201
16202 function FadeModalAnimator(options) {
16203 classCallCheck(this, FadeModalAnimator);
16204
16205 options.timing = options.timing || 'linear';
16206 options.duration = options.duration || '0.3';
16207 options.delay = options.delay || 0;
16208
16209 return possibleConstructorReturn(this, (FadeModalAnimator.__proto__ || Object.getPrototypeOf(FadeModalAnimator)).call(this, options));
16210 }
16211
16212 /**
16213 * @param {HTMLElement} modal
16214 * @param {Function} callback
16215 */
16216
16217
16218 createClass(FadeModalAnimator, [{
16219 key: 'show',
16220 value: function show(modal, callback) {
16221 callback = callback ? callback : function () {};
16222
16223 animit(modal).queue({
16224 opacity: 0
16225 }).wait(this.delay).queue({
16226 opacity: 1.0
16227 }, {
16228 duration: this.duration,
16229 timing: this.timing
16230 }).queue(function (done) {
16231 callback();
16232 done();
16233 }).play();
16234 }
16235
16236 /**
16237 * @param {HTMLElement} modal
16238 * @param {Function} callback
16239 */
16240
16241 }, {
16242 key: 'hide',
16243 value: function hide(modal, callback) {
16244 callback = callback ? callback : function () {};
16245
16246 animit(modal).queue({
16247 opacity: 1
16248 }).wait(this.delay).queue({
16249 opacity: 0
16250 }, {
16251 duration: this.duration,
16252 timing: this.timing
16253 }).queue(function (done) {
16254 callback();
16255 done();
16256 }).play();
16257 }
16258 }]);
16259 return FadeModalAnimator;
16260}(ModalAnimator);
16261
16262/*
16263Copyright 2013-2015 ASIAL CORPORATION
16264
16265Licensed under the Apache License, Version 2.0 (the "License");
16266you may not use this file except in compliance with the License.
16267You may obtain a copy of the License at
16268
16269 http://www.apache.org/licenses/LICENSE-2.0
16270
16271Unless required by applicable law or agreed to in writing, software
16272distributed under the License is distributed on an "AS IS" BASIS,
16273WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16274See the License for the specific language governing permissions and
16275limitations under the License.
16276
16277*/
16278
16279var scheme$11 = {
16280 '': 'modal--*',
16281 'modal__content': 'modal--*__content'
16282};
16283
16284var _animatorDict$2 = {
16285 'default': ModalAnimator,
16286 'fade': FadeModalAnimator,
16287 'none': ModalAnimator
16288};
16289
16290/**
16291 * @element ons-modal
16292 * @category dialog
16293 * @description
16294 * [en]
16295 * Modal component that masks current screen. Underlying components are not subject to any events while the modal component is shown.
16296 *
16297 * This component can be used to block user input while some operation is running or to show some information to the user.
16298 * [/en]
16299 * [ja]
16300 * 画面全体をマスクするモーダル用コンポーネントです。下側にあるコンポーネントは、
16301 * モーダルが表示されている間はイベント通知が行われません。
16302 * [/ja]
16303 * @guide dialogs
16304 * [en]Dialog components[/en]
16305 * [ja]Dialog components[/ja]
16306 * @seealso ons-dialog
16307 * [en]The `<ons-dialog>` component can be used to create a modal dialog.[/en]
16308 * [ja][/ja]
16309 * @codepen devIg
16310 * @example
16311 * <ons-modal id="modal">
16312 * Modal content
16313 * </ons-modal>
16314 * <script>
16315 * var modal = document.getElementById('modal');
16316 * modal.show();
16317 * </script>
16318 */
16319
16320var ModalElement = function (_BaseElement) {
16321 inherits(ModalElement, _BaseElement);
16322
16323 function ModalElement() {
16324 classCallCheck(this, ModalElement);
16325 return possibleConstructorReturn(this, (ModalElement.__proto__ || Object.getPrototypeOf(ModalElement)).apply(this, arguments));
16326 }
16327
16328 createClass(ModalElement, [{
16329 key: 'init',
16330
16331
16332 /**
16333 * @attribute animation
16334 * @type {String}
16335 * @default default
16336 * @description
16337 * [en]The animation used when showing and hiding the modal. Can be either `"none"` or `"fade"`.[/en]
16338 * [ja]モーダルを表示する際のアニメーション名を指定します。"none"もしくは"fade"を指定できます。[/ja]
16339 */
16340
16341 /**
16342 * @attribute animation-options
16343 * @type {Expression}
16344 * @description
16345 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
16346 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. <code>{duration: 0.2, delay: 1, timing: 'ease-in'}</code>[/ja]
16347 */
16348
16349 value: function init() {
16350 var _this2 = this;
16351
16352 contentReady(this, function () {
16353 _this2._compile();
16354 });
16355
16356 this._doorLock = new DoorLock();
16357
16358 this._animatorFactory = new AnimatorFactory({
16359 animators: _animatorDict$2,
16360 baseClass: ModalAnimator,
16361 baseClassName: 'ModalAnimator',
16362 defaultAnimation: this.getAttribute('animation')
16363 });
16364 }
16365
16366 /**
16367 * @property onDeviceBackButton
16368 * @type {Object}
16369 * @description
16370 * [en]Back-button handler.[/en]
16371 * [ja]バックボタンハンドラ。[/ja]
16372 */
16373
16374 }, {
16375 key: '_compile',
16376 value: function _compile() {
16377 this.style.display = 'none';
16378 this.style.zIndex = 10001;
16379 this.classList.add('modal');
16380
16381 if (!util.findChild(this, '.modal__content')) {
16382 var content = document.createElement('div');
16383 content.classList.add('modal__content');
16384
16385 while (this.childNodes[0]) {
16386 var node = this.childNodes[0];
16387 this.removeChild(node);
16388 content.insertBefore(node, null);
16389 }
16390
16391 this.appendChild(content);
16392 }
16393
16394 ModifierUtil.initModifier(this, scheme$11);
16395 }
16396 }, {
16397 key: 'disconnectedCallback',
16398 value: function disconnectedCallback() {
16399 if (this._backButtonHandler) {
16400 this._backButtonHandler.destroy();
16401 }
16402 }
16403 }, {
16404 key: 'connectedCallback',
16405 value: function connectedCallback() {
16406 this.onDeviceBackButton = function () {
16407 return undefined;
16408 };
16409 }
16410
16411 /**
16412 * @property visible
16413 * @readonly
16414 * @type {Boolean}
16415 * @description
16416 * [en]Whether the element is visible or not.[/en]
16417 * [ja]要素が見える場合に`true`。[/ja]
16418 */
16419
16420 }, {
16421 key: 'show',
16422
16423
16424 /**
16425 * @method show
16426 * @signature show([options])
16427 * @param {Object} [options]
16428 * [en]Parameter object.[/en]
16429 * [ja]オプションを指定するオブジェクト。[/ja]
16430 * @param {String} [options.animation]
16431 * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
16432 * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
16433 * @param {String} [options.animationOptions]
16434 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
16435 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
16436 * @description
16437 * [en]Show modal.[/en]
16438 * [ja]モーダルを表示します。[/ja]
16439 * @return {Promise}
16440 * [en]Resolves to the displayed element[/en]
16441 * [ja][/ja]
16442 */
16443 value: function show() {
16444 var _this3 = this;
16445
16446 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16447
16448 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
16449
16450 var callback = options.callback || function () {};
16451
16452 var tryShow = function tryShow() {
16453 var unlock = _this3._doorLock.lock();
16454 var animator = _this3._animatorFactory.newAnimator(options);
16455
16456 return new Promise(function (resolve) {
16457 contentReady(_this3, function () {
16458 _this3.style.display = 'table';
16459 animator.show(_this3, function () {
16460 unlock();
16461
16462 callback();
16463 resolve(_this3);
16464 });
16465 });
16466 });
16467 };
16468
16469 return new Promise(function (resolve) {
16470 _this3._doorLock.waitUnlock(function () {
16471 return resolve(tryShow());
16472 });
16473 });
16474 }
16475
16476 /**
16477 * @method toggle
16478 * @signature toggle([options])
16479 * @param {Object} [options]
16480 * [en]Parameter object.[/en]
16481 * [ja]オプションを指定するオブジェクト。[/ja]
16482 * @param {String} [options.animation]
16483 * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
16484 * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
16485 * @param {String} [options.animationOptions]
16486 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
16487 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
16488 * @description
16489 * [en]Toggle modal visibility.[/en]
16490 * [ja]モーダルの表示を切り替えます。[/ja]
16491 */
16492
16493 }, {
16494 key: 'toggle',
16495 value: function toggle() {
16496 if (this.visible) {
16497 return this.hide.apply(this, arguments);
16498 } else {
16499 return this.show.apply(this, arguments);
16500 }
16501 }
16502
16503 /**
16504 * @method hide
16505 * @signature hide([options])
16506 * @param {Object} [options]
16507 * [en]Parameter object.[/en]
16508 * [ja]オプションを指定するオブジェクト。[/ja]
16509 * @param {String} [options.animation]
16510 * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en]
16511 * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja]
16512 * @param {String} [options.animationOptions]
16513 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
16514 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
16515 * @description
16516 * [en]Hide modal.[/en]
16517 * [ja]モーダルを非表示にします。[/ja]
16518 * @return {Promise}
16519 * [en]Resolves to the hidden element[/en]
16520 * [ja][/ja]
16521 */
16522
16523 }, {
16524 key: 'hide',
16525 value: function hide() {
16526 var _this4 = this;
16527
16528 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16529
16530 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
16531
16532 var callback = options.callback || function () {};
16533
16534 var tryHide = function tryHide() {
16535 var unlock = _this4._doorLock.lock();
16536 var animator = _this4._animatorFactory.newAnimator(options);
16537
16538 return new Promise(function (resolve) {
16539 contentReady(_this4, function () {
16540 animator.hide(_this4, function () {
16541 _this4.style.display = 'none';
16542 unlock();
16543
16544 callback();
16545 resolve(_this4);
16546 });
16547 });
16548 });
16549 };
16550
16551 return new Promise(function (resolve) {
16552 _this4._doorLock.waitUnlock(function () {
16553 return resolve(tryHide());
16554 });
16555 });
16556 }
16557 }, {
16558 key: 'attributeChangedCallback',
16559 value: function attributeChangedCallback(name, last, current) {
16560 if (name === 'modifier') {
16561 return ModifierUtil.onModifierChanged(last, current, this, scheme$11);
16562 }
16563 }
16564
16565 /**
16566 * @param {String} name
16567 * @param {Function} Animator
16568 */
16569
16570 }, {
16571 key: 'onDeviceBackButton',
16572 get: function get() {
16573 return this._backButtonHandler;
16574 },
16575 set: function set(handler) {
16576 if (this._backButtonHandler) {
16577 this._backButtonHandler.destroy();
16578 }
16579
16580 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, handler);
16581 }
16582 }, {
16583 key: 'visible',
16584 get: function get() {
16585 return this.style.display !== 'none';
16586 }
16587 }], [{
16588 key: 'registerAnimator',
16589 value: function registerAnimator(name, Animator) {
16590 if (!(Animator.prototype instanceof ModalAnimator)) {
16591 throw new Error('"Animator" param must inherit OnsModalElement.ModalAnimator');
16592 }
16593 _animatorDict$2[name] = Animator;
16594 }
16595 }, {
16596 key: 'observedAttributes',
16597 get: function get() {
16598 return ['modifier'];
16599 }
16600 }, {
16601 key: 'ModalAnimator',
16602 get: function get() {
16603 return ModalAnimator;
16604 }
16605 }]);
16606 return ModalElement;
16607}(BaseElement);
16608
16609customElements.define('ons-modal', ModalElement);
16610
16611/*
16612Copyright 2013-2015 ASIAL CORPORATION
16613
16614Licensed under the Apache License, Version 2.0 (the "License");
16615you may not use this file except in compliance with the License.
16616You may obtain a copy of the License at
16617
16618 http://www.apache.org/licenses/LICENSE-2.0
16619
16620Unless required by applicable law or agreed to in writing, software
16621distributed under the License is distributed on an "AS IS" BASIS,
16622WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16623See the License for the specific language governing permissions and
16624limitations under the License.
16625
16626*/
16627
16628var NavigatorTransitionAnimator = function () {
16629
16630 /**
16631 * @param {Object} options
16632 * @param {String} options.timing
16633 * @param {Number} options.duration
16634 * @param {Number} options.delay
16635 */
16636 function NavigatorTransitionAnimator(options) {
16637 classCallCheck(this, NavigatorTransitionAnimator);
16638
16639 options = util.extend({
16640 timing: 'linear',
16641 duration: '0.4',
16642 delay: '0'
16643 }, options || {});
16644
16645 this.timing = options.timing;
16646 this.duration = options.duration;
16647 this.delay = options.delay;
16648 }
16649
16650 createClass(NavigatorTransitionAnimator, [{
16651 key: 'push',
16652 value: function push(enterPage, leavePage, callback) {
16653 callback();
16654 }
16655 }, {
16656 key: 'pop',
16657 value: function pop(enterPage, leavePage, callback) {
16658 callback();
16659 }
16660 }], [{
16661 key: 'extend',
16662 value: function extend() {
16663 var properties = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16664
16665
16666 var extendedAnimator = this;
16667 var newAnimator = function newAnimator() {
16668 extendedAnimator.apply(this, arguments);
16669 util.extend(this, properties);
16670 };
16671
16672 newAnimator.prototype = this.prototype;
16673
16674 return newAnimator;
16675 }
16676 }]);
16677 return NavigatorTransitionAnimator;
16678}();
16679
16680/*
16681Copyright 2013-2015 ASIAL CORPORATION
16682
16683Licensed under the Apache License, Version 2.0 (the "License");
16684you may not use this file except in compliance with the License.
16685You may obtain a copy of the License at
16686
16687 http://www.apache.org/licenses/LICENSE-2.0
16688
16689Unless required by applicable law or agreed to in writing, software
16690distributed under the License is distributed on an "AS IS" BASIS,
16691WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16692See the License for the specific language governing permissions and
16693limitations under the License.
16694
16695*/
16696
16697/**
16698 * Slide animator for navigator transition like iOS's screen slide transition.
16699 */
16700
16701var IOSSlideNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
16702 inherits(IOSSlideNavigatorTransitionAnimator, _NavigatorTransitionA);
16703
16704 function IOSSlideNavigatorTransitionAnimator(options) {
16705 classCallCheck(this, IOSSlideNavigatorTransitionAnimator);
16706
16707 options = util.extend({
16708 duration: 0.4,
16709 timing: 'ease',
16710 delay: 0
16711 }, options || {});
16712
16713 var _this = possibleConstructorReturn(this, (IOSSlideNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorTransitionAnimator)).call(this, options));
16714
16715 _this.backgroundMask = util.createElement('\n <div style="position: absolute; width: 100%; height: 100%;\n background-color: black; opacity: 0; z-index: 2"></div>\n ');
16716 return _this;
16717 }
16718
16719 createClass(IOSSlideNavigatorTransitionAnimator, [{
16720 key: '_decompose',
16721 value: function _decompose(page) {
16722 var toolbar = page._getToolbarElement();
16723 var left = toolbar._getToolbarLeftItemsElement();
16724 var right = toolbar._getToolbarRightItemsElement();
16725
16726 var excludeBackButton = function excludeBackButton(elements) {
16727 var result = [];
16728
16729 for (var i = 0; i < elements.length; i++) {
16730 if (elements[i].nodeName.toLowerCase() !== 'ons-back-button') {
16731 result.push(elements[i]);
16732 }
16733 }
16734
16735 return result;
16736 };
16737
16738 var other = [].concat(left.children.length === 0 ? left : excludeBackButton(left.children)).concat(right.children.length === 0 ? right : excludeBackButton(right.children));
16739
16740 return {
16741 toolbarCenter: toolbar._getToolbarCenterItemsElement(),
16742 backButtonIcon: toolbar._getToolbarBackButtonIconElement(),
16743 backButtonLabel: toolbar._getToolbarBackButtonLabelElement(),
16744 other: other,
16745 content: page._getContentElement(),
16746 background: page._getBackgroundElement(),
16747 toolbar: toolbar,
16748 bottomToolbar: page._getBottomToolbarElement()
16749 };
16750 }
16751 }, {
16752 key: '_shouldAnimateToolbar',
16753 value: function _shouldAnimateToolbar(enterPage, leavePage) {
16754 var bothPageHasToolbar = enterPage._canAnimateToolbar() && leavePage._canAnimateToolbar();
16755
16756 var noMaterialToolbar = !enterPage._getToolbarElement().classList.contains('navigation-bar--material') && !leavePage._getToolbarElement().classList.contains('navigation-bar--material');
16757
16758 return bothPageHasToolbar && noMaterialToolbar;
16759 }
16760 }, {
16761 key: '_calculateDelta',
16762 value: function _calculateDelta(element, decomposition) {
16763 var title = void 0,
16764 label = void 0;
16765
16766 var pageRect = element.getBoundingClientRect();
16767 if (decomposition.backButtonLabel.classList.contains('back-button__label')) {
16768 var labelRect = decomposition.backButtonLabel.getBoundingClientRect();
16769 title = Math.round(pageRect.width / 2 - labelRect.width / 2 - labelRect.left);
16770 } else {
16771 title = Math.round(pageRect.width / 2 * 0.6);
16772 }
16773
16774 if (decomposition.backButtonIcon.classList.contains('back-button__icon')) {
16775 label = decomposition.backButtonIcon.getBoundingClientRect().right - 2;
16776 }
16777
16778 return { title: title, label: label };
16779 }
16780
16781 /**
16782 * @param {Object} enterPage
16783 * @param {Object} leavePage
16784 * @param {Function} callback
16785 */
16786
16787 }, {
16788 key: 'push',
16789 value: function push(enterPage, leavePage, callback) {
16790 var _this2 = this;
16791
16792 this.backgroundMask.remove();
16793 leavePage.parentNode.insertBefore(this.backgroundMask, leavePage.nextSibling);
16794
16795 contentReady(enterPage, function () {
16796 var enterPageDecomposition = _this2._decompose(enterPage);
16797 var leavePageDecomposition = _this2._decompose(leavePage);
16798
16799 var delta = _this2._calculateDelta(leavePage, enterPageDecomposition);
16800
16801 var maskClear = animit(_this2.backgroundMask).saveStyle().queue({
16802 opacity: 0,
16803 transform: 'translate3d(0, 0, 0)'
16804 }).wait(_this2.delay).queue({
16805 opacity: 0.05
16806 }, {
16807 duration: _this2.duration,
16808 timing: _this2.timing
16809 }).restoreStyle().queue(function (done) {
16810 _this2.backgroundMask.remove();
16811 done();
16812 });
16813
16814 var shouldAnimateToolbar = _this2._shouldAnimateToolbar(enterPage, leavePage);
16815
16816 if (shouldAnimateToolbar) {
16817 // TODO: Remove this fix
16818 var enterPageToolbarHeight = enterPageDecomposition.toolbar.getBoundingClientRect().height + 'px';
16819 _this2.backgroundMask.style.top = enterPageToolbarHeight;
16820
16821 animit.runAll(maskClear, animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background]).saveStyle().queue({
16822 css: {
16823 transform: 'translate3D(100%, 0px, 0px)'
16824 },
16825 duration: 0
16826 }).wait(_this2.delay).queue({
16827 css: {
16828 transform: 'translate3D(0px, 0px, 0px)'
16829 },
16830 duration: _this2.duration,
16831 timing: _this2.timing
16832 }).restoreStyle(), animit(enterPageDecomposition.toolbar).saveStyle().queue({
16833 css: {
16834 opacity: 0
16835 },
16836 duration: 0
16837 }).queue({
16838 css: {
16839 opacity: 1
16840 },
16841 duration: _this2.duration,
16842 timing: _this2.timing
16843 }).restoreStyle(), animit(enterPageDecomposition.background).queue({
16844 css: {
16845 top: enterPageToolbarHeight
16846 },
16847 duration: 0
16848 }), animit(enterPageDecomposition.toolbarCenter).saveStyle().queue({
16849 css: {
16850 transform: 'translate3d(125%, 0, 0)',
16851 opacity: 1
16852 },
16853 duration: 0
16854 }).wait(_this2.delay).queue({
16855 css: {
16856 transform: 'translate3d(0, 0, 0)',
16857 opacity: 1.0
16858 },
16859 duration: _this2.duration,
16860 timing: _this2.timing
16861 }).restoreStyle(), animit(enterPageDecomposition.backButtonLabel).saveStyle().queue({
16862 css: {
16863 transform: 'translate3d(' + delta.title + 'px, 0, 0)',
16864 opacity: 0
16865 },
16866 duration: 0
16867 }).wait(_this2.delay).queue({
16868 css: {
16869 transform: 'translate3d(0, 0, 0)',
16870 opacity: 1.0
16871 },
16872 duration: _this2.duration,
16873 timing: _this2.timing
16874 }).restoreStyle(), animit(enterPageDecomposition.other).saveStyle().queue({
16875 css: { opacity: 0 },
16876 duration: 0
16877 }).wait(_this2.delay).queue({
16878 css: { opacity: 1 },
16879 duration: _this2.duration,
16880 timing: _this2.timing
16881 }).restoreStyle(), animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background]).saveStyle().queue({
16882 css: {
16883 transform: 'translate3D(0, 0, 0)'
16884 },
16885 duration: 0
16886 }).wait(_this2.delay).queue({
16887 css: {
16888 transform: 'translate3D(-25%, 0px, 0px)'
16889 },
16890 duration: _this2.duration,
16891 timing: _this2.timing
16892 }).restoreStyle().queue(function (done) {
16893 callback();
16894 done();
16895 }), animit(leavePageDecomposition.toolbarCenter).saveStyle().queue({
16896 css: {
16897 transform: 'translate3d(0, 0, 0)',
16898 opacity: 1.0
16899 },
16900 duration: 0
16901 }).wait(_this2.delay).queue({
16902 css: {
16903 transform: 'translate3d(-' + delta.title + 'px, 0, 0)',
16904 opacity: 0
16905 },
16906 duration: _this2.duration,
16907 timing: _this2.timing
16908 }).restoreStyle(), animit(leavePageDecomposition.backButtonLabel).saveStyle().queue({
16909 css: {
16910 transform: 'translate3d(0, 0, 0)',
16911 opacity: 1.0
16912 },
16913 duration: 0
16914 }).wait(_this2.delay).queue({
16915 css: {
16916 transform: 'translate3d(-' + delta.label + 'px, 0, 0)',
16917 opacity: 0
16918 },
16919 duration: _this2.duration,
16920 timing: _this2.timing
16921 }).restoreStyle(), animit(leavePageDecomposition.other).saveStyle().queue({
16922 css: { opacity: 1 },
16923 duration: 0
16924 }).wait(_this2.delay).queue({
16925 css: { opacity: 0 },
16926 duration: _this2.duration,
16927 timing: _this2.timing
16928 }).restoreStyle());
16929 } else {
16930
16931 animit.runAll(maskClear, animit(enterPage).saveStyle().queue({
16932 css: {
16933 transform: 'translate3D(100%, 0px, 0px)'
16934 },
16935 duration: 0
16936 }).wait(_this2.delay).queue({
16937 css: {
16938 transform: 'translate3D(0px, 0px, 0px)'
16939 },
16940 duration: _this2.duration,
16941 timing: _this2.timing
16942 }).restoreStyle(), animit(leavePage).saveStyle().queue({
16943 css: {
16944 transform: 'translate3D(0, 0, 0)'
16945 },
16946 duration: 0
16947 }).wait(_this2.delay).queue({
16948 css: {
16949 transform: 'translate3D(-25%, 0px, 0px)'
16950 },
16951 duration: _this2.duration,
16952 timing: _this2.timing
16953 }).restoreStyle().queue(function (done) {
16954 callback();
16955 done();
16956 }));
16957 }
16958 });
16959 }
16960
16961 /**
16962 * @param {Object} enterPage
16963 * @param {Object} leavePage
16964 * @param {Function} done
16965 */
16966
16967 }, {
16968 key: 'pop',
16969 value: function pop(enterPage, leavePage, done) {
16970 this.backgroundMask.remove();
16971 enterPage.parentNode.insertBefore(this.backgroundMask, enterPage.nextSibling);
16972
16973 var enterPageDecomposition = this._decompose(enterPage);
16974 var leavePageDecomposition = this._decompose(leavePage);
16975
16976 var delta = this._calculateDelta(leavePage, leavePageDecomposition);
16977
16978 var maskClear = animit(this.backgroundMask).saveStyle().queue({
16979 opacity: 0.1,
16980 transform: 'translate3d(0, 0, 0)'
16981 }).wait(this.delay).queue({
16982 opacity: 0
16983 }, {
16984 duration: this.duration,
16985 timing: this.timing
16986 }).restoreStyle().queue(function (done) {
16987 done();
16988 });
16989
16990 var shouldAnimateToolbar = this._shouldAnimateToolbar(enterPage, leavePage);
16991
16992 if (shouldAnimateToolbar) {
16993 var enterPageToolbarHeight = enterPageDecomposition.toolbar.getBoundingClientRect().height + 'px';
16994 this.backgroundMask.style.top = enterPageToolbarHeight;
16995
16996 animit.runAll(maskClear, animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background]).saveStyle().queue({
16997 css: {
16998 transform: 'translate3D(-25%, 0px, 0px)',
16999 opacity: 0.9
17000 },
17001 duration: 0
17002 }).wait(this.delay).queue({
17003 css: {
17004 transform: 'translate3D(0px, 0px, 0px)',
17005 opacity: 1.0
17006 },
17007 duration: this.duration,
17008 timing: this.timing
17009 }).restoreStyle(), animit(enterPageDecomposition.toolbarCenter).saveStyle().queue({
17010 css: {
17011 transform: 'translate3d(-' + delta.title + 'px, 0, 0)',
17012 opacity: 0
17013 },
17014 duration: 0
17015 }).wait(this.delay).queue({
17016 css: {
17017 transform: 'translate3d(0, 0, 0)',
17018 opacity: 1.0
17019 },
17020 duration: this.duration,
17021 timing: this.timing
17022 }).restoreStyle(), animit(enterPageDecomposition.backButtonLabel).saveStyle().queue({
17023 css: {
17024 transform: 'translate3d(-' + delta.label + 'px, 0, 0)'
17025 },
17026 duration: 0
17027 }).wait(this.delay).queue({
17028 css: {
17029 transform: 'translate3d(0, 0, 0)'
17030 },
17031 duration: this.duration,
17032 timing: this.timing
17033 }).restoreStyle(), animit(enterPageDecomposition.other).saveStyle().queue({
17034 css: { opacity: 0 },
17035 duration: 0
17036 }).wait(this.delay).queue({
17037 css: { opacity: 1 },
17038 duration: this.duration,
17039 timing: this.timing
17040 }).restoreStyle(), animit(leavePageDecomposition.background).queue({
17041 css: {
17042 top: enterPageToolbarHeight
17043 },
17044 duration: 0
17045 }), animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background]).queue({
17046 css: {
17047 transform: 'translate3D(0px, 0px, 0px)'
17048 },
17049 duration: 0
17050 }).wait(this.delay).queue({
17051 css: {
17052 transform: 'translate3D(100%, 0px, 0px)'
17053 },
17054 duration: this.duration,
17055 timing: this.timing
17056 }).wait(0).queue(function (finish) {
17057 this.backgroundMask.remove();
17058 done();
17059 finish();
17060 }.bind(this)), animit(leavePageDecomposition.toolbar).queue({
17061 css: {
17062 opacity: 1
17063 },
17064 duration: 0
17065 }).queue({
17066 css: {
17067 opacity: 0
17068 },
17069 duration: this.duration,
17070 timing: this.timing
17071 }), animit(leavePageDecomposition.toolbarCenter).queue({
17072 css: {
17073 transform: 'translate3d(0, 0, 0)'
17074 },
17075 duration: 0
17076 }).wait(this.delay).queue({
17077 css: {
17078 transform: 'translate3d(125%, 0, 0)'
17079 },
17080 duration: this.duration,
17081 timing: this.timing
17082 }), animit(leavePageDecomposition.backButtonLabel).queue({
17083 css: {
17084 transform: 'translate3d(0, 0, 0)',
17085 opacity: 1
17086 },
17087 duration: 0
17088 }).wait(this.delay).queue({
17089 css: {
17090 transform: 'translate3d(' + delta.title + 'px, 0, 0)',
17091 opacity: 0
17092 },
17093 duration: this.duration,
17094 timing: this.timing
17095 }));
17096 } else {
17097 animit.runAll(maskClear, animit(enterPage).saveStyle().queue({
17098 css: {
17099 transform: 'translate3D(-25%, 0px, 0px)',
17100 opacity: 0.9
17101 },
17102 duration: 0
17103 }).wait(this.delay).queue({
17104 css: {
17105 transform: 'translate3D(0px, 0px, 0px)',
17106 opacity: 1.0
17107 },
17108 duration: this.duration,
17109 timing: this.timing
17110 }).restoreStyle(), animit(leavePage).queue({
17111 css: {
17112 transform: 'translate3D(0px, 0px, 0px)'
17113 },
17114 duration: 0
17115 }).wait(this.delay).queue({
17116 css: {
17117 transform: 'translate3D(100%, 0px, 0px)'
17118 },
17119 duration: this.duration,
17120 timing: this.timing
17121 }).queue(function (finish) {
17122 this.backgroundMask.remove();
17123 done();
17124 finish();
17125 }.bind(this)));
17126 }
17127 }
17128 }]);
17129 return IOSSlideNavigatorTransitionAnimator;
17130}(NavigatorTransitionAnimator);
17131
17132/*
17133Copyright 2013-2015 ASIAL CORPORATION
17134
17135Licensed under the Apache License, Version 2.0 (the "License");
17136you may not use this file except in compliance with the License.
17137You may obtain a copy of the License at
17138
17139 http://www.apache.org/licenses/LICENSE-2.0
17140
17141Unless required by applicable law or agreed to in writing, software
17142distributed under the License is distributed on an "AS IS" BASIS,
17143WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17144See the License for the specific language governing permissions and
17145limitations under the License.
17146
17147*/
17148
17149/**
17150 * Lift screen transition.
17151 */
17152
17153var IOSLiftNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17154 inherits(IOSLiftNavigatorTransitionAnimator, _NavigatorTransitionA);
17155
17156 function IOSLiftNavigatorTransitionAnimator(options) {
17157 classCallCheck(this, IOSLiftNavigatorTransitionAnimator);
17158
17159 options = util.extend({
17160 duration: 0.4,
17161 timing: 'cubic-bezier(.1, .7, .1, 1)',
17162 delay: 0
17163 }, options || {});
17164
17165 var _this = possibleConstructorReturn(this, (IOSLiftNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorTransitionAnimator)).call(this, options));
17166
17167 _this.backgroundMask = util.createElement('\n <div style="position: absolute; width: 100%; height: 100%;\n background: linear-gradient(black, white);"></div>\n ');
17168 return _this;
17169 }
17170
17171 /**
17172 * @param {Object} enterPage
17173 * @param {Object} leavePage
17174 * @param {Function} callback
17175 */
17176
17177
17178 createClass(IOSLiftNavigatorTransitionAnimator, [{
17179 key: 'push',
17180 value: function push(enterPage, leavePage, callback) {
17181 var _this2 = this;
17182
17183 this.backgroundMask.remove();
17184 leavePage.parentNode.insertBefore(this.backgroundMask, leavePage);
17185
17186 var maskClear = animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
17187 _this2.backgroundMask.remove();
17188 done();
17189 });
17190
17191 animit.runAll(maskClear, animit(enterPage).saveStyle().queue({
17192 css: {
17193 transform: 'translate3D(0, 100%, 0)'
17194 },
17195 duration: 0
17196 }).wait(this.delay).queue({
17197 css: {
17198 transform: 'translate3D(0, 0, 0)'
17199 },
17200 duration: this.duration,
17201 timing: this.timing
17202 }).restoreStyle().queue(function (done) {
17203 callback();
17204 done();
17205 }), animit(leavePage).queue({
17206 css: {
17207 transform: 'translate3D(0, 0, 0)',
17208 opacity: 1.0
17209 },
17210 duration: 0
17211 }).wait(this.delay).queue({
17212 css: {
17213 transform: 'translate3D(0, -10%, 0)',
17214 opacity: 0.9
17215 },
17216 duration: this.duration,
17217 timing: this.timing
17218 }));
17219 }
17220
17221 /**
17222 * @param {Object} enterPage
17223 * @param {Object} leavePage
17224 * @param {Function} callback
17225 */
17226
17227 }, {
17228 key: 'pop',
17229 value: function pop(enterPage, leavePage, callback) {
17230 var _this3 = this;
17231
17232 this.backgroundMask.remove();
17233 enterPage.parentNode.insertBefore(this.backgroundMask, enterPage);
17234
17235 animit.runAll(animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
17236 _this3.backgroundMask.remove();
17237 done();
17238 }), animit(enterPage).queue({
17239 css: {
17240 transform: 'translate3D(0, -10%, 0)',
17241 opacity: 0.9
17242 },
17243 duration: 0
17244 }).wait(this.delay).queue({
17245 css: {
17246 transform: 'translate3D(0, 0, 0)',
17247 opacity: 1.0
17248 },
17249 duration: this.duration,
17250 timing: this.timing
17251 }).queue(function (done) {
17252 callback();
17253 done();
17254 }), animit(leavePage).queue({
17255 css: {
17256 transform: 'translate3D(0, 0, 0)'
17257 },
17258 duration: 0
17259 }).wait(this.delay).queue({
17260 css: {
17261 transform: 'translate3D(0, 100%, 0)'
17262 },
17263 duration: this.duration,
17264 timing: this.timing
17265 }));
17266 }
17267 }]);
17268 return IOSLiftNavigatorTransitionAnimator;
17269}(NavigatorTransitionAnimator);
17270
17271/*
17272Copyright 2013-2015 ASIAL CORPORATION
17273
17274Licensed under the Apache License, Version 2.0 (the "License");
17275you may not use this file except in compliance with the License.
17276You may obtain a copy of the License at
17277
17278 http://www.apache.org/licenses/LICENSE-2.0
17279
17280Unless required by applicable law or agreed to in writing, software
17281distributed under the License is distributed on an "AS IS" BASIS,
17282WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17283See the License for the specific language governing permissions and
17284limitations under the License.
17285
17286*/
17287
17288/**
17289 * Fade-in screen transition.
17290 */
17291
17292var IOSFadeNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17293 inherits(IOSFadeNavigatorTransitionAnimator, _NavigatorTransitionA);
17294
17295 function IOSFadeNavigatorTransitionAnimator(options) {
17296 classCallCheck(this, IOSFadeNavigatorTransitionAnimator);
17297
17298 options = util.extend({
17299 timing: 'linear',
17300 duration: '0.4',
17301 delay: '0'
17302 }, options || {});
17303
17304 return possibleConstructorReturn(this, (IOSFadeNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorTransitionAnimator)).call(this, options));
17305 }
17306
17307 /**
17308 * @param {Object} enterPage
17309 * @param {Object} leavePage
17310 * @param {Function} callback
17311 */
17312
17313
17314 createClass(IOSFadeNavigatorTransitionAnimator, [{
17315 key: 'push',
17316 value: function push(enterPage, leavePage, callback) {
17317
17318 animit.runAll(animit([enterPage._getContentElement(), enterPage._getBackgroundElement()]).saveStyle().queue({
17319 css: {
17320 transform: 'translate3D(0, 0, 0)',
17321 opacity: 0
17322 },
17323 duration: 0
17324 }).wait(this.delay).queue({
17325 css: {
17326 transform: 'translate3D(0, 0, 0)',
17327 opacity: 1
17328 },
17329 duration: this.duration,
17330 timing: this.timing
17331 }).restoreStyle().queue(function (done) {
17332 callback();
17333 done();
17334 }), animit(enterPage._getToolbarElement()).saveStyle().queue({
17335 css: {
17336 transform: 'translate3D(0, 0, 0)',
17337 opacity: 0
17338 },
17339 duration: 0
17340 }).wait(this.delay).queue({
17341 css: {
17342 transform: 'translate3D(0, 0, 0)',
17343 opacity: 1
17344 },
17345 duration: this.duration,
17346 timing: this.timing
17347 }).restoreStyle());
17348 }
17349
17350 /**
17351 * @param {Object} enterPage
17352 * @param {Object} leavePage
17353 * @param {Function} done
17354 */
17355
17356 }, {
17357 key: 'pop',
17358 value: function pop(enterPage, leavePage, callback) {
17359 animit.runAll(animit([leavePage._getContentElement(), leavePage._getBackgroundElement()]).queue({
17360 css: {
17361 transform: 'translate3D(0, 0, 0)',
17362 opacity: 1
17363 },
17364 duration: 0
17365 }).wait(this.delay).queue({
17366 css: {
17367 transform: 'translate3D(0, 0, 0)',
17368 opacity: 0
17369 },
17370 duration: this.duration,
17371 timing: this.timing
17372 }).queue(function (done) {
17373 callback();
17374 done();
17375 }), animit(leavePage._getToolbarElement()).queue({
17376 css: {
17377 transform: 'translate3D(0, 0, 0)',
17378 opacity: 1
17379 },
17380 duration: 0
17381 }).wait(this.delay).queue({
17382 css: {
17383 transform: 'translate3D(0, 0, 0)',
17384 opacity: 0
17385 },
17386 duration: this.duration,
17387 timing: this.timing
17388 }));
17389 }
17390 }]);
17391 return IOSFadeNavigatorTransitionAnimator;
17392}(NavigatorTransitionAnimator);
17393
17394/*
17395Copyright 2013-2015 ASIAL CORPORATION
17396
17397Licensed under the Apache License, Version 2.0 (the "License");
17398you may not use this file except in compliance with the License.
17399You may obtain a copy of the License at
17400
17401 http://www.apache.org/licenses/LICENSE-2.0
17402
17403Unless required by applicable law or agreed to in writing, software
17404distributed under the License is distributed on an "AS IS" BASIS,
17405WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17406See the License for the specific language governing permissions and
17407limitations under the License.
17408
17409*/
17410
17411/**
17412 * Slide animator for navigator transition.
17413 */
17414
17415var MDSlideNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17416 inherits(MDSlideNavigatorTransitionAnimator, _NavigatorTransitionA);
17417
17418 function MDSlideNavigatorTransitionAnimator(options) {
17419 classCallCheck(this, MDSlideNavigatorTransitionAnimator);
17420
17421 options = util.extend({
17422 duration: 0.3,
17423 timing: 'cubic-bezier(.1, .7, .4, 1)',
17424 delay: 0
17425 }, options || {});
17426
17427 var _this = possibleConstructorReturn(this, (MDSlideNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(MDSlideNavigatorTransitionAnimator)).call(this, options));
17428
17429 _this.backgroundMask = util.createElement('\n <div style="position: absolute; width: 100%; height: 100%; z-index: 2;\n background-color: black; opacity: 0;"></div>\n ');
17430 _this.blackMaskOpacity = 0.4;
17431 return _this;
17432 }
17433
17434 /**
17435 * @param {Object} enterPage
17436 * @param {Object} leavePage
17437 * @param {Function} callback
17438 */
17439
17440
17441 createClass(MDSlideNavigatorTransitionAnimator, [{
17442 key: 'push',
17443 value: function push(enterPage, leavePage, callback) {
17444 var _this2 = this;
17445
17446 this.backgroundMask.remove();
17447 leavePage.parentElement.insertBefore(this.backgroundMask, leavePage.nextSibling);
17448
17449 animit.runAll(animit(this.backgroundMask).saveStyle().queue({
17450 opacity: 0,
17451 transform: 'translate3d(0, 0, 0)'
17452 }).wait(this.delay).queue({
17453 opacity: this.blackMaskOpacity
17454 }, {
17455 duration: this.duration,
17456 timing: this.timing
17457 }).restoreStyle().queue(function (done) {
17458 _this2.backgroundMask.remove();
17459 done();
17460 }), animit(enterPage).saveStyle().queue({
17461 css: {
17462 transform: 'translate3D(100%, 0, 0)'
17463 },
17464 duration: 0
17465 }).wait(this.delay).queue({
17466 css: {
17467 transform: 'translate3D(0, 0, 0)'
17468 },
17469 duration: this.duration,
17470 timing: this.timing
17471 }).restoreStyle(), animit(leavePage).saveStyle().queue({
17472 css: {
17473 transform: 'translate3D(0, 0, 0)'
17474 },
17475 duration: 0
17476 }).wait(this.delay).queue({
17477 css: {
17478 transform: 'translate3D(-45%, 0px, 0px)'
17479 },
17480 duration: this.duration,
17481 timing: this.timing
17482 }).restoreStyle().wait(0.2).queue(function (done) {
17483 callback();
17484 done();
17485 }));
17486 }
17487
17488 /**
17489 * @param {Object} enterPage
17490 * @param {Object} leavePage
17491 * @param {Function} done
17492 */
17493
17494 }, {
17495 key: 'pop',
17496 value: function pop(enterPage, leavePage, done) {
17497 var _this3 = this;
17498
17499 this.backgroundMask.remove();
17500 enterPage.parentNode.insertBefore(this.backgroundMask, enterPage.nextSibling);
17501
17502 animit.runAll(animit(this.backgroundMask).saveStyle().queue({
17503 opacity: this.blackMaskOpacity,
17504 transform: 'translate3d(0, 0, 0)'
17505 }).wait(this.delay).queue({
17506 opacity: 0
17507 }, {
17508 duration: this.duration,
17509 timing: this.timing
17510 }).restoreStyle().queue(function (done) {
17511 _this3.backgroundMask.remove();
17512 done();
17513 }), animit(enterPage).saveStyle().queue({
17514 css: {
17515 transform: 'translate3D(-45%, 0px, 0px)',
17516 opacity: 0.9
17517 },
17518 duration: 0
17519 }).wait(this.delay).queue({
17520 css: {
17521 transform: 'translate3D(0px, 0px, 0px)',
17522 opacity: 1.0
17523 },
17524 duration: this.duration,
17525 timing: this.timing
17526 }).restoreStyle(), animit(leavePage).queue({
17527 css: {
17528 transform: 'translate3D(0px, 0px, 0px)'
17529 },
17530 duration: 0
17531 }).wait(this.delay).queue({
17532 css: {
17533 transform: 'translate3D(100%, 0px, 0px)'
17534 },
17535 duration: this.duration,
17536 timing: this.timing
17537 }).wait(0.2).queue(function (finish) {
17538 done();
17539 finish();
17540 }));
17541 }
17542 }]);
17543 return MDSlideNavigatorTransitionAnimator;
17544}(NavigatorTransitionAnimator);
17545
17546/*
17547Copyright 2013-2015 ASIAL CORPORATION
17548
17549Licensed under the Apache License, Version 2.0 (the "License");
17550you may not use this file except in compliance with the License.
17551You may obtain a copy of the License at
17552
17553 http://www.apache.org/licenses/LICENSE-2.0
17554
17555Unless required by applicable law or agreed to in writing, software
17556distributed under the License is distributed on an "AS IS" BASIS,
17557WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17558See the License for the specific language governing permissions and
17559limitations under the License.
17560
17561*/
17562
17563/**
17564 * Lift screen transition.
17565 */
17566
17567var MDLiftNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17568 inherits(MDLiftNavigatorTransitionAnimator, _NavigatorTransitionA);
17569
17570 function MDLiftNavigatorTransitionAnimator(options) {
17571 classCallCheck(this, MDLiftNavigatorTransitionAnimator);
17572
17573 options = util.extend({
17574 duration: 0.4,
17575 timing: 'cubic-bezier(.1, .7, .1, 1)',
17576 delay: 0.05
17577 }, options || {});
17578
17579 var _this = possibleConstructorReturn(this, (MDLiftNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(MDLiftNavigatorTransitionAnimator)).call(this, options));
17580
17581 _this.backgroundMask = util.createElement('\n <div style="position: absolute; width: 100%; height: 100%;\n background-color: black;"></div>\n ');
17582 return _this;
17583 }
17584
17585 /**
17586 * @param {Object} enterPage
17587 * @param {Object} leavePage
17588 * @param {Function} callback
17589 */
17590
17591
17592 createClass(MDLiftNavigatorTransitionAnimator, [{
17593 key: 'push',
17594 value: function push(enterPage, leavePage, callback) {
17595 var _this2 = this;
17596
17597 this.backgroundMask.remove();
17598 leavePage.parentNode.insertBefore(this.backgroundMask, leavePage);
17599
17600 var maskClear = animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
17601 _this2.backgroundMask.remove();
17602 done();
17603 });
17604
17605 animit.runAll(maskClear, animit(enterPage).saveStyle().queue({
17606 css: {
17607 transform: 'translate3D(0, 100%, 0)'
17608 },
17609 duration: 0
17610 }).wait(this.delay).queue({
17611 css: {
17612 transform: 'translate3D(0, 0, 0)'
17613 },
17614 duration: this.duration,
17615 timing: this.timing
17616 }).restoreStyle().queue(function (done) {
17617 callback();
17618 done();
17619 }), animit(leavePage).queue({
17620 css: {
17621 opacity: 1.0
17622 },
17623 duration: 0
17624 }).queue({
17625 css: {
17626 opacity: 0.4
17627 },
17628 duration: this.duration,
17629 timing: this.timing
17630 }));
17631 }
17632
17633 /**
17634 * @param {Object} enterPage
17635 * @param {Object} leavePage
17636 * @param {Function} callback
17637 */
17638
17639 }, {
17640 key: 'pop',
17641 value: function pop(enterPage, leavePage, callback) {
17642 var _this3 = this;
17643
17644 this.backgroundMask.remove();
17645 enterPage.parentNode.insertBefore(this.backgroundMask, enterPage);
17646
17647 animit.runAll(animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) {
17648 _this3.backgroundMask.remove();
17649 done();
17650 }), animit(enterPage).queue({
17651 css: {
17652 transform: 'translate3D(0, 0, 0)',
17653 opacity: 0.4
17654 },
17655 duration: 0
17656 }).wait(this.delay).queue({
17657 css: {
17658 transform: 'translate3D(0, 0, 0)',
17659 opacity: 1.0
17660 },
17661 duration: this.duration,
17662 timing: this.timing
17663 }).queue(function (done) {
17664 callback();
17665 done();
17666 }), animit(leavePage).queue({
17667 css: {
17668 transform: 'translate3D(0, 0, 0)'
17669 },
17670 duration: 0
17671 }).wait(this.delay).queue({
17672 css: {
17673 transform: 'translate3D(0, 100%, 0)'
17674 },
17675 duration: this.duration,
17676 timing: this.timing
17677 }));
17678 }
17679 }]);
17680 return MDLiftNavigatorTransitionAnimator;
17681}(NavigatorTransitionAnimator);
17682
17683/*
17684Copyright 2013-2015 ASIAL CORPORATION
17685
17686Licensed under the Apache License, Version 2.0 (the "License");
17687you may not use this file except in compliance with the License.
17688You may obtain a copy of the License at
17689
17690 http://www.apache.org/licenses/LICENSE-2.0
17691
17692Unless required by applicable law or agreed to in writing, software
17693distributed under the License is distributed on an "AS IS" BASIS,
17694WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17695See the License for the specific language governing permissions and
17696limitations under the License.
17697
17698*/
17699
17700/**
17701 * Fade-in + Lift screen transition.
17702 */
17703
17704var MDFadeNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17705 inherits(MDFadeNavigatorTransitionAnimator, _NavigatorTransitionA);
17706
17707 function MDFadeNavigatorTransitionAnimator(options) {
17708 classCallCheck(this, MDFadeNavigatorTransitionAnimator);
17709
17710 options = util.extend({
17711 timing: 'ease-out',
17712 duration: '0.25',
17713 delay: '0'
17714 }, options || {});
17715
17716 return possibleConstructorReturn(this, (MDFadeNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(MDFadeNavigatorTransitionAnimator)).call(this, options));
17717 }
17718
17719 /**
17720 * @param {Object} enterPage
17721 * @param {Object} leavePage
17722 * @param {Function} callback
17723 */
17724
17725
17726 createClass(MDFadeNavigatorTransitionAnimator, [{
17727 key: 'push',
17728 value: function push(enterPage, leavePage, callback) {
17729
17730 animit.runAll(animit(enterPage).saveStyle().queue({
17731 css: {
17732 transform: 'translate3D(0, 42px, 0)',
17733 opacity: 0
17734 },
17735 duration: 0
17736 }).wait(this.delay).queue({
17737 css: {
17738 transform: 'translate3D(0, 0, 0)',
17739 opacity: 1
17740 },
17741 duration: this.duration,
17742 timing: this.timing
17743 }).restoreStyle().queue(function (done) {
17744 callback();
17745 done();
17746 }));
17747 }
17748
17749 /**
17750 * @param {Object} enterPage
17751 * @param {Object} leavePage
17752 * @param {Function} done
17753 */
17754
17755 }, {
17756 key: 'pop',
17757 value: function pop(enterPage, leavePage, callback) {
17758 animit.runAll(animit(leavePage).queue({
17759 css: {
17760 transform: 'translate3D(0, 0, 0)'
17761 },
17762 duration: 0
17763 }).wait(0.15).queue({
17764 css: {
17765 transform: 'translate3D(0, 38px, 0)'
17766 },
17767 duration: this.duration,
17768 timing: this.timing
17769 }).queue(function (done) {
17770 callback();
17771 done();
17772 }), animit(leavePage).queue({
17773 css: {
17774 opacity: 1
17775 },
17776 duration: 0
17777 }).wait(0.04).queue({
17778 css: {
17779 opacity: 0
17780 },
17781 duration: this.duration,
17782 timing: this.timing
17783 }));
17784 }
17785 }]);
17786 return MDFadeNavigatorTransitionAnimator;
17787}(NavigatorTransitionAnimator);
17788
17789/*
17790Copyright 2013-2015 ASIAL CORPORATION
17791
17792Licensed under the Apache License, Version 2.0 (the "License");
17793you may not use this file except in compliance with the License.
17794You may obtain a copy of the License at
17795
17796 http://www.apache.org/licenses/LICENSE-2.0
17797
17798Unless required by applicable law or agreed to in writing, software
17799distributed under the License is distributed on an "AS IS" BASIS,
17800WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17801See the License for the specific language governing permissions and
17802limitations under the License.
17803
17804*/
17805
17806var NoneNavigatorTransitionAnimator = function (_NavigatorTransitionA) {
17807 inherits(NoneNavigatorTransitionAnimator, _NavigatorTransitionA);
17808
17809 function NoneNavigatorTransitionAnimator(options) {
17810 classCallCheck(this, NoneNavigatorTransitionAnimator);
17811 return possibleConstructorReturn(this, (NoneNavigatorTransitionAnimator.__proto__ || Object.getPrototypeOf(NoneNavigatorTransitionAnimator)).call(this, options));
17812 }
17813
17814 createClass(NoneNavigatorTransitionAnimator, [{
17815 key: 'push',
17816 value: function push(enterPage, leavePage, callback) {
17817 callback();
17818 }
17819 }, {
17820 key: 'pop',
17821 value: function pop(enterPage, leavePage, callback) {
17822 callback();
17823 }
17824 }]);
17825 return NoneNavigatorTransitionAnimator;
17826}(NavigatorTransitionAnimator);
17827
17828/*
17829Copyright 2013-2015 ASIAL CORPORATION
17830
17831Licensed under the Apache License, Version 2.0 (the "License");
17832you may not use this file except in compliance with the License.
17833You may obtain a copy of the License at
17834
17835 http://www.apache.org/licenses/LICENSE-2.0
17836
17837Unless required by applicable law or agreed to in writing, software
17838distributed under the License is distributed on an "AS IS" BASIS,
17839WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17840See the License for the specific language governing permissions and
17841limitations under the License.
17842
17843*/
17844
17845var _animatorDict$3 = {
17846 'default': function _default() {
17847 return platform.isAndroid() ? MDFadeNavigatorTransitionAnimator : IOSSlideNavigatorTransitionAnimator;
17848 },
17849 'slide': function slide() {
17850 return platform.isAndroid() ? MDSlideNavigatorTransitionAnimator : IOSSlideNavigatorTransitionAnimator;
17851 },
17852 'lift': function lift() {
17853 return platform.isAndroid() ? MDLiftNavigatorTransitionAnimator : IOSLiftNavigatorTransitionAnimator;
17854 },
17855 'fade': function fade() {
17856 return platform.isAndroid() ? MDFadeNavigatorTransitionAnimator : IOSFadeNavigatorTransitionAnimator;
17857 },
17858 'slide-ios': IOSSlideNavigatorTransitionAnimator,
17859 'slide-md': MDSlideNavigatorTransitionAnimator,
17860 'lift-ios': IOSLiftNavigatorTransitionAnimator,
17861 'lift-md': MDLiftNavigatorTransitionAnimator,
17862 'fade-ios': IOSFadeNavigatorTransitionAnimator,
17863 'fade-md': MDFadeNavigatorTransitionAnimator,
17864 'none': NoneNavigatorTransitionAnimator
17865};
17866
17867var rewritables = {
17868 /**
17869 * @param {Element} navigatorSideElement
17870 * @param {Function} callback
17871 */
17872 ready: function ready(navigatorElement, callback) {
17873 callback();
17874 },
17875
17876
17877 /**
17878 * @param {Element} navigatorElement
17879 * @param {Element} target
17880 * @param {Object} options
17881 * @param {Function} callback
17882 */
17883 link: function link(navigatorElement, target, options, callback) {
17884 callback(target);
17885 }
17886};
17887
17888/**
17889 * @element ons-navigator
17890 * @category navigation
17891 * @description
17892 * [en]
17893 * A component that provides page stack management and navigation. Stack navigation is the most common navigation pattern for mobile apps.
17894 *
17895 * When a page is pushed on top of the stack it is displayed with a transition animation. When the user returns to the previous page the top page will be popped from the top of the stack and hidden with an opposite transition animation.
17896 * [/en]
17897 * [ja][/ja]
17898 * @codepen yrhtv
17899 * @tutorial vanilla/Reference/navigator
17900 * @guide multiple-page-navigation
17901 * [en]Guide for page navigation[/en]
17902 * [ja]ページナビゲーションの概要[/ja]
17903 * @guide templates
17904 * [en]Defining multiple pages in single html[/en]
17905 * [ja]複数のページを1つのHTMLに記述する[/ja]
17906 * @guide creating-a-page
17907 * [en]Setting up a page in its `init` event[/en]
17908 * [ja]Setting up a page in its `init` event[/ja]
17909 * @seealso ons-toolbar
17910 * [en]The `<ons-toolbar>` component is used to display a toolbar on the top of a page.[/en]
17911 * [ja][/ja]
17912 * @seealso ons-back-button
17913 * [en]The `<ons-back-button>` component lets the user return to the previous page.[/en]
17914 * [ja][/ja]
17915 * @example
17916 * <ons-navigator id="navigator">
17917 * <ons-page>
17918 * <ons-toolbar>
17919 * <div class="center">
17920 * Title
17921 * </div>
17922 * </ons-toolbar>
17923 * <p>
17924 * <ons-button
17925 * onclick="document.getElementById('navigator').pushPage('page.html')">
17926 * Push page
17927 * </ons-button>
17928 * </p>
17929 * </ons-page>
17930 * </ons-navigator>
17931 *
17932 * <ons-template id="page.html">
17933 * <ons-page>
17934 * <ons-toolbar>
17935 * <div class="left">
17936 * <ons-back-button>Back</ons-back-button>
17937 * </div>
17938 * <div class="center">
17939 * Another page
17940 * </div>
17941 * </ons-toolbar>
17942 * </ons-page>
17943 * </ons-template>
17944 */
17945
17946var NavigatorElement = function (_BaseElement) {
17947 inherits(NavigatorElement, _BaseElement);
17948
17949 function NavigatorElement() {
17950 classCallCheck(this, NavigatorElement);
17951 return possibleConstructorReturn(this, (NavigatorElement.__proto__ || Object.getPrototypeOf(NavigatorElement)).apply(this, arguments));
17952 }
17953
17954 createClass(NavigatorElement, [{
17955 key: 'init',
17956 value: function init() {
17957 this._isRunning = false;
17958 this._pageLoader = defaultPageLoader;
17959
17960 this._updateAnimatorFactory();
17961 }
17962
17963 /**
17964 * @property pageLoader
17965 * @type {PageLoader}
17966 * @description
17967 * [en][/en]
17968 * [ja]PageLoaderインスタンスを格納しています。[/ja]
17969 */
17970
17971 }, {
17972 key: '_getPageTarget',
17973 value: function _getPageTarget() {
17974 return this._page || this.getAttribute('page');
17975 }
17976
17977 /**
17978 * @property page
17979 * @type {*}
17980 * @description
17981 * [en][/en]
17982 * [ja]初期化時に読み込むページを指定します。`page`属性で指定した値よりも`page`プロパティに指定した値を優先します。[/ja]
17983 */
17984
17985 }, {
17986 key: 'connectedCallback',
17987 value: function connectedCallback() {
17988 var _this2 = this;
17989
17990 this.onDeviceBackButton = this._onDeviceBackButton.bind(this);
17991
17992 rewritables.ready(this, function () {
17993 if (_this2.pages.length === 0 && _this2._getPageTarget()) {
17994 _this2.pushPage(_this2._getPageTarget(), { animation: 'none' });
17995 } else if (_this2.pages.length > 0) {
17996 for (var i = 0; i < _this2.pages.length; i++) {
17997 if (_this2.pages[i].nodeName !== 'ONS-PAGE') {
17998 throw new Error('The children of <ons-navigator> need to be of type <ons-page>');
17999 }
18000 }
18001
18002 if (_this2.topPage) {
18003 contentReady(_this2.topPage, function () {
18004 return setTimeout(function () {
18005 _this2.topPage._show();
18006 _this2._updateLastPageBackButton();
18007 }, 0);
18008 });
18009 }
18010 } else {
18011 contentReady(_this2, function () {
18012 if (_this2.pages.length === 0 && _this2._getPageTarget()) {
18013 _this2.pushPage(_this2._getPageTarget(), { animation: 'none' });
18014 }
18015 });
18016 }
18017 });
18018 }
18019 }, {
18020 key: '_updateAnimatorFactory',
18021 value: function _updateAnimatorFactory() {
18022 this._animatorFactory = new AnimatorFactory({
18023 animators: _animatorDict$3,
18024 baseClass: NavigatorTransitionAnimator,
18025 baseClassName: 'NavigatorTransitionAnimator',
18026 defaultAnimation: this.getAttribute('animation')
18027 });
18028 }
18029 }, {
18030 key: 'disconnectedCallback',
18031 value: function disconnectedCallback() {
18032 this._backButtonHandler.destroy();
18033 this._backButtonHandler = null;
18034 }
18035 }, {
18036 key: 'attributeChangedCallback',
18037 value: function attributeChangedCallback(name, last, current) {
18038 if (name === 'animation') {
18039 this._updateAnimatorFactory();
18040 }
18041 }
18042
18043 /**
18044 * @method popPage
18045 * @signature popPage([options])
18046 * @param {Object} [options]
18047 * [en]Parameter object.[/en]
18048 * [ja]オプションを指定するオブジェクト。[/ja]
18049 * @param {String} [options.animation]
18050 * [en]
18051 * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
18052 *
18053 * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
18054 * [/en]
18055 * [ja][/ja]
18056 * @param {String} [options.animationOptions]
18057 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
18058 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
18059 * @param {Boolean} [options.refresh]
18060 * [en]The previous page will be refreshed (destroyed and created again) before popPage action.[/en]
18061 * [ja]popPageする前に、前にあるページを生成しなおして更新する場合にtrueを指定します。[/ja]
18062 * @param {Function} [options.callback]
18063 * [en]Function that is called when the transition has ended.[/en]
18064 * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
18065 * @param {Object} [options.data]
18066 * [en]Custom data that will be stored in the new page element.[/en]
18067 * [ja][/ja]
18068 * @return {Promise}
18069 * [en]Promise which resolves to the revealed page.[/en]
18070 * [ja]明らかにしたページを解決するPromiseを返します。[/ja]
18071 * @description
18072 * [en]Pops the current page from the page stack. The previous page will be displayed.[/en]
18073 * [ja]現在表示中のページをページスタックから取り除きます。一つ前のページに戻ります。[/ja]
18074 */
18075
18076 }, {
18077 key: 'popPage',
18078 value: function popPage() {
18079 var _this3 = this;
18080
18081 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
18082
18083 var _preparePageAndOption = this._preparePageAndOptions(null, options);
18084
18085 options = _preparePageAndOption.options;
18086
18087
18088 var popUpdate = function popUpdate() {
18089 return new Promise(function (resolve) {
18090 _this3.pages[_this3.pages.length - 1]._destroy();
18091 resolve();
18092 });
18093 };
18094
18095 if (!options.refresh) {
18096 return this._popPage(options, popUpdate);
18097 }
18098
18099 var index = this.pages.length - 2;
18100 var oldPage = this.pages[index];
18101
18102 if (!oldPage.name) {
18103 throw new Error('Refresh option cannot be used with pages directly inside the Navigator. Use ons-template instead.');
18104 }
18105
18106 return new Promise(function (resolve) {
18107 var options = { page: oldPage.name, parent: _this3, params: oldPage.pushedOptions.data };
18108 _this3._pageLoader.load(options, function (_ref) {
18109 var element = _ref.element,
18110 unload = _ref.unload;
18111
18112 element = util.extend(element, {
18113 name: oldPage.name,
18114 data: oldPage.data,
18115 pushedOptions: oldPage.pushedOptions,
18116 unload: unload
18117 });
18118
18119 rewritables.link(_this3, element, oldPage.options, function (element) {
18120 _this3.insertBefore(element, oldPage ? oldPage : null);
18121 oldPage._destroy();
18122 resolve();
18123 });
18124 });
18125 }).then(function () {
18126 return _this3._popPage(options, popUpdate);
18127 });
18128 }
18129 }, {
18130 key: '_popPage',
18131 value: function _popPage(options) {
18132 var _this4 = this;
18133
18134 var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
18135 return Promise.resolve();
18136 };
18137
18138 if (this._isRunning) {
18139 return Promise.reject('popPage is already running.');
18140 }
18141
18142 if (this.pages.length <= 1) {
18143 return Promise.reject('ons-navigator\'s page stack is empty.');
18144 }
18145
18146 if (this._emitPrePopEvent()) {
18147 return Promise.reject('Canceled in prepop event.');
18148 }
18149
18150 var length = this.pages.length;
18151
18152 this._isRunning = true;
18153
18154 this.pages[length - 2].updateBackButton(length - 2 > 0);
18155
18156 return new Promise(function (resolve) {
18157 var leavePage = _this4.pages[length - 1];
18158 var enterPage = _this4.pages[length - 2];
18159 enterPage.style.display = 'block';
18160
18161 options.animation = options.animation || leavePage.pushedOptions.animation;
18162 options.animationOptions = util.extend({}, leavePage.pushedOptions.animationOptions, options.animationOptions || {});
18163
18164 if (options.data) {
18165 enterPage.data = util.extend({}, enterPage.data || {}, options.data || {});
18166 }
18167
18168 var callback = function callback() {
18169 update().then(function () {
18170 _this4._isRunning = false;
18171
18172 enterPage._show();
18173 util.triggerElementEvent(_this4, 'postpop', { leavePage: leavePage, enterPage: enterPage, navigator: _this4 });
18174
18175 if (typeof options.callback === 'function') {
18176 options.callback();
18177 }
18178
18179 resolve(enterPage);
18180 });
18181 };
18182
18183 leavePage._hide();
18184 var animator = _this4._animatorFactory.newAnimator(options);
18185 animator.pop(_this4.pages[length - 2], _this4.pages[length - 1], callback);
18186 }).catch(function () {
18187 return _this4._isRunning = false;
18188 });
18189 }
18190
18191 /**
18192 * @method pushPage
18193 * @signature pushPage(page, [options])
18194 * @param {String} page
18195 * [en]Page URL. Can be either a HTML document or a template defined with the `<ons-template>` tag.[/en]
18196 * [ja]pageのURLか、もしくはons-templateで宣言したテンプレートのid属性の値を指定できます。[/ja]
18197 * @param {Object} [options]
18198 * [en]Parameter object.[/en]
18199 * [ja]オプションを指定するオブジェクト。[/ja]
18200 * @param {String} [options.page]
18201 * [en]Page URL. Only necessary if `page` parameter is null or undefined.[/en]
18202 * [ja][/ja]
18203 * @param {String} [options.pageHTML]
18204 * [en]HTML code that will be computed as a new page. Overwrites `page` parameter.[/en]
18205 * [ja][/ja]
18206 * @param {String} [options.animation]
18207 * [en]
18208 * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
18209 *
18210 * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
18211 * [/en]
18212 * [ja][/ja]
18213 * @param {String} [options.animationOptions]
18214 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en]
18215 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
18216 * @param {Function} [options.callback]
18217 * [en]Function that is called when the transition has ended.[/en]
18218 * [ja]pushPage()による画面遷移が終了した時に呼び出される関数オブジェクトを指定します。[/ja]
18219 * @param {Object} [options.data]
18220 * [en]Custom data that will be stored in the new page element.[/en]
18221 * [ja][/ja]
18222 * @return {Promise}
18223 * [en]Promise which resolves to the pushed page.[/en]
18224 * [ja]追加したページを解決するPromiseを返します。[/ja]
18225 * @description
18226 * [en]Pushes the specified page into the stack.[/en]
18227 * [ja]指定したpageを新しいページスタックに追加します。新しいページが表示されます。[/ja]
18228 */
18229
18230 }, {
18231 key: 'pushPage',
18232 value: function pushPage(page) {
18233 var _this5 = this;
18234
18235 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18236
18237 var _preparePageAndOption2 = this._preparePageAndOptions(page, options);
18238
18239 page = _preparePageAndOption2.page;
18240 options = _preparePageAndOption2.options;
18241
18242
18243 var prepare = function prepare(element, unload) {
18244 _this5._verifyPageElement(element);
18245 element = util.extend(element, {
18246 name: options.page,
18247 data: options.data,
18248 unload: unload
18249 });
18250 element.style.display = 'none';
18251 };
18252
18253 if (options.pageHTML) {
18254 return this._pushPage(options, function () {
18255 return new Promise(function (resolve) {
18256 instantPageLoader.load({ page: options.pageHTML, parent: _this5, params: options.data }, function (_ref2) {
18257 var element = _ref2.element,
18258 unload = _ref2.unload;
18259
18260 prepare(element, unload);
18261 resolve();
18262 });
18263 });
18264 });
18265 }
18266
18267 return this._pushPage(options, function () {
18268 return new Promise(function (resolve) {
18269 _this5._pageLoader.load({ page: page, parent: _this5, params: options.data }, function (_ref3) {
18270 var element = _ref3.element,
18271 unload = _ref3.unload;
18272
18273 prepare(element, unload);
18274 resolve();
18275 });
18276 });
18277 });
18278 }
18279 }, {
18280 key: '_pushPage',
18281 value: function _pushPage() {
18282 var _this6 = this;
18283
18284 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
18285 var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
18286 return Promise.resolve();
18287 };
18288
18289 if (this._isRunning) {
18290 return Promise.reject('pushPage is already running.');
18291 }
18292
18293 if (this._emitPrePushEvent()) {
18294 return Promise.reject('Canceled in prepush event.');
18295 }
18296
18297 this._isRunning = true;
18298
18299 var animationOptions = AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options'));
18300 options = util.extend({}, this.options || {}, { animationOptions: animationOptions }, options);
18301
18302 var animator = this._animatorFactory.newAnimator(options);
18303
18304 return update().then(function () {
18305 var pageLength = _this6.pages.length;
18306
18307 var enterPage = _this6.pages[pageLength - 1];
18308 var leavePage = _this6.pages[pageLength - 2];
18309
18310 if (enterPage.nodeName !== 'ONS-PAGE') {
18311 throw new Error('Only elements of type <ons-page> can be pushed to the navigator');
18312 }
18313
18314 enterPage.updateBackButton(pageLength - 1);
18315
18316 enterPage.pushedOptions = util.extend({}, enterPage.pushedOptions || {}, options || {});
18317 enterPage.data = util.extend({}, enterPage.data || {}, options.data || {});
18318 enterPage.name = enterPage.name || options.page;
18319 enterPage.unload = enterPage.unload || options.unload;
18320
18321 return new Promise(function (resolve) {
18322 var done = function done() {
18323 _this6._isRunning = false;
18324
18325 if (leavePage) {
18326 leavePage.style.display = 'none';
18327 }
18328
18329 setImmediate(function () {
18330 return enterPage._show();
18331 });
18332 util.triggerElementEvent(_this6, 'postpush', { leavePage: leavePage, enterPage: enterPage, navigator: _this6 });
18333
18334 if (typeof options.callback === 'function') {
18335 options.callback();
18336 }
18337
18338 resolve(enterPage);
18339 };
18340
18341 enterPage.style.display = 'none';
18342
18343 var push = function push() {
18344 enterPage.style.display = 'block';
18345 if (leavePage) {
18346 leavePage._hide();
18347 animator.push(enterPage, leavePage, done);
18348 } else {
18349 done();
18350 }
18351 };
18352
18353 options._linked ? push() : rewritables.link(_this6, enterPage, options, push);
18354 });
18355 }).catch(function (error) {
18356 _this6._isRunning = false;
18357 throw error;
18358 });
18359 }
18360
18361 /**
18362 * @method replacePage
18363 * @signature replacePage(page, [options])
18364 * @return {Promise}
18365 * [en]Promise which resolves to the new page.[/en]
18366 * [ja]新しいページを解決するPromiseを返します。[/ja]
18367 * @description
18368 * [en]Replaces the current top page with the specified one. Extends `pushPage()` parameters.[/en]
18369 * [ja]現在表示中のページをを指定したページに置き換えます。[/ja]
18370 */
18371
18372 }, {
18373 key: 'replacePage',
18374 value: function replacePage(page) {
18375 var _this7 = this;
18376
18377 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18378
18379 return this.pushPage(page, options).then(function (resolvedValue) {
18380 if (_this7.pages.length > 1) {
18381 _this7.pages[_this7.pages.length - 2]._destroy();
18382 }
18383 _this7._updateLastPageBackButton();
18384
18385 return Promise.resolve(resolvedValue);
18386 });
18387 }
18388
18389 /**
18390 * @method insertPage
18391 * @signature insertPage(index, page, [options])
18392 * @param {Number} index
18393 * [en]The index where it should be inserted.[/en]
18394 * [ja]スタックに挿入する位置のインデックスを指定します。[/ja]
18395 * @return {Promise}
18396 * [en]Promise which resolves to the inserted page.[/en]
18397 * [ja]指定したページを解決するPromiseを返します。[/ja]
18398 * @description
18399 * [en]Insert the specified page into the stack with at a position defined by the `index` argument. Extends `pushPage()` parameters.[/en]
18400 * [ja]指定したpageをページスタックのindexで指定した位置に追加します。[/ja]
18401 */
18402
18403 }, {
18404 key: 'insertPage',
18405 value: function insertPage(index, page) {
18406 var _this8 = this;
18407
18408 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
18409
18410 var _preparePageAndOption3 = this._preparePageAndOptions(page, options);
18411
18412 page = _preparePageAndOption3.page;
18413 options = _preparePageAndOption3.options;
18414
18415 index = this._normalizeIndex(index);
18416
18417 if (index >= this.pages.length) {
18418 return this.pushPage(page, options);
18419 }
18420
18421 page = typeof options.pageHTML === 'string' ? options.pageHTML : page;
18422 var loader = typeof options.pageHTML === 'string' ? instantPageLoader : this._pageLoader;
18423
18424 return new Promise(function (resolve) {
18425 loader.load({ page: page, parent: _this8 }, function (_ref4) {
18426 var element = _ref4.element,
18427 unload = _ref4.unload;
18428
18429 _this8._verifyPageElement(element);
18430 element = util.extend(element, {
18431 name: options.page,
18432 data: options.data,
18433 pushedOptions: options,
18434 unload: unload
18435 });
18436
18437 options.animationOptions = util.extend({}, AnimatorFactory.parseAnimationOptionsString(_this8.getAttribute('animation-options')), options.animationOptions || {});
18438
18439 element.style.display = 'none';
18440 _this8.insertBefore(element, _this8.pages[index]);
18441 _this8.topPage.updateBackButton(true);
18442
18443 rewritables.link(_this8, element, options, function (element) {
18444 setTimeout(function () {
18445 element = null;
18446 resolve(_this8.pages[index]);
18447 }, 1000 / 60);
18448 });
18449 });
18450 });
18451 }
18452
18453 /**
18454 * @method resetToPage
18455 * @signature resetToPage(page, [options])
18456 * @return {Promise}
18457 * [en]Promise which resolves to the new top page.[/en]
18458 * [ja]新しいトップページを解決するPromiseを返します。[/ja]
18459 * @description
18460 * [en]Clears page stack and adds the specified page to the stack. Extends `pushPage()` parameters.[/en]
18461 * [ja]ページスタックをリセットし、指定したページを表示します。[/ja]
18462 */
18463
18464 }, {
18465 key: 'resetToPage',
18466 value: function resetToPage(page) {
18467 var _this9 = this;
18468
18469 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18470
18471 var _preparePageAndOption4 = this._preparePageAndOptions(page, options);
18472
18473 page = _preparePageAndOption4.page;
18474 options = _preparePageAndOption4.options;
18475
18476
18477 if (!options.animator && !options.animation) {
18478 options.animation = 'none';
18479 }
18480
18481 var callback = options.callback;
18482
18483 options.callback = function () {
18484 while (_this9.pages.length > 1) {
18485 _this9.pages[0]._destroy();
18486 }
18487
18488 _this9.pages[0].updateBackButton(false);
18489 callback && callback();
18490 };
18491
18492 if (!options.page && !options.pageHTML && this._getPageTarget()) {
18493 page = options.page = this._getPageTarget();
18494 }
18495
18496 return this.pushPage(page, options);
18497 }
18498
18499 /**
18500 * @method bringPageTop
18501 * @signature bringPageTop(item, [options])
18502 * @param {String|Number} item
18503 * [en]Page URL or index of an existing page in navigator's stack.[/en]
18504 * [ja]ページのURLかもしくはons-navigatorのページスタックのインデックス値を指定します。[/ja]
18505 * @return {Promise}
18506 * [en]Promise which resolves to the new top page.[/en]
18507 * [ja]新しいトップページを解決するPromiseを返します。[/ja]
18508 * @description
18509 * [en]Brings the given page to the top of the page stack if it already exists or pushes it into the stack if doesn't. Extends `pushPage()` parameters.[/en]
18510 * [ja]指定したページをページスタックの一番上に移動します。もし指定したページが無かった場合新しくpushされます。[/ja]
18511 */
18512
18513 }, {
18514 key: 'bringPageTop',
18515 value: function bringPageTop(item) {
18516 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18517
18518 if (['number', 'string'].indexOf(typeof item === 'undefined' ? 'undefined' : _typeof(item)) === -1) {
18519 throw new Error('First argument must be a page name or the index of an existing page. You supplied ' + item);
18520 }
18521 var index = typeof item === 'number' ? this._normalizeIndex(item) : this._lastIndexOfPage(item);
18522 var page = this.pages[index];
18523
18524 if (index < 0) {
18525 return this.pushPage(item, options);
18526 }
18527
18528 var _preparePageAndOption5 = this._preparePageAndOptions(page, options);
18529
18530 options = _preparePageAndOption5.options;
18531
18532
18533 if (index === this.pages.length - 1) {
18534 return Promise.resolve(page);
18535 }
18536 if (!page) {
18537 throw new Error('Failed to find item ' + item);
18538 }
18539 if (this._isRunning) {
18540 return Promise.reject('pushPage is already running.');
18541 }
18542 if (this._emitPrePushEvent()) {
18543 return Promise.reject('Canceled in prepush event.');
18544 }
18545
18546 util.extend(options, {
18547 page: page.name,
18548 _linked: true
18549 });
18550 page.style.display = 'none';
18551 page.setAttribute('_skipinit', '');
18552 page.parentNode.appendChild(page);
18553 return this._pushPage(options);
18554 }
18555 }, {
18556 key: '_preparePageAndOptions',
18557 value: function _preparePageAndOptions(page) {
18558 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18559
18560 if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) != 'object') {
18561 throw new Error('options must be an object. You supplied ' + options);
18562 }
18563
18564 if ((page === null || page === undefined) && options.page) {
18565 page = options.page;
18566 }
18567
18568 options = util.extend({}, this.options || {}, options, { page: page });
18569
18570 return { page: page, options: options };
18571 }
18572 }, {
18573 key: '_updateLastPageBackButton',
18574 value: function _updateLastPageBackButton() {
18575 var index = this.pages.length - 1;
18576 if (index >= 0) {
18577 this.pages[index].updateBackButton(index > 0);
18578 }
18579 }
18580 }, {
18581 key: '_normalizeIndex',
18582 value: function _normalizeIndex(index) {
18583 return index >= 0 ? index : Math.abs(this.pages.length + index) % this.pages.length;
18584 }
18585 }, {
18586 key: '_onDeviceBackButton',
18587 value: function _onDeviceBackButton(event) {
18588 if (this.pages.length > 1) {
18589 this.popPage();
18590 } else {
18591 event.callParentHandler();
18592 }
18593 }
18594 }, {
18595 key: '_lastIndexOfPage',
18596 value: function _lastIndexOfPage(pageName) {
18597 var index = void 0;
18598 for (index = this.pages.length - 1; index >= 0; index--) {
18599 if (this.pages[index].name === pageName) {
18600 break;
18601 }
18602 }
18603 return index;
18604 }
18605 }, {
18606 key: '_emitPreEvent',
18607 value: function _emitPreEvent(name) {
18608 var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
18609
18610 var isCanceled = false;
18611
18612 util.triggerElementEvent(this, 'pre' + name, util.extend({
18613 navigator: this,
18614 currentPage: this.pages[this.pages.length - 1],
18615 cancel: function cancel() {
18616 return isCanceled = true;
18617 }
18618 }, data));
18619
18620 return isCanceled;
18621 }
18622 }, {
18623 key: '_emitPrePushEvent',
18624 value: function _emitPrePushEvent() {
18625 return this._emitPreEvent('push');
18626 }
18627 }, {
18628 key: '_emitPrePopEvent',
18629 value: function _emitPrePopEvent() {
18630 var l = this.pages.length;
18631 return this._emitPreEvent('pop', {
18632 leavePage: this.pages[l - 1],
18633 enterPage: this.pages[l - 2]
18634 });
18635 }
18636
18637 // TODO: 書き直す
18638
18639 }, {
18640 key: '_createPageElement',
18641 value: function _createPageElement(templateHTML) {
18642 var pageElement = util.createElement(internal$1.normalizePageHTML(templateHTML));
18643 this._verifyPageElement(pageElement);
18644 return pageElement;
18645 }
18646
18647 /**
18648 * @param {Element} element
18649 */
18650
18651 }, {
18652 key: '_verifyPageElement',
18653 value: function _verifyPageElement(element) {
18654 if (element.nodeName.toLowerCase() !== 'ons-page') {
18655 throw new Error('You must supply an "ons-page" element to "ons-navigator".');
18656 }
18657 }
18658
18659 /**
18660 * @property onDeviceBackButton
18661 * @type {Object}
18662 * @description
18663 * [en]Back-button handler.[/en]
18664 * [ja]バックボタンハンドラ。[/ja]
18665 */
18666
18667 }, {
18668 key: '_show',
18669 value: function _show() {
18670 if (this.topPage) {
18671 this.topPage._show();
18672 }
18673 }
18674 }, {
18675 key: '_hide',
18676 value: function _hide() {
18677 if (this.topPage) {
18678 this.topPage._hide();
18679 }
18680 }
18681 }, {
18682 key: '_destroy',
18683 value: function _destroy() {
18684 for (var i = this.pages.length - 1; i >= 0; i--) {
18685 this.pages[i]._destroy();
18686 }
18687
18688 this.remove();
18689 }
18690
18691 /**
18692 * @param {String} name
18693 * @param {Function} Animator
18694 */
18695
18696 }, {
18697 key: 'animatorFactory',
18698
18699
18700 /**
18701 * @attribute page
18702 * @initonly
18703 * @type {String}
18704 * @description
18705 * [en]First page to show when navigator is initialized.[/en]
18706 * [ja]ナビゲーターが初期化された時に表示するページを指定します。[/ja]
18707 */
18708
18709 /**
18710 * @attribute animation
18711 * @type {String}
18712 * @default default
18713 * @description
18714 * [en]
18715 * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
18716 *
18717 * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"` depending on the platform.
18718 * [/en]
18719 * [ja][/ja]
18720 */
18721
18722 /**
18723 * @attribute animation-options
18724 * @type {Expression}
18725 * @description
18726 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/en]
18727 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja]
18728 */
18729
18730 /**
18731 * @event prepush
18732 * @description
18733 * [en]Fired just before a page is pushed.[/en]
18734 * [ja]pageがpushされる直前に発火されます。[/ja]
18735 * @param {Object} event [en]Event object.[/en]
18736 * @param {Object} event.navigator
18737 * [en]Component object.[/en]
18738 * [ja]コンポーネントのオブジェクト。[/ja]
18739 * @param {Object} event.currentPage
18740 * [en]Current page object.[/en]
18741 * [ja]現在のpageオブジェクト。[/ja]
18742 * @param {Function} event.cancel
18743 * [en]Call this function to cancel the push.[/en]
18744 * [ja]この関数を呼び出すと、push処理がキャンセルされます。[/ja]
18745 */
18746
18747 /**
18748 * @event prepop
18749 * @description
18750 * [en]Fired just before a page is popped.[/en]
18751 * [ja]pageがpopされる直前に発火されます。[/ja]
18752 * @param {Object} event [en]Event object.[/en]
18753 * @param {Object} event.navigator
18754 * [en]Component object.[/en]
18755 * [ja]コンポーネントのオブジェクト。[/ja]
18756 * @param {Object} event.currentPage
18757 * [en]Current page object.[/en]
18758 * [ja]現在のpageオブジェクト。[/ja]
18759 * @param {Function} event.cancel
18760 * [en]Call this function to cancel the pop.[/en]
18761 * [ja]この関数を呼び出すと、pageのpopがキャンセルされます。[/ja]
18762 */
18763
18764 /**
18765 * @event postpush
18766 * @description
18767 * [en]Fired just after a page is pushed.[/en]
18768 * [ja]pageがpushされてアニメーションが終了してから発火されます。[/ja]
18769 * @param {Object} event [en]Event object.[/en]
18770 * @param {Object} event.navigator
18771 * [en]Component object.[/en]
18772 * [ja]コンポーネントのオブジェクト。[/ja]
18773 * @param {Object} event.enterPage
18774 * [en]Object of the next page.[/en]
18775 * [ja]pushされたpageオブジェクト。[/ja]
18776 * @param {Object} event.leavePage
18777 * [en]Object of the previous page.[/en]
18778 * [ja]以前のpageオブジェクト。[/ja]
18779 */
18780
18781 /**
18782 * @event postpop
18783 * @description
18784 * [en]Fired just after a page is popped.[/en]
18785 * [ja]pageがpopされてアニメーションが終わった後に発火されます。[/ja]
18786 * @param {Object} event [en]Event object.[/en]
18787 * @param {Object} event.navigator
18788 * [en]Component object.[/en]
18789 * [ja]コンポーネントのオブジェクト。[/ja]
18790 * @param {Object} event.enterPage
18791 * [en]Object of the next page.[/en]
18792 * [ja]popされて表示されるページのオブジェクト。[/ja]
18793 * @param {Object} event.leavePage
18794 * [en]Object of the previous page.[/en]
18795 * [ja]popされて消えるページのオブジェクト。[/ja]
18796 */
18797
18798 get: function get() {
18799 return this._animatorFactory;
18800 }
18801 }, {
18802 key: 'pageLoader',
18803 get: function get() {
18804 return this._pageLoader;
18805 },
18806 set: function set(pageLoader) {
18807 if (!(pageLoader instanceof PageLoader)) {
18808 throw Error('First parameter must be an instance of PageLoader.');
18809 }
18810 this._pageLoader = pageLoader;
18811 }
18812 }, {
18813 key: 'page',
18814 get: function get() {
18815 return this._page;
18816 },
18817 set: function set(page) {
18818 this._page = page;
18819 }
18820 }, {
18821 key: 'onDeviceBackButton',
18822 get: function get() {
18823 return this._backButtonHandler;
18824 },
18825 set: function set(callback) {
18826 if (this._backButtonHandler) {
18827 this._backButtonHandler.destroy();
18828 }
18829
18830 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
18831 }
18832
18833 /**
18834 * @property topPage
18835 * @readonly
18836 * @type {HTMLElement}
18837 * @description
18838 * [en]Current top page element. Use this method to access options passed by `pushPage()`-like methods.[/en]
18839 * [ja]現在のページを取得します。pushPage()やresetToPage()メソッドの引数を取得できます。[/ja]
18840 */
18841
18842 }, {
18843 key: 'topPage',
18844 get: function get() {
18845 return this.pages[this.pages.length - 1] || null;
18846 }
18847
18848 /**
18849 * @property pages
18850 * @readonly
18851 * @type {Array}
18852 * @description
18853 * [en]Copy of the navigator's page stack.[/en]
18854 * [ja][/ja]
18855 */
18856
18857 }, {
18858 key: 'pages',
18859 get: function get() {
18860 return util.arrayFrom(this.children).filter(function (n) {
18861 return n.tagName === 'ONS-PAGE';
18862 });
18863 }
18864
18865 /**
18866 * @property options
18867 * @type {Object}
18868 * @description
18869 * [en]Default options object. Attributes have priority over this property.[/en]
18870 * [ja][/ja]
18871 */
18872
18873 /**
18874 * @property options.animation
18875 * @type {String}
18876 * @description
18877 * [en]
18878 * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`.
18879 * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`.
18880 * [/en]
18881 * [ja][/ja]
18882 */
18883
18884 /**
18885 * @property options.animationOptions
18886 * @type {String}
18887 * @description
18888 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
18889 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja]
18890 */
18891
18892 /**
18893 * @property options.callback
18894 * @type {String}
18895 * @description
18896 * [en]Function that is called when the transition has ended.[/en]
18897 * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja]
18898 */
18899
18900 /**
18901 * @property options.refresh
18902 * @default false
18903 * @type {Boolean}
18904 * @description
18905 * [en]If this parameter is `true`, the previous page will be refreshed (destroyed and created again) before `popPage()` action.[/en]
18906 * [ja]popPageする前に、前にあるページを生成しなおして更新する場合にtrueを指定します。[/ja]
18907 */
18908
18909 }, {
18910 key: 'options',
18911 get: function get() {
18912 return this._options;
18913 },
18914 set: function set(object) {
18915 this._options = object;
18916 }
18917 }, {
18918 key: '_isRunning',
18919 set: function set(value) {
18920 this.setAttribute('_is-running', value ? 'true' : 'false');
18921 },
18922 get: function get() {
18923 return JSON.parse(this.getAttribute('_is-running'));
18924 }
18925 }], [{
18926 key: 'registerAnimator',
18927 value: function registerAnimator(name, Animator) {
18928 if (!(Animator.prototype instanceof NavigatorTransitionAnimator)) {
18929 throw new Error('"Animator" param must inherit NavigatorElement.NavigatorTransitionAnimator');
18930 }
18931
18932 _animatorDict$3[name] = Animator;
18933 }
18934 }, {
18935 key: 'observedAttributes',
18936 get: function get() {
18937 return ['animation'];
18938 }
18939 }, {
18940 key: 'animators',
18941 get: function get() {
18942 return _animatorDict$3;
18943 }
18944 }, {
18945 key: 'NavigatorTransitionAnimator',
18946 get: function get() {
18947 return NavigatorTransitionAnimator;
18948 }
18949 }, {
18950 key: 'rewritables',
18951 get: function get() {
18952 return rewritables;
18953 }
18954 }]);
18955 return NavigatorElement;
18956}(BaseElement);
18957
18958customElements.define('ons-navigator', NavigatorElement);
18959
18960/*
18961Copyright 2013-2015 ASIAL CORPORATION
18962
18963Licensed under the Apache License, Version 2.0 (the "License");
18964you may not use this file except in compliance with the License.
18965You may obtain a copy of the License at
18966
18967 http://www.apache.org/licenses/LICENSE-2.0
18968
18969Unless required by applicable law or agreed to in writing, software
18970distributed under the License is distributed on an "AS IS" BASIS,
18971WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18972See the License for the specific language governing permissions and
18973limitations under the License.
18974
18975*/
18976
18977var scheme$13 = {
18978 '': 'navigation-bar--*',
18979 '.navigation-bar__left': 'navigation-bar--*__left',
18980 '.navigation-bar__center': 'navigation-bar--*__center',
18981 '.navigation-bar__right': 'navigation-bar--*__right'
18982};
18983
18984/**
18985 * @element ons-toolbar
18986 * @category page
18987 * @modifier material
18988 * [en]Material Design toolbar.[/en]
18989 * [ja][/ja]
18990 * @modifier transparent
18991 * [en]Transparent toolbar[/en]
18992 * [ja]透明な背景を持つツールバーを表示します。[/ja]
18993 * @modifier noshadow
18994 * [en]Toolbar without shadow[/en]
18995 * [ja]どうしよう[/ja]
18996 * @description
18997 * [en]
18998 * Toolbar component that can be used with navigation.
18999 *
19000 * Left, center and right container can be specified by class names.
19001 *
19002 * This component will automatically displays as a Material Design toolbar when running on Android devices.
19003 * [/en]
19004 * [ja]ナビゲーションで使用するツールバー用コンポーネントです。クラス名により、左、中央、右のコンテナを指定できます。[/ja]
19005 * @codepen aHmGL
19006 * @tutorial vanilla/Reference/page
19007 * @guide adding-a-toolbar [en]Adding a toolbar[/en][ja]ツールバーの追加[/ja]
19008 * @seealso ons-bottom-toolbar
19009 * [en]The `<ons-bottom-toolbar>` displays a toolbar on the bottom of the page.[/en]
19010 * [ja]ons-bottom-toolbarコンポーネント[/ja]
19011 * @seealso ons-back-button
19012 * [en]The `<ons-back-button>` component displays a back button inside the toolbar.[/en]
19013 * [ja]ons-back-buttonコンポーネント[/ja]
19014 * @seealso ons-toolbar-button
19015 * [en]The `<ons-toolbar-button>` component displays a toolbar button inside the toolbar.[/en]
19016 * [ja]ons-toolbar-buttonコンポーネント[/ja]
19017 * @example
19018 * <ons-page>
19019 * <ons-toolbar>
19020 * <div class="left">
19021 * <ons-back-button>
19022 * Back
19023 * </ons-back-button>
19024 * </div>
19025 * <div class="center">
19026 * Title
19027 * </div>
19028 * <div class="right">
19029 * <ons-toolbar-button>
19030 * <ons-icon icon="md-menu"></ons-icon>
19031 * </ons-toolbar-button>
19032 * </div>
19033 * </ons-toolbar>
19034 * </ons-page>
19035 */
19036
19037var ToolbarElement = function (_BaseElement) {
19038 inherits(ToolbarElement, _BaseElement);
19039
19040 function ToolbarElement() {
19041 classCallCheck(this, ToolbarElement);
19042 return possibleConstructorReturn(this, (ToolbarElement.__proto__ || Object.getPrototypeOf(ToolbarElement)).apply(this, arguments));
19043 }
19044
19045 createClass(ToolbarElement, [{
19046 key: 'init',
19047
19048
19049 /**
19050 * @attribute inline
19051 * @initonly
19052 * @description
19053 * [en]Display the toolbar as an inline element.[/en]
19054 * [ja]ツールバーをインラインに置きます。スクロール領域内にそのまま表示されます。[/ja]
19055 */
19056
19057 /**
19058 * @attribute modifier
19059 * @description
19060 * [en]The appearance of the toolbar.[/en]
19061 * [ja]ツールバーの表現を指定します。[/ja]
19062 */
19063
19064 value: function init() {
19065 var _this2 = this;
19066
19067 contentReady(this, function () {
19068 _this2._compile();
19069 });
19070 }
19071 }, {
19072 key: 'attributeChangedCallback',
19073 value: function attributeChangedCallback(name, last, current) {
19074 if (name === 'modifier') {
19075 return ModifierUtil.onModifierChanged(last, current, this, scheme$13);
19076 }
19077 }
19078
19079 /**
19080 * @return {HTMLElement}
19081 */
19082
19083 }, {
19084 key: '_getToolbarLeftItemsElement',
19085 value: function _getToolbarLeftItemsElement() {
19086 return this.querySelector('.left') || internal$1.nullElement;
19087 }
19088
19089 /**
19090 * @return {HTMLElement}
19091 */
19092
19093 }, {
19094 key: '_getToolbarCenterItemsElement',
19095 value: function _getToolbarCenterItemsElement() {
19096 return this.querySelector('.center') || internal$1.nullElement;
19097 }
19098
19099 /**
19100 * @return {HTMLElement}
19101 */
19102
19103 }, {
19104 key: '_getToolbarRightItemsElement',
19105 value: function _getToolbarRightItemsElement() {
19106 return this.querySelector('.right') || internal$1.nullElement;
19107 }
19108
19109 /**
19110 * @return {HTMLElement}
19111 */
19112
19113 }, {
19114 key: '_getToolbarBackButtonLabelElement',
19115 value: function _getToolbarBackButtonLabelElement() {
19116 return this.querySelector('ons-back-button .back-button__label') || internal$1.nullElement;
19117 }
19118
19119 /**
19120 * @return {HTMLElement}
19121 */
19122
19123 }, {
19124 key: '_getToolbarBackButtonIconElement',
19125 value: function _getToolbarBackButtonIconElement() {
19126 return this.querySelector('ons-back-button .back-button__icon') || internal$1.nullElement;
19127 }
19128 }, {
19129 key: '_compile',
19130 value: function _compile() {
19131 autoStyle.prepare(this);
19132 this.classList.add('navigation-bar');
19133 this._ensureToolbarItemElements();
19134 ModifierUtil.initModifier(this, scheme$13);
19135 }
19136 }, {
19137 key: '_ensureToolbarItemElements',
19138 value: function _ensureToolbarItemElements() {
19139 for (var i = this.childNodes.length - 1; i >= 0; i--) {
19140 // case of not element
19141 if (this.childNodes[i].nodeType != 1) {
19142 this.removeChild(this.childNodes[i]);
19143 }
19144 }
19145
19146 var center = this._ensureToolbarElement('center');
19147 center.classList.add('navigation-bar__title');
19148
19149 if (this.children.length !== 1 || !this.children[0].classList.contains('center')) {
19150 var left = this._ensureToolbarElement('left');
19151 var right = this._ensureToolbarElement('right');
19152
19153 if (this.children[0] !== left || this.children[1] !== center || this.children[2] !== right) {
19154 this.appendChild(left);
19155 this.appendChild(center);
19156 this.appendChild(right);
19157 }
19158 }
19159 }
19160 }, {
19161 key: '_ensureToolbarElement',
19162 value: function _ensureToolbarElement(name) {
19163 if (util.findChild(this, '.navigation-bar__' + name)) {
19164 var _element = util.findChild(this, '.navigation-bar__' + name);
19165 _element.classList.add(name);
19166 return _element;
19167 }
19168
19169 var element = util.findChild(this, '.' + name) || util.create('.' + name);
19170 element.classList.add('navigation-bar__' + name);
19171
19172 return element;
19173 }
19174 }], [{
19175 key: 'observedAttributes',
19176 get: function get() {
19177 return ['modifier'];
19178 }
19179 }]);
19180 return ToolbarElement;
19181}(BaseElement);
19182
19183customElements.define('ons-toolbar', ToolbarElement);
19184
19185/*
19186Copyright 2013-2015 ASIAL CORPORATION
19187
19188Licensed under the Apache License, Version 2.0 (the "License");
19189you may not use this file except in compliance with the License.
19190You may obtain a copy of the License at
19191
19192 http://www.apache.org/licenses/LICENSE-2.0
19193
19194Unless required by applicable law or agreed to in writing, software
19195distributed under the License is distributed on an "AS IS" BASIS,
19196WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19197See the License for the specific language governing permissions and
19198limitations under the License.
19199
19200*/
19201
19202var scheme$12 = {
19203 '': 'page--*',
19204 '.page__content': 'page--*__content',
19205 '.page__background': 'page--*__background'
19206};
19207
19208var nullToolbarElement = document.createElement('ons-toolbar'); // requires that 'ons-toolbar' element is registered
19209
19210/**
19211 * @element ons-page
19212 * @category page
19213 * @modifier material
19214 * [en]Material Design style[/en]
19215 * [ja][/ja]
19216 * @description
19217 * [en]
19218 * This component defines the root of each page. If the content is large it will become scrollable.
19219 *
19220 * A navigation bar can be added to the top of the page using the `<ons-toolbar>` element.
19221 * [/en]
19222 * [ja]ページ定義のためのコンポーネントです。このコンポーネントの内容はスクロールが許可されます。[/ja]
19223 * @tutorial vanilla/Reference/page
19224 * @guide creating-a-page
19225 * [en]Setting up a page in its `init` event[/en]
19226 * [ja]Setting up a page in its `init` event[/ja]
19227 * @guide templates
19228 * [en]Defining multiple pages in single html[/en]
19229 * [ja]複数のページを1つのHTMLに記述する[/ja]
19230 * @guide multiple-page-navigation
19231 * [en]Managing multiple pages[/en]
19232 * [ja]複数のページを管理する[/ja]
19233 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
19234 * @seealso ons-toolbar
19235 * [en]Use the `<ons-toolbar>` element to add a navigation bar to the top of the page.[/en]
19236 * [ja][/ja]
19237 * @example
19238 * <ons-page>
19239 * <ons-toolbar>
19240 * <div class="left">
19241 * <ons-back-button>Back</ons-back-button>
19242 * </div>
19243 * <div class="center">Title</div>
19244 * <div class="right">
19245 * <ons-toolbar-button>
19246 * <ons-icon icon="md-menu"></ons-icon>
19247 * </ons-toolbar-button>
19248 * </div>
19249 * </ons-toolbar>
19250 *
19251 * <p>Page content</p>
19252 * </ons-page>
19253 *
19254 * @example
19255 * <script>
19256 * myApp.handler = function(done) {
19257 * loadMore().then(done);
19258 * }
19259 * </script>
19260 *
19261 * <ons-page on-infinite-scroll="myApp.handler">
19262 * <ons-toolbar>
19263 * <div class="center">List</div>
19264 * </ons-toolbar>
19265 *
19266 * <ons-list>
19267 * <ons-list-item>#1</ons-list-item>
19268 * <ons-list-item>#2</ons-list-item>
19269 * <ons-list-item>#3</ons-list-item>
19270 * ...
19271 * </ons-list>
19272 * </ons-page>
19273 */
19274
19275var PageElement = function (_BaseElement) {
19276 inherits(PageElement, _BaseElement);
19277
19278 function PageElement() {
19279 classCallCheck(this, PageElement);
19280 return possibleConstructorReturn(this, (PageElement.__proto__ || Object.getPrototypeOf(PageElement)).apply(this, arguments));
19281 }
19282
19283 createClass(PageElement, [{
19284 key: 'init',
19285
19286
19287 /**
19288 * @event init
19289 * @description
19290 * [en]Fired right after the page is attached.[/en]
19291 * [ja]ページがアタッチされた後に発火します。[/ja]
19292 * @param {Object} event [en]Event object.[/en]
19293 */
19294
19295 /**
19296 * @event show
19297 * @description
19298 * [en]Fired right after the page is shown.[/en]
19299 * [ja]ページが表示された後に発火します。[/ja]
19300 * @param {Object} event [en]Event object.[/en]
19301 */
19302
19303 /**
19304 * @event hide
19305 * @description
19306 * [en]Fired right after the page is hidden.[/en]
19307 * [ja]ページが隠れた後に発火します。[/ja]
19308 * @param {Object} event [en]Event object.[/en]
19309 */
19310
19311 /**
19312 * @event destroy
19313 * @description
19314 * [en]Fired right before the page is destroyed.[/en]
19315 * [ja]ページが破棄される前に発火します。[/ja]
19316 * @param {Object} event [en]Event object.[/en]
19317 */
19318
19319 /**
19320 * @attribute modifier
19321 * @type {String}
19322 * @description
19323 * [en]Specify modifier name to specify custom styles.[/en]
19324 * [ja]スタイル定義をカスタマイズするための名前を指定します。[/ja]
19325 */
19326
19327 /**
19328 * @attribute on-infinite-scroll
19329 * @type {String}
19330 * @description
19331 * [en]Path of the function to be executed on infinite scrolling. Example: `app.loadData`. The function receives a done callback that must be called when it's finished.[/en]
19332 * [ja][/ja]
19333 */
19334
19335 value: function init() {
19336 var _this2 = this;
19337
19338 this.classList.add('page');
19339
19340 contentReady(this, function () {
19341 _this2._compile();
19342
19343 _this2._isShown = false;
19344 _this2._contentElement = _this2._getContentElement();
19345 _this2._isMuted = _this2.hasAttribute('_muted');
19346 _this2._skipInit = _this2.hasAttribute('_skipinit');
19347 _this2.pushedOptions = {};
19348 });
19349 }
19350 }, {
19351 key: 'connectedCallback',
19352 value: function connectedCallback() {
19353 var _this3 = this;
19354
19355 contentReady(this, function () {
19356 if (!_this3._isMuted) {
19357 if (_this3._skipInit) {
19358 _this3.removeAttribute('_skipinit');
19359 } else {
19360 setImmediate(function () {
19361 return util.triggerElementEvent(_this3, 'init');
19362 });
19363 }
19364 }
19365
19366 if (!util.hasAnyComponentAsParent(_this3)) {
19367 setImmediate(function () {
19368 return _this3._show();
19369 });
19370 }
19371
19372 _this3._tryToFillStatusBar();
19373
19374 if (_this3.hasAttribute('on-infinite-scroll')) {
19375 _this3.attributeChangedCallback('on-infinite-scroll', null, _this3.getAttribute('on-infinite-scroll'));
19376 }
19377 });
19378 }
19379 }, {
19380 key: 'updateBackButton',
19381 value: function updateBackButton(show) {
19382 if (this.backButton) {
19383 show ? this.backButton.show() : this.backButton.hide();
19384 }
19385 }
19386 }, {
19387 key: '_tryToFillStatusBar',
19388 value: function _tryToFillStatusBar() {
19389 var _this4 = this;
19390
19391 internal$1.autoStatusBarFill(function () {
19392 var filled = util.findParent(_this4, function (e) {
19393 return e.hasAttribute('status-bar-fill');
19394 });
19395 util.toggleAttribute(_this4, 'status-bar-fill', !filled && (_this4._canAnimateToolbar() || !_this4._hasAPageControlChild()));
19396 });
19397 }
19398 }, {
19399 key: '_hasAPageControlChild',
19400 value: function _hasAPageControlChild() {
19401 return util.findChild(this._contentElement, function (e) {
19402 return e.nodeName.match(/ons-(splitter|sliding-menu|navigator|tabbar)/i);
19403 });
19404 }
19405
19406 /**
19407 * @property onInfiniteScroll
19408 * @description
19409 * [en]Function to be executed when scrolling to the bottom of the page. The function receives a done callback as an argument that must be called when it's finished.[/en]
19410 * [ja][/ja]
19411 */
19412
19413 }, {
19414 key: '_onScroll',
19415 value: function _onScroll() {
19416 var _this5 = this;
19417
19418 var c = this._contentElement,
19419 overLimit = (c.scrollTop + c.clientHeight) / c.scrollHeight >= this._infiniteScrollLimit;
19420
19421 if (this._onInfiniteScroll && !this._loadingContent && overLimit) {
19422 this._loadingContent = true;
19423 this._onInfiniteScroll(function () {
19424 return _this5._loadingContent = false;
19425 });
19426 }
19427 }
19428
19429 /**
19430 * @property onDeviceBackButton
19431 * @type {Object}
19432 * @description
19433 * [en]Back-button handler.[/en]
19434 * [ja]バックボタンハンドラ。[/ja]
19435 */
19436
19437 }, {
19438 key: '_getContentElement',
19439
19440
19441 /**
19442 * @return {HTMLElement}
19443 */
19444 value: function _getContentElement() {
19445 var result = util.findChild(this, '.page__content');
19446 if (result) {
19447 return result;
19448 }
19449 throw Error('fail to get ".page__content" element.');
19450 }
19451
19452 /**
19453 * @return {Boolean}
19454 */
19455
19456 }, {
19457 key: '_canAnimateToolbar',
19458 value: function _canAnimateToolbar() {
19459 if (util.findChild(this, 'ons-toolbar')) {
19460 return true;
19461 }
19462 return !!util.findChild(this._contentElement, function (el) {
19463 return util.match(el, 'ons-toolbar') && !el.hasAttribute('inline');
19464 });
19465 }
19466
19467 /**
19468 * @return {HTMLElement}
19469 */
19470
19471 }, {
19472 key: '_getBackgroundElement',
19473 value: function _getBackgroundElement() {
19474 var result = util.findChild(this, '.page__background');
19475 if (result) {
19476 return result;
19477 }
19478 throw Error('fail to get ".page__background" element.');
19479 }
19480
19481 /**
19482 * @return {HTMLElement}
19483 */
19484
19485 }, {
19486 key: '_getBottomToolbarElement',
19487 value: function _getBottomToolbarElement() {
19488 return util.findChild(this, 'ons-bottom-toolbar') || internal$1.nullElement;
19489 }
19490
19491 /**
19492 * @return {HTMLElement}
19493 */
19494
19495 }, {
19496 key: '_getToolbarElement',
19497 value: function _getToolbarElement() {
19498 return util.findChild(this, 'ons-toolbar') || nullToolbarElement;
19499 }
19500 }, {
19501 key: 'attributeChangedCallback',
19502 value: function attributeChangedCallback(name, last, current) {
19503 var _this6 = this;
19504
19505 if (name === 'modifier') {
19506 return ModifierUtil.onModifierChanged(last, current, this, scheme$12);
19507 } else if (name === '_muted') {
19508 this._isMuted = this.hasAttribute('_muted');
19509 } else if (name === '_skipinit') {
19510 this._skipInit = this.hasAttribute('_skipinit');
19511 } else if (name === 'on-infinite-scroll') {
19512 if (current === null) {
19513 this.onInfiniteScroll = null;
19514 } else {
19515 this.onInfiniteScroll = function (done) {
19516 var f = util.findFromPath(current);
19517 _this6.onInfiniteScroll = f;
19518 f(done);
19519 };
19520 }
19521 }
19522 }
19523 }, {
19524 key: '_compile',
19525 value: function _compile() {
19526 var _this7 = this;
19527
19528 autoStyle.prepare(this);
19529
19530 if (util.findChild(this, '.content')) {
19531 util.findChild(this, '.content').classList.add('page__content');
19532 }
19533
19534 if (util.findChild(this, '.background')) {
19535 util.findChild(this, '.background').classList.add('page__background');
19536 }
19537
19538 if (!util.findChild(this, '.page__content')) {
19539 (function () {
19540 var content = util.create('.page__content');
19541
19542 util.arrayFrom(_this7.childNodes).forEach(function (node) {
19543 if (node.nodeType !== 1 || _this7._elementShouldBeMoved(node)) {
19544 content.appendChild(node);
19545 }
19546 });
19547
19548 var prevNode = util.findChild(_this7, '.page__background') || util.findChild(_this7, 'ons-toolbar');
19549
19550 _this7.insertBefore(content, prevNode && prevNode.nextSibling);
19551 })();
19552 }
19553
19554 if (!util.findChild(this, '.page__background')) {
19555 var background = util.create('.page__background');
19556 this.insertBefore(background, util.findChild(this, '.page__content'));
19557 }
19558
19559 ModifierUtil.initModifier(this, scheme$12);
19560 }
19561 }, {
19562 key: '_elementShouldBeMoved',
19563 value: function _elementShouldBeMoved(el) {
19564 if (el.classList.contains('page__background')) {
19565 return false;
19566 }
19567 var tagName = el.tagName.toLowerCase();
19568 if (tagName === 'ons-fab') {
19569 return !el.hasAttribute('position');
19570 }
19571 var fixedElements = ['ons-toolbar', 'ons-bottom-toolbar', 'ons-modal', 'ons-speed-dial'];
19572 return el.hasAttribute('inline') || fixedElements.indexOf(tagName) === -1;
19573 }
19574 }, {
19575 key: '_show',
19576 value: function _show() {
19577 if (!this._isShown && util.isAttached(this)) {
19578 this._isShown = true;
19579
19580 if (!this._isMuted) {
19581 util.triggerElementEvent(this, 'show');
19582 }
19583
19584 util.propagateAction(this._contentElement, '_show');
19585 }
19586 }
19587 }, {
19588 key: '_hide',
19589 value: function _hide() {
19590 if (this._isShown) {
19591 this._isShown = false;
19592
19593 if (!this._isMuted) {
19594 util.triggerElementEvent(this, 'hide');
19595 }
19596
19597 util.propagateAction(this._contentElement, '_hide');
19598 }
19599 }
19600 }, {
19601 key: '_destroy',
19602 value: function _destroy() {
19603 this._hide();
19604
19605 if (!this._isMuted) {
19606 util.triggerElementEvent(this, 'destroy');
19607 }
19608
19609 if (this.onDeviceBackButton) {
19610 this.onDeviceBackButton.destroy();
19611 }
19612
19613 util.propagateAction(this._contentElement, '_destroy');
19614
19615 if (this.unload instanceof Function) {
19616 this.unload();
19617 }
19618
19619 this.remove();
19620 }
19621
19622 /**
19623 * @property data
19624 * @type {*}
19625 * @description
19626 * [en]User's custom data passed to `pushPage()`-like methods.[/en]
19627 * [ja][/ja]
19628 */
19629
19630 }, {
19631 key: 'name',
19632 set: function set(str) {
19633 this.setAttribute('name', str);
19634 },
19635 get: function get() {
19636 return this.getAttribute('name');
19637 }
19638 }, {
19639 key: 'backButton',
19640 get: function get() {
19641 return this.querySelector('ons-back-button');
19642 }
19643 }, {
19644 key: 'onInfiniteScroll',
19645 set: function set(value) {
19646 if (value === null) {
19647 this._onInfiniteScroll = null;
19648 this._contentElement.removeEventListener('scroll', this._boundOnScroll);
19649 return;
19650 }
19651 if (!(value instanceof Function)) {
19652 throw new Error('onInfiniteScroll must be a function or null');
19653 }
19654 if (!this._onInfiniteScroll) {
19655 this._infiniteScrollLimit = 0.9;
19656 this._boundOnScroll = this._onScroll.bind(this);
19657 this._contentElement.addEventListener('scroll', this._boundOnScroll);
19658 }
19659 this._onInfiniteScroll = value;
19660 },
19661 get: function get() {
19662 return this._onInfiniteScroll;
19663 }
19664 }, {
19665 key: 'onDeviceBackButton',
19666 get: function get() {
19667 return this._backButtonHandler;
19668 },
19669 set: function set(callback) {
19670 if (this._backButtonHandler) {
19671 this._backButtonHandler.destroy();
19672 }
19673
19674 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
19675 }
19676 }], [{
19677 key: 'observedAttributes',
19678 get: function get() {
19679 return ['modifier', '_muted', '_skipinit', 'on-infinite-scroll'];
19680 }
19681 }]);
19682 return PageElement;
19683}(BaseElement);
19684
19685customElements.define('ons-page', PageElement);
19686
19687/*
19688Copyright 2013-2015 ASIAL CORPORATION
19689
19690Licensed under the Apache License, Version 2.0 (the "License");
19691you may not use this file except in compliance with the License.
19692You may obtain a copy of the License at
19693
19694 http://www.apache.org/licenses/LICENSE-2.0
19695
19696Unless required by applicable law or agreed to in writing, software
19697distributed under the License is distributed on an "AS IS" BASIS,
19698WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19699See the License for the specific language governing permissions and
19700limitations under the License.
19701
19702*/
19703var PopoverAnimator = function () {
19704
19705 /**
19706 * @param {Object} options
19707 * @param {String} options.timing
19708 * @param {Number} options.duration
19709 * @param {Number} options.delay
19710 */
19711 function PopoverAnimator() {
19712 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19713 classCallCheck(this, PopoverAnimator);
19714
19715 this.options = util.extend({
19716 timing: 'cubic-bezier(.1, .7, .4, 1)',
19717 duration: 0.2,
19718 delay: 0
19719 }, options);
19720 }
19721
19722 createClass(PopoverAnimator, [{
19723 key: 'show',
19724 value: function show(popover, callback) {
19725 callback();
19726 }
19727 }, {
19728 key: 'hide',
19729 value: function hide(popover, callback) {
19730 callback();
19731 }
19732 }, {
19733 key: '_animate',
19734 value: function _animate(element, _ref) {
19735 var from = _ref.from,
19736 to = _ref.to,
19737 options = _ref.options,
19738 callback = _ref.callback,
19739 _ref$restore = _ref.restore,
19740 restore = _ref$restore === undefined ? false : _ref$restore,
19741 animation = _ref.animation;
19742
19743 options = util.extend({}, this.options, options);
19744
19745 if (animation) {
19746 from = animation.from;
19747 to = animation.to;
19748 }
19749
19750 animation = animit(element);
19751 if (restore) {
19752 animation = animation.saveStyle();
19753 }
19754 animation = animation.queue(from).wait(options.delay).queue({
19755 css: to,
19756 duration: options.duration,
19757 timing: options.timing
19758 });
19759 if (restore) {
19760 animation = animation.restoreStyle();
19761 }
19762 if (callback) {
19763 animation = animation.queue(function (done) {
19764 callback();
19765 done();
19766 });
19767 }
19768 return animation;
19769 }
19770 }, {
19771 key: '_animateAll',
19772 value: function _animateAll(element, animations) {
19773 var _this = this;
19774
19775 Object.keys(animations).forEach(function (key) {
19776 return _this._animate(element[key], animations[key]).play();
19777 });
19778 }
19779 }]);
19780 return PopoverAnimator;
19781}();
19782
19783var fade$1 = {
19784 out: {
19785 from: { opacity: 1.0 },
19786 to: { opacity: 0 }
19787 },
19788 in: {
19789 from: { opacity: 0 },
19790 to: { opacity: 1.0 }
19791 }
19792};
19793
19794var MDFadePopoverAnimator = function (_PopoverAnimator) {
19795 inherits(MDFadePopoverAnimator, _PopoverAnimator);
19796
19797 function MDFadePopoverAnimator() {
19798 classCallCheck(this, MDFadePopoverAnimator);
19799 return possibleConstructorReturn(this, (MDFadePopoverAnimator.__proto__ || Object.getPrototypeOf(MDFadePopoverAnimator)).apply(this, arguments));
19800 }
19801
19802 createClass(MDFadePopoverAnimator, [{
19803 key: 'show',
19804 value: function show(popover, callback) {
19805 this._animateAll(popover, {
19806 _mask: fade$1.in,
19807 _popover: { animation: fade$1.in, restore: true, callback: callback }
19808 });
19809 }
19810 }, {
19811 key: 'hide',
19812 value: function hide(popover, callback) {
19813 this._animateAll(popover, {
19814 _mask: fade$1.out,
19815 _popover: { animation: fade$1.out, restore: true, callback: callback }
19816 });
19817 }
19818 }]);
19819 return MDFadePopoverAnimator;
19820}(PopoverAnimator);
19821
19822var IOSFadePopoverAnimator = function (_MDFadePopoverAnimato) {
19823 inherits(IOSFadePopoverAnimator, _MDFadePopoverAnimato);
19824
19825 function IOSFadePopoverAnimator() {
19826 classCallCheck(this, IOSFadePopoverAnimator);
19827 return possibleConstructorReturn(this, (IOSFadePopoverAnimator.__proto__ || Object.getPrototypeOf(IOSFadePopoverAnimator)).apply(this, arguments));
19828 }
19829
19830 createClass(IOSFadePopoverAnimator, [{
19831 key: 'show',
19832 value: function show(popover, callback) {
19833 this._animateAll(popover, {
19834 _mask: fade$1.in,
19835 _popover: {
19836 from: {
19837 transform: 'scale3d(1.3, 1.3, 1.0)',
19838 opacity: 0
19839 },
19840 to: {
19841 transform: 'scale3d(1.0, 1.0, 1.0)',
19842 opacity: 1.0
19843 },
19844 restore: true,
19845 callback: callback
19846 }
19847 });
19848 }
19849 }]);
19850 return IOSFadePopoverAnimator;
19851}(MDFadePopoverAnimator);
19852
19853/*
19854Copyright 2013-2015 ASIAL CORPORATION
19855
19856Licensed under the Apache License, Version 2.0 (the "License");
19857you may not use this file except in compliance with the License.
19858You may obtain a copy of the License at
19859
19860 http://www.apache.org/licenses/LICENSE-2.0
19861
19862Unless required by applicable law or agreed to in writing, software
19863distributed under the License is distributed on an "AS IS" BASIS,
19864WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19865See the License for the specific language governing permissions and
19866limitations under the License.
19867
19868*/
19869
19870var scheme$14 = {
19871 '.popover': 'popover--*',
19872 '.popover-mask': 'popover-mask--*',
19873 '.popover__container': 'popover__container--*',
19874 '.popover__content': 'popover__content--*',
19875 '.popover__arrow': 'popover__arrow--*'
19876};
19877
19878var _animatorDict$4 = {
19879 'default': function _default() {
19880 return platform.isAndroid() ? MDFadePopoverAnimator : IOSFadePopoverAnimator;
19881 },
19882 'none': PopoverAnimator,
19883 'fade-ios': IOSFadePopoverAnimator,
19884 'fade-md': MDFadePopoverAnimator
19885};
19886
19887var templateSource = util.createFragment('\n <div class="popover-mask"></div>\n <div class="popover__container">\n <div class="popover__content"></div>\n <div class="popover__arrow"></div>\n </div>\n');
19888
19889var positions = {
19890 up: 'bottom',
19891 left: 'right',
19892 down: 'top',
19893 right: 'left'
19894};
19895
19896/**
19897 * @element ons-popover
19898 * @category dialog
19899 * @description
19900 * [en]
19901 * A component that displays a popover next to an element. The popover can be used to display extra information about a component or a tooltip.
19902 *
19903 * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createPopover(template)` utility function and the `<ons-template>` tag.
19904 *
19905 * Another common way to use the popover is to display a menu when a button on the screen is tapped. For Material Design, popover looks exactly as a dropdown menu.
19906 * [/en]
19907 * [ja]ある要素を対象とするポップオーバーを表示するコンポーネントです。[/ja]
19908 * @codepen ZYYRKo
19909 * @tutorial vanilla/Reference/popover
19910 * @guide dialogs
19911 * [en]Dialog components[/en]
19912 * [ja]Dialog components[/ja]
19913 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
19914 * @example
19915 * <ons-button onclick="showPopover(this)">
19916 * Click me!
19917 * </ons-button>
19918 *
19919 * <ons-popover direction="down" id="popover">
19920 * <p>This is a popover!</p>
19921 * </ons-popover>
19922 *
19923 * <script>
19924 * var showPopover = function(element) {
19925 * var popover = document.getElementById('popover');
19926 * popover.show(element);
19927 * };
19928 * </script>
19929 */
19930
19931var PopoverElement = function (_BaseElement) {
19932 inherits(PopoverElement, _BaseElement);
19933
19934 function PopoverElement() {
19935 classCallCheck(this, PopoverElement);
19936 return possibleConstructorReturn(this, (PopoverElement.__proto__ || Object.getPrototypeOf(PopoverElement)).apply(this, arguments));
19937 }
19938
19939 createClass(PopoverElement, [{
19940 key: 'init',
19941 value: function init() {
19942 var _this2 = this;
19943
19944 contentReady(this, function () {
19945 _this2._compile();
19946 _this2._initAnimatorFactory();
19947 });
19948
19949 this._doorLock = new DoorLock();
19950 this._boundOnChange = this._onChange.bind(this);
19951 this._boundCancel = this._cancel.bind(this);
19952 }
19953 }, {
19954 key: '_initAnimatorFactory',
19955 value: function _initAnimatorFactory() {
19956 var factory = new AnimatorFactory({
19957 animators: _animatorDict$4,
19958 baseClass: PopoverAnimator,
19959 baseClassName: 'PopoverAnimator',
19960 defaultAnimation: this.getAttribute('animation') || 'default'
19961 });
19962 this._animator = function (options) {
19963 return factory.newAnimator(options);
19964 };
19965 }
19966 }, {
19967 key: '_positionPopover',
19968 value: function _positionPopover(target) {
19969 var radius = this._radius,
19970 el = this._content,
19971 margin = this._margin;
19972
19973 var pos = target.getBoundingClientRect();
19974 var isMD = util.hasModifier(this, 'material');
19975 var cover = isMD && this.hasAttribute('cover-target');
19976
19977 var distance = {
19978 top: pos.top - margin,
19979 left: pos.left - margin,
19980 right: window.innerWidth - pos.right - margin,
19981 bottom: window.innerHeight - pos.bottom - margin
19982 };
19983
19984 var _calculateDirections2 = this._calculateDirections(distance),
19985 vertical = _calculateDirections2.vertical,
19986 primary = _calculateDirections2.primary,
19987 secondary = _calculateDirections2.secondary;
19988
19989 this._popover.classList.add('popover--' + primary);
19990
19991 var offset = cover ? 0 : (vertical ? pos.height : pos.width) + (isMD ? 0 : 14);
19992 this.style[primary] = Math.max(0, distance[primary] + offset) + margin + 'px';
19993 el.style[primary] = 0;
19994
19995 var l = vertical ? 'width' : 'height';
19996 var sizes = function (style) {
19997 return {
19998 width: parseInt(style.getPropertyValue('width')),
19999 height: parseInt(style.getPropertyValue('height'))
20000 };
20001 }(window.getComputedStyle(el));
20002
20003 el.style[secondary] = Math.max(0, distance[secondary] - (sizes[l] - pos[l]) / 2) + 'px';
20004 this._arrow.style[secondary] = Math.max(radius, distance[secondary] + pos[l] / 2) + 'px';
20005
20006 this._setTransformOrigin(distance, sizes, pos, primary);
20007
20008 // Prevent animit from restoring the style.
20009 el.removeAttribute('data-animit-orig-style');
20010 }
20011 }, {
20012 key: '_setTransformOrigin',
20013 value: function _setTransformOrigin(distance, sizes, pos, primary) {
20014 var calc = function calc(a, o, l) {
20015 return primary === a ? sizes[l] / 2 : distance[a] + (primary === o ? -sizes[l] : sizes[l] - pos[l]) / 2;
20016 };
20017 var x = calc('left', 'right', 'width') + 'px',
20018 y = calc('top', 'bottom', 'height') + 'px';
20019
20020 util.extend(this._popover.style, {
20021 transformOrigin: x + ' ' + y,
20022 webkitTransformOriginX: x,
20023 webkitTransformOriginY: y
20024 });
20025 }
20026 }, {
20027 key: '_calculateDirections',
20028 value: function _calculateDirections(distance) {
20029 var options = (this.getAttribute('direction') || 'up down left right').split(/\s+/).map(function (e) {
20030 return positions[e];
20031 });
20032 var primary = options.sort(function (a, b) {
20033 return distance[a] - distance[b];
20034 })[0];
20035 var vertical = ['top', 'bottom'].indexOf(primary) !== -1;
20036 var secondary = void 0;
20037
20038 if (vertical) {
20039 secondary = distance.left < distance.right ? 'left' : 'right';
20040 } else {
20041 secondary = distance.top < distance.bottom ? 'top' : 'bottom';
20042 }
20043
20044 return { vertical: vertical, primary: primary, secondary: secondary };
20045 }
20046 }, {
20047 key: '_clearStyles',
20048 value: function _clearStyles() {
20049 var _this3 = this;
20050
20051 ['top', 'bottom', 'left', 'right'].forEach(function (e) {
20052 _this3._arrow.style[e] = _this3._content.style[e] = _this3.style[e] = '';
20053 _this3._popover.classList.remove('popover--' + e);
20054 });
20055 }
20056 }, {
20057 key: '_onChange',
20058 value: function _onChange() {
20059 var _this4 = this;
20060
20061 setImmediate(function () {
20062 if (_this4._currentTarget) {
20063 _this4._positionPopover(_this4._currentTarget);
20064 }
20065 });
20066 }
20067 }, {
20068 key: '_compile',
20069 value: function _compile() {
20070 autoStyle.prepare(this);
20071
20072 if (this.classList.contains('popover')) {
20073 return;
20074 }
20075
20076 this.classList.add('popover');
20077
20078 var hasDefaultContainer = this._popover && this._content;
20079
20080 if (hasDefaultContainer) {
20081
20082 if (!this._mask) {
20083 var mask = document.createElement('div');
20084 mask.classList.add('popover-mask');
20085 this.insertBefore(mask, this.firstChild);
20086 }
20087
20088 if (!this._arrow) {
20089 var arrow = document.createElement('div');
20090 arrow.classList.add('popover__arrow');
20091 this._popover.appendChild(arrow);
20092 }
20093 } else {
20094
20095 var template = templateSource.cloneNode(true);
20096 var content = template.querySelector('.popover__content');
20097
20098 while (this.childNodes[0]) {
20099 content.appendChild(this.childNodes[0]);
20100 }
20101
20102 this.appendChild(template);
20103 }
20104
20105 if (this.hasAttribute('style')) {
20106 this._popover.setAttribute('style', this.getAttribute('style'));
20107 this.removeAttribute('style');
20108 }
20109
20110 if (this.hasAttribute('mask-color')) {
20111 this._mask.style.backgroundColor = this.getAttribute('mask-color');
20112 }
20113
20114 ModifierUtil.initModifier(this, scheme$14);
20115 }
20116 }, {
20117 key: '_prepareAnimationOptions',
20118 value: function _prepareAnimationOptions(options) {
20119 if (options.animation && !(options.animation in _animatorDict$4)) {
20120 throw new Error('Animator ' + options.animation + ' is not registered.');
20121 }
20122
20123 options.animationOptions = util.extend(AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')), options.animationOptions || {});
20124 }
20125 }, {
20126 key: '_executeAction',
20127 value: function _executeAction(actions) {
20128 var _this5 = this;
20129
20130 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
20131
20132 var callback = options.callback;
20133 var action = actions.action,
20134 before = actions.before,
20135 after = actions.after;
20136
20137
20138 this._prepareAnimationOptions(options);
20139
20140 var canceled = false;
20141 util.triggerElementEvent(this, 'pre' + action, { // synchronous
20142 popover: this,
20143 cancel: function cancel() {
20144 return canceled = true;
20145 }
20146 });
20147
20148 if (canceled) {
20149 return Promise.reject('Canceled in pre' + action + ' event.');
20150 }
20151
20152 return new Promise(function (resolve) {
20153 _this5._doorLock.waitUnlock(function () {
20154 var unlock = _this5._doorLock.lock();
20155
20156 before && before();
20157
20158 contentReady(_this5, function () {
20159 _this5._animator(options)[action](_this5, function () {
20160 after && after();
20161
20162 unlock();
20163
20164 util.triggerElementEvent(_this5, 'post' + action, { popover: _this5 });
20165
20166 callback && callback();
20167 resolve(_this5);
20168 });
20169 });
20170 });
20171 });
20172 }
20173
20174 /**
20175 * @method show
20176 * @signature show(target, [options])
20177 * @param {String|Event|HTMLElement} target
20178 * [en]Target element. Can be either a CSS selector, an event object or a DOM element.[/en]
20179 * [ja]ポップオーバーのターゲットとなる要素を指定します。CSSセレクタかeventオブジェクトかDOM要素のいずれかを渡せます。[/ja]
20180 * @param {Object} [options]
20181 * [en]Parameter object.[/en]
20182 * [ja]オプションを指定するオブジェクト。[/ja]
20183 * @param {String} [options.animation]
20184 * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en]
20185 * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja]
20186 * @param {String} [options.animationOptions]
20187 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
20188 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
20189 * @param {Function} [options.callback]
20190 * [en]This function is called after the popover has been revealed.[/en]
20191 * [ja]ポップオーバーが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja]
20192 * @description
20193 * [en]Open the popover and point it at a target. The target can be either an event, a CSS selector or a DOM element..[/en]
20194 * [ja]対象とする要素にポップオーバーを表示します。target引数には、$eventオブジェクトやDOMエレメントやCSSセレクタを渡すことが出来ます。[/ja]
20195 * @return {Promise}
20196 * [en]Resolves to the displayed element[/en]
20197 * [ja][/ja]
20198 */
20199
20200 }, {
20201 key: 'show',
20202 value: function show(target) {
20203 var _this6 = this;
20204
20205 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
20206
20207 if (typeof target === 'string') {
20208 target = document.querySelector(target);
20209 } else if (target instanceof Event) {
20210 target = target.target;
20211 }
20212
20213 if (typeof target === 'undefined') {
20214 throw new Error('A target argument must be defined for the popover.');
20215 }
20216
20217 if (!(target instanceof HTMLElement)) {
20218 throw new Error('Invalid target');
20219 }
20220
20221 return this._executeAction({
20222 action: 'show',
20223 before: function before() {
20224 _this6.style.display = 'block';
20225 _this6._currentTarget = target;
20226 _this6._positionPopover(target);
20227 }
20228 }, options);
20229 }
20230
20231 /**
20232 * @method hide
20233 * @signature hide([options])
20234 * @param {Object} [options]
20235 * [en]Parameter object.[/en]
20236 * [ja]オプションを指定するオブジェクト。[/ja]
20237 * @param {String} [options.animation]
20238 * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en]
20239 * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja]
20240 * @param {String} [options.animationOptions]
20241 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
20242 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
20243 * @param {Function} [options.callback]
20244 * [en]This functions is called after the popover has been hidden.[/en]
20245 * [ja]ポップオーバーが隠れた後に呼び出される関数オブジェクトを指定します。[/ja]
20246 * @description
20247 * [en]Close the popover.[/en]
20248 * [ja]ポップオーバーを閉じます。[/ja]
20249 * @return {Promise}
20250 * [en]Resolves to the hidden element[/en]
20251 * [ja][/ja]
20252 */
20253
20254 }, {
20255 key: 'hide',
20256 value: function hide() {
20257 var _this7 = this;
20258
20259 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
20260
20261 return this._executeAction({
20262 action: 'hide',
20263 after: function after() {
20264 _this7.style.display = 'none';
20265 _this7._clearStyles();
20266 }
20267 }, options);
20268 }
20269
20270 /**
20271 * @property visible
20272 * @readonly
20273 * @type {Boolean}
20274 * @description
20275 * [en]Whether the element is visible or not.[/en]
20276 * [ja]要素が見える場合に`true`。[/ja]
20277 */
20278
20279 }, {
20280 key: '_resetBackButtonHandler',
20281 value: function _resetBackButtonHandler() {
20282 var _this8 = this;
20283
20284 // do we need this twice?
20285 this.onDeviceBackButton = function (e) {
20286 return _this8.cancelable ? _this8._cancel() : e.callParentHandler();
20287 };
20288 }
20289 }, {
20290 key: 'connectedCallback',
20291 value: function connectedCallback() {
20292 var _this9 = this;
20293
20294 this._resetBackButtonHandler();
20295
20296 contentReady(this, function () {
20297 _this9._margin = _this9._margin || parseInt(window.getComputedStyle(_this9).getPropertyValue('top'));
20298
20299 // Fix for iframes
20300 if (!_this9._margin) {
20301 _this9._margin = 6;
20302 }
20303
20304 _this9._radius = parseInt(window.getComputedStyle(_this9._content).getPropertyValue('border-top-left-radius'));
20305
20306 _this9._mask.addEventListener('click', _this9._boundCancel, false);
20307
20308 _this9._resetBackButtonHandler();
20309
20310 window.addEventListener('resize', _this9._boundOnChange, false);
20311 });
20312 }
20313 }, {
20314 key: 'disconnectedCallback',
20315 value: function disconnectedCallback() {
20316 var _this10 = this;
20317
20318 contentReady(this, function () {
20319 _this10._mask.removeEventListener('click', _this10._boundCancel, false);
20320
20321 _this10._backButtonHandler.destroy();
20322 _this10._backButtonHandler = null;
20323
20324 window.removeEventListener('resize', _this10._boundOnChange, false);
20325 });
20326 }
20327 }, {
20328 key: 'attributeChangedCallback',
20329 value: function attributeChangedCallback(name, last, current) {
20330 if (name === 'modifier') {
20331 return ModifierUtil.onModifierChanged(last, current, this, scheme$14);
20332 }
20333 if (name === 'direction') {
20334 return this._boundOnChange();
20335 }
20336 if (name === 'animation') {
20337 this._initAnimatorFactory();
20338 }
20339 }
20340 }, {
20341 key: '_cancel',
20342 value: function _cancel() {
20343 var _this11 = this;
20344
20345 if (this.cancelable) {
20346 this.hide({
20347 callback: function callback() {
20348 util.triggerElementEvent(_this11, 'dialog-cancel');
20349 }
20350 });
20351 }
20352 }
20353
20354 /**
20355 * @param {String} name
20356 * @param {PopoverAnimator} Animator
20357 */
20358
20359 }, {
20360 key: '_mask',
20361
20362
20363 /**
20364 * @event preshow
20365 * @description
20366 * [en]Fired just before the popover is displayed.[/en]
20367 * [ja]ポップオーバーが表示される直前に発火します。[/ja]
20368 * @param {Object} event [en]Event object.[/en]
20369 * @param {Object} event.popover
20370 * [en]Component object.[/en]
20371 * [ja]コンポーネントのオブジェクト。[/ja]
20372 * @param {Function} event.cancel
20373 * [en]Call this function to stop the popover from being shown.[/en]
20374 * [ja]この関数を呼び出すと、ポップオーバーの表示がキャンセルされます。[/ja]
20375 */
20376
20377 /**
20378 * @event postshow
20379 * @description
20380 * [en]Fired just after the popover is displayed.[/en]
20381 * [ja]ポップオーバーが表示された直後に発火します。[/ja]
20382 * @param {Object} event [en]Event object.[/en]
20383 * @param {Object} event.popover
20384 * [en]Component object.[/en]
20385 * [ja]コンポーネントのオブジェクト。[/ja]
20386 */
20387
20388 /**
20389 * @event prehide
20390 * @description
20391 * [en]Fired just before the popover is hidden.[/en]
20392 * [ja]ポップオーバーが隠れる直前に発火します。[/ja]
20393 * @param {Object} event [en]Event object.[/en]
20394 * @param {Object} event.popover
20395 * [en]Component object.[/en]
20396 * [ja]コンポーネントのオブジェクト。[/ja]
20397 * @param {Function} event.cancel
20398 * [en]Call this function to stop the popover from being hidden.[/en]
20399 * [ja]この関数を呼び出すと、ポップオーバーが隠れる処理をキャンセルします。[/ja]
20400 */
20401
20402 /**
20403 * @event posthide
20404 * @description
20405 * [en]Fired just after the popover is hidden.[/en]
20406 * [ja]ポップオーバーが隠れた後に発火します。[/ja]
20407 * @param {Object} event [en]Event object.[/en]
20408 * @param {Object} event.popover
20409 * [en]Component object.[/en]
20410 * [ja]コンポーネントのオブジェクト。[/ja]
20411 */
20412
20413 /**
20414 * @attribute modifier
20415 * @type {String}
20416 * @description
20417 * [en]The appearance of the popover.[/en]
20418 * [ja]ポップオーバーの表現を指定します。[/ja]
20419 */
20420
20421 /**
20422 * @attribute direction
20423 * @type {String}
20424 * @description
20425 * [en]
20426 * A space separated list of directions. If more than one direction is specified,
20427 * it will be chosen automatically. Valid directions are `"up"`, `"down"`, `"left"` and `"right"`.
20428 * [/en]
20429 * [ja]
20430 * ポップオーバーを表示する方向を空白区切りで複数指定できます。
20431 * 指定できる方向は、"up", "down", "left", "right"の4つです。空白区切りで複数指定することもできます。
20432 * 複数指定された場合、対象とする要素に合わせて指定した値から自動的に選択されます。
20433 * [/ja]
20434 */
20435
20436 /**
20437 * @attribute cancelable
20438 * @description
20439 * [en]If this attribute is set the popover can be closed by tapping the background or by pressing the back button.[/en]
20440 * [ja]この属性があると、ポップオーバーが表示された時に、背景やバックボタンをタップした時にをポップオーバー閉じます。[/ja]
20441 */
20442
20443 /**
20444 * @attribute cover-target
20445 * @description
20446 * [en]If set the popover will cover the target on the screen.[/en]
20447 * [ja][/ja]
20448 */
20449
20450 /**
20451 * @attribute animation
20452 * @type {String}
20453 * @description
20454 * [en]The animation used when showing an hiding the popover. Can be either `"none"`, `"default"`, `"fade-ios"` or `"fade-md"`.[/en]
20455 * [ja]ポップオーバーを表示する際のアニメーション名を指定します。[/ja]
20456 */
20457
20458 /**
20459 * @attribute animation-options
20460 * @type {Expression}
20461 * @description
20462 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
20463 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
20464 */
20465
20466 /**
20467 * @attribute mask-color
20468 * @type {Color}
20469 * @description
20470 * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en]
20471 * [ja]背景のマスクの色を指定します。デフォルトは"rgba(0, 0, 0, 0.2)"です。[/ja]
20472 */
20473
20474 get: function get() {
20475 return util.findChild(this, '.popover-mask');
20476 }
20477 }, {
20478 key: '_popover',
20479 get: function get() {
20480 return util.findChild(this, '.popover__container');
20481 }
20482 }, {
20483 key: '_content',
20484 get: function get() {
20485 return util.findChild(this._popover, '.popover__content');
20486 }
20487 }, {
20488 key: '_arrow',
20489 get: function get() {
20490 return util.findChild(this._popover, '.popover__arrow');
20491 }
20492 }, {
20493 key: 'visible',
20494 get: function get() {
20495 return window.getComputedStyle(this).getPropertyValue('display') !== 'none';
20496 }
20497
20498 /**
20499 * @property cancelable
20500 * @type {Boolean}
20501 * @description
20502 * [en]
20503 * A boolean value that specifies whether the popover is cancelable or not.
20504 *
20505 * When the popover is cancelable it can be closed by tapping the background or by pressing the back button on Android devices.
20506 * [/en]
20507 * [ja][/ja]
20508 */
20509
20510 }, {
20511 key: 'cancelable',
20512 set: function set(value) {
20513 return util.toggleAttribute(this, 'cancelable', value);
20514 },
20515 get: function get() {
20516 return this.hasAttribute('cancelable');
20517 }
20518
20519 /**
20520 * @property onDeviceBackButton
20521 * @type {Object}
20522 * @description
20523 * [en]Back-button handler.[/en]
20524 * [ja]バックボタンハンドラ。[/ja]
20525 */
20526
20527 }, {
20528 key: 'onDeviceBackButton',
20529 get: function get() {
20530 return this._backButtonHandler;
20531 },
20532 set: function set(callback) {
20533 if (this._backButtonHandler) {
20534 this._backButtonHandler.destroy();
20535 }
20536
20537 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
20538 }
20539 }], [{
20540 key: 'registerAnimator',
20541 value: function registerAnimator(name, Animator) {
20542 if (!(Animator.prototype instanceof PopoverAnimator)) {
20543 throw new Error('"Animator" param must inherit PopoverAnimator');
20544 }
20545 _animatorDict$4[name] = Animator;
20546 }
20547 }, {
20548 key: 'observedAttributes',
20549 get: function get() {
20550 return ['modifier', 'direction', 'animation'];
20551 }
20552 }, {
20553 key: 'PopoverAnimator',
20554 get: function get() {
20555 return PopoverAnimator;
20556 }
20557 }]);
20558 return PopoverElement;
20559}(BaseElement);
20560
20561customElements.define('ons-popover', PopoverElement);
20562
20563/*
20564Copyright 2013-2015 ASIAL CORPORATION
20565
20566Licensed under the Apache License, Version 2.0 (the "License");
20567you may not use this file except in compliance with the License.
20568You may obtain a copy of the License at
20569
20570 http://www.apache.org/licenses/LICENSE-2.0
20571
20572Unless required by applicable law or agreed to in writing, software
20573distributed under the License is distributed on an "AS IS" BASIS,
20574WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20575See the License for the specific language governing permissions and
20576limitations under the License.
20577
20578*/
20579
20580var scheme$15 = {
20581 '.progress-bar': 'progress-bar--*',
20582 '.progress-bar__primary': 'progress-bar__primary--*',
20583 '.progress-bar__secondary': 'progress-bar__secondary--*'
20584};
20585
20586var template = util.createElement('\n <div class="progress-bar">\n <div class="progress-bar__secondary"></div>\n <div class="progress-bar__primary"></div>\n </div>\n');
20587
20588/**
20589 * @element ons-progress-bar
20590 * @category visual
20591 * @description
20592 * [en]
20593 * The component is used to display a linear progress bar. It can either display a progress bar that shows the user how much of a task has been completed. In the case where the percentage is not known it can be used to display an animated progress bar so the user can see that an operation is in progress.
20594 * [/en]
20595 * [ja][/ja]
20596 * @codepen zvQbGj
20597 * @tutorial vanilla/Reference/progress
20598 * @seealso ons-progress-circular
20599 * [en]The `<ons-progress-circular>` component displays a circular progress indicator.[/en]
20600 * [ja][/ja]
20601 * @example
20602 * <ons-progress-bar
20603 * value="55"
20604 * secondary-value="87">
20605 * </ons-progress-bar>
20606 *
20607 * <ons-progress-bar
20608 * indeterminate>
20609 * </ons-progress-bar>
20610 */
20611
20612var ProgressBarElement = function (_BaseElement) {
20613 inherits(ProgressBarElement, _BaseElement);
20614
20615 function ProgressBarElement() {
20616 classCallCheck(this, ProgressBarElement);
20617 return possibleConstructorReturn(this, (ProgressBarElement.__proto__ || Object.getPrototypeOf(ProgressBarElement)).apply(this, arguments));
20618 }
20619
20620 createClass(ProgressBarElement, [{
20621 key: 'init',
20622
20623
20624 /**
20625 * @attribute modifier
20626 * @type {String}
20627 * @description
20628 * [en]Change the appearance of the progress indicator.[/en]
20629 * [ja]プログレスインジケータの見た目を変更します。[/ja]
20630 */
20631
20632 /**
20633 * @attribute value
20634 * @type {Number}
20635 * @description
20636 * [en]Current progress. Should be a value between 0 and 100.[/en]
20637 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20638 */
20639
20640 /**
20641 * @attribute secondary-value
20642 * @type {Number}
20643 * @description
20644 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
20645 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20646 */
20647
20648 /**
20649 * @attribute indeterminate
20650 * @description
20651 * [en]If this attribute is set, an infinite looping animation will be shown.[/en]
20652 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
20653 */
20654
20655 value: function init() {
20656 var _this2 = this;
20657
20658 contentReady(this, function () {
20659 return _this2._compile();
20660 });
20661 }
20662 }, {
20663 key: '_compile',
20664 value: function _compile() {
20665 if (!this._isCompiled()) {
20666 this._template = template.cloneNode(true);
20667 } else {
20668 this._template = util.findChild(this, '.progress-bar');
20669 }
20670
20671 this._primary = util.findChild(this._template, '.progress-bar__primary');
20672 this._secondary = util.findChild(this._template, '.progress-bar__secondary');
20673
20674 this._updateDeterminate();
20675 this._updateValue();
20676
20677 this.appendChild(this._template);
20678
20679 ModifierUtil.initModifier(this, scheme$15);
20680 }
20681 }, {
20682 key: '_isCompiled',
20683 value: function _isCompiled() {
20684 if (!util.findChild(this, '.progress-bar')) {
20685 return false;
20686 }
20687
20688 var barElement = util.findChild(this, '.progress-bar');
20689
20690 if (!util.findChild(barElement, '.progress-bar__secondary')) {
20691 return false;
20692 }
20693
20694 if (!util.findChild(barElement, '.progress-bar__primary')) {
20695 return false;
20696 }
20697
20698 return true;
20699 }
20700 }, {
20701 key: 'attributeChangedCallback',
20702 value: function attributeChangedCallback(name, last, current) {
20703 if (name === 'modifier') {
20704 return ModifierUtil.onModifierChanged(last, current, this, scheme$15);
20705 } else if (name === 'value' || name === 'secondary-value') {
20706 this._updateValue();
20707 } else if (name === 'indeterminate') {
20708 this._updateDeterminate();
20709 }
20710 }
20711 }, {
20712 key: '_updateDeterminate',
20713 value: function _updateDeterminate() {
20714 var _this3 = this;
20715
20716 if (this.hasAttribute('indeterminate')) {
20717 contentReady(this, function () {
20718 _this3._template.classList.add('progress-bar--indeterminate');
20719 _this3._template.classList.remove('progress-bar--determinate');
20720 });
20721 } else {
20722 contentReady(this, function () {
20723 _this3._template.classList.add('progress-bar--determinate');
20724 _this3._template.classList.remove('progress-bar--indeterminate');
20725 });
20726 }
20727 }
20728 }, {
20729 key: '_updateValue',
20730 value: function _updateValue() {
20731 var _this4 = this;
20732
20733 contentReady(this, function () {
20734 _this4._primary.style.width = _this4.hasAttribute('value') ? _this4.getAttribute('value') + '%' : '0%';
20735 _this4._secondary.style.width = _this4.hasAttribute('secondary-value') ? _this4.getAttribute('secondary-value') + '%' : '0%';
20736 });
20737 }
20738
20739 /**
20740 * @property value
20741 * @type {Number}
20742 * @description
20743 * [en]Current progress. Should be a value between 0 and 100.[/en]
20744 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20745 */
20746
20747 }, {
20748 key: 'value',
20749 set: function set(value) {
20750 if (typeof value !== 'number' || value < 0 || value > 100) {
20751 throw new Error('Invalid value');
20752 }
20753
20754 this.setAttribute('value', Math.floor(value));
20755 },
20756 get: function get() {
20757 return parseInt(this.getAttribute('value') || '0');
20758 }
20759
20760 /**
20761 * @property secondaryValue
20762 * @type {Number}
20763 * @description
20764 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
20765 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20766 */
20767
20768 }, {
20769 key: 'secondaryValue',
20770 set: function set(value) {
20771 if (typeof value !== 'number' || value < 0 || value > 100) {
20772 throw new Error('Invalid value');
20773 }
20774
20775 this.setAttribute('secondary-value', Math.floor(value));
20776 },
20777 get: function get() {
20778 return parseInt(this.getAttribute('secondary-value') || '0');
20779 }
20780
20781 /**
20782 * @property indeterminate
20783 * @type {Boolean}
20784 * @description
20785 * [en]If this property is `true`, an infinite looping animation will be shown.[/en]
20786 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
20787 */
20788
20789 }, {
20790 key: 'indeterminate',
20791 set: function set(value) {
20792 if (value) {
20793 this.setAttribute('indeterminate', '');
20794 } else {
20795 this.removeAttribute('indeterminate');
20796 }
20797 },
20798 get: function get() {
20799 return this.hasAttribute('indeterminate');
20800 }
20801 }], [{
20802 key: 'observedAttributes',
20803 get: function get() {
20804 return ['modifier', 'value', 'secondary-value', 'indeterminate'];
20805 }
20806 }]);
20807 return ProgressBarElement;
20808}(BaseElement);
20809
20810customElements.define('ons-progress-bar', ProgressBarElement);
20811
20812/*
20813Copyright 2013-2015 ASIAL CORPORATION
20814
20815Licensed under the Apache License, Version 2.0 (the "License");
20816you may not use this file except in compliance with the License.
20817You may obtain a copy of the License at
20818
20819 http://www.apache.org/licenses/LICENSE-2.0
20820
20821Unless required by applicable law or agreed to in writing, software
20822distributed under the License is distributed on an "AS IS" BASIS,
20823WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20824See the License for the specific language governing permissions and
20825limitations under the License.
20826
20827*/
20828
20829var scheme$16 = {
20830 '.progress-circular': 'progress-circular--*',
20831 '.progress-circular__primary': 'progress-circular__primary--*',
20832 '.progress-circular__secondary': 'progress-circular__secondary--*'
20833};
20834
20835var template$1 = util.createElement('\n <svg class="progress-circular">\n <circle class="progress-circular__secondary" cx="50%" cy="50%" r="40%" fill="none" stroke-width="10%" stroke-miterlimit="10"/>\n <circle class="progress-circular__primary" cx="50%" cy="50%" r="40%" fill="none" stroke-width="10%" stroke-miterlimit="10"/>\n </svg>\n');
20836
20837/**
20838 * @element ons-progress-circular
20839 * @category visual
20840 * @description
20841 * [en]
20842 * This component displays a circular progress indicator. It can either be used to show how much of a task has been completed or to show a looping animation to indicate that an operation is currently running.
20843 * [/en]
20844 * [ja][/ja]
20845 * @codepen EVzMjR
20846 * @tutorial vanilla/Reference/progress
20847 * @seealso ons-progress-bar
20848 * [en]The `<ons-progress-bar>` component displays a bar progress indicator.[/en]
20849 * [ja][/ja]
20850 * @example
20851 * <ons-progress-circular
20852 * value="55"
20853 * secondary-value="87">
20854 * </ons-progress-circular>
20855 *
20856 * <ons-progress-circular
20857 * indeterminate>
20858 * </ons-progress-circular>
20859 */
20860
20861var ProgressCircularElement = function (_BaseElement) {
20862 inherits(ProgressCircularElement, _BaseElement);
20863
20864 function ProgressCircularElement() {
20865 classCallCheck(this, ProgressCircularElement);
20866 return possibleConstructorReturn(this, (ProgressCircularElement.__proto__ || Object.getPrototypeOf(ProgressCircularElement)).apply(this, arguments));
20867 }
20868
20869 createClass(ProgressCircularElement, [{
20870 key: 'init',
20871
20872
20873 /**
20874 * @attribute modifier
20875 * @type {String}
20876 * @description
20877 * [en]Change the appearance of the progress indicator.[/en]
20878 * [ja]プログレスインジケータの見た目を変更します。[/ja]
20879 */
20880
20881 /**
20882 * @attribute value
20883 * @type {Number}
20884 * @description
20885 * [en]Current progress. Should be a value between 0 and 100.[/en]
20886 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20887 */
20888
20889 /**
20890 * @attribute secondary-value
20891 * @type {Number}
20892 * @description
20893 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
20894 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20895 */
20896
20897 /**
20898 * @attribute indeterminate
20899 * @description
20900 * [en]If this attribute is set, an infinite looping animation will be shown.[/en]
20901 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
20902 */
20903
20904 value: function init() {
20905 var _this2 = this;
20906
20907 contentReady(this, function () {
20908 return _this2._compile();
20909 });
20910 }
20911 }, {
20912 key: 'attributeChangedCallback',
20913 value: function attributeChangedCallback(name, last, current) {
20914 if (name === 'modifier') {
20915 return ModifierUtil.onModifierChanged(last, current, this, scheme$16);
20916 } else if (name === 'value' || name === 'secondary-value') {
20917 this._updateValue();
20918 } else if (name === 'indeterminate') {
20919 this._updateDeterminate();
20920 }
20921 }
20922 }, {
20923 key: '_updateDeterminate',
20924 value: function _updateDeterminate() {
20925 var _this3 = this;
20926
20927 if (this.hasAttribute('indeterminate')) {
20928 contentReady(this, function () {
20929 _this3._template.classList.add('progress-circular--indeterminate');
20930 _this3._template.classList.remove('progress-circular--determinate');
20931 });
20932 } else {
20933 contentReady(this, function () {
20934 _this3._template.classList.add('progress-circular--determinate');
20935 _this3._template.classList.remove('progress-circular--indeterminate');
20936 });
20937 }
20938 }
20939 }, {
20940 key: '_updateValue',
20941 value: function _updateValue() {
20942 var _this4 = this;
20943
20944 if (this.hasAttribute('value')) {
20945 contentReady(this, function () {
20946 var per = Math.ceil(_this4.getAttribute('value') * 251.32 * 0.01);
20947 _this4._primary.style['stroke-dasharray'] = per + '%, 251.32%';
20948 });
20949 }
20950 if (this.hasAttribute('secondary-value')) {
20951 contentReady(this, function () {
20952 var per = Math.ceil(_this4.getAttribute('secondary-value') * 251.32 * 0.01);
20953 _this4._secondary.style['stroke-dasharray'] = per + '%, 251.32%';
20954 });
20955 }
20956 }
20957
20958 /**
20959 * @property value
20960 * @type {Number}
20961 * @description
20962 * [en]Current progress. Should be a value between 0 and 100.[/en]
20963 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
20964 */
20965
20966 }, {
20967 key: '_compile',
20968 value: function _compile() {
20969 if (this._isCompiled()) {
20970 this._template = util.findChild(this, '.progress-circular');
20971 } else {
20972 this._template = template$1.cloneNode(true);
20973 }
20974
20975 this._primary = util.findChild(this._template, '.progress-circular__primary');
20976 this._secondary = util.findChild(this._template, '.progress-circular__secondary');
20977
20978 this._updateDeterminate();
20979 this._updateValue();
20980
20981 this.appendChild(this._template);
20982
20983 ModifierUtil.initModifier(this, scheme$16);
20984 }
20985 }, {
20986 key: '_isCompiled',
20987 value: function _isCompiled() {
20988 if (!util.findChild(this, '.progress-circular')) {
20989 return false;
20990 }
20991
20992 var svg = util.findChild(this, '.progress-circular');
20993
20994 if (!util.findChild(svg, '.progress-circular__secondary')) {
20995 return false;
20996 }
20997
20998 if (!util.findChild(svg, '.progress-circular__primary')) {
20999 return false;
21000 }
21001
21002 return true;
21003 }
21004 }, {
21005 key: 'value',
21006 set: function set(value) {
21007 if (typeof value !== 'number' || value < 0 || value > 100) {
21008 throw new Error('Invalid value');
21009 }
21010
21011 this.setAttribute('value', Math.floor(value));
21012 },
21013 get: function get() {
21014 return parseInt(this.getAttribute('value') || '0');
21015 }
21016
21017 /**
21018 * @property secondaryValue
21019 * @type {Number}
21020 * @description
21021 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
21022 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
21023 */
21024
21025 }, {
21026 key: 'secondaryValue',
21027 set: function set(value) {
21028 if (typeof value !== 'number' || value < 0 || value > 100) {
21029 throw new Error('Invalid value');
21030 }
21031
21032 this.setAttribute('secondary-value', Math.floor(value));
21033 },
21034 get: function get() {
21035 return parseInt(this.getAttribute('secondary-value') || '0');
21036 }
21037
21038 /**
21039 * @property indeterminate
21040 * @type {Boolean}
21041 * @description
21042 * [en]If this property is `true`, an infinite looping animation will be shown.[/en]
21043 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
21044 */
21045
21046 }, {
21047 key: 'indeterminate',
21048 set: function set(value) {
21049 if (value) {
21050 this.setAttribute('indeterminate', '');
21051 } else {
21052 this.removeAttribute('indeterminate');
21053 }
21054 },
21055 get: function get() {
21056 return this.hasAttribute('indeterminate');
21057 }
21058 }], [{
21059 key: 'observedAttributes',
21060 get: function get() {
21061 return ['modifier', 'value', 'secondary-value', 'indeterminate'];
21062 }
21063 }]);
21064 return ProgressCircularElement;
21065}(BaseElement);
21066
21067customElements.define('ons-progress-circular', ProgressCircularElement);
21068
21069/*
21070Copyright 2013-2015 ASIAL CORPORATION
21071
21072Licensed under the Apache License, Version 2.0 (the "License");
21073you may not use this file except in compliance with the License.
21074You may obtain a copy of the License at
21075
21076 http://www.apache.org/licenses/LICENSE-2.0
21077
21078Unless required by applicable law or agreed to in writing, software
21079distributed under the License is distributed on an "AS IS" BASIS,
21080WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21081See the License for the specific language governing permissions and
21082limitations under the License.
21083
21084*/
21085
21086var STATE_INITIAL = 'initial';
21087var STATE_PREACTION = 'preaction';
21088var STATE_ACTION = 'action';
21089
21090var removeTransform = function removeTransform(el) {
21091 el.style.transform = '';
21092 el.style.WebkitTransform = '';
21093 el.style.transition = '';
21094 el.style.WebkitTransition = '';
21095};
21096
21097/**
21098 * @element ons-pull-hook
21099 * @category control
21100 * @description
21101 * [en]
21102 * Component that adds **Pull to refresh** functionality to an `<ons-page>` element.
21103 *
21104 * It can be used to perform a task when the user pulls down at the top of the page. A common usage is to refresh the data displayed in a page.
21105 * [/en]
21106 * [ja][/ja]
21107 * @codepen WbJogM
21108 * @tutorial vanilla/Reference/pull-hook
21109 * @example
21110 * <ons-page>
21111 * <ons-pull-hook>
21112 * Release to refresh
21113 * </ons-pull-hook>
21114 * </ons-page>
21115 *
21116 * <script>
21117 * document.querySelector('ons-pull-hook').onAction = function(done) {
21118 * setTimeout(done, 1000);
21119 * };
21120 * </script>
21121 */
21122
21123var PullHookElement = function (_BaseElement) {
21124 inherits(PullHookElement, _BaseElement);
21125
21126 function PullHookElement() {
21127 classCallCheck(this, PullHookElement);
21128 return possibleConstructorReturn(this, (PullHookElement.__proto__ || Object.getPrototypeOf(PullHookElement)).apply(this, arguments));
21129 }
21130
21131 createClass(PullHookElement, [{
21132 key: 'init',
21133
21134
21135 /**
21136 * @event changestate
21137 * @description
21138 * [en]Fired when the state is changed. The state can be either "initial", "preaction" or "action".[/en]
21139 * [ja]コンポーネントの状態が変わった場合に発火します。状態は、"initial", "preaction", "action"のいずれかです。[/ja]
21140 * @param {Object} event
21141 * [en]Event object.[/en]
21142 * [ja]イベントオブジェクト。[/ja]
21143 * @param {Object} event.pullHook
21144 * [en]Component object.[/en]
21145 * [ja]コンポーネントのオブジェクト。[/ja]
21146 * @param {String} event.state
21147 * [en]Current state.[/en]
21148 * [ja]現在の状態名を参照できます。[/ja]
21149 */
21150
21151 /**
21152 * @attribute disabled
21153 * @description
21154 * [en]If this attribute is set the "pull-to-refresh" functionality is disabled.[/en]
21155 * [ja]この属性がある時、disabled状態になりアクションが実行されなくなります[/ja]
21156 */
21157
21158 /**
21159 * @attribute height
21160 * @type {String}
21161 * @description
21162 * [en]Specify the height of the component. When pulled down further than this value it will switch to the "preaction" state. The default value is "64px".[/en]
21163 * [ja]コンポーネントの高さを指定します。この高さ以上にpull downすると"preaction"状態に移行します。デフォルトの値は"64px"です。[/ja]
21164 */
21165
21166 /**
21167 * @attribute threshold-height
21168 * @type {String}
21169 * @description
21170 * [en]Specify the threshold height. The component automatically switches to the "action" state when pulled further than this value. The default value is "96px". A negative value or a value less than the height will disable this property.[/en]
21171 * [ja]閾値となる高さを指定します。この値で指定した高さよりもpull downすると、このコンポーネントは自動的に"action"状態に移行します。[/ja]
21172 */
21173
21174 /**
21175 * @attribute fixed-content
21176 * @description
21177 * [en]If this attribute is set the content of the page will not move when pulling.[/en]
21178 * [ja]この属性がある時、プルフックが引き出されている時にもコンテンツは動きません。[/ja]
21179 */
21180
21181 value: function init() {
21182 this._boundOnDrag = this._onDrag.bind(this);
21183 this._boundOnDragStart = this._onDragStart.bind(this);
21184 this._boundOnDragEnd = this._onDragEnd.bind(this);
21185 this._boundOnScroll = this._onScroll.bind(this);
21186
21187 this._setState(STATE_INITIAL, true);
21188 }
21189 }, {
21190 key: '_setStyle',
21191 value: function _setStyle() {
21192 var height = this.height;
21193
21194 this.style.height = height + 'px';
21195 this.style.lineHeight = height + 'px';
21196 this.style.marginTop = '-1px';
21197 this._pageElement.style.marginTop = '-' + height + 'px';
21198 }
21199 }, {
21200 key: '_onScroll',
21201 value: function _onScroll(event) {
21202 var element = this._pageElement;
21203
21204 if (element.scrollTop < 0) {
21205 element.scrollTop = 0;
21206 }
21207 }
21208 }, {
21209 key: '_generateTranslationTransform',
21210 value: function _generateTranslationTransform(scroll) {
21211 return 'translate3d(0px, ' + scroll + 'px, 0px)';
21212 }
21213 }, {
21214 key: '_onDrag',
21215 value: function _onDrag(event) {
21216 var _this2 = this;
21217
21218 if (this.disabled) {
21219 return;
21220 }
21221
21222 // Hack to make it work on Android 4.4 WebView. Scrolls manually near the top of the page so
21223 // there will be no inertial scroll when scrolling down. Allowing default scrolling will
21224 // kill all 'touchmove' events.
21225 if (platform.isAndroid()) {
21226 var element = this._pageElement;
21227 element.scrollTop = this._startScroll - event.gesture.deltaY;
21228 if (element.scrollTop < window.innerHeight && event.gesture.direction !== 'up') {
21229 event.gesture.preventDefault();
21230 }
21231 }
21232
21233 if (this._currentTranslation === 0 && this._getCurrentScroll() === 0) {
21234 this._transitionDragLength = event.gesture.deltaY;
21235
21236 var direction = event.gesture.interimDirection;
21237 if (direction === 'down') {
21238 this._transitionDragLength -= 1;
21239 } else {
21240 this._transitionDragLength += 1;
21241 }
21242 }
21243
21244 var scroll = Math.max(event.gesture.deltaY - this._startScroll, 0);
21245
21246 if (this._thresholdHeightEnabled() && scroll >= this.thresholdHeight) {
21247 event.gesture.stopDetect();
21248
21249 setImmediate(function () {
21250 return _this2._finish();
21251 });
21252 } else if (scroll >= this.height) {
21253 this._setState(STATE_PREACTION);
21254 } else {
21255 this._setState(STATE_INITIAL);
21256 }
21257
21258 // By stopping propagation only of `dragup` and `dragdown`,
21259 // allowing ancestor elements to detect `dragleft` and `dragright`.
21260 // If we comment out the following `if` block, `ons-splitter` with `ons-pull-hook` will be broken.
21261 if (event.gesture.direction === 'up' || event.gesture.direction === 'down') {
21262 event.stopPropagation();
21263 }
21264 this._translateTo(scroll);
21265 }
21266 }, {
21267 key: '_onDragStart',
21268 value: function _onDragStart(event) {
21269 if (this.disabled) {
21270 return;
21271 }
21272
21273 this._startScroll = this._getCurrentScroll();
21274 }
21275 }, {
21276 key: '_onDragEnd',
21277 value: function _onDragEnd(event) {
21278 if (this.disabled) {
21279 return;
21280 }
21281
21282 if (this._currentTranslation > 0) {
21283 var scroll = this._currentTranslation;
21284
21285 if (scroll > this.height) {
21286 this._finish();
21287 } else {
21288 this._translateTo(0, { animate: true });
21289 }
21290 }
21291 }
21292
21293 /**
21294 * @property onAction
21295 * @type {Function}
21296 * @description
21297 * [en]This will be called in the `action` state if it exists. The function will be given a `done` callback as it's first argument.[/en]
21298 * [ja][/ja]
21299 */
21300
21301 }, {
21302 key: '_finish',
21303 value: function _finish() {
21304 var _this3 = this;
21305
21306 this._setState(STATE_ACTION);
21307 this._translateTo(this.height, { animate: true });
21308 var action = this.onAction || function (done) {
21309 return done();
21310 };
21311 action(function () {
21312 _this3._translateTo(0, { animate: true });
21313 _this3._setState(STATE_INITIAL);
21314 });
21315 }
21316
21317 /**
21318 * @property height
21319 * @type {Number}
21320 * @description
21321 * [en]The height of the pull hook in pixels. The default value is `64px`.[/en]
21322 * [ja][/ja]
21323 */
21324
21325 }, {
21326 key: '_thresholdHeightEnabled',
21327 value: function _thresholdHeightEnabled() {
21328 var th = this.thresholdHeight;
21329 return th > 0 && th >= this.height;
21330 }
21331 }, {
21332 key: '_setState',
21333 value: function _setState(state, noEvent) {
21334 var lastState = this._getState();
21335
21336 this.setAttribute('state', state);
21337
21338 if (!noEvent && lastState !== this._getState()) {
21339 util.triggerElementEvent(this, 'changestate', {
21340 pullHook: this,
21341 state: state,
21342 lastState: lastState
21343 });
21344 }
21345 }
21346 }, {
21347 key: '_getState',
21348 value: function _getState() {
21349 return this.getAttribute('state');
21350 }
21351
21352 /**
21353 * @property state
21354 * @readonly
21355 * @type {String}
21356 * @description
21357 * [en]Current state of the element.[/en]
21358 * [ja][/ja]
21359 */
21360
21361 }, {
21362 key: '_getCurrentScroll',
21363 value: function _getCurrentScroll() {
21364 return this._pageElement.scrollTop;
21365 }
21366
21367 /**
21368 * @property pullDistance
21369 * @readonly
21370 * @type {Number}
21371 * @description
21372 * [en]The current number of pixels the pull hook has moved.[/en]
21373 * [ja]現在のプルフックが引き出された距離をピクセル数。[/ja]
21374 */
21375
21376 }, {
21377 key: '_isContentFixed',
21378 value: function _isContentFixed() {
21379 return this.hasAttribute('fixed-content');
21380 }
21381 }, {
21382 key: '_getScrollableElement',
21383 value: function _getScrollableElement() {
21384 if (this._isContentFixed()) {
21385 return this;
21386 } else {
21387 return this._pageElement;
21388 }
21389 }
21390
21391 /**
21392 * @param {Number} scroll
21393 * @param {Object} options
21394 * @param {Function} [options.callback]
21395 */
21396
21397 }, {
21398 key: '_translateTo',
21399 value: function _translateTo(scroll) {
21400 var _this4 = this;
21401
21402 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
21403
21404 if (this._currentTranslation == 0 && scroll == 0) {
21405 return;
21406 }
21407
21408 var done = function done() {
21409 if (scroll === 0) {
21410 var el = _this4._getScrollableElement();
21411 removeTransform(el);
21412 }
21413
21414 if (options.callback) {
21415 options.callback();
21416 }
21417 };
21418
21419 this._currentTranslation = scroll;
21420
21421 if (options.animate) {
21422 animit(this._getScrollableElement()).queue({
21423 transform: this._generateTranslationTransform(scroll)
21424 }, {
21425 duration: 0.3,
21426 timing: 'cubic-bezier(.1, .7, .1, 1)'
21427 }).play(done);
21428 } else {
21429 animit(this._getScrollableElement()).queue({
21430 transform: this._generateTranslationTransform(scroll)
21431 }).play(done);
21432 }
21433 }
21434 }, {
21435 key: '_disableDragLock',
21436 value: function _disableDragLock() {
21437 // e2e tests need it
21438 this._dragLockDisabled = true;
21439 this._destroyEventListeners();
21440 this._createEventListeners();
21441 }
21442 }, {
21443 key: '_createEventListeners',
21444 value: function _createEventListeners() {
21445 this._gestureDetector = new GestureDetector(this._pageElement, {
21446 dragMinDistance: 1,
21447 dragDistanceCorrection: false,
21448 dragLockToAxis: !this._dragLockDisabled
21449 });
21450
21451 // Bind listeners
21452 //
21453 // Note:
21454 // If we swipe up/down a screen too fast,
21455 // the gesture detector occasionally dispatches a `dragleft` or `dragright`,
21456 // so we need to have the pull hook listen to `dragleft` and `dragright` as well as `dragup` and `dragdown`.
21457 this._gestureDetector.on('dragup dragdown dragleft dragright', this._boundOnDrag);
21458 this._gestureDetector.on('dragstart', this._boundOnDragStart);
21459 this._gestureDetector.on('dragend', this._boundOnDragEnd);
21460
21461 this._pageElement.addEventListener('scroll', this._boundOnScroll, false);
21462 }
21463 }, {
21464 key: '_destroyEventListeners',
21465 value: function _destroyEventListeners() {
21466 if (this._gestureDetector) {
21467 this._gestureDetector.off('dragup dragdown dragleft dragright', this._boundOnDrag);
21468 this._gestureDetector.off('dragstart', this._boundOnDragStart);
21469 this._gestureDetector.off('dragend', this._boundOnDragEnd);
21470
21471 this._gestureDetector.dispose();
21472 this._gestureDetector = null;
21473 }
21474
21475 this._pageElement.removeEventListener('scroll', this._boundOnScroll, false);
21476 }
21477 }, {
21478 key: 'connectedCallback',
21479 value: function connectedCallback() {
21480 this._currentTranslation = 0;
21481 this._pageElement = this.parentNode;
21482
21483 this._createEventListeners();
21484 this._setStyle();
21485 }
21486 }, {
21487 key: 'disconnectedCallback',
21488 value: function disconnectedCallback() {
21489 this._pageElement.style.marginTop = '';
21490
21491 this._destroyEventListeners();
21492 }
21493 }, {
21494 key: 'attributeChangedCallback',
21495 value: function attributeChangedCallback(name, last, current) {
21496 if (name === 'height') {
21497 this._setStyle();
21498 }
21499 }
21500 }, {
21501 key: 'height',
21502 set: function set(value) {
21503 if (!util.isInteger(value)) {
21504 throw new Error('The height must be an integer');
21505 }
21506
21507 this.setAttribute('height', value + 'px');
21508 },
21509 get: function get() {
21510 return parseInt(this.getAttribute('height') || '64', 10);
21511 }
21512
21513 /**
21514 * @property thresholdHeight
21515 * @type {Number}
21516 * @description
21517 * [en]The thresholdHeight of the pull hook in pixels. The default value is `96px`.[/en]
21518 * [ja][/ja]
21519 */
21520
21521 }, {
21522 key: 'thresholdHeight',
21523 set: function set(value) {
21524 if (!util.isInteger(value)) {
21525 throw new Error('The threshold height must be an integer');
21526 }
21527
21528 this.setAttribute('threshold-height', value + 'px');
21529 },
21530 get: function get() {
21531 return parseInt(this.getAttribute('threshold-height') || '96', 10);
21532 }
21533 }, {
21534 key: 'state',
21535 get: function get() {
21536 return this._getState();
21537 }
21538 }, {
21539 key: 'pullDistance',
21540 get: function get() {
21541 return this._currentTranslation;
21542 }
21543
21544 /**
21545 * @property disabled
21546 * @type {Boolean}
21547 * @description
21548 * [en]Whether the element is disabled or not.[/en]
21549 * [ja]無効化されている場合に`true`。[/ja]
21550 */
21551
21552 }, {
21553 key: 'disabled',
21554 set: function set(value) {
21555 return util.toggleAttribute(this, 'disabled', value);
21556 },
21557 get: function get() {
21558 return this.hasAttribute('disabled');
21559 }
21560 }], [{
21561 key: 'observedAttributes',
21562 get: function get() {
21563 return ['height'];
21564 }
21565 }, {
21566 key: 'STATE_INITIAL',
21567 get: function get() {
21568 return STATE_INITIAL;
21569 }
21570 }, {
21571 key: 'STATE_PREACTION',
21572 get: function get() {
21573 return STATE_PREACTION;
21574 }
21575 }, {
21576 key: 'STATE_ACTION',
21577 get: function get() {
21578 return STATE_ACTION;
21579 }
21580 }]);
21581 return PullHookElement;
21582}(BaseElement);
21583
21584customElements.define('ons-pull-hook', PullHookElement);
21585
21586/*
21587Copyright 2013-2016 ASIAL CORPORATION
21588
21589Licensed under the Apache License, Version 2.0 (the "License");
21590you may not use this file except in compliance with the License.
21591You may obtain a copy of the License at
21592
21593 http://www.apache.org/licenses/LICENSE-2.0
21594
21595Unless required by applicable law or agreed to in writing, software
21596distributed under the License is distributed on an "AS IS" BASIS,
21597WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21598See the License for the specific language governing permissions and
21599limitations under the License.
21600
21601*/
21602
21603/**
21604 * @class AnimatorCSS - implementation of Animator class using css transitions
21605 */
21606
21607var AnimatorCSS = function () {
21608 createClass(AnimatorCSS, [{
21609 key: 'animate',
21610
21611
21612 /**
21613 * @method animate
21614 * @desc main animation function
21615 * @param {Element} element
21616 * @param {Object} finalCSS
21617 * @param {number} [duration=200] - duration in milliseconds
21618 * @return {Object} result
21619 * @return {Function} result.then(callback) - sets a callback to be executed after the animation has stopped
21620 * @return {Function} result.stop(options) - stops the animation; if options.stopNext is true then it doesn't call the callback
21621 * @return {Function} result.finish(ms) - finishes the animation in the specified time in milliseconds
21622 * @return {Function} result.speed(ms) - sets the animation speed so that it finishes as if the original duration was the one specified here
21623 * @example
21624 * ````
21625 * var result = animator.animate(el, {opacity: 0.5}, 1000);
21626 *
21627 * el.addEventListener('click', function(e){
21628 * result.speed(200).then(function(){
21629 * console.log('done');
21630 * });
21631 * }, 300);
21632 * ````
21633 */
21634 value: function animate(el, final) {
21635 var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 200;
21636
21637 var start = new Date().getTime(),
21638 initial = {},
21639 stopped = false,
21640 next = false,
21641 timeout = false,
21642 properties = Object.keys(final);
21643
21644 var updateStyles = function updateStyles() {
21645 var s = window.getComputedStyle(el);
21646 properties.forEach(s.getPropertyValue.bind(s));
21647 s = el.offsetHeight;
21648 };
21649
21650 var result = {
21651 stop: function stop() {
21652 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21653
21654 timeout && clearTimeout(timeout);
21655 var k = Math.min(1, (new Date().getTime() - start) / duration);
21656 properties.forEach(function (i) {
21657 el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px');
21658 });
21659 el.style.transitionDuration = '0s';
21660
21661 if (options.stopNext) {
21662 next = false;
21663 } else if (!stopped) {
21664 stopped = true;
21665 next && next();
21666 }
21667 return result;
21668 },
21669 then: function then(cb) {
21670 next = cb;
21671 if (stopped) {
21672 next && next();
21673 }
21674 return result;
21675 },
21676 speed: function speed(newDuration) {
21677 if (internal$1.config.animationsDisabled) {
21678 newDuration = 0;
21679 }
21680 if (!stopped) {
21681 (function () {
21682 timeout && clearTimeout(timeout);
21683
21684 var passed = new Date().getTime() - start;
21685 var k = passed / duration;
21686 var remaining = newDuration * (1 - k);
21687
21688 properties.forEach(function (i) {
21689 el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px');
21690 });
21691
21692 updateStyles();
21693
21694 start = el.speedUpTime;
21695 duration = remaining;
21696
21697 el.style.transitionDuration = duration / 1000 + 's';
21698
21699 properties.forEach(function (i) {
21700 el.style[i] = final[i] + (i == 'opacity' ? '' : 'px');
21701 });
21702
21703 timeout = setTimeout(result.stop, remaining);
21704 })();
21705 }
21706 return result;
21707 },
21708 finish: function finish() {
21709 var milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50;
21710
21711 var k = (new Date().getTime() - start) / duration;
21712
21713 result.speed(milliseconds / (1 - k));
21714 return result;
21715 }
21716 };
21717
21718 if (el.hasAttribute('disabled') || stopped || internal$1.config.animationsDisabled) {
21719 return result;
21720 }
21721
21722 var style = window.getComputedStyle(el);
21723 properties.forEach(function (e) {
21724 var v = parseFloat(style.getPropertyValue(e));
21725 initial[e] = isNaN(v) ? 0 : v;
21726 });
21727
21728 if (!stopped) {
21729 el.style.transitionProperty = properties.join(',');
21730 el.style.transitionDuration = duration / 1000 + 's';
21731
21732 properties.forEach(function (e) {
21733 el.style[e] = final[e] + (e == 'opacity' ? '' : 'px');
21734 });
21735 }
21736
21737 timeout = setTimeout(result.stop, duration);
21738 this._onStopAnimations(el, result.stop);
21739
21740 return result;
21741 }
21742 }]);
21743
21744 function AnimatorCSS() {
21745 classCallCheck(this, AnimatorCSS);
21746
21747 this._queue = [];
21748 this._index = 0;
21749 }
21750
21751 createClass(AnimatorCSS, [{
21752 key: '_onStopAnimations',
21753 value: function _onStopAnimations(el, listener) {
21754 var queue = this._queue;
21755 var i = this._index++;
21756 queue[el] = queue[el] || [];
21757 queue[el][i] = function (options) {
21758 delete queue[el][i];
21759 if (queue[el] && queue[el].length == 0) {
21760 delete queue[el];
21761 }
21762 return listener(options);
21763 };
21764 }
21765
21766 /**
21767 * @method stopAnimations
21768 * @desc stops active animations on a specified element
21769 * @param {Element|Array} element - element or array of elements
21770 * @param {Object} [options={}]
21771 * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true
21772 */
21773
21774 }, {
21775 key: 'stopAnimations',
21776 value: function stopAnimations(el) {
21777 var _this = this;
21778
21779 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
21780
21781 if (Array.isArray(el)) {
21782 return el.forEach(function (el) {
21783 _this.stopAnimations(el, options);
21784 });
21785 }
21786
21787 (this._queue[el] || []).forEach(function (e) {
21788 e(options || {});
21789 });
21790 }
21791
21792 /**
21793 * @method stopAll
21794 * @desc stops all active animations
21795 * @param {Object} [options={}]
21796 * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true
21797 */
21798
21799 }, {
21800 key: 'stopAll',
21801 value: function stopAll() {
21802 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21803
21804 this.stopAnimations(Object.keys(this._queue), options);
21805 }
21806
21807 /**
21808 * @method fade
21809 * @desc fades the element (short version for animate(el, {opacity: 0}))
21810 * @param {Element} element
21811 * @param {number} [duration=200]
21812 */
21813
21814 }, {
21815 key: 'fade',
21816 value: function fade(el) {
21817 var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
21818
21819 return this.animate(el, { opacity: 0 }, duration);
21820 }
21821 }]);
21822 return AnimatorCSS;
21823}();
21824
21825/*
21826Copyright 2013-2015 ASIAL CORPORATION
21827
21828Licensed under the Apache License, Version 2.0 (the "License");
21829you may not use this file except in compliance with the License.
21830You may obtain a copy of the License at
21831
21832 http://www.apache.org/licenses/LICENSE-2.0
21833
21834Unless required by applicable law or agreed to in writing, software
21835distributed under the License is distributed on an "AS IS" BASIS,
21836WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21837See the License for the specific language governing permissions and
21838limitations under the License.
21839
21840*/
21841
21842/**
21843 * @element ons-ripple
21844 * @category visual
21845 * @description
21846 * [en]
21847 * Adds a Material Design "ripple" effect to an element. The ripple effect will spread from the position where the user taps.
21848 *
21849 * Some elements such as `<ons-button>` and `<ons-fab>` support a `ripple` attribute.
21850 * [/en]
21851 * [ja]マテリアルデザインのリップル効果をDOM要素に追加します。[/ja]
21852 * @codepen wKQWdZ
21853 * @tutorial vanilla/Reference/ripple
21854 * @guide cross-platform-styling
21855 * [en]Cross platform styling[/en]
21856 * [ja]Cross platform styling[/ja]
21857 * @example
21858 * <div class="my-div">
21859 * <ons-ripple></ons-ripple>
21860 * </div>
21861 *
21862 * @example
21863 * <ons-button ripple>Click me!</ons-button>
21864 */
21865
21866var RippleElement = function (_BaseElement) {
21867 inherits(RippleElement, _BaseElement);
21868
21869 function RippleElement() {
21870 classCallCheck(this, RippleElement);
21871 return possibleConstructorReturn(this, (RippleElement.__proto__ || Object.getPrototypeOf(RippleElement)).apply(this, arguments));
21872 }
21873
21874 createClass(RippleElement, [{
21875 key: 'init',
21876
21877
21878 /**
21879 * @attribute color
21880 * @type {String}
21881 * @description
21882 * [en]Color of the ripple effect.[/en]
21883 * [ja]リップルエフェクトの色を指定します。[/ja]
21884 */
21885
21886 /**
21887 * @attribute background
21888 * @type {String}
21889 * @description
21890 * [en]Color of the background.[/en]
21891 * [ja]背景の色を設定します。[/ja]
21892 */
21893
21894 /**
21895 * @attribute disabled
21896 * @description
21897 * [en]If this attribute is set, the ripple effect will be disabled.[/en]
21898 * [ja]この属性が設定された場合、リップルエフェクトは無効になります。[/ja]
21899 */
21900
21901 value: function init() {
21902 var _this2 = this;
21903
21904 contentReady(this, function () {
21905 return _this2._compile();
21906 });
21907
21908 this._animator = new AnimatorCSS();
21909
21910 ['color', 'center', 'start-radius', 'background'].forEach(function (e) {
21911 _this2.attributeChangedCallback(e, null, _this2.getAttribute(e));
21912 });
21913 }
21914 }, {
21915 key: '_compile',
21916 value: function _compile() {
21917 this.classList.add('ripple');
21918
21919 this._wave = this.getElementsByClassName('ripple__wave')[0];
21920 this._background = this.getElementsByClassName('ripple__background')[0];
21921
21922 if (!(this._background && this._wave)) {
21923 this._wave = util.create('.ripple__wave');
21924 this._background = util.create('.ripple__background');
21925
21926 this.appendChild(this._wave);
21927 this.appendChild(this._background);
21928 }
21929 }
21930 }, {
21931 key: '_calculateCoords',
21932 value: function _calculateCoords(e) {
21933 var x, y, h, w, r;
21934 var b = this.getBoundingClientRect();
21935 if (this._center) {
21936 x = b.width / 2;
21937 y = b.height / 2;
21938 r = Math.sqrt(x * x + y * y);
21939 } else {
21940 x = (e.clientX || e.changedTouches[0].clientX) - b.left;
21941 y = (e.clientY || e.changedTouches[0].clientY) - b.top;
21942 h = Math.max(y, b.height - y);
21943 w = Math.max(x, b.width - x);
21944 r = Math.sqrt(h * h + w * w);
21945 }
21946 return { x: x, y: y, r: r };
21947 }
21948 }, {
21949 key: '_rippleAnimation',
21950 value: function _rippleAnimation(e) {
21951 var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
21952
21953 var _animator = this._animator,
21954 _wave = this._wave,
21955 _background = this._background,
21956 _minR = this._minR,
21957 _calculateCoords2 = this._calculateCoords(e),
21958 x = _calculateCoords2.x,
21959 y = _calculateCoords2.y,
21960 r = _calculateCoords2.r;
21961
21962 _animator.stopAll({ stopNext: 1 });
21963 _animator.animate(_background, { opacity: 1 }, duration);
21964
21965 util.extend(_wave.style, {
21966 opacity: 1,
21967 top: y - _minR + 'px',
21968 left: x - _minR + 'px',
21969 width: 2 * _minR + 'px',
21970 height: 2 * _minR + 'px'
21971 });
21972
21973 return _animator.animate(_wave, {
21974 top: y - r,
21975 left: x - r,
21976 height: 2 * r,
21977 width: 2 * r
21978 }, duration);
21979 }
21980 }, {
21981 key: '_updateParent',
21982 value: function _updateParent() {
21983 if (!this._parentUpdated && this.parentNode) {
21984 var computedStyle = window.getComputedStyle(this.parentNode);
21985 if (computedStyle.getPropertyValue('position') === 'static') {
21986 this.parentNode.style.position = 'relative';
21987 }
21988 this._parentUpdated = true;
21989 }
21990 }
21991 }, {
21992 key: '_onTap',
21993 value: function _onTap(e) {
21994 var _this3 = this;
21995
21996 if (!this.disabled) {
21997 this._updateParent();
21998 this._rippleAnimation(e.gesture.srcEvent).then(function () {
21999 _this3._animator.fade(_this3._wave);
22000 _this3._animator.fade(_this3._background);
22001 });
22002 }
22003 }
22004 }, {
22005 key: '_onHold',
22006 value: function _onHold(e) {
22007 if (!this.disabled) {
22008 this._updateParent();
22009 this._holding = this._rippleAnimation(e.gesture.srcEvent, 2000);
22010 document.addEventListener('release', this._boundOnRelease);
22011 }
22012 }
22013 }, {
22014 key: '_onRelease',
22015 value: function _onRelease(e) {
22016 var _this4 = this;
22017
22018 if (this._holding) {
22019 this._holding.speed(300).then(function () {
22020 _this4._animator.stopAll({ stopNext: true });
22021 _this4._animator.fade(_this4._wave);
22022 _this4._animator.fade(_this4._background);
22023 });
22024
22025 this._holding = false;
22026 }
22027
22028 document.removeEventListener('release', this._boundOnRelease);
22029 }
22030 }, {
22031 key: '_onDragStart',
22032 value: function _onDragStart(e) {
22033 if (this._holding) {
22034 return this._onRelease(e);
22035 }
22036 if (['left', 'right'].indexOf(e.gesture.direction) != -1) {
22037 this._onTap(e);
22038 }
22039 }
22040 }, {
22041 key: 'connectedCallback',
22042 value: function connectedCallback() {
22043 this._parentNode = this.parentNode;
22044 this._boundOnTap = this._onTap.bind(this);
22045 this._boundOnHold = this._onHold.bind(this);
22046 this._boundOnDragStart = this._onDragStart.bind(this);
22047 this._boundOnRelease = this._onRelease.bind(this);
22048
22049 if (internal$1.config.animationsDisabled) {
22050 this.disabled = true;
22051 } else {
22052 this._parentNode.addEventListener('tap', this._boundOnTap);
22053 this._parentNode.addEventListener('hold', this._boundOnHold);
22054 this._parentNode.addEventListener('dragstart', this._boundOnDragStart);
22055 }
22056 }
22057 }, {
22058 key: 'disconnectedCallback',
22059 value: function disconnectedCallback() {
22060 var pn = this._parentNode || this.parentNode;
22061 pn.removeEventListener('tap', this._boundOnTap);
22062 pn.removeEventListener('hold', this._boundOnHold);
22063 pn.removeEventListener('dragstart', this._boundOnDragStart);
22064 }
22065 }, {
22066 key: 'attributeChangedCallback',
22067 value: function attributeChangedCallback(name, last, current) {
22068 var _this5 = this;
22069
22070 if (name === 'start-radius') {
22071 this._minR = Math.max(0, parseFloat(current) || 0);
22072 }
22073 if (name === 'color' && current) {
22074 contentReady(this, function () {
22075 _this5._wave.style.background = current;
22076 if (!_this5.hasAttribute('background')) {
22077 _this5._background.style.background = current;
22078 }
22079 });
22080 }
22081 if (name === 'background' && (current || last)) {
22082 if (current === 'none') {
22083 contentReady(this, function () {
22084 _this5._background.setAttribute('disabled', 'disabled');
22085 _this5._background.style.background = 'transparent';
22086 });
22087 } else {
22088 contentReady(this, function () {
22089 if (_this5._background.hasAttribute('disabled')) {
22090 _this5._background.removeAttribute('disabled');
22091 }
22092 _this5._background.style.background = current;
22093 });
22094 }
22095 }
22096 if (name === 'center') {
22097 this._center = current != null && current != 'false';
22098 }
22099 }
22100
22101 /**
22102 * @property disabled
22103 * @type {Boolean}
22104 * @description
22105 * [en]Whether the element is disabled or not.[/en]
22106 * [ja]無効化されている場合に`true`。[/ja]
22107 */
22108
22109 }, {
22110 key: 'disabled',
22111 set: function set(value) {
22112 return util.toggleAttribute(this, 'disabled', value);
22113 },
22114 get: function get() {
22115 return this.hasAttribute('disabled');
22116 }
22117 }], [{
22118 key: 'observedAttributes',
22119 get: function get() {
22120 return ['start-radius', 'color', 'background', 'center'];
22121 }
22122 }]);
22123 return RippleElement;
22124}(BaseElement);
22125
22126customElements.define('ons-ripple', RippleElement);
22127
22128/*
22129Copyright 2013-2015 ASIAL CORPORATION
22130
22131Licensed under the Apache License, Version 2.0 (the "License");
22132you may not use this file except in compliance with the License.
22133You may obtain a copy of the License at
22134
22135 http://www.apache.org/licenses/LICENSE-2.0
22136
22137Unless required by applicable law or agreed to in writing, software
22138distributed under the License is distributed on an "AS IS" BASIS,
22139WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22140See the License for the specific language governing permissions and
22141limitations under the License.
22142
22143*/
22144
22145/**
22146 * @element ons-row
22147 * @category grid
22148 * @description
22149 * [en]Represents a row in the grid system. Use with `<ons-col>` to layout components.[/en]
22150 * [ja]グリッドシステムにて行を定義します。ons-colとともに使用し、コンポーネントの配置に使用します。[/ja]
22151 * @codepen GgujC {wide}
22152 * @guide layouting
22153 * [en]Layouting guide[/en]
22154 * [ja]レイアウト調整[/ja]
22155 * @seealso ons-col
22156 * [en]The `<ons-col>` component is used as children of `<ons-row>`.[/en]
22157 * [ja]ons-colコンポーネント[/ja]
22158 * @note
22159 * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-col, they may not be displayed correctly. You can use only one vertical-align.[/en]
22160 * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-colを組み合わせてそれぞれのons-col要素のvertical-align属性の値に別々の値を指定すると、描画が崩れる場合があります。vertical-align属性の値には一つの値だけを指定できます。[/ja]
22161 * @example
22162 * <ons-row>
22163 * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col>
22164 * <ons-col>Text</ons-col>
22165 * </ons-row>
22166 */
22167
22168/**
22169 * @attribute vertical-align
22170 * @type {String}
22171 * @description
22172 * [en]Short hand attribute for aligning vertically. Valid values are top, bottom, and center.[/en]
22173 * [ja]縦に整列するために指定します。top、bottom、centerのいずれかを指定できます。[/ja]
22174 */
22175
22176var RowElement = function (_BaseElement) {
22177 inherits(RowElement, _BaseElement);
22178
22179 function RowElement() {
22180 classCallCheck(this, RowElement);
22181 return possibleConstructorReturn(this, (RowElement.__proto__ || Object.getPrototypeOf(RowElement)).apply(this, arguments));
22182 }
22183
22184 return RowElement;
22185}(BaseElement);
22186
22187customElements.define('ons-row', RowElement);
22188
22189/*
22190Copyright 2013-2015 ASIAL CORPORATION
22191Licensed under the Apache License, Version 2.0 (the "License");
22192you may not use this file except in compliance with the License.
22193You may obtain a copy of the License at
22194 http://www.apache.org/licenses/LICENSE-2.0
22195Unless required by applicable law or agreed to in writing, software
22196distributed under the License is distributed on an "AS IS" BASIS,
22197WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22198See the License for the specific language governing permissions and
22199limitations under the License.
22200*/
22201
22202var scheme$17 = {
22203 '': 'speed-dial__item--*'
22204};
22205
22206/**
22207 * @element ons-speed-dial-item
22208 * @category control
22209 * @description
22210 * [en]
22211 * This component displays the child elements of the Material Design Speed dial component.
22212 * [/en]
22213 * [ja]
22214 * Material DesignのSpeed dialの子要素を表現する要素です。
22215 * [/ja]
22216 * @codepen dYQYLg
22217 * @tutorial vanilla/Reference/speed-dial
22218 * @seealso ons-speed-dial
22219 * [en]The `<ons-speed-dial>` component.[/en]
22220 * [ja]ons-speed-dialコンポーネント[/ja]
22221 * @seealso ons-fab
22222 * [en]ons-fab component[/en]
22223 * [ja]ons-fabコンポーネント[/ja]
22224 * @example
22225 * <ons-speed-dial position="left bottom">
22226 * <ons-fab>
22227 * <ons-icon icon="fa-twitter"></ons-icon>
22228 * </ons-fab>
22229 * <ons-speed-dial-item>A</ons-speed-dial-item>
22230 * <ons-speed-dial-item>B</ons-speed-dial-item>
22231 * <ons-speed-dial-item>C</ons-speed-dial-item>
22232 * </ons-speed-dial>
22233 */
22234
22235var SpeedDialItemElement = function (_BaseElement) {
22236 inherits(SpeedDialItemElement, _BaseElement);
22237
22238 function SpeedDialItemElement() {
22239 classCallCheck(this, SpeedDialItemElement);
22240 return possibleConstructorReturn(this, (SpeedDialItemElement.__proto__ || Object.getPrototypeOf(SpeedDialItemElement)).apply(this, arguments));
22241 }
22242
22243 createClass(SpeedDialItemElement, [{
22244 key: 'init',
22245
22246
22247 /**
22248 * @attribute modifier
22249 * @type {String}
22250 * @description
22251 * [en]The appearance of the component.[/en]
22252 * [ja]このコンポーネントの表現を指定します。[/ja]
22253 */
22254
22255 value: function init() {
22256 this._compile();
22257 this._boundOnClick = this._onClick.bind(this);
22258 }
22259 }, {
22260 key: 'attributeChangedCallback',
22261 value: function attributeChangedCallback(name, last, current) {
22262 switch (name) {
22263 case 'modifier':
22264 ModifierUtil.onModifierChanged(last, current, this, scheme$17);
22265 break;
22266 case 'ripple':
22267 this._updateRipple();
22268 }
22269 }
22270 }, {
22271 key: 'connectedCallback',
22272 value: function connectedCallback() {
22273 this.addEventListener('click', this._boundOnClick, false);
22274 }
22275 }, {
22276 key: 'disconnectedCallback',
22277 value: function disconnectedCallback() {
22278 this.removeEventListener('click', this._boundOnClick, false);
22279 }
22280 }, {
22281 key: '_updateRipple',
22282 value: function _updateRipple() {
22283 util.updateRipple(this);
22284 }
22285 }, {
22286 key: '_onClick',
22287 value: function _onClick(e) {
22288 e.stopPropagation();
22289 }
22290 }, {
22291 key: '_compile',
22292 value: function _compile() {
22293 autoStyle.prepare(this);
22294
22295 this.classList.add('fab');
22296 this.classList.add('fab--mini');
22297 this.classList.add('speed-dial__item');
22298
22299 this._updateRipple();
22300
22301 ModifierUtil.initModifier(this, scheme$17);
22302 }
22303 }], [{
22304 key: 'observedAttributes',
22305 get: function get() {
22306 return ['modifier', 'ripple'];
22307 }
22308 }]);
22309 return SpeedDialItemElement;
22310}(BaseElement);
22311
22312customElements.define('ons-speed-dial-item', SpeedDialItemElement);
22313
22314/*
22315Copyright 2013-2015 ASIAL CORPORATION
22316
22317Licensed under the Apache License, Version 2.0 (the "License");
22318you may not use this file except in compliance with the License.
22319You may obtain a copy of the License at
22320
22321 http://www.apache.org/licenses/LICENSE-2.0
22322
22323Unless required by applicable law or agreed to in writing, software
22324distributed under the License is distributed on an "AS IS" BASIS,
22325WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22326See the License for the specific language governing permissions and
22327limitations under the License.
22328
22329*/
22330
22331/**
22332 * Minimal utility library for manipulating element's style.
22333 */
22334var styler = function styler(element, style) {
22335 return styler.css.apply(styler, arguments);
22336};
22337
22338/**
22339 * Set element's style.
22340 *
22341 * @param {Element} element
22342 * @param {Object} styles
22343 * @return {Element}
22344 */
22345styler.css = function (element, styles) {
22346 var keys = Object.keys(styles);
22347 keys.forEach(function (key) {
22348 if (key in element.style) {
22349 element.style[key] = styles[key];
22350 } else if (styler._prefix(key) in element.style) {
22351 element.style[styler._prefix(key)] = styles[key];
22352 } else {
22353 console.warn('No such style property: ' + key);
22354 }
22355 });
22356 return element;
22357};
22358
22359/**
22360 * Add vendor prefix.
22361 *
22362 * @param {String} name
22363 * @return {String}
22364 */
22365styler._prefix = function () {
22366 var styles = window.getComputedStyle(document.documentElement, '');
22367 var prefix = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1];
22368
22369 return function (name) {
22370 return prefix + name.substr(0, 1).toUpperCase() + name.substr(1);
22371 };
22372}();
22373
22374/**
22375 * @param {Element} element
22376 */
22377styler.clear = function (element) {
22378 styler._clear(element);
22379};
22380
22381/**
22382 * @param {Element} element
22383 */
22384styler._clear = function (element) {
22385 var len = element.style.length;
22386 var style = element.style;
22387 var keys = [];
22388 for (var i = 0; i < len; i++) {
22389 keys.push(style[i]);
22390 }
22391
22392 keys.forEach(function (key) {
22393 style[key] = '';
22394 });
22395};
22396
22397/*
22398Copyright 2013-2015 ASIAL CORPORATION
22399Licensed under the Apache License, Version 2.0 (the "License");
22400you may not use this file except in compliance with the License.
22401You may obtain a copy of the License at
22402 http://www.apache.org/licenses/LICENSE-2.0
22403Unless required by applicable law or agreed to in writing, software
22404distributed under the License is distributed on an "AS IS" BASIS,
22405WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22406See the License for the specific language governing permissions and
22407limitations under the License.
22408*/
22409
22410var scheme$18 = {
22411 '': 'speed-dial--*'
22412};
22413
22414/**
22415 * @element ons-speed-dial
22416 * @category control
22417 * @description
22418 * [en]
22419 * Element that displays a Material Design Speed Dialog component. It is useful when there are more than one primary action that can be performed in a page.
22420 *
22421 * The Speed dial looks like a `<ons-fab>` element but will expand a menu when tapped.
22422 * [/en]
22423 * [ja][/ja]
22424 * @codepen dYQYLg
22425 * @tutorial vanilla/Reference/speed-dial
22426 * @seealso ons-speed-dial-item
22427 * [en]The `<ons-speed-dial-item>` represents a menu item.[/en]
22428 * [ja]ons-speed-dial-itemコンポーネント[/ja]
22429 * @seealso ons-fab
22430 * [en]ons-fab component[/en]
22431 * [ja]ons-fabコンポーネント[/ja]
22432 * @example
22433 * <ons-speed-dial position="left bottom">
22434 * <ons-fab>
22435 * <ons-icon icon="fa-twitter"></ons-icon>
22436 * </ons-fab>
22437 * <ons-speed-dial-item>A</ons-speed-dial-item>
22438 * <ons-speed-dial-item>B</ons-speed-dial-item>
22439 * <ons-speed-dial-item>C</ons-speed-dial-item>
22440 * </ons-speed-dial>
22441 */
22442
22443var SpeedDialElement = function (_BaseElement) {
22444 inherits(SpeedDialElement, _BaseElement);
22445
22446 function SpeedDialElement() {
22447 classCallCheck(this, SpeedDialElement);
22448 return possibleConstructorReturn(this, (SpeedDialElement.__proto__ || Object.getPrototypeOf(SpeedDialElement)).apply(this, arguments));
22449 }
22450
22451 createClass(SpeedDialElement, [{
22452 key: 'init',
22453
22454
22455 /**
22456 * @event open
22457 * @description
22458 * [en]Fired when the menu items are shown.[/en]
22459 * [ja][/ja]
22460 */
22461
22462 /**
22463 * @event close
22464 * @description
22465 * [en]Fired when the menu items are hidden.[/en]
22466 * [ja][/ja]
22467 */
22468
22469 /**
22470 * @attribute modifier
22471 * @type {String}
22472 * @description
22473 * [en]The appearance of the component.[/en]
22474 * [ja]このコンポーネントの表現を指定します。[/ja]
22475 */
22476
22477 /**
22478 * @attribute position
22479 * @type {String}
22480 * @description
22481 * [en]
22482 * Specify the vertical and horizontal position of the component.
22483 * I.e. to display it in the top right corner specify "right top".
22484 * Choose from "right", "left", "top" and "bottom".
22485 * [/en]
22486 * [ja]
22487 * この要素を表示する左右と上下の位置を指定します。
22488 * 例えば、右上に表示する場合には"right top"を指定します。
22489 * 左右と上下の位置の指定には、rightとleft、topとbottomがそれぞれ指定できます。
22490 * [/ja]
22491 */
22492
22493 /**
22494 * @attribute direction
22495 * @type {String}
22496 * @description
22497 * [en]Specify the direction the items are displayed. Possible values are "up", "down", "left" and "right".[/en]
22498 * [ja]
22499 * 要素が表示する方向を指定します。up, down, left, rightが指定できます。
22500 * [/ja]
22501 */
22502
22503 /**
22504 * @attribute disabled
22505 * @description
22506 * [en]Specify if button should be disabled.[/en]
22507 * [ja]無効化する場合に指定します。[/ja]
22508 */
22509
22510 value: function init() {
22511 var _this2 = this;
22512
22513 contentReady(this, function () {
22514 _this2._compile();
22515 });
22516
22517 this._shown = true;
22518 this._itemShown = false;
22519 this._boundOnClick = this._onClick.bind(this);
22520 }
22521 }, {
22522 key: '_compile',
22523 value: function _compile() {
22524 if (!this.classList.contains('speed__dial')) {
22525 this.classList.add('speed__dial');
22526 autoStyle.prepare(this);
22527 this._updateRipple();
22528 ModifierUtil.initModifier(this, scheme$18);
22529
22530 if (this.hasAttribute('direction')) {
22531 this._updateDirection(this.getAttribute('direction'));
22532 } else {
22533 this._updateDirection('up');
22534 }
22535 }
22536
22537 this._updatePosition();
22538 }
22539 }, {
22540 key: 'attributeChangedCallback',
22541 value: function attributeChangedCallback(name, last, current) {
22542 var _this3 = this;
22543
22544 switch (name) {
22545 case 'modifier':
22546 ModifierUtil.onModifierChanged(last, current, this, scheme$18);
22547 break;
22548 case 'ripple':
22549 contentReady(this, function () {
22550 return _this3._updateRipple();
22551 });
22552 break;
22553 case 'direction':
22554 contentReady(this, function () {
22555 return _this3._updateDirection(current);
22556 });
22557 break;
22558 case 'position':
22559 contentReady(this, function () {
22560 return _this3._updatePosition();
22561 });
22562 break;
22563 }
22564 }
22565 }, {
22566 key: 'connectedCallback',
22567 value: function connectedCallback() {
22568 this.addEventListener('click', this._boundOnClick, false);
22569 }
22570 }, {
22571 key: 'disconnectedCallback',
22572 value: function disconnectedCallback() {
22573 this.removeEventListener('click', this._boundOnClick, false);
22574 }
22575 }, {
22576 key: '_onClick',
22577 value: function _onClick(e) {
22578 if (!this.disabled && this._shown) {
22579 this.toggleItems();
22580 }
22581 }
22582 }, {
22583 key: '_show',
22584 value: function _show() {
22585 if (!this.inline) {
22586 this.show();
22587 }
22588 }
22589 }, {
22590 key: '_hide',
22591 value: function _hide() {
22592 if (!this.inline) {
22593 this.hide();
22594 }
22595 }
22596 }, {
22597 key: '_updateRipple',
22598 value: function _updateRipple() {
22599 var fab = util.findChild(this, 'ons-fab');
22600
22601 if (fab) {
22602 this.hasAttribute('ripple') ? fab.setAttribute('ripple', '') : fab.removeAttribute('ripple');
22603 }
22604 }
22605 }, {
22606 key: '_updateDirection',
22607 value: function _updateDirection(direction) {
22608 var children = this.items;
22609 for (var i = 0; i < children.length; i++) {
22610 styler(children[i], {
22611 transitionDelay: 25 * i + 'ms',
22612 bottom: 'auto',
22613 right: 'auto',
22614 top: 'auto',
22615 left: 'auto'
22616 });
22617 }
22618 switch (direction) {
22619 case 'up':
22620 for (var _i = 0; _i < children.length; _i++) {
22621 children[_i].style.bottom = 72 + 56 * _i + 'px';
22622 children[_i].style.right = '8px';
22623 }
22624 break;
22625 case 'down':
22626 for (var _i2 = 0; _i2 < children.length; _i2++) {
22627 children[_i2].style.top = 72 + 56 * _i2 + 'px';
22628 children[_i2].style.left = '8px';
22629 }
22630 break;
22631 case 'left':
22632 for (var _i3 = 0; _i3 < children.length; _i3++) {
22633 children[_i3].style.top = '8px';
22634 children[_i3].style.right = 72 + 56 * _i3 + 'px';
22635 }
22636 break;
22637 case 'right':
22638 for (var _i4 = 0; _i4 < children.length; _i4++) {
22639 children[_i4].style.top = '8px';
22640 children[_i4].style.left = 72 + 56 * _i4 + 'px';
22641 }
22642 break;
22643 default:
22644 throw new Error('Argument must be one of up, down, left or right.');
22645 }
22646 }
22647 }, {
22648 key: '_updatePosition',
22649 value: function _updatePosition() {
22650 var position = this.getAttribute('position');
22651 this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center');
22652 switch (position) {
22653 case 'top right':
22654 case 'right top':
22655 this.classList.add('fab--top__right');
22656 break;
22657 case 'top left':
22658 case 'left top':
22659 this.classList.add('fab--top__left');
22660 break;
22661 case 'bottom right':
22662 case 'right bottom':
22663 this.classList.add('fab--bottom__right');
22664 break;
22665 case 'bottom left':
22666 case 'left bottom':
22667 this.classList.add('fab--bottom__left');
22668 break;
22669 case 'center top':
22670 case 'top center':
22671 this.classList.add('fab--top__center');
22672 break;
22673 case 'center bottom':
22674 case 'bottom center':
22675 this.classList.add('fab--bottom__center');
22676 break;
22677 default:
22678 break;
22679 }
22680 }
22681
22682 /**
22683 * @method show
22684 * @signature show()
22685 * @description
22686 * [en]Show the speed dial.[/en]
22687 * [ja]Speed dialを表示します。[/ja]
22688 */
22689
22690 }, {
22691 key: 'show',
22692 value: function show() {
22693 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22694
22695 this.querySelector('ons-fab').show();
22696 this._shown = true;
22697 }
22698
22699 /**
22700 * @method hide
22701 * @signature hide()
22702 * @description
22703 * [en]Hide the speed dial.[/en]
22704 * [ja]Speed dialを非表示にします。[/ja]
22705 */
22706
22707 }, {
22708 key: 'hide',
22709 value: function hide() {
22710 var _this4 = this;
22711
22712 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22713
22714 this.hideItems();
22715 setTimeout(function () {
22716 _this4.querySelector('ons-fab').hide();
22717 }, 200);
22718 this._shown = false;
22719 }
22720
22721 /**
22722 * @method showItems
22723 * @signature showItems()
22724 * @description
22725 * [en]Show the speed dial items.[/en]
22726 * [ja]Speed dialの子要素を表示します。[/ja]
22727 */
22728
22729 }, {
22730 key: 'showItems',
22731 value: function showItems() {
22732
22733 if (this.hasAttribute('direction')) {
22734 this._updateDirection(this.getAttribute('direction'));
22735 } else {
22736 this._updateDirection('up');
22737 }
22738
22739 if (!this._itemShown) {
22740 var children = this.items;
22741 for (var i = 0; i < children.length; i++) {
22742 styler(children[i], {
22743 transform: 'scale(1)',
22744 transitionDelay: 25 * i + 'ms'
22745 });
22746 }
22747 }
22748 this._itemShown = true;
22749
22750 util.triggerElementEvent(this, 'open');
22751 }
22752
22753 /**
22754 * @method hideItems
22755 * @signature hideItems()
22756 * @description
22757 * [en]Hide the speed dial items.[/en]
22758 * [ja]Speed dialの子要素を非表示にします。[/ja]
22759 */
22760
22761 }, {
22762 key: 'hideItems',
22763 value: function hideItems() {
22764 if (this._itemShown) {
22765 var children = this.items;
22766 for (var i = 0; i < children.length; i++) {
22767 styler(children[i], {
22768 transform: 'scale(0)',
22769 transitionDelay: 25 * (children.length - i) + 'ms'
22770 });
22771 }
22772 }
22773 this._itemShown = false;
22774 util.triggerElementEvent(this, 'close');
22775 }
22776
22777 /**
22778 * @property disabled
22779 * @type {Boolean}
22780 * @description
22781 * [en]Whether the element is disabled or not.[/en]
22782 * [ja]無効化されている場合に`true`。[/ja]
22783 */
22784
22785 }, {
22786 key: 'isOpen',
22787
22788
22789 /**
22790 * @method isOpen
22791 * @signature isOpen()
22792 * @description
22793 * [en]Returns whether the menu is open or not.[/en]
22794 * [ja][/ja]
22795 */
22796 value: function isOpen() {
22797 return this._itemShown;
22798 }
22799
22800 /**
22801 * @method toggle
22802 * @signature toggle()
22803 * @description
22804 * [en]Toggle visibility.[/en]
22805 * [ja]Speed dialの表示非表示を切り替えます。[/ja]
22806 */
22807
22808 }, {
22809 key: 'toggle',
22810 value: function toggle() {
22811 this.visible ? this.hide() : this.show();
22812 }
22813
22814 /**
22815 * @method toggleItems
22816 * @signature toggleItems()
22817 * @description
22818 * [en]Toggle item visibility.[/en]
22819 * [ja]Speed dialの子要素の表示非表示を切り替えます。[/ja]
22820 */
22821
22822 }, {
22823 key: 'toggleItems',
22824 value: function toggleItems() {
22825 if (this.isOpen()) {
22826 this.hideItems();
22827 } else {
22828 this.showItems();
22829 }
22830 }
22831 }, {
22832 key: 'items',
22833 get: function get() {
22834 return util.arrayFrom(this.querySelectorAll('ons-speed-dial-item'));
22835 }
22836 }, {
22837 key: 'disabled',
22838 set: function set(value) {
22839 if (value) {
22840 this.hideItems();
22841 }
22842 util.arrayFrom(this.children).forEach(function (e) {
22843 util.match(e, '.fab') && util.toggleAttribute(e, 'disabled', value);
22844 });
22845
22846 return util.toggleAttribute(this, 'disabled', value);
22847 },
22848 get: function get() {
22849 return this.hasAttribute('disabled');
22850 }
22851
22852 /**
22853 * @property inline
22854 * @readonly
22855 * @type {Boolean}
22856 * @description
22857 * [en]Whether the element is inline or not.[/en]
22858 * [ja]インライン要素の場合に`true`。[/ja]
22859 */
22860
22861 }, {
22862 key: 'inline',
22863 get: function get() {
22864 return this.hasAttribute('inline');
22865 }
22866
22867 /**
22868 * @property visible
22869 * @readonly
22870 * @type {Boolean}
22871 * @description
22872 * [en]Whether the element is visible or not.[/en]
22873 * [ja]要素が見える場合に`true`。[/ja]
22874 */
22875
22876 }, {
22877 key: 'visible',
22878 get: function get() {
22879 return this._shown && this.style.display !== 'none';
22880 }
22881 }], [{
22882 key: 'observedAttributes',
22883 get: function get() {
22884 return ['modifier', 'ripple', 'direction', 'position'];
22885 }
22886 }]);
22887 return SpeedDialElement;
22888}(BaseElement);
22889
22890customElements.define('ons-speed-dial', SpeedDialElement);
22891
22892/*
22893Copyright 2013-2015 ASIAL CORPORATION
22894
22895Licensed under the Apache License, Version 2.0 (the "License");
22896you may not use this file except in compliance with the License.
22897You may obtain a copy of the License at
22898
22899 http://www.apache.org/licenses/LICENSE-2.0
22900
22901Unless required by applicable law or agreed to in writing, software
22902distributed under the License is distributed on an "AS IS" BASIS,
22903WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22904See the License for the specific language governing permissions and
22905limitations under the License.
22906
22907*/
22908
22909var rewritables$1 = {
22910 /**
22911 * @param {Element} element
22912 * @param {Function} callback
22913 */
22914 ready: function ready(element, callback) {
22915 setImmediate(callback);
22916 },
22917
22918
22919 /**
22920 * @param {Element} element
22921 * @param {HTMLFragment} target
22922 * @param {Object} options
22923 * @param {Function} callback
22924 */
22925 link: function link(element, target, options, callback) {
22926 callback(target);
22927 }
22928};
22929
22930/**
22931 * @element ons-splitter-content
22932 * @category menu
22933 * @description
22934 * [en]
22935 * The `<ons-splitter-content>` element is used as a child element of `<ons-splitter>`.
22936 *
22937 * It contains the main content of the page while `<ons-splitter-side>` contains the list.
22938 * [/en]
22939 * [ja]ons-splitter-content要素は、ons-splitter要素の子要素として利用します。[/ja]
22940 * @codepen rOQOML
22941 * @tutorial vanilla/Reference/splitter
22942 * @guide multiple-page-navigation
22943 * [en]Managing multiple pages.[/en]
22944 * [ja]Managing multiple pages[/ja]
22945 * @seealso ons-splitter
22946 * [en]The `<ons-splitter>` component is the parent element.[/en]
22947 * [ja]ons-splitterコンポーネント[/ja]
22948 * @seealso ons-splitter-side
22949 * [en]The `<ons-splitter-side>` component contains the menu.[/en]
22950 * [ja]ons-splitter-sideコンポーネント[/ja]
22951 * @example
22952 * <ons-splitter>
22953 * <ons-splitter-content>
22954 * ...
22955 * </ons-splitter-content>
22956 *
22957 * <ons-splitter-side side="left" width="80%" collapse>
22958 * ...
22959 * </ons-splitter-side>
22960 * </ons-splitter>
22961 */
22962
22963var SplitterContentElement = function (_BaseElement) {
22964 inherits(SplitterContentElement, _BaseElement);
22965
22966 function SplitterContentElement() {
22967 classCallCheck(this, SplitterContentElement);
22968 return possibleConstructorReturn(this, (SplitterContentElement.__proto__ || Object.getPrototypeOf(SplitterContentElement)).apply(this, arguments));
22969 }
22970
22971 createClass(SplitterContentElement, [{
22972 key: 'init',
22973
22974
22975 /**
22976 * @attribute page
22977 * @type {String}
22978 * @description
22979 * [en]
22980 * The url of the content page. If this attribute is used the content will be loaded from a `<ons-template>` tag or a remote file.
22981 *
22982 * It is also possible to put `<ons-page>` element as a child of the element.
22983 * [/en]
22984 * [ja]ons-splitter-content要素に表示するページのURLを指定します。[/ja]
22985 */
22986
22987 value: function init() {
22988 var _this2 = this;
22989
22990 this._page = null;
22991 this._pageLoader = defaultPageLoader;
22992
22993 contentReady(this, function () {
22994 var page = _this2._getPageTarget();
22995
22996 if (page) {
22997 _this2.load(page);
22998 }
22999 });
23000 }
23001 }, {
23002 key: 'connectedCallback',
23003 value: function connectedCallback() {
23004 if (!util.match(this.parentNode, 'ons-splitter')) {
23005 throw new Error('"ons-splitter-content" must have "ons-splitter" as parentNode.');
23006 }
23007 }
23008 }, {
23009 key: '_getPageTarget',
23010 value: function _getPageTarget() {
23011 return this._page || this.getAttribute('page');
23012 }
23013 }, {
23014 key: 'disconnectedCallback',
23015 value: function disconnectedCallback() {}
23016 }, {
23017 key: 'attributeChangedCallback',
23018 value: function attributeChangedCallback(name, last, current) {}
23019
23020 /**
23021 * @property page
23022 * @type {HTMLElement}
23023 * @description
23024 * [en]The page to load in the splitter content.[/en]
23025 * [ja]この要素内に表示するページを指定します。[/ja]
23026 */
23027
23028 }, {
23029 key: 'load',
23030
23031
23032 /**
23033 * @method load
23034 * @signature load(page, [options])
23035 * @param {String} page, [options]
23036 * [en]Page URL. Can be either an HTML document or an `<ons-template>` id.[/en]
23037 * [ja]pageのURLか、ons-templateで宣言したテンプレートのid属性の値を指定します。[/ja]
23038 * @param {Object} [options]
23039 * @param {Function} [options.callback]
23040 * @description
23041 * [en]Show the page specified in `page` in the content.[/en]
23042 * [ja]指定したURLをメインページを読み込みます。[/ja]
23043 * @return {Promise}
23044 * [en]Resolves to the new `<ons-page>` element[/en]
23045 * [ja]`<ons-page>`要素を解決するPromiseオブジェクトを返します。[/ja]
23046 */
23047 value: function load(page) {
23048 var _this3 = this;
23049
23050 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
23051
23052 this._page = page;
23053 var callback = options.callback || function () {};
23054
23055 return new Promise(function (resolve) {
23056 _this3._pageLoader.load({ page: page, parent: _this3, replace: true }, function (_ref) {
23057 var element = _ref.element,
23058 unload = _ref.unload;
23059
23060 rewritables$1.link(_this3, element, options, function (fragment) {
23061 setImmediate(function () {
23062 return _this3._show();
23063 });
23064 callback();
23065
23066 resolve(_this3.firstChild);
23067 });
23068 });
23069 });
23070 }
23071 }, {
23072 key: '_show',
23073 value: function _show() {
23074 util.propagateAction(this, '_show');
23075 }
23076 }, {
23077 key: '_hide',
23078 value: function _hide() {
23079 util.propagateAction(this, '_hide');
23080 }
23081 }, {
23082 key: '_destroy',
23083 value: function _destroy() {
23084 util.propagateAction(this, '_destroy');
23085 this.remove();
23086 }
23087 }, {
23088 key: 'page',
23089 get: function get() {
23090 return this._page;
23091 }
23092
23093 /**
23094 * @param {*} page
23095 */
23096 ,
23097 set: function set(page) {
23098 this._page = page;
23099 }
23100
23101 /**
23102 * @property pageLoader
23103 * @type {Function}
23104 * @description
23105 * [en]Page element loaded in the splitter content.[/en]
23106 * [ja]この要素内に表示するページを指定します。[/ja]
23107 */
23108
23109 }, {
23110 key: 'pageLoader',
23111 get: function get() {
23112 return this._pageLoader;
23113 },
23114 set: function set(loader) {
23115 if (!(loader instanceof PageLoader)) {
23116 throw Error('First parameter must be an instance of PageLoader');
23117 }
23118 this._pageLoader = loader;
23119 }
23120 }], [{
23121 key: 'observedAttributes',
23122 get: function get() {
23123 return [];
23124 }
23125 }, {
23126 key: 'rewritables',
23127 get: function get() {
23128 return rewritables$1;
23129 }
23130 }]);
23131 return SplitterContentElement;
23132}(BaseElement);
23133
23134customElements.define('ons-splitter-content', SplitterContentElement);
23135
23136/*
23137Copyright 2013-2015 ASIAL CORPORATION
23138
23139Licensed under the Apache License, Version 2.0 (the "License");
23140you may not use this file except in compliance with the License.
23141You may obtain a copy of the License at
23142
23143 http://www.apache.org/licenses/LICENSE-2.0
23144
23145Unless required by applicable law or agreed to in writing, software
23146distributed under the License is distributed on an "AS IS" BASIS,
23147WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23148See the License for the specific language governing permissions and
23149limitations under the License.
23150
23151*/
23152
23153var SplitterMaskElement = function (_BaseElement) {
23154 inherits(SplitterMaskElement, _BaseElement);
23155
23156 function SplitterMaskElement() {
23157 classCallCheck(this, SplitterMaskElement);
23158 return possibleConstructorReturn(this, (SplitterMaskElement.__proto__ || Object.getPrototypeOf(SplitterMaskElement)).apply(this, arguments));
23159 }
23160
23161 createClass(SplitterMaskElement, [{
23162 key: 'init',
23163 value: function init() {
23164 this._boundOnClick = this._onClick.bind(this);
23165 }
23166 }, {
23167 key: '_onClick',
23168 value: function _onClick(event) {
23169 if (util.match(this.parentNode, 'ons-splitter')) {
23170 this.parentNode._sides.forEach(function (side) {
23171 return side.close('left').catch(function () {});
23172 });
23173 }
23174 event.stopPropagation();
23175 }
23176 }, {
23177 key: 'attributeChangedCallback',
23178 value: function attributeChangedCallback(name, last, current) {}
23179 }, {
23180 key: 'connectedCallback',
23181 value: function connectedCallback() {
23182 this.addEventListener('click', this._boundOnClick);
23183 }
23184 }, {
23185 key: 'disconnectedCallback',
23186 value: function disconnectedCallback() {
23187 this.removeEventListener('click', this._boundOnClick);
23188 }
23189 }], [{
23190 key: 'observedAttributes',
23191 get: function get() {
23192 return [];
23193 }
23194 }]);
23195 return SplitterMaskElement;
23196}(BaseElement);
23197
23198customElements.define('ons-splitter-mask', SplitterMaskElement);
23199
23200/*
23201Copyright 2013-2015 ASIAL CORPORATION
23202
23203Licensed under the Apache License, Version 2.0 (the "License");
23204you may not use this file except in compliance with the License.
23205You may obtain a copy of the License at
23206
23207 http://www.apache.org/licenses/LICENSE-2.0
23208
23209Unless required by applicable law or agreed to in writing, software
23210distributed under the License is distributed on an "AS IS" BASIS,
23211WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23212See the License for the specific language governing permissions and
23213limitations under the License.
23214
23215*/
23216
23217var SplitterAnimator = function () {
23218 function SplitterAnimator() {
23219 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
23220 classCallCheck(this, SplitterAnimator);
23221
23222 this._options = {
23223 timing: 'cubic-bezier(.1, .7, .1, 1)',
23224 duration: '0.3',
23225 delay: '0'
23226 };
23227 this.updateOptions(options);
23228 }
23229
23230 createClass(SplitterAnimator, [{
23231 key: 'updateOptions',
23232 value: function updateOptions() {
23233 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
23234
23235 util.extend(this._options, options);
23236 this._timing = this._options.timing;
23237 this._duration = this._options.duration;
23238 this._delay = this._options.delay;
23239 }
23240
23241 /**
23242 * @param {Element} sideElement
23243 */
23244
23245 }, {
23246 key: 'activate',
23247 value: function activate(sideElement) {
23248 var _this = this;
23249
23250 var splitter = sideElement.parentNode;
23251
23252 contentReady(splitter, function () {
23253 _this._side = sideElement;
23254 _this._content = splitter.content;
23255 _this._mask = splitter.mask;
23256 });
23257 }
23258 }, {
23259 key: 'inactivate',
23260 value: function inactivate() {
23261 this._content = this._side = this._mask = null;
23262 }
23263 }, {
23264 key: 'translate',
23265 value: function translate(distance) {
23266 animit(this._side).queue({
23267 transform: 'translate3d(' + (this.minus + distance) + 'px, 0px, 0px)'
23268 }).play();
23269 }
23270
23271 /**
23272 * @param {Function} done
23273 */
23274
23275 }, {
23276 key: 'open',
23277 value: function open(done) {
23278 animit.runAll(animit(this._side).wait(this._delay).queue({
23279 transform: 'translate3d(' + this.minus + '100%, 0px, 0px)'
23280 }, {
23281 duration: this._duration,
23282 timing: this._timing
23283 }).queue(function (callback) {
23284 callback();
23285 done && done();
23286 }), animit(this._mask).wait(this._delay).queue({
23287 display: 'block'
23288 }).queue({
23289 opacity: '1'
23290 }, {
23291 duration: this._duration,
23292 timing: 'linear'
23293 }));
23294 }
23295
23296 /**
23297 * @param {Function} done
23298 */
23299
23300 }, {
23301 key: 'close',
23302 value: function close(done) {
23303 var _this2 = this;
23304
23305 animit.runAll(animit(this._side).wait(this._delay).queue({
23306 transform: 'translate3d(0px, 0px, 0px)'
23307 }, {
23308 duration: this._duration,
23309 timing: this._timing
23310 }).queue(function (callback) {
23311 _this2._side.style.webkitTransition = '';
23312 done && done();
23313 callback();
23314 }), animit(this._mask).wait(this._delay).queue({
23315 opacity: '0'
23316 }, {
23317 duration: this._duration,
23318 timing: 'linear'
23319 }).queue({
23320 display: 'none'
23321 }));
23322 }
23323 }, {
23324 key: 'minus',
23325 get: function get() {
23326 return this._side._side === 'right' ? '-' : '';
23327 }
23328 }]);
23329 return SplitterAnimator;
23330}();
23331
23332/*
23333Copyright 2013-2015 ASIAL CORPORATION
23334
23335Licensed under the Apache License, Version 2.0 (the "License");
23336you may not use this file except in compliance with the License.
23337You may obtain a copy of the License at
23338
23339 http://www.apache.org/licenses/LICENSE-2.0
23340
23341Unless required by applicable law or agreed to in writing, software
23342distributed under the License is distributed on an "AS IS" BASIS,
23343WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23344See the License for the specific language governing permissions and
23345limitations under the License.
23346
23347*/
23348
23349var _animatorDict$5 = {
23350 default: SplitterAnimator,
23351 overlay: SplitterAnimator
23352};
23353
23354/**
23355 * @element ons-splitter
23356 * @category menu
23357 * @description
23358 * [en]
23359 * A component that enables responsive layout by implementing both a two-column layout and a sliding menu layout.
23360 *
23361 * It can be configured to automatically expand into a column layout on large screens and collapse the menu on smaller screens. When the menu is collapsed the user can open it by swiping.
23362 * [/en]
23363 * [ja][/ja]
23364 * @codepen rOQOML
23365 * @tutorial vanilla/Reference/splitter
23366 * @guide multiple-page-navigation
23367 * [en]Managing multiple pages.[/en]
23368 * [ja]Managing multiple pages[/ja]
23369 * @seealso ons-splitter-content
23370 * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en]
23371 * [ja]ons-splitter-contentコンポーネント[/ja]
23372 * @seealso ons-splitter-side
23373 * [en]The `<ons-splitter-side>` component contains the menu.[/en]
23374 * [ja]ons-splitter-sideコンポーネント[/ja]
23375 * @example
23376 * <ons-splitter id="splitter">
23377 * <ons-splitter-content>
23378 * ...
23379 * </ons-splitter-content>
23380 *
23381 * <ons-splitter-side side="left" width="80%" collapse swipeable>
23382 * ...
23383 * </ons-splitter-side>
23384 * </ons-splitter>
23385 *
23386 * <script>
23387 * var splitter = document.getElementById('splitter');
23388 * splitter.left.open();
23389 * </script>
23390 */
23391
23392var SplitterElement = function (_BaseElement) {
23393 inherits(SplitterElement, _BaseElement);
23394
23395 function SplitterElement() {
23396 classCallCheck(this, SplitterElement);
23397 return possibleConstructorReturn(this, (SplitterElement.__proto__ || Object.getPrototypeOf(SplitterElement)).apply(this, arguments));
23398 }
23399
23400 createClass(SplitterElement, [{
23401 key: '_getSide',
23402 value: function _getSide(side) {
23403 var element = util.findChild(this, function (e) {
23404 return util.match(e, 'ons-splitter-side') && e.getAttribute('side') === side;
23405 });
23406 return element;
23407 }
23408
23409 /**
23410 * @property left
23411 * @readonly
23412 * @type {HTMLElement}
23413 * @description
23414 * [en]Left `<ons-splitter-side>` element.[/en]
23415 * [ja][/ja]
23416 */
23417
23418 }, {
23419 key: '_onDeviceBackButton',
23420 value: function _onDeviceBackButton(event) {
23421 this._sides.some(function (s) {
23422 return s.isOpen ? s.close() : false;
23423 }) || event.callParentHandler();
23424 }
23425 }, {
23426 key: '_onModeChange',
23427 value: function _onModeChange(e) {
23428 var _this2 = this;
23429
23430 if (e.target.parentNode) {
23431 contentReady(this, function () {
23432 _this2._layout();
23433 });
23434 }
23435 }
23436 }, {
23437 key: '_layout',
23438 value: function _layout() {
23439 var _this3 = this;
23440
23441 this._sides.forEach(function (side) {
23442 _this3.content.style[side.side] = side.mode === 'split' ? side._width : 0;
23443 });
23444 }
23445 }, {
23446 key: 'init',
23447 value: function init() {
23448 var _this4 = this;
23449
23450 this._boundOnModeChange = this._onModeChange.bind(this);
23451
23452 contentReady(this, function () {
23453 _this4._compile();
23454 _this4._layout();
23455 });
23456 }
23457 }, {
23458 key: '_compile',
23459 value: function _compile() {
23460 if (!this.mask) {
23461 this.appendChild(document.createElement('ons-splitter-mask'));
23462 }
23463 }
23464 }, {
23465 key: 'connectedCallback',
23466 value: function connectedCallback() {
23467 this.onDeviceBackButton = this._onDeviceBackButton.bind(this);
23468 this.addEventListener('modechange', this._boundOnModeChange, false);
23469 }
23470 }, {
23471 key: 'disconnectedCallback',
23472 value: function disconnectedCallback() {
23473 this._backButtonHandler.destroy();
23474 this._backButtonHandler = null;
23475 this.removeEventListener('modechange', this._boundOnModeChange, false);
23476 }
23477 }, {
23478 key: 'attributeChangedCallback',
23479 value: function attributeChangedCallback(name, last, current) {}
23480 }, {
23481 key: '_show',
23482 value: function _show() {
23483 util.propagateAction(this, '_show');
23484 }
23485 }, {
23486 key: '_hide',
23487 value: function _hide() {
23488 util.propagateAction(this, '_hide');
23489 }
23490 }, {
23491 key: '_destroy',
23492 value: function _destroy() {
23493 util.propagateAction(this, '_destroy');
23494 this.remove();
23495 }
23496 }, {
23497 key: 'left',
23498 get: function get() {
23499 return this._getSide('left');
23500 }
23501 /**
23502 * @property right
23503 * @readonly
23504 * @type {HTMLElement}
23505 * @description
23506 * [en]Right `<ons-splitter-side>` element.[/en]
23507 * [ja][/ja]
23508 */
23509
23510 }, {
23511 key: 'right',
23512 get: function get() {
23513 return this._getSide('right');
23514 }
23515 }, {
23516 key: '_sides',
23517 get: function get() {
23518 return [this.left, this.right].filter(function (e) {
23519 return e;
23520 });
23521 }
23522 /**
23523 * @property content
23524 * @readonly
23525 * @type {HTMLElement}
23526 * @description
23527 * [en]The `<ons-splitter-content>` element.[/en]
23528 * [ja][/ja]
23529 */
23530
23531 }, {
23532 key: 'content',
23533 get: function get() {
23534 return util.findChild(this, 'ons-splitter-content');
23535 }
23536 }, {
23537 key: 'mask',
23538 get: function get() {
23539 return util.findChild(this, 'ons-splitter-mask');
23540 }
23541
23542 /**
23543 * @property onDeviceBackButton
23544 * @type {Object}
23545 * @description
23546 * [en]Back-button handler.[/en]
23547 * [ja]バックボタンハンドラ。[/ja]
23548 */
23549
23550 }, {
23551 key: 'onDeviceBackButton',
23552 get: function get() {
23553 return this._backButtonHandler;
23554 },
23555 set: function set(callback) {
23556 if (this._backButtonHandler) {
23557 this._backButtonHandler.destroy();
23558 }
23559
23560 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
23561 }
23562 }], [{
23563 key: 'registerAnimator',
23564 value: function registerAnimator(name, Animator) {
23565 if (!(Animator instanceof SplitterAnimator)) {
23566 throw new Error('Animator parameter must be an instance of SplitterAnimator.');
23567 }
23568 _animatorDict$5[name] = Animator;
23569 }
23570 }, {
23571 key: 'SplitterAnimator',
23572 get: function get() {
23573 return SplitterAnimator;
23574 }
23575 }, {
23576 key: 'animators',
23577 get: function get() {
23578 return _animatorDict$5;
23579 }
23580 }]);
23581 return SplitterElement;
23582}(BaseElement);
23583
23584customElements.define('ons-splitter', SplitterElement);
23585
23586/*
23587Copyright 2013-2015 ASIAL CORPORATION
23588
23589Licensed under the Apache License, Version 2.0 (the "License");
23590you may not use this file except in compliance with the License.
23591You may obtain a copy of the License at
23592
23593 http://www.apache.org/licenses/LICENSE-2.0
23594
23595Unless required by applicable law or agreed to in writing, software
23596distributed under the License is distributed on an "AS IS" BASIS,
23597WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23598See the License for the specific language governing permissions and
23599limitations under the License.
23600
23601*/
23602
23603var SPLIT_MODE = 'split';
23604var COLLAPSE_MODE = 'collapse';
23605var CLOSED_STATE = 'closed';
23606var OPEN_STATE = 'open';
23607var CHANGING_STATE = 'changing';
23608
23609var WATCHED_ATTRIBUTES = ['animation', 'width', 'side', 'collapse', 'swipeable', 'swipe-target-width', 'animation-options', 'open-threshold'];
23610
23611var rewritables$2 = {
23612 /**
23613 * @param {Element} splitterSideElement
23614 * @param {Function} callback
23615 */
23616 ready: function ready(splitterSideElement, callback) {
23617 setImmediate(callback);
23618 },
23619
23620
23621 /**
23622 * @param {Element} splitterSideElement
23623 * @param {HTMLFragment} target
23624 * @param {Object} options
23625 * @param {Function} callback
23626 */
23627 link: function link(splitterSideElement, target, options, callback) {
23628 callback(target);
23629 }
23630};
23631
23632var CollapseDetection = function () {
23633 function CollapseDetection(element, target) {
23634 classCallCheck(this, CollapseDetection);
23635
23636 this._element = element;
23637 this._boundOnChange = this._onChange.bind(this);
23638 target && this.changeTarget(target);
23639 }
23640
23641 createClass(CollapseDetection, [{
23642 key: 'changeTarget',
23643 value: function changeTarget(target) {
23644 this.disable();
23645 this._target = target;
23646 if (target) {
23647 this._orientation = ['portrait', 'landscape'].indexOf(target) !== -1;
23648 this.activate();
23649 }
23650 }
23651 }, {
23652 key: '_match',
23653 value: function _match(value) {
23654 if (this._orientation) {
23655 return this._target === (value.isPortrait ? 'portrait' : 'landscape');
23656 }
23657 return value.matches;
23658 }
23659 }, {
23660 key: '_onChange',
23661 value: function _onChange(value) {
23662 this._element._updateMode(this._match(value) ? COLLAPSE_MODE : SPLIT_MODE);
23663 }
23664 }, {
23665 key: 'activate',
23666 value: function activate() {
23667 if (this._orientation) {
23668 orientation.on('change', this._boundOnChange);
23669 this._onChange({ isPortrait: orientation.isPortrait() });
23670 } else {
23671 this._queryResult = window.matchMedia(this._target);
23672 this._queryResult.addListener(this._boundOnChange);
23673 this._onChange(this._queryResult);
23674 }
23675 }
23676 }, {
23677 key: 'disable',
23678 value: function disable() {
23679 if (this._orientation) {
23680 orientation.off('change', this._boundOnChange);
23681 } else if (this._queryResult) {
23682 this._queryResult.removeListener(this._boundOnChange);
23683 this._queryResult = null;
23684 }
23685 }
23686 }]);
23687 return CollapseDetection;
23688}();
23689
23690var widthToPx = function widthToPx(width, parent) {
23691 var _ref = [parseInt(width, 10), /px/.test(width)],
23692 value = _ref[0],
23693 px = _ref[1];
23694
23695 return px ? value : Math.round(parent.offsetWidth * value / 100);
23696};
23697
23698var CollapseMode = function () {
23699 createClass(CollapseMode, [{
23700 key: '_animator',
23701 get: function get() {
23702 return this._element._animator;
23703 }
23704 }]);
23705
23706 function CollapseMode(element) {
23707 classCallCheck(this, CollapseMode);
23708
23709 this._active = false;
23710 this._state = CLOSED_STATE;
23711 this._element = element;
23712 this._lock = new DoorLock();
23713 }
23714
23715 createClass(CollapseMode, [{
23716 key: 'isOpen',
23717 value: function isOpen() {
23718 return this._active && this._state !== CLOSED_STATE;
23719 }
23720 }, {
23721 key: 'handleGesture',
23722 value: function handleGesture(e) {
23723 if (!this._active || this._lock.isLocked() || this._isOpenOtherSideMenu()) {
23724 return;
23725 }
23726 if (e.type === 'dragstart') {
23727 this._onDragStart(e);
23728 } else if (!this._ignoreDrag) {
23729 e.type === 'dragend' ? this._onDragEnd(e) : this._onDrag(e);
23730 }
23731 }
23732 }, {
23733 key: '_onDragStart',
23734 value: function _onDragStart(event) {
23735 var scrolling = !/left|right/.test(event.gesture.direction);
23736 var distance = this._element._side === 'left' ? event.gesture.center.clientX : window.innerWidth - event.gesture.center.clientX;
23737 var area = this._element._swipeTargetWidth;
23738 var isOpen = this.isOpen();
23739 this._ignoreDrag = scrolling || area && distance > area && !isOpen;
23740
23741 this._width = widthToPx(this._element._width, this._element.parentNode);
23742 this._startDistance = this._distance = isOpen ? this._width : 0;
23743 }
23744 }, {
23745 key: '_onDrag',
23746 value: function _onDrag(event) {
23747 event.gesture.preventDefault();
23748 var delta = this._element._side === 'left' ? event.gesture.deltaX : -event.gesture.deltaX;
23749 var distance = Math.max(0, Math.min(this._width, this._startDistance + delta));
23750 if (distance !== this._distance) {
23751 this._animator.translate(distance);
23752 this._distance = distance;
23753 this._state = CHANGING_STATE;
23754 }
23755 }
23756 }, {
23757 key: '_onDragEnd',
23758 value: function _onDragEnd(event) {
23759 var distance = this._distance,
23760 width = this._width,
23761 el = this._element;
23762
23763 var direction = event.gesture.interimDirection;
23764 var shouldOpen = el._side !== direction && distance > width * el._threshold;
23765 this.executeAction(shouldOpen ? 'open' : 'close');
23766 this._ignoreDrag = true;
23767 }
23768 }, {
23769 key: 'layout',
23770 value: function layout() {
23771 if (this._active && this._state === OPEN_STATE) {
23772 this._animator.open();
23773 }
23774 }
23775
23776 // enter collapse mode
23777
23778 }, {
23779 key: 'enterMode',
23780 value: function enterMode() {
23781 if (!this._active) {
23782 this._active = true;
23783 this.layout();
23784 }
23785 }
23786
23787 // exit collapse mode
23788
23789 }, {
23790 key: 'exitMode',
23791 value: function exitMode() {
23792 this._active = false;
23793 }
23794 }, {
23795 key: '_isOpenOtherSideMenu',
23796 value: function _isOpenOtherSideMenu() {
23797 var _this = this;
23798
23799 return util.arrayFrom(this._element.parentElement.children).some(function (e) {
23800 return util.match(e, 'ons-splitter-side') && e !== _this._element && e.isOpen;
23801 });
23802 }
23803
23804 /**
23805 * @param {String} name - 'open' or 'close'
23806 * @param {Object} [options]
23807 * @param {Function} [options.callback]
23808 * @param {Boolean} [options.withoutAnimation]
23809 * @return {Promise} Resolves to the splitter side element or false if not in collapse mode
23810 */
23811
23812 }, {
23813 key: 'executeAction',
23814 value: function executeAction(name) {
23815 var _this2 = this;
23816
23817 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
23818
23819 var FINAL_STATE = name === 'open' ? OPEN_STATE : CLOSED_STATE;
23820
23821 if (!this._active) {
23822 return Promise.resolve(false);
23823 }
23824
23825 if (this._state === FINAL_STATE) {
23826 return Promise.resolve(this._element);
23827 }
23828 if (this._lock.isLocked()) {
23829 return Promise.reject('Splitter side is locked.');
23830 }
23831 if (name === 'open' && this._isOpenOtherSideMenu()) {
23832 return Promise.reject('Another menu is already open.');
23833 }
23834 if (this._element._emitEvent('pre' + name)) {
23835 return Promise.reject('Canceled in pre' + name + ' event.');
23836 }
23837
23838 var callback = options.callback;
23839 var unlock = this._lock.lock();
23840 var done = function done() {
23841 _this2._state = FINAL_STATE;
23842 _this2.layout();
23843 unlock();
23844 _this2._element._emitEvent('post' + name);
23845 callback && callback();
23846 };
23847
23848 if (options.withoutAnimation) {
23849 done();
23850 return Promise.resolve(this._element);
23851 }
23852 this._state = CHANGING_STATE;
23853 return new Promise(function (resolve) {
23854 _this2._animator[name](function () {
23855 done();
23856 resolve(_this2._element);
23857 });
23858 });
23859 }
23860 }]);
23861 return CollapseMode;
23862}();
23863
23864/**
23865 * @element ons-splitter-side
23866 * @category menu
23867 * @description
23868 * [en]
23869 * The `<ons-splitter-side>` element is used as a child element of `<ons-splitter>`.
23870 *
23871 * It will be displayed on either the left or right side of the `<ons-splitter-content>` element.
23872 *
23873 * It supports two modes: collapsed and split. When it's in collapsed mode it will be hidden from view and can be displayed when the user swipes the screen or taps a button. In split mode the element is always shown. It can be configured to automatically switch between the two modes depending on the screen size.
23874 * [/en]
23875 * [ja]ons-splitter-side要素は、ons-splitter要素の子要素として利用します。[/ja]
23876 * @codepen rOQOML
23877 * @tutorial vanilla/Reference/splitter
23878 * @guide multiple-page-navigation
23879 * [en]Managing multiple pages.[/en]
23880 * [ja]Managing multiple pages[/ja]
23881 * @seealso ons-splitter
23882 * [en]The `<ons-splitter>` is the parent component.[/en]
23883 * [ja]ons-splitterコンポーネント[/ja]
23884 * @seealso ons-splitter-content
23885 * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en]
23886 * [ja]ons-splitter-contentコンポーネント[/ja]
23887 * @example
23888 * <ons-splitter>
23889 * <ons-splitter-content>
23890 * ...
23891 * </ons-splitter-content>
23892 *
23893 * <ons-splitter-side side="left" width="80%" collapse>
23894 * ...
23895 * </ons-splitter-side>
23896 * </ons-splitter>
23897 */
23898
23899
23900var SplitterSideElement = function (_BaseElement) {
23901 inherits(SplitterSideElement, _BaseElement);
23902
23903 function SplitterSideElement() {
23904 classCallCheck(this, SplitterSideElement);
23905 return possibleConstructorReturn(this, (SplitterSideElement.__proto__ || Object.getPrototypeOf(SplitterSideElement)).apply(this, arguments));
23906 }
23907
23908 createClass(SplitterSideElement, [{
23909 key: 'init',
23910
23911
23912 /**
23913 * @event modechange
23914 * @description
23915 * [en]Fired just after the component's mode changes.[/en]
23916 * [ja]この要素のモードが変化した際に発火します。[/ja]
23917 * @param {Object} event
23918 * [en]Event object.[/en]
23919 * [ja]イベントオブジェクトです。[/ja]
23920 * @param {Object} event.side
23921 * [en]Component object.[/en]
23922 * [ja]コンポーネントのオブジェクト。[/ja]
23923 * @param {String} event.mode
23924 * [en]Returns the current mode. Can be either `"collapse"` or `"split"`.[/en]
23925 * [ja]現在のモードを返します。[/ja]
23926 */
23927
23928 /**
23929 * @event preopen
23930 * @description
23931 * [en]Fired just before the sliding menu is opened.[/en]
23932 * [ja]スライディングメニューが開く前に発火します。[/ja]
23933 * @param {Object} event
23934 * [en]Event object.[/en]
23935 * [ja]イベントオブジェクトです。[/ja]
23936 * @param {Function} event.cancel
23937 * [en]Call to cancel opening sliding menu.[/en]
23938 * [ja]スライディングメニューが開くのをキャンセルします。[/ja]
23939 * @param {Object} event.side
23940 * [en]Component object.[/en]
23941 * [ja]コンポーネントのオブジェクト。[/ja]
23942 */
23943
23944 /**
23945 * @event postopen
23946 * @description
23947 * [en]Fired just after the sliding menu is opened.[/en]
23948 * [ja]スライディングメニューが開いた後に発火します。[/ja]
23949 * @param {Object} event
23950 * [en]Event object.[/en]
23951 * [ja]イベントオブジェクトです。[/ja]
23952 * @param {Object} event.side
23953 * [en]Component object.[/en]
23954 * [ja]コンポーネントのオブジェクト。[/ja]
23955 */
23956
23957 /**
23958 * @event preclose
23959 * @description
23960 * [en]Fired just before the sliding menu is closed.[/en]
23961 * [ja]スライディングメニューが閉じる前に発火します。[/ja]
23962 * @param {Object} event
23963 * [en]Event object.[/en]
23964 * [ja]イベントオブジェクトです。[/ja]
23965 * @param {Object} event.side
23966 * [en]Component object.[/en]
23967 * [ja]コンポーネントのオブジェクト。[/ja]
23968 * @param {Function} event.cancel
23969 * [en]Call to cancel opening sliding-menu.[/en]
23970 * [ja]スライディングメニューが閉じるのをキャンセルします。[/ja]
23971 */
23972
23973 /**
23974 * @event postclose
23975 * @description
23976 * [en]Fired just after the sliding menu is closed.[/en]
23977 * [ja]スライディングメニューが閉じた後に発火します。[/ja]
23978 * @param {Object} event
23979 * [en]Event object.[/en]
23980 * [ja]イベントオブジェクトです。[/ja]
23981 * @param {Object} event.side
23982 * [en]Component object.[/en]
23983 * [ja]コンポーネントのオブジェクト。[/ja]
23984 */
23985
23986 /**
23987 * @attribute animation
23988 * @type {String}
23989 * @default default
23990 * @description
23991 * [en]Specify the animation. Use one of `"overlay"`, and `"default"`.[/en]
23992 * [ja]アニメーションを指定します。"overlay", "default"のいずれかを指定できます。[/ja]
23993 */
23994
23995 /**
23996 * @attribute animation-options
23997 * @type {Expression}
23998 * @description
23999 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
24000 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
24001 */
24002
24003 /**
24004 * @attribute open-threshold
24005 * @type {Number}
24006 * @default 0.3
24007 * @description
24008 * [en]Specify how much the menu needs to be swiped before opening. A value between `0` and `1`.[/en]
24009 * [ja]どのくらいスワイプすればスライディングメニューを開くかどうかの割合を指定します。0から1の間の数値を指定します。スワイプの距離がここで指定した数値掛けるこの要素の幅よりも大きければ、スワイプが終わった時にこの要素を開きます。デフォルトは0.3です。[/ja]
24010 */
24011
24012 /**
24013 * @attribute collapse
24014 * @type {String}
24015 * @description
24016 * [en]
24017 * Specify the collapse behavior. Valid values are `"portrait"`, `"landscape"` or a media query.
24018 * The strings `"portrait"` and `"landscape"` means the view will collapse when device is in landscape or portrait orientation.
24019 * If the value is a media query, the view will collapse when the media query resolves to `true`.
24020 * If the value is not defined, the view always be in `"collapse"` mode.
24021 * [/en]
24022 * [ja]
24023 * 左側のページを非表示にする条件を指定します。portrait, landscape、width #pxもしくはメディアクエリの指定が可能です。
24024 * portraitもしくはlandscapeを指定すると、デバイスの画面が縦向きもしくは横向きになった時に適用されます。
24025 * メディアクエリを指定すると、指定したクエリに適合している場合に適用されます。
24026 * 値に何も指定しない場合には、常にcollapseモードになります。
24027 * [/ja]
24028 */
24029
24030 /**
24031 * @attribute swipe-target-width
24032 * @type {String}
24033 * @description
24034 * [en]The width of swipeable area calculated from the edge (in pixels). Use this to enable swipe only when the finger touch on the screen edge.[/en]
24035 * [ja]スワイプの判定領域をピクセル単位で指定します。画面の端から指定した距離に達するとページが表示されます。[/ja]
24036 */
24037
24038 /**
24039 * @attribute width
24040 * @type {String}
24041 * @description
24042 * [en]Can be specified in either pixels or as a percentage, e.g. `90%` or `200px`.[/en]
24043 * [ja]この要素の横幅を指定します。pxと%での指定が可能です。eg. 90%, 200px[/ja]
24044 */
24045
24046 /**
24047 * @attribute side
24048 * @type {String}
24049 * @default left
24050 * @description
24051 * [en]Specify which side of the screen the `<ons-splitter-side>` element is located. Possible values are `"left"` and `"right"`.[/en]
24052 * [ja]この要素が左か右かを指定します。指定できる値は"left"か"right"のみです。[/ja]
24053 */
24054
24055 /**
24056 * @attribute mode
24057 * @type {String}
24058 * @description
24059 * [en]Current mode. Possible values are `"collapse"` or `"split"`. This attribute is read only.[/en]
24060 * [ja]現在のモードが設定されます。"collapse"もしくは"split"が指定されます。この属性は読み込み専用です。[/ja]
24061 */
24062
24063 /**
24064 * @attribute page
24065 * @initonly
24066 * @type {String}
24067 * @description
24068 * [en]The URL of the menu page.[/en]
24069 * [ja]ons-splitter-side要素に表示するページのURLを指定します。[/ja]
24070 */
24071
24072 /**
24073 * @attribute swipeable
24074 * @type {Boolean}
24075 * @description
24076 * [en]Whether to enable swipe interaction on collapse mode.[/en]
24077 * [ja]collapseモード時にスワイプ操作を有効にする場合に指定します。[/ja]
24078 */
24079
24080 value: function init() {
24081 var _this4 = this;
24082
24083 this._page = null;
24084 this._pageLoader = defaultPageLoader;
24085 this._collapseMode = new CollapseMode(this);
24086 this._collapseDetection = new CollapseDetection(this);
24087
24088 this._animatorFactory = new AnimatorFactory({
24089 animators: SplitterElement.animators,
24090 baseClass: SplitterAnimator,
24091 baseClassName: 'SplitterAnimator',
24092 defaultAnimation: this.getAttribute('animation')
24093 });
24094 this._boundHandleGesture = function (e) {
24095 return _this4._collapseMode.handleGesture(e);
24096 };
24097 this._watchedAttributes = WATCHED_ATTRIBUTES;
24098 contentReady(this, function () {
24099 rewritables$2.ready(_this4, function () {
24100 var page = _this4._getPageTarget();
24101
24102 if (page) {
24103 _this4.load(page);
24104 }
24105 });
24106 });
24107 }
24108 }, {
24109 key: 'connectedCallback',
24110 value: function connectedCallback() {
24111 var _this5 = this;
24112
24113 if (!util.match(this.parentNode, 'ons-splitter')) {
24114 throw new Error('Parent must be an ons-splitter element.');
24115 }
24116
24117 this._gestureDetector = new GestureDetector(this.parentElement, { dragMinDistance: 1 });
24118
24119 contentReady(this, function () {
24120 _this5._watchedAttributes.forEach(function (e) {
24121 return _this5._update(e);
24122 });
24123 });
24124
24125 if (!this.hasAttribute('side')) {
24126 this.setAttribute('side', 'left');
24127 }
24128 }
24129 }, {
24130 key: '_getPageTarget',
24131 value: function _getPageTarget() {
24132 return this._page || this.getAttribute('page');
24133 }
24134 }, {
24135 key: 'disconnectedCallback',
24136 value: function disconnectedCallback() {
24137 this._collapseDetection.disable();
24138 this._gestureDetector.dispose();
24139 this._gestureDetector = null;
24140 }
24141 }, {
24142 key: 'attributeChangedCallback',
24143 value: function attributeChangedCallback(name, last, current) {
24144 this._update(name, current);
24145 }
24146 }, {
24147 key: '_update',
24148 value: function _update(name, value) {
24149 name = '_update' + name.split('-').map(function (e) {
24150 return e[0].toUpperCase() + e.slice(1);
24151 }).join('');
24152 return this[name](value);
24153 }
24154 }, {
24155 key: '_emitEvent',
24156 value: function _emitEvent(name) {
24157 if (name.slice(0, 3) !== 'pre') {
24158 return util.triggerElementEvent(this, name, { side: this });
24159 }
24160 var isCanceled = false;
24161
24162 util.triggerElementEvent(this, name, {
24163 side: this,
24164 cancel: function cancel() {
24165 return isCanceled = true;
24166 }
24167 });
24168
24169 return isCanceled;
24170 }
24171 }, {
24172 key: '_updateCollapse',
24173 value: function _updateCollapse() {
24174 var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('collapse');
24175
24176 if (value === null || value === 'split') {
24177 this._collapseDetection.disable();
24178 return this._updateMode(SPLIT_MODE);
24179 }
24180 if (value === '' || value === 'collapse') {
24181 this._collapseDetection.disable();
24182 return this._updateMode(COLLAPSE_MODE);
24183 }
24184
24185 this._collapseDetection.changeTarget(value);
24186 }
24187
24188 // readonly attribute for the users
24189
24190 }, {
24191 key: '_updateMode',
24192 value: function _updateMode(mode) {
24193 if (mode !== this._mode) {
24194 this._mode = mode;
24195 this._collapseMode[mode === COLLAPSE_MODE ? 'enterMode' : 'exitMode']();
24196 this.setAttribute('mode', mode);
24197
24198 util.triggerElementEvent(this, 'modechange', { side: this, mode: mode });
24199 }
24200 }
24201 }, {
24202 key: '_updateOpenThreshold',
24203 value: function _updateOpenThreshold() {
24204 var threshold = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('open-threshold');
24205
24206 this._threshold = Math.max(0, Math.min(1, parseFloat(threshold) || 0.3));
24207 }
24208 }, {
24209 key: '_updateSwipeable',
24210 value: function _updateSwipeable() {
24211 var swipeable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('swipeable');
24212
24213 var action = swipeable === null ? 'off' : 'on';
24214
24215 if (this._gestureDetector) {
24216 this._gestureDetector[action]('dragstart dragleft dragright dragend', this._boundHandleGesture);
24217 }
24218 }
24219 }, {
24220 key: '_updateSwipeTargetWidth',
24221 value: function _updateSwipeTargetWidth() {
24222 var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('swipe-target-width');
24223
24224 this._swipeTargetWidth = Math.max(0, parseInt(value) || 0);
24225 }
24226 }, {
24227 key: '_updateWidth',
24228 value: function _updateWidth() {
24229 this.style.width = this._width;
24230 }
24231 }, {
24232 key: '_updateSide',
24233 value: function _updateSide() {
24234 var side = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('side');
24235
24236 this._side = side === 'right' ? side : 'left';
24237 }
24238 }, {
24239 key: '_updateAnimation',
24240 value: function _updateAnimation() {
24241 var animation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation');
24242
24243 this._animator = this._animatorFactory.newAnimator({ animation: animation });
24244 this._animator.activate(this);
24245 }
24246 }, {
24247 key: '_updateAnimationOptions',
24248 value: function _updateAnimationOptions() {
24249 var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation-options');
24250
24251 this._animator.updateOptions(AnimatorFactory.parseAnimationOptionsString(value));
24252 }
24253
24254 /**
24255 * @property page
24256 * @type {*}
24257 * @description
24258 * [en]Page location to load in the splitter side.[/en]
24259 * [ja]この要素内に表示するページを指定します。[/ja]
24260 */
24261
24262 }, {
24263 key: 'open',
24264
24265
24266 /**
24267 * @method open
24268 * @signature open([options])
24269 * @param {Object} [options]
24270 * [en]Parameter object.[/en]
24271 * [ja]オプションを指定するオブジェクト。[/ja]
24272 * @param {Function} [options.callback]
24273 * [en]This function will be called after the menu has been opened.[/en]
24274 * [ja]メニューが開いた後に呼び出される関数オブジェクトを指定します。[/ja]
24275 * @description
24276 * [en]Open menu in collapse mode.[/en]
24277 * [ja]collapseモードになっているons-splitter-side要素を開きます。[/ja]
24278 * @return {Promise}
24279 * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
24280 * [ja][/ja]
24281 */
24282 value: function open() {
24283 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
24284
24285 return this._collapseMode.executeAction('open', options);
24286 }
24287
24288 /**
24289 * @method close
24290 * @signature close([options])
24291 * @param {Object} [options]
24292 * [en]Parameter object.[/en]
24293 * [ja]オプションを指定するオブジェクト。[/ja]
24294 * @param {Function} [options.callback]
24295 * [en]This function will be called after the menu has been closed.[/en]
24296 * [ja]メニューが閉じた後に呼び出される関数オブジェクトを指定します。[/ja]
24297 * @description
24298 * [en]Close menu in collapse mode.[/en]
24299 * [ja]collapseモードになっているons-splitter-side要素を閉じます。[/ja]
24300 * @return {Promise}
24301 * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
24302 * [ja][/ja]
24303 */
24304
24305 }, {
24306 key: 'close',
24307 value: function close() {
24308 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
24309
24310 return this._collapseMode.executeAction('close', options);
24311 }
24312
24313 /**
24314 * @method toggle
24315 * @signature toggle([options])
24316 * @param {Object} [options]
24317 * @description
24318 * [en]Opens if it's closed. Closes if it's open.[/en]
24319 * [ja]開けている場合は要素を閉じますそして開けている場合は要素を開きます。[/ja]
24320 * @return {Promise}
24321 * [en]Resolves to the splitter side element or false if not in collapse mode[/en]
24322 * [ja][/ja]
24323 */
24324
24325 }, {
24326 key: 'toggle',
24327 value: function toggle() {
24328 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
24329
24330 return this.isOpen ? this.close(options) : this.open(options);
24331 }
24332
24333 /**
24334 * @method load
24335 * @signature load(page, [options])
24336 * @param {String} page
24337 * [en]Page URL. Can be either an HTML document or an <ons-template>.[/en]
24338 * [ja]pageのURLか、ons-templateで宣言したテンプレートのid属性の値を指定します。[/ja]
24339 * @param {Object} [options]
24340 * @param {Function} [options.callback]
24341 * @description
24342 * [en]Show the page specified in pageUrl in the right section[/en]
24343 * [ja]指定したURLをメインページを読み込みます。[/ja]
24344 * @return {Promise}
24345 * [en]Resolves to the new page element[/en]
24346 * [ja][/ja]
24347 */
24348
24349 }, {
24350 key: 'load',
24351 value: function load(page) {
24352 var _this6 = this;
24353
24354 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
24355
24356 this._page = page;
24357 var callback = options.callback || function () {};
24358
24359 return new Promise(function (resolve) {
24360 _this6._pageLoader.load({ page: page, parent: _this6, replace: true }, function (_ref2) {
24361 var element = _ref2.element,
24362 unload = _ref2.unload;
24363
24364 rewritables$2.link(_this6, element, options, function (fragment) {
24365 setImmediate(function () {
24366 return _this6._show();
24367 });
24368 callback();
24369
24370 resolve(_this6.firstChild);
24371 });
24372 });
24373 });
24374 }
24375 }, {
24376 key: '_show',
24377 value: function _show() {
24378 util.propagateAction(this, '_show');
24379 }
24380 }, {
24381 key: '_hide',
24382 value: function _hide() {
24383 util.propagateAction(this, '_hide');
24384 }
24385 }, {
24386 key: '_destroy',
24387 value: function _destroy() {
24388 util.propagateAction(this, '_destroy');
24389 this.remove();
24390 }
24391 }, {
24392 key: 'side',
24393 get: function get() {
24394 return this.getAttribute('side') === 'right' ? 'right' : 'left';
24395 }
24396 }, {
24397 key: '_width',
24398 get: function get() {
24399 var width = this.getAttribute('width');
24400 return (/^\d+(px|%)$/.test(width) ? width : '80%'
24401 );
24402 },
24403 set: function set(value) {
24404 this.setAttribute('width', value);
24405 }
24406 }, {
24407 key: 'page',
24408 get: function get() {
24409 return this._page;
24410 }
24411
24412 /**
24413 * @param {*} page
24414 */
24415 ,
24416 set: function set(page) {
24417 this._page = page;
24418 }
24419
24420 /**
24421 * @property pageLoader
24422 * @description
24423 * [en][/en]
24424 * [ja][/ja]
24425 */
24426
24427 }, {
24428 key: 'pageLoader',
24429 get: function get() {
24430 return this._pageLoader;
24431 },
24432 set: function set(loader) {
24433 if (!(loader instanceof PageLoader)) {
24434 throw Error('First parameter must be an instance of PageLoader.');
24435 }
24436 this._pageLoader = loader;
24437 }
24438
24439 /**
24440 * @property mode
24441 * @readonly
24442 * @type {String}
24443 * @description
24444 * [en]Current mode. Possible values are "split", "collapse", "closed", "open" or "changing".[/en]
24445 * [ja][/ja]
24446 */
24447
24448 }, {
24449 key: 'mode',
24450 get: function get() {
24451 return this._mode;
24452 }
24453
24454 /**
24455 * @property isOpen
24456 * @type {Boolean}
24457 * @readonly
24458 * @description
24459 * [en]This value is `true` when the menu is open..[/en]
24460 * [ja][/ja]
24461 */
24462
24463 }, {
24464 key: 'isOpen',
24465 get: function get() {
24466 return this._collapseMode.isOpen();
24467 }
24468 }], [{
24469 key: 'observedAttributes',
24470 get: function get() {
24471 return WATCHED_ATTRIBUTES;
24472 }
24473 }, {
24474 key: 'rewritables',
24475 get: function get() {
24476 return rewritables$2;
24477 }
24478 }]);
24479 return SplitterSideElement;
24480}(BaseElement);
24481
24482customElements.define('ons-splitter-side', SplitterSideElement);
24483
24484/*
24485Copyright 2013-2015 ASIAL CORPORATION
24486
24487Licensed under the Apache License, Version 2.0 (the "License");
24488you may not use this file except in compliance with the License.
24489You may obtain a copy of the License at
24490
24491 http://www.apache.org/licenses/LICENSE-2.0
24492
24493Unless required by applicable law or agreed to in writing, software
24494distributed under the License is distributed on an "AS IS" BASIS,
24495WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24496See the License for the specific language governing permissions and
24497limitations under the License.
24498
24499*/
24500
24501var scheme$19 = {
24502 '': 'switch--*',
24503 '.switch__input': 'switch--*__input',
24504 '.switch__handle': 'switch--*__handle',
24505 '.switch__toggle': 'switch--*__toggle'
24506};
24507
24508var template$2 = util.createFragment('\n <input type="checkbox" class="switch__input">\n <div class="switch__toggle">\n <div class="switch__handle">\n <div class="switch__touch"></div>\n </div>\n </div>\n');
24509
24510var locations = {
24511 ios: [1, 21],
24512 material: [0, 16]
24513};
24514
24515/**
24516 * @element ons-switch
24517 * @category form
24518 * @description
24519 * [en]
24520 * Switch component. The switch can be toggled both by dragging and tapping.
24521 *
24522 * Will automatically displays a Material Design switch on Android devices.
24523 * [/en]
24524 * [ja]スイッチを表示するコンポーネントです。[/ja]
24525 * @modifier material
24526 * [en]Material Design switch[/en]
24527 * [ja][/ja]
24528 * @codepen LpXZQQ
24529 * @tutorial vanilla/Reference/switch
24530 * @guide adding-page-content
24531 * [en]Using form components[/en]
24532 * [ja]フォームを使う[/ja]
24533 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
24534 * @example
24535 * <ons-switch checked></ons-switch>
24536 * <ons-switch disabled></ons-switch>
24537 * <ons-switch modifier="material"></ons-switch>
24538 */
24539
24540var SwitchElement = function (_BaseElement) {
24541 inherits(SwitchElement, _BaseElement);
24542
24543 function SwitchElement() {
24544 classCallCheck(this, SwitchElement);
24545 return possibleConstructorReturn(this, (SwitchElement.__proto__ || Object.getPrototypeOf(SwitchElement)).apply(this, arguments));
24546 }
24547
24548 createClass(SwitchElement, [{
24549 key: 'init',
24550 value: function init() {
24551 var _this2 = this;
24552
24553 this._checked = false;
24554 this._disabled = false;
24555
24556 this._boundOnChange = this._onChange.bind(this);
24557
24558 contentReady(this, function () {
24559 _this2._compile();
24560 ['checked', 'disabled', 'modifier', 'name', 'input-id'].forEach(function (e) {
24561 _this2.attributeChangedCallback(e, null, _this2.getAttribute(e));
24562 });
24563 });
24564 }
24565 }, {
24566 key: '_compile',
24567 value: function _compile() {
24568 autoStyle.prepare(this);
24569
24570 this.classList.add('switch');
24571
24572 if (!(util.findChild(this, '.switch__input') && util.findChild(this, '.switch__toggle'))) {
24573 this.appendChild(template$2.cloneNode(true));
24574 }
24575
24576 ModifierUtil.initModifier(this, scheme$19);
24577
24578 this._checkbox = this.querySelector('.switch__input');
24579 this._handle = this.querySelector('.switch__handle');
24580
24581 this._checkbox.checked = this._checked;
24582 this._checkbox.disbled = this._disabled;
24583 }
24584 }, {
24585 key: 'disconnectedCallback',
24586 value: function disconnectedCallback() {
24587 var _this3 = this;
24588
24589 contentReady(this, function () {
24590 _this3._checkbox.removeEventListener('change', _this3._boundOnChange);
24591 _this3.removeEventListener('dragstart', _this3._onDragStart);
24592 _this3.removeEventListener('hold', _this3._onHold);
24593 _this3.removeEventListener('tap', _this3.click);
24594 _this3.removeEventListener('click', _this3._onClick);
24595 if (_this3._gestureDetector) {
24596 _this3._gestureDetector.dispose();
24597 }
24598 });
24599 }
24600 }, {
24601 key: 'connectedCallback',
24602 value: function connectedCallback() {
24603 var _this4 = this;
24604
24605 contentReady(this, function () {
24606 _this4._checkbox.addEventListener('change', _this4._boundOnChange);
24607 _this4.addEventListener('dragstart', _this4._onDragStart);
24608 _this4.addEventListener('hold', _this4._onHold);
24609 _this4.addEventListener('tap', _this4.click);
24610 _this4.addEventListener('click', _this4._onClick);
24611 _this4._gestureDetector = new GestureDetector(_this4, { dragMinDistance: 1, holdTimeout: 251 });
24612 _this4._boundOnRelease = _this4._onRelease.bind(_this4);
24613 });
24614 }
24615 }, {
24616 key: '_onChange',
24617 value: function _onChange(event) {
24618 util.toggleAttribute(this, 'checked', this.checkbox.checked);
24619 }
24620 }, {
24621 key: '_onClick',
24622 value: function _onClick(ev) {
24623 if (ev.target.classList.contains('switch__touch')) {
24624 ev.preventDefault();
24625 }
24626 }
24627 }, {
24628 key: 'click',
24629 value: function click() {
24630 if (!this._disabled) {
24631 this.checked = !this.checked;
24632
24633 util.triggerElementEvent(this, 'change', {
24634 value: this.checked,
24635 switch: this,
24636 isInteractive: true
24637 });
24638 }
24639 }
24640 }, {
24641 key: '_getPosition',
24642 value: function _getPosition(e) {
24643 var l = this._locations;
24644 return Math.min(l[1], Math.max(l[0], this._startX + e.gesture.deltaX));
24645 }
24646 }, {
24647 key: '_onHold',
24648 value: function _onHold(e) {
24649 if (!this.disabled) {
24650 this.classList.add('switch--active');
24651 document.addEventListener('release', this._boundOnRelease);
24652 }
24653 }
24654 }, {
24655 key: '_onDragStart',
24656 value: function _onDragStart(e) {
24657 if (this.disabled || ['left', 'right'].indexOf(e.gesture.direction) === -1) {
24658 this.classList.remove('switch--active');
24659 return;
24660 }
24661
24662 e.stopPropagation();
24663
24664 this.classList.add('switch--active');
24665 this._startX = this._locations[this.checked ? 1 : 0]; // - e.gesture.deltaX;
24666
24667 this.addEventListener('drag', this._onDrag);
24668 document.addEventListener('release', this._boundOnRelease);
24669 }
24670 }, {
24671 key: '_onDrag',
24672 value: function _onDrag(e) {
24673 e.gesture.srcEvent.preventDefault();
24674 this._handle.style.left = this._getPosition(e) + 'px';
24675 }
24676 }, {
24677 key: '_onRelease',
24678 value: function _onRelease(e) {
24679 var l = this._locations;
24680 var position = this._getPosition(e);
24681 var previousValue = this.checked;
24682
24683 this.checked = position >= (l[0] + l[1]) / 2;
24684
24685 if (this.checked !== previousValue) {
24686 util.triggerElementEvent(this, 'change', {
24687 value: this.checked,
24688 switch: this,
24689 isInteractive: true
24690 });
24691 }
24692
24693 this.removeEventListener('drag', this._onDrag);
24694 document.removeEventListener('release', this._boundOnRelease);
24695
24696 this._handle.style.left = '';
24697 this.classList.remove('switch--active');
24698 }
24699 }, {
24700 key: 'attributeChangedCallback',
24701 value: function attributeChangedCallback(name, last, current) {
24702 var _this5 = this;
24703
24704 contentReady(this, function () {
24705 switch (name) {
24706 case 'modifier':
24707 _this5._isMaterial = (current || '').indexOf('material') !== -1;
24708 _this5._locations = locations[_this5._isMaterial ? 'material' : 'ios'];
24709 ModifierUtil.onModifierChanged(last, current, _this5, scheme$19);
24710 break;
24711 case 'input-id':
24712 _this5._checkbox.id = current;
24713 break;
24714 case 'checked':
24715 _this5._checked = current !== null;
24716 _this5._checkbox.checked = current !== null;
24717 util.toggleAttribute(_this5._checkbox, name, current !== null);
24718 break;
24719 case 'disabled':
24720 _this5._disabled = current !== null;
24721 _this5._checkbox.disabled = current !== null;
24722 util.toggleAttribute(_this5._checkbox, name, current !== null);
24723 }
24724 });
24725 }
24726 }, {
24727 key: 'checked',
24728
24729
24730 /**
24731 * @event change
24732 * @description
24733 * [en]Fired when the switch is toggled.[/en]
24734 * [ja]ON/OFFが変わった時に発火します。[/ja]
24735 * @param {Object} event
24736 * [en]Event object.[/en]
24737 * [ja]イベントオブジェクト。[/ja]
24738 * @param {Object} event.switch
24739 * [en]Switch object.[/en]
24740 * [ja]イベントが発火したSwitchオブジェクトを返します。[/ja]
24741 * @param {Boolean} event.value
24742 * [en]Current value.[/en]
24743 * [ja]現在の値を返します。[/ja]
24744 * @param {Boolean} event.isInteractive
24745 * [en]True if the change was triggered by the user clicking on the switch.[/en]
24746 * [ja]タップやクリックなどのユーザの操作によって変わった場合にはtrueを返します。[/ja]
24747 */
24748
24749 /**
24750 * @attribute modifier
24751 * @type {String}
24752 * @description
24753 * [en]The appearance of the switch.[/en]
24754 * [ja]スイッチの表現を指定します。[/ja]
24755 */
24756
24757 /**
24758 * @attribute disabled
24759 * @description
24760 * [en]Whether the switch is be disabled.[/en]
24761 * [ja]スイッチを無効の状態にする場合に指定します。[/ja]
24762 */
24763
24764 /**
24765 * @attribute checked
24766 * @description
24767 * [en]Whether the switch is checked.[/en]
24768 * [ja]スイッチがONの状態にするときに指定します。[/ja]
24769 */
24770
24771 /**
24772 * @attribute input-id
24773 * @type {String}
24774 * @description
24775 * [en]Specify the `id` attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
24776 * [ja][/ja]
24777 */
24778
24779 /**
24780 * @property checked
24781 * @type {Boolean}
24782 * @description
24783 * [en]This value is `true` if the switch is checked.[/en]
24784 * [ja]スイッチがONの場合に`true`。[/ja]
24785 */
24786
24787 get: function get() {
24788 return this._checked;
24789 },
24790 set: function set(value) {
24791 this._checked = !!value;
24792 util.toggleAttribute(this, 'checked', this._checked);
24793 }
24794
24795 /**
24796 * @property disabled
24797 * @type {Boolean}
24798 * @description
24799 * [en]Whether the element is disabled or not.[/en]
24800 * [ja]無効化されている場合に`true`。[/ja]
24801 */
24802
24803 }, {
24804 key: 'disabled',
24805 get: function get() {
24806 return this._disabled;
24807 },
24808 set: function set(value) {
24809 this._disabled = !!value;
24810 util.toggleAttribute(this, 'disabled', this._disabled);
24811 this._checkbox.disabled = this._disabled;
24812 }
24813
24814 /**
24815 * @property checkbox
24816 * @readonly
24817 * @type {HTMLElement}
24818 * @description
24819 * [en]The underlying checkbox element.[/en]
24820 * [ja]コンポーネント内部のcheckbox要素になります。[/ja]
24821 */
24822
24823 }, {
24824 key: 'checkbox',
24825 get: function get() {
24826 return this._checkbox;
24827 }
24828 }], [{
24829 key: 'observedAttributes',
24830 get: function get() {
24831 return ['modifier', 'input-id', 'checked', 'disabled'];
24832 }
24833 }]);
24834 return SwitchElement;
24835}(BaseElement);
24836
24837customElements.define('ons-switch', SwitchElement);
24838
24839/*
24840Copyright 2013-2015 ASIAL CORPORATION
24841
24842Licensed under the Apache License, Version 2.0 (the "License");
24843you may not use this file except in compliance with the License.
24844You may obtain a copy of the License at
24845
24846 http://www.apache.org/licenses/LICENSE-2.0
24847
24848Unless required by applicable law or agreed to in writing, software
24849distributed under the License is distributed on an "AS IS" BASIS,
24850WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24851See the License for the specific language governing permissions and
24852limitations under the License.
24853
24854*/
24855
24856var TabbarAnimator = function () {
24857
24858 /**
24859 * @param {Object} options
24860 * @param {String} options.timing
24861 * @param {Number} options.duration
24862 * @param {Number} options.delay
24863 */
24864 function TabbarAnimator() {
24865 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
24866 classCallCheck(this, TabbarAnimator);
24867
24868 this.timing = options.timing || 'linear';
24869 this.duration = options.duration !== undefined ? options.duration : '0.4';
24870 this.delay = options.delay !== undefined ? options.delay : '0';
24871 }
24872
24873 /**
24874 * @param {Element} enterPage ons-page element
24875 * @param {Element} leavePage ons-page element
24876 * @param {Number} enterPageIndex
24877 * @param {Number} leavePageIndex
24878 * @param {Function} done
24879 */
24880
24881
24882 createClass(TabbarAnimator, [{
24883 key: 'apply',
24884 value: function apply(enterPage, leavePage, enterPageIndex, leavePageIndex, done) {
24885 throw new Error('This method must be implemented.');
24886 }
24887 }]);
24888 return TabbarAnimator;
24889}();
24890
24891var TabbarNoneAnimator = function (_TabbarAnimator) {
24892 inherits(TabbarNoneAnimator, _TabbarAnimator);
24893
24894 function TabbarNoneAnimator() {
24895 classCallCheck(this, TabbarNoneAnimator);
24896 return possibleConstructorReturn(this, (TabbarNoneAnimator.__proto__ || Object.getPrototypeOf(TabbarNoneAnimator)).apply(this, arguments));
24897 }
24898
24899 createClass(TabbarNoneAnimator, [{
24900 key: 'apply',
24901 value: function apply(enterPage, leavePage, enterIndex, leaveIndex, done) {
24902 setTimeout(done, 1000 / 60);
24903 }
24904 }]);
24905 return TabbarNoneAnimator;
24906}(TabbarAnimator);
24907
24908var TabbarFadeAnimator = function (_TabbarAnimator2) {
24909 inherits(TabbarFadeAnimator, _TabbarAnimator2);
24910
24911 function TabbarFadeAnimator(options) {
24912 classCallCheck(this, TabbarFadeAnimator);
24913
24914 options.timing = options.timing !== undefined ? options.timing : 'linear';
24915 options.duration = options.duration !== undefined ? options.duration : '0.4';
24916 options.delay = options.delay !== undefined ? options.delay : '0';
24917
24918 return possibleConstructorReturn(this, (TabbarFadeAnimator.__proto__ || Object.getPrototypeOf(TabbarFadeAnimator)).call(this, options));
24919 }
24920
24921 createClass(TabbarFadeAnimator, [{
24922 key: 'apply',
24923 value: function apply(enterPage, leavePage, enterPageIndex, leavePageIndex, done) {
24924 animit.runAll(animit(enterPage).saveStyle().queue({
24925 transform: 'translate3D(0, 0, 0)',
24926 opacity: 0
24927 }).wait(this.delay).queue({
24928 transform: 'translate3D(0, 0, 0)',
24929 opacity: 1
24930 }, {
24931 duration: this.duration,
24932 timing: this.timing
24933 }).restoreStyle().queue(function (callback) {
24934 done();
24935 callback();
24936 }), animit(leavePage).queue({
24937 transform: 'translate3D(0, 0, 0)',
24938 opacity: 1
24939 }).wait(this.delay).queue({
24940 transform: 'translate3D(0, 0, 0)',
24941 opacity: 0
24942 }, {
24943 duration: this.duration,
24944 timing: this.timing
24945 }));
24946 }
24947 }]);
24948 return TabbarFadeAnimator;
24949}(TabbarAnimator);
24950
24951var TabbarSlideAnimator = function (_TabbarAnimator3) {
24952 inherits(TabbarSlideAnimator, _TabbarAnimator3);
24953
24954 function TabbarSlideAnimator(options) {
24955 classCallCheck(this, TabbarSlideAnimator);
24956
24957 options.timing = options.timing !== undefined ? options.timing : 'ease-in';
24958 options.duration = options.duration !== undefined ? options.duration : '0.15';
24959 options.delay = options.delay !== undefined ? options.delay : '0';
24960
24961 return possibleConstructorReturn(this, (TabbarSlideAnimator.__proto__ || Object.getPrototypeOf(TabbarSlideAnimator)).call(this, options));
24962 }
24963
24964 /**
24965 * @param {jqLite} enterPage
24966 * @param {jqLite} leavePage
24967 */
24968
24969
24970 createClass(TabbarSlideAnimator, [{
24971 key: 'apply',
24972 value: function apply(enterPage, leavePage, enterIndex, leaveIndex, done) {
24973 var sgn = enterIndex > leaveIndex;
24974
24975 animit.runAll(animit(enterPage).saveStyle().queue({
24976 transform: 'translate3D(' + (sgn ? '' : '-') + '100%, 0, 0)'
24977 }).wait(this.delay).queue({
24978 transform: 'translate3D(0, 0, 0)'
24979 }, {
24980 duration: this.duration,
24981 timing: this.timing
24982 }).restoreStyle().queue(function (callback) {
24983 done();
24984 callback();
24985 }), animit(leavePage).queue({
24986 transform: 'translate3D(0, 0, 0)'
24987 }).wait(this.delay).queue({
24988 transform: 'translate3D(' + (sgn ? '-' : '') + '100%, 0, 0)'
24989 }, {
24990 duration: this.duration,
24991 timing: this.timing
24992 }));
24993 }
24994 }]);
24995 return TabbarSlideAnimator;
24996}(TabbarAnimator);
24997
24998/*
24999Copyright 2013-2015 ASIAL CORPORATION
25000
25001Licensed under the Apache License, Version 2.0 (the "License");
25002you may not use this file except in compliance with the License.
25003You may obtain a copy of the License at
25004
25005 http://www.apache.org/licenses/LICENSE-2.0
25006
25007Unless required by applicable law or agreed to in writing, software
25008distributed under the License is distributed on an "AS IS" BASIS,
25009WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25010See the License for the specific language governing permissions and
25011limitations under the License.
25012
25013*/
25014
25015var scheme$21 = {
25016 '.tab-bar__content': 'tab-bar--*__content',
25017 '.tab-bar': 'tab-bar--*'
25018};
25019
25020var _animatorDict$6 = {
25021 'default': TabbarNoneAnimator,
25022 'fade': TabbarFadeAnimator,
25023 'slide': TabbarSlideAnimator,
25024 'none': TabbarNoneAnimator
25025};
25026
25027var rewritables$3 = {
25028 /**
25029 * @param {Element} tabbarElement
25030 * @param {Function} callback
25031 */
25032 ready: function ready(tabbarElement, callback) {
25033 callback();
25034 },
25035
25036
25037 /**
25038 * @param {Element} tabbarElement
25039 * @param {Element} target
25040 * @param {Object} options
25041 * @param {Function} callback
25042 */
25043 link: function link(tabbarElement, target, options, callback) {
25044 callback(target);
25045 },
25046
25047
25048 /**
25049 * @param {Element} tabbarElement
25050 * @param {Element} target
25051 * @param {Function} callback
25052 */
25053 unlink: function unlink(tabbarElement, target, callback) {
25054 callback(target);
25055 }
25056};
25057
25058var generateId$1 = function () {
25059 var i = 0;
25060 return function () {
25061 return 'ons-tabbar-gen-' + i++;
25062 };
25063}();
25064
25065/**
25066 * @element ons-tabbar
25067 * @category tabbar
25068 * @description
25069 * [en]A component to display a tab bar on the bottom of a page. Used with `<ons-tab>` to manage pages using tabs.[/en]
25070 * [ja]タブバーをページ下部に表示するためのコンポーネントです。ons-tabと組み合わせて使うことで、ページを管理できます。[/ja]
25071 * @codepen pGuDL
25072 * @tutorial vanilla/Reference/tabbar
25073 * @guide multiple-page-navigation
25074 * [en]Managing multiple pages.[/en]
25075 * [ja]Managing multiple pages[/ja]
25076 * @guide templates
25077 * [en]Defining multiple pages in single html[/en]
25078 * [ja]複数のページを1つのHTMLに記述する[/ja]
25079 * @seealso ons-tab
25080 * [en]The `<ons-tab>` component.[/en]
25081 * [ja]ons-tabコンポーネント[/ja]
25082 * @seealso ons-page
25083 * [en]The `<ons-page>` component.[/en]
25084 * [ja]ons-pageコンポーネント[/ja]
25085 * @example
25086 * <ons-tabbar>
25087 * <ons-tab
25088 * page="home.html"
25089 * label="Home"
25090 * active>
25091 * </ons-tab>
25092 * <ons-tab
25093 * page="settings.html"
25094 * label="Settings"
25095 * active>
25096 * </ons-tab>
25097 * </ons-tabbar>
25098 *
25099 * <ons-template id="home.html">
25100 * ...
25101 * </ons-template>
25102 *
25103 * <ons-template id="settings.html">
25104 * ...
25105 * </ons-template>
25106 */
25107
25108var TabbarElement = function (_BaseElement) {
25109 inherits(TabbarElement, _BaseElement);
25110
25111 function TabbarElement() {
25112 classCallCheck(this, TabbarElement);
25113 return possibleConstructorReturn(this, (TabbarElement.__proto__ || Object.getPrototypeOf(TabbarElement)).apply(this, arguments));
25114 }
25115
25116 createClass(TabbarElement, [{
25117 key: 'init',
25118
25119
25120 /**
25121 * @event prechange
25122 * @description
25123 * [en]Fires just before the tab is changed.[/en]
25124 * [ja]アクティブなタブが変わる前に発火します。[/ja]
25125 * @param {Object} event
25126 * [en]Event object.[/en]
25127 * [ja]イベントオブジェクト。[/ja]
25128 * @param {Number} event.index
25129 * [en]Current index.[/en]
25130 * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
25131 * @param {Object} event.tabItem
25132 * [en]Tab item object.[/en]
25133 * [ja]tabItemオブジェクト。[/ja]
25134 * @param {Function} event.cancel
25135 * [en]Call this function to cancel the change event.[/en]
25136 * [ja]この関数を呼び出すと、アクティブなタブの変更がキャンセルされます。[/ja]
25137 */
25138
25139 /**
25140 * @event postchange
25141 * @description
25142 * [en]Fires just after the tab is changed.[/en]
25143 * [ja]アクティブなタブが変わった後に発火します。[/ja]
25144 * @param {Object} event
25145 * [en]Event object.[/en]
25146 * [ja]イベントオブジェクト。[/ja]
25147 * @param {Number} event.index
25148 * [en]Current index.[/en]
25149 * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
25150 * @param {Object} event.tabItem
25151 * [en]Tab item object.[/en]
25152 * [ja]tabItemオブジェクト。[/ja]
25153 */
25154
25155 /**
25156 * @event reactive
25157 * @description
25158 * [en]Fires if the already open tab is tapped again.[/en]
25159 * [ja]すでにアクティブになっているタブがもう一度タップやクリックされた場合に発火します。[/ja]
25160 * @param {Object} event
25161 * [en]Event object.[/en]
25162 * [ja]イベントオブジェクト。[/ja]
25163 * @param {Number} event.index
25164 * [en]Current index.[/en]
25165 * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja]
25166 * @param {Object} event.tabItem
25167 * [en]Tab item object.[/en]
25168 * [ja]tabItemオブジェクト。[/ja]
25169 */
25170
25171 /**
25172 * @attribute animation
25173 * @type {String}
25174 * @default none
25175 * @description
25176 * [en]Animation name. Available values are `"none"`, `"slide"` and `"fade"`. Default is `"none"`.[/en]
25177 * [ja]ページ読み込み時のアニメーションを指定します。"none"、"fade"、"slide"のいずれかを選択できます。デフォルトは"none"です。[/ja]
25178 */
25179
25180 /**
25181 * @attribute animation-options
25182 * @type {Expression}
25183 * @description
25184 * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en]
25185 * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja]
25186 */
25187
25188 /**
25189 * @attribute position
25190 * @initonly
25191 * @type {String}
25192 * @default bottom
25193 * @description
25194 * [en]Tabbar's position. Available values are `"bottom"` and `"top"`. Use `"auto"` to choose position depending on platform (iOS bottom, Android top).[/en]
25195 * [ja]タブバーの位置を指定します。"bottom"もしくは"top"を選択できます。デフォルトは"bottom"です。[/ja]
25196 */
25197
25198 value: function init() {
25199 var _this2 = this;
25200
25201 this._tabbarId = generateId$1();
25202
25203 contentReady(this, function () {
25204 _this2._compile();
25205
25206 var content = _this2._contentElement;
25207 for (var i = 0; i < content.children.length; i++) {
25208 content.children[i].style.display = 'none';
25209 }
25210
25211 var activeIndex = _this2.getAttribute('activeIndex');
25212
25213 var tabbar = _this2._tabbarElement;
25214 if (activeIndex && tabbar.children.length > activeIndex) {
25215 tabbar.children[activeIndex].setAttribute('active', 'true');
25216 }
25217
25218 autoStyle.prepare(_this2);
25219 ModifierUtil.initModifier(_this2, scheme$21);
25220
25221 _this2._animatorFactory = new AnimatorFactory({
25222 animators: _animatorDict$6,
25223 baseClass: TabbarAnimator,
25224 baseClassName: 'TabbarAnimator',
25225 defaultAnimation: _this2.getAttribute('animation')
25226 });
25227 });
25228 }
25229 }, {
25230 key: 'connectedCallback',
25231 value: function connectedCallback() {
25232 var _this3 = this;
25233
25234 contentReady(this, function () {
25235 return _this3._updatePosition();
25236 });
25237 }
25238 }, {
25239 key: '_compile',
25240 value: function _compile() {
25241 if (this._contentElement && this._tabbarElement) {
25242 var content = util.findChild(this, '.tab-bar__content');
25243 var bar = util.findChild(this, '.tab-bar');
25244
25245 content.classList.add('ons-tab-bar__content');
25246 bar.classList.add('ons-tab-bar__footer');
25247 } else {
25248
25249 var _content = util.create('.ons-tab-bar__content.tab-bar__content');
25250 var tabbar = util.create('.tab-bar.ons-tab-bar__footer');
25251
25252 while (this.firstChild) {
25253 tabbar.appendChild(this.firstChild);
25254 }
25255
25256 this.appendChild(_content);
25257 this.appendChild(tabbar);
25258 }
25259 }
25260 }, {
25261 key: '_updatePosition',
25262 value: function _updatePosition() {
25263 var _this4 = this;
25264
25265 var position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('position');
25266
25267 var top = this._top = position === 'top' || position === 'auto' && platform.isAndroid();
25268 var action = top ? util.addModifier : util.removeModifier;
25269
25270 action(this, 'top');
25271
25272 var page = util.findParent(this, 'ons-page');
25273 if (page) {
25274 this.style.top = top ? window.getComputedStyle(page._getContentElement(), null).getPropertyValue('padding-top') : '';
25275
25276 if (util.match(page.firstChild, 'ons-toolbar')) {
25277 action(page.firstChild, 'noshadow');
25278 }
25279 }
25280
25281 internal$1.autoStatusBarFill(function () {
25282 var filled = util.findParent(_this4, function (e) {
25283 return e.hasAttribute('status-bar-fill');
25284 });
25285 util.toggleAttribute(_this4, 'status-bar-fill', top && !filled);
25286 });
25287 }
25288 }, {
25289 key: '_getTabbarElement',
25290 value: function _getTabbarElement() {
25291 return util.findChild(this, '.tab-bar');
25292 }
25293
25294 /**
25295 * @method loadPage
25296 * @deprecated
25297 * @signature loadPage(url, [options])
25298 * @param {String} url
25299 * [en]Page URL. Can be either an HTML document or an `<ons-template>` id.[/en]
25300 * [ja]pageのURLか、もしくはons-templateで宣言したid属性の値を利用できます。[/ja]
25301 * @description
25302 * [en]Displays a new page without changing the active index.[/en]
25303 * [ja]現在のアクティブなインデックスを変更せずに、新しいページを表示します。[/ja]
25304 * @param {Object} [options]
25305 * [en][/en]
25306 * [ja][/ja]
25307 * @param {Object} [options.animation]
25308 * [en][/en]
25309 * [ja][/ja]
25310 * @param {Object} [options.callback]
25311 * [en][/en]
25312 * [ja][/ja]
25313 * @return {Promise}
25314 * [en]Resolves to the new page element.[/en]
25315 * [ja][/ja]
25316 */
25317
25318 }, {
25319 key: 'loadPage',
25320 value: function loadPage(page) {
25321 var _this5 = this;
25322
25323 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
25324
25325 console.warn('The loadPage method has been deprecated and will be removed in the next minor version.');
25326
25327 return new Promise(function (resolve) {
25328 var tab = _this5._tabbarElement.children[0] || new TabElement();
25329 tab._loadPage(page, _this5._contentElement, function (pageElement) {
25330 resolve(_this5._loadPageDOMAsync(pageElement, options));
25331 });
25332 });
25333 }
25334
25335 /**
25336 * @param {Element} pageElement
25337 * @param {Object} [options]
25338 * @param {Object} [options.animation]
25339 * @param {Object} [options.callback]
25340 * @return {Promise} Resolves to the new page element.
25341 */
25342
25343 }, {
25344 key: '_loadPageDOMAsync',
25345 value: function _loadPageDOMAsync(pageElement) {
25346 var _this6 = this;
25347
25348 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
25349
25350 return new Promise(function (resolve) {
25351 rewritables$3.link(_this6, pageElement, options, function (pageElement) {
25352 _this6._contentElement.appendChild(pageElement);
25353
25354 if (_this6.getActiveTabIndex() !== -1) {
25355 resolve(_this6._switchPage(pageElement, options));
25356 } else {
25357 if (options.callback instanceof Function) {
25358 options.callback();
25359 }
25360
25361 _this6._oldPageElement = pageElement;
25362 resolve(pageElement);
25363 }
25364 });
25365 });
25366 }
25367
25368 /**
25369 * @return {String}
25370 */
25371
25372 }, {
25373 key: 'getTabbarId',
25374 value: function getTabbarId() {
25375 return this._tabbarId;
25376 }
25377
25378 /**
25379 * @return {Element/null}
25380 */
25381
25382 }, {
25383 key: '_getCurrentPageElement',
25384 value: function _getCurrentPageElement() {
25385 var pages = this._contentElement.children;
25386 var page = null;
25387 for (var i = 0; i < pages.length; i++) {
25388 if (pages[i].style.display !== 'none') {
25389 page = pages[i];
25390 break;
25391 }
25392 }
25393
25394 if (page && page.nodeName.toLowerCase() !== 'ons-page') {
25395 throw new Error('Invalid state: page element must be a "ons-page" element.');
25396 }
25397
25398 return page;
25399 }
25400 }, {
25401 key: '_switchPage',
25402
25403
25404 /**
25405 * @param {Element} element
25406 * @param {Object} options
25407 * @param {String} [options.animation]
25408 * @param {Function} [options.callback]
25409 * @param {Object} [options.animationOptions]
25410 * @param {Number} options.selectedTabIndex
25411 * @param {Number} options.previousTabIndex
25412 * @return {Promise} Resolves to the new page element.
25413 */
25414 value: function _switchPage(element, options) {
25415 var oldPageElement = this._oldPageElement || internal$1.nullElement;
25416 this._oldPageElement = element;
25417 var animator = this._animatorFactory.newAnimator(options);
25418
25419 return new Promise(function (resolve) {
25420 if (oldPageElement !== internal$1.nullElement) {
25421 oldPageElement._hide();
25422 }
25423
25424 animator.apply(element, oldPageElement, options.selectedTabIndex, options.previousTabIndex, function () {
25425 if (oldPageElement !== internal$1.nullElement) {
25426 oldPageElement.style.display = 'none';
25427 }
25428
25429 element.style.display = 'block';
25430 element._show();
25431
25432 if (options.callback instanceof Function) {
25433 options.callback();
25434 }
25435
25436 resolve(element);
25437 });
25438 });
25439 }
25440
25441 /**
25442 * @method setActiveTab
25443 * @signature setActiveTab(index, [options])
25444 * @param {Number} index
25445 * [en]Tab index.[/en]
25446 * [ja]タブのインデックスを指定します。[/ja]
25447 * @param {Object} [options]
25448 * [en]Parameter object.[/en]
25449 * [ja]オプションを指定するオブジェクト。[/ja]
25450 * @param {Boolean} [options.keepPage]
25451 * [en]If true the page will not be changed.[/en]
25452 * [ja]タブバーが現在表示しているpageを変えない場合にはtrueを指定します。[/ja]
25453 * @param {String} [options.animation]
25454 * [en]Animation name. Available animations are `"fade"`, `"slide"` and `"none"`.[/en]
25455 * [ja]アニメーション名を指定します。`"fade"`、`"slide"`、`"none"`のいずれかを指定できます。[/ja]
25456 * @param {String} [options.animationOptions]
25457 * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en]
25458 * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja]
25459 * @description
25460 * [en]Show specified tab page. Animations and other options can be specified by the second parameter.[/en]
25461 * [ja]指定したインデックスのタブを表示します。アニメーションなどのオプションを指定できます。[/ja]
25462 * @return {Promise}
25463 * [en]Resolves to the new page element.[/en]
25464 * [ja][/ja]
25465 */
25466
25467 }, {
25468 key: 'setActiveTab',
25469 value: function setActiveTab(index) {
25470 var _this7 = this;
25471
25472 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
25473
25474 if (options && (typeof options === 'undefined' ? 'undefined' : _typeof(options)) != 'object') {
25475 throw new Error('options must be an object. You supplied ' + options);
25476 }
25477
25478 options.animationOptions = util.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')));
25479
25480 if (!options.animation && this.hasAttribute('animation')) {
25481 options.animation = this.getAttribute('animation');
25482 }
25483
25484 var previousTab = this._getActiveTabElement(),
25485 selectedTab = this._getTabElement(index),
25486 previousTabIndex = this.getActiveTabIndex(),
25487 selectedTabIndex = index,
25488 previousPageElement = this._getCurrentPageElement();
25489
25490 if (!selectedTab) {
25491 return Promise.reject('Specified index does not match any tab.');
25492 }
25493
25494 if (selectedTabIndex === previousTabIndex) {
25495 util.triggerElementEvent(this, 'reactive', {
25496 index: selectedTabIndex,
25497 tabItem: selectedTab
25498 });
25499
25500 return Promise.resolve(previousPageElement);
25501 }
25502
25503 var canceled = false;
25504
25505 util.triggerElementEvent(this, 'prechange', {
25506 index: selectedTabIndex,
25507 tabItem: selectedTab,
25508 cancel: function cancel() {
25509 return canceled = true;
25510 }
25511 });
25512
25513 if (canceled) {
25514 selectedTab.setInactive();
25515 if (previousTab) {
25516 previousTab.setActive();
25517 }
25518 return Promise.reject('Canceled in prechange event.');
25519 }
25520
25521 selectedTab.setActive();
25522
25523 var params = _extends({}, options, {
25524 previousTabIndex: previousTabIndex,
25525 selectedTabIndex: selectedTabIndex
25526 });
25527
25528 if (previousTab) {
25529 previousTab.setInactive();
25530 } else {
25531 params.animation = 'none';
25532 }
25533
25534 var link = function link(element, callback) {
25535 rewritables$3.link(_this7, element, options, callback);
25536 };
25537
25538 return new Promise(function (resolve) {
25539 selectedTab._loadPageElement(_this7._contentElement, function (pageElement) {
25540 pageElement.removeAttribute('style');
25541
25542 _this7._switchPage(pageElement, params).then(function (page) {
25543 util.triggerElementEvent(_this7, 'postchange', {
25544 index: selectedTabIndex,
25545 tabItem: selectedTab
25546 });
25547
25548 return resolve(page);
25549 });
25550 }, link);
25551 });
25552 }
25553
25554 /**
25555 * @method setTabbarVisibility
25556 * @signature setTabbarVisibility(visible)
25557 * @param {Boolean} visible
25558 * @description
25559 * [en]Used to hide or show the tab bar.[/en]
25560 * [ja][/ja]
25561 */
25562
25563 }, {
25564 key: 'setTabbarVisibility',
25565 value: function setTabbarVisibility(visible) {
25566 this._contentElement.style[this._top ? 'top' : 'bottom'] = visible ? '' : '0px';
25567 this._getTabbarElement().style.display = visible ? '' : 'none';
25568 }
25569
25570 /**
25571 * @method getActiveTabIndex
25572 * @signature getActiveTabIndex()
25573 * @return {Number}
25574 * [en]The index of the currently active tab.[/en]
25575 * [ja]現在アクティブになっているタブのインデックスを返します。[/ja]
25576 * @description
25577 * [en]Returns tab index on current active tab. If active tab is not found, returns -1.[/en]
25578 * [ja]現在アクティブになっているタブのインデックスを返します。現在アクティブなタブがない場合には-1を返します。[/ja]
25579 */
25580
25581 }, {
25582 key: 'getActiveTabIndex',
25583 value: function getActiveTabIndex() {
25584 var tabs = this._getTabbarElement().children;
25585
25586 for (var i = 0; i < tabs.length; i++) {
25587 if (tabs[i] instanceof TabElement && tabs[i].isActive && tabs[i].isActive()) {
25588 return i;
25589 }
25590 }
25591
25592 return -1;
25593 }
25594
25595 /**
25596 * @return {Number} When active tab is not found, returns -1.
25597 */
25598
25599 }, {
25600 key: '_getActiveTabElement',
25601 value: function _getActiveTabElement() {
25602 return this._getTabElement(this.getActiveTabIndex());
25603 }
25604
25605 /**
25606 * @return {Element}
25607 */
25608
25609 }, {
25610 key: '_getTabElement',
25611 value: function _getTabElement(index) {
25612 return this._getTabbarElement().children[index];
25613 }
25614 }, {
25615 key: 'disconnectedCallback',
25616 value: function disconnectedCallback() {}
25617 }, {
25618 key: '_show',
25619 value: function _show() {
25620 var currentPageElement = this._getCurrentPageElement();
25621 if (currentPageElement) {
25622 currentPageElement._show();
25623 }
25624 }
25625 }, {
25626 key: '_hide',
25627 value: function _hide() {
25628 var currentPageElement = this._getCurrentPageElement();
25629 if (currentPageElement) {
25630 currentPageElement._hide();
25631 }
25632 }
25633 }, {
25634 key: '_destroy',
25635 value: function _destroy() {
25636 var pages = this._contentElement.children;
25637 for (var i = pages.length - 1; i >= 0; i--) {
25638 pages[i]._destroy();
25639 }
25640 this.remove();
25641 }
25642 }, {
25643 key: 'attributeChangedCallback',
25644 value: function attributeChangedCallback(name, last, current) {
25645 if (name === 'modifier') {
25646 return ModifierUtil.onModifierChanged(last, current, this, scheme$21);
25647 }
25648 }
25649 }, {
25650 key: '_contentElement',
25651 get: function get() {
25652 return util.findChild(this, '.tab-bar__content');
25653 }
25654 }, {
25655 key: '_tabbarElement',
25656 get: function get() {
25657 return util.findChild(this, '.tab-bar');
25658 }
25659 }, {
25660 key: 'pages',
25661 get: function get() {
25662 return util.arrayFrom(this._contentElement.children);
25663 }
25664 }], [{
25665 key: 'registerAnimator',
25666
25667
25668 /**
25669 * @param {String} name
25670 * @param {Function} Animator
25671 */
25672 value: function registerAnimator(name, Animator) {
25673 if (!(Animator.prototype instanceof TabbarAnimator)) {
25674 throw new Error('"Animator" param must inherit TabbarElement.TabbarAnimator');
25675 }
25676 _animatorDict$6[name] = Animator;
25677 }
25678 }, {
25679 key: 'observedAttributes',
25680 get: function get() {
25681 return ['modifier'];
25682 }
25683 }, {
25684 key: 'rewritables',
25685 get: function get() {
25686 return rewritables$3;
25687 }
25688 }, {
25689 key: 'TabbarAnimator',
25690 get: function get() {
25691 return TabbarAnimator;
25692 }
25693 }]);
25694 return TabbarElement;
25695}(BaseElement);
25696
25697customElements.define('ons-tabbar', TabbarElement);
25698
25699/*
25700Copyright 2013-2015 ASIAL CORPORATION
25701
25702Licensed under the Apache License, Version 2.0 (the "License");
25703you may not use this file except in compliance with the License.
25704You may obtain a copy of the License at
25705
25706 http://www.apache.org/licenses/LICENSE-2.0
25707
25708Unless required by applicable law or agreed to in writing, software
25709distributed under the License is distributed on an "AS IS" BASIS,
25710WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25711See the License for the specific language governing permissions and
25712limitations under the License.
25713
25714*/
25715
25716var scheme$20 = {
25717 '': 'tab-bar--*__item',
25718 '.tab-bar__button': 'tab-bar--*__button'
25719};
25720var templateSource$1 = util.createElement('\n <div>\n <input type="radio" style="display: none">\n <button class="tab-bar__button"></button>\n </div>\n');
25721var defaultInnerTemplateSource = util.createElement('\n <div>\n <div class="tab-bar__icon">\n <ons-icon icon="ion-cloud"></ons-icon>\n </div>\n <div class="tab-bar__label">label</div>\n <div class="tab-bar__badge notification">1</div>\n </div>\n');
25722
25723/**
25724 * @element ons-tab
25725 * @category tabbar
25726 * @description
25727 * [en]Represents a tab inside tab bar. Each `<ons-tab>` represents a page.[/en]
25728 * [ja]
25729 * タブバーに配置される各アイテムのコンポーネントです。それぞれのons-tabはページを表します。
25730 * ons-tab要素の中には、タブに表示されるコンテンツを直接記述することが出来ます。
25731 * [/ja]
25732 * @codepen pGuDL
25733 * @tutorial vanilla/Reference/tabbar
25734 * @guide multiple-page-navigation
25735 * [en]Managing multiple pages.[/en]
25736 * [ja]Managing multiple pages[/ja]]
25737 * @guide templates
25738 * [en]Defining multiple pages in single html[/en]
25739 * [ja]複数のページを1つのHTMLに記述する[/ja]
25740 * @seealso ons-tabbar
25741 * [en]ons-tabbar component[/en]
25742 * [ja]ons-tabbarコンポーネント[/ja]
25743 * @seealso ons-page
25744 * [en]ons-page component[/en]
25745 * [ja]ons-pageコンポーネント[/ja]
25746 * @seealso ons-icon
25747 * [en]ons-icon component[/en]
25748 * [ja]ons-iconコンポーネント[/ja]
25749 * @example
25750 * <ons-tabbar>
25751 * <ons-tab
25752 * page="home.html"
25753 * label="Home"
25754 * active>
25755 * </ons-tab>
25756 * <ons-tab
25757 * page="settings.html"
25758 * label="Settings"
25759 * active>
25760 * </ons-tab>
25761 * </ons-tabbar>
25762 *
25763 * <ons-template id="home.html">
25764 * ...
25765 * </ons-template>
25766 *
25767 * <ons-template id="settings.html">
25768 * ...
25769 * </ons-template>
25770
25771 */
25772
25773var TabElement = function (_BaseElement) {
25774 inherits(TabElement, _BaseElement);
25775
25776 function TabElement() {
25777 classCallCheck(this, TabElement);
25778 return possibleConstructorReturn(this, (TabElement.__proto__ || Object.getPrototypeOf(TabElement)).apply(this, arguments));
25779 }
25780
25781 createClass(TabElement, [{
25782 key: 'init',
25783
25784
25785 /**
25786 * @attribute page
25787 * @initonly
25788 * @type {String}
25789 * @description
25790 * [en]The page that is displayed when the tab is tapped.[/en]
25791 * [ja]ons-tabが参照するページへのURLを指定します。[/ja]
25792 */
25793
25794 /**
25795 * @attribute icon
25796 * @type {String}
25797 * @description
25798 * [en]
25799 * The icon name for the tab. Can specify the same icon name as `<ons-icon>`.
25800 * If you need to use your own icon, create a CSS class with `background-image` or any CSS properties and specify the name of your CSS class here.
25801 * [/en]
25802 * [ja]
25803 * アイコン名を指定します。ons-iconと同じアイコン名を指定できます。
25804 * 個別にアイコンをカスタマイズする場合は、background-imageなどのCSSスタイルを用いて指定できます。
25805 * [/ja]
25806 */
25807
25808 /**
25809 * @attribute active-icon
25810 * @type {String}
25811 * @description
25812 * [en]The name of the icon when the tab is active.[/en]
25813 * [ja]アクティブの際のアイコン名を指定します。[/ja]
25814 */
25815
25816 /**
25817 * @attribute label
25818 * @type {String}
25819 * @description
25820 * [en]The label of the tab item.[/en]
25821 * [ja]アイコン下に表示されるラベルを指定します。[/ja]
25822 */
25823
25824 /**
25825 * @attribute badge
25826 * @type {String}
25827 * @description
25828 * [en]Display a notification badge on top of the tab.[/en]
25829 * [ja]バッジに表示する内容を指定します。[/ja]
25830 */
25831
25832 /**
25833 * @attribute active
25834 * @description
25835 * [en]This attribute should be set to the tab that is active by default.[/en]
25836 * [ja][/ja]
25837 */
25838
25839 value: function init() {
25840 var _this2 = this;
25841
25842 this._pageLoader = defaultPageLoader;
25843 this._page = null;
25844
25845 if (this.hasAttribute('label') || this.hasAttribute('icon') || this.hasAttribute('badge')) {
25846 this._compile();
25847 } else {
25848 contentReady(this, function () {
25849 _this2._compile();
25850 });
25851 }
25852
25853 this._boundOnClick = this._onClick.bind(this);
25854 }
25855 }, {
25856 key: '_getPageTarget',
25857 value: function _getPageTarget() {
25858 return this.page || this.getAttribute('page');
25859 }
25860 }, {
25861 key: '_templateLoaded',
25862 value: function _templateLoaded() {
25863 if (this.children.length == 0) {
25864 return false;
25865 }
25866
25867 var hasInput = this.children[0].getAttribute('type') === 'radio';
25868 var hasButton = util.findChild(this, '.tab-bar__button');
25869
25870 return hasInput && hasButton;
25871 }
25872 }, {
25873 key: '_compile',
25874 value: function _compile() {
25875 autoStyle.prepare(this);
25876
25877 this.classList.add('tab-bar__item');
25878
25879 if (!this._templateLoaded()) {
25880 var fragment = document.createDocumentFragment();
25881 var hasChildren = false;
25882
25883 while (this.childNodes[0]) {
25884 var node = this.childNodes[0];
25885 this.removeChild(node);
25886 fragment.appendChild(node);
25887
25888 if (node.nodeType == Node.ELEMENT_NODE) {
25889 hasChildren = true;
25890 }
25891 }
25892
25893 var template = templateSource$1.cloneNode(true);
25894 while (template.children[0]) {
25895 this.appendChild(template.children[0]);
25896 }
25897
25898 var button = util.findChild(this, '.tab-bar__button');
25899
25900 if (hasChildren) {
25901 button.appendChild(fragment);
25902 this._hasDefaultTemplate = false;
25903 } else {
25904 this._hasDefaultTemplate = true;
25905 this._updateDefaultTemplate();
25906 }
25907 }
25908
25909 ModifierUtil.initModifier(this, scheme$20);
25910 this._updateRipple();
25911 }
25912 }, {
25913 key: '_updateRipple',
25914 value: function _updateRipple() {
25915 // util.updateRipple(this.querySelector('.tab-bar__button'), this);
25916 }
25917 }, {
25918 key: '_updateDefaultTemplate',
25919 value: function _updateDefaultTemplate() {
25920 if (!this._hasDefaultTemplate) {
25921 return;
25922 }
25923
25924 var button = util.findChild(this, '.tab-bar__button');
25925 var template = defaultInnerTemplateSource.cloneNode(true);
25926 if (button.children.length == 0) {
25927 while (template.children[0]) {
25928 button.appendChild(template.children[0]);
25929 }
25930 }
25931
25932 if (!button.querySelector('.tab-bar__icon')) {
25933 button.insertBefore(template.querySelector('.tab-bar__icon'), button.firstChild);
25934 }
25935
25936 if (!button.querySelector('.tab-bar__label')) {
25937 button.appendChild(template.querySelector('.tab-bar__label'));
25938 }
25939
25940 if (!button.querySelector('.tab-bar__badge')) {
25941 button.appendChild(template.querySelector('.tab-bar__badge'));
25942 }
25943
25944 var self = this;
25945 var icon = this.getAttribute('icon');
25946 var label = this.getAttribute('label');
25947 var badge = this.getAttribute('badge');
25948
25949 if (typeof icon === 'string') {
25950 getIconElement().setAttribute('icon', icon);
25951 } else {
25952 var wrapper = button.querySelector('.tab-bar__icon');
25953 if (wrapper) {
25954 wrapper.remove();
25955 }
25956 }
25957
25958 if (typeof label === 'string') {
25959 getLabelElement().textContent = label;
25960 } else {
25961 var _label = getLabelElement();
25962 if (_label) {
25963 _label.remove();
25964 }
25965 }
25966
25967 if (typeof badge === 'string') {
25968 getBadgeElement().textContent = badge;
25969 } else {
25970 var _badge = getBadgeElement();
25971 if (_badge) {
25972 _badge.remove();
25973 }
25974 }
25975
25976 function getLabelElement() {
25977 return self.querySelector('.tab-bar__label');
25978 }
25979
25980 function getIconElement() {
25981 return self.querySelector('ons-icon');
25982 }
25983
25984 function getBadgeElement() {
25985 return self.querySelector('.tab-bar__badge');
25986 }
25987 }
25988 }, {
25989 key: '_onClick',
25990 value: function _onClick() {
25991 var tabbar = this._findTabbarElement();
25992 if (tabbar) {
25993 tabbar.setActiveTab(this._findTabIndex());
25994 }
25995 }
25996 }, {
25997 key: 'setActive',
25998 value: function setActive() {
25999 var radio = util.findChild(this, 'input');
26000 radio.checked = true;
26001 this.classList.add('active');
26002
26003 util.arrayFrom(this.querySelectorAll('[ons-tab-inactive], ons-tab-inactive')).forEach(function (element) {
26004 return element.style.display = 'none';
26005 });
26006 util.arrayFrom(this.querySelectorAll('[ons-tab-active], ons-tab-active')).forEach(function (element) {
26007 return element.style.display = 'inherit';
26008 });
26009 }
26010 }, {
26011 key: 'setInactive',
26012 value: function setInactive() {
26013 var radio = util.findChild(this, 'input');
26014 radio.checked = false;
26015 this.classList.remove('active');
26016
26017 util.arrayFrom(this.querySelectorAll('[ons-tab-inactive], ons-tab-inactive')).forEach(function (element) {
26018 return element.style.display = 'inherit';
26019 });
26020 util.arrayFrom(this.querySelectorAll('[ons-tab-active], ons-tab-active')).forEach(function (element) {
26021 return element.style.display = 'none';
26022 });
26023 }
26024
26025 /**
26026 * @param {Element} parent
26027 * @param {Function} callback
26028 * @param {Function} link
26029 */
26030
26031 }, {
26032 key: '_loadPageElement',
26033 value: function _loadPageElement(parent, callback, link) {
26034 var _this3 = this;
26035
26036 if (!this._loadedPage && !this._getPageTarget()) {
26037 var pages = this._findTabbarElement().pages;
26038 var index = this._findTabIndex();
26039 callback(pages[index]);
26040 } else if (this._loadingPage) {
26041 this._loadingPage.then(function (page) {
26042 callback(page.element);
26043 });
26044 } else if (!this._loadedPage) {
26045 (function () {
26046 var deferred = util.defer();
26047 _this3._loadingPage = deferred.promise;
26048
26049 _this3._pageLoader.load({ page: _this3._getPageTarget(), parent: parent }, function (page) {
26050 _this3._loadedPage = page;
26051 deferred.resolve(page);
26052 delete _this3._loadingPage;
26053
26054 link(page.element, function (element) {
26055 page.element = element;
26056 callback(page.element);
26057 });
26058 });
26059 })();
26060 } else {
26061 callback(this._loadedPage.element);
26062 }
26063 }
26064 }, {
26065 key: '_loadPage',
26066 value: function _loadPage(page, parent, callback) {
26067 this._pageLoader.load({ page: page, parent: parent }, function (page) {
26068 callback(page.element);
26069 });
26070 }
26071 }, {
26072 key: 'isActive',
26073
26074
26075 /**
26076 * @return {Boolean}
26077 */
26078 value: function isActive() {
26079 return this.classList.contains('active');
26080 }
26081 }, {
26082 key: 'disconnectedCallback',
26083 value: function disconnectedCallback() {
26084 this.removeEventListener('click', this._boundOnClick, false);
26085 if (this._loadedPage) {
26086 this._loadedPage.unload();
26087 this._loadedPage = null;
26088 }
26089 }
26090 }, {
26091 key: 'connectedCallback',
26092 value: function connectedCallback() {
26093 var _this4 = this;
26094
26095 contentReady(this, function () {
26096 _this4._ensureElementPosition();
26097
26098 var tabbar = _this4._findTabbarElement();
26099
26100 if (tabbar.hasAttribute('modifier')) {
26101 var prefix = _this4.hasAttribute('modifier') ? _this4.getAttribute('modifier') + ' ' : '';
26102 _this4.setAttribute('modifier', prefix + tabbar.getAttribute('modifier'));
26103 }
26104
26105 var onReady = function onReady() {
26106 if (_this4._getPageTarget() && !_this4.hasLoaded) {
26107 _this4.hasLoaded = true;
26108 _this4._loadPageElement(tabbar._contentElement, function (pageElement) {
26109 pageElement.style.display = 'none';
26110 tabbar._contentElement.appendChild(pageElement);
26111
26112 if (_this4.hasAttribute('active')) {
26113 tabbar.setActiveTab(_this4._findTabIndex());
26114 }
26115 }, function (pageElement, done) {
26116 TabbarElement.rewritables.link(tabbar, pageElement, {}, function (element) {
26117 return done(element);
26118 });
26119 });
26120 }
26121 };
26122
26123 TabbarElement.rewritables.ready(tabbar, onReady);
26124
26125 _this4.addEventListener('click', _this4._boundOnClick, false);
26126 });
26127 }
26128 }, {
26129 key: '_findTabbarElement',
26130 value: function _findTabbarElement() {
26131 if (this.parentNode && this.parentNode.nodeName.toLowerCase() === 'ons-tabbar') {
26132 return this.parentNode;
26133 }
26134
26135 if (this.parentNode.parentNode && this.parentNode.parentNode.nodeName.toLowerCase() === 'ons-tabbar') {
26136 return this.parentNode.parentNode;
26137 }
26138
26139 return null;
26140 }
26141 }, {
26142 key: '_findTabIndex',
26143 value: function _findTabIndex() {
26144 var elements = this.parentNode.children;
26145 for (var i = 0; i < elements.length; i++) {
26146 if (this === elements[i]) {
26147 return i;
26148 }
26149 }
26150 }
26151 }, {
26152 key: '_ensureElementPosition',
26153 value: function _ensureElementPosition() {
26154 if (!this._findTabbarElement()) {
26155 throw new Error('This ons-tab element is must be child of ons-tabbar element.');
26156 }
26157 }
26158 }, {
26159 key: 'attributeChangedCallback',
26160 value: function attributeChangedCallback(name, last, current) {
26161 var _this5 = this;
26162
26163 switch (name) {
26164 case 'modifier':
26165 contentReady(this, function () {
26166 return ModifierUtil.onModifierChanged(last, current, _this5, scheme$20);
26167 });
26168 break;
26169 case 'ripple':
26170 contentReady(this, function () {
26171 return _this5._updateRipple();
26172 });
26173 break;
26174 case 'icon':
26175 case 'label':
26176 case 'badge':
26177 contentReady(this, function () {
26178 return _this5._updateDefaultTemplate();
26179 });
26180 break;
26181 case 'page':
26182 if (typeof current === 'string') {
26183 this._page = current;
26184 }
26185 break;
26186 }
26187 }
26188 }, {
26189 key: 'page',
26190 set: function set(page) {
26191 this._page = page;
26192 },
26193 get: function get() {
26194 return this._page;
26195 }
26196 }, {
26197 key: 'pageLoader',
26198 set: function set(loader) {
26199 if (!(loader instanceof PageLoader)) {
26200 throw Error('First parameter must be an instance of PageLoader.');
26201 }
26202 this._pageLoader = loader;
26203 },
26204 get: function get() {
26205 return this._pageLoader;
26206 }
26207 }, {
26208 key: 'pageElement',
26209 get: function get() {
26210 if (this._loadedPage) {
26211 return this._loadedPage.element;
26212 }
26213
26214 var tabbar = this._findTabbarElement();
26215 var index = this._findTabIndex();
26216
26217 return tabbar._contentElement.children[index];
26218 }
26219 }], [{
26220 key: 'observedAttributes',
26221 get: function get() {
26222 return ['modifier', 'ripple', 'icon', 'label', 'page', 'badge'];
26223 }
26224 }]);
26225 return TabElement;
26226}(BaseElement);
26227
26228customElements.define('ons-tab', TabElement);
26229
26230/*
26231Copyright 2013-2015 ASIAL CORPORATION
26232
26233Licensed under the Apache License, Version 2.0 (the "License");
26234you may not use this file except in compliance with the License.
26235You may obtain a copy of the License at
26236
26237 http://www.apache.org/licenses/LICENSE-2.0
26238
26239Unless required by applicable law or agreed to in writing, software
26240distributed under the License is distributed on an "AS IS" BASIS,
26241WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26242See the License for the specific language governing permissions and
26243limitations under the License.
26244
26245*/
26246
26247var scheme$22 = { '': 'toolbar-button--*' };
26248
26249/**
26250 * @element ons-toolbar-button
26251 * @category page
26252 * @modifier material
26253 * [en]Material Design toolbar button.[/en]
26254 * [ja][/ja]
26255 * @modifier outline
26256 * [en]A button with an outline.[/en]
26257 * [ja]アウトラインをもったボタンを表示します。[/ja]
26258 * @description
26259 * [en]Button component for ons-toolbar and ons-bottom-toolbar.[/en]
26260 * [ja]ons-toolbarあるいはons-bottom-toolbarに設置できるボタン用コンポーネントです。[/ja]
26261 * @codepen aHmGL
26262 * @tutorial vanilla/Reference/page
26263 * @guide adding-a-toolbar
26264 * [en]Adding a toolbar[/en]
26265 * [ja]ツールバーの追加[/ja]
26266 * @seealso ons-toolbar
26267 * [en]The `<ons-toolbar>` component displays a navigation bar at the top of a page.[/en]
26268 * [ja]ons-toolbarコンポーネント[/ja]
26269 * @seealso ons-back-button
26270 * [en]The `<ons-back-button>` displays a back button in the navigation bar.[/en]
26271 * [ja]ons-back-buttonコンポーネント[/ja]
26272 * @example
26273 * <ons-toolbar>
26274 * <div class="left">
26275 * <ons-toolbar-button>
26276 * Button
26277 * </ons-toolbar-button>
26278 * </div>
26279 * <div class="center">
26280 * Title
26281 * </div>
26282 * <div class="right">
26283 * <ons-toolbar-button>
26284 * <ons-icon icon="ion-navicon" size="28px"></ons-icon>
26285 * </ons-toolbar-button>
26286 * </div>
26287 * </ons-toolbar>
26288 */
26289
26290var ToolbarButtonElement = function (_BaseElement) {
26291 inherits(ToolbarButtonElement, _BaseElement);
26292
26293 function ToolbarButtonElement() {
26294 classCallCheck(this, ToolbarButtonElement);
26295 return possibleConstructorReturn(this, (ToolbarButtonElement.__proto__ || Object.getPrototypeOf(ToolbarButtonElement)).apply(this, arguments));
26296 }
26297
26298 createClass(ToolbarButtonElement, [{
26299 key: 'init',
26300
26301
26302 /**
26303 * @attribute modifier
26304 * @type {String}
26305 * @description
26306 * [en]The appearance of the button.[/en]
26307 * [ja]ボタンの表現を指定します。[/ja]
26308 */
26309
26310 /**
26311 * @attribute disabled
26312 * @description
26313 * [en]Specify if button should be disabled.[/en]
26314 * [ja]ボタンを無効化する場合は指定してください。[/ja]
26315 */
26316
26317 value: function init() {
26318 this._compile();
26319 }
26320
26321 /**
26322 * @property disabled
26323 * @type {Boolean}
26324 * @description
26325 * [en]Whether the element is disabled or not.[/en]
26326 * [ja]無効化されている場合に`true`。[/ja]
26327 */
26328
26329 }, {
26330 key: '_compile',
26331 value: function _compile() {
26332 autoStyle.prepare(this);
26333
26334 this.classList.add('toolbar-button');
26335
26336 ModifierUtil.initModifier(this, scheme$22);
26337 }
26338 }, {
26339 key: 'attributeChangedCallback',
26340 value: function attributeChangedCallback(name, last, current) {
26341 if (name === 'modifier') {
26342 return ModifierUtil.onModifierChanged(last, current, this, scheme$22);
26343 }
26344 }
26345 }, {
26346 key: 'disabled',
26347 set: function set(value) {
26348 return util.toggleAttribute(this, 'disabled', value);
26349 },
26350 get: function get() {
26351 return this.hasAttribute('disabled');
26352 }
26353 }], [{
26354 key: 'observedAttributes',
26355 get: function get() {
26356 return ['modifier'];
26357 }
26358 }]);
26359 return ToolbarButtonElement;
26360}(BaseElement);
26361
26362customElements.define('ons-toolbar-button', ToolbarButtonElement);
26363
26364/*
26365Copyright 2013-2015 ASIAL CORPORATION
26366Licensed under the Apache License, Version 2.0 (the "License");
26367you may not use this file except in compliance with the License.
26368You may obtain a copy of the License at
26369 http://www.apache.org/licenses/LICENSE-2.0
26370Unless required by applicable law or agreed to in writing, software
26371distributed under the License is distributed on an "AS IS" BASIS,
26372WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26373See the License for the specific language governing permissions and
26374limitations under the License.
26375*/
26376
26377var scheme$23 = {
26378 '.range': 'range--*',
26379 '.range__left': 'range--*__left'
26380};
26381
26382var templateSource$2 = util.createElement('<div>\n <div class="range__left"></div>\n <input type="range" class="range">\n</div>');
26383
26384var INPUT_ATTRIBUTES$1 = ['autofocus', 'disabled', 'inputmode', 'max', 'min', 'name', 'placeholder', 'readonly', 'size', 'step', 'validator', 'value'];
26385
26386/**
26387 * @element ons-range
26388 * @category form
26389 * @modifier material
26390 * [en]Material Design slider[/en]
26391 * [ja][/ja]
26392 * @description
26393 * [en]
26394 * Range input component. Used to display a draggable slider.
26395 *
26396 * Works very similar to the `<input type="range">` element.
26397 * [/en]
26398 * [ja][/ja]
26399 * @codepen xZQomM
26400 * @tutorial vanilla/Reference/range
26401 * @guide using-modifier [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
26402 * @seealso ons-input
26403 * [en]The `<ons-input>` component is used to display text inputs, radio buttons and checkboxes.[/en]
26404 * [ja][/ja]
26405 * @example
26406 * <ons-range value="20"></ons-range>
26407 * <ons-range modifier="material" value="10"></range>
26408 */
26409
26410var RangeElement = function (_BaseElement) {
26411 inherits(RangeElement, _BaseElement);
26412
26413 function RangeElement() {
26414 classCallCheck(this, RangeElement);
26415 return possibleConstructorReturn(this, (RangeElement.__proto__ || Object.getPrototypeOf(RangeElement)).apply(this, arguments));
26416 }
26417
26418 createClass(RangeElement, [{
26419 key: 'init',
26420 value: function init() {
26421 var _this2 = this;
26422
26423 contentReady(this, function () {
26424 _this2._compile();
26425 _this2._updateBoundAttributes();
26426 _this2._onChange();
26427 });
26428 }
26429 }, {
26430 key: '_compile',
26431 value: function _compile() {
26432 autoStyle.prepare(this);
26433
26434 if (!(util.findChild(this, '.range__left') && util.findChild(this, 'input'))) {
26435 var template = templateSource$2.cloneNode(true);
26436 while (template.children[0]) {
26437 this.appendChild(template.children[0]);
26438 }
26439 }
26440
26441 ModifierUtil.initModifier(this, scheme$23);
26442 }
26443 }, {
26444 key: '_onChange',
26445 value: function _onChange() {
26446 this._left.style.width = 100 * this._ratio + '%';
26447 }
26448 }, {
26449 key: '_onDragstart',
26450 value: function _onDragstart(e) {
26451 e.stopPropagation();
26452 e.gesture.stopPropagation();
26453 }
26454 }, {
26455 key: 'attributeChangedCallback',
26456 value: function attributeChangedCallback(name, last, current) {
26457 var _this3 = this;
26458
26459 if (name === 'modifier') {
26460 ModifierUtil.onModifierChanged(last, current, this, scheme$23);
26461 } else if (INPUT_ATTRIBUTES$1.indexOf(name) >= 0) {
26462 contentReady(this, function () {
26463 _this3._updateBoundAttributes();
26464
26465 if (name === 'min' || name === 'max') {
26466 _this3._onChange();
26467 }
26468 });
26469 }
26470 }
26471 }, {
26472 key: 'connectedCallback',
26473 value: function connectedCallback() {
26474 this.addEventListener('dragstart', this._onDragstart);
26475 this.addEventListener('input', this._onChange);
26476 }
26477 }, {
26478 key: 'disconnectedCallback',
26479 value: function disconnectedCallback() {
26480 this.removeEventListener('dragstart', this._onDragstart);
26481 this.removeEventListener('input', this._onChange);
26482 }
26483 }, {
26484 key: '_updateBoundAttributes',
26485 value: function _updateBoundAttributes() {
26486 var _this4 = this;
26487
26488 INPUT_ATTRIBUTES$1.forEach(function (attr) {
26489 if (_this4.hasAttribute(attr)) {
26490 _this4._input.setAttribute(attr, _this4.getAttribute(attr));
26491 } else {
26492 _this4._input.removeAttribute(attr);
26493 }
26494 });
26495 }
26496 }, {
26497 key: '_ratio',
26498 get: function get() {
26499 // Returns the current ratio.
26500 var min = this._input.min === '' ? 0 : parseInt(this._input.min);
26501 var max = this._input.max === '' ? 100 : parseInt(this._input.max);
26502
26503 return (this.value - min) / (max - min);
26504 }
26505 }, {
26506 key: '_input',
26507 get: function get() {
26508 return this.querySelector('input');
26509 }
26510 }, {
26511 key: '_left',
26512 get: function get() {
26513 return this.querySelector('.range__left');
26514 }
26515
26516 /**
26517 * @property disabled
26518 * @type {Boolean}
26519 * @description
26520 * [en]Whether the element is disabled or not.[/en]
26521 * [ja]無効化されている場合に`true`。[/ja]
26522 */
26523
26524 }, {
26525 key: 'disabled',
26526 set: function set(value) {
26527 return util.toggleAttribute(this, 'disabled', value);
26528 },
26529 get: function get() {
26530 return this.hasAttribute('disabled');
26531 }
26532
26533 /**
26534 * @property value
26535 * @type {Number}
26536 * @description
26537 * [en]Current value.[/en]
26538 * [ja][/ja]
26539 */
26540
26541 }, {
26542 key: 'value',
26543 get: function get() {
26544 return this._input === null ? this.getAttribute('value') : this._input.value;
26545 },
26546 set: function set(val) {
26547 var _this5 = this;
26548
26549 contentReady(this, function () {
26550 _this5._input.value = val;
26551 _this5._onChange();
26552 });
26553 }
26554 }], [{
26555 key: 'observedAttributes',
26556 get: function get() {
26557 return ['modifier'].concat(INPUT_ATTRIBUTES$1);
26558 }
26559 }]);
26560 return RangeElement;
26561}(BaseElement);
26562
26563customElements.define('ons-range', RangeElement);
26564
26565ons$1.TemplateElement = TemplateElement;
26566ons$1.IfElement = IfElement;
26567ons$1.AlertDialogElement = AlertDialogElement;
26568ons$1.BackButtonElement = BackButtonElement;
26569ons$1.BottomToolbarElement = BottomToolbarElement;
26570ons$1.ButtonElement = ButtonElement;
26571ons$1.CarouselItemElement = CarouselItemElement;
26572ons$1.CarouselElement = CarouselElement;
26573ons$1.ColElement = ColElement;
26574ons$1.DialogElement = DialogElement;
26575ons$1.FabElement = FabElement;
26576ons$1.GestureDetectorElement = GestureDetectorElement;
26577ons$1.IconElement = IconElement;
26578ons$1.LazyRepeatElement = LazyRepeatElement;
26579ons$1.ListHeaderElement = ListHeaderElement;
26580ons$1.ListItemElement = ListItemElement;
26581ons$1.ListElement = ListElement;
26582ons$1.InputElement = InputElement;
26583ons$1.ModalElement = ModalElement;
26584ons$1.NavigatorElement = NavigatorElement;
26585ons$1.PageElement = PageElement;
26586ons$1.PopoverElement = PopoverElement;
26587ons$1.ProgressBarElement = ProgressBarElement;
26588ons$1.ProgressCircularElement = ProgressCircularElement;
26589ons$1.PullHookElement = PullHookElement;
26590ons$1.RippleElement = RippleElement;
26591ons$1.RowElement = RowElement;
26592ons$1.SpeedDialItemElement = SpeedDialItemElement;
26593ons$1.SpeedDialElement = SpeedDialElement;
26594ons$1.SplitterContentElement = SplitterContentElement;
26595ons$1.SplitterMaskElement = SplitterMaskElement;
26596ons$1.SplitterSideElement = SplitterSideElement;
26597ons$1.SplitterElement = SplitterElement;
26598ons$1.SwitchElement = SwitchElement;
26599ons$1.TabElement = TabElement;
26600ons$1.TabbarElement = TabbarElement;
26601ons$1.ToolbarButtonElement = ToolbarButtonElement;
26602ons$1.ToolbarElement = ToolbarElement;
26603ons$1.RangeElement = RangeElement;
26604
26605// fastclick
26606window.addEventListener('load', function () {
26607 ons$1.fastClick = FastClick.attach(document.body);
26608}, false);
26609
26610// ons._defaultDeviceBackButtonHandler
26611window.addEventListener('DOMContentLoaded', function () {
26612 ons$1._deviceBackButtonDispatcher.enable();
26613 ons$1._defaultDeviceBackButtonHandler = ons$1._deviceBackButtonDispatcher.createHandler(window.document.body, function () {
26614 navigator.app.exitApp();
26615 });
26616 document.body._gestureDetector = new ons$1.GestureDetector(document.body);
26617}, false);
26618
26619// setup loading placeholder
26620ons$1.ready(function () {
26621 ons$1._setupLoadingPlaceHolders();
26622});
26623
26624// viewport.js
26625new Viewport().setup();
26626
26627return ons$1;
26628
26629})));
26630
26631//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkN1c3RvbUV2ZW50LmpzIiwiTXV0YXRpb25PYnNlcnZlci5qcyIsImFuaW1pdC5qcyIsImNoaWxkTm9kZVJlbW92ZS5qcyIsImNsYXNzTGlzdC5qcyIsImRvY3VtZW50LXJlZ2lzdGVyLWVsZW1lbnQubWF4LmpzIiwiZmFzdGNsaWNrLXBhdGNoZWQuanMiLCJpbm5lckhUTUwuanMiLCJtaWNyb2V2ZW50LmpzIiwicHJvbWlzZS5qcyIsInNldEltbWVkaWF0ZS5qcyIsInZpZXdwb3J0LmpzIiwid2luc3RvcmUtanNjb21wYXQuanMiLCJvbnMvYW5pbWF0aW9uLW9wdGlvbnMtcGFyc2VyLmpzIiwib25zL3V0aWwuanMiLCJvbnMvZ2VzdHVyZS1kZXRlY3Rvci5qcyIsIm9ucy9wbGF0Zm9ybS5qcyIsIm9ucy9jb250ZW50LXJlYWR5LmpzIiwib25zL25vdGlmaWNhdGlvbi5qcyIsIm9ucy9wYWdlLWF0dHJpYnV0ZS1leHByZXNzaW9uLmpzIiwib25zL2ludGVybmFsL2ludGVybmFsLmpzIiwib25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnkuanMiLCJvbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbC5qcyIsIm9ucy9pbnRlcm5hbC9sYXp5LXJlcGVhdC5qcyIsIm9ucy9pbnRlcm5hbC9pbmRleC5qcyIsIm9ucy9vcmllbnRhdGlvbi5qcyIsIm9ucy9zb2Z0d2FyZS1rZXlib2FyZC5qcyIsIm9ucy9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlci5qcyIsIm9ucy9hdXRvc3R5bGUuanMiLCJvbnMvZG9vcmxvY2suanMiLCJvbnMvcGFnZS1sb2FkZXIuanMiLCJvbnMvb25zLmpzIiwib25zL2Jhc2UtZWxlbWVudC5qcyIsImVsZW1lbnRzL29ucy10ZW1wbGF0ZS5qcyIsImVsZW1lbnRzL29ucy1pZi5qcyIsImVsZW1lbnRzL29ucy1hbGVydC1kaWFsb2cvYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtYWxlcnQtZGlhbG9nL2luZGV4LmpzIiwiZWxlbWVudHMvb25zLWJhY2stYnV0dG9uLmpzIiwiZWxlbWVudHMvb25zLWJvdHRvbS10b29sYmFyLmpzIiwiZWxlbWVudHMvb25zLWJ1dHRvbi5qcyIsImVsZW1lbnRzL29ucy1jYXJvdXNlbC1pdGVtLmpzIiwiZWxlbWVudHMvb25zLWNhcm91c2VsLmpzIiwiZWxlbWVudHMvb25zLWNvbC5qcyIsImVsZW1lbnRzL29ucy1kaWFsb2cvYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtZGlhbG9nL2luZGV4LmpzIiwiZWxlbWVudHMvb25zLWZhYi5qcyIsImVsZW1lbnRzL29ucy1nZXN0dXJlLWRldGVjdG9yLmpzIiwiZWxlbWVudHMvb25zLWljb24uanMiLCJlbGVtZW50cy9vbnMtbGF6eS1yZXBlYXQuanMiLCJlbGVtZW50cy9vbnMtbGlzdC1oZWFkZXIuanMiLCJlbGVtZW50cy9vbnMtbGlzdC1pdGVtLmpzIiwiZWxlbWVudHMvb25zLWxpc3QuanMiLCJlbGVtZW50cy9vbnMtaW5wdXQuanMiLCJlbGVtZW50cy9vbnMtbW9kYWwvYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtbW9kYWwvZmFkZS1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1tb2RhbC9pbmRleC5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3IvYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1zbGlkZS1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW9zLWxpZnQtYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1mYWRlLWFuaW1hdG9yLmpzIiwiZWxlbWVudHMvb25zLW5hdmlnYXRvci9tZC1zbGlkZS1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtbGlmdC1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtZmFkZS1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3Ivbm9uZS1hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW5kZXguanMiLCJlbGVtZW50cy9vbnMtdG9vbGJhci5qcyIsImVsZW1lbnRzL29ucy1wYWdlLmpzIiwiZWxlbWVudHMvb25zLXBvcG92ZXIvYW5pbWF0b3IuanMiLCJlbGVtZW50cy9vbnMtcG9wb3Zlci9pbmRleC5qcyIsImVsZW1lbnRzL29ucy1wcm9ncmVzcy1iYXIuanMiLCJlbGVtZW50cy9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXIuanMiLCJlbGVtZW50cy9vbnMtcHVsbC1ob29rLmpzIiwiZWxlbWVudHMvb25zLXJpcHBsZS9hbmltYXRvci1jc3MuanMiLCJlbGVtZW50cy9vbnMtcmlwcGxlL2luZGV4LmpzIiwiZWxlbWVudHMvb25zLXJvdy5qcyIsImVsZW1lbnRzL29ucy1zcGVlZC1kaWFsLWl0ZW0uanMiLCJsaWIvc3R5bGVyLmpzIiwiZWxlbWVudHMvb25zLXNwZWVkLWRpYWwuanMiLCJlbGVtZW50cy9vbnMtc3BsaXR0ZXItY29udGVudC5qcyIsImVsZW1lbnRzL29ucy1zcGxpdHRlci1tYXNrLmpzIiwiZWxlbWVudHMvb25zLXNwbGl0dGVyL2FuaW1hdG9yLmpzIiwiZWxlbWVudHMvb25zLXNwbGl0dGVyL2luZGV4LmpzIiwiZWxlbWVudHMvb25zLXNwbGl0dGVyLXNpZGUuanMiLCJlbGVtZW50cy9vbnMtc3dpdGNoLmpzIiwiZWxlbWVudHMvb25zLXRhYmJhci9hbmltYXRvci5qcyIsImVsZW1lbnRzL29ucy10YWJiYXIvaW5kZXguanMiLCJlbGVtZW50cy9vbnMtdGFiLmpzIiwiZWxlbWVudHMvb25zLXRvb2xiYXItYnV0dG9uLmpzIiwiZWxlbWVudHMvb25zLXJhbmdlLmpzIiwic2V0dXAuanMiXSwibmFtZXMiOlsidW53cmFwIiwic3RyaW5nIiwic2xpY2UiLCJpc09iamVjdFN0cmluZyIsInN0YXJ0c1dpdGgiLCJlbmRzV2l0aCIsImlzQXJyYXlTdHJpbmciLCJpc1F1b3RlZFN0cmluZyIsImVycm9yIiwidG9rZW4iLCJvcmlnaW5hbFN0cmluZyIsIkVycm9yIiwibGVuZ3RoIiwicHJvY2Vzc1Rva2VuIiwiaXNOYU4iLCJwYXJzZU9iamVjdCIsInBhcnNlQXJyYXkiLCJuZXh0VG9rZW4iLCJ0cmltTGVmdCIsImxpbWl0IiwiYyIsImNoYXJDb2RlQXQiLCJuZXN0ZWRPYmplY3QiLCJpIiwiaW5kZXhPZiIsImlzVmFsaWRLZXkiLCJ0ZXN0Iiwia2V5IiwidHJpbSIsIm9iamVjdCIsInJlYWRpbmdLZXkiLCJwcmV2aW91c1Rva2VuIiwiYXJyYXkiLCJwdXNoIiwicGFyc2UiLCJ1dGlsIiwicHJlcGFyZVF1ZXJ5IiwicXVlcnkiLCJGdW5jdGlvbiIsImVsZW1lbnQiLCJtYXRjaCIsImNsYXNzTGlzdCIsImNvbnRhaW5zIiwibm9kZU5hbWUiLCJ0b0xvd2VyQ2FzZSIsImZpbmRDaGlsZCIsImNoaWxkcmVuIiwibm9kZSIsImZpbmRQYXJlbnQiLCJwYXJlbnQiLCJwYXJlbnROb2RlIiwiZG9jdW1lbnQiLCJpc0F0dGFjaGVkIiwiZG9jdW1lbnRFbGVtZW50IiwiaGFzQW55Q29tcG9uZW50QXNQYXJlbnQiLCJwcm9wYWdhdGVBY3Rpb24iLCJhY3Rpb24iLCJjaGlsZE5vZGVzIiwiY2hpbGQiLCJjcmVhdGUiLCJzZWxlY3RvciIsInN0eWxlIiwic3BsaXQiLCJjcmVhdGVFbGVtZW50Iiwic2hpZnQiLCJjbGFzc05hbWUiLCJqb2luIiwiZXh0ZW5kIiwiaHRtbCIsIndyYXBwZXIiLCJjcmVhdGVGcmFnbWVudCIsImZyYWdtZW50IiwiY3JlYXRlRG9jdW1lbnRGcmFnbWVudCIsImZpcnN0Q2hpbGQiLCJhcHBlbmRDaGlsZCIsImRzdCIsImFyZ3MiLCJrZXlzIiwiT2JqZWN0IiwiaiIsImFycmF5RnJvbSIsImFycmF5TGlrZSIsIkFycmF5IiwicHJvdG90eXBlIiwiYXBwbHkiLCJwYXJzZUpTT05PYmplY3RTYWZlbHkiLCJqc29uU3RyaW5nIiwiZmFpbFNhZmUiLCJyZXN1bHQiLCJKU09OIiwiZSIsImZpbmRGcm9tUGF0aCIsInBhdGgiLCJlbCIsIndpbmRvdyIsInRyaWdnZXJFbGVtZW50RXZlbnQiLCJ0YXJnZXQiLCJldmVudE5hbWUiLCJkZXRhaWwiLCJldmVudCIsIkN1c3RvbUV2ZW50IiwiZm9yRWFjaCIsImRpc3BhdGNoRXZlbnQiLCJoYXNNb2RpZmllciIsIm1vZGlmaWVyTmFtZSIsImhhc0F0dHJpYnV0ZSIsImdldEF0dHJpYnV0ZSIsInNvbWUiLCJhZGRNb2RpZmllciIsIm1vZGlmaWVyQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwicmVtb3ZlTW9kaWZpZXIiLCJtb2RpZmllcnMiLCJuZXdNb2RpZmllcnMiLCJmaWx0ZXIiLCJpdGVtIiwidXBkYXRlUGFyZW50UG9zaXRpb24iLCJfcGFyZW50VXBkYXRlZCIsInBhcmVudEVsZW1lbnQiLCJnZXRDb21wdXRlZFN0eWxlIiwiZ2V0UHJvcGVydHlWYWx1ZSIsInBvc2l0aW9uIiwidG9nZ2xlQXR0cmlidXRlIiwibmFtZSIsImVuYWJsZSIsInJlbW92ZUF0dHJpYnV0ZSIsImJpbmRMaXN0ZW5lcnMiLCJsaXN0ZW5lck5hbWVzIiwiYm91bmROYW1lIiwicmVwbGFjZSIsInRvVXBwZXJDYXNlIiwiYmluZCIsImVhY2giLCJvYmoiLCJmIiwidXBkYXRlUmlwcGxlIiwicmlwcGxlRWxlbWVudCIsImluc2VydEJlZm9yZSIsInJlbW92ZSIsImFuaW1hdGlvbk9wdGlvbnNQYXJzZSIsImlzSW50ZWdlciIsInZhbHVlIiwiaXNGaW5pdGUiLCJNYXRoIiwiZmxvb3IiLCJkZWZlciIsImRlZmVycmVkIiwicHJvbWlzZSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiRXZlbnQiLCJVdGlscyIsIkRldGVjdGlvbiIsIlBvaW50ZXJFdmVudCIsIkdlc3R1cmVEZXRlY3RvciIsIm9wdGlvbnMiLCJJbnN0YW5jZSIsImRlZmF1bHRzIiwiRE9DVU1FTlQiLCJIQVNfUE9JTlRFUkVWRU5UUyIsIm5hdmlnYXRvciIsInBvaW50ZXJFbmFibGVkIiwibXNQb2ludGVyRW5hYmxlZCIsIkhBU19UT1VDSEVWRU5UUyIsIklTX01PQklMRSIsInVzZXJBZ2VudCIsIk5PX01PVVNFRVZFTlRTIiwiQ0FMQ1VMQVRFX0lOVEVSVkFMIiwiRVZFTlRfVFlQRVMiLCJESVJFQ1RJT05fRE9XTiIsIkRJUkVDVElPTl9MRUZUIiwiRElSRUNUSU9OX1VQIiwiRElSRUNUSU9OX1JJR0hUIiwiUE9JTlRFUl9NT1VTRSIsIlBPSU5URVJfVE9VQ0giLCJQT0lOVEVSX1BFTiIsIkVWRU5UX1NUQVJUIiwiRVZFTlRfTU9WRSIsIkVWRU5UX0VORCIsIkVWRU5UX1JFTEVBU0UiLCJFVkVOVF9UT1VDSCIsIlJFQURZIiwicGx1Z2lucyIsImdlc3R1cmVzIiwic2V0dXAiLCJkZXRlcm1pbmVFdmVudFR5cGVzIiwiZ2VzdHVyZSIsInJlZ2lzdGVyIiwib25Ub3VjaCIsImRldGVjdCIsInV0aWxzIiwiZGVzdCIsInNyYyIsIm1lcmdlIiwiaGFzT3duUHJvcGVydHkiLCJ1bmRlZmluZWQiLCJvbiIsInR5cGUiLCJoYW5kbGVyIiwiYWRkRXZlbnRMaXN0ZW5lciIsIm9mZiIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJpdGVyYXRvciIsImNvbnRleHQiLCJsZW4iLCJjYWxsIiwiaW5TdHIiLCJmaW5kIiwiaW5BcnJheSIsImluZGV4IiwidG9BcnJheSIsImhhc1BhcmVudCIsImdldENlbnRlciIsInRvdWNoZXMiLCJwYWdlWCIsInBhZ2VZIiwiY2xpZW50WCIsImNsaWVudFkiLCJtaW4iLCJtYXgiLCJ0b3VjaCIsImdldFZlbG9jaXR5IiwiZGVsdGFUaW1lIiwiZGVsdGFYIiwiZGVsdGFZIiwiYWJzIiwiZ2V0QW5nbGUiLCJ0b3VjaDEiLCJ0b3VjaDIiLCJ4IiwieSIsImF0YW4yIiwiUEkiLCJnZXREaXJlY3Rpb24iLCJnZXREaXN0YW5jZSIsInNxcnQiLCJnZXRTY2FsZSIsInN0YXJ0IiwiZW5kIiwiZ2V0Um90YXRpb24iLCJpc1ZlcnRpY2FsIiwiZGlyZWN0aW9uIiwic2V0UHJlZml4ZWRDc3MiLCJwcm9wIiwidG9nZ2xlIiwicHJlZml4ZXMiLCJ0b0NhbWVsQ2FzZSIsInAiLCJ0b2dnbGVCZWhhdmlvciIsInByb3BzIiwiZmFsc2VGbiIsInVzZXJTZWxlY3QiLCJvbnNlbGVjdHN0YXJ0IiwidXNlckRyYWciLCJvbmRyYWdzdGFydCIsInN0ciIsInMiLCJob29rIiwidHlwZXMiLCJldmVudFR5cGUiLCJzZWxmIiwib25Ub3VjaEhhbmRsZXIiLCJldiIsInNyY1R5cGUiLCJpc1BvaW50ZXIiLCJpc01vdXNlIiwidHJpZ2dlclR5cGUiLCJwcmV2ZW50TW91c2VFdmVudHMiLCJidXR0b24iLCJzaG91bGREZXRlY3QiLCJidXR0b25zIiwibWF0Y2hUeXBlIiwidXBkYXRlUG9pbnRlciIsImRvRGV0ZWN0IiwicmVzZXQiLCJ0b3VjaExpc3QiLCJnZXRUb3VjaExpc3QiLCJ0b3VjaExpc3RMZW5ndGgiLCJ0cmlnZ2VyQ2hhbmdlIiwidHJpZ2dlciIsImNoYW5nZWRMZW5ndGgiLCJjaGFuZ2VkVG91Y2hlcyIsInN0YXJ0ZWQiLCJldkRhdGEiLCJjb2xsZWN0RXZlbnREYXRhIiwiaWRlbnRpZmllcnMiLCJjb25jYXQiLCJpZGVudGlmaWVyIiwicG9pbnRlclR5cGUiLCJEYXRlIiwibm93Iiwic3JjRXZlbnQiLCJwcmV2ZW50TWFuaXB1bGF0aW9uIiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iLCJzdG9wRGV0ZWN0IiwidG91Y2hsaXN0IiwicG9pbnRlcnMiLCJwb2ludGVyIiwicG9pbnRlckV2ZW50IiwicG9pbnRlcklkIiwicHQiLCJNU1BPSU5URVJfVFlQRV9NT1VTRSIsIk1TUE9JTlRFUl9UWVBFX1RPVUNIIiwiTVNQT0lOVEVSX1RZUEVfUEVOIiwicmVzZXRMaXN0IiwiZGV0ZWN0aW9uIiwic3RhcnREZXRlY3QiLCJpbnN0IiwiZXZlbnREYXRhIiwiY3VycmVudCIsInN0b3BwZWQiLCJleHRlbmRFdmVudERhdGEiLCJpbnN0T3B0aW9ucyIsInRyaWdnZXJHZXN0dXJlIiwiZW5hYmxlZCIsImxhc3RFdmVudCIsInByZXZpb3VzIiwiZ2V0Q2FsY3VsYXRlZERhdGEiLCJjZW50ZXIiLCJjdXIiLCJyZWNhbGMiLCJjYWxjRXYiLCJsYXN0Q2FsY0V2ZW50IiwiY2FsY0RhdGEiLCJsYXN0Q2FsY0RhdGEiLCJ0aW1lU3RhbXAiLCJmdXR1cmVDYWxjRXZlbnQiLCJ2ZWxvY2l0eSIsImFuZ2xlIiwidmVsb2NpdHlYIiwidmVsb2NpdHlZIiwiaW50ZXJpbUFuZ2xlIiwiaW50ZXJpbURpcmVjdGlvbiIsInN0YXJ0RXYiLCJzdGFydEV2ZW50IiwibGFzdEV2Iiwic29ydCIsImEiLCJiIiwiYmVoYXZpb3IiLCJldmVudFN0YXJ0SGFuZGxlciIsImV2ZW50SGFuZGxlcnMiLCJvbkV2ZW50Iiwib2ZmRXZlbnQiLCJzcGxpY2UiLCJ0cmlnZ2VyRXZlbnQiLCJjcmVhdGVFdmVudCIsImluaXRFdmVudCIsInN0YXRlIiwiZGlzcG9zZSIsImVoIiwidHJpZ2dlcmVkIiwiZHJhZ0dlc3R1cmUiLCJkcmFnTWF4VG91Y2hlcyIsImRpc3RhbmNlIiwiZHJhZ01pbkRpc3RhbmNlIiwic3RhcnRDZW50ZXIiLCJkcmFnRGlzdGFuY2VDb3JyZWN0aW9uIiwiZmFjdG9yIiwiZHJhZ0xvY2tUb0F4aXMiLCJkcmFnTG9ja01pbkRpc3RhbmNlIiwibGFzdERpcmVjdGlvbiIsImRyYWdCbG9ja1ZlcnRpY2FsIiwiZHJhZ0Jsb2NrSG9yaXpvbnRhbCIsIkRyYWciLCJHZXN0dXJlIiwicmVsZWFzZUdlc3R1cmUiLCJ0aW1lciIsImhvbGRHZXN0dXJlIiwic2V0VGltZW91dCIsImhvbGRUaW1lb3V0IiwiaG9sZFRocmVzaG9sZCIsIkhvbGQiLCJSZWxlYXNlIiwiSW5maW5pdHkiLCJTd2lwZSIsInN3aXBlR2VzdHVyZSIsInN3aXBlTWluVG91Y2hlcyIsInN3aXBlTWF4VG91Y2hlcyIsInN3aXBlVmVsb2NpdHlYIiwic3dpcGVWZWxvY2l0eVkiLCJoYXNNb3ZlZCIsInRhcEdlc3R1cmUiLCJwcmV2Iiwic2luY2VQcmV2IiwiZGlkRG91YmxlVGFwIiwidGFwTWF4RGlzdGFuY2UiLCJ0YXBNYXhUaW1lIiwiZG91YmxlVGFwSW50ZXJ2YWwiLCJkb3VibGVUYXBEaXN0YW5jZSIsInRhcEFsd2F5cyIsIlRhcCIsIlRvdWNoIiwidG91Y2hHZXN0dXJlIiwicHJldmVudE1vdXNlIiwidHJhbnNmb3JtR2VzdHVyZSIsInNjYWxlVGhyZXNob2xkIiwic2NhbGUiLCJyb3RhdGlvblRocmVzaG9sZCIsInJvdGF0aW9uIiwidHJhbnNmb3JtTWluU2NhbGUiLCJ0cmFuc2Zvcm1NaW5Sb3RhdGlvbiIsIlRyYW5zZm9ybSIsIlBsYXRmb3JtIiwiX3JlbmRlclBsYXRmb3JtIiwicGxhdGZvcm0iLCJyZWFkeVN0YXRlIiwiY29yZG92YSIsInBob25lZ2FwIiwiUGhvbmVHYXAiLCJkZXZpY2UiLCJvcGVyYSIsIkluc3RhbGxUcmlnZ2VyIiwidG9TdHJpbmciLCJIVE1MRWxlbWVudCIsImNocm9tZSIsImRvY3VtZW50TW9kZSIsInBhcnNlSW50IiwidmVyc2lvbiIsInZlciIsImlzQW5kcm9pZCIsImlzSU9TIiwiaXNXUCIsImlzSVBob25lIiwiaXNJUGFkIiwiaXNJUG9kIiwicmVhZHlNYXAiLCJXZWFrTWFwIiwicXVldWVNYXAiLCJpc0NvbnRlbnRSZWFkeSIsImhhcyIsInNldENvbnRlbnRSZWFkeSIsInNldCIsImFkZENhbGxiYWNrIiwiZm4iLCJnZXQiLCJjb25zdW1lUXVldWUiLCJjYWxsYmFja3MiLCJkZWxldGUiLCJjYWxsYmFjayIsImNvbnRlbnRSZWFkeSIsIm9ic2VydmVyIiwiTXV0YXRpb25PYnNlcnZlciIsIm9ic2VydmUiLCJjaGlsZExpc3QiLCJjaGFyYWN0ZXJEYXRhIiwibm90aWZpY2F0aW9uIiwiX2NyZWF0ZUFsZXJ0RGlhbG9nIiwiaW5wdXRTdHJpbmciLCJpc1Byb21wdCIsImlucHV0VHlwZSIsInBsYWNlaG9sZGVyIiwiZGVmYXVsdFZhbHVlIiwiYnV0dG9uTGFiZWxzIiwibGFiZWwiLCJwcmltYXJ5QnV0dG9uSW5kZXgiLCJfZGVzdHJveURpYWxvZyIsImRpYWxvZyIsIm9uRGlhbG9nQ2FuY2VsIiwiZGVzdHJveSIsInRpdGxlIiwibWVzc2FnZSIsIm1lc3NhZ2VIVE1MIiwibW9kaWZpZXIiLCJzdWJtaXRPbkVudGVyIiwiaW5wdXQiLCJxdWVyeVNlbGVjdG9yIiwib25rZXlwcmVzcyIsImtleUNvZGUiLCJoaWRlIiwidGhlbiIsInJlc29sdmVWYWx1ZSIsImZvb3RlciIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJidXR0b25FbGVtZW50Iiwib25jbGljayIsImNhbmNlbGFibGUiLCJib2R5IiwiY29tcGlsZSIsInNob3ciLCJhdXRvZm9jdXMiLCJmb2N1cyIsIl9ub3JtYWxpemVBcmd1bWVudHMiLCJidXR0b25MYWJlbCIsImlzQXJyYXkiLCJwYXJhbSIsImFsZXJ0IiwiY29uZmlybSIsInByb21wdCIsInBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIiwib3ZlcndyaXRlIiwiX3ZhcmlhYmxlcyIsInBhcnQiLCJpbkludGVycG9sYXRpb24iLCJjdXJyZW50SW5kZXgiLCJ0b2tlbnMiLCJjaGFyQXQiLCJzdWJzdHJpbmciLCJyZSIsInZhcmlhYmxlIiwiZ2V0VmFyaWFibGUiLCJydiIsIm1hcCIsIl9yZXBsYWNlVG9rZW4iLCJleHByZXNzaW9uIiwiX3BhcnNlUGFydCIsIl9yZXBsYWNlVG9rZW5zIiwiX3BhcnNlRXhwcmVzc2lvbiIsImRlZmluZVZhcmlhYmxlIiwiZ2V0TW9iaWxlT1MiLCJnZXRJT1NEZXZpY2UiLCJpc1dlYlZpZXciLCJpbnRlcm5hbCIsImNvbmZpZyIsIm51bGxFbGVtZW50IiwiaXNFbmFibGVkQXV0b1N0YXR1c0JhckZpbGwiLCJhdXRvU3RhdHVzQmFyRmlsbCIsIm5vcm1hbGl6ZVBhZ2VIVE1MIiwid2FpdERPTUNvbnRlbnRMb2FkZWQiLCJvblJlYWR5Iiwic2hvdWxkRmlsbFN0YXR1c0JhciIsImlzSU9TN2Fib3ZlIiwidGVtcGxhdGVTdG9yZSIsIl9zdG9yYWdlIiwidGVtcGxhdGUiLCJ0ZW1wbGF0ZUlkIiwidGVtcGxhdGVzIiwidGV4dENvbnRlbnQiLCJnZXRUZW1wbGF0ZUhUTUxBc3luYyIsInBhZ2UiLCJjYWNoZSIsInhociIsIlhNTEh0dHBSZXF1ZXN0Iiwib3BlbiIsIm9ubG9hZCIsInJlc3BvbnNlIiwicmVzcG9uc2VUZXh0Iiwic3RhdHVzIiwib25lcnJvciIsInNlbmQiLCJnZXRQYWdlSFRNTEFzeW5jIiwicGFnZXMiLCJldmFsdWF0ZSIsImdldFBhZ2UiLCJBbmltYXRvckZhY3RvcnkiLCJvcHRzIiwiX2FuaW1hdG9ycyIsImFuaW1hdG9ycyIsIl9iYXNlQ2xhc3MiLCJiYXNlQ2xhc3MiLCJfYmFzZUNsYXNzTmFtZSIsImJhc2VDbGFzc05hbWUiLCJfYW5pbWF0aW9uIiwiZGVmYXVsdEFuaW1hdGlvbiIsIl9hbmltYXRpb25PcHRpb25zIiwiZGVmYXVsdEFuaW1hdGlvbk9wdGlvbnMiLCJkZWZhdWx0QW5pbWF0b3IiLCJhbmltYXRvciIsImFuaW1hdGlvbiIsIkFuaW1hdG9yIiwiYW5pbWF0aW9uT3B0cyIsImFuaW1hdGlvbk9wdGlvbnMiLCJhbmltYXRpb25zRGlzYWJsZWQiLCJkdXJhdGlvbiIsImRlbGF5IiwiTW9kaWZpZXJVdGlsIiwibGFzdCIsIm1ha2VEaWN0IiwicmVtb3ZlZCIsInJlZHVjZSIsImFkZGVkIiwiZGljdCIsImRpZmYiLCJhZGQiLCJrbGFzcyIsInNjaGVtZSIsIm1hdGNoZXMiLCJ3ZWJraXRNYXRjaGVzU2VsZWN0b3IiLCJtb3pNYXRjaGVzU2VsZWN0b3IiLCJtc01hdGNoZXNTZWxlY3RvciIsInRhcmdldEVsZW1lbnRzIiwiYXBwbHlEaWZmVG9DbGFzc0xpc3QiLCJhcHBseURpZmZUb0VsZW1lbnQiLCJMYXp5UmVwZWF0RGVsZWdhdGUiLCJ1c2VyRGVsZWdhdGUiLCJ0ZW1wbGF0ZUVsZW1lbnQiLCJfdXNlckRlbGVnYXRlIiwiRWxlbWVudCIsIl90ZW1wbGF0ZUVsZW1lbnQiLCJfcmVuZGVyIiwiaXRlbXMiLCJoZWlnaHQiLCJkb25lIiwibG9hZEl0ZW1FbGVtZW50IiwiY3JlYXRlSXRlbUNvbnRlbnQiLCJjb3VudCIsImNvdW50SXRlbXMiLCJ1cGRhdGVJdGVtQ29udGVudCIsImNhbGN1bGF0ZUl0ZW1IZWlnaHQiLCJkZXN0cm95SXRlbSIsIml0ZW1IZWlnaHQiLCJMYXp5UmVwZWF0UHJvdmlkZXIiLCJ3cmFwcGVyRWxlbWVudCIsImRlbGVnYXRlIiwiX3dyYXBwZXJFbGVtZW50IiwiX2RlbGVnYXRlIiwidGFnTmFtZSIsIl9wYWdlQ29udGVudCIsIl9maW5kUGFnZUNvbnRlbnRFbGVtZW50IiwiX3RvcFBvc2l0aW9ucyIsIl9yZW5kZXJlZEl0ZW1zIiwiX3Vua25vd25JdGVtSGVpZ2h0IiwiX2FkZEV2ZW50TGlzdGVuZXJzIiwiX29uQ2hhbmdlIiwicGFnZUNvbnRlbnQiLCJjb250ZW50IiwicmVtb3ZlQ2hpbGQiLCJfaXRlbUhlaWdodCIsIm9mZnNldEhlaWdodCIsImxhc3RWaXNpYmlsaXR5IiwidmlzaWJpbGl0eSIsInN0YXRpY0l0ZW1IZWlnaHQiLCJfcmVtb3ZlQWxsRWxlbWVudHMiLCJfY2hlY2tJdGVtSGVpZ2h0IiwiX2dldEl0ZW1zSW5WaWV3IiwiaGFzUmVuZGVyRnVuY3Rpb24iLCJfbGlzdEhlaWdodCIsImtlZXAiLCJfcmVuZGVyRWxlbWVudCIsIl9yZW1vdmVFbGVtZW50IiwidG9wIiwidXBkYXRlSXRlbSIsIl9pdGVtQ291bnQiLCJtaWRkbGUiLCJfZ2V0SXRlbUhlaWdodCIsImwiLCJvZmZzZXQiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJpbm5lckhlaWdodCIsIl9jb3VudEl0ZW1zIiwiX3JlY2FsY3VsYXRlVG9wUG9zaXRpb25zIiwiX2NhbGN1bGF0ZVN0YXJ0SW5kZXgiLCJmdW5jIiwid2FpdCIsImltbWVkaWF0ZSIsInRpbWVvdXQiLCJjYWxsTm93IiwiYXJndW1lbnRzIiwiX2RlYm91bmNlIiwiX2JvdW5kT25DaGFuZ2UiLCJfYm91bmREb3VibGVGaXJlT25Ub3VjaGVuZCIsIl9wYXJlbnRFbGVtZW50IiwiX3JlbW92ZUV2ZW50TGlzdGVuZXJzIiwiX2lzUG9ydHJhaXQiLCJpc1BvcnRyYWl0IiwiX29uRE9NQ29udGVudExvYWRlZCIsIl9vbk9yaWVudGF0aW9uQ2hhbmdlIiwiX29uUmVzaXplIiwiaW5uZXJXaWR0aCIsIl9pbnN0YWxsSXNQb3J0cmFpdEltcGxlbWVudGF0aW9uIiwiZW1pdCIsIm9yaWVudGF0aW9uIiwibkl0ZXIiLCJpbnRlcnZhbCIsInNldEludGVydmFsIiwidyIsImgiLCJtaXhpbiIsIl9pbml0Iiwic29mdHdhcmVLZXlib2FyZCIsIk1pY3JvRXZlbnQiLCJfdmlzaWJsZSIsIm9uU2hvdyIsIm9uSGlkZSIsImJpbmRFdmVudHMiLCJLZXlib2FyZCIsIm9uc2hvdyIsIm9uaGlkZSIsInZpc2libGUiLCJpc1Zpc2libGUiLCJub1BsdWdpbkVycm9yIiwid2FybiIsIl9kb21Db250ZW50TG9hZGVkIiwiX3JlYWR5IiwiSGFuZGxlclJlcG9zaXRvcnkiLCJkYXRhc2V0IiwiZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZCIsImlkIiwiX2dlbklkIiwiX3N0b3JlIiwiRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIiLCJfaXNFbmFibGVkIiwiX2JvdW5kQ2FsbGJhY2siLCJfY2FsbGJhY2siLCJhZGRCYWNrQnV0dG9uTGlzdGVuZXIiLCJyZW1vdmVCYWNrQnV0dG9uTGlzdGVuZXIiLCJfZGlzcGF0Y2hEZXZpY2VCYWNrQnV0dG9uRXZlbnQiLCJfZWxlbWVudCIsInRyZWUiLCJfY2FwdHVyZVRyZWUiLCJfZmluZEhhbmRsZXJMZWFmRWxlbWVudCIsImNyZWF0ZVRyZWUiLCJhcnJheU9mIiwiY2hpbGRFbGVtZW50IiwiZGlzcGxheSIsImNoaWxkTm9kZSIsImxlZnQiLCJyaWdodCIsImxlZnRaIiwiekluZGV4IiwicmlnaHRaIiwiYXV0b1N0eWxlRW5hYmxlZCIsIm1vZGlmaWVyc01hcCIsInBsYXRmb3JtcyIsImFuZHJvaWQiLCJvbGRNb2RpZmllciIsIm5ld01vZGlmaWVyIiwidW5zaGlmdCIsImlvcyIsInVubG9ja2VkIiwicHJlcGFyZUF1dG9TdHlsZSIsImZvcmNlIiwibW9iaWxlT1MiLCJvbnNQbGF0Zm9ybSIsImdlbmVyYXRlSWQiLCJEb29yTG9jayIsIl9sb2NrTGlzdCIsIl93YWl0TGlzdCIsIl9sb2ciLCJsb2ciLCJ1bmxvY2siLCJfdW5sb2NrIiwiX3RyeVRvRnJlZVdhaXRMaXN0IiwiaXNMb2NrZWQiLCJsb2FkUGFnZSIsInBhcmFtcyIsImlubmVySFRNTCIsIlBhZ2VMb2FkZXIiLCJfbG9hZGVyIiwidW5sb2FkIiwiZGVmYXVsdFBhZ2VMb2FkZXIiLCJpbnN0YW50UGFnZUxvYWRlciIsIm9ucyIsIl91dGlsIiwiX2RldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyIiwiZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIiLCJfaW50ZXJuYWwiLCJQYWdlQXR0cmlidXRlRXhwcmVzc2lvbiIsIl9hbmltYXRpb25PcHRpb25zUGFyc2VyIiwiYW5pbWF0aW9uT3B0aW9uc1BhcnNlciIsIl9hdXRvU3R5bGUiLCJhdXRvU3R5bGUiLCJfRG9vckxvY2siLCJfY29udGVudFJlYWR5IiwiX3JlYWR5TG9jayIsInNlbGVjdCIsImxvY2F0aW9uIiwic2VhcmNoIiwid2FpdERldmljZVJlYWR5IiwiaXNSZWFkeSIsInJlYWR5Iiwid2FpdFVubG9jayIsInNldERlZmF1bHREZXZpY2VCYWNrQnV0dG9uTGlzdGVuZXIiLCJsaXN0ZW5lciIsIl9kZWZhdWx0RGV2aWNlQmFja0J1dHRvbkhhbmRsZXIiLCJzZXRMaXN0ZW5lciIsImRpc2FibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlciIsImRpc2FibGUiLCJlbmFibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlciIsImVuYWJsZUF1dG9TdGF0dXNCYXJGaWxsIiwiZGlzYWJsZUF1dG9TdGF0dXNCYXJGaWxsIiwiZGlzYWJsZUFuaW1hdGlvbnMiLCJlbmFibGVBbmltYXRpb25zIiwiZGlzYWJsZUF1dG9TdHlsaW5nIiwiZW5hYmxlQXV0b1N0eWxpbmciLCJmb3JjZVBsYXRmb3JtU3R5bGluZyIsIm5ld1BsYXRmb3JtIiwiX3BsYXRmb3JtVXBkYXRlIiwicHJlcGFyZSIsIl91cGRhdGVQb3NpdGlvbiIsIl9jcmVhdGVQb3BvdmVyT3JpZ2luYWwiLCJkaXYiLCJwb3BvdmVyIiwibGluayIsImNyZWF0ZVBvcG92ZXIiLCJfY3JlYXRlRGlhbG9nT3JpZ2luYWwiLCJjcmVhdGVEaWFsb2ciLCJfY3JlYXRlQWxlcnREaWFsb2dPcmlnaW5hbCIsImFsZXJ0RGlhbG9nIiwiY3JlYXRlQWxlcnREaWFsb2ciLCJfcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlck9yaWdpbmFsIiwiZWxlbWVudHMiLCJfcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlciIsInJlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIiLCJfc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzIiwiY29udGVudEVsZW1lbnQiLCJjYXRjaCIsInVubG9ja0RldmljZVJlYWR5IiwibG9jayIsIl9zdXBlclNlY3JldE9ucyIsImdldEVsZW1lbnRDbGFzcyIsIkJhc2VFbGVtZW50IiwiaW5pdCIsIlRlbXBsYXRlRWxlbWVudCIsImJ1YmJsZXMiLCJjdXN0b21FbGVtZW50cyIsImRlZmluZSIsIklmRWxlbWVudCIsIl9pc0FsbG93ZWRQbGF0Zm9ybSIsImNvbmRpdGlvbmFsT3JpZW50YXRpb24iLCJjdXJyZW50T3JpZW50YXRpb24iLCJBbGVydERpYWxvZ0FuaW1hdG9yIiwidGltaW5nIiwiQW5kcm9pZEFsZXJ0RGlhbG9nQW5pbWF0b3IiLCJydW5BbGwiLCJhbmltaXQiLCJfbWFzayIsInF1ZXVlIiwiX2RpYWxvZyIsInNhdmVTdHlsZSIsInJlc3RvcmVTdHlsZSIsIklPU0FsZXJ0RGlhbG9nQW5pbWF0b3IiLCJfYW5pbWF0b3JEaWN0IiwiQWxlcnREaWFsb2dFbGVtZW50IiwiX2NvbXBpbGUiLCJfZG9vckxvY2siLCJfYm91bmRDYW5jZWwiLCJfY2FuY2VsIiwiX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSIsIl9hbmltYXRvckZhY3RvcnkiLCJtYXNrIiwiY29udGFpbmVyIiwiYmFja2dyb3VuZENvbG9yIiwiaW5pdE1vZGlmaWVyIiwiY2FuY2VsIiwicGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nIiwidHJ5U2hvdyIsIm5ld0FuaW1hdG9yIiwib3BhY2l0eSIsInRyeUhpZGUiLCJfcnVubmluZyIsIm9uRGV2aWNlQmFja0J1dHRvbiIsImNhbGxQYXJlbnRIYW5kbGVyIiwiX2JhY2tCdXR0b25IYW5kbGVyIiwib25Nb2RpZmllckNoYW5nZWQiLCJjcmVhdGVIYW5kbGVyIiwiQmFja0J1dHRvbkVsZW1lbnQiLCJfb3B0aW9ucyIsIl9ib3VuZE9uQ2xpY2siLCJfb25DbGljayIsImljb24iLCJvbkNsaWNrIiwicG9wUGFnZSIsIkJvdHRvbVRvb2xiYXJFbGVtZW50IiwiQnV0dG9uRWxlbWVudCIsIl91cGRhdGVSaXBwbGUiLCJDYXJvdXNlbEl0ZW1FbGVtZW50Iiwid2lkdGgiLCJWZXJ0aWNhbE1vZGVUcmFpdCIsIl9jdXJyZW50RWxlbWVudFNpemUiLCJzY3JvbGwiLCJfc3R5bGUiLCJfZGltZW5zaW9ucyIsImNlbnRlcmVkIiwicGFkZGluZ1RvcCIsInBhZGRpbmdCb3R0b20iLCJfb2Zmc2V0IiwiX2dldENhcm91c2VsSXRlbVNpemUiLCJfZ2V0Q2Fyb3VzZWxJdGVtRWxlbWVudHMiLCJzaXplQXR0ciIsIl9nZXRDYXJvdXNlbEl0ZW1TaXplQXR0ciIsInNpemVJbmZvIiwiX2RlY29tcG9zZVNpemVTdHJpbmciLCJudW1iZXIiLCJ1bml0IiwiX3VwZGF0ZURpbWVuc2lvbkRhdGEiLCJfdXBkYXRlT2Zmc2V0IiwiX2xheW91dENhcm91c2VsSXRlbXMiLCJIb3Jpem9udGFsTW9kZVRyYWl0IiwicGFkZGluZ0xlZnQiLCJwYWRkaW5nUmlnaHQiLCJDYXJvdXNlbEVsZW1lbnQiLCJfc2Nyb2xsIiwiX2xhc3RBY3RpdmVJbmRleCIsIl9ib3VuZE9uRHJhZyIsIl9vbkRyYWciLCJfYm91bmRPbkRyYWdFbmQiLCJfb25EcmFnRW5kIiwiX2JvdW5kT25SZXNpemUiLCJfbWl4aW4iLCJfaXNWZXJ0aWNhbCIsInNldEFjdGl2ZUluZGV4Iiwib3ZlcmZsb3dYIiwib3ZlcmZsb3dZIiwicmVmcmVzaCIsIl9sYXN0U3RhdGUiLCJpdGVtQ291bnQiLCJlbGVtZW50U2l6ZSIsIl9nZXRFbGVtZW50U2l6ZSIsInJvdW5kIiwiYXR0ck5hbWUiLCJpdGVtU2l6ZUF0dHIiLCJzaXplIiwiX2dldEluaXRpYWxJbmRleCIsIl9zY3JvbGxUbyIsIl9jYWxjdWxhdGVNYXhTY3JvbGwiLCJfdHJ5RmlyZVBvc3RDaGFuZ2VFdmVudCIsImdldEFjdGl2ZUluZGV4IiwiY2Fyb3VzZWxJdGVtU2l6ZSIsImF1dG9TY3JvbGwiLCJfZ2VzdHVyZURldGVjdG9yIiwiX211dGF0aW9uT2JzZXJ2ZXIiLCJfdXBkYXRlU3dpcGVhYmxlIiwiX3VwZGF0ZUF1dG9SZWZyZXNoIiwiZGlzY29ubmVjdCIsInN3aXBlYWJsZSIsImxhc3RBY3RpdmVJbmRleCIsImQiLCJfaXNXcm9uZ0RpcmVjdGlvbiIsIl9sYXN0RHJhZ0V2ZW50IiwiX2dldFNjcm9sbERlbHRhIiwiX2lzT3ZlclNjcm9sbCIsIndhaXRGb3JBY3Rpb24iLCJfZ2V0T3ZlclNjcm9sbERpcmVjdGlvbiIsIl9zY3JvbGxUb0tpbGxPdmVyU2Nyb2xsIiwiX3N0YXJ0TW9tZW50dW1TY3JvbGwiLCJ0cmFpdCIsIl9nZXRTY3JvbGxWZWxvY2l0eSIsInNjcm9sbERlbHRhIiwiX25vcm1hbGl6ZVNjcm9sbFBvc2l0aW9uIiwiX2dlbmVyYXRlU2Nyb2xsVHJhbnNmb3JtIiwicGxheSIsImFyciIsIm5ick9mSXRlbXMiLCJwb3MiLCJsYXN0U2Nyb2xsIiwic2Nyb2xsUmF0aW8iLCJhdXRvU2Nyb2xsUmF0aW8iLCJpc092ZXJzY3JvbGxhYmxlIiwib3ZlcnNjcm9sbGFibGUiLCJub3JtYWxpemVTY3JvbGwiLCJyYXRpbyIsIm1heFNjcm9sbCIsImNlaWwiLCJfc2V0dXAiLCJfc2F2ZUxhc3RTdGF0ZSIsImNhcm91c2VsIiwiX3ByZXBhcmVFdmVudExpc3RlbmVycyIsIl9zZXR1cEluaXRpYWxJbmRleCIsIl9vbkRpcmVjdGlvbkNoYW5nZSIsImF0dHIiLCJwYXJzZUZsb2F0IiwiQ29sRWxlbWVudCIsIl91cGRhdGVXaWR0aCIsIndlYmtpdEJveEZsZXgiLCJ3ZWJraXRGbGV4IiwibW96Qm94RmxleCIsIm1vekZsZXgiLCJtc0ZsZXgiLCJmbGV4IiwibWF4V2lkdGgiLCJEaWFsb2dBbmltYXRvciIsIkFuZHJvaWREaWFsb2dBbmltYXRvciIsIklPU0RpYWxvZ0FuaW1hdG9yIiwiU2xpZGVEaWFsb2dBbmltYXRvciIsIkRpYWxvZ0VsZW1lbnQiLCJGYWJFbGVtZW50IiwidHJhbnNmb3JtIiwid2Via2l0VHJhbnNmb3JtIiwiR2VzdHVyZURldGVjdG9yRWxlbWVudCIsIkljb25FbGVtZW50IiwiX3VwZGF0ZSIsIl9jbGVhbkNsYXNzQXR0cmlidXRlIiwiX2J1aWxkQ2xhc3NBbmRTdHlsZSIsIl9nZXRBdHRyaWJ1dGUiLCJwYXJ0cyIsImRlZiIsIm1kIiwiaWNvbk5hbWUiLCJyZW1vdmVQcm9wZXJ0eSIsImZvbnRTaXplIiwiTGF6eVJlcGVhdEVsZW1lbnQiLCJfbGF6eVJlcGVhdFByb3ZpZGVyIiwiTGlzdEhlYWRlckVsZW1lbnQiLCJMaXN0SXRlbUVsZW1lbnQiLCJfb25Ub3VjaCIsIl9vblJlbGVhc2UiLCJfb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IiLCJ0YXBwZWQiLCJfc2hvdWxkTG9ja09uRHJhZyIsInRyYW5zaXRpb24iLCJfdHJhbnNpdGlvbiIsIndlYmtpdFRyYW5zaXRpb24iLCJNb3pUcmFuc2l0aW9uIiwiX3RhcHBhYmxlIiwiX3RhcEJhY2tncm91bmRDb2xvciIsImJveFNoYWRvdyIsIkxpc3RFbGVtZW50IiwiSU5QVVRfQVRUUklCVVRFUyIsIklucHV0RWxlbWVudCIsImF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayIsIl9ib3VuZE9uSW5wdXQiLCJfb25JbnB1dCIsIl9ib3VuZE9uRm9jdXNpbiIsIl9vbkZvY3VzaW4iLCJfYm91bmREZWxlZ2F0ZUV2ZW50IiwiX2RlbGVnYXRlRXZlbnQiLCJoZWxwZXIiLCJfaW5wdXQiLCJfaGVscGVyIiwiX3VwZGF0ZUJvdW5kQXR0cmlidXRlcyIsIl91cGRhdGVMYWJlbCIsIl91cGRhdGVMYWJlbENsYXNzIiwiY2hlY2tlZCIsIl9ib3VuZE9uRm9jdXNvdXQiLCJpbm5lclRleHQiLCJfc2V0TGFiZWwiLCJ2YWwiLCJNb2RhbEFuaW1hdG9yIiwibW9kYWwiLCJGYWRlTW9kYWxBbmltYXRvciIsIk1vZGFsRWxlbWVudCIsIk5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciIsImVudGVyUGFnZSIsImxlYXZlUGFnZSIsInByb3BlcnRpZXMiLCJleHRlbmRlZEFuaW1hdG9yIiwiSU9TU2xpZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IiLCJiYWNrZ3JvdW5kTWFzayIsInRvb2xiYXIiLCJfZ2V0VG9vbGJhckVsZW1lbnQiLCJfZ2V0VG9vbGJhckxlZnRJdGVtc0VsZW1lbnQiLCJfZ2V0VG9vbGJhclJpZ2h0SXRlbXNFbGVtZW50IiwiZXhjbHVkZUJhY2tCdXR0b24iLCJvdGhlciIsIl9nZXRUb29sYmFyQ2VudGVySXRlbXNFbGVtZW50IiwiX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQiLCJfZ2V0VG9vbGJhckJhY2tCdXR0b25MYWJlbEVsZW1lbnQiLCJfZ2V0Q29udGVudEVsZW1lbnQiLCJfZ2V0QmFja2dyb3VuZEVsZW1lbnQiLCJfZ2V0Qm90dG9tVG9vbGJhckVsZW1lbnQiLCJib3RoUGFnZUhhc1Rvb2xiYXIiLCJfY2FuQW5pbWF0ZVRvb2xiYXIiLCJub01hdGVyaWFsVG9vbGJhciIsImRlY29tcG9zaXRpb24iLCJwYWdlUmVjdCIsImJhY2tCdXR0b25MYWJlbCIsImxhYmVsUmVjdCIsImJhY2tCdXR0b25JY29uIiwibmV4dFNpYmxpbmciLCJlbnRlclBhZ2VEZWNvbXBvc2l0aW9uIiwiX2RlY29tcG9zZSIsImxlYXZlUGFnZURlY29tcG9zaXRpb24iLCJkZWx0YSIsIl9jYWxjdWxhdGVEZWx0YSIsIm1hc2tDbGVhciIsInNob3VsZEFuaW1hdGVUb29sYmFyIiwiX3Nob3VsZEFuaW1hdGVUb29sYmFyIiwiZW50ZXJQYWdlVG9vbGJhckhlaWdodCIsImJvdHRvbVRvb2xiYXIiLCJiYWNrZ3JvdW5kIiwidG9vbGJhckNlbnRlciIsImZpbmlzaCIsIklPU0xpZnROYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IiLCJJT1NGYWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIiwiTURTbGlkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciIsImJsYWNrTWFza09wYWNpdHkiLCJNRExpZnROYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IiLCJNREZhZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IiLCJOb25lTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIiwicmV3cml0YWJsZXMiLCJuYXZpZ2F0b3JFbGVtZW50IiwiTmF2aWdhdG9yRWxlbWVudCIsIl9pc1J1bm5pbmciLCJfcGFnZUxvYWRlciIsIl9wYWdlIiwiX29uRGV2aWNlQmFja0J1dHRvbiIsIl9nZXRQYWdlVGFyZ2V0IiwicHVzaFBhZ2UiLCJ0b3BQYWdlIiwiX3Nob3ciLCJfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uIiwiX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyIsInBvcFVwZGF0ZSIsIl9kZXN0cm95IiwiX3BvcFBhZ2UiLCJvbGRQYWdlIiwicHVzaGVkT3B0aW9ucyIsImRhdGEiLCJsb2FkIiwidXBkYXRlIiwiX2VtaXRQcmVQb3BFdmVudCIsInVwZGF0ZUJhY2tCdXR0b24iLCJfaGlkZSIsInBvcCIsIl92ZXJpZnlQYWdlRWxlbWVudCIsInBhZ2VIVE1MIiwiX3B1c2hQYWdlIiwiX2VtaXRQcmVQdXNoRXZlbnQiLCJwYWdlTGVuZ3RoIiwiX2xpbmtlZCIsInJlc29sdmVkVmFsdWUiLCJfbm9ybWFsaXplSW5kZXgiLCJsb2FkZXIiLCJfbGFzdEluZGV4T2ZQYWdlIiwicGFnZU5hbWUiLCJpc0NhbmNlbGVkIiwiX2VtaXRQcmVFdmVudCIsInRlbXBsYXRlSFRNTCIsInBhZ2VFbGVtZW50IiwicGFnZUxvYWRlciIsIm4iLCJUb29sYmFyRWxlbWVudCIsIl9lbnN1cmVUb29sYmFySXRlbUVsZW1lbnRzIiwibm9kZVR5cGUiLCJfZW5zdXJlVG9vbGJhckVsZW1lbnQiLCJudWxsVG9vbGJhckVsZW1lbnQiLCJQYWdlRWxlbWVudCIsIl9pc1Nob3duIiwiX2NvbnRlbnRFbGVtZW50IiwiX2lzTXV0ZWQiLCJfc2tpcEluaXQiLCJfdHJ5VG9GaWxsU3RhdHVzQmFyIiwiYmFja0J1dHRvbiIsImZpbGxlZCIsIl9oYXNBUGFnZUNvbnRyb2xDaGlsZCIsIm92ZXJMaW1pdCIsInNjcm9sbFRvcCIsImNsaWVudEhlaWdodCIsInNjcm9sbEhlaWdodCIsIl9pbmZpbml0ZVNjcm9sbExpbWl0IiwiX29uSW5maW5pdGVTY3JvbGwiLCJfbG9hZGluZ0NvbnRlbnQiLCJvbkluZmluaXRlU2Nyb2xsIiwiX2VsZW1lbnRTaG91bGRCZU1vdmVkIiwicHJldk5vZGUiLCJmaXhlZEVsZW1lbnRzIiwiX2JvdW5kT25TY3JvbGwiLCJfb25TY3JvbGwiLCJQb3BvdmVyQW5pbWF0b3IiLCJmcm9tIiwidG8iLCJyZXN0b3JlIiwiYW5pbWF0aW9ucyIsIl9hbmltYXRlIiwiZmFkZSIsIk1ERmFkZVBvcG92ZXJBbmltYXRvciIsIl9hbmltYXRlQWxsIiwiaW4iLCJvdXQiLCJJT1NGYWRlUG9wb3ZlckFuaW1hdG9yIiwidGVtcGxhdGVTb3VyY2UiLCJwb3NpdGlvbnMiLCJQb3BvdmVyRWxlbWVudCIsIl9pbml0QW5pbWF0b3JGYWN0b3J5IiwiZmFjdG9yeSIsIl9hbmltYXRvciIsInJhZGl1cyIsIl9yYWRpdXMiLCJfY29udGVudCIsIm1hcmdpbiIsIl9tYXJnaW4iLCJpc01EIiwiY292ZXIiLCJib3R0b20iLCJfY2FsY3VsYXRlRGlyZWN0aW9ucyIsInZlcnRpY2FsIiwicHJpbWFyeSIsInNlY29uZGFyeSIsIl9wb3BvdmVyIiwic2l6ZXMiLCJfYXJyb3ciLCJfc2V0VHJhbnNmb3JtT3JpZ2luIiwiY2FsYyIsIm8iLCJfY3VycmVudFRhcmdldCIsIl9wb3NpdGlvblBvcG92ZXIiLCJoYXNEZWZhdWx0Q29udGFpbmVyIiwiYXJyb3ciLCJjbG9uZU5vZGUiLCJhY3Rpb25zIiwiYmVmb3JlIiwiYWZ0ZXIiLCJfcHJlcGFyZUFuaW1hdGlvbk9wdGlvbnMiLCJjYW5jZWxlZCIsIl9leGVjdXRlQWN0aW9uIiwiX2NsZWFyU3R5bGVzIiwiX3Jlc2V0QmFja0J1dHRvbkhhbmRsZXIiLCJQcm9ncmVzc0JhckVsZW1lbnQiLCJfaXNDb21waWxlZCIsIl90ZW1wbGF0ZSIsIl9wcmltYXJ5IiwiX3NlY29uZGFyeSIsIl91cGRhdGVEZXRlcm1pbmF0ZSIsIl91cGRhdGVWYWx1ZSIsImJhckVsZW1lbnQiLCJQcm9ncmVzc0NpcmN1bGFyRWxlbWVudCIsInBlciIsInN2ZyIsIlNUQVRFX0lOSVRJQUwiLCJTVEFURV9QUkVBQ1RJT04iLCJTVEFURV9BQ1RJT04iLCJyZW1vdmVUcmFuc2Zvcm0iLCJXZWJraXRUcmFuc2Zvcm0iLCJXZWJraXRUcmFuc2l0aW9uIiwiUHVsbEhvb2tFbGVtZW50IiwiX2JvdW5kT25EcmFnU3RhcnQiLCJfb25EcmFnU3RhcnQiLCJfc2V0U3RhdGUiLCJsaW5lSGVpZ2h0IiwibWFyZ2luVG9wIiwiX3BhZ2VFbGVtZW50IiwiZGlzYWJsZWQiLCJfc3RhcnRTY3JvbGwiLCJfY3VycmVudFRyYW5zbGF0aW9uIiwiX2dldEN1cnJlbnRTY3JvbGwiLCJfdHJhbnNpdGlvbkRyYWdMZW5ndGgiLCJfdGhyZXNob2xkSGVpZ2h0RW5hYmxlZCIsInRocmVzaG9sZEhlaWdodCIsIl9maW5pc2giLCJfdHJhbnNsYXRlVG8iLCJhbmltYXRlIiwib25BY3Rpb24iLCJ0aCIsIm5vRXZlbnQiLCJsYXN0U3RhdGUiLCJfZ2V0U3RhdGUiLCJfaXNDb250ZW50Rml4ZWQiLCJfZ2V0U2Nyb2xsYWJsZUVsZW1lbnQiLCJfZ2VuZXJhdGVUcmFuc2xhdGlvblRyYW5zZm9ybSIsIl9kcmFnTG9ja0Rpc2FibGVkIiwiX2Rlc3Ryb3lFdmVudExpc3RlbmVycyIsIl9jcmVhdGVFdmVudExpc3RlbmVycyIsIl9zZXRTdHlsZSIsIkFuaW1hdG9yQ1NTIiwiZmluYWwiLCJnZXRUaW1lIiwiaW5pdGlhbCIsIm5leHQiLCJ1cGRhdGVTdHlsZXMiLCJjbGVhclRpbWVvdXQiLCJrIiwidHJhbnNpdGlvbkR1cmF0aW9uIiwic3RvcE5leHQiLCJjYiIsIm5ld0R1cmF0aW9uIiwicGFzc2VkIiwicmVtYWluaW5nIiwic3BlZWRVcFRpbWUiLCJzdG9wIiwibWlsbGlzZWNvbmRzIiwic3BlZWQiLCJ2IiwidHJhbnNpdGlvblByb3BlcnR5IiwiX29uU3RvcEFuaW1hdGlvbnMiLCJfcXVldWUiLCJfaW5kZXgiLCJzdG9wQW5pbWF0aW9ucyIsIlJpcHBsZUVsZW1lbnQiLCJfd2F2ZSIsImdldEVsZW1lbnRzQnlDbGFzc05hbWUiLCJfYmFja2dyb3VuZCIsInIiLCJfY2VudGVyIiwiX21pblIiLCJfY2FsY3VsYXRlQ29vcmRzIiwic3RvcEFsbCIsImNvbXB1dGVkU3R5bGUiLCJfdXBkYXRlUGFyZW50IiwiX3JpcHBsZUFuaW1hdGlvbiIsIl9ob2xkaW5nIiwiX2JvdW5kT25SZWxlYXNlIiwiX29uVGFwIiwiX3BhcmVudE5vZGUiLCJfYm91bmRPblRhcCIsIl9ib3VuZE9uSG9sZCIsIl9vbkhvbGQiLCJwbiIsIlJvd0VsZW1lbnQiLCJTcGVlZERpYWxJdGVtRWxlbWVudCIsInN0eWxlciIsImNzcyIsInN0eWxlcyIsIl9wcmVmaXgiLCJwcmVmaXgiLCJPTGluayIsInN1YnN0ciIsImNsZWFyIiwiX2NsZWFyIiwiU3BlZWREaWFsRWxlbWVudCIsIl9zaG93biIsIl9pdGVtU2hvd24iLCJfdXBkYXRlRGlyZWN0aW9uIiwidG9nZ2xlSXRlbXMiLCJpbmxpbmUiLCJmYWIiLCJoaWRlSXRlbXMiLCJpc09wZW4iLCJzaG93SXRlbXMiLCJTcGxpdHRlckNvbnRlbnRFbGVtZW50IiwiU3BsaXR0ZXJNYXNrRWxlbWVudCIsIl9zaWRlcyIsInNpZGUiLCJjbG9zZSIsIlNwbGl0dGVyQW5pbWF0b3IiLCJ1cGRhdGVPcHRpb25zIiwiX3RpbWluZyIsIl9kdXJhdGlvbiIsIl9kZWxheSIsInNpZGVFbGVtZW50Iiwic3BsaXR0ZXIiLCJfc2lkZSIsIm1pbnVzIiwiU3BsaXR0ZXJFbGVtZW50IiwiX2xheW91dCIsIm1vZGUiLCJfd2lkdGgiLCJfYm91bmRPbk1vZGVDaGFuZ2UiLCJfb25Nb2RlQ2hhbmdlIiwiX2dldFNpZGUiLCJTUExJVF9NT0RFIiwiQ09MTEFQU0VfTU9ERSIsIkNMT1NFRF9TVEFURSIsIk9QRU5fU1RBVEUiLCJDSEFOR0lOR19TVEFURSIsIldBVENIRURfQVRUUklCVVRFUyIsInNwbGl0dGVyU2lkZUVsZW1lbnQiLCJDb2xsYXBzZURldGVjdGlvbiIsImNoYW5nZVRhcmdldCIsIl90YXJnZXQiLCJfb3JpZW50YXRpb24iLCJhY3RpdmF0ZSIsIl91cGRhdGVNb2RlIiwiX21hdGNoIiwiX3F1ZXJ5UmVzdWx0IiwibWF0Y2hNZWRpYSIsImFkZExpc3RlbmVyIiwicmVtb3ZlTGlzdGVuZXIiLCJ3aWR0aFRvUHgiLCJweCIsIm9mZnNldFdpZHRoIiwiQ29sbGFwc2VNb2RlIiwiX2FjdGl2ZSIsIl9zdGF0ZSIsIl9sb2NrIiwiX2lzT3Blbk90aGVyU2lkZU1lbnUiLCJfaWdub3JlRHJhZyIsInNjcm9sbGluZyIsImFyZWEiLCJfc3dpcGVUYXJnZXRXaWR0aCIsIl9zdGFydERpc3RhbmNlIiwiX2Rpc3RhbmNlIiwidHJhbnNsYXRlIiwic2hvdWxkT3BlbiIsIl90aHJlc2hvbGQiLCJleGVjdXRlQWN0aW9uIiwibGF5b3V0IiwiRklOQUxfU1RBVEUiLCJfZW1pdEV2ZW50Iiwid2l0aG91dEFuaW1hdGlvbiIsIlNwbGl0dGVyU2lkZUVsZW1lbnQiLCJfY29sbGFwc2VNb2RlIiwiX2NvbGxhcHNlRGV0ZWN0aW9uIiwiX2JvdW5kSGFuZGxlR2VzdHVyZSIsImhhbmRsZUdlc3R1cmUiLCJfd2F0Y2hlZEF0dHJpYnV0ZXMiLCJfbW9kZSIsInRocmVzaG9sZCIsImxvY2F0aW9ucyIsIlN3aXRjaEVsZW1lbnQiLCJfY2hlY2tlZCIsIl9kaXNhYmxlZCIsIl9jaGVja2JveCIsIl9oYW5kbGUiLCJkaXNibGVkIiwiY2xpY2siLCJjaGVja2JveCIsIl9sb2NhdGlvbnMiLCJfc3RhcnRYIiwiX2dldFBvc2l0aW9uIiwicHJldmlvdXNWYWx1ZSIsIl9pc01hdGVyaWFsIiwiVGFiYmFyQW5pbWF0b3IiLCJlbnRlclBhZ2VJbmRleCIsImxlYXZlUGFnZUluZGV4IiwiVGFiYmFyTm9uZUFuaW1hdG9yIiwiZW50ZXJJbmRleCIsImxlYXZlSW5kZXgiLCJUYWJiYXJGYWRlQW5pbWF0b3IiLCJUYWJiYXJTbGlkZUFuaW1hdG9yIiwic2duIiwidGFiYmFyRWxlbWVudCIsIlRhYmJhckVsZW1lbnQiLCJfdGFiYmFySWQiLCJhY3RpdmVJbmRleCIsInRhYmJhciIsIl90YWJiYXJFbGVtZW50IiwiYmFyIiwiX3RvcCIsInRhYiIsIlRhYkVsZW1lbnQiLCJfbG9hZFBhZ2UiLCJfbG9hZFBhZ2VET01Bc3luYyIsImdldEFjdGl2ZVRhYkluZGV4IiwiX3N3aXRjaFBhZ2UiLCJfb2xkUGFnZUVsZW1lbnQiLCJvbGRQYWdlRWxlbWVudCIsInNlbGVjdGVkVGFiSW5kZXgiLCJwcmV2aW91c1RhYkluZGV4IiwicHJldmlvdXNUYWIiLCJfZ2V0QWN0aXZlVGFiRWxlbWVudCIsInNlbGVjdGVkVGFiIiwiX2dldFRhYkVsZW1lbnQiLCJwcmV2aW91c1BhZ2VFbGVtZW50IiwiX2dldEN1cnJlbnRQYWdlRWxlbWVudCIsInNldEluYWN0aXZlIiwic2V0QWN0aXZlIiwiX2xvYWRQYWdlRWxlbWVudCIsIl9nZXRUYWJiYXJFbGVtZW50IiwidGFicyIsImlzQWN0aXZlIiwiY3VycmVudFBhZ2VFbGVtZW50IiwiZGVmYXVsdElubmVyVGVtcGxhdGVTb3VyY2UiLCJoYXNJbnB1dCIsImhhc0J1dHRvbiIsIl90ZW1wbGF0ZUxvYWRlZCIsImhhc0NoaWxkcmVuIiwiTm9kZSIsIkVMRU1FTlRfTk9ERSIsIl9oYXNEZWZhdWx0VGVtcGxhdGUiLCJfdXBkYXRlRGVmYXVsdFRlbXBsYXRlIiwiYmFkZ2UiLCJnZXRMYWJlbEVsZW1lbnQiLCJnZXRCYWRnZUVsZW1lbnQiLCJnZXRJY29uRWxlbWVudCIsIl9maW5kVGFiYmFyRWxlbWVudCIsInNldEFjdGl2ZVRhYiIsIl9maW5kVGFiSW5kZXgiLCJyYWRpbyIsIl9sb2FkZWRQYWdlIiwiX2xvYWRpbmdQYWdlIiwiX2Vuc3VyZUVsZW1lbnRQb3NpdGlvbiIsImhhc0xvYWRlZCIsIlRvb2xiYXJCdXR0b25FbGVtZW50IiwiUmFuZ2VFbGVtZW50IiwiX2xlZnQiLCJfcmF0aW8iLCJfb25EcmFnc3RhcnQiLCJmYXN0Q2xpY2siLCJGYXN0Q2xpY2siLCJhdHRhY2giLCJhcHAiLCJleGl0QXBwIiwiVmlld3BvcnQiXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDN1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN0bEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDaFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ241Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ24wQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDNUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3RPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3RNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFDQTdpQixNQUFJOGlCLG1CQUFKLEdBQTBCQSxtQkFBMUI7QUFDQTlpQixNQUFJMG1CLG1CQUFKLEdBQTBCQSxtQkFBMUI7QUFDQTFtQixNQUFJMmpCLGVBQUosR0FBc0JBLGVBQXRCO0FBQ0EzakIsTUFBSW1uQixhQUFKLEdBQW9CQSxhQUFwQjtBQUNBbm5CLE1BQUlrcEIsVUFBSixHQUFpQkEsVUFBakI7QUFDQWxwQixNQUFJMG9CLGFBQUosR0FBb0JBLGFBQXBCO0FBQ0Exb0IsTUFBSTZyQixvQkFBSixHQUEyQkEsb0JBQTNCO0FBQ0E3ckIsTUFBSWtYLGNBQUosR0FBcUJBLGNBQXJCO0FBQ0FsWCxNQUFJOHJCLFlBQUosR0FBbUJBLFlBQW5COzs7QUFHQXgwQyxPQUFPMEcsZ0JBQVAsQ0FBd0IsTUFBeEIsRUFBZ0MsWUFBTTtRQUM5Qmt1QyxTQUFKLEdBQWdCQyxVQUFVQyxNQUFWLENBQWlCejNDLFNBQVM0YSxJQUExQixDQUFoQjtDQURKLEVBRUcsS0FGSDs7O0FBS0FqWSxPQUFPMEcsZ0JBQVAsQ0FBd0Isa0JBQXhCLEVBQTRDLFlBQU07UUFDNUNraUIsMkJBQUosQ0FBZ0M5bUIsTUFBaEM7UUFDSWtvQiwrQkFBSixHQUFzQ3RCLE1BQUlFLDJCQUFKLENBQWdDcUcsYUFBaEMsQ0FBOENqdkIsT0FBTzNDLFFBQVAsQ0FBZ0I0YSxJQUE5RCxFQUFvRSxZQUFNO2NBQ3BHODhCLEdBQVYsQ0FBY0MsT0FBZDtHQURvQyxDQUF0QztXQUdTLzhCLElBQVQsQ0FBY2liLGdCQUFkLEdBQWlDLElBQUl4SyxNQUFJN2tCLGVBQVIsQ0FBd0J4RyxTQUFTNGEsSUFBakMsQ0FBakM7Q0FMRixFQU1HLEtBTkg7OztBQVNBeVEsTUFBSWtCLEtBQUosQ0FBVSxZQUFXO1FBQ2ZrQyx5QkFBSjtDQURGOzs7QUFLQSxJQUFJbXBCLFFBQUosR0FBZXR2QyxLQUFmLEdBRUEiLCJmaWxlIjoib25zZW51aS5qcyIsInNvdXJjZXNDb250ZW50IjpbImlmICghd2luZG93LkN1c3RvbUV2ZW50KSB7XG4gIChmdW5jdGlvbigpIHtcbiAgICB2YXIgQ3VzdG9tRXZlbnQ7XG5cbiAgICBDdXN0b21FdmVudCA9IGZ1bmN0aW9uKGV2ZW50LCBwYXJhbXMpIHtcbiAgICAgIHZhciBldnQ7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge1xuICAgICAgICBidWJibGVzOiBmYWxzZSxcbiAgICAgICAgY2FuY2VsYWJsZTogZmFsc2UsXG4gICAgICAgIGRldGFpbDogdW5kZWZpbmVkXG4gICAgICB9O1xuICAgICAgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoXCJDdXN0b21FdmVudFwiKTtcbiAgICAgIGV2dC5pbml0Q3VzdG9tRXZlbnQoZXZlbnQsIHBhcmFtcy5idWJibGVzLCBwYXJhbXMuY2FuY2VsYWJsZSwgcGFyYW1zLmRldGFpbCk7XG4gICAgICByZXR1cm4gZXZ0O1xuICAgIH07XG5cbiAgICBDdXN0b21FdmVudC5wcm90b3R5cGUgPSB3aW5kb3cuRXZlbnQucHJvdG90eXBlO1xuXG4gICAgd2luZG93LkN1c3RvbUV2ZW50ID0gQ3VzdG9tRXZlbnQ7XG4gIH0pKCk7XG59XG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQgVGhlIFBvbHltZXIgUHJvamVjdCBBdXRob3JzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogVGhpcyBjb2RlIG1heSBvbmx5IGJlIHVzZWQgdW5kZXIgdGhlIEJTRCBzdHlsZSBsaWNlbnNlIGZvdW5kIGF0IGh0dHA6Ly9wb2x5bWVyLmdpdGh1Yi5pby9MSUNFTlNFLnR4dFxuICogVGhlIGNvbXBsZXRlIHNldCBvZiBhdXRob3JzIG1heSBiZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vQVVUSE9SUy50eHRcbiAqIFRoZSBjb21wbGV0ZSBzZXQgb2YgY29udHJpYnV0b3JzIG1heSBiZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vQ09OVFJJQlVUT1JTLnR4dFxuICogQ29kZSBkaXN0cmlidXRlZCBieSBHb29nbGUgYXMgcGFydCBvZiB0aGUgcG9seW1lciBwcm9qZWN0IGlzIGFsc29cbiAqIHN1YmplY3QgdG8gYW4gYWRkaXRpb25hbCBJUCByaWdodHMgZ3JhbnQgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL1BBVEVOVFMudHh0XG4gKi9cbi8vIEB2ZXJzaW9uIDAuNy4yMlxuaWYgKHR5cGVvZiBXZWFrTWFwID09PSBcInVuZGVmaW5lZFwiKSB7XG4gIChmdW5jdGlvbigpIHtcbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG4gICAgdmFyIGNvdW50ZXIgPSBEYXRlLm5vdygpICUgMWU5O1xuICAgIHZhciBXZWFrTWFwID0gZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLm5hbWUgPSBcIl9fc3RcIiArIChNYXRoLnJhbmRvbSgpICogMWU5ID4+PiAwKSArIChjb3VudGVyKysgKyBcIl9fXCIpO1xuICAgIH07XG4gICAgV2Vha01hcC5wcm90b3R5cGUgPSB7XG4gICAgICBzZXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0ga2V5W3RoaXMubmFtZV07XG4gICAgICAgIGlmIChlbnRyeSAmJiBlbnRyeVswXSA9PT0ga2V5KSBlbnRyeVsxXSA9IHZhbHVlOyBlbHNlIGRlZmluZVByb3BlcnR5KGtleSwgdGhpcy5uYW1lLCB7XG4gICAgICAgICAgdmFsdWU6IFsga2V5LCB2YWx1ZSBdLFxuICAgICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH0sXG4gICAgICBnZXQ6IGZ1bmN0aW9uKGtleSkge1xuICAgICAgICB2YXIgZW50cnk7XG4gICAgICAgIHJldHVybiAoZW50cnkgPSBrZXlbdGhpcy5uYW1lXSkgJiYgZW50cnlbMF0gPT09IGtleSA/IGVudHJ5WzFdIDogdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIFwiZGVsZXRlXCI6IGZ1bmN0aW9uKGtleSkge1xuICAgICAgICB2YXIgZW50cnkgPSBrZXlbdGhpcy5uYW1lXTtcbiAgICAgICAgaWYgKCFlbnRyeSB8fCBlbnRyeVswXSAhPT0ga2V5KSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGVudHJ5WzBdID0gZW50cnlbMV0gPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIGhhczogZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIHZhciBlbnRyeSA9IGtleVt0aGlzLm5hbWVdO1xuICAgICAgICBpZiAoIWVudHJ5KSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiBlbnRyeVswXSA9PT0ga2V5O1xuICAgICAgfVxuICAgIH07XG4gICAgd2luZG93LldlYWtNYXAgPSBXZWFrTWFwO1xuICB9KSgpO1xufVxuXG4oZnVuY3Rpb24oZ2xvYmFsKSB7XG4gIGlmIChnbG9iYWwuSnNNdXRhdGlvbk9ic2VydmVyKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciByZWdpc3RyYXRpb25zVGFibGUgPSBuZXcgV2Vha01hcCgpO1xuICB2YXIgc2V0SW1tZWRpYXRlO1xuICBpZiAoL1RyaWRlbnR8RWRnZS8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgIHNldEltbWVkaWF0ZSA9IHNldFRpbWVvdXQ7XG4gIH0gZWxzZSBpZiAod2luZG93LnNldEltbWVkaWF0ZSkge1xuICAgIHNldEltbWVkaWF0ZSA9IHdpbmRvdy5zZXRJbW1lZGlhdGU7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHNldEltbWVkaWF0ZVF1ZXVlID0gW107XG4gICAgdmFyIHNlbnRpbmVsID0gU3RyaW5nKE1hdGgucmFuZG9tKCkpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBmdW5jdGlvbihlKSB7XG4gICAgICBpZiAoZS5kYXRhID09PSBzZW50aW5lbCkge1xuICAgICAgICB2YXIgcXVldWUgPSBzZXRJbW1lZGlhdGVRdWV1ZTtcbiAgICAgICAgc2V0SW1tZWRpYXRlUXVldWUgPSBbXTtcbiAgICAgICAgcXVldWUuZm9yRWFjaChmdW5jdGlvbihmdW5jKSB7XG4gICAgICAgICAgZnVuYygpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgICBzZXRJbW1lZGlhdGVRdWV1ZS5wdXNoKGZ1bmMpO1xuICAgICAgd2luZG93LnBvc3RNZXNzYWdlKHNlbnRpbmVsLCBcIipcIik7XG4gICAgfTtcbiAgfVxuICB2YXIgaXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgdmFyIHNjaGVkdWxlZE9ic2VydmVycyA9IFtdO1xuICBmdW5jdGlvbiBzY2hlZHVsZUNhbGxiYWNrKG9ic2VydmVyKSB7XG4gICAgc2NoZWR1bGVkT2JzZXJ2ZXJzLnB1c2gob2JzZXJ2ZXIpO1xuICAgIGlmICghaXNTY2hlZHVsZWQpIHtcbiAgICAgIGlzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgIHNldEltbWVkaWF0ZShkaXNwYXRjaENhbGxiYWNrcyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHdyYXBJZk5lZWRlZChub2RlKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5TaGFkb3dET01Qb2x5ZmlsbCAmJiB3aW5kb3cuU2hhZG93RE9NUG9seWZpbGwud3JhcElmTmVlZGVkKG5vZGUpIHx8IG5vZGU7XG4gIH1cbiAgZnVuY3Rpb24gZGlzcGF0Y2hDYWxsYmFja3MoKSB7XG4gICAgaXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICB2YXIgb2JzZXJ2ZXJzID0gc2NoZWR1bGVkT2JzZXJ2ZXJzO1xuICAgIHNjaGVkdWxlZE9ic2VydmVycyA9IFtdO1xuICAgIG9ic2VydmVycy5zb3J0KGZ1bmN0aW9uKG8xLCBvMikge1xuICAgICAgcmV0dXJuIG8xLnVpZF8gLSBvMi51aWRfO1xuICAgIH0pO1xuICAgIHZhciBhbnlOb25FbXB0eSA9IGZhbHNlO1xuICAgIG9ic2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uKG9ic2VydmVyKSB7XG4gICAgICB2YXIgcXVldWUgPSBvYnNlcnZlci50YWtlUmVjb3JkcygpO1xuICAgICAgcmVtb3ZlVHJhbnNpZW50T2JzZXJ2ZXJzRm9yKG9ic2VydmVyKTtcbiAgICAgIGlmIChxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgb2JzZXJ2ZXIuY2FsbGJhY2tfKHF1ZXVlLCBvYnNlcnZlcik7XG4gICAgICAgIGFueU5vbkVtcHR5ID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoYW55Tm9uRW1wdHkpIGRpc3BhdGNoQ2FsbGJhY2tzKCk7XG4gIH1cbiAgZnVuY3Rpb24gcmVtb3ZlVHJhbnNpZW50T2JzZXJ2ZXJzRm9yKG9ic2VydmVyKSB7XG4gICAgb2JzZXJ2ZXIubm9kZXNfLmZvckVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgaWYgKCFyZWdpc3RyYXRpb25zKSByZXR1cm47XG4gICAgICByZWdpc3RyYXRpb25zLmZvckVhY2goZnVuY3Rpb24ocmVnaXN0cmF0aW9uKSB7XG4gICAgICAgIGlmIChyZWdpc3RyYXRpb24ub2JzZXJ2ZXIgPT09IG9ic2VydmVyKSByZWdpc3RyYXRpb24ucmVtb3ZlVHJhbnNpZW50T2JzZXJ2ZXJzKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQodGFyZ2V0LCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIG5vZGUgPSB0YXJnZXQ7IG5vZGU7IG5vZGUgPSBub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldChub2RlKTtcbiAgICAgIGlmIChyZWdpc3RyYXRpb25zKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcmVnaXN0cmF0aW9ucy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHZhciByZWdpc3RyYXRpb24gPSByZWdpc3RyYXRpb25zW2pdO1xuICAgICAgICAgIHZhciBvcHRpb25zID0gcmVnaXN0cmF0aW9uLm9wdGlvbnM7XG4gICAgICAgICAgaWYgKG5vZGUgIT09IHRhcmdldCAmJiAhb3B0aW9ucy5zdWJ0cmVlKSBjb250aW51ZTtcbiAgICAgICAgICB2YXIgcmVjb3JkID0gY2FsbGJhY2sob3B0aW9ucyk7XG4gICAgICAgICAgaWYgKHJlY29yZCkgcmVnaXN0cmF0aW9uLmVucXVldWUocmVjb3JkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgdWlkQ291bnRlciA9IDA7XG4gIGZ1bmN0aW9uIEpzTXV0YXRpb25PYnNlcnZlcihjYWxsYmFjaykge1xuICAgIHRoaXMuY2FsbGJhY2tfID0gY2FsbGJhY2s7XG4gICAgdGhpcy5ub2Rlc18gPSBbXTtcbiAgICB0aGlzLnJlY29yZHNfID0gW107XG4gICAgdGhpcy51aWRfID0gKyt1aWRDb3VudGVyO1xuICB9XG4gIEpzTXV0YXRpb25PYnNlcnZlci5wcm90b3R5cGUgPSB7XG4gICAgb2JzZXJ2ZTogZnVuY3Rpb24odGFyZ2V0LCBvcHRpb25zKSB7XG4gICAgICB0YXJnZXQgPSB3cmFwSWZOZWVkZWQodGFyZ2V0KTtcbiAgICAgIGlmICghb3B0aW9ucy5jaGlsZExpc3QgJiYgIW9wdGlvbnMuYXR0cmlidXRlcyAmJiAhb3B0aW9ucy5jaGFyYWN0ZXJEYXRhIHx8IG9wdGlvbnMuYXR0cmlidXRlT2xkVmFsdWUgJiYgIW9wdGlvbnMuYXR0cmlidXRlcyB8fCBvcHRpb25zLmF0dHJpYnV0ZUZpbHRlciAmJiBvcHRpb25zLmF0dHJpYnV0ZUZpbHRlci5sZW5ndGggJiYgIW9wdGlvbnMuYXR0cmlidXRlcyB8fCBvcHRpb25zLmNoYXJhY3RlckRhdGFPbGRWYWx1ZSAmJiAhb3B0aW9ucy5jaGFyYWN0ZXJEYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcigpO1xuICAgICAgfVxuICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KHRhcmdldCk7XG4gICAgICBpZiAoIXJlZ2lzdHJhdGlvbnMpIHJlZ2lzdHJhdGlvbnNUYWJsZS5zZXQodGFyZ2V0LCByZWdpc3RyYXRpb25zID0gW10pO1xuICAgICAgdmFyIHJlZ2lzdHJhdGlvbjtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVnaXN0cmF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocmVnaXN0cmF0aW9uc1tpXS5vYnNlcnZlciA9PT0gdGhpcykge1xuICAgICAgICAgIHJlZ2lzdHJhdGlvbiA9IHJlZ2lzdHJhdGlvbnNbaV07XG4gICAgICAgICAgcmVnaXN0cmF0aW9uLnJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICAgIHJlZ2lzdHJhdGlvbi5vcHRpb25zID0gb3B0aW9ucztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFyZWdpc3RyYXRpb24pIHtcbiAgICAgICAgcmVnaXN0cmF0aW9uID0gbmV3IFJlZ2lzdHJhdGlvbih0aGlzLCB0YXJnZXQsIG9wdGlvbnMpO1xuICAgICAgICByZWdpc3RyYXRpb25zLnB1c2gocmVnaXN0cmF0aW9uKTtcbiAgICAgICAgdGhpcy5ub2Rlc18ucHVzaCh0YXJnZXQpO1xuICAgICAgfVxuICAgICAgcmVnaXN0cmF0aW9uLmFkZExpc3RlbmVycygpO1xuICAgIH0sXG4gICAgZGlzY29ubmVjdDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLm5vZGVzXy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgcmVnaXN0cmF0aW9uID0gcmVnaXN0cmF0aW9uc1tpXTtcbiAgICAgICAgICBpZiAocmVnaXN0cmF0aW9uLm9ic2VydmVyID09PSB0aGlzKSB7XG4gICAgICAgICAgICByZWdpc3RyYXRpb24ucmVtb3ZlTGlzdGVuZXJzKCk7XG4gICAgICAgICAgICByZWdpc3RyYXRpb25zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgdGhpcyk7XG4gICAgICB0aGlzLnJlY29yZHNfID0gW107XG4gICAgfSxcbiAgICB0YWtlUmVjb3JkczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgY29weU9mUmVjb3JkcyA9IHRoaXMucmVjb3Jkc187XG4gICAgICB0aGlzLnJlY29yZHNfID0gW107XG4gICAgICByZXR1cm4gY29weU9mUmVjb3JkcztcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIE11dGF0aW9uUmVjb3JkKHR5cGUsIHRhcmdldCkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5hZGRlZE5vZGVzID0gW107XG4gICAgdGhpcy5yZW1vdmVkTm9kZXMgPSBbXTtcbiAgICB0aGlzLnByZXZpb3VzU2libGluZyA9IG51bGw7XG4gICAgdGhpcy5uZXh0U2libGluZyA9IG51bGw7XG4gICAgdGhpcy5hdHRyaWJ1dGVOYW1lID0gbnVsbDtcbiAgICB0aGlzLmF0dHJpYnV0ZU5hbWVzcGFjZSA9IG51bGw7XG4gICAgdGhpcy5vbGRWYWx1ZSA9IG51bGw7XG4gIH1cbiAgZnVuY3Rpb24gY29weU11dGF0aW9uUmVjb3JkKG9yaWdpbmFsKSB7XG4gICAgdmFyIHJlY29yZCA9IG5ldyBNdXRhdGlvblJlY29yZChvcmlnaW5hbC50eXBlLCBvcmlnaW5hbC50YXJnZXQpO1xuICAgIHJlY29yZC5hZGRlZE5vZGVzID0gb3JpZ2luYWwuYWRkZWROb2Rlcy5zbGljZSgpO1xuICAgIHJlY29yZC5yZW1vdmVkTm9kZXMgPSBvcmlnaW5hbC5yZW1vdmVkTm9kZXMuc2xpY2UoKTtcbiAgICByZWNvcmQucHJldmlvdXNTaWJsaW5nID0gb3JpZ2luYWwucHJldmlvdXNTaWJsaW5nO1xuICAgIHJlY29yZC5uZXh0U2libGluZyA9IG9yaWdpbmFsLm5leHRTaWJsaW5nO1xuICAgIHJlY29yZC5hdHRyaWJ1dGVOYW1lID0gb3JpZ2luYWwuYXR0cmlidXRlTmFtZTtcbiAgICByZWNvcmQuYXR0cmlidXRlTmFtZXNwYWNlID0gb3JpZ2luYWwuYXR0cmlidXRlTmFtZXNwYWNlO1xuICAgIHJlY29yZC5vbGRWYWx1ZSA9IG9yaWdpbmFsLm9sZFZhbHVlO1xuICAgIHJldHVybiByZWNvcmQ7XG4gIH1cbiAgdmFyIGN1cnJlbnRSZWNvcmQsIHJlY29yZFdpdGhPbGRWYWx1ZTtcbiAgZnVuY3Rpb24gZ2V0UmVjb3JkKHR5cGUsIHRhcmdldCkge1xuICAgIHJldHVybiBjdXJyZW50UmVjb3JkID0gbmV3IE11dGF0aW9uUmVjb3JkKHR5cGUsIHRhcmdldCk7XG4gIH1cbiAgZnVuY3Rpb24gZ2V0UmVjb3JkV2l0aE9sZFZhbHVlKG9sZFZhbHVlKSB7XG4gICAgaWYgKHJlY29yZFdpdGhPbGRWYWx1ZSkgcmV0dXJuIHJlY29yZFdpdGhPbGRWYWx1ZTtcbiAgICByZWNvcmRXaXRoT2xkVmFsdWUgPSBjb3B5TXV0YXRpb25SZWNvcmQoY3VycmVudFJlY29yZCk7XG4gICAgcmVjb3JkV2l0aE9sZFZhbHVlLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgcmV0dXJuIHJlY29yZFdpdGhPbGRWYWx1ZTtcbiAgfVxuICBmdW5jdGlvbiBjbGVhclJlY29yZHMoKSB7XG4gICAgY3VycmVudFJlY29yZCA9IHJlY29yZFdpdGhPbGRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgfVxuICBmdW5jdGlvbiByZWNvcmRSZXByZXNlbnRzQ3VycmVudE11dGF0aW9uKHJlY29yZCkge1xuICAgIHJldHVybiByZWNvcmQgPT09IHJlY29yZFdpdGhPbGRWYWx1ZSB8fCByZWNvcmQgPT09IGN1cnJlbnRSZWNvcmQ7XG4gIH1cbiAgZnVuY3Rpb24gc2VsZWN0UmVjb3JkKGxhc3RSZWNvcmQsIG5ld1JlY29yZCkge1xuICAgIGlmIChsYXN0UmVjb3JkID09PSBuZXdSZWNvcmQpIHJldHVybiBsYXN0UmVjb3JkO1xuICAgIGlmIChyZWNvcmRXaXRoT2xkVmFsdWUgJiYgcmVjb3JkUmVwcmVzZW50c0N1cnJlbnRNdXRhdGlvbihsYXN0UmVjb3JkKSkgcmV0dXJuIHJlY29yZFdpdGhPbGRWYWx1ZTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBSZWdpc3RyYXRpb24ob2JzZXJ2ZXIsIHRhcmdldCwgb3B0aW9ucykge1xuICAgIHRoaXMub2JzZXJ2ZXIgPSBvYnNlcnZlcjtcbiAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMudHJhbnNpZW50T2JzZXJ2ZWROb2RlcyA9IFtdO1xuICB9XG4gIFJlZ2lzdHJhdGlvbi5wcm90b3R5cGUgPSB7XG4gICAgZW5xdWV1ZTogZnVuY3Rpb24ocmVjb3JkKSB7XG4gICAgICB2YXIgcmVjb3JkcyA9IHRoaXMub2JzZXJ2ZXIucmVjb3Jkc187XG4gICAgICB2YXIgbGVuZ3RoID0gcmVjb3Jkcy5sZW5ndGg7XG4gICAgICBpZiAocmVjb3Jkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBsYXN0UmVjb3JkID0gcmVjb3Jkc1tsZW5ndGggLSAxXTtcbiAgICAgICAgdmFyIHJlY29yZFRvUmVwbGFjZUxhc3QgPSBzZWxlY3RSZWNvcmQobGFzdFJlY29yZCwgcmVjb3JkKTtcbiAgICAgICAgaWYgKHJlY29yZFRvUmVwbGFjZUxhc3QpIHtcbiAgICAgICAgICByZWNvcmRzW2xlbmd0aCAtIDFdID0gcmVjb3JkVG9SZXBsYWNlTGFzdDtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNjaGVkdWxlQ2FsbGJhY2sodGhpcy5vYnNlcnZlcik7XG4gICAgICB9XG4gICAgICByZWNvcmRzW2xlbmd0aF0gPSByZWNvcmQ7XG4gICAgfSxcbiAgICBhZGRMaXN0ZW5lcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5hZGRMaXN0ZW5lcnNfKHRoaXMudGFyZ2V0KTtcbiAgICB9LFxuICAgIGFkZExpc3RlbmVyc186IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlcykgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NQXR0ck1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hhcmFjdGVyRGF0YSkgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ2hhcmFjdGVyRGF0YU1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hpbGRMaXN0KSBub2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJET01Ob2RlSW5zZXJ0ZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgICBpZiAob3B0aW9ucy5jaGlsZExpc3QgfHwgb3B0aW9ucy5zdWJ0cmVlKSBub2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJET01Ob2RlUmVtb3ZlZFwiLCB0aGlzLCB0cnVlKTtcbiAgICB9LFxuICAgIHJlbW92ZUxpc3RlbmVyczogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyc18odGhpcy50YXJnZXQpO1xuICAgIH0sXG4gICAgcmVtb3ZlTGlzdGVuZXJzXzogZnVuY3Rpb24obm9kZSkge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICBpZiAob3B0aW9ucy5hdHRyaWJ1dGVzKSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01BdHRyTW9kaWZpZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgICBpZiAob3B0aW9ucy5jaGFyYWN0ZXJEYXRhKSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01DaGFyYWN0ZXJEYXRhTW9kaWZpZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgICBpZiAob3B0aW9ucy5jaGlsZExpc3QpIG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIkRPTU5vZGVJbnNlcnRlZFwiLCB0aGlzLCB0cnVlKTtcbiAgICAgIGlmIChvcHRpb25zLmNoaWxkTGlzdCB8fCBvcHRpb25zLnN1YnRyZWUpIG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIkRPTU5vZGVSZW1vdmVkXCIsIHRoaXMsIHRydWUpO1xuICAgIH0sXG4gICAgYWRkVHJhbnNpZW50T2JzZXJ2ZXI6IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGlmIChub2RlID09PSB0aGlzLnRhcmdldCkgcmV0dXJuO1xuICAgICAgdGhpcy5hZGRMaXN0ZW5lcnNfKG5vZGUpO1xuICAgICAgdGhpcy50cmFuc2llbnRPYnNlcnZlZE5vZGVzLnB1c2gobm9kZSk7XG4gICAgICB2YXIgcmVnaXN0cmF0aW9ucyA9IHJlZ2lzdHJhdGlvbnNUYWJsZS5nZXQobm9kZSk7XG4gICAgICBpZiAoIXJlZ2lzdHJhdGlvbnMpIHJlZ2lzdHJhdGlvbnNUYWJsZS5zZXQobm9kZSwgcmVnaXN0cmF0aW9ucyA9IFtdKTtcbiAgICAgIHJlZ2lzdHJhdGlvbnMucHVzaCh0aGlzKTtcbiAgICB9LFxuICAgIHJlbW92ZVRyYW5zaWVudE9ic2VydmVyczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdHJhbnNpZW50T2JzZXJ2ZWROb2RlcyA9IHRoaXMudHJhbnNpZW50T2JzZXJ2ZWROb2RlcztcbiAgICAgIHRoaXMudHJhbnNpZW50T2JzZXJ2ZWROb2RlcyA9IFtdO1xuICAgICAgdHJhbnNpZW50T2JzZXJ2ZWROb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnNfKG5vZGUpO1xuICAgICAgICB2YXIgcmVnaXN0cmF0aW9ucyA9IHJlZ2lzdHJhdGlvbnNUYWJsZS5nZXQobm9kZSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVnaXN0cmF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmIChyZWdpc3RyYXRpb25zW2ldID09PSB0aGlzKSB7XG4gICAgICAgICAgICByZWdpc3RyYXRpb25zLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgdGhpcyk7XG4gICAgfSxcbiAgICBoYW5kbGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgIHN3aXRjaCAoZS50eXBlKSB7XG4gICAgICAgY2FzZSBcIkRPTUF0dHJNb2RpZmllZFwiOlxuICAgICAgICB2YXIgbmFtZSA9IGUuYXR0ck5hbWU7XG4gICAgICAgIHZhciBuYW1lc3BhY2UgPSBlLnJlbGF0ZWROb2RlLm5hbWVzcGFjZVVSSTtcbiAgICAgICAgdmFyIHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICB2YXIgcmVjb3JkID0gbmV3IGdldFJlY29yZChcImF0dHJpYnV0ZXNcIiwgdGFyZ2V0KTtcbiAgICAgICAgcmVjb3JkLmF0dHJpYnV0ZU5hbWUgPSBuYW1lO1xuICAgICAgICByZWNvcmQuYXR0cmlidXRlTmFtZXNwYWNlID0gbmFtZXNwYWNlO1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSBlLmF0dHJDaGFuZ2UgPT09IE11dGF0aW9uRXZlbnQuQURESVRJT04gPyBudWxsIDogZS5wcmV2VmFsdWU7XG4gICAgICAgIGZvckVhY2hBbmNlc3RvckFuZE9ic2VydmVyRW5xdWV1ZVJlY29yZCh0YXJnZXQsIGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgICBpZiAoIW9wdGlvbnMuYXR0cmlidXRlcykgcmV0dXJuO1xuICAgICAgICAgIGlmIChvcHRpb25zLmF0dHJpYnV0ZUZpbHRlciAmJiBvcHRpb25zLmF0dHJpYnV0ZUZpbHRlci5sZW5ndGggJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIuaW5kZXhPZihuYW1lKSA9PT0gLTEgJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIuaW5kZXhPZihuYW1lc3BhY2UpID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAob3B0aW9ucy5hdHRyaWJ1dGVPbGRWYWx1ZSkgcmV0dXJuIGdldFJlY29yZFdpdGhPbGRWYWx1ZShvbGRWYWx1ZSk7XG4gICAgICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICAgY2FzZSBcIkRPTUNoYXJhY3RlckRhdGFNb2RpZmllZFwiOlxuICAgICAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgIHZhciByZWNvcmQgPSBnZXRSZWNvcmQoXCJjaGFyYWN0ZXJEYXRhXCIsIHRhcmdldCk7XG4gICAgICAgIHZhciBvbGRWYWx1ZSA9IGUucHJldlZhbHVlO1xuICAgICAgICBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQodGFyZ2V0LCBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLmNoYXJhY3RlckRhdGEpIHJldHVybjtcbiAgICAgICAgICBpZiAob3B0aW9ucy5jaGFyYWN0ZXJEYXRhT2xkVmFsdWUpIHJldHVybiBnZXRSZWNvcmRXaXRoT2xkVmFsdWUob2xkVmFsdWUpO1xuICAgICAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJET01Ob2RlUmVtb3ZlZFwiOlxuICAgICAgICB0aGlzLmFkZFRyYW5zaWVudE9ic2VydmVyKGUudGFyZ2V0KTtcblxuICAgICAgIGNhc2UgXCJET01Ob2RlSW5zZXJ0ZWRcIjpcbiAgICAgICAgdmFyIGNoYW5nZWROb2RlID0gZS50YXJnZXQ7XG4gICAgICAgIHZhciBhZGRlZE5vZGVzLCByZW1vdmVkTm9kZXM7XG4gICAgICAgIGlmIChlLnR5cGUgPT09IFwiRE9NTm9kZUluc2VydGVkXCIpIHtcbiAgICAgICAgICBhZGRlZE5vZGVzID0gWyBjaGFuZ2VkTm9kZSBdO1xuICAgICAgICAgIHJlbW92ZWROb2RlcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFkZGVkTm9kZXMgPSBbXTtcbiAgICAgICAgICByZW1vdmVkTm9kZXMgPSBbIGNoYW5nZWROb2RlIF07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXZpb3VzU2libGluZyA9IGNoYW5nZWROb2RlLnByZXZpb3VzU2libGluZztcbiAgICAgICAgdmFyIG5leHRTaWJsaW5nID0gY2hhbmdlZE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgIHZhciByZWNvcmQgPSBnZXRSZWNvcmQoXCJjaGlsZExpc3RcIiwgZS50YXJnZXQucGFyZW50Tm9kZSk7XG4gICAgICAgIHJlY29yZC5hZGRlZE5vZGVzID0gYWRkZWROb2RlcztcbiAgICAgICAgcmVjb3JkLnJlbW92ZWROb2RlcyA9IHJlbW92ZWROb2RlcztcbiAgICAgICAgcmVjb3JkLnByZXZpb3VzU2libGluZyA9IHByZXZpb3VzU2libGluZztcbiAgICAgICAgcmVjb3JkLm5leHRTaWJsaW5nID0gbmV4dFNpYmxpbmc7XG4gICAgICAgIGZvckVhY2hBbmNlc3RvckFuZE9ic2VydmVyRW5xdWV1ZVJlY29yZChlLnJlbGF0ZWROb2RlLCBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLmNoaWxkTGlzdCkgcmV0dXJuO1xuICAgICAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgY2xlYXJSZWNvcmRzKCk7XG4gICAgfVxuICB9O1xuICBnbG9iYWwuSnNNdXRhdGlvbk9ic2VydmVyID0gSnNNdXRhdGlvbk9ic2VydmVyO1xuICBpZiAoIWdsb2JhbC5NdXRhdGlvbk9ic2VydmVyKSB7XG4gICAgZ2xvYmFsLk11dGF0aW9uT2JzZXJ2ZXIgPSBKc011dGF0aW9uT2JzZXJ2ZXI7XG4gICAgSnNNdXRhdGlvbk9ic2VydmVyLl9pc1BvbHlmaWxsZWQgPSB0cnVlO1xuICB9XG59KShzZWxmKTsiLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5cbi8qKlxuICogTWluaW1hbCBhbmltYXRpb24gbGlicmFyeSBmb3IgbWFuYWdpbmcgY3NzIHRyYW5zaXRpb24gb24gbW9iaWxlIGJyb3dzZXJzLlxuICovXG53aW5kb3cuYW5pbWl0ID0gKGZ1bmN0aW9uKCl7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgVElNRU9VVF9SQVRJTyA9IDEuNDtcblxuICB2YXIgdXRpbCA9IHtcbiAgfTtcblxuICAvLyBjYXBpdGFsaXplIHN0cmluZ1xuICB1dGlsLmNhcGl0YWxpemUgPSBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xuICB9O1xuXG4gIC8qKlxuICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXNcbiAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLnByb3BlcnR5XG4gICogQHBhcmFtIHtGbG9hdH0gcGFyYW1zLmR1cmF0aW9uXG4gICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy50aW1pbmdcbiAgKi9cbiAgdXRpbC5idWlsZFRyYW5zaXRpb25WYWx1ZSA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICAgIHBhcmFtcy5wcm9wZXJ0eSA9IHBhcmFtcy5wcm9wZXJ0eSB8fCAnYWxsJztcbiAgICBwYXJhbXMuZHVyYXRpb24gPSBwYXJhbXMuZHVyYXRpb24gfHwgMC40O1xuICAgIHBhcmFtcy50aW1pbmcgPSBwYXJhbXMudGltaW5nIHx8ICdsaW5lYXInO1xuXG4gICAgdmFyIHByb3BzID0gcGFyYW1zLnByb3BlcnR5LnNwbGl0KC8gKy8pO1xuXG4gICAgcmV0dXJuIHByb3BzLm1hcChmdW5jdGlvbihwcm9wKSB7XG4gICAgICByZXR1cm4gcHJvcCArICcgJyArIHBhcmFtcy5kdXJhdGlvbiArICdzICcgKyBwYXJhbXMudGltaW5nO1xuICAgIH0pLmpvaW4oJywgJyk7XG4gIH07XG5cbiAgLyoqXG4gICogQWRkIGFuIGV2ZW50IGhhbmRsZXIgb24gXCJ0cmFuc2l0aW9uZW5kXCIgZXZlbnQuXG4gICovXG4gIHV0aWwub25jZU9uVHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG5cbiAgICB2YXIgZm4gPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgaWYgKGVsZW1lbnQgPT0gZXZlbnQudGFyZ2V0KSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcblxuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgICB1dGlsLl90cmFuc2l0aW9uRW5kRXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZXZlbnROYW1lKSB7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGZuLCBmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdXRpbC5fdHJhbnNpdGlvbkVuZEV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZm4sIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZW1vdmVMaXN0ZW5lcnM7XG4gIH07XG5cbiAgdXRpbC5fdHJhbnNpdGlvbkVuZEV2ZW50cyA9IChmdW5jdGlvbigpIHtcblxuICAgIGlmICgnb250cmFuc2l0aW9uZW5kJyBpbiB3aW5kb3cpIHtcbiAgICAgIHJldHVybiBbJ3RyYW5zaXRpb25lbmQnXTtcbiAgICB9XG5cbiAgICBpZiAoJ29ud2Via2l0dHJhbnNpdGlvbmVuZCcgaW4gd2luZG93KSB7XG4gICAgICByZXR1cm4gWyd3ZWJraXRUcmFuc2l0aW9uRW5kJ107XG4gICAgfVxuXG4gICAgaWYgKHV0aWwudmVuZG9yUHJlZml4ID09PSAnd2Via2l0JyB8fCB1dGlsLnZlbmRvclByZWZpeCA9PT0gJ28nIHx8IHV0aWwudmVuZG9yUHJlZml4ID09PSAnbW96JyB8fCB1dGlsLnZlbmRvclByZWZpeCA9PT0gJ21zJykge1xuICAgICAgcmV0dXJuIFt1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uRW5kJywgJ3RyYW5zaXRpb25lbmQnXTtcbiAgICB9XG5cbiAgICByZXR1cm4gW107XG4gIH0pKCk7XG5cbiAgdXRpbC5fY3NzUHJvcGVydHlEaWN0ID0gKGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdHlsZXMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICcnKTtcbiAgICB2YXIgZGljdCA9IHt9O1xuICAgIHZhciBhID0gJ0EnLmNoYXJDb2RlQXQoMCk7XG4gICAgdmFyIHogPSAneicuY2hhckNvZGVBdCgwKTtcblxuICAgIHZhciB1cHBlciA9IGZ1bmN0aW9uKHMpIHtcbiAgICAgIHJldHVybiBzLnN1YnN0cigxKS50b1VwcGVyQ2FzZSgpO1xuICAgIH07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0eWxlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICB2YXIga2V5ID0gc3R5bGVzW2ldXG4gICAgICAgIC5yZXBsYWNlKC9eW1xcLV0rLywgJycpXG4gICAgICAgIC5yZXBsYWNlKC9bXFwtXVthLXpdL2csIHVwcGVyKVxuICAgICAgICAucmVwbGFjZSgvXm1vei8sICdNb3onKTtcblxuICAgICAgaWYgKGEgPD0ga2V5LmNoYXJDb2RlQXQoMCkgJiYgeiA+PSBrZXkuY2hhckNvZGVBdCgwKSkge1xuICAgICAgICBpZiAoa2V5ICE9PSAnY3NzVGV4dCcgJiYga2V5ICE9PSAncGFyZW50VGV4dCcpIHtcbiAgICAgICAgICBkaWN0W2tleV0gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGRpY3Q7XG4gIH0pKCk7XG5cbiAgdXRpbC5oYXNDc3NQcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICByZXR1cm4gbmFtZSBpbiB1dGlsLl9jc3NQcm9wZXJ0eURpY3Q7XG4gIH07XG5cbiAgLyoqXG4gICAqIFZlbmRvciBwcmVmaXggZm9yIGNzcyBwcm9wZXJ0eS5cbiAgICovXG4gIHV0aWwudmVuZG9yUHJlZml4ID0gKGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdHlsZXMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICcnKSxcbiAgICBwcmUgPSAoQXJyYXkucHJvdG90eXBlLnNsaWNlXG4gICAgICAuY2FsbChzdHlsZXMpXG4gICAgICAuam9pbignJylcbiAgICAgIC5tYXRjaCgvLShtb3p8d2Via2l0fG1zKS0vKSB8fCAoc3R5bGVzLk9MaW5rID09PSAnJyAmJiBbJycsICdvJ10pXG4gICAgKVsxXTtcbiAgICByZXR1cm4gcHJlO1xuICB9KSgpO1xuXG4gIHV0aWwuZm9yY2VMYXlvdXRBdE9uY2UgPSBmdW5jdGlvbihlbGVtZW50cywgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhdGNoSW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIC8vIGZvcmNlIGxheW91dFxuICAgICAgICBlbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgIH0pO1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9KTtcbiAgfTtcblxuICB1dGlsLmJhdGNoSW1tZWRpYXRlID0gKGZ1bmN0aW9uKCkge1xuICAgIHZhciBjYWxsYmFja3MgPSBbXTtcblxuICAgIHJldHVybiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBjb25jcmVhdGVDYWxsYmFja3MgPSBjYWxsYmFja3Muc2xpY2UoMCk7XG4gICAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgICAgY29uY3JlYXRlQ2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gICAgfTtcbiAgfSkoKTtcblxuICB1dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUgPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNhbGxiYWNrcyA9IFtdO1xuXG4gICAgdmFyIHJhZiA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93Lm1velJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy5vUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDEwMDAgLyA2MCk7XG4gICAgfTtcblxuICAgIHJldHVybiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmFmKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBjb25jcmVhdGVDYWxsYmFja3MgPSBjYWxsYmFja3Muc2xpY2UoMCk7XG4gICAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgICAgY29uY3JlYXRlQ2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gICAgfTtcbiAgfSkoKTtcblxuICB1dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWUgPSAoZnVuY3Rpb24oKSB7XG4gICAgaWYgKHV0aWwuaGFzQ3NzUHJvcGVydHkoJ3RyYW5zaXRpb25EdXJhdGlvbicpKSB7XG4gICAgICByZXR1cm4gJ3RyYW5zaXRpb24nO1xuICAgIH1cblxuICAgIGlmICh1dGlsLmhhc0Nzc1Byb3BlcnR5KHV0aWwudmVuZG9yUHJlZml4ICsgJ1RyYW5zaXRpb25EdXJhdGlvbicpKSB7XG4gICAgICByZXR1cm4gdXRpbC52ZW5kb3JQcmVmaXggKyAnVHJhbnNpdGlvbic7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0YXRlJyk7XG4gIH0pKCk7XG5cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKi9cbiAgdmFyIEFuaW1pdCA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQW5pbWl0KSkge1xuICAgICAgcmV0dXJuIG5ldyBBbmltaXQoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgdGhpcy5lbGVtZW50cyA9IFtlbGVtZW50XTtcbiAgICB9IGVsc2UgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlbGVtZW50KSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgdGhpcy5lbGVtZW50cyA9IGVsZW1lbnQ7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGaXJzdCBhcmd1bWVudCBtdXN0IGJlIGFuIGFycmF5IG9yIGFuIGluc3RhbmNlIG9mIEhUTUxFbGVtZW50LicpO1xuICAgIH1cblxuICAgIHRoaXMudHJhbnNpdGlvblF1ZXVlID0gW107XG4gICAgdGhpcy5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0ID0gW107XG4gIH07XG5cbiAgQW5pbWl0LnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIEBwcm9wZXJ0eSB7QXJyYXl9XG4gICAgICovXG4gICAgdHJhbnNpdGlvblF1ZXVlOiB1bmRlZmluZWQsXG5cbiAgICAvKipcbiAgICAgKiBAcHJvcGVydHkge0FycmF5fVxuICAgICAqL1xuICAgIGVsZW1lbnRzOiB1bmRlZmluZWQsXG5cbiAgICAvKipcbiAgICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2Ugd2l0aCBwYXNzZWQgYW5pbWF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICovXG4gICAgcGxheTogZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnN0YXJ0QW5pbWF0aW9uKCk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBRdWV1ZSB0cmFuc2l0aW9uIGFuaW1hdGlvbnMgb3Igb3RoZXIgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBlLmcuIGFuaW1pdChlbHQpLnF1ZXVlKHtjb2xvcjogJ3JlZCd9KVxuICAgICAqIGUuZy4gYW5pbWl0KGVsdCkucXVldWUoe2NvbG9yOiAncmVkJ30sIHtkdXJhdGlvbjogMC40fSlcbiAgICAgKiBlLmcuIGFuaW1pdChlbHQpLnF1ZXVlKHtjc3M6IHtjb2xvcjogJ3JlZCd9LCBkdXJhdGlvbjogMC4yfSlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fEFuaW1pdC5UcmFuc2l0aW9ufEZ1bmN0aW9ufSB0cmFuc2l0aW9uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgICAqL1xuICAgIHF1ZXVlOiBmdW5jdGlvbih0cmFuc2l0aW9uLCBvcHRpb25zKSB7XG4gICAgICB2YXIgcXVldWUgPSB0aGlzLnRyYW5zaXRpb25RdWV1ZTtcblxuICAgICAgaWYgKHRyYW5zaXRpb24gJiYgb3B0aW9ucykge1xuICAgICAgICBvcHRpb25zLmNzcyA9IHRyYW5zaXRpb247XG4gICAgICAgIHRyYW5zaXRpb24gPSBuZXcgQW5pbWl0LlRyYW5zaXRpb24ob3B0aW9ucyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghKHRyYW5zaXRpb24gaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCB0cmFuc2l0aW9uIGluc3RhbmNlb2YgQW5pbWl0LlRyYW5zaXRpb24pKSB7XG4gICAgICAgIGlmICh0cmFuc2l0aW9uLmNzcykge1xuICAgICAgICAgIHRyYW5zaXRpb24gPSBuZXcgQW5pbWl0LlRyYW5zaXRpb24odHJhbnNpdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJhbnNpdGlvbiA9IG5ldyBBbmltaXQuVHJhbnNpdGlvbih7XG4gICAgICAgICAgICBjc3M6IHRyYW5zaXRpb25cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodHJhbnNpdGlvbiBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgIHF1ZXVlLnB1c2godHJhbnNpdGlvbik7XG4gICAgICB9IGVsc2UgaWYgKHRyYW5zaXRpb24gaW5zdGFuY2VvZiBBbmltaXQuVHJhbnNpdGlvbikge1xuICAgICAgICBxdWV1ZS5wdXNoKHRyYW5zaXRpb24uYnVpbGQoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYXJndW1lbnRzJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBRdWV1ZSB0cmFuc2l0aW9uIGFuaW1hdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Zsb2F0fSBzZWNvbmRzXG4gICAgICovXG4gICAgd2FpdDogZnVuY3Rpb24oc2Vjb25kcykge1xuICAgICAgaWYgKHNlY29uZHMgPiAwKSB7XG4gICAgICAgIHRoaXMudHJhbnNpdGlvblF1ZXVlLnB1c2goZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIHNldFRpbWVvdXQoZG9uZSwgMTAwMCAqIHNlY29uZHMpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHNhdmVTdHlsZTogZnVuY3Rpb24oKSB7XG5cbiAgICAgIHRoaXMudHJhbnNpdGlvblF1ZXVlLnB1c2goZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICB0aGlzLmVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICB2YXIgY3NzID0gdGhpcy5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0W2luZGV4XSA9IHt9O1xuXG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50LnN0eWxlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjc3NbZWxlbWVudC5zdHlsZVtpXV0gPSBlbGVtZW50LnN0eWxlW2VsZW1lbnQuc3R5bGVbaV1dO1xuICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlc3RvcmUgZWxlbWVudCdzIHN0eWxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgICAqIEBwYXJhbSB7RmxvYXR9IFtvcHRpb25zLmR1cmF0aW9uXVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aW1pbmddXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnRyYW5zaXRpb25dXG4gICAgICovXG4gICAgcmVzdG9yZVN0eWxlOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgICAgaWYgKG9wdGlvbnMudHJhbnNpdGlvbiAmJiAhb3B0aW9ucy5kdXJhdGlvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1wib3B0aW9ucy5kdXJhdGlvblwiIGlzIHJlcXVpcmVkIHdoZW4gXCJvcHRpb25zLnRyYW5zaXRpb25cIiBpcyBlbmFibGVkLicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgdHJhbnNpdGlvbk5hbWUgPSB1dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWU7XG5cbiAgICAgIGlmIChvcHRpb25zLnRyYW5zaXRpb24gfHwgKG9wdGlvbnMuZHVyYXRpb24gJiYgb3B0aW9ucy5kdXJhdGlvbiA+IDApKSB7XG4gICAgICAgIHZhciB0cmFuc2l0aW9uVmFsdWUgPSBvcHRpb25zLnRyYW5zaXRpb24gfHwgKCdhbGwgJyArIG9wdGlvbnMuZHVyYXRpb24gKyAncyAnICsgKG9wdGlvbnMudGltaW5nIHx8ICdsaW5lYXInKSk7XG5cbiAgICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgdmFyIGVsZW1lbnRzID0gdGhpcy5lbGVtZW50cztcbiAgICAgICAgICB2YXIgdGltZW91dElkO1xuXG4gICAgICAgICAgdmFyIGNsZWFyVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdHJhbnNpdGlvbk5hbWVdID0gJyc7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gYWRkIFwidHJhbnNpdGlvbmVuZFwiIGV2ZW50IGhhbmRsZXJcbiAgICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICAgICAgY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBmb3IgZmFpbCBzYWZlLlxuICAgICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIGNsZWFyVHJhbnNpdGlvbigpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH0sIG9wdGlvbnMuZHVyYXRpb24gKiAxMDAwICogVElNRU9VVF9SQVRJTyk7XG5cbiAgICAgICAgICAvLyB0cmFuc2l0aW9uIGFuZCBzdHlsZSBzZXR0aW5nc1xuICAgICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcblxuICAgICAgICAgICAgdmFyIGNzcyA9IHNlbGYubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF07XG5cbiAgICAgICAgICAgIGlmICghY3NzKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncmVzdG9yZVN0eWxlKCk6IFRoZSBzdHlsZSBpcyBub3Qgc2F2ZWQuIEludm9rZSBzYXZlU3R5bGUoKSBiZWZvcmUuJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlbGYubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF0gPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgIHZhciBuYW1lO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGVsZW1lbnQuc3R5bGUubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgbmFtZSA9IGVsZW1lbnQuc3R5bGVbaV07XG4gICAgICAgICAgICAgIGlmIChjc3NbbmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNzc1tuYW1lXSA9ICcnO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdHJhbnNpdGlvbk5hbWVdID0gdHJhbnNpdGlvblZhbHVlO1xuXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhjc3MpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICAgIGlmIChrZXkgIT09IHRyYW5zaXRpb25OYW1lKSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZVtrZXldID0gY3NzW2tleV07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlW3RyYW5zaXRpb25OYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnRyYW5zaXRpb25RdWV1ZS5wdXNoKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICByZXNldCgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgICAgLy8gQ2xlYXIgdHJhbnNpdGlvbiBhbmltYXRpb24gc2V0dGluZ3MuXG4gICAgICAgIHNlbGYuZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50LCBpbmRleCkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdHJhbnNpdGlvbk5hbWVdID0gJ25vbmUnO1xuXG4gICAgICAgICAgdmFyIGNzcyA9IHNlbGYubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF07XG5cbiAgICAgICAgICBpZiAoIWNzcykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZXN0b3JlU3R5bGUoKTogVGhlIHN0eWxlIGlzIG5vdCBzYXZlZC4gSW52b2tlIHNhdmVTdHlsZSgpIGJlZm9yZS4nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzZWxmLmxhc3RTdHlsZUF0dHJpYnV0ZURpY3RbaW5kZXhdID0gdW5kZWZpbmVkO1xuXG4gICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG5hbWUgPSAnJzsgaSA8IGVsZW1lbnQuc3R5bGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5hbWUgPSBlbGVtZW50LnN0eWxlW2ldO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjc3NbZWxlbWVudC5zdHlsZVtpXV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGNzc1tlbGVtZW50LnN0eWxlW2ldXSA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IGNzc1trZXldO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2UuXG4gICAgICovXG4gICAgc3RhcnRBbmltYXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kZXF1ZXVlVHJhbnNpdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvbiA9IHRoaXMudHJhbnNpdGlvblF1ZXVlLnNoaWZ0KCk7XG4gICAgICBpZiAodGhpcy5fY3VycmVudFRyYW5zaXRpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDdXJyZW50IHRyYW5zaXRpb24gZXhpc3RzLicpO1xuICAgICAgfVxuICAgICAgdGhpcy5fY3VycmVudFRyYW5zaXRpb24gPSB0cmFuc2l0aW9uO1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuXG4gICAgICB2YXIgZG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICAgICAgc2VsZi5fY3VycmVudFRyYW5zaXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgc2VsZi5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RhdGU6IFRoaXMgY2FsbGJhY2sgaXMgY2FsbGVkIHR3aWNlLicpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAodHJhbnNpdGlvbikge1xuICAgICAgICB0cmFuc2l0aW9uLmNhbGwodGhpcywgZG9uZSk7XG4gICAgICB9XG4gICAgfVxuXG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7QW5pbWl0fSBhcmd1bWVudHNcbiAgICovXG4gIEFuaW1pdC5ydW5BbGwgPSBmdW5jdGlvbigvKiBhcmd1bWVudHMuLi4gKi8pIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgYXJndW1lbnRzW2ldLnBsYXkoKTtcbiAgICB9XG4gIH07XG5cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtGbG9hdH0gW29wdGlvbnMuZHVyYXRpb25dXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wcm9wZXJ0eV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnRpbWluZ11cbiAgICovXG4gIEFuaW1pdC5UcmFuc2l0aW9uID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgdGhpcy5vcHRpb25zLmR1cmF0aW9uID0gdGhpcy5vcHRpb25zLmR1cmF0aW9uIHx8IDA7XG4gICAgdGhpcy5vcHRpb25zLnRpbWluZyA9IHRoaXMub3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcic7XG4gICAgdGhpcy5vcHRpb25zLmNzcyA9IHRoaXMub3B0aW9ucy5jc3MgfHwge307XG4gICAgdGhpcy5vcHRpb25zLnByb3BlcnR5ID0gdGhpcy5vcHRpb25zLnByb3BlcnR5IHx8ICdhbGwnO1xuICB9O1xuXG4gIEFuaW1pdC5UcmFuc2l0aW9uLnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAgICAgKi9cbiAgICBidWlsZDogZnVuY3Rpb24oKSB7XG5cbiAgICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLm9wdGlvbnMuY3NzKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvcHRpb25zLmNzcyBpcyByZXF1aXJlZC4nKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNzcyA9IGNyZWF0ZUFjdHVhbENzc1Byb3BzKHRoaXMub3B0aW9ucy5jc3MpO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmR1cmF0aW9uID4gMCkge1xuICAgICAgICB2YXIgdHJhbnNpdGlvblZhbHVlID0gdXRpbC5idWlsZFRyYW5zaXRpb25WYWx1ZSh0aGlzLm9wdGlvbnMpO1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgdmFyIGVsZW1lbnRzID0gdGhpcy5lbGVtZW50cztcbiAgICAgICAgICB2YXIgdGltZW91dCA9IHNlbGYub3B0aW9ucy5kdXJhdGlvbiAqIDEwMDAgKiBUSU1FT1VUX1JBVElPO1xuICAgICAgICAgIHZhciB0aW1lb3V0SWQ7XG5cbiAgICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfSwgdGltZW91dCk7XG5cbiAgICAgICAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdXRpbC50cmFuc2l0aW9uUHJvcGVydHlOYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcblxuICAgICAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZVtuYW1lXSA9IGNzc1tuYW1lXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZHVyYXRpb24gPD0gMCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgICB2YXIgZWxlbWVudHMgPSB0aGlzLmVsZW1lbnRzO1xuXG4gICAgICAgICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlW3V0aWwudHJhbnNpdGlvblByb3BlcnR5TmFtZV0gPSAnJztcblxuICAgICAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZVtuYW1lXSA9IGNzc1tuYW1lXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGVsZW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHV0aWwuZm9yY2VMYXlvdXRBdE9uY2UoZWxlbWVudHMsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICB1dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUoY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHV0aWwuYmF0Y2hBbmltYXRpb25GcmFtZShjYWxsYmFjayk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjcmVhdGVBY3R1YWxDc3NQcm9wcyhjc3MpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gY3NzW25hbWVdO1xuXG4gICAgICAgICAgaWYgKHV0aWwuaGFzQ3NzUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IHZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBwcmVmaXhlZCA9IHV0aWwudmVuZG9yUHJlZml4ICsgdXRpbC5jYXBpdGFsaXplKG5hbWUpO1xuICAgICAgICAgIGlmICh1dGlsLmhhc0Nzc1Byb3BlcnR5KHByZWZpeGVkKSkge1xuICAgICAgICAgICAgcmVzdWx0W3ByZWZpeGVkXSA9IHZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRbcHJlZml4ZWRdID0gdmFsdWU7XG4gICAgICAgICAgICByZXN1bHRbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICB9XG4gIH07XG5cblxuICByZXR1cm4gQW5pbWl0O1xufSkoKTtcbiIsIi8qXHJcbiAqIGNoaWxkTm9kZS5yZW1vdmUgbWV0aG9kIHBvbHlmaWxsIGZvciBJRS5cclxuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0NoaWxkTm9kZS9yZW1vdmVcclxuICovXHJcblxyXG4oZnVuY3Rpb24oKSB7XHJcblx0aWYgKCEoJ3JlbW92ZScgaW4gRWxlbWVudC5wcm90b3R5cGUpKSB7XHJcblx0ICBFbGVtZW50LnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcclxuXHQgICAgaWYgKHRoaXMucGFyZW50Tm9kZSkge1xyXG5cdCAgICBcdHRoaXMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzKTtcclxuXHQgICAgfVxyXG5cdCAgfTtcclxuXHR9XHJcbn0pKCk7XHJcbiIsIi8qXHJcbiAqIGNsYXNzTGlzdC5qczogQ3Jvc3MtYnJvd3NlciBmdWxsIGVsZW1lbnQuY2xhc3NMaXN0IGltcGxlbWVudGF0aW9uLlxyXG4gKiAxLjEuMjAxNTAzMTJcclxuICpcclxuICogQnkgRWxpIEdyZXksIGh0dHA6Ly9lbGlncmV5LmNvbVxyXG4gKiBMaWNlbnNlOiBEZWRpY2F0ZWQgdG8gdGhlIHB1YmxpYyBkb21haW4uXHJcbiAqICAgU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbGlncmV5L2NsYXNzTGlzdC5qcy9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXHJcbiAqL1xyXG5cclxuLypnbG9iYWwgc2VsZiwgZG9jdW1lbnQsIERPTUV4Y2VwdGlvbiAqL1xyXG5cclxuLyohIEBzb3VyY2UgaHR0cDovL3B1cmwuZWxpZ3JleS5jb20vZ2l0aHViL2NsYXNzTGlzdC5qcy9ibG9iL21hc3Rlci9jbGFzc0xpc3QuanMgKi9cclxuXHJcbmlmIChcImRvY3VtZW50XCIgaW4gc2VsZikge1xyXG5cclxuLy8gRnVsbCBwb2x5ZmlsbCBmb3IgYnJvd3NlcnMgd2l0aCBubyBjbGFzc0xpc3Qgc3VwcG9ydFxyXG4vLyBJbmNsdWRpbmcgSUUgPCBFZGdlIG1pc3NpbmcgU1ZHRWxlbWVudC5jbGFzc0xpc3RcclxuaWYgKCEoXCJjbGFzc0xpc3RcIiBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiX1wiKSlcclxuICB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMgJiYgIShcImNsYXNzTGlzdFwiIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpKSkge1xyXG5cclxuKGZ1bmN0aW9uICh2aWV3KSB7XHJcblxyXG5cInVzZSBzdHJpY3RcIjtcclxuXHJcbmlmICghKCdFbGVtZW50JyBpbiB2aWV3KSkgcmV0dXJuO1xyXG5cclxudmFyXHJcbiAgICBjbGFzc0xpc3RQcm9wID0gXCJjbGFzc0xpc3RcIlxyXG4gICwgcHJvdG9Qcm9wID0gXCJwcm90b3R5cGVcIlxyXG4gICwgZWxlbUN0clByb3RvID0gdmlldy5FbGVtZW50W3Byb3RvUHJvcF1cclxuICAsIG9iakN0ciA9IE9iamVjdFxyXG4gICwgc3RyVHJpbSA9IFN0cmluZ1twcm90b1Byb3BdLnRyaW0gfHwgZnVuY3Rpb24gKCkge1xyXG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgXCJcIik7XHJcbiAgfVxyXG4gICwgYXJySW5kZXhPZiA9IEFycmF5W3Byb3RvUHJvcF0uaW5kZXhPZiB8fCBmdW5jdGlvbiAoaXRlbSkge1xyXG4gICAgdmFyXHJcbiAgICAgICAgaSA9IDBcclxuICAgICAgLCBsZW4gPSB0aGlzLmxlbmd0aFxyXG4gICAgO1xyXG4gICAgZm9yICg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICBpZiAoaSBpbiB0aGlzICYmIHRoaXNbaV0gPT09IGl0ZW0pIHtcclxuICAgICAgICByZXR1cm4gaTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIC0xO1xyXG4gIH1cclxuICAvLyBWZW5kb3JzOiBwbGVhc2UgYWxsb3cgY29udGVudCBjb2RlIHRvIGluc3RhbnRpYXRlIERPTUV4Y2VwdGlvbnNcclxuICAsIERPTUV4ID0gZnVuY3Rpb24gKHR5cGUsIG1lc3NhZ2UpIHtcclxuICAgIHRoaXMubmFtZSA9IHR5cGU7XHJcbiAgICB0aGlzLmNvZGUgPSBET01FeGNlcHRpb25bdHlwZV07XHJcbiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xyXG4gIH1cclxuICAsIGNoZWNrVG9rZW5BbmRHZXRJbmRleCA9IGZ1bmN0aW9uIChjbGFzc0xpc3QsIHRva2VuKSB7XHJcbiAgICBpZiAodG9rZW4gPT09IFwiXCIpIHtcclxuICAgICAgdGhyb3cgbmV3IERPTUV4KFxyXG4gICAgICAgICAgXCJTWU5UQVhfRVJSXCJcclxuICAgICAgICAsIFwiQW4gaW52YWxpZCBvciBpbGxlZ2FsIHN0cmluZyB3YXMgc3BlY2lmaWVkXCJcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIGlmICgvXFxzLy50ZXN0KHRva2VuKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRE9NRXgoXHJcbiAgICAgICAgICBcIklOVkFMSURfQ0hBUkFDVEVSX0VSUlwiXHJcbiAgICAgICAgLCBcIlN0cmluZyBjb250YWlucyBhbiBpbnZhbGlkIGNoYXJhY3RlclwiXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXJySW5kZXhPZi5jYWxsKGNsYXNzTGlzdCwgdG9rZW4pO1xyXG4gIH1cclxuICAsIENsYXNzTGlzdCA9IGZ1bmN0aW9uIChlbGVtKSB7XHJcbiAgICB2YXJcclxuICAgICAgICB0cmltbWVkQ2xhc3NlcyA9IHN0clRyaW0uY2FsbChlbGVtLmdldEF0dHJpYnV0ZShcImNsYXNzXCIpIHx8IFwiXCIpXHJcbiAgICAgICwgY2xhc3NlcyA9IHRyaW1tZWRDbGFzc2VzID8gdHJpbW1lZENsYXNzZXMuc3BsaXQoL1xccysvKSA6IFtdXHJcbiAgICAgICwgaSA9IDBcclxuICAgICAgLCBsZW4gPSBjbGFzc2VzLmxlbmd0aFxyXG4gICAgO1xyXG4gICAgZm9yICg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICB0aGlzLnB1c2goY2xhc3Nlc1tpXSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLl91cGRhdGVDbGFzc05hbWUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGVsZW0uc2V0QXR0cmlidXRlKFwiY2xhc3NcIiwgdGhpcy50b1N0cmluZygpKTtcclxuICAgIH07XHJcbiAgfVxyXG4gICwgY2xhc3NMaXN0UHJvdG8gPSBDbGFzc0xpc3RbcHJvdG9Qcm9wXSA9IFtdXHJcbiAgLCBjbGFzc0xpc3RHZXR0ZXIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICByZXR1cm4gbmV3IENsYXNzTGlzdCh0aGlzKTtcclxuICB9XHJcbjtcclxuLy8gTW9zdCBET01FeGNlcHRpb24gaW1wbGVtZW50YXRpb25zIGRvbid0IGFsbG93IGNhbGxpbmcgRE9NRXhjZXB0aW9uJ3MgdG9TdHJpbmcoKVxyXG4vLyBvbiBub24tRE9NRXhjZXB0aW9ucy4gRXJyb3IncyB0b1N0cmluZygpIGlzIHN1ZmZpY2llbnQgaGVyZS5cclxuRE9NRXhbcHJvdG9Qcm9wXSA9IEVycm9yW3Byb3RvUHJvcF07XHJcbmNsYXNzTGlzdFByb3RvLml0ZW0gPSBmdW5jdGlvbiAoaSkge1xyXG4gIHJldHVybiB0aGlzW2ldIHx8IG51bGw7XHJcbn07XHJcbmNsYXNzTGlzdFByb3RvLmNvbnRhaW5zID0gZnVuY3Rpb24gKHRva2VuKSB7XHJcbiAgdG9rZW4gKz0gXCJcIjtcclxuICByZXR1cm4gY2hlY2tUb2tlbkFuZEdldEluZGV4KHRoaXMsIHRva2VuKSAhPT0gLTE7XHJcbn07XHJcbmNsYXNzTGlzdFByb3RvLmFkZCA9IGZ1bmN0aW9uICgpIHtcclxuICB2YXJcclxuICAgICAgdG9rZW5zID0gYXJndW1lbnRzXHJcbiAgICAsIGkgPSAwXHJcbiAgICAsIGwgPSB0b2tlbnMubGVuZ3RoXHJcbiAgICAsIHRva2VuXHJcbiAgICAsIHVwZGF0ZWQgPSBmYWxzZVxyXG4gIDtcclxuICBkbyB7XHJcbiAgICB0b2tlbiA9IHRva2Vuc1tpXSArIFwiXCI7XHJcbiAgICBpZiAoY2hlY2tUb2tlbkFuZEdldEluZGV4KHRoaXMsIHRva2VuKSA9PT0gLTEpIHtcclxuICAgICAgdGhpcy5wdXNoKHRva2VuKTtcclxuICAgICAgdXBkYXRlZCA9IHRydWU7XHJcbiAgICB9XHJcbiAgfVxyXG4gIHdoaWxlICgrK2kgPCBsKTtcclxuXHJcbiAgaWYgKHVwZGF0ZWQpIHtcclxuICAgIHRoaXMuX3VwZGF0ZUNsYXNzTmFtZSgpO1xyXG4gIH1cclxufTtcclxuY2xhc3NMaXN0UHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xyXG4gIHZhclxyXG4gICAgICB0b2tlbnMgPSBhcmd1bWVudHNcclxuICAgICwgaSA9IDBcclxuICAgICwgbCA9IHRva2Vucy5sZW5ndGhcclxuICAgICwgdG9rZW5cclxuICAgICwgdXBkYXRlZCA9IGZhbHNlXHJcbiAgICAsIGluZGV4XHJcbiAgO1xyXG4gIGRvIHtcclxuICAgIHRva2VuID0gdG9rZW5zW2ldICsgXCJcIjtcclxuICAgIGluZGV4ID0gY2hlY2tUb2tlbkFuZEdldEluZGV4KHRoaXMsIHRva2VuKTtcclxuICAgIHdoaWxlIChpbmRleCAhPT0gLTEpIHtcclxuICAgICAgdGhpcy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICB1cGRhdGVkID0gdHJ1ZTtcclxuICAgICAgaW5kZXggPSBjaGVja1Rva2VuQW5kR2V0SW5kZXgodGhpcywgdG9rZW4pO1xyXG4gICAgfVxyXG4gIH1cclxuICB3aGlsZSAoKytpIDwgbCk7XHJcblxyXG4gIGlmICh1cGRhdGVkKSB7XHJcbiAgICB0aGlzLl91cGRhdGVDbGFzc05hbWUoKTtcclxuICB9XHJcbn07XHJcbmNsYXNzTGlzdFByb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uICh0b2tlbiwgZm9yY2UpIHtcclxuICB0b2tlbiArPSBcIlwiO1xyXG5cclxuICB2YXJcclxuICAgICAgcmVzdWx0ID0gdGhpcy5jb250YWlucyh0b2tlbilcclxuICAgICwgbWV0aG9kID0gcmVzdWx0ID9cclxuICAgICAgZm9yY2UgIT09IHRydWUgJiYgXCJyZW1vdmVcIlxyXG4gICAgOlxyXG4gICAgICBmb3JjZSAhPT0gZmFsc2UgJiYgXCJhZGRcIlxyXG4gIDtcclxuXHJcbiAgaWYgKG1ldGhvZCkge1xyXG4gICAgdGhpc1ttZXRob2RdKHRva2VuKTtcclxuICB9XHJcblxyXG4gIGlmIChmb3JjZSA9PT0gdHJ1ZSB8fCBmb3JjZSA9PT0gZmFsc2UpIHtcclxuICAgIHJldHVybiBmb3JjZTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuICFyZXN1bHQ7XHJcbiAgfVxyXG59O1xyXG5jbGFzc0xpc3RQcm90by50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcclxuICByZXR1cm4gdGhpcy5qb2luKFwiIFwiKTtcclxufTtcclxuXHJcbmlmIChvYmpDdHIuZGVmaW5lUHJvcGVydHkpIHtcclxuICB2YXIgY2xhc3NMaXN0UHJvcERlc2MgPSB7XHJcbiAgICAgIGdldDogY2xhc3NMaXN0R2V0dGVyXHJcbiAgICAsIGVudW1lcmFibGU6IHRydWVcclxuICAgICwgY29uZmlndXJhYmxlOiB0cnVlXHJcbiAgfTtcclxuICB0cnkge1xyXG4gICAgb2JqQ3RyLmRlZmluZVByb3BlcnR5KGVsZW1DdHJQcm90bywgY2xhc3NMaXN0UHJvcCwgY2xhc3NMaXN0UHJvcERlc2MpO1xyXG4gIH0gY2F0Y2ggKGV4KSB7IC8vIElFIDggZG9lc24ndCBzdXBwb3J0IGVudW1lcmFibGU6dHJ1ZVxyXG4gICAgaWYgKGV4Lm51bWJlciA9PT0gLTB4N0ZGNUVDNTQpIHtcclxuICAgICAgY2xhc3NMaXN0UHJvcERlc2MuZW51bWVyYWJsZSA9IGZhbHNlO1xyXG4gICAgICBvYmpDdHIuZGVmaW5lUHJvcGVydHkoZWxlbUN0clByb3RvLCBjbGFzc0xpc3RQcm9wLCBjbGFzc0xpc3RQcm9wRGVzYyk7XHJcbiAgICB9XHJcbiAgfVxyXG59IGVsc2UgaWYgKG9iakN0cltwcm90b1Byb3BdLl9fZGVmaW5lR2V0dGVyX18pIHtcclxuICBlbGVtQ3RyUHJvdG8uX19kZWZpbmVHZXR0ZXJfXyhjbGFzc0xpc3RQcm9wLCBjbGFzc0xpc3RHZXR0ZXIpO1xyXG59XHJcblxyXG59KHNlbGYpKTtcclxuXHJcbn0gZWxzZSB7XHJcbi8vIFRoZXJlIGlzIGZ1bGwgb3IgcGFydGlhbCBuYXRpdmUgY2xhc3NMaXN0IHN1cHBvcnQsIHNvIGp1c3QgY2hlY2sgaWYgd2UgbmVlZFxyXG4vLyB0byBub3JtYWxpemUgdGhlIGFkZC9yZW1vdmUgYW5kIHRvZ2dsZSBBUElzLlxyXG5cclxuKGZ1bmN0aW9uICgpIHtcclxuICBcInVzZSBzdHJpY3RcIjtcclxuXHJcbiAgdmFyIHRlc3RFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIl9cIik7XHJcblxyXG4gIHRlc3RFbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJjMVwiLCBcImMyXCIpO1xyXG5cclxuICAvLyBQb2x5ZmlsbCBmb3IgSUUgMTAvMTEgYW5kIEZpcmVmb3ggPDI2LCB3aGVyZSBjbGFzc0xpc3QuYWRkIGFuZFxyXG4gIC8vIGNsYXNzTGlzdC5yZW1vdmUgZXhpc3QgYnV0IHN1cHBvcnQgb25seSBvbmUgYXJndW1lbnQgYXQgYSB0aW1lLlxyXG4gIGlmICghdGVzdEVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFwiYzJcIikpIHtcclxuICAgIHZhciBjcmVhdGVNZXRob2QgPSBmdW5jdGlvbihtZXRob2QpIHtcclxuICAgICAgdmFyIG9yaWdpbmFsID0gRE9NVG9rZW5MaXN0LnByb3RvdHlwZVttZXRob2RdO1xyXG5cclxuICAgICAgRE9NVG9rZW5MaXN0LnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24odG9rZW4pIHtcclxuICAgICAgICB2YXIgaSwgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcclxuXHJcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICB0b2tlbiA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgIG9yaWdpbmFsLmNhbGwodGhpcywgdG9rZW4pO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuICAgIH07XHJcbiAgICBjcmVhdGVNZXRob2QoJ2FkZCcpO1xyXG4gICAgY3JlYXRlTWV0aG9kKCdyZW1vdmUnKTtcclxuICB9XHJcblxyXG4gIHRlc3RFbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoXCJjM1wiLCBmYWxzZSk7XHJcblxyXG4gIC8vIFBvbHlmaWxsIGZvciBJRSAxMCBhbmQgRmlyZWZveCA8MjQsIHdoZXJlIGNsYXNzTGlzdC50b2dnbGUgZG9lcyBub3RcclxuICAvLyBzdXBwb3J0IHRoZSBzZWNvbmQgYXJndW1lbnQuXHJcbiAgaWYgKHRlc3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhcImMzXCIpKSB7XHJcbiAgICB2YXIgX3RvZ2dsZSA9IERPTVRva2VuTGlzdC5wcm90b3R5cGUudG9nZ2xlO1xyXG5cclxuICAgIERPTVRva2VuTGlzdC5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24odG9rZW4sIGZvcmNlKSB7XHJcbiAgICAgIGlmICgxIGluIGFyZ3VtZW50cyAmJiAhdGhpcy5jb250YWlucyh0b2tlbikgPT09ICFmb3JjZSkge1xyXG4gICAgICAgIHJldHVybiBmb3JjZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXR1cm4gX3RvZ2dsZS5jYWxsKHRoaXMsIHRva2VuKTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgfVxyXG5cclxuICB0ZXN0RWxlbWVudCA9IG51bGw7XHJcbn0oKSk7XHJcblxyXG59XHJcblxyXG59XHJcblxyXG4iLCIvKiFcblxuQ29weXJpZ2h0IChDKSAyMDE0LTIwMTYgYnkgQW5kcmVhIEdpYW1tYXJjaGkgLSBAV2ViUmVmbGVjdGlvblxuXG5QZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG5vZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG5pbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG50byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG5jb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbmZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG5hbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG5GSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG5PVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG5USEUgU09GVFdBUkUuXG5cbiovXG5cbmlmICgnY3VzdG9tRWxlbWVudHMnIGluIHdpbmRvdykge1xuICB3aW5kb3cuY3VzdG9tRWxlbWVudHMuZGVmaW5lID0gdW5kZWZpbmVkO1xufVxuXG4oZnVuY3Rpb24od2luZG93KXsndXNlIHN0cmljdCc7XG5cbiAgLy8gRE8gTk9UIFVTRSBUSElTIEZJTEUgRElSRUNUTFksIElUIFdPTidUIFdPUktcbiAgLy8gVEhJUyBJUyBBIFBST0pFQ1QgQkFTRUQgT04gQSBCVUlMRCBTWVNURU1cbiAgLy8gVEhJUyBGSUxFIElTIEpVU1QgV1JBUFBFRCBVUCBSRVNVTFRJTkcgSU5cbiAgLy8gYnVpbGQvZG9jdW1lbnQtcmVnaXN0ZXItZWxlbWVudC5qc1xuICAvLyBhbmQgaXRzIC5tYXguanMgY291bnRlciBwYXJ0XG5cbiAgdmFyXG4gICAgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQsXG4gICAgT2JqZWN0ID0gd2luZG93Lk9iamVjdFxuICA7XG5cbiAgdmFyIGh0bWxDbGFzcyA9IChmdW5jdGlvbiAoaW5mbykge1xuICAgIC8vIChDKSBBbmRyZWEgR2lhbW1hcmNoaSAtIEBXZWJSZWZsZWN0aW9uIC0gTUlUIFN0eWxlXG4gICAgdmFyXG4gICAgICBjYXRjaENsYXNzID0gL15bQS1aXStbYS16XS8sXG4gICAgICBmaWx0ZXJCeSA9IGZ1bmN0aW9uIChyZSkge1xuICAgICAgICB2YXIgYXJyID0gW10sIHRhZztcbiAgICAgICAgZm9yICh0YWcgaW4gcmVnaXN0ZXIpIHtcbiAgICAgICAgICBpZiAocmUudGVzdCh0YWcpKSBhcnIucHVzaCh0YWcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgICB9LFxuICAgICAgYWRkID0gZnVuY3Rpb24gKENsYXNzLCB0YWcpIHtcbiAgICAgICAgdGFnID0gdGFnLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmICghKHRhZyBpbiByZWdpc3RlcikpIHtcbiAgICAgICAgICByZWdpc3RlcltDbGFzc10gPSAocmVnaXN0ZXJbQ2xhc3NdIHx8IFtdKS5jb25jYXQodGFnKTtcbiAgICAgICAgICByZWdpc3Rlclt0YWddID0gKHJlZ2lzdGVyW3RhZy50b1VwcGVyQ2FzZSgpXSA9IENsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHJlZ2lzdGVyID0gKE9iamVjdC5jcmVhdGUgfHwgT2JqZWN0KShudWxsKSxcbiAgICAgIGh0bWxDbGFzcyA9IHt9LFxuICAgICAgaSwgc2VjdGlvbiwgdGFncywgQ2xhc3NcbiAgICA7XG4gICAgZm9yIChzZWN0aW9uIGluIGluZm8pIHtcbiAgICAgIGZvciAoQ2xhc3MgaW4gaW5mb1tzZWN0aW9uXSkge1xuICAgICAgICB0YWdzID0gaW5mb1tzZWN0aW9uXVtDbGFzc107XG4gICAgICAgIHJlZ2lzdGVyW0NsYXNzXSA9IHRhZ3M7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgcmVnaXN0ZXJbdGFnc1tpXS50b0xvd2VyQ2FzZSgpXSA9XG4gICAgICAgICAgcmVnaXN0ZXJbdGFnc1tpXS50b1VwcGVyQ2FzZSgpXSA9IENsYXNzO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGh0bWxDbGFzcy5nZXQgPSBmdW5jdGlvbiBnZXQodGFnT3JDbGFzcykge1xuICAgICAgcmV0dXJuIHR5cGVvZiB0YWdPckNsYXNzID09PSAnc3RyaW5nJyA/XG4gICAgICAgIChyZWdpc3Rlclt0YWdPckNsYXNzXSB8fCAoY2F0Y2hDbGFzcy50ZXN0KHRhZ09yQ2xhc3MpID8gW10gOiAnJykpIDpcbiAgICAgICAgZmlsdGVyQnkodGFnT3JDbGFzcyk7XG4gICAgfTtcbiAgICBodG1sQ2xhc3Muc2V0ID0gZnVuY3Rpb24gc2V0KHRhZywgQ2xhc3MpIHtcbiAgICAgIHJldHVybiAoY2F0Y2hDbGFzcy50ZXN0KHRhZykgP1xuICAgICAgICBhZGQodGFnLCBDbGFzcykgOlxuICAgICAgICBhZGQoQ2xhc3MsIHRhZylcbiAgICAgICksIGh0bWxDbGFzcztcbiAgICB9O1xuICAgIHJldHVybiBodG1sQ2xhc3M7XG4gIH0oe1xuICAgIFwiY29sbGVjdGlvbnNcIjoge1xuICAgICAgXCJIVE1MQWxsQ29sbGVjdGlvblwiOiBbXG4gICAgICAgIFwiYWxsXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxDb2xsZWN0aW9uXCI6IFtcbiAgICAgICAgXCJmb3Jtc1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRm9ybUNvbnRyb2xzQ29sbGVjdGlvblwiOiBbXG4gICAgICAgIFwiZWxlbWVudHNcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE9wdGlvbnNDb2xsZWN0aW9uXCI6IFtcbiAgICAgICAgXCJvcHRpb25zXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiZWxlbWVudHNcIjoge1xuICAgICAgXCJFbGVtZW50XCI6IFtcbiAgICAgICAgXCJlbGVtZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxBbmNob3JFbGVtZW50XCI6IFtcbiAgICAgICAgXCJhXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxBcHBsZXRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJhcHBsZXRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEFyZWFFbGVtZW50XCI6IFtcbiAgICAgICAgXCJhcmVhXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxBdHRhY2htZW50RWxlbWVudFwiOiBbXG4gICAgICAgIFwiYXR0YWNobWVudFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQXVkaW9FbGVtZW50XCI6IFtcbiAgICAgICAgXCJhdWRpb1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQlJFbGVtZW50XCI6IFtcbiAgICAgICAgXCJiclwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQmFzZUVsZW1lbnRcIjogW1xuICAgICAgICBcImJhc2VcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEJvZHlFbGVtZW50XCI6IFtcbiAgICAgICAgXCJib2R5XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxCdXR0b25FbGVtZW50XCI6IFtcbiAgICAgICAgXCJidXR0b25cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTENhbnZhc0VsZW1lbnRcIjogW1xuICAgICAgICBcImNhbnZhc1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MQ29udGVudEVsZW1lbnRcIjogW1xuICAgICAgICBcImNvbnRlbnRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTERMaXN0RWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGxcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTERhdGFFbGVtZW50XCI6IFtcbiAgICAgICAgXCJkYXRhXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEYXRhTGlzdEVsZW1lbnRcIjogW1xuICAgICAgICBcImRhdGFsaXN0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEZXRhaWxzRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGV0YWlsc1wiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRGlhbG9nRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGlhbG9nXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEaXJlY3RvcnlFbGVtZW50XCI6IFtcbiAgICAgICAgXCJkaXJcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTERpdkVsZW1lbnRcIjogW1xuICAgICAgICBcImRpdlwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRG9jdW1lbnRcIjogW1xuICAgICAgICBcImRvY3VtZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxFbGVtZW50XCI6IFtcbiAgICAgICAgXCJlbGVtZW50XCIsXG4gICAgICAgIFwiYWJiclwiLFxuICAgICAgICBcImFkZHJlc3NcIixcbiAgICAgICAgXCJhcnRpY2xlXCIsXG4gICAgICAgIFwiYXNpZGVcIixcbiAgICAgICAgXCJiXCIsXG4gICAgICAgIFwiYmRpXCIsXG4gICAgICAgIFwiYmRvXCIsXG4gICAgICAgIFwiY2l0ZVwiLFxuICAgICAgICBcImNvZGVcIixcbiAgICAgICAgXCJjb21tYW5kXCIsXG4gICAgICAgIFwiZGRcIixcbiAgICAgICAgXCJkZm5cIixcbiAgICAgICAgXCJkdFwiLFxuICAgICAgICBcImVtXCIsXG4gICAgICAgIFwiZmlnY2FwdGlvblwiLFxuICAgICAgICBcImZpZ3VyZVwiLFxuICAgICAgICBcImZvb3RlclwiLFxuICAgICAgICBcImhlYWRlclwiLFxuICAgICAgICBcImlcIixcbiAgICAgICAgXCJrYmRcIixcbiAgICAgICAgXCJtYXJrXCIsXG4gICAgICAgIFwibmF2XCIsXG4gICAgICAgIFwibm9zY3JpcHRcIixcbiAgICAgICAgXCJycFwiLFxuICAgICAgICBcInJ0XCIsXG4gICAgICAgIFwicnVieVwiLFxuICAgICAgICBcInNcIixcbiAgICAgICAgXCJzYW1wXCIsXG4gICAgICAgIFwic2VjdGlvblwiLFxuICAgICAgICBcInNtYWxsXCIsXG4gICAgICAgIFwic3Ryb25nXCIsXG4gICAgICAgIFwic3ViXCIsXG4gICAgICAgIFwic3VtbWFyeVwiLFxuICAgICAgICBcInN1cFwiLFxuICAgICAgICBcInVcIixcbiAgICAgICAgXCJ2YXJcIixcbiAgICAgICAgXCJ3YnJcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEVtYmVkRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZW1iZWRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEZpZWxkU2V0RWxlbWVudFwiOiBbXG4gICAgICAgIFwiZmllbGRzZXRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEZvbnRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJmb250XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxGb3JtRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZm9ybVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRnJhbWVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJmcmFtZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MRnJhbWVTZXRFbGVtZW50XCI6IFtcbiAgICAgICAgXCJmcmFtZXNldFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MSFJFbGVtZW50XCI6IFtcbiAgICAgICAgXCJoclwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MSGVhZEVsZW1lbnRcIjogW1xuICAgICAgICBcImhlYWRcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEhlYWRpbmdFbGVtZW50XCI6IFtcbiAgICAgICAgXCJoMVwiLFxuICAgICAgICBcImgyXCIsXG4gICAgICAgIFwiaDNcIixcbiAgICAgICAgXCJoNFwiLFxuICAgICAgICBcImg1XCIsXG4gICAgICAgIFwiaDZcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEh0bWxFbGVtZW50XCI6IFtcbiAgICAgICAgXCJodG1sXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxJRnJhbWVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJpZnJhbWVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTEltYWdlRWxlbWVudFwiOiBbXG4gICAgICAgIFwiaW1nXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxJbnB1dEVsZW1lbnRcIjogW1xuICAgICAgICBcImlucHV0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxLZXlnZW5FbGVtZW50XCI6IFtcbiAgICAgICAgXCJrZXlnZW5cIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTExJRWxlbWVudFwiOiBbXG4gICAgICAgIFwibGlcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTExhYmVsRWxlbWVudFwiOiBbXG4gICAgICAgIFwibGFiZWxcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTExlZ2VuZEVsZW1lbnRcIjogW1xuICAgICAgICBcImxlZ2VuZFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTGlua0VsZW1lbnRcIjogW1xuICAgICAgICBcImxpbmtcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1hcEVsZW1lbnRcIjogW1xuICAgICAgICBcIm1hcFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTWFycXVlZUVsZW1lbnRcIjogW1xuICAgICAgICBcIm1hcnF1ZWVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1lZGlhRWxlbWVudFwiOiBbXG4gICAgICAgIFwibWVkaWFcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE1lbnVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJtZW51XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxNZW51SXRlbUVsZW1lbnRcIjogW1xuICAgICAgICBcIm1lbnVpdGVtXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxNZXRhRWxlbWVudFwiOiBbXG4gICAgICAgIFwibWV0YVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTWV0ZXJFbGVtZW50XCI6IFtcbiAgICAgICAgXCJtZXRlclwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MTW9kRWxlbWVudFwiOiBbXG4gICAgICAgIFwiZGVsXCIsXG4gICAgICAgIFwiaW5zXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxPTGlzdEVsZW1lbnRcIjogW1xuICAgICAgICBcIm9sXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxPYmplY3RFbGVtZW50XCI6IFtcbiAgICAgICAgXCJvYmplY3RcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE9wdEdyb3VwRWxlbWVudFwiOiBbXG4gICAgICAgIFwib3B0Z3JvdXBcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTE9wdGlvbkVsZW1lbnRcIjogW1xuICAgICAgICBcIm9wdGlvblwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MT3V0cHV0RWxlbWVudFwiOiBbXG4gICAgICAgIFwib3V0cHV0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxQYXJhZ3JhcGhFbGVtZW50XCI6IFtcbiAgICAgICAgXCJwXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxQYXJhbUVsZW1lbnRcIjogW1xuICAgICAgICBcInBhcmFtXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxQaWN0dXJlRWxlbWVudFwiOiBbXG4gICAgICAgIFwicGljdHVyZVwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MUHJlRWxlbWVudFwiOiBbXG4gICAgICAgIFwicHJlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxQcm9ncmVzc0VsZW1lbnRcIjogW1xuICAgICAgICBcInByb2dyZXNzXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxRdW90ZUVsZW1lbnRcIjogW1xuICAgICAgICBcImJsb2NrcXVvdGVcIixcbiAgICAgICAgXCJxXCIsXG4gICAgICAgIFwicXVvdGVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFNjcmlwdEVsZW1lbnRcIjogW1xuICAgICAgICBcInNjcmlwdFwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MU2VsZWN0RWxlbWVudFwiOiBbXG4gICAgICAgIFwic2VsZWN0XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTaGFkb3dFbGVtZW50XCI6IFtcbiAgICAgICAgXCJzaGFkb3dcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFNsb3RFbGVtZW50XCI6IFtcbiAgICAgICAgXCJzbG90XCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTb3VyY2VFbGVtZW50XCI6IFtcbiAgICAgICAgXCJzb3VyY2VcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFNwYW5FbGVtZW50XCI6IFtcbiAgICAgICAgXCJzcGFuXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxTdHlsZUVsZW1lbnRcIjogW1xuICAgICAgICBcInN0eWxlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZUNhcHRpb25FbGVtZW50XCI6IFtcbiAgICAgICAgXCJjYXB0aW9uXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZUNlbGxFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0ZFwiLFxuICAgICAgICBcInRoXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZUNvbEVsZW1lbnRcIjogW1xuICAgICAgICBcImNvbFwiLFxuICAgICAgICBcImNvbGdyb3VwXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZUVsZW1lbnRcIjogW1xuICAgICAgICBcInRhYmxlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZVJvd0VsZW1lbnRcIjogW1xuICAgICAgICBcInRyXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUYWJsZVNlY3Rpb25FbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0aGVhZFwiLFxuICAgICAgICBcInRib2R5XCIsXG4gICAgICAgIFwidGZvb3RcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFRlbXBsYXRlRWxlbWVudFwiOiBbXG4gICAgICAgIFwidGVtcGxhdGVcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFRleHRBcmVhRWxlbWVudFwiOiBbXG4gICAgICAgIFwidGV4dGFyZWFcIlxuICAgICAgXSxcbiAgICAgIFwiSFRNTFRpbWVFbGVtZW50XCI6IFtcbiAgICAgICAgXCJ0aW1lXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUaXRsZUVsZW1lbnRcIjogW1xuICAgICAgICBcInRpdGxlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxUcmFja0VsZW1lbnRcIjogW1xuICAgICAgICBcInRyYWNrXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxVTGlzdEVsZW1lbnRcIjogW1xuICAgICAgICBcInVsXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxVbmtub3duRWxlbWVudFwiOiBbXG4gICAgICAgIFwidW5rbm93blwiLFxuICAgICAgICBcInZoZ3JvdXB2XCIsXG4gICAgICAgIFwidmtleWdlblwiXG4gICAgICBdLFxuICAgICAgXCJIVE1MVmlkZW9FbGVtZW50XCI6IFtcbiAgICAgICAgXCJ2aWRlb1wiXG4gICAgICBdXG4gICAgfSxcbiAgICBcIm5vZGVzXCI6IHtcbiAgICAgIFwiQXR0clwiOiBbXG4gICAgICAgIFwibm9kZVwiXG4gICAgICBdLFxuICAgICAgXCJBdWRpb1wiOiBbXG4gICAgICAgIFwiYXVkaW9cIlxuICAgICAgXSxcbiAgICAgIFwiQ0RBVEFTZWN0aW9uXCI6IFtcbiAgICAgICAgXCJub2RlXCJcbiAgICAgIF0sXG4gICAgICBcIkNoYXJhY3RlckRhdGFcIjogW1xuICAgICAgICBcIm5vZGVcIlxuICAgICAgXSxcbiAgICAgIFwiQ29tbWVudFwiOiBbXG4gICAgICAgIFwiI2NvbW1lbnRcIlxuICAgICAgXSxcbiAgICAgIFwiRG9jdW1lbnRcIjogW1xuICAgICAgICBcIiNkb2N1bWVudFwiXG4gICAgICBdLFxuICAgICAgXCJEb2N1bWVudEZyYWdtZW50XCI6IFtcbiAgICAgICAgXCIjZG9jdW1lbnQtZnJhZ21lbnRcIlxuICAgICAgXSxcbiAgICAgIFwiRG9jdW1lbnRUeXBlXCI6IFtcbiAgICAgICAgXCJub2RlXCJcbiAgICAgIF0sXG4gICAgICBcIkhUTUxEb2N1bWVudFwiOiBbXG4gICAgICAgIFwiI2RvY3VtZW50XCJcbiAgICAgIF0sXG4gICAgICBcIkltYWdlXCI6IFtcbiAgICAgICAgXCJpbWdcIlxuICAgICAgXSxcbiAgICAgIFwiT3B0aW9uXCI6IFtcbiAgICAgICAgXCJvcHRpb25cIlxuICAgICAgXSxcbiAgICAgIFwiUHJvY2Vzc2luZ0luc3RydWN0aW9uXCI6IFtcbiAgICAgICAgXCJub2RlXCJcbiAgICAgIF0sXG4gICAgICBcIlNoYWRvd1Jvb3RcIjogW1xuICAgICAgICBcIiNzaGFkb3ctcm9vdFwiXG4gICAgICBdLFxuICAgICAgXCJUZXh0XCI6IFtcbiAgICAgICAgXCIjdGV4dFwiXG4gICAgICBdLFxuICAgICAgXCJYTUxEb2N1bWVudFwiOiBbXG4gICAgICAgIFwieG1sXCJcbiAgICAgIF1cbiAgICB9XG4gIH0pKTtcbiAgXG4gIFxuICAgIHZhclxuICAgIC8vIFYwIHBvbHlmaWxsIGVudHJ5XG4gICAgUkVHSVNURVJfRUxFTUVOVCA9ICdyZWdpc3RlckVsZW1lbnQnLFxuICBcbiAgICAvLyBJRSA8IDExIG9ubHkgKyBvbGQgV2ViS2l0IGZvciBhdHRyaWJ1dGVzICsgZmVhdHVyZSBkZXRlY3Rpb25cbiAgICBFWFBBTkRPX1VJRCA9ICdfXycgKyBSRUdJU1RFUl9FTEVNRU5UICsgKHdpbmRvdy5NYXRoLnJhbmRvbSgpICogMTBlNCA+PiAwKSxcbiAgXG4gICAgLy8gc2hvcnRjdXRzIGFuZCBjb3N0YW50c1xuICAgIEFERF9FVkVOVF9MSVNURU5FUiA9ICdhZGRFdmVudExpc3RlbmVyJyxcbiAgICBBVFRBQ0hFRCA9ICdhdHRhY2hlZCcsXG4gICAgQ0FMTEJBQ0sgPSAnQ2FsbGJhY2snLFxuICAgIERFVEFDSEVEID0gJ2RldGFjaGVkJyxcbiAgICBFWFRFTkRTID0gJ2V4dGVuZHMnLFxuICBcbiAgICBBVFRSSUJVVEVfQ0hBTkdFRF9DQUxMQkFDSyA9ICdhdHRyaWJ1dGVDaGFuZ2VkJyArIENBTExCQUNLLFxuICAgIEFUVEFDSEVEX0NBTExCQUNLID0gQVRUQUNIRUQgKyBDQUxMQkFDSyxcbiAgICBDT05ORUNURURfQ0FMTEJBQ0sgPSAnY29ubmVjdGVkJyArIENBTExCQUNLLFxuICAgIERJU0NPTk5FQ1RFRF9DQUxMQkFDSyA9ICdkaXNjb25uZWN0ZWQnICsgQ0FMTEJBQ0ssXG4gICAgQ1JFQVRFRF9DQUxMQkFDSyA9ICdjcmVhdGVkJyArIENBTExCQUNLLFxuICAgIERFVEFDSEVEX0NBTExCQUNLID0gREVUQUNIRUQgKyBDQUxMQkFDSyxcbiAgXG4gICAgQURESVRJT04gPSAnQURESVRJT04nLFxuICAgIE1PRElGSUNBVElPTiA9ICdNT0RJRklDQVRJT04nLFxuICAgIFJFTU9WQUwgPSAnUkVNT1ZBTCcsXG4gIFxuICAgIERPTV9BVFRSX01PRElGSUVEID0gJ0RPTUF0dHJNb2RpZmllZCcsXG4gICAgRE9NX0NPTlRFTlRfTE9BREVEID0gJ0RPTUNvbnRlbnRMb2FkZWQnLFxuICAgIERPTV9TVUJUUkVFX01PRElGSUVEID0gJ0RPTVN1YnRyZWVNb2RpZmllZCcsXG4gIFxuICAgIFBSRUZJWF9UQUcgPSAnPCcsXG4gICAgUFJFRklYX0lTID0gJz0nLFxuICBcbiAgICAvLyB2YWxpZCBhbmQgaW52YWxpZCBub2RlIG5hbWVzXG4gICAgdmFsaWROYW1lID0gL15bQS1aXVtBLVowLTldKig/Oi1bQS1aMC05XSspKyQvLFxuICAgIGludmFsaWROYW1lcyA9IFtcbiAgICAgICdBTk5PVEFUSU9OLVhNTCcsXG4gICAgICAnQ09MT1ItUFJPRklMRScsXG4gICAgICAnRk9OVC1GQUNFJyxcbiAgICAgICdGT05ULUZBQ0UtU1JDJyxcbiAgICAgICdGT05ULUZBQ0UtVVJJJyxcbiAgICAgICdGT05ULUZBQ0UtRk9STUFUJyxcbiAgICAgICdGT05ULUZBQ0UtTkFNRScsXG4gICAgICAnTUlTU0lORy1HTFlQSCdcbiAgICBdLFxuICBcbiAgICAvLyByZWdpc3RlcmVkIHR5cGVzIGFuZCB0aGVpciBwcm90b3R5cGVzXG4gICAgdHlwZXMgPSBbXSxcbiAgICBwcm90b3MgPSBbXSxcbiAgXG4gICAgLy8gdG8gcXVlcnkgc3Vibm9kZXNcbiAgICBxdWVyeSA9ICcnLFxuICBcbiAgICAvLyBodG1sIHNob3J0Y3V0IHVzZWQgdG8gZmVhdHVyZSBkZXRlY3RcbiAgICBkb2N1bWVudEVsZW1lbnQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG4gIFxuICAgIC8vIEVTNSBpbmxpbmUgaGVscGVycyB8fCBiYXNpYyBwYXRjaGVzXG4gICAgaW5kZXhPZiA9IHR5cGVzLmluZGV4T2YgfHwgZnVuY3Rpb24gKHYpIHtcbiAgICAgIGZvcih2YXIgaSA9IHRoaXMubGVuZ3RoOyBpLS0gJiYgdGhpc1tpXSAhPT0gdjspe31cbiAgICAgIHJldHVybiBpO1xuICAgIH0sXG4gIFxuICAgIC8vIG90aGVyIGhlbHBlcnMgLyBzaG9ydGN1dHNcbiAgICBPUCA9IE9iamVjdC5wcm90b3R5cGUsXG4gICAgaE9QID0gT1AuaGFzT3duUHJvcGVydHksXG4gICAgaVBPID0gT1AuaXNQcm90b3R5cGVPZixcbiAgXG4gICAgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHksXG4gICAgZW1wdHkgPSBbXSxcbiAgICBnT1BEID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixcbiAgICBnT1BOID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMsXG4gICAgZ1BPID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLFxuICAgIHNQTyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZixcbiAgXG4gICAgLy8ganNoaW50IHByb3RvOiB0cnVlXG4gICAgaGFzUHJvdG8gPSAhIU9iamVjdC5fX3Byb3RvX18sXG4gIFxuICAgIC8vIFYxIGhlbHBlcnNcbiAgICBmaXhHZXRDbGFzcyA9IGZhbHNlLFxuICAgIERSRUNFVjEgPSAnX19kcmVDRXYxJyxcbiAgICBjdXN0b21FbGVtZW50cyA9IHdpbmRvdy5jdXN0b21FbGVtZW50cyxcbiAgICB1c2FibGVDdXN0b21FbGVtZW50cyA9ICEhKFxuICAgICAgY3VzdG9tRWxlbWVudHMgJiZcbiAgICAgIGN1c3RvbUVsZW1lbnRzLmRlZmluZSAmJlxuICAgICAgY3VzdG9tRWxlbWVudHMuZ2V0ICYmXG4gICAgICBjdXN0b21FbGVtZW50cy53aGVuRGVmaW5lZFxuICAgICksXG4gICAgRGljdCA9IE9iamVjdC5jcmVhdGUgfHwgT2JqZWN0LFxuICAgIE1hcCA9IHdpbmRvdy5NYXAgfHwgZnVuY3Rpb24gTWFwKCkge1xuICAgICAgdmFyIEsgPSBbXSwgViA9IFtdLCBpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoaykge1xuICAgICAgICAgIHJldHVybiBWW2luZGV4T2YuY2FsbChLLCBrKV07XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24gKGssIHYpIHtcbiAgICAgICAgICBpID0gaW5kZXhPZi5jYWxsKEssIGspO1xuICAgICAgICAgIGlmIChpIDwgMCkgVltLLnB1c2goaykgLSAxXSA9IHY7XG4gICAgICAgICAgZWxzZSBWW2ldID0gdjtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9LFxuICAgIFByb21pc2UgPSB3aW5kb3cuUHJvbWlzZSB8fCBmdW5jdGlvbiAoZm4pIHtcbiAgICAgIHZhclxuICAgICAgICBub3RpZnkgPSBbXSxcbiAgICAgICAgZG9uZSA9IGZhbHNlLFxuICAgICAgICBwID0ge1xuICAgICAgICAgICdjYXRjaCc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgJ3RoZW4nOiBmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgIG5vdGlmeS5wdXNoKGNiKTtcbiAgICAgICAgICAgIGlmIChkb25lKSBzZXRUaW1lb3V0KHJlc29sdmUsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICA7XG4gICAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgICB3aGlsZSAobm90aWZ5Lmxlbmd0aCkgbm90aWZ5LnNoaWZ0KCkodmFsdWUpO1xuICAgICAgfVxuICAgICAgZm4ocmVzb2x2ZSk7XG4gICAgICByZXR1cm4gcDtcbiAgICB9LFxuICAgIGp1c3RDcmVhdGVkID0gZmFsc2UsXG4gICAgY29uc3RydWN0b3JzID0gRGljdChudWxsKSxcbiAgICB3YWl0aW5nTGlzdCA9IERpY3QobnVsbCksXG4gICAgbm9kZU5hbWVzID0gbmV3IE1hcCgpLFxuICAgIHNlY29uZEFyZ3VtZW50ID0gU3RyaW5nLFxuICBcbiAgICAvLyB1c2VkIHRvIGNyZWF0ZSB1bmlxdWUgaW5zdGFuY2VzXG4gICAgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBCcmlkZ2UocHJvdG8pIHtcbiAgICAgIC8vIHNpbGx5IGJyb2tlbiBwb2x5ZmlsbCBwcm9iYWJseSBldmVyIHVzZWQgYnV0IHNob3J0IGVub3VnaCB0byB3b3JrXG4gICAgICByZXR1cm4gcHJvdG8gPyAoKEJyaWRnZS5wcm90b3R5cGUgPSBwcm90byksIG5ldyBCcmlkZ2UoKSkgOiB0aGlzO1xuICAgIH0sXG4gIFxuICAgIC8vIHdpbGwgc2V0IHRoZSBwcm90b3R5cGUgaWYgcG9zc2libGVcbiAgICAvLyBvciBjb3B5IG92ZXIgYWxsIHByb3BlcnRpZXNcbiAgICBzZXRQcm90b3R5cGUgPSBzUE8gfHwgKFxuICAgICAgaGFzUHJvdG8gP1xuICAgICAgICBmdW5jdGlvbiAobywgcCkge1xuICAgICAgICAgIG8uX19wcm90b19fID0gcDtcbiAgICAgICAgICByZXR1cm4gbztcbiAgICAgICAgfSA6IChcbiAgICAgIChnT1BOICYmIGdPUEQpID9cbiAgICAgICAgKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgZnVuY3Rpb24gc2V0UHJvcGVydGllcyhvLCBwKSB7XG4gICAgICAgICAgICBmb3IgKHZhclxuICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgIG5hbWVzID0gZ09QTihwKSxcbiAgICAgICAgICAgICAgaSA9IDAsIGxlbmd0aCA9IG5hbWVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgaSA8IGxlbmd0aDsgaSsrXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAga2V5ID0gbmFtZXNbaV07XG4gICAgICAgICAgICAgIGlmICghaE9QLmNhbGwobywga2V5KSkge1xuICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KG8sIGtleSwgZ09QRChwLCBrZXkpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG8sIHApIHtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgc2V0UHJvcGVydGllcyhvLCBwKTtcbiAgICAgICAgICAgIH0gd2hpbGUgKChwID0gZ1BPKHApKSAmJiAhaVBPLmNhbGwocCwgbykpO1xuICAgICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgICAgfTtcbiAgICAgICAgfSgpKSA6XG4gICAgICAgIGZ1bmN0aW9uIChvLCBwKSB7XG4gICAgICAgICAgZm9yICh2YXIga2V5IGluIHApIHtcbiAgICAgICAgICAgIG9ba2V5XSA9IHBba2V5XTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgIH1cbiAgICApKSxcbiAgXG4gICAgLy8gRE9NIHNob3J0Y3V0cyBhbmQgaGVscGVycywgaWYgYW55XG4gIFxuICAgIE11dGF0aW9uT2JzZXJ2ZXIgPSB3aW5kb3cuTXV0YXRpb25PYnNlcnZlciB8fFxuICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuV2ViS2l0TXV0YXRpb25PYnNlcnZlcixcbiAgXG4gICAgSFRNTEVsZW1lbnRQcm90b3R5cGUgPSAoXG4gICAgICB3aW5kb3cuSFRNTEVsZW1lbnQgfHxcbiAgICAgIHdpbmRvdy5FbGVtZW50IHx8XG4gICAgICB3aW5kb3cuTm9kZVxuICAgICkucHJvdG90eXBlLFxuICBcbiAgICBJRTggPSAhaVBPLmNhbGwoSFRNTEVsZW1lbnRQcm90b3R5cGUsIGRvY3VtZW50RWxlbWVudCksXG4gIFxuICAgIHNhZmVQcm9wZXJ0eSA9IElFOCA/IGZ1bmN0aW9uIChvLCBrLCBkKSB7XG4gICAgICBvW2tdID0gZC52YWx1ZTtcbiAgICAgIHJldHVybiBvO1xuICAgIH0gOiBkZWZpbmVQcm9wZXJ0eSxcbiAgXG4gICAgaXNWYWxpZE5vZGUgPSBJRTggP1xuICAgICAgZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDE7XG4gICAgICB9IDpcbiAgICAgIGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHJldHVybiBpUE8uY2FsbChIVE1MRWxlbWVudFByb3RvdHlwZSwgbm9kZSk7XG4gICAgICB9LFxuICBcbiAgICB0YXJnZXRzID0gSUU4ICYmIFtdLFxuICBcbiAgICBhdHRhY2hTaGFkb3cgPSBIVE1MRWxlbWVudFByb3RvdHlwZS5hdHRhY2hTaGFkb3csXG4gICAgY2xvbmVOb2RlID0gSFRNTEVsZW1lbnRQcm90b3R5cGUuY2xvbmVOb2RlLFxuICAgIGRpc3BhdGNoRXZlbnQgPSBIVE1MRWxlbWVudFByb3RvdHlwZS5kaXNwYXRjaEV2ZW50LFxuICAgIGdldEF0dHJpYnV0ZSA9IEhUTUxFbGVtZW50UHJvdG90eXBlLmdldEF0dHJpYnV0ZSxcbiAgICBoYXNBdHRyaWJ1dGUgPSBIVE1MRWxlbWVudFByb3RvdHlwZS5oYXNBdHRyaWJ1dGUsXG4gICAgcmVtb3ZlQXR0cmlidXRlID0gSFRNTEVsZW1lbnRQcm90b3R5cGUucmVtb3ZlQXR0cmlidXRlLFxuICAgIHNldEF0dHJpYnV0ZSA9IEhUTUxFbGVtZW50UHJvdG90eXBlLnNldEF0dHJpYnV0ZSxcbiAgXG4gICAgLy8gcmVwbGFjZWQgbGF0ZXIgb25cbiAgICBjcmVhdGVFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCxcbiAgICBwYXRjaGVkQ3JlYXRlRWxlbWVudCA9IGNyZWF0ZUVsZW1lbnQsXG4gIFxuICAgIC8vIHNoYXJlZCBvYnNlcnZlciBmb3IgYWxsIGF0dHJpYnV0ZXNcbiAgICBhdHRyaWJ1dGVzT2JzZXJ2ZXIgPSBNdXRhdGlvbk9ic2VydmVyICYmIHtcbiAgICAgIGF0dHJpYnV0ZXM6IHRydWUsXG4gICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgYXR0cmlidXRlT2xkVmFsdWU6IHRydWVcbiAgICB9LFxuICBcbiAgICAvLyB1c2VmdWwgdG8gZGV0ZWN0IG9ubHkgaWYgdGhlcmUncyBubyBNdXRhdGlvbk9ic2VydmVyXG4gICAgRE9NQXR0ck1vZGlmaWVkID0gTXV0YXRpb25PYnNlcnZlciB8fCBmdW5jdGlvbihlKSB7XG4gICAgICBkb2VzTm90U3VwcG9ydERPTUF0dHJNb2RpZmllZCA9IGZhbHNlO1xuICAgICAgZG9jdW1lbnRFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgIERPTV9BVFRSX01PRElGSUVELFxuICAgICAgICBET01BdHRyTW9kaWZpZWRcbiAgICAgICk7XG4gICAgfSxcbiAgXG4gICAgLy8gd2lsbCBib3RoIGJlIHVzZWQgdG8gbWFrZSBET01Ob2RlSW5zZXJ0ZWQgYXN5bmNocm9ub3VzXG4gICAgYXNhcFF1ZXVlLFxuICAgIGFzYXBUaW1lciA9IDAsXG4gIFxuICAgIC8vIGludGVybmFsIGZsYWdzXG4gICAgc2V0TGlzdGVuZXIgPSBmYWxzZSxcbiAgICBkb2VzTm90U3VwcG9ydERPTUF0dHJNb2RpZmllZCA9IHRydWUsXG4gICAgZHJvcERvbUNvbnRlbnRMb2FkZWQgPSB0cnVlLFxuICBcbiAgICAvLyBuZWVkZWQgZm9yIHRoZSBpbm5lckhUTUwgaGVscGVyXG4gICAgbm90RnJvbUlubmVySFRNTEhlbHBlciA9IHRydWUsXG4gIFxuICAgIC8vIG9wdGlvbmFsbHkgZGVmaW5lZCBsYXRlciBvblxuICAgIG9uU3VidHJlZU1vZGlmaWVkLFxuICAgIGNhbGxET01BdHRyTW9kaWZpZWQsXG4gICAgZ2V0QXR0cmlidXRlc01pcnJvcixcbiAgICBvYnNlcnZlcixcbiAgICBvYnNlcnZlLFxuICBcbiAgICAvLyBiYXNlZCBvbiBzZXR0aW5nIHByb3RvdHlwZSBjYXBhYmlsaXR5XG4gICAgLy8gd2lsbCBjaGVjayBwcm90byBvciB0aGUgZXhwYW5kbyBhdHRyaWJ1dGVcbiAgICAvLyBpbiBvcmRlciB0byBzZXR1cCB0aGUgbm9kZSBvbmNlXG4gICAgcGF0Y2hJZk5vdEFscmVhZHksXG4gICAgcGF0Y2hcbiAgO1xuICBcbiAgLy8gb25seSBpZiBuZWVkZWRcbiAgaWYgKCEoUkVHSVNURVJfRUxFTUVOVCBpbiBkb2N1bWVudCkpIHtcbiAgXG4gICAgaWYgKHNQTyB8fCBoYXNQcm90bykge1xuICAgICAgICBwYXRjaElmTm90QWxyZWFkeSA9IGZ1bmN0aW9uIChub2RlLCBwcm90bykge1xuICAgICAgICAgIGlmICghaVBPLmNhbGwocHJvdG8sIG5vZGUpKSB7XG4gICAgICAgICAgICBzZXR1cE5vZGUobm9kZSwgcHJvdG8pO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcGF0Y2ggPSBzZXR1cE5vZGU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcGF0Y2hJZk5vdEFscmVhZHkgPSBmdW5jdGlvbiAobm9kZSwgcHJvdG8pIHtcbiAgICAgICAgICBpZiAoIW5vZGVbRVhQQU5ET19VSURdKSB7XG4gICAgICAgICAgICBub2RlW0VYUEFORE9fVUlEXSA9IE9iamVjdCh0cnVlKTtcbiAgICAgICAgICAgIHNldHVwTm9kZShub2RlLCBwcm90byk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBwYXRjaCA9IHBhdGNoSWZOb3RBbHJlYWR5O1xuICAgIH1cbiAgXG4gICAgaWYgKElFOCkge1xuICAgICAgZG9lc05vdFN1cHBvcnRET01BdHRyTW9kaWZpZWQgPSBmYWxzZTtcbiAgICAgIChmdW5jdGlvbiAoKXtcbiAgICAgICAgdmFyXG4gICAgICAgICAgZGVzY3JpcHRvciA9IGdPUEQoSFRNTEVsZW1lbnRQcm90b3R5cGUsIEFERF9FVkVOVF9MSVNURU5FUiksXG4gICAgICAgICAgYWRkRXZlbnRMaXN0ZW5lciA9IGRlc2NyaXB0b3IudmFsdWUsXG4gICAgICAgICAgcGF0Y2hlZFJlbW92ZUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICB2YXIgZSA9IG5ldyBDdXN0b21FdmVudChET01fQVRUUl9NT0RJRklFRCwge2J1YmJsZXM6IHRydWV9KTtcbiAgICAgICAgICAgIGUuYXR0ck5hbWUgPSBuYW1lO1xuICAgICAgICAgICAgZS5wcmV2VmFsdWUgPSBnZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKTtcbiAgICAgICAgICAgIGUubmV3VmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgZVtSRU1PVkFMXSA9IGUuYXR0ckNoYW5nZSA9IDI7XG4gICAgICAgICAgICByZW1vdmVBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKTtcbiAgICAgICAgICAgIGRpc3BhdGNoRXZlbnQuY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBhdGNoZWRTZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgICAgIHZhclxuICAgICAgICAgICAgICBoYWQgPSBoYXNBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKSxcbiAgICAgICAgICAgICAgb2xkID0gaGFkICYmIGdldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUpLFxuICAgICAgICAgICAgICBlID0gbmV3IEN1c3RvbUV2ZW50KERPTV9BVFRSX01PRElGSUVELCB7YnViYmxlczogdHJ1ZX0pXG4gICAgICAgICAgICA7XG4gICAgICAgICAgICBzZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgICAgICBlLmF0dHJOYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGUucHJldlZhbHVlID0gaGFkID8gb2xkIDogbnVsbDtcbiAgICAgICAgICAgIGUubmV3VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGlmIChoYWQpIHtcbiAgICAgICAgICAgICAgZVtNT0RJRklDQVRJT05dID0gZS5hdHRyQ2hhbmdlID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGVbQURESVRJT05dID0gZS5hdHRyQ2hhbmdlID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3BhdGNoRXZlbnQuY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uUHJvcGVydHlDaGFuZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgLy8ganNoaW50IGVxbnVsbDp0cnVlXG4gICAgICAgICAgICB2YXJcbiAgICAgICAgICAgICAgbm9kZSA9IGUuY3VycmVudFRhcmdldCxcbiAgICAgICAgICAgICAgc3VwZXJTZWNyZXQgPSBub2RlW0VYUEFORE9fVUlEXSxcbiAgICAgICAgICAgICAgcHJvcGVydHlOYW1lID0gZS5wcm9wZXJ0eU5hbWUsXG4gICAgICAgICAgICAgIGV2ZW50XG4gICAgICAgICAgICA7XG4gICAgICAgICAgICBpZiAoc3VwZXJTZWNyZXQuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkge1xuICAgICAgICAgICAgICBzdXBlclNlY3JldCA9IHN1cGVyU2VjcmV0W3Byb3BlcnR5TmFtZV07XG4gICAgICAgICAgICAgIGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KERPTV9BVFRSX01PRElGSUVELCB7YnViYmxlczogdHJ1ZX0pO1xuICAgICAgICAgICAgICBldmVudC5hdHRyTmFtZSA9IHN1cGVyU2VjcmV0Lm5hbWU7XG4gICAgICAgICAgICAgIGV2ZW50LnByZXZWYWx1ZSA9IHN1cGVyU2VjcmV0LnZhbHVlIHx8IG51bGw7XG4gICAgICAgICAgICAgIGV2ZW50Lm5ld1ZhbHVlID0gKHN1cGVyU2VjcmV0LnZhbHVlID0gbm9kZVtwcm9wZXJ0eU5hbWVdIHx8IG51bGwpO1xuICAgICAgICAgICAgICBpZiAoZXZlbnQucHJldlZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBldmVudFtBRERJVElPTl0gPSBldmVudC5hdHRyQ2hhbmdlID0gMDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBldmVudFtNT0RJRklDQVRJT05dID0gZXZlbnQuYXR0ckNoYW5nZSA9IDE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZGlzcGF0Y2hFdmVudC5jYWxsKG5vZGUsIGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIDtcbiAgICAgICAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uICh0eXBlLCBoYW5kbGVyLCBjYXB0dXJlKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdHlwZSA9PT0gRE9NX0FUVFJfTU9ESUZJRUQgJiZcbiAgICAgICAgICAgIHRoaXNbQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdICYmXG4gICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSAhPT0gcGF0Y2hlZFNldEF0dHJpYnV0ZVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhpc1tFWFBBTkRPX1VJRF0gPSB7XG4gICAgICAgICAgICAgIGNsYXNzTmFtZToge1xuICAgICAgICAgICAgICAgIG5hbWU6ICdjbGFzcycsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuY2xhc3NOYW1lXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSA9IHBhdGNoZWRTZXRBdHRyaWJ1dGU7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSA9IHBhdGNoZWRSZW1vdmVBdHRyaWJ1dGU7XG4gICAgICAgICAgICBhZGRFdmVudExpc3RlbmVyLmNhbGwodGhpcywgJ3Byb3BlcnR5Y2hhbmdlJywgb25Qcm9wZXJ0eUNoYW5nZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGFkZEV2ZW50TGlzdGVuZXIuY2FsbCh0aGlzLCB0eXBlLCBoYW5kbGVyLCBjYXB0dXJlKTtcbiAgICAgICAgfTtcbiAgICAgICAgZGVmaW5lUHJvcGVydHkoSFRNTEVsZW1lbnRQcm90b3R5cGUsIEFERF9FVkVOVF9MSVNURU5FUiwgZGVzY3JpcHRvcik7XG4gICAgICB9KCkpO1xuICAgIH0gZWxzZSBpZiAoIU11dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgIGRvY3VtZW50RWxlbWVudFtBRERfRVZFTlRfTElTVEVORVJdKERPTV9BVFRSX01PRElGSUVELCBET01BdHRyTW9kaWZpZWQpO1xuICAgICAgZG9jdW1lbnRFbGVtZW50LnNldEF0dHJpYnV0ZShFWFBBTkRPX1VJRCwgMSk7XG4gICAgICBkb2N1bWVudEVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKEVYUEFORE9fVUlEKTtcbiAgICAgIGlmIChkb2VzTm90U3VwcG9ydERPTUF0dHJNb2RpZmllZCkge1xuICAgICAgICBvblN1YnRyZWVNb2RpZmllZCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgdmFyXG4gICAgICAgICAgICBub2RlID0gdGhpcyxcbiAgICAgICAgICAgIG9sZEF0dHJpYnV0ZXMsXG4gICAgICAgICAgICBuZXdBdHRyaWJ1dGVzLFxuICAgICAgICAgICAga2V5XG4gICAgICAgICAgO1xuICAgICAgICAgIGlmIChub2RlID09PSBlLnRhcmdldCkge1xuICAgICAgICAgICAgb2xkQXR0cmlidXRlcyA9IG5vZGVbRVhQQU5ET19VSURdO1xuICAgICAgICAgICAgbm9kZVtFWFBBTkRPX1VJRF0gPSAobmV3QXR0cmlidXRlcyA9IGdldEF0dHJpYnV0ZXNNaXJyb3Iobm9kZSkpO1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gbmV3QXR0cmlidXRlcykge1xuICAgICAgICAgICAgICBpZiAoIShrZXkgaW4gb2xkQXR0cmlidXRlcykpIHtcbiAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgd2FzIGFkZGVkXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxET01BdHRyTW9kaWZpZWQoXG4gICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgICAgICAgIG9sZEF0dHJpYnV0ZXNba2V5XSxcbiAgICAgICAgICAgICAgICAgIG5ld0F0dHJpYnV0ZXNba2V5XSxcbiAgICAgICAgICAgICAgICAgIEFERElUSU9OXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChuZXdBdHRyaWJ1dGVzW2tleV0gIT09IG9sZEF0dHJpYnV0ZXNba2V5XSkge1xuICAgICAgICAgICAgICAgIC8vIGF0dHJpYnV0ZSB3YXMgY2hhbmdlZFxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsRE9NQXR0ck1vZGlmaWVkKFxuICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICBvbGRBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBuZXdBdHRyaWJ1dGVzW2tleV0sXG4gICAgICAgICAgICAgICAgICBNT0RJRklDQVRJT05cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjaGVja2luZyBpZiBpdCBoYXMgYmVlbiByZW1vdmVkXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBvbGRBdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgIGlmICghKGtleSBpbiBuZXdBdHRyaWJ1dGVzKSkge1xuICAgICAgICAgICAgICAgIC8vIGF0dHJpYnV0ZSByZW1vdmVkXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxET01BdHRyTW9kaWZpZWQoXG4gICAgICAgICAgICAgICAgICAyLFxuICAgICAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgICAgICAgIG9sZEF0dHJpYnV0ZXNba2V5XSxcbiAgICAgICAgICAgICAgICAgIG5ld0F0dHJpYnV0ZXNba2V5XSxcbiAgICAgICAgICAgICAgICAgIFJFTU9WQUxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBjYWxsRE9NQXR0ck1vZGlmaWVkID0gZnVuY3Rpb24gKFxuICAgICAgICAgIGF0dHJDaGFuZ2UsXG4gICAgICAgICAgY3VycmVudFRhcmdldCxcbiAgICAgICAgICBhdHRyTmFtZSxcbiAgICAgICAgICBwcmV2VmFsdWUsXG4gICAgICAgICAgbmV3VmFsdWUsXG4gICAgICAgICAgYWN0aW9uXG4gICAgICAgICkge1xuICAgICAgICAgIHZhciBlID0ge1xuICAgICAgICAgICAgYXR0ckNoYW5nZTogYXR0ckNoYW5nZSxcbiAgICAgICAgICAgIGN1cnJlbnRUYXJnZXQ6IGN1cnJlbnRUYXJnZXQsXG4gICAgICAgICAgICBhdHRyTmFtZTogYXR0ck5hbWUsXG4gICAgICAgICAgICBwcmV2VmFsdWU6IHByZXZWYWx1ZSxcbiAgICAgICAgICAgIG5ld1ZhbHVlOiBuZXdWYWx1ZVxuICAgICAgICAgIH07XG4gICAgICAgICAgZVthY3Rpb25dID0gYXR0ckNoYW5nZTtcbiAgICAgICAgICBvbkRPTUF0dHJNb2RpZmllZChlKTtcbiAgICAgICAgfTtcbiAgICAgICAgZ2V0QXR0cmlidXRlc01pcnJvciA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgZm9yICh2YXJcbiAgICAgICAgICAgIGF0dHIsIG5hbWUsXG4gICAgICAgICAgICByZXN1bHQgPSB7fSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXMgPSBub2RlLmF0dHJpYnV0ZXMsXG4gICAgICAgICAgICBpID0gMCwgbGVuZ3RoID0gYXR0cmlidXRlcy5sZW5ndGg7XG4gICAgICAgICAgICBpIDwgbGVuZ3RoOyBpKytcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGF0dHIgPSBhdHRyaWJ1dGVzW2ldO1xuICAgICAgICAgICAgbmFtZSA9IGF0dHIubmFtZTtcbiAgICAgICAgICAgIGlmIChuYW1lICE9PSAnc2V0QXR0cmlidXRlJykge1xuICAgICAgICAgICAgICByZXN1bHRbbmFtZV0gPSBhdHRyLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgXG4gICAgLy8gc2V0IGFzIGVudW1lcmFibGUsIHdyaXRhYmxlIGFuZCBjb25maWd1cmFibGVcbiAgICBkb2N1bWVudFtSRUdJU1RFUl9FTEVNRU5UXSA9IGZ1bmN0aW9uIHJlZ2lzdGVyRWxlbWVudCh0eXBlLCBvcHRpb25zKSB7XG4gICAgICB1cHBlclR5cGUgPSB0eXBlLnRvVXBwZXJDYXNlKCk7XG4gICAgICBpZiAoIXNldExpc3RlbmVyKSB7XG4gICAgICAgIC8vIG9ubHkgZmlyc3QgdGltZSBkb2N1bWVudC5yZWdpc3RlckVsZW1lbnQgaXMgdXNlZFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHNldCB0aGlzIGxpc3RlbmVyXG4gICAgICAgIC8vIHNldHRpbmcgaXQgYnkgZGVmYXVsdCBtaWdodCBzbG93IGRvd24gZm9yIG5vIHJlYXNvblxuICAgICAgICBzZXRMaXN0ZW5lciA9IHRydWU7XG4gICAgICAgIGlmIChNdXRhdGlvbk9ic2VydmVyKSB7XG4gICAgICAgICAgb2JzZXJ2ZXIgPSAoZnVuY3Rpb24oYXR0YWNoZWQsIGRldGFjaGVkKXtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGNoZWNrRW1BbGwobGlzdCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGxpc3QubGVuZ3RoOyBpIDwgbGVuZ3RoOyBjYWxsYmFjayhsaXN0W2krK10pKXt9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoZnVuY3Rpb24gKHJlY29yZHMpIHtcbiAgICAgICAgICAgICAgZm9yICh2YXJcbiAgICAgICAgICAgICAgICBjdXJyZW50LCBub2RlLCBuZXdWYWx1ZSxcbiAgICAgICAgICAgICAgICBpID0gMCwgbGVuZ3RoID0gcmVjb3Jkcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrK1xuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50ID0gcmVjb3Jkc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudC50eXBlID09PSAnY2hpbGRMaXN0Jykge1xuICAgICAgICAgICAgICAgICAgY2hlY2tFbUFsbChjdXJyZW50LmFkZGVkTm9kZXMsIGF0dGFjaGVkKTtcbiAgICAgICAgICAgICAgICAgIGNoZWNrRW1BbGwoY3VycmVudC5yZW1vdmVkTm9kZXMsIGRldGFjaGVkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgbm9kZSA9IGN1cnJlbnQudGFyZ2V0O1xuICAgICAgICAgICAgICAgICAgaWYgKG5vdEZyb21Jbm5lckhUTUxIZWxwZXIgJiZcbiAgICAgICAgICAgICAgICAgICAgICBub2RlW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXSAmJlxuICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuYXR0cmlidXRlTmFtZSAhPT0gJ3N0eWxlJykge1xuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZSA9IGdldEF0dHJpYnV0ZS5jYWxsKG5vZGUsIGN1cnJlbnQuYXR0cmlidXRlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gY3VycmVudC5vbGRWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgIG5vZGVbQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdKFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5vbGRWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfShleGVjdXRlQWN0aW9uKEFUVEFDSEVEKSwgZXhlY3V0ZUFjdGlvbihERVRBQ0hFRCkpKTtcbiAgICAgICAgICBvYnNlcnZlID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIG9ic2VydmVyLm9ic2VydmUoXG4gICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgc3VidHJlZTogdHJ1ZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBvYnNlcnZlKGRvY3VtZW50KTtcbiAgICAgICAgICBpZiAoYXR0YWNoU2hhZG93KSB7XG4gICAgICAgICAgICBIVE1MRWxlbWVudFByb3RvdHlwZS5hdHRhY2hTaGFkb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHJldHVybiBvYnNlcnZlKGF0dGFjaFNoYWRvdy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFzYXBRdWV1ZSA9IFtdO1xuICAgICAgICAgIGRvY3VtZW50W0FERF9FVkVOVF9MSVNURU5FUl0oJ0RPTU5vZGVJbnNlcnRlZCcsIG9uRE9NTm9kZShBVFRBQ0hFRCkpO1xuICAgICAgICAgIGRvY3VtZW50W0FERF9FVkVOVF9MSVNURU5FUl0oJ0RPTU5vZGVSZW1vdmVkJywgb25ET01Ob2RlKERFVEFDSEVEKSk7XG4gICAgICAgIH1cbiAgXG4gICAgICAgIGRvY3VtZW50W0FERF9FVkVOVF9MSVNURU5FUl0oRE9NX0NPTlRFTlRfTE9BREVELCBvblJlYWR5U3RhdGVDaGFuZ2UpO1xuICAgICAgICBkb2N1bWVudFtBRERfRVZFTlRfTElTVEVORVJdKCdyZWFkeXN0YXRlY2hhbmdlJywgb25SZWFkeVN0YXRlQ2hhbmdlKTtcbiAgXG4gICAgICAgIEhUTUxFbGVtZW50UHJvdG90eXBlLmNsb25lTm9kZSA9IGZ1bmN0aW9uIChkZWVwKSB7XG4gICAgICAgICAgdmFyXG4gICAgICAgICAgICBub2RlID0gY2xvbmVOb2RlLmNhbGwodGhpcywgISFkZWVwKSxcbiAgICAgICAgICAgIGkgPSBnZXRUeXBlSW5kZXgobm9kZSlcbiAgICAgICAgICA7XG4gICAgICAgICAgaWYgKC0xIDwgaSkgcGF0Y2gobm9kZSwgcHJvdG9zW2ldKTtcbiAgICAgICAgICBpZiAoZGVlcCkgbG9vcEFuZFNldHVwKG5vZGUucXVlcnlTZWxlY3RvckFsbChxdWVyeSkpO1xuICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICB9O1xuICAgICAgfVxuICBcbiAgICAgIGlmICgtMiA8IChcbiAgICAgICAgaW5kZXhPZi5jYWxsKHR5cGVzLCBQUkVGSVhfSVMgKyB1cHBlclR5cGUpICtcbiAgICAgICAgaW5kZXhPZi5jYWxsKHR5cGVzLCBQUkVGSVhfVEFHICsgdXBwZXJUeXBlKVxuICAgICAgKSkge1xuICAgICAgICB0aHJvd1R5cGVFcnJvcih0eXBlKTtcbiAgICAgIH1cbiAgXG4gICAgICBpZiAoIXZhbGlkTmFtZS50ZXN0KHVwcGVyVHlwZSkgfHwgLTEgPCBpbmRleE9mLmNhbGwoaW52YWxpZE5hbWVzLCB1cHBlclR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHR5cGUgJyArIHR5cGUgKyAnIGlzIGludmFsaWQnKTtcbiAgICAgIH1cbiAgXG4gICAgICB2YXJcbiAgICAgICAgY29uc3RydWN0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGV4dGVuZGluZyA/XG4gICAgICAgICAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50KG5vZGVOYW1lLCB1cHBlclR5cGUpIDpcbiAgICAgICAgICAgIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQobm9kZU5hbWUpO1xuICAgICAgICB9LFxuICAgICAgICBvcHQgPSBvcHRpb25zIHx8IE9QLFxuICAgICAgICBleHRlbmRpbmcgPSBoT1AuY2FsbChvcHQsIEVYVEVORFMpLFxuICAgICAgICBub2RlTmFtZSA9IGV4dGVuZGluZyA/IG9wdGlvbnNbRVhURU5EU10udG9VcHBlckNhc2UoKSA6IHVwcGVyVHlwZSxcbiAgICAgICAgdXBwZXJUeXBlLFxuICAgICAgICBpXG4gICAgICA7XG4gIFxuICAgICAgaWYgKGV4dGVuZGluZyAmJiAtMSA8IChcbiAgICAgICAgaW5kZXhPZi5jYWxsKHR5cGVzLCBQUkVGSVhfVEFHICsgbm9kZU5hbWUpXG4gICAgICApKSB7XG4gICAgICAgIHRocm93VHlwZUVycm9yKG5vZGVOYW1lKTtcbiAgICAgIH1cbiAgXG4gICAgICBpID0gdHlwZXMucHVzaCgoZXh0ZW5kaW5nID8gUFJFRklYX0lTIDogUFJFRklYX1RBRykgKyB1cHBlclR5cGUpIC0gMTtcbiAgXG4gICAgICBxdWVyeSA9IHF1ZXJ5LmNvbmNhdChcbiAgICAgICAgcXVlcnkubGVuZ3RoID8gJywnIDogJycsXG4gICAgICAgIGV4dGVuZGluZyA/IG5vZGVOYW1lICsgJ1tpcz1cIicgKyB0eXBlLnRvTG93ZXJDYXNlKCkgKyAnXCJdJyA6IG5vZGVOYW1lXG4gICAgICApO1xuICBcbiAgICAgIGNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IChcbiAgICAgICAgcHJvdG9zW2ldID0gaE9QLmNhbGwob3B0LCAncHJvdG90eXBlJykgP1xuICAgICAgICAgIG9wdC5wcm90b3R5cGUgOlxuICAgICAgICAgIGNyZWF0ZShIVE1MRWxlbWVudFByb3RvdHlwZSlcbiAgICAgICk7XG4gIFxuICAgICAgbG9vcEFuZFZlcmlmeShcbiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChxdWVyeSksXG4gICAgICAgIEFUVEFDSEVEXG4gICAgICApO1xuICBcbiAgICAgIHJldHVybiBjb25zdHJ1Y3RvcjtcbiAgICB9O1xuICBcbiAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50ID0gKHBhdGNoZWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gKGxvY2FsTmFtZSwgdHlwZUV4dGVuc2lvbikge1xuICAgICAgdmFyXG4gICAgICAgIGlzID0gZ2V0SXModHlwZUV4dGVuc2lvbiksXG4gICAgICAgIG5vZGUgPSBpcyA/XG4gICAgICAgICAgY3JlYXRlRWxlbWVudC5jYWxsKGRvY3VtZW50LCBsb2NhbE5hbWUsIHNlY29uZEFyZ3VtZW50KGlzKSkgOlxuICAgICAgICAgIGNyZWF0ZUVsZW1lbnQuY2FsbChkb2N1bWVudCwgbG9jYWxOYW1lKSxcbiAgICAgICAgbmFtZSA9ICcnICsgbG9jYWxOYW1lLFxuICAgICAgICBpID0gaW5kZXhPZi5jYWxsKFxuICAgICAgICAgIHR5cGVzLFxuICAgICAgICAgIChpcyA/IFBSRUZJWF9JUyA6IFBSRUZJWF9UQUcpICtcbiAgICAgICAgICAoaXMgfHwgbmFtZSkudG9VcHBlckNhc2UoKVxuICAgICAgICApLFxuICAgICAgICBzZXR1cCA9IC0xIDwgaVxuICAgICAgO1xuICAgICAgaWYgKGlzKSB7XG4gICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKCdpcycsIGlzID0gaXMudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGlmIChzZXR1cCkge1xuICAgICAgICAgIHNldHVwID0gaXNJblFTQShuYW1lLnRvVXBwZXJDYXNlKCksIGlzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbm90RnJvbUlubmVySFRNTEhlbHBlciA9ICFkb2N1bWVudC5jcmVhdGVFbGVtZW50LmlubmVySFRNTEhlbHBlcjtcbiAgICAgIGlmIChzZXR1cCkgcGF0Y2gobm9kZSwgcHJvdG9zW2ldKTtcbiAgICAgIHJldHVybiBub2RlO1xuICAgIH0pO1xuICBcbiAgfVxuICBcbiAgZnVuY3Rpb24gQVNBUCgpIHtcbiAgICB2YXIgcXVldWUgPSBhc2FwUXVldWUuc3BsaWNlKDAsIGFzYXBRdWV1ZS5sZW5ndGgpO1xuICAgIGFzYXBUaW1lciA9IDA7XG4gICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgcXVldWUuc2hpZnQoKS5jYWxsKFxuICAgICAgICBudWxsLCBxdWV1ZS5zaGlmdCgpXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gbG9vcEFuZFZlcmlmeShsaXN0LCBhY3Rpb24pIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gbGlzdC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmVyaWZ5QW5kU2V0dXBBbmRBY3Rpb24obGlzdFtpXSwgYWN0aW9uKTtcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGxvb3BBbmRTZXR1cChsaXN0KSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGxpc3QubGVuZ3RoLCBub2RlOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIG5vZGUgPSBsaXN0W2ldO1xuICAgICAgcGF0Y2gobm9kZSwgcHJvdG9zW2dldFR5cGVJbmRleChub2RlKV0pO1xuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gZXhlY3V0ZUFjdGlvbihhY3Rpb24pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIGlmIChpc1ZhbGlkTm9kZShub2RlKSkge1xuICAgICAgICB2ZXJpZnlBbmRTZXR1cEFuZEFjdGlvbihub2RlLCBhY3Rpb24pO1xuICAgICAgICBsb29wQW5kVmVyaWZ5KFxuICAgICAgICAgIG5vZGUucXVlcnlTZWxlY3RvckFsbChxdWVyeSksXG4gICAgICAgICAgYWN0aW9uXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gZ2V0VHlwZUluZGV4KHRhcmdldCkge1xuICAgIHZhclxuICAgICAgaXMgPSBnZXRBdHRyaWJ1dGUuY2FsbCh0YXJnZXQsICdpcycpLFxuICAgICAgbm9kZU5hbWUgPSB0YXJnZXQubm9kZU5hbWUudG9VcHBlckNhc2UoKSxcbiAgICAgIGkgPSBpbmRleE9mLmNhbGwoXG4gICAgICAgIHR5cGVzLFxuICAgICAgICBpcyA/XG4gICAgICAgICAgICBQUkVGSVhfSVMgKyBpcy50b1VwcGVyQ2FzZSgpIDpcbiAgICAgICAgICAgIFBSRUZJWF9UQUcgKyBub2RlTmFtZVxuICAgICAgKVxuICAgIDtcbiAgICByZXR1cm4gaXMgJiYgLTEgPCBpICYmICFpc0luUVNBKG5vZGVOYW1lLCBpcykgPyAtMSA6IGk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGlzSW5RU0EobmFtZSwgdHlwZSkge1xuICAgIHJldHVybiAtMSA8IHF1ZXJ5LmluZGV4T2YobmFtZSArICdbaXM9XCInICsgdHlwZSArICdcIl0nKTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gb25ET01BdHRyTW9kaWZpZWQoZSkge1xuICAgIHZhclxuICAgICAgbm9kZSA9IGUuY3VycmVudFRhcmdldCxcbiAgICAgIGF0dHJDaGFuZ2UgPSBlLmF0dHJDaGFuZ2UsXG4gICAgICBhdHRyTmFtZSA9IGUuYXR0ck5hbWUsXG4gICAgICB0YXJnZXQgPSBlLnRhcmdldCxcbiAgICAgIGFkZGl0aW9uID0gZVtBRERJVElPTl0gfHwgMixcbiAgICAgIHJlbW92YWwgPSBlW1JFTU9WQUxdIHx8IDNcbiAgICA7XG4gICAgaWYgKG5vdEZyb21Jbm5lckhUTUxIZWxwZXIgJiZcbiAgICAgICAgKCF0YXJnZXQgfHwgdGFyZ2V0ID09PSBub2RlKSAmJlxuICAgICAgICBub2RlW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXSAmJlxuICAgICAgICBhdHRyTmFtZSAhPT0gJ3N0eWxlJyAmJiAoXG4gICAgICAgICAgZS5wcmV2VmFsdWUgIT09IGUubmV3VmFsdWUgfHxcbiAgICAgICAgICAvLyBJRTksIElFMTAsIGFuZCBPcGVyYSAxMiBnb3RjaGFcbiAgICAgICAgICBlLm5ld1ZhbHVlID09PSAnJyAmJiAoXG4gICAgICAgICAgICBhdHRyQ2hhbmdlID09PSBhZGRpdGlvbiB8fFxuICAgICAgICAgICAgYXR0ckNoYW5nZSA9PT0gcmVtb3ZhbFxuICAgICAgICAgIClcbiAgICApKSB7XG4gICAgICBub2RlW0FUVFJJQlVURV9DSEFOR0VEX0NBTExCQUNLXShcbiAgICAgICAgYXR0ck5hbWUsXG4gICAgICAgIGF0dHJDaGFuZ2UgPT09IGFkZGl0aW9uID8gbnVsbCA6IGUucHJldlZhbHVlLFxuICAgICAgICBhdHRyQ2hhbmdlID09PSByZW1vdmFsID8gbnVsbCA6IGUubmV3VmFsdWVcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBvbkRPTU5vZGUoYWN0aW9uKSB7XG4gICAgdmFyIGV4ZWN1dG9yID0gZXhlY3V0ZUFjdGlvbihhY3Rpb24pO1xuICAgIHJldHVybiBmdW5jdGlvbiAoZSkge1xuICAgICAgYXNhcFF1ZXVlLnB1c2goZXhlY3V0b3IsIGUudGFyZ2V0KTtcbiAgICAgIGlmIChhc2FwVGltZXIpIGNsZWFyVGltZW91dChhc2FwVGltZXIpO1xuICAgICAgYXNhcFRpbWVyID0gc2V0VGltZW91dChBU0FQLCAxKTtcbiAgICB9O1xuICB9XG4gIFxuICBmdW5jdGlvbiBvblJlYWR5U3RhdGVDaGFuZ2UoZSkge1xuICAgIGlmIChkcm9wRG9tQ29udGVudExvYWRlZCkge1xuICAgICAgZHJvcERvbUNvbnRlbnRMb2FkZWQgPSBmYWxzZTtcbiAgICAgIGUuY3VycmVudFRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKERPTV9DT05URU5UX0xPQURFRCwgb25SZWFkeVN0YXRlQ2hhbmdlKTtcbiAgICB9XG4gICAgbG9vcEFuZFZlcmlmeShcbiAgICAgIChlLnRhcmdldCB8fCBkb2N1bWVudCkucXVlcnlTZWxlY3RvckFsbChxdWVyeSksXG4gICAgICBlLmRldGFpbCA9PT0gREVUQUNIRUQgPyBERVRBQ0hFRCA6IEFUVEFDSEVEXG4gICAgKTtcbiAgICBpZiAoSUU4KSBwdXJnZSgpO1xuICB9XG4gIFxuICBmdW5jdGlvbiBwYXRjaGVkU2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKSB7XG4gICAgLy8ganNoaW50IHZhbGlkdGhpczp0cnVlXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHNldEF0dHJpYnV0ZS5jYWxsKHNlbGYsIG5hbWUsIHZhbHVlKTtcbiAgICBvblN1YnRyZWVNb2RpZmllZC5jYWxsKHNlbGYsIHt0YXJnZXQ6IHNlbGZ9KTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gc2V0dXBOb2RlKG5vZGUsIHByb3RvKSB7XG4gICAgc2V0UHJvdG90eXBlKG5vZGUsIHByb3RvKTtcbiAgICBpZiAob2JzZXJ2ZXIpIHtcbiAgICAgIG9ic2VydmVyLm9ic2VydmUobm9kZSwgYXR0cmlidXRlc09ic2VydmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRvZXNOb3RTdXBwb3J0RE9NQXR0ck1vZGlmaWVkKSB7XG4gICAgICAgIG5vZGUuc2V0QXR0cmlidXRlID0gcGF0Y2hlZFNldEF0dHJpYnV0ZTtcbiAgICAgICAgbm9kZVtFWFBBTkRPX1VJRF0gPSBnZXRBdHRyaWJ1dGVzTWlycm9yKG5vZGUpO1xuICAgICAgICBub2RlW0FERF9FVkVOVF9MSVNURU5FUl0oRE9NX1NVQlRSRUVfTU9ESUZJRUQsIG9uU3VidHJlZU1vZGlmaWVkKTtcbiAgICAgIH1cbiAgICAgIG5vZGVbQUREX0VWRU5UX0xJU1RFTkVSXShET01fQVRUUl9NT0RJRklFRCwgb25ET01BdHRyTW9kaWZpZWQpO1xuICAgIH1cbiAgICBpZiAobm9kZVtDUkVBVEVEX0NBTExCQUNLXSAmJiBub3RGcm9tSW5uZXJIVE1MSGVscGVyKSB7XG4gICAgICBub2RlLmNyZWF0ZWQgPSB0cnVlO1xuICAgICAgbm9kZVtDUkVBVEVEX0NBTExCQUNLXSgpO1xuICAgICAgbm9kZS5jcmVhdGVkID0gZmFsc2U7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBwdXJnZSgpIHtcbiAgICBmb3IgKHZhclxuICAgICAgbm9kZSxcbiAgICAgIGkgPSAwLFxuICAgICAgbGVuZ3RoID0gdGFyZ2V0cy5sZW5ndGg7XG4gICAgICBpIDwgbGVuZ3RoOyBpKytcbiAgICApIHtcbiAgICAgIG5vZGUgPSB0YXJnZXRzW2ldO1xuICAgICAgaWYgKCFkb2N1bWVudEVsZW1lbnQuY29udGFpbnMobm9kZSkpIHtcbiAgICAgICAgbGVuZ3RoLS07XG4gICAgICAgIHRhcmdldHMuc3BsaWNlKGktLSwgMSk7XG4gICAgICAgIHZlcmlmeUFuZFNldHVwQW5kQWN0aW9uKG5vZGUsIERFVEFDSEVEKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHRocm93VHlwZUVycm9yKHR5cGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgJyArIHR5cGUgKyAnIHR5cGUgaXMgYWxyZWFkeSByZWdpc3RlcmVkJyk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHZlcmlmeUFuZFNldHVwQW5kQWN0aW9uKG5vZGUsIGFjdGlvbikge1xuICAgIHZhclxuICAgICAgZm4sXG4gICAgICBpID0gZ2V0VHlwZUluZGV4KG5vZGUpXG4gICAgO1xuICAgIGlmICgtMSA8IGkpIHtcbiAgICAgIHBhdGNoSWZOb3RBbHJlYWR5KG5vZGUsIHByb3Rvc1tpXSk7XG4gICAgICBpID0gMDtcbiAgICAgIGlmIChhY3Rpb24gPT09IEFUVEFDSEVEICYmICFub2RlW0FUVEFDSEVEXSkge1xuICAgICAgICBub2RlW0RFVEFDSEVEXSA9IGZhbHNlO1xuICAgICAgICBub2RlW0FUVEFDSEVEXSA9IHRydWU7XG4gICAgICAgIGkgPSAxO1xuICAgICAgICBpZiAoSUU4ICYmIGluZGV4T2YuY2FsbCh0YXJnZXRzLCBub2RlKSA8IDApIHtcbiAgICAgICAgICB0YXJnZXRzLnB1c2gobm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoYWN0aW9uID09PSBERVRBQ0hFRCAmJiAhbm9kZVtERVRBQ0hFRF0pIHtcbiAgICAgICAgbm9kZVtBVFRBQ0hFRF0gPSBmYWxzZTtcbiAgICAgICAgbm9kZVtERVRBQ0hFRF0gPSB0cnVlO1xuICAgICAgICBpID0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChpICYmIChmbiA9IG5vZGVbYWN0aW9uICsgQ0FMTEJBQ0tdKSkgZm4uY2FsbChub2RlKTtcbiAgICB9XG4gIH1cbiAgXG4gIFxuICBcbiAgLy8gVjEgaW4gZGEgSG91c2UhXG4gIGZ1bmN0aW9uIEN1c3RvbUVsZW1lbnRSZWdpc3RyeSgpIHt9XG4gIFxuICBDdXN0b21FbGVtZW50UmVnaXN0cnkucHJvdG90eXBlID0ge1xuICAgIGNvbnN0cnVjdG9yOiBDdXN0b21FbGVtZW50UmVnaXN0cnksXG4gICAgLy8gYSB3b3JrYXJvdW5kIGZvciB0aGUgc3R1YmJvcm4gV2ViS2l0XG4gICAgZGVmaW5lOiB1c2FibGVDdXN0b21FbGVtZW50cyA/XG4gICAgICBmdW5jdGlvbiAobmFtZSwgQ2xhc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgICAgICBDRVJEZWZpbmUobmFtZSwgQ2xhc3MsIG9wdGlvbnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBOQU1FID0gbmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgIGNvbnN0cnVjdG9yc1tOQU1FXSA9IHtcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiBDbGFzcyxcbiAgICAgICAgICAgIGNyZWF0ZTogW05BTUVdXG4gICAgICAgICAgfTtcbiAgICAgICAgICBub2RlTmFtZXMuc2V0KENsYXNzLCBOQU1FKTtcbiAgICAgICAgICBjdXN0b21FbGVtZW50cy5kZWZpbmUobmFtZSwgQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9IDpcbiAgICAgIENFUkRlZmluZSxcbiAgICBnZXQ6IHVzYWJsZUN1c3RvbUVsZW1lbnRzID9cbiAgICAgIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiBjdXN0b21FbGVtZW50cy5nZXQobmFtZSkgfHwgZ2V0KG5hbWUpO1xuICAgICAgfSA6XG4gICAgICBnZXQsXG4gICAgd2hlbkRlZmluZWQ6IHVzYWJsZUN1c3RvbUVsZW1lbnRzID9cbiAgICAgIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgIGN1c3RvbUVsZW1lbnRzLndoZW5EZWZpbmVkKG5hbWUpLFxuICAgICAgICAgIHdoZW5EZWZpbmVkKG5hbWUpXG4gICAgICAgIF0pO1xuICAgICAgfSA6XG4gICAgICB3aGVuRGVmaW5lZFxuICB9O1xuICBcbiAgZnVuY3Rpb24gQ0VSRGVmaW5lKG5hbWUsIENsYXNzLCBvcHRpb25zKSB7XG4gICAgdmFyXG4gICAgICBpcyA9IG9wdGlvbnMgJiYgb3B0aW9uc1tFWFRFTkRTXSB8fCAnJyxcbiAgICAgIENQcm90byA9IENsYXNzLnByb3RvdHlwZSxcbiAgICAgIHByb3RvID0gY3JlYXRlKENQcm90byksXG4gICAgICBhdHRyaWJ1dGVzID0gQ2xhc3Mub2JzZXJ2ZWRBdHRyaWJ1dGVzIHx8IGVtcHR5LFxuICAgICAgZGVmaW5pdGlvbiA9IHtwcm90b3R5cGU6IHByb3RvfVxuICAgIDtcbiAgICAvLyBUT0RPOiBpcyB0aGlzIG5lZWRlZCBhdCBhbGwgc2luY2UgaXQncyBpbmhlcml0ZWQ/XG4gICAgLy8gZGVmaW5lUHJvcGVydHkocHJvdG8sICdjb25zdHJ1Y3RvcicsIHt2YWx1ZTogQ2xhc3N9KTtcbiAgICBzYWZlUHJvcGVydHkocHJvdG8sIENSRUFURURfQ0FMTEJBQ0ssIHtcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoanVzdENyZWF0ZWQpIGp1c3RDcmVhdGVkID0gZmFsc2U7XG4gICAgICAgICAgZWxzZSBpZiAoIXRoaXNbRFJFQ0VWMV0pIHtcbiAgICAgICAgICAgIHRoaXNbRFJFQ0VWMV0gPSB0cnVlO1xuICAgICAgICAgICAgbmV3IENsYXNzKHRoaXMpO1xuICAgICAgICAgICAgaWYgKENQcm90b1tDUkVBVEVEX0NBTExCQUNLXSlcbiAgICAgICAgICAgICAgQ1Byb3RvW0NSRUFURURfQ0FMTEJBQ0tdLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB2YXIgaW5mbyA9IGNvbnN0cnVjdG9yc1tub2RlTmFtZXMuZ2V0KENsYXNzKV07XG4gICAgICAgICAgICBpZiAoIXVzYWJsZUN1c3RvbUVsZW1lbnRzIHx8IGluZm8uY3JlYXRlLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgbm90aWZ5QXR0cmlidXRlcyh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgc2FmZVByb3BlcnR5KHByb3RvLCBBVFRSSUJVVEVfQ0hBTkdFRF9DQUxMQkFDSywge1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGlmICgtMSA8IGluZGV4T2YuY2FsbChhdHRyaWJ1dGVzLCBuYW1lKSlcbiAgICAgICAgICBDUHJvdG9bQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKENQcm90b1tDT05ORUNURURfQ0FMTEJBQ0tdKSB7XG4gICAgICBzYWZlUHJvcGVydHkocHJvdG8sIEFUVEFDSEVEX0NBTExCQUNLLCB7XG4gICAgICAgIHZhbHVlOiBDUHJvdG9bQ09OTkVDVEVEX0NBTExCQUNLXVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChDUHJvdG9bRElTQ09OTkVDVEVEX0NBTExCQUNLXSkge1xuICAgICAgc2FmZVByb3BlcnR5KHByb3RvLCBERVRBQ0hFRF9DQUxMQkFDSywge1xuICAgICAgICB2YWx1ZTogQ1Byb3RvW0RJU0NPTk5FQ1RFRF9DQUxMQkFDS11cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoaXMpIGRlZmluaXRpb25bRVhURU5EU10gPSBpcztcbiAgICBuYW1lID0gbmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIGNvbnN0cnVjdG9yc1tuYW1lXSA9IHtcbiAgICAgIGNvbnN0cnVjdG9yOiBDbGFzcyxcbiAgICAgIGNyZWF0ZTogaXMgPyBbaXMsIHNlY29uZEFyZ3VtZW50KG5hbWUpXSA6IFtuYW1lXVxuICAgIH07XG4gICAgbm9kZU5hbWVzLnNldChDbGFzcywgbmFtZSk7XG4gICAgZG9jdW1lbnRbUkVHSVNURVJfRUxFTUVOVF0obmFtZS50b0xvd2VyQ2FzZSgpLCBkZWZpbml0aW9uKTtcbiAgICB3aGVuRGVmaW5lZChuYW1lKTtcbiAgICB3YWl0aW5nTGlzdFtuYW1lXS5yKCk7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGdldChuYW1lKSB7XG4gICAgdmFyIGluZm8gPSBjb25zdHJ1Y3RvcnNbbmFtZS50b1VwcGVyQ2FzZSgpXTtcbiAgICByZXR1cm4gaW5mbyAmJiBpbmZvLmNvbnN0cnVjdG9yO1xuICB9XG4gIFxuICBmdW5jdGlvbiBnZXRJcyhvcHRpb25zKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJyA/XG4gICAgICAgIG9wdGlvbnMgOiAob3B0aW9ucyAmJiBvcHRpb25zLmlzIHx8ICcnKTtcbiAgfVxuICBcbiAgZnVuY3Rpb24gbm90aWZ5QXR0cmlidXRlcyhzZWxmKSB7XG4gICAgdmFyXG4gICAgICBjYWxsYmFjayA9IHNlbGZbQVRUUklCVVRFX0NIQU5HRURfQ0FMTEJBQ0tdLFxuICAgICAgYXR0cmlidXRlcyA9IGNhbGxiYWNrID8gc2VsZi5hdHRyaWJ1dGVzIDogZW1wdHksXG4gICAgICBpID0gYXR0cmlidXRlcy5sZW5ndGgsXG4gICAgICBhdHRyaWJ1dGVcbiAgICA7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgYXR0cmlidXRlID0gIGF0dHJpYnV0ZXNbaV07IC8vIHx8IGF0dHJpYnV0ZXMuaXRlbShpKTtcbiAgICAgIGNhbGxiYWNrLmNhbGwoXG4gICAgICAgIHNlbGYsXG4gICAgICAgIGF0dHJpYnV0ZS5uYW1lIHx8IGF0dHJpYnV0ZS5ub2RlTmFtZSxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgYXR0cmlidXRlLnZhbHVlIHx8IGF0dHJpYnV0ZS5ub2RlVmFsdWVcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiB3aGVuRGVmaW5lZChuYW1lKSB7XG4gICAgbmFtZSA9IG5hbWUudG9VcHBlckNhc2UoKTtcbiAgICBpZiAoIShuYW1lIGluIHdhaXRpbmdMaXN0KSkge1xuICAgICAgd2FpdGluZ0xpc3RbbmFtZV0gPSB7fTtcbiAgICAgIHdhaXRpbmdMaXN0W25hbWVdLnAgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICB3YWl0aW5nTGlzdFtuYW1lXS5yID0gcmVzb2x2ZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gd2FpdGluZ0xpc3RbbmFtZV0ucDtcbiAgfVxuICBcbiAgZnVuY3Rpb24gcG9seWZpbGxWMSgpIHtcbiAgICBpZiAoY3VzdG9tRWxlbWVudHMpIGRlbGV0ZSB3aW5kb3cuY3VzdG9tRWxlbWVudHM7XG4gICAgZGVmaW5lUHJvcGVydHkod2luZG93LCAnY3VzdG9tRWxlbWVudHMnLCB7XG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogbmV3IEN1c3RvbUVsZW1lbnRSZWdpc3RyeSgpXG4gICAgfSk7XG4gICAgZGVmaW5lUHJvcGVydHkod2luZG93LCAnQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5Jywge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgdmFsdWU6IEN1c3RvbUVsZW1lbnRSZWdpc3RyeVxuICAgIH0pO1xuICAgIGZvciAodmFyXG4gICAgICBwYXRjaENsYXNzID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIENsYXNzID0gd2luZG93W25hbWVdO1xuICAgICAgICBpZiAoQ2xhc3MpIHtcbiAgICAgICAgICB3aW5kb3dbbmFtZV0gPSBmdW5jdGlvbiBDdXN0b21FbGVtZW50c1YxKHNlbGYpIHtcbiAgICAgICAgICAgIHZhciBpbmZvLCBpc05hdGl2ZTtcbiAgICAgICAgICAgIGlmICghc2VsZikgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoIXNlbGZbRFJFQ0VWMV0pIHtcbiAgICAgICAgICAgICAganVzdENyZWF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBpbmZvID0gY29uc3RydWN0b3JzW25vZGVOYW1lcy5nZXQoc2VsZi5jb25zdHJ1Y3RvcildO1xuICAgICAgICAgICAgICBpc05hdGl2ZSA9IHVzYWJsZUN1c3RvbUVsZW1lbnRzICYmIGluZm8uY3JlYXRlLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgICAgICAgc2VsZiA9IGlzTmF0aXZlID9cbiAgICAgICAgICAgICAgICBSZWZsZWN0LmNvbnN0cnVjdChDbGFzcywgZW1wdHksIGluZm8uY29uc3RydWN0b3IpIDpcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50LmFwcGx5KGRvY3VtZW50LCBpbmZvLmNyZWF0ZSk7XG4gICAgICAgICAgICAgIHNlbGZbRFJFQ0VWMV0gPSB0cnVlO1xuICAgICAgICAgICAgICBqdXN0Q3JlYXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICBpZiAoIWlzTmF0aXZlKSBub3RpZnlBdHRyaWJ1dGVzKHNlbGYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgfTtcbiAgICAgICAgICB3aW5kb3dbbmFtZV0ucHJvdG90eXBlID0gQ2xhc3MucHJvdG90eXBlO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSB3aW5kb3dbbmFtZV07XG4gICAgICAgICAgfSBjYXRjaChXZWJLaXQpIHtcbiAgICAgICAgICAgIGZpeEdldENsYXNzID0gdHJ1ZTtcbiAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KENsYXNzLCBEUkVDRVYxLCB7dmFsdWU6IHdpbmRvd1tuYW1lXX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIENsYXNzZXMgPSBodG1sQ2xhc3MuZ2V0KC9eSFRNTFtBLVpdKlthLXpdLyksXG4gICAgICBpID0gQ2xhc3Nlcy5sZW5ndGg7XG4gICAgICBpLS07XG4gICAgICBwYXRjaENsYXNzKENsYXNzZXNbaV0pXG4gICAgKSB7fVxuICAgIChkb2N1bWVudC5jcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gKG5hbWUsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBpcyA9IGdldElzKG9wdGlvbnMpO1xuICAgICAgcmV0dXJuIGlzID9cbiAgICAgICAgcGF0Y2hlZENyZWF0ZUVsZW1lbnQuY2FsbCh0aGlzLCBuYW1lLCBzZWNvbmRBcmd1bWVudChpcykpIDpcbiAgICAgICAgcGF0Y2hlZENyZWF0ZUVsZW1lbnQuY2FsbCh0aGlzLCBuYW1lKTtcbiAgICB9KTtcbiAgfVxuICBcbiAgLy8gaWYgY3VzdG9tRWxlbWVudHMgaXMgbm90IHRoZXJlIGF0IGFsbFxuICBpZiAoIWN1c3RvbUVsZW1lbnRzKSBwb2x5ZmlsbFYxKCk7XG4gIGVsc2Uge1xuICAgIC8vIGlmIGF2YWlsYWJsZSB0ZXN0IGV4dGVuZHMgd29yayBhcyBleHBlY3RlZFxuICAgIHRyeSB7XG4gICAgICAoZnVuY3Rpb24gKERSRSwgb3B0aW9ucywgbmFtZSkge1xuICAgICAgICBvcHRpb25zW0VYVEVORFNdID0gJ2EnO1xuICAgICAgICBEUkUucHJvdG90eXBlID0gY3JlYXRlKEhUTUxBbmNob3JFbGVtZW50LnByb3RvdHlwZSk7XG4gICAgICAgIERSRS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBEUkU7XG4gICAgICAgIHdpbmRvdy5jdXN0b21FbGVtZW50cy5kZWZpbmUobmFtZSwgRFJFLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGdldEF0dHJpYnV0ZS5jYWxsKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnLCB7aXM6IG5hbWV9KSwgJ2lzJykgIT09IG5hbWUgfHxcbiAgICAgICAgICAodXNhYmxlQ3VzdG9tRWxlbWVudHMgJiYgZ2V0QXR0cmlidXRlLmNhbGwobmV3IERSRSgpLCAnaXMnKSAhPT0gbmFtZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgb3B0aW9ucztcbiAgICAgICAgfVxuICAgICAgfShcbiAgICAgICAgZnVuY3Rpb24gRFJFKCkge1xuICAgICAgICAgIHJldHVybiBSZWZsZWN0LmNvbnN0cnVjdChIVE1MQW5jaG9yRWxlbWVudCwgW10sIERSRSk7XG4gICAgICAgIH0sXG4gICAgICAgIHt9LFxuICAgICAgICAnZG9jdW1lbnQtcmVnaXN0ZXItZWxlbWVudC1hJ1xuICAgICAgKSk7XG4gICAgfSBjYXRjaChvX08pIHtcbiAgICAgIC8vIG9yIGZvcmNlIHRoZSBwb2x5ZmlsbCBpZiBub3RcbiAgICAgIC8vIGFuZCBrZWVwIGludGVybmFsIG9yaWdpbmFsIHJlZmVyZW5jZVxuICAgICAgcG9seWZpbGxWMSgpO1xuICAgIH1cbiAgfVxuICBcbiAgdHJ5IHtcbiAgICBjcmVhdGVFbGVtZW50LmNhbGwoZG9jdW1lbnQsICdhJywgJ2EnKTtcbiAgfSBjYXRjaChGaXJlRm94KSB7XG4gICAgc2Vjb25kQXJndW1lbnQgPSBmdW5jdGlvbiAoaXMpIHtcbiAgICAgIHJldHVybiB7aXM6IGlzfTtcbiAgICB9O1xuICB9XG4gIFxufSh3aW5kb3cpKTtcbiIsIjsoZnVuY3Rpb24gKCkge1xuXHQndXNlIHN0cmljdCc7XG5cblx0LyoqXG5cdCAqIEBwcmVzZXJ2ZSBGYXN0Q2xpY2s6IHBvbHlmaWxsIHRvIHJlbW92ZSBjbGljayBkZWxheXMgb24gYnJvd3NlcnMgd2l0aCB0b3VjaCBVSXMuXG5cdCAqXG5cdCAqIEBjb2RpbmdzdGFuZGFyZCBmdGxhYnMtanN2MlxuXHQgKiBAY29weXJpZ2h0IFRoZSBGaW5hbmNpYWwgVGltZXMgTGltaXRlZCBbQWxsIFJpZ2h0cyBSZXNlcnZlZF1cblx0ICogQGxpY2Vuc2UgTUlUIExpY2Vuc2UgKHNlZSBMSUNFTlNFLnR4dClcblx0ICovXG5cblx0Lypqc2xpbnQgYnJvd3Nlcjp0cnVlLCBub2RlOnRydWUqL1xuXHQvKmdsb2JhbCBkZWZpbmUsIEV2ZW50LCBOb2RlKi9cblxuXG5cdC8qKlxuXHQgKiBJbnN0YW50aWF0ZSBmYXN0LWNsaWNraW5nIGxpc3RlbmVycyBvbiB0aGUgc3BlY2lmaWVkIGxheWVyLlxuXHQgKlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHtFbGVtZW50fSBsYXllciBUaGUgbGF5ZXIgdG8gbGlzdGVuIG9uXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHRzXG5cdCAqL1xuXHRmdW5jdGlvbiBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpIHtcblx0XHR2YXIgb2xkT25DbGljaztcblxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciBhIGNsaWNrIGlzIGN1cnJlbnRseSBiZWluZyB0cmFja2VkLlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgYm9vbGVhblxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXG5cblx0XHQvKipcblx0XHQgKiBUaW1lc3RhbXAgZm9yIHdoZW4gY2xpY2sgdHJhY2tpbmcgc3RhcnRlZC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gMDtcblxuXG5cdFx0LyoqXG5cdFx0ICogVGhlIGVsZW1lbnQgYmVpbmcgdHJhY2tlZCBmb3IgYSBjbGljay5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIEV2ZW50VGFyZ2V0XG5cdFx0ICovXG5cdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblxuXG5cdFx0LyoqXG5cdFx0ICogWC1jb29yZGluYXRlIG9mIHRvdWNoIHN0YXJ0IGV2ZW50LlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50b3VjaFN0YXJ0WCA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFktY29vcmRpbmF0ZSBvZiB0b3VjaCBzdGFydCBldmVudC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudG91Y2hTdGFydFkgPSAwO1xuXG5cblx0XHQvKipcblx0XHQgKiBJRCBvZiB0aGUgbGFzdCB0b3VjaCwgcmV0cmlldmVkIGZyb20gVG91Y2guaWRlbnRpZmllci5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMubGFzdFRvdWNoSWRlbnRpZmllciA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRvdWNobW92ZSBib3VuZGFyeSwgYmV5b25kIHdoaWNoIGEgY2xpY2sgd2lsbCBiZSBjYW5jZWxsZWQuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRvdWNoQm91bmRhcnkgPSBvcHRpb25zLnRvdWNoQm91bmRhcnkgfHwgMTA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBGYXN0Q2xpY2sgbGF5ZXIuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBFbGVtZW50XG5cdFx0ICovXG5cdFx0dGhpcy5sYXllciA9IGxheWVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG1pbmltdW0gdGltZSBiZXR3ZWVuIHRhcCh0b3VjaHN0YXJ0IGFuZCB0b3VjaGVuZCkgZXZlbnRzXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRhcERlbGF5ID0gb3B0aW9ucy50YXBEZWxheSB8fCAyMDA7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbWF4aW11bSB0aW1lIGZvciBhIHRhcFxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50YXBUaW1lb3V0ID0gb3B0aW9ucy50YXBUaW1lb3V0IHx8IDcwMDtcblxuXHRcdGlmIChGYXN0Q2xpY2subm90TmVlZGVkKGxheWVyKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFNvbWUgb2xkIHZlcnNpb25zIG9mIEFuZHJvaWQgZG9uJ3QgaGF2ZSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZFxuXHRcdGZ1bmN0aW9uIGJpbmQobWV0aG9kLCBjb250ZXh0KSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiBtZXRob2QuYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTsgfTtcblx0XHR9XG5cblxuXHRcdHZhciBtZXRob2RzID0gWydvbk1vdXNlJywgJ29uQ2xpY2snLCAnb25Ub3VjaFN0YXJ0JywgJ29uVG91Y2hNb3ZlJywgJ29uVG91Y2hFbmQnLCAnb25Ub3VjaENhbmNlbCddO1xuXHRcdHZhciBjb250ZXh0ID0gdGhpcztcblx0XHRmb3IgKHZhciBpID0gMCwgbCA9IG1ldGhvZHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG5cdFx0XHRjb250ZXh0W21ldGhvZHNbaV1dID0gYmluZChjb250ZXh0W21ldGhvZHNbaV1dLCBjb250ZXh0KTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdXAgZXZlbnQgaGFuZGxlcnMgYXMgcmVxdWlyZWRcblx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdH1cblxuXHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5vbkNsaWNrLCB0cnVlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5vblRvdWNoU3RhcnQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLm9uVG91Y2hNb3ZlLCBmYWxzZSk7XG5cdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLm9uVG91Y2hFbmQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMub25Ub3VjaENhbmNlbCwgZmFsc2UpO1xuXG5cdFx0Ly8gSGFjayBpcyByZXF1aXJlZCBmb3IgYnJvd3NlcnMgdGhhdCBkb24ndCBzdXBwb3J0IEV2ZW50I3N0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiAoZS5nLiBBbmRyb2lkIDIpXG5cdFx0Ly8gd2hpY2ggaXMgaG93IEZhc3RDbGljayBub3JtYWxseSBzdG9wcyBjbGljayBldmVudHMgYnViYmxpbmcgdG8gY2FsbGJhY2tzIHJlZ2lzdGVyZWQgb24gdGhlIEZhc3RDbGlja1xuXHRcdC8vIGxheWVyIHdoZW4gdGhleSBhcmUgY2FuY2VsbGVkLlxuXHRcdGlmICghRXZlbnQucHJvdG90eXBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbikge1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBybXYgPSBOb2RlLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdHJtdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCBjYWxsYmFjaywgY2FwdHVyZSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cm12LmNhbGwobGF5ZXIsIHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBhZHYgPSBOb2RlLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdGFkdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCAoY2FsbGJhY2suaGlqYWNrZWQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRcdFx0aWYgKCFldmVudC5wcm9wYWdhdGlvblN0b3BwZWQpIHtcblx0XHRcdFx0XHRcdFx0Y2FsbGJhY2soZXZlbnQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pLCBjYXB0dXJlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhZHYuY2FsbChsYXllciwgdHlwZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIElmIGEgaGFuZGxlciBpcyBhbHJlYWR5IGRlY2xhcmVkIGluIHRoZSBlbGVtZW50J3Mgb25jbGljayBhdHRyaWJ1dGUsIGl0IHdpbGwgYmUgZmlyZWQgYmVmb3JlXG5cdFx0Ly8gRmFzdENsaWNrJ3Mgb25DbGljayBoYW5kbGVyLiBGaXggdGhpcyBieSBwdWxsaW5nIG91dCB0aGUgdXNlci1kZWZpbmVkIGhhbmRsZXIgZnVuY3Rpb24gYW5kXG5cdFx0Ly8gYWRkaW5nIGl0IGFzIGxpc3RlbmVyLlxuXHRcdGlmICh0eXBlb2YgbGF5ZXIub25jbGljayA9PT0gJ2Z1bmN0aW9uJykge1xuXG5cdFx0XHQvLyBBbmRyb2lkIGJyb3dzZXIgb24gYXQgbGVhc3QgMy4yIHJlcXVpcmVzIGEgbmV3IHJlZmVyZW5jZSB0byB0aGUgZnVuY3Rpb24gaW4gbGF5ZXIub25jbGlja1xuXHRcdFx0Ly8gLSB0aGUgb2xkIG9uZSB3b24ndCB3b3JrIGlmIHBhc3NlZCB0byBhZGRFdmVudExpc3RlbmVyIGRpcmVjdGx5LlxuXHRcdFx0b2xkT25DbGljayA9IGxheWVyLm9uY2xpY2s7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdG9sZE9uQ2xpY2soZXZlbnQpO1xuXHRcdFx0fSwgZmFsc2UpO1xuXHRcdFx0bGF5ZXIub25jbGljayA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCogV2luZG93cyBQaG9uZSA4LjEgZmFrZXMgdXNlciBhZ2VudCBzdHJpbmcgdG8gbG9vayBsaWtlIEFuZHJvaWQgYW5kIGlQaG9uZS5cblx0KlxuXHQqIEB0eXBlIGJvb2xlYW5cblx0Ki9cblx0dmFyIGRldmljZUlzV2luZG93c1Bob25lID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwiV2luZG93cyBQaG9uZVwiKSA+PSAwO1xuXG5cdC8qKlxuXHQgKiBBbmRyb2lkIHJlcXVpcmVzIGV4Y2VwdGlvbnMuXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0FuZHJvaWQgPSBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0FuZHJvaWQnKSA+IDAgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyByZXF1aXJlcyBleGNlcHRpb25zLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1MgPSAvaVAoYWR8aG9uZXxvZCkvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA0IHJlcXVpcmVzIGFuIGV4Y2VwdGlvbiBmb3Igc2VsZWN0IGVsZW1lbnRzLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1M0ID0gZGV2aWNlSXNJT1MgJiYgKC9PUyA0X1xcZChfXFxkKT8vKS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA2LjAtNy4qIHJlcXVpcmVzIHRoZSB0YXJnZXQgZWxlbWVudCB0byBiZSBtYW51YWxseSBkZXJpdmVkXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0lPU1dpdGhCYWRUYXJnZXQgPSBkZXZpY2VJc0lPUyAmJiAoL09TIFs2LTddX1xcZC8pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cblx0LyoqXG5cdCAqIEJsYWNrQmVycnkgcmVxdWlyZXMgZXhjZXB0aW9ucy5cblx0ICpcblx0ICogQHR5cGUgYm9vbGVhblxuXHQgKi9cblx0dmFyIGRldmljZUlzQmxhY2tCZXJyeTEwID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdCQjEwJykgPiAwO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmUgd2hldGhlciBhIGdpdmVuIGVsZW1lbnQgcmVxdWlyZXMgYSBuYXRpdmUgY2xpY2suXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IG5lZWRzIGEgbmF0aXZlIGNsaWNrXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzQ2xpY2sgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cblx0XHQvLyBEb24ndCBzZW5kIGEgc3ludGhldGljIGNsaWNrIHRvIGRpc2FibGVkIGlucHV0cyAoaXNzdWUgIzYyKVxuXHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRjYXNlICd0ZXh0YXJlYSc6XG5cdFx0XHRpZiAodGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdpbnB1dCc6XG5cblx0XHRcdC8vIEZpbGUgaW5wdXRzIG5lZWQgcmVhbCBjbGlja3Mgb24gaU9TIDYgZHVlIHRvIGEgYnJvd3NlciBidWcgKGlzc3VlICM2OClcblx0XHRcdGlmICgoZGV2aWNlSXNJT1MgJiYgdGFyZ2V0LnR5cGUgPT09ICdmaWxlJykgfHwgdGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdsYWJlbCc6XG5cdFx0Y2FzZSAnaWZyYW1lJzogLy8gaU9TOCBob21lc2NyZWVuIGFwcHMgY2FuIHByZXZlbnQgZXZlbnRzIGJ1YmJsaW5nIGludG8gZnJhbWVzXG5cdFx0Y2FzZSAndmlkZW8nOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICgvXFxibmVlZHNjbGlja1xcYi8pLnRlc3QodGFyZ2V0LmNsYXNzTmFtZSk7XG5cdH07XG5cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lIHdoZXRoZXIgYSBnaXZlbiBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBjbGljayBpbnRvIGVsZW1lbnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBuYXRpdmUgY2xpY2suXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzRm9jdXMgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cdFx0Y2FzZSAndGV4dGFyZWEnOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRcdHJldHVybiAhZGV2aWNlSXNBbmRyb2lkO1xuXHRcdGNhc2UgJ2lucHV0Jzpcblx0XHRcdHN3aXRjaCAodGFyZ2V0LnR5cGUpIHtcblx0XHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0XHRjYXNlICdjaGVja2JveCc6XG5cdFx0XHRjYXNlICdmaWxlJzpcblx0XHRcdGNhc2UgJ2ltYWdlJzpcblx0XHRcdGNhc2UgJ3JhZGlvJzpcblx0XHRcdGNhc2UgJ3N1Ym1pdCc6XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTm8gcG9pbnQgaW4gYXR0ZW1wdGluZyB0byBmb2N1cyBkaXNhYmxlZCBpbnB1dHNcblx0XHRcdHJldHVybiAhdGFyZ2V0LmRpc2FibGVkICYmICF0YXJnZXQucmVhZE9ubHk7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHJldHVybiAoL1xcYm5lZWRzZm9jdXNcXGIvKS50ZXN0KHRhcmdldC5jbGFzc05hbWUpO1xuXHRcdH1cblx0fTtcblxuXG5cdC8qKlxuXHQgKiBTZW5kIGEgY2xpY2sgZXZlbnQgdG8gdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50VGFyZ2V0fEVsZW1lbnR9IHRhcmdldEVsZW1lbnRcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuc2VuZENsaWNrID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCwgZXZlbnQpIHtcblx0XHR2YXIgY2xpY2tFdmVudCwgdG91Y2g7XG5cblx0XHQvLyBPbiBzb21lIEFuZHJvaWQgZGV2aWNlcyBhY3RpdmVFbGVtZW50IG5lZWRzIHRvIGJlIGJsdXJyZWQgb3RoZXJ3aXNlIHRoZSBzeW50aGV0aWMgY2xpY2sgd2lsbCBoYXZlIG5vIGVmZmVjdCAoIzI0KVxuXHRcdGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IHRhcmdldEVsZW1lbnQpIHtcblx0XHRcdGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuXHRcdH1cblxuXHRcdHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG5cblx0XHQvLyBTeW50aGVzaXplIGEgY2xpY2sgZXZlbnQsIHdpdGggYW4gZXh0cmEgYXR0cmlidXRlIHNvIGl0IGNhbiBiZSB0cmFja2VkXG5cdFx0Y2xpY2tFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuXHRcdGNsaWNrRXZlbnQuaW5pdE1vdXNlRXZlbnQodGhpcy5kZXRlcm1pbmVFdmVudFR5cGUodGFyZ2V0RWxlbWVudCksIHRydWUsIHRydWUsIHdpbmRvdywgMSwgdG91Y2guc2NyZWVuWCwgdG91Y2guc2NyZWVuWSwgdG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDAsIG51bGwpO1xuXHRcdGNsaWNrRXZlbnQuZm9yd2FyZGVkVG91Y2hFdmVudCA9IHRydWU7XG5cdFx0dGFyZ2V0RWxlbWVudC5kaXNwYXRjaEV2ZW50KGNsaWNrRXZlbnQpO1xuXHR9O1xuXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZGV0ZXJtaW5lRXZlbnRUeXBlID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXG5cdFx0Ly9Jc3N1ZSAjMTU5OiBBbmRyb2lkIENocm9tZSBTZWxlY3QgQm94IGRvZXMgbm90IG9wZW4gd2l0aCBhIHN5bnRoZXRpYyBjbGljayBldmVudFxuXHRcdGlmIChkZXZpY2VJc0FuZHJvaWQgJiYgdGFyZ2V0RWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdzZWxlY3QnKSB7XG5cdFx0XHRyZXR1cm4gJ21vdXNlZG93bic7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICdjbGljayc7XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXHRcdHZhciBsZW5ndGg7XG5cblx0XHQvLyBJc3N1ZSAjMTYwOiBvbiBpT1MgNywgc29tZSBpbnB1dCBlbGVtZW50cyAoZS5nLiBkYXRlIGRhdGV0aW1lIG1vbnRoKSB0aHJvdyBhIHZhZ3VlIFR5cGVFcnJvciBvbiBzZXRTZWxlY3Rpb25SYW5nZS4gVGhlc2UgZWxlbWVudHMgZG9uJ3QgaGF2ZSBhbiBpbnRlZ2VyIHZhbHVlIGZvciB0aGUgc2VsZWN0aW9uU3RhcnQgYW5kIHNlbGVjdGlvbkVuZCBwcm9wZXJ0aWVzLCBidXQgdW5mb3J0dW5hdGVseSB0aGF0IGNhbid0IGJlIHVzZWQgZm9yIGRldGVjdGlvbiBiZWNhdXNlIGFjY2Vzc2luZyB0aGUgcHJvcGVydGllcyBhbHNvIHRocm93cyBhIFR5cGVFcnJvci4gSnVzdCBjaGVjayB0aGUgdHlwZSBpbnN0ZWFkLiBGaWxlZCBhcyBBcHBsZSBidWcgIzE1MTIyNzI0LlxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiB0YXJnZXRFbGVtZW50LnNldFNlbGVjdGlvblJhbmdlICYmIHRhcmdldEVsZW1lbnQudHlwZS5pbmRleE9mKCdkYXRlJykgIT09IDAgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAndGltZScgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAnbW9udGgnKSB7XG5cdFx0XHRsZW5ndGggPSB0YXJnZXRFbGVtZW50LnZhbHVlLmxlbmd0aDtcblx0XHRcdHRhcmdldEVsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UobGVuZ3RoLCBsZW5ndGgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0YXJnZXRFbGVtZW50LmZvY3VzKCk7XG5cdFx0fVxuXHR9O1xuXG5cblx0LyoqXG5cdCAqIENoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHRhcmdldCBlbGVtZW50IGlzIGEgY2hpbGQgb2YgYSBzY3JvbGxhYmxlIGxheWVyIGFuZCBpZiBzbywgc2V0IGEgZmxhZyBvbiBpdC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLnVwZGF0ZVNjcm9sbFBhcmVudCA9IGZ1bmN0aW9uKHRhcmdldEVsZW1lbnQpIHtcblx0XHR2YXIgc2Nyb2xsUGFyZW50LCBwYXJlbnRFbGVtZW50O1xuXG5cdFx0c2Nyb2xsUGFyZW50ID0gdGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQ7XG5cblx0XHQvLyBBdHRlbXB0IHRvIGRpc2NvdmVyIHdoZXRoZXIgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBzY3JvbGxhYmxlIGxheWVyLiBSZS1jaGVjayBpZiB0aGVcblx0XHQvLyB0YXJnZXQgZWxlbWVudCB3YXMgbW92ZWQgdG8gYW5vdGhlciBwYXJlbnQuXG5cdFx0aWYgKCFzY3JvbGxQYXJlbnQgfHwgIXNjcm9sbFBhcmVudC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0cGFyZW50RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG5cdFx0XHRkbyB7XG5cdFx0XHRcdGlmIChwYXJlbnRFbGVtZW50LnNjcm9sbEhlaWdodCA+IHBhcmVudEVsZW1lbnQub2Zmc2V0SGVpZ2h0KSB7XG5cdFx0XHRcdFx0c2Nyb2xsUGFyZW50ID0gcGFyZW50RWxlbWVudDtcblx0XHRcdFx0XHR0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudCA9IHBhcmVudEVsZW1lbnQ7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRwYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xuXHRcdFx0fSB3aGlsZSAocGFyZW50RWxlbWVudCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWx3YXlzIHVwZGF0ZSB0aGUgc2Nyb2xsIHRvcCB0cmFja2VyIGlmIHBvc3NpYmxlLlxuXHRcdGlmIChzY3JvbGxQYXJlbnQpIHtcblx0XHRcdHNjcm9sbFBhcmVudC5mYXN0Q2xpY2tMYXN0U2Nyb2xsVG9wID0gc2Nyb2xsUGFyZW50LnNjcm9sbFRvcDtcblx0XHR9XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldH0gdGFyZ2V0RWxlbWVudFxuXHQgKiBAcmV0dXJucyB7RWxlbWVudHxFdmVudFRhcmdldH1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldCA9IGZ1bmN0aW9uKGV2ZW50VGFyZ2V0KSB7XG5cblx0XHQvLyBPbiBzb21lIG9sZGVyIGJyb3dzZXJzIChub3RhYmx5IFNhZmFyaSBvbiBpT1MgNC4xIC0gc2VlIGlzc3VlICM1NikgdGhlIGV2ZW50IHRhcmdldCBtYXkgYmUgYSB0ZXh0IG5vZGUuXG5cdFx0aWYgKGV2ZW50VGFyZ2V0Lm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuXHRcdFx0cmV0dXJuIGV2ZW50VGFyZ2V0LnBhcmVudE5vZGU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50VGFyZ2V0O1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIE9uIHRvdWNoIHN0YXJ0LCByZWNvcmQgdGhlIHBvc2l0aW9uIGFuZCBzY3JvbGwgb2Zmc2V0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUub25Ub3VjaFN0YXJ0ID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgdGFyZ2V0RWxlbWVudCwgdG91Y2gsIHNlbGVjdGlvbjtcblxuXHRcdC8vIElnbm9yZSBtdWx0aXBsZSB0b3VjaGVzLCBvdGhlcndpc2UgcGluY2gtdG8tem9vbSBpcyBwcmV2ZW50ZWQgaWYgYm90aCBmaW5nZXJzIGFyZSBvbiB0aGUgRmFzdENsaWNrIGVsZW1lbnQgKGlzc3VlICMxMTEpLlxuXHRcdGlmIChldmVudC50YXJnZXRUb3VjaGVzLmxlbmd0aCA+IDEpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHRhcmdldEVsZW1lbnQgPSB0aGlzLmdldFRhcmdldEVsZW1lbnRGcm9tRXZlbnRUYXJnZXQoZXZlbnQudGFyZ2V0KTtcblx0XHR0b3VjaCA9IGV2ZW50LnRhcmdldFRvdWNoZXNbMF07XG5cblx0XHQvLyBJZ25vcmUgdG91Y2hlcyBvbiBjb250ZW50ZWRpdGFibGUgZWxlbWVudHMgdG8gcHJldmVudCBjb25mbGljdCB3aXRoIHRleHQgc2VsZWN0aW9uLlxuXHRcdC8vIChGb3IgZGV0YWlsczogaHR0cHM6Ly9naXRodWIuY29tL2Z0bGFicy9mYXN0Y2xpY2svcHVsbC8yMTEgKVxuXHRcdGlmICh0YXJnZXRFbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoZGV2aWNlSXNJT1MpIHtcblxuXHRcdFx0Ly8gT25seSB0cnVzdGVkIGV2ZW50cyB3aWxsIGRlc2VsZWN0IHRleHQgb24gaU9TIChpc3N1ZSAjNDkpXG5cdFx0XHRzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG5cdFx0XHRpZiAoc2VsZWN0aW9uLnJhbmdlQ291bnQgJiYgIXNlbGVjdGlvbi5pc0NvbGxhcHNlZCkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCFkZXZpY2VJc0lPUzQpIHtcblxuXHRcdFx0XHQvLyBXZWlyZCB0aGluZ3MgaGFwcGVuIG9uIGlPUyB3aGVuIGFuIGFsZXJ0IG9yIGNvbmZpcm0gZGlhbG9nIGlzIG9wZW5lZCBmcm9tIGEgY2xpY2sgZXZlbnQgY2FsbGJhY2sgKGlzc3VlICMyMyk6XG5cdFx0XHRcdC8vIHdoZW4gdGhlIHVzZXIgbmV4dCB0YXBzIGFueXdoZXJlIGVsc2Ugb24gdGhlIHBhZ2UsIG5ldyB0b3VjaHN0YXJ0IGFuZCB0b3VjaGVuZCBldmVudHMgYXJlIGRpc3BhdGNoZWRcblx0XHRcdFx0Ly8gd2l0aCB0aGUgc2FtZSBpZGVudGlmaWVyIGFzIHRoZSB0b3VjaCBldmVudCB0aGF0IHByZXZpb3VzbHkgdHJpZ2dlcmVkIHRoZSBjbGljayB0aGF0IHRyaWdnZXJlZCB0aGUgYWxlcnQuXG5cdFx0XHRcdC8vIFNhZGx5LCB0aGVyZSBpcyBhbiBpc3N1ZSBvbiBpT1MgNCB0aGF0IGNhdXNlcyBzb21lIG5vcm1hbCB0b3VjaCBldmVudHMgdG8gaGF2ZSB0aGUgc2FtZSBpZGVudGlmaWVyIGFzIGFuXG5cdFx0XHRcdC8vIGltbWVkaWF0ZWx5IHByZWNlZGluZyB0b3VjaCBldmVudCAoaXNzdWUgIzUyKSwgc28gdGhpcyBmaXggaXMgdW5hdmFpbGFibGUgb24gdGhhdCBwbGF0Zm9ybS5cblx0XHRcdFx0Ly8gSXNzdWUgMTIwOiB0b3VjaC5pZGVudGlmaWVyIGlzIDAgd2hlbiBDaHJvbWUgZGV2IHRvb2xzICdFbXVsYXRlIHRvdWNoIGV2ZW50cycgaXMgc2V0IHdpdGggYW4gaU9TIGRldmljZSBVQSBzdHJpbmcsXG5cdFx0XHRcdC8vIHdoaWNoIGNhdXNlcyBhbGwgdG91Y2ggZXZlbnRzIHRvIGJlIGlnbm9yZWQuIEFzIHRoaXMgYmxvY2sgb25seSBhcHBsaWVzIHRvIGlPUywgYW5kIGlPUyBpZGVudGlmaWVycyBhcmUgYWx3YXlzIGxvbmcsXG5cdFx0XHRcdC8vIHJhbmRvbSBpbnRlZ2VycywgaXQncyBzYWZlIHRvIHRvIGNvbnRpbnVlIGlmIHRoZSBpZGVudGlmaWVyIGlzIDAgaGVyZS5cblx0XHRcdFx0aWYgKHRvdWNoLmlkZW50aWZpZXIgJiYgdG91Y2guaWRlbnRpZmllciA9PT0gdGhpcy5sYXN0VG91Y2hJZGVudGlmaWVyKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLmxhc3RUb3VjaElkZW50aWZpZXIgPSB0b3VjaC5pZGVudGlmaWVyO1xuXG5cdFx0XHRcdC8vIElmIHRoZSB0YXJnZXQgZWxlbWVudCBpcyBhIGNoaWxkIG9mIGEgc2Nyb2xsYWJsZSBsYXllciAodXNpbmcgLXdlYmtpdC1vdmVyZmxvdy1zY3JvbGxpbmc6IHRvdWNoKSBhbmQ6XG5cdFx0XHRcdC8vIDEpIHRoZSB1c2VyIGRvZXMgYSBmbGluZyBzY3JvbGwgb24gdGhlIHNjcm9sbGFibGUgbGF5ZXJcblx0XHRcdFx0Ly8gMikgdGhlIHVzZXIgc3RvcHMgdGhlIGZsaW5nIHNjcm9sbCB3aXRoIGFub3RoZXIgdGFwXG5cdFx0XHRcdC8vIHRoZW4gdGhlIGV2ZW50LnRhcmdldCBvZiB0aGUgbGFzdCAndG91Y2hlbmQnIGV2ZW50IHdpbGwgYmUgdGhlIGVsZW1lbnQgdGhhdCB3YXMgdW5kZXIgdGhlIHVzZXIncyBmaW5nZXJcblx0XHRcdFx0Ly8gd2hlbiB0aGUgZmxpbmcgc2Nyb2xsIHdhcyBzdGFydGVkLCBjYXVzaW5nIEZhc3RDbGljayB0byBzZW5kIGEgY2xpY2sgZXZlbnQgdG8gdGhhdCBsYXllciAtIHVubGVzcyBhIGNoZWNrXG5cdFx0XHRcdC8vIGlzIG1hZGUgdG8gZW5zdXJlIHRoYXQgYSBwYXJlbnQgbGF5ZXIgd2FzIG5vdCBzY3JvbGxlZCBiZWZvcmUgc2VuZGluZyBhIHN5bnRoZXRpYyBjbGljayAoaXNzdWUgIzQyKS5cblx0XHRcdFx0dGhpcy51cGRhdGVTY3JvbGxQYXJlbnQodGFyZ2V0RWxlbWVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy50cmFja2luZ0NsaWNrID0gdHJ1ZTtcblx0XHR0aGlzLnRyYWNraW5nQ2xpY2tTdGFydCA9IGV2ZW50LnRpbWVTdGFtcDtcblx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnZXRFbGVtZW50O1xuXG5cdFx0dGhpcy50b3VjaFN0YXJ0WCA9IHRvdWNoLnBhZ2VYO1xuXHRcdHRoaXMudG91Y2hTdGFydFkgPSB0b3VjaC5wYWdlWTtcblxuXHRcdC8vIFByZXZlbnQgcGhhbnRvbSBjbGlja3Mgb24gZmFzdCBkb3VibGUtdGFwIChpc3N1ZSAjMzYpXG5cdFx0aWYgKChldmVudC50aW1lU3RhbXAgLSB0aGlzLmxhc3RDbGlja1RpbWUpIDwgdGhpcy50YXBEZWxheSAmJiAoZXZlbnQudGltZVN0YW1wIC0gdGhpcy5sYXN0Q2xpY2tUaW1lKSA+IC0xKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIEJhc2VkIG9uIGEgdG91Y2htb3ZlIGV2ZW50IG9iamVjdCwgY2hlY2sgd2hldGhlciB0aGUgdG91Y2ggaGFzIG1vdmVkIHBhc3QgYSBib3VuZGFyeSBzaW5jZSBpdCBzdGFydGVkLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUudG91Y2hIYXNNb3ZlZCA9IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0sIGJvdW5kYXJ5ID0gdGhpcy50b3VjaEJvdW5kYXJ5O1xuXG5cdFx0aWYgKE1hdGguYWJzKHRvdWNoLnBhZ2VYIC0gdGhpcy50b3VjaFN0YXJ0WCkgPiBib3VuZGFyeSB8fCBNYXRoLmFicyh0b3VjaC5wYWdlWSAtIHRoaXMudG91Y2hTdGFydFkpID4gYm91bmRhcnkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBVcGRhdGUgdGhlIGxhc3QgcG9zaXRpb24uXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS5vblRvdWNoTW92ZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCF0aGlzLnRyYWNraW5nQ2xpY2spIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIElmIHRoZSB0b3VjaCBoYXMgbW92ZWQsIGNhbmNlbCB0aGUgY2xpY2sgdHJhY2tpbmdcblx0XHRpZiAodGhpcy50YXJnZXRFbGVtZW50ICE9PSB0aGlzLmdldFRhcmdldEVsZW1lbnRGcm9tRXZlbnRUYXJnZXQoZXZlbnQudGFyZ2V0KSB8fCB0aGlzLnRvdWNoSGFzTW92ZWQoZXZlbnQpKSB7XG5cdFx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSBmYWxzZTtcblx0XHRcdHRoaXMudGFyZ2V0RWxlbWVudCA9IG51bGw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH07XG5cblxuXHQvKipcblx0ICogQXR0ZW1wdCB0byBmaW5kIHRoZSBsYWJlbGxlZCBjb250cm9sIGZvciB0aGUgZ2l2ZW4gbGFiZWwgZWxlbWVudC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxIVE1MTGFiZWxFbGVtZW50fSBsYWJlbEVsZW1lbnRcblx0ICogQHJldHVybnMge0VsZW1lbnR8bnVsbH1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZmluZENvbnRyb2wgPSBmdW5jdGlvbihsYWJlbEVsZW1lbnQpIHtcblxuXHRcdC8vIEZhc3QgcGF0aCBmb3IgbmV3ZXIgYnJvd3NlcnMgc3VwcG9ydGluZyB0aGUgSFRNTDUgY29udHJvbCBhdHRyaWJ1dGVcblx0XHRpZiAobGFiZWxFbGVtZW50LmNvbnRyb2wgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIGxhYmVsRWxlbWVudC5jb250cm9sO1xuXHRcdH1cblxuXHRcdC8vIEFsbCBicm93c2VycyB1bmRlciB0ZXN0IHRoYXQgc3VwcG9ydCB0b3VjaCBldmVudHMgYWxzbyBzdXBwb3J0IHRoZSBIVE1MNSBodG1sRm9yIGF0dHJpYnV0ZVxuXHRcdGlmIChsYWJlbEVsZW1lbnQuaHRtbEZvcikge1xuXHRcdFx0cmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGxhYmVsRWxlbWVudC5odG1sRm9yKTtcblx0XHR9XG5cblx0XHQvLyBJZiBubyBmb3IgYXR0cmlidXRlIGV4aXN0cywgYXR0ZW1wdCB0byByZXRyaWV2ZSB0aGUgZmlyc3QgbGFiZWxsYWJsZSBkZXNjZW5kYW50IGVsZW1lbnRcblx0XHQvLyB0aGUgbGlzdCBvZiB3aGljaCBpcyBkZWZpbmVkIGhlcmU6IGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWw1L2Zvcm1zLmh0bWwjY2F0ZWdvcnktbGFiZWxcblx0XHRyZXR1cm4gbGFiZWxFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ2J1dHRvbiwgaW5wdXQ6bm90KFt0eXBlPWhpZGRlbl0pLCBrZXlnZW4sIG1ldGVyLCBvdXRwdXQsIHByb2dyZXNzLCBzZWxlY3QsIHRleHRhcmVhJyk7XG5cdH07XG5cblxuXHQvKipcblx0ICogT24gdG91Y2ggZW5kLCBkZXRlcm1pbmUgd2hldGhlciB0byBzZW5kIGEgY2xpY2sgZXZlbnQgYXQgb25jZS5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hFbmQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBmb3JFbGVtZW50LCB0cmFja2luZ0NsaWNrU3RhcnQsIHRhcmdldFRhZ05hbWUsIHNjcm9sbFBhcmVudCwgdG91Y2gsIHRhcmdldEVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG5cblx0XHRpZiAoIXRoaXMudHJhY2tpbmdDbGljaykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gUHJldmVudCBwaGFudG9tIGNsaWNrcyBvbiBmYXN0IGRvdWJsZS10YXAgKGlzc3VlICMzNilcblx0XHRpZiAoKGV2ZW50LnRpbWVTdGFtcCAtIHRoaXMubGFzdENsaWNrVGltZSkgPCB0aGlzLnRhcERlbGF5ICYmIChldmVudC50aW1lU3RhbXAgLSB0aGlzLmxhc3RDbGlja1RpbWUpID4gLTEpIHtcblx0XHRcdHRoaXMuY2FuY2VsTmV4dENsaWNrID0gdHJ1ZTtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICgoZXZlbnQudGltZVN0YW1wIC0gdGhpcy50cmFja2luZ0NsaWNrU3RhcnQpID4gdGhpcy50YXBUaW1lb3V0KSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBSZXNldCB0byBwcmV2ZW50IHdyb25nIGNsaWNrIGNhbmNlbCBvbiBpbnB1dCAoaXNzdWUgIzE1NikuXG5cdFx0dGhpcy5jYW5jZWxOZXh0Q2xpY2sgPSBmYWxzZTtcblxuXHRcdHRoaXMubGFzdENsaWNrVGltZSA9IGV2ZW50LnRpbWVTdGFtcDtcblxuXHRcdHRyYWNraW5nQ2xpY2tTdGFydCA9IHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0O1xuXHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gMDtcblxuXHRcdC8vIE9uIHNvbWUgaU9TIGRldmljZXMsIHRoZSB0YXJnZXRFbGVtZW50IHN1cHBsaWVkIHdpdGggdGhlIGV2ZW50IGlzIGludmFsaWQgaWYgdGhlIGxheWVyXG5cdFx0Ly8gaXMgcGVyZm9ybWluZyBhIHRyYW5zaXRpb24gb3Igc2Nyb2xsLCBhbmQgaGFzIHRvIGJlIHJlLWRldGVjdGVkIG1hbnVhbGx5LiBOb3RlIHRoYXRcblx0XHQvLyBmb3IgdGhpcyB0byBmdW5jdGlvbiBjb3JyZWN0bHksIGl0IG11c3QgYmUgY2FsbGVkICphZnRlciogdGhlIGV2ZW50IHRhcmdldCBpcyBjaGVja2VkIVxuXHRcdC8vIFNlZSBpc3N1ZSAjNTc7IGFsc28gZmlsZWQgYXMgcmRhcjovLzEzMDQ4NTg5IC5cblx0XHRpZiAoZGV2aWNlSXNJT1NXaXRoQmFkVGFyZ2V0KSB7XG5cdFx0XHR0b3VjaCA9IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdO1xuXG5cdFx0XHQvLyBJbiBjZXJ0YWluIGNhc2VzIGFyZ3VtZW50cyBvZiBlbGVtZW50RnJvbVBvaW50IGNhbiBiZSBuZWdhdGl2ZSwgc28gcHJldmVudCBzZXR0aW5nIHRhcmdldEVsZW1lbnQgdG8gbnVsbFxuXHRcdFx0dGFyZ2V0RWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQodG91Y2gucGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQsIHRvdWNoLnBhZ2VZIC0gd2luZG93LnBhZ2VZT2Zmc2V0KSB8fCB0YXJnZXRFbGVtZW50O1xuXHRcdFx0dGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQuZmFzdENsaWNrU2Nyb2xsUGFyZW50O1xuXHRcdH1cblxuXHRcdHRhcmdldFRhZ05hbWUgPSB0YXJnZXRFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRpZiAodGFyZ2V0VGFnTmFtZSA9PT0gJ2xhYmVsJykge1xuXHRcdFx0Zm9yRWxlbWVudCA9IHRoaXMuZmluZENvbnRyb2wodGFyZ2V0RWxlbWVudCk7XG5cdFx0XHRpZiAoZm9yRWxlbWVudCkge1xuXHRcdFx0XHR0aGlzLmZvY3VzKHRhcmdldEVsZW1lbnQpO1xuXHRcdFx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGFyZ2V0RWxlbWVudCA9IGZvckVsZW1lbnQ7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmICh0aGlzLm5lZWRzRm9jdXModGFyZ2V0RWxlbWVudCkpIHtcblxuXHRcdFx0Ly8gQ2FzZSAxOiBJZiB0aGUgdG91Y2ggc3RhcnRlZCBhIHdoaWxlIGFnbyAoYmVzdCBndWVzcyBpcyAxMDBtcyBiYXNlZCBvbiB0ZXN0cyBmb3IgaXNzdWUgIzM2KSB0aGVuIGZvY3VzIHdpbGwgYmUgdHJpZ2dlcmVkIGFueXdheS4gUmV0dXJuIGVhcmx5IGFuZCB1bnNldCB0aGUgdGFyZ2V0IGVsZW1lbnQgcmVmZXJlbmNlIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgY2xpY2sgd2lsbCBiZSBhbGxvd2VkIHRocm91Z2guXG5cdFx0XHQvLyBDYXNlIDI6IFdpdGhvdXQgdGhpcyBleGNlcHRpb24gZm9yIGlucHV0IGVsZW1lbnRzIHRhcHBlZCB3aGVuIHRoZSBkb2N1bWVudCBpcyBjb250YWluZWQgaW4gYW4gaWZyYW1lLCB0aGVuIGFueSBpbnB1dHRlZCB0ZXh0IHdvbid0IGJlIHZpc2libGUgZXZlbiB0aG91Z2ggdGhlIHZhbHVlIGF0dHJpYnV0ZSBpcyB1cGRhdGVkIGFzIHRoZSB1c2VyIHR5cGVzIChpc3N1ZSAjMzcpLlxuXHRcdFx0aWYgKChldmVudC50aW1lU3RhbXAgLSB0cmFja2luZ0NsaWNrU3RhcnQpID4gMTAwIHx8IChkZXZpY2VJc0lPUyAmJiB3aW5kb3cudG9wICE9PSB3aW5kb3cgJiYgdGFyZ2V0VGFnTmFtZSA9PT0gJ2lucHV0JykpIHtcblx0XHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmZvY3VzKHRhcmdldEVsZW1lbnQpO1xuXHRcdFx0dGhpcy5zZW5kQ2xpY2sodGFyZ2V0RWxlbWVudCwgZXZlbnQpO1xuXG5cdFx0XHQvLyBTZWxlY3QgZWxlbWVudHMgbmVlZCB0aGUgZXZlbnQgdG8gZ28gdGhyb3VnaCBvbiBpT1MgNCwgb3RoZXJ3aXNlIHRoZSBzZWxlY3RvciBtZW51IHdvbid0IG9wZW4uXG5cdFx0XHQvLyBBbHNvIHRoaXMgYnJlYWtzIG9wZW5pbmcgc2VsZWN0cyB3aGVuIFZvaWNlT3ZlciBpcyBhY3RpdmUgb24gaU9TNiwgaU9TNyAoYW5kIHBvc3NpYmx5IG90aGVycylcblx0XHRcdGlmICghZGV2aWNlSXNJT1MgfHwgdGFyZ2V0VGFnTmFtZSAhPT0gJ3NlbGVjdCcpIHtcblx0XHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiAhZGV2aWNlSXNJT1M0KSB7XG5cblx0XHRcdC8vIERvbid0IHNlbmQgYSBzeW50aGV0aWMgY2xpY2sgZXZlbnQgaWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBwYXJlbnQgbGF5ZXIgdGhhdCB3YXMgc2Nyb2xsZWRcblx0XHRcdC8vIGFuZCB0aGlzIHRhcCBpcyBiZWluZyB1c2VkIHRvIHN0b3AgdGhlIHNjcm9sbGluZyAodXN1YWxseSBpbml0aWF0ZWQgYnkgYSBmbGluZyAtIGlzc3VlICM0MikuXG5cdFx0XHRzY3JvbGxQYXJlbnQgPSB0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudDtcblx0XHRcdGlmIChzY3JvbGxQYXJlbnQgJiYgc2Nyb2xsUGFyZW50LmZhc3RDbGlja0xhc3RTY3JvbGxUb3AgIT09IHNjcm9sbFBhcmVudC5zY3JvbGxUb3ApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUHJldmVudCB0aGUgYWN0dWFsIGNsaWNrIGZyb20gZ29pbmcgdGhvdWdoIC0gdW5sZXNzIHRoZSB0YXJnZXQgbm9kZSBpcyBtYXJrZWQgYXMgcmVxdWlyaW5nXG5cdFx0Ly8gcmVhbCBjbGlja3Mgb3IgaWYgaXQgaXMgaW4gdGhlIHdoaXRlbGlzdCBpbiB3aGljaCBjYXNlIG9ubHkgbm9uLXByb2dyYW1tYXRpYyBjbGlja3MgYXJlIHBlcm1pdHRlZC5cblx0XHRpZiAoIXRoaXMubmVlZHNDbGljayh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuc2VuZENsaWNrKHRhcmdldEVsZW1lbnQsIGV2ZW50KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG5cblxuXHQvKipcblx0ICogT24gdG91Y2ggY2FuY2VsLCBzdG9wIHRyYWNraW5nIHRoZSBjbGljay5cblx0ICpcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hDYW5jZWwgPSBmdW5jdGlvbigpIHtcblx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSBmYWxzZTtcblx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIERldGVybWluZSBtb3VzZSBldmVudHMgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uTW91c2UgPSBmdW5jdGlvbihldmVudCkge1xuXG5cdFx0Ly8gSWYgYSB0YXJnZXQgZWxlbWVudCB3YXMgbmV2ZXIgc2V0IChiZWNhdXNlIGEgdG91Y2ggZXZlbnQgd2FzIG5ldmVyIGZpcmVkKSBhbGxvdyB0aGUgZXZlbnRcblx0XHRpZiAoIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmZvcndhcmRlZFRvdWNoRXZlbnQpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIFByb2dyYW1tYXRpY2FsbHkgZ2VuZXJhdGVkIGV2ZW50cyB0YXJnZXRpbmcgYSBzcGVjaWZpYyBlbGVtZW50IHNob3VsZCBiZSBwZXJtaXR0ZWRcblx0XHRpZiAoIWV2ZW50LmNhbmNlbGFibGUpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIERlcml2ZSBhbmQgY2hlY2sgdGhlIHRhcmdldCBlbGVtZW50IHRvIHNlZSB3aGV0aGVyIHRoZSBtb3VzZSBldmVudCBuZWVkcyB0byBiZSBwZXJtaXR0ZWQ7XG5cdFx0Ly8gdW5sZXNzIGV4cGxpY2l0bHkgZW5hYmxlZCwgcHJldmVudCBub24tdG91Y2ggY2xpY2sgZXZlbnRzIGZyb20gdHJpZ2dlcmluZyBhY3Rpb25zLFxuXHRcdC8vIHRvIHByZXZlbnQgZ2hvc3QvZG91YmxlY2xpY2tzLlxuXHRcdGlmICghdGhpcy5uZWVkc0NsaWNrKHRoaXMudGFyZ2V0RWxlbWVudCkgfHwgdGhpcy5jYW5jZWxOZXh0Q2xpY2spIHtcblxuXHRcdFx0Ly8gUHJldmVudCBhbnkgdXNlci1hZGRlZCBsaXN0ZW5lcnMgZGVjbGFyZWQgb24gRmFzdENsaWNrIGVsZW1lbnQgZnJvbSBiZWluZyBmaXJlZC5cblx0XHRcdGlmIChldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24pIHtcblx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIFBhcnQgb2YgdGhlIGhhY2sgZm9yIGJyb3dzZXJzIHRoYXQgZG9uJ3Qgc3VwcG9ydCBFdmVudCNzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gKGUuZy4gQW5kcm9pZCAyKVxuXHRcdFx0XHRldmVudC5wcm9wYWdhdGlvblN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYW5jZWwgdGhlIGV2ZW50XG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgbW91c2UgZXZlbnQgaXMgcGVybWl0dGVkLCByZXR1cm4gdHJ1ZSBmb3IgdGhlIGFjdGlvbiB0byBnbyB0aHJvdWdoLlxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIE9uIGFjdHVhbCBjbGlja3MsIGRldGVybWluZSB3aGV0aGVyIHRoaXMgaXMgYSB0b3VjaC1nZW5lcmF0ZWQgY2xpY2ssIGEgY2xpY2sgYWN0aW9uIG9jY3VycmluZ1xuXHQgKiBuYXR1cmFsbHkgYWZ0ZXIgYSBkZWxheSBhZnRlciBhIHRvdWNoICh3aGljaCBuZWVkcyB0byBiZSBjYW5jZWxsZWQgdG8gYXZvaWQgZHVwbGljYXRpb24pLCBvclxuXHQgKiBhbiBhY3R1YWwgY2xpY2sgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uQ2xpY2sgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBwZXJtaXR0ZWQ7XG5cblx0XHQvLyBJdCdzIHBvc3NpYmxlIGZvciBhbm90aGVyIEZhc3RDbGljay1saWtlIGxpYnJhcnkgZGVsaXZlcmVkIHdpdGggdGhpcmQtcGFydHkgY29kZSB0byBmaXJlIGEgY2xpY2sgZXZlbnQgYmVmb3JlIEZhc3RDbGljayBkb2VzIChpc3N1ZSAjNDQpLiBJbiB0aGF0IGNhc2UsIHNldCB0aGUgY2xpY2stdHJhY2tpbmcgZmxhZyBiYWNrIHRvIGZhbHNlIGFuZCByZXR1cm4gZWFybHkuIFRoaXMgd2lsbCBjYXVzZSBvblRvdWNoRW5kIHRvIHJldHVybiBlYXJseS5cblx0XHRpZiAodGhpcy50cmFja2luZ0NsaWNrKSB7XG5cdFx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHRcdFx0dGhpcy50cmFja2luZ0NsaWNrID0gZmFsc2U7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBWZXJ5IG9kZCBiZWhhdmlvciBvbiBpT1MgKGlzc3VlICMxOCk6IGlmIGEgc3VibWl0IGVsZW1lbnQgaXMgcHJlc2VudCBpbnNpZGUgYSBmb3JtIGFuZCB0aGUgdXNlciBoaXRzIGVudGVyIGluIHRoZSBpT1Mgc2ltdWxhdG9yIG9yIGNsaWNrcyB0aGUgR28gYnV0dG9uIG9uIHRoZSBwb3AtdXAgT1Mga2V5Ym9hcmQgdGhlIGEga2luZCBvZiAnZmFrZScgY2xpY2sgZXZlbnQgd2lsbCBiZSB0cmlnZ2VyZWQgd2l0aCB0aGUgc3VibWl0LXR5cGUgaW5wdXQgZWxlbWVudCBhcyB0aGUgdGFyZ2V0LlxuXHRcdGlmIChldmVudC50YXJnZXQudHlwZSA9PT0gJ3N1Ym1pdCcgJiYgZXZlbnQuZGV0YWlsID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRwZXJtaXR0ZWQgPSB0aGlzLm9uTW91c2UoZXZlbnQpO1xuXG5cdFx0Ly8gT25seSB1bnNldCB0YXJnZXRFbGVtZW50IGlmIHRoZSBjbGljayBpcyBub3QgcGVybWl0dGVkLiBUaGlzIHdpbGwgZW5zdXJlIHRoYXQgdGhlIGNoZWNrIGZvciAhdGFyZ2V0RWxlbWVudCBpbiBvbk1vdXNlIGZhaWxzIGFuZCB0aGUgYnJvd3NlcidzIGNsaWNrIGRvZXNuJ3QgZ28gdGhyb3VnaC5cblx0XHRpZiAoIXBlcm1pdHRlZCkge1xuXHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBJZiBjbGlja3MgYXJlIHBlcm1pdHRlZCwgcmV0dXJuIHRydWUgZm9yIHRoZSBhY3Rpb24gdG8gZ28gdGhyb3VnaC5cblx0XHRyZXR1cm4gcGVybWl0dGVkO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIFJlbW92ZSBhbGwgRmFzdENsaWNrJ3MgZXZlbnQgbGlzdGVuZXJzLlxuXHQgKlxuXHQgKiBAcmV0dXJucyB7dm9pZH1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBsYXllciA9IHRoaXMubGF5ZXI7XG5cblx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdH1cblxuXHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5vbkNsaWNrLCB0cnVlKTtcblx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5vblRvdWNoU3RhcnQsIGZhbHNlKTtcblx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLm9uVG91Y2hNb3ZlLCBmYWxzZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLm9uVG91Y2hFbmQsIGZhbHNlKTtcblx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMub25Ub3VjaENhbmNlbCwgZmFsc2UpO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIENoZWNrIHdoZXRoZXIgRmFzdENsaWNrIGlzIG5lZWRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFbGVtZW50fSBsYXllciBUaGUgbGF5ZXIgdG8gbGlzdGVuIG9uXG5cdCAqL1xuXHRGYXN0Q2xpY2subm90TmVlZGVkID0gZnVuY3Rpb24obGF5ZXIpIHtcblx0XHR2YXIgbWV0YVZpZXdwb3J0O1xuXHRcdHZhciBjaHJvbWVWZXJzaW9uO1xuXHRcdHZhciBibGFja2JlcnJ5VmVyc2lvbjtcblx0XHR2YXIgZmlyZWZveFZlcnNpb247XG5cblx0XHQvLyBEZXZpY2VzIHRoYXQgZG9uJ3Qgc3VwcG9ydCB0b3VjaCBkb24ndCBuZWVkIEZhc3RDbGlja1xuXHRcdGlmICh0eXBlb2Ygd2luZG93Lm9udG91Y2hzdGFydCA9PT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIENocm9tZSB2ZXJzaW9uIC0gemVybyBmb3Igb3RoZXIgYnJvd3NlcnNcblx0XHRjaHJvbWVWZXJzaW9uID0gKygvQ2hyb21lXFwvKFswLTldKykvLmV4ZWMobmF2aWdhdG9yLnVzZXJBZ2VudCkgfHwgWywwXSlbMV07XG5cblx0XHRpZiAoY2hyb21lVmVyc2lvbikge1xuXG5cdFx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRcdG1ldGFWaWV3cG9ydCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT12aWV3cG9ydF0nKTtcblxuXHRcdFx0XHRpZiAobWV0YVZpZXdwb3J0KSB7XG5cdFx0XHRcdFx0Ly8gQ2hyb21lIG9uIEFuZHJvaWQgd2l0aCB1c2VyLXNjYWxhYmxlPVwibm9cIiBkb2Vzbid0IG5lZWQgRmFzdENsaWNrIChpc3N1ZSAjODkpXG5cdFx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydC5jb250ZW50LmluZGV4T2YoJ3VzZXItc2NhbGFibGU9bm8nKSAhPT0gLTEpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyBDaHJvbWUgMzIgYW5kIGFib3ZlIHdpdGggd2lkdGg9ZGV2aWNlLXdpZHRoIG9yIGxlc3MgZG9uJ3QgbmVlZCBGYXN0Q2xpY2tcblx0XHRcdFx0XHRpZiAoY2hyb21lVmVyc2lvbiA+IDMxICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxXaWR0aCA8PSB3aW5kb3cub3V0ZXJXaWR0aCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdC8vIENocm9tZSBkZXNrdG9wIGRvZXNuJ3QgbmVlZCBGYXN0Q2xpY2sgKGlzc3VlICMxNSlcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0JsYWNrQmVycnkxMCkge1xuXHRcdFx0YmxhY2tiZXJyeVZlcnNpb24gPSBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9WZXJzaW9uXFwvKFswLTldKilcXC4oWzAtOV0qKS8pO1xuXG5cdFx0XHQvLyBCbGFja0JlcnJ5IDEwLjMrIGRvZXMgbm90IHJlcXVpcmUgRmFzdGNsaWNrIGxpYnJhcnkuXG5cdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vZnRsYWJzL2Zhc3RjbGljay9pc3N1ZXMvMjUxXG5cdFx0XHRpZiAoYmxhY2tiZXJyeVZlcnNpb25bMV0gPj0gMTAgJiYgYmxhY2tiZXJyeVZlcnNpb25bMl0gPj0gMykge1xuXHRcdFx0XHRtZXRhVmlld3BvcnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9dmlld3BvcnRdJyk7XG5cblx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydCkge1xuXHRcdFx0XHRcdC8vIHVzZXItc2NhbGFibGU9bm8gZWxpbWluYXRlcyBjbGljayBkZWxheS5cblx0XHRcdFx0XHRpZiAobWV0YVZpZXdwb3J0LmNvbnRlbnQuaW5kZXhPZigndXNlci1zY2FsYWJsZT1ubycpICE9PSAtMSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vIHdpZHRoPWRldmljZS13aWR0aCAob3IgbGVzcyB0aGFuIGRldmljZS13aWR0aCkgZWxpbWluYXRlcyBjbGljayBkZWxheS5cblx0XHRcdFx0XHRpZiAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoIDw9IHdpbmRvdy5vdXRlcldpZHRoKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJRTEwIHdpdGggLW1zLXRvdWNoLWFjdGlvbjogbm9uZSBvciBtYW5pcHVsYXRpb24sIHdoaWNoIGRpc2FibGVzIGRvdWJsZS10YXAtdG8tem9vbSAoaXNzdWUgIzk3KVxuXHRcdGlmIChsYXllci5zdHlsZS5tc1RvdWNoQWN0aW9uID09PSAnbm9uZScgfHwgbGF5ZXIuc3R5bGUudG91Y2hBY3Rpb24gPT09ICdtYW5pcHVsYXRpb24nKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBGaXJlZm94IHZlcnNpb24gLSB6ZXJvIGZvciBvdGhlciBicm93c2Vyc1xuXHRcdGZpcmVmb3hWZXJzaW9uID0gKygvRmlyZWZveFxcLyhbMC05XSspLy5leGVjKG5hdmlnYXRvci51c2VyQWdlbnQpIHx8IFssMF0pWzFdO1xuXG5cdFx0aWYgKGZpcmVmb3hWZXJzaW9uID49IDI3KSB7XG5cdFx0XHQvLyBGaXJlZm94IDI3KyBkb2VzIG5vdCBoYXZlIHRhcCBkZWxheSBpZiB0aGUgY29udGVudCBpcyBub3Qgem9vbWFibGUgLSBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD05MjI4OTZcblxuXHRcdFx0bWV0YVZpZXdwb3J0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPXZpZXdwb3J0XScpO1xuXHRcdFx0aWYgKG1ldGFWaWV3cG9ydCAmJiAobWV0YVZpZXdwb3J0LmNvbnRlbnQuaW5kZXhPZigndXNlci1zY2FsYWJsZT1ubycpICE9PSAtMSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsV2lkdGggPD0gd2luZG93Lm91dGVyV2lkdGgpKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIElFMTE6IHByZWZpeGVkIC1tcy10b3VjaC1hY3Rpb24gaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCBhbmQgaXQncyByZWNvbW1lbmRlZCB0byB1c2Ugbm9uLXByZWZpeGVkIHZlcnNpb25cblx0XHQvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvd2luZG93cy9hcHBzL0hoNzY3MzEzLmFzcHhcblx0XHRpZiAobGF5ZXIuc3R5bGUudG91Y2hBY3Rpb24gPT09ICdub25lJyB8fCBsYXllci5zdHlsZS50b3VjaEFjdGlvbiA9PT0gJ21hbmlwdWxhdGlvbicpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBGYWN0b3J5IG1ldGhvZCBmb3IgY3JlYXRpbmcgYSBGYXN0Q2xpY2sgb2JqZWN0XG5cdCAqXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGF5ZXIgVGhlIGxheWVyIHRvIGxpc3RlbiBvblxuXHQgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0c1xuXHQgKi9cblx0RmFzdENsaWNrLmF0dGFjaCA9IGZ1bmN0aW9uKGxheWVyLCBvcHRpb25zKSB7XG5cdFx0cmV0dXJuIG5ldyBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpO1xuXHR9O1xuXG4gIHdpbmRvdy5GYXN0Q2xpY2sgPSBGYXN0Q2xpY2s7XG59KCkpO1xuIiwiLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9XZWJSZWZsZWN0aW9uL2RvY3VtZW50LXJlZ2lzdGVyLWVsZW1lbnQvaXNzdWVzLzIxI2lzc3VlY29tbWVudC0xMDIwMjAzMTFcbnZhciBpbm5lckhUTUwgPSAoZnVuY3Rpb24gKGRvY3VtZW50KSB7XG5cbiAgdmFyXG4gICAgRVhURU5EUyA9ICdleHRlbmRzJyxcbiAgICByZWdpc3RlciA9IGRvY3VtZW50LnJlZ2lzdGVyRWxlbWVudCxcbiAgICBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcbiAgICBkcmUgPSAnZG9jdW1lbnQtcmVnaXN0ZXItZWxlbWVudCcsXG4gICAgaW5uZXJIVE1MID0gcmVnaXN0ZXIuaW5uZXJIVE1MLFxuICAgIGluaXRpYWxpemUsXG4gICAgcmVnaXN0ZXJlZFxuICA7XG5cbiAgLy8gYXZvaWQgZHVwbGljYXRlZCB3cmFwcGVyc1xuICBpZiAoaW5uZXJIVE1MKSByZXR1cm4gaW5uZXJIVE1MO1xuXG4gIHRyeSB7XG5cbiAgICAvLyBmZWF0dXJlIGRldGVjdCB0aGUgcHJvYmxlbVxuICAgIHJlZ2lzdGVyLmNhbGwoXG4gICAgICBkb2N1bWVudCxcbiAgICAgIGRyZSxcbiAgICAgIHtwcm90b3R5cGU6IE9iamVjdC5jcmVhdGUoXG4gICAgICAgIEhUTUxFbGVtZW50LnByb3RvdHlwZSxcbiAgICAgICAge2NyZWF0ZWRDYWxsYmFjazoge3ZhbHVlOiBPYmplY3R9fVxuICAgICAgKX1cbiAgICApO1xuXG4gICAgZGl2LmlubmVySFRNTCA9ICc8JyArIGRyZSArICc+PC8nICsgZHJlICsgJz4nO1xuXG4gICAgLy8gaWYgbmF0aXZlbHkgc3VwcG9ydGVkLCBub3RoaW5nIHRvIGRvXG4gICAgaWYgKCdjcmVhdGVkQ2FsbGJhY2snIGluIGRpdi5xdWVyeVNlbGVjdG9yKGRyZSkpIHtcbiAgICAgIC8vIHJldHVybiBqdXN0IGFuIGlubmVySFRNTCB3cmFwXG4gICAgICByZXR1cm4gKHJlZ2lzdGVyLmlubmVySFRNTCA9IGZ1bmN0aW9uIChlbCwgaHRtbCkge1xuICAgICAgICBlbC5pbm5lckhUTUwgPSBodG1sO1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgfSBjYXRjaChtZWgpIHt9XG5cbiAgLy8gaW4gb3RoZXIgY2FzZXNcbiAgcmVnaXN0ZXJlZCA9IFtdO1xuICBpbml0aWFsaXplID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgaWYgKFxuICAgICAgJ2NyZWF0ZWRDYWxsYmFjaycgaW4gZWwgICAgICAgICB8fFxuICAgICAgJ2F0dGFjaGVkQ2FsbGJhY2snIGluIGVsICAgICAgICB8fFxuICAgICAgJ2RldGFjaGVkQ2FsbGJhY2snIGluIGVsICAgICAgICB8fFxuICAgICAgJ2F0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaycgaW4gZWxcbiAgICApIHJldHVybjtcbiAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50LmlubmVySFRNTEhlbHBlciA9IHRydWU7XG4gICAgZm9yICh2YXJcbiAgICAgIHBhcmVudE5vZGUgPSBlbC5wYXJlbnROb2RlLFxuICAgICAgdHlwZSA9IGVsLmdldEF0dHJpYnV0ZSgnaXMnKSxcbiAgICAgIG5hbWUgPSBlbC5ub2RlTmFtZSxcbiAgICAgIG5vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50LmFwcGx5KFxuICAgICAgICBkb2N1bWVudCxcbiAgICAgICAgdHlwZSA/IFtuYW1lLCB0eXBlXSA6IFtuYW1lXVxuICAgICAgKSxcbiAgICAgIGF0dHJpYnV0ZXMgPSBlbC5hdHRyaWJ1dGVzLFxuICAgICAgaSA9IDAsXG4gICAgICBsZW5ndGggPSBhdHRyaWJ1dGVzLmxlbmd0aCxcbiAgICAgIGF0dHIsIGZjO1xuICAgICAgaSA8IGxlbmd0aDsgaSsrXG4gICAgKSB7XG4gICAgICBhdHRyID0gYXR0cmlidXRlc1tpXTtcbiAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHIubmFtZSwgYXR0ci52YWx1ZSk7XG4gICAgfVxuICAgIGlmIChub2RlLmNyZWF0ZWRDYWxsYmFjaykge1xuICAgICAgbm9kZS5jcmVhdGVkID0gdHJ1ZTtcbiAgICAgIG5vZGUuY3JlYXRlZENhbGxiYWNrKCk7XG4gICAgICBub2RlLmNyZWF0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgd2hpbGUgKChmYyA9IGVsLmZpcnN0Q2hpbGQpKSBub2RlLmFwcGVuZENoaWxkKGZjKTtcbiAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50LmlubmVySFRNTEhlbHBlciA9IGZhbHNlO1xuICAgIGlmIChwYXJlbnROb2RlKSBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChub2RlLCBlbCk7XG4gIH07XG4gIC8vIGF1Z21lbnQgdGhlIGRvY3VtZW50LnJlZ2lzdGVyRWxlbWVudCBtZXRob2RcbiAgcmV0dXJuICgoZG9jdW1lbnQucmVnaXN0ZXJFbGVtZW50ID0gZnVuY3Rpb24gcmVnaXN0ZXJFbGVtZW50KHR5cGUsIG9wdGlvbnMpIHtcbiAgICB2YXIgbmFtZSA9IChvcHRpb25zW0VYVEVORFNdID9cbiAgICAgIChvcHRpb25zW0VYVEVORFNdICsgJ1tpcz1cIicgKyB0eXBlICsgJ1wiXScpIDogdHlwZVxuICAgICkudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAocmVnaXN0ZXJlZC5pbmRleE9mKG5hbWUpIDwgMCkgcmVnaXN0ZXJlZC5wdXNoKG5hbWUpO1xuICAgIHJldHVybiByZWdpc3Rlci5hcHBseShkb2N1bWVudCwgYXJndW1lbnRzKTtcbiAgfSkuaW5uZXJIVE1MID0gZnVuY3Rpb24gKGVsLCBodG1sKSB7XG4gICAgZWwuaW5uZXJIVE1MID0gaHRtbDtcbiAgICBmb3IgKHZhclxuICAgICAgbm9kZXMgPSBlbC5xdWVyeVNlbGVjdG9yQWxsKHJlZ2lzdGVyZWQuam9pbignLCcpKSxcbiAgICAgIGkgPSBub2Rlcy5sZW5ndGg7IGktLTsgaW5pdGlhbGl6ZShub2Rlc1tpXSlcbiAgICApIHt9XG4gICAgcmV0dXJuIGVsO1xuICB9KTtcbn0oZG9jdW1lbnQpKTsiLCIvKipcbiAqIE1pY3JvRXZlbnQgLSB0byBtYWtlIGFueSBqcyBvYmplY3QgYW4gZXZlbnQgZW1pdHRlciAoc2VydmVyIG9yIGJyb3dzZXIpXG4gKiBcbiAqIC0gcHVyZSBqYXZhc2NyaXB0IC0gc2VydmVyIGNvbXBhdGlibGUsIGJyb3dzZXIgY29tcGF0aWJsZVxuICogLSBkb250IHJlbHkgb24gdGhlIGJyb3dzZXIgZG9tc1xuICogLSBzdXBlciBzaW1wbGUgLSB5b3UgZ2V0IGl0IGltbWVkaWF0ZWx5LCBubyBteXN0ZXJ5LCBubyBtYWdpYyBpbnZvbHZlZFxuICpcbiAqIC0gY3JlYXRlIGEgTWljcm9FdmVudERlYnVnIHdpdGggZ29vZGllcyB0byBkZWJ1Z1xuICogICAtIG1ha2UgaXQgc2FmZXIgdG8gdXNlXG4qL1xuXG4vKiogTk9URTogVGhpcyBsaWJyYXJ5IGlzIGN1c3RvbWl6ZWQgZm9yIE9uc2VuIFVJLiAqL1xuXG52YXIgTWljcm9FdmVudCAgPSBmdW5jdGlvbigpe307XG5NaWNyb0V2ZW50LnByb3RvdHlwZSAgPSB7XG4gIG9uICA6IGZ1bmN0aW9uKGV2ZW50LCBmY3Qpe1xuICAgIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgICB0aGlzLl9ldmVudHNbZXZlbnRdID0gdGhpcy5fZXZlbnRzW2V2ZW50XSB8fCBbXTtcbiAgICB0aGlzLl9ldmVudHNbZXZlbnRdLnB1c2goZmN0KTtcbiAgfSxcbiAgb25jZSA6IGZ1bmN0aW9uKGV2ZW50LCBmY3Qpe1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgc2VsZi5vZmYoZXZlbnQsIHdyYXBwZXIpO1xuICAgICAgcmV0dXJuIGZjdC5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgdGhpcy5vbihldmVudCwgd3JhcHBlcik7XG4gIH0sXG4gIG9mZiAgOiBmdW5jdGlvbihldmVudCwgZmN0KXtcbiAgICB0aGlzLl9ldmVudHMgPSB0aGlzLl9ldmVudHMgfHwge307XG4gICAgaWYoIGV2ZW50IGluIHRoaXMuX2V2ZW50cyA9PT0gZmFsc2UgICkgIHJldHVybjtcblxuICAgIHRoaXMuX2V2ZW50c1tldmVudF0gPSB0aGlzLl9ldmVudHNbZXZlbnRdXG4gICAgICAuZmlsdGVyKGZ1bmN0aW9uKF9mY3QpIHtcbiAgICAgICAgaWYgKGZjdCkge1xuICAgICAgICAgICByZXR1cm4gZmN0ICE9PSBfZmN0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0sXG4gIGVtaXQgOiBmdW5jdGlvbihldmVudCAvKiAsIGFyZ3MuLi4gKi8pe1xuICAgIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgICBpZiggZXZlbnQgaW4gdGhpcy5fZXZlbnRzID09PSBmYWxzZSAgKSAgcmV0dXJuO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzLl9ldmVudHNbZXZlbnRdLmxlbmd0aDsgaSsrKXtcbiAgICAgIHRoaXMuX2V2ZW50c1tldmVudF1baV0uYXBwbHkodGhpcywgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIG1peGluIHdpbGwgZGVsZWdhdGUgYWxsIE1pY3JvRXZlbnQuanMgZnVuY3Rpb24gaW4gdGhlIGRlc3RpbmF0aW9uIG9iamVjdFxuICpcbiAqIC0gcmVxdWlyZSgnTWljcm9FdmVudCcpLm1peGluKEZvb2Jhcikgd2lsbCBtYWtlIEZvb2JhciBhYmxlIHRvIHVzZSBNaWNyb0V2ZW50XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHRoZSBvYmplY3Qgd2hpY2ggd2lsbCBzdXBwb3J0IE1pY3JvRXZlbnRcbiovXG5NaWNyb0V2ZW50Lm1peGluICA9IGZ1bmN0aW9uKGRlc3RPYmplY3Qpe1xuICB2YXIgcHJvcHMgPSBbJ29uJywgJ29uY2UnLCAnb2ZmJywgJ2VtaXQnXTtcbiAgZm9yKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSArKyl7XG4gICAgaWYoIHR5cGVvZiBkZXN0T2JqZWN0ID09PSAnZnVuY3Rpb24nICl7XG4gICAgICBkZXN0T2JqZWN0LnByb3RvdHlwZVtwcm9wc1tpXV0gID0gTWljcm9FdmVudC5wcm90b3R5cGVbcHJvcHNbaV1dO1xuICAgIH1lbHNle1xuICAgICAgZGVzdE9iamVjdFtwcm9wc1tpXV0gPSBNaWNyb0V2ZW50LnByb3RvdHlwZVtwcm9wc1tpXV07XG4gICAgfVxuICB9XG59XG5cbi8vIGV4cG9ydCBpbiBjb21tb24ganNcbmlmKCB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmICgnZXhwb3J0cycgaW4gbW9kdWxlKSl7XG4gIG1vZHVsZS5leHBvcnRzICA9IE1pY3JvRXZlbnQ7XG59XG5cbndpbmRvdy5NaWNyb0V2ZW50ID0gTWljcm9FdmVudDtcbiIsIihmdW5jdGlvbiAocm9vdCkge1xuXG4gIC8vIFN0b3JlIHNldFRpbWVvdXQgcmVmZXJlbmNlIHNvIHByb21pc2UtcG9seWZpbGwgd2lsbCBiZSB1bmFmZmVjdGVkIGJ5XG4gIC8vIG90aGVyIGNvZGUgbW9kaWZ5aW5nIHNldFRpbWVvdXQgKGxpa2Ugc2lub24udXNlRmFrZVRpbWVycygpKVxuICB2YXIgc2V0VGltZW91dEZ1bmMgPSBzZXRUaW1lb3V0O1xuXG4gIGZ1bmN0aW9uIG5vb3AoKSB7fVxuICBcbiAgLy8gUG9seWZpbGwgZm9yIEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kXG4gIGZ1bmN0aW9uIGJpbmQoZm4sIHRoaXNBcmcpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgZm4uYXBwbHkodGhpc0FyZywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gUHJvbWlzZShmbikge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ29iamVjdCcpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Byb21pc2VzIG11c3QgYmUgY29uc3RydWN0ZWQgdmlhIG5ldycpO1xuICAgIGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHRocm93IG5ldyBUeXBlRXJyb3IoJ25vdCBhIGZ1bmN0aW9uJyk7XG4gICAgdGhpcy5fc3RhdGUgPSAwO1xuICAgIHRoaXMuX2hhbmRsZWQgPSBmYWxzZTtcbiAgICB0aGlzLl92YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9kZWZlcnJlZHMgPSBbXTtcblxuICAgIGRvUmVzb2x2ZShmbiwgdGhpcyk7XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGUoc2VsZiwgZGVmZXJyZWQpIHtcbiAgICB3aGlsZSAoc2VsZi5fc3RhdGUgPT09IDMpIHtcbiAgICAgIHNlbGYgPSBzZWxmLl92YWx1ZTtcbiAgICB9XG4gICAgaWYgKHNlbGYuX3N0YXRlID09PSAwKSB7XG4gICAgICBzZWxmLl9kZWZlcnJlZHMucHVzaChkZWZlcnJlZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHNlbGYuX2hhbmRsZWQgPSB0cnVlO1xuICAgIFByb21pc2UuX2ltbWVkaWF0ZUZuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBjYiA9IHNlbGYuX3N0YXRlID09PSAxID8gZGVmZXJyZWQub25GdWxmaWxsZWQgOiBkZWZlcnJlZC5vblJlamVjdGVkO1xuICAgICAgaWYgKGNiID09PSBudWxsKSB7XG4gICAgICAgIChzZWxmLl9zdGF0ZSA9PT0gMSA/IHJlc29sdmUgOiByZWplY3QpKGRlZmVycmVkLnByb21pc2UsIHNlbGYuX3ZhbHVlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIHJldDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldCA9IGNiKHNlbGYuX3ZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGRlZmVycmVkLnByb21pc2UsIGUpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXNvbHZlKGRlZmVycmVkLnByb21pc2UsIHJldCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZXNvbHZlKHNlbGYsIG5ld1ZhbHVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFByb21pc2UgUmVzb2x1dGlvbiBQcm9jZWR1cmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9wcm9taXNlcy1hcGx1cy9wcm9taXNlcy1zcGVjI3RoZS1wcm9taXNlLXJlc29sdXRpb24tcHJvY2VkdXJlXG4gICAgICBpZiAobmV3VmFsdWUgPT09IHNlbGYpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0EgcHJvbWlzZSBjYW5ub3QgYmUgcmVzb2x2ZWQgd2l0aCBpdHNlbGYuJyk7XG4gICAgICBpZiAobmV3VmFsdWUgJiYgKHR5cGVvZiBuZXdWYWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG5ld1ZhbHVlID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICB2YXIgdGhlbiA9IG5ld1ZhbHVlLnRoZW47XG4gICAgICAgIGlmIChuZXdWYWx1ZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICBzZWxmLl9zdGF0ZSA9IDM7XG4gICAgICAgICAgc2VsZi5fdmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgICBmaW5hbGUoc2VsZik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgZG9SZXNvbHZlKGJpbmQodGhlbiwgbmV3VmFsdWUpLCBzZWxmKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNlbGYuX3N0YXRlID0gMTtcbiAgICAgIHNlbGYuX3ZhbHVlID0gbmV3VmFsdWU7XG4gICAgICBmaW5hbGUoc2VsZik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KHNlbGYsIGUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlamVjdChzZWxmLCBuZXdWYWx1ZSkge1xuICAgIHNlbGYuX3N0YXRlID0gMjtcbiAgICBzZWxmLl92YWx1ZSA9IG5ld1ZhbHVlO1xuICAgIGZpbmFsZShzZWxmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmFsZShzZWxmKSB7XG4gICAgaWYgKHNlbGYuX3N0YXRlID09PSAyICYmIHNlbGYuX2RlZmVycmVkcy5sZW5ndGggPT09IDApIHtcbiAgICAgIFByb21pc2UuX2ltbWVkaWF0ZUZuKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXNlbGYuX2hhbmRsZWQpIHtcbiAgICAgICAgICBQcm9taXNlLl91bmhhbmRsZWRSZWplY3Rpb25GbihzZWxmLl92YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzZWxmLl9kZWZlcnJlZHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGhhbmRsZShzZWxmLCBzZWxmLl9kZWZlcnJlZHNbaV0pO1xuICAgIH1cbiAgICBzZWxmLl9kZWZlcnJlZHMgPSBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gSGFuZGxlcihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgcHJvbWlzZSkge1xuICAgIHRoaXMub25GdWxmaWxsZWQgPSB0eXBlb2Ygb25GdWxmaWxsZWQgPT09ICdmdW5jdGlvbicgPyBvbkZ1bGZpbGxlZCA6IG51bGw7XG4gICAgdGhpcy5vblJlamVjdGVkID0gdHlwZW9mIG9uUmVqZWN0ZWQgPT09ICdmdW5jdGlvbicgPyBvblJlamVjdGVkIDogbnVsbDtcbiAgICB0aGlzLnByb21pc2UgPSBwcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2UgYSBwb3RlbnRpYWxseSBtaXNiZWhhdmluZyByZXNvbHZlciBmdW5jdGlvbiBhbmQgbWFrZSBzdXJlXG4gICAqIG9uRnVsZmlsbGVkIGFuZCBvblJlamVjdGVkIGFyZSBvbmx5IGNhbGxlZCBvbmNlLlxuICAgKlxuICAgKiBNYWtlcyBubyBndWFyYW50ZWVzIGFib3V0IGFzeW5jaHJvbnkuXG4gICAqL1xuICBmdW5jdGlvbiBkb1Jlc29sdmUoZm4sIHNlbGYpIHtcbiAgICB2YXIgZG9uZSA9IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICBmbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKGRvbmUpIHJldHVybjtcbiAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgIHJlc29sdmUoc2VsZiwgdmFsdWUpO1xuICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICBpZiAoZG9uZSkgcmV0dXJuO1xuICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgcmVqZWN0KHNlbGYsIHJlYXNvbik7XG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGRvbmUpIHJldHVybjtcbiAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgcmVqZWN0KHNlbGYsIGV4KTtcbiAgICB9XG4gIH1cblxuICBQcm9taXNlLnByb3RvdHlwZVsnY2F0Y2gnXSA9IGZ1bmN0aW9uIChvblJlamVjdGVkKSB7XG4gICAgcmV0dXJuIHRoaXMudGhlbihudWxsLCBvblJlamVjdGVkKTtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24gKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gICAgdmFyIHByb20gPSBuZXcgKHRoaXMuY29uc3RydWN0b3IpKG5vb3ApO1xuXG4gICAgaGFuZGxlKHRoaXMsIG5ldyBIYW5kbGVyKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBwcm9tKSk7XG4gICAgcmV0dXJuIHByb207XG4gIH07XG5cbiAgUHJvbWlzZS5hbGwgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcnIpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHJlc29sdmUoW10pO1xuICAgICAgdmFyIHJlbWFpbmluZyA9IGFyZ3MubGVuZ3RoO1xuXG4gICAgICBmdW5jdGlvbiByZXMoaSwgdmFsKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKHZhbCAmJiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIHZhciB0aGVuID0gdmFsLnRoZW47XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgdGhlbi5jYWxsKHZhbCwgZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgICAgICAgIHJlcyhpLCB2YWwpO1xuICAgICAgICAgICAgICB9LCByZWplY3QpO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGFyZ3NbaV0gPSB2YWw7XG4gICAgICAgICAgaWYgKC0tcmVtYWluaW5nID09PSAwKSB7XG4gICAgICAgICAgICByZXNvbHZlKGFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICByZWplY3QoZXgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZXMoaSwgYXJnc1tpXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgUHJvbWlzZS5yZXNvbHZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUuY29uc3RydWN0b3IgPT09IFByb21pc2UpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgIH0pO1xuICB9O1xuXG4gIFByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHJlamVjdCh2YWx1ZSk7XG4gICAgfSk7XG4gIH07XG5cbiAgUHJvbWlzZS5yYWNlID0gZnVuY3Rpb24gKHZhbHVlcykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gdmFsdWVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhbHVlc1tpXS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gVXNlIHBvbHlmaWxsIGZvciBzZXRJbW1lZGlhdGUgZm9yIHBlcmZvcm1hbmNlIGdhaW5zXG4gIFByb21pc2UuX2ltbWVkaWF0ZUZuID0gKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09ICdmdW5jdGlvbicgJiYgZnVuY3Rpb24gKGZuKSB7IHNldEltbWVkaWF0ZShmbik7IH0pIHx8XG4gICAgZnVuY3Rpb24gKGZuKSB7XG4gICAgICBzZXRUaW1lb3V0RnVuYyhmbiwgMCk7XG4gICAgfTtcblxuICBQcm9taXNlLl91bmhhbmRsZWRSZWplY3Rpb25GbiA9IGZ1bmN0aW9uIF91bmhhbmRsZWRSZWplY3Rpb25GbihlcnIpIHtcbiAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUpIHtcbiAgICAgIGNvbnNvbGUud2FybignUG9zc2libGUgVW5oYW5kbGVkIFByb21pc2UgUmVqZWN0aW9uOicsIGVycik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogU2V0IHRoZSBpbW1lZGlhdGUgZnVuY3Rpb24gdG8gZXhlY3V0ZSBjYWxsYmFja3NcbiAgICogQHBhcmFtIGZuIHtmdW5jdGlvbn0gRnVuY3Rpb24gdG8gZXhlY3V0ZVxuICAgKiBAZGVwcmVjYXRlZFxuICAgKi9cbiAgUHJvbWlzZS5fc2V0SW1tZWRpYXRlRm4gPSBmdW5jdGlvbiBfc2V0SW1tZWRpYXRlRm4oZm4pIHtcbiAgICBQcm9taXNlLl9pbW1lZGlhdGVGbiA9IGZuO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDaGFuZ2UgdGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgb24gdW5oYW5kbGVkIHJlamVjdGlvblxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBleGVjdXRlIG9uIHVuaGFuZGxlZCByZWplY3Rpb25cbiAgICogQGRlcHJlY2F0ZWRcbiAgICovXG4gIFByb21pc2UuX3NldFVuaGFuZGxlZFJlamVjdGlvbkZuID0gZnVuY3Rpb24gX3NldFVuaGFuZGxlZFJlamVjdGlvbkZuKGZuKSB7XG4gICAgUHJvbWlzZS5fdW5oYW5kbGVkUmVqZWN0aW9uRm4gPSBmbjtcbiAgfTtcblxuICBpZiAoIXdpbmRvdy5Qcm9taXNlKSB7XG4gICAgd2luZG93LlByb21pc2UgPSBQcm9taXNlO1xuICB9XG59KSh0aGlzKTtcbiIsIi8qXG5Db3B5cmlnaHQgKGMpIDIwMTIgQmFybmVzYW5kbm9ibGUuY29tLCBsbGMsIERvbmF2b24gV2VzdCwgYW5kIERvbWVuaWMgRGVuaWNvbGFcblxuUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nXG5hIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcblwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xud2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvXG5wZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG9cbnRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbmluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG5NRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRVxuTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTlxuT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OXG5XSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCB1bmRlZmluZWQpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIGlmIChnbG9iYWwuc2V0SW1tZWRpYXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbmV4dEhhbmRsZSA9IDE7IC8vIFNwZWMgc2F5cyBncmVhdGVyIHRoYW4gemVyb1xuICAgIHZhciB0YXNrc0J5SGFuZGxlID0ge307XG4gICAgdmFyIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IGZhbHNlO1xuICAgIHZhciBkb2MgPSBnbG9iYWwuZG9jdW1lbnQ7XG4gICAgdmFyIHNldEltbWVkaWF0ZTtcblxuICAgIGZ1bmN0aW9uIGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJncykge1xuICAgICAgICB0YXNrc0J5SGFuZGxlW25leHRIYW5kbGVdID0gcGFydGlhbGx5QXBwbGllZC5hcHBseSh1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgICByZXR1cm4gbmV4dEhhbmRsZSsrO1xuICAgIH1cblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gYWNjZXB0cyB0aGUgc2FtZSBhcmd1bWVudHMgYXMgc2V0SW1tZWRpYXRlLCBidXRcbiAgICAvLyByZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCByZXF1aXJlcyBubyBhcmd1bWVudHMuXG4gICAgZnVuY3Rpb24gcGFydGlhbGx5QXBwbGllZChoYW5kbGVyKSB7XG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGhhbmRsZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGhhbmRsZXIuYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgKG5ldyBGdW5jdGlvbihcIlwiICsgaGFuZGxlcikpKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuSWZQcmVzZW50KGhhbmRsZSkge1xuICAgICAgICAvLyBGcm9tIHRoZSBzcGVjOiBcIldhaXQgdW50aWwgYW55IGludm9jYXRpb25zIG9mIHRoaXMgYWxnb3JpdGhtIHN0YXJ0ZWQgYmVmb3JlIHRoaXMgb25lIGhhdmUgY29tcGxldGVkLlwiXG4gICAgICAgIC8vIFNvIGlmIHdlJ3JlIGN1cnJlbnRseSBydW5uaW5nIGEgdGFzaywgd2UnbGwgbmVlZCB0byBkZWxheSB0aGlzIGludm9jYXRpb24uXG4gICAgICAgIGlmIChjdXJyZW50bHlSdW5uaW5nQVRhc2spIHtcbiAgICAgICAgICAgIC8vIERlbGF5IGJ5IGRvaW5nIGEgc2V0VGltZW91dC4gc2V0SW1tZWRpYXRlIHdhcyB0cmllZCBpbnN0ZWFkLCBidXQgaW4gRmlyZWZveCA3IGl0IGdlbmVyYXRlZCBhXG4gICAgICAgICAgICAvLyBcInRvbyBtdWNoIHJlY3Vyc2lvblwiIGVycm9yLlxuICAgICAgICAgICAgc2V0VGltZW91dChwYXJ0aWFsbHlBcHBsaWVkKHJ1bklmUHJlc2VudCwgaGFuZGxlKSwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGFzayA9IHRhc2tzQnlIYW5kbGVbaGFuZGxlXTtcbiAgICAgICAgICAgIGlmICh0YXNrKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0YXNrKCk7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJJbW1lZGlhdGUoaGFuZGxlKTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xlYXJJbW1lZGlhdGUoaGFuZGxlKSB7XG4gICAgICAgIGRlbGV0ZSB0YXNrc0J5SGFuZGxlW2hhbmRsZV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHByb2Nlc3MubmV4dFRpY2socGFydGlhbGx5QXBwbGllZChydW5JZlByZXNlbnQsIGhhbmRsZSkpO1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYW5Vc2VQb3N0TWVzc2FnZSgpIHtcbiAgICAgICAgLy8gVGhlIHRlc3QgYWdhaW5zdCBgaW1wb3J0U2NyaXB0c2AgcHJldmVudHMgdGhpcyBpbXBsZW1lbnRhdGlvbiBmcm9tIGJlaW5nIGluc3RhbGxlZCBpbnNpZGUgYSB3ZWIgd29ya2VyLFxuICAgICAgICAvLyB3aGVyZSBgZ2xvYmFsLnBvc3RNZXNzYWdlYCBtZWFucyBzb21ldGhpbmcgY29tcGxldGVseSBkaWZmZXJlbnQgYW5kIGNhbid0IGJlIHVzZWQgZm9yIHRoaXMgcHVycG9zZS5cbiAgICAgICAgaWYgKGdsb2JhbC5wb3N0TWVzc2FnZSAmJiAhZ2xvYmFsLmltcG9ydFNjcmlwdHMpIHtcbiAgICAgICAgICAgIHZhciBwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBvbGRPbk1lc3NhZ2UgPSBnbG9iYWwub25tZXNzYWdlO1xuICAgICAgICAgICAgZ2xvYmFsLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlSXNBc3luY2hyb25vdXMgPSBmYWxzZTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBnbG9iYWwucG9zdE1lc3NhZ2UoXCJcIiwgXCIqXCIpO1xuICAgICAgICAgICAgZ2xvYmFsLm9ubWVzc2FnZSA9IG9sZE9uTWVzc2FnZTtcbiAgICAgICAgICAgIHJldHVybiBwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFBvc3RNZXNzYWdlSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIC8vIEluc3RhbGxzIGFuIGV2ZW50IGhhbmRsZXIgb24gYGdsb2JhbGAgZm9yIHRoZSBgbWVzc2FnZWAgZXZlbnQ6IHNlZVxuICAgICAgICAvLyAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0RPTS93aW5kb3cucG9zdE1lc3NhZ2VcbiAgICAgICAgLy8gKiBodHRwOi8vd3d3LndoYXR3Zy5vcmcvc3BlY3Mvd2ViLWFwcHMvY3VycmVudC13b3JrL211bHRpcGFnZS9jb21tcy5odG1sI2Nyb3NzRG9jdW1lbnRNZXNzYWdlc1xuXG4gICAgICAgIHZhciBtZXNzYWdlUHJlZml4ID0gXCJzZXRJbW1lZGlhdGUkXCIgKyBNYXRoLnJhbmRvbSgpICsgXCIkXCI7XG4gICAgICAgIHZhciBvbkdsb2JhbE1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LnNvdXJjZSA9PT0gZ2xvYmFsICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIGV2ZW50LmRhdGEgPT09IFwic3RyaW5nXCIgJiZcbiAgICAgICAgICAgICAgICBldmVudC5kYXRhLmluZGV4T2YobWVzc2FnZVByZWZpeCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICBydW5JZlByZXNlbnQoK2V2ZW50LmRhdGEuc2xpY2UobWVzc2FnZVByZWZpeC5sZW5ndGgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoZ2xvYmFsLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBvbkdsb2JhbE1lc3NhZ2UsIGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsb2JhbC5hdHRhY2hFdmVudChcIm9ubWVzc2FnZVwiLCBvbkdsb2JhbE1lc3NhZ2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gYWRkRnJvbVNldEltbWVkaWF0ZUFyZ3VtZW50cyhhcmd1bWVudHMpO1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKG1lc3NhZ2VQcmVmaXggKyBoYW5kbGUsIFwiKlwiKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbE1lc3NhZ2VDaGFubmVsSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHZhciBjaGFubmVsID0gbmV3IE1lc3NhZ2VDaGFubmVsKCk7XG4gICAgICAgIGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBldmVudC5kYXRhO1xuICAgICAgICAgICAgcnVuSWZQcmVzZW50KGhhbmRsZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gYWRkRnJvbVNldEltbWVkaWF0ZUFyZ3VtZW50cyhhcmd1bWVudHMpO1xuICAgICAgICAgICAgY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZShoYW5kbGUpO1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsUmVhZHlTdGF0ZUNoYW5nZUltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICB2YXIgaHRtbCA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIDxzY3JpcHQ+IGVsZW1lbnQ7IGl0cyByZWFkeXN0YXRlY2hhbmdlIGV2ZW50IHdpbGwgYmUgZmlyZWQgYXN5bmNocm9ub3VzbHkgb25jZSBpdCBpcyBpbnNlcnRlZFxuICAgICAgICAgICAgLy8gaW50byB0aGUgZG9jdW1lbnQuIERvIHNvLCB0aHVzIHF1ZXVpbmcgdXAgdGhlIHRhc2suIFJlbWVtYmVyIHRvIGNsZWFuIHVwIG9uY2UgaXQncyBiZWVuIGNhbGxlZC5cbiAgICAgICAgICAgIHZhciBzY3JpcHQgPSBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKTtcbiAgICAgICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaHRtbC5yZW1vdmVDaGlsZChzY3JpcHQpO1xuICAgICAgICAgICAgICAgIHNjcmlwdCA9IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHRtbC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsU2V0VGltZW91dEltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHBhcnRpYWxseUFwcGxpZWQocnVuSWZQcmVzZW50LCBoYW5kbGUpLCAwKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSWYgc3VwcG9ydGVkLCB3ZSBzaG91bGQgYXR0YWNoIHRvIHRoZSBwcm90b3R5cGUgb2YgZ2xvYmFsLCBzaW5jZSB0aGF0IGlzIHdoZXJlIHNldFRpbWVvdXQgZXQgYWwuIGxpdmUuXG4gICAgdmFyIGF0dGFjaFRvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZihnbG9iYWwpO1xuICAgIGF0dGFjaFRvID0gYXR0YWNoVG8gJiYgYXR0YWNoVG8uc2V0VGltZW91dCA/IGF0dGFjaFRvIDogZ2xvYmFsO1xuXG4gICAgLy8gRG9uJ3QgZ2V0IGZvb2xlZCBieSBlLmcuIGJyb3dzZXJpZnkgZW52aXJvbm1lbnRzLlxuICAgIGlmICh7fS50b1N0cmluZy5jYWxsKGdsb2JhbC5wcm9jZXNzKSA9PT0gXCJbb2JqZWN0IHByb2Nlc3NdXCIpIHtcbiAgICAgICAgLy8gRm9yIE5vZGUuanMgYmVmb3JlIDAuOVxuICAgICAgICBpbnN0YWxsTmV4dFRpY2tJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChjYW5Vc2VQb3N0TWVzc2FnZSgpKSB7XG4gICAgICAgIC8vIEZvciBub24tSUUxMCBtb2Rlcm4gYnJvd3NlcnNcbiAgICAgICAgaW5zdGFsbFBvc3RNZXNzYWdlSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoZ2xvYmFsLk1lc3NhZ2VDaGFubmVsKSB7XG4gICAgICAgIC8vIEZvciB3ZWIgd29ya2Vycywgd2hlcmUgc3VwcG9ydGVkXG4gICAgICAgIGluc3RhbGxNZXNzYWdlQ2hhbm5lbEltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGRvYyAmJiBcIm9ucmVhZHlzdGF0ZWNoYW5nZVwiIGluIGRvYy5jcmVhdGVFbGVtZW50KFwic2NyaXB0XCIpKSB7XG4gICAgICAgIC8vIEZvciBJRSA24oCTOFxuICAgICAgICBpbnN0YWxsUmVhZHlTdGF0ZUNoYW5nZUltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGb3Igb2xkZXIgYnJvd3NlcnNcbiAgICAgICAgaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbigpO1xuICAgIH1cblxuICAgIGF0dGFjaFRvLnNldEltbWVkaWF0ZSA9IHNldEltbWVkaWF0ZTtcbiAgICBhdHRhY2hUby5jbGVhckltbWVkaWF0ZSA9IGNsZWFySW1tZWRpYXRlO1xufShmdW5jdGlvbigpIHtyZXR1cm4gdGhpczt9KCkpKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBWaWV3cG9ydCgpIHtcblxuICAgICAgICB0aGlzLlBSRV9JT1M3X1ZJRVdQT1JUID0gXCJpbml0aWFsLXNjYWxlPTEsIG1heGltdW0tc2NhbGU9MSwgdXNlci1zY2FsYWJsZT1ub1wiO1xuICAgICAgICB0aGlzLklPUzdfVklFV1BPUlQgPSBcImluaXRpYWwtc2NhbGU9MSwgbWF4aW11bS1zY2FsZT0xLCB1c2VyLXNjYWxhYmxlPW5vXCI7XG4gICAgICAgIHRoaXMuREVGQVVMVF9WSUVXUE9SVCA9IFwiaW5pdGlhbC1zY2FsZT0xLCBtYXhpbXVtLXNjYWxlPTEsIHVzZXItc2NhbGFibGU9bm9cIjtcblxuICAgICAgICB0aGlzLmVuc3VyZVZpZXdwb3J0RWxlbWVudCgpO1xuICAgICAgICB0aGlzLnBsYXRmb3JtID0ge307XG4gICAgICAgIHRoaXMucGxhdGZvcm0ubmFtZSA9IHRoaXMuZ2V0UGxhdGZvcm1OYW1lKCk7XG4gICAgICAgIHRoaXMucGxhdGZvcm0udmVyc2lvbiA9IHRoaXMuZ2V0UGxhdGZvcm1WZXJzaW9uKCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFZpZXdwb3J0LnByb3RvdHlwZS5lbnN1cmVWaWV3cG9ydEVsZW1lbnQgPSBmdW5jdGlvbigpe1xuICAgICAgICB0aGlzLnZpZXdwb3J0RWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT12aWV3cG9ydF0nKTtcbiAgICAgICAgaWYoIXRoaXMudmlld3BvcnRFbGVtZW50KXtcbiAgICAgICAgICAgIHRoaXMudmlld3BvcnRFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbWV0YScpO1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydEVsZW1lbnQubmFtZSA9IFwidmlld3BvcnRcIjtcbiAgICAgICAgICAgIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQodGhpcy52aWV3cG9ydEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIFZpZXdwb3J0LnByb3RvdHlwZS5zZXR1cCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMudmlld3BvcnRFbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy52aWV3cG9ydEVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLW5vLWFkanVzdCcpID09IFwidHJ1ZVwiKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMudmlld3BvcnRFbGVtZW50LmdldEF0dHJpYnV0ZSgnY29udGVudCcpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wbGF0Zm9ybS5uYW1lID09ICdpb3MnKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGxhdGZvcm0udmVyc2lvbiA+PSA3ICYmIGlzV2ViVmlldygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnRFbGVtZW50LnNldEF0dHJpYnV0ZSgnY29udGVudCcsIHRoaXMuSU9TN19WSUVXUE9SVCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3cG9ydEVsZW1lbnQuc2V0QXR0cmlidXRlKCdjb250ZW50JywgdGhpcy5QUkVfSU9TN19WSUVXUE9SVCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdwb3J0RWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2NvbnRlbnQnLCB0aGlzLkRFRkFVTFRfVklFV1BPUlQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gaXNXZWJWaWV3KCkge1xuICAgICAgICAgICAgcmV0dXJuICEhKHdpbmRvdy5jb3Jkb3ZhIHx8IHdpbmRvdy5waG9uZWdhcCB8fCB3aW5kb3cuUGhvbmVHYXApO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFZpZXdwb3J0LnByb3RvdHlwZS5nZXRQbGF0Zm9ybU5hbWUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0FuZHJvaWQvaSkpIHtcbiAgICAgICAgICAgIHJldHVybiBcImFuZHJvaWRcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9pUGhvbmV8aVBhZHxpUG9kL2kpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJpb3NcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVua25vd25cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgVmlld3BvcnQucHJvdG90eXBlLmdldFBsYXRmb3JtVmVyc2lvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgc3RhcnQgPSB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdPUyAnKTtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5OdW1iZXIod2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQuc3Vic3RyKHN0YXJ0ICsgMywgMykucmVwbGFjZSgnXycsICcuJykpO1xuICAgIH07XG5cbiAgICB3aW5kb3cuVmlld3BvcnQgPSBWaWV3cG9ydDtcbn0pKCk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBPcGVuIFRlY2hub2xvZ2llcywgSW5jLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4gIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAuICBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbi8vIEphdmFTY3JpcHQgRHluYW1pYyBDb250ZW50IHNoaW0gZm9yIFdpbmRvd3MgU3RvcmUgYXBwc1xuKGZ1bmN0aW9uICgpIHtcblxuICAgIGlmICh3aW5kb3cuTVNBcHAgJiYgTVNBcHAuZXhlY1Vuc2FmZUxvY2FsRnVuY3Rpb24pIHtcblxuICAgICAgICAvLyBTb21lIG5vZGVzIHdpbGwgaGF2ZSBhbiBcImF0dHJpYnV0ZXNcIiBwcm9wZXJ0eSB3aGljaCBzaGFkb3dzIHRoZSBOb2RlLnByb3RvdHlwZS5hdHRyaWJ1dGVzIHByb3BlcnR5XG4gICAgICAgIC8vICBhbmQgbWVhbnMgd2UgZG9uJ3QgYWN0dWFsbHkgc2VlIHRoZSBhdHRyaWJ1dGVzIG9mIHRoZSBOb2RlIChpbnRlcmVzdGluZ2x5IHRoZSBWUyBkZWJ1ZyBjb25zb2xlXG4gICAgICAgIC8vICBhcHBlYXJzIHRvIHN1ZmZlciBmcm9tIHRoZSBzYW1lIGlzc3VlKS5cbiAgICAgICAgLy9cbiAgICAgICAgdmFyIEVsZW1lbnRfc2V0QXR0cmlidXRlID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihFbGVtZW50LnByb3RvdHlwZSwgXCJzZXRBdHRyaWJ1dGVcIikudmFsdWU7XG4gICAgICAgIHZhciBFbGVtZW50X3JlbW92ZUF0dHJpYnV0ZSA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoRWxlbWVudC5wcm90b3R5cGUsIFwicmVtb3ZlQXR0cmlidXRlXCIpLnZhbHVlO1xuICAgICAgICB2YXIgSFRNTEVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRIVE1MUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihIVE1MRWxlbWVudC5wcm90b3R5cGUsIFwiaW5zZXJ0QWRqYWNlbnRIVE1MXCIpO1xuICAgICAgICB2YXIgTm9kZV9nZXRfYXR0cmlidXRlcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTm9kZS5wcm90b3R5cGUsIFwiYXR0cmlidXRlc1wiKS5nZXQ7XG4gICAgICAgIHZhciBOb2RlX2dldF9jaGlsZE5vZGVzID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihOb2RlLnByb3RvdHlwZSwgXCJjaGlsZE5vZGVzXCIpLmdldDtcbiAgICAgICAgdmFyIGRldGVjdGlvbkRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0QXR0cmlidXRlcyhlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gTm9kZV9nZXRfYXR0cmlidXRlcy5jYWxsKGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gc2V0QXR0cmlidXRlKGVsZW1lbnQsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgRWxlbWVudF9zZXRBdHRyaWJ1dGUuY2FsbChlbGVtZW50LCBhdHRyaWJ1dGUsIHZhbHVlKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBpZ25vcmVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlbW92ZUF0dHJpYnV0ZShlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICAgICAgICAgIEVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlLmNhbGwoZWxlbWVudCwgYXR0cmlidXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNoaWxkTm9kZXMoZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIE5vZGVfZ2V0X2NoaWxkTm9kZXMuY2FsbChlbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGVtcHR5KGVsZW1lbnQpIHtcbiAgICAgICAgICAgIHdoaWxlIChlbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVDaGlsZChlbGVtZW50Lmxhc3RDaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBpbnNlcnRBZGphY2VudEhUTUwoZWxlbWVudCwgcG9zaXRpb24sIGh0bWwpIHtcbiAgICAgICAgICAgIEhUTUxFbGVtZW50X2luc2VydEFkamFjZW50SFRNTFByb3BlcnR5RGVzY3JpcHRvci52YWx1ZS5jYWxsKGVsZW1lbnQsIHBvc2l0aW9uLCBodG1sKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGluVW5zYWZlTW9kZSgpIHtcbiAgICAgICAgICAgIHZhciBpc1Vuc2FmZSA9IHRydWU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGRldGVjdGlvbkRpdi5pbm5lckhUTUwgPSBcIjx0ZXN0Lz5cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChleCkge1xuICAgICAgICAgICAgICAgIGlzVW5zYWZlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBpc1Vuc2FmZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNsZWFuc2UoaHRtbCwgdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGNsZWFuZXIgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoXCJjbGVhbmVyXCIpO1xuICAgICAgICAgICAgZW1wdHkoY2xlYW5lci5kb2N1bWVudEVsZW1lbnQpO1xuICAgICAgICAgICAgTVNBcHAuZXhlY1Vuc2FmZUxvY2FsRnVuY3Rpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGluc2VydEFkamFjZW50SFRNTChjbGVhbmVyLmRvY3VtZW50RWxlbWVudCwgXCJhZnRlcmJlZ2luXCIsIGh0bWwpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHZhciBzY3JpcHRzID0gY2xlYW5lci5kb2N1bWVudEVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChcInNjcmlwdFwiKTtcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwoc2NyaXB0cywgZnVuY3Rpb24gKHNjcmlwdCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoc2NyaXB0LnR5cGUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHQudHlwZSA9IFwidGV4dC9pbmVydFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0L2phdmFzY3JpcHRcIjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInRleHQvZWNtYXNjcmlwdFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwidGV4dC94LWphdmFzY3JpcHRcIjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInRleHQvanNjcmlwdFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwidGV4dC9saXZlc2NyaXB0XCI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0ZXh0L2phdmFzY3JpcHQxLjFcIjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInRleHQvamF2YXNjcmlwdDEuMlwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwidGV4dC9qYXZhc2NyaXB0MS4zXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHQudHlwZSA9IFwidGV4dC9pbmVydC1cIiArIHNjcmlwdC50eXBlLnNsaWNlKFwidGV4dC9cIi5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJhcHBsaWNhdGlvbi9lY21hc2NyaXB0XCI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJhcHBsaWNhdGlvbi94LWphdmFzY3JpcHRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcmlwdC50eXBlID0gXCJhcHBsaWNhdGlvbi9pbmVydC1cIiArIHNjcmlwdC50eXBlLnNsaWNlKFwiYXBwbGljYXRpb24vXCIubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYW5zZUF0dHJpYnV0ZXMoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVzID0gZ2V0QXR0cmlidXRlcyhlbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoYXR0cmlidXRlcyAmJiBhdHRyaWJ1dGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHRoZSBhdHRyaWJ1dGVzIGNvbGxlY3Rpb24gaXMgbGl2ZSBpdCBpcyBzaW1wbGVyIHRvIHF1ZXVlIHVwIHRoZSByZW5hbWVzXG4gICAgICAgICAgICAgICAgICAgIHZhciBldmVudHM7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhdHRyaWJ1dGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0cmlidXRlID0gYXR0cmlidXRlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuYW1lID0gYXR0cmlidXRlLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKG5hbWVbMF0gPT09IFwib1wiIHx8IG5hbWVbMF0gPT09IFwiT1wiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuYW1lWzFdID09PSBcIm5cIiB8fCBuYW1lWzFdID09PSBcIk5cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMgPSBldmVudHMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnB1c2goeyBuYW1lOiBhdHRyaWJ1dGUubmFtZSwgdmFsdWU6IGF0dHJpYnV0ZS52YWx1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gZXZlbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZSA9IGV2ZW50c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEF0dHJpYnV0ZShlbGVtZW50LCBcIngtXCIgKyBhdHRyaWJ1dGUubmFtZSwgYXR0cmlidXRlLnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSBjaGlsZE5vZGVzKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjbGVhbnNlQXR0cmlidXRlcyhjaGlsZHJlbltpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2xlYW5zZUF0dHJpYnV0ZXMoY2xlYW5lci5kb2N1bWVudEVsZW1lbnQpO1xuXG4gICAgICAgICAgICB2YXIgY2xlYW5lZE5vZGVzID0gW107XG5cbiAgICAgICAgICAgIGlmICh0YXJnZXRFbGVtZW50LnRhZ05hbWUgPT09ICdIVE1MJykge1xuICAgICAgICAgICAgICAgIGNsZWFuZWROb2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGRvY3VtZW50LmFkb3B0Tm9kZShjbGVhbmVyLmRvY3VtZW50RWxlbWVudCkuY2hpbGROb2Rlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjbGVhbmVyLmhlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYW5lZE5vZGVzID0gY2xlYW5lZE5vZGVzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChkb2N1bWVudC5hZG9wdE5vZGUoY2xlYW5lci5oZWFkKS5jaGlsZE5vZGVzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjbGVhbmVyLmJvZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYW5lZE5vZGVzID0gY2xlYW5lZE5vZGVzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChkb2N1bWVudC5hZG9wdE5vZGUoY2xlYW5lci5ib2R5KS5jaGlsZE5vZGVzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gY2xlYW5lZE5vZGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2xlYW5zZVByb3BlcnR5U2V0dGVyKHByb3BlcnR5LCBzZXR0ZXIpIHtcbiAgICAgICAgICAgIHZhciBwcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEhUTUxFbGVtZW50LnByb3RvdHlwZSwgcHJvcGVydHkpO1xuICAgICAgICAgICAgdmFyIG9yaWdpbmFsU2V0dGVyID0gcHJvcGVydHlEZXNjcmlwdG9yLnNldDtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShIVE1MRWxlbWVudC5wcm90b3R5cGUsIHByb3BlcnR5LCB7XG4gICAgICAgICAgICAgICAgZ2V0OiBwcm9wZXJ0eURlc2NyaXB0b3IuZ2V0LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHdpbmRvdy5XaW5KUyAmJiB3aW5kb3cuV2luSlMuX2V4ZWNVbnNhZmUgJiYgaW5VbnNhZmVNb2RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsU2V0dGVyLmNhbGwodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gY2xlYW5zZSh2YWx1ZSwgdGhhdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBNU0FwcC5leGVjVW5zYWZlTG9jYWxGdW5jdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0dGVyKHByb3BlcnR5RGVzY3JpcHRvciwgdGhhdCwgbm9kZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHByb3BlcnR5RGVzY3JpcHRvci5lbnVtZXJhYmxlLFxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogcHJvcGVydHlEZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNsZWFuc2VQcm9wZXJ0eVNldHRlcihcImlubmVySFRNTFwiLCBmdW5jdGlvbiAocHJvcGVydHlEZXNjcmlwdG9yLCB0YXJnZXQsIGVsZW1lbnRzKSB7XG4gICAgICAgICAgICBlbXB0eSh0YXJnZXQpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGVsZW1lbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LmFwcGVuZENoaWxkKGVsZW1lbnRzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGNsZWFuc2VQcm9wZXJ0eVNldHRlcihcIm91dGVySFRNTFwiLCBmdW5jdGlvbiAocHJvcGVydHlEZXNjcmlwdG9yLCB0YXJnZXQsIGVsZW1lbnRzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gZWxlbWVudHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KFwiYWZ0ZXJlbmRcIiwgZWxlbWVudHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFyZ2V0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGFyZ2V0KTtcbiAgICAgICAgfSk7XG5cbiAgICB9XG5cbn0oKSk7IiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5jb25zdCB1bndyYXAgPSBzdHJpbmcgPT4gc3RyaW5nLnNsaWNlKDEsIC0xKTtcbmNvbnN0IGlzT2JqZWN0U3RyaW5nID0gc3RyaW5nID0+IHN0cmluZy5zdGFydHNXaXRoKCd7JykgJiYgc3RyaW5nLmVuZHNXaXRoKCd9Jyk7XG5jb25zdCBpc0FycmF5U3RyaW5nID0gc3RyaW5nID0+IHN0cmluZy5zdGFydHNXaXRoKCdbJykgJiYgc3RyaW5nLmVuZHNXaXRoKCddJyk7XG5jb25zdCBpc1F1b3RlZFN0cmluZyA9IHN0cmluZyA9PiAoc3RyaW5nLnN0YXJ0c1dpdGgoJ1xcJycpICYmIHN0cmluZy5lbmRzV2l0aCgnXFwnJykpIHx8IChzdHJpbmcuc3RhcnRzV2l0aCgnXCInKSAmJiBzdHJpbmcuZW5kc1dpdGgoJ1wiJykpO1xuXG5jb25zdCBlcnJvciA9ICh0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZykgPT4ge1xuICB0aHJvdyBuZXcgRXJyb3IoJ1VuZXhwZWN0ZWQgdG9rZW4gXFwnJyArIHRva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAnICsgKG9yaWdpbmFsU3RyaW5nLmxlbmd0aCAtIHN0cmluZy5sZW5ndGggLSAxKSArICcgaW4gc3RyaW5nOiBcXCcnICsgb3JpZ2luYWxTdHJpbmcgKyAnXFwnJyk7XG59O1xuXG5jb25zdCBwcm9jZXNzVG9rZW4gPSAodG9rZW4sIHN0cmluZywgb3JpZ2luYWxTdHJpbmcpID0+IHtcbiAgaWYgKHRva2VuID09PSAndHJ1ZScgfHwgdG9rZW4gPT09ICdmYWxzZScpIHtcbiAgICByZXR1cm4gdG9rZW4gPT09ICd0cnVlJztcbiAgfSBlbHNlIGlmIChpc1F1b3RlZFN0cmluZyh0b2tlbikpIHtcbiAgICByZXR1cm4gdW53cmFwKHRva2VuKTtcbiAgfSBlbHNlIGlmICghaXNOYU4odG9rZW4pKSB7XG4gICAgcmV0dXJuICsodG9rZW4pO1xuICB9IGVsc2UgaWYgKGlzT2JqZWN0U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAodG9rZW4pKTtcbiAgfSBlbHNlIGlmIChpc0FycmF5U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZUFycmF5KHVud3JhcCh0b2tlbikpO1xuICB9IGVsc2Uge1xuICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxufTtcblxuY29uc3QgbmV4dFRva2VuID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbUxlZnQoKTtcbiAgbGV0IGxpbWl0ID0gc3RyaW5nLmxlbmd0aDtcblxuICBpZiAoc3RyaW5nWzBdID09PSAnOicgfHwgc3RyaW5nWzBdID09PSAnLCcpIHtcblxuICAgIGxpbWl0ID0gMTtcblxuICB9IGVsc2UgaWYgKHN0cmluZ1swXSA9PT0gJ3snIHx8IHN0cmluZ1swXSA9PT0gJ1snKSB7XG5cbiAgICBjb25zdCBjID0gc3RyaW5nLmNoYXJDb2RlQXQoMCk7XG4gICAgbGV0IG5lc3RlZE9iamVjdCA9IDE7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzdHJpbmcuY2hhckNvZGVBdChpKSA9PT0gYykge1xuICAgICAgICBuZXN0ZWRPYmplY3QrKztcbiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nLmNoYXJDb2RlQXQoaSkgPT09IGMgKyAyKSB7XG4gICAgICAgIG5lc3RlZE9iamVjdC0tO1xuICAgICAgICBpZiAobmVzdGVkT2JqZWN0ID09PSAwKSB7XG4gICAgICAgICAgbGltaXQgPSBpICsgMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICB9IGVsc2UgaWYgKHN0cmluZ1swXSA9PT0gJ1xcJycgfHwgc3RyaW5nWzBdID09PSAnXFxcIicpIHtcblxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoc3RyaW5nW2ldID09PSBzdHJpbmdbMF0pIHtcbiAgICAgICAgbGltaXQgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH0gZWxzZSB7XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKFsnICcsICcsJywgJzonXS5pbmRleE9mKHN0cmluZ1tpXSkgIT09IC0xKSB7XG4gICAgICAgIGxpbWl0ID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIGxpbWl0KTtcbn07XG5cbmNvbnN0IHBhcnNlT2JqZWN0ID0gKHN0cmluZykgPT4ge1xuICBjb25zdCBpc1ZhbGlkS2V5ID0ga2V5ID0+IC9eW0EtWl9cXCRdW0EtWjAtOV9cXCRdKiQvaS50ZXN0KGtleSk7XG5cbiAgc3RyaW5nID0gc3RyaW5nLnRyaW0oKTtcbiAgY29uc3Qgb3JpZ2luYWxTdHJpbmcgPSBzdHJpbmc7XG4gIGNvbnN0IG9iamVjdCA9IHt9O1xuICBsZXQgcmVhZGluZ0tleSA9IHRydWUsIGtleSwgcHJldmlvdXNUb2tlbiwgdG9rZW47XG5cbiAgd2hpbGUoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICBwcmV2aW91c1Rva2VuID0gdG9rZW47XG4gICAgdG9rZW4gPSBuZXh0VG9rZW4oc3RyaW5nKTtcbiAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2UodG9rZW4ubGVuZ3RoLCBzdHJpbmcubGVuZ3RoKS50cmltTGVmdCgpO1xuXG4gICAgaWYgKCh0b2tlbiA9PT0gJzonICYmICghcmVhZGluZ0tleSB8fCAhcHJldmlvdXNUb2tlbiB8fCBwcmV2aW91c1Rva2VuID09PSAnLCcpKVxuICAgICAgIHx8ICh0b2tlbiA9PT0gJywnICYmIHJlYWRpbmdLZXkpXG4gICAgICAgfHwgKHRva2VuICE9PSAnOicgJiYgdG9rZW4gIT09ICcsJyAmJiAocHJldmlvdXNUb2tlbiAmJiBwcmV2aW91c1Rva2VuICE9PSAnLCcgJiYgcHJldmlvdXNUb2tlbiAhPT0gJzonKSkpIHtcbiAgICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICB9IGVsc2UgaWYgKHRva2VuID09PSAnOicgJiYgcmVhZGluZ0tleSAmJiBwcmV2aW91c1Rva2VuKSB7XG4gICAgICBpZiAoaXNWYWxpZEtleShwcmV2aW91c1Rva2VuKSkge1xuICAgICAgICBrZXkgPSBwcmV2aW91c1Rva2VuO1xuICAgICAgICByZWFkaW5nS2V5ID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQga2V5IHRva2VuIFxcJycgKyBwcmV2aW91c1Rva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAwIGluIHN0cmluZzogXFwnJyArIG9yaWdpbmFsU3RyaW5nICsgJ1xcJycpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICcsJyAmJiAhcmVhZGluZ0tleSAmJiBwcmV2aW91c1Rva2VuKSB7XG4gICAgICBvYmplY3Rba2V5XSA9IHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICAgIHJlYWRpbmdLZXkgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0b2tlbikge1xuICAgIG9iamVjdFtrZXldID0gcHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxuXG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBwYXJzZUFycmF5ID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBjb25zdCBvcmlnaW5hbFN0cmluZyA9IHN0cmluZztcbiAgY29uc3QgYXJyYXkgPSBbXTtcbiAgbGV0IHByZXZpb3VzVG9rZW4sIHRva2VuO1xuXG4gIHdoaWxlKHN0cmluZy5sZW5ndGggPiAwKSB7XG4gICAgcHJldmlvdXNUb2tlbiA9IHRva2VuO1xuICAgIHRva2VuID0gbmV4dFRva2VuKHN0cmluZyk7XG4gICAgc3RyaW5nID0gc3RyaW5nLnNsaWNlKHRva2VuLmxlbmd0aCwgc3RyaW5nLmxlbmd0aCkudHJpbUxlZnQoKTtcblxuICAgIGlmICh0b2tlbiA9PT0gJywnICYmICghcHJldmlvdXNUb2tlbiB8fCBwcmV2aW91c1Rva2VuID09PSAnLCcpKSB7XG4gICAgICBlcnJvcih0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZyk7XG4gICAgfSBlbHNlIGlmICh0b2tlbiA9PT0gJywnKSB7XG4gICAgICBhcnJheS5wdXNoKHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRva2VuKSB7XG4gICAgaWYgKHRva2VuICE9PSAnLCcpIHtcbiAgICAgIGFycmF5LnB1c2gocHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYXJyYXk7XG59O1xuXG5jb25zdCBwYXJzZSA9IChzdHJpbmcpID0+IHtcbiAgc3RyaW5nID0gc3RyaW5nLnRyaW0oKTtcblxuICBpZiAoaXNPYmplY3RTdHJpbmcoc3RyaW5nKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAoc3RyaW5nKSk7XG4gIH0gZWxzZSBpZiAoaXNBcnJheVN0cmluZyhzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHBhcnNlQXJyYXkodW53cmFwKHN0cmluZykpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignUHJvdmlkZWQgc3RyaW5nIG11c3QgYmUgb2JqZWN0IG9yIGFycmF5IGxpa2U6ICcgKyBzdHJpbmcpO1xuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBwYXJzZTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltYXRpb25PcHRpb25zUGFyc2UgZnJvbSAnLi9hbmltYXRpb24tb3B0aW9ucy1wYXJzZXInO1xuXG5jb25zdCB1dGlsID0ge307XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmcvRnVuY3Rpb259IHF1ZXJ5IGRvdCBjbGFzcyBuYW1lIG9yIG5vZGUgbmFtZSBvciBtYXRjaGVyIGZ1bmN0aW9uLlxuICogQHJldHVybiB7RnVuY3Rpb259XG4gKi9cbnV0aWwucHJlcGFyZVF1ZXJ5ID0gKHF1ZXJ5KSA9PiB7XG4gIHJldHVybiBxdWVyeSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gcXVlcnkgOiAoZWxlbWVudCkgPT4gdXRpbC5tYXRjaChlbGVtZW50LCBxdWVyeSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtTdHJpbmcvRnVuY3Rpb259IHF1ZXJ5IGRvdCBjbGFzcyBuYW1lIG9yIG5vZGUgbmFtZS5cbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbnV0aWwubWF0Y2ggPSAoZWxlbWVudCwgcXVlcnkpID0+IHtcbiAgaWYgKHF1ZXJ5WzBdID09PSAnLicpIHtcbiAgICByZXR1cm4gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMocXVlcnkuc2xpY2UoMSkpO1xuICB9XG4gIHJldHVybiBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IHF1ZXJ5O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZENoaWxkID0gKGVsZW1lbnQsIHF1ZXJ5KSA9PiB7XG4gIGNvbnN0IG1hdGNoID0gdXRpbC5wcmVwYXJlUXVlcnkocXVlcnkpO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudC5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IG5vZGUgPSBlbGVtZW50LmNoaWxkcmVuW2ldO1xuICAgIGlmIChtYXRjaChub2RlKSkge1xuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZFBhcmVudCA9IChlbGVtZW50LCBxdWVyeSkgPT4ge1xuICBjb25zdCBtYXRjaCA9IHV0aWwucHJlcGFyZVF1ZXJ5KHF1ZXJ5KTtcblxuICBsZXQgcGFyZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xuICBmb3IgKDs7KSB7XG4gICAgaWYgKCFwYXJlbnQgfHwgcGFyZW50ID09PSBkb2N1bWVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChtYXRjaChwYXJlbnQpKSB7XG4gICAgICByZXR1cm4gcGFyZW50O1xuICAgIH1cbiAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50Tm9kZTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbnV0aWwuaXNBdHRhY2hlZCA9IChlbGVtZW50KSA9PiB7XG4gIHdoaWxlIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgIT09IGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG51dGlsLmhhc0FueUNvbXBvbmVudEFzUGFyZW50ID0gKGVsZW1lbnQpID0+IHtcbiAgd2hpbGUgKGVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICE9PSBlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICBpZiAoZWxlbWVudCAmJiBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkubWF0Y2goLyhvbnMtbmF2aWdhdG9yfG9ucy10YWJiYXJ8b25zLXNsaWRpbmctbWVudXxvbnMtc3BsaXQtdmlldykvKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gYWN0aW9uIHRvIHByb3BhZ2F0ZVxuICovXG51dGlsLnByb3BhZ2F0ZUFjdGlvbiA9IChlbGVtZW50LCBhY3Rpb24pID0+IHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjaGlsZCA9IGVsZW1lbnQuY2hpbGROb2Rlc1tpXTtcbiAgICBpZiAoY2hpbGRbYWN0aW9uXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBjaGlsZFthY3Rpb25dKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKGNoaWxkLCBhY3Rpb24pO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBzZWxlY3RvciAtIHRhZyBhbmQgY2xhc3Mgb25seVxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9XG4gKi9cbnV0aWwuY3JlYXRlID0gKHNlbGVjdG9yID0gJycsIHN0eWxlID0ge30pID0+IHtcbiAgY29uc3QgY2xhc3NMaXN0ID0gc2VsZWN0b3Iuc3BsaXQoJy4nKTtcbiAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoY2xhc3NMaXN0LnNoaWZ0KCkgfHwgJ2RpdicpO1xuXG4gIGlmIChjbGFzc0xpc3QubGVuZ3RoKSB7XG4gICAgZWxlbWVudC5jbGFzc05hbWUgPSBjbGFzc0xpc3Quam9pbignICcpO1xuICB9XG5cbiAgdXRpbC5leHRlbmQoZWxlbWVudC5zdHlsZSwgc3R5bGUpO1xuXG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7RWxlbWVudH1cbiAqL1xudXRpbC5jcmVhdGVFbGVtZW50ID0gKGh0bWwpID0+IHtcbiAgY29uc3Qgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBpbm5lckhUTUwod3JhcHBlciwgaHRtbCk7XG5cbiAgaWYgKHdyYXBwZXIuY2hpbGRyZW4ubGVuZ3RoID4gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignXCJodG1sXCIgbXVzdCBiZSBvbmUgd3JhcHBlciBlbGVtZW50LicpO1xuICB9XG5cbiAgcmV0dXJuIHdyYXBwZXIuY2hpbGRyZW5bMF07XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBodG1sXG4gKiBAcmV0dXJuIHtIVE1MRnJhZ21lbnR9XG4gKi9cbnV0aWwuY3JlYXRlRnJhZ21lbnQgPSAoaHRtbCkgPT4ge1xuICBjb25zdCB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIGlubmVySFRNTCh3cmFwcGVyLCBodG1sKTtcbiAgY29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgd2hpbGUgKHdyYXBwZXIuZmlyc3RDaGlsZCkge1xuICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKHdyYXBwZXIuZmlyc3RDaGlsZCk7XG4gIH1cblxuICByZXR1cm4gZnJhZ21lbnQ7XG59O1xuXG4vKlxuICogQHBhcmFtIHtPYmplY3R9IGRzdCBEZXN0aW5hdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0gey4uLk9iamVjdH0gc3JjIFNvdXJjZSBvYmplY3QocykuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZWZlcmVuY2UgdG8gYGRzdGAuXG4gKi9cbnV0aWwuZXh0ZW5kID0gKGRzdCwgLi4uYXJncykgPT4ge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoYXJnc1tpXSkge1xuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGFyZ3NbaV0pO1xuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBrZXlzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IGtleXNbal07XG4gICAgICAgIGRzdFtrZXldID0gYXJnc1tpXVtrZXldO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkc3Q7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7T2JqZWN0fSBhcnJheUxpa2VcbiAqIEByZXR1cm4ge0FycmF5fVxuICovXG51dGlsLmFycmF5RnJvbSA9IChhcnJheUxpa2UpID0+IHtcbiAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5hcHBseShhcnJheUxpa2UpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30ganNvblN0cmluZ1xuICogQHBhcmFtIHtPYmplY3R9IFtmYWlsU2FmZV1cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xudXRpbC5wYXJzZUpTT05PYmplY3RTYWZlbHkgPSAoanNvblN0cmluZywgZmFpbFNhZmUgPSB7fSkgPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IEpTT04ucGFyc2UoJycgKyBqc29uU3RyaW5nKTtcbiAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfSBjYXRjaChlKSB7XG4gICAgcmV0dXJuIGZhaWxTYWZlO1xuICB9XG4gIHJldHVybiBmYWlsU2FmZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGggLSBwYXRoIHN1Y2ggYXMgJ215QXBwLmNvbnRyb2xsZXJzLmRhdGEubG9hZERhdGEnXG4gKiBAcmV0dXJuIHtBbnl9IC0gd2hhdGV2ZXIgaXMgbG9jYXRlZCBhdCB0aGF0IHBhdGhcbiAqL1xudXRpbC5maW5kRnJvbVBhdGggPSAocGF0aCkgPT4ge1xuICBwYXRoID0gcGF0aC5zcGxpdCgnLicpO1xuICB2YXIgZWwgPSB3aW5kb3csIGtleTtcbiAgd2hpbGUgKGtleSA9IHBhdGguc2hpZnQoKSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgZWwgPSBlbFtrZXldO1xuICB9XG4gIHJldHVybiBlbDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0ge09iamVjdH0gW2RldGFpbF1cbiAqIEByZXR1cm4ge0N1c3RvbUV2ZW50fVxuICovXG51dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQgPSAodGFyZ2V0LCBldmVudE5hbWUsIGRldGFpbCA9IHt9KSA9PiB7XG5cbiAgY29uc3QgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG4gICAgYnViYmxlczogdHJ1ZSxcbiAgICBjYW5jZWxhYmxlOiB0cnVlLFxuICAgIGRldGFpbDogZGV0YWlsXG4gIH0pO1xuXG4gIE9iamVjdC5rZXlzKGRldGFpbCkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGV2ZW50W2tleV0gPSBkZXRhaWxba2V5XTtcbiAgfSk7XG5cbiAgdGFyZ2V0LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuXG4gIHJldHVybiBldmVudDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRcbiAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllck5hbWVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbnV0aWwuaGFzTW9kaWZpZXIgPSAodGFyZ2V0LCBtb2RpZmllck5hbWUpID0+IHtcbiAgaWYgKCF0YXJnZXQuaGFzQXR0cmlidXRlKCdtb2RpZmllcicpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0YXJnZXQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpLnNwbGl0KC9cXHMrLykuc29tZShlID0+IGUgPT09IG1vZGlmaWVyTmFtZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJOYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufSBXaGV0aGVyIGl0IHdhcyBhZGRlZCBvciBub3QuXG4gKi9cbnV0aWwuYWRkTW9kaWZpZXIgPSAodGFyZ2V0LCBtb2RpZmllck5hbWUpID0+IHtcbiAgaWYgKHV0aWwuaGFzTW9kaWZpZXIodGFyZ2V0LCBtb2RpZmllck5hbWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbW9kaWZpZXJOYW1lID0gbW9kaWZpZXJOYW1lLnRyaW0oKTtcbiAgY29uc3QgbW9kaWZpZXJBdHRyaWJ1dGUgPSB0YXJnZXQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpIHx8ICcnO1xuICB0YXJnZXQuc2V0QXR0cmlidXRlKCdtb2RpZmllcicsIChtb2RpZmllckF0dHJpYnV0ZSArICcgJyArIG1vZGlmaWVyTmFtZSkudHJpbSgpKTtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJOYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufSBXaGV0aGVyIGl0IHdhcyBmb3VuZCBvciBub3QuXG4gKi9cbnV0aWwucmVtb3ZlTW9kaWZpZXIgPSAodGFyZ2V0LCBtb2RpZmllck5hbWUpID0+IHtcbiAgaWYgKCF0YXJnZXQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgbW9kaWZpZXJzID0gdGFyZ2V0LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKS5zcGxpdCgvXFxzKy8pO1xuXG4gIGNvbnN0IG5ld01vZGlmaWVycyA9IG1vZGlmaWVycy5maWx0ZXIoaXRlbSA9PiBpdGVtICYmIGl0ZW0gIT09IG1vZGlmaWVyTmFtZSk7XG4gIHRhcmdldC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgbmV3TW9kaWZpZXJzLmpvaW4oJyAnKSk7XG5cbiAgcmV0dXJuIG1vZGlmaWVycy5sZW5ndGggIT09IG5ld01vZGlmaWVycy5sZW5ndGg7XG59O1xuXG51dGlsLnVwZGF0ZVBhcmVudFBvc2l0aW9uID0gKGVsKSA9PiB7XG4gIGlmICghZWwuX3BhcmVudFVwZGF0ZWQgJiYgZWwucGFyZW50RWxlbWVudCkge1xuICAgIGlmICh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbC5wYXJlbnRFbGVtZW50KS5nZXRQcm9wZXJ0eVZhbHVlKCdwb3NpdGlvbicpID09PSAnc3RhdGljJykge1xuICAgICAgZWwucGFyZW50RWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XG4gICAgfVxuICAgIGVsLl9wYXJlbnRVcGRhdGVkID0gdHJ1ZTtcbiAgfVxufTtcblxudXRpbC50b2dnbGVBdHRyaWJ1dGUgPSAoZWxlbWVudCwgbmFtZSwgZW5hYmxlKSA9PiB7XG4gIGlmIChlbmFibGUpIHtcbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCAnJyk7XG4gIH0gZWxzZSB7XG4gICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gIH1cbn07XG5cbnV0aWwuYmluZExpc3RlbmVycyA9IChlbGVtZW50LCBsaXN0ZW5lck5hbWVzKSA9PiB7XG4gIGxpc3RlbmVyTmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICBjb25zdCBib3VuZE5hbWUgPSBuYW1lLnJlcGxhY2UoL15fW2Etel0vLCAnX2JvdW5kJyArIG5hbWVbMV0udG9VcHBlckNhc2UoKSk7XG4gICAgZWxlbWVudFtib3VuZE5hbWVdID0gZWxlbWVudFtib3VuZE5hbWVdIHx8IGVsZW1lbnRbbmFtZV0uYmluZChlbGVtZW50KTtcbiAgfSk7XG59O1xuXG51dGlsLmVhY2ggPSAob2JqLCBmKSA9PiBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goa2V5ID0+IGYoa2V5LCBvYmpba2V5XSkpO1xuXG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRcbiAqL1xudXRpbC51cGRhdGVSaXBwbGUgPSAodGFyZ2V0KSA9PiB7XG4gIGNvbnN0IHJpcHBsZUVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0YXJnZXQsICdvbnMtcmlwcGxlJyk7XG5cbiAgaWYgKHRhcmdldC5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpKSB7XG4gICAgaWYgKCFyaXBwbGVFbGVtZW50KSB7XG4gICAgICB0YXJnZXQuaW5zZXJ0QmVmb3JlKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29ucy1yaXBwbGUnKSwgdGFyZ2V0LmZpcnN0Q2hpbGQpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChyaXBwbGVFbGVtZW50KSB7XG4gICAgcmlwcGxlRWxlbWVudC5yZW1vdmUoKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ31cbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xudXRpbC5hbmltYXRpb25PcHRpb25zUGFyc2UgPSBhbmltYXRpb25PcHRpb25zUGFyc2U7XG5cbi8qKlxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICovXG51dGlsLmlzSW50ZWdlciA9ICh2YWx1ZSkgPT4ge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJlxuICAgIGlzRmluaXRlKHZhbHVlKSAmJlxuICAgIE1hdGguZmxvb3IodmFsdWUpID09PSB2YWx1ZTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7T2JlamN0fSBEZWZlcnJlZCBwcm9taXNlLlxuICovXG51dGlsLmRlZmVyID0gKCkgPT4ge1xuICBjb25zdCBkZWZlcnJlZCA9IHt9O1xuICBkZWZlcnJlZC5wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGRlZmVycmVkLnJlc29sdmUgPSByZXNvbHZlO1xuICAgIGRlZmVycmVkLnJlamVjdCA9IHJlamVjdDtcbiAgfSk7XG4gIHJldHVybiBkZWZlcnJlZDtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWw7XG4iLCIvKlxuICogR2VzdHVyZSBkZXRlY3RvciBsaWJyYXJ5IHRoYXQgZm9ya2VkIGZyb20gZ2l0aHViLmNvbS9FaWdodE1lZGlhL2hhbW1lci5qcy5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudCwgVXRpbHMsIERldGVjdGlvbiwgUG9pbnRlckV2ZW50O1xuXG4vKipcbiAqIEBvYmplY3Qgb25zLkdlc3R1cmVEZXRlY3RvclxuICogQGNhdGVnb3J5IGdlc3R1cmVcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVXRpbGl0eSBjbGFzcyBmb3IgZ2VzdHVyZSBkZXRlY3Rpb24uWy9lbl1cbiAqICAgW2phXeOCuOOCp+OCueODgeODo+OCkuaknOefpeOBmeOCi+OBn+OCgeOBruODpuODvOODhuOCo+ODquODhuOCo+OCr+ODqeOCueOBp+OBmeOAglsvamFdXG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kIGNvbnN0cnVjdG9yXG4gKiBAc2lnbmF0dXJlIGNvbnN0cnVjdG9yKGVsZW1lbnRbLCBvcHRpb25zXSlcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1DcmVhdGUgYSBuZXcgR2VzdHVyZURldGVjdG9yIGluc3RhbmNlLlsvZW5dXG4gKiAgW2phXUdlc3R1cmVEZXRlY3RvcuOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqICAgW2VuXU5hbWUgb2YgdGhlIGV2ZW50LlsvZW5dXG4gKiAgIFtqYV3jgrjjgqfjgrnjg4Hjg6PjgpLmpJznn6XjgZnjgotET03opoHntKDjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dT3B0aW9ucyBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcmV0dXJuIHtvbnMuR2VzdHVyZURldGVjdG9yLkluc3RhbmNlfVxuICovXG52YXIgR2VzdHVyZURldGVjdG9yID0gZnVuY3Rpb24gR2VzdHVyZURldGVjdG9yKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIG5ldyBHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2UoZWxlbWVudCwgb3B0aW9ucyB8fCB7fSk7XG59O1xuXG5cbi8qKlxuICogZGVmYXVsdCBzZXR0aW5ncy5cbiAqIG1vcmUgc2V0dGluZ3MgYXJlIGRlZmluZWQgcGVyIGdlc3R1cmUgYXQgYC9nZXN0dXJlc2AuIEVhY2ggZ2VzdHVyZSBjYW4gYmUgZGlzYWJsZWQvZW5hYmxlZFxuICogYnkgc2V0dGluZyBpdCdzIG5hbWUgKGxpa2UgYHN3aXBlYCkgdG8gZmFsc2UuXG4gKiBZb3UgY2FuIHNldCB0aGUgZGVmYXVsdHMgZm9yIGFsbCBpbnN0YW5jZXMgYnkgY2hhbmdpbmcgdGhpcyBvYmplY3QgYmVmb3JlIGNyZWF0aW5nIGFuIGluc3RhbmNlLlxuICogQGV4YW1wbGVcbiAqIGBgYGBcbiAqICBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMuZHJhZyA9IGZhbHNlO1xuICogIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci50b3VjaEFjdGlvbiA9ICdwYW4teSc7XG4gKiAgZGVsZXRlIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci51c2VyU2VsZWN0O1xuICogYGBgYFxuICogQHByb3BlcnR5IGRlZmF1bHRzXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMgPSB7XG4gIGJlaGF2aW9yOiB7XG4gICAgLy8gdXNlclNlbGVjdDogJ25vbmUnLCAvLyBBbHNvIGRpc2FibGVzIHNlbGVjdGlvbiBpbiBgaW5wdXRgIGNoaWxkcmVuXG4gICAgdG91Y2hBY3Rpb246ICdwYW4teScsXG4gICAgdG91Y2hDYWxsb3V0OiAnbm9uZScsXG4gICAgY29udGVudFpvb21pbmc6ICdub25lJyxcbiAgICB1c2VyRHJhZzogJ25vbmUnLFxuICAgIHRhcEhpZ2hsaWdodENvbG9yOiAncmdiYSgwLDAsMCwwKSdcbiAgfVxufTtcblxuLyoqXG4gKiBHZXN0dXJlRGV0ZWN0b3IgZG9jdW1lbnQgd2hlcmUgdGhlIGJhc2UgZXZlbnRzIGFyZSBhZGRlZCBhdFxuICogQHByb3BlcnR5IERPQ1VNRU5UXG4gKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gKiBAZGVmYXVsdCB3aW5kb3cuZG9jdW1lbnRcbiAqL1xuR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5UID0gZG9jdW1lbnQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHBvaW50ZXIgZXZlbnRzXG4gKiBAcHJvcGVydHkgSEFTX1BPSU5URVJFVkVOVFNcbiAqIEB0eXBlIHtCb29sZWFufVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMgPSBuYXZpZ2F0b3IucG9pbnRlckVuYWJsZWQgfHwgbmF2aWdhdG9yLm1zUG9pbnRlckVuYWJsZWQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHRvdWNoIGV2ZW50c1xuICogQHByb3BlcnR5IEhBU19UT1VDSEVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5IQVNfVE9VQ0hFVkVOVFMgPSAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93KTtcblxuLyoqXG4gKiBkZXRlY3QgbW9iaWxlIGJyb3dzZXJzXG4gKiBAcHJvcGVydHkgSVNfTU9CSUxFXG4gKiBAdHlwZSB7Qm9vbGVhbn1cbiAqL1xuR2VzdHVyZURldGVjdG9yLklTX01PQklMRSA9IC9tb2JpbGV8dGFibGV0fGlwKGFkfGhvbmV8b2QpfGFuZHJvaWR8c2lsay9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cbi8qKlxuICogZGV0ZWN0IGlmIHdlIHdhbnQgdG8gc3VwcG9ydCBtb3VzZWV2ZW50cyBhdCBhbGxcbiAqIEBwcm9wZXJ0eSBOT19NT1VTRUVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5OT19NT1VTRUVWRU5UUyA9IChHZXN0dXJlRGV0ZWN0b3IuSEFTX1RPVUNIRVZFTlRTICYmIEdlc3R1cmVEZXRlY3Rvci5JU19NT0JJTEUpIHx8IEdlc3R1cmVEZXRlY3Rvci5IQVNfUE9JTlRFUkVWRU5UUztcblxuLyoqXG4gKiBpbnRlcnZhbCBpbiB3aGljaCBHZXN0dXJlRGV0ZWN0b3IgcmVjYWxjdWxhdGVzIGN1cnJlbnQgdmVsb2NpdHkvZGlyZWN0aW9uL2FuZ2xlIGluIG1zXG4gKiBAcHJvcGVydHkgQ0FMQ1VMQVRFX0lOVEVSVkFMXG4gKiBAdHlwZSB7TnVtYmVyfVxuICogQGRlZmF1bHQgMjVcbiAqL1xuR2VzdHVyZURldGVjdG9yLkNBTENVTEFURV9JTlRFUlZBTCA9IDI1O1xuXG4vKipcbiAqIGV2ZW50dHlwZXMgcGVyIHRvdWNoZXZlbnQgKHN0YXJ0LCBtb3ZlLCBlbmQpIGFyZSBmaWxsZWQgYnkgYEV2ZW50LmRldGVybWluZUV2ZW50VHlwZXNgIG9uIGBzZXR1cGBcbiAqIHRoZSBvYmplY3QgY29udGFpbnMgdGhlIERPTSBldmVudCBuYW1lcyBwZXIgdHlwZSAoYEVWRU5UX1NUQVJUYCwgYEVWRU5UX01PVkVgLCBgRVZFTlRfRU5EYClcbiAqIEBwcm9wZXJ0eSBFVkVOVF9UWVBFU1xuICogQHByaXZhdGVcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbnZhciBFVkVOVF9UWVBFUyA9IHt9O1xuXG4vKipcbiAqIGRpcmVjdGlvbiBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IERJUkVDVElPTl9ET1dOfExFRlR8VVB8UklHSFRcbiAqIEBmaW5hbFxuICogQHR5cGUge1N0cmluZ31cbiAqIEBkZWZhdWx0ICdkb3duJyAnbGVmdCcgJ3VwJyAncmlnaHQnXG4gKi9cbnZhciBESVJFQ1RJT05fRE9XTiA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fRE9XTiA9ICdkb3duJztcbnZhciBESVJFQ1RJT05fTEVGVCA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fTEVGVCA9ICdsZWZ0JztcbnZhciBESVJFQ1RJT05fVVAgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1VQID0gJ3VwJztcbnZhciBESVJFQ1RJT05fUklHSFQgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1JJR0hUID0gJ3JpZ2h0JztcblxuLyoqXG4gKiBwb2ludGVydHlwZSBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IFBPSU5URVJfTU9VU0V8VE9VQ0h8UEVOXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnbW91c2UnICd0b3VjaCcgJ3BlbidcbiAqL1xudmFyIFBPSU5URVJfTU9VU0UgPSBHZXN0dXJlRGV0ZWN0b3IuUE9JTlRFUl9NT1VTRSA9ICdtb3VzZSc7XG52YXIgUE9JTlRFUl9UT1VDSCA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1RPVUNIID0gJ3RvdWNoJztcbnZhciBQT0lOVEVSX1BFTiA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1BFTiA9ICdwZW4nO1xuXG4vKipcbiAqIGV2ZW50dHlwZXNcbiAqIEBwcm9wZXJ0eSBFVkVOVF9TVEFSVHxNT1ZFfEVORHxSRUxFQVNFfFRPVUNIXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnc3RhcnQnICdjaGFuZ2UnICdtb3ZlJyAnZW5kJyAncmVsZWFzZScgJ3RvdWNoJ1xuICovXG52YXIgRVZFTlRfU1RBUlQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfU1RBUlQgPSAnc3RhcnQnO1xudmFyIEVWRU5UX01PVkUgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfTU9WRSA9ICdtb3ZlJztcbnZhciBFVkVOVF9FTkQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfRU5EID0gJ2VuZCc7XG52YXIgRVZFTlRfUkVMRUFTRSA9IEdlc3R1cmVEZXRlY3Rvci5FVkVOVF9SRUxFQVNFID0gJ3JlbGVhc2UnO1xudmFyIEVWRU5UX1RPVUNIID0gR2VzdHVyZURldGVjdG9yLkVWRU5UX1RPVUNIID0gJ3RvdWNoJztcblxuLyoqXG4gKiBpZiB0aGUgd2luZG93IGV2ZW50cyBhcmUgc2V0Li4uXG4gKiBAcHJvcGVydHkgUkVBRFlcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtCb29sZWFufVxuICogQGRlZmF1bHQgZmFsc2VcbiAqL1xuR2VzdHVyZURldGVjdG9yLlJFQURZID0gZmFsc2U7XG5cbi8qKlxuICogcGx1Z2lucyBuYW1lc3BhY2VcbiAqIEBwcm9wZXJ0eSBwbHVnaW5zXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IucGx1Z2lucyA9IEdlc3R1cmVEZXRlY3Rvci5wbHVnaW5zIHx8IHt9O1xuXG4vKipcbiAqIGdlc3R1cmVzIG5hbWVzcGFjZVxuICogc2VlIGAvZ2VzdHVyZXNgIGZvciB0aGUgZGVmaW5pdGlvbnNcbiAqIEBwcm9wZXJ0eSBnZXN0dXJlc1xuICogQHR5cGUge09iamVjdH1cbiAqL1xuR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzID0gR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzIHx8IHt9O1xuXG4vKipcbiAqIHNldHVwIGV2ZW50cyB0byBkZXRlY3QgZ2VzdHVyZXMgb24gdGhlIGRvY3VtZW50XG4gKiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIGNyZWF0aW5nIGFuIG5ldyBpbnN0YW5jZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gc2V0dXAoKSB7XG4gIGlmKEdlc3R1cmVEZXRlY3Rvci5SRUFEWSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIGZpbmQgd2hhdCBldmVudHR5cGVzIHdlIGFkZCBsaXN0ZW5lcnMgdG9cbiAgRXZlbnQuZGV0ZXJtaW5lRXZlbnRUeXBlcygpO1xuXG4gIC8vIFJlZ2lzdGVyIGFsbCBnZXN0dXJlcyBpbnNpZGUgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzXG4gIFV0aWxzLmVhY2goR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLCBmdW5jdGlvbihnZXN0dXJlKSB7XG4gICAgRGV0ZWN0aW9uLnJlZ2lzdGVyKGdlc3R1cmUpO1xuICB9KTtcblxuICAvLyBBZGQgdG91Y2ggZXZlbnRzIG9uIHRoZSBkb2N1bWVudFxuICBFdmVudC5vblRvdWNoKEdlc3R1cmVEZXRlY3Rvci5ET0NVTUVOVCwgRVZFTlRfTU9WRSwgRGV0ZWN0aW9uLmRldGVjdCk7XG4gIEV2ZW50Lm9uVG91Y2goR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5ULCBFVkVOVF9FTkQsIERldGVjdGlvbi5kZXRlY3QpO1xuXG4gIC8vIEdlc3R1cmVEZXRlY3RvciBpcyByZWFkeS4uLiFcbiAgR2VzdHVyZURldGVjdG9yLlJFQURZID0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICpcbiAqIEBjbGFzcyBVdGlsc1xuICogQHN0YXRpY1xuICovXG5VdGlscyA9IEdlc3R1cmVEZXRlY3Rvci51dGlscyA9IHtcbiAgLyoqXG4gICAqIGV4dGVuZCBtZXRob2QsIGNvdWxkIGFsc28gYmUgdXNlZCBmb3IgY2xvbmluZyB3aGVuIGBkZXN0YCBpcyBhbiBlbXB0eSBvYmplY3QuXG4gICAqIGNoYW5nZXMgdGhlIGRlc3Qgb2JqZWN0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkZXN0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzcmNcbiAgICogQHBhcmFtIHtCb29sZWFufSBbbWVyZ2U9ZmFsc2VdICBkbyBhIG1lcmdlXG4gICAqIEByZXR1cm4ge09iamVjdH0gZGVzdFxuICAgKi9cbiAgZXh0ZW5kOiBmdW5jdGlvbiBleHRlbmQoZGVzdCwgc3JjLCBtZXJnZSkge1xuICAgIGZvciAodmFyIGtleSBpbiBzcmMpIHtcbiAgICAgIGlmIChzcmMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiAoZGVzdFtrZXldID09PSB1bmRlZmluZWQgfHwgIW1lcmdlKSkge1xuICAgICAgICBkZXN0W2tleV0gPSBzcmNba2V5XTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHNpbXBsZSBhZGRFdmVudExpc3RlbmVyIHdyYXBwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqL1xuICBvbjogZnVuY3Rpb24gb24oZWxlbWVudCwgdHlwZSwgaGFuZGxlcikge1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBoYW5kbGVyLCBmYWxzZSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHNpbXBsZSByZW1vdmVFdmVudExpc3RlbmVyIHdyYXBwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqL1xuICBvZmY6IGZ1bmN0aW9uIG9mZihlbGVtZW50LCB0eXBlLCBoYW5kbGVyKSB7XG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGhhbmRsZXIsIGZhbHNlKTtcbiAgfSxcblxuICAvKipcbiAgICogZm9yRWFjaCBvdmVyIGFycmF5cyBhbmQgb2JqZWN0c1xuICAgKiBAcGFyYW0ge09iamVjdHxBcnJheX0gb2JqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdG9yXG4gICAqIEBwYXJhbSB7YW55fSBpdGVyYXRvci5pdGVtXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpdGVyYXRvci5pbmRleFxuICAgKiBAcGFyYW0ge09iamVjdHxBcnJheX0gaXRlcmF0b3Iub2JqIHRoZSBzb3VyY2Ugb2JqZWN0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IHZhbHVlIHRvIHVzZSBhcyBgdGhpc2AgaW4gdGhlIGl0ZXJhdG9yXG4gICAqL1xuICBlYWNoOiBmdW5jdGlvbiBlYWNoKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgaSwgbGVuO1xuXG4gICAgLy8gbmF0aXZlIGZvckVhY2ggb24gYXJyYXlzXG4gICAgaWYoJ2ZvckVhY2gnIGluIG9iaikge1xuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgLy8gYXJyYXlzXG4gICAgfSBlbHNlIGlmKG9iai5sZW5ndGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgZm9yKGkgPSAwLCBsZW4gPSBvYmoubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpbaV0sIGksIG9iaikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBvYmplY3RzXG4gICAgfSBlbHNlIHtcbiAgICAgIGZvcihpIGluIG9iaikge1xuICAgICAgICBpZihvYmouaGFzT3duUHJvcGVydHkoaSkgJiZcbiAgICAgICAgICBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9ialtpXSwgaSwgb2JqKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIGZpbmQgaWYgYSBzdHJpbmcgY29udGFpbnMgdGhlIHN0cmluZyB1c2luZyBpbmRleE9mXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzcmNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGZpbmRcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gZm91bmRcbiAgICovXG4gIGluU3RyOiBmdW5jdGlvbiBpblN0cihzcmMsIGZpbmQpIHtcbiAgICByZXR1cm4gc3JjLmluZGV4T2YoZmluZCkgPiAtMTtcbiAgfSxcblxuICAvKipcbiAgICogZmluZCBpZiBhIGFycmF5IGNvbnRhaW5zIHRoZSBvYmplY3QgdXNpbmcgaW5kZXhPZiBvciBhIHNpbXBsZSBwb2x5ZmlsbFxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3JjXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBmaW5kXG4gICAqIEByZXR1cm4ge0Jvb2xlYW58TnVtYmVyfSBmYWxzZSB3aGVuIG5vdCBmb3VuZCwgb3IgdGhlIGluZGV4XG4gICAqL1xuICBpbkFycmF5OiBmdW5jdGlvbiBpbkFycmF5KHNyYywgZmluZCkge1xuICAgIGlmKHNyYy5pbmRleE9mKSB7XG4gICAgICB2YXIgaW5kZXggPSBzcmMuaW5kZXhPZihmaW5kKTtcbiAgICAgIHJldHVybiAoaW5kZXggPT09IC0xKSA/IGZhbHNlIDogaW5kZXg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvcih2YXIgaSA9IDAsIGxlbiA9IHNyYy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZihzcmNbaV0gPT09IGZpbmQpIHtcbiAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogY29udmVydCBhbiBhcnJheS1saWtlIG9iamVjdCAoYGFyZ3VtZW50c2AsIGB0b3VjaGxpc3RgKSB0byBhbiBhcnJheVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgdG9BcnJheTogZnVuY3Rpb24gdG9BcnJheShvYmopIHtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwob2JqLCAwKTtcbiAgfSxcblxuICAvKipcbiAgICogZmluZCBpZiBhIG5vZGUgaXMgaW4gdGhlIGdpdmVuIHBhcmVudFxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBub2RlXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHBhcmVudFxuICAgKiBAcmV0dXJuIHtCb29sZWFufSBmb3VuZFxuICAgKi9cbiAgaGFzUGFyZW50OiBmdW5jdGlvbiBoYXNQYXJlbnQobm9kZSwgcGFyZW50KSB7XG4gICAgd2hpbGUobm9kZSkge1xuICAgICAgaWYobm9kZSA9PSBwYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGdldCB0aGUgY2VudGVyIG9mIGFsbCB0aGUgdG91Y2hlc1xuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEByZXR1cm4ge09iamVjdH0gY2VudGVyIGNvbnRhaW5zIGBwYWdlWGAsIGBwYWdlWWAsIGBjbGllbnRYYCBhbmQgYGNsaWVudFlgIHByb3BlcnRpZXNcbiAgICovXG4gIGdldENlbnRlcjogZnVuY3Rpb24gZ2V0Q2VudGVyKHRvdWNoZXMpIHtcbiAgICB2YXIgcGFnZVggPSBbXSxcbiAgICAgICAgcGFnZVkgPSBbXSxcbiAgICAgICAgY2xpZW50WCA9IFtdLFxuICAgICAgICBjbGllbnRZID0gW10sXG4gICAgICAgIG1pbiA9IE1hdGgubWluLFxuICAgICAgICBtYXggPSBNYXRoLm1heDtcblxuICAgIC8vIG5vIG5lZWQgdG8gbG9vcCB3aGVuIG9ubHkgb25lIHRvdWNoXG4gICAgaWYodG91Y2hlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHBhZ2VYOiB0b3VjaGVzWzBdLnBhZ2VYLFxuICAgICAgICBwYWdlWTogdG91Y2hlc1swXS5wYWdlWSxcbiAgICAgICAgY2xpZW50WDogdG91Y2hlc1swXS5jbGllbnRYLFxuICAgICAgICBjbGllbnRZOiB0b3VjaGVzWzBdLmNsaWVudFlcbiAgICAgIH07XG4gICAgfVxuXG4gICAgVXRpbHMuZWFjaCh0b3VjaGVzLCBmdW5jdGlvbih0b3VjaCkge1xuICAgICAgcGFnZVgucHVzaCh0b3VjaC5wYWdlWCk7XG4gICAgICBwYWdlWS5wdXNoKHRvdWNoLnBhZ2VZKTtcbiAgICAgIGNsaWVudFgucHVzaCh0b3VjaC5jbGllbnRYKTtcbiAgICAgIGNsaWVudFkucHVzaCh0b3VjaC5jbGllbnRZKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBwYWdlWDogKG1pbi5hcHBseShNYXRoLCBwYWdlWCkgKyBtYXguYXBwbHkoTWF0aCwgcGFnZVgpKSAvIDIsXG4gICAgICBwYWdlWTogKG1pbi5hcHBseShNYXRoLCBwYWdlWSkgKyBtYXguYXBwbHkoTWF0aCwgcGFnZVkpKSAvIDIsXG4gICAgICBjbGllbnRYOiAobWluLmFwcGx5KE1hdGgsIGNsaWVudFgpICsgbWF4LmFwcGx5KE1hdGgsIGNsaWVudFgpKSAvIDIsXG4gICAgICBjbGllbnRZOiAobWluLmFwcGx5KE1hdGgsIGNsaWVudFkpICsgbWF4LmFwcGx5KE1hdGgsIGNsaWVudFkpKSAvIDJcbiAgICB9O1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHZlbG9jaXR5IGJldHdlZW4gdHdvIHBvaW50cy4gdW5pdCBpcyBpbiBweCBwZXIgbXMuXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVRpbWVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWFxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFZXG4gICAqIEByZXR1cm4ge09iamVjdH0gdmVsb2NpdHkgYHhgIGFuZCBgeWBcbiAgICovXG4gIGdldFZlbG9jaXR5OiBmdW5jdGlvbiBnZXRWZWxvY2l0eShkZWx0YVRpbWUsIGRlbHRhWCwgZGVsdGFZKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IE1hdGguYWJzKGRlbHRhWCAvIGRlbHRhVGltZSkgfHwgMCxcbiAgICAgIHk6IE1hdGguYWJzKGRlbHRhWSAvIGRlbHRhVGltZSkgfHwgMFxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgYW5nbGUgYmV0d2VlbiB0d28gY29vcmRpbmF0ZXNcbiAgICogQHBhcmFtIHtUb3VjaH0gdG91Y2gxXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9IGFuZ2xlXG4gICAqL1xuICBnZXRBbmdsZTogZnVuY3Rpb24gZ2V0QW5nbGUodG91Y2gxLCB0b3VjaDIpIHtcbiAgICB2YXIgeCA9IHRvdWNoMi5jbGllbnRYIC0gdG91Y2gxLmNsaWVudFgsXG4gICAgICAgIHkgPSB0b3VjaDIuY2xpZW50WSAtIHRvdWNoMS5jbGllbnRZO1xuXG4gICAgcmV0dXJuIE1hdGguYXRhbjIoeSwgeCkgKiAxODAgLyBNYXRoLlBJO1xuICB9LFxuXG4gIC8qKlxuICAgKiBkbyBhIHNtYWxsIGNvbXBhcmlzb24gdG8gZ2V0IHRoZSBkaXJlY3Rpb24gYmV0d2VlbiB0d28gdG91Y2hlcy5cbiAgICogQHBhcmFtIHtUb3VjaH0gdG91Y2gxXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGRpcmVjdGlvbiBtYXRjaGVzIGBESVJFQ1RJT05fTEVGVHxSSUdIVHxVUHxET1dOYFxuICAgKi9cbiAgZ2V0RGlyZWN0aW9uOiBmdW5jdGlvbiBnZXREaXJlY3Rpb24odG91Y2gxLCB0b3VjaDIpIHtcbiAgICB2YXIgeCA9IE1hdGguYWJzKHRvdWNoMS5jbGllbnRYIC0gdG91Y2gyLmNsaWVudFgpLFxuICAgICAgICB5ID0gTWF0aC5hYnModG91Y2gxLmNsaWVudFkgLSB0b3VjaDIuY2xpZW50WSk7XG5cbiAgICBpZih4ID49IHkpIHtcbiAgICAgIHJldHVybiB0b3VjaDEuY2xpZW50WCAtIHRvdWNoMi5jbGllbnRYID4gMCA/IERJUkVDVElPTl9MRUZUIDogRElSRUNUSU9OX1JJR0hUO1xuICAgIH1cbiAgICByZXR1cm4gdG91Y2gxLmNsaWVudFkgLSB0b3VjaDIuY2xpZW50WSA+IDAgPyBESVJFQ1RJT05fVVAgOiBESVJFQ1RJT05fRE9XTjtcbiAgfSxcblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byB0b3VjaGVzXG4gICAqIEBwYXJhbSB7VG91Y2h9dG91Y2gxXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9IGRpc3RhbmNlXG4gICAqL1xuICBnZXREaXN0YW5jZTogZnVuY3Rpb24gZ2V0RGlzdGFuY2UodG91Y2gxLCB0b3VjaDIpIHtcbiAgICB2YXIgeCA9IHRvdWNoMi5jbGllbnRYIC0gdG91Y2gxLmNsaWVudFgsXG4gICAgICAgIHkgPSB0b3VjaDIuY2xpZW50WSAtIHRvdWNoMS5jbGllbnRZO1xuXG4gICAgcmV0dXJuIE1hdGguc3FydCgoeCAqIHgpICsgKHkgKiB5KSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgc2NhbGUgZmFjdG9yIGJldHdlZW4gdHdvIHRvdWNoTGlzdHNcbiAgICogbm8gc2NhbGUgaXMgMSwgYW5kIGdvZXMgZG93biB0byAwIHdoZW4gcGluY2hlZCB0b2dldGhlciwgYW5kIGJpZ2dlciB3aGVuIHBpbmNoZWQgb3V0XG4gICAqIEBwYXJhbSB7QXJyYXl9IHN0YXJ0IGFycmF5IG9mIHRvdWNoZXNcbiAgICogQHBhcmFtIHtBcnJheX0gZW5kIGFycmF5IG9mIHRvdWNoZXNcbiAgICogQHJldHVybiB7TnVtYmVyfSBzY2FsZVxuICAgKi9cbiAgZ2V0U2NhbGU6IGZ1bmN0aW9uIGdldFNjYWxlKHN0YXJ0LCBlbmQpIHtcbiAgICAvLyBuZWVkIHR3byBmaW5nZXJzLi4uXG4gICAgaWYoc3RhcnQubGVuZ3RoID49IDIgJiYgZW5kLmxlbmd0aCA+PSAyKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXREaXN0YW5jZShlbmRbMF0sIGVuZFsxXSkgLyB0aGlzLmdldERpc3RhbmNlKHN0YXJ0WzBdLCBzdGFydFsxXSk7XG4gICAgfVxuICAgIHJldHVybiAxO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHJvdGF0aW9uIGRlZ3JlZXMgYmV0d2VlbiB0d28gdG91Y2hMaXN0c1xuICAgKiBAcGFyYW0ge0FycmF5fSBzdGFydCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEBwYXJhbSB7QXJyYXl9IGVuZCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEByZXR1cm4ge051bWJlcn0gcm90YXRpb25cbiAgICovXG4gIGdldFJvdGF0aW9uOiBmdW5jdGlvbiBnZXRSb3RhdGlvbihzdGFydCwgZW5kKSB7XG4gICAgLy8gbmVlZCB0d28gZmluZ2Vyc1xuICAgIGlmKHN0YXJ0Lmxlbmd0aCA+PSAyICYmIGVuZC5sZW5ndGggPj0gMikge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0QW5nbGUoZW5kWzFdLCBlbmRbMF0pIC0gdGhpcy5nZXRBbmdsZShzdGFydFsxXSwgc3RhcnRbMF0pO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfSxcblxuICAvKipcbiAgICogZmluZCBvdXQgaWYgdGhlIGRpcmVjdGlvbiBpcyB2ZXJ0aWNhbCAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IGRpcmVjdGlvbiBtYXRjaGVzIGBESVJFQ1RJT05fVVB8RE9XTmBcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gaXNfdmVydGljYWxcbiAgICovXG4gIGlzVmVydGljYWw6IGZ1bmN0aW9uIGlzVmVydGljYWwoZGlyZWN0aW9uKSB7XG4gICAgcmV0dXJuIGRpcmVjdGlvbiA9PSBESVJFQ1RJT05fVVAgfHwgZGlyZWN0aW9uID09IERJUkVDVElPTl9ET1dOO1xuICB9LFxuXG4gIC8qKlxuICAgKiBzZXQgY3NzIHByb3BlcnRpZXMgd2l0aCB0aGVpciBwcmVmaXhlc1xuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFt0b2dnbGU9dHJ1ZV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIHNldFByZWZpeGVkQ3NzOiBmdW5jdGlvbiBzZXRQcmVmaXhlZENzcyhlbGVtZW50LCBwcm9wLCB2YWx1ZSwgdG9nZ2xlKSB7XG4gICAgdmFyIHByZWZpeGVzID0gWycnLCAnV2Via2l0JywgJ01veicsICdPJywgJ21zJ107XG4gICAgcHJvcCA9IFV0aWxzLnRvQ2FtZWxDYXNlKHByb3ApO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHByZWZpeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcCA9IHByb3A7XG4gICAgICAvLyBwcmVmaXhlc1xuICAgICAgaWYocHJlZml4ZXNbaV0pIHtcbiAgICAgICAgcCA9IHByZWZpeGVzW2ldICsgcC5zbGljZSgwLCAxKS50b1VwcGVyQ2FzZSgpICsgcC5zbGljZSgxKTtcbiAgICAgIH1cblxuICAgICAgLy8gdGVzdCB0aGUgc3R5bGVcbiAgICAgIGlmKHAgaW4gZWxlbWVudC5zdHlsZSkge1xuICAgICAgICBlbGVtZW50LnN0eWxlW3BdID0gKHRvZ2dsZSA9PT0gbnVsbCB8fCB0b2dnbGUpICYmIHZhbHVlIHx8ICcnO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIHRvZ2dsZSBicm93c2VyIGRlZmF1bHQgYmVoYXZpb3IgYnkgc2V0dGluZyBjc3MgcHJvcGVydGllcy5cbiAgICogYHVzZXJTZWxlY3Q9J25vbmUnYCBhbHNvIHNldHMgYGVsZW1lbnQub25zZWxlY3RzdGFydGAgdG8gZmFsc2VcbiAgICogYHVzZXJEcmFnPSdub25lJ2AgYWxzbyBzZXRzIGBlbGVtZW50Lm9uZHJhZ3N0YXJ0YCB0byBmYWxzZVxuICAgKlxuICAgKiBAcGFyYW0ge0h0bWxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wc1xuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFt0b2dnbGU9dHJ1ZV1cbiAgICovXG4gIHRvZ2dsZUJlaGF2aW9yOiBmdW5jdGlvbiB0b2dnbGVCZWhhdmlvcihlbGVtZW50LCBwcm9wcywgdG9nZ2xlKSB7XG4gICAgaWYoIXByb3BzIHx8ICFlbGVtZW50IHx8ICFlbGVtZW50LnN0eWxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gc2V0IHRoZSBjc3MgcHJvcGVydGllc1xuICAgIFV0aWxzLmVhY2gocHJvcHMsIGZ1bmN0aW9uKHZhbHVlLCBwcm9wKSB7XG4gICAgICBVdGlscy5zZXRQcmVmaXhlZENzcyhlbGVtZW50LCBwcm9wLCB2YWx1ZSwgdG9nZ2xlKTtcbiAgICB9KTtcblxuICAgIHZhciBmYWxzZUZuID0gdG9nZ2xlICYmIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvLyBhbHNvIHRoZSBkaXNhYmxlIG9uc2VsZWN0c3RhcnRcbiAgICBpZihwcm9wcy51c2VyU2VsZWN0ID09ICdub25lJykge1xuICAgICAgZWxlbWVudC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcbiAgICB9XG4gICAgLy8gYW5kIGRpc2FibGUgb25kcmFnc3RhcnRcbiAgICBpZihwcm9wcy51c2VyRHJhZyA9PSAnbm9uZScpIHtcbiAgICAgIGVsZW1lbnQub25kcmFnc3RhcnQgPSBmYWxzZUZuO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogY29udmVydCBhIHN0cmluZyB3aXRoIHVuZGVyc2NvcmVzIHRvIGNhbWVsQ2FzZVxuICAgKiBzbyBwcmV2ZW50X2RlZmF1bHQgYmVjb21lcyBwcmV2ZW50RGVmYXVsdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gICAqIEByZXR1cm4ge1N0cmluZ30gY2FtZWxDYXNlU3RyXG4gICAqL1xuICB0b0NhbWVsQ2FzZTogZnVuY3Rpb24gdG9DYW1lbENhc2Uoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9bXy1dKFthLXpdKS9nLCBmdW5jdGlvbihzKSB7XG4gICAgICByZXR1cm4gc1sxXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0pO1xuICB9XG59O1xuXG5cbi8qKlxuICogQG1vZHVsZSBHZXN0dXJlRGV0ZWN0b3JcbiAqL1xuLyoqXG4gKiBAY2xhc3MgRXZlbnRcbiAqIEBzdGF0aWNcbiAqL1xuRXZlbnQgPSBHZXN0dXJlRGV0ZWN0b3IuZXZlbnQgPSB7XG4gIC8qKlxuICAgKiB3aGVuIHRvdWNoIGV2ZW50cyBoYXZlIGJlZW4gZmlyZWQsIHRoaXMgaXMgdHJ1ZVxuICAgKiB0aGlzIGlzIHVzZWQgdG8gc3RvcCBtb3VzZSBldmVudHNcbiAgICogQHByb3BlcnR5IHByZXZlbnRfbW91c2VldmVudHNcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqL1xuICBwcmV2ZW50TW91c2VFdmVudHM6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBpZiBFVkVOVF9TVEFSVCBoYXMgYmVlbiBmaXJlZFxuICAgKiBAcHJvcGVydHkgc3RhcnRlZFxuICAgKiBAcHJpdmF0ZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICovXG4gIHN0YXJ0ZWQ6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiB3aGVuIHRoZSBtb3VzZSBpcyBob2xkIGRvd24sIHRoaXMgaXMgdHJ1ZVxuICAgKiBAcHJvcGVydHkgc2hvdWxkX2RldGVjdFxuICAgKiBAcHJpdmF0ZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICovXG4gIHNob3VsZERldGVjdDogZmFsc2UsXG5cbiAgLyoqXG4gICAqIHNpbXBsZSBldmVudCBiaW5kZXIgd2l0aCBhIGhvb2sgYW5kIHN1cHBvcnQgZm9yIG11bHRpcGxlIHR5cGVzXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaG9va11cbiAgICogQHBhcmFtIHtPYmplY3R9IGhvb2sudHlwZVxuICAgKi9cbiAgb246IGZ1bmN0aW9uIG9uKGVsZW1lbnQsIHR5cGUsIGhhbmRsZXIsIGhvb2spIHtcbiAgICB2YXIgdHlwZXMgPSB0eXBlLnNwbGl0KCcgJyk7XG4gICAgVXRpbHMuZWFjaCh0eXBlcywgZnVuY3Rpb24odHlwZSkge1xuICAgICAgVXRpbHMub24oZWxlbWVudCwgdHlwZSwgaGFuZGxlcik7XG4gICAgICBob29rICYmIGhvb2sodHlwZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHNpbXBsZSBldmVudCB1bmJpbmRlciB3aXRoIGEgaG9vayBhbmQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgdHlwZXNcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtob29rXVxuICAgKiBAcGFyYW0ge09iamVjdH0gaG9vay50eXBlXG4gICAqL1xuICBvZmY6IGZ1bmN0aW9uIG9mZihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBob29rKSB7XG4gICAgdmFyIHR5cGVzID0gdHlwZS5zcGxpdCgnICcpO1xuICAgIFV0aWxzLmVhY2godHlwZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIFV0aWxzLm9mZihlbGVtZW50LCB0eXBlLCBoYW5kbGVyKTtcbiAgICAgIGhvb2sgJiYgaG9vayh0eXBlKTtcbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogdGhlIGNvcmUgdG91Y2ggZXZlbnQgaGFuZGxlci5cbiAgICogdGhpcyBmaW5kcyBvdXQgaWYgd2Ugc2hvdWxkIHRvIGRldGVjdCBnZXN0dXJlc1xuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogQHJldHVybiBvblRvdWNoSGFuZGxlciB7RnVuY3Rpb259IHRoZSBjb3JlIGV2ZW50IGhhbmRsZXJcbiAgICovXG4gIG9uVG91Y2g6IGZ1bmN0aW9uIG9uVG91Y2goZWxlbWVudCwgZXZlbnRUeXBlLCBoYW5kbGVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIG9uVG91Y2hIYW5kbGVyID0gZnVuY3Rpb24gb25Ub3VjaEhhbmRsZXIoZXYpIHtcbiAgICAgIHZhciBzcmNUeXBlID0gZXYudHlwZS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgIGlzUG9pbnRlciA9IEdlc3R1cmVEZXRlY3Rvci5IQVNfUE9JTlRFUkVWRU5UUyxcbiAgICAgICAgICBpc01vdXNlID0gVXRpbHMuaW5TdHIoc3JjVHlwZSwgJ21vdXNlJyksXG4gICAgICAgICAgdHJpZ2dlclR5cGU7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSBpbiBhIG1vdXNlZXZlbnQsIGJ1dCB0aGVyZSBoYXMgYmVlbiBhIHRvdWNoZXZlbnQgdHJpZ2dlcmVkIGluIHRoaXMgc2Vzc2lvblxuICAgICAgLy8gd2Ugd2FudCB0byBkbyBub3RoaW5nLiBzaW1wbHkgYnJlYWsgb3V0IG9mIHRoZSBldmVudC5cbiAgICAgIGlmKGlzTW91c2UgJiYgc2VsZi5wcmV2ZW50TW91c2VFdmVudHMpIHtcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIC8vIG1vdXNlYnV0dG9uIG11c3QgYmUgZG93blxuICAgICAgfSBlbHNlIGlmKGlzTW91c2UgJiYgZXZlbnRUeXBlID09IEVWRU5UX1NUQVJUICYmIGV2LmJ1dHRvbiA9PT0gMCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYoaXNQb2ludGVyICYmIGV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IChldi5idXR0b25zID09PSAxIHx8IFBvaW50ZXJFdmVudC5tYXRjaFR5cGUoUE9JTlRFUl9UT1VDSCwgZXYpKTtcbiAgICAgICAgLy8ganVzdCBhIHZhbGlkIHN0YXJ0IGV2ZW50LCBidXQgbm8gbW91c2VcbiAgICAgIH0gZWxzZSBpZighaXNNb3VzZSAmJiBldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgICAgc2VsZi5wcmV2ZW50TW91c2VFdmVudHMgPSB0cnVlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIC8vIHVwZGF0ZSB0aGUgcG9pbnRlciBldmVudCBiZWZvcmUgZW50ZXJpbmcgdGhlIGRldGVjdGlvblxuICAgICAgaWYoaXNQb2ludGVyICYmIGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgICAgUG9pbnRlckV2ZW50LnVwZGF0ZVBvaW50ZXIoZXZlbnRUeXBlLCBldik7XG4gICAgICB9XG5cbiAgICAgIC8vIHdlIGFyZSBpbiBhIHRvdWNoL2Rvd24gc3RhdGUsIHNvIGFsbG93ZWQgZGV0ZWN0aW9uIG9mIGdlc3R1cmVzXG4gICAgICBpZihzZWxmLnNob3VsZERldGVjdCkge1xuICAgICAgICB0cmlnZ2VyVHlwZSA9IHNlbGYuZG9EZXRlY3QuY2FsbChzZWxmLCBldiwgZXZlbnRUeXBlLCBlbGVtZW50LCBoYW5kbGVyKTtcbiAgICAgIH1cblxuICAgICAgLy8gLi4uYW5kIHdlIGFyZSBkb25lIHdpdGggdGhlIGRldGVjdGlvblxuICAgICAgLy8gc28gcmVzZXQgZXZlcnl0aGluZyB0byBzdGFydCBlYWNoIGRldGVjdGlvbiB0b3RhbGx5IGZyZXNoXG4gICAgICBpZih0cmlnZ2VyVHlwZSA9PSBFVkVOVF9FTkQpIHtcbiAgICAgICAgc2VsZi5wcmV2ZW50TW91c2VFdmVudHMgPSBmYWxzZTtcbiAgICAgICAgc2VsZi5zaG91bGREZXRlY3QgPSBmYWxzZTtcbiAgICAgICAgUG9pbnRlckV2ZW50LnJlc2V0KCk7XG4gICAgICAgIC8vIHVwZGF0ZSB0aGUgcG9pbnRlcmV2ZW50IG9iamVjdCBhZnRlciB0aGUgZGV0ZWN0aW9uXG4gICAgICB9XG5cbiAgICAgIGlmKGlzUG9pbnRlciAmJiBldmVudFR5cGUgPT0gRVZFTlRfRU5EKSB7XG4gICAgICAgIFBvaW50ZXJFdmVudC51cGRhdGVQb2ludGVyKGV2ZW50VHlwZSwgZXYpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLm9uKGVsZW1lbnQsIEVWRU5UX1RZUEVTW2V2ZW50VHlwZV0sIG9uVG91Y2hIYW5kbGVyKTtcbiAgICByZXR1cm4gb25Ub3VjaEhhbmRsZXI7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHRoZSBjb3JlIGRldGVjdGlvbiBtZXRob2RcbiAgICogdGhpcyBmaW5kcyBvdXQgd2hhdCBHZXN0dXJlRGV0ZWN0b3ItdG91Y2gtZXZlbnRzIHRvIHRyaWdnZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IHRyaWdnZXJUeXBlIG1hdGNoZXMgYEVWRU5UX1NUQVJUfE1PVkV8RU5EYFxuICAgKi9cbiAgZG9EZXRlY3Q6IGZ1bmN0aW9uIGRvRGV0ZWN0KGV2LCBldmVudFR5cGUsIGVsZW1lbnQsIGhhbmRsZXIpIHtcbiAgICB2YXIgdG91Y2hMaXN0ID0gdGhpcy5nZXRUb3VjaExpc3QoZXYsIGV2ZW50VHlwZSk7XG4gICAgdmFyIHRvdWNoTGlzdExlbmd0aCA9IHRvdWNoTGlzdC5sZW5ndGg7XG4gICAgdmFyIHRyaWdnZXJUeXBlID0gZXZlbnRUeXBlO1xuICAgIHZhciB0cmlnZ2VyQ2hhbmdlID0gdG91Y2hMaXN0LnRyaWdnZXI7IC8vIHVzZWQgYnkgZmFrZU11bHRpdG91Y2ggcGx1Z2luXG4gICAgdmFyIGNoYW5nZWRMZW5ndGggPSB0b3VjaExpc3RMZW5ndGg7XG5cbiAgICAvLyBhdCBlYWNoIHRvdWNoc3RhcnQtbGlrZSBldmVudCB3ZSB3YW50IGFsc28gd2FudCB0byB0cmlnZ2VyIGEgVE9VQ0ggZXZlbnQuLi5cbiAgICBpZihldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgIHRyaWdnZXJDaGFuZ2UgPSBFVkVOVF9UT1VDSDtcbiAgICAgIC8vIC4uLnRoZSBzYW1lIGZvciBhIHRvdWNoZW5kLWxpa2UgZXZlbnRcbiAgICB9IGVsc2UgaWYoZXZlbnRUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgdHJpZ2dlckNoYW5nZSA9IEVWRU5UX1JFTEVBU0U7XG5cbiAgICAgIC8vIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdG91Y2hlcyBoYXZlIGJlZW4gcmVtb3ZlZFxuICAgICAgY2hhbmdlZExlbmd0aCA9IHRvdWNoTGlzdC5sZW5ndGggLSAoKGV2LmNoYW5nZWRUb3VjaGVzKSA/IGV2LmNoYW5nZWRUb3VjaGVzLmxlbmd0aCA6IDEpO1xuICAgIH1cblxuICAgIC8vIGFmdGVyIHRoZXJlIGFyZSBzdGlsbCB0b3VjaGVzIG9uIHRoZSBzY3JlZW4sXG4gICAgLy8gd2UganVzdCB3YW50IHRvIHRyaWdnZXIgYSBNT1ZFIGV2ZW50LiBzbyBjaGFuZ2UgdGhlIFNUQVJUIG9yIEVORCB0byBhIE1PVkVcbiAgICAvLyBidXQgb25seSBhZnRlciBkZXRlY3Rpb24gaGFzIGJlZW4gc3RhcnRlZCwgdGhlIGZpcnN0IHRpbWUgd2UgYWN0dWFsbHkgd2FudCBhIFNUQVJUXG4gICAgaWYoY2hhbmdlZExlbmd0aCA+IDAgJiYgdGhpcy5zdGFydGVkKSB7XG4gICAgICB0cmlnZ2VyVHlwZSA9IEVWRU5UX01PVkU7XG4gICAgfVxuXG4gICAgLy8gZGV0ZWN0aW9uIGhhcyBiZWVuIHN0YXJ0ZWQsIHdlIGtlZXAgdHJhY2sgb2YgdGhpcywgc2VlIGFib3ZlXG4gICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcblxuICAgIC8vIGdlbmVyYXRlIHNvbWUgZXZlbnQgZGF0YSwgc29tZSBiYXNpYyBpbmZvcm1hdGlvblxuICAgIHZhciBldkRhdGEgPSB0aGlzLmNvbGxlY3RFdmVudERhdGEoZWxlbWVudCwgdHJpZ2dlclR5cGUsIHRvdWNoTGlzdCwgZXYpO1xuXG4gICAgLy8gdHJpZ2dlciB0aGUgdHJpZ2dlclR5cGUgZXZlbnQgYmVmb3JlIHRoZSBjaGFuZ2UgKFRPVUNILCBSRUxFQVNFKSBldmVudHNcbiAgICAvLyBidXQgdGhlIEVORCBldmVudCBzaG91bGQgYmUgYXQgbGFzdFxuICAgIGlmKGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgIGhhbmRsZXIuY2FsbChEZXRlY3Rpb24sIGV2RGF0YSk7XG4gICAgfVxuXG4gICAgLy8gdHJpZ2dlciBhIGNoYW5nZSAoVE9VQ0gsIFJFTEVBU0UpIGV2ZW50LCB0aGlzIG1lYW5zIHRoZSBsZW5ndGggb2YgdGhlIHRvdWNoZXMgY2hhbmdlZFxuICAgIGlmKHRyaWdnZXJDaGFuZ2UpIHtcbiAgICAgIGV2RGF0YS5jaGFuZ2VkTGVuZ3RoID0gY2hhbmdlZExlbmd0aDtcbiAgICAgIGV2RGF0YS5ldmVudFR5cGUgPSB0cmlnZ2VyQ2hhbmdlO1xuXG4gICAgICBoYW5kbGVyLmNhbGwoRGV0ZWN0aW9uLCBldkRhdGEpO1xuXG4gICAgICBldkRhdGEuZXZlbnRUeXBlID0gdHJpZ2dlclR5cGU7XG4gICAgICBkZWxldGUgZXZEYXRhLmNoYW5nZWRMZW5ndGg7XG4gICAgfVxuXG4gICAgLy8gdHJpZ2dlciB0aGUgRU5EIGV2ZW50XG4gICAgaWYodHJpZ2dlclR5cGUgPT0gRVZFTlRfRU5EKSB7XG4gICAgICBoYW5kbGVyLmNhbGwoRGV0ZWN0aW9uLCBldkRhdGEpO1xuXG4gICAgICAvLyAuLi5hbmQgd2UgYXJlIGRvbmUgd2l0aCB0aGUgZGV0ZWN0aW9uXG4gICAgICAvLyBzbyByZXNldCBldmVyeXRoaW5nIHRvIHN0YXJ0IGVhY2ggZGV0ZWN0aW9uIHRvdGFsbHkgZnJlc2hcbiAgICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cmlnZ2VyVHlwZTtcbiAgfSxcblxuICAvKipcbiAgICogd2UgaGF2ZSBkaWZmZXJlbnQgZXZlbnRzIGZvciBlYWNoIGRldmljZS9icm93c2VyXG4gICAqIGRldGVybWluZSB3aGF0IHdlIG5lZWQgYW5kIHNldCB0aGVtIGluIHRoZSBFVkVOVF9UWVBFUyBjb25zdGFudFxuICAgKiB0aGUgYG9uVG91Y2hgIG1ldGhvZCBpcyBiaW5kIHRvIHRoZXNlIHByb3BlcnRpZXMuXG4gICAqIEByZXR1cm4ge09iamVjdH0gZXZlbnRzXG4gICAqL1xuICBkZXRlcm1pbmVFdmVudFR5cGVzOiBmdW5jdGlvbiBkZXRlcm1pbmVFdmVudFR5cGVzKCkge1xuICAgIHZhciB0eXBlcztcbiAgICBpZihHZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMpIHtcbiAgICAgIGlmKHdpbmRvdy5Qb2ludGVyRXZlbnQpIHtcbiAgICAgICAgdHlwZXMgPSBbXG4gICAgICAgICAgJ3BvaW50ZXJkb3duJyxcbiAgICAgICAgICAncG9pbnRlcm1vdmUnLFxuICAgICAgICAgICdwb2ludGVydXAgcG9pbnRlcmNhbmNlbCBsb3N0cG9pbnRlcmNhcHR1cmUnXG4gICAgICAgIF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0eXBlcyA9IFtcbiAgICAgICAgICAnTVNQb2ludGVyRG93bicsXG4gICAgICAgICAgJ01TUG9pbnRlck1vdmUnLFxuICAgICAgICAgICdNU1BvaW50ZXJVcCBNU1BvaW50ZXJDYW5jZWwgTVNMb3N0UG9pbnRlckNhcHR1cmUnXG4gICAgICAgIF07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKEdlc3R1cmVEZXRlY3Rvci5OT19NT1VTRUVWRU5UUykge1xuICAgICAgdHlwZXMgPSBbXG4gICAgICAgICd0b3VjaHN0YXJ0JyxcbiAgICAgICAgJ3RvdWNobW92ZScsXG4gICAgICAgICd0b3VjaGVuZCB0b3VjaGNhbmNlbCdcbiAgICAgIF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHR5cGVzID0gW1xuICAgICAgICAndG91Y2hzdGFydCBtb3VzZWRvd24nLFxuICAgICAgICAndG91Y2htb3ZlIG1vdXNlbW92ZScsXG4gICAgICAgICd0b3VjaGVuZCB0b3VjaGNhbmNlbCBtb3VzZXVwJ1xuICAgICAgXTtcbiAgICB9XG5cbiAgICBFVkVOVF9UWVBFU1tFVkVOVF9TVEFSVF0gPSB0eXBlc1swXTtcbiAgICBFVkVOVF9UWVBFU1tFVkVOVF9NT1ZFXSA9IHR5cGVzWzFdO1xuICAgIEVWRU5UX1RZUEVTW0VWRU5UX0VORF0gPSB0eXBlc1syXTtcbiAgICByZXR1cm4gRVZFTlRfVFlQRVM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNyZWF0ZSB0b3VjaExpc3QgZGVwZW5kaW5nIG9uIHRoZSBldmVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50VHlwZVxuICAgKiBAcmV0dXJuIHtBcnJheX0gdG91Y2hlc1xuICAgKi9cbiAgZ2V0VG91Y2hMaXN0OiBmdW5jdGlvbiBnZXRUb3VjaExpc3QoZXYsIGV2ZW50VHlwZSkge1xuICAgIC8vIGdldCB0aGUgZmFrZSBwb2ludGVyRXZlbnQgdG91Y2hsaXN0XG4gICAgaWYoR2VzdHVyZURldGVjdG9yLkhBU19QT0lOVEVSRVZFTlRTKSB7XG4gICAgICByZXR1cm4gUG9pbnRlckV2ZW50LmdldFRvdWNoTGlzdCgpO1xuICAgIH1cblxuICAgIC8vIGdldCB0aGUgdG91Y2hsaXN0XG4gICAgaWYoZXYudG91Y2hlcykge1xuICAgICAgaWYoZXZlbnRUeXBlID09IEVWRU5UX01PVkUpIHtcbiAgICAgICAgcmV0dXJuIGV2LnRvdWNoZXM7XG4gICAgICB9XG5cbiAgICAgIHZhciBpZGVudGlmaWVycyA9IFtdO1xuICAgICAgdmFyIGNvbmNhdCA9IFtdLmNvbmNhdChVdGlscy50b0FycmF5KGV2LnRvdWNoZXMpLCBVdGlscy50b0FycmF5KGV2LmNoYW5nZWRUb3VjaGVzKSk7XG4gICAgICB2YXIgdG91Y2hMaXN0ID0gW107XG5cbiAgICAgIFV0aWxzLmVhY2goY29uY2F0LCBmdW5jdGlvbih0b3VjaCkge1xuICAgICAgICBpZihVdGlscy5pbkFycmF5KGlkZW50aWZpZXJzLCB0b3VjaC5pZGVudGlmaWVyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0b3VjaExpc3QucHVzaCh0b3VjaCk7XG4gICAgICAgIH1cbiAgICAgICAgaWRlbnRpZmllcnMucHVzaCh0b3VjaC5pZGVudGlmaWVyKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdG91Y2hMaXN0O1xuICAgIH1cblxuICAgIC8vIG1ha2UgZmFrZSB0b3VjaExpc3QgZnJvbSBtb3VzZSBwb3NpdGlvblxuICAgIGV2LmlkZW50aWZpZXIgPSAxO1xuICAgIHJldHVybiBbZXZdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjb2xsZWN0IGJhc2ljIGV2ZW50IGRhdGFcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlIG1hdGNoZXMgYEVWRU5UX1NUQVJUfE1PVkV8RU5EYFxuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IGV2XG4gICAqL1xuICBjb2xsZWN0RXZlbnREYXRhOiBmdW5jdGlvbiBjb2xsZWN0RXZlbnREYXRhKGVsZW1lbnQsIGV2ZW50VHlwZSwgdG91Y2hlcywgZXYpIHtcbiAgICAvLyBmaW5kIG91dCBwb2ludGVyVHlwZVxuICAgIHZhciBwb2ludGVyVHlwZSA9IFBPSU5URVJfVE9VQ0g7XG4gICAgaWYoVXRpbHMuaW5TdHIoZXYudHlwZSwgJ21vdXNlJykgfHwgUG9pbnRlckV2ZW50Lm1hdGNoVHlwZShQT0lOVEVSX01PVVNFLCBldikpIHtcbiAgICAgIHBvaW50ZXJUeXBlID0gUE9JTlRFUl9NT1VTRTtcbiAgICB9IGVsc2UgaWYoUG9pbnRlckV2ZW50Lm1hdGNoVHlwZShQT0lOVEVSX1BFTiwgZXYpKSB7XG4gICAgICBwb2ludGVyVHlwZSA9IFBPSU5URVJfUEVOO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjZW50ZXI6IFV0aWxzLmdldENlbnRlcih0b3VjaGVzKSxcbiAgICAgIHRpbWVTdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgIHRhcmdldDogZXYudGFyZ2V0LFxuICAgICAgdG91Y2hlczogdG91Y2hlcyxcbiAgICAgIGV2ZW50VHlwZTogZXZlbnRUeXBlLFxuICAgICAgcG9pbnRlclR5cGU6IHBvaW50ZXJUeXBlLFxuICAgICAgc3JjRXZlbnQ6IGV2LFxuXG4gICAgICAvKipcbiAgICAgICAqIHByZXZlbnQgdGhlIGJyb3dzZXIgZGVmYXVsdCBhY3Rpb25zXG4gICAgICAgKiBtb3N0bHkgdXNlZCB0byBkaXNhYmxlIHNjcm9sbGluZyBvZiB0aGUgYnJvd3NlclxuICAgICAgICovXG4gICAgICBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBzcmNFdmVudCA9IHRoaXMuc3JjRXZlbnQ7XG4gICAgICAgIHNyY0V2ZW50LnByZXZlbnRNYW5pcHVsYXRpb24gJiYgc3JjRXZlbnQucHJldmVudE1hbmlwdWxhdGlvbigpO1xuICAgICAgICBzcmNFdmVudC5wcmV2ZW50RGVmYXVsdCAmJiBzcmNFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfSxcblxuICAgICAgLyoqXG4gICAgICAgKiBzdG9wIGJ1YmJsaW5nIHRoZSBldmVudCB1cCB0byBpdHMgcGFyZW50c1xuICAgICAgICovXG4gICAgICBzdG9wUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLnNyY0V2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfSxcblxuICAgICAgLyoqXG4gICAgICAgKiBpbW1lZGlhdGVseSBzdG9wIGdlc3R1cmUgZGV0ZWN0aW9uXG4gICAgICAgKiBtaWdodCBiZSB1c2VmdWwgYWZ0ZXIgYSBzd2lwZSB3YXMgZGV0ZWN0ZWRcbiAgICAgICAqIEByZXR1cm4geyp9XG4gICAgICAgKi9cbiAgICAgIHN0b3BEZXRlY3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gRGV0ZWN0aW9uLnN0b3BEZXRlY3QoKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG59O1xuXG5cbi8qKlxuICogQG1vZHVsZSBHZXN0dXJlRGV0ZWN0b3JcbiAqXG4gKiBAY2xhc3MgUG9pbnRlckV2ZW50XG4gKiBAc3RhdGljXG4gKi9cblBvaW50ZXJFdmVudCA9IEdlc3R1cmVEZXRlY3Rvci5Qb2ludGVyRXZlbnQgPSB7XG4gIC8qKlxuICAgKiBob2xkcyBhbGwgcG9pbnRlcnMsIGJ5IGBpZGVudGlmaWVyYFxuICAgKiBAcHJvcGVydHkgcG9pbnRlcnNcbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHBvaW50ZXJzOiB7fSxcblxuICAvKipcbiAgICogZ2V0IHRoZSBwb2ludGVycyBhcyBhbiBhcnJheVxuICAgKiBAcmV0dXJuIHtBcnJheX0gdG91Y2hsaXN0XG4gICAqL1xuICBnZXRUb3VjaExpc3Q6IGZ1bmN0aW9uIGdldFRvdWNoTGlzdCgpIHtcbiAgICB2YXIgdG91Y2hsaXN0ID0gW107XG4gICAgLy8gd2UgY2FuIHVzZSBmb3JFYWNoIHNpbmNlIHBvaW50ZXJFdmVudHMgb25seSBpcyBpbiBJRTEwXG4gICAgVXRpbHMuZWFjaCh0aGlzLnBvaW50ZXJzLCBmdW5jdGlvbihwb2ludGVyKSB7XG4gICAgICB0b3VjaGxpc3QucHVzaChwb2ludGVyKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdG91Y2hsaXN0O1xuICB9LFxuXG4gIC8qKlxuICAgKiB1cGRhdGUgdGhlIHBvc2l0aW9uIG9mIGEgcG9pbnRlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlIG1hdGNoZXMgYEVWRU5UX1NUQVJUfE1PVkV8RU5EYFxuICAgKiBAcGFyYW0ge09iamVjdH0gcG9pbnRlckV2ZW50XG4gICAqL1xuICB1cGRhdGVQb2ludGVyOiBmdW5jdGlvbiB1cGRhdGVQb2ludGVyKGV2ZW50VHlwZSwgcG9pbnRlckV2ZW50KSB7XG4gICAgaWYoZXZlbnRUeXBlID09IEVWRU5UX0VORCB8fCAoZXZlbnRUeXBlICE9IEVWRU5UX0VORCAmJiBwb2ludGVyRXZlbnQuYnV0dG9ucyAhPT0gMSkpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdO1xuICAgIH0gZWxzZSB7XG4gICAgICBwb2ludGVyRXZlbnQuaWRlbnRpZmllciA9IHBvaW50ZXJFdmVudC5wb2ludGVySWQ7XG4gICAgICB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdID0gcG9pbnRlckV2ZW50O1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogY2hlY2sgaWYgZXYgbWF0Y2hlcyBwb2ludGVydHlwZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcG9pbnRlclR5cGUgbWF0Y2hlcyBgUE9JTlRFUl9NT1VTRXxUT1VDSHxQRU5gXG4gICAqIEBwYXJhbSB7UG9pbnRlckV2ZW50fSBldlxuICAgKi9cbiAgbWF0Y2hUeXBlOiBmdW5jdGlvbiBtYXRjaFR5cGUocG9pbnRlclR5cGUsIGV2KSB7XG4gICAgaWYoIWV2LnBvaW50ZXJUeXBlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIHB0ID0gZXYucG9pbnRlclR5cGUsXG4gICAgICAgIHR5cGVzID0ge307XG5cbiAgICB0eXBlc1tQT0lOVEVSX01PVVNFXSA9IChwdCA9PT0gKGV2Lk1TUE9JTlRFUl9UWVBFX01PVVNFIHx8IFBPSU5URVJfTU9VU0UpKTtcbiAgICB0eXBlc1tQT0lOVEVSX1RPVUNIXSA9IChwdCA9PT0gKGV2Lk1TUE9JTlRFUl9UWVBFX1RPVUNIIHx8IFBPSU5URVJfVE9VQ0gpKTtcbiAgICB0eXBlc1tQT0lOVEVSX1BFTl0gPSAocHQgPT09IChldi5NU1BPSU5URVJfVFlQRV9QRU4gfHwgUE9JTlRFUl9QRU4pKTtcbiAgICByZXR1cm4gdHlwZXNbcG9pbnRlclR5cGVdO1xuICB9LFxuXG4gIC8qKlxuICAgKiByZXNldCB0aGUgc3RvcmVkIHBvaW50ZXJzXG4gICAqL1xuICByZXNldDogZnVuY3Rpb24gcmVzZXRMaXN0KCkge1xuICAgIHRoaXMucG9pbnRlcnMgPSB7fTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKlxuICogQGNsYXNzIERldGVjdGlvblxuICogQHN0YXRpY1xuICovXG5EZXRlY3Rpb24gPSBHZXN0dXJlRGV0ZWN0b3IuZGV0ZWN0aW9uID0ge1xuICAvLyBjb250YWlucyBhbGwgcmVnaXN0ZXJlZCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMgaW4gdGhlIGNvcnJlY3Qgb3JkZXJcbiAgZ2VzdHVyZXM6IFtdLFxuXG4gIC8vIGRhdGEgb2YgdGhlIGN1cnJlbnQgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgZGV0ZWN0aW9uIHNlc3Npb25cbiAgY3VycmVudDogbnVsbCxcblxuICAvLyB0aGUgcHJldmlvdXMgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgc2Vzc2lvbiBkYXRhXG4gIC8vIGlzIGEgZnVsbCBjbG9uZSBvZiB0aGUgcHJldmlvdXMgZ2VzdHVyZS5jdXJyZW50IG9iamVjdFxuICBwcmV2aW91czogbnVsbCxcblxuICAvLyB3aGVuIHRoaXMgYmVjb21lcyB0cnVlLCBubyBnZXN0dXJlcyBhcmUgZmlyZWRcbiAgc3RvcHBlZDogZmFsc2UsXG5cbiAgLyoqXG4gICAqIHN0YXJ0IEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIGRldGVjdGlvblxuICAgKiBAcGFyYW0ge0dlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZX0gaW5zdFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnREYXRhXG4gICAqL1xuICBzdGFydERldGVjdDogZnVuY3Rpb24gc3RhcnREZXRlY3QoaW5zdCwgZXZlbnREYXRhKSB7XG4gICAgLy8gYWxyZWFkeSBidXN5IHdpdGggYSBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBkZXRlY3Rpb24gb24gYW4gZWxlbWVudFxuICAgIGlmKHRoaXMuY3VycmVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3RvcHBlZCA9IGZhbHNlO1xuXG4gICAgLy8gaG9sZHMgY3VycmVudCBzZXNzaW9uXG4gICAgdGhpcy5jdXJyZW50ID0ge1xuICAgICAgaW5zdDogaW5zdCwgLy8gcmVmZXJlbmNlIHRvIEdlc3R1cmVEZXRlY3Rvckluc3RhbmNlIHdlJ3JlIHdvcmtpbmcgZm9yXG4gICAgICBzdGFydEV2ZW50OiBVdGlscy5leHRlbmQoe30sIGV2ZW50RGF0YSksIC8vIHN0YXJ0IGV2ZW50RGF0YSBmb3IgZGlzdGFuY2VzLCB0aW1pbmcgZXRjXG4gICAgICBsYXN0RXZlbnQ6IGZhbHNlLCAvLyBsYXN0IGV2ZW50RGF0YVxuICAgICAgbGFzdENhbGNFdmVudDogZmFsc2UsIC8vIGxhc3QgZXZlbnREYXRhIGZvciBjYWxjdWxhdGlvbnMuXG4gICAgICBmdXR1cmVDYWxjRXZlbnQ6IGZhbHNlLCAvLyBsYXN0IGV2ZW50RGF0YSBmb3IgY2FsY3VsYXRpb25zLlxuICAgICAgbGFzdENhbGNEYXRhOiB7fSwgLy8gbGFzdCBsYXN0Q2FsY0RhdGFcbiAgICAgIG5hbWU6ICcnIC8vIGN1cnJlbnQgZ2VzdHVyZSB3ZSdyZSBpbi9kZXRlY3RlZCwgY2FuIGJlICd0YXAnLCAnaG9sZCcgZXRjXG4gICAgfTtcblxuICAgIHRoaXMuZGV0ZWN0KGV2ZW50RGF0YSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIGRldGVjdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnREYXRhXG4gICAqIEByZXR1cm4ge2FueX1cbiAgICovXG4gIGRldGVjdDogZnVuY3Rpb24gZGV0ZWN0KGV2ZW50RGF0YSkge1xuICAgIGlmKCF0aGlzLmN1cnJlbnQgfHwgdGhpcy5zdG9wcGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZXh0ZW5kIGV2ZW50IGRhdGEgd2l0aCBjYWxjdWxhdGlvbnMgYWJvdXQgc2NhbGUsIGRpc3RhbmNlIGV0Y1xuICAgIGV2ZW50RGF0YSA9IHRoaXMuZXh0ZW5kRXZlbnREYXRhKGV2ZW50RGF0YSk7XG5cbiAgICAvLyBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2UgYW5kIGluc3RhbmNlIG9wdGlvbnNcbiAgICB2YXIgaW5zdCA9IHRoaXMuY3VycmVudC5pbnN0LFxuICAgICAgICBpbnN0T3B0aW9ucyA9IGluc3Qub3B0aW9ucztcblxuICAgIC8vIGNhbGwgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgaGFuZGxlcnNcbiAgICBVdGlscy5lYWNoKHRoaXMuZ2VzdHVyZXMsIGZ1bmN0aW9uIHRyaWdnZXJHZXN0dXJlKGdlc3R1cmUpIHtcbiAgICAgIC8vIG9ubHkgd2hlbiB0aGUgaW5zdGFuY2Ugb3B0aW9ucyBoYXZlIGVuYWJsZWQgdGhpcyBnZXN0dXJlXG4gICAgICBpZighdGhpcy5zdG9wcGVkICYmIGluc3QuZW5hYmxlZCAmJiBpbnN0T3B0aW9uc1tnZXN0dXJlLm5hbWVdKSB7XG4gICAgICAgIGdlc3R1cmUuaGFuZGxlci5jYWxsKGdlc3R1cmUsIGV2ZW50RGF0YSwgaW5zdCk7XG4gICAgICB9XG4gICAgfSwgdGhpcyk7XG5cbiAgICAvLyBzdG9yZSBhcyBwcmV2aW91cyBldmVudCBldmVudFxuICAgIGlmKHRoaXMuY3VycmVudCkge1xuICAgICAgdGhpcy5jdXJyZW50Lmxhc3RFdmVudCA9IGV2ZW50RGF0YTtcbiAgICB9XG5cbiAgICBpZihldmVudERhdGEuZXZlbnRUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgdGhpcy5zdG9wRGV0ZWN0KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZW50RGF0YTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICB9LFxuXG4gIC8qKlxuICAgKiBjbGVhciB0aGUgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgdmFyc1xuICAgKiB0aGlzIGlzIGNhbGxlZCBvbiBlbmREZXRlY3QsIGJ1dCBjYW4gYWxzbyBiZSB1c2VkIHdoZW4gYSBmaW5hbCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBoYXMgYmVlbiBkZXRlY3RlZFxuICAgKiB0byBzdG9wIG90aGVyIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcyBmcm9tIGJlaW5nIGZpcmVkXG4gICAqL1xuICBzdG9wRGV0ZWN0OiBmdW5jdGlvbiBzdG9wRGV0ZWN0KCkge1xuICAgIC8vIGNsb25lIGN1cnJlbnQgZGF0YSB0byB0aGUgc3RvcmUgYXMgdGhlIHByZXZpb3VzIGdlc3R1cmVcbiAgICAvLyB1c2VkIGZvciB0aGUgZG91YmxlIHRhcCBnZXN0dXJlLCBzaW5jZSB0aGlzIGlzIGFuIG90aGVyIGdlc3R1cmUgZGV0ZWN0IHNlc3Npb25cbiAgICB0aGlzLnByZXZpb3VzID0gVXRpbHMuZXh0ZW5kKHt9LCB0aGlzLmN1cnJlbnQpO1xuXG4gICAgLy8gcmVzZXQgdGhlIGN1cnJlbnRcbiAgICB0aGlzLmN1cnJlbnQgPSBudWxsO1xuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB2ZWxvY2l0eSwgYW5nbGUgYW5kIGRpcmVjdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtPYmplY3R9IGNlbnRlclxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFUaW1lXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWVxuICAgKi9cbiAgZ2V0Q2FsY3VsYXRlZERhdGE6IGZ1bmN0aW9uIGdldENhbGN1bGF0ZWREYXRhKGV2LCBjZW50ZXIsIGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICByZWNhbGMgPSBmYWxzZSxcbiAgICAgICAgY2FsY0V2ID0gY3VyLmxhc3RDYWxjRXZlbnQsXG4gICAgICAgIGNhbGNEYXRhID0gY3VyLmxhc3RDYWxjRGF0YTtcblxuICAgIGlmKGNhbGNFdiAmJiBldi50aW1lU3RhbXAgLSBjYWxjRXYudGltZVN0YW1wID4gR2VzdHVyZURldGVjdG9yLkNBTENVTEFURV9JTlRFUlZBTCkge1xuICAgICAgY2VudGVyID0gY2FsY0V2LmNlbnRlcjtcbiAgICAgIGRlbHRhVGltZSA9IGV2LnRpbWVTdGFtcCAtIGNhbGNFdi50aW1lU3RhbXA7XG4gICAgICBkZWx0YVggPSBldi5jZW50ZXIuY2xpZW50WCAtIGNhbGNFdi5jZW50ZXIuY2xpZW50WDtcbiAgICAgIGRlbHRhWSA9IGV2LmNlbnRlci5jbGllbnRZIC0gY2FsY0V2LmNlbnRlci5jbGllbnRZO1xuICAgICAgcmVjYWxjID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZihldi5ldmVudFR5cGUgPT0gRVZFTlRfVE9VQ0ggfHwgZXYuZXZlbnRUeXBlID09IEVWRU5UX1JFTEVBU0UpIHtcbiAgICAgIGN1ci5mdXR1cmVDYWxjRXZlbnQgPSBldjtcbiAgICB9XG5cbiAgICBpZighY3VyLmxhc3RDYWxjRXZlbnQgfHwgcmVjYWxjKSB7XG4gICAgICBjYWxjRGF0YS52ZWxvY2l0eSA9IFV0aWxzLmdldFZlbG9jaXR5KGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpO1xuICAgICAgY2FsY0RhdGEuYW5nbGUgPSBVdGlscy5nZXRBbmdsZShjZW50ZXIsIGV2LmNlbnRlcik7XG4gICAgICBjYWxjRGF0YS5kaXJlY3Rpb24gPSBVdGlscy5nZXREaXJlY3Rpb24oY2VudGVyLCBldi5jZW50ZXIpO1xuXG4gICAgICBjdXIubGFzdENhbGNFdmVudCA9IGN1ci5mdXR1cmVDYWxjRXZlbnQgfHwgZXY7XG4gICAgICBjdXIuZnV0dXJlQ2FsY0V2ZW50ID0gZXY7XG4gICAgfVxuXG4gICAgZXYudmVsb2NpdHlYID0gY2FsY0RhdGEudmVsb2NpdHkueDtcbiAgICBldi52ZWxvY2l0eVkgPSBjYWxjRGF0YS52ZWxvY2l0eS55O1xuICAgIGV2LmludGVyaW1BbmdsZSA9IGNhbGNEYXRhLmFuZ2xlO1xuICAgIGV2LmludGVyaW1EaXJlY3Rpb24gPSBjYWxjRGF0YS5kaXJlY3Rpb247XG4gIH0sXG5cbiAgLyoqXG4gICAqIGV4dGVuZCBldmVudERhdGEgZm9yIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlc1xuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHJldHVybiB7T2JqZWN0fSBldlxuICAgKi9cbiAgZXh0ZW5kRXZlbnREYXRhOiBmdW5jdGlvbiBleHRlbmRFdmVudERhdGEoZXYpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICBzdGFydEV2ID0gY3VyLnN0YXJ0RXZlbnQsXG4gICAgICAgIGxhc3RFdiA9IGN1ci5sYXN0RXZlbnQgfHwgc3RhcnRFdjtcblxuICAgIC8vIHVwZGF0ZSB0aGUgc3RhcnQgdG91Y2hsaXN0IHRvIGNhbGN1bGF0ZSB0aGUgc2NhbGUvcm90YXRpb25cbiAgICBpZihldi5ldmVudFR5cGUgPT0gRVZFTlRfVE9VQ0ggfHwgZXYuZXZlbnRUeXBlID09IEVWRU5UX1JFTEVBU0UpIHtcbiAgICAgIHN0YXJ0RXYudG91Y2hlcyA9IFtdO1xuICAgICAgVXRpbHMuZWFjaChldi50b3VjaGVzLCBmdW5jdGlvbih0b3VjaCkge1xuICAgICAgICBzdGFydEV2LnRvdWNoZXMucHVzaCh7XG4gICAgICAgICAgY2xpZW50WDogdG91Y2guY2xpZW50WCxcbiAgICAgICAgICBjbGllbnRZOiB0b3VjaC5jbGllbnRZXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGRlbHRhVGltZSA9IGV2LnRpbWVTdGFtcCAtIHN0YXJ0RXYudGltZVN0YW1wLFxuICAgICAgICBkZWx0YVggPSBldi5jZW50ZXIuY2xpZW50WCAtIHN0YXJ0RXYuY2VudGVyLmNsaWVudFgsXG4gICAgICAgIGRlbHRhWSA9IGV2LmNlbnRlci5jbGllbnRZIC0gc3RhcnRFdi5jZW50ZXIuY2xpZW50WTtcblxuICAgIHRoaXMuZ2V0Q2FsY3VsYXRlZERhdGEoZXYsIGxhc3RFdi5jZW50ZXIsIGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpO1xuXG4gICAgVXRpbHMuZXh0ZW5kKGV2LCB7XG4gICAgICBzdGFydEV2ZW50OiBzdGFydEV2LFxuXG4gICAgICBkZWx0YVRpbWU6IGRlbHRhVGltZSxcbiAgICAgIGRlbHRhWDogZGVsdGFYLFxuICAgICAgZGVsdGFZOiBkZWx0YVksXG5cbiAgICAgIGRpc3RhbmNlOiBVdGlscy5nZXREaXN0YW5jZShzdGFydEV2LmNlbnRlciwgZXYuY2VudGVyKSxcbiAgICAgIGFuZ2xlOiBVdGlscy5nZXRBbmdsZShzdGFydEV2LmNlbnRlciwgZXYuY2VudGVyKSxcbiAgICAgIGRpcmVjdGlvbjogVXRpbHMuZ2V0RGlyZWN0aW9uKHN0YXJ0RXYuY2VudGVyLCBldi5jZW50ZXIpLFxuICAgICAgc2NhbGU6IFV0aWxzLmdldFNjYWxlKHN0YXJ0RXYudG91Y2hlcywgZXYudG91Y2hlcyksXG4gICAgICByb3RhdGlvbjogVXRpbHMuZ2V0Um90YXRpb24oc3RhcnRFdi50b3VjaGVzLCBldi50b3VjaGVzKVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGV2O1xuICB9LFxuXG4gIC8qKlxuICAgKiByZWdpc3RlciBuZXcgZ2VzdHVyZVxuICAgKiBAcGFyYW0ge09iamVjdH0gZ2VzdHVyZSBvYmplY3QsIHNlZSBgZ2VzdHVyZXMvYCBmb3IgZG9jdW1lbnRhdGlvblxuICAgKiBAcmV0dXJuIHtBcnJheX0gZ2VzdHVyZXNcbiAgICovXG4gIHJlZ2lzdGVyOiBmdW5jdGlvbiByZWdpc3RlcihnZXN0dXJlKSB7XG4gICAgLy8gYWRkIGFuIGVuYWJsZSBnZXN0dXJlIG9wdGlvbnMgaWYgdGhlcmUgaXMgbm8gZ2l2ZW5cbiAgICB2YXIgb3B0aW9ucyA9IGdlc3R1cmUuZGVmYXVsdHMgfHwge307XG4gICAgaWYob3B0aW9uc1tnZXN0dXJlLm5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnNbZ2VzdHVyZS5uYW1lXSA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gZXh0ZW5kIEdlc3R1cmVEZXRlY3RvciBkZWZhdWx0IG9wdGlvbnMgd2l0aCB0aGUgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgb3B0aW9uc1xuICAgIFV0aWxzLmV4dGVuZChHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMsIG9wdGlvbnMsIHRydWUpO1xuXG4gICAgLy8gc2V0IGl0cyBpbmRleFxuICAgIGdlc3R1cmUuaW5kZXggPSBnZXN0dXJlLmluZGV4IHx8IDEwMDA7XG5cbiAgICAvLyBhZGQgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgdG8gdGhlIGxpc3RcbiAgICB0aGlzLmdlc3R1cmVzLnB1c2goZ2VzdHVyZSk7XG5cbiAgICAvLyBzb3J0IHRoZSBsaXN0IGJ5IGluZGV4XG4gICAgdGhpcy5nZXN0dXJlcy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgIGlmKGEuaW5kZXggPCBiLmluZGV4KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGlmKGEuaW5kZXggPiBiLmluZGV4KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIDA7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXN0dXJlcztcbiAgfVxufTtcblxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKi9cblxuLyoqXG4gKiBjcmVhdGUgbmV3IEdlc3R1cmVEZXRlY3RvciBpbnN0YW5jZVxuICogYWxsIG1ldGhvZHMgc2hvdWxkIHJldHVybiB0aGUgaW5zdGFuY2UgaXRzZWxmLCBzbyBpdCBpcyBjaGFpbmFibGUuXG4gKlxuICogQGNsYXNzIEluc3RhbmNlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gb3B0aW9ucyBhcmUgbWVyZ2VkIHdpdGggYEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0c2BcbiAqIEByZXR1cm4ge0dlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZX1cbiAqL1xuR2VzdHVyZURldGVjdG9yLkluc3RhbmNlID0gZnVuY3Rpb24oZWxlbWVudCwgb3B0aW9ucykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgLy8gc2V0dXAgR2VzdHVyZURldGVjdG9ySlMgd2luZG93IGV2ZW50cyBhbmQgcmVnaXN0ZXIgYWxsIGdlc3R1cmVzXG4gIC8vIHRoaXMgYWxzbyBzZXRzIHVwIHRoZSBkZWZhdWx0IG9wdGlvbnNcbiAgc2V0dXAoKTtcblxuICAvKipcbiAgICogQHByb3BlcnR5IGVsZW1lbnRcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcblxuICAvKipcbiAgICogQHByb3BlcnR5IGVuYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIHRoaXMuZW5hYmxlZCA9IHRydWU7XG5cbiAgLyoqXG4gICAqIG9wdGlvbnMsIG1lcmdlZCB3aXRoIHRoZSBkZWZhdWx0c1xuICAgKiBvcHRpb25zIHdpdGggYW4gXyBhcmUgY29udmVydGVkIHRvIGNhbWVsQ2FzZVxuICAgKiBAcHJvcGVydHkgb3B0aW9uc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgVXRpbHMuZWFjaChvcHRpb25zLCBmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgIGRlbGV0ZSBvcHRpb25zW25hbWVdO1xuICAgIG9wdGlvbnNbVXRpbHMudG9DYW1lbENhc2UobmFtZSldID0gdmFsdWU7XG4gIH0pO1xuXG4gIHRoaXMub3B0aW9ucyA9IFV0aWxzLmV4dGVuZChVdGlscy5leHRlbmQoe30sIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cyksIG9wdGlvbnMgfHwge30pO1xuXG4gIC8vIGFkZCBzb21lIGNzcyB0byB0aGUgZWxlbWVudCB0byBwcmV2ZW50IHRoZSBicm93c2VyIGZyb20gZG9pbmcgaXRzIG5hdGl2ZSBiZWhhdmlvclxuICBpZih0aGlzLm9wdGlvbnMuYmVoYXZpb3IpIHtcbiAgICBVdGlscy50b2dnbGVCZWhhdmlvcih0aGlzLmVsZW1lbnQsIHRoaXMub3B0aW9ucy5iZWhhdmlvciwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogZXZlbnQgc3RhcnQgaGFuZGxlciBvbiB0aGUgZWxlbWVudCB0byBzdGFydCB0aGUgZGV0ZWN0aW9uXG4gICAqIEBwcm9wZXJ0eSBldmVudFN0YXJ0SGFuZGxlclxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgdGhpcy5ldmVudFN0YXJ0SGFuZGxlciA9IEV2ZW50Lm9uVG91Y2goZWxlbWVudCwgRVZFTlRfU1RBUlQsIGZ1bmN0aW9uKGV2KSB7XG4gICAgaWYoc2VsZi5lbmFibGVkICYmIGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgRGV0ZWN0aW9uLnN0YXJ0RGV0ZWN0KHNlbGYsIGV2KTtcbiAgICB9IGVsc2UgaWYoZXYuZXZlbnRUeXBlID09IEVWRU5UX1RPVUNIKSB7XG4gICAgICBEZXRlY3Rpb24uZGV0ZWN0KGV2KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBrZWVwIGEgbGlzdCBvZiB1c2VyIGV2ZW50IGhhbmRsZXJzIHdoaWNoIG5lZWRzIHRvIGJlIHJlbW92ZWQgd2hlbiBjYWxsaW5nICdkaXNwb3NlJ1xuICAgKiBAcHJvcGVydHkgZXZlbnRIYW5kbGVyc1xuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqL1xuICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcbn07XG5cbkdlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZS5wcm90b3R5cGUgPSB7XG4gIC8qKlxuICAgKiBAbWV0aG9kIG9uXG4gICAqIEBzaWduYXR1cmUgb24oZ2VzdHVyZXMsIGhhbmRsZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUFkZHMgYW4gZXZlbnQgaGFuZGxlciBmb3IgYSBnZXN0dXJlLiBBdmFpbGFibGUgZ2VzdHVyZXMgYXJlOiBkcmFnLCBkcmFnbGVmdCwgZHJhZ3JpZ2h0LCBkcmFndXAsIGRyYWdkb3duLCBob2xkLCByZWxlYXNlLCBzd2lwZSwgc3dpcGVsZWZ0LCBzd2lwZXJpZ2h0LCBzd2lwZXVwLCBzd2lwZWRvd24sIHRhcCwgZG91YmxldGFwLCB0b3VjaCwgdHJhbnNmb3JtLCBwaW5jaCwgcGluY2hpbiwgcGluY2hvdXQgYW5kIHJvdGF0ZS4gWy9lbl1cbiAgICogIFtqYV3jgrjjgqfjgrnjg4Hjg6Pjgavlr77jgZnjgovjgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgpLov73liqDjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjgrjjgqfjgrnjg4Hjg6PlkI3jga/jgIFkcmFnIGRyYWdsZWZ0IGRyYWdyaWdodCBkcmFndXAgZHJhZ2Rvd24gaG9sZCByZWxlYXNlIHN3aXBlIHN3aXBlbGVmdCBzd2lwZXJpZ2h0IHN3aXBldXAgc3dpcGVkb3duIHRhcCBkb3VibGV0YXAgdG91Y2ggdHJhbnNmb3JtIHBpbmNoIHBpbmNoaW4gcGluY2hvdXQgcm90YXRlIOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBnZXN0dXJlc1xuICAgKiAgIFtlbl1BIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGdlc3R1cmVzLlsvZW5dXG4gICAqICAgW2phXeaknOefpeOBmeOCi+OCuOOCp+OCueODgeODo+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAguOCueODmuODvOOCueOBp+ikh+aVsOaMh+WumuOBmeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogICBbZW5dQW4gZXZlbnQgaGFuZGxpbmcgZnVuY3Rpb24uWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44OP44Oz44OJ44Op44Go44Gq44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIG9uOiBmdW5jdGlvbiBvbkV2ZW50KGdlc3R1cmVzLCBoYW5kbGVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIEV2ZW50Lm9uKHNlbGYuZWxlbWVudCwgZ2VzdHVyZXMsIGhhbmRsZXIsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIHNlbGYuZXZlbnRIYW5kbGVycy5wdXNoKHsgZ2VzdHVyZTogdHlwZSwgaGFuZGxlcjogaGFuZGxlciB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSxcblxuICAvKipcbiAgICogQG1ldGhvZCBvZmZcbiAgICogQHNpZ25hdHVyZSBvZmYoZ2VzdHVyZXMsIGhhbmRsZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVJlbW92ZSBhbiBldmVudCBsaXN0ZW5lci5bL2VuXVxuICAgKiAgW2phXeOCpOODmeODs+ODiOODquOCueODiuODvOOCkuWJiumZpOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBnZXN0dXJlc1xuICAgKiAgIFtlbl1BIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGdlc3R1cmVzLlsvZW5dXG4gICAqICAgW2phXeOCuOOCp+OCueODgeODo+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAguOCueODmuODvOOCueOBp+ikh+aVsOaMh+WumuOBmeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogICBbZW5dQW4gZXZlbnQgaGFuZGxpbmcgZnVuY3Rpb24uWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44OP44Oz44OJ44Op44Go44Gq44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIG9mZjogZnVuY3Rpb24gb2ZmRXZlbnQoZ2VzdHVyZXMsIGhhbmRsZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBFdmVudC5vZmYoc2VsZi5lbGVtZW50LCBnZXN0dXJlcywgaGFuZGxlciwgZnVuY3Rpb24odHlwZSkge1xuICAgICAgdmFyIGluZGV4ID0gVXRpbHMuaW5BcnJheSh7IGdlc3R1cmU6IHR5cGUsIGhhbmRsZXI6IGhhbmRsZXIgfSk7XG4gICAgICBpZihpbmRleCAhPT0gZmFsc2UpIHtcbiAgICAgICAgc2VsZi5ldmVudEhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHRyaWdnZXIgZ2VzdHVyZSBldmVudFxuICAgKiBAbWV0aG9kIHRyaWdnZXJcbiAgICogQHNpZ25hdHVyZSB0cmlnZ2VyKGdlc3R1cmUsIGV2ZW50RGF0YSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IFtldmVudERhdGFdXG4gICAqL1xuICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQoZ2VzdHVyZSwgZXZlbnREYXRhKSB7XG4gICAgLy8gb3B0aW9uYWxcbiAgICBpZighZXZlbnREYXRhKSB7XG4gICAgICBldmVudERhdGEgPSB7fTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgRE9NIGV2ZW50XG4gICAgdmFyIGV2ZW50ID0gR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5ULmNyZWF0ZUV2ZW50KCdFdmVudCcpO1xuICAgIGV2ZW50LmluaXRFdmVudChnZXN0dXJlLCB0cnVlLCB0cnVlKTtcbiAgICBldmVudC5nZXN0dXJlID0gZXZlbnREYXRhO1xuXG4gICAgLy8gdHJpZ2dlciBvbiB0aGUgdGFyZ2V0IGlmIGl0IGlzIGluIHRoZSBpbnN0YW5jZSBlbGVtZW50LFxuICAgIC8vIHRoaXMgaXMgZm9yIGV2ZW50IGRlbGVnYXRpb24gdHJpY2tzXG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQ7XG4gICAgaWYoVXRpbHMuaGFzUGFyZW50KGV2ZW50RGF0YS50YXJnZXQsIGVsZW1lbnQpKSB7XG4gICAgICBlbGVtZW50ID0gZXZlbnREYXRhLnRhcmdldDtcbiAgICB9XG5cbiAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGVuYWJsZVxuICAgKiBAc2lnbmF0dXJlIGVuYWJsZShzdGF0ZSlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dRW5hYmxlIG9yIGRpc2FibGUgZ2VzdHVyZSBkZXRlY3Rpb24uWy9lbl1cbiAgICogIFtqYV3jgrjjgqfjgrnjg4Hjg6PmpJznn6XjgpLmnInlirnljJYv54Sh5Yq55YyW44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtCb29sZWFufSBzdGF0ZVxuICAgKiAgIFtlbl1TcGVjaWZ5IGlmIGl0IHNob3VsZCBiZSBlbmFibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3mnInlirnjgavjgZnjgovjgYvjganjgYbjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZW5hYmxlOiBmdW5jdGlvbiBlbmFibGUoc3RhdGUpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSBzdGF0ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICAvKipcbiAgICogQG1ldGhvZCBkaXNwb3NlXG4gICAqIEBzaWduYXR1cmUgZGlzcG9zZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVJlbW92ZSBhbmQgZGVzdHJveSBhbGwgZXZlbnQgaGFuZGxlcnMgZm9yIHRoaXMgaW5zdGFuY2UuWy9lbl1cbiAgICogIFtqYV3jgZPjga7jgqTjg7Pjgrnjgr/jg7Pjgrnjgafjga7jgrjjgqfjgrnjg4Hjg6Pjga7mpJznn6XjgoTjgIHjgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgpLlhajjgabop6PpmaTjgZfjgablu4Pmo4TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZGlzcG9zZTogZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICB2YXIgaSwgZWg7XG5cbiAgICAvLyB1bmRvIGFsbCBjaGFuZ2VzIG1hZGUgYnkgc3RvcF9icm93c2VyX2JlaGF2aW9yXG4gICAgVXRpbHMudG9nZ2xlQmVoYXZpb3IodGhpcy5lbGVtZW50LCB0aGlzLm9wdGlvbnMuYmVoYXZpb3IsIGZhbHNlKTtcblxuICAgIC8vIHVuYmluZCBhbGwgY3VzdG9tIGV2ZW50IGhhbmRsZXJzXG4gICAgZm9yKGkgPSAtMTsgKGVoID0gdGhpcy5ldmVudEhhbmRsZXJzWysraV0pOykgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgICBVdGlscy5vZmYodGhpcy5lbGVtZW50LCBlaC5nZXN0dXJlLCBlaC5oYW5kbGVyKTtcbiAgICB9XG5cbiAgICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcblxuICAgIC8vIHVuYmluZCB0aGUgc3RhcnQgZXZlbnQgbGlzdGVuZXJcbiAgICBFdmVudC5vZmYodGhpcy5lbGVtZW50LCBFVkVOVF9UWVBFU1tFVkVOVF9TVEFSVF0sIHRoaXMuZXZlbnRTdGFydEhhbmRsZXIpO1xuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIGdlc3R1cmVzXG4gKi9cbi8qKlxuICogTW92ZSB3aXRoIHggZmluZ2VycyAoZGVmYXVsdCAxKSBhcm91bmQgb24gdGhlIHBhZ2UuXG4gKiBQcmV2ZW50aW5nIHRoZSBkZWZhdWx0IGJyb3dzZXIgYmVoYXZpb3IgaXMgYSBnb29kIHdheSB0byBpbXByb3ZlIGZlZWwgYW5kIHdvcmtpbmcuXG4gKiBgYGBgXG4gKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdcIiwgZnVuY3Rpb24oZXYpIHtcbiAqICAgIGNvbnNvbGUubG9nKGV2KTtcbiAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAqICB9KTtcbiAqIGBgYGBcbiAqXG4gKiBAY2xhc3MgRHJhZ1xuICogQHN0YXRpY1xuICovXG4vKipcbiAqIEBldmVudCBkcmFnXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3N0YXJ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2VuZFxuICogQHBhcmFtIHtPYmplY3R9IGV2XG4gKi9cbi8qKlxuICogQGV2ZW50IGRyYXBsZWZ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3JpZ2h0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3VwXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2Rvd25cbiAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICovXG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqL1xuKGZ1bmN0aW9uKG5hbWUpIHtcbiAgdmFyIHRyaWdnZXJlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIGRyYWdHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgdmFyIGN1ciA9IERldGVjdGlvbi5jdXJyZW50O1xuXG4gICAgLy8gbWF4IHRvdWNoZXNcbiAgICBpZihpbnN0Lm9wdGlvbnMuZHJhZ01heFRvdWNoZXMgPiAwICYmXG4gICAgICBldi50b3VjaGVzLmxlbmd0aCA+IGluc3Qub3B0aW9ucy5kcmFnTWF4VG91Y2hlcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN3aXRjaChldi5ldmVudFR5cGUpIHtcbiAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgRVZFTlRfTU9WRTpcbiAgICAgIC8vIHdoZW4gdGhlIGRpc3RhbmNlIHdlIG1vdmVkIGlzIHRvbyBzbWFsbCB3ZSBza2lwIHRoaXMgZ2VzdHVyZVxuICAgICAgLy8gb3Igd2UgY2FuIGJlIGFscmVhZHkgaW4gZHJhZ2dpbmdcbiAgICAgIGlmKGV2LmRpc3RhbmNlIDwgaW5zdC5vcHRpb25zLmRyYWdNaW5EaXN0YW5jZSAmJlxuICAgICAgICBjdXIubmFtZSAhPSBuYW1lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHN0YXJ0Q2VudGVyID0gY3VyLnN0YXJ0RXZlbnQuY2VudGVyO1xuXG4gICAgICAvLyB3ZSBhcmUgZHJhZ2dpbmchXG4gICAgICBpZihjdXIubmFtZSAhPSBuYW1lKSB7XG4gICAgICAgIGN1ci5uYW1lID0gbmFtZTtcbiAgICAgICAgaWYoaW5zdC5vcHRpb25zLmRyYWdEaXN0YW5jZUNvcnJlY3Rpb24gJiYgZXYuZGlzdGFuY2UgPiAwKSB7XG4gICAgICAgICAgLy8gV2hlbiBhIGRyYWcgaXMgdHJpZ2dlcmVkLCBzZXQgdGhlIGV2ZW50IGNlbnRlciB0byBkcmFnTWluRGlzdGFuY2UgcGl4ZWxzIGZyb20gdGhlIG9yaWdpbmFsIGV2ZW50IGNlbnRlci5cbiAgICAgICAgICAvLyBXaXRob3V0IHRoaXMgY29ycmVjdGlvbiwgdGhlIGRyYWdnZWQgZGlzdGFuY2Ugd291bGQganVtcHN0YXJ0IGF0IGRyYWdNaW5EaXN0YW5jZSBwaXhlbHMgaW5zdGVhZCBvZiBhdCAwLlxuICAgICAgICAgIC8vIEl0IG1pZ2h0IGJlIHVzZWZ1bCB0byBzYXZlIHRoZSBvcmlnaW5hbCBzdGFydCBwb2ludCBzb21ld2hlcmVcbiAgICAgICAgICB2YXIgZmFjdG9yID0gTWF0aC5hYnMoaW5zdC5vcHRpb25zLmRyYWdNaW5EaXN0YW5jZSAvIGV2LmRpc3RhbmNlKTtcbiAgICAgICAgICBzdGFydENlbnRlci5wYWdlWCArPSBldi5kZWx0YVggKiBmYWN0b3I7XG4gICAgICAgICAgc3RhcnRDZW50ZXIucGFnZVkgKz0gZXYuZGVsdGFZICogZmFjdG9yO1xuICAgICAgICAgIHN0YXJ0Q2VudGVyLmNsaWVudFggKz0gZXYuZGVsdGFYICogZmFjdG9yO1xuICAgICAgICAgIHN0YXJ0Q2VudGVyLmNsaWVudFkgKz0gZXYuZGVsdGFZICogZmFjdG9yO1xuXG4gICAgICAgICAgLy8gcmVjYWxjdWxhdGUgZXZlbnQgZGF0YSB1c2luZyBuZXcgc3RhcnQgcG9pbnRcbiAgICAgICAgICBldiA9IERldGVjdGlvbi5leHRlbmRFdmVudERhdGEoZXYpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGxvY2sgZHJhZyB0byBheGlzP1xuICAgICAgaWYoY3VyLmxhc3RFdmVudC5kcmFnTG9ja1RvQXhpcyB8fFxuICAgICAgICAoIGluc3Qub3B0aW9ucy5kcmFnTG9ja1RvQXhpcyAmJlxuICAgICAgICAgIGluc3Qub3B0aW9ucy5kcmFnTG9ja01pbkRpc3RhbmNlIDw9IGV2LmRpc3RhbmNlXG4gICAgICAgICkpIHtcbiAgICAgICAgICBldi5kcmFnTG9ja1RvQXhpcyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBrZWVwIGRpcmVjdGlvbiBvbiB0aGUgYXhpcyB0aGF0IHRoZSBkcmFnIGdlc3R1cmUgc3RhcnRlZCBvblxuICAgICAgICB2YXIgbGFzdERpcmVjdGlvbiA9IGN1ci5sYXN0RXZlbnQuZGlyZWN0aW9uO1xuICAgICAgICBpZihldi5kcmFnTG9ja1RvQXhpcyAmJiBsYXN0RGlyZWN0aW9uICE9PSBldi5kaXJlY3Rpb24pIHtcbiAgICAgICAgICBpZihVdGlscy5pc1ZlcnRpY2FsKGxhc3REaXJlY3Rpb24pKSB7XG4gICAgICAgICAgICBldi5kaXJlY3Rpb24gPSAoZXYuZGVsdGFZIDwgMCkgPyBESVJFQ1RJT05fVVAgOiBESVJFQ1RJT05fRE9XTjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXYuZGlyZWN0aW9uID0gKGV2LmRlbHRhWCA8IDApID8gRElSRUNUSU9OX0xFRlQgOiBESVJFQ1RJT05fUklHSFQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmlyc3QgdGltZSwgdHJpZ2dlciBkcmFnc3RhcnQgZXZlbnRcbiAgICAgICAgaWYoIXRyaWdnZXJlZCkge1xuICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lICsgJ3N0YXJ0JywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmlnZ2VyIGV2ZW50c1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpO1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSArIGV2LmRpcmVjdGlvbiwgZXYpO1xuXG4gICAgICAgIHZhciBpc1ZlcnRpY2FsID0gVXRpbHMuaXNWZXJ0aWNhbChldi5kaXJlY3Rpb24pO1xuXG4gICAgICAgIC8vIGJsb2NrIHRoZSBicm93c2VyIGV2ZW50c1xuICAgICAgICBpZigoaW5zdC5vcHRpb25zLmRyYWdCbG9ja1ZlcnRpY2FsICYmIGlzVmVydGljYWwpIHx8XG4gICAgICAgICAgKGluc3Qub3B0aW9ucy5kcmFnQmxvY2tIb3Jpem9udGFsICYmICFpc1ZlcnRpY2FsKSkge1xuICAgICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfUkVMRUFTRTpcbiAgICAgICAgaWYodHJpZ2dlcmVkICYmIGV2LmNoYW5nZWRMZW5ndGggPD0gaW5zdC5vcHRpb25zLmRyYWdNYXhUb3VjaGVzKSB7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKG5hbWUgKyAnZW5kJywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX0VORDpcbiAgICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5EcmFnID0ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIGluZGV4OiA1MCxcbiAgICAgIGhhbmRsZXI6IGRyYWdHZXN0dXJlLFxuICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1pbmltYWwgbW92ZW1lbnQgdGhhdCBoYXZlIHRvIGJlIG1hZGUgYmVmb3JlIHRoZSBkcmFnIGV2ZW50IGdldHMgdHJpZ2dlcmVkXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTWluRGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMTBcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdNaW5EaXN0YW5jZTogMTAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldCBkcmFnRGlzdGFuY2VDb3JyZWN0aW9uIHRvIHRydWUgdG8gbWFrZSB0aGUgc3RhcnRpbmcgcG9pbnQgb2YgdGhlIGRyYWdcbiAgICAgICAgICogYmUgY2FsY3VsYXRlZCBmcm9tIHdoZXJlIHRoZSBkcmFnIHdhcyB0cmlnZ2VyZWQsIG5vdCBmcm9tIHdoZXJlIHRoZSB0b3VjaCBzdGFydGVkLlxuICAgICAgICAgKiBVc2VmdWwgdG8gYXZvaWQgYSBqZXJrLXN0YXJ0aW5nIGRyYWcsIHdoaWNoIGNhbiBtYWtlIGZpbmUtYWRqdXN0bWVudHNcbiAgICAgICAgICogdGhyb3VnaCBkcmFnZ2luZyBkaWZmaWN1bHQsIGFuZCBiZSB2aXN1YWxseSB1bmFwcGVhbGluZy5cbiAgICAgICAgICogQHByb3BlcnR5IGRyYWdEaXN0YW5jZUNvcnJlY3Rpb25cbiAgICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdEaXN0YW5jZUNvcnJlY3Rpb246IHRydWUsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHNldCAwIGZvciB1bmxpbWl0ZWQsIGJ1dCB0aGlzIGNhbiBjb25mbGljdCB3aXRoIHRyYW5zZm9ybVxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ01heFRvdWNoZXNcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ01heFRvdWNoZXM6IDEsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHByZXZlbnQgZGVmYXVsdCBicm93c2VyIGJlaGF2aW9yIHdoZW4gZHJhZ2dpbmcgb2NjdXJzXG4gICAgICAgICAqIGJlIGNhcmVmdWwgd2l0aCBpdCwgaXQgbWFrZXMgdGhlIGVsZW1lbnQgYSBibG9ja2luZyBlbGVtZW50XG4gICAgICAgICAqIHdoZW4geW91IGFyZSB1c2luZyB0aGUgZHJhZyBnZXN0dXJlLCBpdCBpcyBhIGdvb2QgcHJhY3RpY2UgdG8gc2V0IHRoaXMgdHJ1ZVxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ0Jsb2NrSG9yaXpvbnRhbFxuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdCbG9ja0hvcml6b250YWw6IGZhbHNlLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBzYW1lIGFzIGBkcmFnQmxvY2tIb3Jpem9udGFsYCwgYnV0IGZvciB2ZXJ0aWNhbCBtb3ZlbWVudFxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ0Jsb2NrVmVydGljYWxcbiAgICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgICAqIEBkZWZhdWx0IGZhbHNlXG4gICAgICAgICAqL1xuICAgICAgICBkcmFnQmxvY2tWZXJ0aWNhbDogZmFsc2UsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGRyYWdMb2NrVG9BeGlzIGtlZXBzIHRoZSBkcmFnIGdlc3R1cmUgb24gdGhlIGF4aXMgdGhhdCBpdCBzdGFydGVkIG9uLFxuICAgICAgICAgKiBJdCBkaXNhbGxvd3MgdmVydGljYWwgZGlyZWN0aW9ucyBpZiB0aGUgaW5pdGlhbCBkaXJlY3Rpb24gd2FzIGhvcml6b250YWwsIGFuZCB2aWNlIHZlcnNhLlxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ0xvY2tUb0F4aXNcbiAgICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgICAqIEBkZWZhdWx0IGZhbHNlXG4gICAgICAgICAqL1xuICAgICAgICBkcmFnTG9ja1RvQXhpczogZmFsc2UsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGRyYWcgbG9jayBvbmx5IGtpY2tzIGluIHdoZW4gZGlzdGFuY2UgPiBkcmFnTG9ja01pbkRpc3RhbmNlXG4gICAgICAgICAqIFRoaXMgd2F5LCBsb2NraW5nIG9jY3VycyBvbmx5IHdoZW4gdGhlIGRpc3RhbmNlIGhhcyBiZWNvbWUgbGFyZ2UgZW5vdWdoIHRvIHJlbGlhYmx5IGRldGVybWluZSB0aGUgZGlyZWN0aW9uXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTG9ja01pbkRpc3RhbmNlXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDI1XG4gICAgICAgICAqL1xuICAgICAgICBkcmFnTG9ja01pbkRpc3RhbmNlOiAyNVxuICAgICAgfVxuICAgIH07XG4gIH0pKCdkcmFnJyk7XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiB0cmlnZ2VyIGEgc2ltcGxlIGdlc3R1cmUgZXZlbnQsIHNvIHlvdSBjYW4gZG8gYW55dGhpbmcgaW4geW91ciBoYW5kbGVyLlxuICAgKiBvbmx5IHVzYWJsZSBpZiB5b3Uga25vdyB3aGF0IHlvdXIgZG9pbmcuLi5cbiAgICpcbiAgICogQGNsYXNzIEdlc3R1cmVcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBnZXN0dXJlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLkdlc3R1cmUgPSB7XG4gICAgbmFtZTogJ2dlc3R1cmUnLFxuICAgIGluZGV4OiAxMzM3LFxuICAgIGhhbmRsZXI6IGZ1bmN0aW9uIHJlbGVhc2VHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgICBpbnN0LnRyaWdnZXIodGhpcy5uYW1lLCBldik7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAbW9kdWxlIGdlc3R1cmVzXG4gICAqL1xuICAvKipcbiAgICogVG91Y2ggc3RheXMgYXQgdGhlIHNhbWUgcGxhY2UgZm9yIHggdGltZVxuICAgKlxuICAgKiBAY2xhc3MgSG9sZFxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGhvbGRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKi9cbiAgKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgdGltZXI7XG5cbiAgICBmdW5jdGlvbiBob2xkR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSBpbnN0Lm9wdGlvbnMsXG4gICAgICAgICAgY3VycmVudCA9IERldGVjdGlvbi5jdXJyZW50O1xuXG4gICAgICBzd2l0Y2goZXYuZXZlbnRUeXBlKSB7XG4gICAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuXG4gICAgICAgIC8vIHNldCB0aGUgZ2VzdHVyZSBzbyB3ZSBjYW4gY2hlY2sgaW4gdGhlIHRpbWVvdXQgaWYgaXQgc3RpbGwgaXNcbiAgICAgICAgY3VycmVudC5uYW1lID0gbmFtZTtcblxuICAgICAgICAvLyBzZXQgdGltZXIgYW5kIGlmIGFmdGVyIHRoZSB0aW1lb3V0IGl0IHN0aWxsIGlzIGhvbGQsXG4gICAgICAgIC8vIHdlIHRyaWdnZXIgdGhlIGhvbGQgZXZlbnRcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmKGN1cnJlbnQgJiYgY3VycmVudC5uYW1lID09IG5hbWUpIHtcbiAgICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lLCBldik7XG4gICAgICAgICAgfVxuICAgICAgICB9LCBvcHRpb25zLmhvbGRUaW1lb3V0KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfTU9WRTpcbiAgICAgICAgaWYoZXYuZGlzdGFuY2UgPiBvcHRpb25zLmhvbGRUaHJlc2hvbGQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX1JFTEVBU0U6XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5Ib2xkID0ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIGluZGV4OiAxMCxcbiAgICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcHJvcGVydHkgaG9sZFRpbWVvdXRcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgNTAwXG4gICAgICAgICAqL1xuICAgICAgICBob2xkVGltZW91dDogNTAwLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBtb3ZlbWVudCBhbGxvd2VkIHdoaWxlIGhvbGRpbmdcbiAgICAgICAgICogQHByb3BlcnR5IGhvbGRUaHJlc2hvbGRcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMlxuICAgICAgICAgKi9cbiAgICAgICAgaG9sZFRocmVzaG9sZDogMlxuICAgICAgfSxcbiAgICAgIGhhbmRsZXI6IGhvbGRHZXN0dXJlXG4gICAgfTtcbiAgfSkoJ2hvbGQnKTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIHdoZW4gYSB0b3VjaCBpcyBiZWluZyByZWxlYXNlZCBmcm9tIHRoZSBwYWdlXG4gICAqXG4gICAqIEBjbGFzcyBSZWxlYXNlXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcmVsZWFzZVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5SZWxlYXNlID0ge1xuICAgIG5hbWU6ICdyZWxlYXNlJyxcbiAgICBpbmRleDogSW5maW5pdHksXG4gICAgaGFuZGxlcjogZnVuY3Rpb24gcmVsZWFzZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGlmKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUsIGV2KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiB0cmlnZ2VycyBzd2lwZSBldmVudHMgd2hlbiB0aGUgZW5kIHZlbG9jaXR5IGlzIGFib3ZlIHRoZSB0aHJlc2hvbGRcbiAgICogZm9yIGJlc3QgdXNhZ2UsIHNldCBgcHJldmVudERlZmF1bHRgIChvbiB0aGUgZHJhZyBnZXN0dXJlKSB0byBgdHJ1ZWBcbiAgICogYGBgYFxuICAgKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdsZWZ0IHN3aXBlbGVmdFwiLCBmdW5jdGlvbihldikge1xuICAgKiAgICBjb25zb2xlLmxvZyhldik7XG4gICAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgICogIH0pO1xuICAgKiBgYGBgXG4gICAqXG4gICAqIEBjbGFzcyBTd2lwZVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBzd2lwZWxlZnRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlcmlnaHRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBldXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlZG93blxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5Td2lwZSA9IHtcbiAgICBuYW1lOiAnc3dpcGUnLFxuICAgIGluZGV4OiA0MCxcbiAgICBkZWZhdWx0czoge1xuICAgICAgLyoqXG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVNaW5Ub3VjaGVzXG4gICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICovXG4gICAgICBzd2lwZU1pblRvdWNoZXM6IDEsXG5cbiAgICAgIC8qKlxuICAgICAgICogQHByb3BlcnR5IHN3aXBlTWF4VG91Y2hlc1xuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAqL1xuICAgICAgc3dpcGVNYXhUb3VjaGVzOiAxLFxuXG4gICAgICAvKipcbiAgICAgICAqIGhvcml6b250YWwgc3dpcGUgdmVsb2NpdHlcbiAgICAgICAqIEBwcm9wZXJ0eSBzd2lwZVZlbG9jaXR5WFxuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDAuNlxuICAgICAgICovXG4gICAgICBzd2lwZVZlbG9jaXR5WDogMC42LFxuXG4gICAgICAvKipcbiAgICAgICAqIHZlcnRpY2FsIHN3aXBlIHZlbG9jaXR5XG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVWZWxvY2l0eVlcbiAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgKiBAZGVmYXVsdCAwLjZcbiAgICAgICAqL1xuICAgICAgc3dpcGVWZWxvY2l0eVk6IDAuNlxuICAgIH0sXG5cbiAgICBoYW5kbGVyOiBmdW5jdGlvbiBzd2lwZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGlmKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICAgIHZhciB0b3VjaGVzID0gZXYudG91Y2hlcy5sZW5ndGgsXG4gICAgICAgICAgICBvcHRpb25zID0gaW5zdC5vcHRpb25zO1xuXG4gICAgICAgIC8vIG1heCB0b3VjaGVzXG4gICAgICAgIGlmKHRvdWNoZXMgPCBvcHRpb25zLnN3aXBlTWluVG91Y2hlcyB8fFxuICAgICAgICAgIHRvdWNoZXMgPiBvcHRpb25zLnN3aXBlTWF4VG91Y2hlcykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdoZW4gdGhlIGRpc3RhbmNlIHdlIG1vdmVkIGlzIHRvbyBzbWFsbCB3ZSBza2lwIHRoaXMgZ2VzdHVyZVxuICAgICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgICBpZihldi52ZWxvY2l0eVggPiBvcHRpb25zLnN3aXBlVmVsb2NpdHlYIHx8XG4gICAgICAgICAgZXYudmVsb2NpdHlZID4gb3B0aW9ucy5zd2lwZVZlbG9jaXR5WSkge1xuICAgICAgICAgIC8vIHRyaWdnZXIgc3dpcGUgZXZlbnRzXG4gICAgICAgICAgaW5zdC50cmlnZ2VyKHRoaXMubmFtZSwgZXYpO1xuICAgICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUgKyBldi5kaXJlY3Rpb24sIGV2KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIFNpbmdsZSB0YXAgYW5kIGEgZG91YmxlIHRhcCBvbiBhIHBsYWNlXG4gICAqXG4gICAqIEBjbGFzcyBUYXBcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCB0YXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGRvdWJsZXRhcFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBoYXNNb3ZlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdGFwR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSBpbnN0Lm9wdGlvbnMsXG4gICAgICAgICAgY3VycmVudCA9IERldGVjdGlvbi5jdXJyZW50LFxuICAgICAgICAgIHByZXYgPSBEZXRlY3Rpb24ucHJldmlvdXMsXG4gICAgICAgICAgc2luY2VQcmV2LFxuICAgICAgICAgIGRpZERvdWJsZVRhcDtcblxuICAgICAgc3dpdGNoKGV2LmV2ZW50VHlwZSkge1xuICAgICAgY2FzZSBFVkVOVF9TVEFSVDpcbiAgICAgICAgaGFzTW92ZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfTU9WRTpcbiAgICAgICAgaGFzTW92ZWQgPSBoYXNNb3ZlZCB8fCAoZXYuZGlzdGFuY2UgPiBvcHRpb25zLnRhcE1heERpc3RhbmNlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfRU5EOlxuICAgICAgICBpZighVXRpbHMuaW5TdHIoZXYuc3JjRXZlbnQudHlwZSwgJ2NhbmNlbCcpICYmIGV2LmRlbHRhVGltZSA8IG9wdGlvbnMudGFwTWF4VGltZSAmJiAhaGFzTW92ZWQpIHtcbiAgICAgICAgICAvLyBwcmV2aW91cyBnZXN0dXJlLCBmb3IgdGhlIGRvdWJsZSB0YXAgc2luY2UgdGhlc2UgYXJlIHR3byBkaWZmZXJlbnQgZ2VzdHVyZSBkZXRlY3Rpb25zXG4gICAgICAgICAgc2luY2VQcmV2ID0gcHJldiAmJiBwcmV2Lmxhc3RFdmVudCAmJiBldi50aW1lU3RhbXAgLSBwcmV2Lmxhc3RFdmVudC50aW1lU3RhbXA7XG4gICAgICAgICAgZGlkRG91YmxlVGFwID0gZmFsc2U7XG5cbiAgICAgICAgICAvLyBjaGVjayBpZiBkb3VibGUgdGFwXG4gICAgICAgICAgaWYocHJldiAmJiBwcmV2Lm5hbWUgPT0gbmFtZSAmJlxuICAgICAgICAgICAgKHNpbmNlUHJldiAmJiBzaW5jZVByZXYgPCBvcHRpb25zLmRvdWJsZVRhcEludGVydmFsKSAmJlxuICAgICAgICAgICAgZXYuZGlzdGFuY2UgPCBvcHRpb25zLmRvdWJsZVRhcERpc3RhbmNlKSB7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIoJ2RvdWJsZXRhcCcsIGV2KTtcbiAgICAgICAgICAgIGRpZERvdWJsZVRhcCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gZG8gYSBzaW5nbGUgdGFwXG4gICAgICAgICAgaWYoIWRpZERvdWJsZVRhcCB8fCBvcHRpb25zLnRhcEFsd2F5cykge1xuICAgICAgICAgICAgY3VycmVudC5uYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGluc3QudHJpZ2dlcihjdXJyZW50Lm5hbWUsIGV2KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLlRhcCA9IHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICBpbmRleDogMTAwLFxuICAgICAgaGFuZGxlcjogdGFwR2VzdHVyZSxcbiAgICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBtYXggdGltZSBvZiBhIHRhcCwgdGhpcyBpcyBmb3IgdGhlIHNsb3cgdGFwcGVyc1xuICAgICAgICAgKiBAcHJvcGVydHkgdGFwTWF4VGltZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAyNTBcbiAgICAgICAgICovXG4gICAgICAgIHRhcE1heFRpbWU6IDI1MCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IGRpc3RhbmNlIG9mIG1vdmVtZW50IG9mIGEgdGFwLCB0aGlzIGlzIGZvciB0aGUgc2xvdyB0YXBwZXJzXG4gICAgICAgICAqIEBwcm9wZXJ0eSB0YXBNYXhEaXN0YW5jZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAxMFxuICAgICAgICAgKi9cbiAgICAgICAgdGFwTWF4RGlzdGFuY2U6IDEwLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBhbHdheXMgdHJpZ2dlciB0aGUgYHRhcGAgZXZlbnQsIGV2ZW4gd2hpbGUgZG91YmxlLXRhcHBpbmdcbiAgICAgICAgICogQHByb3BlcnR5IHRhcEFsd2F5c1xuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICAgKi9cbiAgICAgICAgdGFwQWx3YXlzOiB0cnVlLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBtYXggZGlzdGFuY2UgYmV0d2VlbiB0d28gdGFwc1xuICAgICAgICAgKiBAcHJvcGVydHkgZG91YmxlVGFwRGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMjBcbiAgICAgICAgICovXG4gICAgICAgIGRvdWJsZVRhcERpc3RhbmNlOiAyMCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IHRpbWUgYmV0d2VlbiB0d28gdGFwc1xuICAgICAgICAgKiBAcHJvcGVydHkgZG91YmxlVGFwSW50ZXJ2YWxcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMzAwXG4gICAgICAgICAqL1xuICAgICAgICBkb3VibGVUYXBJbnRlcnZhbDogMzAwXG4gICAgICB9XG4gICAgfTtcbiAgfSkoJ3RhcCcpO1xuXG4gIC8qKlxuICAgKiBAbW9kdWxlIGdlc3R1cmVzXG4gICAqL1xuICAvKipcbiAgICogd2hlbiBhIHRvdWNoIGlzIGJlaW5nIHRvdWNoZWQgYXQgdGhlIHBhZ2VcbiAgICpcbiAgICogQGNsYXNzIFRvdWNoXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgdG91Y2hcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMuVG91Y2ggPSB7XG4gICAgbmFtZTogJ3RvdWNoJyxcbiAgICBpbmRleDogLUluZmluaXR5LFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAvKipcbiAgICAgICAqIGNhbGwgcHJldmVudERlZmF1bHQgYXQgdG91Y2hzdGFydCwgYW5kIG1ha2VzIHRoZSBlbGVtZW50IGJsb2NraW5nIGJ5IGRpc2FibGluZyB0aGUgc2Nyb2xsaW5nIG9mIHRoZSBwYWdlLFxuICAgICAgICogYnV0IGl0IGltcHJvdmVzIGdlc3R1cmVzIGxpa2UgdHJhbnNmb3JtaW5nIGFuZCBkcmFnZ2luZy5cbiAgICAgICAqIGJlIGNhcmVmdWwgd2l0aCB1c2luZyB0aGlzLCBpdCBjYW4gYmUgdmVyeSBhbm5veWluZyBmb3IgdXNlcnMgdG8gYmUgc3R1Y2sgb24gdGhlIHBhZ2VcbiAgICAgICAqIEBwcm9wZXJ0eSBwcmV2ZW50RGVmYXVsdFxuICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAgICovXG4gICAgICBwcmV2ZW50RGVmYXVsdDogZmFsc2UsXG5cbiAgICAgIC8qKlxuICAgICAgICogZGlzYWJsZSBtb3VzZSBldmVudHMsIHNvIG9ubHkgdG91Y2ggKG9yIHBlbiEpIGlucHV0IHRyaWdnZXJzIGV2ZW50c1xuICAgICAgICogQHByb3BlcnR5IHByZXZlbnRNb3VzZVxuICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAgICovXG4gICAgICBwcmV2ZW50TW91c2U6IGZhbHNlXG4gICAgfSxcbiAgICBoYW5kbGVyOiBmdW5jdGlvbiB0b3VjaEdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGlmKGluc3Qub3B0aW9ucy5wcmV2ZW50TW91c2UgJiYgZXYucG9pbnRlclR5cGUgPT0gUE9JTlRFUl9NT1VTRSkge1xuICAgICAgICBldi5zdG9wRGV0ZWN0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYoaW5zdC5vcHRpb25zLnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9UT1VDSCkge1xuICAgICAgICBpbnN0LnRyaWdnZXIoJ3RvdWNoJywgZXYpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIFVzZXIgd2FudCB0byBzY2FsZSBvciByb3RhdGUgd2l0aCAyIGZpbmdlcnNcbiAgICogUHJldmVudGluZyB0aGUgZGVmYXVsdCBicm93c2VyIGJlaGF2aW9yIGlzIGEgZ29vZCB3YXkgdG8gaW1wcm92ZSBmZWVsIGFuZCB3b3JraW5nLiBUaGlzIGNhbiBiZSBkb25lIHdpdGggdGhlXG4gICAqIGBwcmV2ZW50RGVmYXVsdGAgb3B0aW9uLlxuICAgKlxuICAgKiBAY2xhc3MgVHJhbnNmb3JtXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgdHJhbnNmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCB0cmFuc2Zvcm1zdGFydFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgdHJhbnNmb3JtZW5kXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBwaW5jaGluXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBwaW5jaG91dFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcm90YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICovXG4gIChmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIHRyaWdnZXJlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgc3dpdGNoKGV2LmV2ZW50VHlwZSkge1xuICAgICAgY2FzZSBFVkVOVF9TVEFSVDpcbiAgICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX01PVkU6XG4gICAgICAgIC8vIGF0IGxlYXN0IG11bHRpdG91Y2hcbiAgICAgICAgaWYoZXYudG91Y2hlcy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNjYWxlVGhyZXNob2xkID0gTWF0aC5hYnMoMSAtIGV2LnNjYWxlKTtcbiAgICAgICAgdmFyIHJvdGF0aW9uVGhyZXNob2xkID0gTWF0aC5hYnMoZXYucm90YXRpb24pO1xuXG4gICAgICAgIC8vIHdoZW4gdGhlIGRpc3RhbmNlIHdlIG1vdmVkIGlzIHRvbyBzbWFsbCB3ZSBza2lwIHRoaXMgZ2VzdHVyZVxuICAgICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgICBpZihzY2FsZVRocmVzaG9sZCA8IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5TY2FsZSAmJlxuICAgICAgICAgIHJvdGF0aW9uVGhyZXNob2xkIDwgaW5zdC5vcHRpb25zLnRyYW5zZm9ybU1pblJvdGF0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2UgYXJlIHRyYW5zZm9ybWluZyFcbiAgICAgICAgRGV0ZWN0aW9uLmN1cnJlbnQubmFtZSA9IG5hbWU7XG5cbiAgICAgICAgLy8gZmlyc3QgdGltZSwgdHJpZ2dlciBkcmFnc3RhcnQgZXZlbnRcbiAgICAgICAgaWYoIXRyaWdnZXJlZCkge1xuICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lICsgJ3N0YXJ0JywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpOyAvLyBiYXNpYyB0cmFuc2Zvcm0gZXZlbnRcblxuICAgICAgICAvLyB0cmlnZ2VyIHJvdGF0ZSBldmVudFxuICAgICAgICBpZihyb3RhdGlvblRocmVzaG9sZCA+IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5Sb3RhdGlvbikge1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncm90YXRlJywgZXYpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJpZ2dlciBwaW5jaCBldmVudFxuICAgICAgICBpZihzY2FsZVRocmVzaG9sZCA+IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5TY2FsZSkge1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncGluY2gnLCBldik7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKCdwaW5jaCcgKyAoZXYuc2NhbGUgPCAxID8gJ2luJyA6ICdvdXQnKSwgZXYpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX1JFTEVBU0U6XG4gICAgICAgIGlmKHRyaWdnZXJlZCAmJiBldi5jaGFuZ2VkTGVuZ3RoIDwgMikge1xuICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lICsgJ2VuZCcsIGV2KTtcbiAgICAgICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMuVHJhbnNmb3JtID0ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIGluZGV4OiA0NSxcbiAgICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBtaW5pbWFsIHNjYWxlIGZhY3Rvciwgbm8gc2NhbGUgaXMgMSwgem9vbWluIGlzIHRvIDAgYW5kIHpvb21vdXQgdW50aWwgaGlnaGVyIHRoZW4gMVxuICAgICAgICAgKiBAcHJvcGVydHkgdHJhbnNmb3JtTWluU2NhbGVcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMC4wMVxuICAgICAgICAgKi9cbiAgICAgICAgdHJhbnNmb3JtTWluU2NhbGU6IDAuMDEsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHJvdGF0aW9uIGluIGRlZ3JlZXNcbiAgICAgICAgICogQHByb3BlcnR5IHRyYW5zZm9ybU1pblJvdGF0aW9uXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAgICovXG4gICAgICAgIHRyYW5zZm9ybU1pblJvdGF0aW9uOiAxXG4gICAgICB9LFxuXG4gICAgICBoYW5kbGVyOiB0cmFuc2Zvcm1HZXN0dXJlXG4gICAgfTtcbiAgfSkoJ3RyYW5zZm9ybScpO1xuXG5leHBvcnQgZGVmYXVsdCBHZXN0dXJlRGV0ZWN0b3I7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG4vKipcbiAqIEBvYmplY3Qgb25zLnBsYXRmb3JtXG4gKiBAY2F0ZWdvcnkgdXRpbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1VdGlsaXR5IG1ldGhvZHMgdG8gZGV0ZWN0IGN1cnJlbnQgcGxhdGZvcm0uWy9lbl1cbiAqICAgW2phXeePvuWcqOWun+ihjOOBleOCjOOBpuOBhOOCi+ODl+ODqeODg+ODiOODleOCqeODvOODoOOCkuaknOefpeOBmeOCi+OBn+OCgeOBruODpuODvOODhuOCo+ODquODhuOCo+ODoeOCveODg+ODieOCkuWPjuOCgeOBn+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gKi9cbmNsYXNzIFBsYXRmb3JtIHtcblxuICAvKipcbiAgICogQWxsIGVsZW1lbnRzIHdpbGwgYmUgcmVuZGVyZWQgYXMgaWYgdGhlIGFwcCB3YXMgcnVubmluZyBvbiB0aGlzIHBsYXRmb3JtLlxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKi9cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5fcmVuZGVyUGxhdGZvcm0gPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2VsZWN0XG4gICAqIEBzaWduYXR1cmUgc2VsZWN0KHBsYXRmb3JtKVxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHBsYXRmb3JtIE5hbWUgb2YgdGhlIHBsYXRmb3JtLlxuICAgKiAgIFtlbl1Qb3NzaWJsZSB2YWx1ZXMgYXJlOiBcIm9wZXJhXCIsIFwiZmlyZWZveFwiLCBcInNhZmFyaVwiLCBcImNocm9tZVwiLCBcImllXCIsIFwiYW5kcm9pZFwiLCBcImJsYWNrYmVycnlcIiwgXCJpb3NcIiBvciBcIndwXCIuWy9lbl1cbiAgICogICBbamFdXCJvcGVyYVwiLCBcImZpcmVmb3hcIiwgXCJzYWZhcmlcIiwgXCJjaHJvbWVcIiwgXCJpZVwiLCBcImFuZHJvaWRcIiwgXCJibGFja2JlcnJ5XCIsIFwiaW9zXCIsIFwid3BcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TZXRzIHRoZSBwbGF0Zm9ybSB1c2VkIHRvIHJlbmRlciB0aGUgZWxlbWVudHMuIFVzZWZ1bCBmb3IgdGVzdGluZy5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgpLmj4/nlLvjgZnjgovjgZ/jgoHjgavliKnnlKjjgZnjgovjg5fjg6njg4Pjg4jjg5Xjgqnjg7zjg6DlkI3jgpLoqK3lrprjgZfjgb7jgZnjgILjg4bjgrnjg4jjgavkvr/liKnjgafjgZnjgIJbL2phXVxuICAgKi9cbiAgc2VsZWN0KHBsYXRmb3JtKSB7XG4gICAgaWYgKHR5cGVvZiBwbGF0Zm9ybSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMuX3JlbmRlclBsYXRmb3JtID0gcGxhdGZvcm0udHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNXZWJWaWV3XG4gICAqIEBzaWduYXR1cmUgaXNXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gICAqICAgW2phXUNvcmRvdmHlhoXjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNXZWJWaWV3KCkge1xuICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaXNXZWJWaWV3KCkgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBkb20gY29udGVudHMgbG9hZGVkLicpO1xuICAgIH1cblxuICAgIHJldHVybiAhISh3aW5kb3cuY29yZG92YSB8fCB3aW5kb3cucGhvbmVnYXAgfHwgd2luZG93LlBob25lR2FwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzSU9TXG4gICAqIEBzaWduYXR1cmUgaXNJT1MoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBPUyBpcyBpT1MuWy9lbl1cbiAgICogICBbamFdaU9T5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TKCkge1xuICAgIGlmICh0aGlzLl9yZW5kZXJQbGF0Zm9ybSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3JlbmRlclBsYXRmb3JtID09PSAnaW9zJztcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZXZpY2UgPT09ICdvYmplY3QnICYmICEvYnJvd3Nlci9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSkge1xuICAgICAgcmV0dXJuIC9pT1MvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvaVBob25lfGlQYWR8aVBvZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNBbmRyb2lkXG4gICAqIEBzaWduYXR1cmUgaXNBbmRyb2lkKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgT1MgaXMgQW5kcm9pZC5bL2VuXVxuICAgKiAgIFtqYV1BbmRyb2lk5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQW5kcm9pZCgpIHtcbiAgICBpZiAodGhpcy5fcmVuZGVyUGxhdGZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJQbGF0Zm9ybSA9PT0gJ2FuZHJvaWQnO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0FuZHJvaWQvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNBbmRyb2lkUGhvbmVcbiAgICogQHNpZ25hdHVyZSBpc0FuZHJvaWRQaG9uZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBBbmRyb2lkIHBob25lLlsvZW5dXG4gICAqICAgW2phXUFuZHJvaWTmkLrluK/kuIrjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNBbmRyb2lkUGhvbmUoKSB7XG4gICAgcmV0dXJuIC9BbmRyb2lkL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSAmJiAvTW9iaWxlL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzQW5kcm9pZFRhYmxldFxuICAgKiBAc2lnbmF0dXJlIGlzQW5kcm9pZFRhYmxldCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBBbmRyb2lkIHRhYmxldC5bL2VuXVxuICAgKiAgIFtqYV1BbmRyb2lk44K/44OW44Os44OD44OI5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQW5kcm9pZFRhYmxldCgpIHtcbiAgICByZXR1cm4gL0FuZHJvaWQvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmICEvTW9iaWxlL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNXUCgpIHtcbiAgICBpZiAodGhpcy5fcmVuZGVyUGxhdGZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJQbGF0Zm9ybSA9PT0gJ3dwJztcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZXZpY2UgPT09ICdvYmplY3QnICYmICEvYnJvd3Nlci9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSkge1xuICAgICAgcmV0dXJuIC9XaW4zMk5UfFdpbkNFL2kudGVzdChkZXZpY2UucGxhdGZvcm0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gL1dpbmRvd3MgUGhvbmV8SUVNb2JpbGV8V1BEZXNrdG9wL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvcyBpc0lQaG9uZVxuICAgKiBAc2lnbmF0dXJlIGlzSVBob25lKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgZGV2aWNlIGlzIGlQaG9uZS5bL2VuXVxuICAgKiAgIFtqYV1pUGhvbmXkuIrjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJUGhvbmUoKSB7XG4gICAgcmV0dXJuIC9pUGhvbmUvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJUGFkXG4gICAqIEBzaWduYXR1cmUgaXNJUGFkKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgZGV2aWNlIGlzIGlQYWQuWy9lbl1cbiAgICogICBbamFdaVBhZOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0lQYWQoKSB7XG4gICAgcmV0dXJuIC9pUGFkL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJUG9kKCkge1xuICAgIHJldHVybiAvaVBvZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0JsYWNrQmVycnlcbiAgICogQHNpZ25hdHVyZSBpc0JsYWNrQmVycnkoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQmxhY2tCZXJyeS5bL2VuXVxuICAgKiAgIFtqYV1CbGFja0JlcnJ55LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQmxhY2tCZXJyeSgpIHtcbiAgICBpZiAodGhpcy5fcmVuZGVyUGxhdGZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJQbGF0Zm9ybSA9PT0gJ2JsYWNrYmVycnknO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0JsYWNrQmVycnkvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQmxhY2tCZXJyeXxSSU0gVGFibGV0IE9TfEJCMTAvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzT3BlcmFcbiAgICogQHNpZ25hdHVyZSBpc09wZXJhKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBPcGVyYS5bL2VuXVxuICAgKiAgIFtqYV1PcGVyYeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc09wZXJhKCkge1xuICAgIGlmICh0aGlzLl9yZW5kZXJQbGF0Zm9ybSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3JlbmRlclBsYXRmb3JtID09PSAnb3BlcmEnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gKCEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0ZpcmVmb3hcbiAgICogQHNpZ25hdHVyZSBpc0ZpcmVmb3goKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIEZpcmVmb3guWy9lbl1cbiAgICogICBbamFdRmlyZWZveOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0ZpcmVmb3goKSB7XG4gICAgaWYgKHRoaXMuX3JlbmRlclBsYXRmb3JtKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVuZGVyUGxhdGZvcm0gPT09ICdmaXJlZm94JztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICh0eXBlb2YgSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1NhZmFyaVxuICAgKiBAc2lnbmF0dXJlIGlzU2FmYXJpKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBTYWZhcmkuWy9lbl1cbiAgICogICBbamFdU2FmYXJp5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzU2FmYXJpKCkge1xuICAgIGlmICh0aGlzLl9yZW5kZXJQbGF0Zm9ybSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3JlbmRlclBsYXRmb3JtID09PSAnc2FmYXJpJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwod2luZG93LkhUTUxFbGVtZW50KS5pbmRleE9mKCdDb25zdHJ1Y3RvcicpID4gMCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNDaHJvbWVcbiAgICogQHNpZ25hdHVyZSBpc0Nocm9tZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgQ2hyb21lLlsvZW5dXG4gICAqICAgW2phXUNocm9tZeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0Nocm9tZSgpIHtcbiAgICBpZiAodGhpcy5fcmVuZGVyUGxhdGZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJQbGF0Zm9ybSA9PT0gJ2Nocm9tZSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAoISF3aW5kb3cuY2hyb21lICYmICEoISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDApICYmICEobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgRWRnZS8nKSA+PSAwKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJRVxuICAgKiBAc2lnbmF0dXJlIGlzSUUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIEludGVybmV0IEV4cGxvcmVyLlsvZW5dXG4gICAqICAgW2phXUludGVybmV0IEV4cGxvcmVy5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSUUoKSB7XG4gICAgaWYgKHRoaXMuX3JlbmRlclBsYXRmb3JtKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVuZGVyUGxhdGZvcm0gPT09ICdpZSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZSB8fCAhIWRvY3VtZW50LmRvY3VtZW50TW9kZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0VkZ2VcbiAgICogQHNpZ25hdHVyZSBpc0VkZ2UoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIEVkZ2UuWy9lbl1cbiAgICogICBbamFdRWRnZeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0VkZ2UoKSB7XG4gICAgaWYgKHRoaXMuX3JlbmRlclBsYXRmb3JtKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVuZGVyUGxhdGZvcm0gPT09ICdlZGdlJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIEVkZ2UvJykgPj0gMDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0lPUzdhYm92ZVxuICAgKiBAc2lnbmF0dXJlIGlzSU9TN2Fib3ZlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgaU9TIHZlcnNpb24gaXMgNyBvciBhYm92ZS5bL2VuXVxuICAgKiAgIFtqYV1pT1M35Lul5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TN2Fib3ZlKCkge1xuICAgIGlmICh0eXBlb2YgZGV2aWNlID09PSAnb2JqZWN0JyAmJiAhL2Jyb3dzZXIvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSkpIHtcbiAgICAgIHJldHVybiAoL2lPUy9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSAmJiAocGFyc2VJbnQoZGV2aWNlLnZlcnNpb24uc3BsaXQoJy4nKVswXSkgPj0gNykpO1xuICAgIH0gZWxzZSBpZigvaVBob25lfGlQYWR8aVBvZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgIGNvbnN0IHZlciA9IChuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9cXGJbMC05XStfWzAtOV0rKD86X1swLTldKyk/XFxiLykgfHwgWycnXSlbMF0ucmVwbGFjZSgvXy9nLCAnLicpO1xuICAgICAgcmV0dXJuIChwYXJzZUludCh2ZXIuc3BsaXQoJy4nKVswXSkgPj0gNyk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBnZXRNb2JpbGVPUygpIHtcbiAgICBpZiAodGhpcy5pc0FuZHJvaWQoKSkge1xuICAgICAgcmV0dXJuICdhbmRyb2lkJztcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5pc0lPUygpKSB7XG4gICAgICByZXR1cm4gJ2lvcyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNXUCgpKSB7XG4gICAgICByZXR1cm4gJ3dwJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICByZXR1cm4gJ290aGVyJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0SU9TRGV2aWNlKCkge1xuICAgIGlmICh0aGlzLmlzSVBob25lKCkpIHtcbiAgICAgIHJldHVybiAnaXBob25lJztcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5pc0lQYWQoKSkge1xuICAgICAgcmV0dXJuICdpcGFkJztcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5pc0lQb2QoKSkge1xuICAgICAgcmV0dXJuICdpcG9kJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICByZXR1cm4gJ25hJztcbiAgICB9XG4gIH1cbn1cblxuXG5leHBvcnQgZGVmYXVsdCBuZXcgUGxhdGZvcm0oKTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5jb25zdCByZWFkeU1hcCA9IG5ldyBXZWFrTWFwKCk7XG5jb25zdCBxdWV1ZU1hcCA9IG5ldyBXZWFrTWFwKCk7XG5cbmZ1bmN0aW9uIGlzQ29udGVudFJlYWR5KGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICB9XG4gIHJldHVybiByZWFkeU1hcC5oYXMoZWxlbWVudCk7XG59XG5cbmZ1bmN0aW9uIHNldENvbnRlbnRSZWFkeShlbGVtZW50KSB7XG4gIHJlYWR5TWFwLnNldChlbGVtZW50LCB0cnVlKTtcbn1cblxuZnVuY3Rpb24gYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pIHtcbiAgaWYgKCFxdWV1ZU1hcC5oYXMoZWxlbWVudCkpIHtcbiAgICBxdWV1ZU1hcC5zZXQoZWxlbWVudCwgW10pO1xuICB9XG4gIHF1ZXVlTWFwLmdldChlbGVtZW50KS5wdXNoKGZuKTtcbn1cblxuZnVuY3Rpb24gY29uc3VtZVF1ZXVlKGVsZW1lbnQpIHtcbiAgY29uc3QgY2FsbGJhY2tzID0gcXVldWVNYXAuZ2V0KGVsZW1lbnQsIFtdKSB8fCBbXTtcbiAgcXVldWVNYXAuZGVsZXRlKGVsZW1lbnQpO1xuICBjYWxsYmFja3MuZm9yRWFjaChjYWxsYmFjayA9PiBjYWxsYmFjaygpKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY29udGVudFJlYWR5KGVsZW1lbnQsIGZuID0gKCkgPT4ge30pIHtcbiAgYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pO1xuXG4gIGlmIChpc0NvbnRlbnRSZWFkeShlbGVtZW50KSkge1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKGNoYW5nZXMgPT4ge1xuICAgIHNldENvbnRlbnRSZWFkeShlbGVtZW50KTtcbiAgICBjb25zdW1lUXVldWUoZWxlbWVudCk7XG4gIH0pO1xuICBvYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQsIHtjaGlsZExpc3Q6IHRydWUsIGNoYXJhY3RlckRhdGE6IHRydWV9KTtcblxuICAvLyBmYWlsYmFjayBmb3IgZWxlbWVudHMgaGFzIGVtcHR5IGNvbnRlbnQuXG4gIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgfSk7XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuL2NvbnRlbnQtcmVhZHknO1xuXG4vKipcbiAqIEBvYmplY3Qgb25zLm5vdGlmaWNhdGlvblxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2RpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVdGlsaXR5IG1ldGhvZHMgdG8gY3JlYXRlIGRpZmZlcmVudCBraW5kcyBvZiBhbGVydCBkaWFsb2dzLiBUaGVyZSBhcmUgdGhyZWUgbWV0aG9kcyBhdmFpbGFibGU6XG4gKlxuICogICAgICogYG9ucy5ub3RpZmljYXRpb24uYWxlcnQoKWBcbiAqICAgICAqIGBvbnMubm90aWZpY2F0aW9uLmNvbmZpcm0oKWBcbiAqICAgICAqIGBvbnMubm90aWZpY2F0aW9uLnByb21wdCgpYFxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgZGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBkaWFsb2cgb24gQW5kcm9pZCBkZXZpY2VzLlxuICogICBbL2VuXVxuICogICBbamFd44GE44GP44Gk44GL44Gu56iu6aGe44Gu44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44KS5L2c5oiQ44GZ44KL44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gf44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdIZWxsbywgd29ybGQhJyk7XG4gKlxuICogb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKCdBcmUgeW91IHJlYWR5PycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFuc3dlcikge1xuICogICAgICAgaWYgKGFuc3dlciA9PT0gMSkge1xuICogICAgICAgICBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdMZXRcXCdzIGdvIScpO1xuICogICAgICAgfVxuICogICAgIH1cbiAqICAgKTtcbiAqXG4gKiBvbnMubm90aWZpY2F0aW9uLnByb21wdCgnSG93IG9sZCBhcmUgPycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFnZSkge1xuICogICAgICAgb25zLm5vdGlmaWNhdGlvbi5hbGVydCgnWW91IGFyZSAnICsgYWdlICsgJyB5ZWFycyBvbGQuJyk7XG4gKiAgICAgfVxuICogICApO1xuICovXG5jb25zdCBub3RpZmljYXRpb24gPSB7fTtcblxubm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyA9IG9wdGlvbnMgPT4ge1xuICAvLyBQcm9tcHQgaW5wdXQgc3RyaW5nXG4gIGxldCBpbnB1dFN0cmluZyA9ICcnO1xuICBpZiAob3B0aW9ucy5pc1Byb21wdCkge1xuICAgIGlucHV0U3RyaW5nID0gYFxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwidGV4dC1pbnB1dCB0ZXh0LWlucHV0LS11bmRlcmJhclwiXG4gICAgICAgIHR5cGU9XCIke29wdGlvbnMuaW5wdXRUeXBlIHx8ICd0ZXh0J31cIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIiR7b3B0aW9ucy5wbGFjZWhvbGRlciB8fCAnJ31cIlxuICAgICAgICB2YWx1ZT1cIiR7b3B0aW9ucy5kZWZhdWx0VmFsdWUgfHwgJyd9XCJcbiAgICAgICAgc3R5bGU9XCJ3aWR0aDogMTAwJTsgbWFyZ2luLXRvcDogMTBweDtcIlxuICAgICAgLz5cbiAgICBgO1xuICB9XG5cbiAgLy8gQnV0dG9ucyBzdHJpbmdcbiAgbGV0IGJ1dHRvbnMgPSAnJztcbiAgb3B0aW9ucy5idXR0b25MYWJlbHMuZm9yRWFjaCgobGFiZWwsIGluZGV4KSA9PiB7XG4gICAgYnV0dG9ucyArPSBgXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiXG4gICAgICAgIGFsZXJ0LWRpYWxvZy1idXR0b25cbiAgICAgICAgJHtpbmRleCA9PT0gb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXggPyAnIGFsZXJ0LWRpYWxvZy1idXR0b24tLXByaW1hbCcgOiAnJ31cbiAgICAgICAgJHtvcHRpb25zLmJ1dHRvbkxhYmVscy5sZW5ndGggPD0gMiA/ICcgYWxlcnQtZGlhbG9nLWJ1dHRvbi0tb25lJyA6ICcnfVxuICAgICAgXCI+XG4gICAgICAgICR7bGFiZWx9XG4gICAgICA8L2J1dHRvbj5cbiAgICBgO1xuICB9KTtcblxuICAvLyBEaWFsb2cgRWxlbWVudFxuICBsZXQgZWwgPSB7fTtcbiAgY29uc3QgX2Rlc3Ryb3lEaWFsb2cgPSAoKSA9PiB7XG4gICAgaWYgKGVsLmRpYWxvZy5vbkRpYWxvZ0NhbmNlbCkge1xuICAgICAgZWwuZGlhbG9nLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RpYWxvZy1jYW5jZWwnLCBlbC5kaWFsb2cub25EaWFsb2dDYW5jZWwpO1xuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKGVsKS5mb3JFYWNoKGtleSA9PiBkZWxldGUgZWxba2V5XSk7XG4gICAgZWwgPSBudWxsO1xuXG4gICAgaWYgKG9wdGlvbnMuZGVzdHJveSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBvcHRpb25zLmRlc3Ryb3koKTtcbiAgICB9XG4gIH07XG5cbiAgZWwuZGlhbG9nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb25zLWFsZXJ0LWRpYWxvZycpO1xuICBpbm5lckhUTUwoZWwuZGlhbG9nLCBgXG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1tYXNrXCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZ1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1jb250YWluZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy10aXRsZVwiPlxuICAgICAgICAgICR7b3B0aW9ucy50aXRsZSB8fCAnJ31cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctY29udGVudFwiPlxuICAgICAgICAgICR7b3B0aW9ucy5tZXNzYWdlIHx8IG9wdGlvbnMubWVzc2FnZUhUTUx9XG4gICAgICAgICAgJHtpbnB1dFN0cmluZ31cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJcbiAgICAgICAgICBhbGVydC1kaWFsb2ctZm9vdGVyXG4gICAgICAgICAgJHtvcHRpb25zLmJ1dHRvbkxhYmVscy5sZW5ndGggPD0gMiA/ICcgYWxlcnQtZGlhbG9nLWZvb3Rlci0tb25lJyA6ICcnfVxuICAgICAgICBcIj5cbiAgICAgICAgICAke2J1dHRvbnN9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGApO1xuICBjb250ZW50UmVhZHkoZWwuZGlhbG9nKTtcblxuICAvLyBTZXQgYXR0cmlidXRlc1xuICBbJ2lkJywgJ2NsYXNzJywgJ2FuaW1hdGlvbiddXG4gICAgLmZvckVhY2goYSA9PiBvcHRpb25zLmhhc093blByb3BlcnR5KGEpICYmIGVsLmRpYWxvZy5zZXRBdHRyaWJ1dGUoYSwgb3B0aW9uc1thXSkpO1xuICBpZiAob3B0aW9ucy5tb2RpZmllcikge1xuICAgIHV0aWwuYWRkTW9kaWZpZXIoZWwuZGlhbG9nLCBvcHRpb25zLm1vZGlmaWVyKTtcbiAgfVxuXG4gIGNvbnN0IGRlZmVycmVkID0gdXRpbC5kZWZlcigpO1xuXG4gIC8vIFByb21wdCBldmVudHNcbiAgaWYgKG9wdGlvbnMuaXNQcm9tcHQgJiYgb3B0aW9ucy5zdWJtaXRPbkVudGVyKSB7XG4gICAgZWwuaW5wdXQgPSBlbC5kaWFsb2cucXVlcnlTZWxlY3RvcignLnRleHQtaW5wdXQnKTtcbiAgICBlbC5pbnB1dC5vbmtleXByZXNzID0gZXZlbnQgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IDEzKSB7XG4gICAgICAgIGVsLmRpYWxvZy5oaWRlKClcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlVmFsdWUgPSBlbC5pbnB1dC52YWx1ZTtcbiAgICAgICAgICAgIF9kZXN0cm95RGlhbG9nKCk7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8vIEJ1dHRvbiBldmVudHNcbiAgZWwuZm9vdGVyID0gZWwuZGlhbG9nLnF1ZXJ5U2VsZWN0b3IoJy5hbGVydC1kaWFsb2ctZm9vdGVyJyk7XG4gIHV0aWwuYXJyYXlGcm9tKGVsLmRpYWxvZy5xdWVyeVNlbGVjdG9yQWxsKCcuYWxlcnQtZGlhbG9nLWJ1dHRvbicpKS5mb3JFYWNoKChidXR0b25FbGVtZW50LCBpbmRleCkgPT4ge1xuICAgIGJ1dHRvbkVsZW1lbnQub25jbGljayA9ICgpID0+IHtcbiAgICAgIGVsLmRpYWxvZy5oaWRlKClcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlc29sdmVWYWx1ZSA9IG9wdGlvbnMuaXNQcm9tcHQgPyBlbC5pbnB1dC52YWx1ZSA6IGluZGV4O1xuICAgICAgICAgIGVsLmRpYWxvZy5yZW1vdmUoKTtcbiAgICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2socmVzb2x2ZVZhbHVlKTtcbiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBlbC5mb290ZXIuYXBwZW5kQ2hpbGQoYnV0dG9uRWxlbWVudCk7XG4gIH0pO1xuXG4gIC8vIENhbmNlbCBldmVudHNcbiAgaWYgKG9wdGlvbnMuY2FuY2VsYWJsZSkge1xuICAgIGVsLmRpYWxvZy5jYW5jZWxhYmxlID0gdHJ1ZTtcbiAgICBlbC5kaWFsb2cub25EaWFsb2dDYW5jZWwgPSAoKSA9PiB7XG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgICBlbC5kaWFsb2cucmVtb3ZlKCk7XG4gICAgICAgIF9kZXN0cm95RGlhbG9nKCk7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJlc29sdmVWYWx1ZSA9IG9wdGlvbnMuaXNQcm9tcHQgPyBudWxsIDogLTE7XG4gICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICBkZWZlcnJlZC5yZWplY3QocmVzb2x2ZVZhbHVlKTtcbiAgICB9O1xuICAgIGVsLmRpYWxvZy5hZGRFdmVudExpc3RlbmVyKCdkaWFsb2ctY2FuY2VsJywgZWwuZGlhbG9nLm9uRGlhbG9nQ2FuY2VsLCBmYWxzZSk7XG4gIH1cblxuICAvLyBTaG93IGRpYWxvZ1xuICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsLmRpYWxvZyk7XG4gIG9wdGlvbnMuY29tcGlsZShlbC5kaWFsb2cpO1xuICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgIGVsLmRpYWxvZy5zaG93KClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGVsLmlucHV0ICYmIG9wdGlvbnMuaXNQcm9tcHQgJiYgb3B0aW9ucy5hdXRvZm9jdXMpIHtcbiAgICAgICAgICBlbC5pbnB1dC5mb2N1cygpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG5jb25zdCBfbm9ybWFsaXplQXJndW1lbnRzID0gKG1lc3NhZ2UsIG9wdGlvbnMgPSB7fSwgZGVmYXVsdHMgPSB7fSkgPT4ge1xuICB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyAob3B0aW9ucy5tZXNzYWdlID0gbWVzc2FnZSkgOiAob3B0aW9ucyA9IG1lc3NhZ2UpO1xuICBpZiAoIW9wdGlvbnMubWVzc2FnZSAmJiAhb3B0aW9ucy5tZXNzYWdlSFRNTCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQWxlcnQgZGlhbG9nIG11c3QgY29udGFpbiBhIG1lc3NhZ2UuJyk7XG4gIH1cblxuICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnYnV0dG9uTGFiZWxzJykgfHwgb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnYnV0dG9uTGFiZWwnKSkge1xuICAgIG9wdGlvbnMuYnV0dG9uTGFiZWxzID0gb3B0aW9ucy5idXR0b25MYWJlbHMgfHwgb3B0aW9ucy5idXR0b25MYWJlbDtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkob3B0aW9ucy5idXR0b25MYWJlbHMpKSB7XG4gICAgICBvcHRpb25zLmJ1dHRvbkxhYmVscyA9IFtvcHRpb25zLmJ1dHRvbkxhYmVscyB8fCAnJ11cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdXRpbC5leHRlbmQoe1xuICAgICAgY29tcGlsZTogcGFyYW0gPT4gcGFyYW0sXG4gICAgICBjYWxsYmFjazogcGFyYW0gPT4gcGFyYW0sXG4gICAgICBidXR0b25MYWJlbHM6IFsnT0snXSxcbiAgICAgIHByaW1hcnlCdXR0b25JbmRleDogMCxcbiAgICAgIGFuaW1hdGlvbjogJ2RlZmF1bHQnLFxuICAgICAgY2FuY2VsYWJsZTogZmFsc2VcbiAgICB9LCBkZWZhdWx0cywgb3B0aW9ucyk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgYWxlcnRcbiAqIEBzaWduYXR1cmUgYWxlcnQobWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHdoZW4gdGhlIGRpYWxvZyBpcyBjbG9zZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICogICBbZW5dQWxlcnQgbWVzc2FnZS4gVGhpcyBhcmd1bWVudCBpcyBvcHRpb25hbCBidXQgaWYgaXQncyBub3QgZGVmaW5lZCBlaXRoZXIgYG9wdGlvbnMubWVzc2FnZWAgb3IgYG9wdGlvbnMubWVzc2FnZUhUTUxgIG11c3QgYmUgZGVmaW5lZCBpbnN0ZWFkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubWVzc2FnZV1cbiAqICAgW2VuXUFsZXJ0IG1lc3NhZ2UuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBq+ihqOekuuOBmeOCi+aWh+Wtl+WIl+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubWVzc2FnZUhUTUxdXG4gKiAgIFtlbl1BbGVydCBtZXNzYWdlIGluIEhUTUwuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBq+ihqOekuuOBmeOCi0hUTUzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmcgfCBBcnJheX0gW29wdGlvbnMuYnV0dG9uTGFiZWxzXVxuICogICBbZW5dTGFiZWxzIGZvciB0aGUgYnV0dG9ucy4gRGVmYXVsdCBpcyBgXCJPS1wiYC5bL2VuXVxuICogICBbamFd56K66KqN44Oc44K/44Oz44Gu44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJPS1wi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXhdXG4gKiAgIFtlbl1JbmRleCBvZiBwcmltYXJ5IGJ1dHRvbi4gRGVmYXVsdCBpcyBgMGAuWy9lbl1cbiAqICAgW2phXeODl+ODqeOCpOODnuODquODnOOCv+ODs+OBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBryAwIOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmNhbmNlbGFibGVdXG4gKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIERlZmF1bHQgaXMgYGZhbHNlYC4gSWYgdGhlIGRpYWxvZyBpcyBjYW5jZWxhYmxlIGl0IGNhbiBiZSBjbG9zZWQgYnkgY2xpY2tpbmcgdGhlIGJhY2tncm91bmQgb3IgcHJlc3NpbmcgdGhlIEFuZHJvaWQgYmFjayBidXR0b24uWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOOCreODo+ODs+OCu+ODq+WPr+iDveOBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgbm9uZWAgYW5kIGBmYWRlYC4gRGVmYXVsdCBpcyBgZmFkZWAuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOCkuihqOekuuOBmeOCi+mam+OBruOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuaWRdXG4gKiAgIFtlbl1UaGUgYDxvbnMtYWxlcnQtZGlhbG9nPmAgZWxlbWVudCdzIElELlsvZW5dXG4gKiAgIFtqYV1vbnMtYWxlcnQtZGlhbG9n6KaB57Sg44GuSUTjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNsYXNzXVxuICogICBbZW5dVGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGVsZW1lbnQncyBjbGFzcy5bL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+imgee0oOOBrmNsYXNz44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aXRsZV1cbiAqICAgW2VuXURpYWxvZyB0aXRsZS4gRGVmYXVsdCBpcyBgXCJBbGVydFwiYC5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu5LiK6YOo44Gr6KGo56S644GZ44KL44K/44Kk44OI44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJBbGVydFwi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tb2RpZmllcl1cbiAqICAgW2VuXU1vZGlmaWVyIGZvciB0aGUgZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga5tb2RpZmllcuWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgYWZ0ZXIgZGlhbG9nIGhhcyBiZWVuIGNsb3NlZC5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6ZaJ44GY44KJ44KM44Gf5pmC44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRGlzcGxheSBhbiBhbGVydCBkaWFsb2cgdG8gc2hvdyB0aGUgdXNlciBhIG1lc3NhZ2UuXG4gKlxuICogICAgIFRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlIGNhbiBiZSBlaXRoZXIgc2ltcGxlIHRleHQgb3IgSFRNTC5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24uYWxlcnQobWVzc2FnZSwgb3B0aW9ucyk7XG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi5hbGVydChvcHRpb25zKTtcbiAqICAgICBgYGBcbiAqXG4gKiAgICAgTXVzdCBzcGVjaWZ5IGVpdGhlciBgbWVzc2FnZWAgb3IgYG1lc3NhZ2VIVE1MYC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIOODpuODvOOCtuODvOOBuOODoeODg+OCu+ODvOOCuOOCkuimi+OBm+OCi+OBn+OCgeOBruOCouODqeODvOODiOODgOOCpOOCouODreOCsOOCkuihqOekuuOBl+OBvuOBmeOAglxuICogICAgIOihqOekuuOBmeOCi+ODoeODg+OCu+ODvOOCuOOBr+OAgeODhuOCreOCueODiOOBi+OCguOBl+OBj+OBr0hUTUzjgpLmjIflrprjgafjgY3jgb7jgZnjgIJcbiAqICAgICDjgZPjga7jg6Hjgr3jg4Pjg4njga7lvJXmlbDjgavjga/jgIFvcHRpb25zLm1lc3NhZ2XjgoLjgZfjgY/jga9vcHRpb25zLm1lc3NhZ2VIVE1M44Gu44Gp44Gh44KJ44GL44KS5b+F44Ga5oyH5a6a44GZ44KL5b+F6KaB44GM44GC44KK44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKi9cbm5vdGlmaWNhdGlvbi5hbGVydCA9IChtZXNzYWdlLCBvcHRpb25zKSA9PiB7XG4gIG9wdGlvbnMgPSBfbm9ybWFsaXplQXJndW1lbnRzKG1lc3NhZ2UsIG9wdGlvbnMsIHtcbiAgICB0aXRsZTogJ0FsZXJ0J1xuICB9KTtcblxuICByZXR1cm4gbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhvcHRpb25zKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBjb25maXJtXG4gKiBAc2lnbmF0dXJlIGNvbmZpcm0obWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHRvIHRoZSBpbmRleCBvZiB0aGUgYnV0dG9uIHRoYXQgd2FzIHByZXNzZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICogICBbZW5dQWxlcnQgbWVzc2FnZS4gVGhpcyBhcmd1bWVudCBpcyBvcHRpb25hbCBidXQgaWYgaXQncyBub3QgZGVmaW5lZCBlaXRoZXIgYG9wdGlvbnMubWVzc2FnZWAgb3IgYG9wdGlvbnMubWVzc2FnZUhUTUxgIG11c3QgYmUgZGVmaW5lZCBpbnN0ZWFkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqIEBwYXJhbSB7QXJyYXl9IFtvcHRpb25zLmJ1dHRvbkxhYmVsc11cbiAqICAgW2VuXUxhYmVscyBmb3IgdGhlIGJ1dHRvbnMuIERlZmF1bHQgaXMgYFtcIkNhbmNlbFwiLCBcIk9LXCJdYC5bL2VuXVxuICogICBbamFd44Oc44K/44Oz44Gu44Op44OZ44Or44Gu6YWN5YiX44KS5oyH5a6a44GX44G+44GZ44CCW1wiQ2FuY2VsXCIsIFwiT0tcIl3jgYzjg4fjg5Xjgqnjg6vjg4jjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnByaW1hcnlCdXR0b25JbmRleF1cbiAqICAgW2VuXUluZGV4IG9mIHByaW1hcnkgYnV0dG9uLiBEZWZhdWx0IGlzIGAxYC5bL2VuXVxuICogICBbamFd44OX44Op44Kk44Oe44Oq44Oc44K/44Oz44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvIDEg44Gn44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRGlzcGxheSBhIGRpYWxvZyB0byBhc2sgdGhlIHVzZXIgZm9yIGNvbmZpcm1hdGlvbi4gRXh0ZW5kcyBgYWxlcnQoKWAgcGFyYW1ldGVycy5cbiAqICAgICBUaGUgZGVmYXVsdCBidXR0b24gbGFiZWxzIGFyZSBgXCJDYW5jZWxcImAgYW5kIGBcIk9LXCJgIGJ1dCB0aGV5IGNhbiBiZSBjdXN0b21pemVkLlxuICpcbiAqICAgICBJdCBjYW4gYmUgY2FsbGVkIGluIHRoZSBmb2xsb3dpbmcgd2F5czpcbiAqXG4gKiAgICAgYGBgXG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24uY29uZmlybShvcHRpb25zKTtcbiAqICAgICBgYGBcbiAqXG4gKiAgICAgTXVzdCBzcGVjaWZ5IGVpdGhlciBgbWVzc2FnZWAgb3IgYG1lc3NhZ2VIVE1MYC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIOODpuODvOOCtuOBq+eiuuiqjeOCkuS/g+OBmeODgOOCpOOCouODreOCsOOCkuihqOekuuOBl+OBvuOBmeOAglxuICogICAgIOODh+OCquODq+OBqOOBruODnOOCv+ODs+ODqeODmeODq+OBr+OAgVwiQ2FuY2VsXCLjgahcIk9LXCLjgafjgZnjgYzjgIHjgZPjgozjga/jgZPjga7jg6Hjgr3jg4Pjg4njga7lvJXmlbDjgafjgqvjgrnjgr/jg57jgqTjgrrjgafjgY3jgb7jgZnjgIJcbiAqICAgICDjgZPjga7jg6Hjgr3jg4Pjg4njga7lvJXmlbDjgavjga/jgIFvcHRpb25zLm1lc3NhZ2XjgoLjgZfjgY/jga9vcHRpb25zLm1lc3NhZ2VIVE1M44Gu44Gp44Gh44KJ44GL44KS5b+F44Ga5oyH5a6a44GZ44KL5b+F6KaB44GM44GC44KK44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKi9cbm5vdGlmaWNhdGlvbi5jb25maXJtID0gKG1lc3NhZ2UsIG9wdGlvbnMpID0+IHtcbiAgb3B0aW9ucyA9IF9ub3JtYWxpemVBcmd1bWVudHMobWVzc2FnZSwgb3B0aW9ucywge1xuICAgIGJ1dHRvbkxhYmVsczogWydDYW5jZWwnLCAnT0snXSxcbiAgICBwcmltYXJ5QnV0dG9uSW5kZXg6IDEsXG4gICAgdGl0bGU6ICdDb25maXJtJ1xuICB9KTtcblxuICByZXR1cm4gbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhvcHRpb25zKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBwcm9tcHRcbiAqIEBzaWduYXR1cmUgcHJvbXB0KG1lc3NhZ2UgWywgb3B0aW9uc10gfCBvcHRpb25zKVxuICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAqICAgW2VuXUFsZXJ0IG1lc3NhZ2UuIFRoaXMgYXJndW1lbnQgaXMgb3B0aW9uYWwgYnV0IGlmIGl0J3Mgbm90IGRlZmluZWQgZWl0aGVyIGBvcHRpb25zLm1lc3NhZ2VgIG9yIGBvcHRpb25zLm1lc3NhZ2VIVE1MYCBtdXN0IGJlIGRlZmluZWQgaW5zdGVhZC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1XaWxsIHJlc29sdmUgdG8gdGhlIGlucHV0IHZhbHVlIHdoZW4gdGhlIGRpYWxvZyBpcyBjbG9zZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nIHwgQXJyYXl9IFtvcHRpb25zLmJ1dHRvbkxhYmVsc11cbiAqICAgW2VuXUxhYmVscyBmb3IgdGhlIGJ1dHRvbnMuIERlZmF1bHQgaXMgYFwiT0tcImAuWy9lbl1cbiAqICAgW2phXeeiuuiqjeODnOOCv+ODs+OBruODqeODmeODq+OCkuaMh+WumuOBl+OBvuOBmeOAglwiT0tcIuOBjOODh+ODleOCqeODq+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucHJpbWFyeUJ1dHRvbkluZGV4XVxuICogICBbZW5dSW5kZXggb2YgcHJpbWFyeSBidXR0b24uIERlZmF1bHQgaXMgYDBgLlsvZW5dXG4gKiAgIFtqYV3jg5fjg6njgqTjg57jg6rjg5zjgr/jg7Pjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga8gMCDjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnBsYWNlaG9sZGVyXVxuICogICBbZW5dUGxhY2Vob2xkZXIgZm9yIHRoZSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgIFtqYV3jg4bjgq3jgrnjg4jmrITjga7jg5fjg6zjg7zjgrnjg5vjg6vjg4DjgavooajnpLrjgZnjgovjg4bjgq3jgrnjg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmRlZmF1bHRWYWx1ZV1cbiAqICAgW2VuXURlZmF1bHQgdmFsdWUgZm9yIHRoZSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgIFtqYV3jg4bjgq3jgrnjg4jmrITjga7jg4fjg5Xjgqnjg6vjg4jjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmlucHV0VHlwZV1cbiAqICAgW2VuXVR5cGUgb2YgdGhlIGlucHV0IGVsZW1lbnQgKGBwYXNzd29yZGAsIGBkYXRlYC4uLikuIERlZmF1bHQgaXMgYHRleHRgLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5hdXRvZm9jdXNdXG4gKiAgIFtlbl1BdXRvZm9jdXMgdGhlIGlucHV0IGVsZW1lbnQuIERlZmF1bHQgaXMgYHRydWVgLlsvZW5dXG4gKiAgIFtqYV1pbnB1dOimgee0oOOBq+iHquWLleeahOOBq+ODleOCqeODvOOCq+OCueOBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBr3RydWXjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdWJtaXRPbkVudGVyXVxuICogICBbZW5dU3VibWl0IGF1dG9tYXRpY2FsbHkgd2hlbiBlbnRlciBpcyBwcmVzc2VkLiBEZWZhdWx0IGlzIGB0cnVlYC5bL2VuXVxuICogICBbamFdRW50ZXLjgYzmirzjgZXjgozjgZ/pmpvjgavjgZ3jga5mb3Jt44KSc3VibWl044GZ44KL44GL44Gp44GG44GL44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvdHJ1ZeOBp+OBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXkgYSBkaWFsb2cgd2l0aCBhIHByb21wdCB0byBhc2sgdGhlIHVzZXIgYSBxdWVzdGlvbi4gRXh0ZW5kcyBgYWxlcnQoKWAgcGFyYW1ldGVycy5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG9wdGlvbnMpO1xuICogICAgIGBgYFxuICpcbiAqICAgICBNdXN0IHNwZWNpZnkgZWl0aGVyIGBtZXNzYWdlYCBvciBgbWVzc2FnZUhUTUxgLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44Om44O844K244O844Gr5YWl5Yqb44KS5L+D44GZ44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Oh44K944OD44OJ44Gu5byV5pWw44Gr44Gv44CBb3B0aW9ucy5tZXNzYWdl44KC44GX44GP44Gvb3B0aW9ucy5tZXNzYWdlSFRNTOOBruOBqeOBoeOCieOBi+OCkuW/heOBmuaMh+WumuOBmeOCi+W/heimgeOBjOOBguOCiuOBvuOBmeOAglxuICogICBbL2phXVxuICovXG5ub3RpZmljYXRpb24ucHJvbXB0ID0gKG1lc3NhZ2UsIG9wdGlvbnMpID0+IHtcbiAgb3B0aW9ucyA9IF9ub3JtYWxpemVBcmd1bWVudHMobWVzc2FnZSwgb3B0aW9ucywge1xuICAgIHRpdGxlOiAnQWxlcnQnLFxuICAgIGlzUHJvbXB0OiB0cnVlLFxuICAgIGF1dG9mb2N1czogdHJ1ZSxcbiAgICBzdWJtaXRPbkVudGVyOiB0cnVlXG4gIH0pO1xuXG4gIHJldHVybiBub3RpZmljYXRpb24uX2NyZWF0ZUFsZXJ0RGlhbG9nKG9wdGlvbnMpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgbm90aWZpY2F0aW9uO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm0nO1xuXG5jb25zdCBwYWdlQXR0cmlidXRlRXhwcmVzc2lvbiA9IHtcbiAgX3ZhcmlhYmxlczoge30sXG5cbiAgLyoqXG4gICAqIERlZmluZSBhIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSB2YXJpYWJsZVxuICAgKiBAcGFyYW0ge1N0cmluZ3xGdW5jdGlvbn0gdmFsdWUgVmFsdWUgb2YgdGhlIHZhcmlhYmxlLiBDYW4gYmUgYSBzdHJpbmcgb3IgYSBmdW5jdGlvbi4gVGhlIGZ1bmN0aW9uIG11c3QgcmV0dXJuIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IG92ZXJ3cml0ZSBJZiB0aGlzIHZhbHVlIGlzIGZhbHNlLCBhbiBlcnJvciB3aWxsIGJlIHRocm93biB3aGVuIHRyeWluZyB0byBkZWZpbmUgYSB2YXJpYWJsZSB0aGF0IGhhcyBhbHJlYWR5IGJlZW4gZGVmaW5lZC5cbiAgICovXG4gIGRlZmluZVZhcmlhYmxlOiBmdW5jdGlvbihuYW1lLCB2YWx1ZSwgb3ZlcndyaXRlPWZhbHNlKSB7XG4gICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdWYXJpYWJsZSBuYW1lIG11c3QgYmUgYSBzdHJpbmcuJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgJiYgdHlwZW9mIHZhbHVlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZhcmlhYmxlIHZhbHVlIG11c3QgYmUgYSBzdHJpbmcgb3IgYSBmdW5jdGlvbi4nKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5fdmFyaWFibGVzLmhhc093blByb3BlcnR5KG5hbWUpICYmICFvdmVyd3JpdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgXCIke25hbWV9XCIgaXMgYWxyZWFkeSBkZWZpbmVkLmApO1xuICAgIH1cbiAgICB0aGlzLl92YXJpYWJsZXNbbmFtZV0gPSB2YWx1ZTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGEgdmFyaWFibGUuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIHZhcmlhYmxlLlxuICAgKiBAcmV0dXJuIHtTdHJpbmd8RnVuY3Rpb258bnVsbH1cbiAgICovXG4gIGdldFZhcmlhYmxlOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLl92YXJpYWJsZXMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl92YXJpYWJsZXNbbmFtZV07XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSB2YXJhaWJsZS5cbiAgICovXG4gIHJlbW92ZVZhcmlhYmxlOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMuX3ZhcmlhYmxlc1tuYW1lXTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGFsbCB2YXJpYWJsZXMuXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIGdldEFsbFZhcmlhYmxlczogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhcmlhYmxlcztcbiAgfSxcbiAgX3BhcnNlUGFydDogZnVuY3Rpb24ocGFydCkge1xuICAgIGxldCBjLFxuICAgICAgaW5JbnRlcnBvbGF0aW9uID0gZmFsc2UsXG4gICAgICBjdXJyZW50SW5kZXggPSAwO1xuXG4gICAgY29uc3QgdG9rZW5zID0gW107XG5cbiAgICBpZiAocGFydC5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIHBhcnNlIGVtcHR5IHN0cmluZy4nKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGMgPSBwYXJ0LmNoYXJBdChpKTtcblxuICAgICAgaWYgKGMgPT09ICckJyAmJiBwYXJ0LmNoYXJBdChpICsgMSkgPT09ICd7Jykge1xuICAgICAgICBpZiAoaW5JbnRlcnBvbGF0aW9uKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOZXN0ZWQgaW50ZXJwb2xhdGlvbiBub3Qgc3VwcG9ydGVkLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG9rZW4gPSBwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIGkpO1xuICAgICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY3VycmVudEluZGV4ID0gaTtcbiAgICAgICAgaW5JbnRlcnBvbGF0aW9uID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGMgPT09ICd9Jykge1xuICAgICAgICBpZiAoIWluSW50ZXJwb2xhdGlvbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignfSBtdXN0IGJlIHByZWNlZWRlZCBieSAkeycpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG9rZW4gPSBwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIGkgKyAxKTtcbiAgICAgICAgaWYgKHRva2VuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0b2tlbnMucHVzaChwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIGkgKyAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50SW5kZXggPSBpICsgMTtcbiAgICAgICAgaW5JbnRlcnBvbGF0aW9uID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGluSW50ZXJwb2xhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnRlcm1pbmF0ZWQgaW50ZXJwb2xhdGlvbi4nKTtcbiAgICB9XG5cbiAgICB0b2tlbnMucHVzaChwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIHBhcnQubGVuZ3RoKSk7XG5cbiAgICByZXR1cm4gdG9rZW5zO1xuICB9LFxuICBfcmVwbGFjZVRva2VuOiBmdW5jdGlvbih0b2tlbikge1xuICAgIGNvbnN0IHJlID0gL15cXCR7KC4qPyl9JC8sXG4gICAgICBtYXRjaCA9IHRva2VuLm1hdGNoKHJlKTtcblxuICAgIGlmIChtYXRjaCkge1xuICAgICAgY29uc3QgbmFtZSA9IG1hdGNoWzFdLnRyaW0oKTtcbiAgICAgIGNvbnN0IHZhcmlhYmxlID0gdGhpcy5nZXRWYXJpYWJsZShuYW1lKTtcblxuICAgICAgaWYgKHZhcmlhYmxlID09PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVmFyaWFibGUgXCIke25hbWV9XCIgZG9lcyBub3QgZXhpc3QuYCk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmICh0eXBlb2YgdmFyaWFibGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB2YXJpYWJsZTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBydiA9IHZhcmlhYmxlKCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBydiAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgcmV0dXJuIGEgc3RyaW5nLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJ2O1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiB0b2tlbjtcbiAgICB9XG4gIH0sXG4gIF9yZXBsYWNlVG9rZW5zOiBmdW5jdGlvbih0b2tlbnMpIHtcbiAgICByZXR1cm4gdG9rZW5zLm1hcCh0aGlzLl9yZXBsYWNlVG9rZW4uYmluZCh0aGlzKSk7XG4gIH0sXG4gIF9wYXJzZUV4cHJlc3Npb246IGZ1bmN0aW9uKGV4cHJlc3Npb24pIHtcbiAgICByZXR1cm4gZXhwcmVzc2lvbi5zcGxpdCgnLCcpXG4gICAgICAubWFwKFxuICAgICAgICBmdW5jdGlvbihwYXJ0KSB7XG4gICAgICAgICAgcmV0dXJuIHBhcnQudHJpbSgpO1xuICAgICAgICB9XG4gICAgICApXG4gICAgICAubWFwKHRoaXMuX3BhcnNlUGFydC5iaW5kKHRoaXMpKVxuICAgICAgLm1hcCh0aGlzLl9yZXBsYWNlVG9rZW5zLmJpbmQodGhpcykpXG4gICAgICAubWFwKChwYXJ0KSA9PiBwYXJ0LmpvaW4oJycpKTtcbiAgfSxcblxuICAvKipcbiAgICogRXZhbHVhdGUgYW4gZXhwcmVzc2lvbi5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV4cHJlc3Npb24gQW4gcGFnZSBhdHRyaWJ1dGUgZXhwcmVzc2lvbi5cbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBldmFsdWF0ZTogZnVuY3Rpb24oZXhwcmVzc2lvbikge1xuICAgIGlmICghZXhwcmVzc2lvbikge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9wYXJzZUV4cHJlc3Npb24oZXhwcmVzc2lvbik7XG4gIH1cbn07XG5cbi8vIERlZmluZSBkZWZhdWx0IHZhcmlhYmxlcy5cbnBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uLmRlZmluZVZhcmlhYmxlKCdtb2JpbGVPUycsIHBsYXRmb3JtLmdldE1vYmlsZU9TKCkpO1xucGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZGVmaW5lVmFyaWFibGUoJ2lPU0RldmljZScsIHBsYXRmb3JtLmdldElPU0RldmljZSgpKTtcbnBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uLmRlZmluZVZhcmlhYmxlKCdydW50aW1lJywgKCkgPT4ge1xuICByZXR1cm4gcGxhdGZvcm0uaXNXZWJWaWV3KCkgPyAnY29yZG92YScgOiAnYnJvd3Nlcic7XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb247XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vcGxhdGZvcm0nO1xuaW1wb3J0IHBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIGZyb20gJy4uL3BhZ2UtYXR0cmlidXRlLWV4cHJlc3Npb24nO1xuXG5jb25zdCBpbnRlcm5hbCA9IHt9O1xuXG5pbnRlcm5hbC5jb25maWcgPSB7XG4gIGF1dG9TdGF0dXNCYXJGaWxsOiB0cnVlLFxuICBhbmltYXRpb25zRGlzYWJsZWQ6IGZhbHNlXG59O1xuXG5pbnRlcm5hbC5udWxsRWxlbWVudCA9IHdpbmRvdy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuLyoqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5pbnRlcm5hbC5pc0VuYWJsZWRBdXRvU3RhdHVzQmFyRmlsbCA9ICgpID0+IHtcbiAgcmV0dXJuICEhaW50ZXJuYWwuY29uZmlnLmF1dG9TdGF0dXNCYXJGaWxsO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5pbnRlcm5hbC5ub3JtYWxpemVQYWdlSFRNTCA9IGh0bWwgPT4ge1xuICBodG1sID0gKCcnICsgaHRtbCkudHJpbSgpO1xuXG4gIGlmICghaHRtbC5tYXRjaCgvXjxvbnMtcGFnZS8pKSB7XG4gICAgaHRtbCA9ICc8b25zLXBhZ2UgX211dGVkPicgKyBodG1sICsgJzwvb25zLXBhZ2U+JztcbiAgfVxuXG4gIHJldHVybiBodG1sO1xufTtcblxuaW50ZXJuYWwud2FpdERPTUNvbnRlbnRMb2FkZWQgPSBjYWxsYmFjayA9PiB7XG4gIGlmICh3aW5kb3cuZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnIHx8IHdpbmRvdy5kb2N1bWVudC5yZWFkeVN0YXRlID09ICd1bmluaXRpYWxpemVkJykge1xuICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgY2FsbGJhY2spO1xuICB9IGVsc2Uge1xuICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4gIH1cbn07XG5cbmludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsID0gYWN0aW9uID0+IHtcbiAgY29uc3Qgb25SZWFkeSA9ICgpID0+IHtcbiAgICBpZiAoaW50ZXJuYWwuc2hvdWxkRmlsbFN0YXR1c0JhcigpKSB7XG4gICAgICBhY3Rpb24oKTtcbiAgICB9XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCBvblJlYWR5KTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgb25SZWFkeSk7XG4gIH07XG5cbiAgaWYgKHR5cGVvZiBkZXZpY2UgPT09ICdvYmplY3QnKSB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCBvblJlYWR5KTtcbiAgfSBlbHNlIGlmIChbJ2NvbXBsZXRlJywgJ2ludGVyYWN0aXZlJ10uaW5kZXhPZihkb2N1bWVudC5yZWFkeVN0YXRlKSA9PT0gLTEpIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG4gICAgICBvblJlYWR5KCk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgb25SZWFkeSgpO1xuICB9XG59O1xuXG5pbnRlcm5hbC5zaG91bGRGaWxsU3RhdHVzQmFyID0gKCkgPT4gaW50ZXJuYWwuaXNFbmFibGVkQXV0b1N0YXR1c0JhckZpbGwoKSAmJiBwbGF0Zm9ybS5pc1dlYlZpZXcoKSAmJiBwbGF0Zm9ybS5pc0lPUzdhYm92ZSgpO1xuXG5pbnRlcm5hbC50ZW1wbGF0ZVN0b3JlID0ge1xuICBfc3RvcmFnZToge30sXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nL251bGx9IHRlbXBsYXRlXG4gICAqL1xuICBnZXQoa2V5KSB7XG4gICAgcmV0dXJuIGludGVybmFsLnRlbXBsYXRlU3RvcmUuX3N0b3JhZ2Vba2V5XSB8fCBudWxsO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZW1wbGF0ZVxuICAgKi9cbiAgc2V0KGtleSwgdGVtcGxhdGUpIHtcbiAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLl9zdG9yYWdlW2tleV0gPSB0ZW1wbGF0ZTtcbiAgfVxufTtcblxud2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ190ZW1wbGF0ZWxvYWRlZCcsIGZ1bmN0aW9uKGUpIHtcbiAgaWYgKGUudGFyZ2V0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtdGVtcGxhdGUnKSB7XG4gICAgaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5zZXQoZS50ZW1wbGF0ZUlkLCBlLnRlbXBsYXRlKTtcbiAgfVxufSwgZmFsc2UpO1xuXG53aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xuICByZWdpc3Rlcignc2NyaXB0W3R5cGU9XCJ0ZXh0L29ucy10ZW1wbGF0ZVwiXScpO1xuICByZWdpc3Rlcignc2NyaXB0W3R5cGU9XCJ0ZXh0L3RlbXBsYXRlXCJdJyk7XG4gIHJlZ2lzdGVyKCdzY3JpcHRbdHlwZT1cInRleHQvbmctdGVtcGxhdGVcIl0nKTtcblxuICBmdW5jdGlvbiByZWdpc3RlcihxdWVyeSkge1xuICAgIGNvbnN0IHRlbXBsYXRlcyA9IHdpbmRvdy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRlbXBsYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5zZXQodGVtcGxhdGVzW2ldLmdldEF0dHJpYnV0ZSgnaWQnKSwgdGVtcGxhdGVzW2ldLnRleHRDb250ZW50KTtcbiAgICB9XG4gIH1cbn0sIGZhbHNlKTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogQHJldHVybiB7UHJvbWlzZX1cbiAqL1xuaW50ZXJuYWwuZ2V0VGVtcGxhdGVIVE1MQXN5bmMgPSBmdW5jdGlvbihwYWdlKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgIGNvbnN0IGNhY2hlID0gaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5nZXQocGFnZSk7XG5cbiAgICAgIGlmIChjYWNoZSkge1xuICAgICAgICBjb25zdCBodG1sID0gdHlwZW9mIGNhY2hlID09PSAnc3RyaW5nJyA/IGNhY2hlIDogY2FjaGVbMV07XG4gICAgICAgIHJlc29sdmUoaHRtbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgeGhyLm9wZW4oJ0dFVCcsIHBhZ2UsIHRydWUpO1xuICAgICAgICB4aHIub25sb2FkID0gZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICBjb25zdCBodG1sID0geGhyLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSA0MDAgJiYgeGhyLnN0YXR1cyA8IDYwMCkge1xuICAgICAgICAgICAgcmVqZWN0KGh0bWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUoaHRtbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlIHBhZ2UgaXMgbm90IGZvdW5kOiAke3BhZ2V9YCk7XG4gICAgICAgIH07XG4gICAgICAgIHhoci5zZW5kKG51bGwpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbmludGVybmFsLmdldFBhZ2VIVE1MQXN5bmMgPSBmdW5jdGlvbihwYWdlKSB7XG4gIGNvbnN0IHBhZ2VzID0gcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZXZhbHVhdGUocGFnZSk7XG5cbiAgY29uc3QgZ2V0UGFnZSA9IChwYWdlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBwYWdlICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdNdXN0IHNwZWNpZnkgYSBwYWdlLicpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnRlcm5hbC5nZXRUZW1wbGF0ZUhUTUxBc3luYyhwYWdlKVxuICAgICAgLnRoZW4oXG4gICAgICAgIGZ1bmN0aW9uKGh0bWwpIHtcbiAgICAgICAgICByZXR1cm4gaW50ZXJuYWwubm9ybWFsaXplUGFnZUhUTUwoaHRtbCk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgICAgaWYgKHBhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZ2V0UGFnZShwYWdlcy5zaGlmdCgpKTtcbiAgICAgICAgfVxuICAgICAgKVxuICAgICAgLnRoZW4oaHRtbCA9PiBpbnRlcm5hbC5ub3JtYWxpemVQYWdlSFRNTChodG1sKSk7XG4gIH07XG5cbiAgcmV0dXJuIGdldFBhZ2UocGFnZXMuc2hpZnQoKSk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBpbnRlcm5hbDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL2ludGVybmFsJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQW5pbWF0b3JGYWN0b3J5IHtcblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHNcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMuYW5pbWF0b3JzIFRoZSBkaWN0aW9uYXJ5IGZvciBhbmltYXRvciBjbGFzc2VzXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdHMuYmFzZUNsYXNzIFRoZSBiYXNlIGNsYXNzIG9mIGFuaW1hdG9yc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdHMuYmFzZUNsYXNzTmFtZV0gVGhlIG5hbWUgb2YgdGhlIGJhc2UgY2xhc3Mgb2YgYW5pbWF0b3JzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0cy5kZWZhdWx0QW5pbWF0aW9uXSBUaGUgZGVmYXVsdCBhbmltYXRpb24gbmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdHMuZGVmYXVsdEFuaW1hdGlvbk9wdGlvbnNdIFRoZSBkZWZhdWx0IGFuaW1hdGlvbiBvcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRzKSB7XG4gICAgdGhpcy5fYW5pbWF0b3JzID0gb3B0cy5hbmltYXRvcnM7XG4gICAgdGhpcy5fYmFzZUNsYXNzID0gb3B0cy5iYXNlQ2xhc3M7XG4gICAgdGhpcy5fYmFzZUNsYXNzTmFtZSA9IG9wdHMuYmFzZUNsYXNzTmFtZSB8fCBvcHRzLmJhc2VDbGFzcy5uYW1lO1xuICAgIHRoaXMuX2FuaW1hdGlvbiA9IG9wdHMuZGVmYXVsdEFuaW1hdGlvbiB8fCAnZGVmYXVsdCc7XG4gICAgdGhpcy5fYW5pbWF0aW9uT3B0aW9ucyA9IG9wdHMuZGVmYXVsdEFuaW1hdGlvbk9wdGlvbnMgfHwge307XG5cbiAgICBpZiAoIXRoaXMuX2FuaW1hdG9yc1t0aGlzLl9hbmltYXRpb25dKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHN1Y2ggYW5pbWF0aW9uOiAnICsgdGhpcy5fYW5pbWF0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGpzb25TdHJpbmdcbiAgICogQHJldHVybiB7T2JqZWN0L251bGx9XG4gICAqL1xuICBzdGF0aWMgcGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKGpzb25TdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBqc29uU3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB1dGlsLmFuaW1hdGlvbk9wdGlvbnNQYXJzZShqc29uU3RyaW5nKTtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnICYmIHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignXCJhbmltYXRpb24tb3B0aW9uc1wiIGF0dHJpYnV0ZSBtdXN0IGJlIGEgSlNPTiBvYmplY3Qgc3RyaW5nOiAnICsganNvblN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7fTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcImFuaW1hdGlvbi1vcHRpb25zXCIgYXR0cmlidXRlIG11c3QgYmUgYSBKU09OIG9iamVjdCBzdHJpbmc6ICcgKyBqc29uU3RyaW5nKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICovXG4gIHNldEFuaW1hdGlvbk9wdGlvbnMob3B0aW9ucykge1xuICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dIFRoZSBhbmltYXRpb24gbmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc10gVGhlIGFuaW1hdGlvbiBvcHRpb25zXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0QW5pbWF0b3IgVGhlIGRlZmF1bHQgYW5pbWF0b3IgaW5zdGFuY2VcbiAgICogQHJldHVybiB7T2JqZWN0fSBBbiBhbmltYXRvciBpbnN0YW5jZVxuICAgKi9cbiAgbmV3QW5pbWF0b3Iob3B0aW9ucyA9IHt9LCBkZWZhdWx0QW5pbWF0b3IpIHtcblxuICAgIGxldCBhbmltYXRvciA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5hbmltYXRpb24gaW5zdGFuY2VvZiB0aGlzLl9iYXNlQ2xhc3MpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmFuaW1hdGlvbjtcbiAgICB9XG5cbiAgICBsZXQgQW5pbWF0b3IgPSBudWxsO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmFuaW1hdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIEFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JzW29wdGlvbnMuYW5pbWF0aW9uXTtcbiAgICB9XG5cbiAgICBpZiAoIUFuaW1hdG9yICYmIGRlZmF1bHRBbmltYXRvcikge1xuICAgICAgYW5pbWF0b3IgPSBkZWZhdWx0QW5pbWF0b3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIEFuaW1hdG9yID0gQW5pbWF0b3IgfHwgdGhpcy5fYW5pbWF0b3JzW3RoaXMuX2FuaW1hdGlvbl07XG5cbiAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAge30sXG4gICAgICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgICAgaW50ZXJuYWwuY29uZmlnLmFuaW1hdGlvbnNEaXNhYmxlZCA/IHtkdXJhdGlvbjogMCwgZGVsYXk6IDB9IDoge31cbiAgICAgICk7XG5cbiAgICAgIGFuaW1hdG9yID0gbmV3IEFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpO1xuXG4gICAgICBpZiAodHlwZW9mIGFuaW1hdG9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGFuaW1hdG9yID0gbmV3IGFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIShhbmltYXRvciBpbnN0YW5jZW9mIHRoaXMuX2Jhc2VDbGFzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJhbmltYXRvclwiIGlzIG5vdCBhbiBpbnN0YW5jZSBvZiAnICsgdGhpcy5fYmFzZUNsYXNzTmFtZSArICcuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuaW1hdG9yO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNb2RpZmllclV0aWwge1xuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGxhc3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IGN1cnJlbnRcbiAgICovXG4gIHN0YXRpYyBkaWZmKGxhc3QsIGN1cnJlbnQpIHtcbiAgICBsYXN0ID0gbWFrZURpY3QoKCcnICsgbGFzdCkudHJpbSgpKTtcbiAgICBjdXJyZW50ID0gbWFrZURpY3QoKCcnICsgY3VycmVudCkudHJpbSgpKTtcblxuICAgIGNvbnN0IHJlbW92ZWQgPSBPYmplY3Qua2V5cyhsYXN0KS5yZWR1Y2UoKHJlc3VsdCwgdG9rZW4pID0+IHtcbiAgICAgIGlmICghY3VycmVudFt0b2tlbl0pIHtcbiAgICAgICAgcmVzdWx0LnB1c2godG9rZW4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCBbXSk7XG5cbiAgICBjb25zdCBhZGRlZCA9IE9iamVjdC5rZXlzKGN1cnJlbnQpLnJlZHVjZSgocmVzdWx0LCB0b2tlbikgPT4ge1xuICAgICAgaWYgKCFsYXN0W3Rva2VuXSkge1xuICAgICAgICByZXN1bHQucHVzaCh0b2tlbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIFtdKTtcblxuICAgIHJldHVybiB7YWRkZWQsIHJlbW92ZWR9O1xuXG4gICAgZnVuY3Rpb24gbWFrZURpY3QobW9kaWZpZXIpIHtcbiAgICAgIGNvbnN0IGRpY3QgPSB7fTtcbiAgICAgIE1vZGlmaWVyVXRpbC5zcGxpdChtb2RpZmllcikuZm9yRWFjaCh0b2tlbiA9PiBkaWN0W3Rva2VuXSA9IHRva2VuKTtcbiAgICAgIHJldHVybiBkaWN0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlmZlxuICAgKiBAcGFyYW0ge09iamVjdH0gY2xhc3NMaXN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZW1wbGF0ZVxuICAgKi9cbiAgc3RhdGljIGFwcGx5RGlmZlRvQ2xhc3NMaXN0KGRpZmYsIGNsYXNzTGlzdCwgdGVtcGxhdGUpIHtcbiAgICBkaWZmLmFkZGVkXG4gICAgICAubWFwKG1vZGlmaWVyID0+IHRlbXBsYXRlLnJlcGxhY2UoL1xcKi9nLCBtb2RpZmllcikpXG4gICAgICAuZm9yRWFjaChrbGFzcyA9PiBjbGFzc0xpc3QuYWRkKGtsYXNzKSk7XG5cbiAgICBkaWZmLnJlbW92ZWRcbiAgICAgIC5tYXAobW9kaWZpZXIgPT4gdGVtcGxhdGUucmVwbGFjZSgvXFwqL2csIG1vZGlmaWVyKSlcbiAgICAgIC5mb3JFYWNoKGtsYXNzID0+IGNsYXNzTGlzdC5yZW1vdmUoa2xhc3MpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlmZlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzY2hlbWVcbiAgICovXG4gIHN0YXRpYyBhcHBseURpZmZUb0VsZW1lbnQoZGlmZiwgZWxlbWVudCwgc2NoZW1lKSB7XG4gICAgY29uc3QgbWF0Y2hlcyA9IChlLCBzKSA9PiAoZS5tYXRjaGVzIHx8IGUud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8IGUubW96TWF0Y2hlc1NlbGVjdG9yIHx8IGUubXNNYXRjaGVzU2VsZWN0b3IpLmNhbGwoZSwgcyk7XG4gICAgZm9yIChjb25zdCBzZWxlY3RvciBpbiBzY2hlbWUpIHtcbiAgICAgIGlmIChzY2hlbWUuaGFzT3duUHJvcGVydHkoc2VsZWN0b3IpKSB7XG4gICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnRzID0gIXNlbGVjdG9yIHx8IG1hdGNoZXMoZWxlbWVudCwgc2VsZWN0b3IpID8gW2VsZW1lbnRdIDogZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXRFbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIE1vZGlmaWVyVXRpbC5hcHBseURpZmZUb0NsYXNzTGlzdChkaWZmLCB0YXJnZXRFbGVtZW50c1tpXS5jbGFzc0xpc3QsIHNjaGVtZVtzZWxlY3Rvcl0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBsYXN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjdXJyZW50XG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtPYmplY3R9IHNjaGVtZVxuICAgKi9cbiAgc3RhdGljIG9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIGVsZW1lbnQsIHNjaGVtZSkge1xuICAgIHJldHVybiBNb2RpZmllclV0aWwuYXBwbHlEaWZmVG9FbGVtZW50KE1vZGlmaWVyVXRpbC5kaWZmKGxhc3QsIGN1cnJlbnQpLCBlbGVtZW50LCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtPYmplY3R9IHNjaGVtZVxuICAgKi9cbiAgc3RhdGljIGluaXRNb2RpZmllcihlbGVtZW50LCBzY2hlbWUpIHtcbiAgICBjb25zdCBtb2RpZmllciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpO1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudCh7XG4gICAgICByZW1vdmVkOiBbXSxcbiAgICAgIGFkZGVkOiBNb2RpZmllclV0aWwuc3BsaXQobW9kaWZpZXIpXG4gICAgfSwgZWxlbWVudCwgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBzcGxpdChtb2RpZmllcikge1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGlmaWVyLnRyaW0oKS5zcGxpdCgvICsvKS5maWx0ZXIodG9rZW4gPT4gdG9rZW4gIT09ICcnKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vdXRpbCc7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vcGxhdGZvcm0nO1xuXG5leHBvcnQgY2xhc3MgTGF6eVJlcGVhdERlbGVnYXRlIHtcblxuICBjb25zdHJ1Y3Rvcih1c2VyRGVsZWdhdGUsIHRlbXBsYXRlRWxlbWVudCA9IG51bGwpIHtcbiAgICBpZiAodHlwZW9mIHVzZXJEZWxlZ2F0ZSAhPT0gJ29iamVjdCcgfHwgdXNlckRlbGVnYXRlID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBFcnJvcignXCJkZWxlZ2F0ZVwiIHBhcmFtZXRlciBtdXN0IGJlIGFuIG9iamVjdC4nKTtcbiAgICB9XG4gICAgdGhpcy5fdXNlckRlbGVnYXRlID0gdXNlckRlbGVnYXRlO1xuXG4gICAgaWYgKCEodGVtcGxhdGVFbGVtZW50IGluc3RhbmNlb2YgRWxlbWVudCkgJiYgdGVtcGxhdGVFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICB0aHJvdyBFcnJvcignXCJ0ZW1wbGF0ZUVsZW1lbnRcIiBwYXJhbWV0ZXIgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBFbGVtZW50IG9yIG51bGwuJyk7XG4gICAgfVxuICAgIHRoaXMuX3RlbXBsYXRlRWxlbWVudCA9IHRlbXBsYXRlRWxlbWVudDtcbiAgfVxuXG4gIGdldCBpdGVtSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLl91c2VyRGVsZWdhdGUuaXRlbUhlaWdodDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaGFzUmVuZGVyRnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3VzZXJEZWxlZ2F0ZS5fcmVuZGVyIGluc3RhbmNlb2YgRnVuY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIF9yZW5kZXIoaXRlbXMsIGhlaWdodCkge1xuICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS5fcmVuZGVyKGl0ZW1zLCBoZWlnaHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHBhcmVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lIEEgZnVuY3Rpb24gdGhhdCB0YWtlIGl0ZW0gb2JqZWN0IGFzIHBhcmFtZXRlci5cbiAgICovXG4gIGxvYWRJdGVtRWxlbWVudChpbmRleCwgcGFyZW50LCBkb25lKSB7XG4gICAgaWYgKHRoaXMuX3VzZXJEZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5fdXNlckRlbGVnYXRlLmxvYWRJdGVtRWxlbWVudChpbmRleCwgcGFyZW50LCBlbGVtZW50ID0+IGRvbmUoe2VsZW1lbnR9KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl91c2VyRGVsZWdhdGUuY3JlYXRlSXRlbUNvbnRlbnQoaW5kZXgsIHRoaXMuX3RlbXBsYXRlRWxlbWVudCk7XG4gICAgICBpZiAoIShlbGVtZW50IGluc3RhbmNlb2YgRWxlbWVudCkpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ2NyZWF0ZUl0ZW1Db250ZW50KCkgbXVzdCByZXR1cm4gYW4gaW5zdGFuY2Ugb2YgRWxlbWVudC4nKTtcbiAgICAgIH1cbiAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgIGRvbmUoe2VsZW1lbnR9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKi9cbiAgY291bnRJdGVtcygpIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX3VzZXJEZWxlZ2F0ZS5jb3VudEl0ZW1zKCk7XG4gICAgaWYgKHR5cGVvZiBjb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgIHRocm93IEVycm9yKCdjb3VudEl0ZW1zKCkgbXVzdCByZXR1cm4gYSBudW1iZXIuJyk7XG4gICAgfVxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICogQHBhcmFtIHtFbGVtZW50fSBpdGVtLmVsZW1lbnRcbiAgICovXG4gIHVwZGF0ZUl0ZW0oaW5kZXgsIGl0ZW0pIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLnVwZGF0ZUl0ZW1Db250ZW50IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS51cGRhdGVJdGVtQ29udGVudChpbmRleCwgaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICovXG4gIGNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpO1xuXG4gICAgICBpZiAodHlwZW9mIGhlaWdodCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ2NhbGN1bGF0ZUl0ZW1IZWlnaHQoKSBtdXN0IHJldHVybiBhIG51bWJlci4nKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGhlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICovXG4gIGRlc3Ryb3lJdGVtKGluZGV4LCBpdGVtKSB7XG4gICAgaWYgKHRoaXMuX3VzZXJEZWxlZ2F0ZS5kZXN0cm95SXRlbSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLl91c2VyRGVsZWdhdGUuZGVzdHJveUl0ZW0oaW5kZXgsIGl0ZW0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3kgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl91c2VyRGVsZWdhdGUgPSB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQgPSBudWxsO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBjbGFzcyBwcm92aWRlIGNvcmUgZnVuY3Rpb25zIGZvciBvbnMtbGF6eS1yZXBlYXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYXp5UmVwZWF0UHJvdmlkZXIge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHdyYXBwZXJFbGVtZW50XG4gICAqIEBwYXJhbSB7TGF6eVJlcGVhdERlbGVnYXRlfSBkZWxlZ2F0ZVxuICAgKi9cbiAgY29uc3RydWN0b3Iod3JhcHBlckVsZW1lbnQsIGRlbGVnYXRlKSB7XG4gICAgaWYgKCEoZGVsZWdhdGUgaW5zdGFuY2VvZiBMYXp5UmVwZWF0RGVsZWdhdGUpKSB7XG4gICAgICB0aHJvdyBFcnJvcignXCJkZWxlZ2F0ZVwiIHBhcmFtZXRlciBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIExhenlSZXBlYXREZWxlZ2F0ZS4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl93cmFwcGVyRWxlbWVudCA9IHdyYXBwZXJFbGVtZW50O1xuICAgIHRoaXMuX2RlbGVnYXRlID0gZGVsZWdhdGU7XG5cbiAgICBpZiAod3JhcHBlckVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnb25zLWxpc3QnKSB7XG4gICAgICB3cmFwcGVyRWxlbWVudC5jbGFzc0xpc3QuYWRkKCdsYXp5LWxpc3QnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9wYWdlQ29udGVudCA9IHRoaXMuX2ZpbmRQYWdlQ29udGVudEVsZW1lbnQod3JhcHBlckVsZW1lbnQpO1xuXG4gICAgaWYgKCF0aGlzLl9wYWdlQ29udGVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbnMtbGF6eS1yZXBlYXQgbXVzdCBiZSBhIGRlc2NlbmRhbnQgb2YgYW4gPG9ucy1wYWdlPiBvciBhbiBlbGVtZW50LicpO1xuICAgIH1cblxuICAgIHRoaXMuX3RvcFBvc2l0aW9ucyA9IFtdO1xuICAgIHRoaXMuX3JlbmRlcmVkSXRlbXMgPSB7fTtcblxuICAgIGlmICghdGhpcy5fZGVsZWdhdGUuaXRlbUhlaWdodCAmJiAhdGhpcy5fZGVsZWdhdGUuY2FsY3VsYXRlSXRlbUhlaWdodCgwKSkge1xuICAgICAgdGhpcy5fdW5rbm93bkl0ZW1IZWlnaHQgPSB0cnVlO1xuICAgIH1cbiAgICB0aGlzLl9hZGRFdmVudExpc3RlbmVycygpO1xuICAgIHRoaXMuX29uQ2hhbmdlKCk7XG4gIH1cblxuICBfZmluZFBhZ2VDb250ZW50RWxlbWVudCh3cmFwcGVyRWxlbWVudCkge1xuICAgIGNvbnN0IHBhZ2VDb250ZW50ID0gdXRpbC5maW5kUGFyZW50KHdyYXBwZXJFbGVtZW50LCAnLnBhZ2VfX2NvbnRlbnQnKTtcblxuICAgIGlmIChwYWdlQ29udGVudCkge1xuICAgICAgcmV0dXJuIHBhZ2VDb250ZW50O1xuICAgIH1cblxuICAgIGNvbnN0IHBhZ2UgPSB1dGlsLmZpbmRQYXJlbnQod3JhcHBlckVsZW1lbnQsICdvbnMtcGFnZScpO1xuICAgIGlmIChwYWdlKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gdXRpbC5maW5kQ2hpbGQocGFnZSwgJy5jb250ZW50Jyk7XG4gICAgICBpZiAoY29udGVudCkge1xuICAgICAgICByZXR1cm4gY29udGVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIF9jaGVja0l0ZW1IZWlnaHQoY2FsbGJhY2spIHtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoMCwgdGhpcy5fd3JhcHBlckVsZW1lbnQsIGl0ZW0gPT4ge1xuICAgICAgaWYgKCF0aGlzLl91bmtub3duSXRlbUhlaWdodCkge1xuICAgICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBzdGF0ZScpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkb25lID0gKCkgPT4ge1xuICAgICAgICB0aGlzLl93cmFwcGVyRWxlbWVudC5yZW1vdmVDaGlsZChpdGVtLmVsZW1lbnQpO1xuICAgICAgICBkZWxldGUgdGhpcy5fdW5rbm93bkl0ZW1IZWlnaHQ7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9pdGVtSGVpZ2h0ID0gaXRlbS5lbGVtZW50Lm9mZnNldEhlaWdodDtcblxuICAgICAgaWYgKHRoaXMuX2l0ZW1IZWlnaHQgPiAwKSB7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyByZXRyeSB0byBtZWFzdXJlIG9mZnNldCBoZWlnaHRcbiAgICAgIC8vIGRpcnR5IGZpeCBmb3IgYW5ndWxhcjIgZGlyZWN0aXZlXG4gICAgICBjb25zdCBsYXN0VmlzaWJpbGl0eSA9IHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnZpc2liaWxpdHk7XG4gICAgICB0aGlzLl93cmFwcGVyRWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgICBpdGVtLmVsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuXG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9pdGVtSGVpZ2h0ID0gaXRlbS5lbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgICAgaWYgKHRoaXMuX2l0ZW1IZWlnaHQgPT0gMCkge1xuICAgICAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIHN0YXRlOiB0aGlzLl9pdGVtSGVpZ2h0IG11c3QgYmUgZ3JlYXRlciB0aGFuIHplcm8uJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9IGxhc3RWaXNpYmlsaXR5O1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBzdGF0aWNJdGVtSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLl9kZWxlZ2F0ZS5pdGVtSGVpZ2h0IHx8IHRoaXMuX2l0ZW1IZWlnaHQ7XG4gIH1cblxuICBfY291bnRJdGVtcygpIHtcbiAgICByZXR1cm4gdGhpcy5fZGVsZWdhdGUuY291bnRJdGVtcygpO1xuICB9XG5cbiAgX2dldEl0ZW1IZWlnaHQoaSkge1xuICAgIHJldHVybiB0aGlzLnN0YXRpY0l0ZW1IZWlnaHQgfHwgdGhpcy5fZGVsZWdhdGUuY2FsY3VsYXRlSXRlbUhlaWdodChpKTtcbiAgfVxuXG4gIF9vbkNoYW5nZSgpIHtcbiAgICB0aGlzLl9yZW5kZXIoKTtcbiAgfVxuXG4gIHJlZnJlc2goKSB7XG4gICAgdGhpcy5fcmVtb3ZlQWxsRWxlbWVudHMoKTtcbiAgICB0aGlzLl9vbkNoYW5nZSgpO1xuICB9XG5cbiAgX3JlbmRlcigpIHtcbiAgICBpZiAodGhpcy5fdW5rbm93bkl0ZW1IZWlnaHQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jaGVja0l0ZW1IZWlnaHQodGhpcy5fcmVuZGVyLmJpbmQodGhpcykpO1xuICAgIH1cblxuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5fZ2V0SXRlbXNJblZpZXcoKTtcblxuICAgIGlmICh0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbiAmJiB0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbigpKSB7XG4gICAgICB0aGlzLl9kZWxlZ2F0ZS5fcmVuZGVyKGl0ZW1zLCB0aGlzLl9saXN0SGVpZ2h0KTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGtlZXAgPSB7fTtcblxuICAgIGl0ZW1zLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICB0aGlzLl9yZW5kZXJFbGVtZW50KGl0ZW0pO1xuICAgICAga2VlcFtpdGVtLmluZGV4XSA9IHRydWU7XG4gICAgfSk7XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLl9yZW5kZXJlZEl0ZW1zKS5mb3JFYWNoKGtleSA9PiBrZWVwW2tleV0gfHwgdGhpcy5fcmVtb3ZlRWxlbWVudChrZXkpKTtcblxuICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLmhlaWdodCA9IHRoaXMuX2xpc3RIZWlnaHQgKyAncHgnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVtXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpdGVtLmluZGV4XG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpdGVtLnRvcFxuICAgKi9cbiAgX3JlbmRlckVsZW1lbnQoe2luZGV4LCB0b3B9KSB7XG4gICAgY29uc3QgaXRlbSA9IHRoaXMuX3JlbmRlcmVkSXRlbXNbaW5kZXhdO1xuICAgIGlmIChpdGVtKSB7XG4gICAgICB0aGlzLl9kZWxlZ2F0ZS51cGRhdGVJdGVtKGluZGV4LCBpdGVtKTsgLy8gdXBkYXRlIGlmIGl0IGV4aXN0c1xuICAgICAgaXRlbS5lbGVtZW50LnN0eWxlLnRvcCA9IHRvcCArICdweCc7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fZGVsZWdhdGUubG9hZEl0ZW1FbGVtZW50KGluZGV4LCB0aGlzLl93cmFwcGVyRWxlbWVudCwgaXRlbSA9PiB7XG4gICAgICB1dGlsLmV4dGVuZChpdGVtLmVsZW1lbnQuc3R5bGUsIHtcbiAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgIHRvcDogdG9wICsgJ3B4JyxcbiAgICAgICAgbGVmdDogMCxcbiAgICAgICAgcmlnaHQ6IDBcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XSA9IGl0ZW07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqL1xuICBfcmVtb3ZlRWxlbWVudChpbmRleCkge1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XTtcblxuICAgIHRoaXMuX2RlbGVnYXRlLmRlc3Ryb3lJdGVtKGluZGV4LCBpdGVtKTtcblxuICAgIGlmIChpdGVtLmVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgaXRlbS5lbGVtZW50LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoaXRlbS5lbGVtZW50KTtcbiAgICB9XG5cbiAgICBkZWxldGUgdGhpcy5fcmVuZGVyZWRJdGVtc1tpbmRleF07XG4gIH1cblxuICBfcmVtb3ZlQWxsRWxlbWVudHMoKSB7XG4gICAgT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykuZm9yRWFjaChrZXkgPT4gdGhpcy5fcmVtb3ZlRWxlbWVudChrZXkpKTtcbiAgfVxuXG4gIF9jYWxjdWxhdGVTdGFydEluZGV4KGN1cnJlbnQpIHtcbiAgICBsZXQgc3RhcnQgPSAwO1xuICAgIGxldCBlbmQgPSB0aGlzLl9pdGVtQ291bnQgLSAxO1xuXG4gICAgaWYgKHRoaXMuc3RhdGljSXRlbUhlaWdodCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KC1jdXJyZW50IC8gdGhpcy5zdGF0aWNJdGVtSGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBpbmRleCBhdCB0b3Agb2Ygc2NyZWVuIHNvIHdlIGNhbiBzcGVlZCB1cCByZW5kZXJpbmcuXG4gICAgZm9yICg7Oykge1xuICAgICAgY29uc3QgbWlkZGxlID0gTWF0aC5mbG9vcigoc3RhcnQgKyBlbmQpIC8gMik7XG4gICAgICBjb25zdCB2YWx1ZSA9IGN1cnJlbnQgKyB0aGlzLl90b3BQb3NpdGlvbnNbbWlkZGxlXTtcblxuICAgICAgaWYgKGVuZCA8IHN0YXJ0KSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAwICYmIHZhbHVlICsgdGhpcy5fZ2V0SXRlbUhlaWdodChtaWRkbGUpID4gMCkge1xuICAgICAgICByZXR1cm4gbWlkZGxlO1xuICAgICAgfSBlbHNlIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPj0gMCkge1xuICAgICAgICBlbmQgPSBtaWRkbGUgLSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhcnQgPSBtaWRkbGUgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9yZWNhbGN1bGF0ZVRvcFBvc2l0aW9ucygpIHtcbiAgICBjb25zdCBsID0gTWF0aC5taW4odGhpcy5fdG9wUG9zaXRpb25zLmxlbmd0aCwgdGhpcy5faXRlbUNvdW50KTtcbiAgICB0aGlzLl90b3BQb3NpdGlvbnNbMF0gPSAwO1xuICAgIGZvciAobGV0IGkgPSAxLCBsOyBpIDwgbDsgaSsrKSB7XG4gICAgICB0aGlzLl90b3BQb3NpdGlvbnNbaV0gPSB0aGlzLl90b3BQb3NpdGlvbnNbaSAtIDFdICsgdGhpcy5fZ2V0SXRlbUhlaWdodChpKTtcbiAgICB9XG4gIH1cblxuICBfZ2V0SXRlbXNJblZpZXcoKSB7XG4gICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5fd3JhcHBlckVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuICAgIGNvbnN0IGxpbWl0ID0gNCAqIHdpbmRvdy5pbm5lckhlaWdodCAtIG9mZnNldDtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX2NvdW50SXRlbXMoKTtcblxuICAgIGlmIChjb3VudCAhPT0gdGhpcy5faXRlbUNvdW50KXtcbiAgICAgIHRoaXMuX2l0ZW1Db3VudCA9IGNvdW50O1xuICAgICAgdGhpcy5fcmVjYWxjdWxhdGVUb3BQb3NpdGlvbnMoKTtcbiAgICB9XG5cbiAgICBsZXQgaSA9IE1hdGgubWF4KDAsIHRoaXMuX2NhbGN1bGF0ZVN0YXJ0SW5kZXgob2Zmc2V0KSAtIDMwKTtcblxuICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgZm9yICh2YXIgdG9wID0gdGhpcy5fdG9wUG9zaXRpb25zW2ldOyBpIDwgY291bnQgJiYgdG9wIDwgbGltaXQ7IGkrKykge1xuICAgICAgaWYgKGkgPj0gdGhpcy5fdG9wUG9zaXRpb25zLmxlbmd0aCkgeyAvLyBwZXJmIG9wdGltaXphdGlvblxuICAgICAgICB0aGlzLl90b3BQb3NpdGlvbnMubGVuZ3RoICs9IDEwMDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdG9wUG9zaXRpb25zW2ldID0gdG9wO1xuICAgICAgaXRlbXMucHVzaCh7dG9wLCBpbmRleDogaX0pO1xuICAgICAgdG9wICs9IHRoaXMuX2dldEl0ZW1IZWlnaHQoaSk7XG4gICAgfVxuICAgIHRoaXMuX2xpc3RIZWlnaHQgPSB0b3A7XG5cbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cblxuICBfZGVib3VuY2UoZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4gICAgbGV0IHRpbWVvdXQ7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgY29uc3QgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIGlmIChjYWxsTm93KSB7XG4gICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH0sIHdhaXQpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBfZG91YmxlRmlyZU9uVG91Y2hlbmQoKSB7XG4gICAgdGhpcy5fcmVuZGVyKCk7XG4gICAgdGhpcy5fZGVib3VuY2UodGhpcy5fcmVuZGVyLmJpbmQodGhpcyksIDEwMCk7XG4gIH1cblxuICBfYWRkRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdXRpbC5iaW5kTGlzdGVuZXJzKHRoaXMsIFsnX29uQ2hhbmdlJywgJ19kb3VibGVGaXJlT25Ub3VjaGVuZCddKTtcblxuICAgIGlmIChwbGF0Zm9ybS5pc0lPUygpKSB7XG4gICAgICB0aGlzLl9ib3VuZE9uQ2hhbmdlID0gdGhpcy5fZGVib3VuY2UodGhpcy5fYm91bmRPbkNoYW5nZSwgMzApO1xuICAgIH1cblxuICAgIHRoaXMuX3BhZ2VDb250ZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25DaGFuZ2UsIHRydWUpO1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzSU9TKCkpIHtcbiAgICAgIHRoaXMuX3BhZ2VDb250ZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UsIHRydWUpO1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kLCB0cnVlKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gIH1cblxuICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJT1MoKSkge1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gICAgICB0aGlzLl9wYWdlQ29udGVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX2JvdW5kRG91YmxlRmlyZU9uVG91Y2hlbmQsIHRydWUpO1xuICAgIH1cblxuICAgIHdpbmRvdy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLl9ib3VuZE9uQ2hhbmdlLCB0cnVlKTtcbiAgfVxuXG4gIGRlc3Ryb3koKSB7XG4gICAgdGhpcy5fcmVtb3ZlQWxsRWxlbWVudHMoKTtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5kZXN0cm95KCk7XG4gICAgdGhpcy5fcGFyZW50RWxlbWVudCA9IHRoaXMuX2RlbGVnYXRlID0gdGhpcy5fcmVuZGVyZWRJdGVtcyA9IG51bGw7XG4gICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgfVxufVxuXG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4vaW50ZXJuYWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IHtMYXp5UmVwZWF0UHJvdmlkZXIsIExhenlSZXBlYXREZWxlZ2F0ZX0gZnJvbSAnLi9sYXp5LXJlcGVhdCc7XG5cbmludGVybmFsLkFuaW1hdG9yRmFjdG9yeSA9IEFuaW1hdG9yRmFjdG9yeTtcbmludGVybmFsLk1vZGlmaWVyVXRpbCA9IE1vZGlmaWVyVXRpbDtcbmludGVybmFsLkxhenlSZXBlYXRQcm92aWRlciA9IExhenlSZXBlYXRQcm92aWRlcjtcbmludGVybmFsLkxhenlSZXBlYXREZWxlZ2F0ZSA9IExhenlSZXBlYXREZWxlZ2F0ZTtcblxuZXhwb3J0IGRlZmF1bHQgaW50ZXJuYWw7XG5cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmNvbnN0IGNyZWF0ZSA9ICgpID0+IHtcblxuICAvKipcbiAgICogQG9iamVjdCBvbnMub3JpZW50YXRpb25cbiAgICogQGNhdGVnb3J5IHV0aWxcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVV0aWxpdHkgbWV0aG9kcyBmb3Igb3JpZW50YXRpb24gZGV0ZWN0aW9uLlsvZW5dXG4gICAqICAgW2phXeeUu+mdouOBruOCquODquOCqOODs+ODhuODvOOCt+ODp+ODs+aknOefpeOBruOBn+OCgeOBruODpuODvOODhuOCo+ODquODhuOCo+ODoeOCveODg+ODieOCkuWPjuOCgeOBpuOBhOOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqL1xuICBjb25zdCBvYmogPSB7XG4gICAgLyoqXG4gICAgICogQGV2ZW50IGNoYW5nZVxuICAgICAqIEBkZXNjcmlwdGlvblxuICAgICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGRldmljZSBvcmllbnRhdGlvbiBjaGFuZ2VzLlsvZW5dXG4gICAgICogICBbamFd44OH44OQ44Kk44K544Gu44Kq44Oq44Ko44Oz44OG44O844K344On44Oz44GM5aSJ5YyW44GX44Gf6Zqb44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gZXZlbnQuaXNQb3J0cmFpdFxuICAgICAqICAgW2VuXVdpbGwgYmUgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcmllbnRhdGlvbiBpcyBwb3J0cmFpdCBtb2RlLlsvZW5dXG4gICAgICogICBbamFd54++5Zyo44Gu44Kq44Oq44Ko44Oz44OG44O844K344On44Oz44GMcG9ydHJhaXTjga7loLTlkIjjgat0cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICAgKi9cblxuICAgIC8qKlxuICAgICAqIEBtZXRob2Qgb25cbiAgICAgKiBAc2lnbmF0dXJlIG9uKGV2ZW50TmFtZSwgbGlzdGVuZXIpXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dQWRkIGFuIGV2ZW50IGxpc3RlbmVyLlsvZW5dXG4gICAgICogICBbamFd44Kk44OZ44Oz44OI44Oq44K544OK44O844KS6L+95Yqg44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gICAgICogICBbZW5dTmFtZSBvZiB0aGUgZXZlbnQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyXG4gICAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgZPjga7jgqTjg5njg7Pjg4jjgYznmbrngavjgZXjgozjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBvbmNlXG4gICAgICogQHNpZ25hdHVyZSBvbmNlKGV2ZW50TmFtZSwgbGlzdGVuZXIpXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogIFtlbl1BZGQgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCdzIG9ubHkgdHJpZ2dlcmVkIG9uY2UuWy9lbl1cbiAgICAgKiAgW2phXeS4gOW6puOBoOOBkeWRvOOBs+WHuuOBleOCjOOCi+OCpOODmeODs+ODiOODquOCueODiuODvOOCkui/veWKoOOBl+OBvuOBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqICAgW2VuXU5hbWUgb2YgdGhlIGV2ZW50LlsvZW5dXG4gICAgICogICBbamFd44Kk44OZ44Oz44OI5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lclxuICAgICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLlsvZW5dXG4gICAgICogICBbamFd44Kk44OZ44Oz44OI44GM55m654Gr44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICAgKi9cblxuICAgIC8qKlxuICAgICAqIEBtZXRob2Qgb2ZmXG4gICAgICogQHNpZ25hdHVyZSBvZmYoZXZlbnROYW1lLCBbbGlzdGVuZXJdKVxuICAgICAqIEBkZXNjcmlwdGlvblxuICAgICAqICBbZW5dUmVtb3ZlIGFuIGV2ZW50IGxpc3RlbmVyLiBJZiB0aGUgbGlzdGVuZXIgaXMgbm90IHNwZWNpZmllZCBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgdHlwZSB3aWxsIGJlIHJlbW92ZWQuWy9lbl1cbiAgICAgKiAgW2phXeOCpOODmeODs+ODiOODquOCueODiuODvOOCkuWJiumZpOOBl+OBvuOBmeOAguOCguOBl+OCpOODmeODs+ODiOODquOCueODiuODvOOCkuaMh+WumuOBl+OBquOBi+OBo+OBn+WgtOWQiOOBq+OBr+OAgeOBneOBruOCpOODmeODs+ODiOOBq+e0kOOBpeOBj+WFqOOBpuOBruOCpOODmeODs+ODiOODquOCueODiuODvOOBjOWJiumZpOOBleOCjOOBvuOBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqICAgW2VuXU5hbWUgb2YgdGhlIGV2ZW50LlsvZW5dXG4gICAgICogICBbamFd44Kk44OZ44Oz44OI5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lclxuICAgICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLlsvZW5dXG4gICAgICogICBbamFd5YmK6Zmk44GZ44KL44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICAgKi9cblxuICAgIC8vIGFjdHVhbCBpbXBsZW1lbnRhdGlvbiB0byBkZXRlY3QgaWYgd2hldGhlciBjdXJyZW50IHNjcmVlbiBpcyBwb3J0cmFpdCBvciBub3RcbiAgICBfaXNQb3J0cmFpdDogZmFsc2UsXG5cbiAgICAvKipcbiAgICAgKiBAbWV0aG9kIGlzUG9ydHJhaXRcbiAgICAgKiBAc2lnbmF0dXJlIGlzUG9ydHJhaXQoKVxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBjdXJyZW50IG9yaWVudGF0aW9uIGlzIHBvcnRyYWl0IG1vZGUuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxwb3J0cmFpdOODouODvOODieOBruWgtOWQiOOBq3RydWXjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgICAqIEBkZXNjcmlwdGlvblxuICAgICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgY3VycmVudCBzY3JlZW4gb3JpZW50YXRpb24gaXMgcG9ydHJhaXQgb3Igbm90LlsvZW5dXG4gICAgICogICBbamFd44Kq44Oq44Ko44Oz44OG44O844K344On44Oz44GMcG9ydHJhaXTjg6Ljg7zjg4njgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuICAgIGlzUG9ydHJhaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2lzUG9ydHJhaXQoKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBpc0xhbmRzY2FwZVxuICAgICAqIEBzaWduYXR1cmUgaXNMYW5kc2NhcGUoKVxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBjdXJyZW50IG9yaWVudGF0aW9uIGlzIGxhbmRzY2FwZSBtb2RlLlsvZW5dXG4gICAgICogICBbamFd44Kq44Oq44Ko44Oz44OG44O844K344On44Oz44GMbGFuZHNjYXBl44Oi44O844OJ44Gu5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBjdXJyZW50IHNjcmVlbiBvcmllbnRhdGlvbiBpcyBsYW5kc2NhcGUgb3Igbm90LlsvZW5dXG4gICAgICogICBbamFd44Kq44Oq44Ko44Oz44OG44O844K344On44Oz44GMbGFuZHNjYXBl44Oi44O844OJ44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICAgKi9cbiAgICBpc0xhbmRzY2FwZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gIXRoaXMuaXNQb3J0cmFpdCgpO1xuICAgIH0sXG5cbiAgICBfaW5pdDogZnVuY3Rpb24oKSB7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgdGhpcy5fb25ET01Db250ZW50TG9hZGVkLmJpbmQodGhpcyksIGZhbHNlKTtcblxuICAgICAgaWYgKCdvcmllbnRhdGlvbicgaW4gd2luZG93KSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UuYmluZCh0aGlzKSwgZmFsc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuX29uUmVzaXplLmJpbmQodGhpcyksIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNQb3J0cmFpdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX29uRE9NQ29udGVudExvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLl9pbnN0YWxsSXNQb3J0cmFpdEltcGxlbWVudGF0aW9uKCk7XG4gICAgICB0aGlzLmVtaXQoJ2NoYW5nZScsIHtpc1BvcnRyYWl0OiB0aGlzLmlzUG9ydHJhaXQoKX0pO1xuICAgIH0sXG5cbiAgICBfaW5zdGFsbElzUG9ydHJhaXRJbXBsZW1lbnRhdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBpc1BvcnRyYWl0ID0gd2luZG93LmlubmVyV2lkdGggPCB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAgIGlmICghKCdvcmllbnRhdGlvbicgaW4gd2luZG93KSkge1xuICAgICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHdpbmRvdy5pbm5lckhlaWdodCA+IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmICh3aW5kb3cub3JpZW50YXRpb24gJSAxODAgPT09IDApIHtcbiAgICAgICAgdGhpcy5faXNQb3J0cmFpdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiBNYXRoLmFicyh3aW5kb3cub3JpZW50YXRpb24gJSAxODApID09PSAwID8gaXNQb3J0cmFpdCA6ICFpc1BvcnRyYWl0O1xuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5faXNQb3J0cmFpdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiBNYXRoLmFicyh3aW5kb3cub3JpZW50YXRpb24gJSAxODApID09PSA5MCA/IGlzUG9ydHJhaXQgOiAhaXNQb3J0cmFpdDtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgX29uT3JpZW50YXRpb25DaGFuZ2U6IGZ1bmN0aW9uKCkge1xuICAgICAgY29uc3QgaXNQb3J0cmFpdCA9IHRoaXMuX2lzUG9ydHJhaXQoKTtcblxuICAgICAgLy8gV2FpdCBmb3IgdGhlIGRpbWVuc2lvbnMgdG8gY2hhbmdlIGJlY2F1c2VcbiAgICAgIC8vIG9mIEFuZHJvaWQgaW5jb25zaXN0ZW5jeS5cbiAgICAgIGxldCBuSXRlciA9IDA7XG4gICAgICBjb25zdCBpbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgbkl0ZXIrKztcblxuICAgICAgICBjb25zdCB3ID0gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgIGNvbnN0IGggPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAgICAgaWYgKChpc1BvcnRyYWl0ICYmIHcgPD0gaCkgfHxcbiAgICAgICAgICAgKCFpc1BvcnRyYWl0ICYmIHcgPj0gaCkpIHtcbiAgICAgICAgICB0aGlzLmVtaXQoJ2NoYW5nZScsIHtpc1BvcnRyYWl0OiBpc1BvcnRyYWl0fSk7XG4gICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgIH0gZWxzZSBpZiAobkl0ZXIgPT09IDUwKSB7XG4gICAgICAgICAgdGhpcy5lbWl0KCdjaGFuZ2UnLCB7aXNQb3J0cmFpdDogaXNQb3J0cmFpdH0pO1xuICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICB9LCAyMCk7XG4gICAgfSxcblxuICAgIC8vIFJ1biBvbiBub3QgbW9iaWxlIGJyb3dzZXIuXG4gICAgX29uUmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuZW1pdCgnY2hhbmdlJywge2lzUG9ydHJhaXQ6IHRoaXMuaXNQb3J0cmFpdCgpfSk7XG4gICAgfVxuICB9O1xuXG4gIE1pY3JvRXZlbnQubWl4aW4ob2JqKTtcblxuICByZXR1cm4gb2JqO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgY3JlYXRlKCkuX2luaXQoKTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmNvbnN0IHNvZnR3YXJlS2V5Ym9hcmQgPSBuZXcgTWljcm9FdmVudCgpO1xuc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuXG5jb25zdCBvblNob3cgPSAoKSA9PiB7XG4gIHNvZnR3YXJlS2V5Ym9hcmQuX3Zpc2libGUgPSB0cnVlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ3Nob3cnKTtcbn07XG5cbmNvbnN0IG9uSGlkZSA9ICgpID0+IHtcbiAgc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2hpZGUnKTtcbn07XG5cbmNvbnN0IGJpbmRFdmVudHMgPSAoKSA9PiB7XG4gIGlmICh0eXBlb2YgS2V5Ym9hcmQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21hcnRpbm1vc2UvY29yZG92YS1rZXlib2FyZC9ibG9iLzk1ZjNkYTNhMzhkOGY4ZTFmYTQxZmJmNDAxNDUzNTJjMTM1MzVhMDAvUkVBRE1FLm1kXG4gICAgS2V5Ym9hcmQub25zaG93ID0gb25TaG93O1xuICAgIEtleWJvYXJkLm9uaGlkZSA9IG9uSGlkZTtcbiAgICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2luaXQnLCB7dmlzaWJsZTogS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY29yZG92YS5wbHVnaW5zICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29yZG92YS5wbHVnaW5zLktleWJvYXJkICE9PSAndW5kZWZpbmVkJykge1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kcmlmdHljby9pb25pYy1wbHVnaW5zLWtleWJvYXJkL2Jsb2IvY2EyN2VjZi9SRUFETUUubWRcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbmF0aXZlLmtleWJvYXJkc2hvdycsIG9uU2hvdyk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ25hdGl2ZS5rZXlib2FyZGhpZGUnLCBvbkhpZGUpO1xuICAgIHNvZnR3YXJlS2V5Ym9hcmQuZW1pdCgnaW5pdCcsIHt2aXNpYmxlOiBjb3Jkb3ZhLnBsdWdpbnMuS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbmNvbnN0IG5vUGx1Z2luRXJyb3IgPSAoKSA9PiB7XG4gIGNvbnNvbGUud2Fybignb25zLWtleWJvYXJkOiBDb3Jkb3ZhIEtleWJvYXJkIHBsdWdpbiBpcyBub3QgcHJlc2VudC4nKTtcbn07XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgKCkgPT4ge1xuICBpZiAoIWJpbmRFdmVudHMoKSkge1xuICAgIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbb25zLWtleWJvYXJkLWFjdGl2ZV0nKSB8fFxuICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW29ucy1rZXlib2FyZC1pbmFjdGl2ZV0nKSkge1xuICAgICAgbm9QbHVnaW5FcnJvcigpO1xuICAgIH1cblxuICAgIHNvZnR3YXJlS2V5Ym9hcmQub24gPSBub1BsdWdpbkVycm9yO1xuICB9XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgc29mdHdhcmVLZXlib2FyZDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuL3BsYXRmb3JtJztcblxuXG5jb25zdCB1dGlsID0ge1xuICBfcmVhZHk6IGZhbHNlLFxuXG4gIF9kb21Db250ZW50TG9hZGVkOiBmYWxzZSxcblxuICBfb25ET01Db250ZW50TG9hZGVkOiAoKSA9PiB7XG4gICAgdXRpbC5fZG9tQ29udGVudExvYWRlZCA9IHRydWU7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNXZWJWaWV3KCkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsICgpID0+IHtcbiAgICAgICAgdXRpbC5fcmVhZHkgPSB0cnVlO1xuICAgICAgfSwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLl9yZWFkeSA9IHRydWU7XG4gICAgfVxuICB9LFxuXG4gIGFkZEJhY2tCdXR0b25MaXN0ZW5lcjogZnVuY3Rpb24oZm4pIHtcbiAgICBpZiAoIXRoaXMuX2RvbUNvbnRlbnRMb2FkZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBtZXRob2QgaXMgYXZhaWxhYmxlIGFmdGVyIERPTUNvbnRlbnRMb2FkZWQnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcmVhZHkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICByZW1vdmVCYWNrQnV0dG9uTGlzdGVuZXI6IGZ1bmN0aW9uKGZuKSB7XG4gICAgaWYgKCF0aGlzLl9kb21Db250ZW50TG9hZGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBET01Db250ZW50TG9hZGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWR5KSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn07XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHV0aWwuX29uRE9NQ29udGVudExvYWRlZCgpLCBmYWxzZSk7XG5cbmNvbnN0IEhhbmRsZXJSZXBvc2l0b3J5ID0ge1xuICBfc3RvcmU6IHt9LFxuXG4gIF9nZW5JZDogKCgpID0+IHtcbiAgICBsZXQgaSA9IDA7XG4gICAgcmV0dXJuICgpID0+IGkrKztcbiAgfSkoKSxcblxuICBzZXQ6IGZ1bmN0aW9uKGVsZW1lbnQsIGhhbmRsZXIpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHRoaXMucmVtb3ZlKGVsZW1lbnQpO1xuICAgIH1cbiAgICBjb25zdCBpZCA9IGVsZW1lbnQuZGF0YXNldC5kZXZpY2VCYWNrQnV0dG9uSGFuZGxlcklkID0gSGFuZGxlclJlcG9zaXRvcnkuX2dlbklkKCk7XG4gICAgdGhpcy5fc3RvcmVbaWRdID0gaGFuZGxlcjtcbiAgfSxcblxuICByZW1vdmU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zdG9yZVtlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZF07XG4gICAgICBkZWxldGUgZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQ7XG4gICAgfVxuICB9LFxuXG4gIGdldDogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIGlmICghdGhpcy5fc3RvcmVbaWRdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fc3RvcmVbaWRdO1xuICB9LFxuXG4gIGhhczogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIHJldHVybiAhIXRoaXMuX3N0b3JlW2lkXTtcbiAgfVxufTtcblxuY2xhc3MgRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9pc0VuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9ib3VuZENhbGxiYWNrID0gdGhpcy5fY2FsbGJhY2suYmluZCh0aGlzKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEVuYWJsZSB0byBoYW5kbGUgJ2JhY2tidXR0b24nIGV2ZW50cy5cbiAgICovXG4gIGVuYWJsZSgpIHtcbiAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgdXRpbC5hZGRCYWNrQnV0dG9uTGlzdGVuZXIodGhpcy5fYm91bmRDYWxsYmFjayk7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlIHRvIGhhbmRsZSAnYmFja2J1dHRvbicgZXZlbnRzLlxuICAgKi9cbiAgZGlzYWJsZSgpIHtcbiAgICBpZiAodGhpcy5faXNFbmFibGVkKSB7XG4gICAgICB1dGlsLnJlbW92ZUJhY2tCdXR0b25MaXN0ZW5lcih0aGlzLl9ib3VuZENhbGxiYWNrKTtcbiAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaXJlIGEgJ2JhY2tidXR0b24nIGV2ZW50IG1hbnVhbGx5LlxuICAgKi9cbiAgZmlyZURldmljZUJhY2tCdXR0b25FdmVudCgpIHtcbiAgICBjb25zdCBldmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdFdmVudCcpO1xuICAgIGV2ZW50LmluaXRFdmVudCgnYmFja2J1dHRvbicsIHRydWUsIHRydWUpO1xuICAgIGRvY3VtZW50LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICB9XG5cbiAgX2NhbGxiYWNrKCkge1xuICAgIHRoaXMuX2Rpc3BhdGNoRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgY3JlYXRlSGFuZGxlcihlbGVtZW50LCBjYWxsYmFjaykge1xuICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEhUTUxFbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgaWYgKCEoY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBGdW5jdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB7XG4gICAgICBfY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgX2VsZW1lbnQ6IGVsZW1lbnQsXG5cbiAgICAgIGRpc2FibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBIYW5kbGVyUmVwb3NpdG9yeS5yZW1vdmUoZWxlbWVudCk7XG4gICAgICB9LFxuXG4gICAgICBzZXRMaXN0ZW5lcjogZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICAgIH0sXG5cbiAgICAgIGVuYWJsZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIEhhbmRsZXJSZXBvc2l0b3J5LnNldChlbGVtZW50LCB0aGlzKTtcbiAgICAgIH0sXG5cbiAgICAgIGlzRW5hYmxlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBIYW5kbGVyUmVwb3NpdG9yeS5nZXQoZWxlbWVudCkgPT09IHRoaXM7XG4gICAgICB9LFxuXG4gICAgICBkZXN0cm95OiBmdW5jdGlvbigpIHtcbiAgICAgICAgSGFuZGxlclJlcG9zaXRvcnkucmVtb3ZlKGVsZW1lbnQpO1xuICAgICAgICB0aGlzLl9jYWxsYmFjayA9IHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBoYW5kbGVyLmVuYWJsZSgpO1xuXG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICBfZGlzcGF0Y2hEZXZpY2VCYWNrQnV0dG9uRXZlbnQoKSB7XG4gICAgY29uc3QgdHJlZSA9IHRoaXMuX2NhcHR1cmVUcmVlKCk7XG5cbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fZmluZEhhbmRsZXJMZWFmRWxlbWVudCh0cmVlKTtcblxuICAgIGxldCBoYW5kbGVyID0gSGFuZGxlclJlcG9zaXRvcnkuZ2V0KGVsZW1lbnQpO1xuICAgIGhhbmRsZXIuX2NhbGxiYWNrKGNyZWF0ZUV2ZW50KGVsZW1lbnQpKTtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUV2ZW50KGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9lbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjYWxsUGFyZW50SGFuZGxlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgbGV0IHBhcmVudCA9IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgICAgIHdoaWxlIChwYXJlbnQpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSBIYW5kbGVyUmVwb3NpdG9yeS5nZXQocGFyZW50KTtcbiAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLl9jYWxsYmFjayhjcmVhdGVFdmVudChwYXJlbnQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgX2NhcHR1cmVUcmVlKCkge1xuICAgIHJldHVybiBjcmVhdGVUcmVlKGRvY3VtZW50LmJvZHkpO1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlVHJlZShlbGVtZW50KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBlbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjaGlsZHJlbjogQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZihlbGVtZW50LmNoaWxkcmVuKS5tYXAoZnVuY3Rpb24oY2hpbGRFbGVtZW50KSB7XG5cbiAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50LnN0eWxlLmRpc3BsYXkgPT09ICdub25lJykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjaGlsZEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID09PSAwICYmICFIYW5kbGVyUmVwb3NpdG9yeS5oYXMoY2hpbGRFbGVtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNyZWF0ZVRyZWUoY2hpbGRFbGVtZW50KTtcblxuICAgICAgICAgIGlmIChyZXN1bHQuY2hpbGRyZW4ubGVuZ3RoID09PSAwICYmICFIYW5kbGVyUmVwb3NpdG9yeS5oYXMocmVzdWx0LmVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIFtyZXN1bHRdO1xuICAgICAgICB9KSlcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXJyYXlPZih0YXJnZXQpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVzdWx0LnB1c2godGFyZ2V0W2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSB0cmVlXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2ZpbmRIYW5kbGVyTGVhZkVsZW1lbnQodHJlZSkge1xuICAgIHJldHVybiBmaW5kKHRyZWUpO1xuXG4gICAgZnVuY3Rpb24gZmluZChub2RlKSB7XG4gICAgICBpZiAobm9kZS5jaGlsZHJlbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG5vZGUuZWxlbWVudDtcbiAgICAgIH1cblxuICAgICAgaWYgKG5vZGUuY2hpbGRyZW4ubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBmaW5kKG5vZGUuY2hpbGRyZW5bMF0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbm9kZS5jaGlsZHJlbi5tYXAoZnVuY3Rpb24oY2hpbGROb2RlKSB7XG4gICAgICAgIHJldHVybiBjaGlsZE5vZGUuZWxlbWVudDtcbiAgICAgIH0pLnJlZHVjZShmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICAgICAgICBpZiAoIWxlZnQpIHtcbiAgICAgICAgICByZXR1cm4gcmlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsZWZ0WiA9IHBhcnNlSW50KHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGxlZnQsICcnKS56SW5kZXgsIDEwKTtcbiAgICAgICAgY29uc3QgcmlnaHRaID0gcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUocmlnaHQsICcnKS56SW5kZXgsIDEwKTtcblxuICAgICAgICBpZiAoIWlzTmFOKGxlZnRaKSAmJiAhaXNOYU4ocmlnaHRaKSkge1xuICAgICAgICAgIHJldHVybiBsZWZ0WiA+IHJpZ2h0WiA/IGxlZnQgOiByaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FwdHVyaW5nIGJhY2tidXR0b24taGFuZGxlciBpcyBmYWlsdXJlLicpO1xuICAgICAgfSwgbnVsbCk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG5ldyBEZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlcigpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc1BsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm0nO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcblxubGV0IGF1dG9TdHlsZUVuYWJsZWQgPSB0cnVlO1xuXG4vLyBNb2RpZmllcnNcbmNvbnN0IG1vZGlmaWVyc01hcCA9IHtcbiAgJ3F1aWV0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ2xpZ2h0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ291dGxpbmUnOiAnbWF0ZXJpYWwtLWZsYXQnLFxuICAnY3RhJzogJycsXG4gICdsYXJnZS0tcXVpZXQnOiAnbWF0ZXJpYWwtLWZsYXQgbGFyZ2UnLFxuICAnbGFyZ2UtLWN0YSc6ICdsYXJnZScsXG4gICdub2JvcmRlcic6ICcnLFxuICAnY2hldnJvbic6ICcnLFxuICAndGFwcGFibGUnOiAnJ1xufTtcblxuY29uc3QgcGxhdGZvcm1zID0ge307XG5cbnBsYXRmb3Jtcy5hbmRyb2lkID0gZWxlbWVudCA9PiB7XG5cbiAgaWYgKCEvb25zLWZhYnxvbnMtc3BlZWQtZGlhbHxvbnMtcHJvZ3Jlc3MvLnRlc3QoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkpICYmXG4gICAgIS9tYXRlcmlhbC8udGVzdChlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSkpIHtcblxuICAgIGNvbnN0IG9sZE1vZGlmaWVyID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgfHwgJyc7XG5cbiAgICBjb25zdCBuZXdNb2RpZmllciA9IG9sZE1vZGlmaWVyLnRyaW0oKS5zcGxpdCgvXFxzKy8pLm1hcChlID0+IG1vZGlmaWVyc01hcC5oYXNPd25Qcm9wZXJ0eShlKSA/IG1vZGlmaWVyc01hcFtlXSA6IGUpO1xuICAgIG5ld01vZGlmaWVyLnVuc2hpZnQoJ21hdGVyaWFsJyk7XG5cbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnbW9kaWZpZXInLCBuZXdNb2RpZmllci5qb2luKCcgJykudHJpbSgpKTtcbiAgfVxuXG4gIC8vIEVmZmVjdHNcbiAgaWYgKC9vbnMtYnV0dG9ufG9ucy1saXN0LWl0ZW18b25zLWZhYnxvbnMtc3BlZWQtZGlhbHxvbnMtdGFiJC8udGVzdChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSlcbiAgICAmJiAhZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpXG4gICAgJiYgIXV0aWwuZmluZENoaWxkKGVsZW1lbnQsICdvbnMtcmlwcGxlJykpIHtcblxuICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1saXN0LWl0ZW0nKSB7XG4gICAgICBpZiAoZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ3RhcHBhYmxlJykpIHtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3JpcHBsZScsICcnKTtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3RhcHBhYmxlJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdyaXBwbGUnLCAnJyk7XG4gICAgfVxuICB9XG59O1xuXG5wbGF0Zm9ybXMuaW9zID0gZWxlbWVudCA9PiB7XG5cbiAvLyBNb2RpZmllcnNcbiBpZiAoL21hdGVyaWFsLy50ZXN0KGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKSkge1xuICAgdXRpbC5yZW1vdmVNb2RpZmllcihlbGVtZW50LCAnbWF0ZXJpYWwnKTtcblxuICAgaWYgKHV0aWwucmVtb3ZlTW9kaWZpZXIoZWxlbWVudCwgJ21hdGVyaWFsLS1mbGF0JykpIHtcbiAgICAgdXRpbC5hZGRNb2RpZmllcihlbGVtZW50LCAodXRpbC5yZW1vdmVNb2RpZmllcihlbGVtZW50LCAnbGFyZ2UnKSkgPyAnbGFyZ2UtLXF1aWV0JyA6ICdxdWlldCcpO1xuICAgfVxuXG4gICBpZiAoIWVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKSB7XG4gICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdtb2RpZmllcicpO1xuICAgfVxuIH1cblxuIC8vIEVmZmVjdHNcbiBpZiAoZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpKSB7XG4gICBpZiAoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtbGlzdC1pdGVtJykge1xuICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgndGFwcGFibGUnLCAnJyk7XG4gICB9XG5cbiAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdyaXBwbGUnKTtcbiB9XG59O1xuXG5jb25zdCB1bmxvY2tlZCA9IHtcbiAgYW5kcm9pZDogdHJ1ZVxufTtcblxuY29uc3QgcHJlcGFyZUF1dG9TdHlsZSA9IChlbGVtZW50LCBmb3JjZSkgPT4ge1xuICBpZiAoYXV0b1N0eWxlRW5hYmxlZCAmJiAhZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGUtYXV0by1zdHlsaW5nJykpIHtcbiAgICBjb25zdCBtb2JpbGVPUyA9IG9uc1BsYXRmb3JtLmdldE1vYmlsZU9TKCk7XG4gICAgaWYgKHBsYXRmb3Jtcy5oYXNPd25Qcm9wZXJ0eShtb2JpbGVPUykgJiYgKHVubG9ja2VkLmhhc093blByb3BlcnR5KG1vYmlsZU9TKSB8fCBmb3JjZSkpIHtcbiAgICAgIHBsYXRmb3Jtc1ttb2JpbGVPU10oZWxlbWVudCk7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIGlzRW5hYmxlZDogKCkgPT4gYXV0b1N0eWxlRW5hYmxlZCxcbiAgZW5hYmxlOiAoKSA9PiBhdXRvU3R5bGVFbmFibGVkID0gdHJ1ZSxcbiAgZGlzYWJsZTogKCkgPT4gYXV0b1N0eWxlRW5hYmxlZCA9IGZhbHNlLFxuICBwcmVwYXJlOiBwcmVwYXJlQXV0b1N0eWxlXG59O1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuY29uc3QgZ2VuZXJhdGVJZCA9IChmdW5jdGlvbigpIHtcbiAgbGV0IGkgPSAwO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGkrKztcbiAgfTtcbn0pKCk7XG5cbi8qKlxuICogRG9vciBsb2NraW5nIHN5c3RlbS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5sb2ddXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERvb3JMb2NrIHtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9sb2NrTGlzdCA9IFtdO1xuICAgIHRoaXMuX3dhaXRMaXN0ID0gW107XG4gICAgdGhpcy5fbG9nID0gb3B0aW9ucy5sb2cgfHwgZnVuY3Rpb24oKSB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIGxvY2suXG4gICAqXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBDYWxsYmFjayBmb3IgdW5sb2NraW5nLlxuICAgKi9cbiAgbG9jaygpIHtcbiAgICBjb25zdCB1bmxvY2sgPSAoKSA9PiB7XG4gICAgICB0aGlzLl91bmxvY2sodW5sb2NrKTtcbiAgICB9O1xuICAgIHVubG9jay5pZCA9IGdlbmVyYXRlSWQoKTtcbiAgICB0aGlzLl9sb2NrTGlzdC5wdXNoKHVubG9jayk7XG4gICAgdGhpcy5fbG9nKCdsb2NrOiAnICsgKHVubG9jay5pZCkpO1xuXG4gICAgcmV0dXJuIHVubG9jaztcbiAgfVxuXG4gIF91bmxvY2soZm4pIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuX2xvY2tMaXN0LmluZGV4T2YoZm4pO1xuICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBmdW5jdGlvbiBpcyBub3QgcmVnaXN0ZXJlZCBpbiB0aGUgbG9jayBsaXN0LicpO1xuICAgIH1cblxuICAgIHRoaXMuX2xvY2tMaXN0LnNwbGljZShpbmRleCwgMSk7XG4gICAgdGhpcy5fbG9nKCd1bmxvY2s6ICcgKyBmbi5pZCk7XG5cbiAgICB0aGlzLl90cnlUb0ZyZWVXYWl0TGlzdCgpO1xuICB9XG5cbiAgX3RyeVRvRnJlZVdhaXRMaXN0KCkge1xuICAgIHdoaWxlICghdGhpcy5pc0xvY2tlZCgpICYmIHRoaXMuX3dhaXRMaXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuX3dhaXRMaXN0LnNoaWZ0KCkoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmb3Igd2FpdGluZyB1bmxvY2tlZCBkb29yLlxuICAgKlxuICAgKiBAcGFyYW1zIHtGdW5jdGlvbn0gY2FsbGJhY2sgQ2FsbGJhY2sgb24gdW5sb2NraW5nIHRoZSBkb29yIGNvbXBsZXRlbHkuXG4gICAqL1xuICB3YWl0VW5sb2NrKGNhbGxiYWNrKSB7XG4gICAgaWYgKCEoY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGNhbGxiYWNrIHBhcmFtIG11c3QgYmUgYSBmdW5jdGlvbi4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc0xvY2tlZCgpKSB7XG4gICAgICB0aGlzLl93YWl0TGlzdC5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzTG9ja2VkKCkge1xuICAgIHJldHVybiB0aGlzLl9sb2NrTGlzdC5sZW5ndGggPiAwO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuL2ludGVybmFsJztcblxuLy8gRGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBmb3IgZ2xvYmFsIFBhZ2VMb2FkZXIuXG5mdW5jdGlvbiBsb2FkUGFnZSh7cGFnZSwgcGFyZW50LCBwYXJhbXMgPSB7fSwgcmVwbGFjZX0sIGRvbmUpIHtcbiAgaW50ZXJuYWwuZ2V0UGFnZUhUTUxBc3luYyhwYWdlKS50aGVuKGh0bWwgPT4ge1xuICAgIGlmIChyZXBsYWNlKSB7XG4gICAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbihwYXJlbnQsICdfZGVzdHJveScpO1xuICAgICAgcGFyZW50LmlubmVySFRNTCA9ICcnO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnQgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoaHRtbC50cmltKCkpO1xuICAgIHBhcmVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcblxuICAgIGRvbmUoe1xuICAgICAgZWxlbWVudDogZWxlbWVudCxcbiAgICAgIHVubG9hZDogKCkgPT4gZWxlbWVudC5yZW1vdmUoKVxuICAgIH0pO1xuICB9KTtcbn1cblxuZXhwb3J0IGNsYXNzIFBhZ2VMb2FkZXIge1xuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2ZuXSBSZXR1cm5zIGFuIG9iamVjdCB0aGF0IGhhcyBcImVsZW1lbnRcIiBwcm9wZXJ0eSBhbmQgXCJ1bmxvYWRcIiBmdW5jdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGZuKSB7XG4gICAgdGhpcy5fbG9hZGVyID0gZm4gaW5zdGFuY2VvZiBGdW5jdGlvbiA/IGZuIDogbG9hZFBhZ2U7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGludGVybmFsIGxvYWRlciBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIHNldCBpbnRlcm5hbExvYWRlcihmbikge1xuICAgIGlmICghKGZuIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB0aHJvdyBFcnJvcignRmlyc3QgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgRnVuY3Rpb24nKTtcbiAgICB9XG4gICAgdGhpcy5fbG9hZGVyID0gZm47XG4gIH1cblxuICBnZXQgaW50ZXJuYWxMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2FueX0gb3B0aW9ucy5wYWdlXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gb3B0aW9ucy5wYXJlbnQgQSBsb2NhdGlvbiB0byBsb2FkIHBhZ2UuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5wYXJhbXNdIEV4dHJhIHBhcmFtZXRlcnMgZm9yIG9ucy1wYWdlLlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnJlcGxhY2VdIFJlbW92ZSB0aGUgcHJldmlvdXMgY29udGVudC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZSBUYWtlIGFuIG9iamVjdCB0aGF0IGhhcyBcImVsZW1lbnRcIiBwcm9wZXJ0eSBhbmQgXCJ1bmxvYWRcIiBmdW5jdGlvbi5cbiAgICovXG4gIGxvYWQoe3BhZ2UsIHBhcmVudCwgcGFyYW1zID0ge30sIHJlcGxhY2V9LCBkb25lKSB7XG4gICAgdGhpcy5fbG9hZGVyKHtwYWdlLCBwYXJlbnQsIHBhcmFtcywgcmVwbGFjZX0sIHJlc3VsdCA9PiB7XG4gICAgICBpZiAoIShyZXN1bHQuZWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgICAgIHRocm93IEVycm9yKCd0YXJnZXQuZWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEVsZW1lbnQuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghKHJlc3VsdC51bmxvYWQgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ3RhcmdldC51bmxvYWQgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBGdW5jdGlvbi4nKTtcbiAgICAgIH1cblxuICAgICAgZG9uZShyZXN1bHQpO1xuICAgIH0sIHBhcmFtcyk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRQYWdlTG9hZGVyID0gbmV3IFBhZ2VMb2FkZXIoKTtcblxuZXhwb3J0IGNvbnN0IGluc3RhbnRQYWdlTG9hZGVyID0gbmV3IFBhZ2VMb2FkZXIoZnVuY3Rpb24oe3BhZ2UsIHBhcmVudCwgcGFyYW1zID0ge30sIHJlcGxhY2V9LCBkb25lKSB7XG4gIGlmIChyZXBsYWNlKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24ocGFyZW50LCAnX2Rlc3Ryb3knKTtcbiAgICBwYXJlbnQuaW5uZXJIVE1MID0gJyc7XG4gIH1cblxuICBjb25zdCBlbGVtZW50ID0gdXRpbC5jcmVhdGVFbGVtZW50KHBhZ2UudHJpbSgpKTtcbiAgcGFyZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuXG4gIGRvbmUoe1xuICAgIGVsZW1lbnQ6IGVsZW1lbnQsXG4gICAgdW5sb2FkOiAoKSA9PiBlbGVtZW50LnJlbW92ZSgpXG4gIH0pO1xufSk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IEdlc3R1cmVEZXRlY3RvciBmcm9tICcuL2dlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm0nO1xuaW1wb3J0IG5vdGlmaWNhdGlvbiBmcm9tICcuL25vdGlmaWNhdGlvbic7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi9pbnRlcm5hbCc7XG5pbXBvcnQgb3JpZW50YXRpb24gZnJvbSAnLi9vcmllbnRhdGlvbic7XG5pbXBvcnQgc29mdHdhcmVLZXlib2FyZCBmcm9tICcuL3NvZnR3YXJlLWtleWJvYXJkJztcbmltcG9ydCBQYWdlQXR0cmlidXRlRXhwcmVzc2lvbiBmcm9tICcuL3BhZ2UtYXR0cmlidXRlLWV4cHJlc3Npb24nO1xuaW1wb3J0IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyIGZyb20gJy4vZGV2aWNlLWJhY2stYnV0dG9uLWRpc3BhdGNoZXInO1xuaW1wb3J0IGFuaW1hdGlvbk9wdGlvbnNQYXJzZXIgZnJvbSAnLi9hbmltYXRpb24tb3B0aW9ucy1wYXJzZXInO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuL2F1dG9zdHlsZSc7XG5pbXBvcnQgRG9vckxvY2sgZnJvbSAnLi9kb29ybG9jayc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4vY29udGVudC1yZWFkeSc7XG5pbXBvcnQge2RlZmF1bHRQYWdlTG9hZGVyLCBQYWdlTG9hZGVyfSBmcm9tICcuL3BhZ2UtbG9hZGVyJztcblxuLyoqXG4gKiBAb2JqZWN0IG9uc1xuICogQGNhdGVnb3J5IHV0aWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbamFdT25zZW4gVUnjgafliKnnlKjjgafjgY3jgovjgrDjg63jg7zjg5Djg6vjgarjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICogICBbZW5dQSBnbG9iYWwgb2JqZWN0IHRoYXQncyB1c2VkIGluIE9uc2VuIFVJLiBbL2VuXVxuICovXG5jb25zdCBvbnMgPSB7fTtcblxub25zLl91dGlsID0gdXRpbDtcbm9ucy5fZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlcjtcbm9ucy5faW50ZXJuYWwgPSBpbnRlcm5hbDtcbm9ucy5HZXN0dXJlRGV0ZWN0b3IgPSBHZXN0dXJlRGV0ZWN0b3I7XG5vbnMucGxhdGZvcm0gPSBwbGF0Zm9ybTtcbm9ucy5zb2Z0d2FyZUtleWJvYXJkID0gc29mdHdhcmVLZXlib2FyZDtcbm9ucy5wYWdlQXR0cmlidXRlRXhwcmVzc2lvbiA9IFBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uO1xub25zLm9yaWVudGF0aW9uID0gb3JpZW50YXRpb247XG5vbnMubm90aWZpY2F0aW9uID0gbm90aWZpY2F0aW9uO1xub25zLl9hbmltYXRpb25PcHRpb25zUGFyc2VyID0gYW5pbWF0aW9uT3B0aW9uc1BhcnNlcjtcbm9ucy5fYXV0b1N0eWxlID0gYXV0b1N0eWxlO1xub25zLl9Eb29yTG9jayA9IERvb3JMb2NrO1xub25zLl9jb250ZW50UmVhZHkgPSBjb250ZW50UmVhZHk7XG5vbnMuZGVmYXVsdFBhZ2VMb2FkZXIgPSBkZWZhdWx0UGFnZUxvYWRlcjtcbm9ucy5QYWdlTG9hZGVyID0gUGFnZUxvYWRlcjtcblxub25zLl9yZWFkeUxvY2sgPSBuZXcgRG9vckxvY2soKTtcblxub25zLnBsYXRmb3JtLnNlbGVjdCgod2luZG93LmxvY2F0aW9uLnNlYXJjaC5tYXRjaCgvcGxhdGZvcm09KFtcXHctXSspLykgfHwgW10pWzFdKTtcblxud2FpdERldmljZVJlYWR5KCk7XG5cbi8qKlxuICogQG1ldGhvZCBpc1JlYWR5XG4gKiBAc2lnbmF0dXJlIGlzUmVhZHkoKVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqICAgW2VuXVdpbGwgYmUgdHJ1ZSBpZiBPbnNlbiBVSSBpcyBpbml0aWFsaXplZC5bL2VuXVxuICogICBbamFd5Yid5pyf5YyW44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dUmV0dXJucyB0cnVlIGlmIE9uc2VuIFVJIGlzIGluaXRpYWxpemVkLlsvZW5dXG4gKiAgIFtqYV1PbnNlbiBVSeOBjOOBmeOBp+OBq+WIneacn+WMluOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBmeODoeOCveODg+ODieOBp+OBmeOAglsvamFdXG4gKi9cbm9ucy5pc1JlYWR5ID0gKCkgPT4ge1xuICByZXR1cm4gIW9ucy5fcmVhZHlMb2NrLmlzTG9ja2VkKCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgaXNXZWJWaWV3XG4gKiBAc2lnbmF0dXJlIGlzV2ViVmlldygpXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJldHVybnMgdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GZ44Oh44K944OD44OJ44Gn44GZ44CCWy9qYV1cbiAqL1xub25zLmlzV2ViVmlldyA9IG9ucy5wbGF0Zm9ybS5pc1dlYlZpZXc7XG5cbi8qKlxuICogQG1ldGhvZCByZWFkeVxuICogQHNpZ25hdHVyZSByZWFkeShjYWxsYmFjaylcbiAqIEBkZXNjcmlwdGlvblxuICogICBbamFd44Ki44OX44Oq44Gu5Yid5pyf5YyW44Gr5Yip55So44GZ44KL44Oh44K944OD44OJ44Gn44GZ44CC5rih44GV44KM44Gf6Zai5pWw44Gv44CBT25zZW4gVUnjga7liJ3mnJ/ljJbjgYzntYLkuobjgZfjgabjgYTjgovmmYLngrnjgaflv4XjgZrlkbzjgbDjgozjgb7jgZnjgIJbL2phXVxuICogICBbZW5dTWV0aG9kIHVzZWQgdG8gd2FpdCBmb3IgYXBwIGluaXRpYWxpemF0aW9uLiBUaGUgY2FsbGJhY2sgd2lsbCBub3QgYmUgZXhlY3V0ZWQgdW50aWwgT25zZW4gVUkgaGFzIGJlZW4gY29tcGxldGVseSBpbml0aWFsaXplZC5bL2VuXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgYWZ0ZXIgT25zZW4gVUkgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuWy9lbl1cbiAqICAgW2phXU9uc2VuIFVJ44GM5Yid5pyf5YyW44GM5a6M5LqG44GX44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLnJlYWR5ID0gY2FsbGJhY2sgPT4ge1xuICBpZiAob25zLmlzUmVhZHkoKSkge1xuICAgIGNhbGxiYWNrKCk7XG4gIH0gZWxzZSB7XG4gICAgb25zLl9yZWFkeUxvY2sud2FpdFVubG9jayhjYWxsYmFjayk7XG4gIH1cbn07XG5cbi8qKlxuICogQG1ldGhvZCBzZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyXG4gKiBAc2lnbmF0dXJlIHNldERlZmF1bHREZXZpY2VCYWNrQnV0dG9uTGlzdGVuZXIobGlzdGVuZXIpXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lclxuICogICBbZW5dRnVuY3Rpb24gdGhhdCBleGVjdXRlcyB3aGVuIGRldmljZSBiYWNrIGJ1dHRvbiBpcyBwcmVzc2VkLlsvZW5dXG4gKiAgIFtqYV3jg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgYzmirzjgZXjgozjgZ/mmYLjgavlrp/ooYzjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1TZXQgZGVmYXVsdCBoYW5kbGVyIGZvciBkZXZpY2UgYmFjayBidXR0b24uWy9lbl1cbiAqICAgW2phXeODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OBruOBn+OCgeOBruODh+ODleOCqeODq+ODiOOBruODj+ODs+ODieODqeOCkuioreWumuOBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5zZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyID0gZnVuY3Rpb24obGlzdGVuZXIpIHtcbiAgb25zLl9kZWZhdWx0RGV2aWNlQmFja0J1dHRvbkhhbmRsZXIuc2V0TGlzdGVuZXIobGlzdGVuZXIpO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGRpc2FibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlclxuICogQHNpZ25hdHVyZSBkaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIoKVxuICogQGRlc2NyaXB0aW9uXG4gKiBbZW5dRGlzYWJsZSBkZXZpY2UgYmFjayBidXR0b24gZXZlbnQgaGFuZGxlci5bL2VuXVxuICogW2phXeODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OBruOCpOODmeODs+ODiOOCkuWPl+OBkeS7mOOBkeOBquOBhOOCiOOBhuOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5kaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIgPSBmdW5jdGlvbigpIHtcbiAgb25zLl9kZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5kaXNhYmxlKCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXJcbiAqIEBzaWduYXR1cmUgZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIoKVxuICogQGRlc2NyaXB0aW9uXG4gKiBbZW5dRW5hYmxlIGRldmljZSBiYWNrIGJ1dHRvbiBldmVudCBoYW5kbGVyLlsvZW5dXG4gKiBbamFd44OH44OQ44Kk44K544Gu44OQ44OD44Kv44Oc44K/44Oz44Gu44Kk44OZ44Oz44OI44KS5Y+X44GR5LuY44GR44KL44KI44GG44Gr44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLmVuYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gIG9ucy5fZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuZW5hYmxlKCk7XG59O1xuXG5cbi8qKlxuICogQG1ldGhvZCBlbmFibGVBdXRvU3RhdHVzQmFyRmlsbFxuICogQHNpZ25hdHVyZSBlbmFibGVBdXRvU3RhdHVzQmFyRmlsbCgpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUVuYWJsZSBzdGF0dXMgYmFyIGZpbGwgZmVhdHVyZSBvbiBpT1M3IGFuZCBhYm92ZS5bL2VuXVxuICogICBbamFdaU9TN+S7peS4iuOBp+OAgeOCueODhuODvOOCv+OCueODkOODvOmDqOWIhuOBrumrmOOBleOCkuiHquWLleeahOOBq+Wfi+OCgeOCi+WHpueQhuOCkuacieWKueOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5lbmFibGVBdXRvU3RhdHVzQmFyRmlsbCA9ICgpID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIG11c3QgYmUgY2FsbGVkIGJlZm9yZSBvbnMuaXNSZWFkeSgpIGlzIHRydWUuJyk7XG4gIH1cbiAgb25zLl9pbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGwgPSB0cnVlO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGRpc2FibGVBdXRvU3RhdHVzQmFyRmlsbFxuICogQHNpZ25hdHVyZSBkaXNhYmxlQXV0b1N0YXR1c0JhckZpbGwoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1EaXNhYmxlIHN0YXR1cyBiYXIgZmlsbCBmZWF0dXJlIG9uIGlPUzcgYW5kIGFib3ZlLlsvZW5dXG4gKiAgIFtqYV1pT1M35Lul5LiK44Gn44CB44K544OG44O844K/44K544OQ44O86YOo5YiG44Gu6auY44GV44KS6Ieq5YuV55qE44Gr5Z+L44KB44KL5Yem55CG44KS54Sh5Yq544Gr44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLmRpc2FibGVBdXRvU3RhdHVzQmFyRmlsbCA9ICgpID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIG11c3QgYmUgY2FsbGVkIGJlZm9yZSBvbnMuaXNSZWFkeSgpIGlzIHRydWUuJyk7XG4gIH1cbiAgb25zLl9pbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGwgPSBmYWxzZTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBkaXNhYmxlQW5pbWF0aW9uc1xuICogQHNpZ25hdHVyZSBkaXNhYmxlQW5pbWF0aW9ucygpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXURpc2FibGUgYWxsIGFuaW1hdGlvbnMuIENvdWxkIGJlIGhhbmR5IGZvciB0ZXN0aW5nIGFuZCBvbGRlciBkZXZpY2VzLlsvZW5dXG4gKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgpLlhajjgabnhKHlirnjgavjgZfjgb7jgZnjgILjg4bjgrnjg4jjga7pmpvjgavkvr/liKnjgafjgZnjgIJbL2phXVxuICovXG5vbnMuZGlzYWJsZUFuaW1hdGlvbnMgPSAoKSA9PiB7XG4gIG9ucy5faW50ZXJuYWwuY29uZmlnLmFuaW1hdGlvbnNEaXNhYmxlZCA9IHRydWU7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQW5pbWF0aW9uc1xuICogQHNpZ25hdHVyZSBlbmFibGVBbmltYXRpb25zKClcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dRW5hYmxlIGFuaW1hdGlvbnMgKGRlZmF1bHQpLlsvZW5dXG4gKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgpLmnInlirnjgavjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuZW5hYmxlQW5pbWF0aW9ucyA9ICgpID0+IHtcbiAgb25zLl9pbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZGlzYWJsZUF1dG9TdHlsaW5nXG4gKiBAc2lnbmF0dXJlIGRpc2FibGVBdXRvU3R5bGluZygpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXURpc2FibGUgYXV0b21hdGljIHN0eWxpbmcuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm9ucy5kaXNhYmxlQXV0b1N0eWxpbmcgPSBvbnMuX2F1dG9TdHlsZS5kaXNhYmxlO1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQXV0b1N0eWxpbmdcbiAqIEBzaWduYXR1cmUgZW5hYmxlQXV0b1N0eWxpbmcoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgYXV0b21hdGljIHN0eWxpbmcgYmFzZWQgb24gT1MgKGRlZmF1bHQpLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMuZW5hYmxlQXV0b1N0eWxpbmcgPSBvbnMuX2F1dG9TdHlsZS5lbmFibGU7XG5cbi8qKlxuICogQG1ldGhvZCBmb3JjZVBsYXRmb3JtU3R5bGluZ1xuICogQHNpZ25hdHVyZSBmb3JjZVBsYXRmb3JtU3R5bGluZyhwbGF0Zm9ybSlcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dUmVmcmVzaCBzdHlsaW5nIGZvciB0aGUgZ2l2ZW4gcGxhdGZvcm0uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm0gTmV3IHBsYXRmb3JtIHRvIHN0eWxlIHRoZSBlbGVtZW50cy5cbiAqL1xub25zLmZvcmNlUGxhdGZvcm1TdHlsaW5nID0gbmV3UGxhdGZvcm0gPT4ge1xuICBvbnMuZW5hYmxlQXV0b1N0eWxpbmcoKTtcbiAgb25zLnBsYXRmb3JtLnNlbGVjdChuZXdQbGF0Zm9ybSB8fCAnaW9zJyk7XG5cbiAgb25zLl91dGlsLmFycmF5RnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcqJykpXG4gICAgLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnb25zLWlmJykge1xuICAgICAgICBlbGVtZW50Ll9wbGF0Zm9ybVVwZGF0ZSgpO1xuICAgICAgfSBlbHNlIGlmIChlbGVtZW50LnRhZ05hbWUubWF0Y2goL15vbnMtL2kpKSB7XG4gICAgICAgIG9ucy5fYXV0b1N0eWxlLnByZXBhcmUoZWxlbWVudCwgdHJ1ZSk7XG4gICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy10YWJiYXInKSB7XG4gICAgICAgICAgZWxlbWVudC5fdXBkYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMubGlua11cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbm9ucy5fY3JlYXRlUG9wb3Zlck9yaWdpbmFsID0gZnVuY3Rpb24ocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG5cbiAgaWYgKCFwYWdlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWdlIHVybCBtdXN0IGJlIGRlZmluZWQuJyk7XG4gIH1cblxuICByZXR1cm4gb25zLl9pbnRlcm5hbC5nZXRQYWdlSFRNTEFzeW5jKHBhZ2UpLnRoZW4oaHRtbCA9PiB7XG4gICAgaHRtbCA9IGh0bWwubWF0Y2goLzxvbnMtcG9wb3Zlci9naSkgPyBgPGRpdj4ke2h0bWx9PC9kaXY+YCA6IGA8b25zLXBvcG92ZXI+JHtodG1sfTwvb25zLXBvcG92ZXI+YDtcbiAgICBjb25zdCBkaXYgPSBvbnMuX3V0aWwuY3JlYXRlRWxlbWVudCgnPGRpdj4nICsgaHRtbCArICc8L2Rpdj4nKTtcblxuICAgIGNvbnN0IHBvcG92ZXIgPSBkaXYucXVlcnlTZWxlY3Rvcignb25zLXBvcG92ZXInKTtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHBvcG92ZXIpO1xuXG4gICAgaWYgKG9wdGlvbnMubGluayBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBvcHRpb25zLmxpbmsocG9wb3Zlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvcG92ZXI7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGNyZWF0ZVBvcG92ZXJcbiAqIEBzaWduYXR1cmUgY3JlYXRlUG9wb3ZlcihwYWdlLCBbb3B0aW9uc10pXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogICBbZW5dUGFnZSBuYW1lLiBDYW4gYmUgZWl0aGVyIGFuIEhUTUwgZmlsZSBvciBhbiA8b25zLXRlbXBsYXRlPiBjb250YWluaW5nIGEgPG9ucy1kaWFsb2c+IGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr29ucy10ZW1wbGF0ZeOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMucGFyZW50U2NvcGVdXG4gKiAgIFtlbl1QYXJlbnQgc2NvcGUgb2YgdGhlIGRpYWxvZy4gVXNlZCB0byBiaW5kIG1vZGVscyBhbmQgYWNjZXNzIHNjb3BlIG1ldGhvZHMgZnJvbSB0aGUgZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDlhoXjgafliKnnlKjjgZnjgovopqrjgrnjgrPjg7zjg5fjgpLmjIflrprjgZfjgb7jgZnjgILjg4DjgqTjgqLjg63jgrDjgYvjgonjg6Ljg4fjg6vjgoTjgrnjgrPjg7zjg5fjga7jg6Hjgr3jg4Pjg4njgavjgqLjgq/jgrvjgrnjgZnjgovjga7jgavkvb/jgYTjgb7jgZnjgILjgZPjga7jg5Hjg6njg6Hjg7zjgr/jga9Bbmd1bGFySlPjg5DjgqTjg7Pjg4fjgqPjg7PjgrDjgafjga7jgb/liKnnlKjjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHJldHVybiB7UHJvbWlzZX1cbiAqICAgW2VuXVByb21pc2Ugb2JqZWN0IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHBvcG92ZXIgY29tcG9uZW50IG9iamVjdC5bL2VuXVxuICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844Gu44Kz44Oz44Od44O844ON44Oz44OI44Kq44OW44K444Kn44Kv44OI44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNyZWF0ZSBhIHBvcG92ZXIgaW5zdGFuY2UgZnJvbSBhIHRlbXBsYXRlLlsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgYvjgonjg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuY3JlYXRlUG9wb3ZlciA9IG9ucy5fY3JlYXRlUG9wb3Zlck9yaWdpbmFsO1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5saW5rXVxuICogQHJldHVybiB7UHJvbWlzZX1cbiAqL1xub25zLl9jcmVhdGVEaWFsb2dPcmlnaW5hbCA9IGZ1bmN0aW9uKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuXG4gIGlmICghcGFnZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFnZSB1cmwgbXVzdCBiZSBkZWZpbmVkLicpO1xuICB9XG5cbiAgcmV0dXJuIG9ucy5faW50ZXJuYWwuZ2V0UGFnZUhUTUxBc3luYyhwYWdlKS50aGVuKGh0bWwgPT4ge1xuICAgIGh0bWwgPSBodG1sLm1hdGNoKC88b25zLWRpYWxvZy9naSkgPyBgPGRpdj4ke2h0bWx9PC9kaXY+YCA6IGA8b25zLWRpYWxvZz4ke2h0bWx9PC9vbnMtZGlhbG9nPmA7XG4gICAgY29uc3QgZGl2ID0gb25zLl91dGlsLmNyZWF0ZUVsZW1lbnQoJzxkaXY+JyArIGh0bWwgKyAnPC9kaXY+Jyk7XG5cbiAgICBjb25zdCBkaWFsb2cgPSBkaXYucXVlcnlTZWxlY3Rvcignb25zLWRpYWxvZycpO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGlhbG9nKTtcblxuICAgIGlmIChvcHRpb25zLmxpbmsgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgb3B0aW9ucy5saW5rKGRpYWxvZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRpYWxvZztcbiAgfSk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgY3JlYXRlRGlhbG9nXG4gKiBAc2lnbmF0dXJlIGNyZWF0ZURpYWxvZyhwYWdlLCBbb3B0aW9uc10pXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogICBbZW5dUGFnZSBuYW1lLiBDYW4gYmUgZWl0aGVyIGFuIEhUTUwgZmlsZSBvciBhbiA8b25zLXRlbXBsYXRlPiBjb250YWluaW5nIGEgPG9ucy1kaWFsb2c+IGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr29ucy10ZW1wbGF0ZeOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgZGlhbG9nIGNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBruOCs+ODs+ODneODvOODjeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOCkuino+axuuOBmeOCi1Byb21pc2Xjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1DcmVhdGUgYSBkaWFsb2cgaW5zdGFuY2UgZnJvbSBhIHRlbXBsYXRlLlsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgYvjgonjg4DjgqTjgqLjg63jgrDjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuY3JlYXRlRGlhbG9nID0gb25zLl9jcmVhdGVEaWFsb2dPcmlnaW5hbDtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMubGlua11cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbm9ucy5fY3JlYXRlQWxlcnREaWFsb2dPcmlnaW5hbCA9IGZ1bmN0aW9uKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuXG4gIGlmICghcGFnZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFnZSB1cmwgbXVzdCBiZSBkZWZpbmVkLicpO1xuICB9XG5cbiAgcmV0dXJuIG9ucy5faW50ZXJuYWwuZ2V0UGFnZUhUTUxBc3luYyhwYWdlKS50aGVuKGh0bWwgPT4ge1xuICAgIGh0bWwgPSBodG1sLm1hdGNoKC88b25zLWFsZXJ0LWRpYWxvZy9naSkgPyBgPGRpdj4ke2h0bWx9PC9kaXY+YCA6IGA8b25zLWFsZXJ0LWRpYWxvZz4ke2h0bWx9PC9vbnMtYWxlcnQtZGlhbG9nPmA7XG4gICAgY29uc3QgZGl2ID0gb25zLl91dGlsLmNyZWF0ZUVsZW1lbnQoJzxkaXY+JyArIGh0bWwgKyAnPC9kaXY+Jyk7XG5cbiAgICBjb25zdCBhbGVydERpYWxvZyA9IGRpdi5xdWVyeVNlbGVjdG9yKCdvbnMtYWxlcnQtZGlhbG9nJyk7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhbGVydERpYWxvZyk7XG5cbiAgICBpZiAob3B0aW9ucy5saW5rIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIG9wdGlvbnMubGluayhhbGVydERpYWxvZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFsZXJ0RGlhbG9nO1xuICB9KTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBjcmVhdGVBbGVydERpYWxvZ1xuICogQHNpZ25hdHVyZSBjcmVhdGVBbGVydERpYWxvZyhwYWdlLCBbb3B0aW9uc10pXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogICBbZW5dUGFnZSBuYW1lLiBDYW4gYmUgZWl0aGVyIGFuIEhUTUwgZmlsZSBvciBhbiA8b25zLXRlbXBsYXRlPiBjb250YWluaW5nIGEgPG9ucy1hbGVydC1kaWFsb2c+IGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr29ucy10ZW1wbGF0ZeOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgYWxlcnQgZGlhbG9nIGNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBruOCs+ODs+ODneODvOODjeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOCkuino+axuuOBmeOCi1Byb21pc2Xjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1DcmVhdGUgYSBhbGVydCBkaWFsb2cgaW5zdGFuY2UgZnJvbSBhIHRlbXBsYXRlLlsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgYvjgonjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuY3JlYXRlQWxlcnREaWFsb2cgPSBvbnMuX2NyZWF0ZUFsZXJ0RGlhbG9nT3JpZ2luYWw7XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGxpbmtcbiAqL1xub25zLl9yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyT3JpZ2luYWwgPSBmdW5jdGlvbihwYWdlLCBsaW5rKSB7XG4gIGNvbnN0IGVsZW1lbnRzID0gb25zLl91dGlsLmFycmF5RnJvbSh3aW5kb3cuZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyXScpKTtcblxuICBpZiAoZWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgIGVsZW1lbnRzXG4gICAgICAuZmlsdGVyKGVsZW1lbnQgPT4gIWVsZW1lbnQuZ2V0QXR0cmlidXRlKCdwYWdlJykpXG4gICAgICAuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyJywgcGFnZSk7XG4gICAgICAgIG9ucy5fcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcihlbGVtZW50LCBwYWdlLCBsaW5rKTtcbiAgICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignTm8gb25zLWxvYWRpbmctcGxhY2Vob2xkZXIgZXhpc3RzLicpO1xuICB9XG59O1xuXG4vKipcbiAqIEBtZXRob2QgcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlclxuICogQHNpZ25hdHVyZSByZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyKHBhZ2UpXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICogICBbZW5dUGFnZSBuYW1lLiBDYW4gYmUgZWl0aGVyIGFuIEhUTUwgZmlsZSBvciBhbiA8b25zLXRlbXBsYXRlPiBlbGVtZW50LlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44Gvb25zLXRlbXBsYXRl44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1JZiBubyBwYWdlIGlzIGRlZmluZWQgZm9yIHRoZSBgb25zLWxvYWRpbmctcGxhY2Vob2xkZXJgIGF0dHJpYnV0ZSBpdCB3aWxsIHdhaXQgZm9yIHRoaXMgbWV0aG9kIGJlaW5nIGNhbGxlZCBiZWZvcmUgbG9hZGluZyB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdb25zLWxvYWRpbmctcGxhY2Vob2xkZXLjga7lsZ7mgKflgKTjgajjgZfjgabjg5rjg7zjgrjjgYzmjIflrprjgZXjgozjgabjgYTjgarjgYTloLTlkIjjga/jgIHjg5rjg7zjgrjjg63jg7zjg4nliY3jgavlkbzjgbDjgozjgotvbnMucmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcuWHpueQhuOBjOihjOOCj+OCjOOCi+OBvuOBp+ihqOekuuOBleOCjOOBvuOBm+OCk+OAglsvamFdXG4gKi9cbm9ucy5yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyID0gb25zLl9yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyT3JpZ2luYWw7XG5cbm9ucy5fc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzID0gZnVuY3Rpb24oKSB7XG4gIG9ucy5yZWFkeSgoKSA9PiB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBvbnMuX3V0aWwuYXJyYXlGcm9tKHdpbmRvdy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbb25zLWxvYWRpbmctcGxhY2Vob2xkZXJdJykpO1xuXG4gICAgZWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGNvbnN0IHBhZ2UgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnb25zLWxvYWRpbmctcGxhY2Vob2xkZXInKTtcbiAgICAgIGlmICh0eXBlb2YgcGFnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgb25zLl9yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyKGVsZW1lbnQsIHBhZ2UpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn07XG5cbm9ucy5fcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIHBhZ2UsIGxpbmspIHtcbiAgbGluayA9IGxpbmsgfHwgZnVuY3Rpb24oZWxlbWVudCwgZG9uZSkgeyBkb25lKCk7IH07XG4gIG9ucy5faW50ZXJuYWwuZ2V0UGFnZUhUTUxBc3luYyhwYWdlKS50aGVuKGh0bWwgPT4ge1xuXG4gICAgd2hpbGUgKGVsZW1lbnQuZmlyc3RDaGlsZCkge1xuICAgICAgZWxlbWVudC5yZW1vdmVDaGlsZChlbGVtZW50LmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRlbnRFbGVtZW50ID0gb25zLl91dGlsLmNyZWF0ZUVsZW1lbnQoJzxkaXY+JyArIGh0bWwgKyAnPC9kaXY+Jyk7XG4gICAgY29udGVudEVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblxuICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY29udGVudEVsZW1lbnQpO1xuXG4gICAgbGluayhjb250ZW50RWxlbWVudCwgZnVuY3Rpb24oKSB7XG4gICAgICBjb250ZW50RWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgfSk7XG5cbiAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlZCB0byByZXNvbHZlIHBsYWNlaG9sZGVyOiAnICsgZXJyb3IpO1xuICB9KTtcbn07XG5cbmZ1bmN0aW9uIHdhaXREZXZpY2VSZWFkeSgpIHtcbiAgY29uc3QgdW5sb2NrRGV2aWNlUmVhZHkgPSBvbnMuX3JlYWR5TG9jay5sb2NrKCk7XG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgKCkgPT4ge1xuICAgIGlmIChvbnMuaXNXZWJWaWV3KCkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIHVubG9ja0RldmljZVJlYWR5LCBmYWxzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHVubG9ja0RldmljZVJlYWR5KCk7XG4gICAgfVxuICB9LCBmYWxzZSk7XG59XG5cbndpbmRvdy5fc3VwZXJTZWNyZXRPbnMgPSBvbnM7XG5leHBvcnQgZGVmYXVsdCBvbnM7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5mdW5jdGlvbiBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgIT09ICdmdW5jdGlvbicpIHsgLy8gY2FzZSBvZiBTYWZhcmlcbiAgICBjb25zdCBCYXNlRWxlbWVudCA9ICgpID0+IHt9O1xuICAgIEJhc2VFbGVtZW50LnByb3RvdHlwZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHJldHVybiBCYXNlRWxlbWVudDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gSFRNTEVsZW1lbnQ7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZUVsZW1lbnQgZXh0ZW5kcyBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGNvbnN0cnVjdG9yKHNlbGYpIHtcbiAgICBzZWxmID0gc3VwZXIoc2VsZik7XG4gICAgc2VsZi5pbml0KCk7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cblxuICBpbml0KCkgeyB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXRlbXBsYXRlXG4gKiBAY2F0ZWdvcnkgdXRpbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEZWZpbmUgYSBzZXBhcmF0ZSBIVE1MIGZyYWdtZW50IGFuZCB1c2UgYXMgYSB0ZW1wbGF0ZS5cbiAqXG4gKiAgICAgVGhlc2UgdGVtcGxhdGVzIGNhbiBiZSBsb2FkZWQgYXMgcGFnZXMgaW4gYDxvbnMtbmF2aWdhdG9yPmAsIGA8b25zLXRhYmJhcj5gIGFuZCBgPG9ucy1zcGxpdHRlcj5gLiBUaGV5IGNhbiBhbHNvIGJlIHVzZWQgdG8gZ2VuZXJhdGUgZGlhbG9ncy5cbiAqICAgWy9lbl1cbiAqICAgW2phXeODhuODs+ODl+ODrOODvOODiOOBqOOBl+OBpuS9v+eUqOOBmeOCi+OBn+OCgeOBrkhUTUzjg5Xjg6njgrDjg6Hjg7Pjg4jjgpLlrprnvqnjgZfjgb7jgZnjgILjgZPjga7opoHntKDjgadIVE1M44KS5a6j6KiA44GZ44KL44Go44CBaWTlsZ7mgKfjgavmjIflrprjgZfjgZ/lkI3liY3jgpJwYWdl44GuVVJM44Go44GX44Gmb25zLW5hdmlnYXRvcuOBquOBqeOBruOCs+ODs+ODneODvOODjeODs+ODiOOBi+OCieWPgueFp+OBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAZ3VpZGUgdGVtcGxhdGVzXG4gKiAgIFtlbl1EZWZpbmluZyBtdWx0aXBsZSBwYWdlcyBpbiBzaW5nbGUgaHRtbFsvZW5dXG4gKiAgIFtqYV3opIfmlbDjga7jg5rjg7zjgrjjgpIx44Gk44GuSFRNTOOBq+iomOi/sOOBmeOCi1svamFdXG4gKiBAc2VlYWxzbyBvbnMtbmF2aWdhdG9yXG4gKiAgIFtlbl1UaGUgYDxvbnMtbmF2aWdhdG9yPmAgY29tcG9uZW50IGVuYWJsZXMgc3RhY2sgYmFzZWQgbmF2aWdhdGlvbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10YWJiYXJcbiAqICAgW2VuXVRoZSBgPG9ucy10YWJiYXI+YCBjb21wb25lbnQgaXMgdXNlZCB0byBhZGQgdGFiIG5hdmlnYXRpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXJcbiAqICAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlcj5gIGNvbXBvbmVudCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBkcmFnZ2FibGUgbWVudSBvciBjb2x1bW4gYmFzZWQgbGF5b3V0LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtdGVtcGxhdGUgaWQ9XCJmb29iYXIuaHRtbFwiPlxuICogICA8b25zLXBhZ2U+XG4gKiAgICAgUGFnZSBjb250ZW50XG4gKiAgIDwvb25zLXBhZ2U+XG4gKiA8L29ucy10ZW1wbGF0ZT5cbiAqXG4gKiA8b25zLW5hdmlnYXRvciBwYWdlPVwiZm9vYmFyLmh0bWxcIj5cbiAqIDwvb25zLW5hdmlnYXRvcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVtcGxhdGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdGVtcGxhdGVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGVtcGxhdGUgY29udGVudC4gVGhpcyBwcm9wZXJ0eSBjYW4gbm90IGJlIHVzZWQgd2l0aCBBbmd1bGFySlMgYmluZGluZ3MuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIHRoaXMudGVtcGxhdGUgPSB0aGlzLmlubmVySFRNTDtcblxuICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgIHRoaXMucmVtb3ZlQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB2YXIgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoJ190ZW1wbGF0ZWxvYWRlZCcsIHtidWJibGVzOiB0cnVlLCBjYW5jZWxhYmxlOiB0cnVlfSk7XG4gICAgZXZlbnQudGVtcGxhdGUgPSB0aGlzLnRlbXBsYXRlO1xuICAgIGV2ZW50LnRlbXBsYXRlSWQgPSB0aGlzLmdldEF0dHJpYnV0ZSgnaWQnKTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdGVtcGxhdGUnLCBUZW1wbGF0ZUVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9yaWVudGF0aW9uIGZyb20gJy4uL29ucy9vcmllbnRhdGlvbic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pZlxuICogQGNhdGVnb3J5IGNvbmRpdGlvbmFsXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvaWZcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ29uZGl0aW9uYWxseSBkaXNwbGF5IGNvbnRlbnQgZGVwZW5kaW5nIG9uIHRoZSBwbGF0Zm9ybSwgZGV2aWNlIG9yaWVudGF0aW9uIG9yIGJvdGguXG4gKlxuICogICAgIFNvbWV0aW1lcyBpdCBpcyB1c2VmdWwgdG8gY29uZGl0aW9uYWxseSBoaWRlIG9yIHNob3cgY2VydGFpbiBjb21wb25lbnRzIGJhc2VkIG9uIHBsYXRmb3JtLiBXaGVuIHJ1bm5pbmcgb24gaU9TIHRoZSBgPG9ucy1pZj5gIGVsZW1lbnQgY2FuIGJlIHVzZWQgdG8gaGlkZSB0aGUgYDxvbnMtZmFiPmAgZWxlbWVudC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZ3VpZGUgY3Jvc3MtcGxhdGZvcm0tc3R5bGluZyBbZW5dSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dW2phXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtcGFnZT5cbiAqICAgPG9ucy1pZiBvcmllbnRhdGlvbj1cImxhbmRzY2FwZVwiPlxuICogICAgIExhbmRzY2FwZSB2aWV3IVxuICogICA8L29ucy1pZj5cbiAqICAgPG9ucy1pZiBwbGF0Zm9ybT1cImFuZHJvaWRcIj5cbiAqICAgICBUaGlzIGlzIEFuZHJvaWQuXG4gKiAgIDwvb25zLWlmPlxuICogICA8b25zLWlmIHBsYXRmb3JtPVwiaW9zIG90aGVyXCI+XG4gKiAgICAgVGhpcyBpcyBub3QgQW5kcm9pZC5cbiAqICAgPC9vbnMtaWY+XG4gKiA8L29ucy1wYWdlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJZkVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcGxhdGZvcm1cbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwYWNlLXNlcGFyYXRlZCBwbGF0Zm9ybSBuYW1lcy4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJpb3NcImAsIGBcImFuZHJvaWRcImAsIGBcIndpbmRvd3NcImAgYW5kIGBcIm90aGVyXCJgLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgb3JpZW50YXRpb25cbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dRWl0aGVyIGBcInBvcnRyYWl0XCJgIG9yIGBcImxhbmRzY2FwZVwiYC5bL2VuXVxuICAgKiAgW2phXXBvcnRyYWl044KC44GX44GP44GvbGFuZHNjYXBl44KS5oyH5a6a44GX44G+44GZWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHBsYXRmb3JtLl9yZW5kZXJQbGF0Zm9ybSAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9wbGF0Zm9ybVVwZGF0ZSgpO1xuICAgICAgfSBlbHNlIGlmICghdGhpcy5faXNBbGxvd2VkUGxhdGZvcm0oKSkge1xuICAgICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgICAgdGhpcy5jaGlsZE5vZGVzWzBdLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3BsYXRmb3JtVXBkYXRlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlKCk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBvcmllbnRhdGlvbi5vbignY2hhbmdlJywgdGhpcy5fb25PcmllbnRhdGlvbkNoYW5nZS5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ29yaWVudGF0aW9uJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSkge1xuICAgIGlmIChuYW1lID09PSAnb3JpZW50YXRpb24nKSB7XG4gICAgICB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlKCk7XG4gICAgfVxuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgb3JpZW50YXRpb24ub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlKTtcbiAgfVxuXG4gIF9wbGF0Zm9ybVVwZGF0ZSgpIHtcbiAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSB0aGlzLl9pc0FsbG93ZWRQbGF0Zm9ybSgpID8gJycgOiAnbm9uZSc7XG4gIH1cblxuICBfaXNBbGxvd2VkUGxhdGZvcm0oKSB7XG4gICAgcmV0dXJuICF0aGlzLmdldEF0dHJpYnV0ZSgncGxhdGZvcm0nKSB8fCB0aGlzLmdldEF0dHJpYnV0ZSgncGxhdGZvcm0nKS5zcGxpdCgvXFxzKy8pLmluZGV4T2YocGxhdGZvcm0uZ2V0TW9iaWxlT1MoKSkgPj0gMDtcbiAgfVxuXG4gIF9vbk9yaWVudGF0aW9uQ2hhbmdlKCkge1xuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnb3JpZW50YXRpb24nKSAmJiB0aGlzLl9pc0FsbG93ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICBjb25zdCBjb25kaXRpb25hbE9yaWVudGF0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ29yaWVudGF0aW9uJykudG9Mb3dlckNhc2UoKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRPcmllbnRhdGlvbiA9IG9yaWVudGF0aW9uLmlzUG9ydHJhaXQoKSA/ICdwb3J0cmFpdCcgOiAnbGFuZHNjYXBlJztcblxuICAgICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gKGNvbmRpdGlvbmFsT3JpZW50YXRpb24gPT09IGN1cnJlbnRPcmllbnRhdGlvbikgPyAnJyA6ICdub25lJztcbiAgICB9XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtaWYnLCBJZkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuZXhwb3J0IGNsYXNzIEFsZXJ0RGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnbGluZWFyJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMn0gPSB7fSkge1xuICAgIHRoaXMudGltaW5nID0gdGltaW5nO1xuICAgIHRoaXMuZGVsYXkgPSBkZWxheTtcbiAgICB0aGlzLmR1cmF0aW9uID0gZHVyYXRpb247XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIHNob3coZGlhbG9nLCBkb25lKSB7XG4gICAgZG9uZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBoaWRlKGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxufVxuXG4vKipcbiAqIEFuZHJvaWQgc3R5bGUgYW5pbWF0b3IgZm9yIGFsZXJ0IGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgQWxlcnREaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuNCwgMSknLCBkdXJhdGlvbiA9IDAuMiwgZGVsYXkgPSAwfSA9IHt9KSB7XG4gICAgc3VwZXIoe2R1cmF0aW9uLCB0aW1pbmcsIGRlbGF5fSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApIHNjYWxlM2QoMC45LCAwLjksIDEuMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMC4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCkgc2NhbGUzZCgxLjAsIDEuMCwgMS4wKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2cpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCkgc2NhbGUzZCgxLjAsIDEuMCwgMS4wKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKDAuOSwgMC45LCAxLjApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBhbGVydCBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBJT1NBbGVydERpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgQWxlcnREaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuNCwgMSknLCBkdXJhdGlvbiA9IDAuMiwgZGVsYXkgPSAwfSA9IHt9KSB7XG4gICAgc3VwZXIoe2R1cmF0aW9uLCB0aW1pbmcsIGRlbGF5fSk7XG4gIH1cblxuICAvKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2cpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCkgc2NhbGUzZCgxLjMsIDEuMywgMS4wKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAwLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKDEuMCwgMS4wLCAxLjApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZylcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiAwLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG5cbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCB7QWxlcnREaWFsb2dBbmltYXRvciwgSU9TQWxlcnREaWFsb2dBbmltYXRvciwgQW5kcm9pZEFsZXJ0RGlhbG9nQW5pbWF0b3J9IGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uLy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi8uLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5hbGVydC1kaWFsb2cnOiAnYWxlcnQtZGlhbG9nLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctY29udGFpbmVyJzogJ2FsZXJ0LWRpYWxvZy1jb250YWluZXItLSonLFxuICAnLmFsZXJ0LWRpYWxvZy10aXRsZSc6ICdhbGVydC1kaWFsb2ctdGl0bGUtLSonLFxuICAnLmFsZXJ0LWRpYWxvZy1jb250ZW50JzogJ2FsZXJ0LWRpYWxvZy1jb250ZW50LS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctZm9vdGVyJzogJ2FsZXJ0LWRpYWxvZy1mb290ZXItLSonLFxuICAnLmFsZXJ0LWRpYWxvZy1idXR0b24nOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWZvb3Rlci0tb25lJzogJ2FsZXJ0LWRpYWxvZy1mb290ZXItLW9uZS0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWJ1dHRvbi0tb25lJzogJ2FsZXJ0LWRpYWxvZy1idXR0b24tLW9uZS0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcHJpbWFsJzogJ2FsZXJ0LWRpYWxvZy1idXR0b24tLXByaW1hbC0tKicsXG4gICcuYWxlcnQtZGlhbG9nLW1hc2snOiAnYWxlcnQtZGlhbG9nLW1hc2stLSonLFxuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdub25lJzogQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2RlZmF1bHQnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvclxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYWxlcnQtZGlhbG9nXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIEFsZXJ0IGRpYWxvZyB0aGF0IGlzIGRpc3BsYXllZCBvbiB0b3Agb2YgdGhlIGN1cnJlbnQgc2NyZWVuLiBVc2VmdWwgZm9yIGRpc3BsYXlpbmcgcXVlc3Rpb25zLCB3YXJuaW5ncyBvciBlcnJvciBtZXNzYWdlcyB0byB0aGUgdXNlci4gVGhlIHRpdGxlLCBjb250ZW50IGFuZCBidXR0b25zIGNhbiBiZSBlYXNpbHkgY3VzdG9taXplZCBhbmQgaXQgd2lsbCBhdXRvbWF0aWNhbGx5IHN3aXRjaCBzdHlsZSBiYXNlZCBvbiB0aGUgcGxhdGZvcm0uXG4gKlxuICogICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZUFsZXJ0RGlhbG9nKHRlbXBsYXRlKWAgdXRpbGl0eSBmdW5jdGlvbiBhbmQgdGhlIGA8b25zLXRlbXBsYXRlPmAgdGFnLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIFF3d3h5cFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2RpYWxvZ1xuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSBkaWFsb2dzXG4gKiAgIFtlbl1EaWFsb2cgY29tcG9uZW50c1svZW5dXG4gKiAgIFtqYV1EaWFsb2cgY29tcG9uZW50c1svamFdXG4gKiBAc2VlYWxzbyBvbnMtZGlhbG9nXG4gKiAgIFtlbl1vbnMtZGlhbG9nIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtZGlhbG9n44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1wb3BvdmVyXG4gKiAgIFtlbl1vbnMtcG9wb3ZlciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMubm90aWZpY2F0aW9uXG4gKiAgIFtlbl1Vc2luZyBvbnMubm90aWZpY2F0aW9uIHV0aWxpdHkgZnVuY3Rpb25zLlsvZW5dXG4gKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZnjgovjgavjga/jgIFvbnMubm90aWZpY2F0aW9u44Kq44OW44K444Kn44Kv44OI44Gu44Oh44K944OD44OJ44KS5L2/44GG44GT44Go44KC44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWFsZXJ0LWRpYWxvZyBpZD1cImFsZXJ0LWRpYWxvZ1wiPlxuICogICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLXRpdGxlXCI+V2FybmluZyE8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1jb250ZW50XCI+XG4gKiAgICAgQW4gZXJyb3IgaGFzIG9jY3VycmVkIVxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1mb290ZXJcIj5cbiAqICAgICA8YnV0dG9uIGlkPVwiYWxlcnQtZGlhbG9nLWJ1dHRvblwiIGNsYXNzPVwiYWxlcnQtZGlhbG9nLWJ1dHRvblwiPk9LPC9idXR0b24+XG4gKiAgIDwvZGl2PlxuICogPC9vbnMtYWxlcnQtZGlhbG9nPlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0LWRpYWxvZycpLnNob3coKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbGVydERpYWxvZ0VsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgYWxlcnQgZGlhbG9nIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWxlcnREaWFsb2dcbiAgICogICBbZW5dQWxlcnQgZGlhbG9nIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dRXhlY3V0ZSB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBzaG93aW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruihqOekuuOCkuatouOCgeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGFsZXJ0IGRpYWxvZyBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44Gf55u05b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFsZXJ0RGlhbG9nXG4gICAqICAgW2VuXUFsZXJ0IGRpYWxvZyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVoaWRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgYWxlcnQgZGlhbG9nIGlzIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWxlcnREaWFsb2dcbiAgICogICBbZW5dQWxlcnQgZGlhbG9nIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dRXhlY3V0ZSB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBoaWRpbmcuWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6ZaJ44GY44KI44GG44Go44GZ44KL44Gu44KS5q2i44KB44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGFsZXJ0IGRpYWxvZyBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5hbGVydERpYWxvZ1xuICAgKiAgIFtlbl1BbGVydCBkaWFsb2cgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBkaWFsb2cuWy9lbl1cbiAgICogIFtqYV3jg4DjgqTjgqLjg63jgrDjga7opovjgZ/nm67jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjYW5jZWxhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgZGlhbG9nIGNhbiBiZSBjbG9zZWQgYnkgdGFwcGluZyB0aGUgYmFja2dyb3VuZCBvciBieSBwcmVzc2luZyB0aGUgYmFjayBidXR0b24gb24gQW5kcm9pZCBkZXZpY2VzLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBkaWFsb2cgaXMgZGlzYWJsZWQuWy9lbl1cbiAgICogIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga9kaXNhYmxlZOeKtuaFi+OBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBkZWZhdWx0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhbmltYXRpb24gdXNlZCB3aGVuIHNob3dpbmcgYW5kIGhpZGluZyB0aGUgZGlhbG9nLiBDYW4gYmUgZWl0aGVyIGBcIm5vbmVcImAgb3IgYFwiZGVmYXVsdFwiYC5bL2VuXVxuICAgKiAgW2phXeODgOOCpOOCouODreOCsOOCkuihqOekuuOBmeOCi+mam+OBruOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBp+OBr1wibm9uZVwi44GLXCJkZWZhdWx0XCLjgYzmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb24tb3B0aW9uc1xuICAgKiBAdHlwZSB7RXhwcmVzc2lvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIHRpbWluZyBhbmQgZGVsYXkgd2l0aCBhbiBvYmplY3QgbGl0ZXJhbC4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgILkvovvvJp7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgcmdiYSgwLCAwLCAwLCAwLjIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kIG1hc2suIERlZmF1bHQgaXMgXCJyZ2JhKDAsIDAsIDAsIDAuMilcIi5bL2VuXVxuICAgKiAgW2phXeiDjOaZr+OBruODnuOCueOCr+OBruiJsuOCkuaMh+WumuOBl+OBvuOBmeOAglwicmdiYSgwLCAwLCAwLCAwLjIpXCLjgYzjg4fjg5Xjgqnjg6vjg4jlgKTjgafjgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuXG4gICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG4gICAgdGhpcy5fYm91bmRDYW5jZWwgPSB0aGlzLl9jYW5jZWwuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpXG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2RpYWxvZygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2cnKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX3RpdGxlRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcy5fZGlhbG9nLmNoaWxkcmVuWzBdLCAnLmFsZXJ0LWRpYWxvZy10aXRsZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2NvbnRlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0sICcuYWxlcnQtZGlhbG9nLWNvbnRlbnQnKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgdGhpcy5fYW5pbWF0b3JGYWN0b3J5ID0gbmV3IEFuaW1hdG9yRmFjdG9yeSh7XG4gICAgICBhbmltYXRvcnM6IF9hbmltYXRvckRpY3QsXG4gICAgICBiYXNlQ2xhc3M6IEFsZXJ0RGlhbG9nQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnQWxlcnREaWFsb2dBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJylcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgLyoqXG4gICAgICogRXhwZWN0ZWQgcmVzdWx0IGFmdGVyIGNvbXBpbGU6XG4gICAgICpcbiAgICAgKiA8b25zLWFsZXJ0LWRpYWxvZyBzdHlsZT1cIm5vbmVcIj5cbiAgICAgKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctbWFza1wiPjwvZGl2PlxuICAgICAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZ1wiPlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRhaW5lclwiPi4uLjwvZGl2PlxuICAgICAqICAgPC9kaXY+XG4gICAgICogPC9vbnMtYWxlcnQtZGlhbG9nPlxuICAgICAqL1xuXG4gICAgY29uc3QgY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblxuICAgIGlmICghdGhpcy5fbWFzayAmJiAhdGhpcy5fZGlhbG9nKSB7XG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21hc2spIHtcbiAgICAgIGNvbnN0IG1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIG1hc2suY2xhc3NMaXN0LmFkZCgnYWxlcnQtZGlhbG9nLW1hc2snKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKG1hc2ssIHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fZGlhbG9nKSB7XG4gICAgICBjb25zdCBkaWFsb2cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGRpYWxvZy5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2cnKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGRpYWxvZywgbnVsbCk7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2csICcuYWxlcnQtZGlhbG9nLWNvbnRhaW5lcicpKSB7XG4gICAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2ctY29udGFpbmVyJyk7XG4gICAgICB0aGlzLl9kaWFsb2cuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0uYXBwZW5kQ2hpbGQoY29udGVudCk7XG5cbiAgICB0aGlzLl9kaWFsb2cuc3R5bGUuekluZGV4ID0gMjAwMDE7XG4gICAgdGhpcy5fbWFzay5zdHlsZS56SW5kZXggPSAyMDAwMDtcblxuICAgIGlmICh0aGlzLmdldEF0dHJpYnV0ZSgnbWFzay1jb2xvcicpKSB7XG4gICAgICB0aGlzLl9tYXNrLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHRoaXMuZ2V0QXR0cmlidXRlKCdtYXNrLWNvbG9yJyk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2FuY2VsYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGRpYWxvZyBpcyBjYW5jZWxhYmxlIG9yIG5vdC4gQSBjYW5jZWxhYmxlIGRpYWxvZyBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0IGNhbmNlbGFibGUodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NhbmNlbGFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgY2FuY2VsYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NhbmNlbGFibGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjga7jga/jgIFcImZhZGVcIiwgXCJub25lXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT4gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgYWZ0ZXIgdGhlIGRpYWxvZyBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovjgrPjg7zjg6vjg5Djg4Pjgq/jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgYWxlcnQgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXUEgYFByb21pc2VgIG9iamVjdCB0aGF0IHJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2hvdyhvcHRpb25zID0ge30pIHtcbiAgICBsZXQgY2FuY2VsID0gZmFsc2U7XG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8IGZ1bmN0aW9uKCkge307XG5cbiAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgIEFuaW1hdG9yRmFjdG9yeS5wYXJzZUFuaW1hdGlvbk9wdGlvbnNTdHJpbmcodGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbi1vcHRpb25zJykpXG4gICAgKTtcblxuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncHJlc2hvdycsIHtcbiAgICAgIGFsZXJ0RGlhbG9nOiB0aGlzLFxuICAgICAgY2FuY2VsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FuY2VsID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICghY2FuY2VsKSB7XG4gICAgICBjb25zdCB0cnlTaG93ID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9kb29yTG9jay5sb2NrKCk7XG4gICAgICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgIHRoaXMuX21hc2suc3R5bGUub3BhY2l0eSA9ICcxJztcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgICAgIGFuaW1hdG9yLnNob3codGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLl92aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgdW5sb2NrKCk7XG5cbiAgICAgICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0c2hvdycsIHthbGVydERpYWxvZzogdGhpc30pO1xuXG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIHRoaXMuX2Rvb3JMb2NrLndhaXRVbmxvY2soKCkgPT4gcmVzb2x2ZSh0cnlTaG93KCkpKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXNob3cgZXZlbnQuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJmYWRlXCJgIGFuZCBgXCJub25lXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwiZmFkZVwiLCBcIm5vbmVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiAgPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT4gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgYWZ0ZXIgdGhlIGRpYWxvZyBoYXMgYmVlbiBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu44OA44Kk44Ki44Ot44Kw44GM6ZaJ44GY44Gf5pmC44Gr5ZG844Gz5Ye644GV44KM44KL44Kz44O844Or44OQ44OD44Kv44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdGhlIGFsZXJ0IGRpYWxvZy5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgpLplonjgZjjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgaGlkZGVuIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgaGlkZShvcHRpb25zID0ge30pIHtcbiAgICBsZXQgY2FuY2VsID0gZmFsc2U7XG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8IGZ1bmN0aW9uKCkge307XG5cbiAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgIEFuaW1hdG9yRmFjdG9yeS5wYXJzZUFuaW1hdGlvbk9wdGlvbnNTdHJpbmcodGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbi1vcHRpb25zJykpXG4gICAgKTtcblxuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncHJlaGlkZScsIHtcbiAgICAgIGFsZXJ0RGlhbG9nOiB0aGlzLFxuICAgICAgY2FuY2VsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FuY2VsID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICghY2FuY2VsKSB7XG4gICAgICBjb25zdCB0cnlIaWRlID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9kb29yTG9jay5sb2NrKCk7XG4gICAgICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgYW5pbWF0b3IuaGlkZSh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICB1bmxvY2soKTtcblxuICAgICAgICAgICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RoaWRlJywge2FsZXJ0RGlhbG9nOiB0aGlzfSk7XG5cbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgdGhpcy5fZG9vckxvY2sud2FpdFVubG9jaygoKSA9PiByZXNvbHZlKHRyeUhpZGUoKSkpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ2FuY2VsZWQgaW4gcHJlaGlkZSBldmVudC4nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZpc2libGVcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZGlhbG9nIGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlzaWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuICBnZXQgb25EZXZpY2VCYWNrQnV0dG9uKCkge1xuICAgIHJldHVybiB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcjtcbiAgfVxuXG4gIHNldCBvbkRldmljZUJhY2tCdXR0b24oY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5fYmFja0J1dHRvbkhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIodGhpcywgY2FsbGJhY2spO1xuICB9XG5cbiAgX2NhbmNlbCgpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxhYmxlICYmICF0aGlzLl9ydW5uaW5nKSB7XG4gICAgICB0aGlzLl9ydW5uaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaGlkZSgpXG4gICAgICAgIC50aGVuKFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnZGlhbG9nLWNhbmNlbCcpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgKCkgPT4gdGhpcy5fcnVubmluZyA9IGZhbHNlXG4gICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24gPSBlID0+IHRoaXMuY2FuY2VsYWJsZSA/IHRoaXMuX2NhbmNlbCgpIDogZS5jYWxsUGFyZW50SGFuZGxlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX21hc2suYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZENhbmNlbCwgZmFsc2UpO1xuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gbnVsbDtcblxuICAgIHRoaXMuX21hc2sucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZENhbmNlbC5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdhbmltYXRpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gICAgZWxzZSBpZiAobmFtZSA9PT0gJ2FuaW1hdGlvbicpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge0RpYWxvZ0FuaW1hdG9yfSBBbmltYXRvclxuICAgKi9cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvci5wcm90b3R5cGUgaW5zdGFuY2VvZiBBbGVydERpYWxvZ0FuaW1hdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0IE9uc0FsZXJ0RGlhbG9nRWxlbWVudC5BbGVydERpYWxvZ0FuaW1hdG9yJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgQWxlcnREaWFsb2dBbmltYXRvcigpIHtcbiAgICByZXR1cm4gQWxlcnREaWFsb2dBbmltYXRvcjtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1hbGVydC1kaWFsb2cnLCBBbGVydERpYWxvZ0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbnZhciBzY2hlbWUgPSB7XG4gICcnOiAnYmFjay1idXR0b24tLSonLFxuICAnLmJhY2stYnV0dG9uX19pY29uJzogJ2JhY2stYnV0dG9uLS0qX19pY29uJyxcbiAgJy5iYWNrLWJ1dHRvbl9fbGFiZWwnOiAnYmFjay1idXR0b24tLSpfX2xhYmVsJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYmFjay1idXR0b25cbiAqIEBjYXRlZ29yeSBuYXZpZ2F0aW9uXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIEJhY2sgYnV0dG9uIGNvbXBvbmVudCBmb3IgYDxvbnMtdG9vbGJhcj5gLiBQdXQgaXQgaW4gdGhlIGxlZnQgcGFydCBvZiB0aGUgYDxvbnMtdG9vbGJhcj5gLlxuICpcbiAqICAgICBJdCB3aWxsIGZpbmQgdGhlIHBhcmVudCBgPG9ucy1uYXZpZ2F0b3I+YCBlbGVtZW50IGFuZCBwb3AgYSBwYWdlIHdoZW4gY2xpY2tlZC4gVGhpcyBiZWhhdmlvciBjYW4gYmUgb3ZlcnJpZGVuIGJ5IHNwZWNpZnlpbmcgdGhlIGBvbkNsaWNrYCBwcm9wZXJ0eS5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiBhSG1HTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL25hdmlnYXRvclxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1vbnMtdG9vbGJhciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW5hdmlnYXRvclxuICogICBbZW5db25zLW5hdmlnYXRvciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLW5hdmlnYXRvcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10b29sYmFyPlxuICogICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgIDxvbnMtYmFjay1idXR0b24+QmFjazwvb25zLWJhY2stYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIFRpdGxlXG4gKiAgIDxkaXY+XG4gKiA8L29ucy10b29sYmFyPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgYmFjayBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjga7opovjgZ/nm67jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLl9vcHRpb25zID0ge307XG4gICAgdGhpcy5fYm91bmRPbkNsaWNrID0gdGhpcy5fb25DbGljay5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2JhY2stYnV0dG9uJyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcuYmFjay1idXR0b25fX2xhYmVsJykpIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2xhYmVsJyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgbGFiZWwuYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQobGFiZWwpO1xuICAgIH1cblxuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrLWJ1dHRvbl9faWNvbicpKSB7XG4gICAgICBjb25zdCBpY29uID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2ljb24nKTtcblxuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUoaWNvbiwgdGhpcy5jaGlsZHJlblswXSk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcHRpb25zIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMuYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIFwic2xpZGVcIiwgXCJsaWZ0XCIsIFwiZmFkZVwiIGFuZCBcIm5vbmVcIi5cbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIFwiLWlvc1wiIG9yIFwiLW1kXCJcbiAgICogICAgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gXCJsaWZ0LWlvc1wiLCBcImxpZnQtbWRcIi4gRGVmYXVsdHMgdmFsdWVzIGFyZSBcInNsaWRlLWlvc1wiIGFuZCBcImZhZGUtbWRcIi5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YFsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmNhbGxiYWNrXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg6Hjgr3jg4Pjg4njgavjgojjgovnlLvpnaLpgbfnp7vjgYzntYLkuobjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMucmVmcmVzaFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHByZXZpb3VzIHBhZ2Ugd2lsbCBiZSByZWZyZXNoZWQgKGRlc3Ryb3llZCBhbmQgY3JlYXRlZCBhZ2FpbikgYmVmb3JlIHBvcFBhZ2UgYWN0aW9uLlsvZW5dXG4gICAqICAgW2phXXBvcFBhZ2XjgZnjgovliY3jgavjgIHliY3jgavjgYLjgovjg5rjg7zjgrjjgpLnlJ/miJDjgZfjgarjgYrjgZfjgabmm7TmlrDjgZnjgovloLTlkIjjgat0cnVl44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBvcHRpb25zKCkge1xuICAgIHJldHVybiB0aGlzLl9vcHRpb25zO1xuICB9XG5cbiAgc2V0IG9wdGlvbnMob2JqZWN0KSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9iamVjdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25DbGlja1xuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Vc2VkIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJhY2sgYnV0dG9uIGJlaGF2aW9yLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBfb25DbGljaygpIHtcbiAgICBpZiAodGhpcy5vbkNsaWNrKSB7XG4gICAgICB0aGlzLm9uQ2xpY2suYXBwbHkodGhpcyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgY29uc3QgbmF2aWdhdG9yID0gdXRpbC5maW5kUGFyZW50KHRoaXMsICdvbnMtbmF2aWdhdG9yJyk7XG4gICAgICBpZiAobmF2aWdhdG9yKSB7XG4gICAgICAgIG5hdmlnYXRvci5wb3BQYWdlKHRoaXMub3B0aW9ucyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gIH1cblxuICBzaG93KCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdpbmxpbmUtYmxvY2snO1xuICB9XG5cbiAgaGlkZSgpIHtcbiAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYmFjay1idXR0b24nLCBCYWNrQnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IHNjaGVtZSA9IHsnJzogJ2JvdHRvbS1iYXItLSonfTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYm90dG9tLXRvb2xiYXJcbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVRvb2xiYXIgY29tcG9uZW50IHRoYXQgaXMgcG9zaXRpb25lZCBhdCB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLlsvZW5dXG4gKiAgIFtqYV3jg5rjg7zjgrjkuIvpg6jjgavphY3nva7jgZXjgozjgovjg4Tjg7zjg6vjg5Djg7znlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIHRyYW5zcGFyZW50XG4gKiAgIFtlbl1NYWtlIHRoZSB0b29sYmFyIHRyYW5zcGFyZW50LlsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7og4zmma/jgpLpgI/mmI7jgavjgZfjgabooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXIgW2VuXW9ucy10b29sYmFyIGNvbXBvbmVudFsvZW5dW2phXW9ucy10b29sYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWJvdHRvbS10b29sYmFyPlxuICogICBDb250ZW50XG4gKiA8L29ucy1ib3R0b20tdG9vbGJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQm90dG9tVG9vbGJhckVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgdG9vbGJhci5bL2VuXVxuICAgKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7opovjgZ/nm67jga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnYm90dG9tLWJhcicpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1wYWdlJykpIHtcbiAgICAgIHRoaXMucGFyZW50Tm9kZS5jbGFzc0xpc3QuYWRkKCdwYWdlLXdpdGgtYm90dG9tLXRvb2xiYXInKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllciddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgfVxuICB9XG5cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYm90dG9tLXRvb2xiYXInLCBCb3R0b21Ub29sYmFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IHNjaGVtZSA9IHsnJzogJ2J1dHRvbi0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1idXR0b25cbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgb3V0bGluZVxuICogICBbZW5dQnV0dG9uIHdpdGggb3V0bGluZSBhbmQgdHJhbnNwYXJlbnQgYmFja2dyb3VuZFsvZW5dXG4gKiAgIFtqYV3jgqLjgqbjg4jjg6njgqTjg7PjgpLmjIHjgaPjgZ/jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxpZ2h0XG4gKiAgIFtlbl1CdXR0b24gdGhhdCBkb2Vzbid0IHN0YW5kIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gf44Gq44GE44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBxdWlldFxuICogICBbZW5dQnV0dG9uIHdpdGggbm8gb3V0bGluZSBhbmQgb3IgYmFja2dyb3VuZC4uWy9lbl1cbiAqICAgW2phXeaeoOe3muOChOiDjOaZr+OBjOeEoeOBhOaWh+Wtl+OBoOOBkeOBruODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgY3RhXG4gKiAgIFtlbl1CdXR0b24gdGhhdCByZWFsbHkgc3RhbmRzIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gk44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBsYXJnZVxuICogICBbZW5dTGFyZ2UgYnV0dG9uIHRoYXQgY292ZXJzIHRoZSB3aWR0aCBvZiB0aGUgc2NyZWVuLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgovlpKfjgY3jgarjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxhcmdlLS1xdWlldFxuICogICBbZW5dTGFyZ2UgcXVpZXQgYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotxdWlldOODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbGFyZ2UtLWN0YVxuICogICBbZW5dTGFyZ2UgY2FsbCB0byBhY3Rpb24gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotjdGHjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gYnV0dG9uWy9lbl1cbiAqICAgW2phXeODnuODhuODquOCouODq+ODh+OCtuOCpOODs+OBruODnOOCv+ODs1svamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWwtLWZsYXRcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBmbGF0IGJ1dHRvblsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg5Xjg6njg4Pjg4jjg5zjgr/jg7NbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBCdXR0b24gY29tcG9uZW50LiBJZiB5b3Ugd2FudCB0byBwbGFjZSBhIGJ1dHRvbiBpbiBhIHRvb2xiYXIsIHVzZSBgPG9ucy10b29sYmFyLWJ1dHRvbj5gIG9yIGA8b25zLWJhY2stYnV0dG9uPmAgaW5zdGVhZC5cbiAqXG4gKiAgICAgV2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gYnV0dG9uIHdpdGggYSByaXBwbGUgZWZmZWN0IG9uIEFuZHJvaWQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg5zjgr/jg7PnlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgILjg4Tjg7zjg6vjg5Djg7zjgavjg5zjgr/jg7PjgpLoqK3nva7jgZnjgovloLTlkIjjga/jgIFvbnMtdG9vbGJhci1idXR0b27jgoLjgZfjgY/jga9vbnMtYmFjay1idXR0b27jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgpLkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gaExheXhcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9idXR0b25cbiAqIEBndWlkZSBCdXR0b24gW2VuXUd1aWRlIGZvciBgPG9ucy1idXR0b24+YFsvZW5dW2phXTxvbnMtYnV0dG9uPuOBruS9v+OBhOaWuVsvamFdXG4gKiBAZ3VpZGUgdXNpbmctbW9kaWZpZXIgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZ3VpZGUgY3Jvc3MtcGxhdGZvcm0tc3R5bGluZyBbZW5dSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dW2phXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYnV0dG9uIG1vZGlmaWVyPVwibGFyZ2UtLWN0YVwiPlxuICogICBUYXAgTWVcbiAqIDwvb25zLWJ1dHRvbj5cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5zjgr/jg7Pjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0LlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7PjgpLnhKHlirnljJbjgZnjgovloLTlkIjjga/mjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3JpcHBsZSddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGJ1dHRvbiBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2J1dHRvbicpO1xuXG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBfdXBkYXRlUmlwcGxlKCkge1xuICAgIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMpO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWJ1dHRvbicsIEJ1dHRvbkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5jb25zdCBzY2hlbWUgPSB7Jyc6ICdjYXJvdXNlbC1pdGVtLS0qJ307XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWNhcm91c2VsLWl0ZW1cbiAqIEBjYXRlZ29yeSBjYXJvdXNlbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBDYXJvdXNlbCBpdGVtIGNvbXBvbmVudC4gVXNlZCBhcyBhIGNoaWxkIG9mIHRoZSBgPG9ucy1jYXJvdXNlbD5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4geGJiek9RXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvY2Fyb3VzZWxcbiAqIEBzZWVhbHNvIG9ucy1jYXJvdXNlbFxuICogICBbZW5dYDxvbnMtY2Fyb3VzZWw+YCBjb21wb25lbnRzWy9lbl1cbiAqICAgW2phXTxvbnMtY2Fyb3VzZWw+44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWNhcm91c2VsIHN0eWxlPVwid2lkdGg6IDEwMCU7IGhlaWdodDogMjAwcHhcIj5cbiAqICAgPG9ucy1jYXJvdXNlbC1pdGVtPlxuICogICAgLi4uXG4gKiAgIDwvb25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgIDxvbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgIC4uLlxuICogICA8L29ucy1jYXJvdXNlbC1pdGVtPlxuICogPC9vbnMtY2Fyb3VzZWw+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhcm91c2VsSXRlbUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJ11cbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtY2Fyb3VzZWwtaXRlbScsIENhcm91c2VsSXRlbUVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IEdlc3R1cmVEZXRlY3RvciBmcm9tICcuLi9vbnMvZ2VzdHVyZS1kZXRlY3Rvcic7XG5pbXBvcnQgRG9vckxvY2sgZnJvbSAnLi4vb25zL2Rvb3Jsb2NrJztcblxuY29uc3QgVmVydGljYWxNb2RlVHJhaXQgPSB7XG5cbiAgX2dldFNjcm9sbERlbHRhOiBmdW5jdGlvbihldmVudCkge1xuICAgIHJldHVybiBldmVudC5nZXN0dXJlLmRlbHRhWTtcbiAgfSxcblxuICBfZ2V0U2Nyb2xsVmVsb2NpdHk6IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgcmV0dXJuIGV2ZW50Lmdlc3R1cmUudmVsb2NpdHlZO1xuICB9LFxuXG4gIF9nZXRFbGVtZW50U2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgaWYgKCF0aGlzLl9jdXJyZW50RWxlbWVudFNpemUpIHtcbiAgICAgIHRoaXMuX2N1cnJlbnRFbGVtZW50U2l6ZSA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9jdXJyZW50RWxlbWVudFNpemU7XG4gIH0sXG5cbiAgX2dlbmVyYXRlU2Nyb2xsVHJhbnNmb3JtOiBmdW5jdGlvbihzY3JvbGwpIHtcbiAgICByZXR1cm4gJ3RyYW5zbGF0ZTNkKDBweCwgJyArIC1zY3JvbGwgKyAncHgsIDBweCknO1xuICB9LFxuXG4gIF91cGRhdGVEaW1lbnNpb25EYXRhOiBmdW5jdGlvbigpe1xuICAgIHRoaXMuX3N0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcyk7XG4gICAgdGhpcy5fZGltZW5zaW9ucyA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIH0sXG5cbiAgX3VwZGF0ZU9mZnNldDogZnVuY3Rpb24oKXtcbiAgICBpZiAodGhpcy5jZW50ZXJlZCkge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gKHRoaXMuX2RpbWVuc2lvbnMuaGVpZ2h0IHx8IDApIC0gcGFyc2VJbnQodGhpcy5fc3R5bGUucGFkZGluZ1RvcCwgMTApIC0gcGFyc2VJbnQodGhpcy5fc3R5bGUucGFkZGluZ0JvdHRvbSwgMTApO1xuICAgICAgdGhpcy5fb2Zmc2V0ID0gLShoZWlnaHQgLSB0aGlzLl9nZXRDYXJvdXNlbEl0ZW1TaXplKCkpIC8gMjtcbiAgICB9XG4gIH0sXG5cbiAgX2xheW91dENhcm91c2VsSXRlbXM6IGZ1bmN0aW9uKCkge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtRWxlbWVudHMoKTtcblxuICAgIGNvbnN0IHNpemVBdHRyID0gdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZUF0dHIoKTtcbiAgICBjb25zdCBzaXplSW5mbyA9IHRoaXMuX2RlY29tcG9zZVNpemVTdHJpbmcoc2l6ZUF0dHIpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgY2hpbGRyZW5baV0uc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgY2hpbGRyZW5baV0uc3R5bGUuaGVpZ2h0ID0gc2l6ZUF0dHI7XG4gICAgICBjaGlsZHJlbltpXS5zdHlsZS52aXNpYmlsaXR5ID0gJ3Zpc2libGUnO1xuICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gKGkgKiBzaXplSW5mby5udW1iZXIpICsgc2l6ZUluZm8udW5pdDtcbiAgICB9XG4gIH0sXG5cbiAgX3NldHVwOiBmdW5jdGlvbigpe1xuICAgIHRoaXMuX3VwZGF0ZURpbWVuc2lvbkRhdGEoKTtcbiAgICB0aGlzLl91cGRhdGVPZmZzZXQoKTtcbiAgICB0aGlzLl9sYXlvdXRDYXJvdXNlbEl0ZW1zKCk7XG4gIH1cbn07XG5cbmNvbnN0IEhvcml6b250YWxNb2RlVHJhaXQgPSB7XG5cbiAgX2dldFNjcm9sbERlbHRhOiBmdW5jdGlvbihldmVudCkge1xuICAgIHJldHVybiBldmVudC5nZXN0dXJlLmRlbHRhWDtcbiAgfSxcblxuICBfZ2V0U2Nyb2xsVmVsb2NpdHk6IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgcmV0dXJuIGV2ZW50Lmdlc3R1cmUudmVsb2NpdHlYO1xuICB9LFxuXG4gIF9nZXRFbGVtZW50U2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgaWYgKCF0aGlzLl9jdXJyZW50RWxlbWVudFNpemUpIHtcbiAgICAgIHRoaXMuX2N1cnJlbnRFbGVtZW50U2l6ZSA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRFbGVtZW50U2l6ZTtcbiAgfSxcblxuICBfZ2VuZXJhdGVTY3JvbGxUcmFuc2Zvcm06IGZ1bmN0aW9uKHNjcm9sbCkge1xuICAgIHJldHVybiAndHJhbnNsYXRlM2QoJyArIC1zY3JvbGwgKyAncHgsIDBweCwgMHB4KSc7XG4gIH0sXG5cbiAgX3VwZGF0ZURpbWVuc2lvbkRhdGE6IGZ1bmN0aW9uKCl7XG4gICAgdGhpcy5fc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzKTtcbiAgICB0aGlzLl9kaW1lbnNpb25zID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgfSxcblxuICBfdXBkYXRlT2Zmc2V0OiBmdW5jdGlvbigpe1xuICAgIGlmICh0aGlzLmNlbnRlcmVkKSB7XG4gICAgICBjb25zdCB3aWR0aCA9ICh0aGlzLl9kaW1lbnNpb25zLndpZHRoIHx8IDApIC0gcGFyc2VJbnQodGhpcy5fc3R5bGUucGFkZGluZ0xlZnQsIDEwKSAtIHBhcnNlSW50KHRoaXMuX3N0eWxlLnBhZGRpbmdSaWdodCwgMTApO1xuICAgICAgdGhpcy5fb2Zmc2V0ID0gLSh3aWR0aCAtIHRoaXMuX2dldENhcm91c2VsSXRlbVNpemUoKSkgLyAyO1xuICAgIH1cbiAgfSxcblxuICBfbGF5b3V0Q2Fyb3VzZWxJdGVtczogZnVuY3Rpb24oKSB7XG4gICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpO1xuXG4gICAgY29uc3Qgc2l6ZUF0dHIgPSB0aGlzLl9nZXRDYXJvdXNlbEl0ZW1TaXplQXR0cigpO1xuICAgIGNvbnN0IHNpemVJbmZvID0gdGhpcy5fZGVjb21wb3NlU2l6ZVN0cmluZyhzaXplQXR0cik7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjaGlsZHJlbltpXS5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICBjaGlsZHJlbltpXS5zdHlsZS53aWR0aCA9IHNpemVBdHRyO1xuICAgICAgY2hpbGRyZW5baV0uc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJztcbiAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLmxlZnQgPSAoaSAqIHNpemVJbmZvLm51bWJlcikgKyBzaXplSW5mby51bml0O1xuICAgIH1cbiAgfSxcblxuICBfc2V0dXA6IGZ1bmN0aW9uKCl7XG4gICAgdGhpcy5fdXBkYXRlRGltZW5zaW9uRGF0YSgpO1xuICAgIHRoaXMuX3VwZGF0ZU9mZnNldCgpO1xuICAgIHRoaXMuX2xheW91dENhcm91c2VsSXRlbXMoKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtY2Fyb3VzZWxcbiAqIEBjYXRlZ29yeSBjYXJvdXNlbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBDYXJvdXNlbCBjb21wb25lbnQuIEEgY2Fyb3VzZWwgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBzZXZlcmFsIGl0ZW1zIGluIHRoZSBzYW1lIHNwYWNlLlxuICpcbiAqICAgICBUaGUgY29tcG9uZW50IHN1cHBvcnRzIGRpc3BsYXlpbmcgY29udGVudCBib3RoIGhvcml6b250YWxseSBhbmQgdmVydGljYWxseS4gVGhlIHVzZXIgY2FuIHNjcm9sbCB0aHJvdWdoIHRoZSBpdGVtcyBieSBkcmFnZ2luZyBhbmQgaXQgY2FuIGFsc28gYmUgY29udHJvbGxlciBwcm9ncmFtbWF0aWNhbGx5LlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhiYnpPUVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2Nhcm91c2VsXG4gKiBAc2VlYWxzbyBvbnMtY2Fyb3VzZWwtaXRlbVxuICogICBbZW5dYDxvbnMtY2Fyb3VzZWwtaXRlbT5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtY2Fyb3VzZWwtaXRlbeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1jYXJvdXNlbCBzdHlsZT1cIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDIwMHB4XCI+XG4gKiAgIDxvbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgIC4uLlxuICogICA8L29ucy1jYXJvdXNlbC1pdGVtPlxuICogICA8b25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgICAuLi5cbiAqICAgPC9vbnMtY2Fyb3VzZWwtaXRlbT5cbiAqIDwvb25zLWNhcm91c2VsPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYXJvdXNlbEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0Y2hhbmdlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBjdXJyZW50IGNhcm91c2VsIGl0ZW0gaGFzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo6KGo56S644GX44Gm44GE44KL44Kr44Or44O844K744Or44Gu6KaB57Sg44GM5aSJ44KP44Gj44Gf5pmC44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuY2Fyb3VzZWxcbiAgICogICBbZW5dQ2Fyb3VzZWwgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOBjOeZuueBq+OBl+OBn0Nhcm91c2Vs44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmFjdGl2ZUluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgYWN0aXZlIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOCouOCr+ODhuOCo+ODluOBq+OBquOBo+OBpuOBhOOCi+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOAglsvamFdXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBldmVudC5sYXN0QWN0aXZlSW5kZXhcbiAgICogICBbZW5dUHJldmlvdXMgYWN0aXZlIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeS7peWJjeOCouOCr+ODhuOCo+ODluOBoOOBo+OBn+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcmVmcmVzaFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgd2hlbiB0aGUgY2Fyb3VzZWwgaGFzIGJlZW4gcmVmcmVzaGVkLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+OBjOabtOaWsOOBleOCjOOBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmNhcm91c2VsXG4gICAqICAgW2VuXUNhcm91c2VsIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgYznmbrngavjgZfjgZ9DYXJvdXNlbOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgb3ZlcnNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgd2hlbiB0aGUgY2Fyb3VzZWwgaGFzIGJlZW4gb3ZlcnNjcm9sbGVkLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+OBjOOCquODvOODkOODvOOCueOCr+ODreODvOODq+OBl+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmNhcm91c2VsXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGNhcm91c2VsIGhhcyBiZWVuIHJlZnJlc2hlZC5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjgYzmm7TmlrDjgZXjgozjgZ/mmYLjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuYWN0aXZlSW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBhY3RpdmUgaW5kZXguWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL6KaB57Sg44Gu44Kk44Oz44OH44OD44Kv44K544CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50LmRpcmVjdGlvblxuICAgKiAgIFtlbl1DYW4gYmUgb25lIG9mIGVpdGhlciBcInVwXCIsIFwiZG93blwiLCBcImxlZnRcIiBvciBcInJpZ2h0XCIuWy9lbl1cbiAgICogICBbamFd44Kq44O844OQ44O844K544Kv44Ot44O844Or44GV44KM44Gf5pa55ZCR44GM5b6X44KJ44KM44G+44GZ44CCXCJ1cFwiLCBcImRvd25cIiwgXCJsZWZ0XCIsIFwicmlnaHRcIuOBruOBhOOBmuOCjOOBi+OBruaWueWQkeOBjOa4oeOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LndhaXRUb1JldHVyblxuICAgKiAgIFtlbl1UYWtlcyBhIDxjb2RlPlByb21pc2U8L2NvZGU+IG9iamVjdCBhcyBhbiBhcmd1bWVudC4gVGhlIGNhcm91c2VsIHdpbGwgbm90IHNjcm9sbCBiYWNrIHVudGlsIHRoZSBwcm9taXNlIGhhcyBiZWVuIHJlc29sdmVkIG9yIHJlamVjdGVkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOBr1Byb21pc2Xjgqrjg5bjgrjjgqfjgq/jg4jjgpLlvJXmlbDjgajjgZfjgablj5fjgZHlj5bjgorjgb7jgZnjgILmuKHjgZfjgZ9Qcm9taXNl44Kq44OW44K444Kn44Kv44OI44GMcmVzb2x2ZeOBleOCjOOCi+OBi3JlamVjdOOBleOCjOOCi+OBvuOBp+OAgeOCq+ODq+ODvOOCu+ODq+OBr+OCueOCr+ODreODvOODq+ODkOODg+OCr+OBl+OBvuOBm+OCk+OAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpcmVjdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGRpcmVjdGlvbiBvZiB0aGUgY2Fyb3VzZWwuIENhbiBiZSBlaXRoZXIgXCJob3Jpem9udGFsXCIgb3IgXCJ2ZXJ0aWNhbFwiLiBEZWZhdWx0IGlzIFwiaG9yaXpvbnRhbFwiLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+OBruaWueWQkeOCkuaMh+WumuOBl+OBvuOBmeOAglwiaG9yaXpvbnRhbFwi44GLXCJ2ZXJ0aWNhbFwi44KS5oyH5a6a44Gn44GN44G+44GZ44CCXCJob3Jpem9udGFsXCLjgYzjg4fjg5Xjgqnjg6vjg4jlgKTjgafjgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmdWxsc2NyZWVuXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgY292ZXIgdGhlIHdob2xlIHNjcmVlbi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovjgajjgIFhYnNvbHV0ZeODneOCuOOCt+ODp+ODs+OCkuS9v+OBo+OBpuOCq+ODq+ODvOOCu+ODq+OBjOiHquWLleeahOOBq+eUu+mdouOBhOOBo+OBseOBhOOBq+W6g+OBjOOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG92ZXJzY3JvbGxhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgYmUgc2Nyb2xsYWJsZSBvdmVyIHRoZSBlZGdlLiBJdCB3aWxsIGJvdW5jZSBiYWNrIHdoZW4gcmVsZWFzZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB44K/44OD44OB44KE44OJ44Op44OD44Kw44Gn56uv44G+44Gn44K544Kv44Ot44O844Or44GX44Gf5pmC44Gr44CB44OQ44Km44Oz44OJ44GZ44KL44KI44GG44Gq5Yq55p6c44GM5b2T44Gf44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2VudGVyZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgY2Fyb3VzZWwgdGhlbiB0aGUgc2VsZWN0ZWQgaXRlbSB3aWxsIGJlIGluIHRoZSBjZW50ZXIgb2YgdGhlIGNhcm91c2VsIGluc3RlYWQgb2YgdGhlIGJlZ2lubmluZy4gVXNlZnVsIG9ubHkgd2hlbiB0aGUgaXRlbXMgYXJlIHNtYWxsZXIgdGhhbiB0aGUgY2Fyb3VzZWwuIFsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgemBuOOCk+OBp+OBhOOCi29ucy1jYXJvdXNlbC1pdGVt44Gv44Kr44Or44O844K744Or44Gu55yf44KT5Lit44G46KGM44GN44G+44GZ44CC6aCF55uu44GM44Kr44Or44O844K744Or44KI44KK44KC5bCP44GV44GE5aC05ZCI44Gr44Gu44G/44CB44GT44KM44Gv5L6/5Yip44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaXRlbS13aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICAgW2VuXW9ucy1jYXJvdXNlbC1pdGVtJ3Mgd2lkdGguIE9ubHkgd29ya3Mgd2hlbiB0aGUgZGlyZWN0aW9uIGlzIHNldCB0byBcImhvcml6b250YWxcIi5bL2VuXVxuICAgKiAgICBbamFdb25zLWNhcm91c2VsLWl0ZW3jga7luYXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lsZ7mgKfjga/jgIFkaXJlY3Rpb27lsZ7mgKfjgatcImhvcml6b250YWxcIuOCkuaMh+WumuOBl+OBn+aZguOBruOBv+acieWKueOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGl0ZW0taGVpZ2h0XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1vbnMtY2Fyb3VzZWwtaXRlbSdzIGhlaWdodC4gT25seSB3b3JrcyB3aGVuIHRoZSBkaXJlY3Rpb24gaXMgc2V0IHRvIFwidmVydGljYWxcIi5bL2VuXVxuICAgKiAgIFtqYV1vbnMtY2Fyb3VzZWwtaXRlbeOBrumrmOOBleOCkuaMh+WumuOBl+OBvuOBmeOAguOBk+OBruWxnuaAp+OBr+OAgWRpcmVjdGlvbuWxnuaAp+OBq1widmVydGljYWxcIuOCkuaMh+WumuOBl+OBn+aZguOBruOBv+acieWKueOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGF1dG8tc2Nyb2xsXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgYmUgYXV0b21hdGljYWxseSBzY3JvbGxlZCB0byB0aGUgY2xvc2VzdCBpdGVtIGJvcmRlciB3aGVuIHJlbGVhc2VkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeS4gOeVqui/keOBhGNhcm91c2VsLWl0ZW3jga7looPnlYzjgb7jgafoh6rli5XnmoTjgavjgrnjgq/jg63jg7zjg6vjgZnjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhdXRvLXNjcm9sbC1yYXRpb1xuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICAgW2VuXUEgbnVtYmVyIGJldHdlZW4gMC4wIGFuZCAxLjAgdGhhdCBzcGVjaWZpZXMgaG93IG11Y2ggdGhlIHVzZXIgbXVzdCBkcmFnIHRoZSBjYXJvdXNlbCBpbiBvcmRlciBmb3IgaXQgdG8gYXV0byBzY3JvbGwgdG8gdGhlIG5leHQgaXRlbS5bL2VuXVxuICAgKiAgICBbamFdMC4w44GL44KJMS4w44G+44Gn44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CC44Kr44Or44O844K744Or44Gu6KaB57Sg44KS44Gp44KM44GQ44KJ44GE44Gu5Ymy5ZCI44G+44Gn44OJ44Op44OD44Kw44GZ44KL44Go5qyh44Gu6KaB57Sg44Gr6Ieq5YuV55qE44Gr44K544Kv44Ot44O844Or44GZ44KL44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGVhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIGNhbiBiZSBzY3JvbGxlZCBieSBkcmFnIG9yIHN3aXBlLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeOCq+ODq+ODvOOCu+ODq+OCkuOCueODr+OCpOODl+OChOODieODqeODg+OCsOOBp+enu+WLleOBp+OBjeOCi+OCiOOBhuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIGlzIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgWRyYWfjgoR0b3VjaOOChHN3aXBl44KS5Y+X44GR5LuY44GR44Gq44GP44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5pdGlhbC1pbmRleFxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGluZGV4IG9mIHRoZSBvbnMtY2Fyb3VzZWwtaXRlbSB0byBzaG93IGluaXRpYWxseS4gRGVmYXVsdCBpcyAwLlsvZW5dXG4gICAqICAgW2phXeacgOWIneOBq+ihqOekuuOBmeOCi29ucy1jYXJvdXNlbC1pdGVt44KSMOWni+OBvuOCiuOBruOCpOODs+ODh+ODg+OCr+OCueOBp+aMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOWApOOBryAwIOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGF1dG8tcmVmcmVzaFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hlbiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgYXV0b21hdGljYWxseSByZWZyZXNoIHdoZW4gdGhlIG51bWJlciBvZiBjaGlsZCBub2RlcyBjaGFuZ2UuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB5a2Q6KaB57Sg44Gu5pWw44GM5aSJ44KP44KL44Go44Kr44Or44O844K744Or44Gv6Ieq5YuV55qE44Gr5pu05paw44GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgILkvovvvJp7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fZG9vckxvY2sgPSBuZXcgRG9vckxvY2soKTtcbiAgICB0aGlzLl9zY3JvbGwgPSAwO1xuICAgIHRoaXMuX29mZnNldCA9IDA7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gMDtcblxuICAgIHRoaXMuX2JvdW5kT25EcmFnID0gdGhpcy5fb25EcmFnLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRPbkRyYWdFbmQgPSB0aGlzLl9vbkRyYWdFbmQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9ib3VuZE9uUmVzaXplID0gdGhpcy5fb25SZXNpemUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX21peGluKHRoaXMuX2lzVmVydGljYWwoKSA/IFZlcnRpY2FsTW9kZVRyYWl0IDogSG9yaXpvbnRhbE1vZGVUcmFpdCk7XG4gIH1cblxuICBfb25SZXNpemUoKSB7XG4gICAgY29uc3QgaSA9IHRoaXMuX3Njcm9sbCAvIHRoaXMuX2N1cnJlbnRFbGVtZW50U2l6ZTtcbiAgICBkZWxldGUgdGhpcy5fY3VycmVudEVsZW1lbnRTaXplO1xuICAgIHRoaXMuc2V0QWN0aXZlSW5kZXgoaSk7XG4gIH1cblxuICBfb25EaXJlY3Rpb25DaGFuZ2UoKSB7XG4gICAgaWYgKHRoaXMuX2lzVmVydGljYWwoKSkge1xuICAgICAgdGhpcy5zdHlsZS5vdmVyZmxvd1ggPSAnYXV0byc7XG4gICAgICB0aGlzLnN0eWxlLm92ZXJmbG93WSA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0eWxlLm92ZXJmbG93WCA9ICcnO1xuICAgICAgdGhpcy5zdHlsZS5vdmVyZmxvd1kgPSAnYXV0byc7XG4gICAgfVxuXG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gIH1cblxuICBfc2F2ZUxhc3RTdGF0ZSgpIHtcbiAgICB0aGlzLl9sYXN0U3RhdGUgPSB7XG4gICAgICBlbGVtZW50U2l6ZTogdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpLFxuICAgICAgY2Fyb3VzZWxFbGVtZW50Q291bnQ6IHRoaXMuaXRlbUNvdW50LFxuICAgICAgd2lkdGg6IHRoaXMuX2dldENhcm91c2VsSXRlbVNpemUoKSAqIHRoaXMuaXRlbUNvdW50XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqL1xuICBfZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpIHtcbiAgICBjb25zdCBzaXplQXR0ciA9IHRoaXMuX2dldENhcm91c2VsSXRlbVNpemVBdHRyKCk7XG4gICAgY29uc3Qgc2l6ZUluZm8gPSB0aGlzLl9kZWNvbXBvc2VTaXplU3RyaW5nKHNpemVBdHRyKTtcbiAgICBjb25zdCBlbGVtZW50U2l6ZSA9IHRoaXMuX2dldEVsZW1lbnRTaXplKCk7XG5cbiAgICBpZiAoc2l6ZUluZm8udW5pdCA9PT0gJyUnKSB7XG4gICAgICByZXR1cm4gTWF0aC5yb3VuZChzaXplSW5mby5udW1iZXIgLyAxMDAgKiBlbGVtZW50U2l6ZSk7XG4gICAgfSBlbHNlIGlmIChzaXplSW5mby51bml0ID09PSAncHgnKSB7XG4gICAgICByZXR1cm4gc2l6ZUluZm8ubnVtYmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RhdGUnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKi9cbiAgX2dldEluaXRpYWxJbmRleCgpIHtcbiAgICBjb25zdCBpbmRleCA9IHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdpbml0aWFsLWluZGV4JyksIDEwKTtcblxuICAgIGlmICh0eXBlb2YgaW5kZXggPT09ICdudW1iZXInICYmICFpc05hTihpbmRleCkpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLm1pbihpbmRleCwgdGhpcy5pdGVtQ291bnQgLSAxKSwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBfZ2V0Q2Fyb3VzZWxJdGVtU2l6ZUF0dHIoKSB7XG4gICAgY29uc3QgYXR0ck5hbWUgPSAnaXRlbS0nICsgKHRoaXMuX2lzVmVydGljYWwoKSA/ICdoZWlnaHQnIDogJ3dpZHRoJyk7XG4gICAgY29uc3QgaXRlbVNpemVBdHRyID0gKCcnICsgdGhpcy5nZXRBdHRyaWJ1dGUoYXR0ck5hbWUpKS50cmltKCk7XG5cbiAgICByZXR1cm4gaXRlbVNpemVBdHRyLm1hdGNoKC9eXFxkKyhweHwlKSQvKSA/IGl0ZW1TaXplQXR0ciA6ICcxMDAlJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBfZGVjb21wb3NlU2l6ZVN0cmluZyhzaXplKSB7XG4gICAgY29uc3QgbWF0Y2hlcyA9IHNpemUubWF0Y2goL14oXFxkKykocHh8JSkvKTtcblxuICAgIHJldHVybiB7XG4gICAgICBudW1iZXI6IHBhcnNlSW50KG1hdGNoZXNbMV0sIDEwKSxcbiAgICAgIHVuaXQ6IG1hdGNoZXNbMl0sXG4gICAgfTtcbiAgfVxuXG4gIF9zZXR1cEluaXRpYWxJbmRleCgpIHtcbiAgICB0aGlzLl9zY3JvbGwgPSAodGhpcy5fb2Zmc2V0IHx8IDApICsgdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpICogdGhpcy5fZ2V0SW5pdGlhbEluZGV4KCk7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gdGhpcy5fZ2V0SW5pdGlhbEluZGV4KCk7XG4gICAgdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNldEFjdGl2ZUluZGV4XG4gICAqIEBzaWduYXR1cmUgc2V0QWN0aXZlSW5kZXgoaW5kZXgsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqICAgW2VuXVRoZSBpbmRleCB0aGF0IHRoZSBjYXJvdXNlbCBzaG91bGQgYmUgc2V0IHRvLlsvZW5dXG4gICAqICAgW2phXWNhcm91c2Vs6KaB57Sg44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIGFuaW1hdGlvbiBpcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgaW5kZXggb2YgdGhlIGA8b25zLWNhcm91c2VsLWl0ZW0+YCB0byBzaG93LlsvZW5dXG4gICAqICAgW2phXeihqOekuuOBmeOCi29ucy1jYXJvdXNlbC1pdGVt44KSaW5kZXjjgafmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0QWN0aXZlSW5kZXgoaW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmIChvcHRpb25zICYmIHR5cGVvZiBvcHRpb25zICE9ICdvYmplY3QnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ29wdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QuIFlvdSBzdXBwbGllZCAnICsgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zID0gdXRpbC5leHRlbmQoXG4gICAgICB7IGR1cmF0aW9uOiAwLjMsIHRpbWluZzogJ2N1YmljLWJlemllciguMSwgLjcsIC4xLCAxKScgfSxcbiAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgIHRoaXMuaGFzQXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpID8gdXRpbC5hbmltYXRpb25PcHRpb25zUGFyc2UodGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbi1vcHRpb25zJykpIDoge31cbiAgICApO1xuXG4gICAgaW5kZXggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihpbmRleCwgdGhpcy5pdGVtQ291bnQgLSAxKSk7XG4gICAgY29uc3Qgc2Nyb2xsID0gKHRoaXMuX29mZnNldCB8fCAwKSArIHRoaXMuX2dldENhcm91c2VsSXRlbVNpemUoKSAqIGluZGV4O1xuICAgIGNvbnN0IG1heCA9IHRoaXMuX2NhbGN1bGF0ZU1heFNjcm9sbCgpO1xuXG4gICAgdGhpcy5fc2Nyb2xsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCBzY3JvbGwpKTtcbiAgICByZXR1cm4gdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsLCBvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMuX3RyeUZpcmVQb3N0Q2hhbmdlRXZlbnQoKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0pO1xuXG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBnZXRBY3RpdmVJbmRleFxuICAgKiBAc2lnbmF0dXJlIGdldEFjdGl2ZUluZGV4KClcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKiAgIFtlbl1UaGUgY3VycmVudCBjYXJvdXNlbCBpdGVtIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBl+OBpuOBhOOCi+OCq+ODq+ODvOOCu+ODq+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOBjOi/lOOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IHZpc2libGUgYDxvbnMtY2Fyb3VzZWwtaXRlbT5gLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBleOCjOOBpuOBhOOCi29ucy1jYXJvdXNlbC1pdGVt6KaB57Sg44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldEFjdGl2ZUluZGV4KCkge1xuICAgIGNvbnN0IHNjcm9sbCA9IHRoaXMuX3Njcm9sbCAtICh0aGlzLl9vZmZzZXQgfHwgMCk7XG4gICAgY29uc3QgY291bnQgPSB0aGlzLml0ZW1Db3VudDtcbiAgICBjb25zdCBzaXplID0gdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpO1xuXG4gICAgaWYgKHNjcm9sbCA8IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGxldCBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICBpZiAoc2l6ZSAqIGkgPD0gc2Nyb2xsICYmIHNpemUgKiAoaSArIDEpID4gc2Nyb2xsKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1heCBjYXJvdXNlbCBpbmRleFxuICAgIHJldHVybiBpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbmV4dFxuICAgKiBAc2lnbmF0dXJlIG5leHQoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaGFzIGZpbmlzaGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0byBgXCJub25lXCJgIHRoZSB0cmFuc2l0aW9ucyB3aWxsIG5vdCBiZSBhbmltYXRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3BlY2lmeSB0aGUgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IG5leHQgYDxvbnMtY2Fyb3VzZWwtaXRlbT5gLlsvZW5dXG4gICAqICAgW2phXeasoeOBrm9ucy1jYXJvdXNlbC1pdGVt44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIG5leHQob3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnNldEFjdGl2ZUluZGV4KHRoaXMuZ2V0QWN0aXZlSW5kZXgoKSArIDEsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcHJldlxuICAgKiBAc2lnbmF0dXJlIHByZXYoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaGFzIGZpbmlzaGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0byBgXCJub25lXCJgIHRoZSB0cmFuc2l0aW9ucyB3aWxsIG5vdCBiZSBhbmltYXRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3BlY2lmeSB0aGUgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IHByZXZpb3VzIGA8b25zLWNhcm91c2VsLWl0ZW0+YC5bL2VuXVxuICAgKiAgIFtqYV3liY3jga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBwcmV2KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy5zZXRBY3RpdmVJbmRleCh0aGlzLmdldEFjdGl2ZUluZGV4KCkgLSAxLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgX2lzRW5hYmxlZENoYW5nZUV2ZW50KCkge1xuICAgIGNvbnN0IGVsZW1lbnRTaXplID0gdGhpcy5fZ2V0RWxlbWVudFNpemUoKTtcbiAgICBjb25zdCBjYXJvdXNlbEl0ZW1TaXplID0gdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpO1xuXG4gICAgcmV0dXJuIHRoaXMuYXV0b1Njcm9sbCAmJiBNYXRoLmFicyhlbGVtZW50U2l6ZSAtIGNhcm91c2VsSXRlbVNpemUpIDwgMC41O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBfaXNWZXJ0aWNhbCgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpID09PSAndmVydGljYWwnO1xuICB9XG5cbiAgX3ByZXBhcmVFdmVudExpc3RlbmVycygpIHtcbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgR2VzdHVyZURldGVjdG9yKHRoaXMsIHtcbiAgICAgIGRyYWdNaW5EaXN0YW5jZTogMSxcbiAgICAgIGRyYWdMb2NrVG9BeGlzOiB0cnVlXG4gICAgfSk7XG4gICAgdGhpcy5fbXV0YXRpb25PYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCgpID0+IHRoaXMucmVmcmVzaCgpKTtcblxuICAgIHRoaXMuX3VwZGF0ZVN3aXBlYWJsZSgpO1xuICAgIHRoaXMuX3VwZGF0ZUF1dG9SZWZyZXNoKCk7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPblJlc2l6ZSwgdHJ1ZSk7XG4gIH1cblxuICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBudWxsO1xuXG4gICAgdGhpcy5fbXV0YXRpb25PYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgdGhpcy5fbXV0YXRpb25PYnNlcnZlciA9IG51bGw7XG5cbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPblJlc2l6ZSwgdHJ1ZSk7XG4gIH1cblxuICBfdXBkYXRlU3dpcGVhYmxlKCkge1xuICAgIGlmICh0aGlzLl9nZXN0dXJlRGV0ZWN0b3IpIHtcbiAgICAgIGlmICh0aGlzLnN3aXBlYWJsZSkge1xuICAgICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3Iub24oJ2RyYWcgZHJhZ2xlZnQgZHJhZ3JpZ2h0IGRyYWd1cCBkcmFnZG93biBzd2lwZSBzd2lwZWxlZnQgc3dpcGVyaWdodCBzd2lwZXVwIHN3aXBlZG93bicsIHRoaXMuX2JvdW5kT25EcmFnKTtcbiAgICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLm9uKCdkcmFnZW5kJywgdGhpcy5fYm91bmRPbkRyYWdFbmQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLm9mZignZHJhZyBkcmFnbGVmdCBkcmFncmlnaHQgZHJhZ3VwIGRyYWdkb3duIHN3aXBlIHN3aXBlbGVmdCBzd2lwZXJpZ2h0IHN3aXBldXAgc3dpcGVkb3duJywgdGhpcy5fYm91bmRPbkRyYWcpO1xuICAgICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3Iub2ZmKCdkcmFnZW5kJywgdGhpcy5fYm91bmRPbkRyYWdFbmQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVBdXRvUmVmcmVzaCgpIHtcbiAgICBpZiAodGhpcy5fbXV0YXRpb25PYnNlcnZlcikge1xuICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdhdXRvLXJlZnJlc2gnKSkge1xuICAgICAgICB0aGlzLl9tdXRhdGlvbk9ic2VydmVyLm9ic2VydmUodGhpcywge2NoaWxkTGlzdDogdHJ1ZX0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fbXV0YXRpb25PYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgX3RyeUZpcmVQb3N0Q2hhbmdlRXZlbnQoKSB7XG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gdGhpcy5nZXRBY3RpdmVJbmRleCgpO1xuXG4gICAgaWYgKHRoaXMuX2xhc3RBY3RpdmVJbmRleCAhPT0gY3VycmVudEluZGV4KSB7XG4gICAgICBjb25zdCBsYXN0QWN0aXZlSW5kZXggPSB0aGlzLl9sYXN0QWN0aXZlSW5kZXg7XG4gICAgICB0aGlzLl9sYXN0QWN0aXZlSW5kZXggPSBjdXJyZW50SW5kZXg7XG5cbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncG9zdGNoYW5nZScsIHtcbiAgICAgICAgY2Fyb3VzZWw6IHRoaXMsXG4gICAgICAgIGFjdGl2ZUluZGV4OiBjdXJyZW50SW5kZXgsXG4gICAgICAgIGxhc3RBY3RpdmVJbmRleDogbGFzdEFjdGl2ZUluZGV4XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfaXNXcm9uZ0RpcmVjdGlvbihkKSB7XG4gICAgLy8gdGhpcy5fbGFzdERyYWdEaXJlY3Rpb24gPSBkO1xuICAgIHJldHVybiB0aGlzLl9pc1ZlcnRpY2FsKCkgPyAoZCA9PT0gJ2xlZnQnIHx8IGQgPT09ICdyaWdodCcpIDogKGQgPT09ICd1cCcgfHwgZCA9PT0gJ2Rvd24nKTtcbiAgfVxuXG4gIF9vbkRyYWcoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5faXNXcm9uZ0RpcmVjdGlvbihldmVudC5nZXN0dXJlLmRpcmVjdGlvbikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIHRoaXMuX2xhc3REcmFnRXZlbnQgPSBldmVudDtcblxuICAgIGNvbnN0IHNjcm9sbCA9IHRoaXMuX3Njcm9sbCAtIHRoaXMuX2dldFNjcm9sbERlbHRhKGV2ZW50KTtcbiAgICB0aGlzLl9zY3JvbGxUbyhzY3JvbGwpO1xuICAgIGV2ZW50Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcblxuICAgIHRoaXMuX3RyeUZpcmVQb3N0Q2hhbmdlRXZlbnQoKTtcbiAgfVxuXG4gIF9vbkRyYWdFbmQoZXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuX2xhc3REcmFnRXZlbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fY3VycmVudEVsZW1lbnRTaXplID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3Njcm9sbCA9IHRoaXMuX3Njcm9sbCAtIHRoaXMuX2dldFNjcm9sbERlbHRhKGV2ZW50KTtcblxuICAgIC8vIGlmICghdGhpcy5faXNXcm9uZ0RpcmVjdGlvbih0aGlzLl9sYXN0RHJhZ0RpcmVjdGlvbikgJiYgdGhpcy5fZ2V0U2Nyb2xsRGVsdGEoZXZlbnQpICE9PSAwKSB7XG4gICAgLy8gICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAvLyB9XG5cbiAgICBpZiAodGhpcy5faXNPdmVyU2Nyb2xsKHRoaXMuX3Njcm9sbCkpIHtcbiAgICAgIGxldCB3YWl0Rm9yQWN0aW9uID0gZmFsc2U7XG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ292ZXJzY3JvbGwnLCB7XG4gICAgICAgIGNhcm91c2VsOiB0aGlzLFxuICAgICAgICBhY3RpdmVJbmRleDogdGhpcy5nZXRBY3RpdmVJbmRleCgpLFxuICAgICAgICBkaXJlY3Rpb246IHRoaXMuX2dldE92ZXJTY3JvbGxEaXJlY3Rpb24oKSxcbiAgICAgICAgd2FpdFRvUmV0dXJuOiAocHJvbWlzZSkgPT4ge1xuICAgICAgICAgIHdhaXRGb3JBY3Rpb24gPSB0cnVlO1xuICAgICAgICAgIHByb21pc2UudGhlbigoKSA9PiB0aGlzLl9zY3JvbGxUb0tpbGxPdmVyU2Nyb2xsKCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgaWYgKCF3YWl0Rm9yQWN0aW9uKSB7XG4gICAgICAgIHRoaXMuX3Njcm9sbFRvS2lsbE92ZXJTY3JvbGwoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fc3RhcnRNb21lbnR1bVNjcm9sbCgpO1xuICAgIH1cbiAgICB0aGlzLl9sYXN0RHJhZ0V2ZW50ID0gbnVsbDtcblxuICAgIGV2ZW50Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gdHJhaXRcbiAgICovXG4gIF9taXhpbih0cmFpdCkge1xuICAgIE9iamVjdC5rZXlzKHRyYWl0KS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgdGhpc1trZXldID0gdHJhaXRba2V5XTtcbiAgICB9LmJpbmQodGhpcykpO1xuICB9XG5cbiAgX3N0YXJ0TW9tZW50dW1TY3JvbGwoKSB7XG4gICAgaWYgKHRoaXMuX2xhc3REcmFnRXZlbnQpIHtcbiAgICAgIGNvbnN0IHZlbG9jaXR5ID0gdGhpcy5fZ2V0U2Nyb2xsVmVsb2NpdHkodGhpcy5fbGFzdERyYWdFdmVudCk7XG4gICAgICBjb25zdCBkdXJhdGlvbiA9IDAuMztcbiAgICAgIGNvbnN0IHNjcm9sbERlbHRhID0gZHVyYXRpb24gKiAxMDAgKiB2ZWxvY2l0eTtcbiAgICAgIGNvbnN0IHNjcm9sbCA9IHRoaXMuX25vcm1hbGl6ZVNjcm9sbFBvc2l0aW9uKFxuICAgICAgICB0aGlzLl9zY3JvbGwgKyAodGhpcy5fZ2V0U2Nyb2xsRGVsdGEodGhpcy5fbGFzdERyYWdFdmVudCkgPiAwID8gLXNjcm9sbERlbHRhIDogc2Nyb2xsRGVsdGEpXG4gICAgICApO1xuXG4gICAgICB0aGlzLl9zY3JvbGwgPSBzY3JvbGw7XG5cbiAgICAgIGFuaW1pdCh0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogdGhpcy5fZ2VuZXJhdGVTY3JvbGxUcmFuc2Zvcm0odGhpcy5fc2Nyb2xsKVxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogJ2N1YmljLWJlemllciguMSwgLjcsIC4xLCAxKSdcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgdGhpcy5fdHJ5RmlyZVBvc3RDaGFuZ2VFdmVudCgpO1xuICAgICAgICB9LmJpbmQodGhpcykpXG4gICAgICAgIC5wbGF5KCk7XG4gICAgfVxuICB9XG5cbiAgX25vcm1hbGl6ZVNjcm9sbFBvc2l0aW9uKHNjcm9sbCkge1xuICAgIGNvbnN0IG1heCA9IHRoaXMuX2NhbGN1bGF0ZU1heFNjcm9sbCgpO1xuXG4gICAgaWYgKCF0aGlzLmF1dG9TY3JvbGwpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbihtYXgsIHNjcm9sbCkpO1xuICAgIH1cbiAgICBsZXQgYXJyID0gW107XG4gICAgY29uc3Qgc2l6ZSA9IHRoaXMuX2dldENhcm91c2VsSXRlbVNpemUoKTtcbiAgICBjb25zdCBuYnJPZkl0ZW1zID0gdGhpcy5pdGVtQ291bnQ7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ick9mSXRlbXM7IGkrKykge1xuICAgICAgaWYgKGkgKiBzaXplICsgdGhpcy5fb2Zmc2V0IDwgbWF4KSB7XG4gICAgICAgIGFyci5wdXNoKGkgKiBzaXplICsgdGhpcy5fb2Zmc2V0KTtcbiAgICAgIH1cbiAgICB9XG4gICAgYXJyLnB1c2gobWF4KTtcblxuICAgIGFyci5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gICAgICBsZWZ0ID0gTWF0aC5hYnMobGVmdCAtIHNjcm9sbCk7XG4gICAgICByaWdodCA9IE1hdGguYWJzKHJpZ2h0IC0gc2Nyb2xsKTtcblxuICAgICAgcmV0dXJuIGxlZnQgLSByaWdodDtcbiAgICB9KTtcblxuICAgIGFyciA9IGFyci5maWx0ZXIoZnVuY3Rpb24oaXRlbSwgcG9zKSB7XG4gICAgICByZXR1cm4gIXBvcyB8fCBpdGVtICE9IGFycltwb3MgLSAxXTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGxhc3RTY3JvbGwgPSB0aGlzLl9sYXN0QWN0aXZlSW5kZXggKiBzaXplICsgdGhpcy5fb2Zmc2V0O1xuICAgIGNvbnN0IHNjcm9sbFJhdGlvID0gTWF0aC5hYnMoc2Nyb2xsIC0gbGFzdFNjcm9sbCkgLyBzaXplO1xuICAgIGxldCByZXN1bHQgPSBhcnJbMF07XG5cbiAgICBpZiAoc2Nyb2xsUmF0aW8gPD0gdGhpcy5hdXRvU2Nyb2xsUmF0aW8pIHtcbiAgICAgIHJlc3VsdCA9IGxhc3RTY3JvbGw7XG4gICAgfSBlbHNlIGlmIChzY3JvbGxSYXRpbyA8IDEuMCkge1xuICAgICAgaWYgKGFyclswXSA9PT0gbGFzdFNjcm9sbCAmJiBhcnIubGVuZ3RoID4gMSkge1xuICAgICAgICByZXN1bHQgPSBhcnJbMV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKG1heCwgcmVzdWx0KSk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBfZ2V0Q2Fyb3VzZWxJdGVtRWxlbWVudHMoKSB7XG4gICAgcmV0dXJuIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGRyZW4pXG4gICAgICAuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1jYXJvdXNlbC1pdGVtJyk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHNjcm9sbFxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBjYXJvdXNlbCBlbGVtZW50XG4gICAqL1xuICBfc2Nyb2xsVG8oc2Nyb2xsLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpc092ZXJzY3JvbGxhYmxlID0gdGhpcy5vdmVyc2Nyb2xsYWJsZTtcblxuICAgIGNvbnN0IG5vcm1hbGl6ZVNjcm9sbCA9IChzY3JvbGwpID0+IHtcbiAgICAgIGNvbnN0IHJhdGlvID0gMC4zNTtcblxuICAgICAgaWYgKHNjcm9sbCA8IDApIHtcbiAgICAgICAgcmV0dXJuIGlzT3ZlcnNjcm9sbGFibGUgPyBNYXRoLnJvdW5kKHNjcm9sbCAqIHJhdGlvKSA6IDA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1heFNjcm9sbCA9IHRoaXMuX2NhbGN1bGF0ZU1heFNjcm9sbCgpO1xuICAgICAgaWYgKG1heFNjcm9sbCA8IHNjcm9sbCkge1xuICAgICAgICByZXR1cm4gaXNPdmVyc2Nyb2xsYWJsZSA/IG1heFNjcm9sbCArIE1hdGgucm91bmQoKHNjcm9sbCAtIG1heFNjcm9sbCkgKiByYXRpbykgOiBtYXhTY3JvbGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzY3JvbGw7XG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIGFuaW1pdCh0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogdGhpcy5fZ2VuZXJhdGVTY3JvbGxUcmFuc2Zvcm0obm9ybWFsaXplU2Nyb2xsKHNjcm9sbCkpXG4gICAgICAgIH0sIG9wdGlvbnMuYW5pbWF0aW9uICAhPT0gJ25vbmUnID8gb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIDoge30pXG4gICAgICAgIC5wbGF5KCgpID0+IHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBfY2FsY3VsYXRlTWF4U2Nyb2xsKCkge1xuICAgIGNvbnN0IG1heCA9IHRoaXMuaXRlbUNvdW50ICogdGhpcy5fZ2V0Q2Fyb3VzZWxJdGVtU2l6ZSgpIC0gdGhpcy5fZ2V0RWxlbWVudFNpemUoKTtcbiAgICByZXR1cm4gTWF0aC5jZWlsKG1heCA8IDAgPyAwIDogbWF4KTsgLy8gTmVlZCB0byByZXR1cm4gYW4gaW50ZWdlciB2YWx1ZS5cbiAgfVxuXG4gIF9pc092ZXJTY3JvbGwoc2Nyb2xsKSB7XG4gICAgaWYgKHNjcm9sbCA8IDAgfHwgc2Nyb2xsID4gdGhpcy5fY2FsY3VsYXRlTWF4U2Nyb2xsKCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBfZ2V0T3ZlclNjcm9sbERpcmVjdGlvbigpIHtcbiAgICBpZiAodGhpcy5faXNWZXJ0aWNhbCgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsIDw9IDAgPyAndXAnIDogJ2Rvd24nO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsIDw9IDAgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIH1cbiAgfVxuXG4gIF9zY3JvbGxUb0tpbGxPdmVyU2Nyb2xsKCkge1xuICAgIGNvbnN0IGR1cmF0aW9uID0gMC40O1xuXG4gICAgaWYgKHRoaXMuX3Njcm9sbCA8IDApIHtcbiAgICAgIGFuaW1pdCh0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogdGhpcy5fZ2VuZXJhdGVTY3JvbGxUcmFuc2Zvcm0oMClcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC40LCAuMSwgMSknXG4gICAgICAgIH0pXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIHRoaXMuX3RyeUZpcmVQb3N0Q2hhbmdlRXZlbnQoKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKVxuICAgICAgICAucGxheSgpO1xuICAgICAgdGhpcy5fc2Nyb2xsID0gMDtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBtYXhTY3JvbGwgPSB0aGlzLl9jYWxjdWxhdGVNYXhTY3JvbGwoKTtcblxuICAgIGlmIChtYXhTY3JvbGwgPCB0aGlzLl9zY3JvbGwpIHtcbiAgICAgIGFuaW1pdCh0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogdGhpcy5fZ2VuZXJhdGVTY3JvbGxUcmFuc2Zvcm0obWF4U2Nyb2xsKVxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogJ2N1YmljLWJlemllciguMSwgLjQsIC4xLCAxKSdcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgdGhpcy5fdHJ5RmlyZVBvc3RDaGFuZ2VFdmVudCgpO1xuICAgICAgICB9LmJpbmQodGhpcykpXG4gICAgICAgIC5wbGF5KCk7XG4gICAgICB0aGlzLl9zY3JvbGwgPSBtYXhTY3JvbGw7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpdGVtQ291bnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgbnVtYmVyIG9mIGNhcm91c2VsIGl0ZW1zLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+imgee0oOOBruaVsOOBp+OBmeOAglsvamFdXG4gICAqL1xuICBnZXQgaXRlbUNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRDYXJvdXNlbEl0ZW1FbGVtZW50cygpLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlZnJlc2hcbiAgICogQHNpZ25hdHVyZSByZWZyZXNoKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVwZGF0ZSB0aGUgbGF5b3V0IG9mIHRoZSBjYXJvdXNlbC4gVXNlZCB3aGVuIGFkZGluZyBgPG9ucy1jYXJvdXNlbC1pdGVtcz5gIGR5bmFtaWNhbGx5IG9yIHRvIGF1dG9tYXRpY2FsbHkgYWRqdXN0IHRoZSBzaXplLlsvZW5dXG4gICAqICAgW2phXeODrOOCpOOCouOCpuODiOOChOWGhemDqOOBrueKtuaFi+OCkuacgOaWsOOBruOCguOBruOBq+abtOaWsOOBl+OBvuOBmeOAgm9ucy1jYXJvdXNlbC1pdGVt44KS5YuV55qE44Gr5aKX44KE44GX44Gf44KK44CBb25zLWNhcm91c2Vs44Gu5aSn44GN44GV44KS5YuV55qE44Gr5aSJ44GI44KL6Zqb44Gr5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHJlZnJlc2goKSB7XG4gICAgLy8gQnVnIGZpeFxuICAgIGlmICh0aGlzLl9nZXRDYXJvdXNlbEl0ZW1TaXplKCkgPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9taXhpbih0aGlzLl9pc1ZlcnRpY2FsKCkgPyBWZXJ0aWNhbE1vZGVUcmFpdCA6IEhvcml6b250YWxNb2RlVHJhaXQpO1xuICAgIHRoaXMuX3NldHVwKCk7XG5cbiAgICBpZiAodGhpcy5fbGFzdFN0YXRlICYmIHRoaXMuX2xhc3RTdGF0ZS53aWR0aCA+IDApIHtcbiAgICAgIGxldCBzY3JvbGwgPSB0aGlzLl9zY3JvbGw7Ly8gLSB0aGlzLl9vZmZzZXQ7XG5cbiAgICAgIGlmICh0aGlzLl9pc092ZXJTY3JvbGwoc2Nyb2xsKSkge1xuICAgICAgICB0aGlzLl9zY3JvbGxUb0tpbGxPdmVyU2Nyb2xsKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodGhpcy5hdXRvU2Nyb2xsKSB7XG4gICAgICAgICAgc2Nyb2xsID0gdGhpcy5fbm9ybWFsaXplU2Nyb2xsUG9zaXRpb24oc2Nyb2xsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3Njcm9sbFRvKHNjcm9sbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fc2F2ZUxhc3RTdGF0ZSgpO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdyZWZyZXNoJywge2Nhcm91c2VsOiB0aGlzfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBmaXJzdFxuICAgKiBAc2lnbmF0dXJlIGZpcnN0KClcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBmaXJzdCBgPG9ucy1jYXJvdXNlbC1pdGVtPmAuWy9lbl1cbiAgICogICBbamFd5pyA5Yid44Gub25zLWNhcm91c2VsLWl0ZW3jgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZmlyc3Qob3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnNldEFjdGl2ZUluZGV4KDAsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbGFzdFxuICAgKiBAc2lnbmF0dXJlIGxhc3QoKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaGFzIGZpbmlzaGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0byBgXCJub25lXCJgIHRoZSB0cmFuc2l0aW9ucyB3aWxsIG5vdCBiZSBhbmltYXRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3BlY2lmeSB0aGUgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVJlc29sdmVzIHRvIHRoZSBjYXJvdXNlbCBlbGVtZW50Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgbGFzdCBvbnMtY2Fyb3VzZWwgaXRlbS5bL2VuXVxuICAgKiAgIFtqYV3mnIDlvozjga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsYXN0KG9wdGlvbnMpIHtcbiAgICB0aGlzLnNldEFjdGl2ZUluZGV4KFxuICAgICAgTWF0aC5tYXgodGhpcy5pdGVtQ291bnQgLSAxLCAwKSwgb3B0aW9uc1xuICAgICk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9wcmVwYXJlRXZlbnRMaXN0ZW5lcnMoKTtcblxuICAgIHRoaXMuX3NldHVwKCk7XG4gICAgdGhpcy5fc2V0dXBJbml0aWFsSW5kZXgoKTtcblxuICAgIHRoaXMuX3NhdmVMYXN0U3RhdGUoKTtcblxuICAgIC8vIEZpeCByZW5kZXJpbmcgZ2xpdGNoIG9uIEFuZHJvaWQgNC4xXG4gICAgaWYgKHRoaXMub2Zmc2V0SGVpZ2h0ID09PSAwKSB7XG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5yZWZyZXNoKCkpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ3N3aXBlYWJsZScsICdhdXRvLXJlZnJlc2gnLCAnZGlyZWN0aW9uJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnc3dpcGVhYmxlJzpcbiAgICAgICAgdGhpcy5fdXBkYXRlU3dpcGVhYmxlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYXV0by1yZWZyZXNoJzpcbiAgICAgICAgdGhpcy5fdXBkYXRlQXV0b1JlZnJlc2goKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkaXJlY3Rpb24nOlxuICAgICAgICB0aGlzLl9vbkRpcmVjdGlvbkNoYW5nZSgpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxSYXRpb1xuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgYXV0byBzY3JvbGwgcmF0aW8uIFsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruOCquODvOODiOOCueOCr+ODreODvOODq+OBrnJhdGlv5YCk44CCWy9qYV1cbiAgICovXG4gIGdldCBhdXRvU2Nyb2xsUmF0aW8oKSB7XG4gICAgY29uc3QgYXR0ciA9IHRoaXMuZ2V0QXR0cmlidXRlKCdhdXRvLXNjcm9sbC1yYXRpbycpO1xuXG4gICAgaWYgKCFhdHRyKSB7XG4gICAgICByZXR1cm4gMC41O1xuICAgIH1cblxuICAgIGNvbnN0IHNjcm9sbFJhdGlvID0gcGFyc2VGbG9hdChhdHRyKTtcbiAgICBpZiAoc2Nyb2xsUmF0aW8gPCAwLjAgfHwgc2Nyb2xsUmF0aW8gPiAxLjApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCByYXRpby4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXNOYU4oc2Nyb2xsUmF0aW8pID8gMC41IDogc2Nyb2xsUmF0aW87XG4gIH1cblxuICBzZXQgYXV0b1Njcm9sbFJhdGlvKHJhdGlvKSB7XG4gICAgaWYgKHJhdGlvIDwgMC4wIHx8IHJhdGlvID4gMS4wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcmF0aW8uJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsLXJhdGlvJywgcmF0aW8pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIHRoZSBjYXJvdXNlbCBpcyBzd2lwZWFibGUuWy9lbl1cbiAgICogICBbamFdc3dpcGVhYmxl44Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgc3dpcGVhYmxlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnc3dpcGVhYmxlJyk7XG4gIH1cblxuICBzZXQgc3dpcGVhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzd2lwZWFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIGF1dG8gc2Nyb2xsIGlzIGVuYWJsZWQuWy9lbl1cbiAgICogICBbamFd44Kq44O844OI44K544Kv44Ot44O844Or44GM5pyJ5Yq544Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgYXV0b1Njcm9sbCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsJyk7XG4gIH1cblxuICBzZXQgYXV0b1Njcm9sbCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnYXV0by1zY3JvbGwnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgY2Fyb3VzZWwgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3ZlcnNjcm9sbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjYXJvdXNlbCBpcyBvdmVyc2Nyb2xsYWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFdb3ZlcnNjcm9sbOOBp+OBjeOCjOOBsHRydWXjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IG92ZXJzY3JvbGxhYmxlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnb3ZlcnNjcm9sbGFibGUnKTtcbiAgfVxuXG4gIHNldCBvdmVyc2Nyb2xsYWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnb3ZlcnNjcm9sbGFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNlbnRlcmVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgY2Fyb3VzZWwgaXMgY2VudGVyZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXWNlbnRlcmVk54q25oWL44Gr44Gq44Gj44Gm44GE44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgY2VudGVyZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdjZW50ZXJlZCcpO1xuICB9XG5cbiAgc2V0IGNlbnRlcmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdjZW50ZXJlZCcsIHZhbHVlKTtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1jYXJvdXNlbCcsIENhcm91c2VsRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWNvbFxuICogQGNhdGVnb3J5IGdyaWRcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dUmVwcmVzZW50cyBhIGNvbHVtbiBpbiB0aGUgZ3JpZCBzeXN0ZW0uIFVzZSB3aXRoIGA8b25zLXJvdz5gIHRvIGxheW91dCBjb21wb25lbnRzLlsvZW5dXG4gKiAgIFtqYV3jgrDjg6rjg4Pjg4njgrfjgrnjg4bjg6DjgavjgabliJfjgpLlrprnvqnjgZfjgb7jgZnjgIJvbnMtcm9344Go44Go44KC44Gr5L2/55So44GX44CB44Kz44Oz44Od44O844ON44Oz44OI44Gu44Os44Kk44Ki44Km44OI44Gr5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBub3RlXG4gKiAgIFtlbl1Gb3IgQW5kcm9pZCA0LjMgYW5kIGVhcmxpZXIsIGFuZCBpT1M2IGFuZCBlYXJsaWVyLCB3aGVuIHVzaW5nIG1peGVkIGFsaWdubWVudCB3aXRoIG9ucy1yb3cgYW5kIG9ucy1jb2x1bW4sIHRoZXkgbWF5IG5vdCBiZSBkaXNwbGF5ZWQgY29ycmVjdGx5LiBZb3UgY2FuIHVzZSBvbmx5IG9uZSBhbGlnbm1lbnQuWy9lbl1cbiAqICAgW2phXUFuZHJvaWQgNC4z5Lul5YmN44CB44KC44GX44GP44GvaU9TIDbku6XliY3jga5PU+OBruWgtOWQiOOAgW9ucy1yb3fjgahvbnMtY29sdW1u44KS57WE44G/5ZCI44KP44Gb44Gf5aC05ZCI44Gr5o+P55S744GM5bSp44KM44KL5aC05ZCI44GM44GC44KK44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIEdndWpDIHt3aWRlfVxuICogQGd1aWRlIGxheW91dGluZyBbZW5dTGF5b3V0aW5nIGd1aWRlWy9lbl1bamFd44Os44Kk44Ki44Km44OI5qmf6IO9Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1yb3dcbiAqICAgW2VuXVRoZSBgPG9ucy1yb3c+YCBjb21wb25lbnQgaXMgdGhlIHBhcmVudCBvZiBgPG9ucy1jb2w+YC5bL2VuXVxuICogICBbamFdb25zLXJvd+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1yb3c+XG4gKiAgIDxvbnMtY29sIHdpZHRoPVwiNTBweFwiPjxvbnMtaWNvbiBpY29uPVwiZmEtdHdpdHRlclwiPjwvb25zLWljb24+PC9vbnMtY29sPlxuICogICA8b25zLWNvbD5UZXh0PC9vbnMtY29sPlxuICogPC9vbnMtcm93PlxuICovXG5cbi8qKlxuICogQGF0dHJpYnV0ZSB2ZXJ0aWNhbC1hbGlnblxuICogQHR5cGUge1N0cmluZ31cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVmVydGljYWwgYWxpZ25tZW50IG9mIHRoZSBjb2x1bW4uIFZhbGlkIHZhbHVlcyBhcmUgXCJ0b3BcIiwgXCJjZW50ZXJcIiwgYW5kIFwiYm90dG9tXCIuWy9lbl1cbiAqICAgW2phXee4puOBrumFjee9ruOCkuaMh+WumuOBmeOCi+OAglwidG9wXCIsIFwiY2VudGVyXCIsIFwiYm90dG9tXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICovXG5cbi8qKlxuICogQGF0dHJpYnV0ZSB3aWR0aFxuICogQHR5cGUge1N0cmluZ31cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVGhlIHdpZHRoIG9mIHRoZSBjb2x1bW4uIFZhbGlkIHZhbHVlcyBhcmUgY3NzIHdpZHRoIHZhbHVlcyAoXCIxMCVcIiwgXCI1MHB4XCIpLlsvZW5dXG4gKiAgIFtqYV3jgqvjg6njg6Djga7mqKrluYXjgpLmjIflrprjgZnjgovjgILjg5Hjg7zjgrvjg7Pjg4jjgoLjgZfjgY/jga/jg5Tjgq/jgrvjg6vjgafmjIflrprjgZfjgb7jgZnvvIgxMCXjgoQ1MHB477yJ44CCWy9qYV1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29sRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICBpbml0KCkge1xuICAgIGlmICh0aGlzLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSkge1xuICAgICAgdGhpcy5fdXBkYXRlV2lkdGgoKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWyd3aWR0aCddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ3dpZHRoJykge1xuICAgICAgdGhpcy5fdXBkYXRlV2lkdGgoKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlV2lkdGgoKSB7XG4gICAgbGV0IHdpZHRoID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJyk7XG4gICAgaWYgKHR5cGVvZiB3aWR0aCAgPT09ICdzdHJpbmcnKSB7XG4gICAgICB3aWR0aCA9ICgnJyArIHdpZHRoKS50cmltKCk7XG4gICAgICB3aWR0aCA9IHdpZHRoLm1hdGNoKC9eXFxkKyQvKSA/IHdpZHRoICsgJyUnIDogd2lkdGg7XG5cbiAgICAgIHRoaXMuc3R5bGUud2Via2l0Qm94RmxleCA9ICcwJztcbiAgICAgIHRoaXMuc3R5bGUud2Via2l0RmxleCA9ICcwIDAgJyArIHdpZHRoO1xuICAgICAgdGhpcy5zdHlsZS5tb3pCb3hGbGV4ID0gJzAnO1xuICAgICAgdGhpcy5zdHlsZS5tb3pGbGV4ID0gJzAgMCAnICsgd2lkdGg7XG4gICAgICB0aGlzLnN0eWxlLm1zRmxleCA9ICcwIDAgJyArIHdpZHRoO1xuICAgICAgdGhpcy5zdHlsZS5mbGV4ID0gJzAgMCAnICsgd2lkdGg7XG4gICAgICB0aGlzLnN0eWxlLm1heFdpZHRoID0gd2lkdGg7XG4gICAgfVxuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNvbCcsIENvbEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuZXhwb3J0IGNsYXNzIERpYWxvZ0FuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICB0aGlzLnRpbWluZyA9IHRpbWluZztcbiAgICB0aGlzLmRlbGF5ID0gZGVsYXk7XG4gICAgdGhpcy5kdXJhdGlvbiA9IGR1cmF0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBzaG93KGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgaGlkZShkaWFsb2csIGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBbmRyb2lkIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmRyb2lkRGlhbG9nQW5pbWF0b3IgZXh0ZW5kcyBEaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdlYXNlLWluLW91dCcsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjN9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2cpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTYwJSwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMC4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC02MCUsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcblxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIElPU0RpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgRGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnZWFzZS1pbi1vdXQnLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4zfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIDMwMCUsIDApJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZylcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAzMDAlLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG5cbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogU2xpZGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNsaWRlRGlhbG9nQW5pbWF0b3IgZXh0ZW5kcyBEaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuNCwgMSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKC01MCUsIC0zNTAlLCAwKScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoLTUwJSwgLTUwJSwgMCknLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZylcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgtNTAlLCAtNTAlLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgtNTAlLCAtMzUwJSwgMCknXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IHtEaWFsb2dBbmltYXRvciwgSU9TRGlhbG9nQW5pbWF0b3IsIEFuZHJvaWREaWFsb2dBbmltYXRvciwgU2xpZGVEaWFsb2dBbmltYXRvcn0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi8uLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi8uLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyIGZyb20gJy4uLy4uL29ucy9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlcic7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLmRpYWxvZyc6ICdkaWFsb2ctLSonLFxuICAnLmRpYWxvZy1jb250YWluZXInOiAnZGlhbG9nLWNvbnRhaW5lci0tKicsXG4gICcuZGlhbG9nLW1hc2snOiAnZGlhbG9nLW1hc2stLSonXG59O1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gQW5kcm9pZERpYWxvZ0FuaW1hdG9yIDogSU9TRGlhbG9nQW5pbWF0b3IsXG4gICdzbGlkZSc6IFNsaWRlRGlhbG9nQW5pbWF0b3IsXG4gICdub25lJzogRGlhbG9nQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWRpYWxvZ1xuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaWFsb2cgdGhhdCBpcyBkaXNwbGF5ZWQgb24gdG9wIG9mIGN1cnJlbnQgc2NyZWVuLiBBcyBvcHBvc2VkIHRvIHRoZSBgPG9ucy1hbGVydC1kaWFsb2c+YCBlbGVtZW50LCB0aGlzIGNvbXBvbmVudCBjYW4gY29udGFpbiBhbnkga2luZCBvZiBjb250ZW50LlxuICpcbiAqICAgICBUbyB1c2UgdGhlIGVsZW1lbnQgaXQgY2FuIGVpdGhlciBiZSBhdHRhY2hlZCBkaXJlY3RseSB0byB0aGUgYDxib2R5PmAgZWxlbWVudCBvciBkeW5hbWljYWxseSBjcmVhdGVkIGZyb20gYSB0ZW1wbGF0ZSB1c2luZyB0aGUgYG9ucy5jcmVhdGVEaWFsb2codGVtcGxhdGUpYCB1dGlsaXR5IGZ1bmN0aW9uIGFuZCB0aGUgYDxvbnMtdGVtcGxhdGU+YCB0YWcuXG4gKlxuICogICAgIFRoZSBkaWFsb2cgaXMgdXNlZnVsIGZvciBkaXNwbGF5aW5nIG1lbnVzLCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9yIHRvIGFzayB0aGUgdXNlciB0byBtYWtlIGEgZGVjaXNpb24uXG4gKlxuICogICAgIEl0IHdpbGwgYXV0b21hdGljYWxseSBiZSBkaXNwbGF5ZWQgYXMgTWF0ZXJpYWwgRGVzaWduIHdoZW4gcnVubmluZyBvbiBhbiBBbmRyb2lkIGRldmljZS5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXURpc3BsYXkgYSBNYXRlcmlhbCBEZXNpZ24gZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4genh4YUdhXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvZGlhbG9nXG4gKiBAZ3VpZGUgZGlhbG9nc1xuICogICBbZW5dRGlhbG9nIGNvbXBvbmVudHNbL2VuXVxuICogICBbamFdRGlhbG9nIGNvbXBvbmVudHNbL2phXVxuICogQGd1aWRlIHVzaW5nLW1vZGlmaWVyIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQHNlZWFsc28gb25zLWFsZXJ0LWRpYWxvZ1xuICogICBbZW5dYDxvbnMtYWxlcnQtZGlhbG9nPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1hbGVydC1kaWFsb2fjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXBvcG92ZXJcbiAqICAgW2VuXWA8b25zLXBvcG92ZXI+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXBvcG92ZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW1vZGFsXG4gKiAgIFtlbl1gPG9ucy1tb2RhbD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbW9kYWzjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtZGlhbG9nIGlkPVwiZGlhbG9nXCI+XG4gKiAgIDxwPlRoaXMgaXMgYSBkaWFsb2chPC9wPlxuICogPC9vbnMtZGlhbG9nPlxuICpcbiAqIDxzY3JpcHQ+XG4gKiAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkaWFsb2cnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGlhbG9nRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IHByZXNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgZGlhbG9nIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmRpYWxvZ1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1FeGVjdXRlIHRoaXMgZnVuY3Rpb24gdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gYmVpbmcgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0c2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGRpYWxvZyBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogW2phXeODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5kaWFsb2dcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZWhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgZGlhbG9nIGlzIGhpZGRlbi5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmRpYWxvZ1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1FeGVjdXRlIHRoaXMgZnVuY3Rpb24gdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gYmVpbmcgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBrumdnuihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBkaWFsb2cgaXMgaGlkZGVuLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuZGlhbG9nXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGRpYWxvZy5bL2VuXVxuICAgKiAgW2phXeODgOOCpOOCouODreOCsOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNhbmNlbGFibGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODgOOCpOOCouODreOCsOOBr2Rpc2FibGVk54q25oWL44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBkaWFsb2cuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCBvciBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCLjgoLjgZfjgY/jga9cImRlZmF1bHRcIuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgcmdiYSgwLCAwLCAwLCAwLjIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kIG1hc2suIERlZmF1bHQgaXMgYFwicmdiYSgwLCAwLCAwLCAwLjIpXCJgLlsvZW5dXG4gICAqICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBjOODh+ODleOCqeODq+ODiOWApOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9kaWFsb2coKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuZGlhbG9nJyk7XG4gIH1cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuXG4gICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG4gICAgdGhpcy5fYm91bmRDYW5jZWwgPSB0aGlzLl9jYW5jZWwuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogRGlhbG9nQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnRGlhbG9nQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblxuICAgIC8qIEV4cGVjdGVkIHJlc3VsdDpcbiAgICAgKiAgIDxvbnMtZGlhbG9nPlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nLW1hc2tcIj48L2Rpdj5cbiAgICAgKiAgICAgPGRpdiBjbGFzcz1cImRpYWxvZ1wiPlxuICAgICAqICAgICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctY29udGFpbmVyXCI+Li4uPC9kaXY+XG4gICAgICogICAgIDwvZGl2PlxuICAgICAqICAgPC9vbnMtZGlhbG9nPlxuICAgICAqL1xuXG4gICAgaWYgKCF0aGlzLl9kaWFsb2cpIHtcbiAgICAgIGNvbnN0IGRpYWxvZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZGlhbG9nLmNsYXNzTGlzdC5hZGQoJ2RpYWxvZycpO1xuXG4gICAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGRpYWxvZy5jbGFzc0xpc3QuYWRkKCdkaWFsb2ctY29udGFpbmVyJyk7XG5cbiAgICAgIGRpYWxvZy5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuXG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmZpcnN0Q2hpbGQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmFwcGVuZENoaWxkKGRpYWxvZyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl9tYXNrKSB7XG4gICAgICBjb25zdCBtYXNrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBtYXNrLmNsYXNzTGlzdC5hZGQoJ2RpYWxvZy1tYXNrJyk7XG4gICAgICB0aGlzLmluc2VydEJlZm9yZShtYXNrLCB0aGlzLmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIHRoaXMuX2RpYWxvZy5zdHlsZS56SW5kZXggPSAyMDAwMTtcbiAgICB0aGlzLl9tYXNrLnN0eWxlLnpJbmRleCA9IDIwMDAwO1xuXG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcsICcnKTtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuICBnZXQgb25EZXZpY2VCYWNrQnV0dG9uKCkge1xuICAgIHJldHVybiB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcjtcbiAgfVxuXG4gIHNldCBvbkRldmljZUJhY2tCdXR0b24oY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5fYmFja0J1dHRvbkhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIodGhpcywgY2FsbGJhY2spO1xuICB9XG5cbiAgX2NhbmNlbCgpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxhYmxlICYmICF0aGlzLl9ydW5uaW5nKSB7XG4gICAgICB0aGlzLl9ydW5uaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaGlkZSgpXG4gICAgICAgIC50aGVuKFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnZGlhbG9nLWNhbmNlbCcpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgKCkgPT4gdGhpcy5fcnVubmluZyA9IGZhbHNlXG4gICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3coW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgZGlhbG9nIGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNob3cgdGhlIGRpYWxvZy5bL2VuXVxuICAgKiAgW2phXeODgOOCpOOCouODreOCsOOCkumWi+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5cbiAgICovXG4gIHNob3cob3B0aW9ucyA9IHt9KSB7XG4gICAgbGV0IGNhbmNlbCA9IGZhbHNlO1xuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuXG4gICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zID0gdXRpbC5leHRlbmQoXG4gICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgfHwge30sXG4gICAgICBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKVxuICAgICk7XG5cbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3ByZXNob3cnLCB7XG4gICAgICBkaWFsb2c6IHRoaXMsXG4gICAgICBjYW5jZWw6IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYW5jZWwgPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKCFjYW5jZWwpIHtcbiAgICAgIGNvbnN0IHRyeVNob3cgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHVubG9jayA9IHRoaXMuX2Rvb3JMb2NrLmxvY2soKTtcbiAgICAgICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcbiAgICAgICAgdGhpcy5fbWFzay5zdHlsZS5vcGFjaXR5ID0gJzEnO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgYW5pbWF0b3Iuc2hvdyh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuX3Zpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgICB1bmxvY2soKTtcblxuICAgICAgICAgICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RzaG93Jywge2RpYWxvZzogdGhpc30pO1xuXG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIHRoaXMuX2Rvb3JMb2NrLndhaXRVbmxvY2soKCkgPT4gcmVzb2x2ZSh0cnlTaG93KCkpKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXNob3cgZXZlbnQuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb25zIGlzIGNhbGxlZCBhZnRlciB0aGUgZGlhbG9nIGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBoaWRlKG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBjYW5jZWwgPSBmYWxzZTtcbiAgICBjb25zdCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2sgfHwgZnVuY3Rpb24oKSB7fTtcblxuICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKFxuICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9LFxuICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSlcbiAgICApO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwcmVoaWRlJywge1xuICAgICAgZGlhbG9nOiB0aGlzLFxuICAgICAgY2FuY2VsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FuY2VsID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICghY2FuY2VsKSB7XG4gICAgICBjb25zdCB0cnlIaWRlID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9kb29yTG9jay5sb2NrKCk7XG4gICAgICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgYW5pbWF0b3IuaGlkZSh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICB1bmxvY2soKTtcblxuICAgICAgICAgICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RoaWRlJywge2RpYWxvZzogdGhpc30pO1xuXG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIHRoaXMuX2Rvb3JMb2NrLndhaXRVbmxvY2soKCkgPT4gcmVzb2x2ZSh0cnlIaWRlKCkpKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZWhpZGUgZXZlbnQuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGRpYWxvZyBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHZpc2libGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Zpc2libGU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZGlhbG9nIGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNhbmNlbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIEEgY2FuY2VsYWJsZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldCBjYW5jZWxhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdjYW5jZWxhYmxlJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGNhbmNlbGFibGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdjYW5jZWxhYmxlJyk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLm9uRGV2aWNlQmFja0J1dHRvbiA9IGUgPT4gdGhpcy5jYW5jZWxhYmxlID8gdGhpcy5fY2FuY2VsKCkgOiBlLmNhbGxQYXJlbnRIYW5kbGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fbWFzay5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kQ2FuY2VsLCBmYWxzZSk7XG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBudWxsO1xuXG4gICAgdGhpcy5fbWFzay5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kQ2FuY2VsLmJpbmQodGhpcyksIGZhbHNlKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2FuaW1hdGlvbiddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgcmV0dXJuIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgIH1cbiAgICBlbHNlIGlmIChuYW1lID09PSAnYW5pbWF0aW9uJykge1xuICAgICAgdGhpcy5fdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RGlhbG9nQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIERpYWxvZ0FuaW1hdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0IE9uc0RpYWxvZ0VsZW1lbnQuRGlhbG9nQW5pbWF0b3InKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBEaWFsb2dBbmltYXRvcigpIHtcbiAgICByZXR1cm4gRGlhbG9nQW5pbWF0b3I7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZGlhbG9nJywgRGlhbG9nRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdmYWItLSonXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1mYWJcbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIFRoZSBGbG9hdGluZyBhY3Rpb24gYnV0dG9uIGlzIGEgY2lyY3VsYXIgYnV0dG9uIGRlZmluZWQgaW4gdGhlIFtNYXRlcmlhbCBEZXNpZ24gc3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9kZXNpZ24vc3BlYy9jb21wb25lbnRzL2J1dHRvbnMtZmxvYXRpbmctYWN0aW9uLWJ1dHRvbi5odG1sKS4gVGhleSBhcmUgb2Z0ZW4gdXNlZCB0byBwcm9tb3RlIHRoZSBwcmltYXJ5IGFjdGlvbiBvZiB0aGUgYXBwLlxuICpcbiAqICAgICBJdCBjYW4gYmUgZGlzcGxheWVkIGVpdGhlciBhcyBhbiBpbmxpbmUgZWxlbWVudCBvciBpbiBvbmUgb2YgdGhlIGNvcm5lcnMuIE5vcm1hbGx5IGl0IHdpbGwgYmUgcG9zaXRpb25lZCBpbiB0aGUgbG93ZXIgcmlnaHQgY29ybmVyIG9mIHRoZSBzY3JlZW4uXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2ZhYlxuICogQGd1aWRlIGNyb3NzLXBsYXRmb3JtLXN0eWxpbmcgW2VuXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2VuXVtqYV1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGVlZC1kaWFsXG4gKiAgIFtlbl1UaGUgYDxvbnMtc3BlZWQtZGlhbD5gIGNvbXBvbmVudCBpcyBhIEZsb2F0aW5nIGFjdGlvbiBidXR0b24gdGhhdCBkaXNwbGF5cyBhIG1lbnUgd2hlbiB0YXBwZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhYkVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXeODnOOCv+ODs+OBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJpcHBsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBkZWZpbmVkLCB0aGUgYnV0dG9uIHdpbGwgaGF2ZSBhIHJpcHBsZSBlZmZlY3Qgd2hlbiB0YXBwZWQuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwb3NpdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgcG9zaXRpb24gb2YgdGhlIGJ1dHRvbi4gU2hvdWxkIGJlIGEgc3RyaW5nIGxpa2UgYFwiYm90dG9tIHJpZ2h0XCJgIG9yIGBcInRvcCBsZWZ0XCJgLiBJZiB0aGlzIGF0dHJpYnV0ZSBpcyBub3QgZGVmaW5lZCBpdCB3aWxsIGJlIGRpc3BsYXllZCBhcyBhbiBpbmxpbmUgZWxlbWVudC5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IGlmIGJ1dHRvbiBzaG91bGQgYmUgZGlzYWJsZWQuWy9lbl1cbiAgICogICBbamFd44Oc44K/44Oz44KS54Sh5Yq55YyW44GZ44KL5aC05ZCI44Gv5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYicpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmZhYl9faWNvbicpKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgY29udGVudC5jbGFzc0xpc3QuYWRkKCdmYWJfX2ljb24nKTtcblxuICAgICAgdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZE5vZGVzKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICBpZiAoIWVsZW1lbnQudGFnTmFtZSB8fCBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSAhPT0gJ29ucy1yaXBwbGUnKSB7XG4gICAgICAgICAgY29udGVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0aGlzLmFwcGVuZENoaWxkKGNvbnRlbnQpO1xuICAgIH1cblxuICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuXG4gICAgdGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcblxuICAgIHRoaXMuc2hvdygpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAncmlwcGxlJywgJ3Bvc2l0aW9uJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgdGhpcy5zaG93KCk7XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICB0aGlzLmhpZGUoKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gIH1cblxuICBfdXBkYXRlUG9zaXRpb24oKSB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgncG9zaXRpb24nKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoXG4gICAgICAnZmFiLS10b3BfX2xlZnQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19yaWdodCcsXG4gICAgICAnZmFiLS1ib3R0b21fX2xlZnQnLFxuICAgICAgJ2ZhYi0tdG9wX19yaWdodCcsXG4gICAgICAnZmFiLS10b3BfX2NlbnRlcicsXG4gICAgICAnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgIGNhc2UgJ3RvcCByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCB0b3AnOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RvcCBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCBib3R0b20nOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciB0b3AnOlxuICAgICAgY2FzZSAndG9wIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciBib3R0b20nOlxuICAgICAgY2FzZSAnYm90dG9tIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU2hvdyB0aGUgZmxvYXRpbmcgYWN0aW9uIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuc3R5bGUudHJhbnNmb3JtID0gJ3NjYWxlKDEpJztcbiAgICB0aGlzLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdzY2FsZSgxKSc7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUhpZGUgdGhlIGZsb2F0aW5nIGFjdGlvbiBidXR0b24uWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cbiAgaGlkZShvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLnN0eWxlLnRyYW5zZm9ybSA9ICdzY2FsZSgwKSc7XG4gICAgdGhpcy5zdHlsZS53ZWJraXRUcmFuc2Zvcm0gPSAnc2NhbGUoMCknO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHlsZS50cmFuc2Zvcm0gPT09ICdzY2FsZSgxKScgJiYgdGhpcy5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZSc7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIHRoZSB2aXNpYmlsaXR5IG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHRvZ2dsZSgpIHtcbiAgICB0aGlzLnZpc2libGUgPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdygpO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWZhYicsIEZhYkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IEdlc3R1cmVEZXRlY3RvciBmcm9tICcuLi9vbnMvZ2VzdHVyZS1kZXRlY3Rvcic7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWdlc3R1cmUtZGV0ZWN0b3JcbiAqIEBjYXRlZ29yeSBnZXN0dXJlXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbXBvbmVudCB0byBkZXRlY3QgZmluZ2VyIGdlc3R1cmVzIHdpdGhpbiB0aGUgd3JhcHBlZCBlbGVtZW50LiBGb2xsb3dpbmcgZ2VzdHVyZXMgYXJlIHN1cHBvcnRlZDpcbiAqICAgICAtIERyYWcgZ2VzdHVyZXM6IGBkcmFnYCwgYGRyYWdsZWZ0YCwgYGRyYWdyaWdodGAsIGBkcmFndXBgLCBgZHJhZ2Rvd25gXG4gKiAgICAgLSBIb2xkIGdlc3R1cmVzOiBgaG9sZGAsIGByZWxlYXNlYFxuICogICAgIC0gU3dpcGUgZ2VzdHVyZXM6IGBzd2lwZWAsIGBzd2lwZWxlZnRgLCBgc3dpcGVyaWdodGAsIGBzd2lwZXVwYCwgYHN3aXBlZG93bmBcbiAqICAgICAtIFRhcCBnZXN0dXJlczogYHRhcGAsIGBkb3VibGV0YXBgXG4gKiAgICAgLSBQaW5jaCBnZXN0dXJlczogYHBpbmNoYCwgYHBpbmNoaW5gLCBgcGluY2hvdXRgXG4gKiAgICAgLSBPdGhlciBnZXN0dXJlczogYHRvdWNoYCwgYHRyYW5zZm9ybWAsIGByb3RhdGVgXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3opoHntKDlhoXjga7jgrjjgqfjgrnjg4Hjg6Pjg7zmk43kvZzjgpLmpJznn6XjgZfjgb7jgZnjgILoqbPjgZfjgY/jga/jgqzjgqTjg4njgpLlj4LnhafjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICogQGd1aWRlIGdlc3R1cmUtZGV0ZWN0b3JcbiAqICAgW2VuXURldGVjdGluZyBmaW5nZXIgZ2VzdHVyZXNbL2VuXVxuICogICBbamFd44K444Kn44K544OB44Oj44O85pON5L2c44Gu5qSc55+lWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWdlc3R1cmUtZGV0ZWN0b3I+XG4gKiAgIDxkaXYgaWQ9XCJkZXRlY3QtYXJlYVwiIHN0eWxlPVwid2lkdGg6IDEwMHB4OyBoZWlnaHQ6IDEwMHB4O1wiPlxuICogICAgIFN3aXBlIEhlcmVcbiAqICAgPC9kaXY+XG4gKiA8L29ucy1nZXN0dXJlLWRldGVjdG9yPlxuICpcbiAqIDxzY3JpcHQ+XG4gKiAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3N3aXBlbGVmdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gKiAgICAgaWYgKGV2ZW50LnRhcmdldC5tYXRjaGVzKCcjZGV0ZWN0LWFyZWEnKSkge1xuICogICAgICAgY29uc29sZS5sb2coJ1N3aXBlIGxlZnQgaXMgZGV0ZWN0ZWQuJyk7XG4gKiAgICAgfVxuICogICB9KTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHZXN0dXJlRGV0ZWN0b3JFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuICBpbml0KCkge1xuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcyk7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZ2VzdHVyZS1kZXRlY3RvcicsIEdlc3R1cmVEZXRlY3RvckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtaWNvblxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaXNwbGF5cyBhbiBpY29uLiBUaGUgZm9sbG93aW5nIGljb24gc3VpdGVzIGFyZSBhdmFpbGFibGU6XG4gKlxuICogICAgICogW0ZvbnQgQXdlc29tZV0oaHR0cHM6Ly9mb3J0YXdlc29tZS5naXRodWIuaW8vRm9udC1Bd2Vzb21lLylcbiAqICAgICAqIFtJb25pY29uc10oaHR0cDovL2lvbmljb25zLmNvbS8pXG4gKiAgICAgKiBbTWF0ZXJpYWwgRGVzaWduIEljb25pYyBGb250XShodHRwOi8vemF2b2xva2xvbS5naXRodWIuaW8vbWF0ZXJpYWwtZGVzaWduLWljb25pYy1mb250LylcbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB4QWh2Z1xuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2ljb25cbiAqIEBndWlkZSBjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1pY29uXG4gKiAgIGljb249XCJtZC1jYXJcIlxuICogICBzaXplPVwiMjBweFwiXG4gKiAgIHN0eWxlPVwiY29sb3I6IHJlZFwiPlxuICogPC9vbnMtaWNvbj5cbiAqXG4gKiA8b25zLWJ1dHRvbj5cbiAqICAgPG9ucy1pY29uIGljb249XCJtZC1jYXJcIj48L29ucy1pY29uPlxuICogICBDYXJcbiAqIDwvb25zLWJ1dHRvbj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSWNvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWNvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBUaGUgaWNvbiBuYW1lLiBgXCJtZC1cImAgcHJlZml4IGZvciBNYXRlcmlhbCBJY29ucywgYFwiZmEtXCJgIGZvciBGb250IEF3ZXNvbWUgYW5kIGBcImlvbi1cImAgcHJlZml4IGZvciBJb25pY29ucy5cbiAgICpcbiAgICogICAgIFNlZSBhbGwgYXZhaWxhYmxlIGljb25zIG9uIHRoZWlyIHJlc3BlY3RpdmUgc2l0ZXM6XG4gICAqXG4gICAqICAgICAqIFtGb250IEF3ZXNvbWVdKGh0dHBzOi8vZm9ydGF3ZXNvbWUuZ2l0aHViLmlvL0ZvbnQtQXdlc29tZS8pXG4gICAqICAgICAqIFtJb25pY29uc10oaHR0cDovL2lvbmljb25zLmNvbSlcbiAgICogICAgICogW01hdGVyaWFsIERlc2lnbiBJY29uaWMgRm9udF0oaHR0cDovL3phdm9sb2tsb20uZ2l0aHViLmlvL21hdGVyaWFsLWRlc2lnbi1pY29uaWMtZm9udC8pXG4gICAqXG4gICAqICAgICBJY29ucyBjYW4gYWxzbyBiZSBzdHlsZWQgYmFzZWQgb24gbW9kaWZpZXIgcHJlc2VuY2UuIEFkZCBjb21tYS1zZXBhcmF0ZWQgaWNvbnMgd2l0aCBgXCJtb2RpZmllck5hbWU6XCJgIHByZWZpeC5cbiAgICpcbiAgICogICAgIFRoZSBjb2RlOlxuICAgKlxuICAgKiAgICAgYGBgXG4gICAqICAgICA8b25zLWljb25cbiAgICogICAgICAgaWNvbj1cImlvbi1lZGl0LCBtYXRlcmlhbDptZC1lZGl0XCI+XG4gICAqICAgICA8L29ucy1pY29uPlxuICAgKiAgICAgYGBgXG4gICAqXG4gICAqICAgICB3aWxsIGRpc3BsYXkgYFwibWQtZWRpdFwiYCBmb3IgTWF0ZXJpYWwgRGVzaWduIGFuZCBgXCJpb24tZWRpdFwiYCBhcyB0aGUgZGVmYXVsdCBpY29uLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHNpemVzIG9mIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIGxnLCAyeCwgM3gsIDR4LCA1eCwgb3IgaW4gdGhlIHNpemUgaW4gcGl4ZWxzLlxuICAgKiAgICAgSWNvbnMgY2FuIGFsc28gYmUgc3R5bGVkIGJhc2VkIG9uIG1vZGlmaWVyIHByZXNlbmNlLiBBZGQgY29tbWEtc2VwYXJhdGVkIGljb25zIHdpdGggYFwibW9kaWZpZXJOYW1lOlwiYCBwcmVmaXguXG4gICAqXG4gICAqICAgICBUaGUgY29kZTpcbiAgICpcbiAgICogICAgIGBgYFxuICAgKiAgICAgPG9ucy1pY29uXG4gICAqICAgICAgIGljb249XCJpb24tZWRpdFwiXG4gICAqICAgICAgIHNpemU9XCIzMnB4LCBtYXRlcmlhbDoyNHB4XCI+XG4gICAqICAgICA8L29ucy1pY29uPlxuICAgKiAgICAgYGBgXG4gICAqXG4gICAqICAgICB3aWxsIHJlbmRlciBhcyBhIGAyNHB4YCBpY29uIGlmIHRoZSBgXCJtYXRlcmlhbFwiYCBtb2RpZmllciBpcyBwcmVzZW50IGFuZCBgMzJweGAgb3RoZXJ3aXNlLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJvdGF0ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTnVtYmVyIG9mIGRlZ3JlZXMgdG8gcm90YXRlIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIDkwLCAxODAgYW5kIDI3MC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjgqTjgrPjg7PjgpLlm57ou6LjgZfjgabooajnpLrjgZfjgb7jgZnjgII5MCwgMTgwLCAyNzDjgYvjgonmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmaXhlZC13aWR0aFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dV2hlbiB1c2VkIGluIGEgbGlzdCwgeW91IHdhbnQgdGhlIGljb25zIHRvIGhhdmUgdGhlIHNhbWUgd2lkdGggc28gdGhhdCB0aGV5IGFsaWduIHZlcnRpY2FsbHkgYnkgZGVmaW5pbmcgdGhpcyBhdHRyaWJ1dGUuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzcGluXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoZXRoZXIgdGhlIGljb24gc2hvdWxkIGJlIHNwaW5uaW5nLlsvZW5dXG4gICAqICAgW2phXeOCouOCpOOCs+ODs+OCkuWbnui7ouOBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fY29tcGlsZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnaWNvbicsICdzaXplJywgJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChbJ2ljb24nLCAnc2l6ZScsICdtb2RpZmllciddLmluZGV4T2YobmFtZSkgIT09IC0xKSB7XG4gICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICB9XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLl91cGRhdGUoKTtcbiAgfVxuXG4gIF91cGRhdGUoKSB7XG4gICAgdGhpcy5fY2xlYW5DbGFzc0F0dHJpYnV0ZSgpO1xuICAgIGNvbnN0IHtjbGFzc0xpc3QsIHN0eWxlfSA9IHRoaXMuX2J1aWxkQ2xhc3NBbmRTdHlsZSh0aGlzLl9nZXRBdHRyaWJ1dGUoJ2ljb24nKSwgdGhpcy5fZ2V0QXR0cmlidXRlKCdzaXplJykpO1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMuc3R5bGUsIHN0eWxlKTtcblxuICAgIGNsYXNzTGlzdC5mb3JFYWNoKGNsYXNzTmFtZSA9PiB0aGlzLmNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKSk7XG4gIH1cblxuICBfZ2V0QXR0cmlidXRlKGF0dHIpIHtcbiAgICBjb25zdCBwYXJ0cyA9ICh0aGlzLmdldEF0dHJpYnV0ZShhdHRyKSB8fCAnJykuc3BsaXQoL1xccyosXFxzKi8pO1xuICAgIGNvbnN0IGRlZiA9IHBhcnRzWzBdO1xuICAgIGxldCBtZCA9IHBhcnRzWzFdO1xuICAgIG1kID0gKG1kIHx8ICcnKS5zcGxpdCgvXFxzKjpcXHMqLyk7XG4gICAgcmV0dXJuICh1dGlsLmhhc01vZGlmaWVyKHRoaXMsIG1kWzBdKSA/IG1kWzFdIDogZGVmKSB8fCAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdW5uZWVkZWQgY2xhc3MgdmFsdWUuXG4gICAqL1xuICBfY2xlYW5DbGFzc0F0dHJpYnV0ZSgpIHtcbiAgICB1dGlsLmFycmF5RnJvbSh0aGlzLmNsYXNzTGlzdClcbiAgICAgIC5maWx0ZXIoY2xhc3NOYW1lID0+IC9eKGZhJHxmYS18aW9uLXx6bWRpLSkvLnRlc3QoY2xhc3NOYW1lKSlcbiAgICAgIC5mb3JFYWNoKGNsYXNzTmFtZSA9PiB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoY2xhc3NOYW1lKSk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoJ3ptZGknKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoJ29ucy1pY29uLS1pb24nKTtcbiAgfVxuXG4gIF9idWlsZENsYXNzQW5kU3R5bGUoaWNvbk5hbWUsIHNpemUpIHtcbiAgICBjb25zdCBjbGFzc0xpc3QgPSBbJ29ucy1pY29uJ107XG4gICAgY29uc3Qgc3R5bGUgPSB7fTtcblxuICAgIC8vIEljb25cbiAgICBpZiAoaWNvbk5hbWUuaW5kZXhPZignaW9uLScpID09PSAwKSB7XG4gICAgICBjbGFzc0xpc3QucHVzaChpY29uTmFtZSk7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnb25zLWljb24tLWlvbicpO1xuICAgIH0gZWxzZSBpZiAoaWNvbk5hbWUuaW5kZXhPZignZmEtJykgPT09IDApIHtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKGljb25OYW1lKTtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKCdmYScpO1xuICAgIH0gZWxzZSBpZihpY29uTmFtZS5pbmRleE9mKCdtZC0nKSA9PT0gMCkgIHtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKCd6bWRpJyk7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnem1kaS0nICsgaWNvbk5hbWUuc3BsaXQoL1xcLSguKyk/LylbMV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnZmEnKTtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKCdmYS0nICsgaWNvbk5hbWUpO1xuICAgIH1cblxuICAgIC8vIFNpemVcbiAgICBpZiAoc2l6ZS5tYXRjaCgvXlsxLTVdeHxsZyQvKSkge1xuICAgICAgY2xhc3NMaXN0LnB1c2goJ2ZhLScgKyBzaXplKTtcbiAgICAgIHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2ZvbnQtc2l6ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZS5mb250U2l6ZSA9IHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsYXNzTGlzdDogY2xhc3NMaXN0LFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1pY29uJywgSWNvbkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCB7TGF6eVJlcGVhdERlbGVnYXRlLCBMYXp5UmVwZWF0UHJvdmlkZXJ9IGZyb20gJy4uL29ucy9pbnRlcm5hbC9sYXp5LXJlcGVhdCc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxhenktcmVwZWF0XG4gKiBAY2F0ZWdvcnkgbGlzdFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVc2luZyB0aGlzIGNvbXBvbmVudCBhIGxpc3Qgd2l0aCBtaWxsaW9ucyBvZiBpdGVtcyBjYW4gYmUgcmVuZGVyZWQgd2l0aG91dCBhIGRyb3AgaW4gcGVyZm9ybWFuY2UuXG4gKiAgICAgSXQgZG9lcyB0aGF0IGJ5IFwibGF6aWx5XCIgbG9hZGluZyBlbGVtZW50cyBpbnRvIHRoZSBET00gd2hlbiB0aGV5IGNvbWUgaW50byB2aWV3IGFuZFxuICogICAgIHJlbW92aW5nIGl0ZW1zIGZyb20gdGhlIERPTSB3aGVuIHRoZXkgYXJlIG5vdCB2aXNpYmxlLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI5YaF44Gn5o+P55S744GV44KM44KL44Ki44Kk44OG44Og44GuRE9N6KaB57Sg44Gu6Kqt44G/6L6844G/44Gv44CB55S76Z2i44Gr6KaL44GI44Gd44GG44Gr44Gq44Gj44Gf5pmC44G+44Gn6Ieq5YuV55qE44Gr6YGF5bu244GV44KM44CBXG4gKiAgICAg55S76Z2i44GL44KJ6KaL44GI44Gq44GP44Gq44Gj44Gf5aC05ZCI44Gr44Gv44Gd44Gu6KaB57Sg44Gv5YuV55qE44Gr44Ki44Oz44Ot44O844OJ44GV44KM44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44KS5L2/44GG44GT44Go44Gn44CB44OR44OV44Kp44O844Oe44Oz44K544KS5Yqj5YyW44GV44Gb44KL44GT44Go54Sh44GX44Gr5beo5aSn44Gq5pWw44Gu6KaB57Sg44KS5o+P55S744Gn44GN44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBRd3JHQm1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9sYXp5LXJlcGVhdFxuICogQHNlZWFsc28gb25zLWxpc3RcbiAqICAgW2VuXVRoZSBgPG9ucy1saXN0PmAgZWxlbWVudCBpcyB1c2VkIHRvIHJlbmRlciBhIGxpc3QuWy9lbl1cbiAqICAgW2phXWA8b25zLWxpc3Q+YOimgee0oOOBr+ODquOCueODiOOCkuaPj+eUu+OBmeOCi+OBruOBq+S9v+OCj+OCjOOBvuOBmeOAglsvamFdXG4gKiBAZ3VpZGUgaW5maW5pdGUtc2Nyb2xsXG4gKiAgIFtlbl1Mb2FkaW5nIG1vcmUgaXRlbXMgb24gaW5maW5pdGUgc2Nyb2xsWy9lbl1cbiAqICAgW2phXUxvYWRpbmcgbW9yZSBpdGVtcyBvbiBpbmZpbml0ZSBzY3JvbGxbL2phXVxuICogQGV4YW1wbGVcbiAqIDxzY3JpcHQ+XG4gKiAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24oKSB7XG4gKiAgICAgdmFyIGxhenlSZXBlYXQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjbGlzdCcpO1xuICogICAgIGxhenlSZXBlYXQuZGVsZWdhdGUgPSB7XG4gKiAgICAgIGNyZWF0ZUl0ZW1Db250ZW50OiBmdW5jdGlvbihpLCB0ZW1wbGF0ZSkge1xuICogICAgICAgIHZhciBkb20gPSB0ZW1wbGF0ZS5jbG9uZU5vZGUodHJ1ZSk7XG4gKiAgICAgICAgZG9tLmlubmVyVGV4dCA9IGk7XG4gKlxuICogICAgICAgIHJldHVybiBkb207XG4gKiAgICAgIH0sXG4gKiAgICAgIGNvdW50SXRlbXM6IGZ1bmN0aW9uKCkge1xuICogICAgICAgIHJldHVybiAxMDAwMDAwMDtcbiAqICAgICAgfSxcbiAqICAgICAgZGVzdHJveUl0ZW06IGZ1bmN0aW9uKGluZGV4LCBpdGVtKSB7XG4gKiAgICAgICAgY29uc29sZS5sb2coJ0Rlc3Ryb3llZCBpdGVtIHdpdGggaW5kZXg6ICcgKyBpbmRleCk7XG4gKiAgICAgIH1cbiAqICAgICB9O1xuICogICB9KTtcbiAqIDwvc2NyaXB0PlxuICpcbiAqIDxvbnMtbGlzdCBpZD1cImxpc3RcIj5cbiAqICAgPG9ucy1sYXp5LXJlcGVhdD5cbiAqICAgICA8b25zLWxpc3QtaXRlbT48L29ucy1saXN0LWl0ZW0+XG4gKiAgIDwvb25zLWxhenktcmVwZWF0PlxuICogPC9vbnMtbGlzdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGF6eVJlcGVhdEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdXRpbC51cGRhdGVQYXJlbnRQb3NpdGlvbih0aGlzKTtcblxuICAgIC8vIG5vdCB2ZXJ5IGdvb2QgaWRlYSBhbmQgYWxzbyBub3QgZG9jdW1lbnRlZFxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnZGVsZWdhdGUnKSkge1xuICAgICAgdGhpcy5kZWxlZ2F0ZSA9IHdpbmRvd1t0aGlzLmdldEF0dHJpYnV0ZSgnZGVsZWdhdGUnKV07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkZWxlZ2F0ZVxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IGEgZGVsZWdhdGUgb2JqZWN0IHRvIGxvYWQgYW5kIHVubG9hZCBpdGVtIGVsZW1lbnRzLlsvZW5dXG4gICAqICBbamFd6KaB57Sg44Gu44Ot44O844OJ44CB44Ki44Oz44Ot44O844OJ44Gq44Gp44Gu5Yem55CG44KS5aeU6K2y44GZ44KL44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkZWxlZ2F0ZS5jcmVhdGVJdGVtQ29udGVudFxuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1cbiAgICogICAgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIGBIVE1MRWxlbWVudGAuXG4gICAqXG4gICAqICAgICBUbyBoZWxwIHJlbmRlcmluZyB0aGUgZWxlbWVudCwgdGhlIGN1cnJlbnQgaW5kZXggYW5kIGEgdGVtcGxhdGUgaXMgc3VwcGxpZWQgYXMgYXJndW1lbnRzLiBUaGUgdGVtcGxhdGUgaXMgdGhlIGluaXRpYWwgY29udGVudCBvZiB0aGUgYDxvbnMtbGF6eS1yZXBlYXQ+YCBlbGVtZW50LlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44GT44Gu6Zai5pWw44GvYEhUTUxFbGVtZW50YOOCkui/lOOBl+OBpuOBj+OBoOOBleOBhOOAglxuICAgKiAgICAg6KaB57Sg44KS55Sf5oiQ44GX44KE44GZ44GP44GZ44KL44Gf44KB44Gr44CB54++5Zyo44Gu44Ki44Kk44OG44Og44Gu44Kk44Oz44OH44OD44Kv44K544Go44OG44Oz44OX44Os44O844OI44GM5byV5pWw44Gr5rih44GV44KM44G+44GZ44CCXG4gICAqICAgICDjgZPjga7jg4bjg7Pjg5fjg6zjg7zjg4jjga/jgIFgPG9ucy1sYXp5LXJlcGVhdD5g6KaB57Sg44Gu44Kz44Oz44OG44Oz44OE44GM5rih44GV44KM44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkZWxlZ2F0ZS5jb3VudEl0ZW1zXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3VsZCByZXR1cm4gdGhlIG51bWJlciBvZiBpdGVtcyBpbiB0aGUgbGlzdC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jlhoXjga7jgqLjgqTjg4bjg6DmlbDjgpLov5TjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHRcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBTaG91bGQgcmV0dXJuIHRoZSBoZWlnaHQgb2YgYW4gaXRlbS4gVGhlIGluZGV4IGlzIHByb3ZpZGVkIGFzIGFuIGFyZ3VtZW50LlxuICAgKlxuICAgKiAgICAgVGhpcyBpcyBpbXBvcnRhbnQgd2hlbiByZW5kZXJpbmcgbGlzdHMgd2hlcmUgdGhlIGl0ZW1zIGhhdmUgZGlmZmVyZW50IGhlaWdodC5cbiAgICpcbiAgICogICAgIFRoZSBmdW5jdGlvbiBpcyBvcHRpb25hbCBhbmQgaWYgaXQgaXNuJ3QgcHJlc2VudCB0aGUgaGVpZ2h0IG9mIHRoZSBmaXJzdCBpdGVtIHdpbGwgYmUgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkIGFuZCB1c2VkIGZvciBhbGwgb3RoZXIgaXRlbXMuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdXG4gICAqICAgICDjgqLjgqTjg4bjg6Djga7pq5jjgZUo44OU44Kv44K744OrKeOCkui/lOOBl+OBpuOBj+OBoOOBleOBhOOAguOCouOCpOODhuODoOOBruOCpOODs+ODh+ODg+OCr+OCueWApOOBr+W8leaVsOOBp+a4oeOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44GT44Gu6Zai5pWw44Gv44CB44Gd44KM44Ge44KM44Gu44Ki44Kk44Og44GM6YGV44Gj44Gf6auY44GV44KS5oyB44Gk44Oq44K544OI44KS44Os44Oz44OA44Oq44Oz44Kw44GZ44KL6Zqb44Gr6YeN6KaB44Gn44GZ44CCXG4gICAqICAgICDjgZPjga7plqLmlbDjga/jgqrjg5fjgrfjg6fjg4rjg6vjgafjgZnjgILjgoLjgZfjgZPjga7plqLmlbDjgYznhKHjgYTloLTlkIjjgavjga/jgIFcbiAgICogICAgIOacgOWIneOBruOCouOCpOODhuODoOOBrumrmOOBleOBjOS7luOBruOBmeOBueOBpuOBruOCouOCpOODhuODoOOBrumrmOOBleOBqOOBl+OBpuWIqeeUqOOBleOCjOOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGUuZGVzdHJveUl0ZW1cbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgY2FsbGVkIHdoZW4gYW4gaXRlbSBpcyByZW1vdmVkIGZyb20gdGhlIERPTS4gVGhlIGluZGV4IGFuZCBET00gZWxlbWVudCBpcyBwcm92aWRlZCBhcyBhcmd1bWVudHMuXG4gICAqXG4gICAqICAgICBUaGUgZnVuY3Rpb24gaXMgb3B0aW9uYWwgYnV0IG1heSBiZSBpbXBvcnRhbnQgaW4gb3JkZXIgdG8gYXZvaWQgbWVtb3J5IGxlYWtzLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44GT44Gu6Zai5pWw44Gv44CB44GC44KL44Ki44Kk44OG44Og44GMRE9N44OE44Oq44O844GL44KJ6Zmk44GL44KM44Gf5pmC44Gr5ZG844Gz5Ye644GV44KM44G+44GZ44CCXG4gICAqICAgICDjgqLjgqTjg4bjg6Djga7jgqTjg7Pjg4fjg4Pjgq/jgrnlgKTjgahET03opoHntKDjgYzlvJXmlbDjgajjgZfjgabmuKHjgZXjgozjgb7jgZnjgIJcbiAgICogICAgIOOBk+OBrumWouaVsOOBr+OCquODl+OCt+ODp+ODiuODq+OBp+OBmeOBjOOAgeWQhOOCouOCpOODhuODoOOBruW+jOWHpueQhuOBjOW/heimgeOBquWgtOWQiOOBq+OBr+ODoeODouODquODvOODquODvOOCr+OCkumBv+OBkeOCi+OBn+OCgeOBq+mHjeimgeOBp+OBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIHNldCBkZWxlZ2F0ZSh1c2VyRGVsZWdhdGUpIHtcbiAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIgJiYgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyLmRlc3Ryb3koKTtcblxuICAgIGlmICghdGhpcy5fdGVtcGxhdGVFbGVtZW50ICYmIHRoaXMuY2hpbGRyZW5bMF0pIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlRWxlbWVudCA9IHRoaXMucmVtb3ZlQ2hpbGQodGhpcy5jaGlsZHJlblswXSk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVsZWdhdGUgPSBuZXcgTGF6eVJlcGVhdERlbGVnYXRlKHVzZXJEZWxlZ2F0ZSwgdGhpcy5fdGVtcGxhdGVFbGVtZW50IHx8IG51bGwpO1xuICAgIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlciA9IG5ldyBMYXp5UmVwZWF0UHJvdmlkZXIodGhpcy5wYXJlbnRFbGVtZW50LCBkZWxlZ2F0ZSk7XG4gIH1cblxuICBnZXQgZGVsZWdhdGUoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIHByb3BlcnR5IGNhbiBvbmx5IGJlIHVzZWQgdG8gc2V0IHRoZSBkZWxlZ2F0ZSBvYmplY3QuJyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCByZWZyZXNoXG4gICAqIEBzaWduYXR1cmUgcmVmcmVzaCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZWZyZXNoIHRoZSBsaXN0LiBVc2UgdGhpcyBtZXRob2Qgd2hlbiB0aGUgZGF0YSBoYXMgY2hhbmdlZC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jjgpLmm7TmlrDjgZfjgb7jgZnjgILjgoLjgZfjg4fjg7zjgr/jgYzlpInjgo/jgaPjgZ/loLTlkIjjgavjga/jgZPjga7jg6Hjgr3jg4Pjg4njgpLkvb/jgaPjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cbiAgcmVmcmVzaCgpIHtcbiAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIgJiYgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyLnJlZnJlc2goKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7fVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIpIHtcbiAgICAgIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlci5kZXN0cm95KCk7XG4gICAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxhenktcmVwZWF0JywgTGF6eVJlcGVhdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuXG5jb25zdCBzY2hlbWUgPSB7Jyc6ICdsaXN0X19oZWFkZXItLSonfTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtbGlzdC1oZWFkZXJcbiAqIEBjYXRlZ29yeSBsaXN0XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUhlYWRlciBlbGVtZW50IGZvciBsaXN0IGl0ZW1zLiBNdXN0IGJlIHB1dCBpbnNpZGUgdGhlIGA8b25zLWxpc3Q+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXeODquOCueODiOimgee0oOOBq+S9v+eUqOOBmeOCi+ODmOODg+ODgOODvOeUqOOCs+ODs+ODneODvOODjeODs+ODiOOAgm9ucy1saXN044Go5YWx44Gr5L2/55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0XG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1pdGVtXG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdC1pdGVtPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN0LWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGd1aWRlIGxpc3RzIFtlbl1Vc2luZyBsaXN0c1svZW5dW2phXeODquOCueODiOOCkuS9v+OBhlsvamFdXG4gKiBAY29kZXBlbiB5eGNDdFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2xpc3RcbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dRGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBsaXN0IGhlYWRlci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWxpc3Q+XG4gKiAgIDxvbnMtbGlzdC1oZWFkZXI+SGVhZGVyIFRleHQ8L29ucy1saXN0LWhlYWRlcj5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqIDwvb25zLWxpc3Q+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpc3RIZWFkZXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgbGlzdCBoZWFkZXIuWy9lbl1cbiAgICogICBbamFd44OY44OD44OA44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLl9jb21waWxlKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2xpc3RfX2hlYWRlcicpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICByZXR1cm4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgfVxuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxpc3QtaGVhZGVyJywgTGlzdEhlYWRlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5saXN0X19pdGVtJzogJ2xpc3RfX2l0ZW0tLSonLFxuICAnLmxpc3RfX2l0ZW1fX2xlZnQnOiAnbGlzdF9faXRlbS0tKl9fbGVmdCcsXG4gICcubGlzdF9faXRlbV9fY2VudGVyJzogJ2xpc3RfX2l0ZW0tLSpfX2NlbnRlcicsXG4gICcubGlzdF9faXRlbV9fcmlnaHQnOiAnbGlzdF9faXRlbS0tKl9fcmlnaHQnLFxuICAnLmxpc3RfX2l0ZW1fX2xhYmVsJzogJ2xpc3RfX2l0ZW0tLSpfX2xhYmVsJyxcbiAgJy5saXN0X19pdGVtX190aXRsZSc6ICdsaXN0X19pdGVtLS0qX190aXRsZScsXG4gICcubGlzdF9faXRlbV9fc3VidGl0bGUnOiAnbGlzdF9faXRlbS0tKl9fc3VidGl0bGUnLFxuICAnLmxpc3RfX2l0ZW1fX3RodW1ibmFpbCc6ICdsaXN0X19pdGVtLS0qX190aHVtYm5haWwnLFxuICAnLmxpc3RfX2l0ZW1fX2ljb24nOiAnbGlzdF9faXRlbS0tKl9faWNvbidcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxpc3QtaXRlbVxuICogQGNhdGVnb3J5IGxpc3RcbiAqIEBtb2RpZmllciB0YXBwYWJsZVxuICogICBbZW5dTWFrZSB0aGUgbGlzdCBpdGVtIGNoYW5nZSBhcHBlYXJhbmNlIHdoZW4gaXQncyB0YXBwZWQuIE9uIGlPUyBpdCBpcyBiZXR0ZXIgdG8gdXNlIHRoZSBcInRhcHBhYmxlXCIgYW5kIFwidGFwLWJhY2tncm91bmQtY29sb3JcIiBhdHRyaWJ1dGUgZm9yIGJldHRlciBiZWhhdmlvciB3aGVuIHNjcm9sbGluZy5bL2VuXVxuICogICBbamFd44K/44OD44OX44KE44Kv44Oq44OD44Kv44GX44Gf5pmC44Gr5Yq55p6c44GM6KGo56S644GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBjaGV2cm9uXG4gKiAgIFtlbl1EaXNwbGF5IGEgY2hldnJvbiBhdCB0aGUgcmlnaHQgZW5kIG9mIHRoZSBsaXN0IGl0ZW0gYW5kIG1ha2UgaXQgY2hhbmdlIGFwcGVhcmFuY2Ugd2hlbiB0YXBwZWQuIFRoZSBjaGV2cm9uIGlzIG5vdCBkaXNwbGF5ZWQgaW4gTWF0ZXJpYWwgRGVzaWduLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIGxvbmdkaXZpZGVyXG4gKiAgIFtlbl1EaXNwbGF5cyBhIGxvbmcgaG9yaXpvbnRhbCBkaXZpZGVyIGJldHdlZW4gaXRlbXMuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgbm9kaXZpZGVyXG4gKiAgIFtlbl1SZW1vdmVzIHRoZSBkaXZpZGVyIGJldHdlZW4gbGlzdCBpdGVtcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dRGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBsaXN0IGl0ZW0uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbXBvbmVudCB0aGF0IHJlcHJlc2VudHMgZWFjaCBpdGVtIGluIHRoZSBsaXN0LiBNdXN0IGJlIHB1dCBpbnNpZGUgdGhlIGA8b25zLWxpc3Q+YCBjb21wb25lbnQuXG4gKlxuICogICAgIFRoZSBsaXN0IGl0ZW0gaXMgY29tcG9zZWQgb2YgdGhyZWUgcGFydHMgdGhhdCBhcmUgcmVwcmVzZW50ZWQgd2l0aCB0aGUgYGxlZnRgLCBgY2VudGVyYCBhbmQgYHJpZ2h0YCBjbGFzc2VzLiBUaGVzZSBjbGFzc2VzIGNhbiBiZSB1c2VkIHRvIGVuc3VyZSB0aGF0IHRoZSBjb250ZW50IG9mIHRoZSBsaXN0IGl0ZW1zIGlzIHByb3Blcmx5IGFsaWduZWQuXG4gKlxuICogICAgIGBgYFxuICogICAgIDxvbnMtbGlzdC1pdGVtPlxuICogICAgICAgPGRpdiBjbGFzcz1cImxlZnRcIj5MZWZ0PC9kaXY+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwiY2VudGVyXCI+Q2VudGVyPC9kaXY+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5SaWdodDwvZGl2PlxuICogICAgIDwvb25zLWxpc3QtaXRlbT5cbiAqICAgICBgYGBcbiAqXG4gKiAgICAgVGhlcmUgaXMgYWxzbyBhIG51bWJlciBvZiBjbGFzc2VzIChwcmVmaXhlZCB3aXRoIGBsaXN0X19pdGVtX18qYCkgdGhhdCBoZWxwIHdoZW4gcHV0dGluZyB0aGluZ3MgbGlrZSBpY29ucyBhbmQgdGh1bWJuYWlscyBpbnRvIHRoZSBsaXN0IGl0ZW1zLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0XG4gKiAgIFtlbl1vbnMtbGlzdCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWxpc3TjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWxpc3QtaGVhZGVyXG4gKiAgIFtlbl1vbnMtbGlzdC1oZWFkZXIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN0LWhlYWRlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZ3VpZGUgbGlzdHNcbiAqICAgW2VuXVVzaW5nIGxpc3RzWy9lbl1cbiAqICAgW2phXeODquOCueODiOOCkuS9v+OBhlsvamFdXG4gKiBAY29kZXBlbiB5eGNDdFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2xpc3RcbiAqIEBleGFtcGxlXG4gKiA8b25zLWxpc3QtaXRlbT5cbiAqICAgPGRpdiBjbGFzcz1cImxlZnRcIj5cbiAqICAgICA8b25zLWljb24gaWNvbj1cIm1kLWZhY2VcIiBjbGFzcz1cImxpc3RfX2l0ZW1fX2ljb25cIj48L29ucy1pY29uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIDxkaXYgY2xhc3M9XCJsaXN0X19pdGVtX190aXRsZVwiPlRpdGxlPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cImxpc3RfX2l0ZW1fX3N1YnRpdGxlXCI+U3VidGl0bGU8L2Rpdj5cbiAqICAgPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJyaWdodFwiPlxuICogICAgIDxvbnMtc3dpdGNoPjwvb25zLXN3aXRjaD5cbiAqICAgPC9kaXY+XG4gKiA8L29ucy1saXN0LWl0ZW0+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpc3RJdGVtRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGxpc3QgaXRlbS5bL2VuXVxuICAgKiAgIFtqYV3lkITopoHntKDjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBsb2NrLW9uLWRyYWdcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVByZXZlbnQgdmVydGljYWwgc2Nyb2xsaW5nIHdoZW4gdGhlIHVzZXIgZHJhZ3MgaG9yaXpvbnRhbGx5LlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+OBqOOAgeODpuODvOOCtuODvOOBjOOBk+OBruimgee0oOOCkuaoquaWueWQkeOBq+ODieODqeODg+OCsOOBl+OBpuOBhOOCi+aZguOBq+OAgee4puaWueWQkeOBruOCueOCr+ODreODvOODq+OBjOi1t+OBjeOBquOBhOOCiOOBhuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRhcHBhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTWFrZXMgdGhlIGVsZW1lbnQgcmVhY3QgdG8gdGFwcy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0YXAtYmFja2dyb3VuZC1jb2xvclxuICAgKiBAdHlwZSB7Q29sb3J9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl0gQ2hhbmdlcyB0aGUgYmFja2dyb3VuZCBjb2xvciB3aGVuIHRhcHBlZC4gRm9yIHRoaXMgdG8gd29yaywgdGhlIGF0dHJpYnV0ZSBcInRhcHBhYmxlXCIgbmVlZHMgdG8gYmUgc2V0LiBUaGUgZGVmYXVsdCBjb2xvciBpcyBcIiNkOWQ5ZDlcIi4gSXQgd2lsbCBkaXNwbGF5IGFzIGEgcmlwcGxlIGVmZmVjdCBvbiBBbmRyb2lkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnbGlzdF9faXRlbScpO1xuXG4gICAgbGV0IGxlZnQsIGNlbnRlciwgcmlnaHQ7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGVsID0gdGhpcy5jaGlsZHJlbltpXTtcblxuICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucygnbGVmdCcpKSB7XG4gICAgICAgIGVsLmNsYXNzTGlzdC5hZGQoJ2xpc3RfX2l0ZW1fX2xlZnQnKTtcbiAgICAgICAgbGVmdCA9IGVsO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdjZW50ZXInKSkge1xuICAgICAgICBjZW50ZXIgPSBlbDtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucygncmlnaHQnKSkge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKCdsaXN0X19pdGVtX19yaWdodCcpO1xuICAgICAgICByaWdodCA9IGVsO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghY2VudGVyKSB7XG4gICAgICBjZW50ZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgaWYgKCFsZWZ0ICYmICFyaWdodCkge1xuICAgICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgICAgY2VudGVyLmFwcGVuZENoaWxkKHRoaXMuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLmNoaWxkTm9kZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBjb25zdCBlbCA9IHRoaXMuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgICBpZiAoZWwgIT09IGxlZnQgJiYgZWwgIT09IHJpZ2h0KSB7XG4gICAgICAgICAgICBjZW50ZXIuaW5zZXJ0QmVmb3JlKGVsLCBjZW50ZXIuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGNlbnRlciwgcmlnaHQgfHwgbnVsbCk7XG4gICAgfVxuXG4gICAgY2VudGVyLmNsYXNzTGlzdC5hZGQoJ2NlbnRlcicpO1xuICAgIGNlbnRlci5jbGFzc0xpc3QuYWRkKCdsaXN0X19pdGVtX19jZW50ZXInKTtcblxuICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuXG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignZHJhZycsIHRoaXMuX29uRHJhZyk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fb25Ub3VjaCk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vblRvdWNoKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25SZWxlYXNlKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25SZWxlYXNlKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgdGhpcy5fb25SZWxlYXNlKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobGVhdmUnLCB0aGlzLl9vblJlbGVhc2UpO1xuXG4gICAgdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLnN0eWxlLmJhY2tncm91bmRDb2xvcjtcblxuICAgIHRoaXMudGFwcGVkID0gZmFsc2U7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWcnLCB0aGlzLl9vbkRyYWcpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2gpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25Ub3VjaCk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGxlYXZlJywgdGhpcy5fb25SZWxlYXNlKTtcbiAgfVxuXG4gIGdldCBfdHJhbnNpdGlvbigpIHtcbiAgICByZXR1cm4gJ2JhY2tncm91bmQtY29sb3IgMC4wcyBsaW5lYXIgMC4wMnMsIGJveC1zaGFkb3cgMC4wcyBsaW5lYXIgMC4wMnMnO1xuICB9XG5cbiAgZ2V0IF90YXBwYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ3RhcHBhYmxlJyk7XG4gIH1cblxuICBnZXQgX3RhcEJhY2tncm91bmRDb2xvcigpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3RhcC1iYWNrZ3JvdW5kLWNvbG9yJykgfHwgJyNkOWQ5ZDknO1xuICB9XG5cbiAgX3VwZGF0ZVJpcHBsZSgpIHtcbiAgICB1dGlsLnVwZGF0ZVJpcHBsZSh0aGlzKTtcbiAgfVxuXG4gIF9vbkRyYWcoZXZlbnQpIHtcbiAgICBjb25zdCBnZXN0dXJlID0gZXZlbnQuZ2VzdHVyZTtcbiAgICAvLyBQcmV2ZW50IHZlcnRpY2FsIHNjcm9sbGluZyBpZiB0aGUgdXNlcnMgcGFucyBsZWZ0IG9yIHJpZ2h0LlxuICAgIGlmICh0aGlzLl9zaG91bGRMb2NrT25EcmFnKCkgJiYgWydsZWZ0JywgJ3JpZ2h0J10uaW5kZXhPZihnZXN0dXJlLmRpcmVjdGlvbikgPiAtMSkge1xuICAgICAgZ2VzdHVyZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIF9vblRvdWNoKCkge1xuICAgIGlmICh0aGlzLnRhcHBlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudGFwcGVkID0gdHJ1ZTtcblxuICAgIHRoaXMuc3R5bGUudHJhbnNpdGlvbiA9IHRoaXMuX3RyYW5zaXRpb247XG4gICAgdGhpcy5zdHlsZS53ZWJraXRUcmFuc2l0aW9uID0gdGhpcy5fdHJhbnNpdGlvbjtcbiAgICB0aGlzLnN0eWxlLk1velRyYW5zaXRpb24gPSB0aGlzLl90cmFuc2l0aW9uO1xuXG4gICAgaWYgKHRoaXMuX3RhcHBhYmxlKSB7XG4gICAgICBpZiAodGhpcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgICAgdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLnN0eWxlLmJhY2tncm91bmRDb2xvcjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLl90YXBCYWNrZ3JvdW5kQ29sb3I7XG4gICAgICB0aGlzLnN0eWxlLmJveFNoYWRvdyA9IGAwcHggLTFweCAwcHggMHB4ICR7dGhpcy5fdGFwQmFja2dyb3VuZENvbG9yfWA7XG4gICAgfVxuICB9XG5cbiAgX29uUmVsZWFzZSgpIHtcbiAgICB0aGlzLnRhcHBlZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5zdHlsZS50cmFuc2l0aW9uID0gJyc7XG4gICAgdGhpcy5zdHlsZS53ZWJraXRUcmFuc2l0aW9uID0gJyc7XG4gICAgdGhpcy5zdHlsZS5Nb3pUcmFuc2l0aW9uID0gJyc7XG5cbiAgICB0aGlzLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHRoaXMuX29yaWdpbmFsQmFja2dyb3VuZENvbG9yIHx8ICcnO1xuICAgIHRoaXMuc3R5bGUuYm94U2hhZG93ID0gJyc7XG4gIH1cblxuICBfc2hvdWxkTG9ja09uRHJhZygpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2xvY2stb24tZHJhZycpO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxpc3QtaXRlbScsIExpc3RJdGVtRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IHNjaGVtZSA9IHsnJzogJ2xpc3QtLSonfTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtbGlzdFxuICogQGNhdGVnb3J5IGxpc3RcbiAqIEBtb2RpZmllciBpbnNldFxuICogICBbZW5dSW5zZXQgbGlzdCB0aGF0IGRvZXNuJ3QgY292ZXIgdGhlIHdob2xlIHdpZHRoIG9mIHRoZSBwYXJlbnQuWy9lbl1cbiAqICAgW2phXeimquimgee0oOOBrueUu+mdouOBhOOBo+OBseOBhOOBq+W6g+OBjOOCieOBquOBhOODquOCueODiOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbm9ib3JkZXJcbiAqICAgW2VuXUEgbGlzdCB3aXRoIG5vIGJvcmRlcnMgYXQgdGhlIHRvcCBhbmQgYm90dG9tLlsvZW5dXG4gKiAgIFtqYV3jg6rjgrnjg4jjga7kuIrkuIvjga7jg5zjg7zjg4Djg7zjgYznhKHjgYTjg6rjgrnjg4jjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1Db21wb25lbnQgdG8gZGVmaW5lIGEgbGlzdCwgYW5kIHRoZSBjb250YWluZXIgZm9yIG9ucy1saXN0LWl0ZW0ocykuWy9lbl1cbiAqICAgW2phXeODquOCueODiOOCkuihqOePvuOBmeOCi+OBn+OCgeOBruOCs+ODs+ODneODvOODjeODs+ODiOOAgm9ucy1saXN0LWl0ZW3jga7jgrPjg7Pjg4bjg4rjgajjgZfjgabkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQHNlZWFsc28gb25zLWxpc3QtaXRlbVxuICogICBbZW5db25zLWxpc3QtaXRlbSBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWxpc3QtaXRlbeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1oZWFkZXJcbiAqICAgW2VuXW9ucy1saXN0LWhlYWRlciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWxpc3QtaGVhZGVy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1sYXp5LXJlcGVhdFxuICogICBbZW5db25zLWxhenktcmVwZWF0IGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGF6eS1yZXBlYXTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGd1aWRlIGxpc3RzXG4gKiAgIFtlbl1Vc2luZyBsaXN0c1svZW5dXG4gKiAgIFtqYV3jg6rjgrnjg4jjgpLkvb/jgYZbL2phXVxuICogQGd1aWRlIGluZmluaXRlLXNjcm9sbFxuICogICBbZW5dTG9hZGluZyBtb3JlIGl0ZW1zIG9uIGluZmluaXRlIHNjcm9sbFsvZW5dXG4gKiAgIFtqYV1Mb2FkaW5nIG1vcmUgaXRlbXMgb24gaW5maW5pdGUgc2Nyb2xsWy9qYV1cbiAqIEBjb2RlcGVuIHl4Y0N0XG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvbGlzdFxuICogQGV4YW1wbGVcbiAqIDxvbnMtbGlzdD5cbiAqICAgPG9ucy1saXN0LWhlYWRlcj5IZWFkZXIgVGV4dDwvb25zLWxpc3QtaGVhZGVyPlxuICogICA8b25zLWxpc3QtaXRlbT5JdGVtPC9vbnMtbGlzdC1pdGVtPlxuICogICA8b25zLWxpc3QtaXRlbT5JdGVtPC9vbnMtbGlzdC1pdGVtPlxuICogPC9vbnMtbGlzdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGlzdEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBsaXN0LlsvZW5dXG4gICAqICAgW2phXeODquOCueODiOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fY29tcGlsZSgpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdsaXN0Jyk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtbGlzdCcsIExpc3RFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKicsXG4gICcudGV4dC1pbnB1dF9fbGFiZWwnOiAndGV4dC1pbnB1dC0tKl9fbGFiZWwnLFxuICAnLnJhZGlvLWJ1dHRvbic6ICdyYWRpby1idXR0b24tLSonLFxuICAnLnJhZGlvLWJ1dHRvbl9faW5wdXQnOiAncmFkaW8tYnV0dG9uLS0qX19pbnB1dCcsXG4gICcucmFkaW8tYnV0dG9uX19jaGVja21hcmsnOiAncmFkaW8tYnV0dG9uLS0qX19jaGVja21hcmsnLFxuICAnLmNoZWNrYm94JzogJ2NoZWNrYm94LS0qJyxcbiAgJy5jaGVja2JveF9faW5wdXQnOiAnY2hlY2tib3gtLSpfX2lucHV0JyxcbiAgJy5jaGVja2JveF9fY2hlY2ttYXJrJzogJ2NoZWNrYm94LS0qX19jaGVja21hcmsnXG59O1xuXG5jb25zdCBJTlBVVF9BVFRSSUJVVEVTID0gW1xuICAnYXV0b2NhcGl0YWxpemUnLFxuICAnYXV0b2NvbXBsZXRlJyxcbiAgJ2F1dG9jb3JyZWN0JyxcbiAgJ2F1dG9mb2N1cycsXG4gICdkaXNhYmxlZCcsXG4gICdpbnB1dG1vZGUnLFxuICAnbWF4JyxcbiAgJ21heGxlbmd0aCcsXG4gICdtaW4nLFxuICAnbWlubGVuZ3RoJyxcbiAgJ25hbWUnLFxuICAncGF0dGVybicsXG4gICdwbGFjZWhvbGRlcicsXG4gICdyZWFkb25seScsXG4gICdzaXplJyxcbiAgJ3N0ZXAnLFxuICAndHlwZScsXG4gICd2YWxpZGF0b3InLFxuICAndmFsdWUnXG5dO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pbnB1dFxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogIFtlbl1EaXNwbGF5cyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHVuZGVyYmFyXG4gKiAgW2VuXURpc3BsYXlzIGEgaG9yaXpvbnRhbCBsaW5lIHVuZGVybmVhdGggYSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgW2phXVsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICBbZW5dXG4gKiAgICBBbiBpbnB1dCBlbGVtZW50LiBUaGUgYHR5cGVgIGF0dHJpYnV0ZSBjYW4gYmUgdXNlZCB0byBjaGFuZ2UgdGhlIGlucHV0IHR5cGUuIEFsbCB0ZXh0IGlucHV0IHR5cGVzIGFzIHdlbGwgYXMgYGNoZWNrYm94YCBhbmQgYHJhZGlvYCBhcmUgc3VwcG9ydGVkLlxuICpcbiAqICAgIFRoZSBjb21wb25lbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHJlbmRlciBhcyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dCBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQ+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLWlucHV0PmAgZWxlbWVudC5cbiAqICBbL2VuXVxuICogIFtqYV1bL2phXVxuICogQGNvZGVwZW4gb2pReExqXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvaW5wdXRcbiAqIEBzZWVhbHNvIG9ucy1yYW5nZVxuICogICBbZW5dVGhlIGA8b25zLXJhbmdlPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSByYW5nZSBzbGlkZXIuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc3dpdGNoXG4gKiAgIFtlbl1UaGUgYDxvbnMtc3dpdGNoPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBkcmFnZ2FibGUgdG9nZ2xlIHN3aXRjaC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSBhZGRpbmctcGFnZS1jb250ZW50XG4gKiAgIFtlbl1Vc2luZyBmb3JtIGNvbXBvbmVudHNbL2VuXVxuICogICBbamFd44OV44Kp44O844Og44KS5L2/44GGWy9qYV1cbiAqIEBndWlkZSB1c2luZy1tb2RpZmllciBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWlucHV0IHBsYWNlaG9sZGVyPVwiVXNlcm5hbWVcIiBmbG9hdD48L29ucy1pbnB1dD5cbiAqIDxvbnMtaW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2hlY2tlZD48L29ucy1pbnB1dD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW5wdXRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBsYWNlaG9sZGVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QbGFjZWhvbGRlciB0ZXh0LiBJbiBNYXRlcmlhbCBEZXNpZ24sIHRoaXMgcGxhY2Vob2xkZXIgd2lsbCBiZSBhIGZsb2F0aW5nIGxhYmVsLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGZsb2F0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHByZXNlbnQsIHRoZSBwbGFjZWhvbGRlciB3aWxsIGJlIGFuaW1hdGVkIGluIE1hdGVyaWFsIERlc2lnbi5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOioreWumuOBleOCjOOBn+aZguOAgeODqeODmeODq+OBr+OCouODi+ODoeODvOOCt+ODp+ODs+OBmeOCi+OCiOOBhuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHR5cGVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dXG4gICAqICAgIFNwZWNpZnkgdGhlIGlucHV0IHR5cGUuIFRoaXMgaXMgdGhlIHNhbWUgYXMgdGhlIFwidHlwZVwiIGF0dHJpYnV0ZSBmb3Igbm9ybWFsIGlucHV0cy4gSG93ZXZlciwgZm9yIFwicmFuZ2VcIiB5b3Ugc2hvdWxkIGluc3RlYWQgdXNlIDxvbnMtcmFuZ2U+IGVsZW1lbnQuXG4gICAqXG4gICAqICAgIFBsZWFzZSB0YWtlIGEgbG9vayBhdCBbTUROXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQjYXR0ci10eXBlKSBmb3IgYW4gZXhoYXVzdGl2ZSBsaXN0IG9mIHBvc3NpYmxlIHZhbHVlcy4gRGVwZW5kaW5nIG9uIHRoZSBwbGF0Zm9ybSBhbmQgYnJvd3NlciB2ZXJzaW9uIHNvbWUgb2YgdGhlc2UgbWlnaHQgbm90IHdvcmsuXG4gICAqICBbL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGlucHV0LWlkXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIFwiaWRcIiBhdHRyaWJ1dGUgb2YgdGhlIGlubmVyIGA8aW5wdXQ+YCBlbGVtZW50LiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIDxsYWJlbCBmb3I9XCIuLi5cIj4gZWxlbWVudHMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjb250ZW50LWxlZnRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIEhUTUwgY29udGVudCBvZiBgPG9ucy1pbnB1dD5gIGlzIHBsYWNlZCBiZWZvcmUgdGhlIGFjdHVhbCBpbnB1dCBhcyBhIGxhYmVsLiBPbWl0IHRoaXMgdG8gZGlzcGxheSBpdCBhZnRlciB0aGUgaW5wdXQuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnY2hlY2tlZCcsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKCdjaGVja2VkJykpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5fYm91bmRPbklucHV0ID0gdGhpcy5fb25JbnB1dC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX2JvdW5kT25Gb2N1c2luID0gdGhpcy5fb25Gb2N1c2luLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50ID0gdGhpcy5fZGVsZWdhdGVFdmVudC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggIT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoZWxwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgaGVscGVyLmNsYXNzTGlzdC5hZGQoJ19oZWxwZXInKTtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xhYmVsJyk7XG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JykpO1xuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChoZWxwZXIpO1xuXG4gICAgY29uc3QgbGFiZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgbGFiZWwuY2xhc3NMaXN0LmFkZCgnaW5wdXQtbGFiZWwnKTtcblxuICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGROb2RlcykuZm9yRWFjaChlbGVtZW50ID0+IGxhYmVsLmFwcGVuZENoaWxkKGVsZW1lbnQpKTtcbiAgICB0aGlzLmhhc0F0dHJpYnV0ZSgnY29udGVudC1sZWZ0JykgPyBjb250YWluZXIuaW5zZXJ0QmVmb3JlKGxhYmVsLCBjb250YWluZXIuZmlyc3RDaGlsZCkgOiBjb250YWluZXIuYXBwZW5kQ2hpbGQobGFiZWwpO1xuXG4gICAgdGhpcy5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuXG4gICAgc3dpdGNoICh0aGlzLmdldEF0dHJpYnV0ZSgndHlwZScpKSB7XG4gICAgICBjYXNlICdjaGVja2JveCc6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnY2hlY2tib3gnKTtcbiAgICAgICAgdGhpcy5faW5wdXQuY2xhc3NMaXN0LmFkZCgnY2hlY2tib3hfX2lucHV0Jyk7XG4gICAgICAgIHRoaXMuX2hlbHBlci5jbGFzc0xpc3QuYWRkKCdjaGVja2JveF9fY2hlY2ttYXJrJyk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAncmFkaW8nOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3JhZGlvLWJ1dHRvbicpO1xuICAgICAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QuYWRkKCdyYWRpby1idXR0b25fX2lucHV0Jyk7XG4gICAgICAgIHRoaXMuX2hlbHBlci5jbGFzc0xpc3QuYWRkKCdyYWRpby1idXR0b25fX2NoZWNrbWFyaycpO1xuICAgICAgICB0aGlzLl91cGRhdGVCb3VuZEF0dHJpYnV0ZXMoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRoaXMuX2lucHV0LmNsYXNzTGlzdC5hZGQoJ3RleHQtaW5wdXQnKTtcbiAgICAgICAgdGhpcy5faGVscGVyLmNsYXNzTGlzdC5hZGQoJ3RleHQtaW5wdXRfX2xhYmVsJyk7XG4gICAgICAgIHRoaXMuX2lucHV0LnBhcmVudEVsZW1lbnQuY2xhc3NMaXN0LmFkZCgndGV4dC1pbnB1dF9fY29udGFpbmVyJyk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlTGFiZWwoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQm91bmRBdHRyaWJ1dGVzKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUxhYmVsQ2xhc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpbnB1dC1pZCcpKSB7XG4gICAgICB0aGlzLl9pbnB1dC5pZCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdpbnB1dC1pZCcpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3BsYWNlaG9sZGVyJywgJ2lucHV0LWlkJywgJ2NoZWNrZWQnLCAuLi5JTlBVVF9BVFRSSUJVVEVTXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSkpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3BsYWNlaG9sZGVyJykge1xuICAgICAgcmV0dXJuIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVMYWJlbCgpKTtcbiAgICB9IGlmIChuYW1lID09PSAnaW5wdXQtaWQnKSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5faW5wdXQuaWQgPSBjdXJyZW50KTtcbiAgICB9IGlmIChuYW1lID09PSAnY2hlY2tlZCcpIHtcbiAgICAgIHRoaXMuY2hlY2tlZCA9IGN1cnJlbnQgIT09IG51bGw7XG4gICAgfVxuICAgIGVsc2UgaWYgKElOUFVUX0FUVFJJQlVURVMuaW5kZXhPZihuYW1lKSA+PSAwKSB7XG4gICAgICByZXR1cm4gY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX2lucHV0LnR5cGUgIT09ICdjaGVja2JveCcgJiYgdGhpcy5faW5wdXQudHlwZSAhPT0gJ3JhZGlvJykge1xuICAgICAgICB0aGlzLl9pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIHRoaXMuX2JvdW5kT25JbnB1dCk7XG4gICAgICAgIHRoaXMuX2lucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCB0aGlzLl9ib3VuZE9uRm9jdXNpbik7XG4gICAgICAgIHRoaXMuX2lucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3Vzb3V0JywgdGhpcy5fYm91bmRPbkZvY3Vzb3V0KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9ib3VuZERlbGVnYXRlRXZlbnQpO1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHRoaXMuX2JvdW5kRGVsZWdhdGVFdmVudCk7XG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5faW5wdXQucmVtb3ZlRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9ib3VuZE9uSW5wdXQpO1xuICAgICAgdGhpcy5faW5wdXQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXNpbicsIHRoaXMuX2JvdW5kT25Gb2N1c2luKTtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50KTtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLl9ib3VuZERlbGVnYXRlRXZlbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgX3NldExhYmVsKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgPSB2YWx1ZTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLl9oZWxwZXIuaW5uZXJUZXh0ID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZUxhYmVsKCkge1xuICAgIHRoaXMuX3NldExhYmVsKHRoaXMuaGFzQXR0cmlidXRlKCdwbGFjZWhvbGRlcicpID8gdGhpcy5nZXRBdHRyaWJ1dGUoJ3BsYWNlaG9sZGVyJykgOiAnJyk7XG4gIH1cblxuICBfdXBkYXRlQm91bmRBdHRyaWJ1dGVzKCkge1xuICAgIElOUFVUX0FUVFJJQlVURVMuZm9yRWFjaCgoYXR0cikgPT4ge1xuICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKGF0dHIpKSB7XG4gICAgICAgIHRoaXMuX2lucHV0LnNldEF0dHJpYnV0ZShhdHRyLCB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5faW5wdXQucmVtb3ZlQXR0cmlidXRlKGF0dHIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3VwZGF0ZUxhYmVsQ2xhc3MoKSB7XG4gICAgaWYgKHRoaXMudmFsdWUgPT09ICcnKSB7XG4gICAgICB0aGlzLl9oZWxwZXIuY2xhc3NMaXN0LnJlbW92ZSgndGV4dC1pbnB1dC0tbWF0ZXJpYWxfX2xhYmVsLS1hY3RpdmUnKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoWydjaGVja2JveCcsICdyYWRpbyddLmluZGV4T2YodGhpcy5nZXRBdHRyaWJ1dGUoJ3R5cGUnKSkgPT09IC0xKXtcbiAgICAgIHRoaXMuX2hlbHBlci5jbGFzc0xpc3QuYWRkKCd0ZXh0LWlucHV0LS1tYXRlcmlhbF9fbGFiZWwtLWFjdGl2ZScpO1xuICAgIH1cbiAgfVxuXG4gIF9kZWxlZ2F0ZUV2ZW50KGV2ZW50KSB7XG4gICAgY29uc3QgZSA9IG5ldyBDdXN0b21FdmVudChldmVudC50eXBlLCB7XG4gICAgICBidWJibGVzOiBmYWxzZSxcbiAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoRXZlbnQoZSk7XG4gIH1cblxuICBfb25JbnB1dChldmVudCkge1xuICAgIHRoaXMuX3VwZGF0ZUxhYmVsQ2xhc3MoKTtcbiAgfVxuXG4gIF9vbkZvY3VzaW4oZXZlbnQpIHtcbiAgICB0aGlzLl91cGRhdGVMYWJlbENsYXNzKCk7XG4gIH1cblxuICBnZXQgX2lucHV0KCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ2lucHV0Jyk7XG4gIH1cblxuICBnZXQgX2hlbHBlcigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcuX2hlbHBlcicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGlucHV0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lucHV0ID09PSBudWxsXG4gICAgICA/IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpXG4gICAgICA6IHRoaXMuX2lucHV0LnZhbHVlO1xuICB9XG5cbiAgc2V0IHZhbHVlKHZhbCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC52YWx1ZSA9IHZhbDtcbiAgICAgIHRoaXMuX29uSW5wdXQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGlucHV0IGlzIGNoZWNrZWQgb3Igbm90LiBPbmx5IHdvcmtzIGZvciBgcmFkaW9gIGFuZCBgY2hlY2tib3hgIHR5cGUgaW5wdXRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgY2hlY2tlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5faW5wdXQuY2hlY2tlZDtcbiAgfVxuXG4gIHNldCBjaGVja2VkKHZhbCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC5jaGVja2VkID0gdmFsO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGlucHV0IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBnZXQgX2lzVGV4dElucHV0KCkge1xuICAgIHJldHVybiB0aGlzLnR5cGUgIT09ICdyYWRpbycgJiYgdGhpcy50eXBlICE9PSAnY2hlY2tib3gnO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtaW5wdXQnLCBJbnB1dEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9kYWxBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5kZWxheSA9IDA7XG4gICAgdGhpcy5kdXJhdGlvbiA9IDAuMjtcblxuICAgIHRoaXMudGltaW5nID0gb3B0aW9ucy50aW1pbmcgfHwgdGhpcy50aW1pbmc7XG4gICAgdGhpcy5kdXJhdGlvbiA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiB0aGlzLmR1cmF0aW9uO1xuICAgIHRoaXMuZGVsYXkgPSBvcHRpb25zLmRlbGF5ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmRlbGF5IDogdGhpcy5kZWxheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IG1vZGFsXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKG1vZGFsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cbn1cbiIsIlxuLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE1vZGFsQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhZGVNb2RhbEFuaW1hdG9yIGV4dGVuZHMgTW9kYWxBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIG9wdGlvbnMudGltaW5nID0gb3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcic7XG4gICAgb3B0aW9ucy5kdXJhdGlvbiA9IG9wdGlvbnMuZHVyYXRpb24gfHwgJzAuMyc7XG4gICAgb3B0aW9ucy5kZWxheSA9IG9wdGlvbnMuZGVsYXkgfHwgMDtcblxuICAgIHN1cGVyKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IG1vZGFsXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KG1vZGFsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQobW9kYWwpXG4gICAgICAucXVldWUoe1xuICAgICAgICBvcGFjaXR5OiAwXG4gICAgICB9KVxuICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgIC5xdWV1ZSh7XG4gICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgfSwge1xuICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgfSlcbiAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IG1vZGFsXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKG1vZGFsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQobW9kYWwpXG4gICAgICAucXVldWUoe1xuICAgICAgICBvcGFjaXR5OiAxXG4gICAgICB9KVxuICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgIC5xdWV1ZSh7XG4gICAgICAgIG9wYWNpdHk6IDBcbiAgICAgIH0sIHtcbiAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgIH0pXG4gICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBNb2RhbEFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IEZhZGVNb2RhbEFuaW1hdG9yIGZyb20gJy4vZmFkZS1hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi8uLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlciBmcm9tICcuLi8uLi9vbnMvZGV2aWNlLWJhY2stYnV0dG9uLWRpc3BhdGNoZXInO1xuaW1wb3J0IERvb3JMb2NrIGZyb20gJy4uLy4uL29ucy9kb29ybG9jayc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ21vZGFsLS0qJyxcbiAgJ21vZGFsX19jb250ZW50JzogJ21vZGFsLS0qX19jb250ZW50J1xufTtcblxuY29uc3QgX2FuaW1hdG9yRGljdCA9IHtcbiAgJ2RlZmF1bHQnOiBNb2RhbEFuaW1hdG9yLFxuICAnZmFkZSc6IEZhZGVNb2RhbEFuaW1hdG9yLFxuICAnbm9uZSc6IE1vZGFsQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW1vZGFsXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIE1vZGFsIGNvbXBvbmVudCB0aGF0IG1hc2tzIGN1cnJlbnQgc2NyZWVuLiBVbmRlcmx5aW5nIGNvbXBvbmVudHMgYXJlIG5vdCBzdWJqZWN0IHRvIGFueSBldmVudHMgd2hpbGUgdGhlIG1vZGFsIGNvbXBvbmVudCBpcyBzaG93bi5cbiAqXG4gKiAgICAgVGhpcyBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gYmxvY2sgdXNlciBpbnB1dCB3aGlsZSBzb21lIG9wZXJhdGlvbiBpcyBydW5uaW5nIG9yIHRvIHNob3cgc29tZSBpbmZvcm1hdGlvbiB0byB0aGUgdXNlci5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIOeUu+mdouWFqOS9k+OCkuODnuOCueOCr+OBmeOCi+ODouODvOODgOODq+eUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguS4i+WBtOOBq+OBguOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBr+OAgVxuICogICAgIOODouODvOODgOODq+OBjOihqOekuuOBleOCjOOBpuOBhOOCi+mWk+OBr+OCpOODmeODs+ODiOmAmuefpeOBjOihjOOCj+OCjOOBvuOBm+OCk+OAglxuICogICBbL2phXVxuICogQGd1aWRlIGRpYWxvZ3NcbiAqICAgW2VuXURpYWxvZyBjb21wb25lbnRzWy9lbl1cbiAqICAgW2phXURpYWxvZyBjb21wb25lbnRzWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1kaWFsb2dcbiAqICAgW2VuXVRoZSBgPG9ucy1kaWFsb2c+YCBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGEgbW9kYWwgZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gZGV2SWdcbiAqIEBleGFtcGxlXG4gKiA8b25zLW1vZGFsIGlkPVwibW9kYWxcIj5cbiAqICAgTW9kYWwgY29udGVudFxuICogPC9vbnMtbW9kYWw+XG4gKiA8c2NyaXB0PlxuICogICB2YXIgbW9kYWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbW9kYWwnKTtcbiAqICAgbW9kYWwuc2hvdygpO1xuICogPC9zY3JpcHQ+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1vZGFsRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYW5pbWF0aW9uIHVzZWQgd2hlbiBzaG93aW5nIGFuZCBoaWRpbmcgdGhlIG1vZGFsLiBDYW4gYmUgZWl0aGVyIGBcIm5vbmVcImAgb3IgYFwiZmFkZVwiYC5bL2VuXVxuICAgKiAgW2phXeODouODvOODgOODq+OCkuihqOekuuOBmeOCi+mam+OBruOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwi44KC44GX44GP44GvXCJmYWRlXCLjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb24tb3B0aW9uc1xuICAgKiBAdHlwZSB7RXhwcmVzc2lvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIHRpbWluZyBhbmQgZGVsYXkgd2l0aCBhbiBvYmplY3QgbGl0ZXJhbC4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgIJlLmcuIDxjb2RlPntkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9PC9jb2RlPlsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG5cbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTW9kYWxBbmltYXRvcixcbiAgICAgIGJhc2VDbGFzc05hbWU6ICdNb2RhbEFuaW1hdG9yJyxcbiAgICAgIGRlZmF1bHRBbmltYXRpb246IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihoYW5kbGVyKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5jcmVhdGVIYW5kbGVyKHRoaXMsIGhhbmRsZXIpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHRoaXMuc3R5bGUuekluZGV4ID0gMTAwMDE7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdtb2RhbCcpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLm1vZGFsX19jb250ZW50JykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnbW9kYWxfX2NvbnRlbnQnKTtcblxuICAgICAgd2hpbGUgKHRoaXMuY2hpbGROb2Rlc1swXSkge1xuICAgICAgICBjb25zdCBub2RlID0gdGhpcy5jaGlsZE5vZGVzWzBdO1xuICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICBjb250ZW50Lmluc2VydEJlZm9yZShub2RlLCBudWxsKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChjb250ZW50KTtcbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAodGhpcy5fYmFja0J1dHRvbkhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLm9uRGV2aWNlQmFja0J1dHRvbiA9ICgpID0+IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZSc7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdyhbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcImZhZGVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCIsIFwiZmFkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IG1vZGFsLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KG9wdGlvbnMgPSB7fSkge1xuICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKFxuICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9LFxuICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSlcbiAgICApO1xuXG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8IGZ1bmN0aW9uKCkge307XG5cbiAgICBjb25zdCB0cnlTaG93ID0gKCkgPT4ge1xuICAgICAgY29uc3QgdW5sb2NrID0gdGhpcy5fZG9vckxvY2subG9jaygpO1xuICAgICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAndGFibGUnO1xuICAgICAgICAgIGFuaW1hdG9yLnNob3codGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgdW5sb2NrKCk7XG5cbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLl9kb29yTG9jay53YWl0VW5sb2NrKCgpID0+IHJlc29sdmUodHJ5U2hvdygpKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJmYWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIG1vZGFsIHZpc2liaWxpdHkuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44Gu6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZSgpIHtcbiAgICBpZiAodGhpcy52aXNpYmxlKSB7XG4gICAgICByZXR1cm4gdGhpcy5oaWRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnNob3cuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcImZhZGVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCIsIFwiZmFkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIG1vZGFsLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OCkumdnuihqOekuuOBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBoaWRlKG9wdGlvbnMgPSB7fSkge1xuICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKFxuICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9LFxuICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSlcbiAgICApO1xuXG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8IGZ1bmN0aW9uKCkge307XG5cbiAgICBjb25zdCB0cnlIaWRlID0gKCkgPT4ge1xuICAgICAgY29uc3QgdW5sb2NrID0gdGhpcy5fZG9vckxvY2subG9jaygpO1xuICAgICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgICBhbmltYXRvci5oaWRlKHRoaXMsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIHVubG9jaygpO1xuXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fZG9vckxvY2sud2FpdFVubG9jaygoKSA9PiByZXNvbHZlKHRyeUhpZGUoKSkpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gQW5pbWF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckFuaW1hdG9yKG5hbWUsIEFuaW1hdG9yKSB7XG4gICAgaWYgKCEoQW5pbWF0b3IucHJvdG90eXBlIGluc3RhbmNlb2YgTW9kYWxBbmltYXRvcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJBbmltYXRvclwiIHBhcmFtIG11c3QgaW5oZXJpdCBPbnNNb2RhbEVsZW1lbnQuTW9kYWxBbmltYXRvcicpO1xuICAgIH1cbiAgICBfYW5pbWF0b3JEaWN0W25hbWVdID0gQW5pbWF0b3I7XG4gIH1cblxuICBzdGF0aWMgZ2V0IE1vZGFsQW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIE1vZGFsQW5pbWF0b3I7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtbW9kYWwnLCBNb2RhbEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3Ige1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50aW1pbmdcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZHVyYXRpb25cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZGVsYXlcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe1xuICAgICAgdGltaW5nOiAnbGluZWFyJyxcbiAgICAgIGR1cmF0aW9uOiAnMC40JyxcbiAgICAgIGRlbGF5OiAnMCdcbiAgICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICAgIHRoaXMudGltaW5nID0gb3B0aW9ucy50aW1pbmc7XG4gICAgdGhpcy5kdXJhdGlvbiA9IG9wdGlvbnMuZHVyYXRpb247XG4gICAgdGhpcy5kZWxheSA9IG9wdGlvbnMuZGVsYXk7XG4gIH1cblxuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHN0YXRpYyBleHRlbmQocHJvcGVydGllcyA9IHt9KSB7XG5cbiAgICBjb25zdCBleHRlbmRlZEFuaW1hdG9yID0gdGhpcztcbiAgICBjb25zdCBuZXdBbmltYXRvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgZXh0ZW5kZWRBbmltYXRvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgdXRpbC5leHRlbmQodGhpcywgcHJvcGVydGllcyk7XG4gICAgfTtcblxuICAgIG5ld0FuaW1hdG9yLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuXG4gICAgcmV0dXJuIG5ld0FuaW1hdG9yO1xuICB9XG59XG5cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuLyoqXG4gKiBTbGlkZSBhbmltYXRvciBmb3IgbmF2aWdhdG9yIHRyYW5zaXRpb24gbGlrZSBpT1MncyBzY3JlZW4gc2xpZGUgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSU9TU2xpZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe1xuICAgICAgZHVyYXRpb246IDAuNCxcbiAgICAgIHRpbWluZzogJ2Vhc2UnLFxuICAgICAgZGVsYXk6IDBcbiAgICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzayA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gICAgICA8ZGl2IHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlO1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBibGFjazsgb3BhY2l0eTogMDsgei1pbmRleDogMlwiPjwvZGl2PlxuICAgIGApO1xuICB9XG5cbiAgX2RlY29tcG9zZShwYWdlKSB7XG4gICAgY29uc3QgdG9vbGJhciA9IHBhZ2UuX2dldFRvb2xiYXJFbGVtZW50KCk7XG4gICAgY29uc3QgbGVmdCA9IHRvb2xiYXIuX2dldFRvb2xiYXJMZWZ0SXRlbXNFbGVtZW50KCk7XG4gICAgY29uc3QgcmlnaHQgPSB0b29sYmFyLl9nZXRUb29sYmFyUmlnaHRJdGVtc0VsZW1lbnQoKTtcblxuICAgIGNvbnN0IGV4Y2x1ZGVCYWNrQnV0dG9uID0gZnVuY3Rpb24oZWxlbWVudHMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChlbGVtZW50c1tpXS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLWJhY2stYnV0dG9uJykge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGVsZW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBjb25zdCBvdGhlciA9IFtdXG4gICAgICAuY29uY2F0KGxlZnQuY2hpbGRyZW4ubGVuZ3RoID09PSAwID8gbGVmdCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKGxlZnQuY2hpbGRyZW4pKVxuICAgICAgLmNvbmNhdChyaWdodC5jaGlsZHJlbi5sZW5ndGggPT09IDAgPyByaWdodCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKHJpZ2h0LmNoaWxkcmVuKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9vbGJhckNlbnRlcjogdG9vbGJhci5fZ2V0VG9vbGJhckNlbnRlckl0ZW1zRWxlbWVudCgpLFxuICAgICAgYmFja0J1dHRvbkljb246IHRvb2xiYXIuX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQoKSxcbiAgICAgIGJhY2tCdXR0b25MYWJlbDogdG9vbGJhci5fZ2V0VG9vbGJhckJhY2tCdXR0b25MYWJlbEVsZW1lbnQoKSxcbiAgICAgIG90aGVyOiBvdGhlcixcbiAgICAgIGNvbnRlbnQ6IHBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksXG4gICAgICBiYWNrZ3JvdW5kOiBwYWdlLl9nZXRCYWNrZ3JvdW5kRWxlbWVudCgpLFxuICAgICAgdG9vbGJhcjogdG9vbGJhcixcbiAgICAgIGJvdHRvbVRvb2xiYXI6IHBhZ2UuX2dldEJvdHRvbVRvb2xiYXJFbGVtZW50KClcbiAgICB9O1xuICB9XG5cbiAgX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZSwgbGVhdmVQYWdlKSB7XG4gICAgY29uc3QgYm90aFBhZ2VIYXNUb29sYmFyID1cbiAgICAgIGVudGVyUGFnZS5fY2FuQW5pbWF0ZVRvb2xiYXIoKSAmJiBsZWF2ZVBhZ2UuX2NhbkFuaW1hdGVUb29sYmFyKCk7XG5cbiAgICB2YXIgbm9NYXRlcmlhbFRvb2xiYXIgPVxuICAgICAgIWVudGVyUGFnZS5fZ2V0VG9vbGJhckVsZW1lbnQoKS5jbGFzc0xpc3QuY29udGFpbnMoJ25hdmlnYXRpb24tYmFyLS1tYXRlcmlhbCcpICYmXG4gICAgICAhbGVhdmVQYWdlLl9nZXRUb29sYmFyRWxlbWVudCgpLmNsYXNzTGlzdC5jb250YWlucygnbmF2aWdhdGlvbi1iYXItLW1hdGVyaWFsJyk7XG5cbiAgICByZXR1cm4gYm90aFBhZ2VIYXNUb29sYmFyICYmIG5vTWF0ZXJpYWxUb29sYmFyO1xuICB9XG5cbiAgX2NhbGN1bGF0ZURlbHRhKGVsZW1lbnQsIGRlY29tcG9zaXRpb24pIHtcbiAgICBsZXQgdGl0bGUsIGxhYmVsO1xuXG4gICAgY29uc3QgcGFnZVJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2JhY2stYnV0dG9uX19sYWJlbCcpKSB7XG4gICAgICBjb25zdCBsYWJlbFJlY3QgPSBkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHRpdGxlID0gTWF0aC5yb3VuZCgocGFnZVJlY3Qud2lkdGggLyAyKSAtIChsYWJlbFJlY3Qud2lkdGggLyAyKSAtIGxhYmVsUmVjdC5sZWZ0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGl0bGUgPSBNYXRoLnJvdW5kKChwYWdlUmVjdC53aWR0aCAvIDIpICogMC42KTtcbiAgICB9XG5cbiAgICBpZiAoZGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uSWNvbi5jbGFzc0xpc3QuY29udGFpbnMoJ2JhY2stYnV0dG9uX19pY29uJykpIHtcbiAgICAgIGxhYmVsID0gZGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uSWNvbi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5yaWdodCAtIDI7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt0aXRsZSwgbGFiZWx9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGVudGVyUGFnZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbGVhdmVQYWdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgbGVhdmVQYWdlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGxlYXZlUGFnZS5uZXh0U2libGluZyk7XG5cbiAgICBjb250ZW50UmVhZHkoZW50ZXJQYWdlLCAoKSA9PiB7XG4gICAgICBjb25zdCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uID0gdGhpcy5fZGVjb21wb3NlKGVudGVyUGFnZSk7XG4gICAgICBjb25zdCBsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uID0gdGhpcy5fZGVjb21wb3NlKGxlYXZlUGFnZSk7XG5cbiAgICAgIGNvbnN0IGRlbHRhID0gdGhpcy5fY2FsY3VsYXRlRGVsdGEobGVhdmVQYWdlLCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uKTtcblxuICAgICAgY29uc3QgbWFza0NsZWFyID0gYW5pbWl0KHRoaXMuYmFja2dyb3VuZE1hc2spXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMC4wNVxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKChkb25lKSA9PiB7XG4gICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzaG91bGRBbmltYXRlVG9vbGJhciA9IHRoaXMuX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZSwgbGVhdmVQYWdlKTtcblxuICAgICAgaWYgKHNob3VsZEFuaW1hdGVUb29sYmFyKSB7XG4gICAgICAgIC8vIFRPRE86IFJlbW92ZSB0aGlzIGZpeFxuICAgICAgICBjb25zdCBlbnRlclBhZ2VUb29sYmFySGVpZ2h0ID0gZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCArICdweCc7XG4gICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2suc3R5bGUudG9wID0gZW50ZXJQYWdlVG9vbGJhckhlaWdodDtcblxuICAgICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgICAgbWFza0NsZWFyLFxuXG4gICAgICAgICAgYW5pbWl0KFtlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSlcbiAgICAgICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMTAwJSwgMHB4LCAwcHgpJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMHB4LCAwcHgsIDBweCknLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5yZXN0b3JlU3R5bGUoKSxcblxuICAgICAgICAgIGFuaW1pdChlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLnRvb2xiYXIpXG4gICAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnJlc3RvcmVTdHlsZSgpLFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja2dyb3VuZClcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIHRvcDogZW50ZXJQYWdlVG9vbGJhckhlaWdodFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyKVxuICAgICAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgxMjUlLCAwLCAwKScsXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnJlc3RvcmVTdHlsZSgpLFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja0J1dHRvbkxhYmVsKVxuICAgICAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgnICsgZGVsdGEudGl0bGUgKyAncHgsIDAsIDApJyxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVzdG9yZVN0eWxlKCksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5vdGhlcilcbiAgICAgICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7b3BhY2l0eTogMH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge29wYWNpdHk6IDF9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5yZXN0b3JlU3R5bGUoKSxcblxuICAgICAgICAgIGFuaW1pdChbbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5jb250ZW50LCBsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmJvdHRvbVRvb2xiYXIsIGxlYXZlUGFnZURlY29tcG9zaXRpb24uYmFja2dyb3VuZF0pXG4gICAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoLTI1JSwgMHB4LCAwcHgpJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgICAgIH0pLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24udG9vbGJhckNlbnRlcilcbiAgICAgICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtJyArIGRlbHRhLnRpdGxlICsgJ3B4LCAwLCAwKScsXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVzdG9yZVN0eWxlKCksXG5cbiAgICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLScgKyBkZWx0YS5sYWJlbCArICdweCwgMCwgMCknLFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnJlc3RvcmVTdHlsZSgpLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24ub3RoZXIpXG4gICAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge29wYWNpdHk6IDF9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtvcGFjaXR5OiAwfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVzdG9yZVN0eWxlKClcblxuICAgICAgICApO1xuXG4gICAgICB9IGVsc2Uge1xuXG4gICAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgICBtYXNrQ2xlYXIsXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgxMDAlLCAwcHgsIDBweCknLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwcHgsIDBweCwgMHB4KScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnJlc3RvcmVTdHlsZSgpLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKC0yNSUsIDBweCwgMHB4KSdcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG5cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBkb25lKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBlbnRlclBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgZW50ZXJQYWdlLm5leHRTaWJsaW5nKTtcblxuICAgIGNvbnN0IGVudGVyUGFnZURlY29tcG9zaXRpb24gPSB0aGlzLl9kZWNvbXBvc2UoZW50ZXJQYWdlKTtcbiAgICBjb25zdCBsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uID0gdGhpcy5fZGVjb21wb3NlKGxlYXZlUGFnZSk7XG5cbiAgICBjb25zdCBkZWx0YSA9IHRoaXMuX2NhbGN1bGF0ZURlbHRhKGxlYXZlUGFnZSwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbik7XG5cbiAgICBjb25zdCBtYXNrQ2xlYXIgPSBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaylcbiAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgLnF1ZXVlKHtcbiAgICAgICAgb3BhY2l0eTogMC4xLFxuICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKSdcbiAgICAgIH0pXG4gICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgLnF1ZXVlKHtcbiAgICAgICAgb3BhY2l0eTogMFxuICAgICAgfSwge1xuICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgfSlcbiAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgLnF1ZXVlKChkb25lKSA9PiB7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pO1xuXG4gICAgY29uc3Qgc2hvdWxkQW5pbWF0ZVRvb2xiYXIgPSB0aGlzLl9zaG91bGRBbmltYXRlVG9vbGJhcihlbnRlclBhZ2UsIGxlYXZlUGFnZSk7XG5cbiAgICBpZiAoc2hvdWxkQW5pbWF0ZVRvb2xiYXIpIHtcbiAgICAgIGNvbnN0IGVudGVyUGFnZVRvb2xiYXJIZWlnaHQgPSBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLnRvb2xiYXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0ICsgJ3B4JztcbiAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2suc3R5bGUudG9wID0gZW50ZXJQYWdlVG9vbGJhckhlaWdodDtcblxuICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICBtYXNrQ2xlYXIsXG5cbiAgICAgICAgYW5pbWl0KFtlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSlcbiAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKC0yNSUsIDBweCwgMHB4KScsXG4gICAgICAgICAgICAgIG9wYWNpdHk6IDAuOVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSlcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMHB4LCAwcHgsIDBweCknLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5yZXN0b3JlU3R5bGUoKSxcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLScgKyBkZWx0YS50aXRsZSArICdweCwgMCwgMCknLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICB9KVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsXG4gICAgICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlc3RvcmVTdHlsZSgpLFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC0nICsgZGVsdGEubGFiZWwgKyAncHgsIDAsIDApJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSlcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVzdG9yZVN0eWxlKCksXG5cbiAgICAgICAgYW5pbWl0KGVudGVyUGFnZURlY29tcG9zaXRpb24ub3RoZXIpXG4gICAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge29wYWNpdHk6IDB9LFxuICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICB9KVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge29wYWNpdHk6IDF9LFxuICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVzdG9yZVN0eWxlKCksXG5cbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24uYmFja2dyb3VuZClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRvcDogZW50ZXJQYWdlVG9vbGJhckhlaWdodFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KFtsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGxlYXZlUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDBweCwgMHB4LCAwcHgpJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSlcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMTAwJSwgMHB4LCAwcHgpJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLndhaXQoMClcbiAgICAgICAgICAucXVldWUoZnVuY3Rpb24oZmluaXNoKSB7XG4gICAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgZmluaXNoKCk7XG4gICAgICAgICAgfS5iaW5kKHRoaXMpKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICB9KVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgxMjUlLCAwLCAwKSdcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsXG4gICAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKCcgKyBkZWx0YS50aXRsZSArICdweCwgMCwgMCknLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgbWFza0NsZWFyLFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgtMjUlLCAwcHgsIDBweCknLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAwLjlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDBweCwgMHB4LCAwcHgpJyxcbiAgICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVzdG9yZVN0eWxlKCksXG5cbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDBweCwgMHB4LCAwcHgpJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgICAgfSlcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMTAwJSwgMHB4LCAwcHgpJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGZpbmlzaCkge1xuICAgICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgICAgIGZpbmlzaCgpO1xuICAgICAgICAgIH0uYmluZCh0aGlzKSlcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuXG4vKipcbiAqIExpZnQgc2NyZWVuIHRyYW5zaXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElPU0xpZnROYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe1xuICAgICAgZHVyYXRpb246IDAuNCxcbiAgICAgIHRpbWluZzogJ2N1YmljLWJlemllciguMSwgLjcsIC4xLCAxKScsXG4gICAgICBkZWxheTogMFxuICAgIH0sIG9wdGlvbnMgfHwge30pO1xuXG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICB0aGlzLmJhY2tncm91bmRNYXNrID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgICAgIDxkaXYgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IHdpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCU7XG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudChibGFjaywgd2hpdGUpO1wiPjwvZGl2PlxuICAgIGApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UpO1xuXG4gICAgY29uc3QgbWFza0NsZWFyID0gYW5pbWl0KHRoaXMuYmFja2dyb3VuZE1hc2spXG4gICAgICAud2FpdCh0aGlzLmRlbGF5ICsgdGhpcy5kdXJhdGlvbilcbiAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBtYXNrQ2xlYXIsXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMTAwJSwgMCknLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgLTEwJSwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMC45XG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgZW50ZXJQYWdlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSArIHRoaXMuZHVyYXRpb24pXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAtMTAlLCAwKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAwLjlcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAxLjBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChsZWF2ZVBhZ2UpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAxMDAlLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcblxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5cbi8qKlxuICogRmFkZS1pbiBzY3JlZW4gdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSU9TRmFkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBleHRlbmRzIE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgZHVyYXRpb246ICcwLjQnLFxuICAgICAgZGVsYXk6ICcwJ1xuICAgIH0sIG9wdGlvbnMgfHwge30pO1xuXG4gICAgc3VwZXIob3B0aW9ucyk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoW2VudGVyUGFnZS5fZ2V0Q29udGVudEVsZW1lbnQoKSwgZW50ZXJQYWdlLl9nZXRCYWNrZ3JvdW5kRWxlbWVudCgpXSlcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UuX2dldFRvb2xiYXJFbGVtZW50KCkpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KFtsZWF2ZVBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksIGxlYXZlUGFnZS5fZ2V0QmFja2dyb3VuZEVsZW1lbnQoKV0pXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZS5fZ2V0VG9vbGJhckVsZW1lbnQoKSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG5cbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuXG4vKipcbiAqIFNsaWRlIGFuaW1hdG9yIGZvciBuYXZpZ2F0b3IgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURTbGlkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBleHRlbmRzIE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICBkdXJhdGlvbjogMC4zLFxuICAgICAgdGltaW5nOiAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJyxcbiAgICAgIGRlbGF5OiAwXG4gICAgfSwgb3B0aW9ucyB8fCB7fSk7XG5cbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICAgICAgPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsgei1pbmRleDogMjtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogYmxhY2s7IG9wYWNpdHk6IDA7XCI+PC9kaXY+XG4gICAgYCk7XG4gICAgdGhpcy5ibGFja01hc2tPcGFjaXR5ID0gMC40O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UubmV4dFNpYmxpbmcpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KHRoaXMuYmFja2dyb3VuZE1hc2spXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogdGhpcy5ibGFja01hc2tPcGFjaXR5XG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDEwMCUsIDAsIDApJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgtNDUlLCAwcHgsIDBweCknXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgICAud2FpdCgwLjIpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBkb25lKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBlbnRlclBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgZW50ZXJQYWdlLm5leHRTaWJsaW5nKTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdCh0aGlzLmJhY2tncm91bmRNYXNrKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiB0aGlzLmJsYWNrTWFza09wYWNpdHksXG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSlcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgtNDUlLCAwcHgsIDBweCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMC45XG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMHB4LCAwcHgsIDBweCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDBweCwgMHB4LCAwcHgpJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDEwMCUsIDBweCwgMHB4KSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQoMC4yKVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZmluaXNoKSB7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIGZpbmlzaCgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5cbi8qKlxuICogTGlmdCBzY3JlZW4gdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURMaWZ0TmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgIGR1cmF0aW9uOiAwLjQsXG4gICAgICB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLFxuICAgICAgZGVsYXk6IDAuMDVcbiAgICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzayA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gICAgICA8ZGl2IHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlO1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBibGFjaztcIj48L2Rpdj5cbiAgICBgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBsZWF2ZVBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgbGVhdmVQYWdlKTtcblxuICAgIGNvbnN0IG1hc2tDbGVhciA9IGFuaW1pdCh0aGlzLmJhY2tncm91bmRNYXNrKVxuICAgICAgLndhaXQodGhpcy5kZWxheSArIHRoaXMuZHVyYXRpb24pXG4gICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgbWFza0NsZWFyLFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDEwMCUsIDApJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXN0b3JlU3R5bGUoKVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuNFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHBvcChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGVudGVyUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBlbnRlclBhZ2UpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KHRoaXMuYmFja2dyb3VuZE1hc2spXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkgKyB0aGlzLmR1cmF0aW9uKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMC40XG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogMFxuICAgICAgICB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMTAwJSwgMCknXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcblxuLyoqXG4gKiBGYWRlLWluICsgTGlmdCBzY3JlZW4gdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURGYWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgIHRpbWluZzogJ2Vhc2Utb3V0JyxcbiAgICAgIGR1cmF0aW9uOiAnMC4yNScsXG4gICAgICBkZWxheTogJzAnXG4gICAgfSwgb3B0aW9ucyB8fCB7fSk7XG5cbiAgICBzdXBlcihvcHRpb25zKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgIC5zYXZlU3R5bGUoKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGNzczoge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgNDJweCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3RvcmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZShmdW5jdGlvbihkb25lKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQoMC4xNSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDM4cHgsIDApJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucXVldWUoZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBjc3M6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9LFxuICAgICAgICAgIGR1cmF0aW9uOiAwXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KDAuMDQpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgY3NzOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMudGltaW5nXG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTm9uZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBleHRlbmRzIE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihvcHRpb25zKTtcbiAgfVxuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgSU9TU2xpZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9pb3Mtc2xpZGUtYW5pbWF0b3InO1xuaW1wb3J0IElPU0xpZnROYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9pb3MtbGlmdC1hbmltYXRvcic7XG5pbXBvcnQgSU9TRmFkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBmcm9tICcuL2lvcy1mYWRlLWFuaW1hdG9yJztcbmltcG9ydCBNRFNsaWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIGZyb20gJy4vbWQtc2xpZGUtYW5pbWF0b3InO1xuaW1wb3J0IE1ETGlmdE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBmcm9tICcuL21kLWxpZnQtYW5pbWF0b3InO1xuaW1wb3J0IE1ERmFkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciBmcm9tICcuL21kLWZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IE5vbmVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IgZnJvbSAnLi9ub25lLWFuaW1hdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCB7UGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXIsIGluc3RhbnRQYWdlTG9hZGVyfSBmcm9tICcuLi8uLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gTURGYWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIDogSU9TU2xpZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IsXG4gICdzbGlkZSc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gTURTbGlkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciA6IElPU1NsaWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yLFxuICAnbGlmdCc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gTURMaWZ0TmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yIDogSU9TTGlmdE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1ERmFkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvciA6IElPU0ZhZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IsXG4gICdzbGlkZS1pb3MnOiBJT1NTbGlkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvcixcbiAgJ3NsaWRlLW1kJzogTURTbGlkZU5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvcixcbiAgJ2xpZnQtaW9zJzogSU9TTGlmdE5hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvcixcbiAgJ2xpZnQtbWQnOiBNRExpZnROYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IsXG4gICdmYWRlLWlvcyc6IElPU0ZhZGVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IsXG4gICdmYWRlLW1kJzogTURGYWRlTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yLFxuICAnbm9uZSc6IE5vbmVOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3Jcbn07XG5cbmNvbnN0IHJld3JpdGFibGVzID0ge1xuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBuYXZpZ2F0b3JTaWRlRWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkobmF2aWdhdG9yRWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IG5hdmlnYXRvckVsZW1lbnRcbiAgICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGxpbmsobmF2aWdhdG9yRWxlbWVudCwgdGFyZ2V0LCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKHRhcmdldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW5hdmlnYXRvclxuICogQGNhdGVnb3J5IG5hdmlnYXRpb25cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQSBjb21wb25lbnQgdGhhdCBwcm92aWRlcyBwYWdlIHN0YWNrIG1hbmFnZW1lbnQgYW5kIG5hdmlnYXRpb24uIFN0YWNrIG5hdmlnYXRpb24gaXMgdGhlIG1vc3QgY29tbW9uIG5hdmlnYXRpb24gcGF0dGVybiBmb3IgbW9iaWxlIGFwcHMuXG4gKlxuICogICAgIFdoZW4gYSBwYWdlIGlzIHB1c2hlZCBvbiB0b3Agb2YgdGhlIHN0YWNrIGl0IGlzIGRpc3BsYXllZCB3aXRoIGEgdHJhbnNpdGlvbiBhbmltYXRpb24uIFdoZW4gdGhlIHVzZXIgcmV0dXJucyB0byB0aGUgcHJldmlvdXMgcGFnZSB0aGUgdG9wIHBhZ2Ugd2lsbCBiZSBwb3BwZWQgZnJvbSB0aGUgdG9wIG9mIHRoZSBzdGFjayBhbmQgaGlkZGVuIHdpdGggYW4gb3Bwb3NpdGUgdHJhbnNpdGlvbiBhbmltYXRpb24uXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4geXJodHZcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9uYXZpZ2F0b3JcbiAqIEBndWlkZSBtdWx0aXBsZS1wYWdlLW5hdmlnYXRpb25cbiAqICAgW2VuXUd1aWRlIGZvciBwYWdlIG5hdmlnYXRpb25bL2VuXVxuICogICBbamFd44Oa44O844K444OK44OT44Ky44O844K344On44Oz44Gu5qaC6KaBWy9qYV1cbiAqIEBndWlkZSB0ZW1wbGF0ZXNcbiAqICAgW2VuXURlZmluaW5nIG11bHRpcGxlIHBhZ2VzIGluIHNpbmdsZSBodG1sWy9lbl1cbiAqICAgW2phXeikh+aVsOOBruODmuODvOOCuOOCkjHjgaTjga5IVE1M44Gr6KiY6L+w44GZ44KLWy9qYV1cbiAqIEBndWlkZSBjcmVhdGluZy1hLXBhZ2VcbiAqICAgW2VuXVNldHRpbmcgdXAgYSBwYWdlIGluIGl0cyBgaW5pdGAgZXZlbnRbL2VuXVxuICogICBbamFdU2V0dGluZyB1cCBhIHBhZ2UgaW4gaXRzIGBpbml0YCBldmVudFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdG9vbGJhclxuICogICBbZW5dVGhlIGA8b25zLXRvb2xiYXI+YCBjb21wb25lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgdG9vbGJhciBvbiB0aGUgdG9wIG9mIGEgcGFnZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1iYWNrLWJ1dHRvblxuICogICBbZW5dVGhlIGA8b25zLWJhY2stYnV0dG9uPmAgY29tcG9uZW50IGxldHMgdGhlIHVzZXIgcmV0dXJuIHRvIHRoZSBwcmV2aW91cyBwYWdlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtbmF2aWdhdG9yIGlkPVwibmF2aWdhdG9yXCI+XG4gKiAgIDxvbnMtcGFnZT5cbiAqICAgICA8b25zLXRvb2xiYXI+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwiY2VudGVyXCI+XG4gKiAgICAgICAgIFRpdGxlXG4gKiAgICAgICA8L2Rpdj5cbiAqICAgICA8L29ucy10b29sYmFyPlxuICogICAgIDxwPlxuICogICAgICAgPG9ucy1idXR0b25cbiAqICAgICAgICAgb25jbGljaz1cImRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduYXZpZ2F0b3InKS5wdXNoUGFnZSgncGFnZS5odG1sJylcIj5cbiAqICAgICAgICAgUHVzaCBwYWdlXG4gKiAgICAgICA8L29ucy1idXR0b24+XG4gKiAgICAgPC9wPlxuICogICA8L29ucy1wYWdlPlxuICogPC9vbnMtbmF2aWdhdG9yPlxuICpcbiAqIDxvbnMtdGVtcGxhdGUgaWQ9XCJwYWdlLmh0bWxcIj5cbiAqICAgPG9ucy1wYWdlPlxuICogICAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+XG4gKiAgICAgICAgIDxvbnMtYmFjay1idXR0b24+QmFjazwvb25zLWJhY2stYnV0dG9uPlxuICogICAgICAgPC9kaXY+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwiY2VudGVyXCI+XG4gKiAgICAgICAgIEFub3RoZXIgcGFnZVxuICogICAgICAgPC9kaXY+XG4gKiAgICAgPC9vbnMtdG9vbGJhcj5cbiAqICAgPC9vbnMtcGFnZT5cbiAqIDwvb25zLXRlbXBsYXRlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJzdCBwYWdlIHRvIHNob3cgd2hlbiBuYXZpZ2F0b3IgaXMgaW5pdGlhbGl6ZWQuWy9lbl1cbiAgICogICBbamFd44OK44OT44Ky44O844K/44O844GM5Yid5pyf5YyW44GV44KM44Gf5pmC44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJzbGlkZVwiYCwgYFwibGlmdFwiYCwgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5cbiAgICpcbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIGBcIi1pb3NcImAgb3IgYFwiLW1kXCJgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gYFwibGlmdC1pb3NcImAsIGBcImxpZnQtbWRcImAuIERlZmF1bHRzIHZhbHVlcyBhcmUgYFwic2xpZGUtaW9zXCJgIGFuZCBgXCJmYWRlLW1kXCJgIGRlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0uXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgIJlLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXB1c2hcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgovnm7TliY3jgavnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmN1cnJlbnRQYWdlXG4gICAqICAgW2VuXUN1cnJlbnQgcGFnZSBvYmplY3QuWy9lbl1cbiAgICogICBbamFd54++5Zyo44GucGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRoaXMgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBwdXNoLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXB1c2jlh6bnkIbjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXBvcFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44KL55u05YmN44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jdXJyZW50UGFnZVxuICAgKiAgIFtlbl1DdXJyZW50IHBhZ2Ugb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgcG9wLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXBhZ2Xjga5wb3DjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RwdXNoXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgabjgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgYzntYLkuobjgZfjgabjgYvjgonnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmVudGVyUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIG5leHQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV1wdXNo44GV44KM44GfcGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5sZWF2ZVBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBwcmV2aW91cyBwYWdlLlsvZW5dXG4gICAqICAgW2phXeS7peWJjeOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3Rwb3BcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44Gm44Ki44OL44Oh44O844K344On44Oz44GM57WC44KP44Gj44Gf5b6M44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5lbnRlclBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBuZXh0IHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm6KGo56S644GV44KM44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmxlYXZlUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIHByZXZpb3VzIHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm5raI44GI44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IGFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICByZXR1cm4gdGhpcy5fYW5pbWF0b3JGYWN0b3J5O1xuICB9XG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZTtcbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gZGVmYXVsdFBhZ2VMb2FkZXI7XG5cbiAgICB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgcGFnZUxvYWRlclxuICAgKiBAdHlwZSB7UGFnZUxvYWRlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVsvZW5dXG4gICAqICAgW2phXVBhZ2VMb2FkZXLjgqTjg7Pjgrnjgr/jg7PjgrnjgpLmoLzntI3jgZfjgabjgYTjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihwYWdlTG9hZGVyKSB7XG4gICAgaWYgKCEocGFnZUxvYWRlciBpbnN0YW5jZW9mIFBhZ2VMb2FkZXIpKSB7XG4gICAgICB0aHJvdyBFcnJvcignRmlyc3QgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgUGFnZUxvYWRlci4nKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IHBhZ2VMb2FkZXI7XG4gIH1cblxuICBfZ2V0UGFnZVRhcmdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZSB8fCB0aGlzLmdldEF0dHJpYnV0ZSgncGFnZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlXG4gICAqIEB0eXBlIHsqfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dWy9lbl1cbiAgICogICBbamFd5Yid5pyf5YyW5pmC44Gr6Kqt44G/6L6844KA44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCYHBhZ2Vg5bGe5oCn44Gn5oyH5a6a44GX44Gf5YCk44KI44KK44KCYHBhZ2Vg44OX44Ot44OR44OG44Kj44Gr5oyH5a6a44GX44Gf5YCk44KS5YSq5YWI44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgc2V0IHBhZ2UocGFnZSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24gPSB0aGlzLl9vbkRldmljZUJhY2tCdXR0b24uYmluZCh0aGlzKTtcblxuXG4gICAgcmV3cml0YWJsZXMucmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID09PSAwICYmIHRoaXMuX2dldFBhZ2VUYXJnZXQoKSkge1xuICAgICAgICB0aGlzLnB1c2hQYWdlKHRoaXMuX2dldFBhZ2VUYXJnZXQoKSwge2FuaW1hdGlvbjogJ25vbmUnfSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAodGhpcy5wYWdlc1tpXS5ub2RlTmFtZSAhPT0gJ09OUy1QQUdFJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY2hpbGRyZW4gb2YgPG9ucy1uYXZpZ2F0b3I+IG5lZWQgdG8gYmUgb2YgdHlwZSA8b25zLXBhZ2U+Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMudG9wUGFnZSkge1xuICAgICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLnRvcFBhZ2UsICgpID0+XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgdGhpcy50b3BQYWdlLl9zaG93KCk7XG4gICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUxhc3RQYWdlQmFja0J1dHRvbigpO1xuICAgICAgICAgICAgfSwgMClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMCAmJiB0aGlzLl9nZXRQYWdlVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgIHRoaXMucHVzaFBhZ2UodGhpcy5fZ2V0UGFnZVRhcmdldCgpLCB7YW5pbWF0aW9uOiAnbm9uZSd9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ05hdmlnYXRvclRyYW5zaXRpb25BbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJylcbiAgICB9KTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IG51bGw7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydhbmltYXRpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdhbmltYXRpb24nKSB7XG4gICAgICB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBwb3BQYWdlXG4gICAqIEBzaWduYXR1cmUgcG9wUGFnZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1cbiAgICogICAgIEFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwic2xpZGVcImAsIGBcImxpZnRcImAsIGBcImZhZGVcImAgYW5kIGBcIm5vbmVcImAuXG4gICAqXG4gICAqICAgICBUaGVzZSBhcmUgcGxhdGZvcm0gYmFzZWQgYW5pbWF0aW9ucy4gRm9yIGZpeGVkIGFuaW1hdGlvbnMsIGFkZCBgXCItaW9zXCJgIG9yIGBcIi1tZFwiYCBzdWZmaXggdG8gdGhlIGFuaW1hdGlvbiBuYW1lLiBFLmcuIGBcImxpZnQtaW9zXCJgLCBgXCJsaWZ0LW1kXCJgLiBEZWZhdWx0cyB2YWx1ZXMgYXJlIGBcInNsaWRlLWlvc1wiYCBhbmQgYFwiZmFkZS1tZFwiYC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5yZWZyZXNoXVxuICAgKiAgIFtlbl1UaGUgcHJldmlvdXMgcGFnZSB3aWxsIGJlIHJlZnJlc2hlZCAoZGVzdHJveWVkIGFuZCBjcmVhdGVkIGFnYWluKSBiZWZvcmUgcG9wUGFnZSBhY3Rpb24uWy9lbl1cbiAgICogICBbamFdcG9wUGFnZeOBmeOCi+WJjeOBq+OAgeWJjeOBq+OBguOCi+ODmuODvOOCuOOCkueUn+aIkOOBl+OBquOBiuOBl+OBpuabtOaWsOOBmeOCi+WgtOWQiOOBq3RydWXjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Oh44K944OD44OJ44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmRhdGFdXG4gICAqICAgW2VuXUN1c3RvbSBkYXRhIHRoYXQgd2lsbCBiZSBzdG9yZWQgaW4gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgcmV2ZWFsZWQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mmI7jgonjgYvjgavjgZfjgZ/jg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVBvcHMgdGhlIGN1cnJlbnQgcGFnZSBmcm9tIHRoZSBwYWdlIHN0YWNrLiBUaGUgcHJldmlvdXMgcGFnZSB3aWxsIGJlIGRpc3BsYXllZC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjooajnpLrkuK3jga7jg5rjg7zjgrjjgpLjg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgYvjgonlj5bjgorpmaTjgY3jgb7jgZnjgILkuIDjgaTliY3jga7jg5rjg7zjgrjjgavmiLvjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcG9wUGFnZShvcHRpb25zID0ge30pIHtcbiAgICAoe29wdGlvbnN9ID0gdGhpcy5fcHJlcGFyZVBhZ2VBbmRPcHRpb25zKG51bGwsIG9wdGlvbnMpKTtcblxuICAgIGNvbnN0IHBvcFVwZGF0ZSA9ICgpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLnBhZ2VzW3RoaXMucGFnZXMubGVuZ3RoIC0gMV0uX2Rlc3Ryb3koKTtcbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcblxuICAgIGlmICghb3B0aW9ucy5yZWZyZXNoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcG9wUGFnZShvcHRpb25zLCBwb3BVcGRhdGUpO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAyO1xuICAgIGNvbnN0IG9sZFBhZ2UgPSB0aGlzLnBhZ2VzW2luZGV4XTtcblxuICAgIGlmICghb2xkUGFnZS5uYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlZnJlc2ggb3B0aW9uIGNhbm5vdCBiZSB1c2VkIHdpdGggcGFnZXMgZGlyZWN0bHkgaW5zaWRlIHRoZSBOYXZpZ2F0b3IuIFVzZSBvbnMtdGVtcGxhdGUgaW5zdGVhZC4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBjb25zdCBvcHRpb25zID0ge3BhZ2U6IG9sZFBhZ2UubmFtZSwgcGFyZW50OiB0aGlzLCBwYXJhbXM6IG9sZFBhZ2UucHVzaGVkT3B0aW9ucy5kYXRhfTtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZChvcHRpb25zLCAoe2VsZW1lbnQsIHVubG9hZH0pID0+IHtcbiAgICAgICAgZWxlbWVudCA9IHV0aWwuZXh0ZW5kKGVsZW1lbnQsIHtcbiAgICAgICAgICBuYW1lOiBvbGRQYWdlLm5hbWUsXG4gICAgICAgICAgZGF0YTogb2xkUGFnZS5kYXRhLFxuICAgICAgICAgIHB1c2hlZE9wdGlvbnM6IG9sZFBhZ2UucHVzaGVkT3B0aW9ucyxcbiAgICAgICAgICB1bmxvYWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV3cml0YWJsZXMubGluayh0aGlzLCBlbGVtZW50LCBvbGRQYWdlLm9wdGlvbnMsIGVsZW1lbnQgPT4ge1xuICAgICAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIG9sZFBhZ2UgPyBvbGRQYWdlIDogbnVsbCk7XG4gICAgICAgICAgb2xkUGFnZS5fZGVzdHJveSgpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgIH0pLnRoZW4oKCkgPT4gdGhpcy5fcG9wUGFnZShvcHRpb25zLCBwb3BVcGRhdGUpKTtcbiAgfVxuXG4gIF9wb3BQYWdlKG9wdGlvbnMsIHVwZGF0ZSA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgpKSB7XG4gICAgaWYgKHRoaXMuX2lzUnVubmluZykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdwb3BQYWdlIGlzIGFscmVhZHkgcnVubmluZy4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYWdlcy5sZW5ndGggPD0gMSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdvbnMtbmF2aWdhdG9yXFwncyBwYWdlIHN0YWNrIGlzIGVtcHR5LicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbWl0UHJlUG9wRXZlbnQoKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDYW5jZWxlZCBpbiBwcmVwb3AgZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5wYWdlcy5sZW5ndGg7XG5cbiAgICB0aGlzLl9pc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgdGhpcy5wYWdlc1tsZW5ndGggLSAyXS51cGRhdGVCYWNrQnV0dG9uKChsZW5ndGggLSAyKSA+IDApO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdmFyIGxlYXZlUGFnZSA9IHRoaXMucGFnZXNbbGVuZ3RoIC0gMV07XG4gICAgICB2YXIgZW50ZXJQYWdlID0gdGhpcy5wYWdlc1tsZW5ndGggLSAyXTtcbiAgICAgIGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblxuICAgICAgb3B0aW9ucy5hbmltYXRpb24gPSBvcHRpb25zLmFuaW1hdGlvbiB8fCBsZWF2ZVBhZ2UucHVzaGVkT3B0aW9ucy5hbmltYXRpb247XG4gICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAge30sXG4gICAgICAgIGxlYXZlUGFnZS5wdXNoZWRPcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fVxuICAgICAgKTtcblxuICAgICAgaWYgKG9wdGlvbnMuZGF0YSkge1xuICAgICAgICBlbnRlclBhZ2UuZGF0YSA9IHV0aWwuZXh0ZW5kKHt9LCBlbnRlclBhZ2UuZGF0YSB8fCB7fSwgb3B0aW9ucy5kYXRhIHx8IHt9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICAgIHVwZGF0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgZW50ZXJQYWdlLl9zaG93KCk7XG4gICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0cG9wJywge2xlYXZlUGFnZSwgZW50ZXJQYWdlLCBuYXZpZ2F0b3I6IHRoaXN9KTtcblxuICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgb3B0aW9ucy5jYWxsYmFjaygpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJlc29sdmUoZW50ZXJQYWdlKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBsZWF2ZVBhZ2UuX2hpZGUoKTtcbiAgICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuICAgICAgYW5pbWF0b3IucG9wKHRoaXMucGFnZXNbbGVuZ3RoIC0gMl0sIHRoaXMucGFnZXNbbGVuZ3RoIC0gMV0sIGNhbGxiYWNrKTtcbiAgICB9KS5jYXRjaCgoKSA9PiB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHB1c2hQYWdlXG4gICAqIEBzaWduYXR1cmUgcHVzaFBhZ2UocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhIEhUTUwgZG9jdW1lbnQgb3IgYSB0ZW1wbGF0ZSBkZWZpbmVkIHdpdGggdGhlIGA8b25zLXRlbXBsYXRlPmAgdGFnLlsvZW5dXG4gICAqICAgW2phXXBhZ2Xjga5VUkzjgYvjgIHjgoLjgZfjgY/jga9vbnMtdGVtcGxhdGXjgaflrqPoqIDjgZfjgZ/jg4bjg7Pjg5fjg6zjg7zjg4jjga5pZOWxnuaAp+OBruWApOOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMucGFnZV1cbiAgICogICBbZW5dUGFnZSBVUkwuIE9ubHkgbmVjZXNzYXJ5IGlmIGBwYWdlYCBwYXJhbWV0ZXIgaXMgbnVsbCBvciB1bmRlZmluZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnBhZ2VIVE1MXVxuICAgKiAgIFtlbl1IVE1MIGNvZGUgdGhhdCB3aWxsIGJlIGNvbXB1dGVkIGFzIGEgbmV3IHBhZ2UuIE92ZXJ3cml0ZXMgYHBhZ2VgIHBhcmFtZXRlci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1cbiAgICogICAgIEFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwic2xpZGVcImAsIGBcImxpZnRcImAsIGBcImZhZGVcImAgYW5kIGBcIm5vbmVcImAuXG4gICAqXG4gICAqICAgICBUaGVzZSBhcmUgcGxhdGZvcm0gYmFzZWQgYW5pbWF0aW9ucy4gRm9yIGZpeGVkIGFuaW1hdGlvbnMsIGFkZCBgXCItaW9zXCJgIG9yIGBcIi1tZFwiYCBzdWZmaXggdG8gdGhlIGFuaW1hdGlvbiBuYW1lLiBFLmcuIGBcImxpZnQtaW9zXCJgLCBgXCJsaWZ0LW1kXCJgLiBEZWZhdWx0cyB2YWx1ZXMgYXJlIGBcInNsaWRlLWlvc1wiYCBhbmQgYFwiZmFkZS1tZFwiYC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YCBbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFdcHVzaFBhZ2UoKeOBq+OCiOOCi+eUu+mdoumBt+enu+OBjOe1guS6huOBl+OBn+aZguOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5kYXRhXVxuICAgKiAgIFtlbl1DdXN0b20gZGF0YSB0aGF0IHdpbGwgYmUgc3RvcmVkIGluIHRoZSBuZXcgcGFnZSBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIHB1c2hlZCBwYWdlLlsvZW5dXG4gICAqICAgW2phXei/veWKoOOBl+OBn+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUHVzaGVzIHRoZSBzcGVjaWZpZWQgcGFnZSBpbnRvIHRoZSBzdGFjay5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ9wYWdl44KS5paw44GX44GE44Oa44O844K444K544K/44OD44Kv44Gr6L+95Yqg44GX44G+44GZ44CC5paw44GX44GE44Oa44O844K444GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgICh7cGFnZSwgb3B0aW9uc30gPSB0aGlzLl9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucykpO1xuXG4gICAgY29uc3QgcHJlcGFyZSA9IChlbGVtZW50LCB1bmxvYWQpID0+IHtcbiAgICAgIHRoaXMuX3ZlcmlmeVBhZ2VFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgZWxlbWVudCA9IHV0aWwuZXh0ZW5kKGVsZW1lbnQsIHtcbiAgICAgICAgbmFtZTogb3B0aW9ucy5wYWdlLFxuICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgICAgIHVubG9hZFxuICAgICAgfSk7XG4gICAgICBlbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLnBhZ2VIVE1MKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHVzaFBhZ2Uob3B0aW9ucywgKCkgPT4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIGluc3RhbnRQYWdlTG9hZGVyLmxvYWQoe3BhZ2U6IG9wdGlvbnMucGFnZUhUTUwsIHBhcmVudDogdGhpcywgcGFyYW1zOiBvcHRpb25zLmRhdGF9LCAoe2VsZW1lbnQsIHVubG9hZH0pID0+IHtcbiAgICAgICAgICBwcmVwYXJlKGVsZW1lbnQsIHVubG9hZCk7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fcHVzaFBhZ2Uob3B0aW9ucywgKCkgPT4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLl9wYWdlTG9hZGVyLmxvYWQoe3BhZ2UsIHBhcmVudDogdGhpcywgcGFyYW1zOiBvcHRpb25zLmRhdGF9LCAoe2VsZW1lbnQsIHVubG9hZH0pID0+IHtcbiAgICAgICAgcHJlcGFyZShlbGVtZW50LCB1bmxvYWQpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9KSk7XG4gIH1cblxuICBfcHVzaFBhZ2Uob3B0aW9ucyA9IHt9LCB1cGRhdGUgPSAoKSA9PiBQcm9taXNlLnJlc29sdmUoKSkge1xuICAgIGlmICh0aGlzLl9pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgncHVzaFBhZ2UgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbWl0UHJlUHVzaEV2ZW50KCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ2FuY2VsZWQgaW4gcHJlcHVzaCBldmVudC4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl9pc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgY29uc3QgYW5pbWF0aW9uT3B0aW9ucyA9IEFuaW1hdG9yRmFjdG9yeS5wYXJzZUFuaW1hdGlvbk9wdGlvbnNTdHJpbmcodGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbi1vcHRpb25zJykpO1xuICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zIHx8IHt9LCB7YW5pbWF0aW9uT3B0aW9uc30sIG9wdGlvbnMpO1xuXG4gICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdXBkYXRlKCkudGhlbigoKSA9PiB7XG4gICAgICBjb25zdCBwYWdlTGVuZ3RoID0gdGhpcy5wYWdlcy5sZW5ndGg7XG5cbiAgICAgIHZhciBlbnRlclBhZ2UgID0gdGhpcy5wYWdlc1twYWdlTGVuZ3RoIC0gMV07XG4gICAgICB2YXIgbGVhdmVQYWdlID0gdGhpcy5wYWdlc1twYWdlTGVuZ3RoIC0gMl07XG5cbiAgICAgIGlmIChlbnRlclBhZ2Uubm9kZU5hbWUgIT09ICdPTlMtUEFHRScpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPbmx5IGVsZW1lbnRzIG9mIHR5cGUgPG9ucy1wYWdlPiBjYW4gYmUgcHVzaGVkIHRvIHRoZSBuYXZpZ2F0b3InKTtcbiAgICAgIH1cblxuICAgICAgZW50ZXJQYWdlLnVwZGF0ZUJhY2tCdXR0b24ocGFnZUxlbmd0aCAtIDEpO1xuXG4gICAgICBlbnRlclBhZ2UucHVzaGVkT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHt9LCBlbnRlclBhZ2UucHVzaGVkT3B0aW9ucyB8fCB7fSwgb3B0aW9ucyB8fCB7fSk7XG4gICAgICBlbnRlclBhZ2UuZGF0YSA9IHV0aWwuZXh0ZW5kKHt9LCBlbnRlclBhZ2UuZGF0YSB8fCB7fSwgb3B0aW9ucy5kYXRhIHx8IHt9KTtcbiAgICAgIGVudGVyUGFnZS5uYW1lID0gZW50ZXJQYWdlLm5hbWUgfHwgb3B0aW9ucy5wYWdlO1xuICAgICAgZW50ZXJQYWdlLnVubG9hZCA9IGVudGVyUGFnZS51bmxvYWQgfHwgb3B0aW9ucy51bmxvYWQ7XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgdmFyIGRvbmUgPSAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG5cbiAgICAgICAgICBpZiAobGVhdmVQYWdlKSB7XG4gICAgICAgICAgICBsZWF2ZVBhZ2Uuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gZW50ZXJQYWdlLl9zaG93KCkpO1xuICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncG9zdHB1c2gnLCB7bGVhdmVQYWdlLCBlbnRlclBhZ2UsIG5hdmlnYXRvcjogdGhpc30pO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmVzb2x2ZShlbnRlclBhZ2UpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICAgIHZhciBwdXNoID0gKCkgPT4gIHtcbiAgICAgICAgICBlbnRlclBhZ2Uuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgICAgaWYgKGxlYXZlUGFnZSkge1xuICAgICAgICAgICAgbGVhdmVQYWdlLl9oaWRlKCk7XG4gICAgICAgICAgICBhbmltYXRvci5wdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBkb25lKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBvcHRpb25zLl9saW5rZWQgPyBwdXNoKCkgOiByZXdyaXRhYmxlcy5saW5rKHRoaXMsIGVudGVyUGFnZSwgb3B0aW9ucywgcHVzaCk7XG4gICAgICB9KTtcbiAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCByZXBsYWNlUGFnZVxuICAgKiBAc2lnbmF0dXJlIHJlcGxhY2VQYWdlKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgbmV3IHBhZ2UuWy9lbl1cbiAgICogICBbamFd5paw44GX44GE44Oa44O844K444KS6Kej5rG644GZ44KLUHJvbWlzZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXBsYWNlcyB0aGUgY3VycmVudCB0b3AgcGFnZSB3aXRoIHRoZSBzcGVjaWZpZWQgb25lLiBFeHRlbmRzIGBwdXNoUGFnZSgpYCBwYXJhbWV0ZXJzLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuS4reOBruODmuODvOOCuOOCkuOCkuaMh+WumuOBl+OBn+ODmuODvOOCuOOBq+e9ruOBjeaPm+OBiOOBvuOBmeOAglsvamFdXG4gICAqL1xuICByZXBsYWNlUGFnZShwYWdlLCBvcHRpb25zID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5wdXNoUGFnZShwYWdlLCBvcHRpb25zKVxuICAgICAgLnRoZW4ocmVzb2x2ZWRWYWx1ZSA9PiB7XG4gICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB0aGlzLnBhZ2VzW3RoaXMucGFnZXMubGVuZ3RoIC0gMl0uX2Rlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGVMYXN0UGFnZUJhY2tCdXR0b24oKTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc29sdmVkVmFsdWUpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpbnNlcnRQYWdlXG4gICAqIEBzaWduYXR1cmUgaW5zZXJ0UGFnZShpbmRleCwgcGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogICBbZW5dVGhlIGluZGV4IHdoZXJlIGl0IHNob3VsZCBiZSBpbnNlcnRlZC5bL2VuXVxuICAgKiAgIFtqYV3jgrnjgr/jg4Pjgq/jgavmjL/lhaXjgZnjgovkvY3nva7jga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1Qcm9taXNlIHdoaWNoIHJlc29sdmVzIHRvIHRoZSBpbnNlcnRlZCBwYWdlLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSW5zZXJ0IHRoZSBzcGVjaWZpZWQgcGFnZSBpbnRvIHRoZSBzdGFjayB3aXRoIGF0IGEgcG9zaXRpb24gZGVmaW5lZCBieSB0aGUgYGluZGV4YCBhcmd1bWVudC4gRXh0ZW5kcyBgcHVzaFBhZ2UoKWAgcGFyYW1ldGVycy5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ9wYWdl44KS44Oa44O844K444K544K/44OD44Kv44GuaW5kZXjjgafmjIflrprjgZfjgZ/kvY3nva7jgavov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgaW5zZXJ0UGFnZShpbmRleCwgcGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG4gICAgaW5kZXggPSB0aGlzLl9ub3JtYWxpemVJbmRleChpbmRleCk7XG5cbiAgICBpZiAoaW5kZXggPj0gdGhpcy5wYWdlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHBhZ2UgPSB0eXBlb2Ygb3B0aW9ucy5wYWdlSFRNTCA9PT0gJ3N0cmluZycgPyBvcHRpb25zLnBhZ2VIVE1MIDogcGFnZTtcbiAgICBjb25zdCBsb2FkZXIgPSB0eXBlb2Ygb3B0aW9ucy5wYWdlSFRNTCA9PT0gJ3N0cmluZycgPyBpbnN0YW50UGFnZUxvYWRlciA6IHRoaXMuX3BhZ2VMb2FkZXI7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBsb2FkZXIubG9hZCh7cGFnZSwgcGFyZW50OiB0aGlzfSwgKHtlbGVtZW50LCB1bmxvYWR9KSA9PiB7XG4gICAgICAgIHRoaXMuX3ZlcmlmeVBhZ2VFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICBlbGVtZW50ID0gdXRpbC5leHRlbmQoZWxlbWVudCwge1xuICAgICAgICAgIG5hbWU6IG9wdGlvbnMucGFnZSxcbiAgICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgICAgICAgcHVzaGVkT3B0aW9uczogb3B0aW9ucyxcbiAgICAgICAgICB1bmxvYWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zID0gdXRpbC5leHRlbmQoXG4gICAgICAgICAge30sXG4gICAgICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSksXG4gICAgICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9XG4gICAgICAgICk7XG5cbiAgICAgICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLmluc2VydEJlZm9yZShlbGVtZW50LCB0aGlzLnBhZ2VzW2luZGV4XSk7XG4gICAgICAgIHRoaXMudG9wUGFnZS51cGRhdGVCYWNrQnV0dG9uKHRydWUpO1xuXG4gICAgICAgIHJld3JpdGFibGVzLmxpbmsodGhpcywgZWxlbWVudCwgb3B0aW9ucywgZWxlbWVudCA9PiB7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBlbGVtZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5wYWdlc1tpbmRleF0pO1xuICAgICAgICAgIH0sIDEwMDAgLyA2MCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCByZXNldFRvUGFnZVxuICAgKiBAc2lnbmF0dXJlIHJlc2V0VG9QYWdlKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgbmV3IHRvcCBwYWdlLlsvZW5dXG4gICAqICAgW2phXeaWsOOBl+OBhOODiOODg+ODl+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xlYXJzIHBhZ2Ugc3RhY2sgYW5kIGFkZHMgdGhlIHNwZWNpZmllZCBwYWdlIHRvIHRoZSBzdGFjay4gRXh0ZW5kcyBgcHVzaFBhZ2UoKWAgcGFyYW1ldGVycy5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgpLjg6rjgrvjg4Pjg4jjgZfjgIHmjIflrprjgZfjgZ/jg5rjg7zjgrjjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcmVzZXRUb1BhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG5cbiAgICBpZiAoIW9wdGlvbnMuYW5pbWF0b3IgJiYgIW9wdGlvbnMuYW5pbWF0aW9uKSB7XG4gICAgICBvcHRpb25zLmFuaW1hdGlvbiA9ICdub25lJztcbiAgICB9XG5cbiAgICBjb25zdCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2s7XG5cbiAgICBvcHRpb25zLmNhbGxiYWNrID0gKCkgPT4ge1xuICAgICAgd2hpbGUgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aGlzLnBhZ2VzWzBdLl9kZXN0cm95KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGFnZXNbMF0udXBkYXRlQmFja0J1dHRvbihmYWxzZSk7XG4gICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgIH07XG5cbiAgICBpZiAoIW9wdGlvbnMucGFnZSAmJiAhb3B0aW9ucy5wYWdlSFRNTCAmJiB0aGlzLl9nZXRQYWdlVGFyZ2V0KCkpIHtcbiAgICAgIHBhZ2UgPSBvcHRpb25zLnBhZ2UgPSB0aGlzLl9nZXRQYWdlVGFyZ2V0KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucHVzaFBhZ2UocGFnZSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBicmluZ1BhZ2VUb3BcbiAgICogQHNpZ25hdHVyZSBicmluZ1BhZ2VUb3AoaXRlbSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGl0ZW1cbiAgICogICBbZW5dUGFnZSBVUkwgb3IgaW5kZXggb2YgYW4gZXhpc3RpbmcgcGFnZSBpbiBuYXZpZ2F0b3IncyBzdGFjay5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjga5VUkzjgYvjgoLjgZfjgY/jga9vbnMtbmF2aWdhdG9y44Gu44Oa44O844K444K544K/44OD44Kv44Gu44Kk44Oz44OH44OD44Kv44K55YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgbmV3IHRvcCBwYWdlLlsvZW5dXG4gICAqICAgW2phXeaWsOOBl+OBhOODiOODg+ODl+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQnJpbmdzIHRoZSBnaXZlbiBwYWdlIHRvIHRoZSB0b3Agb2YgdGhlIHBhZ2Ugc3RhY2sgaWYgaXQgYWxyZWFkeSBleGlzdHMgb3IgcHVzaGVzIGl0IGludG8gdGhlIHN0YWNrIGlmIGRvZXNuJ3QuIEV4dGVuZHMgYHB1c2hQYWdlKClgIHBhcmFtZXRlcnMuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44Gf44Oa44O844K444KS44Oa44O844K444K544K/44OD44Kv44Gu5LiA55Wq5LiK44Gr56e75YuV44GX44G+44GZ44CC44KC44GX5oyH5a6a44GX44Gf44Oa44O844K444GM54Sh44GL44Gj44Gf5aC05ZCI5paw44GX44GPcHVzaOOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuICBicmluZ1BhZ2VUb3AoaXRlbSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKFsnbnVtYmVyJywgJ3N0cmluZyddLmluZGV4T2YodHlwZW9mIGl0ZW0pID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGaXJzdCBhcmd1bWVudCBtdXN0IGJlIGEgcGFnZSBuYW1lIG9yIHRoZSBpbmRleCBvZiBhbiBleGlzdGluZyBwYWdlLiBZb3Ugc3VwcGxpZWQgJyArIGl0ZW0pO1xuICAgIH1cbiAgICBjb25zdCBpbmRleCA9IHR5cGVvZiBpdGVtID09PSAnbnVtYmVyJyA/IHRoaXMuX25vcm1hbGl6ZUluZGV4KGl0ZW0pIDogdGhpcy5fbGFzdEluZGV4T2ZQYWdlKGl0ZW0pO1xuICAgIGNvbnN0IHBhZ2UgPSB0aGlzLnBhZ2VzW2luZGV4XTtcblxuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKGl0ZW0sIG9wdGlvbnMpO1xuICAgIH1cbiAgICAoe29wdGlvbnN9ID0gdGhpcy5fcHJlcGFyZVBhZ2VBbmRPcHRpb25zKHBhZ2UsIG9wdGlvbnMpKTtcblxuICAgIGlmIChpbmRleCA9PT0gdGhpcy5wYWdlcy5sZW5ndGggLSAxKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHBhZ2UpO1xuICAgIH1cbiAgICBpZiAoIXBhZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGZpbmQgaXRlbSAnICsgaXRlbSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgncHVzaFBhZ2UgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fZW1pdFByZVB1c2hFdmVudCgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXB1c2ggZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgdXRpbC5leHRlbmQob3B0aW9ucywge1xuICAgICAgcGFnZTogcGFnZS5uYW1lLFxuICAgICAgX2xpbmtlZDogdHJ1ZVxuICAgIH0pO1xuICAgIHBhZ2Uuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICBwYWdlLnNldEF0dHJpYnV0ZSgnX3NraXBpbml0JywgJycpO1xuICAgIHBhZ2UucGFyZW50Tm9kZS5hcHBlbmRDaGlsZChwYWdlKTtcbiAgICByZXR1cm4gdGhpcy5fcHVzaFBhZ2Uob3B0aW9ucyk7XG4gIH1cblxuICBfcHJlcGFyZVBhZ2VBbmRPcHRpb25zKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucyAhPSAnb2JqZWN0Jykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvcHRpb25zIG11c3QgYmUgYW4gb2JqZWN0LiBZb3Ugc3VwcGxpZWQgJyArIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmICgocGFnZSA9PT0gbnVsbCB8fCBwYWdlID09PSB1bmRlZmluZWQpICYmIG9wdGlvbnMucGFnZSkge1xuICAgICAgcGFnZSA9IG9wdGlvbnMucGFnZTtcbiAgICB9XG5cbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe30sIHRoaXMub3B0aW9ucyB8fCB7fSwgb3B0aW9ucywge3BhZ2V9KTtcblxuICAgIHJldHVybiB7cGFnZSwgb3B0aW9uc307XG4gIH1cblxuICBfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uKCkge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB0aGlzLnBhZ2VzW2luZGV4XS51cGRhdGVCYWNrQnV0dG9uKGluZGV4ID4gMCk7XG4gICAgfVxuICB9XG5cbiAgX25vcm1hbGl6ZUluZGV4KGluZGV4KSB7XG4gICAgcmV0dXJuIGluZGV4ID49IDAgPyBpbmRleCA6IE1hdGguYWJzKHRoaXMucGFnZXMubGVuZ3RoICsgaW5kZXgpICUgdGhpcy5wYWdlcy5sZW5ndGg7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgdGhpcy5wb3BQYWdlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gICAgfVxuICB9XG5cbiAgX2xhc3RJbmRleE9mUGFnZShwYWdlTmFtZSkge1xuICAgIGxldCBpbmRleDtcbiAgICBmb3IgKGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgICBpZiAodGhpcy5wYWdlc1tpbmRleF0ubmFtZSA9PT0gcGFnZU5hbWUpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIF9lbWl0UHJlRXZlbnQobmFtZSwgZGF0YSA9IHt9KSB7XG4gICAgbGV0IGlzQ2FuY2VsZWQgPSBmYWxzZTtcblxuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncHJlJyArIG5hbWUsIHV0aWwuZXh0ZW5kKHtcbiAgICAgIG5hdmlnYXRvcjogdGhpcyxcbiAgICAgIGN1cnJlbnRQYWdlOiB0aGlzLnBhZ2VzW3RoaXMucGFnZXMubGVuZ3RoIC0gMV0sXG4gICAgICBjYW5jZWw6ICgpID0+IGlzQ2FuY2VsZWQgPSB0cnVlXG4gICAgfSwgZGF0YSkpO1xuXG4gICAgcmV0dXJuIGlzQ2FuY2VsZWQ7XG4gIH1cblxuICBfZW1pdFByZVB1c2hFdmVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZW1pdFByZUV2ZW50KCdwdXNoJyk7XG4gIH1cblxuICBfZW1pdFByZVBvcEV2ZW50KCkge1xuICAgIGNvbnN0IGwgPSB0aGlzLnBhZ2VzLmxlbmd0aDtcbiAgICByZXR1cm4gdGhpcy5fZW1pdFByZUV2ZW50KCdwb3AnLCB7XG4gICAgICBsZWF2ZVBhZ2U6IHRoaXMucGFnZXNbbCAtIDFdLFxuICAgICAgZW50ZXJQYWdlOiB0aGlzLnBhZ2VzW2wgLSAyXVxuICAgIH0pO1xuICB9XG5cbiAgLy8gVE9ETzog5pu444GN55u044GZXG4gIF9jcmVhdGVQYWdlRWxlbWVudCh0ZW1wbGF0ZUhUTUwpIHtcbiAgICBjb25zdCBwYWdlRWxlbWVudCA9IHV0aWwuY3JlYXRlRWxlbWVudChpbnRlcm5hbC5ub3JtYWxpemVQYWdlSFRNTCh0ZW1wbGF0ZUhUTUwpKTtcbiAgICB0aGlzLl92ZXJpZnlQYWdlRWxlbWVudChwYWdlRWxlbWVudCk7XG4gICAgcmV0dXJuIHBhZ2VFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICAgKi9cbiAgX3ZlcmlmeVBhZ2VFbGVtZW50KGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLXBhZ2UnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBtdXN0IHN1cHBseSBhbiBcIm9ucy1wYWdlXCIgZWxlbWVudCB0byBcIm9ucy1uYXZpZ2F0b3JcIi4nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cbiAgZ2V0IG9uRGV2aWNlQmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fYmFja0J1dHRvbkhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25EZXZpY2VCYWNrQnV0dG9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5jcmVhdGVIYW5kbGVyKHRoaXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdG9wUGFnZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCB0b3AgcGFnZSBlbGVtZW50LiBVc2UgdGhpcyBtZXRob2QgdG8gYWNjZXNzIG9wdGlvbnMgcGFzc2VkIGJ5IGBwdXNoUGFnZSgpYC1saWtlIG1ldGhvZHMuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44Oa44O844K444KS5Y+W5b6X44GX44G+44GZ44CCcHVzaFBhZ2UoKeOChHJlc2V0VG9QYWdlKCnjg6Hjgr3jg4Pjg4njga7lvJXmlbDjgpLlj5blvpfjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHRvcFBhZ2UoKSB7XG4gICAgcmV0dXJuIHRoaXMucGFnZXNbdGhpcy5wYWdlcy5sZW5ndGggLSAxXSB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlc1xuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0FycmF5fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ29weSBvZiB0aGUgbmF2aWdhdG9yJ3MgcGFnZSBzdGFjay5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VzKCkge1xuICAgIHJldHVybiB1dGlsXG4gICAgICAuYXJyYXlGcm9tKHRoaXMuY2hpbGRyZW4pXG4gICAgICAuZmlsdGVyKG4gPT4gbi50YWdOYW1lID09PSAnT05TLVBBR0UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9uc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRGVmYXVsdCBvcHRpb25zIG9iamVjdC4gQXR0cmlidXRlcyBoYXZlIHByaW9yaXR5IG92ZXIgdGhpcyBwcm9wZXJ0eS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMuYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1cbiAgICogICAgIEFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwic2xpZGVcImAsIGBcImxpZnRcImAsIGBcImZhZGVcImAgYW5kIGBcIm5vbmVcImAuXG4gICAqICAgICBUaGVzZSBhcmUgcGxhdGZvcm0gYmFzZWQgYW5pbWF0aW9ucy4gRm9yIGZpeGVkIGFuaW1hdGlvbnMsIGFkZCBgXCItaW9zXCJgIG9yIGBcIi1tZFwiYCBzdWZmaXggdG8gdGhlIGFuaW1hdGlvbiBuYW1lLiBFLmcuIGBcImxpZnQtaW9zXCJgLCBgXCJsaWZ0LW1kXCJgLiBEZWZhdWx0cyB2YWx1ZXMgYXJlIGBcInNsaWRlLWlvc1wiYCBhbmQgYFwiZmFkZS1tZFwiYC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmNhbGxiYWNrXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg6Hjgr3jg4Pjg4njgavjgojjgovnlLvpnaLpgbfnp7vjgYzntYLkuobjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnMucmVmcmVzaFxuICAgKiBAZGVmYXVsdCAgZmFsc2VcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIHBhcmFtZXRlciBpcyBgdHJ1ZWAsIHRoZSBwcmV2aW91cyBwYWdlIHdpbGwgYmUgcmVmcmVzaGVkIChkZXN0cm95ZWQgYW5kIGNyZWF0ZWQgYWdhaW4pIGJlZm9yZSBgcG9wUGFnZSgpYCBhY3Rpb24uWy9lbl1cbiAgICogICBbamFdcG9wUGFnZeOBmeOCi+WJjeOBq+OAgeWJjeOBq+OBguOCi+ODmuODvOOCuOOCkueUn+aIkOOBl+OBquOBiuOBl+OBpuabtOaWsOOBmeOCi+WgtOWQiOOBq3RydWXjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cbiAgc2V0IG9wdGlvbnMob2JqZWN0KSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9iamVjdDtcbiAgfVxuXG4gIHNldCBfaXNSdW5uaW5nKHZhbHVlKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ19pcy1ydW5uaW5nJywgdmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgfVxuICBnZXQgX2lzUnVubmluZygpIHtcbiAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdfaXMtcnVubmluZycpKTtcbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICh0aGlzLnRvcFBhZ2UpIHtcbiAgICAgIHRoaXMudG9wUGFnZS5fc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIGlmICh0aGlzLnRvcFBhZ2UpIHtcbiAgICAgIHRoaXMudG9wUGFnZS5faGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIF9kZXN0cm95KCkge1xuICAgIGZvciAobGV0IGkgPSB0aGlzLnBhZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB0aGlzLnBhZ2VzW2ldLl9kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBBbmltYXRvclxuICAgKi9cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvci5wcm90b3R5cGUgaW5zdGFuY2VvZiBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3IpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1wiQW5pbWF0b3JcIiBwYXJhbSBtdXN0IGluaGVyaXQgTmF2aWdhdG9yRWxlbWVudC5OYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3InKTtcbiAgICB9XG5cbiAgICBfYW5pbWF0b3JEaWN0W25hbWVdID0gQW5pbWF0b3I7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGFuaW1hdG9ycygpIHtcbiAgICByZXR1cm4gX2FuaW1hdG9yRGljdDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgTmF2aWdhdG9yVHJhbnNpdGlvbkFuaW1hdG9yKCkge1xuICAgIHJldHVybiBOYXZpZ2F0b3JUcmFuc2l0aW9uQW5pbWF0b3I7XG4gIH1cblxuICBzdGF0aWMgZ2V0IHJld3JpdGFibGVzKCkge1xuICAgIHJldHVybiByZXdyaXRhYmxlcztcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1uYXZpZ2F0b3InLCBOYXZpZ2F0b3JFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICduYXZpZ2F0aW9uLWJhci0tKicsXG4gICcubmF2aWdhdGlvbi1iYXJfX2xlZnQnOiAnbmF2aWdhdGlvbi1iYXItLSpfX2xlZnQnLFxuICAnLm5hdmlnYXRpb24tYmFyX19jZW50ZXInOiAnbmF2aWdhdGlvbi1iYXItLSpfX2NlbnRlcicsXG4gICcubmF2aWdhdGlvbi1iYXJfX3JpZ2h0JzogJ25hdmlnYXRpb24tYmFyLS0qX19yaWdodCdcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXRvb2xiYXJcbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiB0b29sYmFyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHRyYW5zcGFyZW50XG4gKiAgIFtlbl1UcmFuc3BhcmVudCB0b29sYmFyWy9lbl1cbiAqICAgW2phXemAj+aYjuOBquiDjOaZr+OCkuaMgeOBpOODhOODvOODq+ODkOODvOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbm9zaGFkb3dcbiAqICAgW2VuXVRvb2xiYXIgd2l0aG91dCBzaGFkb3dbL2VuXVxuICogICBbamFd44Gp44GG44GX44KI44GGWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVG9vbGJhciBjb21wb25lbnQgdGhhdCBjYW4gYmUgdXNlZCB3aXRoIG5hdmlnYXRpb24uXG4gKlxuICogICAgIExlZnQsIGNlbnRlciBhbmQgcmlnaHQgY29udGFpbmVyIGNhbiBiZSBzcGVjaWZpZWQgYnkgY2xhc3MgbmFtZXMuXG4gKlxuICogICAgIFRoaXMgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSBkaXNwbGF5cyBhcyBhIE1hdGVyaWFsIERlc2lnbiB0b29sYmFyIHdoZW4gcnVubmluZyBvbiBBbmRyb2lkIGRldmljZXMuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg4rjg5PjgrLjg7zjgrfjg6fjg7Pjgafkvb/nlKjjgZnjgovjg4Tjg7zjg6vjg5Djg7znlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgILjgq/jg6njgrnlkI3jgavjgojjgorjgIHlt6bjgIHkuK3lpK7jgIHlj7Pjga7jgrPjg7Pjg4bjg4rjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gYUhtR0xcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wYWdlXG4gKiBAZ3VpZGUgYWRkaW5nLWEtdG9vbGJhciBbZW5dQWRkaW5nIGEgdG9vbGJhclsvZW5dW2phXeODhOODvOODq+ODkOODvOOBrui/veWKoFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtYm90dG9tLXRvb2xiYXJcbiAqICAgW2VuXVRoZSBgPG9ucy1ib3R0b20tdG9vbGJhcj5gIGRpc3BsYXlzIGEgdG9vbGJhciBvbiB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLlsvZW5dXG4gKiAgIFtqYV1vbnMtYm90dG9tLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWJhY2stYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtYmFjay1idXR0b24+YCBjb21wb25lbnQgZGlzcGxheXMgYSBiYWNrIGJ1dHRvbiBpbnNpZGUgdGhlIHRvb2xiYXIuWy9lbl1cbiAqICAgW2phXW9ucy1iYWNrLWJ1dHRvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdG9vbGJhci1idXR0b25cbiAqICAgW2VuXVRoZSBgPG9ucy10b29sYmFyLWJ1dHRvbj5gIGNvbXBvbmVudCBkaXNwbGF5cyBhIHRvb2xiYXIgYnV0dG9uIGluc2lkZSB0aGUgdG9vbGJhci5bL2VuXVxuICogICBbamFdb25zLXRvb2xiYXItYnV0dG9u44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXBhZ2U+XG4gKiAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgICAgPG9ucy1iYWNrLWJ1dHRvbj5cbiAqICAgICAgICAgQmFja1xuICogICAgICAgPC9vbnMtYmFjay1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgICAgVGl0bGVcbiAqICAgICA8L2Rpdj5cbiAqICAgICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5cbiAqICAgICAgIDxvbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgICAgIDxvbnMtaWNvbiBpY29uPVwibWQtbWVudVwiPjwvb25zLWljb24+XG4gKiAgICAgICA8L29ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgICA8L2Rpdj5cbiAqICAgPC9vbnMtdG9vbGJhcj5cbiAqIDwvb25zLXBhZ2U+XG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVG9vbGJhckVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5saW5lXG4gICAqIEBpbml0b25seVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRGlzcGxheSB0aGUgdG9vbGJhciBhcyBhbiBpbmxpbmUgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjgpLjgqTjg7Pjg6njgqTjg7Pjgavnva7jgY3jgb7jgZnjgILjgrnjgq/jg63jg7zjg6vpoJjln5/lhoXjgavjgZ3jga7jgb7jgb7ooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHRvb2xiYXIuWy9lbl1cbiAgICogICBbamFd44OE44O844Or44OQ44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9XG4gICAqL1xuICBfZ2V0VG9vbGJhckxlZnRJdGVtc0VsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLmxlZnQnKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyQ2VudGVySXRlbXNFbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy5jZW50ZXInKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyUmlnaHRJdGVtc0VsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLnJpZ2h0JykgfHwgaW50ZXJuYWwubnVsbEVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9XG4gICAqL1xuICBfZ2V0VG9vbGJhckJhY2tCdXR0b25MYWJlbEVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWJhY2stYnV0dG9uIC5iYWNrLWJ1dHRvbl9fbGFiZWwnKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyQmFja0J1dHRvbkljb25FbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ29ucy1iYWNrLWJ1dHRvbiAuYmFjay1idXR0b25fX2ljb24nKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnbmF2aWdhdGlvbi1iYXInKTtcbiAgICB0aGlzLl9lbnN1cmVUb29sYmFySXRlbUVsZW1lbnRzKCk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2Vuc3VyZVRvb2xiYXJJdGVtRWxlbWVudHMoKSB7XG4gICAgZm9yIChsZXQgaSA9IHRoaXMuY2hpbGROb2Rlcy5sZW5ndGggLSAxOyBpID49IDAgOyBpLS0pIHtcbiAgICAgIC8vIGNhc2Ugb2Ygbm90IGVsZW1lbnRcbiAgICAgIGlmICh0aGlzLmNoaWxkTm9kZXNbaV0ubm9kZVR5cGUgIT0gMSkge1xuICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuY2hpbGROb2Rlc1tpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgY2VudGVyID0gdGhpcy5fZW5zdXJlVG9vbGJhckVsZW1lbnQoJ2NlbnRlcicpO1xuICAgIGNlbnRlci5jbGFzc0xpc3QuYWRkKCduYXZpZ2F0aW9uLWJhcl9fdGl0bGUnKTtcblxuICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCAhPT0gMSB8fCAhdGhpcy5jaGlsZHJlblswXS5jbGFzc0xpc3QuY29udGFpbnMoJ2NlbnRlcicpKSB7XG4gICAgICBjb25zdCBsZWZ0ID0gdGhpcy5fZW5zdXJlVG9vbGJhckVsZW1lbnQoJ2xlZnQnKTtcbiAgICAgIGNvbnN0IHJpZ2h0ID0gdGhpcy5fZW5zdXJlVG9vbGJhckVsZW1lbnQoJ3JpZ2h0Jyk7XG5cbiAgICAgIGlmICh0aGlzLmNoaWxkcmVuWzBdICE9PSBsZWZ0IHx8IHRoaXMuY2hpbGRyZW5bMV0gIT09IGNlbnRlciB8fCB0aGlzLmNoaWxkcmVuWzJdICE9PSByaWdodCkge1xuICAgICAgICB0aGlzLmFwcGVuZENoaWxkKGxlZnQpO1xuICAgICAgICB0aGlzLmFwcGVuZENoaWxkKGNlbnRlcik7XG4gICAgICAgIHRoaXMuYXBwZW5kQ2hpbGQocmlnaHQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9lbnN1cmVUb29sYmFyRWxlbWVudChuYW1lKSB7XG4gICAgaWYgKHV0aWwuZmluZENoaWxkKHRoaXMsICcubmF2aWdhdGlvbi1iYXJfXycgKyBuYW1lKSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcubmF2aWdhdGlvbi1iYXJfXycgKyBuYW1lKTtcbiAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChuYW1lKTtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLicgKyBuYW1lKSB8fCB1dGlsLmNyZWF0ZSgnLicgKyBuYW1lKTtcbiAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ25hdmlnYXRpb24tYmFyX18nICsgbmFtZSk7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy10b29sYmFyJywgVG9vbGJhckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vb25zL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5pbXBvcnQgJy4vb25zLXRvb2xiYXInOyAvLyBlbnN1cmVzIHRoYXQgJ29ucy10b29sYmFyJyBlbGVtZW50IGlzIHJlZ2lzdGVyZWRcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3BhZ2UtLSonLFxuICAnLnBhZ2VfX2NvbnRlbnQnOiAncGFnZS0tKl9fY29udGVudCcsXG4gICcucGFnZV9fYmFja2dyb3VuZCc6ICdwYWdlLS0qX19iYWNrZ3JvdW5kJ1xufTtcblxuY29uc3QgbnVsbFRvb2xiYXJFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb25zLXRvb2xiYXInKTsgLy8gcmVxdWlyZXMgdGhhdCAnb25zLXRvb2xiYXInIGVsZW1lbnQgaXMgcmVnaXN0ZXJlZFxuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wYWdlXG4gKiBAY2F0ZWdvcnkgcGFnZVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhpcyBjb21wb25lbnQgZGVmaW5lcyB0aGUgcm9vdCBvZiBlYWNoIHBhZ2UuIElmIHRoZSBjb250ZW50IGlzIGxhcmdlIGl0IHdpbGwgYmVjb21lIHNjcm9sbGFibGUuXG4gKlxuICogICAgIEEgbmF2aWdhdGlvbiBiYXIgY2FuIGJlIGFkZGVkIHRvIHRoZSB0b3Agb2YgdGhlIHBhZ2UgdXNpbmcgdGhlIGA8b25zLXRvb2xiYXI+YCBlbGVtZW50LlxuICogICBbL2VuXVxuICogICBbamFd44Oa44O844K45a6a576p44Gu44Gf44KB44Gu44Kz44Oz44Od44O844ON44Oz44OI44Gn44GZ44CC44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44Gu5YaF5a6544Gv44K544Kv44Ot44O844Or44GM6Kix5Y+v44GV44KM44G+44GZ44CCWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wYWdlXG4gKiBAZ3VpZGUgY3JlYXRpbmctYS1wYWdlXG4gKiAgIFtlbl1TZXR0aW5nIHVwIGEgcGFnZSBpbiBpdHMgYGluaXRgIGV2ZW50Wy9lbl1cbiAqICAgW2phXVNldHRpbmcgdXAgYSBwYWdlIGluIGl0cyBgaW5pdGAgZXZlbnRbL2phXVxuICogQGd1aWRlIHRlbXBsYXRlc1xuICogICBbZW5dRGVmaW5pbmcgbXVsdGlwbGUgcGFnZXMgaW4gc2luZ2xlIGh0bWxbL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KSMeOBpOOBrkhUTUzjgavoqJjov7DjgZnjgotbL2phXVxuICogQGd1aWRlIG11bHRpcGxlLXBhZ2UtbmF2aWdhdGlvblxuICogICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXNbL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBndWlkZSB1c2luZy1tb2RpZmllciBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1Vc2UgdGhlIGA8b25zLXRvb2xiYXI+YCBlbGVtZW50IHRvIGFkZCBhIG5hdmlnYXRpb24gYmFyIHRvIHRoZSB0b3Agb2YgdGhlIHBhZ2UuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wYWdlPlxuICogICA8b25zLXRvb2xiYXI+XG4gKiAgICAgPGRpdiBjbGFzcz1cImxlZnRcIj5cbiAqICAgICAgIDxvbnMtYmFjay1idXR0b24+QmFjazwvb25zLWJhY2stYnV0dG9uPlxuICogICAgIDwvZGl2PlxuICogICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5UaXRsZTwvZGl2PlxuICogICAgIDxkaXYgY2xhc3M9XCJyaWdodFwiPlxuICogICAgICAgPG9ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgICAgICAgPG9ucy1pY29uIGljb249XCJtZC1tZW51XCI+PC9vbnMtaWNvbj5cbiAqICAgICAgIDwvb25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgIDwvZGl2PlxuICogICA8L29ucy10b29sYmFyPlxuICpcbiAqICAgPHA+UGFnZSBjb250ZW50PC9wPlxuICogPC9vbnMtcGFnZT5cbiAqXG4gKiBAZXhhbXBsZVxuICogPHNjcmlwdD5cbiAqICAgbXlBcHAuaGFuZGxlciA9IGZ1bmN0aW9uKGRvbmUpIHtcbiAqICAgICBsb2FkTW9yZSgpLnRoZW4oZG9uZSk7XG4gKiAgIH1cbiAqIDwvc2NyaXB0PlxuICpcbiAqIDxvbnMtcGFnZSBvbi1pbmZpbml0ZS1zY3JvbGw9XCJteUFwcC5oYW5kbGVyXCI+XG4gKiAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICA8ZGl2IGNsYXNzPVwiY2VudGVyXCI+TGlzdDwvZGl2PlxuICogICA8L29ucy10b29sYmFyPlxuICpcbiAqICAgPG9ucy1saXN0PlxuICogICAgIDxvbnMtbGlzdC1pdGVtPiMxPC9vbnMtbGlzdC1pdGVtPlxuICogICAgIDxvbnMtbGlzdC1pdGVtPiMyPC9vbnMtbGlzdC1pdGVtPlxuICogICAgIDxvbnMtbGlzdC1pdGVtPiMzPC9vbnMtbGlzdC1pdGVtPlxuICogICAgIC4uLlxuICogICA8L29ucy1saXN0PlxuICogPC9vbnMtcGFnZT5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFnZUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBpbml0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCByaWdodCBhZnRlciB0aGUgcGFnZSBpcyBhdHRhY2hlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjgYzjgqLjgr/jg4Pjg4HjgZXjgozjgZ/lvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHJpZ2h0IGFmdGVyIHRoZSBwYWdlIGlzIHNob3duLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOihqOekuuOBleOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgcmlnaHQgYWZ0ZXIgdGhlIHBhZ2UgaXMgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgZGVzdHJveVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgcmlnaHQgYmVmb3JlIHRoZSBwYWdlIGlzIGRlc3Ryb3llZC5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjgYznoLTmo4TjgZXjgozjgovliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBtb2RpZmllciBuYW1lIHRvIHNwZWNpZnkgY3VzdG9tIHN0eWxlcy5bL2VuXVxuICAgKiAgIFtqYV3jgrnjgr/jgqTjg6vlrprnvqnjgpLjgqvjgrnjgr/jg57jgqTjgrrjgZnjgovjgZ/jgoHjga7lkI3liY3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBvbi1pbmZpbml0ZS1zY3JvbGxcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVBhdGggb2YgdGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIG9uIGluZmluaXRlIHNjcm9sbGluZy4gRXhhbXBsZTogYGFwcC5sb2FkRGF0YWAuIFRoZSBmdW5jdGlvbiByZWNlaXZlcyBhIGRvbmUgY2FsbGJhY2sgdGhhdCBtdXN0IGJlIGNhbGxlZCB3aGVuIGl0J3MgZmluaXNoZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3BhZ2UnKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG5cbiAgICAgIHRoaXMuX2lzU2hvd24gPSBmYWxzZTtcbiAgICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50ID0gdGhpcy5fZ2V0Q29udGVudEVsZW1lbnQoKTtcbiAgICAgIHRoaXMuX2lzTXV0ZWQgPSB0aGlzLmhhc0F0dHJpYnV0ZSgnX211dGVkJyk7XG4gICAgICB0aGlzLl9za2lwSW5pdCA9IHRoaXMuaGFzQXR0cmlidXRlKCdfc2tpcGluaXQnKTtcbiAgICAgIHRoaXMucHVzaGVkT3B0aW9ucyA9IHt9O1xuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmICghdGhpcy5faXNNdXRlZCkge1xuICAgICAgICBpZiAodGhpcy5fc2tpcEluaXQpIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSgnX3NraXBpbml0Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnaW5pdCcpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIXV0aWwuaGFzQW55Q29tcG9uZW50QXNQYXJlbnQodGhpcykpIHtcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3RyeVRvRmlsbFN0YXR1c0JhcigpO1xuXG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ29uLWluZmluaXRlLXNjcm9sbCcpKSB7XG4gICAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdvbi1pbmZpbml0ZS1zY3JvbGwnLCBudWxsLCB0aGlzLmdldEF0dHJpYnV0ZSgnb24taW5maW5pdGUtc2Nyb2xsJykpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlQmFja0J1dHRvbihzaG93KSB7XG4gICAgaWYgKHRoaXMuYmFja0J1dHRvbikge1xuICAgICAgc2hvdyA/IHRoaXMuYmFja0J1dHRvbi5zaG93KCkgOiB0aGlzLmJhY2tCdXR0b24uaGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIHNldCBuYW1lKHN0cikge1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCduYW1lJywgc3RyKTtcbiAgfVxuXG4gIGdldCBuYW1lKCkge1xuICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnbmFtZScpO1xuICB9XG5cbiAgZ2V0IGJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWJhY2stYnV0dG9uJyk7XG4gIH1cblxuICBfdHJ5VG9GaWxsU3RhdHVzQmFyKCl7XG4gICAgaW50ZXJuYWwuYXV0b1N0YXR1c0JhckZpbGwoKCkgPT4ge1xuICAgICAgY29uc3QgZmlsbGVkID0gdXRpbC5maW5kUGFyZW50KHRoaXMsIGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcpKTtcbiAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzdGF0dXMtYmFyLWZpbGwnLCAhZmlsbGVkICYmICh0aGlzLl9jYW5BbmltYXRlVG9vbGJhcigpIHx8ICF0aGlzLl9oYXNBUGFnZUNvbnRyb2xDaGlsZCgpKSk7XG4gICAgfSk7XG4gIH1cblxuICBfaGFzQVBhZ2VDb250cm9sQ2hpbGQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMuX2NvbnRlbnRFbGVtZW50LCBlID0+IGUubm9kZU5hbWUubWF0Y2goL29ucy0oc3BsaXR0ZXJ8c2xpZGluZy1tZW51fG5hdmlnYXRvcnx0YWJiYXIpL2kpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25JbmZpbml0ZVNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1GdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHNjcm9sbGluZyB0byB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLiBUaGUgZnVuY3Rpb24gcmVjZWl2ZXMgYSBkb25lIGNhbGxiYWNrIGFzIGFuIGFyZ3VtZW50IHRoYXQgbXVzdCBiZSBjYWxsZWQgd2hlbiBpdCdzIGZpbmlzaGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG4gIHNldCBvbkluZmluaXRlU2Nyb2xsKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICB0aGlzLl9vbkluZmluaXRlU2Nyb2xsID0gbnVsbDtcbiAgICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbkluZmluaXRlU2Nyb2xsIG11c3QgYmUgYSBmdW5jdGlvbiBvciBudWxsJyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5fb25JbmZpbml0ZVNjcm9sbCkge1xuICAgICAgdGhpcy5faW5maW5pdGVTY3JvbGxMaW1pdCA9IDAuOTtcbiAgICAgIHRoaXMuX2JvdW5kT25TY3JvbGwgPSB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fY29udGVudEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPblNjcm9sbCk7XG4gICAgfVxuICAgIHRoaXMuX29uSW5maW5pdGVTY3JvbGwgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBvbkluZmluaXRlU2Nyb2xsKCkge1xuICAgIHJldHVybiB0aGlzLl9vbkluZmluaXRlU2Nyb2xsO1xuICB9XG5cbiAgX29uU2Nyb2xsKCkge1xuICAgIGNvbnN0IGMgPSB0aGlzLl9jb250ZW50RWxlbWVudCxcbiAgICAgIG92ZXJMaW1pdCA9IChjLnNjcm9sbFRvcCArIGMuY2xpZW50SGVpZ2h0KSAvIGMuc2Nyb2xsSGVpZ2h0ID49IHRoaXMuX2luZmluaXRlU2Nyb2xsTGltaXQ7XG5cbiAgICBpZiAodGhpcy5fb25JbmZpbml0ZVNjcm9sbCAmJiAhdGhpcy5fbG9hZGluZ0NvbnRlbnQgJiYgb3ZlckxpbWl0KSB7XG4gICAgICB0aGlzLl9sb2FkaW5nQ29udGVudCA9IHRydWU7XG4gICAgICB0aGlzLl9vbkluZmluaXRlU2Nyb2xsKCgpID0+IHRoaXMuX2xvYWRpbmdDb250ZW50ID0gZmFsc2UpO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9XG4gICAqL1xuICBfZ2V0Q29udGVudEVsZW1lbnQoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wYWdlX19jb250ZW50Jyk7XG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgdGhyb3cgRXJyb3IoJ2ZhaWwgdG8gZ2V0IFwiLnBhZ2VfX2NvbnRlbnRcIiBlbGVtZW50LicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBfY2FuQW5pbWF0ZVRvb2xiYXIoKSB7XG4gICAgaWYgKHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuICEhdXRpbC5maW5kQ2hpbGQodGhpcy5fY29udGVudEVsZW1lbnQsIGVsID0+IHtcbiAgICAgIHJldHVybiB1dGlsLm1hdGNoKGVsLCAnb25zLXRvb2xiYXInKSAmJiAhZWwuaGFzQXR0cmlidXRlKCdpbmxpbmUnKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRCYWNrZ3JvdW5kRWxlbWVudCgpIHtcbiAgICBjb25zdCByZXN1bHQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2JhY2tncm91bmQnKTtcbiAgICBpZiAocmVzdWx0KSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICB0aHJvdyBFcnJvcignZmFpbCB0byBnZXQgXCIucGFnZV9fYmFja2dyb3VuZFwiIGVsZW1lbnQuJyk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9XG4gICAqL1xuICBfZ2V0Qm90dG9tVG9vbGJhckVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtYm90dG9tLXRvb2xiYXInKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXRvb2xiYXInKSB8fCBudWxsVG9vbGJhckVsZW1lbnQ7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdfbXV0ZWQnLCAnX3NraXBpbml0JywgJ29uLWluZmluaXRlLXNjcm9sbCddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgcmV0dXJuIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ19tdXRlZCcpIHtcbiAgICAgIHRoaXMuX2lzTXV0ZWQgPSB0aGlzLmhhc0F0dHJpYnV0ZSgnX211dGVkJyk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAnX3NraXBpbml0Jykge1xuICAgICAgdGhpcy5fc2tpcEluaXQgPSB0aGlzLmhhc0F0dHJpYnV0ZSgnX3NraXBpbml0Jyk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAnb24taW5maW5pdGUtc2Nyb2xsJykge1xuICAgICAgaWYgKGN1cnJlbnQgPT09IG51bGwpIHtcbiAgICAgICAgdGhpcy5vbkluZmluaXRlU2Nyb2xsID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub25JbmZpbml0ZVNjcm9sbCA9IChkb25lKSA9PiB7XG4gICAgICAgICAgY29uc3QgZiA9IHV0aWwuZmluZEZyb21QYXRoKGN1cnJlbnQpO1xuICAgICAgICAgIHRoaXMub25JbmZpbml0ZVNjcm9sbCA9IGY7XG4gICAgICAgICAgZihkb25lKTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGlmICh1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmNvbnRlbnQnKSkge1xuICAgICAgdXRpbC5maW5kQ2hpbGQodGhpcywgJy5jb250ZW50JykuY2xhc3NMaXN0LmFkZCgncGFnZV9fY29udGVudCcpO1xuICAgIH1cblxuICAgIGlmICh1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmJhY2tncm91bmQnKSkge1xuICAgICAgdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrZ3JvdW5kJykuY2xhc3NMaXN0LmFkZCgncGFnZV9fYmFja2dyb3VuZCcpO1xuICAgIH1cblxuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wYWdlX19jb250ZW50JykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSB1dGlsLmNyZWF0ZSgnLnBhZ2VfX2NvbnRlbnQnKTtcblxuICAgICAgdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZE5vZGVzKS5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSB8fCB0aGlzLl9lbGVtZW50U2hvdWxkQmVNb3ZlZChub2RlKSkge1xuICAgICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBwcmV2Tm9kZSA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcucGFnZV9fYmFja2dyb3VuZCcpIHx8IHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtdG9vbGJhcicpO1xuXG4gICAgICB0aGlzLmluc2VydEJlZm9yZShjb250ZW50LCBwcmV2Tm9kZSAmJiBwcmV2Tm9kZS5uZXh0U2libGluZyk7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2JhY2tncm91bmQnKSkge1xuICAgICAgY29uc3QgYmFja2dyb3VuZCA9IHV0aWwuY3JlYXRlKCcucGFnZV9fYmFja2dyb3VuZCcpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUoYmFja2dyb3VuZCwgdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wYWdlX19jb250ZW50JykpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9lbGVtZW50U2hvdWxkQmVNb3ZlZChlbCkge1xuICAgIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ3BhZ2VfX2JhY2tncm91bmQnKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0YWdOYW1lID0gZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh0YWdOYW1lID09PSAnb25zLWZhYicpIHtcbiAgICAgIHJldHVybiAhZWwuaGFzQXR0cmlidXRlKCdwb3NpdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBmaXhlZEVsZW1lbnRzID0gWydvbnMtdG9vbGJhcicsICdvbnMtYm90dG9tLXRvb2xiYXInLCAnb25zLW1vZGFsJywgJ29ucy1zcGVlZC1kaWFsJ107XG4gICAgcmV0dXJuIGVsLmhhc0F0dHJpYnV0ZSgnaW5saW5lJykgfHwgZml4ZWRFbGVtZW50cy5pbmRleE9mKHRhZ05hbWUpID09PSAtMTtcbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICghdGhpcy5faXNTaG93biAmJiB1dGlsLmlzQXR0YWNoZWQodGhpcykpIHtcbiAgICAgIHRoaXMuX2lzU2hvd24gPSB0cnVlO1xuXG4gICAgICBpZiAoIXRoaXMuX2lzTXV0ZWQpIHtcbiAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdzaG93Jyk7XG4gICAgICB9XG5cbiAgICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMuX2NvbnRlbnRFbGVtZW50LCAnX3Nob3cnKTtcbiAgICB9XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICBpZiAodGhpcy5faXNTaG93bikge1xuICAgICAgdGhpcy5faXNTaG93biA9IGZhbHNlO1xuXG4gICAgICBpZiAoIXRoaXMuX2lzTXV0ZWQpIHtcbiAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdoaWRlJyk7XG4gICAgICB9XG5cbiAgICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMuX2NvbnRlbnRFbGVtZW50LCAnX2hpZGUnKTtcbiAgICB9XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB0aGlzLl9oaWRlKCk7XG5cbiAgICBpZiAoIXRoaXMuX2lzTXV0ZWQpIHtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnZGVzdHJveScpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9uRGV2aWNlQmFja0J1dHRvbikge1xuICAgICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24uZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMuX2NvbnRlbnRFbGVtZW50LCAnX2Rlc3Ryb3knKTtcblxuICAgIGlmICh0aGlzLnVubG9hZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLnVubG9hZCgpO1xuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlKCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRhdGFcbiAgICogQHR5cGUgeyp9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Vc2VyJ3MgY3VzdG9tIGRhdGEgcGFzc2VkIHRvIGBwdXNoUGFnZSgpYC1saWtlIG1ldGhvZHMuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXBhZ2UnLCBQYWdlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuXG5leHBvcnQgY2xhc3MgUG9wb3ZlckFuaW1hdG9yIHtcblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMudGltaW5nXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmR1cmF0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmRlbGF5XG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuNCwgMSknLFxuICAgICAgZHVyYXRpb246IDAuMixcbiAgICAgIGRlbGF5OiAwXG4gICAgfSwgb3B0aW9ucyk7XG4gIH1cblxuICBzaG93KHBvcG92ZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGhpZGUocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgX2FuaW1hdGUoZWxlbWVudCwge2Zyb20sIHRvLCBvcHRpb25zLCBjYWxsYmFjaywgcmVzdG9yZSA9IGZhbHNlLCBhbmltYXRpb259KSB7XG4gICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHt9LCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKGFuaW1hdGlvbikge1xuICAgICAgZnJvbSA9IGFuaW1hdGlvbi5mcm9tO1xuICAgICAgdG8gPSBhbmltYXRpb24udG87XG4gICAgfVxuXG4gICAgYW5pbWF0aW9uID0gYW5pbWl0KGVsZW1lbnQpO1xuICAgIGlmIChyZXN0b3JlKSB7XG4gICAgICBhbmltYXRpb24gPSBhbmltYXRpb24uc2F2ZVN0eWxlKCk7XG4gICAgfVxuICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZShmcm9tKS53YWl0KG9wdGlvbnMuZGVsYXkpLnF1ZXVlKHtcbiAgICAgIGNzczogdG8sXG4gICAgICBkdXJhdGlvbjogb3B0aW9ucy5kdXJhdGlvbixcbiAgICAgIHRpbWluZzogb3B0aW9ucy50aW1pbmdcbiAgICB9KTtcbiAgICBpZiAocmVzdG9yZSkge1xuICAgICAgYW5pbWF0aW9uID0gYW5pbWF0aW9uLnJlc3RvcmVTdHlsZSgpO1xuICAgIH1cbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZSgoZG9uZSkgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFuaW1hdGlvbjtcbiAgfVxuXG4gIF9hbmltYXRlQWxsKGVsZW1lbnQsIGFuaW1hdGlvbnMpIHtcbiAgICBPYmplY3Qua2V5cyhhbmltYXRpb25zKS5mb3JFYWNoKGtleSA9PiB0aGlzLl9hbmltYXRlKGVsZW1lbnRba2V5XSwgYW5pbWF0aW9uc1trZXldKS5wbGF5KCkpO1xuICB9XG5cbn1cblxuY29uc3QgZmFkZSA9IHtcbiAgb3V0OiB7XG4gICAgZnJvbToge29wYWNpdHk6IDEuMH0sXG4gICAgdG86IHtvcGFjaXR5OiAwfVxuICB9LFxuICBpbjoge1xuICAgIGZyb206IHtvcGFjaXR5OiAwfSxcbiAgICB0bzoge29wYWNpdHk6IDEuMH1cbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIE1ERmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIFBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUuaW4sIHJlc3RvcmU6IHRydWUsIGNhbGxiYWNrfVxuICAgIH0pO1xuICB9XG5cbiAgaGlkZShwb3BvdmVyLCBjYWxsYmFjaykge1xuICAgIHRoaXMuX2FuaW1hdGVBbGwocG9wb3Zlciwge1xuICAgICAgX21hc2s6IGZhZGUub3V0LFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUub3V0LCByZXN0b3JlOiB0cnVlLCBjYWxsYmFja31cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSU9TRmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIE1ERmFkZVBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHtcbiAgICAgICAgZnJvbToge1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3NjYWxlM2QoMS4zLCAxLjMsIDEuMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSxcbiAgICAgICAgdG86IHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZTNkKDEuMCwgMS4wLCAgMS4wKScsXG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3RvcmU6IHRydWUsXG4gICAgICAgIGNhbGxiYWNrXG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IHtQb3BvdmVyQW5pbWF0b3IsIElPU0ZhZGVQb3BvdmVyQW5pbWF0b3IsIE1ERmFkZVBvcG92ZXJBbmltYXRvcn0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi8uLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlciBmcm9tICcuLi8uLi9vbnMvZGV2aWNlLWJhY2stYnV0dG9uLWRpc3BhdGNoZXInO1xuaW1wb3J0IERvb3JMb2NrIGZyb20gJy4uLy4uL29ucy9kb29ybG9jayc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnBvcG92ZXInOiAncG9wb3Zlci0tKicsXG4gICcucG9wb3Zlci1tYXNrJzogJ3BvcG92ZXItbWFzay0tKicsXG4gICcucG9wb3Zlcl9fY29udGFpbmVyJzogJ3BvcG92ZXJfX2NvbnRhaW5lci0tKicsXG4gICcucG9wb3Zlcl9fY29udGVudCc6ICdwb3BvdmVyX19jb250ZW50LS0qJyxcbiAgJy5wb3BvdmVyX19hcnJvdyc6ICdwb3BvdmVyX19hcnJvdy0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBNREZhZGVQb3BvdmVyQW5pbWF0b3IgOiBJT1NGYWRlUG9wb3ZlckFuaW1hdG9yLFxuICAnbm9uZSc6IFBvcG92ZXJBbmltYXRvcixcbiAgJ2ZhZGUtaW9zJzogSU9TRmFkZVBvcG92ZXJBbmltYXRvcixcbiAgJ2ZhZGUtbWQnOiBNREZhZGVQb3BvdmVyQW5pbWF0b3Jcbn07XG5cbmNvbnN0IHRlbXBsYXRlU291cmNlID0gdXRpbC5jcmVhdGVGcmFnbWVudChgXG4gIDxkaXYgY2xhc3M9XCJwb3BvdmVyLW1hc2tcIj48L2Rpdj5cbiAgPGRpdiBjbGFzcz1cInBvcG92ZXJfX2NvbnRhaW5lclwiPlxuICAgIDxkaXYgY2xhc3M9XCJwb3BvdmVyX19jb250ZW50XCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInBvcG92ZXJfX2Fycm93XCI+PC9kaXY+XG4gIDwvZGl2PlxuYCk7XG5cbmNvbnN0IHBvc2l0aW9ucyA9IHtcbiAgdXA6ICdib3R0b20nLFxuICBsZWZ0OiAncmlnaHQnLFxuICBkb3duOiAndG9wJyxcbiAgcmlnaHQ6ICdsZWZ0J1xufTtcblxuY29uc3QgZGlyZWN0aW9ucyA9IE9iamVjdC5rZXlzKHBvc2l0aW9ucyk7XG4vKipcbiAqIEBlbGVtZW50IG9ucy1wb3BvdmVyXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICBbZW5dXG4gKiAgICBBIGNvbXBvbmVudCB0aGF0IGRpc3BsYXlzIGEgcG9wb3ZlciBuZXh0IHRvIGFuIGVsZW1lbnQuIFRoZSBwb3BvdmVyIGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgZXh0cmEgaW5mb3JtYXRpb24gYWJvdXQgYSBjb21wb25lbnQgb3IgYSB0b29sdGlwLlxuICpcbiAqICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZVBvcG92ZXIodGVtcGxhdGUpYCB1dGlsaXR5IGZ1bmN0aW9uIGFuZCB0aGUgYDxvbnMtdGVtcGxhdGU+YCB0YWcuXG4gKlxuICogICAgQW5vdGhlciBjb21tb24gd2F5IHRvIHVzZSB0aGUgcG9wb3ZlciBpcyB0byBkaXNwbGF5IGEgbWVudSB3aGVuIGEgYnV0dG9uIG9uIHRoZSBzY3JlZW4gaXMgdGFwcGVkLiBGb3IgTWF0ZXJpYWwgRGVzaWduLCBwb3BvdmVyIGxvb2tzIGV4YWN0bHkgYXMgYSBkcm9wZG93biBtZW51LlxuICogIFsvZW5dXG4gKiAgW2phXeOBguOCi+imgee0oOOCkuWvvuixoeOBqOOBmeOCi+ODneODg+ODl+OCquODvOODkOODvOOCkuihqOekuuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAY29kZXBlbiBaWVlSS29cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wb3BvdmVyXG4gKiBAZ3VpZGUgZGlhbG9nc1xuICogIFtlbl1EaWFsb2cgY29tcG9uZW50c1svZW5dXG4gKiAgW2phXURpYWxvZyBjb21wb25lbnRzWy9qYV1cbiAqIEBndWlkZSB1c2luZy1tb2RpZmllciBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLWJ1dHRvbiBvbmNsaWNrPVwic2hvd1BvcG92ZXIodGhpcylcIj5cbiAqICAgQ2xpY2sgbWUhXG4gKiA8L29ucy1idXR0b24+XG4gKlxuICogPG9ucy1wb3BvdmVyIGRpcmVjdGlvbj1cImRvd25cIiBpZD1cInBvcG92ZXJcIj5cbiAqICAgPHA+VGhpcyBpcyBhIHBvcG92ZXIhPC9wPlxuICogPC9vbnMtcG9wb3Zlcj5cbiAqXG4gKiA8c2NyaXB0PlxuICogICB2YXIgc2hvd1BvcG92ZXIgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gKiAgICAgdmFyIHBvcG92ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncG9wb3ZlcicpO1xuICogICAgIHBvcG92ZXIuc2hvdyhlbGVtZW50KTtcbiAqICAgfTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb3BvdmVyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IHByZXNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBwb3BvdmVyIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQucG9wb3ZlclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRoaXMgZnVuY3Rpb24gdG8gc3RvcCB0aGUgcG9wb3ZlciBmcm9tIGJlaW5nIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgeODneODg+ODl+OCquODvOODkOODvOOBruihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHBvcG92ZXIgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wb3BvdmVyXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVoaWRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgcG9wb3ZlciBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnBvcG92ZXJcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIHN0b3AgdGhlIHBvcG92ZXIgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5ZG844Gz5Ye644GZ44Go44CB44Od44OD44OX44Kq44O844OQ44O844GM6Zqg44KM44KL5Yem55CG44KS44Kt44Oj44Oz44K744Or44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgcG9wb3ZlciBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844GM6Zqg44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnBvcG92ZXJcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgcG9wb3Zlci5bL2VuXVxuICAgKiAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpcmVjdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1cbiAgICogICAgQSBzcGFjZSBzZXBhcmF0ZWQgbGlzdCBvZiBkaXJlY3Rpb25zLiBJZiBtb3JlIHRoYW4gb25lIGRpcmVjdGlvbiBpcyBzcGVjaWZpZWQsXG4gICAqICAgIGl0IHdpbGwgYmUgY2hvc2VuIGF1dG9tYXRpY2FsbHkuIFZhbGlkIGRpcmVjdGlvbnMgYXJlIGBcInVwXCJgLCBgXCJkb3duXCJgLCBgXCJsZWZ0XCJgIGFuZCBgXCJyaWdodFwiYC5cbiAgICogIFsvZW5dXG4gICAqICBbamFdXG4gICAqICAgIOODneODg+ODl+OCquODvOODkOODvOOCkuihqOekuuOBmeOCi+aWueWQkeOCkuepuueZveWMuuWIh+OCiuOBp+ikh+aVsOaMh+WumuOBp+OBjeOBvuOBmeOAglxuICAgKiAgICDmjIflrprjgafjgY3jgovmlrnlkJHjga/jgIFcInVwXCIsIFwiZG93blwiLCBcImxlZnRcIiwgXCJyaWdodFwi44GuNOOBpOOBp+OBmeOAguepuueZveWMuuWIh+OCiuOBp+ikh+aVsOaMh+WumuOBmeOCi+OBk+OBqOOCguOBp+OBjeOBvuOBmeOAglxuICAgKiAgICDopIfmlbDmjIflrprjgZXjgozjgZ/loLTlkIjjgIHlr77osaHjgajjgZnjgovopoHntKDjgavlkIjjgo/jgZvjgabmjIflrprjgZfjgZ/lgKTjgYvjgonoh6rli5XnmoTjgavpgbjmip7jgZXjgozjgb7jgZnjgIJcbiAgICogIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNhbmNlbGFibGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgcG9wb3ZlciBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+OBqOOAgeODneODg+ODl+OCquODvOODkOODvOOBjOihqOekuuOBleOCjOOBn+aZguOBq+OAgeiDjOaZr+OChOODkOODg+OCr+ODnOOCv+ODs+OCkuOCv+ODg+ODl+OBl+OBn+aZguOBq+OCkuODneODg+ODl+OCquODvOODkOODvOmWieOBmOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNvdmVyLXRhcmdldFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgc2V0IHRoZSBwb3BvdmVyIHdpbGwgY292ZXIgdGhlIHRhcmdldCBvbiB0aGUgc2NyZWVuLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbiBoaWRpbmcgdGhlIHBvcG92ZXIuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCwgYFwiZGVmYXVsdFwiYCwgYFwiZmFkZS1pb3NcImAgb3IgYFwiZmFkZS1tZFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb24tb3B0aW9uc1xuICAgKiBAdHlwZSB7RXhwcmVzc2lvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIHRpbWluZyBhbmQgZGVsYXkgd2l0aCBhbiBvYmplY3QgbGl0ZXJhbC4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbWFzay1jb2xvclxuICAgKiBAdHlwZSB7Q29sb3J9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Db2xvciBvZiB0aGUgYmFja2dyb3VuZCBtYXNrLiBEZWZhdWx0IGlzIGBcInJnYmEoMCwgMCwgMCwgMC4yKVwiYC5bL2VuXVxuICAgKiAgIFtqYV3og4zmma/jga7jg57jgrnjgq/jga7oibLjgpLmjIflrprjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga9cInJnYmEoMCwgMCwgMCwgMC4yKVwi44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IF9tYXNrKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXItbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9wb3BvdmVyKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXJfX2NvbnRhaW5lcicpO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9wb3BvdmVyLCAnLnBvcG92ZXJfX2NvbnRlbnQnKTtcbiAgfVxuXG4gIGdldCBfYXJyb3coKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMuX3BvcG92ZXIsICcucG9wb3Zlcl9fYXJyb3cnKTtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICAgIHRoaXMuX2luaXRBbmltYXRvckZhY3RvcnkoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG4gICAgdGhpcy5fYm91bmRPbkNoYW5nZSA9IHRoaXMuX29uQ2hhbmdlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRDYW5jZWwgPSB0aGlzLl9jYW5jZWwuYmluZCh0aGlzKTtcbiAgfVxuXG4gIF9pbml0QW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogUG9wb3ZlckFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ1BvcG92ZXJBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJykgfHwgJ2RlZmF1bHQnXG4gICAgfSk7XG4gICAgdGhpcy5fYW5pbWF0b3IgPSAob3B0aW9ucykgPT4gZmFjdG9yeS5uZXdBbmltYXRvcihvcHRpb25zKTtcbiAgfVxuXG4gIF9wb3NpdGlvblBvcG92ZXIodGFyZ2V0KSB7XG4gICAgY29uc3Qge19yYWRpdXM6IHJhZGl1cywgX2NvbnRlbnQ6IGVsLCBfbWFyZ2luOiBtYXJnaW59ID0gdGhpcztcbiAgICBjb25zdCBwb3MgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgaXNNRCA9IHV0aWwuaGFzTW9kaWZpZXIodGhpcywgJ21hdGVyaWFsJyk7XG4gICAgY29uc3QgY292ZXIgPSBpc01EICYmIHRoaXMuaGFzQXR0cmlidXRlKCdjb3Zlci10YXJnZXQnKTtcblxuICAgIGNvbnN0IGRpc3RhbmNlID0ge1xuICAgICAgdG9wOiBwb3MudG9wIC0gbWFyZ2luLFxuICAgICAgbGVmdDogcG9zLmxlZnQgLSBtYXJnaW4sXG4gICAgICByaWdodDogd2luZG93LmlubmVyV2lkdGggLSBwb3MucmlnaHQgLSBtYXJnaW4sXG4gICAgICBib3R0b206IHdpbmRvdy5pbm5lckhlaWdodCAtIHBvcy5ib3R0b20gLSBtYXJnaW5cbiAgICB9O1xuXG4gICAgY29uc3Qge3ZlcnRpY2FsLCBwcmltYXJ5LCBzZWNvbmRhcnl9ID0gdGhpcy5fY2FsY3VsYXRlRGlyZWN0aW9ucyhkaXN0YW5jZSk7XG4gICAgdGhpcy5fcG9wb3Zlci5jbGFzc0xpc3QuYWRkKCdwb3BvdmVyLS0nICsgcHJpbWFyeSk7XG5cbiAgICBjb25zdCBvZmZzZXQgPSBjb3ZlciA/IDAgOiAodmVydGljYWwgPyBwb3MuaGVpZ2h0IDogcG9zLndpZHRoKSArIChpc01EID8gMCA6IDE0KTtcbiAgICB0aGlzLnN0eWxlW3ByaW1hcnldID0gTWF0aC5tYXgoMCwgZGlzdGFuY2VbcHJpbWFyeV0gKyBvZmZzZXQpICsgbWFyZ2luICsgJ3B4JztcbiAgICBlbC5zdHlsZVtwcmltYXJ5XSA9IDA7XG5cbiAgICBjb25zdCBsID0gdmVydGljYWwgPyAnd2lkdGgnIDogJ2hlaWdodCc7XG4gICAgY29uc3Qgc2l6ZXMgPSAoc3R5bGUgPT4gKHtcbiAgICAgIHdpZHRoOiBwYXJzZUludChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCd3aWR0aCcpKSxcbiAgICAgIGhlaWdodDogcGFyc2VJbnQoc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnaGVpZ2h0JykpXG4gICAgfSkpKHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKSk7XG5cbiAgICBlbC5zdHlsZVtzZWNvbmRhcnldID0gTWF0aC5tYXgoMCwgZGlzdGFuY2Vbc2Vjb25kYXJ5XSAtIChzaXplc1tsXSAtIHBvc1tsXSkgLyAyKSArICdweCc7XG4gICAgdGhpcy5fYXJyb3cuc3R5bGVbc2Vjb25kYXJ5XSA9IE1hdGgubWF4KHJhZGl1cywgZGlzdGFuY2Vbc2Vjb25kYXJ5XSArIHBvc1tsXSAvIDIpICsgJ3B4JztcblxuICAgIHRoaXMuX3NldFRyYW5zZm9ybU9yaWdpbihkaXN0YW5jZSwgc2l6ZXMsIHBvcywgcHJpbWFyeSk7XG5cbiAgICAvLyBQcmV2ZW50IGFuaW1pdCBmcm9tIHJlc3RvcmluZyB0aGUgc3R5bGUuXG4gICAgZWwucmVtb3ZlQXR0cmlidXRlKCdkYXRhLWFuaW1pdC1vcmlnLXN0eWxlJyk7XG4gIH1cblxuICBfc2V0VHJhbnNmb3JtT3JpZ2luKGRpc3RhbmNlLCBzaXplcywgcG9zLCBwcmltYXJ5KSB7XG4gICAgY29uc3QgY2FsYyA9IChhLCBvLCBsKSA9PiBwcmltYXJ5ID09PSBhID8gc2l6ZXNbbF0gLyAyIDogZGlzdGFuY2VbYV0gKyAocHJpbWFyeSA9PT0gbyA/IC1zaXplc1tsXSA6IHNpemVzW2xdIC0gcG9zW2xdKSAvIDI7XG4gICAgY29uc3QgW3gsIHldID0gW2NhbGMoJ2xlZnQnLCAncmlnaHQnLCAnd2lkdGgnKSArICdweCcsIGNhbGMoJ3RvcCcsICdib3R0b20nLCAnaGVpZ2h0JykgKyAncHgnXTtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLl9wb3BvdmVyLnN0eWxlLCB7XG4gICAgICB0cmFuc2Zvcm1PcmlnaW46IHggKyAnICcgKyB5LFxuICAgICAgd2Via2l0VHJhbnNmb3JtT3JpZ2luWDogeCxcbiAgICAgIHdlYmtpdFRyYW5zZm9ybU9yaWdpblk6IHlcbiAgICB9KTtcbiAgfVxuXG4gIF9jYWxjdWxhdGVEaXJlY3Rpb25zKGRpc3RhbmNlKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9ICh0aGlzLmdldEF0dHJpYnV0ZSgnZGlyZWN0aW9uJykgfHwgJ3VwIGRvd24gbGVmdCByaWdodCcpLnNwbGl0KC9cXHMrLykubWFwKGUgPT4gcG9zaXRpb25zW2VdKTtcbiAgICBjb25zdCBwcmltYXJ5ID0gb3B0aW9ucy5zb3J0KChhLCBiKSA9PiBkaXN0YW5jZVthXSAtIGRpc3RhbmNlW2JdKVswXTtcbiAgICBjb25zdCB2ZXJ0aWNhbCA9IFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2YocHJpbWFyeSkgIT09IC0xO1xuICAgIGxldCBzZWNvbmRhcnk7XG5cbiAgICBpZiAodmVydGljYWwpIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLmxlZnQgPCBkaXN0YW5jZS5yaWdodCA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLnRvcCA8IGRpc3RhbmNlLmJvdHRvbSA/ICd0b3AnIDogJ2JvdHRvbSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt2ZXJ0aWNhbCwgcHJpbWFyeSwgc2Vjb25kYXJ5fTtcbiAgfVxuXG4gIF9jbGVhclN0eWxlcygpIHtcbiAgICBbJ3RvcCcsICdib3R0b20nLCAnbGVmdCcsICdyaWdodCddLmZvckVhY2goZSA9PiB7XG4gICAgICB0aGlzLl9hcnJvdy5zdHlsZVtlXSA9IHRoaXMuX2NvbnRlbnQuc3R5bGVbZV0gPSB0aGlzLnN0eWxlW2VdID0gJyc7XG4gICAgICB0aGlzLl9wb3BvdmVyLmNsYXNzTGlzdC5yZW1vdmUoYHBvcG92ZXItLSR7ZX1gKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9vbkNoYW5nZSgpIHtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX2N1cnJlbnRUYXJnZXQpIHtcbiAgICAgICAgdGhpcy5fcG9zaXRpb25Qb3BvdmVyKHRoaXMuX2N1cnJlbnRUYXJnZXQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICBpZiAodGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ3BvcG92ZXInKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgncG9wb3ZlcicpO1xuXG4gICAgY29uc3QgaGFzRGVmYXVsdENvbnRhaW5lciA9IHRoaXMuX3BvcG92ZXIgJiYgdGhpcy5fY29udGVudDtcblxuICAgIGlmIChoYXNEZWZhdWx0Q29udGFpbmVyKSB7XG5cbiAgICAgIGlmICghdGhpcy5fbWFzaykge1xuICAgICAgICBjb25zdCBtYXNrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIG1hc2suY2xhc3NMaXN0LmFkZCgncG9wb3Zlci1tYXNrJyk7XG4gICAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKG1hc2ssIHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5fYXJyb3cpIHtcbiAgICAgICAgY29uc3QgYXJyb3cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgYXJyb3cuY2xhc3NMaXN0LmFkZCgncG9wb3Zlcl9fYXJyb3cnKTtcbiAgICAgICAgdGhpcy5fcG9wb3Zlci5hcHBlbmRDaGlsZChhcnJvdyk7XG4gICAgICB9XG5cbiAgICB9IGVsc2Uge1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IHRlbXBsYXRlU291cmNlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSB0ZW1wbGF0ZS5xdWVyeVNlbGVjdG9yKCcucG9wb3Zlcl9fY29udGVudCcpO1xuXG4gICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZCh0ZW1wbGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdzdHlsZScpKSB7XG4gICAgICB0aGlzLl9wb3BvdmVyLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCB0aGlzLmdldEF0dHJpYnV0ZSgnc3R5bGUnKSk7XG4gICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSgnc3R5bGUnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ21hc2stY29sb3InKSkge1xuICAgICAgdGhpcy5fbWFzay5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLmdldEF0dHJpYnV0ZSgnbWFzay1jb2xvcicpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9wcmVwYXJlQW5pbWF0aW9uT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0aW9uICYmICEob3B0aW9ucy5hbmltYXRpb24gaW4gX2FuaW1hdG9yRGljdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQW5pbWF0b3IgJHtvcHRpb25zLmFuaW1hdGlvbn0gaXMgbm90IHJlZ2lzdGVyZWQuYCk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zID0gdXRpbC5leHRlbmQoXG4gICAgICBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSxcbiAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fVxuICAgICk7XG4gIH1cblxuICBfZXhlY3V0ZUFjdGlvbihhY3Rpb25zLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2s7XG4gICAgY29uc3Qge2FjdGlvbiwgYmVmb3JlLCBhZnRlcn0gPSBhY3Rpb25zO1xuXG4gICAgdGhpcy5fcHJlcGFyZUFuaW1hdGlvbk9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICBsZXQgY2FuY2VsZWQgPSBmYWxzZTtcbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgYHByZSR7YWN0aW9ufWAsIHsgLy8gc3luY2hyb25vdXNcbiAgICAgIHBvcG92ZXI6IHRoaXMsXG4gICAgICBjYW5jZWw6ICgpID0+IGNhbmNlbGVkID0gdHJ1ZVxuICAgIH0pO1xuXG4gICAgaWYgKGNhbmNlbGVkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoYENhbmNlbGVkIGluIHByZSR7YWN0aW9ufSBldmVudC5gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLl9kb29yTG9jay53YWl0VW5sb2NrKCgpID0+IHtcbiAgICAgICAgY29uc3QgdW5sb2NrID0gdGhpcy5fZG9vckxvY2subG9jaygpO1xuXG4gICAgICAgIGJlZm9yZSAmJiBiZWZvcmUoKTtcblxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2FuaW1hdG9yKG9wdGlvbnMpW2FjdGlvbl0odGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgYWZ0ZXIgJiYgYWZ0ZXIoKTtcblxuICAgICAgICAgICAgdW5sb2NrKCk7XG5cbiAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCBgcG9zdCR7YWN0aW9ufWAsIHtwb3BvdmVyOiB0aGlzfSk7XG5cbiAgICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3codGFyZ2V0LCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7U3RyaW5nfEV2ZW50fEhUTUxFbGVtZW50fSB0YXJnZXRcbiAgICogICBbZW5dVGFyZ2V0IGVsZW1lbnQuIENhbiBiZSBlaXRoZXIgYSBDU1Mgc2VsZWN0b3IsIGFuIGV2ZW50IG9iamVjdCBvciBhIERPTSBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBruOCv+ODvOOCsuODg+ODiOOBqOOBquOCi+imgee0oOOCkuaMh+WumuOBl+OBvuOBmeOAgkNTU+OCu+ODrOOCr+OCv+OBi2V2ZW5044Kq44OW44K444Kn44Kv44OI44GLRE9N6KaB57Sg44Gu44GE44Ga44KM44GL44KS5rih44Gb44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiAgVXNlIG9uZSBvZiBgXCJmYWRlLWlvc1wiYCwgYFwiZmFkZS1tZFwiYCwgYFwibm9uZVwiYCBhbmQgYFwiZGVmYXVsdFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcImZhZGUtaW9zXCIsIFwiZmFkZS1tZFwiLCBcIm5vbmVcIiwgXCJkZWZhdWx0XCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFmdGVyIHRoZSBwb3BvdmVyIGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcGVuIHRoZSBwb3BvdmVyIGFuZCBwb2ludCBpdCBhdCBhIHRhcmdldC4gVGhlIHRhcmdldCBjYW4gYmUgZWl0aGVyIGFuIGV2ZW50LCBhIENTUyBzZWxlY3RvciBvciBhIERPTSBlbGVtZW50Li5bL2VuXVxuICAgKiAgIFtqYV3lr77osaHjgajjgZnjgovopoHntKDjgavjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZfjgb7jgZnjgIJ0YXJnZXTlvJXmlbDjgavjga/jgIEkZXZlbnTjgqrjg5bjgrjjgqfjgq/jg4jjgoRET03jgqjjg6zjg6Hjg7Pjg4jjgoRDU1Pjgrvjg6zjgq/jgr/jgpLmuKHjgZnjgZPjgajjgYzlh7rmnaXjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgZGlzcGxheWVkIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2hvdyh0YXJnZXQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICh0eXBlb2YgdGFyZ2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0YXJnZXQpO1xuICAgIH0gZWxzZSBpZiAodGFyZ2V0IGluc3RhbmNlb2YgRXZlbnQpIHtcbiAgICAgIHRhcmdldCA9IHRhcmdldC50YXJnZXQ7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0YXJnZXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgdGFyZ2V0IGFyZ3VtZW50IG11c3QgYmUgZGVmaW5lZCBmb3IgdGhlIHBvcG92ZXIuJyk7XG4gICAgfVxuXG4gICAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0YXJnZXQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fZXhlY3V0ZUFjdGlvbih7XG4gICAgICBhY3Rpb246ICdzaG93JyxcbiAgICAgIGJlZm9yZTogKCkgPT4ge1xuICAgICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgICB0aGlzLl9jdXJyZW50VGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICB0aGlzLl9wb3NpdGlvblBvcG92ZXIodGFyZ2V0KTtcbiAgICAgIH1cbiAgICB9LCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGhpZGVcbiAgICogQHNpZ25hdHVyZSBoaWRlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiAgVXNlIG9uZSBvZiBgXCJmYWRlLWlvc1wiYCwgYFwiZmFkZS1tZFwiYCwgYFwibm9uZVwiYCBhbmQgYFwiZGVmYXVsdFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcImZhZGUtaW9zXCIsIFwiZmFkZS1tZFwiLCBcIm5vbmVcIiwgXCJkZWZhdWx0XCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb25zIGlzIGNhbGxlZCBhZnRlciB0aGUgcG9wb3ZlciBoYXMgYmVlbiBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844GM6Zqg44KM44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNsb3NlIHRoZSBwb3BvdmVyLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBoaWRlKG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9leGVjdXRlQWN0aW9uKHtcbiAgICAgIGFjdGlvbjogJ2hpZGUnLFxuICAgICAgYWZ0ZXI6ICgpID0+IHtcbiAgICAgICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLl9jbGVhclN0eWxlcygpO1xuICAgICAgfVxuICAgIH0sIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzKS5nZXRQcm9wZXJ0eVZhbHVlKCdkaXNwbGF5JykgIT09ICdub25lJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2FuY2VsYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgQSBib29sZWFuIHZhbHVlIHRoYXQgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIHBvcG92ZXIgaXMgY2FuY2VsYWJsZSBvciBub3QuXG4gICAqXG4gICAqICAgICBXaGVuIHRoZSBwb3BvdmVyIGlzIGNhbmNlbGFibGUgaXQgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldCBjYW5jZWxhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdjYW5jZWxhYmxlJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGNhbmNlbGFibGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdjYW5jZWxhYmxlJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cbiAgZ2V0IG9uRGV2aWNlQmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fYmFja0J1dHRvbkhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25EZXZpY2VCYWNrQnV0dG9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5jcmVhdGVIYW5kbGVyKHRoaXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIF9yZXNldEJhY2tCdXR0b25IYW5kbGVyKCkgeyAvLyBkbyB3ZSBuZWVkIHRoaXMgdHdpY2U/XG4gICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24gPSBlID0+IHRoaXMuY2FuY2VsYWJsZSA/IHRoaXMuX2NhbmNlbCgpIDogZS5jYWxsUGFyZW50SGFuZGxlcigpO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fcmVzZXRCYWNrQnV0dG9uSGFuZGxlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX21hcmdpbiA9IHRoaXMuX21hcmdpbiB8fCBwYXJzZUludCh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzKS5nZXRQcm9wZXJ0eVZhbHVlKCd0b3AnKSk7XG5cbiAgICAgIC8vIEZpeCBmb3IgaWZyYW1lc1xuICAgICAgaWYgKCF0aGlzLl9tYXJnaW4pIHtcbiAgICAgICAgdGhpcy5fbWFyZ2luID0gNjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fcmFkaXVzID0gcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcy5fY29udGVudCkuZ2V0UHJvcGVydHlWYWx1ZSgnYm9yZGVyLXRvcC1sZWZ0LXJhZGl1cycpKTtcblxuICAgICAgdGhpcy5fbWFzay5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kQ2FuY2VsLCBmYWxzZSk7XG5cbiAgICAgIHRoaXMuX3Jlc2V0QmFja0J1dHRvbkhhbmRsZXIoKTtcblxuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UsIGZhbHNlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9tYXNrLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRDYW5jZWwsIGZhbHNlKTtcblxuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBudWxsO1xuXG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgZmFsc2UpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnZGlyZWN0aW9uJywgJ2FuaW1hdGlvbiddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgcmV0dXJuIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgIH1cbiAgICBpZiAobmFtZSA9PT0gJ2RpcmVjdGlvbicpIHtcbiAgICAgIHJldHVybiB0aGlzLl9ib3VuZE9uQ2hhbmdlKCk7XG4gICAgfVxuICAgIGlmIChuYW1lID09PSAnYW5pbWF0aW9uJykge1xuICAgICAgdGhpcy5faW5pdEFuaW1hdG9yRmFjdG9yeSgpO1xuICAgIH1cbiAgfVxuXG5cbiAgX2NhbmNlbCgpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxhYmxlKSB7XG4gICAgICB0aGlzLmhpZGUoe1xuICAgICAgICBjYWxsYmFjazogKCkgPT4ge1xuICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnZGlhbG9nLWNhbmNlbCcpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtQb3BvdmVyQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFBvcG92ZXJBbmltYXRvcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJBbmltYXRvclwiIHBhcmFtIG11c3QgaW5oZXJpdCBQb3BvdmVyQW5pbWF0b3InKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBQb3BvdmVyQW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIFBvcG92ZXJBbmltYXRvcjtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1wb3BvdmVyJywgUG9wb3ZlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnByb2dyZXNzLWJhcic6ICdwcm9ncmVzcy1iYXItLSonLFxuICAnLnByb2dyZXNzLWJhcl9fcHJpbWFyeSc6ICdwcm9ncmVzcy1iYXJfX3ByaW1hcnktLSonLFxuICAnLnByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5JzogJ3Byb2dyZXNzLWJhcl9fc2Vjb25kYXJ5LS0qJ1xufTtcblxuY29uc3QgdGVtcGxhdGUgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtYmFyXCI+XG4gICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5XCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhcl9fcHJpbWFyeVwiPjwvZGl2PlxuICA8L2Rpdj5cbmApO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wcm9ncmVzcy1iYXJcbiAqIEBjYXRlZ29yeSB2aXN1YWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhlIGNvbXBvbmVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBsaW5lYXIgcHJvZ3Jlc3MgYmFyLiBJdCBjYW4gZWl0aGVyIGRpc3BsYXkgYSBwcm9ncmVzcyBiYXIgdGhhdCBzaG93cyB0aGUgdXNlciBob3cgbXVjaCBvZiBhIHRhc2sgaGFzIGJlZW4gY29tcGxldGVkLiBJbiB0aGUgY2FzZSB3aGVyZSB0aGUgcGVyY2VudGFnZSBpcyBub3Qga25vd24gaXQgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhbiBhbmltYXRlZCBwcm9ncmVzcyBiYXIgc28gdGhlIHVzZXIgY2FuIHNlZSB0aGF0IGFuIG9wZXJhdGlvbiBpcyBpbiBwcm9ncmVzcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB6dlFiR2pcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wcm9ncmVzc1xuICogQHNlZWFsc28gb25zLXByb2dyZXNzLWNpcmN1bGFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+YCBjb21wb25lbnQgZGlzcGxheXMgYSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3IuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wcm9ncmVzcy1iYXJcbiAqICB2YWx1ZT1cIjU1XCJcbiAqICBzZWNvbmRhcnktdmFsdWU9XCI4N1wiPlxuICogPC9vbnMtcHJvZ3Jlc3MtYmFyPlxuICpcbiAqIDxvbnMtcHJvZ3Jlc3MtYmFyXG4gKiAgaW5kZXRlcm1pbmF0ZT5cbiAqIDwvb25zLXByb2dyZXNzLWJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZ3Jlc3NCYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICAgKiAgIFtqYV3jg5fjg63jgrDjg6zjgrnjgqTjg7PjgrjjgrHjg7zjgr/jga7opovjgZ/nm67jgpLlpInmm7TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNlY29uZGFyeS12YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbmRldGVybWluYXRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGlmICghdGhpcy5faXNDb21waWxlZCgpKSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZSA9IHRlbXBsYXRlLmNsb25lTm9kZSh0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdGVtcGxhdGUgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWJhcicpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByaW1hcnkgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSwgJy5wcm9ncmVzcy1iYXJfX3ByaW1hcnknKTtcbiAgICB0aGlzLl9zZWNvbmRhcnkgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSwgJy5wcm9ncmVzcy1iYXJfX3NlY29uZGFyeScpO1xuXG4gICAgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB0aGlzLl91cGRhdGVWYWx1ZSgpO1xuXG4gICAgdGhpcy5hcHBlbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBfaXNDb21waWxlZCgpIHtcbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcucHJvZ3Jlc3MtYmFyJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBiYXJFbGVtZW50ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wcm9ncmVzcy1iYXInKTtcblxuICAgIGlmICghdXRpbC5maW5kQ2hpbGQoYmFyRWxlbWVudCwgJy5wcm9ncmVzcy1iYXJfX3NlY29uZGFyeScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZChiYXJFbGVtZW50LCAnLnByb2dyZXNzLWJhcl9fcHJpbWFyeScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICd2YWx1ZScsICdzZWNvbmRhcnktdmFsdWUnLCAnaW5kZXRlcm1pbmF0ZSddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgcmV0dXJuIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3ZhbHVlJyB8fCBuYW1lID09PSAnc2Vjb25kYXJ5LXZhbHVlJykge1xuICAgICAgdGhpcy5fdXBkYXRlVmFsdWUoKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICdpbmRldGVybWluYXRlJykge1xuICAgICAgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRGV0ZXJtaW5hdGUoKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpbmRldGVybWluYXRlJykpIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX3RlbXBsYXRlLmNsYXNzTGlzdC5hZGQoYHByb2dyZXNzLWJhci0taW5kZXRlcm1pbmF0ZWApO1xuICAgICAgICB0aGlzLl90ZW1wbGF0ZS5jbGFzc0xpc3QucmVtb3ZlKGBwcm9ncmVzcy1iYXItLWRldGVybWluYXRlYCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICB0aGlzLl90ZW1wbGF0ZS5jbGFzc0xpc3QuYWRkKGBwcm9ncmVzcy1iYXItLWRldGVybWluYXRlYCk7XG4gICAgICAgIHRoaXMuX3RlbXBsYXRlLmNsYXNzTGlzdC5yZW1vdmUoYHByb2dyZXNzLWJhci0taW5kZXRlcm1pbmF0ZWApO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVZhbHVlKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9wcmltYXJ5LnN0eWxlLndpZHRoID0gKHRoaXMuaGFzQXR0cmlidXRlKCd2YWx1ZScpKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpICsgJyUnIDogJzAlJztcbiAgICAgIHRoaXMuX3NlY29uZGFyeS5zdHlsZS53aWR0aCA9IHRoaXMuaGFzQXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSArICclJyA6ICcwJSc7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCB2YWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHZhbHVlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3ZhbHVlJywgTWF0aC5mbG9vcih2YWx1ZSkpO1xuICB9XG5cbiAgZ2V0IHZhbHVlKCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmdldEF0dHJpYnV0ZSgndmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzZWNvbmRhcnlWYWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cbiAgc2V0IHNlY29uZGFyeVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgdmFsdWUgPCAwIHx8IHZhbHVlID4gMTAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmFsdWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc2Vjb25kYXJ5LXZhbHVlJywgTWF0aC5mbG9vcih2YWx1ZSkpO1xuICB9XG5cbiAgZ2V0IHNlY29uZGFyeVZhbHVlKCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmdldEF0dHJpYnV0ZSgnc2Vjb25kYXJ5LXZhbHVlJykgfHwgJzAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgaW5kZXRlcm1pbmF0ZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgLCBhbiBpbmZpbml0ZSBsb29waW5nIGFuaW1hdGlvbiB3aWxsIGJlIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOioreWumuOBleOCjOOBn+WgtOWQiOOAgeODq+ODvOODl+OBmeOCi+OCouODi+ODoeODvOOCt+ODp+ODs+OBjOihqOekuuOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuICBzZXQgaW5kZXRlcm1pbmF0ZSh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2luZGV0ZXJtaW5hdGUnLCAnJyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5yZW1vdmVBdHRyaWJ1dGUoJ2luZGV0ZXJtaW5hdGUnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaW5kZXRlcm1pbmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2luZGV0ZXJtaW5hdGUnKTtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1wcm9ncmVzcy1iYXInLCBQcm9ncmVzc0JhckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnByb2dyZXNzLWNpcmN1bGFyJzogJ3Byb2dyZXNzLWNpcmN1bGFyLS0qJyxcbiAgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeSc6ICdwcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeS0tKicsXG4gICcucHJvZ3Jlc3MtY2lyY3VsYXJfX3NlY29uZGFyeSc6ICdwcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5LS0qJ1xufTtcblxuY29uc3QgdGVtcGxhdGUgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICA8c3ZnIGNsYXNzPVwicHJvZ3Jlc3MtY2lyY3VsYXJcIj5cbiAgICA8Y2lyY2xlIGNsYXNzPVwicHJvZ3Jlc3MtY2lyY3VsYXJfX3NlY29uZGFyeVwiIGN4PVwiNTAlXCIgY3k9XCI1MCVcIiByPVwiNDAlXCIgZmlsbD1cIm5vbmVcIiBzdHJva2Utd2lkdGg9XCIxMCVcIiBzdHJva2UtbWl0ZXJsaW1pdD1cIjEwXCIvPlxuICAgIDxjaXJjbGUgY2xhc3M9XCJwcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeVwiIGN4PVwiNTAlXCIgY3k9XCI1MCVcIiByPVwiNDAlXCIgZmlsbD1cIm5vbmVcIiBzdHJva2Utd2lkdGg9XCIxMCVcIiBzdHJva2UtbWl0ZXJsaW1pdD1cIjEwXCIvPlxuICA8L3N2Zz5cbmApO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wcm9ncmVzcy1jaXJjdWxhclxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGlzIGNvbXBvbmVudCBkaXNwbGF5cyBhIGNpcmN1bGFyIHByb2dyZXNzIGluZGljYXRvci4gSXQgY2FuIGVpdGhlciBiZSB1c2VkIHRvIHNob3cgaG93IG11Y2ggb2YgYSB0YXNrIGhhcyBiZWVuIGNvbXBsZXRlZCBvciB0byBzaG93IGEgbG9vcGluZyBhbmltYXRpb24gdG8gaW5kaWNhdGUgdGhhdCBhbiBvcGVyYXRpb24gaXMgY3VycmVudGx5IHJ1bm5pbmcuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gRVZ6TWpSXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcHJvZ3Jlc3NcbiAqIEBzZWVhbHNvIG9ucy1wcm9ncmVzcy1iYXJcbiAqICAgW2VuXVRoZSBgPG9ucy1wcm9ncmVzcy1iYXI+YCBjb21wb25lbnQgZGlzcGxheXMgYSBiYXIgcHJvZ3Jlc3MgaW5kaWNhdG9yLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXJcbiAqICB2YWx1ZT1cIjU1XCJcbiAqICBzZWNvbmRhcnktdmFsdWU9XCI4N1wiPlxuICogPC9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+XG4gKlxuICogPG9ucy1wcm9ncmVzcy1jaXJjdWxhclxuICogIGluZGV0ZXJtaW5hdGU+XG4gKiA8L29ucy1wcm9ncmVzcy1jaXJjdWxhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZ3Jlc3NDaXJjdWxhckVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNoYW5nZSB0aGUgYXBwZWFyYW5jZSBvZiB0aGUgcHJvZ3Jlc3MgaW5kaWNhdG9yLlsvZW5dXG4gICAqICAgW2phXeODl+ODreOCsOODrOOCueOCpOODs+OCuOOCseODvOOCv+OBruimi+OBn+ebruOCkuWkieabtOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2Vjb25kYXJ5LXZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHNlY29uZGFyeSBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu77yS55Wq55uu44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGluZGV0ZXJtaW5hdGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCwgYW4gaW5maW5pdGUgbG9vcGluZyBhbmltYXRpb24gd2lsbCBiZSBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzoqK3lrprjgZXjgozjgZ/loLTlkIjjgIHjg6vjg7zjg5fjgZnjgovjgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAndmFsdWUnLCAnc2Vjb25kYXJ5LXZhbHVlJywgJ2luZGV0ZXJtaW5hdGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICd2YWx1ZScgfHwgbmFtZSA9PT0gJ3NlY29uZGFyeS12YWx1ZScpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAnaW5kZXRlcm1pbmF0ZScpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZURldGVybWluYXRlKCkge1xuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnaW5kZXRlcm1pbmF0ZScpKSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICB0aGlzLl90ZW1wbGF0ZS5jbGFzc0xpc3QuYWRkKGBwcm9ncmVzcy1jaXJjdWxhci0taW5kZXRlcm1pbmF0ZWApO1xuICAgICAgICB0aGlzLl90ZW1wbGF0ZS5jbGFzc0xpc3QucmVtb3ZlKGBwcm9ncmVzcy1jaXJjdWxhci0tZGV0ZXJtaW5hdGVgKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX3RlbXBsYXRlLmNsYXNzTGlzdC5hZGQoYHByb2dyZXNzLWNpcmN1bGFyLS1kZXRlcm1pbmF0ZWApO1xuICAgICAgICB0aGlzLl90ZW1wbGF0ZS5jbGFzc0xpc3QucmVtb3ZlKGBwcm9ncmVzcy1jaXJjdWxhci0taW5kZXRlcm1pbmF0ZWApO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVZhbHVlKCkge1xuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgndmFsdWUnKSkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgY29uc3QgcGVyID0gTWF0aC5jZWlsKHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpICogMjUxLjMyICogMC4wMSk7XG4gICAgICAgIHRoaXMuX3ByaW1hcnkuc3R5bGVbJ3N0cm9rZS1kYXNoYXJyYXknXSA9IHBlciArICclLCAyNTEuMzIlJztcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ3NlY29uZGFyeS12YWx1ZScpKSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICBjb25zdCBwZXIgPSAgTWF0aC5jZWlsKHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSAqIDI1MS4zMiAqIDAuMDEpO1xuICAgICAgICB0aGlzLl9zZWNvbmRhcnkuc3R5bGVbJ3N0cm9rZS1kYXNoYXJyYXknXSA9IHBlciArICclLCAyNTEuMzIlJztcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cbiAgc2V0IHZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgdmFsdWUgPCAwIHx8IHZhbHVlID4gMTAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmFsdWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgndmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpIHx8ICcwJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHNlY29uZGFyeVZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHNlY29uZGFyeSBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu77yS55Wq55uu44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuICBzZXQgc2Vjb25kYXJ5VmFsdWUodmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCB2YWx1ZSA8IDAgfHwgdmFsdWUgPiAxMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgc2Vjb25kYXJ5VmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmRldGVybWluYXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNldCBpbmRldGVybWluYXRlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnaW5kZXRlcm1pbmF0ZScsICcnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSgnaW5kZXRlcm1pbmF0ZScpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpbmRldGVybWluYXRlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnaW5kZXRlcm1pbmF0ZScpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKHRoaXMuX2lzQ29tcGlsZWQoKSkge1xuICAgICAgdGhpcy5fdGVtcGxhdGUgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdGVtcGxhdGUuY2xvbmVOb2RlKHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByaW1hcnkgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSwgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpO1xuICAgIHRoaXMuX3NlY29uZGFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWNpcmN1bGFyX19zZWNvbmRhcnknKTtcblxuICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgdGhpcy5fdXBkYXRlVmFsdWUoKTtcblxuICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fdGVtcGxhdGUpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2lzQ29tcGlsZWQoKSB7XG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBzdmcgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcHJvZ3Jlc3MtY2lyY3VsYXInLCBQcm9ncmVzc0NpcmN1bGFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vb25zL2dlc3R1cmUtZGV0ZWN0b3InO1xuXG5jb25zdCBTVEFURV9JTklUSUFMID0gJ2luaXRpYWwnO1xuY29uc3QgU1RBVEVfUFJFQUNUSU9OID0gJ3ByZWFjdGlvbic7XG5jb25zdCBTVEFURV9BQ1RJT04gPSAnYWN0aW9uJztcblxuY29uc3QgcmVtb3ZlVHJhbnNmb3JtID0gKGVsKSA9PiB7XG4gIGVsLnN0eWxlLnRyYW5zZm9ybSA9ICcnO1xuICBlbC5zdHlsZS5XZWJraXRUcmFuc2Zvcm0gPSAnJztcbiAgZWwuc3R5bGUudHJhbnNpdGlvbiA9ICcnO1xuICBlbC5zdHlsZS5XZWJraXRUcmFuc2l0aW9uID0gJyc7XG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wdWxsLWhvb2tcbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbXBvbmVudCB0aGF0IGFkZHMgKipQdWxsIHRvIHJlZnJlc2gqKiBmdW5jdGlvbmFsaXR5IHRvIGFuIGA8b25zLXBhZ2U+YCBlbGVtZW50LlxuICpcbiAqICAgICBJdCBjYW4gYmUgdXNlZCB0byBwZXJmb3JtIGEgdGFzayB3aGVuIHRoZSB1c2VyIHB1bGxzIGRvd24gYXQgdGhlIHRvcCBvZiB0aGUgcGFnZS4gQSBjb21tb24gdXNhZ2UgaXMgdG8gcmVmcmVzaCB0aGUgZGF0YSBkaXNwbGF5ZWQgaW4gYSBwYWdlLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIFdiSm9nTVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3B1bGwtaG9va1xuICogQGV4YW1wbGVcbiAqIDxvbnMtcGFnZT5cbiAqICAgPG9ucy1wdWxsLWhvb2s+XG4gKiAgICAgUmVsZWFzZSB0byByZWZyZXNoXG4gKiAgIDwvb25zLXB1bGwtaG9vaz5cbiAqIDwvb25zLXBhZ2U+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignb25zLXB1bGwtaG9vaycpLm9uQWN0aW9uID0gZnVuY3Rpb24oZG9uZSkge1xuICogICAgIHNldFRpbWVvdXQoZG9uZSwgMTAwMCk7XG4gKiAgIH07XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHVsbEhvb2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgY2hhbmdlc3RhdGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN0YXRlIGlzIGNoYW5nZWQuIFRoZSBzdGF0ZSBjYW4gYmUgZWl0aGVyIFwiaW5pdGlhbFwiLCBcInByZWFjdGlvblwiIG9yIFwiYWN0aW9uXCIuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu54q25oWL44GM5aSJ44KP44Gj44Gf5aC05ZCI44Gr55m654Gr44GX44G+44GZ44CC54q25oWL44Gv44CBXCJpbml0aWFsXCIsIFwicHJlYWN0aW9uXCIsIFwiYWN0aW9uXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wdWxsSG9va1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudC5zdGF0ZVxuICAgKiAgIFtlbl1DdXJyZW50IHN0YXRlLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrueKtuaFi+WQjeOCkuWPgueFp+OBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIFwicHVsbC10by1yZWZyZXNoXCIgZnVuY3Rpb25hbGl0eSBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIFkaXNhYmxlZOeKtuaFi+OBq+OBquOCiuOCouOCr+OCt+ODp+ODs+OBjOWun+ihjOOBleOCjOOBquOBj+OBquOCiuOBvuOBmVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGhlaWdodFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgaGVpZ2h0IG9mIHRoZSBjb21wb25lbnQuIFdoZW4gcHVsbGVkIGRvd24gZnVydGhlciB0aGFuIHRoaXMgdmFsdWUgaXQgd2lsbCBzd2l0Y2ggdG8gdGhlIFwicHJlYWN0aW9uXCIgc3RhdGUuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIFwiNjRweFwiLlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBrumrmOOBleOCkuaMh+WumuOBl+OBvuOBmeOAguOBk+OBrumrmOOBleS7peS4iuOBq3B1bGwgZG93buOBmeOCi+OBqFwicHJlYWN0aW9uXCLnirbmhYvjgavnp7vooYzjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga7lgKTjga9cIjY0cHhcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRocmVzaG9sZC1oZWlnaHRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIHRocmVzaG9sZCBoZWlnaHQuIFRoZSBjb21wb25lbnQgYXV0b21hdGljYWxseSBzd2l0Y2hlcyB0byB0aGUgXCJhY3Rpb25cIiBzdGF0ZSB3aGVuIHB1bGxlZCBmdXJ0aGVyIHRoYW4gdGhpcyB2YWx1ZS4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgXCI5NnB4XCIuIEEgbmVnYXRpdmUgdmFsdWUgb3IgYSB2YWx1ZSBsZXNzIHRoYW4gdGhlIGhlaWdodCB3aWxsIGRpc2FibGUgdGhpcyBwcm9wZXJ0eS5bL2VuXVxuICAgKiAgIFtqYV3plr7lgKTjgajjgarjgovpq5jjgZXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lgKTjgafmjIflrprjgZfjgZ/pq5jjgZXjgojjgorjgoJwdWxsIGRvd27jgZnjgovjgajjgIHjgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga/oh6rli5XnmoTjgatcImFjdGlvblwi54q25oWL44Gr56e76KGM44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZml4ZWQtY29udGVudFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjb250ZW50IG9mIHRoZSBwYWdlIHdpbGwgbm90IG1vdmUgd2hlbiBwdWxsaW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODl+ODq+ODleODg+OCr+OBjOW8leOBjeWHuuOBleOCjOOBpuOBhOOCi+aZguOBq+OCguOCs+ODs+ODhuODs+ODhOOBr+WLleOBjeOBvuOBm+OCk+OAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fYm91bmRPbkRyYWcgPSB0aGlzLl9vbkRyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9ib3VuZE9uRHJhZ1N0YXJ0ID0gdGhpcy5fb25EcmFnU3RhcnQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9ib3VuZE9uRHJhZ0VuZCA9IHRoaXMuX29uRHJhZ0VuZC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX2JvdW5kT25TY3JvbGwgPSB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5fc2V0U3RhdGUoU1RBVEVfSU5JVElBTCwgdHJ1ZSk7XG4gIH1cblxuICBfc2V0U3R5bGUoKSB7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICB0aGlzLnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG4gICAgdGhpcy5zdHlsZS5saW5lSGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcbiAgICB0aGlzLnN0eWxlLm1hcmdpblRvcCA9ICctMXB4JztcbiAgICB0aGlzLl9wYWdlRWxlbWVudC5zdHlsZS5tYXJnaW5Ub3AgPSBgLSR7aGVpZ2h0fXB4YDtcbiAgfVxuXG4gIF9vblNjcm9sbChldmVudCkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9wYWdlRWxlbWVudDtcblxuICAgIGlmIChlbGVtZW50LnNjcm9sbFRvcCA8IDApIHtcbiAgICAgIGVsZW1lbnQuc2Nyb2xsVG9wID0gMDtcbiAgICB9XG4gIH1cblxuICBfZ2VuZXJhdGVUcmFuc2xhdGlvblRyYW5zZm9ybShzY3JvbGwpIHtcbiAgICByZXR1cm4gYHRyYW5zbGF0ZTNkKDBweCwgJHtzY3JvbGx9cHgsIDBweClgO1xuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSGFjayB0byBtYWtlIGl0IHdvcmsgb24gQW5kcm9pZCA0LjQgV2ViVmlldy4gU2Nyb2xscyBtYW51YWxseSBuZWFyIHRoZSB0b3Agb2YgdGhlIHBhZ2Ugc29cbiAgICAvLyB0aGVyZSB3aWxsIGJlIG5vIGluZXJ0aWFsIHNjcm9sbCB3aGVuIHNjcm9sbGluZyBkb3duLiBBbGxvd2luZyBkZWZhdWx0IHNjcm9sbGluZyB3aWxsXG4gICAgLy8ga2lsbCBhbGwgJ3RvdWNobW92ZScgZXZlbnRzLlxuICAgIGlmIChwbGF0Zm9ybS5pc0FuZHJvaWQoKSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX3BhZ2VFbGVtZW50O1xuICAgICAgZWxlbWVudC5zY3JvbGxUb3AgPSB0aGlzLl9zdGFydFNjcm9sbCAtIGV2ZW50Lmdlc3R1cmUuZGVsdGFZO1xuICAgICAgaWYgKGVsZW1lbnQuc2Nyb2xsVG9wIDwgd2luZG93LmlubmVySGVpZ2h0ICYmIGV2ZW50Lmdlc3R1cmUuZGlyZWN0aW9uICE9PSAndXAnKSB7XG4gICAgICAgIGV2ZW50Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID09PSAwICYmIHRoaXMuX2dldEN1cnJlbnRTY3JvbGwoKSA9PT0gMCkge1xuICAgICAgdGhpcy5fdHJhbnNpdGlvbkRyYWdMZW5ndGggPSBldmVudC5nZXN0dXJlLmRlbHRhWTtcblxuICAgICAgY29uc3QgZGlyZWN0aW9uID0gZXZlbnQuZ2VzdHVyZS5pbnRlcmltRGlyZWN0aW9uO1xuICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ2Rvd24nKSB7XG4gICAgICAgIHRoaXMuX3RyYW5zaXRpb25EcmFnTGVuZ3RoIC09IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9uRHJhZ0xlbmd0aCArPSAxO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHNjcm9sbCA9IE1hdGgubWF4KGV2ZW50Lmdlc3R1cmUuZGVsdGFZIC0gdGhpcy5fc3RhcnRTY3JvbGwsIDApO1xuXG4gICAgaWYgKHRoaXMuX3RocmVzaG9sZEhlaWdodEVuYWJsZWQoKSAmJiBzY3JvbGwgPj0gdGhpcy50aHJlc2hvbGRIZWlnaHQpIHtcbiAgICAgIGV2ZW50Lmdlc3R1cmUuc3RvcERldGVjdCgpO1xuXG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5fZmluaXNoKCkpO1xuICAgIH0gZWxzZSBpZiAoc2Nyb2xsID49IHRoaXMuaGVpZ2h0KSB7XG4gICAgICB0aGlzLl9zZXRTdGF0ZShTVEFURV9QUkVBQ1RJT04pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zZXRTdGF0ZShTVEFURV9JTklUSUFMKTtcbiAgICB9XG5cbiAgICAvLyBCeSBzdG9wcGluZyBwcm9wYWdhdGlvbiBvbmx5IG9mIGBkcmFndXBgIGFuZCBgZHJhZ2Rvd25gLFxuICAgIC8vIGFsbG93aW5nIGFuY2VzdG9yIGVsZW1lbnRzIHRvIGRldGVjdCBgZHJhZ2xlZnRgIGFuZCBgZHJhZ3JpZ2h0YC5cbiAgICAvLyBJZiB3ZSBjb21tZW50IG91dCB0aGUgZm9sbG93aW5nIGBpZmAgYmxvY2ssIGBvbnMtc3BsaXR0ZXJgIHdpdGggYG9ucy1wdWxsLWhvb2tgIHdpbGwgYmUgYnJva2VuLlxuICAgIGlmIChldmVudC5nZXN0dXJlLmRpcmVjdGlvbiA9PT0gJ3VwJyB8fCBldmVudC5nZXN0dXJlLmRpcmVjdGlvbiA9PT0gJ2Rvd24nKSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICB0aGlzLl90cmFuc2xhdGVUbyhzY3JvbGwpO1xuICB9XG5cbiAgX29uRHJhZ1N0YXJ0KGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGFydFNjcm9sbCA9IHRoaXMuX2dldEN1cnJlbnRTY3JvbGwoKTtcbiAgfVxuXG4gIF9vbkRyYWdFbmQoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9jdXJyZW50VHJhbnNsYXRpb24gPiAwKSB7XG4gICAgICBjb25zdCBzY3JvbGwgPSB0aGlzLl9jdXJyZW50VHJhbnNsYXRpb247XG5cbiAgICAgIGlmIChzY3JvbGwgPiB0aGlzLmhlaWdodCkge1xuICAgICAgICB0aGlzLl9maW5pc2goKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3RyYW5zbGF0ZVRvKDAsIHthbmltYXRlOiB0cnVlfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkFjdGlvblxuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIHdpbGwgYmUgY2FsbGVkIGluIHRoZSBgYWN0aW9uYCBzdGF0ZSBpZiBpdCBleGlzdHMuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGdpdmVuIGEgYGRvbmVgIGNhbGxiYWNrIGFzIGl0J3MgZmlyc3QgYXJndW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgX2ZpbmlzaCgpIHtcbiAgICB0aGlzLl9zZXRTdGF0ZShTVEFURV9BQ1RJT04pO1xuICAgIHRoaXMuX3RyYW5zbGF0ZVRvKHRoaXMuaGVpZ2h0LCB7YW5pbWF0ZTogdHJ1ZX0pO1xuICAgIGNvbnN0IGFjdGlvbiA9IHRoaXMub25BY3Rpb24gfHwgKGRvbmUgPT4gZG9uZSgpKTtcbiAgICBhY3Rpb24oKCkgPT4ge1xuICAgICAgdGhpcy5fdHJhbnNsYXRlVG8oMCwge2FuaW1hdGU6IHRydWV9KTtcbiAgICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX0lOSVRJQUwpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBoZWlnaHRcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBoZWlnaHQgb2YgdGhlIHB1bGwgaG9vayBpbiBwaXhlbHMuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGA2NHB4YC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0IGhlaWdodCh2YWx1ZSkge1xuICAgIGlmICghdXRpbC5pc0ludGVnZXIodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBoZWlnaHQgbXVzdCBiZSBhbiBpbnRlZ2VyJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIGAke3ZhbHVlfXB4YCk7XG4gIH1cblxuICBnZXQgaGVpZ2h0KCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmdldEF0dHJpYnV0ZSgnaGVpZ2h0JykgfHwgJzY0JywgMTApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB0aHJlc2hvbGRIZWlnaHRcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB0aHJlc2hvbGRIZWlnaHQgb2YgdGhlIHB1bGwgaG9vayBpbiBwaXhlbHMuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGA5NnB4YC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0IHRocmVzaG9sZEhlaWdodCh2YWx1ZSkge1xuICAgIGlmICghdXRpbC5pc0ludGVnZXIodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSB0aHJlc2hvbGQgaGVpZ2h0IG11c3QgYmUgYW4gaW50ZWdlcicpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCd0aHJlc2hvbGQtaGVpZ2h0JywgYCR7dmFsdWV9cHhgKTtcbiAgfVxuXG4gIGdldCB0aHJlc2hvbGRIZWlnaHQoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCd0aHJlc2hvbGQtaGVpZ2h0JykgfHwgJzk2JywgMTApO1xuICB9XG5cbiAgX3RocmVzaG9sZEhlaWdodEVuYWJsZWQoKSB7XG4gICAgY29uc3QgdGggPSB0aGlzLnRocmVzaG9sZEhlaWdodDtcbiAgICByZXR1cm4gdGggPiAwICYmIHRoID49IHRoaXMuaGVpZ2h0O1xuICB9XG5cbiAgX3NldFN0YXRlKHN0YXRlLCBub0V2ZW50KSB7XG4gICAgY29uc3QgbGFzdFN0YXRlID0gdGhpcy5fZ2V0U3RhdGUoKTtcblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzdGF0ZScsIHN0YXRlKTtcblxuICAgIGlmICghbm9FdmVudCAmJiBsYXN0U3RhdGUgIT09IHRoaXMuX2dldFN0YXRlKCkpIHtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnY2hhbmdlc3RhdGUnLCB7XG4gICAgICAgIHB1bGxIb29rOiB0aGlzLFxuICAgICAgICBzdGF0ZTogc3RhdGUsXG4gICAgICAgIGxhc3RTdGF0ZTogbGFzdFN0YXRlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfZ2V0U3RhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdzdGF0ZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzdGF0ZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc3RhdGUgb2YgdGhlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBzdGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U3RhdGUoKTtcbiAgfVxuXG4gIF9nZXRDdXJyZW50U2Nyb2xsKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlRWxlbWVudC5zY3JvbGxUb3A7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHB1bGxEaXN0YW5jZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBjdXJyZW50IG51bWJlciBvZiBwaXhlbHMgdGhlIHB1bGwgaG9vayBoYXMgbW92ZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44OX44Or44OV44OD44Kv44GM5byV44GN5Ye644GV44KM44Gf6Led6Zui44KS44OU44Kv44K744Or5pWw44CCWy9qYV1cbiAgICovXG4gIGdldCBwdWxsRGlzdGFuY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBfaXNDb250ZW50Rml4ZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdmaXhlZC1jb250ZW50Jyk7XG4gIH1cblxuICBfZ2V0U2Nyb2xsYWJsZUVsZW1lbnQoKSB7XG4gICAgaWYgKHRoaXMuX2lzQ29udGVudEZpeGVkKCkpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcGFnZUVsZW1lbnQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBzY3JvbGxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqL1xuICBfdHJhbnNsYXRlVG8oc2Nyb2xsLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAodGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID09IDAgJiYgc2Nyb2xsID09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBkb25lID0gKCkgPT4ge1xuICAgICAgaWYgKHNjcm9sbCA9PT0gMCkge1xuICAgICAgICBjb25zdCBlbCA9IHRoaXMuX2dldFNjcm9sbGFibGVFbGVtZW50KCk7XG4gICAgICAgIHJlbW92ZVRyYW5zZm9ybShlbCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLmNhbGxiYWNrKSB7XG4gICAgICAgIG9wdGlvbnMuY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID0gc2Nyb2xsO1xuXG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0ZSkge1xuICAgICAgYW5pbWl0KHRoaXMuX2dldFNjcm9sbGFibGVFbGVtZW50KCkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiB0aGlzLl9nZW5lcmF0ZVRyYW5zbGF0aW9uVHJhbnNmb3JtKHNjcm9sbClcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiAwLjMsXG4gICAgICAgICAgdGltaW5nOiAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjEsIDEpJ1xuICAgICAgICB9KVxuICAgICAgICAucGxheShkb25lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYW5pbWl0KHRoaXMuX2dldFNjcm9sbGFibGVFbGVtZW50KCkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiB0aGlzLl9nZW5lcmF0ZVRyYW5zbGF0aW9uVHJhbnNmb3JtKHNjcm9sbClcbiAgICAgICAgfSlcbiAgICAgICAgLnBsYXkoZG9uZSk7XG4gICAgfVxuICB9XG5cbiAgX2Rpc2FibGVEcmFnTG9jaygpIHsgLy8gZTJlIHRlc3RzIG5lZWQgaXRcbiAgICB0aGlzLl9kcmFnTG9ja0Rpc2FibGVkID0gdHJ1ZTtcbiAgICB0aGlzLl9kZXN0cm95RXZlbnRMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLl9jcmVhdGVFdmVudExpc3RlbmVycygpO1xuICB9XG5cbiAgX2NyZWF0ZUV2ZW50TGlzdGVuZXJzKCkge1xuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcy5fcGFnZUVsZW1lbnQsIHtcbiAgICAgIGRyYWdNaW5EaXN0YW5jZTogMSxcbiAgICAgIGRyYWdEaXN0YW5jZUNvcnJlY3Rpb246IGZhbHNlLFxuICAgICAgZHJhZ0xvY2tUb0F4aXM6ICF0aGlzLl9kcmFnTG9ja0Rpc2FibGVkXG4gICAgfSk7XG5cbiAgICAvLyBCaW5kIGxpc3RlbmVyc1xuICAgIC8vXG4gICAgLy8gTm90ZTpcbiAgICAvLyBJZiB3ZSBzd2lwZSB1cC9kb3duIGEgc2NyZWVuIHRvbyBmYXN0LFxuICAgIC8vIHRoZSBnZXN0dXJlIGRldGVjdG9yIG9jY2FzaW9uYWxseSBkaXNwYXRjaGVzIGEgYGRyYWdsZWZ0YCBvciBgZHJhZ3JpZ2h0YCxcbiAgICAvLyBzbyB3ZSBuZWVkIHRvIGhhdmUgdGhlIHB1bGwgaG9vayBsaXN0ZW4gdG8gYGRyYWdsZWZ0YCBhbmQgYGRyYWdyaWdodGAgYXMgd2VsbCBhcyBgZHJhZ3VwYCBhbmQgYGRyYWdkb3duYC5cbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3Iub24oJ2RyYWd1cCBkcmFnZG93biBkcmFnbGVmdCBkcmFncmlnaHQnLCB0aGlzLl9ib3VuZE9uRHJhZyk7XG4gICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLm9uKCdkcmFnc3RhcnQnLCB0aGlzLl9ib3VuZE9uRHJhZ1N0YXJ0KTtcbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3Iub24oJ2RyYWdlbmQnLCB0aGlzLl9ib3VuZE9uRHJhZ0VuZCk7XG5cbiAgICB0aGlzLl9wYWdlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLl9ib3VuZE9uU2Nyb2xsLCBmYWxzZSk7XG4gIH1cblxuICBfZGVzdHJveUV2ZW50TGlzdGVuZXJzKCkge1xuICAgIGlmICh0aGlzLl9nZXN0dXJlRGV0ZWN0b3IpIHtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3Rvci5vZmYoJ2RyYWd1cCBkcmFnZG93biBkcmFnbGVmdCBkcmFncmlnaHQnLCB0aGlzLl9ib3VuZE9uRHJhZyk7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3Iub2ZmKCdkcmFnc3RhcnQnLCB0aGlzLl9ib3VuZE9uRHJhZ1N0YXJ0KTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3Rvci5vZmYoJ2RyYWdlbmQnLCB0aGlzLl9ib3VuZE9uRHJhZ0VuZCk7XG5cbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3Rvci5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuX3BhZ2VFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwsIGZhbHNlKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbiA9IDA7XG4gICAgdGhpcy5fcGFnZUVsZW1lbnQgPSB0aGlzLnBhcmVudE5vZGU7XG5cbiAgICB0aGlzLl9jcmVhdGVFdmVudExpc3RlbmVycygpO1xuICAgIHRoaXMuX3NldFN0eWxlKCk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9wYWdlRWxlbWVudC5zdHlsZS5tYXJnaW5Ub3AgPSAnJztcblxuICAgIHRoaXMuX2Rlc3Ryb3lFdmVudExpc3RlbmVycygpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnaGVpZ2h0J107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnaGVpZ2h0Jykge1xuICAgICAgdGhpcy5fc2V0U3R5bGUoKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IFNUQVRFX0lOSVRJQUwoKSB7XG4gICAgcmV0dXJuIFNUQVRFX0lOSVRJQUw7XG4gIH1cblxuICBzdGF0aWMgZ2V0IFNUQVRFX1BSRUFDVElPTigpIHtcbiAgICByZXR1cm4gU1RBVEVfUFJFQUNUSU9OO1xuICB9XG5cbiAgc3RhdGljIGdldCBTVEFURV9BQ1RJT04oKSB7XG4gICAgcmV0dXJuIFNUQVRFX0FDVElPTjtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1wdWxsLWhvb2snLCBQdWxsSG9va0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTYgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IGludGVybmFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbCc7XG5cbi8qKlxuICogQGNsYXNzIEFuaW1hdG9yQ1NTIC0gaW1wbGVtZW50YXRpb24gb2YgQW5pbWF0b3IgY2xhc3MgdXNpbmcgY3NzIHRyYW5zaXRpb25zXG4gKi9cbmNsYXNzIEFuaW1hdG9yQ1NTIHtcblxuICAvKipcbiAgICogQG1ldGhvZCBhbmltYXRlXG4gICAqIEBkZXNjIG1haW4gYW5pbWF0aW9uIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gZmluYWxDU1NcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtkdXJhdGlvbj0yMDBdIC0gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzXG4gICAqIEByZXR1cm4ge09iamVjdH0gcmVzdWx0XG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQudGhlbihjYWxsYmFjaykgLSBzZXRzIGEgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgYWZ0ZXIgdGhlIGFuaW1hdGlvbiBoYXMgc3RvcHBlZFxuICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gcmVzdWx0LnN0b3Aob3B0aW9ucykgLSBzdG9wcyB0aGUgYW5pbWF0aW9uOyBpZiBvcHRpb25zLnN0b3BOZXh0IGlzIHRydWUgdGhlbiBpdCBkb2Vzbid0IGNhbGwgdGhlIGNhbGxiYWNrXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQuZmluaXNoKG1zKSAtIGZpbmlzaGVzIHRoZSBhbmltYXRpb24gaW4gdGhlIHNwZWNpZmllZCB0aW1lIGluIG1pbGxpc2Vjb25kc1xuICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gcmVzdWx0LnNwZWVkKG1zKSAtIHNldHMgdGhlIGFuaW1hdGlvbiBzcGVlZCBzbyB0aGF0IGl0IGZpbmlzaGVzIGFzIGlmIHRoZSBvcmlnaW5hbCBkdXJhdGlvbiB3YXMgdGhlIG9uZSBzcGVjaWZpZWQgaGVyZVxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBgXG4gICAqICB2YXIgcmVzdWx0ID0gYW5pbWF0b3IuYW5pbWF0ZShlbCwge29wYWNpdHk6IDAuNX0sIDEwMDApO1xuICAgKlxuICAgKiAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbihlKXtcbiAgICogICAgcmVzdWx0LnNwZWVkKDIwMCkudGhlbihmdW5jdGlvbigpe1xuICAgKiAgICAgIGNvbnNvbGUubG9nKCdkb25lJyk7XG4gICAqICAgIH0pO1xuICAgKiAgfSwgMzAwKTtcbiAgICogYGBgYFxuICAgKi9cbiAgYW5pbWF0ZShlbCwgZmluYWwsIGR1cmF0aW9uID0gMjAwKSB7XG4gICAgdmFyIHN0YXJ0ID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcbiAgICAgICAgaW5pdGlhbCA9IHt9LFxuICAgICAgICBzdG9wcGVkID0gZmFsc2UsXG4gICAgICAgIG5leHQgPSBmYWxzZSxcbiAgICAgICAgdGltZW91dCA9IGZhbHNlLFxuICAgICAgICBwcm9wZXJ0aWVzID0gT2JqZWN0LmtleXMoZmluYWwpO1xuXG4gICAgdmFyIHVwZGF0ZVN0eWxlcyA9ICgpID0+IHtcbiAgICAgIGxldCBzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgICAgcHJvcGVydGllcy5mb3JFYWNoKHMuZ2V0UHJvcGVydHlWYWx1ZS5iaW5kKHMpKTtcbiAgICAgIHMgPSBlbC5vZmZzZXRIZWlnaHQ7XG4gICAgfTtcblxuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICBzdG9wOiAob3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgIHRpbWVvdXQgJiYgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICB2YXIgayA9IE1hdGgubWluKDEsICgobmV3IERhdGUoKSkuZ2V0VGltZSgpIC0gc3RhcnQpIC8gZHVyYXRpb24pO1xuICAgICAgICBwcm9wZXJ0aWVzLmZvckVhY2goaSA9PiB7XG4gICAgICAgICAgZWwuc3R5bGVbaV0gPSAoMSAtIGspICogaW5pdGlhbFtpXSArIGsgKiBmaW5hbFtpXSArIChpID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICBlbC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSAnMHMnO1xuXG4gICAgICAgIGlmIChvcHRpb25zLnN0b3BOZXh0KSB7XG4gICAgICAgICAgbmV4dCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKCFzdG9wcGVkKSB7XG4gICAgICAgICAgc3RvcHBlZCA9IHRydWU7XG4gICAgICAgICAgbmV4dCAmJiBuZXh0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0sXG4gICAgICB0aGVuOiAoY2IpID0+IHtcbiAgICAgICAgbmV4dCA9IGNiO1xuICAgICAgICBpZiAoc3RvcHBlZCkge1xuICAgICAgICAgIG5leHQgJiYgbmV4dCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICAgc3BlZWQ6IChuZXdEdXJhdGlvbikgPT4ge1xuICAgICAgICBpZiAoaW50ZXJuYWwuY29uZmlnLmFuaW1hdGlvbnNEaXNhYmxlZCkge1xuICAgICAgICAgIG5ld0R1cmF0aW9uID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0b3BwZWQpIHtcbiAgICAgICAgICB0aW1lb3V0ICYmIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICAgIGNvbnN0IHBhc3NlZCA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBzdGFydDtcbiAgICAgICAgICBjb25zdCAgayA9IHBhc3NlZCAvIGR1cmF0aW9uO1xuICAgICAgICAgIGNvbnN0IHJlbWFpbmluZyA9IG5ld0R1cmF0aW9uICogKDEgLSBrKTtcblxuICAgICAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChpID0+IHtcbiAgICAgICAgICAgIGVsLnN0eWxlW2ldID0gKDEgLSBrKSAqIGluaXRpYWxbaV0gKyBrICogZmluYWxbaV0gKyAoaSA9PSAnb3BhY2l0eScgPyAnJyA6ICdweCcpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgdXBkYXRlU3R5bGVzKCk7XG5cbiAgICAgICAgICBzdGFydCA9IGVsLnNwZWVkVXBUaW1lO1xuICAgICAgICAgIGR1cmF0aW9uID0gcmVtYWluaW5nO1xuXG4gICAgICAgICAgZWwuc3R5bGUudHJhbnNpdGlvbkR1cmF0aW9uID0gZHVyYXRpb24gLyAxMDAwICsgJ3MnO1xuXG4gICAgICAgICAgcHJvcGVydGllcy5mb3JFYWNoKGkgPT4ge1xuICAgICAgICAgICAgZWwuc3R5bGVbaV0gPSBmaW5hbFtpXSArIChpID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChyZXN1bHQuc3RvcCwgcmVtYWluaW5nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIGZpbmlzaDogKG1pbGxpc2Vjb25kcyA9IDUwKSA9PiB7XG4gICAgICAgIHZhciBrID0gKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBzdGFydCkgLyBkdXJhdGlvbjtcblxuICAgICAgICByZXN1bHQuc3BlZWQobWlsbGlzZWNvbmRzIC8gKDEgLSBrKSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGlmIChlbC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgfHwgc3RvcHBlZCB8fCBpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHZhciBzdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKTtcbiAgICBwcm9wZXJ0aWVzLmZvckVhY2goZSA9PiB7XG4gICAgICBjb25zdCB2ID0gcGFyc2VGbG9hdChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKGUpKTtcbiAgICAgIGluaXRpYWxbZV0gPSBpc05hTih2KSA/IDAgOiB2O1xuICAgIH0pO1xuXG5cbiAgICBpZiAoIXN0b3BwZWQpIHtcbiAgICAgIGVsLnN0eWxlLnRyYW5zaXRpb25Qcm9wZXJ0eSA9IHByb3BlcnRpZXMuam9pbignLCcpO1xuICAgICAgZWwuc3R5bGUudHJhbnNpdGlvbkR1cmF0aW9uID0gZHVyYXRpb24gLyAxMDAwICsgJ3MnO1xuXG4gICAgICBwcm9wZXJ0aWVzLmZvckVhY2goZSA9PiB7XG4gICAgICAgIGVsLnN0eWxlW2VdID0gZmluYWxbZV0gKyAoZSA9PSAnb3BhY2l0eScgPyAnJyA6ICdweCcpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGltZW91dCA9IHNldFRpbWVvdXQocmVzdWx0LnN0b3AsIGR1cmF0aW9uKTtcbiAgICB0aGlzLl9vblN0b3BBbmltYXRpb25zKGVsLCByZXN1bHQuc3RvcCk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5fcXVldWUgPSBbXTtcbiAgICB0aGlzLl9pbmRleCA9IDA7XG4gIH1cblxuICBfb25TdG9wQW5pbWF0aW9ucyhlbCwgbGlzdGVuZXIpIHtcbiAgICB2YXIgcXVldWUgPSB0aGlzLl9xdWV1ZTtcbiAgICB2YXIgaSA9IHRoaXMuX2luZGV4Kys7XG4gICAgcXVldWVbZWxdID0gcXVldWVbZWxdIHx8IFtdO1xuICAgIHF1ZXVlW2VsXVtpXSA9IChvcHRpb25zKSA9PiB7XG4gICAgICBkZWxldGUgcXVldWVbZWxdW2ldO1xuICAgICAgaWYgKHF1ZXVlW2VsXSAmJiBxdWV1ZVtlbF0ubGVuZ3RoID09IDApIHtcbiAgICAgICAgZGVsZXRlIHF1ZXVlW2VsXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsaXN0ZW5lcihvcHRpb25zKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICogQG1ldGhvZCBzdG9wQW5pbWF0aW9uc1xuICAqIEBkZXNjIHN0b3BzIGFjdGl2ZSBhbmltYXRpb25zIG9uIGEgc3BlY2lmaWVkIGVsZW1lbnRcbiAgKiBAcGFyYW0ge0VsZW1lbnR8QXJyYXl9IGVsZW1lbnQgLSBlbGVtZW50IG9yIGFycmF5IG9mIGVsZW1lbnRzXG4gICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XVxuICAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuc3RvcE5leHRdIC0gdGhlIGNhbGxiYWNrcyBhZnRlciB0aGUgYW5pbWF0aW9ucyB3b24ndCBiZSBjYWxsZWQgaWYgdGhpcyBvcHRpb24gaXMgdHJ1ZVxuICAqL1xuICBzdG9wQW5pbWF0aW9ucyhlbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZWwpKSB7XG4gICAgICByZXR1cm4gZWwuZm9yRWFjaChlbCA9PiB7XG4gICAgICAgIHRoaXMuc3RvcEFuaW1hdGlvbnMoZWwsIG9wdGlvbnMpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgKHRoaXMuX3F1ZXVlW2VsXSB8fCBbXSkuZm9yRWFjaChlID0+IHsgZShvcHRpb25zIHx8IHt9KTsgfSk7XG4gIH1cblxuICAvKipcbiAgKiBAbWV0aG9kIHN0b3BBbGxcbiAgKiBAZGVzYyBzdG9wcyBhbGwgYWN0aXZlIGFuaW1hdGlvbnNcbiAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dXG4gICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdG9wTmV4dF0gLSB0aGUgY2FsbGJhY2tzIGFmdGVyIHRoZSBhbmltYXRpb25zIHdvbid0IGJlIGNhbGxlZCBpZiB0aGlzIG9wdGlvbiBpcyB0cnVlXG4gICovXG4gIHN0b3BBbGwob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5zdG9wQW5pbWF0aW9ucyhPYmplY3Qua2V5cyh0aGlzLl9xdWV1ZSksIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICogQG1ldGhvZCBmYWRlXG4gICogQGRlc2MgZmFkZXMgdGhlIGVsZW1lbnQgKHNob3J0IHZlcnNpb24gZm9yIGFuaW1hdGUoZWwsIHtvcGFjaXR5OiAwfSkpXG4gICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gICogQHBhcmFtIHtudW1iZXJ9IFtkdXJhdGlvbj0yMDBdXG4gICovXG4gIGZhZGUoZWwsIGR1cmF0aW9uID0gMjAwKSB7XG4gICAgcmV0dXJuIHRoaXMuYW5pbWF0ZShlbCwge29wYWNpdHk6IDB9LCBkdXJhdGlvbik7XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBbmltYXRvckNTUztcblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvci1jc3MnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXJpcHBsZVxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBBZGRzIGEgTWF0ZXJpYWwgRGVzaWduIFwicmlwcGxlXCIgZWZmZWN0IHRvIGFuIGVsZW1lbnQuIFRoZSByaXBwbGUgZWZmZWN0IHdpbGwgc3ByZWFkIGZyb20gdGhlIHBvc2l0aW9uIHdoZXJlIHRoZSB1c2VyIHRhcHMuXG4gKlxuICogICAgIFNvbWUgZWxlbWVudHMgc3VjaCBhcyBgPG9ucy1idXR0b24+YCBhbmQgYDxvbnMtZmFiPmAgIHN1cHBvcnQgYSBgcmlwcGxlYCBhdHRyaWJ1dGUuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg6rjg4Pjg5fjg6vlirnmnpzjgpJET03opoHntKDjgavov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gd0tRV2RaXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcmlwcGxlXG4gKiBAZ3VpZGUgY3Jvc3MtcGxhdGZvcm0tc3R5bGluZ1xuICogIFtlbl1Dcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1cbiAqICBbamFdQ3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPGRpdiBjbGFzcz1cIm15LWRpdlwiPlxuICogIDxvbnMtcmlwcGxlPjwvb25zLXJpcHBsZT5cbiAqIDwvZGl2PlxuICpcbiAqIEBleGFtcGxlXG4gKiA8b25zLWJ1dHRvbiByaXBwbGU+Q2xpY2sgbWUhPC9vbnMtYnV0dG9uPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSaXBwbGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNvbG9yXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Db2xvciBvZiB0aGUgcmlwcGxlIGVmZmVjdC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjg4Pjg5fjg6vjgqjjg5Xjgqfjgq/jg4jjga7oibLjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBiYWNrZ3JvdW5kXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Db2xvciBvZiB0aGUgYmFja2dyb3VuZC5bL2VuXVxuICAgKiAgIFtqYV3og4zmma/jga7oibLjgpLoqK3lrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0LCB0aGUgcmlwcGxlIGVmZmVjdCB3aWxsIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOioreWumuOBleOCjOOBn+WgtOWQiOOAgeODquODg+ODl+ODq+OCqOODleOCp+OCr+ODiOOBr+eEoeWKueOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG5cbiAgICB0aGlzLl9hbmltYXRvciA9IG5ldyBBbmltYXRvcigpO1xuXG4gICAgWydjb2xvcicsICdjZW50ZXInLCAnc3RhcnQtcmFkaXVzJywgJ2JhY2tncm91bmQnXS5mb3JFYWNoKGUgPT4ge1xuICAgICAgdGhpcy5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2soZSwgbnVsbCwgdGhpcy5nZXRBdHRyaWJ1dGUoZSkpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdyaXBwbGUnKTtcblxuICAgIHRoaXMuX3dhdmUgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fd2F2ZScpWzBdO1xuICAgIHRoaXMuX2JhY2tncm91bmQgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fYmFja2dyb3VuZCcpWzBdO1xuXG4gICAgaWYgKCEodGhpcy5fYmFja2dyb3VuZCAmJiB0aGlzLl93YXZlKSkge1xuICAgICAgdGhpcy5fd2F2ZSA9IHV0aWwuY3JlYXRlKCcucmlwcGxlX193YXZlJyk7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kID0gdXRpbC5jcmVhdGUoJy5yaXBwbGVfX2JhY2tncm91bmQnKTtcblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZCh0aGlzLl93YXZlKTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fYmFja2dyb3VuZCk7XG4gICAgfVxuICB9XG5cbiAgX2NhbGN1bGF0ZUNvb3JkcyhlKSB7XG4gICAgdmFyIHgsIHksIGgsIHcsIHI7XG4gICAgdmFyIGIgPSB0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmICh0aGlzLl9jZW50ZXIpIHtcbiAgICAgIHggPSBiLndpZHRoIC8gMjtcbiAgICAgIHkgPSBiLmhlaWdodCAvIDI7XG4gICAgICByID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB4ID0gKGUuY2xpZW50WCB8fCBlLmNoYW5nZWRUb3VjaGVzWzBdLmNsaWVudFgpIC0gYi5sZWZ0O1xuICAgICAgeSA9IChlLmNsaWVudFkgfHwgZS5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRZKSAtIGIudG9wO1xuICAgICAgaCA9IE1hdGgubWF4KHksIGIuaGVpZ2h0IC0geSk7XG4gICAgICB3ID0gTWF0aC5tYXgoeCwgYi53aWR0aCAtIHgpO1xuICAgICAgciA9IE1hdGguc3FydChoICogaCArIHcgKiB3KTtcbiAgICB9XG4gICAgcmV0dXJuIHt4LCB5LCByfTtcbiAgfVxuXG4gIF9yaXBwbGVBbmltYXRpb24oZSwgZHVyYXRpb24gPSAzMDApIHtcbiAgICB2YXJcbiAgICAgIHtfYW5pbWF0b3IsIF93YXZlLCBfYmFja2dyb3VuZCwgX21pblJ9ID0gdGhpcyxcbiAgICAgIHt4LCB5LCByfSA9IHRoaXMuX2NhbGN1bGF0ZUNvb3JkcyhlKTtcblxuICAgIF9hbmltYXRvci5zdG9wQWxsKHtzdG9wTmV4dDogMX0pO1xuICAgIF9hbmltYXRvci5hbmltYXRlKF9iYWNrZ3JvdW5kLCB7b3BhY2l0eTogMX0sIGR1cmF0aW9uKTtcblxuICAgIHV0aWwuZXh0ZW5kKF93YXZlLnN0eWxlLCB7XG4gICAgICBvcGFjaXR5OiAxLFxuICAgICAgdG9wOiB5IC0gX21pblIgKyAncHgnLFxuICAgICAgbGVmdDogeCAtIF9taW5SICsgJ3B4JyxcbiAgICAgIHdpZHRoOiAyICogX21pblIgKyAncHgnLFxuICAgICAgaGVpZ2h0OiAyICogX21pblIgKyAncHgnXG4gICAgfSk7XG5cbiAgICByZXR1cm4gX2FuaW1hdG9yLmFuaW1hdGUoX3dhdmUsIHtcbiAgICAgIHRvcDogeSAtIHIsXG4gICAgICBsZWZ0OiB4IC0gcixcbiAgICAgIGhlaWdodDogMiAqIHIsXG4gICAgICB3aWR0aDogMiAqIHJcbiAgICB9LCBkdXJhdGlvbik7XG4gIH1cblxuICBfdXBkYXRlUGFyZW50KCkge1xuICAgIGlmICghdGhpcy5fcGFyZW50VXBkYXRlZCAmJiB0aGlzLnBhcmVudE5vZGUpIHtcbiAgICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLnBhcmVudE5vZGUpO1xuICAgICAgaWYgKGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgncG9zaXRpb24nKSA9PT0gJ3N0YXRpYycpIHtcbiAgICAgICAgdGhpcy5wYXJlbnROb2RlLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICAgIH1cbiAgICAgIHRoaXMuX3BhcmVudFVwZGF0ZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIF9vblRhcChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICB0aGlzLl91cGRhdGVQYXJlbnQoKTtcbiAgICAgIHRoaXMuX3JpcHBsZUFuaW1hdGlvbihlLmdlc3R1cmUuc3JjRXZlbnQpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX3dhdmUpO1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX2JhY2tncm91bmQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX29uSG9sZChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICB0aGlzLl91cGRhdGVQYXJlbnQoKTtcbiAgICAgIHRoaXMuX2hvbGRpbmcgPSB0aGlzLl9yaXBwbGVBbmltYXRpb24oZS5nZXN0dXJlLnNyY0V2ZW50LCAyMDAwKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3JlbGVhc2UnLCB0aGlzLl9ib3VuZE9uUmVsZWFzZSk7XG4gICAgfVxuICB9XG5cbiAgX29uUmVsZWFzZShlKSB7XG4gICAgaWYgKHRoaXMuX2hvbGRpbmcpIHtcbiAgICAgIHRoaXMuX2hvbGRpbmcuc3BlZWQoMzAwKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3Iuc3RvcEFsbCh7c3RvcE5leHQ6IHRydWV9KTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl93YXZlKTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl9iYWNrZ3JvdW5kKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9ob2xkaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX2JvdW5kT25SZWxlYXNlKTtcbiAgfVxuXG4gIF9vbkRyYWdTdGFydChlKSB7XG4gICAgaWYgKHRoaXMuX2hvbGRpbmcpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vblJlbGVhc2UoZSk7XG4gICAgfVxuICAgIGlmIChbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGUuZ2VzdHVyZS5kaXJlY3Rpb24pICE9IC0xKSB7XG4gICAgICB0aGlzLl9vblRhcChlKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9wYXJlbnROb2RlID0gdGhpcy5wYXJlbnROb2RlO1xuICAgIHRoaXMuX2JvdW5kT25UYXAgPSB0aGlzLl9vblRhcC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX2JvdW5kT25Ib2xkID0gdGhpcy5fb25Ib2xkLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRPbkRyYWdTdGFydCA9IHRoaXMuX29uRHJhZ1N0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRPblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcblxuICAgIGlmIChpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICB0aGlzLmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9ib3VuZE9uVGFwKTtcbiAgICAgIHRoaXMuX3BhcmVudE5vZGUuYWRkRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX2JvdW5kT25Ib2xkKTtcbiAgICAgIHRoaXMuX3BhcmVudE5vZGUuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fYm91bmRPbkRyYWdTdGFydCk7XG4gICAgfVxuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29uc3QgcG4gPSB0aGlzLl9wYXJlbnROb2RlIHx8IHRoaXMucGFyZW50Tm9kZTtcbiAgICBwbi5yZW1vdmVFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9ib3VuZE9uVGFwKTtcbiAgICBwbi5yZW1vdmVFdmVudExpc3RlbmVyKCdob2xkJywgdGhpcy5fYm91bmRPbkhvbGQpO1xuICAgIHBuLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMuX2JvdW5kT25EcmFnU3RhcnQpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnc3RhcnQtcmFkaXVzJywgJ2NvbG9yJywgJ2JhY2tncm91bmQnLCAnY2VudGVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnc3RhcnQtcmFkaXVzJykge1xuICAgICAgdGhpcy5fbWluUiA9IE1hdGgubWF4KDAsIHBhcnNlRmxvYXQoY3VycmVudCkgfHwgMCk7XG4gICAgfVxuICAgIGlmIChuYW1lID09PSAnY29sb3InICYmIGN1cnJlbnQpIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX3dhdmUuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnQ7XG4gICAgICAgIGlmICghdGhpcy5oYXNBdHRyaWJ1dGUoJ2JhY2tncm91bmQnKSkge1xuICAgICAgICAgIHRoaXMuX2JhY2tncm91bmQuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAobmFtZSA9PT0gJ2JhY2tncm91bmQnICYmIChjdXJyZW50IHx8IGxhc3QpKSB7XG4gICAgICBpZiAoY3VycmVudCA9PT0gJ25vbmUnKSB7XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zdHlsZS5iYWNrZ3JvdW5kID0gJ3RyYW5zcGFyZW50JztcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLl9iYWNrZ3JvdW5kLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuX2JhY2tncm91bmQuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnQ7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobmFtZSA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHRoaXMuX2NlbnRlciA9IGN1cnJlbnQgIT0gbnVsbCAmJiBjdXJyZW50ICE9ICdmYWxzZSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1yaXBwbGUnLCBSaXBwbGVFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcm93XG4gKiBAY2F0ZWdvcnkgZ3JpZFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1SZXByZXNlbnRzIGEgcm93IGluIHRoZSBncmlkIHN5c3RlbS4gVXNlIHdpdGggYDxvbnMtY29sPmAgdG8gbGF5b3V0IGNvbXBvbmVudHMuWy9lbl1cbiAqICAgW2phXeOCsOODquODg+ODieOCt+OCueODhuODoOOBq+OBpuihjOOCkuWumue+qeOBl+OBvuOBmeOAgm9ucy1jb2zjgajjgajjgoLjgavkvb/nlKjjgZfjgIHjgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7phY3nva7jgavkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gR2d1akMge3dpZGV9XG4gKiBAZ3VpZGUgbGF5b3V0aW5nXG4gKiAgIFtlbl1MYXlvdXRpbmcgZ3VpZGVbL2VuXVxuICogICBbamFd44Os44Kk44Ki44Km44OI6Kq/5pW0Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1jb2xcbiAqICAgW2VuXVRoZSBgPG9ucy1jb2w+YCBjb21wb25lbnQgaXMgdXNlZCBhcyBjaGlsZHJlbiBvZiBgPG9ucy1yb3c+YC5bL2VuXVxuICogICBbamFdb25zLWNvbOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAbm90ZVxuICogICBbZW5dRm9yIEFuZHJvaWQgNC4zIGFuZCBlYXJsaWVyLCBhbmQgaU9TNiBhbmQgZWFybGllciwgd2hlbiB1c2luZyBtaXhlZCBhbGlnbm1lbnQgd2l0aCBvbnMtcm93IGFuZCBvbnMtY29sLCB0aGV5IG1heSBub3QgYmUgZGlzcGxheWVkIGNvcnJlY3RseS4gWW91IGNhbiB1c2Ugb25seSBvbmUgdmVydGljYWwtYWxpZ24uWy9lbl1cbiAqICAgW2phXUFuZHJvaWQgNC4z5Lul5YmN44CB44KC44GX44GP44GvaU9TIDbku6XliY3jga5PU+OBruWgtOWQiOOAgW9ucy1yb3fjgahvbnMtY29s44KS57WE44G/5ZCI44KP44Gb44Gm44Gd44KM44Ge44KM44Gub25zLWNvbOimgee0oOOBrnZlcnRpY2FsLWFsaWdu5bGe5oCn44Gu5YCk44Gr5Yil44CF44Gu5YCk44KS5oyH5a6a44GZ44KL44Go44CB5o+P55S744GM5bSp44KM44KL5aC05ZCI44GM44GC44KK44G+44GZ44CCdmVydGljYWwtYWxpZ27lsZ7mgKfjga7lgKTjgavjga/kuIDjgaTjga7lgKTjgaDjgZHjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtcm93PlxuICogICA8b25zLWNvbCB3aWR0aD1cIjUwcHhcIj48b25zLWljb24gaWNvbj1cImZhLXR3aXR0ZXJcIj48L29ucy1pY29uPjwvb25zLWNvbD5cbiAqICAgPG9ucy1jb2w+VGV4dDwvb25zLWNvbD5cbiAqIDwvb25zLXJvdz5cbiAqL1xuXG4vKipcbiAqIEBhdHRyaWJ1dGUgdmVydGljYWwtYWxpZ25cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNob3J0IGhhbmQgYXR0cmlidXRlIGZvciBhbGlnbmluZyB2ZXJ0aWNhbGx5LiBWYWxpZCB2YWx1ZXMgYXJlIHRvcCwgYm90dG9tLCBhbmQgY2VudGVyLlsvZW5dXG4gKiAgIFtqYV3nuKbjgavmlbTliJfjgZnjgovjgZ/jgoHjgavmjIflrprjgZfjgb7jgZnjgIJ0b3DjgIFib3R0b23jgIFjZW50ZXLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJvd0VsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXJvdycsIFJvd0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3NwZWVkLWRpYWxfX2l0ZW0tLSonLFxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BlZWQtZGlhbC1pdGVtXG4gKiBAY2F0ZWdvcnkgY29udHJvbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGlzIGNvbXBvbmVudCBkaXNwbGF5cyB0aGUgY2hpbGQgZWxlbWVudHMgb2YgdGhlIE1hdGVyaWFsIERlc2lnbiBTcGVlZCBkaWFsIGNvbXBvbmVudC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIE1hdGVyaWFsIERlc2lnbuOBrlNwZWVkIGRpYWzjga7lrZDopoHntKDjgpLooajnj77jgZnjgovopoHntKDjgafjgZnjgIJcbiAqICAgWy9qYV1cbiAqIEBjb2RlcGVuIGRZUVlMZ1xuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwZWVkLWRpYWxcbiAqIEBzZWVhbHNvIG9ucy1zcGVlZC1kaWFsXG4gKiAgIFtlbl1UaGUgYDxvbnMtc3BlZWQtZGlhbD5gIGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdb25zLXNwZWVkLWRpYWzjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWZhYlxuICogICBbZW5db25zLWZhYiBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWZhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGVlZC1kaWFsIHBvc2l0aW9uPVwibGVmdCBib3R0b21cIj5cbiAqICAgPG9ucy1mYWI+XG4gKiAgICAgPG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj5cbiAqICAgPC9vbnMtZmFiPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5BPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5CPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5DPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogPC9vbnMtc3BlZWQtZGlhbD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BlZWREaWFsSXRlbUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBjb21wb25lbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgdGhpcy5fYm91bmRPbkNsaWNrID0gdGhpcy5fb25DbGljay5iaW5kKHRoaXMpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAncmlwcGxlJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gIH1cblxuICBfdXBkYXRlUmlwcGxlKCkge1xuICAgIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMpO1xuICB9XG5cbiAgX29uQ2xpY2soZSkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiJyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLW1pbmknKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3NwZWVkLWRpYWxfX2l0ZW0nKTtcblxuICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwZWVkLWRpYWwtaXRlbScsIFNwZWVkRGlhbEl0ZW1FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbi8qKlxuICogTWluaW1hbCB1dGlsaXR5IGxpYnJhcnkgZm9yIG1hbmlwdWxhdGluZyBlbGVtZW50J3Mgc3R5bGUuXG4gKi9cbmNvbnN0IHN0eWxlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIHN0eWxlKSB7XG4gIHJldHVybiBzdHlsZXIuY3NzLmFwcGx5KHN0eWxlciwgYXJndW1lbnRzKTtcbn07XG5cbi8qKlxuICogU2V0IGVsZW1lbnQncyBzdHlsZS5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZXNcbiAqIEByZXR1cm4ge0VsZW1lbnR9XG4gKi9cbnN0eWxlci5jc3MgPSBmdW5jdGlvbihlbGVtZW50LCBzdHlsZXMpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhzdHlsZXMpO1xuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKGtleSBpbiBlbGVtZW50LnN0eWxlKSB7XG4gICAgICBlbGVtZW50LnN0eWxlW2tleV0gPSBzdHlsZXNba2V5XTtcbiAgICB9IGVsc2UgaWYgKHN0eWxlci5fcHJlZml4KGtleSkgaW4gZWxlbWVudC5zdHlsZSkge1xuICAgICAgZWxlbWVudC5zdHlsZVtzdHlsZXIuX3ByZWZpeChrZXkpXSA9IHN0eWxlc1trZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLndhcm4oJ05vIHN1Y2ggc3R5bGUgcHJvcGVydHk6ICcgKyBrZXkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBBZGQgdmVuZG9yIHByZWZpeC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5zdHlsZXIuX3ByZWZpeCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIHN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJycpO1xuICB2YXIgcHJlZml4ID0gKEFycmF5LnByb3RvdHlwZS5zbGljZVxuICAgIC5jYWxsKHN0eWxlcylcbiAgICAuam9pbignJylcbiAgICAubWF0Y2goLy0obW96fHdlYmtpdHxtcyktLykgfHwgKHN0eWxlcy5PTGluayA9PT0gJycgJiYgWycnLCAnbyddKVxuICApWzFdO1xuXG4gIHJldHVybiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIHByZWZpeCArIG5hbWUuc3Vic3RyKDAsIDEpLnRvVXBwZXJDYXNlKCkgKyBuYW1lLnN1YnN0cigxKTtcbiAgfTtcbn0pKCk7XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKi9cbnN0eWxlci5jbGVhciA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgc3R5bGVyLl9jbGVhcihlbGVtZW50KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKi9cbnN0eWxlci5fY2xlYXIgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gIHZhciBsZW4gPSBlbGVtZW50LnN0eWxlLmxlbmd0aDtcbiAgdmFyIHN0eWxlID0gZWxlbWVudC5zdHlsZTtcbiAgdmFyIGtleXMgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGtleXMucHVzaChzdHlsZVtpXSk7XG4gIH1cblxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgc3R5bGVba2V5XSA9ICcnO1xuICB9KTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHN0eWxlcjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBzdHlsZXIgZnJvbSAnLi4vbGliL3N0eWxlcic7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdzcGVlZC1kaWFsLS0qJyxcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXNwZWVkLWRpYWxcbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIEVsZW1lbnQgdGhhdCBkaXNwbGF5cyBhIE1hdGVyaWFsIERlc2lnbiBTcGVlZCBEaWFsb2cgY29tcG9uZW50LiBJdCBpcyB1c2VmdWwgd2hlbiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSBwcmltYXJ5IGFjdGlvbiB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgaW4gYSBwYWdlLlxuICpcbiAqICAgICBUaGUgU3BlZWQgZGlhbCBsb29rcyBsaWtlIGEgYDxvbnMtZmFiPmAgZWxlbWVudCBidXQgd2lsbCBleHBhbmQgYSBtZW51IHdoZW4gdGFwcGVkLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIGRZUVlMZ1xuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwZWVkLWRpYWxcbiAqIEBzZWVhbHNvIG9ucy1zcGVlZC1kaWFsLWl0ZW1cbiAqICAgW2VuXVRoZSBgPG9ucy1zcGVlZC1kaWFsLWl0ZW0+YCByZXByZXNlbnRzIGEgbWVudSBpdGVtLlsvZW5dXG4gKiAgIFtqYV1vbnMtc3BlZWQtZGlhbC1pdGVt44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1mYWJcbiAqICAgW2VuXW9ucy1mYWIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1mYWLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc3BlZWQtZGlhbCBwb3NpdGlvbj1cImxlZnQgYm90dG9tXCI+XG4gKiAgIDxvbnMtZmFiPlxuICogICAgIDxvbnMtaWNvbiBpY29uPVwiZmEtdHdpdHRlclwiPjwvb25zLWljb24+XG4gKiAgIDwvb25zLWZhYj5cbiAqICAgPG9ucy1zcGVlZC1kaWFsLWl0ZW0+QTwvb25zLXNwZWVkLWRpYWwtaXRlbT5cbiAqICAgPG9ucy1zcGVlZC1kaWFsLWl0ZW0+Qjwvb25zLXNwZWVkLWRpYWwtaXRlbT5cbiAqICAgPG9ucy1zcGVlZC1kaWFsLWl0ZW0+Qzwvb25zLXNwZWVkLWRpYWwtaXRlbT5cbiAqIDwvb25zLXNwZWVkLWRpYWw+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwZWVkRGlhbEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBvcGVuXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCB3aGVuIHRoZSBtZW51IGl0ZW1zIGFyZSBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IGNsb3NlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCB3aGVuIHRoZSBtZW51IGl0ZW1zIGFyZSBoaWRkZW4uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBjb21wb25lbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgdmVydGljYWwgYW5kIGhvcml6b250YWwgcG9zaXRpb24gb2YgdGhlIGNvbXBvbmVudC5cbiAgICogICAgIEkuZS4gdG8gZGlzcGxheSBpdCBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBzcGVjaWZ5IFwicmlnaHQgdG9wXCIuXG4gICAqICAgICBDaG9vc2UgZnJvbSBcInJpZ2h0XCIsIFwibGVmdFwiLCBcInRvcFwiIGFuZCBcImJvdHRvbVwiLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44GT44Gu6KaB57Sg44KS6KGo56S644GZ44KL5bem5Y+z44Go5LiK5LiL44Gu5L2N572u44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDkvovjgYjjgbDjgIHlj7PkuIrjgavooajnpLrjgZnjgovloLTlkIjjgavjga9cInJpZ2h0IHRvcFwi44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDlt6blj7PjgajkuIrkuIvjga7kvY3nva7jga7mjIflrprjgavjga/jgIFyaWdodOOBqGxlZnTjgIF0b3Djgahib3R0b23jgYzjgZ3jgozjgZ7jgozmjIflrprjgafjgY3jgb7jgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGRpcmVjdGlvbiB0aGUgaXRlbXMgYXJlIGRpc3BsYXllZC4gUG9zc2libGUgdmFsdWVzIGFyZSBcInVwXCIsIFwiZG93blwiLCBcImxlZnRcIiBhbmQgXCJyaWdodFwiLlsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg6KaB57Sg44GM6KGo56S644GZ44KL5pa55ZCR44KS5oyH5a6a44GX44G+44GZ44CCdXAsIGRvd24sIGxlZnQsIHJpZ2h044GM5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZnjgovloLTlkIjjgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLl9zaG93biA9IHRydWU7XG4gICAgdGhpcy5faXRlbVNob3duID0gZmFsc2U7XG4gICAgdGhpcy5fYm91bmRPbkNsaWNrID0gdGhpcy5fb25DbGljay5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKCF0aGlzLmNsYXNzTGlzdC5jb250YWlucygnc3BlZWRfX2RpYWwnKSkge1xuICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdzcGVlZF9fZGlhbCcpO1xuICAgICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcblxuICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdkaXJlY3Rpb24nKSkge1xuICAgICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24odGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZURpcmVjdGlvbigndXAnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAncmlwcGxlJywgJ2RpcmVjdGlvbicsICdwb3NpdGlvbiddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZVJpcHBsZSgpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkaXJlY3Rpb24nOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fdXBkYXRlRGlyZWN0aW9uKGN1cnJlbnQpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVQb3NpdGlvbigpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZ2V0IGl0ZW1zKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLnF1ZXJ5U2VsZWN0b3JBbGwoJ29ucy1zcGVlZC1kaWFsLWl0ZW0nKSk7XG4gIH1cblxuICBfb25DbGljayhlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkICYmIHRoaXMuX3Nob3duKSB7XG4gICAgICB0aGlzLnRvZ2dsZUl0ZW1zKCk7XG4gICAgfVxuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgaWYgKCF0aGlzLmlubGluZSkge1xuICAgICAgdGhpcy5zaG93KCk7XG4gICAgfVxuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgaWYgKCF0aGlzLmlubGluZSkge1xuICAgICAgdGhpcy5oaWRlKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVJpcHBsZSgpIHtcbiAgICBjb25zdCBmYWIgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLWZhYicpO1xuXG4gICAgaWYgKGZhYikge1xuICAgICAgdGhpcy5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpID8gZmFiLnNldEF0dHJpYnV0ZSgncmlwcGxlJywgJycpIDogZmFiLnJlbW92ZUF0dHJpYnV0ZSgncmlwcGxlJyk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZURpcmVjdGlvbihkaXJlY3Rpb24pIHtcbiAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuaXRlbXM7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgc3R5bGVyKGNoaWxkcmVuW2ldLCB7XG4gICAgICAgIHRyYW5zaXRpb25EZWxheTogMjUgKiBpICsgJ21zJyxcbiAgICAgICAgYm90dG9tOiAnYXV0bycsXG4gICAgICAgIHJpZ2h0OiAnYXV0bycsXG4gICAgICAgIHRvcDogJ2F1dG8nLFxuICAgICAgICBsZWZ0OiAnYXV0bydcbiAgICAgIH0pO1xuICAgIH1cbiAgICBzd2l0Y2ggKGRpcmVjdGlvbikge1xuICAgICAgY2FzZSAndXAnOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUuYm90dG9tID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLnJpZ2h0ID0gJzhweCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkb3duJzpcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLnRvcCA9IDcyICsgNTYgKiBpICsgJ3B4JztcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS5sZWZ0ID0gJzhweCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLnRvcCA9ICc4cHgnO1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLnJpZ2h0ID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gJzhweCc7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUubGVmdCA9IDcyICsgNTYgKiBpICsgJ3B4JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdXAsIGRvd24sIGxlZnQgb3IgcmlnaHQuJyk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKCkge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJyk7XG4gICAgdGhpcy5jbGFzc0xpc3QucmVtb3ZlKFxuICAgICAgJ2ZhYi0tdG9wX19sZWZ0JyxcbiAgICAgICdmYWItLWJvdHRvbV9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19sZWZ0JyxcbiAgICAgICdmYWItLXRvcF9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tdG9wX19jZW50ZXInLFxuICAgICAgJ2ZhYi0tYm90dG9tX19jZW50ZXInKTtcbiAgICBzd2l0Y2gocG9zaXRpb24pIHtcbiAgICAgIGNhc2UgJ3RvcCByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCB0b3AnOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RvcCBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCBib3R0b20nOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciB0b3AnOlxuICAgICAgY2FzZSAndG9wIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciBib3R0b20nOlxuICAgICAgY2FzZSAnYm90dG9tIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgdGhlIHNwZWVkIGRpYWwuWy9lbl1cbiAgICogICBbamFdU3BlZWQgZGlhbOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBzaG93KG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWZhYicpLnNob3coKTtcbiAgICB0aGlzLl9zaG93biA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBzcGVlZCBkaWFsLlsvZW5dXG4gICAqICAgW2phXVNwZWVkIGRpYWzjgpLpnZ7ooajnpLrjgavjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgaGlkZShvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmhpZGVJdGVtcygpO1xuICAgIHNldFRpbWVvdXQoKCk9PntcbiAgICAgIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWZhYicpLmhpZGUoKTtcbiAgICB9LCAyMDApO1xuICAgIHRoaXMuX3Nob3duID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93SXRlbXNcbiAgICogQHNpZ25hdHVyZSBzaG93SXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgc3BlZWQgZGlhbCBpdGVtcy5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNob3dJdGVtcygpIHtcblxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnZGlyZWN0aW9uJykpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURpcmVjdGlvbih0aGlzLmdldEF0dHJpYnV0ZSgnZGlyZWN0aW9uJykpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24oJ3VwJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl9pdGVtU2hvd24pIHtcbiAgICAgIGNvbnN0IGNoaWxkcmVuID0gdGhpcy5pdGVtcztcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3R5bGVyKGNoaWxkcmVuW2ldLCB7XG4gICAgICAgICAgdHJhbnNmb3JtOiAnc2NhbGUoMSknLFxuICAgICAgICAgIHRyYW5zaXRpb25EZWxheTogMjUgKiBpICsgJ21zJ1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5faXRlbVNob3duID0gdHJ1ZTtcblxuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnb3BlbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZUl0ZW1zXG4gICAqIEBzaWduYXR1cmUgaGlkZUl0ZW1zKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdGhlIHNwZWVkIGRpYWwgaXRlbXMuWy9lbl1cbiAgICogICBbamFdU3BlZWQgZGlhbOOBruWtkOimgee0oOOCkumdnuihqOekuuOBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBoaWRlSXRlbXMoKSB7XG4gICAgaWYgKHRoaXMuX2l0ZW1TaG93bikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBzdHlsZXIoY2hpbGRyZW5baV0sIHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZSgwKScsXG4gICAgICAgICAgdHJhbnNpdGlvbkRlbGF5OiAyNSAqIChjaGlsZHJlbi5sZW5ndGggLSBpKSArICdtcydcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuX2l0ZW1TaG93biA9IGZhbHNlO1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnY2xvc2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLmhpZGVJdGVtcygpO1xuICAgIH1cbiAgICB1dGlsLmFycmF5RnJvbSh0aGlzLmNoaWxkcmVuKS5mb3JFYWNoKGUgPT4ge1xuICAgICAgdXRpbC5tYXRjaChlLCAnLmZhYicpICYmIHV0aWwudG9nZ2xlQXR0cmlidXRlKGUsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmxpbmVcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBpbmxpbmUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeOCpOODs+ODqeOCpOODs+imgee0oOOBruWgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgaW5saW5lKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnaW5saW5lJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZpc2libGVcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHZpc2libGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Nob3duICYmIHRoaXMuc3R5bGUuZGlzcGxheSAhPT0gJ25vbmUnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNPcGVuXG4gICAqIEBzaWduYXR1cmUgaXNPcGVuKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgbWVudSBpcyBvcGVuIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgaXNPcGVuKCkge1xuICAgIHJldHVybiB0aGlzLl9pdGVtU2hvd247XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIHZpc2liaWxpdHkuWy9lbl1cbiAgICogICBbamFdU3BlZWQgZGlhbOOBruihqOekuumdnuihqOekuuOCkuWIh+OCiuabv+OBiOOBvuOBmeOAglsvamFdXG4gICAqL1xuICB0b2dnbGUoKSB7XG4gICAgdGhpcy52aXNpYmxlID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZUl0ZW1zXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlSXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIGl0ZW0gdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44Gu6KGo56S66Z2e6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZUl0ZW1zKCkge1xuICAgIGlmICh0aGlzLmlzT3BlbigpKSB7XG4gICAgICB0aGlzLmhpZGVJdGVtcygpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNob3dJdGVtcygpO1xuICAgIH1cbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zcGVlZC1kaWFsJywgU3BlZWREaWFsRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vb25zL2ludGVybmFsJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IHtQYWdlTG9hZGVyLCBkZWZhdWx0UGFnZUxvYWRlcn0gZnJvbSAnLi4vb25zL3BhZ2UtbG9hZGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCByZXdyaXRhYmxlcyA9IHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkoZWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBzZXRJbW1lZGlhdGUoY2FsbGJhY2spO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtIVE1MRnJhZ21lbnR9IHRhcmdldFxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgbGluayhlbGVtZW50LCB0YXJnZXQsIG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sodGFyZ2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BsaXR0ZXItY29udGVudFxuICogQGNhdGVnb3J5IG1lbnVcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIFRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgZWxlbWVudCBpcyB1c2VkIGFzIGEgY2hpbGQgZWxlbWVudCBvZiBgPG9ucy1zcGxpdHRlcj5gLlxuICpcbiAqICAgIEl0IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2Ugd2hpbGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbnRhaW5zIHRoZSBsaXN0LlxuICogIFsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1jb250ZW506KaB57Sg44Gv44CBb25zLXNwbGl0dGVy6KaB57Sg44Gu5a2Q6KaB57Sg44Go44GX44Gm5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgbXVsdGlwbGUtcGFnZS1uYXZpZ2F0aW9uXG4gKiAgW2VuXU1hbmFnaW5nIG11bHRpcGxlIHBhZ2VzLlsvZW5dXG4gKiAgW2phXU1hbmFnaW5nIG11bHRpcGxlIHBhZ2VzWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlclxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBjb21wb25lbnQgaXMgdGhlIHBhcmVudCBlbGVtZW50LlsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXItc2lkZVxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbXBvbmVudCBjb250YWlucyB0aGUgbWVudS5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItc2lkZeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGxpdHRlcj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlckNvbnRlbnRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHVybCBvZiB0aGUgY29udGVudCBwYWdlLiBJZiB0aGlzIGF0dHJpYnV0ZSBpcyB1c2VkIHRoZSBjb250ZW50IHdpbGwgYmUgbG9hZGVkIGZyb20gYSBgPG9ucy10ZW1wbGF0ZT5gIHRhZyBvciBhIHJlbW90ZSBmaWxlLlxuICAgKlxuICAgKiAgICAgSXQgaXMgYWxzbyBwb3NzaWJsZSB0byBwdXQgYDxvbnMtcGFnZT5gIGVsZW1lbnQgYXMgYSBjaGlsZCBvZiB0aGUgZWxlbWVudC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1vbnMtc3BsaXR0ZXItY29udGVudOimgee0oOOBq+ihqOekuuOBmeOCi+ODmuODvOOCuOOBrlVSTOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fcGFnZSA9IG51bGw7XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGRlZmF1bHRQYWdlTG9hZGVyO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLl9nZXRQYWdlVGFyZ2V0KCk7XG5cbiAgICAgIGlmIChwYWdlKSB7XG4gICAgICAgIHRoaXMubG9hZChwYWdlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICghdXRpbC5tYXRjaCh0aGlzLnBhcmVudE5vZGUsICdvbnMtc3BsaXR0ZXInKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBcIm9ucy1zcGxpdHRlci1jb250ZW50XCIgbXVzdCBoYXZlIFwib25zLXNwbGl0dGVyXCIgYXMgcGFyZW50Tm9kZS5gKTtcbiAgICB9XG4gIH1cblxuICBfZ2V0UGFnZVRhcmdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZSB8fCB0aGlzLmdldEF0dHJpYnV0ZSgncGFnZScpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7fVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHBhZ2UgdG8gbG9hZCBpbiB0aGUgc3BsaXR0ZXIgY29udGVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDlhoXjgavooajnpLrjgZnjgovjg5rjg7zjgrjjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHsqfSBwYWdlXG4gICAqL1xuICBzZXQgcGFnZShwYWdlKSB7XG4gICAgdGhpcy5fcGFnZSA9IHBhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VMb2FkZXJcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGFnZSBlbGVtZW50IGxvYWRlZCBpbiB0aGUgc3BsaXR0ZXIgY29udGVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDlhoXjgavooajnpLrjgZnjgovjg5rjg7zjgrjjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihsb2FkZXIpIHtcbiAgICBpZiAoIShsb2FkZXIgaW5zdGFuY2VvZiBQYWdlTG9hZGVyKSkge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ZpcnN0IHBhcmFtZXRlciBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIFBhZ2VMb2FkZXInKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGxvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGxvYWRcbiAgICogQHNpZ25hdHVyZSBsb2FkKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhZ2UsIFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGRvY3VtZW50IG9yIGFuIGA8b25zLXRlbXBsYXRlPmAgaWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgW9ucy10ZW1wbGF0ZeOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgdGhlIHBhZ2Ugc3BlY2lmaWVkIGluIGBwYWdlYCBpbiB0aGUgY29udGVudC5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ9VUkzjgpLjg6HjgqTjg7Pjg5rjg7zjgrjjgpLoqq3jgb/ovrzjgb/jgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgbmV3IGA8b25zLXBhZ2U+YCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdYDxvbnMtcGFnZT5g6KaB57Sg44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsb2FkKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlLCBwYXJlbnQ6IHRoaXMsIHJlcGxhY2U6IHRydWV9LCAoe2VsZW1lbnQsIHVubG9hZH0pID0+IHtcbiAgICAgICAgcmV3cml0YWJsZXMubGluayh0aGlzLCBlbGVtZW50LCBvcHRpb25zLCBmcmFnbWVudCA9PiB7XG4gICAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcblxuICAgICAgICAgIHJlc29sdmUodGhpcy5maXJzdENoaWxkKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfc2hvdycpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbih0aGlzLCAnX2Rlc3Ryb3knKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCByZXdyaXRhYmxlcygpIHtcbiAgICByZXR1cm4gcmV3cml0YWJsZXM7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXItY29udGVudCcsIFNwbGl0dGVyQ29udGVudEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlck1hc2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fYm91bmRPbkNsaWNrID0gdGhpcy5fb25DbGljay5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX29uQ2xpY2soZXZlbnQpIHtcbiAgICBpZiAodXRpbC5tYXRjaCh0aGlzLnBhcmVudE5vZGUsICdvbnMtc3BsaXR0ZXInKSkge1xuICAgICAgdGhpcy5wYXJlbnROb2RlLl9zaWRlcy5mb3JFYWNoKHNpZGUgPT4gc2lkZS5jbG9zZSgnbGVmdCcpLmNhdGNoKCgpID0+IHt9KSk7XG4gICAgfVxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2spO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljayk7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXItbWFzaycsIFNwbGl0dGVyTWFza0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwbGl0dGVyQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX29wdGlvbnMgPSB7XG4gICAgICB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLFxuICAgICAgZHVyYXRpb246ICcwLjMnLFxuICAgICAgZGVsYXk6ICcwJ1xuICAgIH07XG4gICAgdGhpcy51cGRhdGVPcHRpb25zKG9wdGlvbnMpO1xuICB9XG5cbiAgdXBkYXRlT3B0aW9ucyhvcHRpb25zID0ge30pIHtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLl9vcHRpb25zLCBvcHRpb25zKTtcbiAgICB0aGlzLl90aW1pbmcgPSB0aGlzLl9vcHRpb25zLnRpbWluZztcbiAgICB0aGlzLl9kdXJhdGlvbiA9IHRoaXMuX29wdGlvbnMuZHVyYXRpb247XG4gICAgdGhpcy5fZGVsYXkgPSB0aGlzLl9vcHRpb25zLmRlbGF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gc2lkZUVsZW1lbnRcbiAgICovXG4gIGFjdGl2YXRlKHNpZGVFbGVtZW50KSB7XG4gICAgY29uc3Qgc3BsaXR0ZXIgPSBzaWRlRWxlbWVudC5wYXJlbnROb2RlO1xuXG4gICAgY29udGVudFJlYWR5KHNwbGl0dGVyLCAoKSA9PiB7XG4gICAgICB0aGlzLl9zaWRlID0gc2lkZUVsZW1lbnQ7XG4gICAgICB0aGlzLl9jb250ZW50ID0gc3BsaXR0ZXIuY29udGVudDtcbiAgICAgIHRoaXMuX21hc2sgPSBzcGxpdHRlci5tYXNrO1xuICAgIH0pO1xuICB9XG5cbiAgaW5hY3RpdmF0ZSgpIHtcbiAgICB0aGlzLl9jb250ZW50ID0gdGhpcy5fc2lkZSA9IHRoaXMuX21hc2sgPSBudWxsO1xuICB9XG5cbiAgZ2V0IG1pbnVzKCkge1xuICAgIHJldHVybiB0aGlzLl9zaWRlLl9zaWRlID09PSAncmlnaHQnID8gJy0nIDogJyc7XG4gIH1cblxuICB0cmFuc2xhdGUoZGlzdGFuY2UpIHtcbiAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgIC5xdWV1ZSh7XG4gICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5taW51cyArIGRpc3RhbmNlfXB4LCAwcHgsIDBweClgXG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRoaXMuX3NpZGUpXG4gICAgICAgIC53YWl0KHRoaXMuX2RlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5taW51c30xMDAlLCAwcHgsIDBweClgXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5fZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLl90aW1pbmdcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKGNhbGxiYWNrID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX21hc2spXG4gICAgICAgIC53YWl0KHRoaXMuX2RlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBvcGFjaXR5OiAnMSdcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLl9kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zaWRlKVxuICAgICAgICAud2FpdCh0aGlzLl9kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwcHgsIDBweCwgMHB4KSdcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLl9kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMuX3RpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucXVldWUoY2FsbGJhY2sgPT4ge1xuICAgICAgICAgIHRoaXMuX3NpZGUuc3R5bGUud2Via2l0VHJhbnNpdGlvbiA9ICcnO1xuICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQodGhpcy5fbWFzaylcbiAgICAgICAgLndhaXQodGhpcy5fZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogJzAnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5fZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiAnbGluZWFyJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBkaXNwbGF5OiAnbm9uZSdcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IFNwbGl0dGVyQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICBkZWZhdWx0OiBTcGxpdHRlckFuaW1hdG9yLFxuICBvdmVybGF5OiBTcGxpdHRlckFuaW1hdG9yXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zcGxpdHRlclxuICogQGNhdGVnb3J5IG1lbnVcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIEEgY29tcG9uZW50IHRoYXQgZW5hYmxlcyByZXNwb25zaXZlIGxheW91dCBieSBpbXBsZW1lbnRpbmcgYm90aCBhIHR3by1jb2x1bW4gbGF5b3V0IGFuZCBhIHNsaWRpbmcgbWVudSBsYXlvdXQuXG4gKlxuICogICAgSXQgY2FuIGJlIGNvbmZpZ3VyZWQgdG8gYXV0b21hdGljYWxseSBleHBhbmQgaW50byBhIGNvbHVtbiBsYXlvdXQgb24gbGFyZ2Ugc2NyZWVucyBhbmQgY29sbGFwc2UgdGhlIG1lbnUgb24gc21hbGxlciBzY3JlZW5zLiBXaGVuIHRoZSBtZW51IGlzIGNvbGxhcHNlZCB0aGUgdXNlciBjYW4gb3BlbiBpdCBieSBzd2lwaW5nLlxuICogIFsvZW5dXG4gKiAgW2phXVsvamFdXG4gKiBAY29kZXBlbiByT1FPTUxcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9zcGxpdHRlclxuICogQGd1aWRlIG11bHRpcGxlLXBhZ2UtbmF2aWdhdGlvblxuICogIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogIFtqYV1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlc1svamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXItY29udGVudFxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXItY29udGVudD5gIGNvbXBvbmVudCBjb250YWlucyB0aGUgbWFpbiBjb250ZW50IG9mIHRoZSBwYWdlLlsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1jb250ZW5044Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlci1zaWRlXG4gKiAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlci1zaWRlPmAgY29tcG9uZW50IGNvbnRhaW5zIHRoZSBtZW51LlsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1zaWRl44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNwbGl0dGVyIGlkPVwic3BsaXR0ZXJcIj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZSBzd2lwZWFibGU+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLXNwbGl0dGVyLXNpZGU+XG4gKiA8L29ucy1zcGxpdHRlcj5cbiAqXG4gKiA8c2NyaXB0PlxuICogICB2YXIgc3BsaXR0ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3BsaXR0ZXInKTtcbiAqICAgc3BsaXR0ZXIubGVmdC5vcGVuKCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BsaXR0ZXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIF9nZXRTaWRlKHNpZGUpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgZSA9PiB7XG4gICAgICByZXR1cm4gdXRpbC5tYXRjaChlLCAnb25zLXNwbGl0dGVyLXNpZGUnKSAmJiBlLmdldEF0dHJpYnV0ZSgnc2lkZScpID09PSBzaWRlO1xuICAgIH0pO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBsZWZ0XG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1MZWZ0IGA8b25zLXNwbGl0dGVyLXNpZGU+YCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgbGVmdCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U2lkZSgnbGVmdCcpO1xuICB9XG4gIC8qKlxuICAgKiBAcHJvcGVydHkgcmlnaHRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJpZ2h0IGA8b25zLXNwbGl0dGVyLXNpZGU+YCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgcmlnaHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFNpZGUoJ3JpZ2h0Jyk7XG4gIH1cblxuICBnZXQgX3NpZGVzKCkge1xuICAgIHJldHVybiBbdGhpcy5sZWZ0LCB0aGlzLnJpZ2h0XS5maWx0ZXIoZSA9PiBlKTtcbiAgfVxuICAvKipcbiAgICogQHByb3BlcnR5IGNvbnRlbnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IGNvbnRlbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtc3BsaXR0ZXItY29udGVudCcpO1xuICB9XG5cbiAgZ2V0IG1hc2soKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtc3BsaXR0ZXItbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgdGhpcy5fc2lkZXMuc29tZShzID0+IHMuaXNPcGVuID8gcy5jbG9zZSgpIDogZmFsc2UpIHx8IGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gIH1cblxuICBfb25Nb2RlQ2hhbmdlKGUpIHtcbiAgICBpZiAoZS50YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fbGF5b3V0KCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfbGF5b3V0KCkge1xuICAgIHRoaXMuX3NpZGVzLmZvckVhY2goc2lkZSA9PiB7XG4gICAgICB0aGlzLmNvbnRlbnQuc3R5bGVbc2lkZS5zaWRlXSA9IHNpZGUubW9kZSA9PT0gJ3NwbGl0JyA/IHNpZGUuX3dpZHRoIDogMDtcbiAgICB9KTtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fYm91bmRPbk1vZGVDaGFuZ2UgPSB0aGlzLl9vbk1vZGVDaGFuZ2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgICB0aGlzLl9sYXlvdXQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGlmICghdGhpcy5tYXNrKSB7XG4gICAgICB0aGlzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29ucy1zcGxpdHRlci1tYXNrJykpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMub25EZXZpY2VCYWNrQnV0dG9uID0gdGhpcy5fb25EZXZpY2VCYWNrQnV0dG9uLmJpbmQodGhpcyk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdtb2RlY2hhbmdlJywgdGhpcy5fYm91bmRPbk1vZGVDaGFuZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IG51bGw7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb2RlY2hhbmdlJywgdGhpcy5fYm91bmRPbk1vZGVDaGFuZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7fVxuXG4gIF9zaG93KCkge1xuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfc2hvdycpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbih0aGlzLCAnX2Rlc3Ryb3knKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvciBpbnN0YW5jZW9mIFNwbGl0dGVyQW5pbWF0b3IpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FuaW1hdG9yIHBhcmFtZXRlciBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIFNwbGl0dGVyQW5pbWF0b3IuJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgU3BsaXR0ZXJBbmltYXRvcigpIHtcbiAgICByZXR1cm4gU3BsaXR0ZXJBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwbGl0dGVyJywgU3BsaXR0ZXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IG9yaWVudGF0aW9uIGZyb20gJy4uL29ucy9vcmllbnRhdGlvbic7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vb25zL2ludGVybmFsJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IFNwbGl0dGVyQW5pbWF0b3IgZnJvbSAnLi9vbnMtc3BsaXR0ZXIvYW5pbWF0b3InO1xuaW1wb3J0IEdlc3R1cmVEZXRlY3RvciBmcm9tICcuLi9vbnMvZ2VzdHVyZS1kZXRlY3Rvcic7XG5pbXBvcnQgRG9vckxvY2sgZnJvbSAnLi4vb25zL2Rvb3Jsb2NrJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IHsgUGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXJ9IGZyb20gJy4uL29ucy9wYWdlLWxvYWRlcic7XG5pbXBvcnQgU3BsaXR0ZXJFbGVtZW50IGZyb20gJy4vb25zLXNwbGl0dGVyJztcblxuY29uc3QgU1BMSVRfTU9ERSA9ICdzcGxpdCc7XG5jb25zdCBDT0xMQVBTRV9NT0RFID0gJ2NvbGxhcHNlJztcbmNvbnN0IENMT1NFRF9TVEFURSA9ICdjbG9zZWQnO1xuY29uc3QgT1BFTl9TVEFURSA9ICdvcGVuJztcbmNvbnN0IENIQU5HSU5HX1NUQVRFID0gJ2NoYW5naW5nJztcblxuY29uc3QgV0FUQ0hFRF9BVFRSSUJVVEVTID0gWydhbmltYXRpb24nLCAnd2lkdGgnLCAnc2lkZScsICdjb2xsYXBzZScsICdzd2lwZWFibGUnLCAnc3dpcGUtdGFyZ2V0LXdpZHRoJywgJ2FuaW1hdGlvbi1vcHRpb25zJywgJ29wZW4tdGhyZXNob2xkJ107XG5cblxuY29uc3QgcmV3cml0YWJsZXMgPSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHNwbGl0dGVyU2lkZUVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHJlYWR5KHNwbGl0dGVyU2lkZUVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgc2V0SW1tZWRpYXRlKGNhbGxiYWNrKTtcbiAgfSxcblxuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBzcGxpdHRlclNpZGVFbGVtZW50XG4gICAqIEBwYXJhbSB7SFRNTEZyYWdtZW50fSB0YXJnZXRcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGxpbmsoc3BsaXR0ZXJTaWRlRWxlbWVudCwgdGFyZ2V0LCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKHRhcmdldCk7XG4gIH1cbn07XG5cbmNsYXNzIENvbGxhcHNlRGV0ZWN0aW9uIHtcbiAgY29uc3RydWN0b3IoZWxlbWVudCwgdGFyZ2V0KSB7XG4gICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgdGhpcy5fYm91bmRPbkNoYW5nZSA9IHRoaXMuX29uQ2hhbmdlLmJpbmQodGhpcyk7XG4gICAgdGFyZ2V0ICYmIHRoaXMuY2hhbmdlVGFyZ2V0KHRhcmdldCk7XG4gIH1cblxuICBjaGFuZ2VUYXJnZXQodGFyZ2V0KSB7XG4gICAgdGhpcy5kaXNhYmxlKCk7XG4gICAgdGhpcy5fdGFyZ2V0ID0gdGFyZ2V0O1xuICAgIGlmICh0YXJnZXQpIHtcbiAgICAgIHRoaXMuX29yaWVudGF0aW9uID0gWydwb3J0cmFpdCcsICdsYW5kc2NhcGUnXS5pbmRleE9mKHRhcmdldCkgIT09IC0xO1xuICAgICAgdGhpcy5hY3RpdmF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIF9tYXRjaCh2YWx1ZSkge1xuICAgIGlmICh0aGlzLl9vcmllbnRhdGlvbikge1xuICAgICAgcmV0dXJuIHRoaXMuX3RhcmdldCA9PT0gKHZhbHVlLmlzUG9ydHJhaXQgPyAncG9ydHJhaXQnIDogJ2xhbmRzY2FwZScpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUubWF0Y2hlcztcbiAgfVxuXG4gIF9vbkNoYW5nZSh2YWx1ZSkge1xuICAgIHRoaXMuX2VsZW1lbnQuX3VwZGF0ZU1vZGUodGhpcy5fbWF0Y2godmFsdWUpID8gQ09MTEFQU0VfTU9ERSA6IFNQTElUX01PREUpO1xuICB9XG5cbiAgYWN0aXZhdGUoKSB7XG4gICAgaWYgKHRoaXMuX29yaWVudGF0aW9uKSB7XG4gICAgICBvcmllbnRhdGlvbi5vbignY2hhbmdlJywgdGhpcy5fYm91bmRPbkNoYW5nZSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh7aXNQb3J0cmFpdDogb3JpZW50YXRpb24uaXNQb3J0cmFpdCgpfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0ID0gd2luZG93Lm1hdGNoTWVkaWEodGhpcy5fdGFyZ2V0KTtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0LmFkZExpc3RlbmVyKHRoaXMuX2JvdW5kT25DaGFuZ2UpO1xuICAgICAgdGhpcy5fb25DaGFuZ2UodGhpcy5fcXVlcnlSZXN1bHQpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2FibGUoKSB7XG4gICAgaWYgKHRoaXMuX29yaWVudGF0aW9uKSB7XG4gICAgICBvcmllbnRhdGlvbi5vZmYoJ2NoYW5nZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fcXVlcnlSZXN1bHQpIHtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0LnJlbW92ZUxpc3RlbmVyKHRoaXMuX2JvdW5kT25DaGFuZ2UpO1xuICAgICAgdGhpcy5fcXVlcnlSZXN1bHQgPSBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCB3aWR0aFRvUHggPSAod2lkdGgsIHBhcmVudCkgPT4ge1xuICBjb25zdCBbdmFsdWUsIHB4XSA9IFtwYXJzZUludCh3aWR0aCwgMTApLCAvcHgvLnRlc3Qod2lkdGgpXTtcbiAgcmV0dXJuIHB4ID8gdmFsdWUgOiBNYXRoLnJvdW5kKHBhcmVudC5vZmZzZXRXaWR0aCAqIHZhbHVlIC8gMTAwKTtcbn07XG5cbmNsYXNzIENvbGxhcHNlTW9kZSB7XG4gIGdldCBfYW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQuX2FuaW1hdG9yO1xuICB9XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudCkge1xuICAgIHRoaXMuX2FjdGl2ZSA9IGZhbHNlO1xuICAgIHRoaXMuX3N0YXRlID0gQ0xPU0VEX1NUQVRFO1xuICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMuX2xvY2sgPSBuZXcgRG9vckxvY2soKTtcbiAgfVxuXG4gIGlzT3BlbigpIHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlICYmIHRoaXMuX3N0YXRlICE9PSBDTE9TRURfU1RBVEU7XG4gIH1cblxuICBoYW5kbGVHZXN0dXJlKGUpIHtcbiAgICBpZiAoIXRoaXMuX2FjdGl2ZSB8fCB0aGlzLl9sb2NrLmlzTG9ja2VkKCkgfHwgdGhpcy5faXNPcGVuT3RoZXJTaWRlTWVudSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChlLnR5cGUgPT09ICdkcmFnc3RhcnQnKSB7XG4gICAgICB0aGlzLl9vbkRyYWdTdGFydChlKTtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICBlLnR5cGUgPT09ICdkcmFnZW5kJyA/IHRoaXMuX29uRHJhZ0VuZChlKSA6IHRoaXMuX29uRHJhZyhlKTtcbiAgICB9XG4gIH1cblxuICBfb25EcmFnU3RhcnQoZXZlbnQpIHtcbiAgICBjb25zdCBzY3JvbGxpbmcgPSAhL2xlZnR8cmlnaHQvLnRlc3QoZXZlbnQuZ2VzdHVyZS5kaXJlY3Rpb24pO1xuICAgIGNvbnN0IGRpc3RhbmNlID0gdGhpcy5fZWxlbWVudC5fc2lkZSA9PT0gJ2xlZnQnID8gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WCA6IHdpbmRvdy5pbm5lcldpZHRoIC0gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WDtcbiAgICBjb25zdCBhcmVhID0gdGhpcy5fZWxlbWVudC5fc3dpcGVUYXJnZXRXaWR0aDtcbiAgICBjb25zdCBpc09wZW4gPSB0aGlzLmlzT3BlbigpO1xuICAgIHRoaXMuX2lnbm9yZURyYWcgPSBzY3JvbGxpbmcgfHwgKGFyZWEgJiYgZGlzdGFuY2UgPiBhcmVhICYmICFpc09wZW4pO1xuXG4gICAgdGhpcy5fd2lkdGggPSB3aWR0aFRvUHgodGhpcy5fZWxlbWVudC5fd2lkdGgsIHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZSk7XG4gICAgdGhpcy5fc3RhcnREaXN0YW5jZSA9IHRoaXMuX2Rpc3RhbmNlID0gaXNPcGVuID8gdGhpcy5fd2lkdGggOiAwO1xuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGV2ZW50Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCBkZWx0YSA9IHRoaXMuX2VsZW1lbnQuX3NpZGUgPT09ICdsZWZ0JyA/IGV2ZW50Lmdlc3R1cmUuZGVsdGFYIDogLWV2ZW50Lmdlc3R1cmUuZGVsdGFYO1xuICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odGhpcy5fd2lkdGgsIHRoaXMuX3N0YXJ0RGlzdGFuY2UgKyBkZWx0YSkpO1xuICAgIGlmIChkaXN0YW5jZSAhPT0gdGhpcy5fZGlzdGFuY2UpIHtcbiAgICAgIHRoaXMuX2FuaW1hdG9yLnRyYW5zbGF0ZShkaXN0YW5jZSk7XG4gICAgICB0aGlzLl9kaXN0YW5jZSA9IGRpc3RhbmNlO1xuICAgICAgdGhpcy5fc3RhdGUgPSBDSEFOR0lOR19TVEFURTtcbiAgICB9XG4gIH1cblxuICBfb25EcmFnRW5kKGV2ZW50KSB7XG4gICAgY29uc3Qge19kaXN0YW5jZTogZGlzdGFuY2UsIF93aWR0aDogd2lkdGgsIF9lbGVtZW50OiBlbH0gPSB0aGlzO1xuICAgIGNvbnN0IGRpcmVjdGlvbiA9IGV2ZW50Lmdlc3R1cmUuaW50ZXJpbURpcmVjdGlvbjtcbiAgICBjb25zdCBzaG91bGRPcGVuID0gZWwuX3NpZGUgIT09IGRpcmVjdGlvbiAmJiBkaXN0YW5jZSA+IHdpZHRoICogZWwuX3RocmVzaG9sZDtcbiAgICB0aGlzLmV4ZWN1dGVBY3Rpb24oc2hvdWxkT3BlbiA/ICdvcGVuJyA6ICdjbG9zZScpO1xuICAgIHRoaXMuX2lnbm9yZURyYWcgPSB0cnVlO1xuICB9XG5cbiAgbGF5b3V0KCkge1xuICAgIGlmICh0aGlzLl9hY3RpdmUgJiYgdGhpcy5fc3RhdGUgPT09IE9QRU5fU1RBVEUpIHtcbiAgICAgIHRoaXMuX2FuaW1hdG9yLm9wZW4oKTtcbiAgICB9XG4gIH1cblxuICAvLyBlbnRlciBjb2xsYXBzZSBtb2RlXG4gIGVudGVyTW9kZSgpIHtcbiAgICBpZiAoIXRoaXMuX2FjdGl2ZSkge1xuICAgICAgdGhpcy5fYWN0aXZlID0gdHJ1ZTtcbiAgICAgIHRoaXMubGF5b3V0KCk7XG4gICAgfVxuICB9XG5cbiAgLy8gZXhpdCBjb2xsYXBzZSBtb2RlXG4gIGV4aXRNb2RlKCkge1xuICAgIHRoaXMuX2FjdGl2ZSA9IGZhbHNlO1xuICB9XG5cbiAgX2lzT3Blbk90aGVyU2lkZU1lbnUoKSB7XG4gICAgcmV0dXJuIHV0aWwuYXJyYXlGcm9tKHRoaXMuX2VsZW1lbnQucGFyZW50RWxlbWVudC5jaGlsZHJlbikuc29tZShlID0+IHtcbiAgICAgIHJldHVybiB1dGlsLm1hdGNoKGUsICdvbnMtc3BsaXR0ZXItc2lkZScpICYmIGUgIT09IHRoaXMuX2VsZW1lbnQgJiYgZS5pc09wZW47XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSAnb3Blbicgb3IgJ2Nsb3NlJ1xuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLndpdGhvdXRBbmltYXRpb25dXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBzcGxpdHRlciBzaWRlIGVsZW1lbnQgb3IgZmFsc2UgaWYgbm90IGluIGNvbGxhcHNlIG1vZGVcbiAgICovXG4gIGV4ZWN1dGVBY3Rpb24obmFtZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgRklOQUxfU1RBVEUgPSBuYW1lID09PSAnb3BlbicgPyBPUEVOX1NUQVRFIDogQ0xPU0VEX1NUQVRFO1xuXG4gICAgaWYgKCF0aGlzLl9hY3RpdmUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gRklOQUxfU1RBVEUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fZWxlbWVudCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9sb2NrLmlzTG9ja2VkKCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnU3BsaXR0ZXIgc2lkZSBpcyBsb2NrZWQuJyk7XG4gICAgfVxuICAgIGlmIChuYW1lID09PSAnb3BlbicgJiYgdGhpcy5faXNPcGVuT3RoZXJTaWRlTWVudSgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0Fub3RoZXIgbWVudSBpcyBhbHJlYWR5IG9wZW4uJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9lbGVtZW50Ll9lbWl0RXZlbnQoYHByZSR7bmFtZX1gKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGBDYW5jZWxlZCBpbiBwcmUke25hbWV9IGV2ZW50LmApO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjaztcbiAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9sb2NrLmxvY2soKTtcbiAgICBjb25zdCBkb25lID0gKCkgPT4ge1xuICAgICAgdGhpcy5fc3RhdGUgPSBGSU5BTF9TVEFURTtcbiAgICAgIHRoaXMubGF5b3V0KCk7XG4gICAgICB1bmxvY2soKTtcbiAgICAgIHRoaXMuX2VsZW1lbnQuX2VtaXRFdmVudChgcG9zdCR7bmFtZX1gKTtcbiAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLndpdGhvdXRBbmltYXRpb24pIHtcbiAgICAgIGRvbmUoKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fZWxlbWVudCk7XG4gICAgfVxuICAgIHRoaXMuX3N0YXRlID0gQ0hBTkdJTkdfU1RBVEU7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fYW5pbWF0b3JbbmFtZV0oKCkgPT4ge1xuICAgICAgICBkb25lKCk7XG4gICAgICAgIHJlc29sdmUodGhpcy5fZWxlbWVudCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zcGxpdHRlci1zaWRlXG4gKiBAY2F0ZWdvcnkgbWVudVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgVGhlIGA8b25zLXNwbGl0dGVyLXNpZGU+YCBlbGVtZW50IGlzIHVzZWQgYXMgYSBjaGlsZCBlbGVtZW50IG9mIGA8b25zLXNwbGl0dGVyPmAuXG4gKlxuICogICAgSXQgd2lsbCBiZSBkaXNwbGF5ZWQgb24gZWl0aGVyIHRoZSBsZWZ0IG9yIHJpZ2h0IHNpZGUgb2YgdGhlIGA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+YCBlbGVtZW50LlxuICpcbiAqICAgIEl0IHN1cHBvcnRzIHR3byBtb2RlczogY29sbGFwc2VkIGFuZCBzcGxpdC4gV2hlbiBpdCdzIGluIGNvbGxhcHNlZCBtb2RlIGl0IHdpbGwgYmUgaGlkZGVuIGZyb20gdmlldyBhbmQgY2FuIGJlIGRpc3BsYXllZCB3aGVuIHRoZSB1c2VyIHN3aXBlcyB0aGUgc2NyZWVuIG9yIHRhcHMgYSBidXR0b24uIEluIHNwbGl0IG1vZGUgdGhlIGVsZW1lbnQgaXMgYWx3YXlzIHNob3duLiBJdCBjYW4gYmUgY29uZmlndXJlZCB0byBhdXRvbWF0aWNhbGx5IHN3aXRjaCBiZXR3ZWVuIHRoZSB0d28gbW9kZXMgZGVwZW5kaW5nIG9uIHRoZSBzY3JlZW4gc2l6ZS5cbiAqICBbL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItc2lkZeimgee0oOOBr+OAgW9ucy1zcGxpdHRlcuimgee0oOOBruWtkOimgee0oOOBqOOBl+OBpuWIqeeUqOOBl+OBvuOBmeOAglsvamFdXG4gKiBAY29kZXBlbiByT1FPTUxcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9zcGxpdHRlclxuICogQGd1aWRlIG11bHRpcGxlLXBhZ2UtbmF2aWdhdGlvblxuICogIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogIFtqYV1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlc1svamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXJcbiAqICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyPmAgaXMgdGhlIHBhcmVudCBjb21wb25lbnQuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlci1jb250ZW50XG4gKiAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgY29tcG9uZW50IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2UuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVyLWNvbnRlbnTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc3BsaXR0ZXI+XG4gKiAgIDxvbnMtc3BsaXR0ZXItY29udGVudD5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItY29udGVudD5cbiAqXG4gKiAgIDxvbnMtc3BsaXR0ZXItc2lkZSBzaWRlPVwibGVmdFwiIHdpZHRoPVwiODAlXCIgY29sbGFwc2U+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLXNwbGl0dGVyLXNpZGU+XG4gKiA8L29ucy1zcGxpdHRlcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BsaXR0ZXJTaWRlRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IG1vZGVjaGFuZ2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGNvbXBvbmVudCdzIG1vZGUgY2hhbmdlcy5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDjga7jg6Ljg7zjg4njgYzlpInljJbjgZfjgZ/pmpvjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5zaWRlXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50Lm1vZGVcbiAgICogICBbZW5dUmV0dXJucyB0aGUgY3VycmVudCBtb2RlLiBDYW4gYmUgZWl0aGVyIGBcImNvbGxhcHNlXCJgIG9yIGBcInNwbGl0XCJgLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruODouODvOODieOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlb3BlblxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIHNsaWRpbmcgbWVudSBpcyBvcGVuZWQuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaL44GP5YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0byBjYW5jZWwgb3BlbmluZyBzbGlkaW5nIG1lbnUuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaL44GP44Gu44KS44Kt44Oj44Oz44K744Or44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RvcGVuXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBzbGlkaW5nIG1lbnUgaXMgb3BlbmVkLlsvZW5dXG4gICAqICAgW2phXeOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOBjOmWi+OBhOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZWNsb3NlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgc2xpZGluZyBtZW51IGlzIGNsb3NlZC5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6njgqTjg4fjgqPjg7PjgrDjg6Hjg4vjg6Xjg7zjgYzplonjgZjjgovliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5zaWRlXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUNhbGwgdG8gY2FuY2VsIG9wZW5pbmcgc2xpZGluZy1tZW51LlsvZW5dXG4gICAqICAgW2phXeOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOBjOmWieOBmOOCi+OBruOCkuOCreODo+ODs+OCu+ODq+OBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNsb3NlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBzbGlkaW5nIG1lbnUgaXMgY2xvc2VkLlsvZW5dXG4gICAqICAgW2phXeOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOBjOmWieOBmOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgIGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uLiBVc2Ugb25lIG9mIGBcIm92ZXJsYXlcImAsIGFuZCBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz44KS5oyH5a6a44GX44G+44GZ44CCXCJvdmVybGF5XCIsIFwiZGVmYXVsdFwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG9wZW4tdGhyZXNob2xkXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0ICAwLjNcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSBob3cgbXVjaCB0aGUgbWVudSBuZWVkcyB0byBiZSBzd2lwZWQgYmVmb3JlIG9wZW5pbmcuIEEgdmFsdWUgYmV0d2VlbiBgMGAgYW5kIGAxYC5bL2VuXVxuICAgKiAgW2phXeOBqeOBruOBj+OCieOBhOOCueODr+OCpOODl+OBmeOCjOOBsOOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOCkumWi+OBj+OBi+OBqeOBhuOBi+OBruWJsuWQiOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokx44Gu6ZaT44Gu5pWw5YCk44KS5oyH5a6a44GX44G+44GZ44CC44K544Ov44Kk44OX44Gu6Led6Zui44GM44GT44GT44Gn5oyH5a6a44GX44Gf5pWw5YCk5o6b44GR44KL44GT44Gu6KaB57Sg44Gu5bmF44KI44KK44KC5aSn44GN44GR44KM44Gw44CB44K544Ov44Kk44OX44GM57WC44KP44Gj44Gf5pmC44Gr44GT44Gu6KaB57Sg44KS6ZaL44GN44G+44GZ44CC44OH44OV44Kp44Or44OI44GvMC4z44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY29sbGFwc2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgY29sbGFwc2UgYmVoYXZpb3IuIFZhbGlkIHZhbHVlcyBhcmUgYFwicG9ydHJhaXRcImAsIGBcImxhbmRzY2FwZVwiYCBvciBhIG1lZGlhIHF1ZXJ5LlxuICAgKiAgICAgVGhlIHN0cmluZ3MgYFwicG9ydHJhaXRcImAgYW5kIGBcImxhbmRzY2FwZVwiYCBtZWFucyB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gZGV2aWNlIGlzIGluIGxhbmRzY2FwZSBvciBwb3J0cmFpdCBvcmllbnRhdGlvbi5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBhIG1lZGlhIHF1ZXJ5LCB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gdGhlIG1lZGlhIHF1ZXJ5IHJlc29sdmVzIHRvIGB0cnVlYC5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBub3QgZGVmaW5lZCwgdGhlIHZpZXcgYWx3YXlzIGJlIGluIGBcImNvbGxhcHNlXCJgIG1vZGUuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdXG4gICAqICAgICDlt6blgbTjga7jg5rjg7zjgrjjgpLpnZ7ooajnpLrjgavjgZnjgovmnaHku7bjgpLmjIflrprjgZfjgb7jgZnjgIJwb3J0cmFpdCwgbGFuZHNjYXBl44CBd2lkdGggI3B444KC44GX44GP44Gv44Oh44OH44Kj44Ki44Kv44Ko44Oq44Gu5oyH5a6a44GM5Y+v6IO944Gn44GZ44CCXG4gICAqICAgICBwb3J0cmFpdOOCguOBl+OBj+OBr2xhbmRzY2FwZeOCkuaMh+WumuOBmeOCi+OBqOOAgeODh+ODkOOCpOOCueOBrueUu+mdouOBjOe4puWQkeOBjeOCguOBl+OBj+OBr+aoquWQkeOBjeOBq+OBquOBo+OBn+aZguOBq+mBqeeUqOOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44Oh44OH44Kj44Ki44Kv44Ko44Oq44KS5oyH5a6a44GZ44KL44Go44CB5oyH5a6a44GX44Gf44Kv44Ko44Oq44Gr6YGp5ZCI44GX44Gm44GE44KL5aC05ZCI44Gr6YGp55So44GV44KM44G+44GZ44CCXG4gICAqICAgICDlgKTjgavkvZXjgoLmjIflrprjgZfjgarjgYTloLTlkIjjgavjga/jgIHluLjjgatjb2xsYXBzZeODouODvOODieOBq+OBquOCiuOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHN3aXBlLXRhcmdldC13aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHdpZHRoIG9mIHN3aXBlYWJsZSBhcmVhIGNhbGN1bGF0ZWQgZnJvbSB0aGUgZWRnZSAoaW4gcGl4ZWxzKS4gVXNlIHRoaXMgdG8gZW5hYmxlIHN3aXBlIG9ubHkgd2hlbiB0aGUgZmluZ2VyIHRvdWNoIG9uIHRoZSBzY3JlZW4gZWRnZS5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6/jgqTjg5fjga7liKTlrprpoJjln5/jgpLjg5Tjgq/jgrvjg6vljZjkvY3jgafmjIflrprjgZfjgb7jgZnjgILnlLvpnaLjga7nq6/jgYvjgonmjIflrprjgZfjgZ/ot53pm6LjgavpgZTjgZnjgovjgajjg5rjg7zjgrjjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB3aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2FuIGJlIHNwZWNpZmllZCBpbiBlaXRoZXIgcGl4ZWxzIG9yIGFzIGEgcGVyY2VudGFnZSwgZS5nLiBgOTAlYCBvciBgMjAwcHhgLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOOBruaoquW5heOCkuaMh+WumuOBl+OBvuOBmeOAgnB444GoJeOBp+OBruaMh+WumuOBjOWPr+iDveOBp+OBmeOAgmVnLiA5MCUsIDIwMHB4Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2lkZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBsZWZ0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoaWNoIHNpZGUgb2YgdGhlIHNjcmVlbiB0aGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgaXMgbG9jYXRlZC4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJsZWZ0XCJgIGFuZCBgXCJyaWdodFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDjgYzlt6bjgYvlj7PjgYvjgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovlgKTjga9cImxlZnRcIuOBi1wicmlnaHRcIuOBruOBv+OBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgbW9kZS4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJjb2xsYXBzZVwiYCBvciBgXCJzcGxpdFwiYC4gVGhpcyBhdHRyaWJ1dGUgaXMgcmVhZCBvbmx5LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruODouODvOODieOBjOioreWumuOBleOCjOOBvuOBmeOAglwiY29sbGFwc2VcIuOCguOBl+OBj+OBr1wic3BsaXRcIuOBjOaMh+WumuOBleOCjOOBvuOBmeOAguOBk+OBruWxnuaAp+OBr+iqreOBv+i+vOOBv+WwgueUqOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgVVJMIG9mIHRoZSBtZW51IHBhZ2UuWy9lbl1cbiAgICogICBbamFdb25zLXNwbGl0dGVyLXNpZGXopoHntKDjgavooajnpLrjgZnjgovjg5rjg7zjgrjjga5VUkzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRvIGVuYWJsZSBzd2lwZSBpbnRlcmFjdGlvbiBvbiBjb2xsYXBzZSBtb2RlLlsvZW5dXG4gICAqICAgW2phXWNvbGxhcHNl44Oi44O844OJ5pmC44Gr44K544Ov44Kk44OX5pON5L2c44KS5pyJ5Yq544Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgaW5pdCgpIHtcbiAgICB0aGlzLl9wYWdlID0gbnVsbDtcbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gZGVmYXVsdFBhZ2VMb2FkZXI7XG4gICAgdGhpcy5fY29sbGFwc2VNb2RlID0gbmV3IENvbGxhcHNlTW9kZSh0aGlzKTtcbiAgICB0aGlzLl9jb2xsYXBzZURldGVjdGlvbiA9IG5ldyBDb2xsYXBzZURldGVjdGlvbih0aGlzKTtcblxuICAgIHRoaXMuX2FuaW1hdG9yRmFjdG9yeSA9IG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBTcGxpdHRlckVsZW1lbnQuYW5pbWF0b3JzLFxuICAgICAgYmFzZUNsYXNzOiBTcGxpdHRlckFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ1NwbGl0dGVyQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gICAgdGhpcy5fYm91bmRIYW5kbGVHZXN0dXJlID0gKGUpID0+IHRoaXMuX2NvbGxhcHNlTW9kZS5oYW5kbGVHZXN0dXJlKGUpO1xuICAgIHRoaXMuX3dhdGNoZWRBdHRyaWJ1dGVzID0gV0FUQ0hFRF9BVFRSSUJVVEVTO1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICByZXdyaXRhYmxlcy5yZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLl9nZXRQYWdlVGFyZ2V0KCk7XG5cbiAgICAgICAgaWYgKHBhZ2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWQocGFnZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKCF1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1zcGxpdHRlcicpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhcmVudCBtdXN0IGJlIGFuIG9ucy1zcGxpdHRlciBlbGVtZW50LicpO1xuICAgIH1cblxuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcy5wYXJlbnRFbGVtZW50LCB7ZHJhZ01pbkRpc3RhbmNlOiAxfSk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fd2F0Y2hlZEF0dHJpYnV0ZXMuZm9yRWFjaChlID0+IHRoaXMuX3VwZGF0ZShlKSk7XG4gICAgfSk7XG5cbiAgICBpZiAoIXRoaXMuaGFzQXR0cmlidXRlKCdzaWRlJykpIHtcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzaWRlJywgJ2xlZnQnKTtcbiAgICB9XG4gIH1cblxuICBfZ2V0UGFnZVRhcmdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZSB8fCB0aGlzLmdldEF0dHJpYnV0ZSgncGFnZScpO1xuICB9XG5cbiAgZ2V0IHNpZGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdzaWRlJykgPT09ICdyaWdodCcgPyAncmlnaHQnIDogJ2xlZnQnO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uZGlzYWJsZSgpO1xuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3Rvci5kaXNwb3NlKCk7XG4gICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yID0gbnVsbDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBXQVRDSEVEX0FUVFJJQlVURVM7XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHRoaXMuX3VwZGF0ZShuYW1lLCBjdXJyZW50KTtcbiAgfVxuXG4gIF91cGRhdGUobmFtZSwgdmFsdWUpIHtcbiAgICBuYW1lID0gJ191cGRhdGUnICsgbmFtZS5zcGxpdCgnLScpLm1hcChlID0+IGVbMF0udG9VcHBlckNhc2UoKSArIGUuc2xpY2UoMSkpLmpvaW4oJycpO1xuICAgIHJldHVybiB0aGlzW25hbWVdKHZhbHVlKTtcbiAgfVxuXG4gIF9lbWl0RXZlbnQobmFtZSkge1xuICAgIGlmIChuYW1lLnNsaWNlKDAsIDMpICE9PSAncHJlJykge1xuICAgICAgcmV0dXJuIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCBuYW1lLCB7c2lkZTogdGhpc30pO1xuICAgIH1cbiAgICBsZXQgaXNDYW5jZWxlZCA9IGZhbHNlO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsIG5hbWUsIHtcbiAgICAgIHNpZGU6IHRoaXMsXG4gICAgICBjYW5jZWw6ICgpID0+IGlzQ2FuY2VsZWQgPSB0cnVlXG4gICAgfSk7XG5cbiAgICByZXR1cm4gaXNDYW5jZWxlZDtcbiAgfVxuXG4gIF91cGRhdGVDb2xsYXBzZSh2YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdjb2xsYXBzZScpKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnc3BsaXQnKSB7XG4gICAgICB0aGlzLl9jb2xsYXBzZURldGVjdGlvbi5kaXNhYmxlKCk7XG4gICAgICByZXR1cm4gdGhpcy5fdXBkYXRlTW9kZShTUExJVF9NT0RFKTtcbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJ2NvbGxhcHNlJykge1xuICAgICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uZGlzYWJsZSgpO1xuICAgICAgcmV0dXJuIHRoaXMuX3VwZGF0ZU1vZGUoQ09MTEFQU0VfTU9ERSk7XG4gICAgfVxuXG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uY2hhbmdlVGFyZ2V0KHZhbHVlKTtcbiAgfVxuXG4gIC8vIHJlYWRvbmx5IGF0dHJpYnV0ZSBmb3IgdGhlIHVzZXJzXG4gIF91cGRhdGVNb2RlKG1vZGUpIHtcbiAgICBpZiAobW9kZSAhPT0gdGhpcy5fbW9kZSkge1xuICAgICAgdGhpcy5fbW9kZSA9IG1vZGU7XG4gICAgICB0aGlzLl9jb2xsYXBzZU1vZGVbbW9kZSA9PT0gQ09MTEFQU0VfTU9ERSA/ICdlbnRlck1vZGUnIDogJ2V4aXRNb2RlJ10oKTtcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdtb2RlJywgbW9kZSk7XG5cbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnbW9kZWNoYW5nZScsIHtzaWRlOiB0aGlzLCBtb2RlOiBtb2RlfSk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZU9wZW5UaHJlc2hvbGQodGhyZXNob2xkID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ29wZW4tdGhyZXNob2xkJykpIHtcbiAgICB0aGlzLl90aHJlc2hvbGQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBwYXJzZUZsb2F0KHRocmVzaG9sZCkgfHwgMC4zKSk7XG4gIH1cblxuICBfdXBkYXRlU3dpcGVhYmxlKHN3aXBlYWJsZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdzd2lwZWFibGUnKSkge1xuICAgIGNvbnN0IGFjdGlvbiA9IHN3aXBlYWJsZSA9PT0gbnVsbCA/ICdvZmYnIDogJ29uJztcblxuICAgIGlmICh0aGlzLl9nZXN0dXJlRGV0ZWN0b3IpIHtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnc3RhcnQgZHJhZ2xlZnQgZHJhZ3JpZ2h0IGRyYWdlbmQnLCB0aGlzLl9ib3VuZEhhbmRsZUdlc3R1cmUpO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVTd2lwZVRhcmdldFdpZHRoKHZhbHVlID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRhcmdldC13aWR0aCcpKSB7XG4gICAgdGhpcy5fc3dpcGVUYXJnZXRXaWR0aCA9IE1hdGgubWF4KDAsIHBhcnNlSW50KHZhbHVlKSB8fCAwKTtcbiAgfVxuXG4gIF91cGRhdGVXaWR0aCgpIHtcbiAgICB0aGlzLnN0eWxlLndpZHRoID0gdGhpcy5fd2lkdGg7XG4gIH1cblxuICBnZXQgX3dpZHRoKCkge1xuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJyk7XG4gICAgcmV0dXJuIC9eXFxkKyhweHwlKSQvLnRlc3Qod2lkdGgpID8gd2lkdGggOiAnODAlJztcbiAgfVxuXG4gIHNldCBfd2lkdGgodmFsdWUpIHtcbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCB2YWx1ZSk7XG4gIH1cblxuICBfdXBkYXRlU2lkZShzaWRlID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NpZGUnKSkge1xuICAgIHRoaXMuX3NpZGUgPSBzaWRlID09PSAncmlnaHQnID8gc2lkZSA6ICdsZWZ0JztcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRpb24oYW5pbWF0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpKSB7XG4gICAgdGhpcy5fYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Ioe2FuaW1hdGlvbn0pO1xuICAgIHRoaXMuX2FuaW1hdG9yLmFjdGl2YXRlKHRoaXMpO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdGlvbk9wdGlvbnModmFsdWUgPSB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSkge1xuICAgIHRoaXMuX2FuaW1hdG9yLnVwZGF0ZU9wdGlvbnMoQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh2YWx1ZSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlXG4gICAqIEB0eXBlIHsqfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGFnZSBsb2NhdGlvbiB0byBsb2FkIGluIHRoZSBzcGxpdHRlciBzaWRlLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOWGheOBq+ihqOekuuOBmeOCi+ODmuODvOOCuOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgcGFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyp9IHBhZ2VcbiAgICovXG4gIHNldCBwYWdlKHBhZ2UpIHtcbiAgICB0aGlzLl9wYWdlID0gcGFnZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgcGFnZUxvYWRlclxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBwYWdlTG9hZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlTG9hZGVyO1xuICB9XG5cbiAgc2V0IHBhZ2VMb2FkZXIobG9hZGVyKSB7XG4gICAgaWYgKCEobG9hZGVyIGluc3RhbmNlb2YgUGFnZUxvYWRlcikpIHtcbiAgICAgIHRocm93IEVycm9yKCdGaXJzdCBwYXJhbWV0ZXIgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBQYWdlTG9hZGVyLicpO1xuICAgIH1cbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gbG9hZGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBtb2RlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBtb2RlLiBQb3NzaWJsZSB2YWx1ZXMgYXJlIFwic3BsaXRcIiwgXCJjb2xsYXBzZVwiLCBcImNsb3NlZFwiLCBcIm9wZW5cIiBvciBcImNoYW5naW5nXCIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBtb2RlKCkge1xuICAgIHJldHVybiB0aGlzLl9tb2RlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpc09wZW5cbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEByZWFkb25seVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhpcyB2YWx1ZSBpcyBgdHJ1ZWAgd2hlbiB0aGUgbWVudSBpcyBvcGVuLi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IGlzT3BlbigpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGFwc2VNb2RlLmlzT3BlbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgb3BlblxuICAgKiBAc2lnbmF0dXJlIG9wZW4oW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIG1lbnUgaGFzIGJlZW4gb3BlbmVkLlsvZW5dXG4gICAqICAgW2phXeODoeODi+ODpeODvOOBjOmWi+OBhOOBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcGVuIG1lbnUgaW4gY29sbGFwc2UgbW9kZS5bL2VuXVxuICAgKiAgIFtqYV1jb2xsYXBzZeODouODvOODieOBq+OBquOBo+OBpuOBhOOCi29ucy1zcGxpdHRlci1zaWRl6KaB57Sg44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBvcGVuKG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9jb2xsYXBzZU1vZGUuZXhlY3V0ZUFjdGlvbignb3BlbicsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgY2xvc2VcbiAgICogQHNpZ25hdHVyZSBjbG9zZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciB0aGUgbWVudSBoYXMgYmVlbiBjbG9zZWQuWy9lbl1cbiAgICogICBbamFd44Oh44OL44Ol44O844GM6ZaJ44GY44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNsb3NlIG1lbnUgaW4gY29sbGFwc2UgbW9kZS5bL2VuXVxuICAgKiAgIFtqYV1jb2xsYXBzZeODouODvOODieOBq+OBquOBo+OBpuOBhOOCi29ucy1zcGxpdHRlci1zaWRl6KaB57Sg44KS6ZaJ44GY44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBjbG9zZShvcHRpb25zID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGFwc2VNb2RlLmV4ZWN1dGVBY3Rpb24oJ2Nsb3NlJywgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcGVucyBpZiBpdCdzIGNsb3NlZC4gQ2xvc2VzIGlmIGl0J3Mgb3Blbi5bL2VuXVxuICAgKiAgIFtqYV3plovjgZHjgabjgYTjgovloLTlkIjjga/opoHntKDjgpLplonjgZjjgb7jgZnjgZ3jgZfjgabplovjgZHjgabjgYTjgovloLTlkIjjga/opoHntKDjgpLplovjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgc3BsaXR0ZXIgc2lkZSBlbGVtZW50IG9yIGZhbHNlIGlmIG5vdCBpbiBjb2xsYXBzZSBtb2RlWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHRvZ2dsZShvcHRpb25zID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5pc09wZW4gPyB0aGlzLmNsb3NlKG9wdGlvbnMpIDogdGhpcy5vcGVuKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbG9hZFxuICAgKiBAc2lnbmF0dXJlIGxvYWQocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGRvY3VtZW50IG9yIGFuIDxvbnMtdGVtcGxhdGU+LlsvZW5dXG4gICAqICAgW2phXXBhZ2Xjga5VUkzjgYvjgIFvbnMtdGVtcGxhdGXjgaflrqPoqIDjgZfjgZ/jg4bjg7Pjg5fjg6zjg7zjg4jjga5pZOWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IHRoZSBwYWdlIHNwZWNpZmllZCBpbiBwYWdlVXJsIGluIHRoZSByaWdodCBzZWN0aW9uWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44GfVVJM44KS44Oh44Kk44Oz44Oa44O844K444KS6Kqt44G/6L6844G/44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIG5ldyBwYWdlIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgbG9hZChwYWdlLCBvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9wYWdlID0gcGFnZTtcbiAgICBjb25zdCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2sgfHwgKCgpID0+IHt9KTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZCh7cGFnZSwgcGFyZW50OiB0aGlzLCByZXBsYWNlOiB0cnVlfSwgKHtlbGVtZW50LCB1bmxvYWR9KSA9PiB7XG4gICAgICAgIHJld3JpdGFibGVzLmxpbmsodGhpcywgZWxlbWVudCwgb3B0aW9ucywgZnJhZ21lbnQgPT4ge1xuICAgICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9zaG93KCkpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG5cbiAgICAgICAgICByZXNvbHZlKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbih0aGlzLCAnX3Nob3cnKTtcbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfaGlkZScpO1xuICB9XG5cbiAgX2Rlc3Ryb3koKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19kZXN0cm95Jyk7XG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgcmV3cml0YWJsZXMoKSB7XG4gICAgcmV0dXJuIHJld3JpdGFibGVzO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwbGl0dGVyLXNpZGUnLCBTcGxpdHRlclNpZGVFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IEdlc3R1cmVEZXRlY3RvciBmcm9tICcuLi9vbnMvZ2VzdHVyZS1kZXRlY3Rvcic7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdzd2l0Y2gtLSonLFxuICAnLnN3aXRjaF9faW5wdXQnOiAnc3dpdGNoLS0qX19pbnB1dCcsXG4gICcuc3dpdGNoX19oYW5kbGUnOiAnc3dpdGNoLS0qX19oYW5kbGUnLFxuICAnLnN3aXRjaF9fdG9nZ2xlJzogJ3N3aXRjaC0tKl9fdG9nZ2xlJ1xufTtcblxuY29uc3QgdGVtcGxhdGUgPSB1dGlsLmNyZWF0ZUZyYWdtZW50KGBcbiAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGNsYXNzPVwic3dpdGNoX19pbnB1dFwiPlxuICA8ZGl2IGNsYXNzPVwic3dpdGNoX190b2dnbGVcIj5cbiAgICA8ZGl2IGNsYXNzPVwic3dpdGNoX19oYW5kbGVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzd2l0Y2hfX3RvdWNoXCI+PC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuYCk7XG5cbmNvbnN0IGxvY2F0aW9ucyA9IHtcbiAgaW9zOiBbMSwgMjFdLFxuICBtYXRlcmlhbDogWzAsIDE2XVxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3dpdGNoXG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBTd2l0Y2ggY29tcG9uZW50LiBUaGUgc3dpdGNoIGNhbiBiZSB0b2dnbGVkIGJvdGggYnkgZHJhZ2dpbmcgYW5kIHRhcHBpbmcuXG4gKlxuICogICAgIFdpbGwgYXV0b21hdGljYWxseSBkaXNwbGF5cyBhIE1hdGVyaWFsIERlc2lnbiBzd2l0Y2ggb24gQW5kcm9pZCBkZXZpY2VzLlxuICogICBbL2VuXVxuICogICBbamFd44K544Kk44OD44OB44KS6KGo56S644GZ44KL44Kz44Oz44Od44O844ON44Oz44OI44Gn44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dTWF0ZXJpYWwgRGVzaWduIHN3aXRjaFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gTHBYWlFRXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc3dpdGNoXG4gKiBAZ3VpZGUgYWRkaW5nLXBhZ2UtY29udGVudFxuICogICBbZW5dVXNpbmcgZm9ybSBjb21wb25lbnRzWy9lbl1cbiAqICAgW2phXeODleOCqeODvOODoOOCkuS9v+OBhlsvamFdXG4gKiBAZ3VpZGUgdXNpbmctbW9kaWZpZXIgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zd2l0Y2ggY2hlY2tlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBkaXNhYmxlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBtb2RpZmllcj1cIm1hdGVyaWFsXCI+PC9vbnMtc3dpdGNoPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN3aXRjaEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBjaGFuZ2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN3aXRjaCBpcyB0b2dnbGVkLlsvZW5dXG4gICAqICAgW2phXU9OL09GRuOBjOWkieOCj+OBo+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnN3aXRjaFxuICAgKiAgIFtlbl1Td2l0Y2ggb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOBjOeZuueBq+OBl+OBn1N3aXRjaOOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZXZlbnQudmFsdWVcbiAgICogICBbZW5dQ3VycmVudCB2YWx1ZS5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7lgKTjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGV2ZW50LmlzSW50ZXJhY3RpdmVcbiAgICogICBbZW5dVHJ1ZSBpZiB0aGUgY2hhbmdlIHdhcyB0cmlnZ2VyZWQgYnkgdGhlIHVzZXIgY2xpY2tpbmcgb24gdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg4Pjg5fjgoTjgq/jg6rjg4Pjgq/jgarjganjga7jg6bjg7zjgrbjga7mk43kvZzjgavjgojjgaPjgablpInjgo/jgaPjgZ/loLTlkIjjgavjga90cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgW2phXeOCueOCpOODg+ODgeOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBzd2l0Y2ggaXMgYmUgZGlzYWJsZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44KS54Sh5Yq544Gu54q25oWL44Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2hlY2tlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7nirbmhYvjgavjgZnjgovjgajjgY3jgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYGlkYCBhdHRyaWJ1dGUgb2YgdGhlIGlubmVyIGA8aW5wdXQ+YCBlbGVtZW50LiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGA8bGFiZWwgZm9yPVwiLi4uXCI+YCBlbGVtZW50cy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNoZWNrZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIHZhbHVlIGlzIGB0cnVlYCBpZiB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7loLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICBnZXQgY2hlY2tlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fY2hlY2tlZDtcbiAgfVxuXG4gIHNldCBjaGVja2VkKHZhbHVlKSB7XG4gICAgdGhpcy5fY2hlY2tlZCA9ICEhdmFsdWU7XG4gICAgdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NoZWNrZWQnLCB0aGlzLl9jaGVja2VkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZDtcbiAgfVxuXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHRoaXMuX2Rpc2FibGVkID0gISF2YWx1ZTtcbiAgICB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB0aGlzLl9kaXNhYmxlZCk7XG4gICAgdGhpcy5fY2hlY2tib3guZGlzYWJsZWQgPSB0aGlzLl9kaXNhYmxlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tib3hcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB1bmRlcmx5aW5nIGNoZWNrYm94IGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI5YaF6YOo44GuY2hlY2tib3jopoHntKDjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IGNoZWNrYm94KCkge1xuICAgIHJldHVybiB0aGlzLl9jaGVja2JveDtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fY2hlY2tlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2Rpc2FibGVkID0gZmFsc2U7XG5cbiAgICB0aGlzLl9ib3VuZE9uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgICBbJ2NoZWNrZWQnLCAnZGlzYWJsZWQnLCAnbW9kaWZpZXInLCAnbmFtZScsICdpbnB1dC1pZCddLmZvckVhY2goZSA9PiB7XG4gICAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGUsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKGUpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3N3aXRjaCcpO1xuXG4gICAgaWYgKCEodXRpbC5maW5kQ2hpbGQodGhpcywgJy5zd2l0Y2hfX2lucHV0JykgJiYgdXRpbC5maW5kQ2hpbGQodGhpcywgJy5zd2l0Y2hfX3RvZ2dsZScpKSkge1xuICAgICAgdGhpcy5hcHBlbmRDaGlsZCh0ZW1wbGF0ZS5jbG9uZU5vZGUodHJ1ZSkpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcblxuICAgIHRoaXMuX2NoZWNrYm94ID0gdGhpcy5xdWVyeVNlbGVjdG9yKCcuc3dpdGNoX19pbnB1dCcpO1xuICAgIHRoaXMuX2hhbmRsZSA9IHRoaXMucXVlcnlTZWxlY3RvcignLnN3aXRjaF9faGFuZGxlJyk7XG5cbiAgICB0aGlzLl9jaGVja2JveC5jaGVja2VkID0gdGhpcy5fY2hlY2tlZDtcbiAgICB0aGlzLl9jaGVja2JveC5kaXNibGVkID0gdGhpcy5fZGlzYWJsZWQ7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY2hlY2tib3gucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fYm91bmRPbkNoYW5nZSk7XG4gICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ1N0YXJ0KTtcbiAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX29uSG9sZCk7XG4gICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RhcCcsIHRoaXMuY2xpY2spO1xuICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2xpY2spO1xuICAgICAgaWYgKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcikge1xuICAgICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IuZGlzcG9zZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NoZWNrYm94LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UpO1xuICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2hvbGQnLCB0aGlzLl9vbkhvbGQpO1xuICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLmNsaWNrKTtcbiAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcywge2RyYWdNaW5EaXN0YW5jZTogMSwgaG9sZFRpbWVvdXQ6IDI1MX0pO1xuICAgICAgdGhpcy5fYm91bmRPblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9vbkNoYW5nZShldmVudCkge1xuICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdjaGVja2VkJywgdGhpcy5jaGVja2JveC5jaGVja2VkKTtcbiAgfVxuXG4gIF9vbkNsaWNrKGV2KSB7XG4gICAgaWYgKGV2LnRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoJ3N3aXRjaF9fdG91Y2gnKSkge1xuICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICBjbGljaygpIHtcbiAgICBpZiAoIXRoaXMuX2Rpc2FibGVkKSB7XG4gICAgICB0aGlzLmNoZWNrZWQgPSAhdGhpcy5jaGVja2VkO1xuXG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ2NoYW5nZScsIHtcbiAgICAgICAgdmFsdWU6IHRoaXMuY2hlY2tlZCxcbiAgICAgICAgc3dpdGNoOiB0aGlzLFxuICAgICAgICBpc0ludGVyYWN0aXZlOiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfZ2V0UG9zaXRpb24oZSkge1xuICAgIGNvbnN0IGwgPSB0aGlzLl9sb2NhdGlvbnM7XG4gICAgcmV0dXJuIE1hdGgubWluKGxbMV0sIE1hdGgubWF4KGxbMF0sIHRoaXMuX3N0YXJ0WCArIGUuZ2VzdHVyZS5kZWx0YVgpKTtcbiAgfVxuXG4gIF9vbkhvbGQoZSkge1xuICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdzd2l0Y2gtLWFjdGl2ZScpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX2JvdW5kT25SZWxlYXNlKTtcbiAgICB9XG4gIH1cblxuICBfb25EcmFnU3RhcnQoZSkge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IFsnbGVmdCcsICdyaWdodCddLmluZGV4T2YoZS5nZXN0dXJlLmRpcmVjdGlvbikgPT09IC0xKSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoJ3N3aXRjaC0tYWN0aXZlJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnc3dpdGNoLS1hY3RpdmUnKTtcbiAgICB0aGlzLl9zdGFydFggPSB0aGlzLl9sb2NhdGlvbnNbdGhpcy5jaGVja2VkID8gMSA6IDBdOy8vIC0gZS5nZXN0dXJlLmRlbHRhWDtcblxuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignZHJhZycsIHRoaXMuX29uRHJhZyk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX2JvdW5kT25SZWxlYXNlKTtcbiAgfVxuXG4gIF9vbkRyYWcoZSkge1xuICAgIGUuZ2VzdHVyZS5zcmNFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuX2hhbmRsZS5zdHlsZS5sZWZ0ID0gdGhpcy5fZ2V0UG9zaXRpb24oZSkgKyAncHgnO1xuICB9XG5cbiAgX29uUmVsZWFzZShlKSB7XG4gICAgY29uc3QgbCA9IHRoaXMuX2xvY2F0aW9ucztcbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuX2dldFBvc2l0aW9uKGUpO1xuICAgIGNvbnN0IHByZXZpb3VzVmFsdWUgPSB0aGlzLmNoZWNrZWQ7XG5cbiAgICB0aGlzLmNoZWNrZWQgPSBwb3NpdGlvbiA+PSAobFswXSArIGxbMV0pIC8gMjtcblxuICAgIGlmICh0aGlzLmNoZWNrZWQgIT09IHByZXZpb3VzVmFsdWUpIHtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnY2hhbmdlJywge1xuICAgICAgICB2YWx1ZTogdGhpcy5jaGVja2VkLFxuICAgICAgICBzd2l0Y2g6IHRoaXMsXG4gICAgICAgIGlzSW50ZXJhY3RpdmU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZycsIHRoaXMuX29uRHJhZyk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX2JvdW5kT25SZWxlYXNlKTtcblxuICAgIHRoaXMuX2hhbmRsZS5zdHlsZS5sZWZ0ID0gJyc7XG4gICAgdGhpcy5jbGFzc0xpc3QucmVtb3ZlKCdzd2l0Y2gtLWFjdGl2ZScpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnaW5wdXQtaWQnLCAnY2hlY2tlZCcsICdkaXNhYmxlZCddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgc3dpdGNoKG5hbWUpIHtcbiAgICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICAgIHRoaXMuX2lzTWF0ZXJpYWwgPSAoY3VycmVudCB8fCAnJykuaW5kZXhPZignbWF0ZXJpYWwnKSAhPT0gLTE7XG4gICAgICAgICAgdGhpcy5fbG9jYXRpb25zID0gbG9jYXRpb25zW3RoaXMuX2lzTWF0ZXJpYWwgPyAnbWF0ZXJpYWwnIDogJ2lvcyddO1xuICAgICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdpbnB1dC1pZCc6XG4gICAgICAgICAgdGhpcy5fY2hlY2tib3guaWQgPSBjdXJyZW50O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdjaGVja2VkJzpcbiAgICAgICAgICB0aGlzLl9jaGVja2VkID0gY3VycmVudCAhPT0gbnVsbDtcbiAgICAgICAgICB0aGlzLl9jaGVja2JveC5jaGVja2VkID0gY3VycmVudCAhPT0gbnVsbDtcbiAgICAgICAgICB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLl9jaGVja2JveCwgbmFtZSwgY3VycmVudCAhPT0gbnVsbCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2Rpc2FibGVkJzpcbiAgICAgICAgICB0aGlzLl9kaXNhYmxlZCA9IGN1cnJlbnQgIT09IG51bGw7XG4gICAgICAgICAgdGhpcy5fY2hlY2tib3guZGlzYWJsZWQgPSBjdXJyZW50ICE9PSBudWxsO1xuICAgICAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMuX2NoZWNrYm94LCBuYW1lLCBjdXJyZW50ICE9PSBudWxsKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zd2l0Y2gnLCBTd2l0Y2hFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmV4cG9ydCBjbGFzcyBUYWJiYXJBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy50aW1pbmcgPSBvcHRpb25zLnRpbWluZyB8fCAnbGluZWFyJztcbiAgICB0aGlzLmR1cmF0aW9uID0gb3B0aW9ucy5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kdXJhdGlvbiA6ICcwLjQnO1xuICAgIHRoaXMuZGVsYXkgPSBvcHRpb25zLmRlbGF5ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmRlbGF5IDogJzAnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZW50ZXJQYWdlIG9ucy1wYWdlIGVsZW1lbnRcbiAgICogQHBhcmFtIHtFbGVtZW50fSBsZWF2ZVBhZ2Ugb25zLXBhZ2UgZWxlbWVudFxuICAgKiBAcGFyYW0ge051bWJlcn0gZW50ZXJQYWdlSW5kZXhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlYXZlUGFnZUluZGV4XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIGFwcGx5KGVudGVyUGFnZSwgbGVhdmVQYWdlLCBlbnRlclBhZ2VJbmRleCwgbGVhdmVQYWdlSW5kZXgsIGRvbmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIG11c3QgYmUgaW1wbGVtZW50ZWQuJyk7XG4gIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgVGFiYmFyTm9uZUFuaW1hdG9yIGV4dGVuZHMgVGFiYmFyQW5pbWF0b3Ige1xuICBhcHBseShlbnRlclBhZ2UsIGxlYXZlUGFnZSwgZW50ZXJJbmRleCwgbGVhdmVJbmRleCwgZG9uZSkge1xuICAgIHNldFRpbWVvdXQoZG9uZSwgMTAwMCAvIDYwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgVGFiYmFyRmFkZUFuaW1hdG9yIGV4dGVuZHMgVGFiYmFyQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zLnRpbWluZyA9IG9wdGlvbnMudGltaW5nICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRpbWluZyA6ICdsaW5lYXInO1xuICAgIG9wdGlvbnMuZHVyYXRpb24gPSBvcHRpb25zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmR1cmF0aW9uIDogJzAuNCc7XG4gICAgb3B0aW9ucy5kZWxheSA9IG9wdGlvbnMuZGVsYXkgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZGVsYXkgOiAnMCc7XG5cbiAgICBzdXBlcihvcHRpb25zKTtcbiAgfVxuXG4gIGFwcGx5KGVudGVyUGFnZSwgbGVhdmVQYWdlLCBlbnRlclBhZ2VJbmRleCwgbGVhdmVQYWdlSW5kZXgsIGRvbmUpIHtcbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KGVudGVyUGFnZSlcbiAgICAgICAgLnNhdmVTdHlsZSgpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyxcbiAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUYWJiYXJTbGlkZUFuaW1hdG9yIGV4dGVuZHMgVGFiYmFyQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zLnRpbWluZyA9IG9wdGlvbnMudGltaW5nICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRpbWluZyA6ICdlYXNlLWluJztcbiAgICBvcHRpb25zLmR1cmF0aW9uID0gb3B0aW9ucy5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kdXJhdGlvbiA6ICcwLjE1JztcbiAgICBvcHRpb25zLmRlbGF5ID0gb3B0aW9ucy5kZWxheSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kZWxheSA6ICcwJztcblxuICAgIHN1cGVyKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7anFMaXRlfSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtqcUxpdGV9IGxlYXZlUGFnZVxuICAgKi9cbiAgYXBwbHkoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGVudGVySW5kZXgsIGxlYXZlSW5kZXgsIGRvbmUpIHtcbiAgICBjb25zdCBzZ24gPSBlbnRlckluZGV4ID4gbGVhdmVJbmRleDtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAuc2F2ZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgnICsgKHNnbiA/ICcnIDogJy0nKSArICcxMDAlLCAwLCAwKScsXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICAgICAucmVzdG9yZVN0eWxlKClcbiAgICAgICAgLnF1ZXVlKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pLFxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsXG4gICAgICAgIH0pXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoJyArIChzZ24gPyAnLScgOiAnJykgKyAnMTAwJSwgMCwgMCknLFxuICAgICAgICB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICAgICAgdGltaW5nOiB0aGlzLnRpbWluZ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi8uLi9vbnMvYmFzZS1lbGVtZW50JztcbmltcG9ydCB7VGFiYmFyQW5pbWF0b3IsIFRhYmJhckZhZGVBbmltYXRvciwgVGFiYmFyTm9uZUFuaW1hdG9yLCBUYWJiYXJTbGlkZUFuaW1hdG9yfSBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBUYWJFbGVtZW50IGZyb20gJy4uL29ucy10YWInO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy50YWItYmFyX19jb250ZW50JzogJ3RhYi1iYXItLSpfX2NvbnRlbnQnLFxuICAnLnRhYi1iYXInOiAndGFiLWJhci0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogVGFiYmFyTm9uZUFuaW1hdG9yLFxuICAnZmFkZSc6IFRhYmJhckZhZGVBbmltYXRvcixcbiAgJ3NsaWRlJzogVGFiYmFyU2xpZGVBbmltYXRvcixcbiAgJ25vbmUnOiBUYWJiYXJOb25lQW5pbWF0b3Jcbn07XG5cbmNvbnN0IHJld3JpdGFibGVzID0ge1xuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSB0YWJiYXJFbGVtZW50XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICByZWFkeSh0YWJiYXJFbGVtZW50LCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gdGFiYmFyRWxlbWVudFxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldFxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgbGluayh0YWJiYXJFbGVtZW50LCB0YXJnZXQsIG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sodGFyZ2V0KTtcbiAgfSxcblxuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSB0YWJiYXJFbGVtZW50XG4gICAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICB1bmxpbmsodGFiYmFyRWxlbWVudCwgdGFyZ2V0LCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKHRhcmdldCk7XG4gIH1cbn07XG5cbmNvbnN0IGdlbmVyYXRlSWQgPSAoKCkgPT4ge1xuICBsZXQgaSA9IDA7XG4gIHJldHVybiAoKSA9PiAnb25zLXRhYmJhci1nZW4tJyArIChpKyspO1xufSkoKTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdGFiYmFyXG4gKiBAY2F0ZWdvcnkgdGFiYmFyXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUEgY29tcG9uZW50IHRvIGRpc3BsYXkgYSB0YWIgYmFyIG9uIHRoZSBib3R0b20gb2YgYSBwYWdlLiBVc2VkIHdpdGggYDxvbnMtdGFiPmAgdG8gbWFuYWdlIHBhZ2VzIHVzaW5nIHRhYnMuWy9lbl1cbiAqICAgW2phXeOCv+ODluODkOODvOOCkuODmuODvOOCuOS4i+mDqOOBq+ihqOekuuOBmeOCi+OBn+OCgeOBruOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAgm9ucy10YWLjgajntYTjgb/lkIjjgo/jgZvjgabkvb/jgYbjgZPjgajjgafjgIHjg5rjg7zjgrjjgpLnrqHnkIbjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gcEd1RExcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS90YWJiYXJcbiAqIEBndWlkZSBtdWx0aXBsZS1wYWdlLW5hdmlnYXRpb25cbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFdTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXNbL2phXVxuICogQGd1aWRlIHRlbXBsYXRlc1xuICogICBbZW5dRGVmaW5pbmcgbXVsdGlwbGUgcGFnZXMgaW4gc2luZ2xlIGh0bWxbL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KSMeOBpOOBrkhUTUzjgavoqJjov7DjgZnjgotbL2phXVxuICogQHNlZWFsc28gb25zLXRhYlxuICogICBbZW5dVGhlIGA8b25zLXRhYj5gIGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdb25zLXRhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcGFnZVxuICogICBbZW5dVGhlIGA8b25zLXBhZ2U+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXW9ucy1wYWdl44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRhYmJhcj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwiaG9tZS5odG1sXCJcbiAqICAgICBsYWJlbD1cIkhvbWVcIlxuICogICAgIGFjdGl2ZT5cbiAqICAgPC9vbnMtdGFiPlxuICogICA8b25zLXRhYlxuICogICAgIHBhZ2U9XCJzZXR0aW5ncy5odG1sXCJcbiAqICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqIDwvb25zLXRhYmJhcj5cbiAqXG4gKiA8b25zLXRlbXBsYXRlIGlkPVwiaG9tZS5odG1sXCI+XG4gKiAgIC4uLlxuICogPC9vbnMtdGVtcGxhdGU+XG4gKlxuICogPG9ucy10ZW1wbGF0ZSBpZD1cInNldHRpbmdzLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L29ucy10ZW1wbGF0ZT5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGFiYmFyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IHByZWNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMganVzdCBiZWZvcmUgdGhlIHRhYiBpcyBjaGFuZ2VkLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+ODhuOCo+ODluOBquOCv+ODluOBjOWkieOCj+OCi+WJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgaW5kZXguWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KLb25zLXRhYuOBruOCpOODs+ODh+ODg+OCr+OCueOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC50YWJJdGVtXG4gICAqICAgW2VuXVRhYiBpdGVtIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV10YWJJdGVt44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUNhbGwgdGhpcyBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGNoYW5nZSBldmVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlkbzjgbPlh7rjgZnjgajjgIHjgqLjgq/jg4bjgqPjg5bjgarjgr/jg5bjga7lpInmm7TjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RjaGFuZ2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVzIGp1c3QgYWZ0ZXIgdGhlIHRhYiBpcyBjaGFuZ2VkLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+ODhuOCo+ODluOBquOCv+ODluOBjOWkieOCj+OBo+OBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgaW5kZXguWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KLb25zLXRhYuOBruOCpOODs+ODh+ODg+OCr+OCueOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC50YWJJdGVtXG4gICAqICAgW2VuXVRhYiBpdGVtIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV10YWJJdGVt44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCByZWFjdGl2ZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMgaWYgdGhlIGFscmVhZHkgb3BlbiB0YWIgaXMgdGFwcGVkIGFnYWluLlsvZW5dXG4gICAqICAgW2phXeOBmeOBp+OBq+OCouOCr+ODhuOCo+ODluOBq+OBquOBo+OBpuOBhOOCi+OCv+ODluOBjOOCguOBhuS4gOW6puOCv+ODg+ODl+OChOOCr+ODquODg+OCr+OBleOCjOOBn+WgtOWQiOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgaW5kZXguWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KLb25zLXRhYuOBruOCpOODs+ODh+ODg+OCr+OCueOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC50YWJJdGVtXG4gICAqICAgW2VuXVRhYiBpdGVtIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV10YWJJdGVt44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IG5vbmVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgdmFsdWVzIGFyZSBgXCJub25lXCJgLCBgXCJzbGlkZVwiYCBhbmQgYFwiZmFkZVwiYC4gRGVmYXVsdCBpcyBgXCJub25lXCJgLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOiqreOBv+i+vOOBv+aZguOBruOCouODi+ODoeODvOOCt+ODp+ODs+OCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwi44CBXCJmYWRlXCLjgIFcInNsaWRlXCLjga7jgYTjgZrjgozjgYvjgpLpgbjmip7jgafjgY3jgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga9cIm5vbmVcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwb3NpdGlvblxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYm90dG9tXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UYWJiYXIncyBwb3NpdGlvbi4gQXZhaWxhYmxlIHZhbHVlcyBhcmUgYFwiYm90dG9tXCJgIGFuZCBgXCJ0b3BcImAuIFVzZSBgXCJhdXRvXCJgIHRvIGNob29zZSBwb3NpdGlvbiBkZXBlbmRpbmcgb24gcGxhdGZvcm0gKGlPUyBib3R0b20sIEFuZHJvaWQgdG9wKS5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg5bjg5Djg7zjga7kvY3nva7jgpLmjIflrprjgZfjgb7jgZnjgIJcImJvdHRvbVwi44KC44GX44GP44GvXCJ0b3BcIuOCkumBuOaKnuOBp+OBjeOBvuOBmeOAguODh+ODleOCqeODq+ODiOOBr1wiYm90dG9tXCLjgafjgZnjgIJbL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIHRoaXMuX3RhYmJhcklkID0gZ2VuZXJhdGVJZCgpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcblxuICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuX2NvbnRlbnRFbGVtZW50O1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb250ZW50LmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnRlbnQuY2hpbGRyZW5baV0uc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIH1cblxuICAgICAgY29uc3QgYWN0aXZlSW5kZXggPSB0aGlzLmdldEF0dHJpYnV0ZSgnYWN0aXZlSW5kZXgnKTtcblxuICAgICAgY29uc3QgdGFiYmFyID0gdGhpcy5fdGFiYmFyRWxlbWVudDtcbiAgICAgIGlmIChhY3RpdmVJbmRleCAmJiB0YWJiYXIuY2hpbGRyZW4ubGVuZ3RoID4gYWN0aXZlSW5kZXgpIHtcbiAgICAgICAgdGFiYmFyLmNoaWxkcmVuW2FjdGl2ZUluZGV4XS5zZXRBdHRyaWJ1dGUoJ2FjdGl2ZScsICd0cnVlJyk7XG4gICAgICB9XG5cbiAgICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuXG4gICAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgICBiYXNlQ2xhc3M6IFRhYmJhckFuaW1hdG9yLFxuICAgICAgICBiYXNlQ2xhc3NOYW1lOiAnVGFiYmFyQW5pbWF0b3InLFxuICAgICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJylcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCkpO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy50YWItYmFyX19jb250ZW50Jyk7XG4gIH1cblxuICBnZXQgX3RhYmJhckVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcudGFiLWJhcicpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRlbnRFbGVtZW50ICYmIHRoaXMuX3RhYmJhckVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRhYi1iYXJfX2NvbnRlbnQnKTtcbiAgICAgIGNvbnN0IGJhciA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcudGFiLWJhcicpO1xuXG4gICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ29ucy10YWItYmFyX19jb250ZW50Jyk7XG4gICAgICBiYXIuY2xhc3NMaXN0LmFkZCgnb25zLXRhYi1iYXJfX2Zvb3RlcicpO1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIGNvbnN0IGNvbnRlbnQgPSB1dGlsLmNyZWF0ZSgnLm9ucy10YWItYmFyX19jb250ZW50LnRhYi1iYXJfX2NvbnRlbnQnKTtcbiAgICAgIGNvbnN0IHRhYmJhciA9IHV0aWwuY3JlYXRlKCcudGFiLWJhci5vbnMtdGFiLWJhcl9fZm9vdGVyJyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgdGFiYmFyLmFwcGVuZENoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQoY29udGVudCk7XG4gICAgICB0aGlzLmFwcGVuZENoaWxkKHRhYmJhcik7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJykpIHtcbiAgICBjb25zdCB0b3AgPSB0aGlzLl90b3AgPSBwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgKHBvc2l0aW9uID09PSAnYXV0bycgJiYgcGxhdGZvcm0uaXNBbmRyb2lkKCkpO1xuICAgIGNvbnN0IGFjdGlvbiA9IHRvcCA/IHV0aWwuYWRkTW9kaWZpZXIgOiB1dGlsLnJlbW92ZU1vZGlmaWVyO1xuXG4gICAgYWN0aW9uKHRoaXMsICd0b3AnKTtcblxuICAgIGNvbnN0IHBhZ2UgPSB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy1wYWdlJyk7XG4gICAgaWYgKHBhZ2UpIHtcbiAgICAgIHRoaXMuc3R5bGUudG9wID0gdG9wID8gd2luZG93LmdldENvbXB1dGVkU3R5bGUocGFnZS5fZ2V0Q29udGVudEVsZW1lbnQoKSwgbnVsbCkuZ2V0UHJvcGVydHlWYWx1ZSgncGFkZGluZy10b3AnKSA6ICcnO1xuXG4gICAgICBpZiAodXRpbC5tYXRjaChwYWdlLmZpcnN0Q2hpbGQsICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICAgIGFjdGlvbihwYWdlLmZpcnN0Q2hpbGQsICdub3NoYWRvdycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsKCgpID0+IHtcbiAgICAgIGNvbnN0IGZpbGxlZCA9IHV0aWwuZmluZFBhcmVudCh0aGlzLCBlID0+IGUuaGFzQXR0cmlidXRlKCdzdGF0dXMtYmFyLWZpbGwnKSk7XG4gICAgICB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnc3RhdHVzLWJhci1maWxsJywgdG9wICYmICFmaWxsZWQpO1xuICAgIH0pO1xuICB9XG5cbiAgX2dldFRhYmJhckVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcudGFiLWJhcicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbG9hZFBhZ2VcbiAgICogQGRlcHJlY2F0ZWRcbiAgICogQHNpZ25hdHVyZSBsb2FkUGFnZSh1cmwsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGRvY3VtZW50IG9yIGFuIGA8b25zLXRlbXBsYXRlPmAgaWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr29ucy10ZW1wbGF0ZeOBp+Wuo+iogOOBl+OBn2lk5bGe5oCn44Gu5YCk44KS5Yip55So44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXlzIGEgbmV3IHBhZ2Ugd2l0aG91dCBjaGFuZ2luZyB0aGUgYWN0aXZlIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruOCouOCr+ODhuOCo+ODluOBquOCpOODs+ODh+ODg+OCr+OCueOCkuWkieabtOOBm+OBmuOBq+OAgeaWsOOBl+OBhOODmuODvOOCuOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgbmV3IHBhZ2UgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgbG9hZFBhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc29sZS53YXJuKCdUaGUgbG9hZFBhZ2UgbWV0aG9kIGhhcyBiZWVuIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgbmV4dCBtaW5vciB2ZXJzaW9uLicpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgdGFiID0gdGhpcy5fdGFiYmFyRWxlbWVudC5jaGlsZHJlblswXSB8fCBuZXcgVGFiRWxlbWVudCgpO1xuICAgICAgdGFiLl9sb2FkUGFnZShwYWdlLCB0aGlzLl9jb250ZW50RWxlbWVudCwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICByZXNvbHZlKHRoaXMuX2xvYWRQYWdlRE9NQXN5bmMocGFnZUVsZW1lbnQsIG9wdGlvbnMpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gcGFnZUVsZW1lbnRcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50LlxuICAgKi9cbiAgX2xvYWRQYWdlRE9NQXN5bmMocGFnZUVsZW1lbnQsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHJld3JpdGFibGVzLmxpbmsodGhpcywgcGFnZUVsZW1lbnQsIG9wdGlvbnMsIHBhZ2VFbGVtZW50ID0+IHtcbiAgICAgICAgdGhpcy5fY29udGVudEVsZW1lbnQuYXBwZW5kQ2hpbGQocGFnZUVsZW1lbnQpO1xuXG4gICAgICAgIGlmICh0aGlzLmdldEFjdGl2ZVRhYkluZGV4KCkgIT09IC0xKSB7XG4gICAgICAgICAgcmVzb2x2ZSh0aGlzLl9zd2l0Y2hQYWdlKHBhZ2VFbGVtZW50LCBvcHRpb25zKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fb2xkUGFnZUVsZW1lbnQgPSBwYWdlRWxlbWVudDtcbiAgICAgICAgICByZXNvbHZlKHBhZ2VFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0VGFiYmFySWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3RhYmJhcklkO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnQvbnVsbH1cbiAgICovXG4gIF9nZXRDdXJyZW50UGFnZUVsZW1lbnQoKSB7XG4gICAgY29uc3QgcGFnZXMgPSB0aGlzLl9jb250ZW50RWxlbWVudC5jaGlsZHJlbjtcbiAgICBsZXQgcGFnZSA9IG51bGw7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBhZ2VzW2ldLnN0eWxlLmRpc3BsYXkgIT09ICdub25lJykge1xuICAgICAgICBwYWdlID0gcGFnZXNbaV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwYWdlICYmIHBhZ2Uubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAhPT0gJ29ucy1wYWdlJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0YXRlOiBwYWdlIGVsZW1lbnQgbXVzdCBiZSBhIFwib25zLXBhZ2VcIiBlbGVtZW50LicpO1xuICAgIH1cblxuICAgIHJldHVybiBwYWdlO1xuICB9XG5cbiAgZ2V0IHBhZ2VzKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLl9jb250ZW50RWxlbWVudC5jaGlsZHJlbik7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuc2VsZWN0ZWRUYWJJbmRleFxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5wcmV2aW91c1RhYkluZGV4XG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50LlxuICAgKi9cbiAgX3N3aXRjaFBhZ2UoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIGNvbnN0IG9sZFBhZ2VFbGVtZW50ID0gdGhpcy5fb2xkUGFnZUVsZW1lbnQgfHwgaW50ZXJuYWwubnVsbEVsZW1lbnQ7XG4gICAgdGhpcy5fb2xkUGFnZUVsZW1lbnQgPSBlbGVtZW50O1xuICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgaWYgKG9sZFBhZ2VFbGVtZW50ICE9PSBpbnRlcm5hbC5udWxsRWxlbWVudCkge1xuICAgICAgICBvbGRQYWdlRWxlbWVudC5faGlkZSgpO1xuICAgICAgfVxuXG4gICAgICBhbmltYXRvci5hcHBseShlbGVtZW50LCBvbGRQYWdlRWxlbWVudCwgb3B0aW9ucy5zZWxlY3RlZFRhYkluZGV4LCBvcHRpb25zLnByZXZpb3VzVGFiSW5kZXgsICgpID0+IHtcbiAgICAgICAgaWYgKG9sZFBhZ2VFbGVtZW50ICE9PSBpbnRlcm5hbC5udWxsRWxlbWVudCkge1xuICAgICAgICAgIG9sZFBhZ2VFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgICBlbGVtZW50Ll9zaG93KCk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc29sdmUoZWxlbWVudCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNldEFjdGl2ZVRhYlxuICAgKiBAc2lnbmF0dXJlIHNldEFjdGl2ZVRhYihpbmRleCwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogICBbZW5dVGFiIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeOCv+ODluOBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmtlZXBQYWdlXVxuICAgKiAgIFtlbl1JZiB0cnVlIHRoZSBwYWdlIHdpbGwgbm90IGJlIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844GM54++5Zyo6KGo56S644GX44Gm44GE44KLcGFnZeOCkuWkieOBiOOBquOBhOWgtOWQiOOBq+OBr3RydWXjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcImZhZGVcImAsIGBcInNsaWRlXCJgIGFuZCBgXCJub25lXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAgmBcImZhZGVcImDjgIFgXCJzbGlkZVwiYOOAgWBcIm5vbmVcImDjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgc3BlY2lmaWVkIHRhYiBwYWdlLiBBbmltYXRpb25zIGFuZCBvdGhlciBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQgYnkgdGhlIHNlY29uZCBwYXJhbWV0ZXIuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44Gf44Kk44Oz44OH44OD44Kv44K544Gu44K/44OW44KS6KGo56S644GX44G+44GZ44CC44Ki44OL44Oh44O844K344On44Oz44Gq44Gp44Gu44Kq44OX44K344On44Oz44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldEFjdGl2ZVRhYihpbmRleCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgdHlwZW9mIG9wdGlvbnMgIT0gJ29iamVjdCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignb3B0aW9ucyBtdXN0IGJlIGFuIG9iamVjdC4gWW91IHN1cHBsaWVkICcgKyBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgIEFuaW1hdG9yRmFjdG9yeS5wYXJzZUFuaW1hdGlvbk9wdGlvbnNTdHJpbmcodGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbi1vcHRpb25zJykpXG4gICAgKTtcblxuICAgIGlmICghb3B0aW9ucy5hbmltYXRpb24gJiYgdGhpcy5oYXNBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpKSB7XG4gICAgICBvcHRpb25zLmFuaW1hdGlvbiA9IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcmV2aW91c1RhYiA9IHRoaXMuX2dldEFjdGl2ZVRhYkVsZW1lbnQoKSxcbiAgICAgIHNlbGVjdGVkVGFiID0gdGhpcy5fZ2V0VGFiRWxlbWVudChpbmRleCksXG4gICAgICBwcmV2aW91c1RhYkluZGV4ID0gdGhpcy5nZXRBY3RpdmVUYWJJbmRleCgpLFxuICAgICAgc2VsZWN0ZWRUYWJJbmRleCA9IGluZGV4LFxuICAgICAgcHJldmlvdXNQYWdlRWxlbWVudCA9IHRoaXMuX2dldEN1cnJlbnRQYWdlRWxlbWVudCgpO1xuXG4gICAgaWYgKCFzZWxlY3RlZFRhYikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdTcGVjaWZpZWQgaW5kZXggZG9lcyBub3QgbWF0Y2ggYW55IHRhYi4nKTtcbiAgICB9XG5cbiAgICBpZiAoc2VsZWN0ZWRUYWJJbmRleCA9PT0gcHJldmlvdXNUYWJJbmRleCkge1xuICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdyZWFjdGl2ZScsIHtcbiAgICAgICAgaW5kZXg6IHNlbGVjdGVkVGFiSW5kZXgsXG4gICAgICAgIHRhYkl0ZW06IHNlbGVjdGVkVGFiXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcmV2aW91c1BhZ2VFbGVtZW50KTtcbiAgICB9XG5cbiAgICBsZXQgY2FuY2VsZWQgPSBmYWxzZTtcblxuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncHJlY2hhbmdlJywge1xuICAgICAgaW5kZXg6IHNlbGVjdGVkVGFiSW5kZXgsXG4gICAgICB0YWJJdGVtOiBzZWxlY3RlZFRhYixcbiAgICAgIGNhbmNlbDogKCkgPT4gY2FuY2VsZWQgPSB0cnVlXG4gICAgfSk7XG5cbiAgICBpZiAoY2FuY2VsZWQpIHtcbiAgICAgIHNlbGVjdGVkVGFiLnNldEluYWN0aXZlKCk7XG4gICAgICBpZiAocHJldmlvdXNUYWIpIHtcbiAgICAgICAgcHJldmlvdXNUYWIuc2V0QWN0aXZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZWNoYW5nZSBldmVudC4nKTtcbiAgICB9XG5cbiAgICBzZWxlY3RlZFRhYi5zZXRBY3RpdmUoKTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBwcmV2aW91c1RhYkluZGV4OiBwcmV2aW91c1RhYkluZGV4LFxuICAgICAgc2VsZWN0ZWRUYWJJbmRleDogc2VsZWN0ZWRUYWJJbmRleFxuICAgIH07XG5cbiAgICBpZiAocHJldmlvdXNUYWIpIHtcbiAgICAgIHByZXZpb3VzVGFiLnNldEluYWN0aXZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcmFtcy5hbmltYXRpb24gPSAnbm9uZSc7XG4gICAgfVxuXG4gICAgY29uc3QgbGluayA9IChlbGVtZW50LCBjYWxsYmFjaykgPT4ge1xuICAgICAgcmV3cml0YWJsZXMubGluayh0aGlzLCBlbGVtZW50LCBvcHRpb25zLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHNlbGVjdGVkVGFiLl9sb2FkUGFnZUVsZW1lbnQodGhpcy5fY29udGVudEVsZW1lbnQsIHBhZ2VFbGVtZW50ID0+IHtcbiAgICAgICAgcGFnZUVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdzdHlsZScpO1xuXG4gICAgICAgIHRoaXMuX3N3aXRjaFBhZ2UocGFnZUVsZW1lbnQsIHBhcmFtcylcbiAgICAgICAgICAgIC50aGVuKChwYWdlKSA9PiB7XG4gICAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncG9zdGNoYW5nZScsIHtcbiAgICAgICAgICAgICAgICBpbmRleDogc2VsZWN0ZWRUYWJJbmRleCxcbiAgICAgICAgICAgICAgICB0YWJJdGVtOiBzZWxlY3RlZFRhYlxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShwYWdlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgfSwgbGluayk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRUYWJiYXJWaXNpYmlsaXR5XG4gICAqIEBzaWduYXR1cmUgc2V0VGFiYmFyVmlzaWJpbGl0eSh2aXNpYmxlKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZpc2libGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZWQgdG8gaGlkZSBvciBzaG93IHRoZSB0YWIgYmFyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXRUYWJiYXJWaXNpYmlsaXR5KHZpc2libGUpIHtcbiAgICB0aGlzLl9jb250ZW50RWxlbWVudC5zdHlsZVt0aGlzLl90b3AgPyAndG9wJyA6ICdib3R0b20nXSA9IHZpc2libGUgPyAnJyA6ICcwcHgnO1xuICAgIHRoaXMuX2dldFRhYmJhckVsZW1lbnQoKS5zdHlsZS5kaXNwbGF5ID0gdmlzaWJsZSA/ICcnIDogJ25vbmUnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgZ2V0QWN0aXZlVGFiSW5kZXhcbiAgICogQHNpZ25hdHVyZSBnZXRBY3RpdmVUYWJJbmRleCgpXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICogICBbZW5dVGhlIGluZGV4IG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIHRhYi5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgovjgr/jg5bjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB0YWIgaW5kZXggb24gY3VycmVudCBhY3RpdmUgdGFiLiBJZiBhY3RpdmUgdGFiIGlzIG5vdCBmb3VuZCwgcmV0dXJucyAtMS5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgovjgr/jg5bjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLov5TjgZfjgb7jgZnjgILnj77lnKjjgqLjgq/jg4bjgqPjg5bjgarjgr/jg5bjgYzjgarjgYTloLTlkIjjgavjga8tMeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXRBY3RpdmVUYWJJbmRleCgpIHtcbiAgICBjb25zdCB0YWJzID0gdGhpcy5fZ2V0VGFiYmFyRWxlbWVudCgpLmNoaWxkcmVuO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YWJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGFic1tpXSBpbnN0YW5jZW9mIFRhYkVsZW1lbnQgJiYgdGFic1tpXS5pc0FjdGl2ZSAmJiB0YWJzW2ldLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge051bWJlcn0gV2hlbiBhY3RpdmUgdGFiIGlzIG5vdCBmb3VuZCwgcmV0dXJucyAtMS5cbiAgICovXG4gIF9nZXRBY3RpdmVUYWJFbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRUYWJFbGVtZW50KHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgoKSk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIF9nZXRUYWJFbGVtZW50KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFRhYmJhckVsZW1lbnQoKS5jaGlsZHJlbltpbmRleF07XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHsgfVxuXG4gIF9zaG93KCkge1xuICAgIGNvbnN0IGN1cnJlbnRQYWdlRWxlbWVudCA9IHRoaXMuX2dldEN1cnJlbnRQYWdlRWxlbWVudCgpO1xuICAgIGlmIChjdXJyZW50UGFnZUVsZW1lbnQpIHtcbiAgICAgIGN1cnJlbnRQYWdlRWxlbWVudC5fc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIGNvbnN0IGN1cnJlbnRQYWdlRWxlbWVudCA9IHRoaXMuX2dldEN1cnJlbnRQYWdlRWxlbWVudCgpO1xuICAgIGlmIChjdXJyZW50UGFnZUVsZW1lbnQpIHtcbiAgICAgIGN1cnJlbnRQYWdlRWxlbWVudC5faGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIF9kZXN0cm95KCkge1xuICAgIGNvbnN0IHBhZ2VzID0gdGhpcy5fY29udGVudEVsZW1lbnQuY2hpbGRyZW47XG4gICAgZm9yIChsZXQgaSA9IHBhZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBwYWdlc1tpXS5fZGVzdHJveSgpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IHJld3JpdGFibGVzKCkge1xuICAgIHJldHVybiByZXdyaXRhYmxlcztcbiAgfVxuXG4gIHN0YXRpYyBnZXQgVGFiYmFyQW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIFRhYmJhckFuaW1hdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFRhYmJhckFuaW1hdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0IFRhYmJhckVsZW1lbnQuVGFiYmFyQW5pbWF0b3InKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG59XG5cbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXRhYmJhcicsIFRhYmJhckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgVGFiYmFyRWxlbWVudCBmcm9tICcuL29ucy10YWJiYXInO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQge1BhZ2VMb2FkZXIsIGRlZmF1bHRQYWdlTG9hZGVyfSBmcm9tICcuLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAndGFiLWJhci0tKl9faXRlbScsXG4gICcudGFiLWJhcl9fYnV0dG9uJzogJ3RhYi1iYXItLSpfX2J1dHRvbidcbn07XG5jb25zdCB0ZW1wbGF0ZVNvdXJjZSA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gIDxkaXY+XG4gICAgPGlucHV0IHR5cGU9XCJyYWRpb1wiIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiPlxuICAgIDxidXR0b24gY2xhc3M9XCJ0YWItYmFyX19idXR0b25cIj48L2J1dHRvbj5cbiAgPC9kaXY+XG5gKTtcbmNvbnN0IGRlZmF1bHRJbm5lclRlbXBsYXRlU291cmNlID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgPGRpdj5cbiAgICA8ZGl2IGNsYXNzPVwidGFiLWJhcl9faWNvblwiPlxuICAgICAgPG9ucy1pY29uIGljb249XCJpb24tY2xvdWRcIj48L29ucy1pY29uPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJ0YWItYmFyX19sYWJlbFwiPmxhYmVsPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInRhYi1iYXJfX2JhZGdlIG5vdGlmaWNhdGlvblwiPjE8L2Rpdj5cbiAgPC9kaXY+XG5gKTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdGFiXG4gKiBAY2F0ZWdvcnkgdGFiYmFyXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlcHJlc2VudHMgYSB0YWIgaW5zaWRlIHRhYiBiYXIuIEVhY2ggYDxvbnMtdGFiPmAgcmVwcmVzZW50cyBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXVxuICogICAgIOOCv+ODluODkOODvOOBq+mFjee9ruOBleOCjOOCi+WQhOOCouOCpOODhuODoOOBruOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguOBneOCjOOBnuOCjOOBrm9ucy10YWLjga/jg5rjg7zjgrjjgpLooajjgZfjgb7jgZnjgIJcbiAqICAgICBvbnMtdGFi6KaB57Sg44Gu5Lit44Gr44Gv44CB44K/44OW44Gr6KGo56S644GV44KM44KL44Kz44Oz44OG44Oz44OE44KS55u05o6l6KiY6L+w44GZ44KL44GT44Go44GM5Ye65p2l44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBwR3VETFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3RhYmJhclxuICogQGd1aWRlIG11bHRpcGxlLXBhZ2UtbmF2aWdhdGlvblxuICogICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICAgW2phXU1hbmFnaW5nIG11bHRpcGxlIHBhZ2VzWy9qYV1dXG4gKiBAZ3VpZGUgdGVtcGxhdGVzXG4gKiAgIFtlbl1EZWZpbmluZyBtdWx0aXBsZSBwYWdlcyBpbiBzaW5nbGUgaHRtbFsvZW5dXG4gKiAgIFtqYV3opIfmlbDjga7jg5rjg7zjgrjjgpIx44Gk44GuSFRNTOOBq+iomOi/sOOBmeOCi1svamFdXG4gKiBAc2VlYWxzbyBvbnMtdGFiYmFyXG4gKiAgIFtlbl1vbnMtdGFiYmFyIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtdGFiYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1wYWdlXG4gKiAgIFtlbl1vbnMtcGFnZSBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXBhZ2XjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWljb25cbiAqICAgW2VuXW9ucy1pY29uIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtaWNvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10YWJiYXI+XG4gKiAgIDxvbnMtdGFiXG4gKiAgICAgcGFnZT1cImhvbWUuaHRtbFwiXG4gKiAgICAgbGFiZWw9XCJIb21lXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwic2V0dGluZ3MuaHRtbFwiXG4gKiAgICAgbGFiZWw9XCJTZXR0aW5nc1wiXG4gKiAgICAgYWN0aXZlPlxuICogICA8L29ucy10YWI+XG4gKiA8L29ucy10YWJiYXI+XG4gKlxuICogPG9ucy10ZW1wbGF0ZSBpZD1cImhvbWUuaHRtbFwiPlxuICogICAuLi5cbiAqIDwvb25zLXRlbXBsYXRlPlxuICpcbiAqIDxvbnMtdGVtcGxhdGUgaWQ9XCJzZXR0aW5ncy5odG1sXCI+XG4gKiAgIC4uLlxuICogPC9vbnMtdGVtcGxhdGU+XG5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGFiRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwYWdlXG4gICAqIEBpbml0b25seVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHBhZ2UgdGhhdCBpcyBkaXNwbGF5ZWQgd2hlbiB0aGUgdGFiIGlzIHRhcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1vbnMtdGFi44GM5Y+C54Wn44GZ44KL44Oa44O844K444G444GuVVJM44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWNvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBUaGUgaWNvbiBuYW1lIGZvciB0aGUgdGFiLiBDYW4gc3BlY2lmeSB0aGUgc2FtZSBpY29uIG5hbWUgYXMgYDxvbnMtaWNvbj5gLlxuICAgKiAgICAgSWYgeW91IG5lZWQgdG8gdXNlIHlvdXIgb3duIGljb24sIGNyZWF0ZSBhIENTUyBjbGFzcyB3aXRoIGBiYWNrZ3JvdW5kLWltYWdlYCBvciBhbnkgQ1NTIHByb3BlcnRpZXMgYW5kIHNwZWNpZnkgdGhlIG5hbWUgb2YgeW91ciBDU1MgY2xhc3MgaGVyZS5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOCouOCpOOCs+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAgm9ucy1pY29u44Go5ZCM44GY44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgICDlgIvliKXjgavjgqLjgqTjgrPjg7PjgpLjgqvjgrnjgr/jg57jgqTjgrrjgZnjgovloLTlkIjjga/jgIFiYWNrZ3JvdW5kLWltYWdl44Gq44Gp44GuQ1NT44K544K/44Kk44Or44KS55So44GE44Gm5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlLWljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBuYW1lIG9mIHRoZSBpY29uIHdoZW4gdGhlIHRhYiBpcyBhY3RpdmUuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gu6Zqb44Gu44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbGFiZWxcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBsYWJlbCBvZiB0aGUgdGFiIGl0ZW0uWy9lbl1cbiAgICogICBbamFd44Ki44Kk44Kz44Oz5LiL44Gr6KGo56S644GV44KM44KL44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYmFkZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXkgYSBub3RpZmljYXRpb24gYmFkZ2Ugb24gdG9wIG9mIHRoZSB0YWIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44K444Gr6KGo56S644GZ44KL5YaF5a6544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIGF0dHJpYnV0ZSBzaG91bGQgYmUgc2V0IHRvIHRoZSB0YWIgdGhhdCBpcyBhY3RpdmUgYnkgZGVmYXVsdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICBpbml0KCkge1xuICAgIHRoaXMuX3BhZ2VMb2FkZXIgPSBkZWZhdWx0UGFnZUxvYWRlcjtcbiAgICB0aGlzLl9wYWdlID0gbnVsbDtcblxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnbGFiZWwnKSB8fCB0aGlzLmhhc0F0dHJpYnV0ZSgnaWNvbicpIHx8IHRoaXMuaGFzQXR0cmlidXRlKCdiYWRnZScpKSB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuX2JvdW5kT25DbGljayA9IHRoaXMuX29uQ2xpY2suYmluZCh0aGlzKTtcbiAgfVxuXG4gIF9nZXRQYWdlVGFyZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLnBhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgfVxuXG4gIHNldCBwYWdlKHBhZ2UpIHtcbiAgICB0aGlzLl9wYWdlID0gcGFnZTtcbiAgfVxuXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgc2V0IHBhZ2VMb2FkZXIobG9hZGVyKSB7XG4gICAgaWYgKCEobG9hZGVyIGluc3RhbmNlb2YgUGFnZUxvYWRlcikpIHtcbiAgICAgIHRocm93IEVycm9yKCdGaXJzdCBwYXJhbWV0ZXIgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBQYWdlTG9hZGVyLicpO1xuICAgIH1cbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gbG9hZGVyO1xuICB9XG5cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBfdGVtcGxhdGVMb2FkZWQoKSB7XG4gICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNJbnB1dCA9IHRoaXMuY2hpbGRyZW5bMF0uZ2V0QXR0cmlidXRlKCd0eXBlJykgPT09ICdyYWRpbyc7XG4gICAgY29uc3QgaGFzQnV0dG9uID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy50YWItYmFyX19idXR0b24nKTtcblxuICAgIHJldHVybiBoYXNJbnB1dCAmJiBoYXNCdXR0b247XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgndGFiLWJhcl9faXRlbScpO1xuXG4gICAgaWYgKCF0aGlzLl90ZW1wbGF0ZUxvYWRlZCgpKSB7XG4gICAgICBjb25zdCBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgIGxldCBoYXNDaGlsZHJlbiA9IGZhbHNlO1xuXG4gICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLmNoaWxkTm9kZXNbMF07XG4gICAgICAgIHRoaXMucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKG5vZGUpO1xuXG4gICAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IE5vZGUuRUxFTUVOVF9OT0RFKSB7XG4gICAgICAgICAgaGFzQ2hpbGRyZW4gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gdGVtcGxhdGVTb3VyY2UuY2xvbmVOb2RlKHRydWUpO1xuICAgICAgd2hpbGUgKHRlbXBsYXRlLmNoaWxkcmVuWzBdKSB7XG4gICAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGVtcGxhdGUuY2hpbGRyZW5bMF0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBidXR0b24gPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRhYi1iYXJfX2J1dHRvbicpO1xuXG4gICAgICBpZiAoaGFzQ2hpbGRyZW4pIHtcbiAgICAgICAgYnV0dG9uLmFwcGVuZENoaWxkKGZyYWdtZW50KTtcbiAgICAgICAgdGhpcy5faGFzRGVmYXVsdFRlbXBsYXRlID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9oYXNEZWZhdWx0VGVtcGxhdGUgPSB0cnVlO1xuICAgICAgICB0aGlzLl91cGRhdGVEZWZhdWx0VGVtcGxhdGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG4gIH1cblxuICBfdXBkYXRlUmlwcGxlKCkge1xuICAgIC8vIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2J1dHRvbicpLCB0aGlzKTtcbiAgfVxuXG4gIF91cGRhdGVEZWZhdWx0VGVtcGxhdGUoKSB7XG4gICAgaWYgKCF0aGlzLl9oYXNEZWZhdWx0VGVtcGxhdGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBidXR0b24gPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRhYi1iYXJfX2J1dHRvbicpO1xuICAgIGNvbnN0IHRlbXBsYXRlID0gZGVmYXVsdElubmVyVGVtcGxhdGVTb3VyY2UuY2xvbmVOb2RlKHRydWUpO1xuICAgIGlmIChidXR0b24uY2hpbGRyZW4ubGVuZ3RoID09IDApIHtcbiAgICAgIHdoaWxlICh0ZW1wbGF0ZS5jaGlsZHJlblswXSkge1xuICAgICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGVtcGxhdGUuY2hpbGRyZW5bMF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghYnV0dG9uLnF1ZXJ5U2VsZWN0b3IoJy50YWItYmFyX19pY29uJykpIHtcbiAgICAgIGJ1dHRvbi5pbnNlcnRCZWZvcmUodGVtcGxhdGUucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2ljb24nKSwgYnV0dG9uLmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIGlmICghYnV0dG9uLnF1ZXJ5U2VsZWN0b3IoJy50YWItYmFyX19sYWJlbCcpKSB7XG4gICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGVtcGxhdGUucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2xhYmVsJykpO1xuICAgIH1cblxuICAgIGlmICghYnV0dG9uLnF1ZXJ5U2VsZWN0b3IoJy50YWItYmFyX19iYWRnZScpKSB7XG4gICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGVtcGxhdGUucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2JhZGdlJykpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGNvbnN0IGljb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgnaWNvbicpO1xuICAgIGNvbnN0IGxhYmVsID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2xhYmVsJyk7XG4gICAgY29uc3QgYmFkZ2UgPSB0aGlzLmdldEF0dHJpYnV0ZSgnYmFkZ2UnKTtcblxuICAgIGlmICh0eXBlb2YgaWNvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGdldEljb25FbGVtZW50KCkuc2V0QXR0cmlidXRlKCdpY29uJywgaWNvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHdyYXBwZXIgPSBidXR0b24ucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2ljb24nKTtcbiAgICAgIGlmICh3cmFwcGVyKSB7XG4gICAgICAgIHdyYXBwZXIucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBsYWJlbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGdldExhYmVsRWxlbWVudCgpLnRleHRDb250ZW50ID0gbGFiZWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gZ2V0TGFiZWxFbGVtZW50KCk7XG4gICAgICBpZiAobGFiZWwpIHtcbiAgICAgICAgbGFiZWwucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBiYWRnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGdldEJhZGdlRWxlbWVudCgpLnRleHRDb250ZW50ID0gYmFkZ2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gZ2V0QmFkZ2VFbGVtZW50KCk7XG4gICAgICBpZiAoYmFkZ2UpIHtcbiAgICAgICAgYmFkZ2UucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0TGFiZWxFbGVtZW50KCkge1xuICAgICAgcmV0dXJuIHNlbGYucXVlcnlTZWxlY3RvcignLnRhYi1iYXJfX2xhYmVsJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SWNvbkVsZW1lbnQoKSB7XG4gICAgICByZXR1cm4gc2VsZi5xdWVyeVNlbGVjdG9yKCdvbnMtaWNvbicpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJhZGdlRWxlbWVudCgpIHtcbiAgICAgIHJldHVybiBzZWxmLnF1ZXJ5U2VsZWN0b3IoJy50YWItYmFyX19iYWRnZScpO1xuICAgIH1cbiAgfVxuXG4gIF9vbkNsaWNrKCkge1xuICAgIGNvbnN0IHRhYmJhciA9IHRoaXMuX2ZpbmRUYWJiYXJFbGVtZW50KCk7XG4gICAgaWYgKHRhYmJhcikge1xuICAgICAgdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLl9maW5kVGFiSW5kZXgoKSk7XG4gICAgfVxuICB9XG5cbiAgc2V0QWN0aXZlKCkge1xuICAgIGNvbnN0IHJhZGlvID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJ2lucHV0Jyk7XG4gICAgcmFkaW8uY2hlY2tlZCA9IHRydWU7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTtcblxuICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMucXVlcnlTZWxlY3RvckFsbCgnW29ucy10YWItaW5hY3RpdmVdLCBvbnMtdGFiLWluYWN0aXZlJykpXG4gICAgICAuZm9yRWFjaChlbGVtZW50ID0+IGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJyk7XG4gICAgdXRpbC5hcnJheUZyb20odGhpcy5xdWVyeVNlbGVjdG9yQWxsKCdbb25zLXRhYi1hY3RpdmVdLCBvbnMtdGFiLWFjdGl2ZScpKVxuICAgICAgLmZvckVhY2goZWxlbWVudCA9PiBlbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnaW5oZXJpdCcpO1xuICB9XG5cbiAgc2V0SW5hY3RpdmUoKSB7XG4gICAgY29uc3QgcmFkaW8gPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnaW5wdXQnKTtcbiAgICByYWRpby5jaGVja2VkID0gZmFsc2U7XG4gICAgdGhpcy5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcblxuICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMucXVlcnlTZWxlY3RvckFsbCgnW29ucy10YWItaW5hY3RpdmVdLCBvbnMtdGFiLWluYWN0aXZlJykpXG4gICAgICAuZm9yRWFjaChlbGVtZW50ID0+IGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdpbmhlcml0Jyk7XG4gICAgdXRpbC5hcnJheUZyb20odGhpcy5xdWVyeVNlbGVjdG9yQWxsKCdbb25zLXRhYi1hY3RpdmVdLCBvbnMtdGFiLWFjdGl2ZScpKVxuICAgICAgLmZvckVhY2goZWxlbWVudCA9PiBlbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gcGFyZW50XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpbmtcbiAgICovXG4gIF9sb2FkUGFnZUVsZW1lbnQocGFyZW50LCBjYWxsYmFjaywgbGluaykge1xuICAgIGlmICghdGhpcy5fbG9hZGVkUGFnZSAmJiAhdGhpcy5fZ2V0UGFnZVRhcmdldCgpKSB7XG4gICAgICBjb25zdCBwYWdlcyA9IHRoaXMuX2ZpbmRUYWJiYXJFbGVtZW50KCkucGFnZXM7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuX2ZpbmRUYWJJbmRleCgpO1xuICAgICAgY2FsbGJhY2socGFnZXNbaW5kZXhdKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2xvYWRpbmdQYWdlKSB7XG4gICAgICB0aGlzLl9sb2FkaW5nUGFnZS50aGVuKChwYWdlKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHBhZ2UuZWxlbWVudCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLl9sb2FkZWRQYWdlKSB7XG4gICAgICBjb25zdCBkZWZlcnJlZCA9IHV0aWwuZGVmZXIoKTtcbiAgICAgIHRoaXMuX2xvYWRpbmdQYWdlID0gZGVmZXJyZWQucHJvbWlzZTtcblxuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlOiB0aGlzLl9nZXRQYWdlVGFyZ2V0KCksIHBhcmVudH0sIHBhZ2UgPT4ge1xuICAgICAgICB0aGlzLl9sb2FkZWRQYWdlID0gcGFnZTtcbiAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShwYWdlKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2xvYWRpbmdQYWdlO1xuXG4gICAgICAgIGxpbmsocGFnZS5lbGVtZW50LCBlbGVtZW50ID0+IHtcbiAgICAgICAgICBwYWdlLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgIGNhbGxiYWNrKHBhZ2UuZWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKHRoaXMuX2xvYWRlZFBhZ2UuZWxlbWVudCk7XG4gICAgfVxuICB9XG5cbiAgX2xvYWRQYWdlKHBhZ2UsIHBhcmVudCwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9wYWdlTG9hZGVyLmxvYWQoe3BhZ2UsIHBhcmVudH0sIHBhZ2UgPT4ge1xuICAgICAgY2FsbGJhY2socGFnZS5lbGVtZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBwYWdlRWxlbWVudCgpIHtcbiAgICBpZiAodGhpcy5fbG9hZGVkUGFnZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlZFBhZ2UuZWxlbWVudDtcbiAgICB9XG5cbiAgICBjb25zdCB0YWJiYXIgPSB0aGlzLl9maW5kVGFiYmFyRWxlbWVudCgpO1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5fZmluZFRhYkluZGV4KCk7XG5cbiAgICByZXR1cm4gdGFiYmFyLl9jb250ZW50RWxlbWVudC5jaGlsZHJlbltpbmRleF07XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQWN0aXZlKCkge1xuICAgIHJldHVybiB0aGlzLmNsYXNzTGlzdC5jb250YWlucygnYWN0aXZlJyk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gICAgaWYgKHRoaXMuX2xvYWRlZFBhZ2UpIHtcbiAgICAgIHRoaXMuX2xvYWRlZFBhZ2UudW5sb2FkKCk7XG4gICAgICB0aGlzLl9sb2FkZWRQYWdlID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fZW5zdXJlRWxlbWVudFBvc2l0aW9uKCk7XG5cbiAgICAgIGNvbnN0IHRhYmJhciA9IHRoaXMuX2ZpbmRUYWJiYXJFbGVtZW50KCk7XG5cbiAgICAgIGlmICh0YWJiYXIuaGFzQXR0cmlidXRlKCdtb2RpZmllcicpKSB7XG4gICAgICAgIGNvbnN0IHByZWZpeCA9IHRoaXMuaGFzQXR0cmlidXRlKCdtb2RpZmllcicpID8gdGhpcy5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgKyAnICcgOiAnJztcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgcHJlZml4ICsgdGFiYmFyLmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG9uUmVhZHkgPSAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLl9nZXRQYWdlVGFyZ2V0KCkgJiYgIXRoaXMuaGFzTG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5oYXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuX2xvYWRQYWdlRWxlbWVudCh0YWJiYXIuX2NvbnRlbnRFbGVtZW50LCBwYWdlRWxlbWVudCA9PiB7XG4gICAgICAgICAgICBwYWdlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgdGFiYmFyLl9jb250ZW50RWxlbWVudC5hcHBlbmRDaGlsZChwYWdlRWxlbWVudCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLl9maW5kVGFiSW5kZXgoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwgKHBhZ2VFbGVtZW50LCBkb25lKSA9PiB7XG4gICAgICAgICAgICBUYWJiYXJFbGVtZW50LnJld3JpdGFibGVzLmxpbmsodGFiYmFyLCBwYWdlRWxlbWVudCwge30sIGVsZW1lbnQgPT4gZG9uZShlbGVtZW50KSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIFRhYmJhckVsZW1lbnQucmV3cml0YWJsZXMucmVhZHkodGFiYmFyLCBvblJlYWR5KTtcblxuICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICAgIH0pO1xuICB9XG5cbiAgX2ZpbmRUYWJiYXJFbGVtZW50KCkge1xuICAgIGlmICh0aGlzLnBhcmVudE5vZGUgJiYgdGhpcy5wYXJlbnROb2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtdGFiYmFyJykge1xuICAgICAgcmV0dXJuIHRoaXMucGFyZW50Tm9kZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYXJlbnROb2RlLnBhcmVudE5vZGUgJiYgdGhpcy5wYXJlbnROb2RlLnBhcmVudE5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy10YWJiYXInKSB7XG4gICAgICByZXR1cm4gdGhpcy5wYXJlbnROb2RlLnBhcmVudE5vZGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBfZmluZFRhYkluZGV4KCkge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5wYXJlbnROb2RlLmNoaWxkcmVuO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICh0aGlzID09PSBlbGVtZW50c1tpXSkge1xuICAgICAgICByZXR1cm4gaTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfZW5zdXJlRWxlbWVudFBvc2l0aW9uKCkge1xuICAgIGlmICghdGhpcy5fZmluZFRhYmJhckVsZW1lbnQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIG9ucy10YWIgZWxlbWVudCBpcyBtdXN0IGJlIGNoaWxkIG9mIG9ucy10YWJiYXIgZWxlbWVudC4nKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnLCAnaWNvbicsICdsYWJlbCcsICdwYWdlJywgJ2JhZGdlJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVSaXBwbGUoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaWNvbic6XG4gICAgICBjYXNlICdsYWJlbCc6XG4gICAgICBjYXNlICdiYWRnZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVEZWZhdWx0VGVtcGxhdGUoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncGFnZSc6XG4gICAgICAgIGlmICh0eXBlb2YgY3VycmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLl9wYWdlID0gY3VycmVudDtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdGFiJywgVGFiRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vb25zL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IHNjaGVtZSA9IHsnJzogJ3Rvb2xiYXItYnV0dG9uLS0qJ307XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXRvb2xiYXItYnV0dG9uXG4gKiBAY2F0ZWdvcnkgcGFnZVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gdG9vbGJhciBidXR0b24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgb3V0bGluZVxuICogICBbZW5dQSBidXR0b24gd2l0aCBhbiBvdXRsaW5lLlsvZW5dXG4gKiAgIFtqYV3jgqLjgqbjg4jjg6njgqTjg7PjgpLjgoLjgaPjgZ/jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1CdXR0b24gY29tcG9uZW50IGZvciBvbnMtdG9vbGJhciBhbmQgb25zLWJvdHRvbS10b29sYmFyLlsvZW5dXG4gKiAgIFtqYV1vbnMtdG9vbGJhcuOBguOCi+OBhOOBr29ucy1ib3R0b20tdG9vbGJhcuOBq+ioree9ruOBp+OBjeOCi+ODnOOCv+ODs+eUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAY29kZXBlbiBhSG1HTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3BhZ2VcbiAqIEBndWlkZSBhZGRpbmctYS10b29sYmFyXG4gKiAgIFtlbl1BZGRpbmcgYSB0b29sYmFyWy9lbl1cbiAqICAgW2phXeODhOODvOODq+ODkOODvOOBrui/veWKoFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdG9vbGJhclxuICogICBbZW5dVGhlIGA8b25zLXRvb2xiYXI+YCBjb21wb25lbnQgZGlzcGxheXMgYSBuYXZpZ2F0aW9uIGJhciBhdCB0aGUgdG9wIG9mIGEgcGFnZS5bL2VuXVxuICogICBbamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWJhY2stYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtYmFjay1idXR0b24+YCBkaXNwbGF5cyBhIGJhY2sgYnV0dG9uIGluIHRoZSBuYXZpZ2F0aW9uIGJhci5bL2VuXVxuICogICBbamFdb25zLWJhY2stYnV0dG9u44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRvb2xiYXI+XG4gKiAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+XG4gKiAgICAgPG9ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgICAgIEJ1dHRvblxuICogICAgIDwvb25zLXRvb2xiYXItYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIFRpdGxlXG4gKiAgIDwvZGl2PlxuICogICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5cbiAqICAgICA8b25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgICAgPG9ucy1pY29uIGljb249XCJpb24tbmF2aWNvblwiIHNpemU9XCIyOHB4XCI+PC9vbnMtaWNvbj5cbiAqICAgICA8L29ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgPC9kaXY+XG4gKiA8L29ucy10b29sYmFyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUb29sYmFyQnV0dG9uRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGJ1dHRvbi5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7Pjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBpZiBidXR0b24gc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBpuOBj+OBoOOBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIGluaXQoKSB7XG4gICAgdGhpcy5fY29tcGlsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKCd0b29sYmFyLWJ1dHRvbicpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9vbGJhci1idXR0b24nLCBUb29sYmFyQnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL29ucy9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5yYW5nZSc6ICdyYW5nZS0tKicsXG4gICcucmFuZ2VfX2xlZnQnOiAncmFuZ2UtLSpfX2xlZnQnXG59O1xuXG5jb25zdCB0ZW1wbGF0ZVNvdXJjZSA9IHV0aWwuY3JlYXRlRWxlbWVudChgPGRpdj5cbiAgPGRpdiBjbGFzcz1cInJhbmdlX19sZWZ0XCI+PC9kaXY+XG4gIDxpbnB1dCB0eXBlPVwicmFuZ2VcIiBjbGFzcz1cInJhbmdlXCI+XG48L2Rpdj5gKTtcblxuY29uc3QgSU5QVVRfQVRUUklCVVRFUyA9IFtcbiAgJ2F1dG9mb2N1cycsXG4gICdkaXNhYmxlZCcsXG4gICdpbnB1dG1vZGUnLFxuICAnbWF4JyxcbiAgJ21pbicsXG4gICduYW1lJyxcbiAgJ3BsYWNlaG9sZGVyJyxcbiAgJ3JlYWRvbmx5JyxcbiAgJ3NpemUnLFxuICAnc3RlcCcsXG4gICd2YWxpZGF0b3InLFxuICAndmFsdWUnXG5dO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1yYW5nZVxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dTWF0ZXJpYWwgRGVzaWduIHNsaWRlclsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBSYW5nZSBpbnB1dCBjb21wb25lbnQuIFVzZWQgdG8gZGlzcGxheSBhIGRyYWdnYWJsZSBzbGlkZXIuXG4gKlxuICogICAgIFdvcmtzIHZlcnkgc2ltaWxhciB0byB0aGUgYDxpbnB1dCB0eXBlPVwicmFuZ2VcIj5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4geFpRb21NXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcmFuZ2VcbiAqIEBndWlkZSB1c2luZy1tb2RpZmllciBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1pbnB1dFxuICogICBbZW5dVGhlIGA8b25zLWlucHV0PmAgY29tcG9uZW50IGlzIHVzZWQgdG8gZGlzcGxheSB0ZXh0IGlucHV0cywgcmFkaW8gYnV0dG9ucyBhbmQgY2hlY2tib3hlcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJhbmdlIHZhbHVlPVwiMjBcIj48L29ucy1yYW5nZT5cbiAqIDxvbnMtcmFuZ2UgbW9kaWZpZXI9XCJtYXRlcmlhbFwiIHZhbHVlPVwiMTBcIj48L3JhbmdlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSYW5nZUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgaW5pdCgpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgICAgdGhpcy5fdXBkYXRlQm91bmRBdHRyaWJ1dGVzKCk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICBpZiAoISh1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnJhbmdlX19sZWZ0JykgJiYgdXRpbC5maW5kQ2hpbGQodGhpcywgJ2lucHV0JykpKSB7XG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IHRlbXBsYXRlU291cmNlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgIHdoaWxlICh0ZW1wbGF0ZS5jaGlsZHJlblswXSkge1xuICAgICAgICB0aGlzLmFwcGVuZENoaWxkKHRlbXBsYXRlLmNoaWxkcmVuWzBdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBfb25DaGFuZ2UoKSB7XG4gICAgdGhpcy5fbGVmdC5zdHlsZS53aWR0aCA9ICgxMDAgKiB0aGlzLl9yYXRpbykgKyAnJSc7XG4gIH1cblxuICBfb25EcmFnc3RhcnQoZSkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZS5nZXN0dXJlLnN0b3BQcm9wYWdhdGlvbigpO1xuICB9XG5cbiAgZ2V0IF9yYXRpbygpIHtcbiAgICAvLyBSZXR1cm5zIHRoZSBjdXJyZW50IHJhdGlvLlxuICAgIGNvbnN0IG1pbiA9IHRoaXMuX2lucHV0Lm1pbiA9PT0gJycgPyAwIDogcGFyc2VJbnQodGhpcy5faW5wdXQubWluKTtcbiAgICBjb25zdCBtYXggPSB0aGlzLl9pbnB1dC5tYXggPT09ICcnID8gMTAwIDogcGFyc2VJbnQodGhpcy5faW5wdXQubWF4KTtcblxuICAgIHJldHVybiAodGhpcy52YWx1ZSAtIG1pbikgLyAobWF4IC0gbWluKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgLi4uSU5QVVRfQVRUUklCVVRFU107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoSU5QVVRfQVRUUklCVVRFUy5pbmRleE9mKG5hbWUpID49IDApIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpO1xuXG4gICAgICAgIGlmIChuYW1lID09PSAnbWluJyB8fCBuYW1lID09PSAnbWF4Jykge1xuICAgICAgICAgIHRoaXMuX29uQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fb25EcmFnc3RhcnQpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9vbkNoYW5nZSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ3N0YXJ0KTtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2lucHV0JywgdGhpcy5fb25DaGFuZ2UpO1xuICB9XG5cbiAgX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpIHtcbiAgICBJTlBVVF9BVFRSSUJVVEVTLmZvckVhY2goKGF0dHIpID0+IHtcbiAgICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZShhdHRyKSkge1xuICAgICAgICB0aGlzLl9pbnB1dC5zZXRBdHRyaWJ1dGUoYXR0ciwgdGhpcy5nZXRBdHRyaWJ1dGUoYXR0cikpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGdldCBfaW5wdXQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignaW5wdXQnKTtcbiAgfVxuXG4gIGdldCBfbGVmdCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcucmFuZ2VfX2xlZnQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHZhbHVlLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lucHV0ID09PSBudWxsXG4gICAgICA/IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpXG4gICAgICA6IHRoaXMuX2lucHV0LnZhbHVlO1xuICB9XG5cbiAgc2V0IHZhbHVlKHZhbCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC52YWx1ZSA9IHZhbDtcbiAgICAgIHRoaXMuX29uQ2hhbmdlKCk7XG4gICAgfSk7XG4gIH1cbn1cblxuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcmFuZ2UnLCBSYW5nZUVsZW1lbnQpO1xuIiwiaW1wb3J0IG9ucyBmcm9tICcuL29ucy9vbnMnO1xuXG5pbXBvcnQgVGVtcGxhdGVFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXRlbXBsYXRlJztcbmltcG9ydCBJZkVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtaWYnO1xuaW1wb3J0IEFsZXJ0RGlhbG9nRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1hbGVydC1kaWFsb2cnO1xuaW1wb3J0IEJhY2tCdXR0b25FbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWJhY2stYnV0dG9uJztcbmltcG9ydCBCb3R0b21Ub29sYmFyRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1ib3R0b20tdG9vbGJhcic7XG5pbXBvcnQgQnV0dG9uRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1idXR0b24nO1xuaW1wb3J0IENhcm91c2VsSXRlbUVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtY2Fyb3VzZWwtaXRlbSc7XG5pbXBvcnQgQ2Fyb3VzZWxFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWNhcm91c2VsJztcbmltcG9ydCBDb2xFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWNvbCc7XG5pbXBvcnQgRGlhbG9nRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1kaWFsb2cnO1xuaW1wb3J0IEZhYkVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtZmFiJztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3JFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWdlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0IEljb25FbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWljb24nO1xuaW1wb3J0IExhenlSZXBlYXRFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWxhenktcmVwZWF0JztcbmltcG9ydCBMaXN0SGVhZGVyRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1saXN0LWhlYWRlcic7XG5pbXBvcnQgTGlzdEl0ZW1FbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWxpc3QtaXRlbSc7XG5pbXBvcnQgTGlzdEVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtbGlzdCc7XG5pbXBvcnQgSW5wdXRFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLWlucHV0JztcbmltcG9ydCBNb2RhbEVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtbW9kYWwnO1xuaW1wb3J0IE5hdmlnYXRvckVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtbmF2aWdhdG9yJztcbmltcG9ydCBQYWdlRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1wYWdlJztcbmltcG9ydCBQb3BvdmVyRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1wb3BvdmVyJztcbmltcG9ydCBQcm9ncmVzc0JhckVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtcHJvZ3Jlc3MtYmFyJztcbmltcG9ydCBQcm9ncmVzc0NpcmN1bGFyRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1wcm9ncmVzcy1jaXJjdWxhcic7XG5pbXBvcnQgUHVsbEhvb2tFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXB1bGwtaG9vayc7XG5pbXBvcnQgUmlwcGxlRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1yaXBwbGUnO1xuaW1wb3J0IFJvd0VsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtcm93JztcbmltcG9ydCBTcGVlZERpYWxJdGVtRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1zcGVlZC1kaWFsLWl0ZW0nO1xuaW1wb3J0IFNwZWVkRGlhbEVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbCc7XG5pbXBvcnQgU3BsaXR0ZXJDb250ZW50RWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy1zcGxpdHRlci1jb250ZW50JztcbmltcG9ydCBTcGxpdHRlck1hc2tFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyLW1hc2snO1xuaW1wb3J0IFNwbGl0dGVyU2lkZUVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtc3BsaXR0ZXItc2lkZSc7XG5pbXBvcnQgU3BsaXR0ZXJFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyJztcbmltcG9ydCBTd2l0Y2hFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXN3aXRjaCc7XG5pbXBvcnQgVGFiRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy10YWInO1xuaW1wb3J0IFRhYmJhckVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtdGFiYmFyJztcbmltcG9ydCBUb29sYmFyQnV0dG9uRWxlbWVudCBmcm9tICcuL2VsZW1lbnRzL29ucy10b29sYmFyLWJ1dHRvbic7XG5pbXBvcnQgVG9vbGJhckVsZW1lbnQgZnJvbSAnLi9lbGVtZW50cy9vbnMtdG9vbGJhcic7XG5pbXBvcnQgUmFuZ2VFbGVtZW50IGZyb20gJy4vZWxlbWVudHMvb25zLXJhbmdlJztcblxub25zLlRlbXBsYXRlRWxlbWVudCA9IFRlbXBsYXRlRWxlbWVudDtcbm9ucy5JZkVsZW1lbnQgPSBJZkVsZW1lbnQ7XG5vbnMuQWxlcnREaWFsb2dFbGVtZW50ID0gQWxlcnREaWFsb2dFbGVtZW50O1xub25zLkJhY2tCdXR0b25FbGVtZW50ID0gQmFja0J1dHRvbkVsZW1lbnQ7XG5vbnMuQm90dG9tVG9vbGJhckVsZW1lbnQgPSBCb3R0b21Ub29sYmFyRWxlbWVudDtcbm9ucy5CdXR0b25FbGVtZW50ID0gQnV0dG9uRWxlbWVudDtcbm9ucy5DYXJvdXNlbEl0ZW1FbGVtZW50ID0gQ2Fyb3VzZWxJdGVtRWxlbWVudDtcbm9ucy5DYXJvdXNlbEVsZW1lbnQgPSBDYXJvdXNlbEVsZW1lbnQ7XG5vbnMuQ29sRWxlbWVudCA9IENvbEVsZW1lbnQ7XG5vbnMuRGlhbG9nRWxlbWVudCA9IERpYWxvZ0VsZW1lbnQ7XG5vbnMuRmFiRWxlbWVudCA9IEZhYkVsZW1lbnQ7XG5vbnMuR2VzdHVyZURldGVjdG9yRWxlbWVudCA9IEdlc3R1cmVEZXRlY3RvckVsZW1lbnQ7XG5vbnMuSWNvbkVsZW1lbnQgPSBJY29uRWxlbWVudDtcbm9ucy5MYXp5UmVwZWF0RWxlbWVudCA9IExhenlSZXBlYXRFbGVtZW50O1xub25zLkxpc3RIZWFkZXJFbGVtZW50ID0gTGlzdEhlYWRlckVsZW1lbnQ7XG5vbnMuTGlzdEl0ZW1FbGVtZW50ID0gTGlzdEl0ZW1FbGVtZW50O1xub25zLkxpc3RFbGVtZW50ID0gTGlzdEVsZW1lbnQ7XG5vbnMuSW5wdXRFbGVtZW50ID0gSW5wdXRFbGVtZW50O1xub25zLk1vZGFsRWxlbWVudCA9IE1vZGFsRWxlbWVudDtcbm9ucy5OYXZpZ2F0b3JFbGVtZW50ID0gTmF2aWdhdG9yRWxlbWVudDtcbm9ucy5QYWdlRWxlbWVudCA9IFBhZ2VFbGVtZW50O1xub25zLlBvcG92ZXJFbGVtZW50ID0gUG9wb3ZlckVsZW1lbnQ7XG5vbnMuUHJvZ3Jlc3NCYXJFbGVtZW50ID0gUHJvZ3Jlc3NCYXJFbGVtZW50O1xub25zLlByb2dyZXNzQ2lyY3VsYXJFbGVtZW50ID0gUHJvZ3Jlc3NDaXJjdWxhckVsZW1lbnQ7XG5vbnMuUHVsbEhvb2tFbGVtZW50ID0gUHVsbEhvb2tFbGVtZW50O1xub25zLlJpcHBsZUVsZW1lbnQgPSBSaXBwbGVFbGVtZW50O1xub25zLlJvd0VsZW1lbnQgPSBSb3dFbGVtZW50O1xub25zLlNwZWVkRGlhbEl0ZW1FbGVtZW50ID0gU3BlZWREaWFsSXRlbUVsZW1lbnQ7XG5vbnMuU3BlZWREaWFsRWxlbWVudCA9IFNwZWVkRGlhbEVsZW1lbnQ7XG5vbnMuU3BsaXR0ZXJDb250ZW50RWxlbWVudCA9IFNwbGl0dGVyQ29udGVudEVsZW1lbnQ7XG5vbnMuU3BsaXR0ZXJNYXNrRWxlbWVudCA9IFNwbGl0dGVyTWFza0VsZW1lbnQ7XG5vbnMuU3BsaXR0ZXJTaWRlRWxlbWVudCA9IFNwbGl0dGVyU2lkZUVsZW1lbnQ7XG5vbnMuU3BsaXR0ZXJFbGVtZW50ID0gU3BsaXR0ZXJFbGVtZW50O1xub25zLlN3aXRjaEVsZW1lbnQgPSBTd2l0Y2hFbGVtZW50O1xub25zLlRhYkVsZW1lbnQgPSBUYWJFbGVtZW50O1xub25zLlRhYmJhckVsZW1lbnQgPSBUYWJiYXJFbGVtZW50O1xub25zLlRvb2xiYXJCdXR0b25FbGVtZW50ID0gVG9vbGJhckJ1dHRvbkVsZW1lbnQ7XG5vbnMuVG9vbGJhckVsZW1lbnQgPSBUb29sYmFyRWxlbWVudDtcbm9ucy5SYW5nZUVsZW1lbnQgPSBSYW5nZUVsZW1lbnQ7XG5cbi8vIGZhc3RjbGlja1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgb25zLmZhc3RDbGljayA9IEZhc3RDbGljay5hdHRhY2goZG9jdW1lbnQuYm9keSk7XG59LCBmYWxzZSk7XG5cbi8vIG9ucy5fZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgb25zLl9kZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5lbmFibGUoKTtcbiAgb25zLl9kZWZhdWx0RGV2aWNlQmFja0J1dHRvbkhhbmRsZXIgPSBvbnMuX2RldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIod2luZG93LmRvY3VtZW50LmJvZHksICgpID0+IHtcbiAgICBuYXZpZ2F0b3IuYXBwLmV4aXRBcHAoKTtcbiAgfSk7XG4gIGRvY3VtZW50LmJvZHkuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBvbnMuR2VzdHVyZURldGVjdG9yKGRvY3VtZW50LmJvZHkpO1xufSwgZmFsc2UpO1xuXG4vLyBzZXR1cCBsb2FkaW5nIHBsYWNlaG9sZGVyXG5vbnMucmVhZHkoZnVuY3Rpb24oKSB7XG4gIG9ucy5fc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzKCk7XG59KTtcblxuLy8gdmlld3BvcnQuanNcbm5ldyBWaWV3cG9ydCgpLnNldHVwKCk7XG5cbmV4cG9ydCBkZWZhdWx0IG9ucztcbiJdfQ==