1 | /*! onsenui v2.0.4 - 2016-11-04 */
|
2 | if (!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
|
34 | if (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 | /*
|
375 | Copyright 2013-2015 ASIAL CORPORATION
|
376 |
|
377 | Licensed under the Apache License, Version 2.0 (the "License");
|
378 | you may not use this file except in compliance with the License.
|
379 | You may obtain a copy of the License at
|
380 |
|
381 | http://www.apache.org/licenses/LICENSE-2.0
|
382 |
|
383 | Unless required by applicable law or agreed to in writing, software
|
384 | distributed under the License is distributed on an "AS IS" BASIS,
|
385 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
386 | See the License for the specific language governing permissions and
|
387 | limitations under the License.
|
388 |
|
389 | */
|
390 |
|
391 |
|
392 | /**
|
393 | * Minimal animation library for managing css transition on mobile browsers.
|
394 | */
|
395 | window.animit = (function(){
|
396 | ;
|
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 |
|
1001 | if ("document" in self) {
|
1002 |
|
1003 | // Full polyfill for browsers with no classList support
|
1004 | // Including IE < Edge missing SVGElement.classList
|
1005 | if (!("classList" in document.createElement("_"))
|
1006 | || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
|
1007 |
|
1008 | (function (view) {
|
1009 |
|
1010 | ;
|
1011 |
|
1012 | if (!('Element' in view)) return;
|
1013 |
|
1014 | var
|
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.
|
1076 | DOMEx[protoProp] = Error[protoProp];
|
1077 | classListProto.item = function (i) {
|
1078 | return this[i] || null;
|
1079 | };
|
1080 | classListProto.contains = function (token) {
|
1081 | token += "";
|
1082 | return checkTokenAndGetIndex(this, token) !== -1;
|
1083 | };
|
1084 | classListProto.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 | };
|
1105 | classListProto.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 | };
|
1129 | classListProto.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 | };
|
1150 | classListProto.toString = function () {
|
1151 | return this.join(" ");
|
1152 | };
|
1153 |
|
1154 | if (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 | ;
|
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 |
|
1231 | Copyright (C) 2014-2016 by Andrea Giammarchi - @WebReflection
|
1232 |
|
1233 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
1234 | of this software and associated documentation files (the "Software"), to deal
|
1235 | in the Software without restriction, including without limitation the rights
|
1236 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
1237 | copies of the Software, and to permit persons to whom the Software is
|
1238 | furnished to do so, subject to the following conditions:
|
1239 |
|
1240 | The above copyright notice and this permission notice shall be included in
|
1241 | all copies or substantial portions of the Software.
|
1242 |
|
1243 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
1244 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
1245 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
1246 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
1247 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
1248 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
1249 | THE SOFTWARE.
|
1250 |
|
1251 | */
|
1252 |
|
1253 | if ('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 | ;
|
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
|
3494 | var 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 |
|
3599 | var MicroEvent = function(){};
|
3600 | MicroEvent.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 | */
|
3644 | MicroEvent.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
|
3656 | if( typeof module !== "undefined" && ('exports' in module)){
|
3657 | module.exports = MicroEvent;
|
3658 | }
|
3659 |
|
3660 | window.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 | /*
|
3894 | Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola
|
3895 |
|
3896 | Permission is hereby granted, free of charge, to any person obtaining
|
3897 | a copy of this software and associated documentation files (the
|
3898 | "Software"), to deal in the Software without restriction, including
|
3899 | without limitation the rights to use, copy, modify, merge, publish,
|
3900 | distribute, sublicense, and/or sell copies of the Software, and to
|
3901 | permit persons to whom the Software is furnished to do so, subject to
|
3902 | the following conditions:
|
3903 |
|
3904 | The above copyright notice and this permission notice shall be
|
3905 | included in all copies or substantial portions of the Software.
|
3906 |
|
3907 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
3908 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
3909 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
3910 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
3911 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
3912 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
3913 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3914 |
|
3915 | */
|
3916 | (function (global, undefined) {
|
3917 | ;
|
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 | /*
|
4344 | Copyright 2013-2015 ASIAL CORPORATION
|
4345 |
|
4346 | Licensed under the Apache License, Version 2.0 (the "License");
|
4347 | you may not use this file except in compliance with the License.
|
4348 | You may obtain a copy of the License at
|
4349 |
|
4350 | http://www.apache.org/licenses/LICENSE-2.0
|
4351 |
|
4352 | Unless required by applicable law or agreed to in writing, software
|
4353 | distributed under the License is distributed on an "AS IS" BASIS,
|
4354 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
4355 | See the License for the specific language governing permissions and
|
4356 | limitations under the License.
|
4357 |
|
4358 | */
|
4359 |
|
4360 | var unwrap = function unwrap(string) {
|
4361 | return string.slice(1, -1);
|
4362 | };
|
4363 | var isObjectString = function isObjectString(string) {
|
4364 | return string.startsWith('{') && string.endsWith('}');
|
4365 | };
|
4366 | var isArrayString = function isArrayString(string) {
|
4367 | return string.startsWith('[') && string.endsWith(']');
|
4368 | };
|
4369 | var isQuotedString = function isQuotedString(string) {
|
4370 | return string.startsWith('\'') && string.endsWith('\'') || string.startsWith('"') && string.endsWith('"');
|
4371 | };
|
4372 |
|
4373 | var 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 |
|
4377 | var 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 |
|
4393 | var 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 |
|
4436 | var 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 |
|
4477 | var 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 |
|
4507 | var 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 |
|
4519 | var _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 |
|
4529 | var 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 |
|
4646 | var classCallCheck = function (instance, Constructor) {
|
4647 | if (!(instance instanceof Constructor)) {
|
4648 | throw new TypeError("Cannot call a class as a function");
|
4649 | }
|
4650 | };
|
4651 |
|
4652 | var 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 |
|
4676 | var _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 |
|
4690 | var 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 |
|
4715 | var 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 |
|
4741 | var 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 |
|
4751 | var 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 | /*
|
4774 | Copyright 2013-2015 ASIAL CORPORATION
|
4775 |
|
4776 | Licensed under the Apache License, Version 2.0 (the "License");
|
4777 | you may not use this file except in compliance with the License.
|
4778 | You may obtain a copy of the License at
|
4779 |
|
4780 | http://www.apache.org/licenses/LICENSE-2.0
|
4781 |
|
4782 | Unless required by applicable law or agreed to in writing, software
|
4783 | distributed under the License is distributed on an "AS IS" BASIS,
|
4784 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
4785 | See the License for the specific language governing permissions and
|
4786 | limitations under the License.
|
4787 |
|
4788 | */
|
4789 |
|
4790 | var util = {};
|
4791 |
|
4792 | /**
|
4793 | * @param {String/Function} query dot class name or node name or matcher function.
|
4794 | * @return {Function}
|
4795 | */
|
4796 | util.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 | */
|
4807 | util.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 | */
|
4819 | util.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 | */
|
4836 | util.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 | */
|
4855 | util.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 | */
|
4869 | util.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 | */
|
4883 | util.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 | */
|
4899 | util.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 | */
|
4919 | util.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 | */
|
4934 | util.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 | */
|
4951 | util.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 | */
|
4973 | util.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 | */
|
4982 | util.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 | */
|
5000 | util.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 | */
|
5017 | util.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 | */
|
5041 | util.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 | */
|
5055 | util.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 | */
|
5071 | util.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 |
|
5086 | util.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 |
|
5095 | util.toggleAttribute = function (element, name, enable) {
|
5096 | if (enable) {
|
5097 | element.setAttribute(name, '');
|
5098 | } else {
|
5099 | element.removeAttribute(name);
|
5100 | }
|
5101 | };
|
5102 |
|
5103 | util.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 |
|
5110 | util.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 | */
|
5119 | util.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 | */
|
5135 | util.animationOptionsParse = parse;
|
5136 |
|
5137 | /**
|
5138 | * @param {*} value
|
5139 | */
|
5140 | util.isInteger = function (value) {
|
5141 | return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
|
5142 | };
|
5143 |
|
5144 | /**
|
5145 | * @return {Obejct} Deferred promise.
|
5146 | */
|
5147 | util.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 |
|
5160 | var Event$1;
|
5161 | var Utils;
|
5162 | var Detection;
|
5163 | var 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 | */
|
5187 | var 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 | */
|
5205 | GestureDetector.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 | */
|
5222 | GestureDetector.DOCUMENT = document;
|
5223 |
|
5224 | /**
|
5225 | * detect support for pointer events
|
5226 | * @property HAS_POINTEREVENTS
|
5227 | * @type {Boolean}
|
5228 | */
|
5229 | GestureDetector.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;
|
5230 |
|
5231 | /**
|
5232 | * detect support for touch events
|
5233 | * @property HAS_TOUCHEVENTS
|
5234 | * @type {Boolean}
|
5235 | */
|
5236 | GestureDetector.HAS_TOUCHEVENTS = 'ontouchstart' in window;
|
5237 |
|
5238 | /**
|
5239 | * detect mobile browsers
|
5240 | * @property IS_MOBILE
|
5241 | * @type {Boolean}
|
5242 | */
|
5243 | GestureDetector.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 | */
|
5250 | GestureDetector.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 | */
|
5258 | GestureDetector.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 | */
|
5268 | var 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 | */
|
5277 | var DIRECTION_DOWN = GestureDetector.DIRECTION_DOWN = 'down';
|
5278 | var DIRECTION_LEFT = GestureDetector.DIRECTION_LEFT = 'left';
|
5279 | var DIRECTION_UP = GestureDetector.DIRECTION_UP = 'up';
|
5280 | var 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 | */
|
5289 | var POINTER_MOUSE = GestureDetector.POINTER_MOUSE = 'mouse';
|
5290 | var POINTER_TOUCH = GestureDetector.POINTER_TOUCH = 'touch';
|
5291 | var 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 | */
|
5300 | var EVENT_START = GestureDetector.EVENT_START = 'start';
|
5301 | var EVENT_MOVE = GestureDetector.EVENT_MOVE = 'move';
|
5302 | var EVENT_END = GestureDetector.EVENT_END = 'end';
|
5303 | var EVENT_RELEASE = GestureDetector.EVENT_RELEASE = 'release';
|
5304 | var 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 | */
|
5313 | GestureDetector.READY = false;
|
5314 |
|
5315 | /**
|
5316 | * plugins namespace
|
5317 | * @property plugins
|
5318 | * @type {Object}
|
5319 | */
|
5320 | GestureDetector.plugins = GestureDetector.plugins || {};
|
5321 |
|
5322 | /**
|
5323 | * gestures namespace
|
5324 | * see `/gestures` for the definitions
|
5325 | * @property gestures
|
5326 | * @type {Object}
|
5327 | */
|
5328 | GestureDetector.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 | */
|
5335 | function 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 | */
|
5362 | Utils = 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 | */
|
5699 | Event$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 | */
|
6012 | PointerEvent = 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 | */
|
6080 | Detection = 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 | */
|
6308 | GestureDetector.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 |
|
6367 | GestureDetector.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 | */
|
6708 | GestureDetector.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 | */
|
6804 | GestureDetector.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 | */
|
6850 | GestureDetector.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 | */
|
7029 | GestureDetector.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 | /*
|
7188 | Copyright 2013-2015 ASIAL CORPORATION
|
7189 |
|
7190 | Licensed under the Apache License, Version 2.0 (the "License");
|
7191 | you may not use this file except in compliance with the License.
|
7192 | You may obtain a copy of the License at
|
7193 |
|
7194 | http://www.apache.org/licenses/LICENSE-2.0
|
7195 |
|
7196 | Unless required by applicable law or agreed to in writing, software
|
7197 | distributed under the License is distributed on an "AS IS" BASIS,
|
7198 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
7199 | See the License for the specific language governing permissions and
|
7200 | limitations 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 | */
|
7211 | var 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 |
|
7599 | var platform = new Platform();
|
7600 |
|
7601 | /*
|
7602 | Copyright 2013-2015 ASIAL CORPORATION
|
7603 |
|
7604 | Licensed under the Apache License, Version 2.0 (the "License");
|
7605 | you may not use this file except in compliance with the License.
|
7606 | You may obtain a copy of the License at
|
7607 |
|
7608 | http://www.apache.org/licenses/LICENSE-2.0
|
7609 |
|
7610 | Unless required by applicable law or agreed to in writing, software
|
7611 | distributed under the License is distributed on an "AS IS" BASIS,
|
7612 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
7613 | See the License for the specific language governing permissions and
|
7614 | limitations under the License.
|
7615 |
|
7616 | */
|
7617 | var readyMap = new WeakMap();
|
7618 | var queueMap = new WeakMap();
|
7619 |
|
7620 | function isContentReady(element) {
|
7621 | if (element.childNodes.length > 0) {
|
7622 | setContentReady(element);
|
7623 | }
|
7624 | return readyMap.has(element);
|
7625 | }
|
7626 |
|
7627 | function setContentReady(element) {
|
7628 | readyMap.set(element, true);
|
7629 | }
|
7630 |
|
7631 | function addCallback(element, fn) {
|
7632 | if (!queueMap.has(element)) {
|
7633 | queueMap.set(element, []);
|
7634 | }
|
7635 | queueMap.get(element).push(fn);
|
7636 | }
|
7637 |
|
7638 | function consumeQueue(element) {
|
7639 | var callbacks = queueMap.get(element, []) || [];
|
7640 | queueMap.delete(element);
|
7641 | callbacks.forEach(function (callback) {
|
7642 | return callback();
|
7643 | });
|
7644 | }
|
7645 |
|
7646 | function 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 | /*
|
7670 | Copyright 2013-2015 ASIAL CORPORATION
|
7671 |
|
7672 | Licensed under the Apache License, Version 2.0 (the "License");
|
7673 | you may not use this file except in compliance with the License.
|
7674 | You may obtain a copy of the License at
|
7675 |
|
7676 | http://www.apache.org/licenses/LICENSE-2.0
|
7677 |
|
7678 | Unless required by applicable law or agreed to in writing, software
|
7679 | distributed under the License is distributed on an "AS IS" BASIS,
|
7680 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
7681 | See the License for the specific language governing permissions and
|
7682 | limitations 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 | */
|
7720 | var notification = {};
|
7721 |
|
7722 | notification._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 |
|
7826 | var _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 | */
|
7922 | notification.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 | */
|
7967 | notification.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 | */
|
8028 | notification.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 | /*
|
8040 | Copyright 2013-2015 ASIAL CORPORATION
|
8041 |
|
8042 | Licensed under the Apache License, Version 2.0 (the "License");
|
8043 | you may not use this file except in compliance with the License.
|
8044 | You may obtain a copy of the License at
|
8045 |
|
8046 | http://www.apache.org/licenses/LICENSE-2.0
|
8047 |
|
8048 | Unless required by applicable law or agreed to in writing, software
|
8049 | distributed under the License is distributed on an "AS IS" BASIS,
|
8050 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8051 | See the License for the specific language governing permissions and
|
8052 | limitations under the License.
|
8053 |
|
8054 | */
|
8055 |
|
8056 | var 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.
|
8211 | pageAttributeExpression.defineVariable('mobileOS', platform.getMobileOS());
|
8212 | pageAttributeExpression.defineVariable('iOSDevice', platform.getIOSDevice());
|
8213 | pageAttributeExpression.defineVariable('runtime', function () {
|
8214 | return platform.isWebView() ? 'cordova' : 'browser';
|
8215 | });
|
8216 |
|
8217 | /*
|
8218 | Copyright 2013-2015 ASIAL CORPORATION
|
8219 |
|
8220 | Licensed under the Apache License, Version 2.0 (the "License");
|
8221 | you may not use this file except in compliance with the License.
|
8222 | You may obtain a copy of the License at
|
8223 |
|
8224 | http://www.apache.org/licenses/LICENSE-2.0
|
8225 |
|
8226 | Unless required by applicable law or agreed to in writing, software
|
8227 | distributed under the License is distributed on an "AS IS" BASIS,
|
8228 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8229 | See the License for the specific language governing permissions and
|
8230 | limitations under the License.
|
8231 |
|
8232 | */
|
8233 |
|
8234 | var internal$1 = {};
|
8235 |
|
8236 | internal$1.config = {
|
8237 | autoStatusBarFill: true,
|
8238 | animationsDisabled: false
|
8239 | };
|
8240 |
|
8241 | internal$1.nullElement = window.document.createElement('div');
|
8242 |
|
8243 | /**
|
8244 | * @return {Boolean}
|
8245 | */
|
8246 | internal$1.isEnabledAutoStatusBarFill = function () {
|
8247 | return !!internal$1.config.autoStatusBarFill;
|
8248 | };
|
8249 |
|
8250 | /**
|
8251 | * @param {String} html
|
8252 | * @return {String}
|
8253 | */
|
8254 | internal$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 |
|
8264 | internal$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 |
|
8272 | internal$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 |
|
8292 | internal$1.shouldFillStatusBar = function () {
|
8293 | return internal$1.isEnabledAutoStatusBarFill() && platform.isWebView() && platform.isIOS7above();
|
8294 | };
|
8295 |
|
8296 | internal$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 |
|
8317 | window.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 |
|
8323 | window.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 | */
|
8340 | internal$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 | */
|
8374 | internal$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 | /*
|
8399 | Copyright 2013-2015 ASIAL CORPORATION
|
8400 |
|
8401 | Licensed under the Apache License, Version 2.0 (the "License");
|
8402 | you may not use this file except in compliance with the License.
|
8403 | You may obtain a copy of the License at
|
8404 |
|
8405 | http://www.apache.org/licenses/LICENSE-2.0
|
8406 |
|
8407 | Unless required by applicable law or agreed to in writing, software
|
8408 | distributed under the License is distributed on an "AS IS" BASIS,
|
8409 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8410 | See the License for the specific language governing permissions and
|
8411 | limitations under the License.
|
8412 |
|
8413 | */
|
8414 |
|
8415 | var 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 | /*
|
8526 | Copyright 2013-2015 ASIAL CORPORATION
|
8527 |
|
8528 | Licensed under the Apache License, Version 2.0 (the "License");
|
8529 | you may not use this file except in compliance with the License.
|
8530 | You may obtain a copy of the License at
|
8531 |
|
8532 | http://www.apache.org/licenses/LICENSE-2.0
|
8533 |
|
8534 | Unless required by applicable law or agreed to in writing, software
|
8535 | distributed under the License is distributed on an "AS IS" BASIS,
|
8536 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8537 | See the License for the specific language governing permissions and
|
8538 | limitations under the License.
|
8539 |
|
8540 | */
|
8541 |
|
8542 | var 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 | /*
|
8674 | Copyright 2013-2015 ASIAL CORPORATION
|
8675 |
|
8676 | Licensed under the Apache License, Version 2.0 (the "License");
|
8677 | you may not use this file except in compliance with the License.
|
8678 | You may obtain a copy of the License at
|
8679 |
|
8680 | http://www.apache.org/licenses/LICENSE-2.0
|
8681 |
|
8682 | Unless required by applicable law or agreed to in writing, software
|
8683 | distributed under the License is distributed on an "AS IS" BASIS,
|
8684 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8685 | See the License for the specific language governing permissions and
|
8686 | limitations under the License.
|
8687 |
|
8688 | */
|
8689 |
|
8690 | var 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 | */
|
8836 | var 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 | /*
|
9178 | Copyright 2013-2015 ASIAL CORPORATION
|
9179 |
|
9180 | Licensed under the Apache License, Version 2.0 (the "License");
|
9181 | you may not use this file except in compliance with the License.
|
9182 | You may obtain a copy of the License at
|
9183 |
|
9184 | http://www.apache.org/licenses/LICENSE-2.0
|
9185 |
|
9186 | Unless required by applicable law or agreed to in writing, software
|
9187 | distributed under the License is distributed on an "AS IS" BASIS,
|
9188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9189 | See the License for the specific language governing permissions and
|
9190 | limitations under the License.
|
9191 |
|
9192 | */
|
9193 | internal$1.AnimatorFactory = AnimatorFactory;
|
9194 | internal$1.ModifierUtil = ModifierUtil;
|
9195 | internal$1.LazyRepeatProvider = LazyRepeatProvider;
|
9196 | internal$1.LazyRepeatDelegate = LazyRepeatDelegate;
|
9197 |
|
9198 | /*
|
9199 | Copyright 2013-2015 ASIAL CORPORATION
|
9200 |
|
9201 | Licensed under the Apache License, Version 2.0 (the "License");
|
9202 | you may not use this file except in compliance with the License.
|
9203 | You may obtain a copy of the License at
|
9204 |
|
9205 | http://www.apache.org/licenses/LICENSE-2.0
|
9206 |
|
9207 | Unless required by applicable law or agreed to in writing, software
|
9208 | distributed under the License is distributed on an "AS IS" BASIS,
|
9209 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9210 | See the License for the specific language governing permissions and
|
9211 | limitations under the License.
|
9212 |
|
9213 | */
|
9214 |
|
9215 | var 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 |
|
9385 | var orientation = create()._init();
|
9386 |
|
9387 | /*
|
9388 | Copyright 2013-2015 ASIAL CORPORATION
|
9389 |
|
9390 | Licensed under the Apache License, Version 2.0 (the "License");
|
9391 | you may not use this file except in compliance with the License.
|
9392 | You may obtain a copy of the License at
|
9393 |
|
9394 | http://www.apache.org/licenses/LICENSE-2.0
|
9395 |
|
9396 | Unless required by applicable law or agreed to in writing, software
|
9397 | distributed under the License is distributed on an "AS IS" BASIS,
|
9398 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9399 | See the License for the specific language governing permissions and
|
9400 | limitations under the License.
|
9401 |
|
9402 | */
|
9403 |
|
9404 | var softwareKeyboard = new MicroEvent();
|
9405 | softwareKeyboard._visible = false;
|
9406 |
|
9407 | var onShow = function onShow() {
|
9408 | softwareKeyboard._visible = true;
|
9409 | softwareKeyboard.emit('show');
|
9410 | };
|
9411 |
|
9412 | var onHide = function onHide() {
|
9413 | softwareKeyboard._visible = false;
|
9414 | softwareKeyboard.emit('hide');
|
9415 | };
|
9416 |
|
9417 | var 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 |
|
9437 | var noPluginError = function noPluginError() {
|
9438 | console.warn('ons-keyboard: Cordova Keyboard plugin is not present.');
|
9439 | };
|
9440 |
|
9441 | document.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 | /*
|
9452 | Copyright 2013-2015 ASIAL CORPORATION
|
9453 |
|
9454 | Licensed under the Apache License, Version 2.0 (the "License");
|
9455 | you may not use this file except in compliance with the License.
|
9456 | You may obtain a copy of the License at
|
9457 |
|
9458 | http://www.apache.org/licenses/LICENSE-2.0
|
9459 |
|
9460 | Unless required by applicable law or agreed to in writing, software
|
9461 | distributed under the License is distributed on an "AS IS" BASIS,
|
9462 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9463 | See the License for the specific language governing permissions and
|
9464 | limitations under the License.
|
9465 |
|
9466 | */
|
9467 |
|
9468 | var 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 | };
|
9513 | window.addEventListener('DOMContentLoaded', function () {
|
9514 | return util$2._onDOMContentLoaded();
|
9515 | }, false);
|
9516 |
|
9517 | var 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 |
|
9567 | var 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 |
|
9776 | var deviceBackButtonDispatcher = new DeviceBackButtonDispatcher();
|
9777 |
|
9778 | /*
|
9779 | Copyright 2013-2015 ASIAL CORPORATION
|
9780 |
|
9781 | Licensed under the Apache License, Version 2.0 (the "License");
|
9782 | you may not use this file except in compliance with the License.
|
9783 | You may obtain a copy of the License at
|
9784 |
|
9785 | http://www.apache.org/licenses/LICENSE-2.0
|
9786 |
|
9787 | Unless required by applicable law or agreed to in writing, software
|
9788 | distributed under the License is distributed on an "AS IS" BASIS,
|
9789 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9790 | See the License for the specific language governing permissions and
|
9791 | limitations under the License.
|
9792 |
|
9793 | */
|
9794 |
|
9795 | var autoStyleEnabled = true;
|
9796 |
|
9797 | // Modifiers
|
9798 | var 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 |
|
9810 | var platforms = {};
|
9811 |
|
9812 | platforms.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 |
|
9840 | platforms.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 |
|
9865 | var unlocked = {
|
9866 | android: true
|
9867 | };
|
9868 |
|
9869 | var 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 |
|
9878 | var 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 | /*
|
9892 | Copyright 2013-2015 ASIAL CORPORATION
|
9893 |
|
9894 | Licensed under the Apache License, Version 2.0 (the "License");
|
9895 | you may not use this file except in compliance with the License.
|
9896 | You may obtain a copy of the License at
|
9897 |
|
9898 | http://www.apache.org/licenses/LICENSE-2.0
|
9899 |
|
9900 | Unless required by applicable law or agreed to in writing, software
|
9901 | distributed under the License is distributed on an "AS IS" BASIS,
|
9902 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
9903 | See the License for the specific language governing permissions and
|
9904 | limitations under the License.
|
9905 |
|
9906 | */
|
9907 |
|
9908 | var 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 |
|
9922 | var 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 | /*
|
10008 | Copyright 2013-2015 ASIAL CORPORATION
|
10009 |
|
10010 | Licensed under the Apache License, Version 2.0 (the "License");
|
10011 | you may not use this file except in compliance with the License.
|
10012 | You may obtain a copy of the License at
|
10013 |
|
10014 | http://www.apache.org/licenses/LICENSE-2.0
|
10015 |
|
10016 | Unless required by applicable law or agreed to in writing, software
|
10017 | distributed under the License is distributed on an "AS IS" BASIS,
|
10018 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10019 | See the License for the specific language governing permissions and
|
10020 | limitations under the License.
|
10021 |
|
10022 | */
|
10023 | // Default implementation for global PageLoader.
|
10024 | function 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 |
|
10049 | var 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 |
|
10109 | var defaultPageLoader = new PageLoader();
|
10110 |
|
10111 | var 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 | /*
|
10135 | Copyright 2013-2015 ASIAL CORPORATION
|
10136 |
|
10137 | Licensed under the Apache License, Version 2.0 (the "License");
|
10138 | you may not use this file except in compliance with the License.
|
10139 | You may obtain a copy of the License at
|
10140 |
|
10141 | http://www.apache.org/licenses/LICENSE-2.0
|
10142 |
|
10143 | Unless required by applicable law or agreed to in writing, software
|
10144 | distributed under the License is distributed on an "AS IS" BASIS,
|
10145 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10146 | See the License for the specific language governing permissions and
|
10147 | limitations 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 | */
|
10158 | var ons$1 = {};
|
10159 |
|
10160 | ons$1._util = util;
|
10161 | ons$1._deviceBackButtonDispatcher = deviceBackButtonDispatcher;
|
10162 | ons$1._internal = internal$1;
|
10163 | ons$1.GestureDetector = GestureDetector;
|
10164 | ons$1.platform = platform;
|
10165 | ons$1.softwareKeyboard = softwareKeyboard;
|
10166 | ons$1.pageAttributeExpression = pageAttributeExpression;
|
10167 | ons$1.orientation = orientation;
|
10168 | ons$1.notification = notification;
|
10169 | ons$1._animationOptionsParser = parse;
|
10170 | ons$1._autoStyle = autoStyle;
|
10171 | ons$1._DoorLock = DoorLock;
|
10172 | ons$1._contentReady = contentReady;
|
10173 | ons$1.defaultPageLoader = defaultPageLoader;
|
10174 | ons$1.PageLoader = PageLoader;
|
10175 |
|
10176 | ons$1._readyLock = new DoorLock();
|
10177 |
|
10178 | ons$1.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]);
|
10179 |
|
10180 | waitDeviceReady();
|
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 | */
|
10192 | ons$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 | */
|
10206 | ons$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 | */
|
10218 | ons$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 | */
|
10236 | ons$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 | */
|
10247 | ons$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 | */
|
10258 | ons$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 | */
|
10269 | ons$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 | */
|
10283 | ons$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 | */
|
10297 | ons$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 | */
|
10308 | ons$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 | */
|
10319 | ons$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 | */
|
10328 | ons$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 | */
|
10338 | ons$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 | */
|
10360 | ons$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 | */
|
10402 | ons$1.createPopover = ons$1._createPopoverOriginal;
|
10403 |
|
10404 | /**
|
10405 | * @param {String} page
|
10406 | * @param {Object} [options]
|
10407 | * @param {Function} [options.link]
|
10408 | * @return {Promise}
|
10409 | */
|
10410 | ons$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 | */
|
10449 | ons$1.createDialog = ons$1._createDialogOriginal;
|
10450 |
|
10451 | /**
|
10452 | * @param {String} page
|
10453 | * @param {Object} [options]
|
10454 | * @param {Function} [options.link]
|
10455 | * @return {Promise}
|
10456 | */
|
10457 | ons$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 | */
|
10496 | ons$1.createAlertDialog = ons$1._createAlertDialogOriginal;
|
10497 |
|
10498 | /**
|
10499 | * @param {String} page
|
10500 | * @param {Function} link
|
10501 | */
|
10502 | ons$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 | */
|
10527 | ons$1.resolveLoadingPlaceholder = ons$1._resolveLoadingPlaceholderOriginal;
|
10528 |
|
10529 | ons$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 |
|
10542 | ons$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 |
|
10565 | function 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 |
|
10576 | window._superSecretOns = ons$1;
|
10577 |
|
10578 | /*
|
10579 | Copyright 2013-2015 ASIAL CORPORATION
|
10580 |
|
10581 | Licensed under the Apache License, Version 2.0 (the "License");
|
10582 | you may not use this file except in compliance with the License.
|
10583 | You may obtain a copy of the License at
|
10584 |
|
10585 | http://www.apache.org/licenses/LICENSE-2.0
|
10586 |
|
10587 | Unless required by applicable law or agreed to in writing, software
|
10588 | distributed under the License is distributed on an "AS IS" BASIS,
|
10589 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10590 | See the License for the specific language governing permissions and
|
10591 | limitations under the License.
|
10592 |
|
10593 | */
|
10594 |
|
10595 | function 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 |
|
10606 | var 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 | /*
|
10627 | Copyright 2013-2015 ASIAL CORPORATION
|
10628 |
|
10629 | Licensed under the Apache License, Version 2.0 (the "License");
|
10630 | you may not use this file except in compliance with the License.
|
10631 | You may obtain a copy of the License at
|
10632 |
|
10633 | http://www.apache.org/licenses/LICENSE-2.0
|
10634 |
|
10635 | Unless required by applicable law or agreed to in writing, software
|
10636 | distributed under the License is distributed on an "AS IS" BASIS,
|
10637 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10638 | See the License for the specific language governing permissions and
|
10639 | limitations 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 |
|
10676 | var 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 |
|
10716 | customElements.define('ons-template', TemplateElement);
|
10717 |
|
10718 | /*
|
10719 | Copyright 2013-2015 ASIAL CORPORATION
|
10720 |
|
10721 | Licensed under the Apache License, Version 2.0 (the "License");
|
10722 | you may not use this file except in compliance with the License.
|
10723 | You may obtain a copy of the License at
|
10724 |
|
10725 | http://www.apache.org/licenses/LICENSE-2.0
|
10726 |
|
10727 | Unless required by applicable law or agreed to in writing, software
|
10728 | distributed under the License is distributed on an "AS IS" BASIS,
|
10729 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10730 | See the License for the specific language governing permissions and
|
10731 | limitations 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 |
|
10761 | var 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 |
|
10852 | customElements.define('ons-if', IfElement);
|
10853 |
|
10854 | /*
|
10855 | Copyright 2013-2015 ASIAL CORPORATION
|
10856 |
|
10857 | Licensed under the Apache License, Version 2.0 (the "License");
|
10858 | you may not use this file except in compliance with the License.
|
10859 | You may obtain a copy of the License at
|
10860 |
|
10861 | http://www.apache.org/licenses/LICENSE-2.0
|
10862 |
|
10863 | Unless required by applicable law or agreed to in writing, software
|
10864 | distributed under the License is distributed on an "AS IS" BASIS,
|
10865 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10866 | See the License for the specific language governing permissions and
|
10867 | limitations under the License.
|
10868 |
|
10869 | */
|
10870 |
|
10871 | var 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 | */
|
10917 | var 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 | */
|
11012 | var 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 | /*
|
11103 | Copyright 2013-2015 ASIAL CORPORATION
|
11104 |
|
11105 | Licensed under the Apache License, Version 2.0 (the "License");
|
11106 | you may not use this file except in compliance with the License.
|
11107 | You may obtain a copy of the License at
|
11108 |
|
11109 | http://www.apache.org/licenses/LICENSE-2.0
|
11110 |
|
11111 | Unless required by applicable law or agreed to in writing, software
|
11112 | distributed under the License is distributed on an "AS IS" BASIS,
|
11113 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11114 | See the License for the specific language governing permissions and
|
11115 | limitations under the License.
|
11116 |
|
11117 | */
|
11118 |
|
11119 | var 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 |
|
11133 | var _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 |
|
11185 | var 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 |
|
11716 | customElements.define('ons-alert-dialog', AlertDialogElement);
|
11717 |
|
11718 | /*
|
11719 | Copyright 2013-2015 ASIAL CORPORATION
|
11720 |
|
11721 | Licensed under the Apache License, Version 2.0 (the "License");
|
11722 | you may not use this file except in compliance with the License.
|
11723 | You may obtain a copy of the License at
|
11724 |
|
11725 | http://www.apache.org/licenses/LICENSE-2.0
|
11726 |
|
11727 | Unless required by applicable law or agreed to in writing, software
|
11728 | distributed under the License is distributed on an "AS IS" BASIS,
|
11729 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11730 | See the License for the specific language governing permissions and
|
11731 | limitations under the License.
|
11732 |
|
11733 | */
|
11734 |
|
11735 | var 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 |
|
11773 | var 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 |
|
11934 | customElements.define('ons-back-button', BackButtonElement);
|
11935 |
|
11936 | /*
|
11937 | Copyright 2013-2015 ASIAL CORPORATION
|
11938 |
|
11939 | Licensed under the Apache License, Version 2.0 (the "License");
|
11940 | you may not use this file except in compliance with the License.
|
11941 | You may obtain a copy of the License at
|
11942 |
|
11943 | http://www.apache.org/licenses/LICENSE-2.0
|
11944 |
|
11945 | Unless required by applicable law or agreed to in writing, software
|
11946 | distributed under the License is distributed on an "AS IS" BASIS,
|
11947 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11948 | See the License for the specific language governing permissions and
|
11949 | limitations under the License.
|
11950 |
|
11951 | */
|
11952 |
|
11953 | var 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 |
|
11971 | var 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 |
|
12017 | customElements.define('ons-bottom-toolbar', BottomToolbarElement);
|
12018 |
|
12019 | /*
|
12020 | Copyright 2013-2015 ASIAL CORPORATION
|
12021 |
|
12022 | Licensed under the Apache License, Version 2.0 (the "License");
|
12023 | you may not use this file except in compliance with the License.
|
12024 | You may obtain a copy of the License at
|
12025 |
|
12026 | http://www.apache.org/licenses/LICENSE-2.0
|
12027 |
|
12028 | Unless required by applicable law or agreed to in writing, software
|
12029 | distributed under the License is distributed on an "AS IS" BASIS,
|
12030 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12031 | See the License for the specific language governing permissions and
|
12032 | limitations under the License.
|
12033 |
|
12034 | */
|
12035 |
|
12036 | var 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 |
|
12086 | var 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 |
|
12176 | customElements.define('ons-button', ButtonElement);
|
12177 |
|
12178 | /*
|
12179 | Copyright 2013-2015 ASIAL CORPORATION
|
12180 |
|
12181 | Licensed under the Apache License, Version 2.0 (the "License");
|
12182 | you may not use this file except in compliance with the License.
|
12183 | You may obtain a copy of the License at
|
12184 |
|
12185 | http://www.apache.org/licenses/LICENSE-2.0
|
12186 |
|
12187 | Unless required by applicable law or agreed to in writing, software
|
12188 | distributed under the License is distributed on an "AS IS" BASIS,
|
12189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12190 | See the License for the specific language governing permissions and
|
12191 | limitations under the License.
|
12192 |
|
12193 | */
|
12194 |
|
12195 | var 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 |
|
12221 | var 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 |
|
12251 | customElements.define('ons-carousel-item', CarouselItemElement);
|
12252 |
|
12253 | /*
|
12254 | Copyright 2013-2015 ASIAL CORPORATION
|
12255 |
|
12256 | Licensed under the Apache License, Version 2.0 (the "License");
|
12257 | you may not use this file except in compliance with the License.
|
12258 | You may obtain a copy of the License at
|
12259 |
|
12260 | http://www.apache.org/licenses/LICENSE-2.0
|
12261 |
|
12262 | Unless required by applicable law or agreed to in writing, software
|
12263 | distributed under the License is distributed on an "AS IS" BASIS,
|
12264 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12265 | See the License for the specific language governing permissions and
|
12266 | limitations under the License.
|
12267 |
|
12268 | */
|
12269 |
|
12270 | var 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 |
|
12325 | var 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 |
|
12406 | var 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 |
|
13444 | customElements.define('ons-carousel', CarouselElement);
|
13445 |
|
13446 | /*
|
13447 | Copyright 2013-2015 ASIAL CORPORATION
|
13448 |
|
13449 | Licensed under the Apache License, Version 2.0 (the "License");
|
13450 | you may not use this file except in compliance with the License.
|
13451 | You may obtain a copy of the License at
|
13452 |
|
13453 | http://www.apache.org/licenses/LICENSE-2.0
|
13454 |
|
13455 | Unless required by applicable law or agreed to in writing, software
|
13456 | distributed under the License is distributed on an "AS IS" BASIS,
|
13457 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13458 | See the License for the specific language governing permissions and
|
13459 | limitations 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 |
|
13500 | var 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 |
|
13548 | customElements.define('ons-col', ColElement);
|
13549 |
|
13550 | /*
|
13551 | Copyright 2013-2015 ASIAL CORPORATION
|
13552 |
|
13553 | Licensed under the Apache License, Version 2.0 (the "License");
|
13554 | you may not use this file except in compliance with the License.
|
13555 | You may obtain a copy of the License at
|
13556 |
|
13557 | http://www.apache.org/licenses/LICENSE-2.0
|
13558 |
|
13559 | Unless required by applicable law or agreed to in writing, software
|
13560 | distributed under the License is distributed on an "AS IS" BASIS,
|
13561 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13562 | See the License for the specific language governing permissions and
|
13563 | limitations under the License.
|
13564 |
|
13565 | */
|
13566 |
|
13567 | var 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 | */
|
13613 | var 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 | */
|
13708 | var 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 | */
|
13799 | var 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 | /*
|
13888 | Copyright 2013-2015 ASIAL CORPORATION
|
13889 |
|
13890 | Licensed under the Apache License, Version 2.0 (the "License");
|
13891 | you may not use this file except in compliance with the License.
|
13892 | You may obtain a copy of the License at
|
13893 |
|
13894 | http://www.apache.org/licenses/LICENSE-2.0
|
13895 |
|
13896 | Unless required by applicable law or agreed to in writing, software
|
13897 | distributed under the License is distributed on an "AS IS" BASIS,
|
13898 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13899 | See the License for the specific language governing permissions and
|
13900 | limitations under the License.
|
13901 |
|
13902 | */
|
13903 |
|
13904 | var scheme$5 = {
|
13905 | '.dialog': 'dialog--*',
|
13906 | '.dialog-container': 'dialog-container--*',
|
13907 | '.dialog-mask': 'dialog-mask--*'
|
13908 | };
|
13909 |
|
13910 | var _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 |
|
13960 | var 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 |
|
14449 | customElements.define('ons-dialog', DialogElement);
|
14450 |
|
14451 | /*
|
14452 | Copyright 2013-2015 ASIAL CORPORATION
|
14453 | Licensed under the Apache License, Version 2.0 (the "License");
|
14454 | you may not use this file except in compliance with the License.
|
14455 | You may obtain a copy of the License at
|
14456 | http://www.apache.org/licenses/LICENSE-2.0
|
14457 | Unless required by applicable law or agreed to in writing, software
|
14458 | distributed under the License is distributed on an "AS IS" BASIS,
|
14459 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14460 | See the License for the specific language governing permissions and
|
14461 | limitations under the License.
|
14462 | */
|
14463 |
|
14464 | var 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 |
|
14485 | var 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 |
|
14717 | customElements.define('ons-fab', FabElement);
|
14718 |
|
14719 | /*
|
14720 | Copyright 2013-2015 ASIAL CORPORATION
|
14721 |
|
14722 | Licensed under the Apache License, Version 2.0 (the "License");
|
14723 | you may not use this file except in compliance with the License.
|
14724 | You may obtain a copy of the License at
|
14725 |
|
14726 | http://www.apache.org/licenses/LICENSE-2.0
|
14727 |
|
14728 | Unless required by applicable law or agreed to in writing, software
|
14729 | distributed under the License is distributed on an "AS IS" BASIS,
|
14730 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14731 | See the License for the specific language governing permissions and
|
14732 | limitations 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 |
|
14769 | var 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 |
|
14786 | customElements.define('ons-gesture-detector', GestureDetectorElement);
|
14787 |
|
14788 | /*
|
14789 | Copyright 2013-2015 ASIAL CORPORATION
|
14790 |
|
14791 | Licensed under the Apache License, Version 2.0 (the "License");
|
14792 | you may not use this file except in compliance with the License.
|
14793 | You may obtain a copy of the License at
|
14794 |
|
14795 | http://www.apache.org/licenses/LICENSE-2.0
|
14796 |
|
14797 | Unless required by applicable law or agreed to in writing, software
|
14798 | distributed under the License is distributed on an "AS IS" BASIS,
|
14799 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14800 | See the License for the specific language governing permissions and
|
14801 | limitations 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 |
|
14833 | var 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 |
|
15024 | customElements.define('ons-icon', IconElement);
|
15025 |
|
15026 | /*
|
15027 | Copyright 2013-2015 ASIAL CORPORATION
|
15028 | Licensed under the Apache License, Version 2.0 (the "License");
|
15029 | you may not use this file except in compliance with the License.
|
15030 | You may obtain a copy of the License at
|
15031 | http://www.apache.org/licenses/LICENSE-2.0
|
15032 | Unless required by applicable law or agreed to in writing, software
|
15033 | distributed under the License is distributed on an "AS IS" BASIS,
|
15034 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15035 | See the License for the specific language governing permissions and
|
15036 | limitations 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 |
|
15089 | var 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 |
|
15219 | customElements.define('ons-lazy-repeat', LazyRepeatElement);
|
15220 |
|
15221 | /*
|
15222 | Copyright 2013-2015 ASIAL CORPORATION
|
15223 |
|
15224 | Licensed under the Apache License, Version 2.0 (the "License");
|
15225 | you may not use this file except in compliance with the License.
|
15226 | You may obtain a copy of the License at
|
15227 |
|
15228 | http://www.apache.org/licenses/LICENSE-2.0
|
15229 |
|
15230 | Unless required by applicable law or agreed to in writing, software
|
15231 | distributed under the License is distributed on an "AS IS" BASIS,
|
15232 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15233 | See the License for the specific language governing permissions and
|
15234 | limitations under the License.
|
15235 |
|
15236 | */
|
15237 |
|
15238 | var 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 |
|
15266 | var 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 |
|
15312 | customElements.define('ons-list-header', ListHeaderElement);
|
15313 |
|
15314 | /*
|
15315 | Copyright 2013-2015 ASIAL CORPORATION
|
15316 |
|
15317 | Licensed under the Apache License, Version 2.0 (the "License");
|
15318 | you may not use this file except in compliance with the License.
|
15319 | You may obtain a copy of the License at
|
15320 |
|
15321 | http://www.apache.org/licenses/LICENSE-2.0
|
15322 |
|
15323 | Unless required by applicable law or agreed to in writing, software
|
15324 | distributed under the License is distributed on an "AS IS" BASIS,
|
15325 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15326 | See the License for the specific language governing permissions and
|
15327 | limitations under the License.
|
15328 |
|
15329 | */
|
15330 |
|
15331 | var 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 |
|
15404 | var 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 |
|
15624 | customElements.define('ons-list-item', ListItemElement);
|
15625 |
|
15626 | /*
|
15627 | Copyright 2013-2015 ASIAL CORPORATION
|
15628 |
|
15629 | Licensed under the Apache License, Version 2.0 (the "License");
|
15630 | you may not use this file except in compliance with the License.
|
15631 | You may obtain a copy of the License at
|
15632 |
|
15633 | http://www.apache.org/licenses/LICENSE-2.0
|
15634 |
|
15635 | Unless required by applicable law or agreed to in writing, software
|
15636 | distributed under the License is distributed on an "AS IS" BASIS,
|
15637 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15638 | See the License for the specific language governing permissions and
|
15639 | limitations under the License.
|
15640 |
|
15641 | */
|
15642 |
|
15643 | var 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 |
|
15682 | var 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 |
|
15728 | customElements.define('ons-list', ListElement);
|
15729 |
|
15730 | /*
|
15731 | Copyright 2013-2015 ASIAL CORPORATION
|
15732 | Licensed under the Apache License, Version 2.0 (the "License");
|
15733 | you may not use this file except in compliance with the License.
|
15734 | You may obtain a copy of the License at
|
15735 | http://www.apache.org/licenses/LICENSE-2.0
|
15736 | Unless required by applicable law or agreed to in writing, software
|
15737 | distributed under the License is distributed on an "AS IS" BASIS,
|
15738 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15739 | See the License for the specific language governing permissions and
|
15740 | limitations under the License.
|
15741 | */
|
15742 |
|
15743 | var 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 |
|
15754 | var 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 |
|
15791 | var 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 |
|
16113 | customElements.define('ons-input', InputElement);
|
16114 |
|
16115 | /*
|
16116 | Copyright 2013-2015 ASIAL CORPORATION
|
16117 |
|
16118 | Licensed under the Apache License, Version 2.0 (the "License");
|
16119 | you may not use this file except in compliance with the License.
|
16120 | You may obtain a copy of the License at
|
16121 |
|
16122 | http://www.apache.org/licenses/LICENSE-2.0
|
16123 |
|
16124 | Unless required by applicable law or agreed to in writing, software
|
16125 | distributed under the License is distributed on an "AS IS" BASIS,
|
16126 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16127 | See the License for the specific language governing permissions and
|
16128 | limitations under the License.
|
16129 |
|
16130 | */
|
16131 |
|
16132 | var 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 | /*
|
16179 | Copyright 2013-2015 ASIAL CORPORATION
|
16180 |
|
16181 | Licensed under the Apache License, Version 2.0 (the "License");
|
16182 | you may not use this file except in compliance with the License.
|
16183 | You may obtain a copy of the License at
|
16184 |
|
16185 | http://www.apache.org/licenses/LICENSE-2.0
|
16186 |
|
16187 | Unless required by applicable law or agreed to in writing, software
|
16188 | distributed under the License is distributed on an "AS IS" BASIS,
|
16189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16190 | See the License for the specific language governing permissions and
|
16191 | limitations under the License.
|
16192 |
|
16193 | */
|
16194 |
|
16195 | /**
|
16196 | * iOS style animator for dialog.
|
16197 | */
|
16198 |
|
16199 | var 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 | /*
|
16263 | Copyright 2013-2015 ASIAL CORPORATION
|
16264 |
|
16265 | Licensed under the Apache License, Version 2.0 (the "License");
|
16266 | you may not use this file except in compliance with the License.
|
16267 | You may obtain a copy of the License at
|
16268 |
|
16269 | http://www.apache.org/licenses/LICENSE-2.0
|
16270 |
|
16271 | Unless required by applicable law or agreed to in writing, software
|
16272 | distributed under the License is distributed on an "AS IS" BASIS,
|
16273 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16274 | See the License for the specific language governing permissions and
|
16275 | limitations under the License.
|
16276 |
|
16277 | */
|
16278 |
|
16279 | var scheme$11 = {
|
16280 | '': 'modal--*',
|
16281 | 'modal__content': 'modal--*__content'
|
16282 | };
|
16283 |
|
16284 | var _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 |
|
16320 | var 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 |
|
16609 | customElements.define('ons-modal', ModalElement);
|
16610 |
|
16611 | /*
|
16612 | Copyright 2013-2015 ASIAL CORPORATION
|
16613 |
|
16614 | Licensed under the Apache License, Version 2.0 (the "License");
|
16615 | you may not use this file except in compliance with the License.
|
16616 | You may obtain a copy of the License at
|
16617 |
|
16618 | http://www.apache.org/licenses/LICENSE-2.0
|
16619 |
|
16620 | Unless required by applicable law or agreed to in writing, software
|
16621 | distributed under the License is distributed on an "AS IS" BASIS,
|
16622 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16623 | See the License for the specific language governing permissions and
|
16624 | limitations under the License.
|
16625 |
|
16626 | */
|
16627 |
|
16628 | var 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 | /*
|
16681 | Copyright 2013-2015 ASIAL CORPORATION
|
16682 |
|
16683 | Licensed under the Apache License, Version 2.0 (the "License");
|
16684 | you may not use this file except in compliance with the License.
|
16685 | You may obtain a copy of the License at
|
16686 |
|
16687 | http://www.apache.org/licenses/LICENSE-2.0
|
16688 |
|
16689 | Unless required by applicable law or agreed to in writing, software
|
16690 | distributed under the License is distributed on an "AS IS" BASIS,
|
16691 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16692 | See the License for the specific language governing permissions and
|
16693 | limitations under the License.
|
16694 |
|
16695 | */
|
16696 |
|
16697 | /**
|
16698 | * Slide animator for navigator transition like iOS's screen slide transition.
|
16699 | */
|
16700 |
|
16701 | var 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 | /*
|
17133 | Copyright 2013-2015 ASIAL CORPORATION
|
17134 |
|
17135 | Licensed under the Apache License, Version 2.0 (the "License");
|
17136 | you may not use this file except in compliance with the License.
|
17137 | You may obtain a copy of the License at
|
17138 |
|
17139 | http://www.apache.org/licenses/LICENSE-2.0
|
17140 |
|
17141 | Unless required by applicable law or agreed to in writing, software
|
17142 | distributed under the License is distributed on an "AS IS" BASIS,
|
17143 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17144 | See the License for the specific language governing permissions and
|
17145 | limitations under the License.
|
17146 |
|
17147 | */
|
17148 |
|
17149 | /**
|
17150 | * Lift screen transition.
|
17151 | */
|
17152 |
|
17153 | var 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 | /*
|
17272 | Copyright 2013-2015 ASIAL CORPORATION
|
17273 |
|
17274 | Licensed under the Apache License, Version 2.0 (the "License");
|
17275 | you may not use this file except in compliance with the License.
|
17276 | You may obtain a copy of the License at
|
17277 |
|
17278 | http://www.apache.org/licenses/LICENSE-2.0
|
17279 |
|
17280 | Unless required by applicable law or agreed to in writing, software
|
17281 | distributed under the License is distributed on an "AS IS" BASIS,
|
17282 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17283 | See the License for the specific language governing permissions and
|
17284 | limitations under the License.
|
17285 |
|
17286 | */
|
17287 |
|
17288 | /**
|
17289 | * Fade-in screen transition.
|
17290 | */
|
17291 |
|
17292 | var 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 | /*
|
17395 | Copyright 2013-2015 ASIAL CORPORATION
|
17396 |
|
17397 | Licensed under the Apache License, Version 2.0 (the "License");
|
17398 | you may not use this file except in compliance with the License.
|
17399 | You may obtain a copy of the License at
|
17400 |
|
17401 | http://www.apache.org/licenses/LICENSE-2.0
|
17402 |
|
17403 | Unless required by applicable law or agreed to in writing, software
|
17404 | distributed under the License is distributed on an "AS IS" BASIS,
|
17405 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17406 | See the License for the specific language governing permissions and
|
17407 | limitations under the License.
|
17408 |
|
17409 | */
|
17410 |
|
17411 | /**
|
17412 | * Slide animator for navigator transition.
|
17413 | */
|
17414 |
|
17415 | var 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 | /*
|
17547 | Copyright 2013-2015 ASIAL CORPORATION
|
17548 |
|
17549 | Licensed under the Apache License, Version 2.0 (the "License");
|
17550 | you may not use this file except in compliance with the License.
|
17551 | You may obtain a copy of the License at
|
17552 |
|
17553 | http://www.apache.org/licenses/LICENSE-2.0
|
17554 |
|
17555 | Unless required by applicable law or agreed to in writing, software
|
17556 | distributed under the License is distributed on an "AS IS" BASIS,
|
17557 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17558 | See the License for the specific language governing permissions and
|
17559 | limitations under the License.
|
17560 |
|
17561 | */
|
17562 |
|
17563 | /**
|
17564 | * Lift screen transition.
|
17565 | */
|
17566 |
|
17567 | var 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 | /*
|
17684 | Copyright 2013-2015 ASIAL CORPORATION
|
17685 |
|
17686 | Licensed under the Apache License, Version 2.0 (the "License");
|
17687 | you may not use this file except in compliance with the License.
|
17688 | You may obtain a copy of the License at
|
17689 |
|
17690 | http://www.apache.org/licenses/LICENSE-2.0
|
17691 |
|
17692 | Unless required by applicable law or agreed to in writing, software
|
17693 | distributed under the License is distributed on an "AS IS" BASIS,
|
17694 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17695 | See the License for the specific language governing permissions and
|
17696 | limitations under the License.
|
17697 |
|
17698 | */
|
17699 |
|
17700 | /**
|
17701 | * Fade-in + Lift screen transition.
|
17702 | */
|
17703 |
|
17704 | var 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 | /*
|
17790 | Copyright 2013-2015 ASIAL CORPORATION
|
17791 |
|
17792 | Licensed under the Apache License, Version 2.0 (the "License");
|
17793 | you may not use this file except in compliance with the License.
|
17794 | You may obtain a copy of the License at
|
17795 |
|
17796 | http://www.apache.org/licenses/LICENSE-2.0
|
17797 |
|
17798 | Unless required by applicable law or agreed to in writing, software
|
17799 | distributed under the License is distributed on an "AS IS" BASIS,
|
17800 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17801 | See the License for the specific language governing permissions and
|
17802 | limitations under the License.
|
17803 |
|
17804 | */
|
17805 |
|
17806 | var 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 | /*
|
17829 | Copyright 2013-2015 ASIAL CORPORATION
|
17830 |
|
17831 | Licensed under the Apache License, Version 2.0 (the "License");
|
17832 | you may not use this file except in compliance with the License.
|
17833 | You may obtain a copy of the License at
|
17834 |
|
17835 | http://www.apache.org/licenses/LICENSE-2.0
|
17836 |
|
17837 | Unless required by applicable law or agreed to in writing, software
|
17838 | distributed under the License is distributed on an "AS IS" BASIS,
|
17839 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17840 | See the License for the specific language governing permissions and
|
17841 | limitations under the License.
|
17842 |
|
17843 | */
|
17844 |
|
17845 | var _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 |
|
17867 | var 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 |
|
17946 | var 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 |
|
18958 | customElements.define('ons-navigator', NavigatorElement);
|
18959 |
|
18960 | /*
|
18961 | Copyright 2013-2015 ASIAL CORPORATION
|
18962 |
|
18963 | Licensed under the Apache License, Version 2.0 (the "License");
|
18964 | you may not use this file except in compliance with the License.
|
18965 | You may obtain a copy of the License at
|
18966 |
|
18967 | http://www.apache.org/licenses/LICENSE-2.0
|
18968 |
|
18969 | Unless required by applicable law or agreed to in writing, software
|
18970 | distributed under the License is distributed on an "AS IS" BASIS,
|
18971 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
18972 | See the License for the specific language governing permissions and
|
18973 | limitations under the License.
|
18974 |
|
18975 | */
|
18976 |
|
18977 | var 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 |
|
19037 | var 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 |
|
19183 | customElements.define('ons-toolbar', ToolbarElement);
|
19184 |
|
19185 | /*
|
19186 | Copyright 2013-2015 ASIAL CORPORATION
|
19187 |
|
19188 | Licensed under the Apache License, Version 2.0 (the "License");
|
19189 | you may not use this file except in compliance with the License.
|
19190 | You may obtain a copy of the License at
|
19191 |
|
19192 | http://www.apache.org/licenses/LICENSE-2.0
|
19193 |
|
19194 | Unless required by applicable law or agreed to in writing, software
|
19195 | distributed under the License is distributed on an "AS IS" BASIS,
|
19196 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19197 | See the License for the specific language governing permissions and
|
19198 | limitations under the License.
|
19199 |
|
19200 | */
|
19201 |
|
19202 | var scheme$12 = {
|
19203 | '': 'page--*',
|
19204 | '.page__content': 'page--*__content',
|
19205 | '.page__background': 'page--*__background'
|
19206 | };
|
19207 |
|
19208 | var 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 |
|
19275 | var 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 |
|
19685 | customElements.define('ons-page', PageElement);
|
19686 |
|
19687 | /*
|
19688 | Copyright 2013-2015 ASIAL CORPORATION
|
19689 |
|
19690 | Licensed under the Apache License, Version 2.0 (the "License");
|
19691 | you may not use this file except in compliance with the License.
|
19692 | You may obtain a copy of the License at
|
19693 |
|
19694 | http://www.apache.org/licenses/LICENSE-2.0
|
19695 |
|
19696 | Unless required by applicable law or agreed to in writing, software
|
19697 | distributed under the License is distributed on an "AS IS" BASIS,
|
19698 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19699 | See the License for the specific language governing permissions and
|
19700 | limitations under the License.
|
19701 |
|
19702 | */
|
19703 | var 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 |
|
19783 | var 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 |
|
19794 | var 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 |
|
19822 | var 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 | /*
|
19854 | Copyright 2013-2015 ASIAL CORPORATION
|
19855 |
|
19856 | Licensed under the Apache License, Version 2.0 (the "License");
|
19857 | you may not use this file except in compliance with the License.
|
19858 | You may obtain a copy of the License at
|
19859 |
|
19860 | http://www.apache.org/licenses/LICENSE-2.0
|
19861 |
|
19862 | Unless required by applicable law or agreed to in writing, software
|
19863 | distributed under the License is distributed on an "AS IS" BASIS,
|
19864 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19865 | See the License for the specific language governing permissions and
|
19866 | limitations under the License.
|
19867 |
|
19868 | */
|
19869 |
|
19870 | var 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 |
|
19878 | var _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 |
|
19887 | var 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 |
|
19889 | var 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 |
|
19931 | var 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 |
|
20561 | customElements.define('ons-popover', PopoverElement);
|
20562 |
|
20563 | /*
|
20564 | Copyright 2013-2015 ASIAL CORPORATION
|
20565 |
|
20566 | Licensed under the Apache License, Version 2.0 (the "License");
|
20567 | you may not use this file except in compliance with the License.
|
20568 | You may obtain a copy of the License at
|
20569 |
|
20570 | http://www.apache.org/licenses/LICENSE-2.0
|
20571 |
|
20572 | Unless required by applicable law or agreed to in writing, software
|
20573 | distributed under the License is distributed on an "AS IS" BASIS,
|
20574 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
20575 | See the License for the specific language governing permissions and
|
20576 | limitations under the License.
|
20577 |
|
20578 | */
|
20579 |
|
20580 | var scheme$15 = {
|
20581 | '.progress-bar': 'progress-bar--*',
|
20582 | '.progress-bar__primary': 'progress-bar__primary--*',
|
20583 | '.progress-bar__secondary': 'progress-bar__secondary--*'
|
20584 | };
|
20585 |
|
20586 | var 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 |
|
20612 | var 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 |
|
20810 | customElements.define('ons-progress-bar', ProgressBarElement);
|
20811 |
|
20812 | /*
|
20813 | Copyright 2013-2015 ASIAL CORPORATION
|
20814 |
|
20815 | Licensed under the Apache License, Version 2.0 (the "License");
|
20816 | you may not use this file except in compliance with the License.
|
20817 | You may obtain a copy of the License at
|
20818 |
|
20819 | http://www.apache.org/licenses/LICENSE-2.0
|
20820 |
|
20821 | Unless required by applicable law or agreed to in writing, software
|
20822 | distributed under the License is distributed on an "AS IS" BASIS,
|
20823 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
20824 | See the License for the specific language governing permissions and
|
20825 | limitations under the License.
|
20826 |
|
20827 | */
|
20828 |
|
20829 | var scheme$16 = {
|
20830 | '.progress-circular': 'progress-circular--*',
|
20831 | '.progress-circular__primary': 'progress-circular__primary--*',
|
20832 | '.progress-circular__secondary': 'progress-circular__secondary--*'
|
20833 | };
|
20834 |
|
20835 | var 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 |
|
20861 | var 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 |
|
21067 | customElements.define('ons-progress-circular', ProgressCircularElement);
|
21068 |
|
21069 | /*
|
21070 | Copyright 2013-2015 ASIAL CORPORATION
|
21071 |
|
21072 | Licensed under the Apache License, Version 2.0 (the "License");
|
21073 | you may not use this file except in compliance with the License.
|
21074 | You may obtain a copy of the License at
|
21075 |
|
21076 | http://www.apache.org/licenses/LICENSE-2.0
|
21077 |
|
21078 | Unless required by applicable law or agreed to in writing, software
|
21079 | distributed under the License is distributed on an "AS IS" BASIS,
|
21080 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21081 | See the License for the specific language governing permissions and
|
21082 | limitations under the License.
|
21083 |
|
21084 | */
|
21085 |
|
21086 | var STATE_INITIAL = 'initial';
|
21087 | var STATE_PREACTION = 'preaction';
|
21088 | var STATE_ACTION = 'action';
|
21089 |
|
21090 | var 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 |
|
21123 | var 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 |
|
21584 | customElements.define('ons-pull-hook', PullHookElement);
|
21585 |
|
21586 | /*
|
21587 | Copyright 2013-2016 ASIAL CORPORATION
|
21588 |
|
21589 | Licensed under the Apache License, Version 2.0 (the "License");
|
21590 | you may not use this file except in compliance with the License.
|
21591 | You may obtain a copy of the License at
|
21592 |
|
21593 | http://www.apache.org/licenses/LICENSE-2.0
|
21594 |
|
21595 | Unless required by applicable law or agreed to in writing, software
|
21596 | distributed under the License is distributed on an "AS IS" BASIS,
|
21597 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21598 | See the License for the specific language governing permissions and
|
21599 | limitations under the License.
|
21600 |
|
21601 | */
|
21602 |
|
21603 | /**
|
21604 | * @class AnimatorCSS - implementation of Animator class using css transitions
|
21605 | */
|
21606 |
|
21607 | var 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 | /*
|
21826 | Copyright 2013-2015 ASIAL CORPORATION
|
21827 |
|
21828 | Licensed under the Apache License, Version 2.0 (the "License");
|
21829 | you may not use this file except in compliance with the License.
|
21830 | You may obtain a copy of the License at
|
21831 |
|
21832 | http://www.apache.org/licenses/LICENSE-2.0
|
21833 |
|
21834 | Unless required by applicable law or agreed to in writing, software
|
21835 | distributed under the License is distributed on an "AS IS" BASIS,
|
21836 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21837 | See the License for the specific language governing permissions and
|
21838 | limitations 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 |
|
21866 | var 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 |
|
22126 | customElements.define('ons-ripple', RippleElement);
|
22127 |
|
22128 | /*
|
22129 | Copyright 2013-2015 ASIAL CORPORATION
|
22130 |
|
22131 | Licensed under the Apache License, Version 2.0 (the "License");
|
22132 | you may not use this file except in compliance with the License.
|
22133 | You may obtain a copy of the License at
|
22134 |
|
22135 | http://www.apache.org/licenses/LICENSE-2.0
|
22136 |
|
22137 | Unless required by applicable law or agreed to in writing, software
|
22138 | distributed under the License is distributed on an "AS IS" BASIS,
|
22139 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22140 | See the License for the specific language governing permissions and
|
22141 | limitations 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 |
|
22176 | var 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 |
|
22187 | customElements.define('ons-row', RowElement);
|
22188 |
|
22189 | /*
|
22190 | Copyright 2013-2015 ASIAL CORPORATION
|
22191 | Licensed under the Apache License, Version 2.0 (the "License");
|
22192 | you may not use this file except in compliance with the License.
|
22193 | You may obtain a copy of the License at
|
22194 | http://www.apache.org/licenses/LICENSE-2.0
|
22195 | Unless required by applicable law or agreed to in writing, software
|
22196 | distributed under the License is distributed on an "AS IS" BASIS,
|
22197 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22198 | See the License for the specific language governing permissions and
|
22199 | limitations under the License.
|
22200 | */
|
22201 |
|
22202 | var 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 |
|
22235 | var 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 |
|
22312 | customElements.define('ons-speed-dial-item', SpeedDialItemElement);
|
22313 |
|
22314 | /*
|
22315 | Copyright 2013-2015 ASIAL CORPORATION
|
22316 |
|
22317 | Licensed under the Apache License, Version 2.0 (the "License");
|
22318 | you may not use this file except in compliance with the License.
|
22319 | You may obtain a copy of the License at
|
22320 |
|
22321 | http://www.apache.org/licenses/LICENSE-2.0
|
22322 |
|
22323 | Unless required by applicable law or agreed to in writing, software
|
22324 | distributed under the License is distributed on an "AS IS" BASIS,
|
22325 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22326 | See the License for the specific language governing permissions and
|
22327 | limitations under the License.
|
22328 |
|
22329 | */
|
22330 |
|
22331 | /**
|
22332 | * Minimal utility library for manipulating element's style.
|
22333 | */
|
22334 | var 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 | */
|
22345 | styler.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 | */
|
22365 | styler._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 | */
|
22377 | styler.clear = function (element) {
|
22378 | styler._clear(element);
|
22379 | };
|
22380 |
|
22381 | /**
|
22382 | * @param {Element} element
|
22383 | */
|
22384 | styler._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 | /*
|
22398 | Copyright 2013-2015 ASIAL CORPORATION
|
22399 | Licensed under the Apache License, Version 2.0 (the "License");
|
22400 | you may not use this file except in compliance with the License.
|
22401 | You may obtain a copy of the License at
|
22402 | http://www.apache.org/licenses/LICENSE-2.0
|
22403 | Unless required by applicable law or agreed to in writing, software
|
22404 | distributed under the License is distributed on an "AS IS" BASIS,
|
22405 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22406 | See the License for the specific language governing permissions and
|
22407 | limitations under the License.
|
22408 | */
|
22409 |
|
22410 | var 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 |
|
22443 | var 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 |
|
22890 | customElements.define('ons-speed-dial', SpeedDialElement);
|
22891 |
|
22892 | /*
|
22893 | Copyright 2013-2015 ASIAL CORPORATION
|
22894 |
|
22895 | Licensed under the Apache License, Version 2.0 (the "License");
|
22896 | you may not use this file except in compliance with the License.
|
22897 | You may obtain a copy of the License at
|
22898 |
|
22899 | http://www.apache.org/licenses/LICENSE-2.0
|
22900 |
|
22901 | Unless required by applicable law or agreed to in writing, software
|
22902 | distributed under the License is distributed on an "AS IS" BASIS,
|
22903 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22904 | See the License for the specific language governing permissions and
|
22905 | limitations under the License.
|
22906 |
|
22907 | */
|
22908 |
|
22909 | var 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 |
|
22963 | var 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 |
|
23134 | customElements.define('ons-splitter-content', SplitterContentElement);
|
23135 |
|
23136 | /*
|
23137 | Copyright 2013-2015 ASIAL CORPORATION
|
23138 |
|
23139 | Licensed under the Apache License, Version 2.0 (the "License");
|
23140 | you may not use this file except in compliance with the License.
|
23141 | You may obtain a copy of the License at
|
23142 |
|
23143 | http://www.apache.org/licenses/LICENSE-2.0
|
23144 |
|
23145 | Unless required by applicable law or agreed to in writing, software
|
23146 | distributed under the License is distributed on an "AS IS" BASIS,
|
23147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
23148 | See the License for the specific language governing permissions and
|
23149 | limitations under the License.
|
23150 |
|
23151 | */
|
23152 |
|
23153 | var 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 |
|
23198 | customElements.define('ons-splitter-mask', SplitterMaskElement);
|
23199 |
|
23200 | /*
|
23201 | Copyright 2013-2015 ASIAL CORPORATION
|
23202 |
|
23203 | Licensed under the Apache License, Version 2.0 (the "License");
|
23204 | you may not use this file except in compliance with the License.
|
23205 | You may obtain a copy of the License at
|
23206 |
|
23207 | http://www.apache.org/licenses/LICENSE-2.0
|
23208 |
|
23209 | Unless required by applicable law or agreed to in writing, software
|
23210 | distributed under the License is distributed on an "AS IS" BASIS,
|
23211 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
23212 | See the License for the specific language governing permissions and
|
23213 | limitations under the License.
|
23214 |
|
23215 | */
|
23216 |
|
23217 | var 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 | /*
|
23333 | Copyright 2013-2015 ASIAL CORPORATION
|
23334 |
|
23335 | Licensed under the Apache License, Version 2.0 (the "License");
|
23336 | you may not use this file except in compliance with the License.
|
23337 | You may obtain a copy of the License at
|
23338 |
|
23339 | http://www.apache.org/licenses/LICENSE-2.0
|
23340 |
|
23341 | Unless required by applicable law or agreed to in writing, software
|
23342 | distributed under the License is distributed on an "AS IS" BASIS,
|
23343 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
23344 | See the License for the specific language governing permissions and
|
23345 | limitations under the License.
|
23346 |
|
23347 | */
|
23348 |
|
23349 | var _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 |
|
23392 | var 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 |
|
23584 | customElements.define('ons-splitter', SplitterElement);
|
23585 |
|
23586 | /*
|
23587 | Copyright 2013-2015 ASIAL CORPORATION
|
23588 |
|
23589 | Licensed under the Apache License, Version 2.0 (the "License");
|
23590 | you may not use this file except in compliance with the License.
|
23591 | You may obtain a copy of the License at
|
23592 |
|
23593 | http://www.apache.org/licenses/LICENSE-2.0
|
23594 |
|
23595 | Unless required by applicable law or agreed to in writing, software
|
23596 | distributed under the License is distributed on an "AS IS" BASIS,
|
23597 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
23598 | See the License for the specific language governing permissions and
|
23599 | limitations under the License.
|
23600 |
|
23601 | */
|
23602 |
|
23603 | var SPLIT_MODE = 'split';
|
23604 | var COLLAPSE_MODE = 'collapse';
|
23605 | var CLOSED_STATE = 'closed';
|
23606 | var OPEN_STATE = 'open';
|
23607 | var CHANGING_STATE = 'changing';
|
23608 |
|
23609 | var WATCHED_ATTRIBUTES = ['animation', 'width', 'side', 'collapse', 'swipeable', 'swipe-target-width', 'animation-options', 'open-threshold'];
|
23610 |
|
23611 | var 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 |
|
23632 | var 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 |
|
23690 | var 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 |
|
23698 | var 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 |
|
23900 | var 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 |
|
24482 | customElements.define('ons-splitter-side', SplitterSideElement);
|
24483 |
|
24484 | /*
|
24485 | Copyright 2013-2015 ASIAL CORPORATION
|
24486 |
|
24487 | Licensed under the Apache License, Version 2.0 (the "License");
|
24488 | you may not use this file except in compliance with the License.
|
24489 | You may obtain a copy of the License at
|
24490 |
|
24491 | http://www.apache.org/licenses/LICENSE-2.0
|
24492 |
|
24493 | Unless required by applicable law or agreed to in writing, software
|
24494 | distributed under the License is distributed on an "AS IS" BASIS,
|
24495 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
24496 | See the License for the specific language governing permissions and
|
24497 | limitations under the License.
|
24498 |
|
24499 | */
|
24500 |
|
24501 | var scheme$19 = {
|
24502 | '': 'switch--*',
|
24503 | '.switch__input': 'switch--*__input',
|
24504 | '.switch__handle': 'switch--*__handle',
|
24505 | '.switch__toggle': 'switch--*__toggle'
|
24506 | };
|
24507 |
|
24508 | var 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 |
|
24510 | var 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 |
|
24540 | var 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 |
|
24837 | customElements.define('ons-switch', SwitchElement);
|
24838 |
|
24839 | /*
|
24840 | Copyright 2013-2015 ASIAL CORPORATION
|
24841 |
|
24842 | Licensed under the Apache License, Version 2.0 (the "License");
|
24843 | you may not use this file except in compliance with the License.
|
24844 | You may obtain a copy of the License at
|
24845 |
|
24846 | http://www.apache.org/licenses/LICENSE-2.0
|
24847 |
|
24848 | Unless required by applicable law or agreed to in writing, software
|
24849 | distributed under the License is distributed on an "AS IS" BASIS,
|
24850 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
24851 | See the License for the specific language governing permissions and
|
24852 | limitations under the License.
|
24853 |
|
24854 | */
|
24855 |
|
24856 | var 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 |
|
24891 | var 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 |
|
24908 | var 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 |
|
24951 | var 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 | /*
|
24999 | Copyright 2013-2015 ASIAL CORPORATION
|
25000 |
|
25001 | Licensed under the Apache License, Version 2.0 (the "License");
|
25002 | you may not use this file except in compliance with the License.
|
25003 | You may obtain a copy of the License at
|
25004 |
|
25005 | http://www.apache.org/licenses/LICENSE-2.0
|
25006 |
|
25007 | Unless required by applicable law or agreed to in writing, software
|
25008 | distributed under the License is distributed on an "AS IS" BASIS,
|
25009 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
25010 | See the License for the specific language governing permissions and
|
25011 | limitations under the License.
|
25012 |
|
25013 | */
|
25014 |
|
25015 | var scheme$21 = {
|
25016 | '.tab-bar__content': 'tab-bar--*__content',
|
25017 | '.tab-bar': 'tab-bar--*'
|
25018 | };
|
25019 |
|
25020 | var _animatorDict$6 = {
|
25021 | 'default': TabbarNoneAnimator,
|
25022 | 'fade': TabbarFadeAnimator,
|
25023 | 'slide': TabbarSlideAnimator,
|
25024 | 'none': TabbarNoneAnimator
|
25025 | };
|
25026 |
|
25027 | var 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 |
|
25058 | var 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 |
|
25108 | var 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 |
|
25697 | customElements.define('ons-tabbar', TabbarElement);
|
25698 |
|
25699 | /*
|
25700 | Copyright 2013-2015 ASIAL CORPORATION
|
25701 |
|
25702 | Licensed under the Apache License, Version 2.0 (the "License");
|
25703 | you may not use this file except in compliance with the License.
|
25704 | You may obtain a copy of the License at
|
25705 |
|
25706 | http://www.apache.org/licenses/LICENSE-2.0
|
25707 |
|
25708 | Unless required by applicable law or agreed to in writing, software
|
25709 | distributed under the License is distributed on an "AS IS" BASIS,
|
25710 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
25711 | See the License for the specific language governing permissions and
|
25712 | limitations under the License.
|
25713 |
|
25714 | */
|
25715 |
|
25716 | var scheme$20 = {
|
25717 | '': 'tab-bar--*__item',
|
25718 | '.tab-bar__button': 'tab-bar--*__button'
|
25719 | };
|
25720 | var templateSource$1 = util.createElement('\n <div>\n <input type="radio" style="display: none">\n <button class="tab-bar__button"></button>\n </div>\n');
|
25721 | var 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 |
|
25773 | var 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 |
|
26228 | customElements.define('ons-tab', TabElement);
|
26229 |
|
26230 | /*
|
26231 | Copyright 2013-2015 ASIAL CORPORATION
|
26232 |
|
26233 | Licensed under the Apache License, Version 2.0 (the "License");
|
26234 | you may not use this file except in compliance with the License.
|
26235 | You may obtain a copy of the License at
|
26236 |
|
26237 | http://www.apache.org/licenses/LICENSE-2.0
|
26238 |
|
26239 | Unless required by applicable law or agreed to in writing, software
|
26240 | distributed under the License is distributed on an "AS IS" BASIS,
|
26241 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
26242 | See the License for the specific language governing permissions and
|
26243 | limitations under the License.
|
26244 |
|
26245 | */
|
26246 |
|
26247 | var 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 |
|
26290 | var 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 |
|
26362 | customElements.define('ons-toolbar-button', ToolbarButtonElement);
|
26363 |
|
26364 | /*
|
26365 | Copyright 2013-2015 ASIAL CORPORATION
|
26366 | Licensed under the Apache License, Version 2.0 (the "License");
|
26367 | you may not use this file except in compliance with the License.
|
26368 | You may obtain a copy of the License at
|
26369 | http://www.apache.org/licenses/LICENSE-2.0
|
26370 | Unless required by applicable law or agreed to in writing, software
|
26371 | distributed under the License is distributed on an "AS IS" BASIS,
|
26372 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
26373 | See the License for the specific language governing permissions and
|
26374 | limitations under the License.
|
26375 | */
|
26376 |
|
26377 | var scheme$23 = {
|
26378 | '.range': 'range--*',
|
26379 | '.range__left': 'range--*__left'
|
26380 | };
|
26381 |
|
26382 | var templateSource$2 = util.createElement('<div>\n <div class="range__left"></div>\n <input type="range" class="range">\n</div>');
|
26383 |
|
26384 | var 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 |
|
26410 | var 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 |
|
26563 | customElements.define('ons-range', RangeElement);
|
26564 |
|
26565 | ons$1.TemplateElement = TemplateElement;
|
26566 | ons$1.IfElement = IfElement;
|
26567 | ons$1.AlertDialogElement = AlertDialogElement;
|
26568 | ons$1.BackButtonElement = BackButtonElement;
|
26569 | ons$1.BottomToolbarElement = BottomToolbarElement;
|
26570 | ons$1.ButtonElement = ButtonElement;
|
26571 | ons$1.CarouselItemElement = CarouselItemElement;
|
26572 | ons$1.CarouselElement = CarouselElement;
|
26573 | ons$1.ColElement = ColElement;
|
26574 | ons$1.DialogElement = DialogElement;
|
26575 | ons$1.FabElement = FabElement;
|
26576 | ons$1.GestureDetectorElement = GestureDetectorElement;
|
26577 | ons$1.IconElement = IconElement;
|
26578 | ons$1.LazyRepeatElement = LazyRepeatElement;
|
26579 | ons$1.ListHeaderElement = ListHeaderElement;
|
26580 | ons$1.ListItemElement = ListItemElement;
|
26581 | ons$1.ListElement = ListElement;
|
26582 | ons$1.InputElement = InputElement;
|
26583 | ons$1.ModalElement = ModalElement;
|
26584 | ons$1.NavigatorElement = NavigatorElement;
|
26585 | ons$1.PageElement = PageElement;
|
26586 | ons$1.PopoverElement = PopoverElement;
|
26587 | ons$1.ProgressBarElement = ProgressBarElement;
|
26588 | ons$1.ProgressCircularElement = ProgressCircularElement;
|
26589 | ons$1.PullHookElement = PullHookElement;
|
26590 | ons$1.RippleElement = RippleElement;
|
26591 | ons$1.RowElement = RowElement;
|
26592 | ons$1.SpeedDialItemElement = SpeedDialItemElement;
|
26593 | ons$1.SpeedDialElement = SpeedDialElement;
|
26594 | ons$1.SplitterContentElement = SplitterContentElement;
|
26595 | ons$1.SplitterMaskElement = SplitterMaskElement;
|
26596 | ons$1.SplitterSideElement = SplitterSideElement;
|
26597 | ons$1.SplitterElement = SplitterElement;
|
26598 | ons$1.SwitchElement = SwitchElement;
|
26599 | ons$1.TabElement = TabElement;
|
26600 | ons$1.TabbarElement = TabbarElement;
|
26601 | ons$1.ToolbarButtonElement = ToolbarButtonElement;
|
26602 | ons$1.ToolbarElement = ToolbarElement;
|
26603 | ons$1.RangeElement = RangeElement;
|
26604 |
|
26605 | // fastclick
|
26606 | window.addEventListener('load', function () {
|
26607 | ons$1.fastClick = FastClick.attach(document.body);
|
26608 | }, false);
|
26609 |
|
26610 | // ons._defaultDeviceBackButtonHandler
|
26611 | window.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
|
26620 | ons$1.ready(function () {
|
26621 | ons$1._setupLoadingPlaceHolders();
|
26622 | });
|
26623 |
|
26624 | // viewport.js
|
26625 | new Viewport().setup();
|
26626 |
|
26627 | return 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==
|