ng-voice-inputs
Version:
This library provides Voice Recognition service to fill the form input fields (text, datepicker, textarea, button-click) for Angular application.
535 lines • 44.3 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: lib/ng-voice-inputs.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Injectable } from '@angular/core';
import * as moment_ from 'moment/moment';
import * as i0 from "@angular/core";
/** @type {?} */
const moment = moment_;
import { Subject } from 'rxjs';
/** @type {?} */
const UNIT = {
zero: 0,
first: 1,
one: 1,
second: 2,
two: 2,
third: 3,
thirteenth: 13,
thirteen: 13,
three: 3,
fourth: 4,
fourteenth: 14,
fourteen: 14,
four: 4,
fifteenth: 15,
fifteen: 15,
fifth: 5,
five: 5,
sixth: 6,
sixteenth: 16,
sixteen: 16,
six: 6,
seventeenth: 17,
seventeen: 17,
seventh: 7,
seven: 7,
eighteenth: 18,
eighteen: 18,
eighth: 8,
eight: 8,
nineteenth: 19,
nineteen: 19,
ninth: 9,
nine: 9,
tenth: 10,
ten: 10,
eleventh: 11,
eleven: 11,
twelfth: 12,
twelve: 12,
a: 1,
};
/** @type {?} */
const TWOS = {
ten: 10,
eleven: 11,
twelve: 12,
thirteen: 13,
fourteen: 14,
fifteen: 15,
sixteen: 16,
seventeen: 17,
eighteen: 18,
nineteen: 19
};
/** @type {?} */
const TEN = {
twenty: 20,
twentieth: 20,
thirty: 30,
thirtieth: 30,
forty: 40,
fortieth: 40,
fifty: 50,
fiftieth: 50,
sixty: 60,
sixtieth: 60,
seventy: 70,
seventieth: 70,
eighty: 80,
eightieth: 80,
ninety: 90,
ninetieth: 90,
};
/** @type {?} */
const MAGNITUDE = {
hundred: 100,
hundredth: 100,
thousand: 1000,
million: 1000000,
billion: 1000000000,
trillion: 1000000000000,
quadrillion: 1000000000000000,
quintillion: 1000000000000000000,
sextillion: 1000000000000000000000,
septillion: 1000000000000000000000000,
octillion: 1000000000000000000000000000,
nonillion: 1000000000000000000000000000000,
decillion: 1000000000000000000000000000000000,
};
/** @type {?} */
const NUMBER = Object.assign({}, UNIT, TEN, MAGNITUDE);
/** @type {?} */
const SUFFIXES = ['st', 'nd', 'rd', 'th'];
/** @type {?} */
const MONTHS = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
/** @type {?} */
const KEY_WORDS_FWD_NAV = ['forward', 'next'];
/** @type {?} */
const KEY_WORDS_BCK_NAV = ['back', 'backward', 'previous'];
/** @type {?} */
const KEY_WORDS_CLEAR = ['clear', 'clean', 'delete', 'remove'];
/** @type {?} */
const KEY_WORDS_CLICK = ['click', 'submit', 'expand', 'open', 'show'];
/** @type {?} */
const KEY_WORDS_STOP = ['stop', 'end', 'done'];
/** @type {?} */
const KEY_WORDS_SCROLL_UP = ['scroll up', 'go up', 'up'];
/** @type {?} */
const KEY_WORDS_SCROLL_DOWN = ['scroll down', 'go down', 'down'];
/** @type {?} */
const KEY_WORDS_SCROLL_RIGHT = ['scroll right', 'go right', 'right'];
/** @type {?} */
const KEY_WORDS_SCROLL_LEFT = ['scroll left', 'go left', 'left'];
/** @type {?} */
const KEY_WORDS_SCROLL_TOP = ['scroll top', 'go top', 'top'];
/** @type {?} */
const KEY_WORDS_SCROLL_BOTTOM = ['scroll bottom', 'go bottom', 'bottom'];
/** @type {?} */
const KEY_WORDS_SCROLL_CONTINUE = ['keep scrolling', 'scroll', 'scrolling', 'continue scrolling'];
/** @type {?} */
const KEY_WORDS_SCROLL = [
...KEY_WORDS_SCROLL_UP,
...KEY_WORDS_SCROLL_DOWN,
...KEY_WORDS_SCROLL_RIGHT,
...KEY_WORDS_SCROLL_LEFT,
...KEY_WORDS_SCROLL_TOP,
...KEY_WORDS_SCROLL_BOTTOM,
...KEY_WORDS_SCROLL_CONTINUE
];
/** @type {?} */
const KEY_WORDS_INST = ['goto', 'switch', 'go', ...KEY_WORDS_CLEAR, ...KEY_WORDS_CLICK, ...KEY_WORDS_SCROLL];
// Instruction types
/** @type {?} */
const KEY_WORDS_NAV = [
...KEY_WORDS_FWD_NAV,
...KEY_WORDS_BCK_NAV,
...KEY_WORDS_STOP,
...KEY_WORDS_SCROLL,
'first', 'last',
];
// Navigation types
/** @type {?} */
const KEY_WORDS = [...KEY_WORDS_INST, ...KEY_WORDS_NAV];
/** @type {?} */
const INST_MAPPINGS = {
next: KEY_WORDS_FWD_NAV,
previous: KEY_WORDS_BCK_NAV,
first: ['first'],
last: ['last'],
clear: KEY_WORDS_CLEAR,
click: KEY_WORDS_CLICK,
stop: KEY_WORDS_STOP,
scrollUp: KEY_WORDS_SCROLL_UP,
scrollDown: KEY_WORDS_SCROLL_DOWN,
scrollLeft: KEY_WORDS_SCROLL_LEFT,
scrollRight: KEY_WORDS_SCROLL_RIGHT,
scrollTop: KEY_WORDS_SCROLL_TOP,
scrollBottom: KEY_WORDS_SCROLL_BOTTOM,
scrollContinue: KEY_WORDS_SCROLL_CONTINUE
};
export class VuiVoiceRecognitionService {
constructor() {
this.response = new Subject();
this.inputRefs = [];
this.currentRef = 0;
}
/**
* @param {?} speechKeys
* @param {?} inputType
* @return {?}
*/
isInputSwitch(speechKeys, inputType) {
if (inputType == 'address' && !speechKeys.some((/**
* @param {?} key
* @return {?}
*/
key => KEY_WORDS_INST.includes(key)))) {
return false;
}
if (speechKeys.some((/**
* @param {?} key
* @return {?}
*/
key => KEY_WORDS.includes(key)))) {
return true;
}
return false;
}
/**
* @param {?} speechText
* @param {?} inputType
* @return {?}
*/
findInstructionType(speechText, inputType) {
/** @type {?} */
let type = '';
speechText = speechText.trim().toLocaleLowerCase();
/** @type {?} */
let speechKeys = speechText.trim().toLocaleLowerCase().split(' ');
if (this.isInputSwitch(speechKeys, inputType)) {
/** @type {?} */
const foundKey = Object.keys(INST_MAPPINGS).find((/**
* @param {?} instType
* @return {?}
*/
(instType) => speechKeys.some((/**
* @param {?} key
* @return {?}
*/
key => INST_MAPPINGS[instType].includes(key)))));
type = foundKey ? `COMMAND_${foundKey.toUpperCase()}` : '';
}
else {
type = 'INPUT';
}
return type;
}
/**
* @param {?} speechText
* @param {?} inputType
* @return {?}
*/
interpretSpeech(speechText, inputType) {
/** @type {?} */
let instType = this.findInstructionType(speechText, inputType);
if (instType != 'INPUT') {
return instType;
}
if (inputType == 'text' || inputType == 'address') {
return speechText;
}
if (inputType == 'number') {
return this.wordsToNumber(speechText);
}
if (inputType == 'date') {
speechText = speechText.replace('from', '');
/** @type {?} */
let dates = speechText.trim().split('to ');
/** @type {?} */
let parsedDates = [];
dates.forEach((/**
* @param {?} dateStr
* @return {?}
*/
(dateStr) => {
parsedDates.push(this.dateParser(dateStr));
}));
if (parsedDates[0].isValid()) {
return parsedDates;
}
}
return null;
}
/**
* @param {?} dateStr
* @return {?}
*/
dateParser(dateStr) {
/** @type {?} */
let parsedDate;
/** @type {?} */
let cleanDateStr = dateStr;
/** @type {?} */
let dateParts = dateStr.trim().split(' ');
/** @type {?} */
let datePartObj = {};
/** @type {?} */
let isPureNumber = false;
/** @type {?} */
let cleanDateParts = [];
if (dateParts.length == 3) {
cleanDateParts = dateParts.map((/**
* @param {?} dateStr
* @return {?}
*/
(dateStr) => this.eliminateString(dateStr)));
isPureNumber = cleanDateParts.every((/**
* @param {?} dateStr
* @return {?}
*/
(dateStr) => Number.isInteger(dateStr)));
}
if (isPureNumber) {
cleanDateStr = cleanDateParts.join('-');
}
else {
/** @type {?} */
const currentDate = moment();
dateParts.forEach((/**
* @param {?} dateStr
* @return {?}
*/
(dateStr) => {
datePartObj = this.parseDatePart(dateStr, datePartObj);
}));
/** @type {?} */
const availableKeys = Object.keys(datePartObj).join('-');
switch (availableKeys) {
case 'date':
datePartObj.month = currentDate.format('MM');
case 'date-month':
datePartObj.year = currentDate.format('YYYY');
break;
case 'year':
datePartObj.month = '01';
case 'month-year':
datePartObj.date = '01';
break;
case 'month':
datePartObj.year = currentDate.format('YYYY');
datePartObj.date = '01';
}
cleanDateStr = this.dateBuilder(datePartObj);
}
parsedDate = moment(cleanDateStr).toDate();
return parsedDate;
}
/**
* @param {?} datePartObj
* @return {?}
*/
dateBuilder(datePartObj) {
/** @type {?} */
let dateStr = '';
dateStr = `${datePartObj.year}-${datePartObj.month}-${datePartObj.date}`;
return dateStr;
}
/**
*
* @param {?} datePart Incomplete date part eg, '21st' is the date part for the date '21st July 2020'
* @param {?} datePartObj // Inherited from caller & updated with parsed object. Can be year, month or date
* @return {?}
*/
parseDatePart(datePart, datePartObj) {
if (this.isYearType(datePart)) {
/** @type {?} */
const year = this.wordsToNumber(datePart);
datePartObj.year = year;
}
else if (this.isDateType(datePart)) {
/** @type {?} */
const date = this.wordsToNumber(datePart);
datePartObj.date = date;
}
else if (this.isMonthType(datePart)) {
/** @type {?} */
const month = MONTHS.indexOf(datePart.toUpperCase()) + 1;
datePartObj.month = month < 10 ? '0' + month : month;
}
return datePartObj;
}
/**
* @param {?} datePart
* @return {?}
*/
isDateType(datePart) {
/** @type {?} */
let isDatePart = false;
isDatePart = (/\d/.test(datePart) && SUFFIXES.includes(datePart.substr(datePart.length - 2)));
if (!isDatePart) {
/** @type {?} */
const number = this.wordsToNumber(datePart);
if (number > 0 && number <= 31) {
isDatePart = true;
}
}
return isDatePart;
}
/**
* @param {?} datePart
* @param {?} datePartObj
* @return {?}
*/
parseDateVal(datePart, datePartObj) {
/** @type {?} */
let isDatePart = false;
/** @type {?} */
let convertedNum = 0;
isDatePart = SUFFIXES.some((/**
* @param {?} key
* @return {?}
*/
(key) => {
return datePart.includes(key);
}));
if (!isDatePart) {
convertedNum = this.wordsToNumber(datePart);
if (convertedNum > 0 && convertedNum <= 31) {
isDatePart = true;
}
}
if (isDatePart) {
datePartObj.date = convertedNum;
}
}
/**
* @param {?} datePart
* @return {?}
*/
isMonthType(datePart) {
/** @type {?} */
const month = MONTHS.indexOf(datePart.toUpperCase());
return month > -1;
}
/**
* @param {?} datePart
* @param {?} datePartObj
* @return {?}
*/
parseMonthVal(datePart, datePartObj) {
/** @type {?} */
const month = MONTHS.indexOf(datePart.toUpperCase());
if (month > -1) {
datePartObj.month = month < 10 ? '0' + month : month;
}
}
/**
* @param {?} datePart
* @return {?}
*/
isYearType(datePart) {
/** @type {?} */
let year = this.wordsToNumber(datePart);
return year > 1000;
}
/**
* @param {?} datePart
* @param {?} datePartObj
* @return {?}
*/
parseYearVal(datePart, datePartObj) {
/** @type {?} */
const year = this.wordsToNumber(datePart);
if (year > 1000) {
datePartObj.year = year;
}
}
/**
* @param {?} word
* @return {?}
*/
wordsToNumber(word) {
// Returning integer if it is not actual word
if (!Number.isNaN(parseInt(word))) {
return parseInt(word);
}
word = word.replace(/and/g, ''); // Replace joiners
// Replace joiners
/** @type {?} */
let words = word.toLowerCase().trim().split(' ');
/** @type {?} */
let num = 0;
/** @type {?} */
let numStr = '';
/** @type {?} */
let tens = 0;
words = this.parseColloquialWords(words);
words.forEach((/**
* @param {?} wordStr
* @return {?}
*/
wordStr => {
wordStr = this.eliminateString(wordStr);
if (typeof wordStr == 'number') {
num = wordStr;
}
else {
if (UNIT[wordStr]) {
num = num + NUMBER[wordStr];
}
else if (TEN[wordStr]) {
num = num + TEN[wordStr];
}
else if (MAGNITUDE[wordStr]) {
num = num * MAGNITUDE[wordStr];
}
}
}));
return num;
}
/**
* @param {?} wordsArr
* @return {?}
*/
parseColloquialWords(wordsArr) {
if (wordsArr.length == 2) {
if (TEN[wordsArr[0]] && (TEN[wordsArr[1]] || TWOS[wordsArr[1]])) {
wordsArr.splice(1, 0, 'hundred');
}
}
if (MAGNITUDE[wordsArr[0]]) {
wordsArr.splice(0, 0, 'one');
}
return wordsArr;
}
/**
* @param {?} word
* @return {?}
*/
eliminateString(word) {
if (/\d/.test(word) && SUFFIXES.includes(word.substr(word.length - 2))) {
word = word.substr(0, word.length - 2); // Remove last suffixes such as 'st', 'th' from 1st, 10th
word = parseInt(word);
}
return word;
}
}
VuiVoiceRecognitionService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
/** @nocollapse */ VuiVoiceRecognitionService.ngInjectableDef = i0.defineInjectable({ factory: function VuiVoiceRecognitionService_Factory() { return new VuiVoiceRecognitionService(); }, token: VuiVoiceRecognitionService, providedIn: "root" });
if (false) {
/** @type {?} */
VuiVoiceRecognitionService.prototype.response;
/** @type {?} */
VuiVoiceRecognitionService.prototype.inputRefs;
/** @type {?} */
VuiVoiceRecognitionService.prototype.currentRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctdm9pY2UtaW5wdXRzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZy12b2ljZS1pbnB1dHMvIiwic291cmNlcyI6WyJsaWIvbmctdm9pY2UtaW5wdXRzLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQWMsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZELE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDOzs7TUFDbkMsTUFBTSxHQUFHLE9BQU87QUFDdEIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQzs7TUFHekIsSUFBSSxHQUFHO0lBQ1gsSUFBSSxFQUFFLENBQUM7SUFDUCxLQUFLLEVBQUUsQ0FBQztJQUNSLEdBQUcsRUFBRSxDQUFDO0lBQ04sTUFBTSxFQUFFLENBQUM7SUFDVCxHQUFHLEVBQUUsQ0FBQztJQUNOLEtBQUssRUFBRSxDQUFDO0lBQ1IsVUFBVSxFQUFFLEVBQUU7SUFDZCxRQUFRLEVBQUUsRUFBRTtJQUNaLEtBQUssRUFBRSxDQUFDO0lBQ1IsTUFBTSxFQUFFLENBQUM7SUFDVCxVQUFVLEVBQUUsRUFBRTtJQUNkLFFBQVEsRUFBRSxFQUFFO0lBQ1osSUFBSSxFQUFFLENBQUM7SUFDUCxTQUFTLEVBQUUsRUFBRTtJQUNiLE9BQU8sRUFBRSxFQUFFO0lBQ1gsS0FBSyxFQUFFLENBQUM7SUFDUixJQUFJLEVBQUUsQ0FBQztJQUNQLEtBQUssRUFBRSxDQUFDO0lBQ1IsU0FBUyxFQUFFLEVBQUU7SUFDYixPQUFPLEVBQUUsRUFBRTtJQUNYLEdBQUcsRUFBRSxDQUFDO0lBQ04sV0FBVyxFQUFFLEVBQUU7SUFDZixTQUFTLEVBQUUsRUFBRTtJQUNiLE9BQU8sRUFBRSxDQUFDO0lBQ1YsS0FBSyxFQUFFLENBQUM7SUFDUixVQUFVLEVBQUUsRUFBRTtJQUNkLFFBQVEsRUFBRSxFQUFFO0lBQ1osTUFBTSxFQUFFLENBQUM7SUFDVCxLQUFLLEVBQUUsQ0FBQztJQUNS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bWVudFJlZiwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgbW9tZW50XyBmcm9tICdtb21lbnQvbW9tZW50JztcbmNvbnN0IG1vbWVudCA9IG1vbWVudF87XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgVnVpUmVzcG9uc2UgZnJvbSAnLi92dWktcmVzcG9uc2UnO1xuXG5jb25zdCBVTklUID0ge1xuICB6ZXJvOiAwLFxuICBmaXJzdDogMSxcbiAgb25lOiAxLFxuICBzZWNvbmQ6IDIsXG4gIHR3bzogMixcbiAgdGhpcmQ6IDMsXG4gIHRoaXJ0ZWVudGg6IDEzLFxuICB0aGlydGVlbjogMTMsXG4gIHRocmVlOiAzLFxuICBmb3VydGg6IDQsXG4gIGZvdXJ0ZWVudGg6IDE0LFxuICBmb3VydGVlbjogMTQsXG4gIGZvdXI6IDQsXG4gIGZpZnRlZW50aDogMTUsXG4gIGZpZnRlZW46IDE1LFxuICBmaWZ0aDogNSxcbiAgZml2ZTogNSxcbiAgc2l4dGg6IDYsXG4gIHNpeHRlZW50aDogMTYsXG4gIHNpeHRlZW46IDE2LFxuICBzaXg6IDYsXG4gIHNldmVudGVlbnRoOiAxNyxcbiAgc2V2ZW50ZWVuOiAxNyxcbiAgc2V2ZW50aDogNyxcbiAgc2V2ZW46IDcsXG4gIGVpZ2h0ZWVudGg6IDE4LFxuICBlaWdodGVlbjogMTgsXG4gIGVpZ2h0aDogOCxcbiAgZWlnaHQ6IDgsXG4gIG5pbmV0ZWVudGg6IDE5LFxuICBuaW5ldGVlbjogMTksXG4gIG5pbnRoOiA5LFxuICBuaW5lOiA5LFxuICB0ZW50aDogMTAsXG4gIHRlbjogMTAsXG4gIGVsZXZlbnRoOiAxMSxcbiAgZWxldmVuOiAxMSxcbiAgdHdlbGZ0aDogMTIsXG4gIHR3ZWx2ZTogMTIsXG4gIGE6IDEsXG59O1xuXG5jb25zdCBUV09TID0ge1xuICB0ZW46IDEwLFxuICBlbGV2ZW46IDExLCBcbiAgdHdlbHZlOiAxMiwgXG4gIHRoaXJ0ZWVuOiAxMywgXG4gIGZvdXJ0ZWVuOiAxNCwgXG4gIGZpZnRlZW46IDE1LCBcbiAgc2l4dGVlbjogMTYsIFxuICBzZXZlbnRlZW46IDE3LFxuICBlaWdodGVlbjogMTgsXG4gIG5pbmV0ZWVuOiAxOVxufVxuXG5jb25zdCBURU4gPSB7XG4gIHR3ZW50eTogMjAsXG4gIHR3ZW50aWV0aDogMjAsXG4gIHRoaXJ0eTogMzAsXG4gIHRoaXJ0aWV0aDogMzAsXG4gIGZvcnR5OiA0MCxcbiAgZm9ydGlldGg6IDQwLFxuICBmaWZ0eTogNTAsXG4gIGZpZnRpZXRoOiA1MCxcbiAgc2l4dHk6IDYwLFxuICBzaXh0aWV0aDogNjAsXG4gIHNldmVudHk6IDcwLFxuICBzZXZlbnRpZXRoOiA3MCxcbiAgZWlnaHR5OiA4MCxcbiAgZWlnaHRpZXRoOiA4MCxcbiAgbmluZXR5OiA5MCxcbiAgbmluZXRpZXRoOiA5MCxcbn07XG5cbmNvbnN0IE1BR05JVFVERSA9IHtcbiAgaHVuZHJlZDogMTAwLFxuICBodW5kcmVkdGg6IDEwMCxcbiAgdGhvdXNhbmQ6IDEwMDAsXG4gIG1pbGxpb246IDEwMDAwMDAsXG4gIGJpbGxpb246IDEwMDAwMDAwMDAsXG4gIHRyaWxsaW9uOiAxMDAwMDAwMDAwMDAwLFxuICBxdWFkcmlsbGlvbjogMTAwMDAwMDAwMDAwMDAwMCxcbiAgcXVpbnRpbGxpb246IDEwMDAwMDAwMDAwMDAwMDAwMDAsXG4gIHNleHRpbGxpb246IDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAsXG4gIHNlcHRpbGxpb246IDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAsXG4gIG9jdGlsbGlvbjogMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCxcbiAgbm9uaWxsaW9uOiAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLFxuICBkZWNpbGxpb246IDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAsXG59O1xuXG5jb25zdCBOVU1CRVIgPSB7IC4uLlVOSVQsIC4uLlRFTiwgLi4uTUFHTklUVURFIH07XG5jb25zdCBTVUZGSVhFUyA9IFsnc3QnLCAnbmQnLCAncmQnLCAndGgnXTtcblxuY29uc3QgTU9OVEhTID0gW1wiSkFOVUFSWVwiLCBcIkZFQlJVQVJZXCIsIFwiTUFSQ0hcIiwgXCJBUFJJTFwiLCBcIk1BWVwiLCBcIkpVTkVcIiwgXCJKVUxZXCIsIFwiQVVHVVNUXCIsIFwiU0VQVEVNQkVSXCIsIFwiT0NUT0JFUlwiLCBcIk5PVkVNQkVSXCIsIFwiREVDRU1CRVJcIl07XG5cbmNvbnN0IEtFWV9XT1JEU19GV0RfTkFWID0gWydmb3J3YXJkJywgJ25leHQnXTtcbmNvbnN0IEtFWV9XT1JEU19CQ0tfTkFWID0gWydiYWNrJywgJ2JhY2t3YXJkJywgJ3ByZXZpb3VzJ107XG5jb25zdCBLRVlfV09SRFNfQ0xFQVIgPSBbJ2NsZWFyJywgJ2NsZWFuJywgJ2RlbGV0ZScsICdyZW1vdmUnXTtcbmNvbnN0IEtFWV9XT1JEU19DTElDSyA9IFsnY2xpY2snLCAnc3VibWl0JywgJ2V4cGFuZCcsICdvcGVuJywgJ3Nob3cnXTtcbmNvbnN0IEtFWV9XT1JEU19TVE9QID0gWydzdG9wJywgJ2VuZCcsICdkb25lJ107XG5jb25zdCBLRVlfV09SRFNfU0NST0xMX1VQID0gWydzY3JvbGwgdXAnLCAnZ28gdXAnLCAndXAnXTtcbmNvbnN0IEtFWV9XT1JEU19TQ1JPTExfRE9XTiA9IFsnc2Nyb2xsIGRvd24nLCAnZ28gZG93bicsICdkb3duJ107XG5jb25zdCBLRVlfV09SRFNfU0NST0xMX1JJR0hUID0gWydzY3JvbGwgcmlnaHQnLCAnZ28gcmlnaHQnLCAncmlnaHQnXTtcbmNvbnN0IEtFWV9XT1JEU19TQ1JPTExfTEVGVCA9IFsnc2Nyb2xsIGxlZnQnLCAnZ28gbGVmdCcsICdsZWZ0J107XG5jb25zdCBLRVlfV09SRFNfU0NST0xMX1RPUCA9IFsnc2Nyb2xsIHRvcCcsICdnbyB0b3AnLCAndG9wJ107XG5jb25zdCBLRVlfV09SRFNfU0NST0xMX0JPVFRPTSA9IFsnc2Nyb2xsIGJvdHRvbScsICdnbyBib3R0b20nLCAnYm90dG9tJ107XG5jb25zdCBLRVlfV09SRFNfU0NST0xMX0NPTlRJTlVFID0gWydrZWVwIHNjcm9sbGluZycsICdzY3JvbGwnLCAnc2Nyb2xsaW5nJywgJ2NvbnRpbnVlIHNjcm9sbGluZyddXG5jb25zdCBLRVlfV09SRFNfU0NST0xMID0gW1xuICAuLi5LRVlfV09SRFNfU0NST0xMX1VQLFxuICAuLi5LRVlfV09SRFNfU0NST0xMX0RPV04sXG4gIC4uLktFWV9XT1JEU19TQ1JPTExfUklHSFQsXG4gIC4uLktFWV9XT1JEU19TQ1JPTExfTEVGVCxcbiAgLi4uS0VZX1dPUkRTX1NDUk9MTF9UT1AsXG4gIC4uLktFWV9XT1JEU19TQ1JPTExfQk9UVE9NLFxuICAuLi5LRVlfV09SRFNfU0NST0xMX0NPTlRJTlVFXG5dO1xuXG5jb25zdCBLRVlfV09SRFNfSU5TVCA9IFsnZ290bycsICdzd2l0Y2gnLCAnZ28nLCAuLi5LRVlfV09SRFNfQ0xFQVIsIC4uLktFWV9XT1JEU19DTElDSywgLi4uS0VZX1dPUkRTX1NDUk9MTF07IC8vIEluc3RydWN0aW9uIHR5cGVzXG5jb25zdCBLRVlfV09SRFNfTkFWID0gW1xuICAuLi5LRVlfV09SRFNfRldEX05BVixcbiAgLi4uS0VZX1dPUkRTX0JDS19OQVYsXG4gIC4uLktFWV9XT1JEU19TVE9QLFxuICAuLi5LRVlfV09SRFNfU0NST0xMXG4gICwgJ2ZpcnN0JywgJ2xhc3QnLFxuXTsgLy8gTmF2aWdhdGlvbiB0eXBlc1xuXG5jb25zdCBLRVlfV09SRFMgPSBbLi4uS0VZX1dPUkRTX0lOU1QsIC4uLktFWV9XT1JEU19OQVZdO1xuXG5jb25zdCBJTlNUX01BUFBJTkdTID0ge1xuICBuZXh0OiBLRVlfV09SRFNfRldEX05BVixcbiAgcHJldmlvdXM6IEtFWV9XT1JEU19CQ0tfTkFWLFxuICBmaXJzdDogWydmaXJzdCddLFxuICBsYXN0OiBbJ2xhc3QnXSxcbiAgY2xlYXI6IEtFWV9XT1JEU19DTEVBUixcbiAgY2xpY2s6IEtFWV9XT1JEU19DTElDSyxcbiAgc3RvcDogS0VZX1dPUkRTX1NUT1AsXG4gIHNjcm9sbFVwOiBLRVlfV09SRFNfU0NST0xMX1VQLFxuICBzY3JvbGxEb3duOiBLRVlfV09SRFNfU0NST0xMX0RPV04sXG4gIHNjcm9sbExlZnQ6IEtFWV9XT1JEU19TQ1JPTExfTEVGVCxcbiAgc2Nyb2xsUmlnaHQ6IEtFWV9XT1JEU19TQ1JPTExfUklHSFQsXG4gIHNjcm9sbFRvcDogS0VZX1dPUkRTX1NDUk9MTF9UT1AsXG4gIHNjcm9sbEJvdHRvbTogS0VZX1dPUkRTX1NDUk9MTF9CT1RUT00sXG4gIHNjcm9sbENvbnRpbnVlOiBLRVlfV09SRFNfU0NST0xMX0NPTlRJTlVFXG59XG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBWdWlWb2ljZVJlY29nbml0aW9uU2VydmljZSB7XG4gIHJlc3BvbnNlOiBTdWJqZWN0PFZ1aVJlc3BvbnNlPiA9IG5ldyBTdWJqZWN0PFZ1aVJlc3BvbnNlPigpO1xuXG4gIGlucHV0UmVmczogQXJyYXk8RWxlbWVudFJlZj4gPSBbXTtcbiAgY3VycmVudFJlZjogbnVtYmVyID0gMDtcblxuICBpc0lucHV0U3dpdGNoKHNwZWVjaEtleXM6IGFueVtdLCBpbnB1dFR5cGU6IHN0cmluZykge1xuICAgIGlmIChpbnB1dFR5cGUgPT0gJ2FkZHJlc3MnICYmICFzcGVlY2hLZXlzLnNvbWUoa2V5ID0+IEtFWV9XT1JEU19JTlNULmluY2x1ZGVzKGtleSkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChzcGVlY2hLZXlzLnNvbWUoa2V5ID0+IEtFWV9XT1JEUy5pbmNsdWRlcyhrZXkpKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZpbmRJbnN0cnVjdGlvblR5cGUoc3BlZWNoVGV4dDogc3RyaW5nLCBpbnB1dFR5cGU6IHN0cmluZykge1xuICAgIGxldCB0eXBlID0gJyc7XG4gICAgc3BlZWNoVGV4dCA9IHNwZWVjaFRleHQudHJpbSgpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgbGV0IHNwZWVjaEtleXMgPSBzcGVlY2hUZXh0LnRyaW0oKS50b0xvY2FsZUxvd2VyQ2FzZSgpLnNwbGl0KCcgJyk7XG4gICAgaWYgKHRoaXMuaXNJbnB1dFN3aXRjaChzcGVlY2hLZXlzLCBpbnB1dFR5cGUpKSB7XG4gICAgICBjb25zdCBmb3VuZEtleSA9IE9iamVjdC5rZXlzKElOU1RfTUFQUElOR1MpLmZpbmQoKGluc3RUeXBlOiBzdHJpbmcpID0+IHNwZWVjaEtleXMuc29tZShrZXkgPT4gSU5TVF9NQVBQSU5HU1tpbnN0VHlwZV0uaW5jbHVkZXMoa2V5KSkpO1xuICAgICAgdHlwZSA9IGZvdW5kS2V5ID8gYENPTU1BTkRfJHtmb3VuZEtleS50b1VwcGVyQ2FzZSgpfWAgOiAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgdHlwZSA9ICdJTlBVVCc7XG4gICAgfVxuICAgIHJldHVybiB0eXBlO1xuICB9XG5cbiAgaW50ZXJwcmV0U3BlZWNoKHNwZWVjaFRleHQ6IHN0cmluZywgaW5wdXRUeXBlOiBzdHJpbmcpIHtcbiAgICBsZXQgaW5zdFR5cGUgPSB0aGlzLmZpbmRJbnN0cnVjdGlvblR5cGUoc3BlZWNoVGV4dCwgaW5wdXRUeXBlKTtcbiAgICBpZiAoaW5zdFR5cGUgIT0gJ0lOUFVUJykge1xuICAgICAgcmV0dXJuIGluc3RUeXBlO1xuICAgIH1cblxuICAgIGlmIChpbnB1dFR5cGUgPT0gJ3RleHQnIHx8IGlucHV0VHlwZSA9PSAnYWRkcmVzcycpIHtcbiAgICAgIHJldHVybiBzcGVlY2hUZXh0O1xuICAgIH1cblxuICAgIGlmIChpbnB1dFR5cGUgPT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiB0aGlzLndvcmRzVG9OdW1iZXIoc3BlZWNoVGV4dCk7XG4gICAgfVxuXG4gICAgaWYgKGlucHV0VHlwZSA9PSAnZGF0ZScpIHtcbiAgICAgIHNwZWVjaFRleHQgPSBzcGVlY2hUZXh0LnJlcGxhY2UoJ2Zyb20nLCAnJyk7XG4gICAgICBsZXQgZGF0ZXMgPSAgc3BlZWNoVGV4dC50cmltKCkuc3BsaXQoJ3RvICcpO1xuICAgICAgbGV0IHBhcnNlZERhdGVzOiBBcnJheTxhbnk+ID0gW107XG4gICAgICBkYXRlcy5mb3JFYWNoKChkYXRlU3RyOiBzdHJpbmcpID0+IHtcbiAgICAgICAgcGFyc2VkRGF0ZXMucHVzaCh0aGlzLmRhdGVQYXJzZXIoZGF0ZVN0cikpO1xuICAgICAgfSk7XG4gIFxuICAgICAgaWYgKHBhcnNlZERhdGVzWzBdLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gcGFyc2VkRGF0ZXM7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZGF0ZVBhcnNlcihkYXRlU3RyOiBzdHJpbmcpOiBEYXRlIHtcbiAgICBsZXQgcGFyc2VkRGF0ZTogRGF0ZTtcbiAgICBsZXQgY2xlYW5EYXRlU3RyID0gZGF0ZVN0cjtcbiAgICBsZXQgZGF0ZVBhcnRzID0gZGF0ZVN0ci50cmltKCkuc3BsaXQoJyAnKTtcbiAgICBsZXQgZGF0ZVBhcnRPYmo6IGFueSA9IHt9O1xuICAgIGxldCBpc1B1cmVOdW1iZXIgPSBmYWxzZTtcbiAgICBsZXQgY2xlYW5EYXRlUGFydHMgPSBbXTtcblxuICAgIGlmIChkYXRlUGFydHMubGVuZ3RoID09IDMpIHtcbiAgICAgIGNsZWFuRGF0ZVBhcnRzID0gZGF0ZVBhcnRzLm1hcCgoZGF0ZVN0cikgPT4gdGhpcy5lbGltaW5hdGVTdHJpbmcoZGF0ZVN0cikpO1xuICAgICAgaXNQdXJlTnVtYmVyID0gY2xlYW5EYXRlUGFydHMuZXZlcnkoKGRhdGVTdHIpID0+IE51bWJlci5pc0ludGVnZXIoZGF0ZVN0cikpO1xuICAgIH1cblxuICAgIGlmIChpc1B1cmVOdW1iZXIpIHtcbiAgICAgIGNsZWFuRGF0ZVN0ciA9IGNsZWFuRGF0ZVBhcnRzLmpvaW4oJy0nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgY3VycmVudERhdGUgPSBtb21lbnQoKTtcbiAgICAgIGRhdGVQYXJ0cy5mb3JFYWNoKChkYXRlU3RyKSA9PiB7XG4gICAgICAgIGRhdGVQYXJ0T2JqID0gdGhpcy5wYXJzZURhdGVQYXJ0KGRhdGVTdHIsIGRhdGVQYXJ0T2JqKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBhdmFpbGFibGVLZXlzID0gT2JqZWN0LmtleXMoZGF0ZVBhcnRPYmopLmpvaW4oJy0nKTtcbiAgICAgXG4gICAgICBzd2l0Y2ggKGF2YWlsYWJsZUtleXMpIHtcbiAgICAgICAgY2FzZSAnZGF0ZSc6IFxuICAgICAgICAgIGRhdGVQYXJ0T2JqLm1vbnRoID0gY3VycmVudERhdGUuZm9ybWF0KCdNTScpO1xuICAgICAgICBjYXNlICdkYXRlLW1vbnRoJzpcbiAgICAgICAgICBkYXRlUGFydE9iai55ZWFyID0gY3VycmVudERhdGUuZm9ybWF0KCdZWVlZJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICAgIGRhdGVQYXJ0T2JqLm1vbnRoID0gJzAxJztcbiAgICAgICAgY2FzZSAnbW9udGgteWVhcic6XG4gICAgICAgICAgZGF0ZVBhcnRPYmouZGF0ZSA9ICcwMSc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICBkYXRlUGFydE9iai55ZWFyID0gY3VycmVudERhdGUuZm9ybWF0KCdZWVlZJyk7XG4gICAgICAgICAgZGF0ZVBhcnRPYmouZGF0ZSA9ICcwMSc7XG4gICAgICB9XG4gICAgICBjbGVhbkRhdGVTdHIgPSB0aGlzLmRhdGVCdWlsZGVyKGRhdGVQYXJ0T2JqKTtcbiAgICB9XG4gICAgcGFyc2VkRGF0ZSA9IG1vbWVudChjbGVhbkRhdGVTdHIpLnRvRGF0ZSgpO1xuICAgIHJldHVybiBwYXJzZWREYXRlO1xuICB9XG5cbiAgZGF0ZUJ1aWxkZXIoZGF0ZVBhcnRPYmo6IGFueSk6IHN0cmluZyB7XG4gICAgbGV0IGRhdGVTdHIgPSAnJztcbiAgICBkYXRlU3RyID0gYCR7ZGF0ZVBhcnRPYmoueWVhcn0tJHtkYXRlUGFydE9iai5tb250aH0tJHtkYXRlUGFydE9iai5kYXRlfWA7XG4gICAgcmV0dXJuIGRhdGVTdHI7XG4gIH1cblxuICAvKipcbiAgICogXG4gICAqIEBwYXJhbSBkYXRlUGFydCBJbmNvbXBsZXRlIGRhdGUgcGFydCBlZywgJzIxc3QnIGlzIHRoZSBkYXRlIHBhcnQgZm9yIHRoZSBkYXRlICcyMXN0IEp1bHkgMjAyMCdcbiAgICogQHBhcmFtIGRhdGVQYXJ0T2JqIC8vIEluaGVyaXRlZCBmcm9tIGNhbGxlciAmIHVwZGF0ZWQgd2l0aCBwYXJzZWQgb2JqZWN0LiBDYW4gYmUgeWVhciwgbW9udGggb3IgZGF0ZVxuICAgKi9cbiAgcGFyc2VEYXRlUGFydChkYXRlUGFydDogc3RyaW5nLCBkYXRlUGFydE9iajogYW55KTogYW55IHtcbiAgICBpZiAodGhpcy5pc1llYXJUeXBlKGRhdGVQYXJ0KSkge1xuICAgICAgY29uc3QgeWVhciA9IHRoaXMud29yZHNUb051bWJlcihkYXRlUGFydCk7XG4gICAgICBkYXRlUGFydE9iai55ZWFyID0geWVhcjtcbiAgICB9IGVsc2UgaWYgKHRoaXMuaXNEYXRlVHlwZShkYXRlUGFydCkpIHtcbiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLndvcmRzVG9OdW1iZXIoZGF0ZVBhcnQpO1xuICAgICAgZGF0ZVBhcnRPYmouZGF0ZSA9IGRhdGU7XG4gICAgfSBlbHNlIGlmICh0aGlzLmlzTW9udGhUeXBlKGRhdGVQYXJ0KSkge1xuICAgICAgY29uc3QgbW9udGggPSBNT05USFMuaW5kZXhPZihkYXRlUGFydC50b1VwcGVyQ2FzZSgpKSArIDE7XG4gICAgICBkYXRlUGFydE9iai5tb250aCA9IG1vbnRoIDwgMTAgPyAnMCcgKyBtb250aCA6IG1vbnRoO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZVBhcnRPYmo7XG4gIH1cblxuICBpc0RhdGVUeXBlKGRhdGVQYXJ0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBsZXQgaXNEYXRlUGFydCA9IGZhbHNlO1xuICAgIGlzRGF0ZVBhcnQgPSAoL1xcZC8udGVzdChkYXRlUGFydCkgJiYgU1VGRklYRVMuaW5jbHVkZXMoZGF0ZVBhcnQuc3Vic3RyKCBkYXRlUGFydC5sZW5ndGggLSAyKSkpO1xuXG4gICAgaWYgKCFpc0RhdGVQYXJ0KSB7XG4gICAgICBjb25zdCBudW1iZXIgPSB0aGlzLndvcmRzVG9OdW1iZXIoZGF0ZVBhcnQpO1xuICAgICAgaWYgKG51bWJlciA+IDAgJiYgbnVtYmVyIDw9IDMxKSB7XG4gICAgICAgIGlzRGF0ZVBhcnQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaXNEYXRlUGFydDtcbiAgfVxuXG4gIHBhcnNlRGF0ZVZhbChkYXRlUGFydCwgZGF0ZVBhcnRPYmopIHtcbiAgICBsZXQgaXNEYXRlUGFydCA9IGZhbHNlO1xuICAgIGxldCBjb252ZXJ0ZWROdW0gPSAwO1xuICAgIGlzRGF0ZVBhcnQgPSBTVUZGSVhFUy5zb21lKChrZXkpID0+IHtcbiAgICAgIHJldHVybiBkYXRlUGFydC5pbmNsdWRlcyhrZXkpO1xuICAgIH0pO1xuXG4gICAgaWYgKCFpc0RhdGVQYXJ0KSB7XG4gICAgICBjb252ZXJ0ZWROdW0gPSB0aGlzLndvcmRzVG9OdW1iZXIoZGF0ZVBhcnQpO1xuICAgICAgaWYgKGNvbnZlcnRlZE51bSA+IDAgJiYgY29udmVydGVkTnVtIDw9IDMxKSB7XG4gICAgICAgIGlzRGF0ZVBhcnQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpc0RhdGVQYXJ0KSB7XG4gICAgICBkYXRlUGFydE9iai5kYXRlID0gY29udmVydGVkTnVtO1xuICAgIH1cbiAgfVxuXG4gIGlzTW9udGhUeXBlKGRhdGVQYXJ0KSB7XG4gICAgY29uc3QgbW9udGggPSBNT05USFMuaW5kZXhPZihkYXRlUGFydC50b1VwcGVyQ2FzZSgpKTtcbiAgICByZXR1cm4gbW9udGggPiAtMTtcbiAgfVxuXG4gIHBhcnNlTW9udGhWYWwoZGF0ZVBhcnQsIGRhdGVQYXJ0T2JqKSB7XG4gICAgY29uc3QgbW9udGggPSBNT05USFMuaW5kZXhPZihkYXRlUGFydC50b1VwcGVyQ2FzZSgpKTtcbiAgICBpZiAobW9udGggPiAtMSkge1xuICAgICAgZGF0ZVBhcnRPYmoubW9udGggPSBtb250aCA8IDEwID8gJzAnICsgbW9udGggOiBtb250aDtcbiAgICB9XG4gIH1cblxuICBpc1llYXJUeXBlKGRhdGVQYXJ0KSB7XG4gICAgbGV0IHllYXIgPSB0aGlzLndvcmRzVG9OdW1iZXIoZGF0ZVBhcnQpO1xuICAgIHJldHVybiB5ZWFyID4gMTAwMDtcbiAgfVxuXG4gIHBhcnNlWWVhclZhbChkYXRlUGFydCwgZGF0ZVBhcnRPYmopIHtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy53b3Jkc1RvTnVtYmVyKGRhdGVQYXJ0KTtcbiAgICBpZiAoeWVhciA+IDEwMDApIHtcbiAgICAgIGRhdGVQYXJ0T2JqLnllYXIgPSB5ZWFyO1xuICAgIH1cbiAgfVxuXG4gIHdvcmRzVG9OdW1iZXIod29yZCkge1xuICAgIFxuICAgIC8vIFJldHVybmluZyBpbnRlZ2VyIGlmIGl0IGlzIG5vdCBhY3R1YWwgd29yZFxuICAgIGlmICghTnVtYmVyLmlzTmFOKHBhcnNlSW50KHdvcmQpKSkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHdvcmQpO1xuICAgIH1cblxuICAgIHdvcmQgPSB3b3JkLnJlcGxhY2UoL2FuZC9nLCAnJyk7IC8vIFJlcGxhY2Ugam9pbmVyc1xuICAgIGxldCB3b3JkcyA9IHdvcmQudG9Mb3dlckNhc2UoKS50cmltKCkuc3BsaXQoJyAnKTtcbiAgICBsZXQgbnVtID0gMDtcbiAgICBsZXQgbnVtU3RyID0gJyc7XG4gICAgbGV0IHRlbnMgPSAwO1xuICAgIFxuICAgIHdvcmRzID0gdGhpcy5wYXJzZUNvbGxvcXVpYWxXb3Jkcyh3b3Jkcyk7XG4gICAgIFxuICAgIHdvcmRzLmZvckVhY2god29yZFN0ciA9PiB7XG4gICAgICB3b3JkU3RyID0gdGhpcy5lbGltaW5hdGVTdHJpbmcod29yZFN0cik7XG4gICAgICBpZiAodHlwZW9mIHdvcmRTdHIgPT0gJ251bWJlcicpIHtcbiAgICAgICAgbnVtID0gd29yZFN0cjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChVTklUW3dvcmRTdHJdKSB7XG4gICAgICAgICAgbnVtID0gbnVtICsgIE5VTUJFUlt3b3JkU3RyXTtcbiAgICAgICAgfSBlbHNlIGlmIChURU5bd29yZFN0cl0pIHtcbiAgICAgICAgICBudW0gPSBudW0gKyBURU5bd29yZFN0cl07XG4gICAgICAgIH0gZWxzZSBpZiAoTUFHTklUVURFW3dvcmRTdHJdKSB7IFxuICAgICAgICAgIG51bSA9IG51bSAqIE1BR05JVFVERVt3b3JkU3RyXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfSk7XG4gICAgcmV0dXJuIG51bTtcbiAgfVxuXG4gIHBhcnNlQ29sbG9xdWlhbFdvcmRzKHdvcmRzQXJyKSB7XG4gICAgaWYgKHdvcmRzQXJyLmxlbmd0aCA9PSAyKSB7XG4gICAgICBpZiAoVEVOW3dvcmRzQXJyWzBdXSAmJiAoVEVOW3dvcmRzQXJyWzFdXSB8fCBUV09TW3dvcmRzQXJyWzFdXSkpIHtcbiAgICAgICAgd29yZHNBcnIuc3BsaWNlKDEsIDAsICdodW5kcmVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChNQUdOSVRVREVbd29yZHNBcnJbMF1dKSB7XG4gICAgICB3b3Jkc0Fyci5zcGxpY2UoMCwgMCwgJ29uZScpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gd29yZHNBcnI7XG4gIH1cblxuICBlbGltaW5hdGVTdHJpbmcod29yZCkge1xuICAgIGlmICgvXFxkLy50ZXN0KHdvcmQpICYmIFNVRkZJWEVTLmluY2x1ZGVzKHdvcmQuc3Vic3RyKCB3b3JkLmxlbmd0aCAtIDIpKSkge1xuICAgICAgd29yZCA9IHdvcmQuc3Vic3RyKDAsIHdvcmQubGVuZ3RoIC0gMik7IC8vIFJlbW92ZSBsYXN0IHN1ZmZpeGVzIHN1Y2ggYXMgJ3N0JywgJ3RoJyBmcm9tIDFzdCwgMTB0aFxuICAgICAgd29yZCA9IHBhcnNlSW50KHdvcmQpO1xuICAgIH1cbiAgICByZXR1cm4gd29yZDtcbiAgfVxufVxuIl19