UNPKG

cie-calculator-flap

Version:

Easily generate CIE References

3,794 lines 308 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.CIECalculator = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg00 = function() {};

Alg00.prototype = new CIEStrategy();
Alg00.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    var acc = 0;
    var tmpInput = input.reference.split("").reverse().join("")
    for(var i = 0; i < input.reference.length; i++) {
      acc += cieUtils.sequentialAdd( parseInt(tmpInput[i],10) * ( ( (i+1)%2 !== 0 ) ? 2 : 1) );
    }

    return input.reference + (cieUtils.nearestMultipleOf(acc,10) - acc)%10;
  }
};

module.exports.Alg00 = Alg00;

},{"./cie_strategy.js":25,"./cie_utils.js":26}],2:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg02 = function() {};

Alg02.prototype = new CIEStrategy();
Alg02.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 6,max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var acc = 0;
    var reference = parseInput(input).reverse();

    //console.log('---------');
    //console.log('\Referencia:',input.reference);
    //console.log('\Referencia Numerica:',reference.join(''));
    for(var i = 0; i < reference.length; i++) {
      var m = ( ( (i+1)%2 !== 0 ) ? 2 : 1);
      //console.log(reference[i] + ' * ' + m + ' = ' + (parseInt(reference[i],10) * m) + '\tReduccion : ' + cieUtils.sequentialAdd( parseInt(reference[i],10) * m ));
      acc += cieUtils.sequentialAdd( parseInt(reference[i],10) * m );
    }
    //console.log('Suma:',acc);
    //console.log('Multiplo 10:',cieUtils.nearestMultipleOf(acc,10));
    //console.log('Digito:',(cieUtils.nearestMultipleOf(acc,10) - acc));
    //console.log('Referencia Completa:',input.reference.toUpperCase() + (cieUtils.nearestMultipleOf(acc,10) - acc));

    return input.reference.toUpperCase() + (cieUtils.nearestMultipleOf(acc,10) - acc);
  }
};

module.exports.Alg02 = Alg02;

var parseInput = function(input) {
  var charToNum = {
    A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, I: 9, J: 1, K: 2, L: 3,
    M: 4, N: 5, O: 6, P: 7, Q: 8, R: 9, S: 1, T: 2, U: 3, V: 4, W: 5, X: 6,
    Y: 7, Z: 8, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 0: 0
  };
  return cieUtils.replaceCharWithNum(input.reference.toUpperCase(), charToNum);
};

},{"./cie_strategy.js":25,"./cie_utils.js":26}],3:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg03 = function() {};

Alg03.prototype = new CIEStrategy();
Alg03.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var acc = 0;
    var reference = parseInput(input);
    for(var i = 0; i < reference.length; i++) {
      acc += parseInt(reference[i],10) * (i + 2);
    }
    return input.reference + (7-(acc % 7));
  }
};

module.exports.Alg03 = Alg03;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  return _.last(input.reference,6).reverse();
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],4:[function(require,module,exports){

'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg04 = function() {};

Alg04.prototype = new CIEStrategy();
Alg04.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 18}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var reference =  parseInput(input);
    var acc = cieUtils.weightedReduce(reference, [11,13,17,19,23]) - reference[0]*11;
    return input.reference + cieUtils.pad(((acc + 330)%97)+1,2);
  }
};

module.exports.Alg04 = Alg04;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  return _.toArray(input.reference).reverse();
};


},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],5:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg06 = function() {};

Alg06.prototype = new CIEStrategy();
Alg06.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 18}},
      branch: {length: {min: 1,max: 8}},
      account: {length: {min: 1,max: 8}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var reference = parseInput(input);
    var acc = cieUtils.weightedReduce(reference,[37,31,29,23,19,17,13,11]);

    return input.reference + (99 - (acc % 97));
  }
};

module.exports.Alg06 = Alg06;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  var paddedBranch = _.toArray(cieUtils.pad(input.branch,8));
  var paddedAccount= _.toArray(cieUtils.pad(input.account,8));
  var paddedReference= _.last(cieUtils.pad(input.reference,8), 8);
  return paddedBranch.concat(paddedAccount, paddedReference).reverse();
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],6:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg10 = function() {};

Alg10.prototype = new CIEStrategy();
Alg10.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 12}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var condensedInput = parseInput(input);
    var acc = cieUtils.weightedReduce(condensedInput.reference,[11,13,17,19,23]);

    return input.reference + condensedInput.date + condensedInput.amount + '2' + cieUtils.pad(((acc%97)+1),2);
  }
};

module.exports.Alg10 = Alg10;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  var paddedDate = cieUtils.pad((input.date.substr(4,4)-2014)*372 + (input.date.substr(2,2)-1)*31 + (input.date.substr(0,2)-1),4);
  var paddedAmount = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[7,3,1])%10;

  return {
    reference: _.toArray(input.reference + paddedDate + paddedAmount + '2').reverse(),
    amount: paddedAmount,
    date: paddedDate
  };
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],7:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg11 = function() {};

Alg11.prototype = new CIEStrategy();
Alg11.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 12}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    /*var acc = 0;
    var tmpInput = input.reference.split("").reverse().join("")
    for(var i = 0; i < input.reference.length; i++) {
      acc += cieUtils.sequentialAdd( parseInt(tmpInput[i],10) * ( ( (i+1)%2 !== 0 ) ? 2 : 1) );
    }*/

    //return input.reference + (cieUtils.nearestMultipleOf(acc,10) - acc)%10;
    return checkDigits(input.reference, input.date, input.amount);
  }
};

module.exports.Alg11 = Alg11;

function checkDigits(Fpositions,Edate,APay){

  /*let A=1,J=1;
  let B=2,K=2,S=2;
  let C=3,L=3,T=3;
  let D=4,M=4,U=4;
  let E=5,N=5,V=5;
  let F=6,O=6,W=6;
  let G=7,P=7,X=7;
  let H=8,Q=8,Y=8;
  let I=9,R=9,Z=9;*/

  let charToNum ={
    A:1,J:1,
    B:2,K:2,S:2,
    C:3,L:3,T:3,
    D:4,M:4,U:4,
    E:5,N:5,V:5,
    F:6,O:6,W:6,
    G:7,P:7,X:7,
    H:8,Q:8,Y:8,
    I:9,R:9,Z:9
  };

  let date = Edate;
  let dateBase = 2014;
  let dFormat = date;//.replace(/-/g, "");

  //Date

  let day = dFormat.substr(0,2);
  let month = dFormat.substr(2,2);
  let year = dFormat.substr(-4);

  let d = parseInt(day);
  let m = parseInt(month);
  let y = parseInt(year);

  let rYear  = (y - dateBase) * 372;
  let rMonth = (m - 1) * 31;
  let rDay   = (d - 1);

  let dateConden = (rYear+rMonth+rDay);

  // importe

  let VP = [7,3,1];
  let rVp = [];
  let iVP = 0;
  let imp = APay;
  let impFormat1 = imp.replace(/\./g, '');
  let impFormat  = impFormat1.replace(/,/g, '');
  let iCad = impFormat.length-1;

  for(let cont=0; cont<=impFormat.length; cont++){
    if(iVP === VP.length){
      iVP = 0;
    }else{
      let valorC = impFormat.charAt(iCad);
      let oVp = VP[iVP];
      console.log(valorC);
      let op = parseInt(valorC) * oVp;
      rVp.unshift(op);
      iCad--;
      iVP++;
    }
  }

  let sum = rVp.reduce((a, b) => a + b, 0);
  let cDigit = (sum % 10);

  //let random = Math.round(Math.random()*9);
  let random = 2;//Math.round(Math.random()*9);

  let result = Fpositions+dateConden+cDigit+random;

  //Referencia

  let refVP = [11,13,17,19,23];
  let rFVP = [];
  let irVP = 0;
  let iCadRef = result.length-1;

  for(let aux=0; aux<=result.length+2; aux++){
    if(irVP === refVP.length){
      irVP = 0;
    }else{
      let valorC = result.charAt(iCadRef);
      let oVp = refVP[irVP];
      let op = (charToNum[valorC]?charToNum[valorC]:parseInt(valorC)) * oVp;
      rFVP.unshift(op);
      iCadRef--;
      irVP++;
    }
  }
  let sumRef = rFVP.reduce((a, b) => a + b, 0);
  let refDigit = (sumRef % 97) + 1;
  let dLength = refDigit.toString();
  let dLengthC = dLength.length;

  if( dLengthC === 1){
    let Zero = '0';
    let addZero = Zero+refDigit;
    let finalReference = result+addZero;
    return finalReference;
  }else{
    let finalReference = result+refDigit;
    return finalReference;
  }
//
}

},{"./cie_strategy.js":25,"./cie_utils.js":26}],8:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg14 = function() {};

Alg14.prototype = new CIEStrategy();
Alg14.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 18}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    return mVerificador(input.reference);
  }
};

module.exports.Alg14 = Alg14;

function mVerificador(ref){

  let charToNum = {
    A:1,J:1,
    B:2,K:2,S:2,
    C:3,L:3,T:3,
    D:4,M:4,U:4,
    E:5,N:5,V:5,
    F:6,O:6,W:6,
    G:7,P:7,X:7,
    H:8,Q:8,Y:8,
    I:9,R:9,Z:9
  };

  let valoresPonderadores = [13,17,19,23,11];
  let valores = [];
  //let cadena = '000SAR4280';
  let indice = ref.length-2;
  let indiceVP = 0;


  for(let contador=0; contador<ref.length-1; contador++){
    if(indiceVP === valoresPonderadores.length){
      indiceVP = 0;
    }
      let valorC = ref.charAt(indice);
      let vp = valoresPonderadores[indiceVP];
      let op = (charToNum[valorC]?charToNum[valorC]:parseInt(valorC)) * vp;
      valores.unshift(op);
      indice--;
      indiceVP++;
  }
  let suma = valores.reduce((a, b) => a + b, 0);
  let sumaTotal = suma + 330;
  let residuo = (sumaTotal % 97);
  let dVerificador = (residuo+1);
  let vCadena = dVerificador.toString();
  let referencia = ref+vCadena;
  return referencia;
}

},{"./cie_strategy.js":25,"./cie_utils.js":26}],9:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg21 = function() {};

Alg21.prototype = new CIEStrategy();
Alg21.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 20}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 15}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var condensedInput = parseInput(input);
    var acc = cieUtils.weightedReduce(_.toArray(condensedInput.reference).reverse(),[11,13,17,19,23]);
    var acc_2 = ((acc % 97)+1)%10;

    return condensedInput.reference + acc_2;
  }
};

module.exports.Alg21 = Alg21;

var isLeap = function(year) {
  console.log('year',year);
  return new Date(year, 1, 29).getDate() === 29;
}
// TODO Maybe move this to a template?
var parseInput = function(input) {
  var month_multiplier = 31;
  switch (input.date.substr(2,2)) {
    case 4:
    case 6:
    case 9:
    case 11:
      month_multiplier = 30;
      break;
    case 2:
      month_multiplier = (isLeap(input.date.substr(4,4)) ? 29 : 28)
      break;
  }
  var paddedDate = cieUtils.pad((input.date.substr(4,4)-2014)*360 + (input.date.substr(2,2)-1)*month_multiplier + (input.date.substr(0,2)-1),4);
  var paddedAmount1 = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[1,2,3,7,11,13,17])%10;
  var paddedAmount2 = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[2,3,7,11,13,17,1])%10;
  var paddedAmount3 = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[3,7,11,13,17,1,2])%10;

  var tmp_reference = input.reference + paddedDate + paddedAmount1 + paddedAmount2 + paddedAmount3;

  return {
    reference: tmp_reference,
    amount: '' + paddedAmount1 + paddedAmount2 + paddedAmount3,
    date: paddedDate
  };
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],10:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg27 = function() {};

Alg27.prototype = new CIEStrategy();
Alg27.prototype = {
  execute: function(input) {

    var validationRules = {
      reference:  {length: {min: 1,  max: 18}},
      account:    {length: {min: 1,   max: 8}},
      branch:     {length: {min: 1,   max: 8}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    return applyAlgorithm27(input.reference, input.branch, input.account);
  }
};

module.exports.Alg27 = Alg27;

let applyAlgorithm27 = (reference, sucursal, account) => {
  let validator = new RegExp(/^[0-9A-Z]{3,20}$/g)

  let referenceEncoder = {
    "A": 2, "B": 2, "C": 2, "D": 3, "E": 3,
    "F": 3, "G": 4, "H": 4, "I": 4, "J": 5,
    "K": 5, "L": 5, "M": 6, "N": 6, "O": 6,
    "P": 7, "Q": 7, "R": 7, "S": 8, "T": 8,
    "U": 8, "V": 9, "W": 9, "X": 9, "Y": 0,
    "Z": 0, "0": 0, "1": 1, "2": 2, "3": 3,
    "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
  };

  let fullReference = "";
  // let sucursal = "7006";
  // let account = "00863367";

  if(validator.test(reference)) {
    for(let letter of reference){
      fullReference += referenceEncoder[letter];
    }

    while(fullReference.length < 18){
      fullReference = `0${fullReference}`;
    }

    fullReference = `${account}${fullReference}`;
    fullReference = `00000${fullReference}`;
    fullReference = `${sucursal}${fullReference}`;

    let serie   = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
    let results = [];
    let serieIndex = 12;

    fullReference = fullReference.split("").reverse().join("");

    for(let number of fullReference) {
      //console.log(`${number} * ${serie[serieIndex]} = ${number * serie[serieIndex]}`);
      results.push(number * serie[serieIndex]);
      serieIndex = (serieIndex !== 0) ? serieIndex - 1 : 12;
    }

    let sum = 0;
    for(let result of results){
      sum += result;
    }

    let res    = sum % 97;
    let digits = 99 - res;

    let getDigits = (number) => {
      return (number.toString().length === 2) ? number : `0${number}`;
    };

    //document.getElementById("response").innerHTML = `${reference}${getDigits(digits)}`;
    return `${reference}${getDigits(digits)}`;
  } else {
    //alert("Input invalid");
    return;
  }
};

},{"./cie_strategy.js":25,"./cie_utils.js":26}],11:[function(require,module,exports){
'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg35 = function() {};

Alg35.prototype = new CIEStrategy();
Alg35.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1, max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var acc = cieUtils.sequentialWeightedReduce(parseInput(input), [4,3,8]);
    return input.reference.toUpperCase() + (cieUtils.nearestMultipleOf(acc,10) - acc)%10;
  }
};

module.exports.Alg35 = Alg35;

var parseInput = function(input) {
  var charToNum = {
    A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, I: 9, J: 10, K: 11, L: 12, M: 13,
    N: 14,O: 15, P: 16, Q: 17, R: 18, S: 19, T: 20, U: 21, V: 22, W: 23, X: 24, Y: 25,
    Z: 26,1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 0: 0
  };
  return cieUtils.replaceCharWithNum(input.reference.toUpperCase(), charToNum);
};


},{"./cie_strategy.js":25,"./cie_utils.js":26}],12:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg36 = function() {};

Alg36.prototype = new CIEStrategy();
Alg36.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1, max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var acc = cieUtils.sequentialWeightedReduce(parseInput(input), [2,1]);
    return input.reference.toUpperCase() + (cieUtils.nearestMultipleOf(acc,10) - acc)%10;
  }
};

module.exports.Alg36 = Alg36;

var parseInput = function(input) {
  var charToNum = {
    A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, I: 9,
    J: 1, K: 2, L: 3, M: 4,N: 5, O: 6, P: 7, Q: 8, R: 9,
    S: 1, T: 2, U: 3, V: 4, W: 5, X: 6, Y: 7,Z: 8,
    1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 0: 0
  };
  return _.toArray(cieUtils.replaceCharWithNum(input.reference.toUpperCase(), charToNum)).reverse();
};


},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],13:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg37 = function() {};

Alg37.prototype = new CIEStrategy();
Alg37.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1, max: 19}}
    };
    if (!cieUtils.validateInput(input, validationRules)) {
      throw new Error('Longitud invalida');
    }

    var reference = parseInput(input);
    var acc = cieUtils.weightedReduce(reference, [11,13,17, 19,23]);

    return input.reference.toUpperCase() + cieUtils.pad(((acc + 330 - reference[0]*11)%97)+1,2);
  }
};

module.exports.Alg37 = Alg37;

var parseInput = function(input) {
  var charToNum = {
    A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, I: 9,
    J: 1, K: 2, L: 3, M: 4,N: 5, O: 6, P: 7, Q: 8, R: 9,
    S: 1, T: 2, U: 3, V: 4, W: 5, X: 6, Y: 7,Z: 8,
    1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 0: 0
  };
  return _.toArray(cieUtils.replaceCharWithNum(input.reference.toUpperCase(), charToNum)).reverse();
};


},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],14:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg45 = function() {};

Alg45.prototype = new CIEStrategy();
Alg45.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 10}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    return applyAlgorithm45(input.date, input.amount, input.reference);
  }
};

module.exports.Alg45 = Alg45;

let base36Encoder = {
  0: "0", 1: "1", 2: "2", 3: "3", 4: "4",
  5: "5", 6: "6", 7: "7", 8: "8", 9: "9",
  10: "A", 11: "B", 12: "C", 13: "D", 14: "E",
  15: "F", 16: "G", 17: "H", 18: "I", 19: "J",
  20: "K", 21: "L", 22: "M", 23: "N", 24: "O",
  25: "P", 26: "Q", 27: "R", 28: "S", 29: "T",
  30: "U", 31: "V", 32: "W", 33: "X", 34: "Y", 35: "Z",
}

let referenceEncoder = {
  "A": 1, "B": 2, "C": 3, "D": 4, "E": 5,
  "F": 6, "G": 7, "H": 8, "I": 9, "J": 1,
  "K": 2, "L": 3, "M": 4, "N": 5, "O": 6,
  "P": 7, "Q": 8, "R": 9, "S": 1, "T": 2,
  "U": 3, "V": 4, "W": 5, "X": 6, "Y": 7,
  "Z": 8, "0": 0, "1": 1, "2": 2, "3": 3,
  "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
}

function generateRemainingList(number) {
  let remainingList = [];
  let quotient      = number;

  while(Math.trunc(quotient) != 0) {
    remainingList.push(quotient % 36);
    quotient = Math.trunc(quotient / 36);
  }

  return remainingList;
}

function generateCode(remainingList) {
  let code = "";
  for(let number of remainingList)
    code += base36Encoder[number];

  return code;
}

function addZeros(number, limit) {
  while(number.length < limit) {
    number = `0${number}`;
  }
  return number;
}

/*function isValid () {
  let dateValidator      = new RegExp(/^[0-9]{8}$/)
  let amountValidator    = new RegExp(/^[0-9]+.[0-9]{2}$/)
  let referenceValidator = new RegExp(/^[0-9A-Z]{10,20}$/g)

  if (dateValidator.test(document.getElementById('date').value),
      amountValidator.test(document.getElementById('amount').value),
      referenceValidator.test(document.getElementById('reference').value)) {
    applyAlgorithm45(document.getElementById('date').value, document.getElementById('amount').value, document.getElementById('reference').value)
  } else {
    alert("invalid")
  }
}*/

//document.getElementById("btn").addEventListener("click", isValid);

function applyAlgorithm45(date, amount, reference) {
  console.log(date, amount, reference)
  reference = reference.toUpperCase();
  
  let dateCode = generateCode(generateRemainingList(`${date.substring(0, 4)}${date.substring(date.length-2, date.length)}`));
  let reverseDateCode = (dateCode.length < 4) ? addZeros(dateCode.split("").reverse().join(""), 4) : dateCode.split("").reverse().join("");

  ///////////////

  let fullAmount = null;
  if(amount.includes('.'))
    fullAmount = amount.split('.').join("");
  else
    fullAmount = amount;

  let amountCode = generateCode(generateRemainingList(fullAmount));

  let reverseAmountCode = (amountCode.length < 4) ? addZeros(amountCode.split("").reverse().join(""), 5) : amountCode.split("").reverse().join("");

  ///////////////

  let fullReference = `${reference}${reverseDateCode}${reverseAmountCode}`

  let encodedReference = "";
  for(let item of fullReference)
    encodedReference += referenceEncoder[item];

  let serie   = [1, 2];
  let results = [];
  let serieIndex = 1;

  for(let number of encodedReference.split("").reverse().join("")) {
    results.push(new String(number * serie[serieIndex]))
    serieIndex = (serieIndex != 0) ? serieIndex - 1 : 1;
  }

  let singleNumbers = [];
  for(let number of results) {
    if(number.length > 1)
      singleNumbers.push(number.split("").reduce((previous, current) => { return (new Number(previous) + new Number(current)) }, 0))
    else
      singleNumbers.push(new Number(number));
  }

  let sum = singleNumbers.reduce((previous, current) => { return previous + current }, 0);

  let digit = (10 - new Number( (new String(sum % 10).length > 1) ? new String(sum % 10).split("").reverse().join("")[0] : sum % 10) );

  if(digit === 10)
    digit = 0;

  console.log(fullReference, digit)
  //document.getElementById("response").innerHTML = `${fullReference}${digit}`;
  return `${fullReference}${digit}`;
}

},{"./cie_strategy.js":25,"./cie_utils.js":26}],15:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg62 = function() {};

Alg62.prototype = new CIEStrategy();
Alg62.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 10}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var condensedInput = parseInput(input);

    return input.reference + condensedInput.date + condensedInput.amount + '2';
  }
};

module.exports.Alg62 = Alg62;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  var paddedDate = cieUtils.pad((input.date.substr(4,4)-1988)*372 + (input.date.substr(2,2)-1)*31 + (input.date.substr(0,2)-1),4);
  var expandedAmount = fooAmount(_.without(_.toArray(input.amount),'.'));
  var reducedAmount = weightedReduceWithMult(_.toArray(expandedAmount).reverse(),[7,3,1]);

  return {
    reference: _.toArray(input.reference + paddedDate + reducedAmount + '2').reverse(),
    amount: reducedAmount,
    date: paddedDate
  };
};

var fooAmount = function(amount) {
  return _.reduce(amount, function(memo, num) {
    var x = (memo.length < 8) ? (num + (parseInt(num)+1)) + '' : num;
    return memo + x;
  },'')
};

var weightedReduceWithMult = function(input, weights, debug) {
  var acc = 0;
  var acc2 = '';
  for (var i = 0; i < input.length; i++) {
    if (debug)
      {
        console.log('input: ' + input[i] + ' w: ' + weights[i%weights.length] + ' = ' + parseInt(input[i] * weights[i%weights.length]));
      }
      acc += parseInt(input[i] * weights[i%weights.length]);
      acc = cieUtils.sequentialAdd(acc);
      if (parseInt(i) % 3 == 2) {
        acc2 += acc % 10;
      }
  }
  return acc2;
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],16:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg72 = function() {};

Alg72.prototype = new CIEStrategy();
Alg72.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 40}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }

    return algorithm72(input.reference, input.date, input.amount);
  }
};

module.exports.Alg72 = Alg72;

/*************************************************************************
 ****************************** Algorithm 72 ******************************
 **************************************************************************/

/**
 * Add check digits to create a final reference
 * @param {string} reference
 * @param {string} expirationDate
 * @param {string} amount
 * @returns {string} finalReference
 */
function algorithm72(reference, expirationDate, amount) {

  var condensedDateCheckDigit = processExpirationDate(expirationDate);

  var amountCheckDigit = processAmount(amount);

  var referenceCheckDigit = processReference(reference, condensedDateCheckDigit, amountCheckDigit);

  console.log('condensedDateCheckDigit: ', condensedDateCheckDigit, 'amountCheckDigit: ', amountCheckDigit, 'referenceCheckDigit: ', referenceCheckDigit);

  var finalReference = reference + condensedDateCheckDigit + amountCheckDigit + referenceCheckDigit;

  console.log('finalReference: ', finalReference);

  return finalReference;
}

function processExpirationDate(expirationDate){
  var day = expirationDate.substring(0,2);
  var month = expirationDate.substring(2,4);
  var year = expirationDate.substring(6,8);

  var dateInt = parseInt(day + '' + month + '' + year);
  var  remainderArray = new Array();
  var quotientBoolean= true;

  do {
    var quotient = Math.floor(dateInt / 36);
    var remainder = dateInt % 36;

    remainderArray.push(remainder);
    dateInt = quotient;

    if(quotient == 0)
      quotientBoolean = false;

  } while (quotientBoolean);

  var checkDigit = '';
  for (var i = remainderArray.length - 1; i > -1; i--) {
    checkDigit += remainderMap.get(remainderArray[i]);
  }

  if(checkDigit.length < 4){
    do{
      checkDigit = '0' + checkDigit;
    }while(checkDigit.length < 4);
  }

  return checkDigit;
}

function processAmount(amountStr){
  var amount = parseInt(amountStr.replace('.', ''));

  var  remainderArray = new Array();
  var quotientBoolean= true;

  do {
    var quotient = Math.floor(amount / 36);
    var remainder = amount % 36;

    remainderArray.push(remainder);
    amount = quotient;

    if(quotient == 0)
      quotientBoolean = false;

  } while (quotientBoolean);

  var checkDigit = '';
  for (var i = remainderArray.length - 1; i > -1; i--) {
    checkDigit += remainderMap.get(remainderArray[i]);
  }

  if(checkDigit.length < 5){
    do{
      checkDigit = '0' + checkDigit;
    }while(checkDigit.length < 5);
  }

  return checkDigit;
}

function processReference(reference, expirationDate, amount){
  var fullReference = reference + expirationDate + amount;
  var resultReference = '';

  for(var i = 0; i < fullReference.length; i++){
    if(!isNumeric(fullReference[i]))
      resultReference += referenceMap.get(fullReference[i]);
    else
      resultReference += fullReference[i];
  }

  var multiplier = 2;
  var digits = new Array();
  var multiplierBoolean = true;

  for (var i = resultReference.length - 1; i > -1; i--) {
    var digit = resultReference[i] * multiplier;

    if (digit > 9) {
      var subDigits = digit.toString().split('');

      digit = 0;

      subDigits.forEach(function (number) {
        digit += parseInt(number);
      });
    }

    digits.push(digit);

    multiplier = multiplierBoolean ? 1 : 2;

    multiplierBoolean = !multiplierBoolean;
  }

  var sum = 0;

  digits.forEach(function (number) {
    sum += parseInt(number);
  });

  var remainder = sum % 10;

  var checkDigit = (remainder != 0) ? (10 - remainder) : remainder;

  return checkDigit;
}

/*************************************************************************
 ********************************* Utils **********************************
 **************************************************************************/

function isNumeric(value) {
  return /^-?\d+$/.test(value);
}

const remainderMap = new Map([
  [0, '0'],
  [1, '1'],
  [2, '2'],
  [3, '3'],
  [4, '4'],
  [5, '5'],
  [6, '6'],
  [7, '7'],
  [8, '8'],
  [9, '9'],
  [10, 'A'],
  [11, 'B'],
  [12, 'C'],
  [13, 'D'],
  [14, 'E'],
  [15, 'F'],
  [16, 'G'],
  [17, 'H'],
  [18, 'I'],
  [19, 'J'],
  [20, 'K'],
  [21, 'L'],
  [22, 'M'],
  [23, 'N'],
  [24, 'O'],
  [25, 'P'],
  [26, 'Q'],
  [27, 'R'],
  [28, 'S'],
  [29, 'T'],
  [30, 'U'],
  [31, 'V'],
  [32, 'W'],
  [33, 'X'],
  [34, 'Y'],
  [35, 'Z']
]);

const referenceMap = new Map([
  ['A', 1],
  ['B', 2],
  ['C', 3],
  ['D', 4],
  ['E', 5],
  ['F', 6],
  ['G', 7],
  ['H', 8],
  ['I', 9],
  ['J', 1],
  ['K', 2],
  ['L', 3],
  ['M', 4],
  ['N', 5],
  ['O', 6],
  ['P', 7],
  ['Q', 8],
  ['R', 9],
  ['S', 1],
  ['T', 2],
  ['U', 3],
  ['V', 4],
  ['W', 5],
  ['X', 6],
  ['Y', 7],
  ['Z', 8]
]);

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],17:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg77 = function() {};

Alg77.prototype = new CIEStrategy();
Alg77.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 1,max: 12}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var condensedInput = parseInput(input);
    var acc = cieUtils.weightedReduce(condensedInput.reference,[11,13,17,19,23]);

    return input.reference + condensedInput.date + condensedInput.amount + '2' + cieUtils.pad(((acc%97)+1),2);
  }
};

module.exports.Alg77 = Alg77;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  var paddedDate = cieUtils.pad((input.date.substr(4,4)-2013)*372 + (input.date.substr(2,2)-1)*31 + (input.date.substr(0,2)-1),4);
  var paddedAmount = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[7,3,1])%10;

  return {
    reference: _.toArray(input.reference + paddedDate + paddedAmount + '2').reverse(),
    amount: paddedAmount,
    date: paddedDate
  };
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],18:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg80 = function() {};

Alg80.prototype = new CIEStrategy();
Alg80.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 21,max: 49}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    return algorithm80(input.reference);
  }
};

module.exports.Alg80 = Alg80;


/*************************************************************************
 ****************************** Algorithm 80 ******************************
 **************************************************************************/

/**
 * Add a check digit to the reference
 * @param {string} reference
 * @returns {number} resultReference
 */
function algorithm80(reference) {

  if(!isNumeric(reference)){
    console.error('La referencia debe ser Númerica');
    return;
  }

  var multiplier = 2;
  var digits = new Array();
  var multiplierBoolean = true;

  for (var i = reference.length - 1; i > -1; i--) {
    var digit = reference[i] * multiplier;

    if (digit > 9) {
      var subDigits = digit.toString().split('');

      digit = 0;

      subDigits.forEach(function (number) {
        digit += parseInt(number);
      });
    }

    digits.push(digit);

    multiplier = multiplierBoolean ? 1 : 2;

    multiplierBoolean = !multiplierBoolean;
  }

  var sum = 0;

  digits.forEach(function (number) {
    sum += parseInt(number);
  });

  var remainder = sum % 10;

  var checkDigit = (remainder != 0) ? (10 - remainder) : remainder;
  console.log('checkDigit: ', checkDigit);

  var resultReference = reference + checkDigit;
  console.log('resultReference: ', resultReference);

  if (resultReference.length < 21)
    console.warn('La longitud mínima de la referencia resultante deber ser de 21');

  if (resultReference.length > 50)
    console.warn('La longitud máxima de la referencia resultante deber ser de 50');

  return resultReference;
}

function processExpirationDate(expirationDate){
  var day = expirationDate.substring(0,2);
  var month = expirationDate.substring(2,4);
  var year = expirationDate.substring(6,8);

  var dateInt = parseInt(day + '' + month + '' + year);
  var  remainderArray = new Array();
  var quotientBoolean= true;

  do {
    var quotient = Math.floor(dateInt / 36);
    var remainder = dateInt % 36;

    remainderArray.push(remainder);
    dateInt = quotient;

    if(quotient == 0)
      quotientBoolean = false;

  } while (quotientBoolean);

  var checkDigit = '';
  for (var i = remainderArray.length - 1; i > -1; i--) {
    checkDigit += remainderMap.get(remainderArray[i]);
  }

  if(checkDigit.length < 4){
    do{
      checkDigit = '0' + checkDigit;
    }while(checkDigit.length < 4);
  }

  return checkDigit;
}

function processAmount(amountStr){
  var amount = parseInt(amountStr.replace('.', ''));

  var  remainderArray = new Array();
  var quotientBoolean= true;

  do {
    var quotient = Math.floor(amount / 36);
    var remainder = amount % 36;

    remainderArray.push(remainder);
    amount = quotient;

    if(quotient == 0)
      quotientBoolean = false;

  } while (quotientBoolean);

  var checkDigit = '';
  for (var i = remainderArray.length - 1; i > -1; i--) {
    checkDigit += remainderMap.get(remainderArray[i]);
  }

  if(checkDigit.length < 5){
    do{
      checkDigit = '0' + checkDigit;
    }while(checkDigit.length < 5);
  }

  return checkDigit;
}

function processReference(reference, expirationDate, amount){
  var fullReference = reference + expirationDate + amount;
  var resultReference = '';

  for(var i = 0; i < fullReference.length; i++){
    if(!isNumeric(fullReference[i]))
      resultReference += referenceMap.get(fullReference[i]);
    else
      resultReference += fullReference[i];
  }

  var multiplier = 2;
  var digits = new Array();
  var multiplierBoolean = true;

  for (var i = resultReference.length - 1; i > -1; i--) {
    var digit = resultReference[i] * multiplier;

    if (digit > 9) {
      var subDigits = digit.toString().split('');

      digit = 0;

      subDigits.forEach(function (number) {
        digit += parseInt(number);
      });
    }

    digits.push(digit);

    multiplier = multiplierBoolean ? 1 : 2;

    multiplierBoolean = !multiplierBoolean;
  }

  var sum = 0;

  digits.forEach(function (number) {
    sum += parseInt(number);
  });

  var remainder = sum % 10;

  var checkDigit = 10 - remainder;

  return checkDigit;
}

/*************************************************************************
 ********************************* Utils **********************************
 **************************************************************************/

function isNumeric(value) {
  return /^-?\d+$/.test(value);
}

const remainderMap = new Map([
  [0, '0'],
  [1, '1'],
  [2, '2'],
  [3, '3'],
  [4, '4'],
  [5, '5'],
  [6, '6'],
  [7, '7'],
  [8, '8'],
  [9, '9'],
  [10, 'A'],
  [11, 'B'],
  [12, 'C'],
  [13, 'D'],
  [14, 'E'],
  [15, 'F'],
  [16, 'G'],
  [17, 'H'],
  [18, 'I'],
  [19, 'J'],
  [20, 'K'],
  [21, 'L'],
  [22, 'M'],
  [23, 'N'],
  [24, 'O'],
  [25, 'P'],
  [26, 'Q'],
  [27, 'R'],
  [28, 'S'],
  [29, 'T'],
  [30, 'U'],
  [31, 'V'],
  [32, 'W'],
  [33, 'X'],
  [34, 'Y'],
  [35, 'Z']
]);

const referenceMap = new Map([
  ['A', 1],
  ['B', 2],
  ['C', 3],
  ['D', 4],
  ['E', 5],
  ['F', 6],
  ['G', 7],
  ['H', 8],
  ['I', 9],
  ['J', 1],
  ['K', 2],
  ['L', 3],
  ['M', 4],
  ['N', 5],
  ['O', 6],
  ['P', 7],
  ['Q', 8],
  ['R', 9],
  ['S', 1],
  ['T', 2],
  ['U', 3],
  ['V', 4],
  ['W', 5],
  ['X', 6],
  ['Y', 7],
  ['Z', 8]
]);

},{"./cie_strategy.js":25,"./cie_utils.js":26}],19:[function(require,module,exports){

'use strict';

var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg81 = function() {};

Alg81.prototype = new CIEStrategy();
Alg81.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 21, max: 49}}
    };

    if (!cieUtils.validateInput(input, validationRules)) {
      var error = new Error('Longitud invalida');
      error.status = '422';
      throw error;
    }

    return alg81(input.reference);
  }
};

module.exports.Alg81 = Alg81;

function alg81(reference){
  var digitVerify = algorithm(reference.toUpperCase());
  var reference81 = reference + digitVerify;
  return reference81;
}

function algorithm(data){
  console.log(data);
  var transformAlphanumeric = replaceAlphanumeric(data);
  console.log(transformAlphanumeric);
  var transformNumeric = buildNumeric(transformAlphanumeric);
  console.log(transformNumeric);
  var transformUnifyInfo = unifyInfo(transformNumeric);
  console.log(transformUnifyInfo);
  var digitVeirfy = "" + searchDigitVerify(transformUnifyInfo);
  return digitVeirfy.charAt(digitVeirfy.length-1);
}

function replaceAlphanumeric(data){
  var mapAlphanumeric = new Map([["A", 1], ["B", 2], ["C", 3], ["D", 4], ["E", 5], ["F", 6], ["G", 7], ["H", 8], ["I", 9], ["J", 1], ["K", 2], ["L", 3], ["M", 4], ["N", 5], ["O", 6], ["P", 7], ["Q", 8], ["R", 9], ["S", 1], ["T", 2], ["U", 3], ["V", 4], ["W", 5], ["X", 6], ["Y", 7], ["Z", 8]]);
  var transform = "";
  for (let characterData of data) {
    var infoCharacter = characterData;
    if(mapAlphanumeric.has(characterData)){
      infoCharacter = mapAlphanumeric.get(characterData);
    }
    transform += infoCharacter;
  }
  return transform;
}

function buildNumeric(data){
  var transform = [data.length];
  var isSecond = true;
  for(var i = data.length-1; i >= 0; i--) {
    var dataNumber = Number(data.charAt(i));
    var numberMultiply = isSecond ? 2 : 1;
    isSecond = isSecond ? false : true;
    transform[i] = (numberMultiply * dataNumber);
  }
  return transform;
}

function unifyInfo(data){
  var transform = [];
  for (let numberData of data) {
    var sumData = 0;
    var infoData = "" + numberData;
    for (let characterData of infoData) {
      sumData += Number(characterData);
    }
    transform.push(sumData);
  }
  return transform;
}

function searchDigitVerify(data){
  var sumData = 0;
  for (let numberData of data) {
    sumData += numberData;
  }

  var numberAux = 10;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;
  return numberAux - residue;
}


},{"./cie_strategy.js":25,"./cie_utils.js":26}],20:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg82 = function() {};

Alg82.prototype = new CIEStrategy();
Alg82.prototype = {
  execute: function(input) {
    var validationRules = {
      reference: {length: {min: 15,max: 42}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}},
      digit: {length: {min: 1,max: 1}}
    };
    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }
    var condensedInput = parseInput(input);
    var acc = cieUtils.weightedReduce(condensedInput.reference,[11,13,17,19,23]);

    return input.reference + condensedInput.date + condensedInput.amount + input.digit + cieUtils.pad(((acc%97)+1),2);
  }
};

module.exports.Alg82 = Alg82;

// TODO Maybe move this to a template?
var parseInput = function(input) {
  var charToNum = {
    A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, I: 9, J: 1, K: 2, L: 3,
    M: 4, N: 5, O: 6, P: 7, Q: 8, R: 9, S: 2, T: 3, U: 4, V: 5, W: 6, X: 7,
    Y: 8, Z: 9, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 0: 0
  };

  var numOnlyReference = cieUtils.replaceCharWithNum(input.reference.toUpperCase(), charToNum).join('');
  var paddedDate = cieUtils.pad((input.date.substr(4,4)-2014)*372 + (input.date.substr(2,2)-1)*31 + (input.date.substr(0,2)-1),4);
  var paddedAmount = cieUtils.weightedReduce(_.without(_.toArray(input.amount),'.').reverse(),[7,3,1])%10;

  return {
    reference: _.toArray(numOnlyReference + paddedDate + paddedAmount + input.digit).reverse(),
    amount: paddedAmount,
    date: paddedDate
  };
};

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],21:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg89 = function() {};

Alg89.prototype = new CIEStrategy();
Alg89.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 42}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }

    return alg89(input.date, input.amount, input.reference);
  }
};

module.exports.Alg89 = Alg89;

var contantLeft = 0;
var yearBase = 2013;
var yearMultiply = 372;
var unitSubtraction = 1;
var monthMultiply = 31;
var digitVerifyConstant = 2;
var mapAlphanumeric = new Map([["A", 2], ["B", 2], ["C", 2], ["D", 3], ["E", 3], ["F", 3], ["G", 4], ["H", 4], ["I", 4], ["J", 5], ["K", 5], ["L", 5], ["M", 6], ["N", 6], ["O", 6], ["P", 7], ["Q", 7], ["R", 7], ["S", 8], ["T", 8], ["U", 8], ["V", 9], ["W", 9], ["X", 9], ["Y", 0], ["Z", 0]]);

function alg89(dateExpired, amount, reference){
  var digitVerifyDate = algorithmDate(dateExpired);

  var amountFormat = convertToPounds(amount);

  var digitVerifyAmount = algorithmAmount(amountFormat);
  console.log(digitVerifyDate);
  console.log(digitVerifyAmount);
  console.log(reference);
  var reference89 = reference + digitVerifyDate + digitVerifyAmount + digitVerifyConstant;
  var digitVerifyReference = algorithmReference(reference89.toUpperCase());
  console.log(digitVerifyReference);
  reference89 = reference89 + digitVerifyReference;
  return reference89;
}

function convertToPounds(str) {	
	var n = Number.parseFloat(str);
  if(!str || isNaN(n) || n < 0) return 0;
  return n.toFixed(2);
}

function algorithmReference(data){
  console.log(data);
  var dataReplace = replaceAlphanumeric(data);
  var isPosition = 1
  var mapMultiply = new Map([[1, 11], [2, 13], [3, 17], [4, 19], [5, 23]]);
  var sumData = 0;
  for(var i = dataReplace.length-1; i >= 0; i--) {
    var dataNumber = Number(dataReplace.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  console.log(sumData);
  var numberAux = 97;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;
  return missingData(2, (residue + 1).toString());
}

function replaceAlphanumeric(data){
  var transform = "";
  for (let characterData of data) {
    var infoCharacter = characterData;
    if(mapAlphanumeric.has(characterData)){
      infoCharacter = mapAlphanumeric.get(characterData);
    }
    transform += infoCharacter;
  }
  return transform;
}

function algorithmAmount(data){
  console.log(data);
  var dataTransform = data.split('.').join("");
  console.log(dataTransform);
  var isPosition = 1
  var mapMultiply = new Map([[1, 7], [2, 3], [3, 1]]);
  //var isThree = true;
  //var isSecond = false;
  var sumData = 0;
  for(var i = dataTransform.length-1; i >= 0; i--) {
    var dataNumber = Number(dataTransform.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  console.log(sumData);
  var numberAux = 10;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;

  return residue.toString().charAt(residue.toString().length-1);
}

function algorithmDate(data){
  console.log(data);
  var dayData = data.substring(0, 2);
  var monthData = data.substring(2, 4);
  var yearData = data.substring(4, 8);

  var yearSubtraction = yearData - yearBase;
  console.log(yearSubtraction);

  var yearresultMultiply = yearSubtraction * yearMultiply;
  console.log(yearresultMultiply);

  var monthResultSubtraction = Number(monthData) - unitSubtraction;
  console.log(monthResultSubtraction);

  var monthResultMultiply = monthResultSubtraction * monthMultiply;
  console.log(monthResultMultiply);

  var dayResultSubtraction = Number(dayData) - unitSubtraction;
  console.log(dayResultSubtraction);

  return missingData(4, yearresultMultiply + monthResultMultiply + dayResultSubtraction);
}

function missingData(minLengthMissing, data){
  var missingLeft = minLengthMissing - data.length;
  for (var i = 0; i < missingLeft; i++) {
    data = contantLeft + data;
  }
  return data;
}

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],22:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg91 = function() {};

Alg91.prototype = new CIEStrategy();
Alg91.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 42}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }

    return alg91(input.date, input.amount, input.reference);
  }
};

module.exports.Alg91 = Alg91;

var contantLeft = 0;
var yearBase = 2013;
var yearMultiply = 372;
var unitSubtraction = 1;
var monthMultiply = 31;
var digitVerifyConstant = 2;
var mapAlphanumeric = new Map([["A", 1], ["B", 2], ["C", 3], ["D", 4], ["E", 5], ["F", 6], ["G", 7], ["H", 8], ["I", 9], ["J", 1], ["K", 2], ["L", 3], ["M", 4], ["N", 5], ["O", 6], ["P", 7], ["Q", 8], ["R", 9], ["S", 2], ["T", 3], ["U", 4], ["V", 5], ["W", 6], ["X", 7], ["Y", 8], ["Z", 9]]);

function alg91(dateExpired, amount, reference){
  var digitVerifyDate = algorithmDate(dateExpired);

  var amountFormat = convertToPounds(amount);

  var digitVerifyAmount = algorithmAmount(amountFormat);
  var reference91 = reference + digitVerifyDate + digitVerifyAmount + digitVerifyConstant;
  var digitVerifyReference = algorithmReference(reference91.toUpperCase());
  reference91 = reference91 + digitVerifyReference;
  return reference91;
}

function convertToPounds(str) {	
	var n = Number.parseFloat(str);
  if(!str || isNaN(n) || n < 0) return 0;
  return n.toFixed(2);
}

function algorithmReference(data){
  var dataReplace = replaceAlphanumeric(data);
  var isPosition = 1
  var mapMultiply = new Map([[1, 11], [2, 13], [3, 17], [4, 19], [5, 23]]);
  var sumData = 0;
  for(var i = dataReplace.length-1; i >= 0; i--) {
    var dataNumber = Number(dataReplace.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  var numberAux = 97;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;
  var digitVerifyReference = residue + 1;

  digitVerifyReference = digitVerifyReference.toString();

  return missingData(2, digitVerifyReference.toString());
}

function replaceAlphanumeric(data){
  var transform = "";
  for (let characterData of data) {
    var infoCharacter = characterData;
    if(mapAlphanumeric.has(characterData)){
      infoCharacter = mapAlphanumeric.get(characterData);
    }
    transform += infoCharacter;
  }
  return transform;
}

function algorithmAmount(data){
  var dataTransform = data.split('.').join("");
  var isPosition = 1
  var mapMultiply = new Map([[1, 7], [2, 3], [3, 1]]);
  var sumData = 0;
  for(var i = dataTransform.length-1; i >= 0; i--) {
    var dataNumber = Number(dataTransform.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  var numberAux = 10;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;
  
  return residue.toString().charAt(residue.toString().length-1);
}

function algorithmDate(data){
  var dayData = data.substring(0, 2);
  var monthData = data.substring(2, 4);
  var yearData = data.substring(4, 8);

  var yearSubtraction = yearData - yearBase;

  var yearresultMultiply = yearSubtraction * yearMultiply;

  var monthResultSubtraction = Number(monthData) - unitSubtraction;

  var monthResultMultiply = monthResultSubtraction * monthMultiply;

  var dayResultSubtraction = Number(dayData) - unitSubtraction;

  var digitVerifyDate = yearresultMultiply + monthResultMultiply + dayResultSubtraction;

  return missingData(4, digitVerifyDate.toString());
}

function missingData(minLengthMissing, data){
  var missingLeft = minLengthMissing - data.length;
  for (var i = 0; i < missingLeft; i++) {
    data = contantLeft + data;
  }
  return data;
}

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],23:[function(require,module,exports){
'use strict';

var _ = require('underscore');
var CIEStrategy = require('./cie_strategy.js').CIEStrategy;
var CIEUtils = require('./cie_utils.js').CIEUtils;
var cieUtils = new CIEUtils();

var Alg94 = function() {};

Alg94.prototype = new CIEStrategy();
Alg94.prototype = {
  execute: function(input) {

    var validationRules = {
      reference: {length: {min: 1,max: 42}},
      date: {length: {min: 8,max: 8}},
      amount: {length: {min: 1,max: 12}}
    };

    if (!cieUtils.validateInput(input,validationRules )) {
      throw new Error('Longitud invalida');
    }

    return alg94(input.date, input.amount, input.reference);
  }
};

module.exports.Alg94 = Alg94;

var contantLeft = 0;
var yearBase = 2013;
var yearMultiply = 372;
var unitSubtraction = 1;
var monthMultiply = 31;
var digitVerifyConstant = 2;

function alg94(dateExpired, amount, reference){
  var digitVerifyDate = algorithmDate(dateExpired);

  var amountFormat = convertToPounds(amount);

  var digitVerifyAmount = algorithmAmount(amountFormat);
  var reference94 = reference + digitVerifyDate + digitVerifyAmount + digitVerifyConstant;
  var digitVerifyReference = algorithmReference(reference94.toUpperCase());
  reference94 = reference94 + digitVerifyReference;
  return reference94;
}

function convertToPounds(str) {	
	var n = Number.parseFloat(str);
  if(!str || isNaN(n) || n < 0) return 0;
  return n.toFixed(2);
}

function algorithmAmount(data){
  var dataTransform = data.split('.').join("");
  var isPosition = 1
  var mapMultiply = new Map([[1, 7], [2, 3], [3, 1]]);
  var sumData = 0;
  for(var i = dataTransform.length-1; i >= 0; i--) {
    var dataNumber = Number(dataTransform.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  var numberAux = 10;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;

  return residue.toString().charAt(residue.toString().length-1);
}

function algorithmReference(data){
  var dataReplace = data;
  var isPosition = 1
  var mapMultiply = new Map([[1, 11], [2, 13], [3, 17], [4, 19], [5, 23]]);
  var sumData = 0;
  for(var i = dataReplace.length-1; i >= 0; i--) {
    var dataNumber = Number(dataReplace.charAt(i));
    var numberMultiply = 0;
    if(mapMultiply.has(isPosition)){
      numberMultiply = mapMultiply.get(isPosition);
    }else{
      isPosition = 1;
      numberMultiply = mapMultiply.get(isPosition);
    }
    isPosition++;
    var resultMultiply = (numberMultiply * dataNumber);
    sumData += resultMultiply;
  }
  var numberAux = 97;
  var residue = ((sumData % numberAux) + numberAux) % numberAux;
  var digitVerifyReference = residue + 1;

  digitVerifyReference = digitVerifyReference.toString();

  return missingData(2, digitVerifyReference.toString());
}

function algorithmDate(data){
  var dayData = data.substring(0, 2);
  var monthData = data.substring(2, 4);
  var yearData = data.substring(4, 8);

  var yearSubtraction = yearData - yearBase;

  var yearresultMultiply = yearSubtraction * yearMultiply;

  var monthResultSubtraction = Number(monthData) - unitSubtraction;

  var monthResultMultiply = monthResultSubtraction * monthMultiply;

  var dayResultSubtraction = Number(dayData) - unitSubtraction;

  var digitVerifyDate = yearresultMultiply + monthResultMultiply + dayResultSubtraction;

  return missingData(4, digitVerifyDate.toString());
}

function missingData(minLengthMissing, data){
  var missingLeft = minLengthMissing - data.length;
  for (var i = 0; i < missingLeft; i++) {
    data = contantLeft + data;
  }
  return data;
}

},{"./cie_strategy.js":25,"./cie_utils.js":26,"underscore":28}],24:[function(require,module,exports){
'use strict';

var CIECalculator = function () {
  this.strategy = '';
};

CIECalculator.prototype = {
  setStrategy: function(strategy) {
    this.strategy = strategy;
  },
  execute: function(reference) {
    return this.strategy.execute(reference);
  }
};

module.exports.CIECalculator = CIECalculator;

},{}],25:[function(require,module,exports){
'use strict';

var CIEStrategy = function() {};

CIEStrategy.prototype = {
  execute: function() {
    throw new Error('CIEStrategy#execute needs to be overridden.');
  }
};

module.exports.CIEStrategy = CIEStrategy;

},{}],26:[function(require,module,exports){
'use strict';

var _ = require('underscore');

var CIEUtils = function() {};

CIEUtils.prototype = {
  nearestMultipleOf: function(val, base) {
    return (val % 10 == 0) ? val : (Math.floor(val/base) + 1)*base;
  },
  sequentialAdd:   function(input) {
    return _.reduce(input.toString(), function(memo,num) { return memo + parseInt(num); }, 0);
  },
  replaceCharWithNum: function(input, charToNum) {
    return _.map(input, function(x) { return charToNum[x];});
  },
  pad: function(n, width, z) {
    z = z || '0';
    n = n + '';
    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
  },
  validateLength: function(field, min, max) {
    return (field.length >= min && field.length <= max);
  },
  weightedReduce: function(input, weights, debug) {
    var acc =0;
    for (var i = 0; i < input.length; i++) {
      if (debug)
        {
          console.log('input: ' + input[i] + ' w: ' + weights[i%weights.length] + ' = ' + parseInt(input[i] * weights[i%weights.length]));
        }
      acc += parseInt(input[i] * weights[i%weights.length]);
    }
    return acc;
  },
  sequentialWeightedReduce: function(input, weights, debug) {
    var acc =0;
    for (var i = 0; i < input.length; i++) {
      if (debug)
        {
          console.log('input: ' + input[i] + ' w: ' + weights[i%weights.length] + ' = ' + CIEUtils.prototype.sequentialAdd(parseInt(input[i] * weights[i%weights.length])));
        }

      var tmp = CIEUtils.prototype.sequentialAdd(parseInt(input[i] * weights[i%weights.length]));

      while(tmp.toString().length !== 1) {
        tmp = CIEUtils.prototype.sequentialAdd(tmp);
      }
      acc += tmp;
    }
    return acc;
  },
  validateInput:  function(input, validationRules) {
    var validateLengths = function(input, validationRules) {
      return _.reduce(_.keys(validationRules), function(memo, k) {
        return memo && CIEUtils.prototype.validateLength(input[k], validationRules[k].length.min, validationRules[k].length.max);
      }, true);
    };
    return validateLengths(input,validationRules);
  }
};

module.exports.CIEUtils = CIEUtils;

},{"underscore":28}],27:[function(require,module,exports){
'use strict';

var CIECalculator = require('./lib/strategies/cie_calculator.js').CIECalculator;
var Alg00 = require('./lib/strategies/alg00.js').Alg00;
var Alg02 = require('./lib/strategies/alg02.js').Alg02;
var Alg03 = require('./lib/strategies/alg03.js').Alg03;
var Alg04 = require('./lib/strategies/alg04.js').Alg04;
var Alg06 = require('./lib/strategies/alg06.js').Alg06;
var Alg10 = require('./lib/strategies/alg10.js').Alg10;
var Alg11 = require('./lib/strategies/alg11.js').Alg11;
var Alg14 = require('./lib/strategies/alg14.js').Alg14;
var Alg21 = require('./lib/strategies/alg21.js').Alg21;
var Alg27 = require('./lib/strategies/alg27.js').Alg27;
var Alg35 = require('./lib/strategies/alg35.js').Alg35;
var Alg36 = require('./lib/strategies/alg36.js').Alg36;
var Alg37 = require('./lib/strategies/alg37.js').Alg37;
var Alg45 = require('./lib/strategies/alg45.js').Alg45;
var Alg62 = require('./lib/strategies/alg62.js').Alg62;
var Alg72 = require('./lib/strategies/alg72.js').Alg72;
var Alg77 = require('./lib/strategies/alg77.js').Alg77;
var Alg80 = require('./lib/strategies/alg80.js').Alg80;
var Alg81 = require('./lib/strategies/alg81.js').Alg81;
var Alg82 = require('./lib/strategies/alg82.js').Alg82;
var Alg89 = require('./lib/strategies/alg89.js').Alg89;
var Alg91 = require('./lib/strategies/alg91.js').Alg91;
var Alg94 = require('./lib/strategies/alg94.js').Alg94;

module.exports = function(params) {
  var calculator = new CIECalculator();
  calculator.setStrategy(eval('new Alg'+params.alg+'()'));
  return calculator.execute(params);
}

},{"./lib/strategies/alg00.js":1,"./lib/strategies/alg02.js":2,"./lib/strategies/alg03.js":3,"./lib/strategies/alg04.js":4,"./lib/strategies/alg06.js":5,"./lib/strategies/alg10.js":6,"./lib/strategies/alg11.js":7,"./lib/strategies/alg14.js":8,"./lib/strategies/alg21.js":9,"./lib/strategies/alg27.js":10,"./lib/strategies/alg35.js":11,"./lib/strategies/alg36.js":12,"./lib/strategies/alg37.js":13,"./lib/strategies/alg45.js":14,"./lib/strategies/alg62.js":15,"./lib/strategies/alg72.js":16,"./lib/strategies/alg77.js":17,"./lib/strategies/alg80.js":18,"./lib/strategies/alg81.js":19,"./lib/strategies/alg82.js":20,"./lib/strategies/alg89.js":21,"./lib/strategies/alg91.js":22,"./lib/strategies/alg94.js":23,"./lib/strategies/cie_calculator.js":24}],28:[function(require,module,exports){
//     Underscore.js 1.8.3
//     http://underscorejs.org
//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `exports` on the server.
  var root = this;

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var
    push             = ArrayProto.push,
    slice            = ArrayProto.slice,
    toString         = ObjProto.toString,
    hasOwnProperty   = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind,
    nativeCreate       = Object.create;

  // Naked function reference for surrogate-prototype-swapping.
  var Ctor = function(){};

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  // Export the Underscore object for **Node.js**, with
  // backwards-compatibility for the old `require()` API. If we're in
  // the browser, add `_` as a global object.
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

  // Current version.
  _.VERSION = '1.8.3';

  // Internal function that returns an efficient (for current engines) version
  // of the passed-in callback, to be repeatedly applied in other Underscore
  // functions.
  var optimizeCb = function(func, context, argCount) {
    if (context === void 0) return func;
    switch (argCount == null ? 3 : argCount) {
      case 1: return function(value) {
        return func.call(context, value);
      };
      case 2: return function(value, other) {
        return func.call(context, value, other);
      };
      case 3: return function(value, index, collection) {
        return func.call(context, value, index, collection);
      };
      case 4: return function(accumulator, value, index, collection) {
        return func.call(context, accumulator, value, index, collection);
      };
    }
    return function() {
      return func.apply(context, arguments);
    };
  };

  // A mostly-internal function to generate callbacks that can be applied
  // to each element in a collection, returning the desired result — either
  // identity, an arbitrary callback, a property matcher, or a property accessor.
  var cb = function(value, context, argCount) {
    if (value == null) return _.identity;
    if (_.isFunction(value)) return optimizeCb(value, context, argCount);
    if (_.isObject(value)) return _.matcher(value);
    return _.property(value);
  };
  _.iteratee = function(value, context) {
    return cb(value, context, Infinity);
  };

  // An internal function for creating assigner functions.
  var createAssigner = function(keysFunc, undefinedOnly) {
    return function(obj) {
      var length = arguments.length;
      if (length < 2 || obj == null) return obj;
      for (var index = 1; index < length; index++) {
        var source = arguments[index],
            keys = keysFunc(source),
            l = keys.length;
        for (var i = 0; i < l; i++) {
          var key = keys[i];
          if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
        }
      }
      return obj;
    };
  };

  // An internal function for creating a new object that inherits from another.
  var baseCreate = function(prototype) {
    if (!_.isObject(prototype)) return {};
    if (nativeCreate) return nativeCreate(prototype);
    Ctor.prototype = prototype;
    var result = new Ctor;
    Ctor.prototype = null;
    return result;
  };

  var property = function(key) {
    return function(obj) {
      return obj == null ? void 0 : obj[key];
    };
  };

  // Helper for collection methods to determine whether a collection
  // should be iterated as an array or as an object
  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
  var getLength = property('length');
  var isArrayLike = function(collection) {
    var length = getLength(collection);
    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
  };

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles raw objects in addition to array-likes. Treats all
  // sparse array-likes as if they were dense.
  _.each = _.forEach = function(obj, iteratee, context) {
    iteratee = optimizeCb(iteratee, context);
    var i, length;
    if (isArrayLike(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

  // Return the results of applying the iteratee to each element.
  _.map = _.collect = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length,
        results = Array(length);
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      results[index] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

  // Create a reducing function iterating left or right.
  function createReduce(dir) {
    // Optimized iterator function as using arguments.length
    // in the main function will deoptimize the, see #1991.
    function iterator(obj, iteratee, memo, keys, index, length) {
      for (; index >= 0 && index < length; index += dir) {
        var currentKey = keys ? keys[index] : index;
        memo = iteratee(memo, obj[currentKey], currentKey, obj);
      }
      return memo;
    }

    return function(obj, iteratee, memo, context) {
      iteratee = optimizeCb(iteratee, context, 4);
      var keys = !isArrayLike(obj) && _.keys(obj),
          length = (keys || obj).length,
          index = dir > 0 ? 0 : length - 1;
      // Determine the initial value if none is provided.
      if (arguments.length < 3) {
        memo = obj[keys ? keys[index] : index];
        index += dir;
      }
      return iterator(obj, iteratee, memo, keys, index, length);
    };
  }

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`.
  _.reduce = _.foldl = _.inject = createReduce(1);

  // The right-associative version of reduce, also known as `foldr`.
  _.reduceRight = _.foldr = createReduce(-1);

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, predicate, context) {
    var key;
    if (isArrayLike(obj)) {
      key = _.findIndex(obj, predicate, context);
    } else {
      key = _.findKey(obj, predicate, context);
    }
    if (key !== void 0 && key !== -1) return obj[key];
  };

  // Return all the elements that pass a truth test.
  // Aliased as `select`.
  _.filter = _.select = function(obj, predicate, context) {
    var results = [];
    predicate = cb(predicate, context);
    _.each(obj, function(value, index, list) {
      if (predicate(value, index, list)) results.push(value);
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, predicate, context) {
    return _.filter(obj, _.negate(cb(predicate)), context);
  };

  // Determine whether all of the elements match a truth test.
  // Aliased as `all`.
  _.every = _.all = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (!predicate(obj[currentKey], currentKey, obj)) return false;
    }
    return true;
  };

  // Determine if at least one element in the object matches a truth test.
  // Aliased as `any`.
  _.some = _.any = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (predicate(obj[currentKey], currentKey, obj)) return true;
    }
    return false;
  };

  // Determine if the array or object contains a given item (using `===`).
  // Aliased as `includes` and `include`.
  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
    if (!isArrayLike(obj)) obj = _.values(obj);
    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
    return _.indexOf(obj, item, fromIndex) >= 0;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    var isFunc = _.isFunction(method);
    return _.map(obj, function(value) {
      var func = isFunc ? method : value[method];
      return func == null ? func : func.apply(value, args);
    });
  };

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, _.property(key));
  };

  // Convenience version of a common use case of `filter`: selecting only objects
  // containing specific `key:value` pairs.
  _.where = function(obj, attrs) {
    return _.filter(obj, _.matcher(attrs));
  };

  // Convenience version of a common use case of `find`: getting the first object
  // containing specific `key:value` pairs.
  _.findWhere = function(obj, attrs) {
    return _.find(obj, _.matcher(attrs));
  };

  // Return the maximum element (or element-based computation).
  _.max = function(obj, iteratee, context) {
    var result = -Infinity, lastComputed = -Infinity,
        value, computed;
    if (iteratee == null && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value > result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index, list) {
        computed = iteratee(value, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = value;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iteratee, context) {
    var result = Infinity, lastComputed = Infinity,
        value, computed;
    if (iteratee == null && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value < result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index, list) {
        computed = iteratee(value, index, list);
        if (computed < lastComputed || computed === Infinity && result === Infinity) {
          result = value;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Shuffle a collection, using the modern version of the
  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
  _.shuffle = function(obj) {
    var set = isArrayLike(obj) ? obj : _.values(obj);
    var length = set.length;
    var shuffled = Array(length);
    for (var index = 0, rand; index < length; index++) {
      rand = _.random(0, index);
      if (rand !== index) shuffled[index] = shuffled[rand];
      shuffled[rand] = set[index];
    }
    return shuffled;
  };

  // Sample **n** random values from a collection.
  // If **n** is not specified, returns a single random element.
  // The internal `guard` argument allows it to work with `map`.
  _.sample = function(obj, n, guard) {
    if (n == null || guard) {
      if (!isArrayLike(obj)) obj = _.values(obj);
      return obj[_.random(obj.length - 1)];
    }
    return _.shuffle(obj).slice(0, Math.max(0, n));
  };

  // Sort the object's values by a criterion produced by an iteratee.
  _.sortBy = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value: value,
        index: index,
        criteria: iteratee(value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria;
      var b = right.criteria;
      if (a !== b) {
        if (a > b || a === void 0) return 1;
        if (a < b || b === void 0) return -1;
      }
      return left.index - right.index;
    }), 'value');
  };

  // An internal function used for aggregate "group by" operations.
  var group = function(behavior) {
    return function(obj, iteratee, context) {
      var result = {};
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index) {
        var key = iteratee(value, index, obj);
        behavior(result, value, key);
      });
      return result;
    };
  };

  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
  });

  // Indexes the object's values by a criterion, similar to `groupBy`, but for
  // when you know that your index values will be unique.
  _.indexBy = group(function(result, value, key) {
    result[key] = value;
  });

  // Counts instances of an object that group by a certain criterion. Pass
  // either a string attribute to count by, or a function that returns the
  // criterion.
  _.countBy = group(function(result, value, key) {
    if (_.has(result, key)) result[key]++; else result[key] = 1;
  });

  // Safely create a real, live array from anything iterable.
  _.toArray = function(obj) {
    if (!obj) return [];
    if (_.isArray(obj)) return slice.call(obj);
    if (isArrayLike(obj)) return _.map(obj, _.identity);
    return _.values(obj);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    if (obj == null) return 0;
    return isArrayLike(obj) ? obj.length : _.keys(obj).length;
  };

  // Split a collection into two arrays: one whose elements all satisfy the given
  // predicate, and one whose elements all do not satisfy the predicate.
  _.partition = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var pass = [], fail = [];
    _.each(obj, function(value, key, obj) {
      (predicate(value, key, obj) ? pass : fail).push(value);
    });
    return [pass, fail];
  };

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head` and `take`. The **guard** check
  // allows it to work with `_.map`.
  _.first = _.head = _.take = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[0];
    return _.initial(array, array.length - n);
  };

  // Returns everything but the last entry of the array. Especially useful on
  // the arguments object. Passing **n** will return all the values in
  // the array, excluding the last N.
  _.initial = function(array, n, guard) {
    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
  };

  // Get the last element of an array. Passing **n** will return the last N
  // values in the array.
  _.last = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[array.length - 1];
    return _.rest(array, Math.max(0, array.length - n));
  };

  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
  // Especially useful on the arguments object. Passing an **n** will return
  // the rest N values in the array.
  _.rest = _.tail = _.drop = function(array, n, guard) {
    return slice.call(array, n == null || guard ? 1 : n);
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, _.identity);
  };

  // Internal implementation of a recursive `flatten` function.
  var flatten = function(input, shallow, strict, startIndex) {
    var output = [], idx = 0;
    for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
      var value = input[i];
      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
        //flatten current level of array or arguments object
        if (!shallow) value = flatten(value, shallow, strict);
        var j = 0, len = value.length;
        output.length += len;
        while (j < len) {
          output[idx++] = value[j++];
        }
      } else if (!strict) {
        output[idx++] = value;
      }
    }
    return output;
  };

  // Flatten out an array, either recursively (by default), or just one level.
  _.flatten = function(array, shallow) {
    return flatten(array, shallow, false);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = cb(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = getLength(array); i < length; i++) {
      var value = array[i],
          computed = iteratee ? iteratee(value, i, array) : value;
      if (isSorted) {
        if (!i || seen !== computed) result.push(value);
        seen = computed;
      } else if (iteratee) {
        if (!_.contains(seen, computed)) {
          seen.push(computed);
          result.push(value);
        }
      } else if (!_.contains(result, value)) {
        result.push(value);
      }
    }
    return result;
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = function() {
    return _.uniq(flatten(arguments, true, true));
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays.
  _.intersection = function(array) {
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0, length = getLength(array); i < length; i++) {
      var item = array[i];
      if (_.contains(result, item)) continue;
      for (var j = 1; j < argsLength; j++) {
        if (!_.contains(arguments[j], item)) break;
      }
      if (j === argsLength) result.push(item);
    }
    return result;
  };

  // Take the difference between one array and a number of other arrays.
  // Only the elements present in just the first array will remain.
  _.difference = function(array) {
    var rest = flatten(arguments, true, true, 1);
    return _.filter(array, function(value){
      return !_.contains(rest, value);
    });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function() {
    return _.unzip(arguments);
  };

  // Complement of _.zip. Unzip accepts an array of arrays and groups
  // each array's elements on shared indices
  _.unzip = function(array) {
    var length = array && _.max(array, getLength).length || 0;
    var result = Array(length);

    for (var index = 0; index < length; index++) {
      result[index] = _.pluck(array, index);
    }
    return result;
  };

  // Converts lists into objects. Pass either a single array of `[key, value]`
  // pairs, or two parallel arrays of the same length -- one of keys, and one of
  // the corresponding values.
  _.object = function(list, values) {
    var result = {};
    for (var i = 0, length = getLength(list); i < length; i++) {
      if (values) {
        result[list[i]] = values[i];
      } else {
        result[list[i][0]] = list[i][1];
      }
    }
    return result;
  };

  // Generator function to create the findIndex and findLastIndex functions
  function createPredicateIndexFinder(dir) {
    return function(array, predicate, context) {
      predicate = cb(predicate, context);
      var length = getLength(array);
      var index = dir > 0 ? 0 : length - 1;
      for (; index >= 0 && index < length; index += dir) {
        if (predicate(array[index], index, array)) return index;
      }
      return -1;
    };
  }

  // Returns the first index on an array-like that passes a predicate test
  _.findIndex = createPredicateIndexFinder(1);
  _.findLastIndex = createPredicateIndexFinder(-1);

  // Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = cb(iteratee, context, 1);
    var value = iteratee(obj);
    var low = 0, high = getLength(array);
    while (low < high) {
      var mid = Math.floor((low + high) / 2);
      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
    }
    return low;
  };

  // Generator function to create the indexOf and lastIndexOf functions
  function createIndexFinder(dir, predicateFind, sortedIndex) {
    return function(array, item, idx) {
      var i = 0, length = getLength(array);
      if (typeof idx == 'number') {
        if (dir > 0) {
            i = idx >= 0 ? idx : Math.max(idx + length, i);
        } else {
            length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
        }
      } else if (sortedIndex && idx && length) {
        idx = sortedIndex(array, item);
        return array[idx] === item ? idx : -1;
      }
      if (item !== item) {
        idx = predicateFind(slice.call(array, i, length), _.isNaN);
        return idx >= 0 ? idx + i : -1;
      }
      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
        if (array[idx] === item) return idx;
      }
      return -1;
    };
  }

  // Return the position of the first occurrence of an item in an array,
  // or -1 if the item is not included in the array.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (stop == null) {
      stop = start || 0;
      start = 0;
    }
    step = step || 1;

    var length = Math.max(Math.ceil((stop - start) / step), 0);
    var range = Array(length);

    for (var idx = 0; idx < length; idx++, start += step) {
      range[idx] = start;
    }

    return range;
  };

  // Function (ahem) Functions
  // ------------------

  // Determines whether to execute a function as a constructor
  // or a normal function with the provided arguments
  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
    var self = baseCreate(sourceFunc.prototype);
    var result = sourceFunc.apply(self, args);
    if (_.isObject(result)) return result;
    return self;
  };

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
  // available.
  _.bind = function(func, context) {
    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
    var args = slice.call(arguments, 2);
    var bound = function() {
      return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
    };
    return bound;
  };

  // Partially apply a function by creating a version that has had some of its
  // arguments pre-filled, without changing its dynamic `this` context. _ acts
  // as a placeholder, allowing any combination of arguments to be pre-filled.
  _.partial = function(func) {
    var boundArgs = slice.call(arguments, 1);
    var bound = function() {
      var position = 0, length = boundArgs.length;
      var args = Array(length);
      for (var i = 0; i < length; i++) {
        args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
      }
      while (position < arguments.length) args.push(arguments[position++]);
      return executeBound(func, bound, this, this, args);
    };
    return bound;
  };

  // Bind a number of an object's methods to that object. Remaining arguments
  // are the method names to be bound. Useful for ensuring that all callbacks
  // defined on an object belong to it.
  _.bindAll = function(obj) {
    var i, length = arguments.length, key;
    if (length <= 1) throw new Error('bindAll must be passed function names');
    for (i = 1; i < length; i++) {
      key = arguments[i];
      obj[key] = _.bind(obj[key], obj);
    }
    return obj;
  };

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memoize = function(key) {
      var cache = memoize.cache;
      var address = '' + (hasher ? hasher.apply(this, arguments) : key);
      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
      return cache[address];
    };
    memoize.cache = {};
    return memoize;
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){
      return func.apply(null, args);
    }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = _.partial(_.delay, _, 1);

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time. Normally, the throttled function will run
  // as much as it can, without ever going more than once per `wait` duration;
  // but if you'd like to disable the execution on the leading edge, pass
  // `{leading: false}`. To disable execution on the trailing edge, ditto.
  _.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };
    return function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
      var last = _.now() - timestamp;

      if (last < wait && last >= 0) {
        timeout = setTimeout(later, wait - last);
      } else {
        timeout = null;
        if (!immediate) {
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        }
      }
    };

    return function() {
      context = this;
      args = arguments;
      timestamp = _.now();
      var callNow = immediate && !timeout;
      if (!timeout) timeout = setTimeout(later, wait);
      if (callNow) {
        result = func.apply(context, args);
        context = args = null;
      }

      return result;
    };
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return _.partial(wrapper, func);
  };

  // Returns a negated version of the passed-in predicate.
  _.negate = function(predicate) {
    return function() {
      return !predicate.apply(this, arguments);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var args = arguments;
    var start = args.length - 1;
    return function() {
      var i = start;
      var result = args[start].apply(this, arguments);
      while (i--) result = args[i].call(this, result);
      return result;
    };
  };

  // Returns a function that will only be executed on and after the Nth call.
  _.after = function(times, func) {
    return function() {
      if (--times < 1) {
        return func.apply(this, arguments);
      }
    };
  };

  // Returns a function that will only be executed up to (but not including) the Nth call.
  _.before = function(times, func) {
    var memo;
    return function() {
      if (--times > 0) {
        memo = func.apply(this, arguments);
      }
      if (times <= 1) func = null;
      return memo;
    };
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = _.partial(_.before, 2);

  // Object Functions
  // ----------------

  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
                      'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];

  function collectNonEnumProps(obj, keys) {
    var nonEnumIdx = nonEnumerableProps.length;
    var constructor = obj.constructor;
    var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;

    // Constructor is a special case.
    var prop = 'constructor';
    if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);

    while (nonEnumIdx--) {
      prop = nonEnumerableProps[nonEnumIdx];
      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
        keys.push(prop);
      }
    }
  }

  // Retrieve the names of an object's own properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`
  _.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    // Ahem, IE < 9.
    if (hasEnumBug) collectNonEnumProps(obj, keys);
    return keys;
  };

  // Retrieve all the property names of an object.
  _.allKeys = function(obj) {
    if (!_.isObject(obj)) return [];
    var keys = [];
    for (var key in obj) keys.push(key);
    // Ahem, IE < 9.
    if (hasEnumBug) collectNonEnumProps(obj, keys);
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var values = Array(length);
    for (var i = 0; i < length; i++) {
      values[i] = obj[keys[i]];
    }
    return values;
  };

  // Returns the results of applying the iteratee to each element of the object
  // In contrast to _.map it returns an object
  _.mapObject = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys =  _.keys(obj),
          length = keys.length,
          results = {},
          currentKey;
      for (var index = 0; index < length; index++) {
        currentKey = keys[index];
        results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
      }
      return results;
  };

  // Convert an object into a list of `[key, value]` pairs.
  _.pairs = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var pairs = Array(length);
    for (var i = 0; i < length; i++) {
      pairs[i] = [keys[i], obj[keys[i]]];
    }
    return pairs;
  };

  // Invert the keys and values of an object. The values must be serializable.
  _.invert = function(obj) {
    var result = {};
    var keys = _.keys(obj);
    for (var i = 0, length = keys.length; i < length; i++) {
      result[obj[keys[i]]] = keys[i];
    }
    return result;
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = createAssigner(_.allKeys);

  // Assigns a given object with all the own properties in the passed-in object(s)
  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
  _.extendOwn = _.assign = createAssigner(_.keys);

  // Returns the first key on an object that passes a predicate test
  _.findKey = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = _.keys(obj), key;
    for (var i = 0, length = keys.length; i < length; i++) {
      key = keys[i];
      if (predicate(obj[key], key, obj)) return key;
    }
  };

  // Return a copy of the object only containing the whitelisted properties.
  _.pick = function(object, oiteratee, context) {
    var result = {}, obj = object, iteratee, keys;
    if (obj == null) return result;
    if (_.isFunction(oiteratee)) {
      keys = _.allKeys(obj);
      iteratee = optimizeCb(oiteratee, context);
    } else {
      keys = flatten(arguments, false, false, 1);
      iteratee = function(value, key, obj) { return key in obj; };
      obj = Object(obj);
    }
    for (var i = 0, length = keys.length; i < length; i++) {
      var key = keys[i];
      var value = obj[key];
      if (iteratee(value, key, obj)) result[key] = value;
    }
    return result;
  };

   // Return a copy of the object without the blacklisted properties.
  _.omit = function(obj, iteratee, context) {
    if (_.isFunction(iteratee)) {
      iteratee = _.negate(iteratee);
    } else {
      var keys = _.map(flatten(arguments, false, false, 1), String);
      iteratee = function(value, key) {
        return !_.contains(keys, key);
      };
    }
    return _.pick(obj, iteratee, context);
  };

  // Fill in a given object with default properties.
  _.defaults = createAssigner(_.allKeys, true);

  // Creates an object that inherits from the given prototype object.
  // If additional properties are provided then they will be added to the
  // created object.
  _.create = function(prototype, props) {
    var result = baseCreate(prototype);
    if (props) _.extendOwn(result, props);
    return result;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    if (!_.isObject(obj)) return obj;
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Returns whether an object has a given set of `key:value` pairs.
  _.isMatch = function(object, attrs) {
    var keys = _.keys(attrs), length = keys.length;
    if (object == null) return !length;
    var obj = Object(object);
    for (var i = 0; i < length; i++) {
      var key = keys[i];
      if (attrs[key] !== obj[key] || !(key in obj)) return false;
    }
    return true;
  };


  // Internal recursive comparison function for `isEqual`.
  var eq = function(a, b, aStack, bStack) {
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    // A strict comparison is necessary because `null == undefined`.
    if (a == null || b == null) return a === b;
    // Unwrap any wrapped objects.
    if (a instanceof _) a = a._wrapped;
    if (b instanceof _) b = b._wrapped;
    // Compare `[[Class]]` names.
    var className = toString.call(a);
    if (className !== toString.call(b)) return false;
    switch (className) {
      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
      case '[object RegExp]':
      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
      case '[object String]':
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
        // equivalent to `new String("5")`.
        return '' + a === '' + b;
      case '[object Number]':
        // `NaN`s are equivalent, but non-reflexive.
        // Object(NaN) is equivalent to NaN
        if (+a !== +a) return +b !== +b;
        // An `egal` comparison is performed for other numeric values.
        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
      case '[object Date]':
      case '[object Boolean]':
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
        // millisecond representations. Note that invalid dates with millisecond representations
        // of `NaN` are not equivalent.
        return +a === +b;
    }

    var areArrays = className === '[object Array]';
    if (!areArrays) {
      if (typeof a != 'object' || typeof b != 'object') return false;

      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
      // from different frames are.
      var aCtor = a.constructor, bCtor = b.constructor;
      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
                               _.isFunction(bCtor) && bCtor instanceof bCtor)
                          && ('constructor' in a && 'constructor' in b)) {
        return false;
      }
    }
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.

    // Initializing stack of traversed objects.
    // It's done here since we only need them for objects and arrays comparison.
    aStack = aStack || [];
    bStack = bStack || [];
    var length = aStack.length;
    while (length--) {
      // Linear search. Performance is inversely proportional to the number of
      // unique nested structures.
      if (aStack[length] === a) return bStack[length] === b;
    }

    // Add the first object to the stack of traversed objects.
    aStack.push(a);
    bStack.push(b);

    // Recursively compare objects and arrays.
    if (areArrays) {
      // Compare array lengths to determine if a deep comparison is necessary.
      length = a.length;
      if (length !== b.length) return false;
      // Deep compare the contents, ignoring non-numeric properties.
      while (length--) {
        if (!eq(a[length], b[length], aStack, bStack)) return false;
      }
    } else {
      // Deep compare objects.
      var keys = _.keys(a), key;
      length = keys.length;
      // Ensure that both objects contain the same number of properties before comparing deep equality.
      if (_.keys(b).length !== length) return false;
      while (length--) {
        // Deep compare each member
        key = keys[length];
        if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
      }
    }
    // Remove the first object from the stack of traversed objects.
    aStack.pop();
    bStack.pop();
    return true;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    return eq(a, b);
  };

  // Is a given array, string, or object empty?
  // An "empty" object has no enumerable own-properties.
  _.isEmpty = function(obj) {
    if (obj == null) return true;
    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
    return _.keys(obj).length === 0;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType === 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
  };

  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
    _['is' + name] = function(obj) {
      return toString.call(obj) === '[object ' + name + ']';
    };
  });

  // Define a fallback version of the method in browsers (ahem, IE < 9), where
  // there isn't any inspectable "Arguments" type.
  if (!_.isArguments(arguments)) {
    _.isArguments = function(obj) {
      return _.has(obj, 'callee');
    };
  }

  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
  // IE 11 (#1621), and in Safari 8 (#1929).
  if (typeof /./ != 'function' && typeof Int8Array != 'object') {
    _.isFunction = function(obj) {
      return typeof obj == 'function' || false;
    };
  }

  // Is a given object a finite number?
  _.isFinite = function(obj) {
    return isFinite(obj) && !isNaN(parseFloat(obj));
  };

  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
  _.isNaN = function(obj) {
    return _.isNumber(obj) && obj !== +obj;
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Shortcut function for checking if an object has a given property directly
  // on itself (in other words, not on a prototype).
  _.has = function(obj, key) {
    return obj != null && hasOwnProperty.call(obj, key);
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iteratees.
  _.identity = function(value) {
    return value;
  };

  // Predicate-generating functions. Often useful outside of Underscore.
  _.constant = function(value) {
    return function() {
      return value;
    };
  };

  _.noop = function(){};

  _.property = property;

  // Generates a function for a given object that returns a given property.
  _.propertyOf = function(obj) {
    return obj == null ? function(){} : function(key) {
      return obj[key];
    };
  };

  // Returns a predicate for checking whether an object has a given set of
  // `key:value` pairs.
  _.matcher = _.matches = function(attrs) {
    attrs = _.extendOwn({}, attrs);
    return function(obj) {
      return _.isMatch(obj, attrs);
    };
  };

  // Run a function **n** times.
  _.times = function(n, iteratee, context) {
    var accum = Array(Math.max(0, n));
    iteratee = optimizeCb(iteratee, context, 1);
    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
    return accum;
  };

  // Return a random integer between min and max (inclusive).
  _.random = function(min, max) {
    if (max == null) {
      max = min;
      min = 0;
    }
    return min + Math.floor(Math.random() * (max - min + 1));
  };

  // A (possibly faster) way to get the current timestamp as an integer.
  _.now = Date.now || function() {
    return new Date().getTime();
  };

   // List of HTML entities for escaping.
  var escapeMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };
  var unescapeMap = _.invert(escapeMap);

  // Functions for escaping and unescaping strings to/from HTML interpolation.
  var createEscaper = function(map) {
    var escaper = function(match) {
      return map[match];
    };
    // Regexes for identifying a key that needs to be escaped
    var source = '(?:' + _.keys(map).join('|') + ')';
    var testRegexp = RegExp(source);
    var replaceRegexp = RegExp(source, 'g');
    return function(string) {
      string = string == null ? '' : '' + string;
      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
    };
  };
  _.escape = createEscaper(escapeMap);
  _.unescape = createEscaper(unescapeMap);

  // If the value of the named `property` is a function then invoke it with the
  // `object` as context; otherwise, return it.
  _.result = function(object, property, fallback) {
    var value = object == null ? void 0 : object[property];
    if (value === void 0) {
      value = fallback;
    }
    return _.isFunction(value) ? value.call(object) : value;
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = ++idCounter + '';
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g,
    escape      : /<%-([\s\S]+?)%>/g
  };

  // When customizing `templateSettings`, if you don't want to define an
  // interpolation, evaluation or escaping regex, we need one that is
  // guaranteed not to match.
  var noMatch = /(.)^/;

  // Certain characters need to be escaped so that they can be put into a
  // string literal.
  var escapes = {
    "'":      "'",
    '\\':     '\\',
    '\r':     'r',
    '\n':     'n',
    '\u2028': 'u2028',
    '\u2029': 'u2029'
  };

  var escaper = /\\|'|\r|\n|\u2028|\u2029/g;

  var escapeChar = function(match) {
    return '\\' + escapes[match];
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  // NB: `oldSettings` only exists for backwards compatibility.
  _.template = function(text, settings, oldSettings) {
    if (!settings && oldSettings) settings = oldSettings;
    settings = _.defaults({}, settings, _.templateSettings);

    // Combine delimiters into one regular expression via alternation.
    var matcher = RegExp([
      (settings.escape || noMatch).source,
      (settings.interpolate || noMatch).source,
      (settings.evaluate || noMatch).source
    ].join('|') + '|$', 'g');

    // Compile the template source, escaping string literals appropriately.
    var index = 0;
    var source = "__p+='";
    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
      source += text.slice(index, offset).replace(escaper, escapeChar);
      index = offset + match.length;

      if (escape) {
        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
      } else if (interpolate) {
        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
      } else if (evaluate) {
        source += "';\n" + evaluate + "\n__p+='";
      }

      // Adobe VMs need the match returned to produce the correct offest.
      return match;
    });
    source += "';\n";

    // If a variable is not specified, place data values in local scope.
    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

    source = "var __t,__p='',__j=Array.prototype.join," +
      "print=function(){__p+=__j.call(arguments,'');};\n" +
      source + 'return __p;\n';

    try {
      var render = new Function(settings.variable || 'obj', '_', source);
    } catch (e) {
      e.source = source;
      throw e;
    }

    var template = function(data) {
      return render.call(this, data, _);
    };

    // Provide the compiled source as a convenience for precompilation.
    var argument = settings.variable || 'obj';
    template.source = 'function(' + argument + '){\n' + source + '}';

    return template;
  };

  // Add a "chain" function. Start chaining a wrapped Underscore object.
  _.chain = function(obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

  // OOP
  // ---------------
  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.

  // Helper function to continue chaining intermediate results.
  var result = function(instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
  };

  // Add your own custom functions to the Underscore object.
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = _[name] = obj[name];
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return result(this, func.apply(_, args));
      };
    });
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      var obj = this._wrapped;
      method.apply(obj, arguments);
      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
      return result(this, obj);
    };
  });

  // Add all accessor Array functions to the wrapper.
  _.each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      return result(this, method.apply(this._wrapped, arguments));
    };
  });

  // Extracts the result from a wrapped and chained object.
  _.prototype.value = function() {
    return this._wrapped;
  };

  // Provide unwrapping proxy for some methods used in engine operations
  // such as arithmetic and JSON stringification.
  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;

  _.prototype.toString = function() {
    return '' + this._wrapped;
  };

  // AMD registration happens at the end for compatibility with AMD loaders
  // that may not enforce next-turn semantics on modules. Even though general
  // practice for AMD registration is to be anonymous, underscore registers
  // as a named module because, like jQuery, it is a base library that is
  // popular enough to be bundled in a third party lib, but not be part of
  // an AMD load request. Those cases could generate an error when an
  // anonymous define() is called outside of a loader request.
  if (typeof define === 'function' && define.amd) {
    define('underscore', [], function() {
      return _;
    });
  }
}.call(this));

},{}]},{},[27])(27)
});

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGcwMC5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzAyLmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnMDMuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGcwNC5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzA2LmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnMTAuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGcxMS5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzE0LmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnMjEuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGcyNy5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzM1LmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnMzYuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGczNy5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzQ1LmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnNjIuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGc3Mi5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzc3LmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnODAuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGc4MS5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzgyLmpzIiwibGliL3N0cmF0ZWdpZXMvYWxnODkuanMiLCJsaWIvc3RyYXRlZ2llcy9hbGc5MS5qcyIsImxpYi9zdHJhdGVnaWVzL2FsZzk0LmpzIiwibGliL3N0cmF0ZWdpZXMvY2llX2NhbGN1bGF0b3IuanMiLCJsaWIvc3RyYXRlZ2llcy9jaWVfc3RyYXRlZ3kuanMiLCJsaWIvc3RyYXRlZ2llcy9jaWVfdXRpbHMuanMiLCJtYWluLmpzIiwibm9kZV9tb2R1bGVzL3VuZGVyc2NvcmUvdW5kZXJzY29yZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIlxyXG4ndXNlIHN0cmljdCc7XHJcblxyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGcwMCA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGcwMC5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnMDAucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxOX19XHJcbiAgICB9O1xyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LCB2YWxpZGF0aW9uUnVsZXMpKSB7XHJcbiAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgICAgZXJyb3Iuc3RhdHVzID0gJzQyMic7XHJcbiAgICAgIHRocm93IGVycm9yO1xyXG4gICAgfVxyXG5cclxuICAgIHZhciBhY2MgPSAwO1xyXG4gICAgdmFyIHRtcElucHV0ID0gaW5wdXQucmVmZXJlbmNlLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpXHJcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5wdXQucmVmZXJlbmNlLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGFjYyArPSBjaWVVdGlscy5zZXF1ZW50aWFsQWRkKCBwYXJzZUludCh0bXBJbnB1dFtpXSwxMCkgKiAoICggKGkrMSklMiAhPT0gMCApID8gMiA6IDEpICk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArIChjaWVVdGlscy5uZWFyZXN0TXVsdGlwbGVPZihhY2MsMTApIC0gYWNjKSUxMDtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGcwMCA9IEFsZzAwO1xyXG4iLCJcclxuJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMDIgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMDIucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzAyLnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiA2LG1heDogMTl9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGFjYyA9IDA7XHJcbiAgICB2YXIgcmVmZXJlbmNlID0gcGFyc2VJbnB1dChpbnB1dCkucmV2ZXJzZSgpO1xyXG5cclxuICAgIC8vY29uc29sZS5sb2coJy0tLS0tLS0tLScpO1xyXG4gICAgLy9jb25zb2xlLmxvZygnXFxSZWZlcmVuY2lhOicsaW5wdXQucmVmZXJlbmNlKTtcclxuICAgIC8vY29uc29sZS5sb2coJ1xcUmVmZXJlbmNpYSBOdW1lcmljYTonLHJlZmVyZW5jZS5qb2luKCcnKSk7XHJcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcmVmZXJlbmNlLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHZhciBtID0gKCAoIChpKzEpJTIgIT09IDAgKSA/IDIgOiAxKTtcclxuICAgICAgLy9jb25zb2xlLmxvZyhyZWZlcmVuY2VbaV0gKyAnICogJyArIG0gKyAnID0gJyArIChwYXJzZUludChyZWZlcmVuY2VbaV0sMTApICogbSkgKyAnXFx0UmVkdWNjaW9uIDogJyArIGNpZVV0aWxzLnNlcXVlbnRpYWxBZGQoIHBhcnNlSW50KHJlZmVyZW5jZVtpXSwxMCkgKiBtICkpO1xyXG4gICAgICBhY2MgKz0gY2llVXRpbHMuc2VxdWVudGlhbEFkZCggcGFyc2VJbnQocmVmZXJlbmNlW2ldLDEwKSAqIG0gKTtcclxuICAgIH1cclxuICAgIC8vY29uc29sZS5sb2coJ1N1bWE6JyxhY2MpO1xyXG4gICAgLy9jb25zb2xlLmxvZygnTXVsdGlwbG8gMTA6JyxjaWVVdGlscy5uZWFyZXN0TXVsdGlwbGVPZihhY2MsMTApKTtcclxuICAgIC8vY29uc29sZS5sb2coJ0RpZ2l0bzonLChjaWVVdGlscy5uZWFyZXN0TXVsdGlwbGVPZihhY2MsMTApIC0gYWNjKSk7XHJcbiAgICAvL2NvbnNvbGUubG9nKCdSZWZlcmVuY2lhIENvbXBsZXRhOicsaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCkgKyAoY2llVXRpbHMubmVhcmVzdE11bHRpcGxlT2YoYWNjLDEwKSAtIGFjYykpO1xyXG5cclxuICAgIHJldHVybiBpbnB1dC5yZWZlcmVuY2UudG9VcHBlckNhc2UoKSArIChjaWVVdGlscy5uZWFyZXN0TXVsdGlwbGVPZihhY2MsMTApIC0gYWNjKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGcwMiA9IEFsZzAyO1xyXG5cclxudmFyIHBhcnNlSW5wdXQgPSBmdW5jdGlvbihpbnB1dCkge1xyXG4gIHZhciBjaGFyVG9OdW0gPSB7XHJcbiAgICBBOiAxLCBCOiAyLCBDOiAzLCBEOiA0LCBFOiA1LCBGOiA2LCBHOiA3LCBIOiA4LCBJOiA5LCBKOiAxLCBLOiAyLCBMOiAzLFxyXG4gICAgTTogNCwgTjogNSwgTzogNiwgUDogNywgUTogOCwgUjogOSwgUzogMSwgVDogMiwgVTogMywgVjogNCwgVzogNSwgWDogNixcclxuICAgIFk6IDcsIFo6IDgsIDE6IDEsIDI6IDIsIDM6IDMsIDQ6IDQsIDU6IDUsIDY6IDYsIDc6IDcsIDg6IDgsIDk6IDksIDA6IDBcclxuICB9O1xyXG4gIHJldHVybiBjaWVVdGlscy5yZXBsYWNlQ2hhcldpdGhOdW0oaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCksIGNoYXJUb051bSk7XHJcbn07XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBfID0gcmVxdWlyZSgndW5kZXJzY29yZScpO1xyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGcwMyA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGcwMy5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnMDMucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxOX19XHJcbiAgICB9O1xyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LCB2YWxpZGF0aW9uUnVsZXMpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYWNjID0gMDtcclxuICAgIHZhciByZWZlcmVuY2UgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCByZWZlcmVuY2UubGVuZ3RoOyBpKyspIHtcclxuICAgICAgYWNjICs9IHBhcnNlSW50KHJlZmVyZW5jZVtpXSwxMCkgKiAoaSArIDIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArICg3LShhY2MgJSA3KSk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnMDMgPSBBbGcwMztcclxuXHJcbi8vIFRPRE8gTWF5YmUgbW92ZSB0aGlzIHRvIGEgdGVtcGxhdGU/XHJcbnZhciBwYXJzZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuICByZXR1cm4gXy5sYXN0KGlucHV0LnJlZmVyZW5jZSw2KS5yZXZlcnNlKCk7XHJcbn07XHJcbiIsIlxyXG4ndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMDQgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMDQucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzA0LnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTh9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcblxyXG4gICAgdmFyIHJlZmVyZW5jZSA9ICBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShyZWZlcmVuY2UsIFsxMSwxMywxNywxOSwyM10pIC0gcmVmZXJlbmNlWzBdKjExO1xyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArIGNpZVV0aWxzLnBhZCgoKGFjYyArIDMzMCklOTcpKzEsMik7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnMDQgPSBBbGcwNDtcclxuXHJcbi8vIFRPRE8gTWF5YmUgbW92ZSB0aGlzIHRvIGEgdGVtcGxhdGU/XHJcbnZhciBwYXJzZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuICByZXR1cm4gXy50b0FycmF5KGlucHV0LnJlZmVyZW5jZSkucmV2ZXJzZSgpO1xyXG59O1xyXG5cclxuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzA2ID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzA2LnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGcwNi5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuICAgIHZhciB2YWxpZGF0aW9uUnVsZXMgPSB7XHJcbiAgICAgIHJlZmVyZW5jZToge2xlbmd0aDoge21pbjogMSxtYXg6IDE4fX0sXHJcbiAgICAgIGJyYW5jaDoge2xlbmd0aDoge21pbjogMSxtYXg6IDh9fSxcclxuICAgICAgYWNjb3VudDoge2xlbmd0aDoge21pbjogMSxtYXg6IDh9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcbiAgICB2YXIgcmVmZXJlbmNlID0gcGFyc2VJbnB1dChpbnB1dCk7XHJcbiAgICB2YXIgYWNjID0gY2llVXRpbHMud2VpZ2h0ZWRSZWR1Y2UocmVmZXJlbmNlLFszNywzMSwyOSwyMywxOSwxNywxMywxMV0pO1xyXG5cclxuICAgIHJldHVybiBpbnB1dC5yZWZlcmVuY2UgKyAoOTkgLSAoYWNjICUgOTcpKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGcwNiA9IEFsZzA2O1xyXG5cclxuLy8gVE9ETyBNYXliZSBtb3ZlIHRoaXMgdG8gYSB0ZW1wbGF0ZT9cclxudmFyIHBhcnNlSW5wdXQgPSBmdW5jdGlvbihpbnB1dCkge1xyXG4gIHZhciBwYWRkZWRCcmFuY2ggPSBfLnRvQXJyYXkoY2llVXRpbHMucGFkKGlucHV0LmJyYW5jaCw4KSk7XHJcbiAgdmFyIHBhZGRlZEFjY291bnQ9IF8udG9BcnJheShjaWVVdGlscy5wYWQoaW5wdXQuYWNjb3VudCw4KSk7XHJcbiAgdmFyIHBhZGRlZFJlZmVyZW5jZT0gXy5sYXN0KGNpZVV0aWxzLnBhZChpbnB1dC5yZWZlcmVuY2UsOCksIDgpO1xyXG4gIHJldHVybiBwYWRkZWRCcmFuY2guY29uY2F0KHBhZGRlZEFjY291bnQsIHBhZGRlZFJlZmVyZW5jZSkucmV2ZXJzZSgpO1xyXG59O1xyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMTAgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMTAucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzEwLnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fSxcclxuICAgICAgZGF0ZToge2xlbmd0aDoge21pbjogOCxtYXg6IDh9fSxcclxuICAgICAgYW1vdW50OiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcbiAgICB2YXIgY29uZGVuc2VkSW5wdXQgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShjb25kZW5zZWRJbnB1dC5yZWZlcmVuY2UsWzExLDEzLDE3LDE5LDIzXSk7XHJcblxyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArIGNvbmRlbnNlZElucHV0LmRhdGUgKyBjb25kZW5zZWRJbnB1dC5hbW91bnQgKyAnMicgKyBjaWVVdGlscy5wYWQoKChhY2MlOTcpKzEpLDIpO1xyXG4gIH1cclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzLkFsZzEwID0gQWxnMTA7XHJcblxyXG4vLyBUT0RPIE1heWJlIG1vdmUgdGhpcyB0byBhIHRlbXBsYXRlP1xyXG52YXIgcGFyc2VJbnB1dCA9IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgdmFyIHBhZGRlZERhdGUgPSBjaWVVdGlscy5wYWQoKGlucHV0LmRhdGUuc3Vic3RyKDQsNCktMjAxNCkqMzcyICsgKGlucHV0LmRhdGUuc3Vic3RyKDIsMiktMSkqMzEgKyAoaW5wdXQuZGF0ZS5zdWJzdHIoMCwyKS0xKSw0KTtcclxuICB2YXIgcGFkZGVkQW1vdW50ID0gY2llVXRpbHMud2VpZ2h0ZWRSZWR1Y2UoXy53aXRob3V0KF8udG9BcnJheShpbnB1dC5hbW91bnQpLCcuJykucmV2ZXJzZSgpLFs3LDMsMV0pJTEwO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcmVmZXJlbmNlOiBfLnRvQXJyYXkoaW5wdXQucmVmZXJlbmNlICsgcGFkZGVkRGF0ZSArIHBhZGRlZEFtb3VudCArICcyJykucmV2ZXJzZSgpLFxyXG4gICAgYW1vdW50OiBwYWRkZWRBbW91bnQsXHJcbiAgICBkYXRlOiBwYWRkZWREYXRlXHJcbiAgfTtcclxufTtcclxuIiwiXHJcbid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzExID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzExLnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGcxMS5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19XHJcbiAgICB9O1xyXG5cclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICAgIGVycm9yLnN0YXR1cyA9ICc0MjInO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH1cclxuXHJcbiAgICAvKnZhciBhY2MgPSAwO1xyXG4gICAgdmFyIHRtcElucHV0ID0gaW5wdXQucmVmZXJlbmNlLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpXHJcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5wdXQucmVmZXJlbmNlLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGFjYyArPSBjaWVVdGlscy5zZXF1ZW50aWFsQWRkKCBwYXJzZUludCh0bXBJbnB1dFtpXSwxMCkgKiAoICggKGkrMSklMiAhPT0gMCApID8gMiA6IDEpICk7XHJcbiAgICB9Ki9cclxuXHJcbiAgICAvL3JldHVybiBpbnB1dC5yZWZlcmVuY2UgKyAoY2llVXRpbHMubmVhcmVzdE11bHRpcGxlT2YoYWNjLDEwKSAtIGFjYyklMTA7XHJcbiAgICByZXR1cm4gY2hlY2tEaWdpdHMoaW5wdXQucmVmZXJlbmNlLCBpbnB1dC5kYXRlLCBpbnB1dC5hbW91bnQpO1xyXG4gIH1cclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzLkFsZzExID0gQWxnMTE7XHJcblxyXG5mdW5jdGlvbiBjaGVja0RpZ2l0cyhGcG9zaXRpb25zLEVkYXRlLEFQYXkpe1xyXG5cclxuICAvKmxldCBBPTEsSj0xO1xyXG4gIGxldCBCPTIsSz0yLFM9MjtcclxuICBsZXQgQz0zLEw9MyxUPTM7XHJcbiAgbGV0IEQ9NCxNPTQsVT00O1xyXG4gIGxldCBFPTUsTj01LFY9NTtcclxuICBsZXQgRj02LE89NixXPTY7XHJcbiAgbGV0IEc9NyxQPTcsWD03O1xyXG4gIGxldCBIPTgsUT04LFk9ODtcclxuICBsZXQgST05LFI9OSxaPTk7Ki9cclxuXHJcbiAgbGV0IGNoYXJUb051bSA9e1xyXG4gICAgQToxLEo6MSxcclxuICAgIEI6MixLOjIsUzoyLFxyXG4gICAgQzozLEw6MyxUOjMsXHJcbiAgICBEOjQsTTo0LFU6NCxcclxuICAgIEU6NSxOOjUsVjo1LFxyXG4gICAgRjo2LE86NixXOjYsXHJcbiAgICBHOjcsUDo3LFg6NyxcclxuICAgIEg6OCxROjgsWTo4LFxyXG4gICAgSTo5LFI6OSxaOjlcclxuICB9O1xyXG5cclxuICBsZXQgZGF0ZSA9IEVkYXRlO1xyXG4gIGxldCBkYXRlQmFzZSA9IDIwMTQ7XHJcbiAgbGV0IGRGb3JtYXQgPSBkYXRlOy8vLnJlcGxhY2UoLy0vZywgXCJcIik7XHJcblxyXG4gIC8vRGF0ZVxyXG5cclxuICBsZXQgZGF5ID0gZEZvcm1hdC5zdWJzdHIoMCwyKTtcclxuICBsZXQgbW9udGggPSBkRm9ybWF0LnN1YnN0cigyLDIpO1xyXG4gIGxldCB5ZWFyID0gZEZvcm1hdC5zdWJzdHIoLTQpO1xyXG5cclxuICBsZXQgZCA9IHBhcnNlSW50KGRheSk7XHJcbiAgbGV0IG0gPSBwYXJzZUludChtb250aCk7XHJcbiAgbGV0IHkgPSBwYXJzZUludCh5ZWFyKTtcclxuXHJcbiAgbGV0IHJZZWFyICA9ICh5IC0gZGF0ZUJhc2UpICogMzcyO1xyXG4gIGxldCByTW9udGggPSAobSAtIDEpICogMzE7XHJcbiAgbGV0IHJEYXkgICA9IChkIC0gMSk7XHJcblxyXG4gIGxldCBkYXRlQ29uZGVuID0gKHJZZWFyK3JNb250aCtyRGF5KTtcclxuXHJcbiAgLy8gaW1wb3J0ZVxyXG5cclxuICBsZXQgVlAgPSBbNywzLDFdO1xyXG4gIGxldCByVnAgPSBbXTtcclxuICBsZXQgaVZQID0gMDtcclxuICBsZXQgaW1wID0gQVBheTtcclxuICBsZXQgaW1wRm9ybWF0MSA9IGltcC5yZXBsYWNlKC9cXC4vZywgJycpO1xyXG4gIGxldCBpbXBGb3JtYXQgID0gaW1wRm9ybWF0MS5yZXBsYWNlKC8sL2csICcnKTtcclxuICBsZXQgaUNhZCA9IGltcEZvcm1hdC5sZW5ndGgtMTtcclxuXHJcbiAgZm9yKGxldCBjb250PTA7IGNvbnQ8PWltcEZvcm1hdC5sZW5ndGg7IGNvbnQrKyl7XHJcbiAgICBpZihpVlAgPT09IFZQLmxlbmd0aCl7XHJcbiAgICAgIGlWUCA9IDA7XHJcbiAgICB9ZWxzZXtcclxuICAgICAgbGV0IHZhbG9yQyA9IGltcEZvcm1hdC5jaGFyQXQoaUNhZCk7XHJcbiAgICAgIGxldCBvVnAgPSBWUFtpVlBdO1xyXG4gICAgICBjb25zb2xlLmxvZyh2YWxvckMpO1xyXG4gICAgICBsZXQgb3AgPSBwYXJzZUludCh2YWxvckMpICogb1ZwO1xyXG4gICAgICByVnAudW5zaGlmdChvcCk7XHJcbiAgICAgIGlDYWQtLTtcclxuICAgICAgaVZQKys7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBsZXQgc3VtID0gclZwLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xyXG4gIGxldCBjRGlnaXQgPSAoc3VtICUgMTApO1xyXG5cclxuICAvL2xldCByYW5kb20gPSBNYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkqOSk7XHJcbiAgbGV0IHJhbmRvbSA9IDI7Ly9NYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkqOSk7XHJcblxyXG4gIGxldCByZXN1bHQgPSBGcG9zaXRpb25zK2RhdGVDb25kZW4rY0RpZ2l0K3JhbmRvbTtcclxuXHJcbiAgLy9SZWZlcmVuY2lhXHJcblxyXG4gIGxldCByZWZWUCA9IFsxMSwxMywxNywxOSwyM107XHJcbiAgbGV0IHJGVlAgPSBbXTtcclxuICBsZXQgaXJWUCA9IDA7XHJcbiAgbGV0IGlDYWRSZWYgPSByZXN1bHQubGVuZ3RoLTE7XHJcblxyXG4gIGZvcihsZXQgYXV4PTA7IGF1eDw9cmVzdWx0Lmxlbmd0aCsyOyBhdXgrKyl7XHJcbiAgICBpZihpclZQID09PSByZWZWUC5sZW5ndGgpe1xyXG4gICAgICBpclZQID0gMDtcclxuICAgIH1lbHNle1xyXG4gICAgICBsZXQgdmFsb3JDID0gcmVzdWx0LmNoYXJBdChpQ2FkUmVmKTtcclxuICAgICAgbGV0IG9WcCA9IHJlZlZQW2lyVlBdO1xyXG4gICAgICBsZXQgb3AgPSAoY2hhclRvTnVtW3ZhbG9yQ10/Y2hhclRvTnVtW3ZhbG9yQ106cGFyc2VJbnQodmFsb3JDKSkgKiBvVnA7XHJcbiAgICAgIHJGVlAudW5zaGlmdChvcCk7XHJcbiAgICAgIGlDYWRSZWYtLTtcclxuICAgICAgaXJWUCsrO1xyXG4gICAgfVxyXG4gIH1cclxuICBsZXQgc3VtUmVmID0gckZWUC5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcclxuICBsZXQgcmVmRGlnaXQgPSAoc3VtUmVmICUgOTcpICsgMTtcclxuICBsZXQgZExlbmd0aCA9IHJlZkRpZ2l0LnRvU3RyaW5nKCk7XHJcbiAgbGV0IGRMZW5ndGhDID0gZExlbmd0aC5sZW5ndGg7XHJcblxyXG4gIGlmKCBkTGVuZ3RoQyA9PT0gMSl7XHJcbiAgICBsZXQgWmVybyA9ICcwJztcclxuICAgIGxldCBhZGRaZXJvID0gWmVybytyZWZEaWdpdDtcclxuICAgIGxldCBmaW5hbFJlZmVyZW5jZSA9IHJlc3VsdCthZGRaZXJvO1xyXG4gICAgcmV0dXJuIGZpbmFsUmVmZXJlbmNlO1xyXG4gIH1lbHNle1xyXG4gICAgbGV0IGZpbmFsUmVmZXJlbmNlID0gcmVzdWx0K3JlZkRpZ2l0O1xyXG4gICAgcmV0dXJuIGZpbmFsUmVmZXJlbmNlO1xyXG4gIH1cclxuLy9cclxufVxyXG4iLCJcclxuJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMTQgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMTQucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzE0LnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuICAgIHZhciB2YWxpZGF0aW9uUnVsZXMgPSB7XHJcbiAgICAgIHJlZmVyZW5jZToge2xlbmd0aDoge21pbjogMSxtYXg6IDE4fX1cclxuICAgIH07XHJcblxyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LCB2YWxpZGF0aW9uUnVsZXMpKSB7XHJcbiAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgICAgZXJyb3Iuc3RhdHVzID0gJzQyMic7XHJcbiAgICAgIHRocm93IGVycm9yO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtVmVyaWZpY2Fkb3IoaW5wdXQucmVmZXJlbmNlKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGcxNCA9IEFsZzE0O1xyXG5cclxuZnVuY3Rpb24gbVZlcmlmaWNhZG9yKHJlZil7XHJcblxyXG4gIGxldCBjaGFyVG9OdW0gPSB7XHJcbiAgICBBOjEsSjoxLFxyXG4gICAgQjoyLEs6MixTOjIsXHJcbiAgICBDOjMsTDozLFQ6MyxcclxuICAgIEQ6NCxNOjQsVTo0LFxyXG4gICAgRTo1LE46NSxWOjUsXHJcbiAgICBGOjYsTzo2LFc6NixcclxuICAgIEc6NyxQOjcsWDo3LFxyXG4gICAgSDo4LFE6OCxZOjgsXHJcbiAgICBJOjksUjo5LFo6OVxyXG4gIH07XHJcblxyXG4gIGxldCB2YWxvcmVzUG9uZGVyYWRvcmVzID0gWzEzLDE3LDE5LDIzLDExXTtcclxuICBsZXQgdmFsb3JlcyA9IFtdO1xyXG4gIC8vbGV0IGNhZGVuYSA9ICcwMDBTQVI0MjgwJztcclxuICBsZXQgaW5kaWNlID0gcmVmLmxlbmd0aC0yO1xyXG4gIGxldCBpbmRpY2VWUCA9IDA7XHJcblxyXG5cclxuICBmb3IobGV0IGNvbnRhZG9yPTA7IGNvbnRhZG9yPHJlZi5sZW5ndGgtMTsgY29udGFkb3IrKyl7XHJcbiAgICBpZihpbmRpY2VWUCA9PT0gdmFsb3Jlc1BvbmRlcmFkb3Jlcy5sZW5ndGgpe1xyXG4gICAgICBpbmRpY2VWUCA9IDA7XHJcbiAgICB9XHJcbiAgICAgIGxldCB2YWxvckMgPSByZWYuY2hhckF0KGluZGljZSk7XHJcbiAgICAgIGxldCB2cCA9IHZhbG9yZXNQb25kZXJhZG9yZXNbaW5kaWNlVlBdO1xyXG4gICAgICBsZXQgb3AgPSAoY2hhclRvTnVtW3ZhbG9yQ10/Y2hhclRvTnVtW3ZhbG9yQ106cGFyc2VJbnQodmFsb3JDKSkgKiB2cDtcclxuICAgICAgdmFsb3Jlcy51bnNoaWZ0KG9wKTtcclxuICAgICAgaW5kaWNlLS07XHJcbiAgICAgIGluZGljZVZQKys7XHJcbiAgfVxyXG4gIGxldCBzdW1hID0gdmFsb3Jlcy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcclxuICBsZXQgc3VtYVRvdGFsID0gc3VtYSArIDMzMDtcclxuICBsZXQgcmVzaWR1byA9IChzdW1hVG90YWwgJSA5Nyk7XHJcbiAgbGV0IGRWZXJpZmljYWRvciA9IChyZXNpZHVvKzEpO1xyXG4gIGxldCB2Q2FkZW5hID0gZFZlcmlmaWNhZG9yLnRvU3RyaW5nKCk7XHJcbiAgbGV0IHJlZmVyZW5jaWEgPSByZWYrdkNhZGVuYTtcclxuICByZXR1cm4gcmVmZXJlbmNpYTtcclxufVxyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMjEgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMjEucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzIxLnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMjB9fSxcclxuICAgICAgZGF0ZToge2xlbmd0aDoge21pbjogOCxtYXg6IDh9fSxcclxuICAgICAgYW1vdW50OiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTV9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcbiAgICB2YXIgY29uZGVuc2VkSW5wdXQgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShfLnRvQXJyYXkoY29uZGVuc2VkSW5wdXQucmVmZXJlbmNlKS5yZXZlcnNlKCksWzExLDEzLDE3LDE5LDIzXSk7XHJcbiAgICB2YXIgYWNjXzIgPSAoKGFjYyAlIDk3KSsxKSUxMDtcclxuXHJcbiAgICByZXR1cm4gY29uZGVuc2VkSW5wdXQucmVmZXJlbmNlICsgYWNjXzI7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnMjEgPSBBbGcyMTtcclxuXHJcbnZhciBpc0xlYXAgPSBmdW5jdGlvbih5ZWFyKSB7XHJcbiAgY29uc29sZS5sb2coJ3llYXInLHllYXIpO1xyXG4gIHJldHVybiBuZXcgRGF0ZSh5ZWFyLCAxLCAyOSkuZ2V0RGF0ZSgpID09PSAyOTtcclxufVxyXG4vLyBUT0RPIE1heWJlIG1vdmUgdGhpcyB0byBhIHRlbXBsYXRlP1xyXG52YXIgcGFyc2VJbnB1dCA9IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgdmFyIG1vbnRoX211bHRpcGxpZXIgPSAzMTtcclxuICBzd2l0Y2ggKGlucHV0LmRhdGUuc3Vic3RyKDIsMikpIHtcclxuICAgIGNhc2UgNDpcclxuICAgIGNhc2UgNjpcclxuICAgIGNhc2UgOTpcclxuICAgIGNhc2UgMTE6XHJcbiAgICAgIG1vbnRoX211bHRpcGxpZXIgPSAzMDtcclxuICAgICAgYnJlYWs7XHJcbiAgICBjYXNlIDI6XHJcbiAgICAgIG1vbnRoX211bHRpcGxpZXIgPSAoaXNMZWFwKGlucHV0LmRhdGUuc3Vic3RyKDQsNCkpID8gMjkgOiAyOClcclxuICAgICAgYnJlYWs7XHJcbiAgfVxyXG4gIHZhciBwYWRkZWREYXRlID0gY2llVXRpbHMucGFkKChpbnB1dC5kYXRlLnN1YnN0cig0LDQpLTIwMTQpKjM2MCArIChpbnB1dC5kYXRlLnN1YnN0cigyLDIpLTEpKm1vbnRoX211bHRpcGxpZXIgKyAoaW5wdXQuZGF0ZS5zdWJzdHIoMCwyKS0xKSw0KTtcclxuICB2YXIgcGFkZGVkQW1vdW50MSA9IGNpZVV0aWxzLndlaWdodGVkUmVkdWNlKF8ud2l0aG91dChfLnRvQXJyYXkoaW5wdXQuYW1vdW50KSwnLicpLnJldmVyc2UoKSxbMSwyLDMsNywxMSwxMywxN10pJTEwO1xyXG4gIHZhciBwYWRkZWRBbW91bnQyID0gY2llVXRpbHMud2VpZ2h0ZWRSZWR1Y2UoXy53aXRob3V0KF8udG9BcnJheShpbnB1dC5hbW91bnQpLCcuJykucmV2ZXJzZSgpLFsyLDMsNywxMSwxMywxNywxXSklMTA7XHJcbiAgdmFyIHBhZGRlZEFtb3VudDMgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShfLndpdGhvdXQoXy50b0FycmF5KGlucHV0LmFtb3VudCksJy4nKS5yZXZlcnNlKCksWzMsNywxMSwxMywxNywxLDJdKSUxMDtcclxuXHJcbiAgdmFyIHRtcF9yZWZlcmVuY2UgPSBpbnB1dC5yZWZlcmVuY2UgKyBwYWRkZWREYXRlICsgcGFkZGVkQW1vdW50MSArIHBhZGRlZEFtb3VudDIgKyBwYWRkZWRBbW91bnQzO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcmVmZXJlbmNlOiB0bXBfcmVmZXJlbmNlLFxyXG4gICAgYW1vdW50OiAnJyArIHBhZGRlZEFtb3VudDEgKyBwYWRkZWRBbW91bnQyICsgcGFkZGVkQW1vdW50MyxcclxuICAgIGRhdGU6IHBhZGRlZERhdGVcclxuICB9O1xyXG59O1xyXG4iLCJcclxuJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMjcgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMjcucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzI3LnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuICAgIHZhciB2YWxpZGF0aW9uUnVsZXMgPSB7XHJcbiAgICAgIHJlZmVyZW5jZTogIHtsZW5ndGg6IHttaW46IDEsICBtYXg6IDE4fX0sXHJcbiAgICAgIGFjY291bnQ6ICAgIHtsZW5ndGg6IHttaW46IDEsICAgbWF4OiA4fX0sXHJcbiAgICAgIGJyYW5jaDogICAgIHtsZW5ndGg6IHttaW46IDEsICAgbWF4OiA4fX1cclxuICAgIH07XHJcblxyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LCB2YWxpZGF0aW9uUnVsZXMpKSB7XHJcbiAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgICAgZXJyb3Iuc3RhdHVzID0gJzQyMic7XHJcbiAgICAgIHRocm93IGVycm9yO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBhcHBseUFsZ29yaXRobTI3KGlucHV0LnJlZmVyZW5jZSwgaW5wdXQuYnJhbmNoLCBpbnB1dC5hY2NvdW50KTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGcyNyA9IEFsZzI3O1xyXG5cclxubGV0IGFwcGx5QWxnb3JpdGhtMjcgPSAocmVmZXJlbmNlLCBzdWN1cnNhbCwgYWNjb3VudCkgPT4ge1xyXG4gIGxldCB2YWxpZGF0b3IgPSBuZXcgUmVnRXhwKC9eWzAtOUEtWl17MywyMH0kL2cpXHJcblxyXG4gIGxldCByZWZlcmVuY2VFbmNvZGVyID0ge1xyXG4gICAgXCJBXCI6IDIsIFwiQlwiOiAyLCBcIkNcIjogMiwgXCJEXCI6IDMsIFwiRVwiOiAzLFxyXG4gICAgXCJGXCI6IDMsIFwiR1wiOiA0LCBcIkhcIjogNCwgXCJJXCI6IDQsIFwiSlwiOiA1LFxyXG4gICAgXCJLXCI6IDUsIFwiTFwiOiA1LCBcIk1cIjogNiwgXCJOXCI6IDYsIFwiT1wiOiA2LFxyXG4gICAgXCJQXCI6IDcsIFwiUVwiOiA3LCBcIlJcIjogNywgXCJTXCI6IDgsIFwiVFwiOiA4LFxyXG4gICAgXCJVXCI6IDgsIFwiVlwiOiA5LCBcIldcIjogOSwgXCJYXCI6IDksIFwiWVwiOiAwLFxyXG4gICAgXCJaXCI6IDAsIFwiMFwiOiAwLCBcIjFcIjogMSwgXCIyXCI6IDIsIFwiM1wiOiAzLFxyXG4gICAgXCI0XCI6IDQsIFwiNVwiOiA1LCBcIjZcIjogNiwgXCI3XCI6IDcsIFwiOFwiOiA4LCBcIjlcIjogOSxcclxuICB9O1xyXG5cclxuICBsZXQgZnVsbFJlZmVyZW5jZSA9IFwiXCI7XHJcbiAgLy8gbGV0IHN1Y3Vyc2FsID0gXCI3MDA2XCI7XHJcbiAgLy8gbGV0IGFjY291bnQgPSBcIjAwODYzMzY3XCI7XHJcblxyXG4gIGlmKHZhbGlkYXRvci50ZXN0KHJlZmVyZW5jZSkpIHtcclxuICAgIGZvcihsZXQgbGV0dGVyIG9mIHJlZmVyZW5jZSl7XHJcbiAgICAgIGZ1bGxSZWZlcmVuY2UgKz0gcmVmZXJlbmNlRW5jb2RlcltsZXR0ZXJdO1xyXG4gICAgfVxyXG5cclxuICAgIHdoaWxlKGZ1bGxSZWZlcmVuY2UubGVuZ3RoIDwgMTgpe1xyXG4gICAgICBmdWxsUmVmZXJlbmNlID0gYDAke2Z1bGxSZWZlcmVuY2V9YDtcclxuICAgIH1cclxuXHJcbiAgICBmdWxsUmVmZXJlbmNlID0gYCR7YWNjb3VudH0ke2Z1bGxSZWZlcmVuY2V9YDtcclxuICAgIGZ1bGxSZWZlcmVuY2UgPSBgMDAwMDAke2Z1bGxSZWZlcmVuY2V9YDtcclxuICAgIGZ1bGxSZWZlcmVuY2UgPSBgJHtzdWN1cnNhbH0ke2Z1bGxSZWZlcmVuY2V9YDtcclxuXHJcbiAgICBsZXQgc2VyaWUgICA9IFsxLCAyLCAzLCA1LCA3LCAxMSwgMTMsIDE3LCAxOSwgMjMsIDI5LCAzMSwgMzddO1xyXG4gICAgbGV0IHJlc3VsdHMgPSBbXTtcclxuICAgIGxldCBzZXJpZUluZGV4ID0gMTI7XHJcblxyXG4gICAgZnVsbFJlZmVyZW5jZSA9IGZ1bGxSZWZlcmVuY2Uuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIik7XHJcblxyXG4gICAgZm9yKGxldCBudW1iZXIgb2YgZnVsbFJlZmVyZW5jZSkge1xyXG4gICAgICAvL2NvbnNvbGUubG9nKGAke251bWJlcn0gKiAke3NlcmllW3NlcmllSW5kZXhdfSA9ICR7bnVtYmVyICogc2VyaWVbc2VyaWVJbmRleF19YCk7XHJcbiAgICAgIHJlc3VsdHMucHVzaChudW1iZXIgKiBzZXJpZVtzZXJpZUluZGV4XSk7XHJcbiAgICAgIHNlcmllSW5kZXggPSAoc2VyaWVJbmRleCAhPT0gMCkgPyBzZXJpZUluZGV4IC0gMSA6IDEyO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBzdW0gPSAwO1xyXG4gICAgZm9yKGxldCByZXN1bHQgb2YgcmVzdWx0cyl7XHJcbiAgICAgIHN1bSArPSByZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHJlcyAgICA9IHN1bSAlIDk3O1xyXG4gICAgbGV0IGRpZ2l0cyA9IDk5IC0gcmVzO1xyXG5cclxuICAgIGxldCBnZXREaWdpdHMgPSAobnVtYmVyKSA9PiB7XHJcbiAgICAgIHJldHVybiAobnVtYmVyLnRvU3RyaW5nKCkubGVuZ3RoID09PSAyKSA/IG51bWJlciA6IGAwJHtudW1iZXJ9YDtcclxuICAgIH07XHJcblxyXG4gICAgLy9kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInJlc3BvbnNlXCIpLmlubmVySFRNTCA9IGAke3JlZmVyZW5jZX0ke2dldERpZ2l0cyhkaWdpdHMpfWA7XHJcbiAgICByZXR1cm4gYCR7cmVmZXJlbmNlfSR7Z2V0RGlnaXRzKGRpZ2l0cyl9YDtcclxuICB9IGVsc2Uge1xyXG4gICAgLy9hbGVydChcIklucHV0IGludmFsaWRcIik7XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG59O1xyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGczNSA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGczNS5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnMzUucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsIG1heDogMTl9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGFjYyA9IGNpZVV0aWxzLnNlcXVlbnRpYWxXZWlnaHRlZFJlZHVjZShwYXJzZUlucHV0KGlucHV0KSwgWzQsMyw4XSk7XHJcbiAgICByZXR1cm4gaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCkgKyAoY2llVXRpbHMubmVhcmVzdE11bHRpcGxlT2YoYWNjLDEwKSAtIGFjYyklMTA7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnMzUgPSBBbGczNTtcclxuXHJcbnZhciBwYXJzZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuICB2YXIgY2hhclRvTnVtID0ge1xyXG4gICAgQTogMSwgQjogMiwgQzogMywgRDogNCwgRTogNSwgRjogNiwgRzogNywgSDogOCwgSTogOSwgSjogMTAsIEs6IDExLCBMOiAxMiwgTTogMTMsXHJcbiAgICBOOiAxNCxPOiAxNSwgUDogMTYsIFE6IDE3LCBSOiAxOCwgUzogMTksIFQ6IDIwLCBVOiAyMSwgVjogMjIsIFc6IDIzLCBYOiAyNCwgWTogMjUsXHJcbiAgICBaOiAyNiwxOiAxLCAyOiAyLCAzOiAzLCA0OiA0LCA1OiA1LCA2OiA2LCA3OiA3LCA4OiA4LCA5OiA5LCAwOiAwXHJcbiAgfTtcclxuICByZXR1cm4gY2llVXRpbHMucmVwbGFjZUNoYXJXaXRoTnVtKGlucHV0LnJlZmVyZW5jZS50b1VwcGVyQ2FzZSgpLCBjaGFyVG9OdW0pO1xyXG59O1xyXG5cclxuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzM2ID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzM2LnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGczNi5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuICAgIHZhciB2YWxpZGF0aW9uUnVsZXMgPSB7XHJcbiAgICAgIHJlZmVyZW5jZToge2xlbmd0aDoge21pbjogMSwgbWF4OiAxOX19XHJcbiAgICB9O1xyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LCB2YWxpZGF0aW9uUnVsZXMpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYWNjID0gY2llVXRpbHMuc2VxdWVudGlhbFdlaWdodGVkUmVkdWNlKHBhcnNlSW5wdXQoaW5wdXQpLCBbMiwxXSk7XHJcbiAgICByZXR1cm4gaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCkgKyAoY2llVXRpbHMubmVhcmVzdE11bHRpcGxlT2YoYWNjLDEwKSAtIGFjYyklMTA7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnMzYgPSBBbGczNjtcclxuXHJcbnZhciBwYXJzZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuICB2YXIgY2hhclRvTnVtID0ge1xyXG4gICAgQTogMSwgQjogMiwgQzogMywgRDogNCwgRTogNSwgRjogNiwgRzogNywgSDogOCwgSTogOSxcclxuICAgIEo6IDEsIEs6IDIsIEw6IDMsIE06IDQsTjogNSwgTzogNiwgUDogNywgUTogOCwgUjogOSxcclxuICAgIFM6IDEsIFQ6IDIsIFU6IDMsIFY6IDQsIFc6IDUsIFg6IDYsIFk6IDcsWjogOCxcclxuICAgIDE6IDEsIDI6IDIsIDM6IDMsIDQ6IDQsIDU6IDUsIDY6IDYsIDc6IDcsIDg6IDgsIDk6IDksIDA6IDBcclxuICB9O1xyXG4gIHJldHVybiBfLnRvQXJyYXkoY2llVXRpbHMucmVwbGFjZUNoYXJXaXRoTnVtKGlucHV0LnJlZmVyZW5jZS50b1VwcGVyQ2FzZSgpLCBjaGFyVG9OdW0pKS5yZXZlcnNlKCk7XHJcbn07XHJcblxyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnMzcgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnMzcucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzM3LnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLCBtYXg6IDE5fX1cclxuICAgIH07XHJcbiAgICBpZiAoIWNpZVV0aWxzLnZhbGlkYXRlSW5wdXQoaW5wdXQsIHZhbGlkYXRpb25SdWxlcykpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb25naXR1ZCBpbnZhbGlkYScpO1xyXG4gICAgfVxyXG5cclxuICAgIHZhciByZWZlcmVuY2UgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShyZWZlcmVuY2UsIFsxMSwxMywxNywgMTksMjNdKTtcclxuXHJcbiAgICByZXR1cm4gaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCkgKyBjaWVVdGlscy5wYWQoKChhY2MgKyAzMzAgLSByZWZlcmVuY2VbMF0qMTEpJTk3KSsxLDIpO1xyXG4gIH1cclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzLkFsZzM3ID0gQWxnMzc7XHJcblxyXG52YXIgcGFyc2VJbnB1dCA9IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgdmFyIGNoYXJUb051bSA9IHtcclxuICAgIEE6IDEsIEI6IDIsIEM6IDMsIEQ6IDQsIEU6IDUsIEY6IDYsIEc6IDcsIEg6IDgsIEk6IDksXHJcbiAgICBKOiAxLCBLOiAyLCBMOiAzLCBNOiA0LE46IDUsIE86IDYsIFA6IDcsIFE6IDgsIFI6IDksXHJcbiAgICBTOiAxLCBUOiAyLCBVOiAzLCBWOiA0LCBXOiA1LCBYOiA2LCBZOiA3LFo6IDgsXHJcbiAgICAxOiAxLCAyOiAyLCAzOiAzLCA0OiA0LCA1OiA1LCA2OiA2LCA3OiA3LCA4OiA4LCA5OiA5LCAwOiAwXHJcbiAgfTtcclxuICByZXR1cm4gXy50b0FycmF5KGNpZVV0aWxzLnJlcGxhY2VDaGFyV2l0aE51bShpbnB1dC5yZWZlcmVuY2UudG9VcHBlckNhc2UoKSwgY2hhclRvTnVtKSkucmV2ZXJzZSgpO1xyXG59O1xyXG5cclxuIiwiXHJcbid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzQ1ID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzQ1LnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGc0NS5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMH19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19XHJcbiAgICB9O1xyXG5cclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICAgIGVycm9yLnN0YXR1cyA9ICc0MjInO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYXBwbHlBbGdvcml0aG00NShpbnB1dC5kYXRlLCBpbnB1dC5hbW91bnQsIGlucHV0LnJlZmVyZW5jZSk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnNDUgPSBBbGc0NTtcclxuXHJcbmxldCBiYXNlMzZFbmNvZGVyID0ge1xyXG4gIDA6IFwiMFwiLCAxOiBcIjFcIiwgMjogXCIyXCIsIDM6IFwiM1wiLCA0OiBcIjRcIixcclxuICA1OiBcIjVcIiwgNjogXCI2XCIsIDc6IFwiN1wiLCA4OiBcIjhcIiwgOTogXCI5XCIsXHJcbiAgMTA6IFwiQVwiLCAxMTogXCJCXCIsIDEyOiBcIkNcIiwgMTM6IFwiRFwiLCAxNDogXCJFXCIsXHJcbiAgMTU6IFwiRlwiLCAxNjogXCJHXCIsIDE3OiBcIkhcIiwgMTg6IFwiSVwiLCAxOTogXCJKXCIsXHJcbiAgMjA6IFwiS1wiLCAyMTogXCJMXCIsIDIyOiBcIk1cIiwgMjM6IFwiTlwiLCAyNDogXCJPXCIsXHJcbiAgMjU6IFwiUFwiLCAyNjogXCJRXCIsIDI3OiBcIlJcIiwgMjg6IFwiU1wiLCAyOTogXCJUXCIsXHJcbiAgMzA6IFwiVVwiLCAzMTogXCJWXCIsIDMyOiBcIldcIiwgMzM6IFwiWFwiLCAzNDogXCJZXCIsIDM1OiBcIlpcIixcclxufVxyXG5cclxubGV0IHJlZmVyZW5jZUVuY29kZXIgPSB7XHJcbiAgXCJBXCI6IDEsIFwiQlwiOiAyLCBcIkNcIjogMywgXCJEXCI6IDQsIFwiRVwiOiA1LFxyXG4gIFwiRlwiOiA2LCBcIkdcIjogNywgXCJIXCI6IDgsIFwiSVwiOiA5LCBcIkpcIjogMSxcclxuICBcIktcIjogMiwgXCJMXCI6IDMsIFwiTVwiOiA0LCBcIk5cIjogNSwgXCJPXCI6IDYsXHJcbiAgXCJQXCI6IDcsIFwiUVwiOiA4LCBcIlJcIjogOSwgXCJTXCI6IDEsIFwiVFwiOiAyLFxyXG4gIFwiVVwiOiAzLCBcIlZcIjogNCwgXCJXXCI6IDUsIFwiWFwiOiA2LCBcIllcIjogNyxcclxuICBcIlpcIjogOCwgXCIwXCI6IDAsIFwiMVwiOiAxLCBcIjJcIjogMiwgXCIzXCI6IDMsXHJcbiAgXCI0XCI6IDQsIFwiNVwiOiA1LCBcIjZcIjogNiwgXCI3XCI6IDcsIFwiOFwiOiA4LCBcIjlcIjogOSxcclxufVxyXG5cclxuZnVuY3Rpb24gZ2VuZXJhdGVSZW1haW5pbmdMaXN0KG51bWJlcikge1xyXG4gIGxldCByZW1haW5pbmdMaXN0ID0gW107XHJcbiAgbGV0IHF1b3RpZW50ICAgICAgPSBudW1iZXI7XHJcblxyXG4gIHdoaWxlKE1hdGgudHJ1bmMocXVvdGllbnQpICE9IDApIHtcclxuICAgIHJlbWFpbmluZ0xpc3QucHVzaChxdW90aWVudCAlIDM2KTtcclxuICAgIHF1b3RpZW50ID0gTWF0aC50cnVuYyhxdW90aWVudCAvIDM2KTtcclxuICB9XHJcblxyXG4gIHJldHVybiByZW1haW5pbmdMaXN0O1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZW5lcmF0ZUNvZGUocmVtYWluaW5nTGlzdCkge1xyXG4gIGxldCBjb2RlID0gXCJcIjtcclxuICBmb3IobGV0IG51bWJlciBvZiByZW1haW5pbmdMaXN0KVxyXG4gICAgY29kZSArPSBiYXNlMzZFbmNvZGVyW251bWJlcl07XHJcblxyXG4gIHJldHVybiBjb2RlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBhZGRaZXJvcyhudW1iZXIsIGxpbWl0KSB7XHJcbiAgd2hpbGUobnVtYmVyLmxlbmd0aCA8IGxpbWl0KSB7XHJcbiAgICBudW1iZXIgPSBgMCR7bnVtYmVyfWA7XHJcbiAgfVxyXG4gIHJldHVybiBudW1iZXI7XHJcbn1cclxuXHJcbi8qZnVuY3Rpb24gaXNWYWxpZCAoKSB7XHJcbiAgbGV0IGRhdGVWYWxpZGF0b3IgICAgICA9IG5ldyBSZWdFeHAoL15bMC05XXs4fSQvKVxyXG4gIGxldCBhbW91bnRWYWxpZGF0b3IgICAgPSBuZXcgUmVnRXhwKC9eWzAtOV0rLlswLTldezJ9JC8pXHJcbiAgbGV0IHJlZmVyZW5jZVZhbGlkYXRvciA9IG5ldyBSZWdFeHAoL15bMC05QS1aXXsxMCwyMH0kL2cpXHJcblxyXG4gIGlmIChkYXRlVmFsaWRhdG9yLnRlc3QoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUnKS52YWx1ZSksXHJcbiAgICAgIGFtb3VudFZhbGlkYXRvci50ZXN0KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhbW91bnQnKS52YWx1ZSksXHJcbiAgICAgIHJlZmVyZW5jZVZhbGlkYXRvci50ZXN0KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyZWZlcmVuY2UnKS52YWx1ZSkpIHtcclxuICAgIGFwcGx5QWxnb3JpdGhtNDUoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGUnKS52YWx1ZSwgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2Ftb3VudCcpLnZhbHVlLCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncmVmZXJlbmNlJykudmFsdWUpXHJcbiAgfSBlbHNlIHtcclxuICAgIGFsZXJ0KFwiaW52YWxpZFwiKVxyXG4gIH1cclxufSovXHJcblxyXG4vL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYnRuXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBpc1ZhbGlkKTtcclxuXHJcbmZ1bmN0aW9uIGFwcGx5QWxnb3JpdGhtNDUoZGF0ZSwgYW1vdW50LCByZWZlcmVuY2UpIHtcclxuICBjb25zb2xlLmxvZyhkYXRlLCBhbW91bnQsIHJlZmVyZW5jZSlcclxuICByZWZlcmVuY2UgPSByZWZlcmVuY2UudG9VcHBlckNhc2UoKTtcclxuICBcclxuICBsZXQgZGF0ZUNvZGUgPSBnZW5lcmF0ZUNvZGUoZ2VuZXJhdGVSZW1haW5pbmdMaXN0KGAke2RhdGUuc3Vic3RyaW5nKDAsIDQpfSR7ZGF0ZS5zdWJzdHJpbmcoZGF0ZS5sZW5ndGgtMiwgZGF0ZS5sZW5ndGgpfWApKTtcclxuICBsZXQgcmV2ZXJzZURhdGVDb2RlID0gKGRhdGVDb2RlLmxlbmd0aCA8IDQpID8gYWRkWmVyb3MoZGF0ZUNvZGUuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIiksIDQpIDogZGF0ZUNvZGUuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIik7XHJcblxyXG4gIC8vLy8vLy8vLy8vLy8vL1xyXG5cclxuICBsZXQgZnVsbEFtb3VudCA9IG51bGw7XHJcbiAgaWYoYW1vdW50LmluY2x1ZGVzKCcuJykpXHJcbiAgICBmdWxsQW1vdW50ID0gYW1vdW50LnNwbGl0KCcuJykuam9pbihcIlwiKTtcclxuICBlbHNlXHJcbiAgICBmdWxsQW1vdW50ID0gYW1vdW50O1xyXG5cclxuICBsZXQgYW1vdW50Q29kZSA9IGdlbmVyYXRlQ29kZShnZW5lcmF0ZVJlbWFpbmluZ0xpc3QoZnVsbEFtb3VudCkpO1xyXG5cclxuICBsZXQgcmV2ZXJzZUFtb3VudENvZGUgPSAoYW1vdW50Q29kZS5sZW5ndGggPCA0KSA/IGFkZFplcm9zKGFtb3VudENvZGUuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIiksIDUpIDogYW1vdW50Q29kZS5zcGxpdChcIlwiKS5yZXZlcnNlKCkuam9pbihcIlwiKTtcclxuXHJcbiAgLy8vLy8vLy8vLy8vLy8vXHJcblxyXG4gIGxldCBmdWxsUmVmZXJlbmNlID0gYCR7cmVmZXJlbmNlfSR7cmV2ZXJzZURhdGVDb2RlfSR7cmV2ZXJzZUFtb3VudENvZGV9YFxyXG5cclxuICBsZXQgZW5jb2RlZFJlZmVyZW5jZSA9IFwiXCI7XHJcbiAgZm9yKGxldCBpdGVtIG9mIGZ1bGxSZWZlcmVuY2UpXHJcbiAgICBlbmNvZGVkUmVmZXJlbmNlICs9IHJlZmVyZW5jZUVuY29kZXJbaXRlbV07XHJcblxyXG4gIGxldCBzZXJpZSAgID0gWzEsIDJdO1xyXG4gIGxldCByZXN1bHRzID0gW107XHJcbiAgbGV0IHNlcmllSW5kZXggPSAxO1xyXG5cclxuICBmb3IobGV0IG51bWJlciBvZiBlbmNvZGVkUmVmZXJlbmNlLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpKSB7XHJcbiAgICByZXN1bHRzLnB1c2gobmV3IFN0cmluZyhudW1iZXIgKiBzZXJpZVtzZXJpZUluZGV4XSkpXHJcbiAgICBzZXJpZUluZGV4ID0gKHNlcmllSW5kZXggIT0gMCkgPyBzZXJpZUluZGV4IC0gMSA6IDE7XHJcbiAgfVxyXG5cclxuICBsZXQgc2luZ2xlTnVtYmVycyA9IFtdO1xyXG4gIGZvcihsZXQgbnVtYmVyIG9mIHJlc3VsdHMpIHtcclxuICAgIGlmKG51bWJlci5sZW5ndGggPiAxKVxyXG4gICAgICBzaW5nbGVOdW1iZXJzLnB1c2gobnVtYmVyLnNwbGl0KFwiXCIpLnJlZHVjZSgocHJldmlvdXMsIGN1cnJlbnQpID0+IHsgcmV0dXJuIChuZXcgTnVtYmVyKHByZXZpb3VzKSArIG5ldyBOdW1iZXIoY3VycmVudCkpIH0sIDApKVxyXG4gICAgZWxzZVxyXG4gICAgICBzaW5nbGVOdW1iZXJzLnB1c2gobmV3IE51bWJlcihudW1iZXIpKTtcclxuICB9XHJcblxyXG4gIGxldCBzdW0gPSBzaW5nbGVOdW1iZXJzLnJlZHVjZSgocHJldmlvdXMsIGN1cnJlbnQpID0+IHsgcmV0dXJuIHByZXZpb3VzICsgY3VycmVudCB9LCAwKTtcclxuXHJcbiAgbGV0IGRpZ2l0ID0gKDEwIC0gbmV3IE51bWJlciggKG5ldyBTdHJpbmcoc3VtICUgMTApLmxlbmd0aCA+IDEpID8gbmV3IFN0cmluZyhzdW0gJSAxMCkuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIilbMF0gOiBzdW0gJSAxMCkgKTtcclxuXHJcbiAgaWYoZGlnaXQgPT09IDEwKVxyXG4gICAgZGlnaXQgPSAwO1xyXG5cclxuICBjb25zb2xlLmxvZyhmdWxsUmVmZXJlbmNlLCBkaWdpdClcclxuICAvL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwicmVzcG9uc2VcIikuaW5uZXJIVE1MID0gYCR7ZnVsbFJlZmVyZW5jZX0ke2RpZ2l0fWA7XHJcbiAgcmV0dXJuIGAke2Z1bGxSZWZlcmVuY2V9JHtkaWdpdH1gO1xyXG59XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBfID0gcmVxdWlyZSgndW5kZXJzY29yZScpO1xyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGc2MiA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGc2Mi5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnNjIucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMH19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19XHJcbiAgICB9O1xyXG4gICAgaWYgKCFjaWVVdGlscy52YWxpZGF0ZUlucHV0KGlucHV0LHZhbGlkYXRpb25SdWxlcyApKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignTG9uZ2l0dWQgaW52YWxpZGEnKTtcclxuICAgIH1cclxuICAgIHZhciBjb25kZW5zZWRJbnB1dCA9IHBhcnNlSW5wdXQoaW5wdXQpO1xyXG5cclxuICAgIHJldHVybiBpbnB1dC5yZWZlcmVuY2UgKyBjb25kZW5zZWRJbnB1dC5kYXRlICsgY29uZGVuc2VkSW5wdXQuYW1vdW50ICsgJzInO1xyXG4gIH1cclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzLkFsZzYyID0gQWxnNjI7XHJcblxyXG4vLyBUT0RPIE1heWJlIG1vdmUgdGhpcyB0byBhIHRlbXBsYXRlP1xyXG52YXIgcGFyc2VJbnB1dCA9IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgdmFyIHBhZGRlZERhdGUgPSBjaWVVdGlscy5wYWQoKGlucHV0LmRhdGUuc3Vic3RyKDQsNCktMTk4OCkqMzcyICsgKGlucHV0LmRhdGUuc3Vic3RyKDIsMiktMSkqMzEgKyAoaW5wdXQuZGF0ZS5zdWJzdHIoMCwyKS0xKSw0KTtcclxuICB2YXIgZXhwYW5kZWRBbW91bnQgPSBmb29BbW91bnQoXy53aXRob3V0KF8udG9BcnJheShpbnB1dC5hbW91bnQpLCcuJykpO1xyXG4gIHZhciByZWR1Y2VkQW1vdW50ID0gd2VpZ2h0ZWRSZWR1Y2VXaXRoTXVsdChfLnRvQXJyYXkoZXhwYW5kZWRBbW91bnQpLnJldmVyc2UoKSxbNywzLDFdKTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHJlZmVyZW5jZTogXy50b0FycmF5KGlucHV0LnJlZmVyZW5jZSArIHBhZGRlZERhdGUgKyByZWR1Y2VkQW1vdW50ICsgJzInKS5yZXZlcnNlKCksXHJcbiAgICBhbW91bnQ6IHJlZHVjZWRBbW91bnQsXHJcbiAgICBkYXRlOiBwYWRkZWREYXRlXHJcbiAgfTtcclxufTtcclxuXHJcbnZhciBmb29BbW91bnQgPSBmdW5jdGlvbihhbW91bnQpIHtcclxuICByZXR1cm4gXy5yZWR1Y2UoYW1vdW50LCBmdW5jdGlvbihtZW1vLCBudW0pIHtcclxuICAgIHZhciB4ID0gKG1lbW8ubGVuZ3RoIDwgOCkgPyAobnVtICsgKHBhcnNlSW50KG51bSkrMSkpICsgJycgOiBudW07XHJcbiAgICByZXR1cm4gbWVtbyArIHg7XHJcbiAgfSwnJylcclxufTtcclxuXHJcbnZhciB3ZWlnaHRlZFJlZHVjZVdpdGhNdWx0ID0gZnVuY3Rpb24oaW5wdXQsIHdlaWdodHMsIGRlYnVnKSB7XHJcbiAgdmFyIGFjYyA9IDA7XHJcbiAgdmFyIGFjYzIgPSAnJztcclxuICBmb3IgKHZhciBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICBpZiAoZGVidWcpXHJcbiAgICAgIHtcclxuICAgICAgICBjb25zb2xlLmxvZygnaW5wdXQ6ICcgKyBpbnB1dFtpXSArICcgdzogJyArIHdlaWdodHNbaSV3ZWlnaHRzLmxlbmd0aF0gKyAnID0gJyArIHBhcnNlSW50KGlucHV0W2ldICogd2VpZ2h0c1tpJXdlaWdodHMubGVuZ3RoXSkpO1xyXG4gICAgICB9XHJcbiAgICAgIGFjYyArPSBwYXJzZUludChpbnB1dFtpXSAqIHdlaWdodHNbaSV3ZWlnaHRzLmxlbmd0aF0pO1xyXG4gICAgICBhY2MgPSBjaWVVdGlscy5zZXF1ZW50aWFsQWRkKGFjYyk7XHJcbiAgICAgIGlmIChwYXJzZUludChpKSAlIDMgPT0gMikge1xyXG4gICAgICAgIGFjYzIgKz0gYWNjICUgMTA7XHJcbiAgICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIGFjYzI7XHJcbn07XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBfID0gcmVxdWlyZSgndW5kZXJzY29yZScpO1xyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGc3MiA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGc3Mi5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnNzIucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcblxyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogNDB9fSxcclxuICAgICAgZGF0ZToge2xlbmd0aDoge21pbjogOCxtYXg6IDh9fSxcclxuICAgICAgYW1vdW50OiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fVxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAoIWNpZVV0aWxzLnZhbGlkYXRlSW5wdXQoaW5wdXQsdmFsaWRhdGlvblJ1bGVzICkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb25naXR1ZCBpbnZhbGlkYScpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBhbGdvcml0aG03MihpbnB1dC5yZWZlcmVuY2UsIGlucHV0LmRhdGUsIGlucHV0LmFtb3VudCk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnNzIgPSBBbGc3MjtcclxuXHJcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogQWxnb3JpdGhtIDcyICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG4vKipcclxuICogQWRkIGNoZWNrIGRpZ2l0cyB0byBjcmVhdGUgYSBmaW5hbCByZWZlcmVuY2VcclxuICogQHBhcmFtIHtzdHJpbmd9IHJlZmVyZW5jZVxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXhwaXJhdGlvbkRhdGVcclxuICogQHBhcmFtIHtzdHJpbmd9IGFtb3VudFxyXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBmaW5hbFJlZmVyZW5jZVxyXG4gKi9cclxuZnVuY3Rpb24gYWxnb3JpdGhtNzIocmVmZXJlbmNlLCBleHBpcmF0aW9uRGF0ZSwgYW1vdW50KSB7XHJcblxyXG4gIHZhciBjb25kZW5zZWREYXRlQ2hlY2tEaWdpdCA9IHByb2Nlc3NFeHBpcmF0aW9uRGF0ZShleHBpcmF0aW9uRGF0ZSk7XHJcblxyXG4gIHZhciBhbW91bnRDaGVja0RpZ2l0ID0gcHJvY2Vzc0Ftb3VudChhbW91bnQpO1xyXG5cclxuICB2YXIgcmVmZXJlbmNlQ2hlY2tEaWdpdCA9IHByb2Nlc3NSZWZlcmVuY2UocmVmZXJlbmNlLCBjb25kZW5zZWREYXRlQ2hlY2tEaWdpdCwgYW1vdW50Q2hlY2tEaWdpdCk7XHJcblxyXG4gIGNvbnNvbGUubG9nKCdjb25kZW5zZWREYXRlQ2hlY2tEaWdpdDogJywgY29uZGVuc2VkRGF0ZUNoZWNrRGlnaXQsICdhbW91bnRDaGVja0RpZ2l0OiAnLCBhbW91bnRDaGVja0RpZ2l0LCAncmVmZXJlbmNlQ2hlY2tEaWdpdDogJywgcmVmZXJlbmNlQ2hlY2tEaWdpdCk7XHJcblxyXG4gIHZhciBmaW5hbFJlZmVyZW5jZSA9IHJlZmVyZW5jZSArIGNvbmRlbnNlZERhdGVDaGVja0RpZ2l0ICsgYW1vdW50Q2hlY2tEaWdpdCArIHJlZmVyZW5jZUNoZWNrRGlnaXQ7XHJcblxyXG4gIGNvbnNvbGUubG9nKCdmaW5hbFJlZmVyZW5jZTogJywgZmluYWxSZWZlcmVuY2UpO1xyXG5cclxuICByZXR1cm4gZmluYWxSZWZlcmVuY2U7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHByb2Nlc3NFeHBpcmF0aW9uRGF0ZShleHBpcmF0aW9uRGF0ZSl7XHJcbiAgdmFyIGRheSA9IGV4cGlyYXRpb25EYXRlLnN1YnN0cmluZygwLDIpO1xyXG4gIHZhciBtb250aCA9IGV4cGlyYXRpb25EYXRlLnN1YnN0cmluZygyLDQpO1xyXG4gIHZhciB5ZWFyID0gZXhwaXJhdGlvbkRhdGUuc3Vic3RyaW5nKDYsOCk7XHJcblxyXG4gIHZhciBkYXRlSW50ID0gcGFyc2VJbnQoZGF5ICsgJycgKyBtb250aCArICcnICsgeWVhcik7XHJcbiAgdmFyICByZW1haW5kZXJBcnJheSA9IG5ldyBBcnJheSgpO1xyXG4gIHZhciBxdW90aWVudEJvb2xlYW49IHRydWU7XHJcblxyXG4gIGRvIHtcclxuICAgIHZhciBxdW90aWVudCA9IE1hdGguZmxvb3IoZGF0ZUludCAvIDM2KTtcclxuICAgIHZhciByZW1haW5kZXIgPSBkYXRlSW50ICUgMzY7XHJcblxyXG4gICAgcmVtYWluZGVyQXJyYXkucHVzaChyZW1haW5kZXIpO1xyXG4gICAgZGF0ZUludCA9IHF1b3RpZW50O1xyXG5cclxuICAgIGlmKHF1b3RpZW50ID09IDApXHJcbiAgICAgIHF1b3RpZW50Qm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICB9IHdoaWxlIChxdW90aWVudEJvb2xlYW4pO1xyXG5cclxuICB2YXIgY2hlY2tEaWdpdCA9ICcnO1xyXG4gIGZvciAodmFyIGkgPSByZW1haW5kZXJBcnJheS5sZW5ndGggLSAxOyBpID4gLTE7IGktLSkge1xyXG4gICAgY2hlY2tEaWdpdCArPSByZW1haW5kZXJNYXAuZ2V0KHJlbWFpbmRlckFycmF5W2ldKTtcclxuICB9XHJcblxyXG4gIGlmKGNoZWNrRGlnaXQubGVuZ3RoIDwgNCl7XHJcbiAgICBkb3tcclxuICAgICAgY2hlY2tEaWdpdCA9ICcwJyArIGNoZWNrRGlnaXQ7XHJcbiAgICB9d2hpbGUoY2hlY2tEaWdpdC5sZW5ndGggPCA0KTtcclxuICB9XHJcblxyXG4gIHJldHVybiBjaGVja0RpZ2l0O1xyXG59XHJcblxyXG5mdW5jdGlvbiBwcm9jZXNzQW1vdW50KGFtb3VudFN0cil7XHJcbiAgdmFyIGFtb3VudCA9IHBhcnNlSW50KGFtb3VudFN0ci5yZXBsYWNlKCcuJywgJycpKTtcclxuXHJcbiAgdmFyICByZW1haW5kZXJBcnJheSA9IG5ldyBBcnJheSgpO1xyXG4gIHZhciBxdW90aWVudEJvb2xlYW49IHRydWU7XHJcblxyXG4gIGRvIHtcclxuICAgIHZhciBxdW90aWVudCA9IE1hdGguZmxvb3IoYW1vdW50IC8gMzYpO1xyXG4gICAgdmFyIHJlbWFpbmRlciA9IGFtb3VudCAlIDM2O1xyXG5cclxuICAgIHJlbWFpbmRlckFycmF5LnB1c2gocmVtYWluZGVyKTtcclxuICAgIGFtb3VudCA9IHF1b3RpZW50O1xyXG5cclxuICAgIGlmKHF1b3RpZW50ID09IDApXHJcbiAgICAgIHF1b3RpZW50Qm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICB9IHdoaWxlIChxdW90aWVudEJvb2xlYW4pO1xyXG5cclxuICB2YXIgY2hlY2tEaWdpdCA9ICcnO1xyXG4gIGZvciAodmFyIGkgPSByZW1haW5kZXJBcnJheS5sZW5ndGggLSAxOyBpID4gLTE7IGktLSkge1xyXG4gICAgY2hlY2tEaWdpdCArPSByZW1haW5kZXJNYXAuZ2V0KHJlbWFpbmRlckFycmF5W2ldKTtcclxuICB9XHJcblxyXG4gIGlmKGNoZWNrRGlnaXQubGVuZ3RoIDwgNSl7XHJcbiAgICBkb3tcclxuICAgICAgY2hlY2tEaWdpdCA9ICcwJyArIGNoZWNrRGlnaXQ7XHJcbiAgICB9d2hpbGUoY2hlY2tEaWdpdC5sZW5ndGggPCA1KTtcclxuICB9XHJcblxyXG4gIHJldHVybiBjaGVja0RpZ2l0O1xyXG59XHJcblxyXG5mdW5jdGlvbiBwcm9jZXNzUmVmZXJlbmNlKHJlZmVyZW5jZSwgZXhwaXJhdGlvbkRhdGUsIGFtb3VudCl7XHJcbiAgdmFyIGZ1bGxSZWZlcmVuY2UgPSByZWZlcmVuY2UgKyBleHBpcmF0aW9uRGF0ZSArIGFtb3VudDtcclxuICB2YXIgcmVzdWx0UmVmZXJlbmNlID0gJyc7XHJcblxyXG4gIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsUmVmZXJlbmNlLmxlbmd0aDsgaSsrKXtcclxuICAgIGlmKCFpc051bWVyaWMoZnVsbFJlZmVyZW5jZVtpXSkpXHJcbiAgICAgIHJlc3VsdFJlZmVyZW5jZSArPSByZWZlcmVuY2VNYXAuZ2V0KGZ1bGxSZWZlcmVuY2VbaV0pO1xyXG4gICAgZWxzZVxyXG4gICAgICByZXN1bHRSZWZlcmVuY2UgKz0gZnVsbFJlZmVyZW5jZVtpXTtcclxuICB9XHJcblxyXG4gIHZhciBtdWx0aXBsaWVyID0gMjtcclxuICB2YXIgZGlnaXRzID0gbmV3IEFycmF5KCk7XHJcbiAgdmFyIG11bHRpcGxpZXJCb29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgZm9yICh2YXIgaSA9IHJlc3VsdFJlZmVyZW5jZS5sZW5ndGggLSAxOyBpID4gLTE7IGktLSkge1xyXG4gICAgdmFyIGRpZ2l0ID0gcmVzdWx0UmVmZXJlbmNlW2ldICogbXVsdGlwbGllcjtcclxuXHJcbiAgICBpZiAoZGlnaXQgPiA5KSB7XHJcbiAgICAgIHZhciBzdWJEaWdpdHMgPSBkaWdpdC50b1N0cmluZygpLnNwbGl0KCcnKTtcclxuXHJcbiAgICAgIGRpZ2l0ID0gMDtcclxuXHJcbiAgICAgIHN1YkRpZ2l0cy5mb3JFYWNoKGZ1bmN0aW9uIChudW1iZXIpIHtcclxuICAgICAgICBkaWdpdCArPSBwYXJzZUludChudW1iZXIpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBkaWdpdHMucHVzaChkaWdpdCk7XHJcblxyXG4gICAgbXVsdGlwbGllciA9IG11bHRpcGxpZXJCb29sZWFuID8gMSA6IDI7XHJcblxyXG4gICAgbXVsdGlwbGllckJvb2xlYW4gPSAhbXVsdGlwbGllckJvb2xlYW47XHJcbiAgfVxyXG5cclxuICB2YXIgc3VtID0gMDtcclxuXHJcbiAgZGlnaXRzLmZvckVhY2goZnVuY3Rpb24gKG51bWJlcikge1xyXG4gICAgc3VtICs9IHBhcnNlSW50KG51bWJlcik7XHJcbiAgfSk7XHJcblxyXG4gIHZhciByZW1haW5kZXIgPSBzdW0gJSAxMDtcclxuXHJcbiAgdmFyIGNoZWNrRGlnaXQgPSAocmVtYWluZGVyICE9IDApID8gKDEwIC0gcmVtYWluZGVyKSA6IHJlbWFpbmRlcjtcclxuXHJcbiAgcmV0dXJuIGNoZWNrRGlnaXQ7XHJcbn1cclxuXHJcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogVXRpbHMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG5mdW5jdGlvbiBpc051bWVyaWModmFsdWUpIHtcclxuICByZXR1cm4gL14tP1xcZCskLy50ZXN0KHZhbHVlKTtcclxufVxyXG5cclxuY29uc3QgcmVtYWluZGVyTWFwID0gbmV3IE1hcChbXHJcbiAgWzAsICcwJ10sXHJcbiAgWzEsICcxJ10sXHJcbiAgWzIsICcyJ10sXHJcbiAgWzMsICczJ10sXHJcbiAgWzQsICc0J10sXHJcbiAgWzUsICc1J10sXHJcbiAgWzYsICc2J10sXHJcbiAgWzcsICc3J10sXHJcbiAgWzgsICc4J10sXHJcbiAgWzksICc5J10sXHJcbiAgWzEwLCAnQSddLFxyXG4gIFsxMSwgJ0InXSxcclxuICBbMTIsICdDJ10sXHJcbiAgWzEzLCAnRCddLFxyXG4gIFsxNCwgJ0UnXSxcclxuICBbMTUsICdGJ10sXHJcbiAgWzE2LCAnRyddLFxyXG4gIFsxNywgJ0gnXSxcclxuICBbMTgsICdJJ10sXHJcbiAgWzE5LCAnSiddLFxyXG4gIFsyMCwgJ0snXSxcclxuICBbMjEsICdMJ10sXHJcbiAgWzIyLCAnTSddLFxyXG4gIFsyMywgJ04nXSxcclxuICBbMjQsICdPJ10sXHJcbiAgWzI1LCAnUCddLFxyXG4gIFsyNiwgJ1EnXSxcclxuICBbMjcsICdSJ10sXHJcbiAgWzI4LCAnUyddLFxyXG4gIFsyOSwgJ1QnXSxcclxuICBbMzAsICdVJ10sXHJcbiAgWzMxLCAnViddLFxyXG4gIFszMiwgJ1cnXSxcclxuICBbMzMsICdYJ10sXHJcbiAgWzM0LCAnWSddLFxyXG4gIFszNSwgJ1onXVxyXG5dKTtcclxuXHJcbmNvbnN0IHJlZmVyZW5jZU1hcCA9IG5ldyBNYXAoW1xyXG4gIFsnQScsIDFdLFxyXG4gIFsnQicsIDJdLFxyXG4gIFsnQycsIDNdLFxyXG4gIFsnRCcsIDRdLFxyXG4gIFsnRScsIDVdLFxyXG4gIFsnRicsIDZdLFxyXG4gIFsnRycsIDddLFxyXG4gIFsnSCcsIDhdLFxyXG4gIFsnSScsIDldLFxyXG4gIFsnSicsIDFdLFxyXG4gIFsnSycsIDJdLFxyXG4gIFsnTCcsIDNdLFxyXG4gIFsnTScsIDRdLFxyXG4gIFsnTicsIDVdLFxyXG4gIFsnTycsIDZdLFxyXG4gIFsnUCcsIDddLFxyXG4gIFsnUScsIDhdLFxyXG4gIFsnUicsIDldLFxyXG4gIFsnUycsIDFdLFxyXG4gIFsnVCcsIDJdLFxyXG4gIFsnVScsIDNdLFxyXG4gIFsnVicsIDRdLFxyXG4gIFsnVycsIDVdLFxyXG4gIFsnWCcsIDZdLFxyXG4gIFsnWScsIDddLFxyXG4gIFsnWicsIDhdXHJcbl0pO1xyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxudmFyIENJRVN0cmF0ZWd5ID0gcmVxdWlyZSgnLi9jaWVfc3RyYXRlZ3kuanMnKS5DSUVTdHJhdGVneTtcclxudmFyIENJRVV0aWxzID0gcmVxdWlyZSgnLi9jaWVfdXRpbHMuanMnKS5DSUVVdGlscztcclxudmFyIGNpZVV0aWxzID0gbmV3IENJRVV0aWxzKCk7XHJcblxyXG52YXIgQWxnNzcgPSBmdW5jdGlvbigpIHt9O1xyXG5cclxuQWxnNzcucHJvdG90eXBlID0gbmV3IENJRVN0cmF0ZWd5KCk7XHJcbkFsZzc3LnByb3RvdHlwZSA9IHtcclxuICBleGVjdXRlOiBmdW5jdGlvbihpbnB1dCkge1xyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fSxcclxuICAgICAgZGF0ZToge2xlbmd0aDoge21pbjogOCxtYXg6IDh9fSxcclxuICAgICAgYW1vdW50OiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcbiAgICB2YXIgY29uZGVuc2VkSW5wdXQgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShjb25kZW5zZWRJbnB1dC5yZWZlcmVuY2UsWzExLDEzLDE3LDE5LDIzXSk7XHJcblxyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArIGNvbmRlbnNlZElucHV0LmRhdGUgKyBjb25kZW5zZWRJbnB1dC5hbW91bnQgKyAnMicgKyBjaWVVdGlscy5wYWQoKChhY2MlOTcpKzEpLDIpO1xyXG4gIH1cclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzLkFsZzc3ID0gQWxnNzc7XHJcblxyXG4vLyBUT0RPIE1heWJlIG1vdmUgdGhpcyB0byBhIHRlbXBsYXRlP1xyXG52YXIgcGFyc2VJbnB1dCA9IGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgdmFyIHBhZGRlZERhdGUgPSBjaWVVdGlscy5wYWQoKGlucHV0LmRhdGUuc3Vic3RyKDQsNCktMjAxMykqMzcyICsgKGlucHV0LmRhdGUuc3Vic3RyKDIsMiktMSkqMzEgKyAoaW5wdXQuZGF0ZS5zdWJzdHIoMCwyKS0xKSw0KTtcclxuICB2YXIgcGFkZGVkQW1vdW50ID0gY2llVXRpbHMud2VpZ2h0ZWRSZWR1Y2UoXy53aXRob3V0KF8udG9BcnJheShpbnB1dC5hbW91bnQpLCcuJykucmV2ZXJzZSgpLFs3LDMsMV0pJTEwO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcmVmZXJlbmNlOiBfLnRvQXJyYXkoaW5wdXQucmVmZXJlbmNlICsgcGFkZGVkRGF0ZSArIHBhZGRlZEFtb3VudCArICcyJykucmV2ZXJzZSgpLFxyXG4gICAgYW1vdW50OiBwYWRkZWRBbW91bnQsXHJcbiAgICBkYXRlOiBwYWRkZWREYXRlXHJcbiAgfTtcclxufTtcclxuIiwiXHJcbid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzgwID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzgwLnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGc4MC5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDIxLG1heDogNDl9fVxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAoIWNpZVV0aWxzLnZhbGlkYXRlSW5wdXQoaW5wdXQsIHZhbGlkYXRpb25SdWxlcykpIHtcclxuICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdMb25naXR1ZCBpbnZhbGlkYScpO1xyXG4gICAgICBlcnJvci5zdGF0dXMgPSAnNDIyJztcclxuICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGFsZ29yaXRobTgwKGlucHV0LnJlZmVyZW5jZSk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnODAgPSBBbGc4MDtcclxuXHJcblxyXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIEFsZ29yaXRobSA4MCAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xyXG5cclxuLyoqXHJcbiAqIEFkZCBhIGNoZWNrIGRpZ2l0IHRvIHRoZSByZWZlcmVuY2VcclxuICogQHBhcmFtIHtzdHJpbmd9IHJlZmVyZW5jZVxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSByZXN1bHRSZWZlcmVuY2VcclxuICovXHJcbmZ1bmN0aW9uIGFsZ29yaXRobTgwKHJlZmVyZW5jZSkge1xyXG5cclxuICBpZighaXNOdW1lcmljKHJlZmVyZW5jZSkpe1xyXG4gICAgY29uc29sZS5lcnJvcignTGEgcmVmZXJlbmNpYSBkZWJlIHNlciBOw7ptZXJpY2EnKTtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIHZhciBtdWx0aXBsaWVyID0gMjtcclxuICB2YXIgZGlnaXRzID0gbmV3IEFycmF5KCk7XHJcbiAgdmFyIG11bHRpcGxpZXJCb29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgZm9yICh2YXIgaSA9IHJlZmVyZW5jZS5sZW5ndGggLSAxOyBpID4gLTE7IGktLSkge1xyXG4gICAgdmFyIGRpZ2l0ID0gcmVmZXJlbmNlW2ldICogbXVsdGlwbGllcjtcclxuXHJcbiAgICBpZiAoZGlnaXQgPiA5KSB7XHJcbiAgICAgIHZhciBzdWJEaWdpdHMgPSBkaWdpdC50b1N0cmluZygpLnNwbGl0KCcnKTtcclxuXHJcbiAgICAgIGRpZ2l0ID0gMDtcclxuXHJcbiAgICAgIHN1YkRpZ2l0cy5mb3JFYWNoKGZ1bmN0aW9uIChudW1iZXIpIHtcclxuICAgICAgICBkaWdpdCArPSBwYXJzZUludChudW1iZXIpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBkaWdpdHMucHVzaChkaWdpdCk7XHJcblxyXG4gICAgbXVsdGlwbGllciA9IG11bHRpcGxpZXJCb29sZWFuID8gMSA6IDI7XHJcblxyXG4gICAgbXVsdGlwbGllckJvb2xlYW4gPSAhbXVsdGlwbGllckJvb2xlYW47XHJcbiAgfVxyXG5cclxuICB2YXIgc3VtID0gMDtcclxuXHJcbiAgZGlnaXRzLmZvckVhY2goZnVuY3Rpb24gKG51bWJlcikge1xyXG4gICAgc3VtICs9IHBhcnNlSW50KG51bWJlcik7XHJcbiAgfSk7XHJcblxyXG4gIHZhciByZW1haW5kZXIgPSBzdW0gJSAxMDtcclxuXHJcbiAgdmFyIGNoZWNrRGlnaXQgPSAocmVtYWluZGVyICE9IDApID8gKDEwIC0gcmVtYWluZGVyKSA6IHJlbWFpbmRlcjtcclxuICBjb25zb2xlLmxvZygnY2hlY2tEaWdpdDogJywgY2hlY2tEaWdpdCk7XHJcblxyXG4gIHZhciByZXN1bHRSZWZlcmVuY2UgPSByZWZlcmVuY2UgKyBjaGVja0RpZ2l0O1xyXG4gIGNvbnNvbGUubG9nKCdyZXN1bHRSZWZlcmVuY2U6ICcsIHJlc3VsdFJlZmVyZW5jZSk7XHJcblxyXG4gIGlmIChyZXN1bHRSZWZlcmVuY2UubGVuZ3RoIDwgMjEpXHJcbiAgICBjb25zb2xlLndhcm4oJ0xhIGxvbmdpdHVkIG3DrW5pbWEgZGUgbGEgcmVmZXJlbmNpYSByZXN1bHRhbnRlIGRlYmVyIHNlciBkZSAyMScpO1xyXG5cclxuICBpZiAocmVzdWx0UmVmZXJlbmNlLmxlbmd0aCA+IDUwKVxyXG4gICAgY29uc29sZS53YXJuKCdMYSBsb25naXR1ZCBtw6F4aW1hIGRlIGxhIHJlZmVyZW5jaWEgcmVzdWx0YW50ZSBkZWJlciBzZXIgZGUgNTAnKTtcclxuXHJcbiAgcmV0dXJuIHJlc3VsdFJlZmVyZW5jZTtcclxufVxyXG5cclxuZnVuY3Rpb24gcHJvY2Vzc0V4cGlyYXRpb25EYXRlKGV4cGlyYXRpb25EYXRlKXtcclxuICB2YXIgZGF5ID0gZXhwaXJhdGlvbkRhdGUuc3Vic3RyaW5nKDAsMik7XHJcbiAgdmFyIG1vbnRoID0gZXhwaXJhdGlvbkRhdGUuc3Vic3RyaW5nKDIsNCk7XHJcbiAgdmFyIHllYXIgPSBleHBpcmF0aW9uRGF0ZS5zdWJzdHJpbmcoNiw4KTtcclxuXHJcbiAgdmFyIGRhdGVJbnQgPSBwYXJzZUludChkYXkgKyAnJyArIG1vbnRoICsgJycgKyB5ZWFyKTtcclxuICB2YXIgIHJlbWFpbmRlckFycmF5ID0gbmV3IEFycmF5KCk7XHJcbiAgdmFyIHF1b3RpZW50Qm9vbGVhbj0gdHJ1ZTtcclxuXHJcbiAgZG8ge1xyXG4gICAgdmFyIHF1b3RpZW50ID0gTWF0aC5mbG9vcihkYXRlSW50IC8gMzYpO1xyXG4gICAgdmFyIHJlbWFpbmRlciA9IGRhdGVJbnQgJSAzNjtcclxuXHJcbiAgICByZW1haW5kZXJBcnJheS5wdXNoKHJlbWFpbmRlcik7XHJcbiAgICBkYXRlSW50ID0gcXVvdGllbnQ7XHJcblxyXG4gICAgaWYocXVvdGllbnQgPT0gMClcclxuICAgICAgcXVvdGllbnRCb29sZWFuID0gZmFsc2U7XHJcblxyXG4gIH0gd2hpbGUgKHF1b3RpZW50Qm9vbGVhbik7XHJcblxyXG4gIHZhciBjaGVja0RpZ2l0ID0gJyc7XHJcbiAgZm9yICh2YXIgaSA9IHJlbWFpbmRlckFycmF5Lmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XHJcbiAgICBjaGVja0RpZ2l0ICs9IHJlbWFpbmRlck1hcC5nZXQocmVtYWluZGVyQXJyYXlbaV0pO1xyXG4gIH1cclxuXHJcbiAgaWYoY2hlY2tEaWdpdC5sZW5ndGggPCA0KXtcclxuICAgIGRve1xyXG4gICAgICBjaGVja0RpZ2l0ID0gJzAnICsgY2hlY2tEaWdpdDtcclxuICAgIH13aGlsZShjaGVja0RpZ2l0Lmxlbmd0aCA8IDQpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGNoZWNrRGlnaXQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHByb2Nlc3NBbW91bnQoYW1vdW50U3RyKXtcclxuICB2YXIgYW1vdW50ID0gcGFyc2VJbnQoYW1vdW50U3RyLnJlcGxhY2UoJy4nLCAnJykpO1xyXG5cclxuICB2YXIgIHJlbWFpbmRlckFycmF5ID0gbmV3IEFycmF5KCk7XHJcbiAgdmFyIHF1b3RpZW50Qm9vbGVhbj0gdHJ1ZTtcclxuXHJcbiAgZG8ge1xyXG4gICAgdmFyIHF1b3RpZW50ID0gTWF0aC5mbG9vcihhbW91bnQgLyAzNik7XHJcbiAgICB2YXIgcmVtYWluZGVyID0gYW1vdW50ICUgMzY7XHJcblxyXG4gICAgcmVtYWluZGVyQXJyYXkucHVzaChyZW1haW5kZXIpO1xyXG4gICAgYW1vdW50ID0gcXVvdGllbnQ7XHJcblxyXG4gICAgaWYocXVvdGllbnQgPT0gMClcclxuICAgICAgcXVvdGllbnRCb29sZWFuID0gZmFsc2U7XHJcblxyXG4gIH0gd2hpbGUgKHF1b3RpZW50Qm9vbGVhbik7XHJcblxyXG4gIHZhciBjaGVja0RpZ2l0ID0gJyc7XHJcbiAgZm9yICh2YXIgaSA9IHJlbWFpbmRlckFycmF5Lmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XHJcbiAgICBjaGVja0RpZ2l0ICs9IHJlbWFpbmRlck1hcC5nZXQocmVtYWluZGVyQXJyYXlbaV0pO1xyXG4gIH1cclxuXHJcbiAgaWYoY2hlY2tEaWdpdC5sZW5ndGggPCA1KXtcclxuICAgIGRve1xyXG4gICAgICBjaGVja0RpZ2l0ID0gJzAnICsgY2hlY2tEaWdpdDtcclxuICAgIH13aGlsZShjaGVja0RpZ2l0Lmxlbmd0aCA8IDUpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGNoZWNrRGlnaXQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHByb2Nlc3NSZWZlcmVuY2UocmVmZXJlbmNlLCBleHBpcmF0aW9uRGF0ZSwgYW1vdW50KXtcclxuICB2YXIgZnVsbFJlZmVyZW5jZSA9IHJlZmVyZW5jZSArIGV4cGlyYXRpb25EYXRlICsgYW1vdW50O1xyXG4gIHZhciByZXN1bHRSZWZlcmVuY2UgPSAnJztcclxuXHJcbiAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxSZWZlcmVuY2UubGVuZ3RoOyBpKyspe1xyXG4gICAgaWYoIWlzTnVtZXJpYyhmdWxsUmVmZXJlbmNlW2ldKSlcclxuICAgICAgcmVzdWx0UmVmZXJlbmNlICs9IHJlZmVyZW5jZU1hcC5nZXQoZnVsbFJlZmVyZW5jZVtpXSk7XHJcbiAgICBlbHNlXHJcbiAgICAgIHJlc3VsdFJlZmVyZW5jZSArPSBmdWxsUmVmZXJlbmNlW2ldO1xyXG4gIH1cclxuXHJcbiAgdmFyIG11bHRpcGxpZXIgPSAyO1xyXG4gIHZhciBkaWdpdHMgPSBuZXcgQXJyYXkoKTtcclxuICB2YXIgbXVsdGlwbGllckJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICBmb3IgKHZhciBpID0gcmVzdWx0UmVmZXJlbmNlLmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XHJcbiAgICB2YXIgZGlnaXQgPSByZXN1bHRSZWZlcmVuY2VbaV0gKiBtdWx0aXBsaWVyO1xyXG5cclxuICAgIGlmIChkaWdpdCA+IDkpIHtcclxuICAgICAgdmFyIHN1YkRpZ2l0cyA9IGRpZ2l0LnRvU3RyaW5nKCkuc3BsaXQoJycpO1xyXG5cclxuICAgICAgZGlnaXQgPSAwO1xyXG5cclxuICAgICAgc3ViRGlnaXRzLmZvckVhY2goZnVuY3Rpb24gKG51bWJlcikge1xyXG4gICAgICAgIGRpZ2l0ICs9IHBhcnNlSW50KG51bWJlcik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGRpZ2l0cy5wdXNoKGRpZ2l0KTtcclxuXHJcbiAgICBtdWx0aXBsaWVyID0gbXVsdGlwbGllckJvb2xlYW4gPyAxIDogMjtcclxuXHJcbiAgICBtdWx0aXBsaWVyQm9vbGVhbiA9ICFtdWx0aXBsaWVyQm9vbGVhbjtcclxuICB9XHJcblxyXG4gIHZhciBzdW0gPSAwO1xyXG5cclxuICBkaWdpdHMuZm9yRWFjaChmdW5jdGlvbiAobnVtYmVyKSB7XHJcbiAgICBzdW0gKz0gcGFyc2VJbnQobnVtYmVyKTtcclxuICB9KTtcclxuXHJcbiAgdmFyIHJlbWFpbmRlciA9IHN1bSAlIDEwO1xyXG5cclxuICB2YXIgY2hlY2tEaWdpdCA9IDEwIC0gcmVtYWluZGVyO1xyXG5cclxuICByZXR1cm4gY2hlY2tEaWdpdDtcclxufVxyXG5cclxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiBVdGlscyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcbmZ1bmN0aW9uIGlzTnVtZXJpYyh2YWx1ZSkge1xyXG4gIHJldHVybiAvXi0/XFxkKyQvLnRlc3QodmFsdWUpO1xyXG59XHJcblxyXG5jb25zdCByZW1haW5kZXJNYXAgPSBuZXcgTWFwKFtcclxuICBbMCwgJzAnXSxcclxuICBbMSwgJzEnXSxcclxuICBbMiwgJzInXSxcclxuICBbMywgJzMnXSxcclxuICBbNCwgJzQnXSxcclxuICBbNSwgJzUnXSxcclxuICBbNiwgJzYnXSxcclxuICBbNywgJzcnXSxcclxuICBbOCwgJzgnXSxcclxuICBbOSwgJzknXSxcclxuICBbMTAsICdBJ10sXHJcbiAgWzExLCAnQiddLFxyXG4gIFsxMiwgJ0MnXSxcclxuICBbMTMsICdEJ10sXHJcbiAgWzE0LCAnRSddLFxyXG4gIFsxNSwgJ0YnXSxcclxuICBbMTYsICdHJ10sXHJcbiAgWzE3LCAnSCddLFxyXG4gIFsxOCwgJ0knXSxcclxuICBbMTksICdKJ10sXHJcbiAgWzIwLCAnSyddLFxyXG4gIFsyMSwgJ0wnXSxcclxuICBbMjIsICdNJ10sXHJcbiAgWzIzLCAnTiddLFxyXG4gIFsyNCwgJ08nXSxcclxuICBbMjUsICdQJ10sXHJcbiAgWzI2LCAnUSddLFxyXG4gIFsyNywgJ1InXSxcclxuICBbMjgsICdTJ10sXHJcbiAgWzI5LCAnVCddLFxyXG4gIFszMCwgJ1UnXSxcclxuICBbMzEsICdWJ10sXHJcbiAgWzMyLCAnVyddLFxyXG4gIFszMywgJ1gnXSxcclxuICBbMzQsICdZJ10sXHJcbiAgWzM1LCAnWiddXHJcbl0pO1xyXG5cclxuY29uc3QgcmVmZXJlbmNlTWFwID0gbmV3IE1hcChbXHJcbiAgWydBJywgMV0sXHJcbiAgWydCJywgMl0sXHJcbiAgWydDJywgM10sXHJcbiAgWydEJywgNF0sXHJcbiAgWydFJywgNV0sXHJcbiAgWydGJywgNl0sXHJcbiAgWydHJywgN10sXHJcbiAgWydIJywgOF0sXHJcbiAgWydJJywgOV0sXHJcbiAgWydKJywgMV0sXHJcbiAgWydLJywgMl0sXHJcbiAgWydMJywgM10sXHJcbiAgWydNJywgNF0sXHJcbiAgWydOJywgNV0sXHJcbiAgWydPJywgNl0sXHJcbiAgWydQJywgN10sXHJcbiAgWydRJywgOF0sXHJcbiAgWydSJywgOV0sXHJcbiAgWydTJywgMV0sXHJcbiAgWydUJywgMl0sXHJcbiAgWydVJywgM10sXHJcbiAgWydWJywgNF0sXHJcbiAgWydXJywgNV0sXHJcbiAgWydYJywgNl0sXHJcbiAgWydZJywgN10sXHJcbiAgWydaJywgOF1cclxuXSk7XHJcbiIsIlxyXG4ndXNlIHN0cmljdCc7XHJcblxyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGc4MSA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGc4MS5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnODEucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcblxyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAyMSwgbWF4OiA0OX19XHJcbiAgICB9O1xyXG5cclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSkge1xyXG4gICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICAgIGVycm9yLnN0YXR1cyA9ICc0MjInO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYWxnODEoaW5wdXQucmVmZXJlbmNlKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGc4MSA9IEFsZzgxO1xyXG5cclxuZnVuY3Rpb24gYWxnODEocmVmZXJlbmNlKXtcclxuICB2YXIgZGlnaXRWZXJpZnkgPSBhbGdvcml0aG0ocmVmZXJlbmNlLnRvVXBwZXJDYXNlKCkpO1xyXG4gIHZhciByZWZlcmVuY2U4MSA9IHJlZmVyZW5jZSArIGRpZ2l0VmVyaWZ5O1xyXG4gIHJldHVybiByZWZlcmVuY2U4MTtcclxufVxyXG5cclxuZnVuY3Rpb24gYWxnb3JpdGhtKGRhdGEpe1xyXG4gIGNvbnNvbGUubG9nKGRhdGEpO1xyXG4gIHZhciB0cmFuc2Zvcm1BbHBoYW51bWVyaWMgPSByZXBsYWNlQWxwaGFudW1lcmljKGRhdGEpO1xyXG4gIGNvbnNvbGUubG9nKHRyYW5zZm9ybUFscGhhbnVtZXJpYyk7XHJcbiAgdmFyIHRyYW5zZm9ybU51bWVyaWMgPSBidWlsZE51bWVyaWModHJhbnNmb3JtQWxwaGFudW1lcmljKTtcclxuICBjb25zb2xlLmxvZyh0cmFuc2Zvcm1OdW1lcmljKTtcclxuICB2YXIgdHJhbnNmb3JtVW5pZnlJbmZvID0gdW5pZnlJbmZvKHRyYW5zZm9ybU51bWVyaWMpO1xyXG4gIGNvbnNvbGUubG9nKHRyYW5zZm9ybVVuaWZ5SW5mbyk7XHJcbiAgdmFyIGRpZ2l0VmVpcmZ5ID0gXCJcIiArIHNlYXJjaERpZ2l0VmVyaWZ5KHRyYW5zZm9ybVVuaWZ5SW5mbyk7XHJcbiAgcmV0dXJuIGRpZ2l0VmVpcmZ5LmNoYXJBdChkaWdpdFZlaXJmeS5sZW5ndGgtMSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlcGxhY2VBbHBoYW51bWVyaWMoZGF0YSl7XHJcbiAgdmFyIG1hcEFscGhhbnVtZXJpYyA9IG5ldyBNYXAoW1tcIkFcIiwgMV0sIFtcIkJcIiwgMl0sIFtcIkNcIiwgM10sIFtcIkRcIiwgNF0sIFtcIkVcIiwgNV0sIFtcIkZcIiwgNl0sIFtcIkdcIiwgN10sIFtcIkhcIiwgOF0sIFtcIklcIiwgOV0sIFtcIkpcIiwgMV0sIFtcIktcIiwgMl0sIFtcIkxcIiwgM10sIFtcIk1cIiwgNF0sIFtcIk5cIiwgNV0sIFtcIk9cIiwgNl0sIFtcIlBcIiwgN10sIFtcIlFcIiwgOF0sIFtcIlJcIiwgOV0sIFtcIlNcIiwgMV0sIFtcIlRcIiwgMl0sIFtcIlVcIiwgM10sIFtcIlZcIiwgNF0sIFtcIldcIiwgNV0sIFtcIlhcIiwgNl0sIFtcIllcIiwgN10sIFtcIlpcIiwgOF1dKTtcclxuICB2YXIgdHJhbnNmb3JtID0gXCJcIjtcclxuICBmb3IgKGxldCBjaGFyYWN0ZXJEYXRhIG9mIGRhdGEpIHtcclxuICAgIHZhciBpbmZvQ2hhcmFjdGVyID0gY2hhcmFjdGVyRGF0YTtcclxuICAgIGlmKG1hcEFscGhhbnVtZXJpYy5oYXMoY2hhcmFjdGVyRGF0YSkpe1xyXG4gICAgICBpbmZvQ2hhcmFjdGVyID0gbWFwQWxwaGFudW1lcmljLmdldChjaGFyYWN0ZXJEYXRhKTtcclxuICAgIH1cclxuICAgIHRyYW5zZm9ybSArPSBpbmZvQ2hhcmFjdGVyO1xyXG4gIH1cclxuICByZXR1cm4gdHJhbnNmb3JtO1xyXG59XHJcblxyXG5mdW5jdGlvbiBidWlsZE51bWVyaWMoZGF0YSl7XHJcbiAgdmFyIHRyYW5zZm9ybSA9IFtkYXRhLmxlbmd0aF07XHJcbiAgdmFyIGlzU2Vjb25kID0gdHJ1ZTtcclxuICBmb3IodmFyIGkgPSBkYXRhLmxlbmd0aC0xOyBpID49IDA7IGktLSkge1xyXG4gICAgdmFyIGRhdGFOdW1iZXIgPSBOdW1iZXIoZGF0YS5jaGFyQXQoaSkpO1xyXG4gICAgdmFyIG51bWJlck11bHRpcGx5ID0gaXNTZWNvbmQgPyAyIDogMTtcclxuICAgIGlzU2Vjb25kID0gaXNTZWNvbmQgPyBmYWxzZSA6IHRydWU7XHJcbiAgICB0cmFuc2Zvcm1baV0gPSAobnVtYmVyTXVsdGlwbHkgKiBkYXRhTnVtYmVyKTtcclxuICB9XHJcbiAgcmV0dXJuIHRyYW5zZm9ybTtcclxufVxyXG5cclxuZnVuY3Rpb24gdW5pZnlJbmZvKGRhdGEpe1xyXG4gIHZhciB0cmFuc2Zvcm0gPSBbXTtcclxuICBmb3IgKGxldCBudW1iZXJEYXRhIG9mIGRhdGEpIHtcclxuICAgIHZhciBzdW1EYXRhID0gMDtcclxuICAgIHZhciBpbmZvRGF0YSA9IFwiXCIgKyBudW1iZXJEYXRhO1xyXG4gICAgZm9yIChsZXQgY2hhcmFjdGVyRGF0YSBvZiBpbmZvRGF0YSkge1xyXG4gICAgICBzdW1EYXRhICs9IE51bWJlcihjaGFyYWN0ZXJEYXRhKTtcclxuICAgIH1cclxuICAgIHRyYW5zZm9ybS5wdXNoKHN1bURhdGEpO1xyXG4gIH1cclxuICByZXR1cm4gdHJhbnNmb3JtO1xyXG59XHJcblxyXG5mdW5jdGlvbiBzZWFyY2hEaWdpdFZlcmlmeShkYXRhKXtcclxuICB2YXIgc3VtRGF0YSA9IDA7XHJcbiAgZm9yIChsZXQgbnVtYmVyRGF0YSBvZiBkYXRhKSB7XHJcbiAgICBzdW1EYXRhICs9IG51bWJlckRhdGE7XHJcbiAgfVxyXG5cclxuICB2YXIgbnVtYmVyQXV4ID0gMTA7XHJcbiAgdmFyIHJlc2lkdWUgPSAoKHN1bURhdGEgJSBudW1iZXJBdXgpICsgbnVtYmVyQXV4KSAlIG51bWJlckF1eDtcclxuICByZXR1cm4gbnVtYmVyQXV4IC0gcmVzaWR1ZTtcclxufVxyXG5cclxuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzgyID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzgyLnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGc4Mi5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuICAgIHZhciB2YWxpZGF0aW9uUnVsZXMgPSB7XHJcbiAgICAgIHJlZmVyZW5jZToge2xlbmd0aDoge21pbjogMTUsbWF4OiA0Mn19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19LFxyXG4gICAgICBkaWdpdDoge2xlbmd0aDoge21pbjogMSxtYXg6IDF9fVxyXG4gICAgfTtcclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcbiAgICB2YXIgY29uZGVuc2VkSW5wdXQgPSBwYXJzZUlucHV0KGlucHV0KTtcclxuICAgIHZhciBhY2MgPSBjaWVVdGlscy53ZWlnaHRlZFJlZHVjZShjb25kZW5zZWRJbnB1dC5yZWZlcmVuY2UsWzExLDEzLDE3LDE5LDIzXSk7XHJcblxyXG4gICAgcmV0dXJuIGlucHV0LnJlZmVyZW5jZSArIGNvbmRlbnNlZElucHV0LmRhdGUgKyBjb25kZW5zZWRJbnB1dC5hbW91bnQgKyBpbnB1dC5kaWdpdCArIGNpZVV0aWxzLnBhZCgoKGFjYyU5NykrMSksMik7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnODIgPSBBbGc4MjtcclxuXHJcbi8vIFRPRE8gTWF5YmUgbW92ZSB0aGlzIHRvIGEgdGVtcGxhdGU/XHJcbnZhciBwYXJzZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuICB2YXIgY2hhclRvTnVtID0ge1xyXG4gICAgQTogMSwgQjogMiwgQzogMywgRDogNCwgRTogNSwgRjogNiwgRzogNywgSDogOCwgSTogOSwgSjogMSwgSzogMiwgTDogMyxcclxuICAgIE06IDQsIE46IDUsIE86IDYsIFA6IDcsIFE6IDgsIFI6IDksIFM6IDIsIFQ6IDMsIFU6IDQsIFY6IDUsIFc6IDYsIFg6IDcsXHJcbiAgICBZOiA4LCBaOiA5LCAxOiAxLCAyOiAyLCAzOiAzLCA0OiA0LCA1OiA1LCA2OiA2LCA3OiA3LCA4OiA4LCA5OiA5LCAwOiAwXHJcbiAgfTtcclxuXHJcbiAgdmFyIG51bU9ubHlSZWZlcmVuY2UgPSBjaWVVdGlscy5yZXBsYWNlQ2hhcldpdGhOdW0oaW5wdXQucmVmZXJlbmNlLnRvVXBwZXJDYXNlKCksIGNoYXJUb051bSkuam9pbignJyk7XHJcbiAgdmFyIHBhZGRlZERhdGUgPSBjaWVVdGlscy5wYWQoKGlucHV0LmRhdGUuc3Vic3RyKDQsNCktMjAxNCkqMzcyICsgKGlucHV0LmRhdGUuc3Vic3RyKDIsMiktMSkqMzEgKyAoaW5wdXQuZGF0ZS5zdWJzdHIoMCwyKS0xKSw0KTtcclxuICB2YXIgcGFkZGVkQW1vdW50ID0gY2llVXRpbHMud2VpZ2h0ZWRSZWR1Y2UoXy53aXRob3V0KF8udG9BcnJheShpbnB1dC5hbW91bnQpLCcuJykucmV2ZXJzZSgpLFs3LDMsMV0pJTEwO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcmVmZXJlbmNlOiBfLnRvQXJyYXkobnVtT25seVJlZmVyZW5jZSArIHBhZGRlZERhdGUgKyBwYWRkZWRBbW91bnQgKyBpbnB1dC5kaWdpdCkucmV2ZXJzZSgpLFxyXG4gICAgYW1vdW50OiBwYWRkZWRBbW91bnQsXHJcbiAgICBkYXRlOiBwYWRkZWREYXRlXHJcbiAgfTtcclxufTtcclxuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzg5ID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzg5LnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGc4OS5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiA0Mn19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19XHJcbiAgICB9O1xyXG5cclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGFsZzg5KGlucHV0LmRhdGUsIGlucHV0LmFtb3VudCwgaW5wdXQucmVmZXJlbmNlKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGc4OSA9IEFsZzg5O1xyXG5cclxudmFyIGNvbnRhbnRMZWZ0ID0gMDtcclxudmFyIHllYXJCYXNlID0gMjAxMztcclxudmFyIHllYXJNdWx0aXBseSA9IDM3MjtcclxudmFyIHVuaXRTdWJ0cmFjdGlvbiA9IDE7XHJcbnZhciBtb250aE11bHRpcGx5ID0gMzE7XHJcbnZhciBkaWdpdFZlcmlmeUNvbnN0YW50ID0gMjtcclxudmFyIG1hcEFscGhhbnVtZXJpYyA9IG5ldyBNYXAoW1tcIkFcIiwgMl0sIFtcIkJcIiwgMl0sIFtcIkNcIiwgMl0sIFtcIkRcIiwgM10sIFtcIkVcIiwgM10sIFtcIkZcIiwgM10sIFtcIkdcIiwgNF0sIFtcIkhcIiwgNF0sIFtcIklcIiwgNF0sIFtcIkpcIiwgNV0sIFtcIktcIiwgNV0sIFtcIkxcIiwgNV0sIFtcIk1cIiwgNl0sIFtcIk5cIiwgNl0sIFtcIk9cIiwgNl0sIFtcIlBcIiwgN10sIFtcIlFcIiwgN10sIFtcIlJcIiwgN10sIFtcIlNcIiwgOF0sIFtcIlRcIiwgOF0sIFtcIlVcIiwgOF0sIFtcIlZcIiwgOV0sIFtcIldcIiwgOV0sIFtcIlhcIiwgOV0sIFtcIllcIiwgMF0sIFtcIlpcIiwgMF1dKTtcclxuXHJcbmZ1bmN0aW9uIGFsZzg5KGRhdGVFeHBpcmVkLCBhbW91bnQsIHJlZmVyZW5jZSl7XHJcbiAgdmFyIGRpZ2l0VmVyaWZ5RGF0ZSA9IGFsZ29yaXRobURhdGUoZGF0ZUV4cGlyZWQpO1xyXG5cclxuICB2YXIgYW1vdW50Rm9ybWF0ID0gY29udmVydFRvUG91bmRzKGFtb3VudCk7XHJcblxyXG4gIHZhciBkaWdpdFZlcmlmeUFtb3VudCA9IGFsZ29yaXRobUFtb3VudChhbW91bnRGb3JtYXQpO1xyXG4gIGNvbnNvbGUubG9nKGRpZ2l0VmVyaWZ5RGF0ZSk7XHJcbiAgY29uc29sZS5sb2coZGlnaXRWZXJpZnlBbW91bnQpO1xyXG4gIGNvbnNvbGUubG9nKHJlZmVyZW5jZSk7XHJcbiAgdmFyIHJlZmVyZW5jZTg5ID0gcmVmZXJlbmNlICsgZGlnaXRWZXJpZnlEYXRlICsgZGlnaXRWZXJpZnlBbW91bnQgKyBkaWdpdFZlcmlmeUNvbnN0YW50O1xyXG4gIHZhciBkaWdpdFZlcmlmeVJlZmVyZW5jZSA9IGFsZ29yaXRobVJlZmVyZW5jZShyZWZlcmVuY2U4OS50b1VwcGVyQ2FzZSgpKTtcclxuICBjb25zb2xlLmxvZyhkaWdpdFZlcmlmeVJlZmVyZW5jZSk7XHJcbiAgcmVmZXJlbmNlODkgPSByZWZlcmVuY2U4OSArIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlO1xyXG4gIHJldHVybiByZWZlcmVuY2U4OTtcclxufVxyXG5cclxuZnVuY3Rpb24gY29udmVydFRvUG91bmRzKHN0cikge1x0XHJcblx0dmFyIG4gPSBOdW1iZXIucGFyc2VGbG9hdChzdHIpO1xyXG4gIGlmKCFzdHIgfHwgaXNOYU4obikgfHwgbiA8IDApIHJldHVybiAwO1xyXG4gIHJldHVybiBuLnRvRml4ZWQoMik7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFsZ29yaXRobVJlZmVyZW5jZShkYXRhKXtcclxuICBjb25zb2xlLmxvZyhkYXRhKTtcclxuICB2YXIgZGF0YVJlcGxhY2UgPSByZXBsYWNlQWxwaGFudW1lcmljKGRhdGEpO1xyXG4gIHZhciBpc1Bvc2l0aW9uID0gMVxyXG4gIHZhciBtYXBNdWx0aXBseSA9IG5ldyBNYXAoW1sxLCAxMV0sIFsyLCAxM10sIFszLCAxN10sIFs0LCAxOV0sIFs1LCAyM11dKTtcclxuICB2YXIgc3VtRGF0YSA9IDA7XHJcbiAgZm9yKHZhciBpID0gZGF0YVJlcGxhY2UubGVuZ3RoLTE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICB2YXIgZGF0YU51bWJlciA9IE51bWJlcihkYXRhUmVwbGFjZS5jaGFyQXQoaSkpO1xyXG4gICAgdmFyIG51bWJlck11bHRpcGx5ID0gMDtcclxuICAgIGlmKG1hcE11bHRpcGx5Lmhhcyhpc1Bvc2l0aW9uKSl7XHJcbiAgICAgIG51bWJlck11bHRpcGx5ID0gbWFwTXVsdGlwbHkuZ2V0KGlzUG9zaXRpb24pO1xyXG4gICAgfWVsc2V7XHJcbiAgICAgIGlzUG9zaXRpb24gPSAxO1xyXG4gICAgICBudW1iZXJNdWx0aXBseSA9IG1hcE11bHRpcGx5LmdldChpc1Bvc2l0aW9uKTtcclxuICAgIH1cclxuICAgIGlzUG9zaXRpb24rKztcclxuICAgIHZhciByZXN1bHRNdWx0aXBseSA9IChudW1iZXJNdWx0aXBseSAqIGRhdGFOdW1iZXIpO1xyXG4gICAgc3VtRGF0YSArPSByZXN1bHRNdWx0aXBseTtcclxuICB9XHJcbiAgY29uc29sZS5sb2coc3VtRGF0YSk7XHJcbiAgdmFyIG51bWJlckF1eCA9IDk3O1xyXG4gIHZhciByZXNpZHVlID0gKChzdW1EYXRhICUgbnVtYmVyQXV4KSArIG51bWJlckF1eCkgJSBudW1iZXJBdXg7XHJcbiAgcmV0dXJuIG1pc3NpbmdEYXRhKDIsIChyZXNpZHVlICsgMSkudG9TdHJpbmcoKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlcGxhY2VBbHBoYW51bWVyaWMoZGF0YSl7XHJcbiAgdmFyIHRyYW5zZm9ybSA9IFwiXCI7XHJcbiAgZm9yIChsZXQgY2hhcmFjdGVyRGF0YSBvZiBkYXRhKSB7XHJcbiAgICB2YXIgaW5mb0NoYXJhY3RlciA9IGNoYXJhY3RlckRhdGE7XHJcbiAgICBpZihtYXBBbHBoYW51bWVyaWMuaGFzKGNoYXJhY3RlckRhdGEpKXtcclxuICAgICAgaW5mb0NoYXJhY3RlciA9IG1hcEFscGhhbnVtZXJpYy5nZXQoY2hhcmFjdGVyRGF0YSk7XHJcbiAgICB9XHJcbiAgICB0cmFuc2Zvcm0gKz0gaW5mb0NoYXJhY3RlcjtcclxuICB9XHJcbiAgcmV0dXJuIHRyYW5zZm9ybTtcclxufVxyXG5cclxuZnVuY3Rpb24gYWxnb3JpdGhtQW1vdW50KGRhdGEpe1xyXG4gIGNvbnNvbGUubG9nKGRhdGEpO1xyXG4gIHZhciBkYXRhVHJhbnNmb3JtID0gZGF0YS5zcGxpdCgnLicpLmpvaW4oXCJcIik7XHJcbiAgY29uc29sZS5sb2coZGF0YVRyYW5zZm9ybSk7XHJcbiAgdmFyIGlzUG9zaXRpb24gPSAxXHJcbiAgdmFyIG1hcE11bHRpcGx5ID0gbmV3IE1hcChbWzEsIDddLCBbMiwgM10sIFszLCAxXV0pO1xyXG4gIC8vdmFyIGlzVGhyZWUgPSB0cnVlO1xyXG4gIC8vdmFyIGlzU2Vjb25kID0gZmFsc2U7XHJcbiAgdmFyIHN1bURhdGEgPSAwO1xyXG4gIGZvcih2YXIgaSA9IGRhdGFUcmFuc2Zvcm0ubGVuZ3RoLTE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICB2YXIgZGF0YU51bWJlciA9IE51bWJlcihkYXRhVHJhbnNmb3JtLmNoYXJBdChpKSk7XHJcbiAgICB2YXIgbnVtYmVyTXVsdGlwbHkgPSAwO1xyXG4gICAgaWYobWFwTXVsdGlwbHkuaGFzKGlzUG9zaXRpb24pKXtcclxuICAgICAgbnVtYmVyTXVsdGlwbHkgPSBtYXBNdWx0aXBseS5nZXQoaXNQb3NpdGlvbik7XHJcbiAgICB9ZWxzZXtcclxuICAgICAgaXNQb3NpdGlvbiA9IDE7XHJcbiAgICAgIG51bWJlck11bHRpcGx5ID0gbWFwTXVsdGlwbHkuZ2V0KGlzUG9zaXRpb24pO1xyXG4gICAgfVxyXG4gICAgaXNQb3NpdGlvbisrO1xyXG4gICAgdmFyIHJlc3VsdE11bHRpcGx5ID0gKG51bWJlck11bHRpcGx5ICogZGF0YU51bWJlcik7XHJcbiAgICBzdW1EYXRhICs9IHJlc3VsdE11bHRpcGx5O1xyXG4gIH1cclxuICBjb25zb2xlLmxvZyhzdW1EYXRhKTtcclxuICB2YXIgbnVtYmVyQXV4ID0gMTA7XHJcbiAgdmFyIHJlc2lkdWUgPSAoKHN1bURhdGEgJSBudW1iZXJBdXgpICsgbnVtYmVyQXV4KSAlIG51bWJlckF1eDtcclxuXHJcbiAgcmV0dXJuIHJlc2lkdWUudG9TdHJpbmcoKS5jaGFyQXQocmVzaWR1ZS50b1N0cmluZygpLmxlbmd0aC0xKTtcclxufVxyXG5cclxuZnVuY3Rpb24gYWxnb3JpdGhtRGF0ZShkYXRhKXtcclxuICBjb25zb2xlLmxvZyhkYXRhKTtcclxuICB2YXIgZGF5RGF0YSA9IGRhdGEuc3Vic3RyaW5nKDAsIDIpO1xyXG4gIHZhciBtb250aERhdGEgPSBkYXRhLnN1YnN0cmluZygyLCA0KTtcclxuICB2YXIgeWVhckRhdGEgPSBkYXRhLnN1YnN0cmluZyg0LCA4KTtcclxuXHJcbiAgdmFyIHllYXJTdWJ0cmFjdGlvbiA9IHllYXJEYXRhIC0geWVhckJhc2U7XHJcbiAgY29uc29sZS5sb2coeWVhclN1YnRyYWN0aW9uKTtcclxuXHJcbiAgdmFyIHllYXJyZXN1bHRNdWx0aXBseSA9IHllYXJTdWJ0cmFjdGlvbiAqIHllYXJNdWx0aXBseTtcclxuICBjb25zb2xlLmxvZyh5ZWFycmVzdWx0TXVsdGlwbHkpO1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRTdWJ0cmFjdGlvbiA9IE51bWJlcihtb250aERhdGEpIC0gdW5pdFN1YnRyYWN0aW9uO1xyXG4gIGNvbnNvbGUubG9nKG1vbnRoUmVzdWx0U3VidHJhY3Rpb24pO1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRNdWx0aXBseSA9IG1vbnRoUmVzdWx0U3VidHJhY3Rpb24gKiBtb250aE11bHRpcGx5O1xyXG4gIGNvbnNvbGUubG9nKG1vbnRoUmVzdWx0TXVsdGlwbHkpO1xyXG5cclxuICB2YXIgZGF5UmVzdWx0U3VidHJhY3Rpb24gPSBOdW1iZXIoZGF5RGF0YSkgLSB1bml0U3VidHJhY3Rpb247XHJcbiAgY29uc29sZS5sb2coZGF5UmVzdWx0U3VidHJhY3Rpb24pO1xyXG5cclxuICByZXR1cm4gbWlzc2luZ0RhdGEoNCwgeWVhcnJlc3VsdE11bHRpcGx5ICsgbW9udGhSZXN1bHRNdWx0aXBseSArIGRheVJlc3VsdFN1YnRyYWN0aW9uKTtcclxufVxyXG5cclxuZnVuY3Rpb24gbWlzc2luZ0RhdGEobWluTGVuZ3RoTWlzc2luZywgZGF0YSl7XHJcbiAgdmFyIG1pc3NpbmdMZWZ0ID0gbWluTGVuZ3RoTWlzc2luZyAtIGRhdGEubGVuZ3RoO1xyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbWlzc2luZ0xlZnQ7IGkrKykge1xyXG4gICAgZGF0YSA9IGNvbnRhbnRMZWZ0ICsgZGF0YTtcclxuICB9XHJcbiAgcmV0dXJuIGRhdGE7XHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XHJcbnZhciBDSUVTdHJhdGVneSA9IHJlcXVpcmUoJy4vY2llX3N0cmF0ZWd5LmpzJykuQ0lFU3RyYXRlZ3k7XHJcbnZhciBDSUVVdGlscyA9IHJlcXVpcmUoJy4vY2llX3V0aWxzLmpzJykuQ0lFVXRpbHM7XHJcbnZhciBjaWVVdGlscyA9IG5ldyBDSUVVdGlscygpO1xyXG5cclxudmFyIEFsZzkxID0gZnVuY3Rpb24oKSB7fTtcclxuXHJcbkFsZzkxLnByb3RvdHlwZSA9IG5ldyBDSUVTdHJhdGVneSgpO1xyXG5BbGc5MS5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcbiAgICB2YXIgdmFsaWRhdGlvblJ1bGVzID0ge1xyXG4gICAgICByZWZlcmVuY2U6IHtsZW5ndGg6IHttaW46IDEsbWF4OiA0Mn19LFxyXG4gICAgICBkYXRlOiB7bGVuZ3RoOiB7bWluOiA4LG1heDogOH19LFxyXG4gICAgICBhbW91bnQ6IHtsZW5ndGg6IHttaW46IDEsbWF4OiAxMn19XHJcbiAgICB9O1xyXG5cclxuICAgIGlmICghY2llVXRpbHMudmFsaWRhdGVJbnB1dChpbnB1dCx2YWxpZGF0aW9uUnVsZXMgKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvbmdpdHVkIGludmFsaWRhJyk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGFsZzkxKGlucHV0LmRhdGUsIGlucHV0LmFtb3VudCwgaW5wdXQucmVmZXJlbmNlKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5BbGc5MSA9IEFsZzkxO1xyXG5cclxudmFyIGNvbnRhbnRMZWZ0ID0gMDtcclxudmFyIHllYXJCYXNlID0gMjAxMztcclxudmFyIHllYXJNdWx0aXBseSA9IDM3MjtcclxudmFyIHVuaXRTdWJ0cmFjdGlvbiA9IDE7XHJcbnZhciBtb250aE11bHRpcGx5ID0gMzE7XHJcbnZhciBkaWdpdFZlcmlmeUNvbnN0YW50ID0gMjtcclxudmFyIG1hcEFscGhhbnVtZXJpYyA9IG5ldyBNYXAoW1tcIkFcIiwgMV0sIFtcIkJcIiwgMl0sIFtcIkNcIiwgM10sIFtcIkRcIiwgNF0sIFtcIkVcIiwgNV0sIFtcIkZcIiwgNl0sIFtcIkdcIiwgN10sIFtcIkhcIiwgOF0sIFtcIklcIiwgOV0sIFtcIkpcIiwgMV0sIFtcIktcIiwgMl0sIFtcIkxcIiwgM10sIFtcIk1cIiwgNF0sIFtcIk5cIiwgNV0sIFtcIk9cIiwgNl0sIFtcIlBcIiwgN10sIFtcIlFcIiwgOF0sIFtcIlJcIiwgOV0sIFtcIlNcIiwgMl0sIFtcIlRcIiwgM10sIFtcIlVcIiwgNF0sIFtcIlZcIiwgNV0sIFtcIldcIiwgNl0sIFtcIlhcIiwgN10sIFtcIllcIiwgOF0sIFtcIlpcIiwgOV1dKTtcclxuXHJcbmZ1bmN0aW9uIGFsZzkxKGRhdGVFeHBpcmVkLCBhbW91bnQsIHJlZmVyZW5jZSl7XHJcbiAgdmFyIGRpZ2l0VmVyaWZ5RGF0ZSA9IGFsZ29yaXRobURhdGUoZGF0ZUV4cGlyZWQpO1xyXG5cclxuICB2YXIgYW1vdW50Rm9ybWF0ID0gY29udmVydFRvUG91bmRzKGFtb3VudCk7XHJcblxyXG4gIHZhciBkaWdpdFZlcmlmeUFtb3VudCA9IGFsZ29yaXRobUFtb3VudChhbW91bnRGb3JtYXQpO1xyXG4gIHZhciByZWZlcmVuY2U5MSA9IHJlZmVyZW5jZSArIGRpZ2l0VmVyaWZ5RGF0ZSArIGRpZ2l0VmVyaWZ5QW1vdW50ICsgZGlnaXRWZXJpZnlDb25zdGFudDtcclxuICB2YXIgZGlnaXRWZXJpZnlSZWZlcmVuY2UgPSBhbGdvcml0aG1SZWZlcmVuY2UocmVmZXJlbmNlOTEudG9VcHBlckNhc2UoKSk7XHJcbiAgcmVmZXJlbmNlOTEgPSByZWZlcmVuY2U5MSArIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlO1xyXG4gIHJldHVybiByZWZlcmVuY2U5MTtcclxufVxyXG5cclxuZnVuY3Rpb24gY29udmVydFRvUG91bmRzKHN0cikge1x0XHJcblx0dmFyIG4gPSBOdW1iZXIucGFyc2VGbG9hdChzdHIpO1xyXG4gIGlmKCFzdHIgfHwgaXNOYU4obikgfHwgbiA8IDApIHJldHVybiAwO1xyXG4gIHJldHVybiBuLnRvRml4ZWQoMik7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFsZ29yaXRobVJlZmVyZW5jZShkYXRhKXtcclxuICB2YXIgZGF0YVJlcGxhY2UgPSByZXBsYWNlQWxwaGFudW1lcmljKGRhdGEpO1xyXG4gIHZhciBpc1Bvc2l0aW9uID0gMVxyXG4gIHZhciBtYXBNdWx0aXBseSA9IG5ldyBNYXAoW1sxLCAxMV0sIFsyLCAxM10sIFszLCAxN10sIFs0LCAxOV0sIFs1LCAyM11dKTtcclxuICB2YXIgc3VtRGF0YSA9IDA7XHJcbiAgZm9yKHZhciBpID0gZGF0YVJlcGxhY2UubGVuZ3RoLTE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICB2YXIgZGF0YU51bWJlciA9IE51bWJlcihkYXRhUmVwbGFjZS5jaGFyQXQoaSkpO1xyXG4gICAgdmFyIG51bWJlck11bHRpcGx5ID0gMDtcclxuICAgIGlmKG1hcE11bHRpcGx5Lmhhcyhpc1Bvc2l0aW9uKSl7XHJcbiAgICAgIG51bWJlck11bHRpcGx5ID0gbWFwTXVsdGlwbHkuZ2V0KGlzUG9zaXRpb24pO1xyXG4gICAgfWVsc2V7XHJcbiAgICAgIGlzUG9zaXRpb24gPSAxO1xyXG4gICAgICBudW1iZXJNdWx0aXBseSA9IG1hcE11bHRpcGx5LmdldChpc1Bvc2l0aW9uKTtcclxuICAgIH1cclxuICAgIGlzUG9zaXRpb24rKztcclxuICAgIHZhciByZXN1bHRNdWx0aXBseSA9IChudW1iZXJNdWx0aXBseSAqIGRhdGFOdW1iZXIpO1xyXG4gICAgc3VtRGF0YSArPSByZXN1bHRNdWx0aXBseTtcclxuICB9XHJcbiAgdmFyIG51bWJlckF1eCA9IDk3O1xyXG4gIHZhciByZXNpZHVlID0gKChzdW1EYXRhICUgbnVtYmVyQXV4KSArIG51bWJlckF1eCkgJSBudW1iZXJBdXg7XHJcbiAgdmFyIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlID0gcmVzaWR1ZSArIDE7XHJcblxyXG4gIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlID0gZGlnaXRWZXJpZnlSZWZlcmVuY2UudG9TdHJpbmcoKTtcclxuXHJcbiAgcmV0dXJuIG1pc3NpbmdEYXRhKDIsIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlLnRvU3RyaW5nKCkpO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZXBsYWNlQWxwaGFudW1lcmljKGRhdGEpe1xyXG4gIHZhciB0cmFuc2Zvcm0gPSBcIlwiO1xyXG4gIGZvciAobGV0IGNoYXJhY3RlckRhdGEgb2YgZGF0YSkge1xyXG4gICAgdmFyIGluZm9DaGFyYWN0ZXIgPSBjaGFyYWN0ZXJEYXRhO1xyXG4gICAgaWYobWFwQWxwaGFudW1lcmljLmhhcyhjaGFyYWN0ZXJEYXRhKSl7XHJcbiAgICAgIGluZm9DaGFyYWN0ZXIgPSBtYXBBbHBoYW51bWVyaWMuZ2V0KGNoYXJhY3RlckRhdGEpO1xyXG4gICAgfVxyXG4gICAgdHJhbnNmb3JtICs9IGluZm9DaGFyYWN0ZXI7XHJcbiAgfVxyXG4gIHJldHVybiB0cmFuc2Zvcm07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFsZ29yaXRobUFtb3VudChkYXRhKXtcclxuICB2YXIgZGF0YVRyYW5zZm9ybSA9IGRhdGEuc3BsaXQoJy4nKS5qb2luKFwiXCIpO1xyXG4gIHZhciBpc1Bvc2l0aW9uID0gMVxyXG4gIHZhciBtYXBNdWx0aXBseSA9IG5ldyBNYXAoW1sxLCA3XSwgWzIsIDNdLCBbMywgMV1dKTtcclxuICB2YXIgc3VtRGF0YSA9IDA7XHJcbiAgZm9yKHZhciBpID0gZGF0YVRyYW5zZm9ybS5sZW5ndGgtMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgIHZhciBkYXRhTnVtYmVyID0gTnVtYmVyKGRhdGFUcmFuc2Zvcm0uY2hhckF0KGkpKTtcclxuICAgIHZhciBudW1iZXJNdWx0aXBseSA9IDA7XHJcbiAgICBpZihtYXBNdWx0aXBseS5oYXMoaXNQb3NpdGlvbikpe1xyXG4gICAgICBudW1iZXJNdWx0aXBseSA9IG1hcE11bHRpcGx5LmdldChpc1Bvc2l0aW9uKTtcclxuICAgIH1lbHNle1xyXG4gICAgICBpc1Bvc2l0aW9uID0gMTtcclxuICAgICAgbnVtYmVyTXVsdGlwbHkgPSBtYXBNdWx0aXBseS5nZXQoaXNQb3NpdGlvbik7XHJcbiAgICB9XHJcbiAgICBpc1Bvc2l0aW9uKys7XHJcbiAgICB2YXIgcmVzdWx0TXVsdGlwbHkgPSAobnVtYmVyTXVsdGlwbHkgKiBkYXRhTnVtYmVyKTtcclxuICAgIHN1bURhdGEgKz0gcmVzdWx0TXVsdGlwbHk7XHJcbiAgfVxyXG4gIHZhciBudW1iZXJBdXggPSAxMDtcclxuICB2YXIgcmVzaWR1ZSA9ICgoc3VtRGF0YSAlIG51bWJlckF1eCkgKyBudW1iZXJBdXgpICUgbnVtYmVyQXV4O1xyXG4gIFxyXG4gIHJldHVybiByZXNpZHVlLnRvU3RyaW5nKCkuY2hhckF0KHJlc2lkdWUudG9TdHJpbmcoKS5sZW5ndGgtMSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFsZ29yaXRobURhdGUoZGF0YSl7XHJcbiAgdmFyIGRheURhdGEgPSBkYXRhLnN1YnN0cmluZygwLCAyKTtcclxuICB2YXIgbW9udGhEYXRhID0gZGF0YS5zdWJzdHJpbmcoMiwgNCk7XHJcbiAgdmFyIHllYXJEYXRhID0gZGF0YS5zdWJzdHJpbmcoNCwgOCk7XHJcblxyXG4gIHZhciB5ZWFyU3VidHJhY3Rpb24gPSB5ZWFyRGF0YSAtIHllYXJCYXNlO1xyXG5cclxuICB2YXIgeWVhcnJlc3VsdE11bHRpcGx5ID0geWVhclN1YnRyYWN0aW9uICogeWVhck11bHRpcGx5O1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRTdWJ0cmFjdGlvbiA9IE51bWJlcihtb250aERhdGEpIC0gdW5pdFN1YnRyYWN0aW9uO1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRNdWx0aXBseSA9IG1vbnRoUmVzdWx0U3VidHJhY3Rpb24gKiBtb250aE11bHRpcGx5O1xyXG5cclxuICB2YXIgZGF5UmVzdWx0U3VidHJhY3Rpb24gPSBOdW1iZXIoZGF5RGF0YSkgLSB1bml0U3VidHJhY3Rpb247XHJcblxyXG4gIHZhciBkaWdpdFZlcmlmeURhdGUgPSB5ZWFycmVzdWx0TXVsdGlwbHkgKyBtb250aFJlc3VsdE11bHRpcGx5ICsgZGF5UmVzdWx0U3VidHJhY3Rpb247XHJcblxyXG4gIHJldHVybiBtaXNzaW5nRGF0YSg0LCBkaWdpdFZlcmlmeURhdGUudG9TdHJpbmcoKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1pc3NpbmdEYXRhKG1pbkxlbmd0aE1pc3NpbmcsIGRhdGEpe1xyXG4gIHZhciBtaXNzaW5nTGVmdCA9IG1pbkxlbmd0aE1pc3NpbmcgLSBkYXRhLmxlbmd0aDtcclxuICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdMZWZ0OyBpKyspIHtcclxuICAgIGRhdGEgPSBjb250YW50TGVmdCArIGRhdGE7XHJcbiAgfVxyXG4gIHJldHVybiBkYXRhO1xyXG59XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBfID0gcmVxdWlyZSgndW5kZXJzY29yZScpO1xyXG52YXIgQ0lFU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2NpZV9zdHJhdGVneS5qcycpLkNJRVN0cmF0ZWd5O1xyXG52YXIgQ0lFVXRpbHMgPSByZXF1aXJlKCcuL2NpZV91dGlscy5qcycpLkNJRVV0aWxzO1xyXG52YXIgY2llVXRpbHMgPSBuZXcgQ0lFVXRpbHMoKTtcclxuXHJcbnZhciBBbGc5NCA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5BbGc5NC5wcm90b3R5cGUgPSBuZXcgQ0lFU3RyYXRlZ3koKTtcclxuQWxnOTQucHJvdG90eXBlID0ge1xyXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKGlucHV0KSB7XHJcblxyXG4gICAgdmFyIHZhbGlkYXRpb25SdWxlcyA9IHtcclxuICAgICAgcmVmZXJlbmNlOiB7bGVuZ3RoOiB7bWluOiAxLG1heDogNDJ9fSxcclxuICAgICAgZGF0ZToge2xlbmd0aDoge21pbjogOCxtYXg6IDh9fSxcclxuICAgICAgYW1vdW50OiB7bGVuZ3RoOiB7bWluOiAxLG1heDogMTJ9fVxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAoIWNpZVV0aWxzLnZhbGlkYXRlSW5wdXQoaW5wdXQsdmFsaWRhdGlvblJ1bGVzICkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb25naXR1ZCBpbnZhbGlkYScpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBhbGc5NChpbnB1dC5kYXRlLCBpbnB1dC5hbW91bnQsIGlucHV0LnJlZmVyZW5jZSk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQWxnOTQgPSBBbGc5NDtcclxuXHJcbnZhciBjb250YW50TGVmdCA9IDA7XHJcbnZhciB5ZWFyQmFzZSA9IDIwMTM7XHJcbnZhciB5ZWFyTXVsdGlwbHkgPSAzNzI7XHJcbnZhciB1bml0U3VidHJhY3Rpb24gPSAxO1xyXG52YXIgbW9udGhNdWx0aXBseSA9IDMxO1xyXG52YXIgZGlnaXRWZXJpZnlDb25zdGFudCA9IDI7XHJcblxyXG5mdW5jdGlvbiBhbGc5NChkYXRlRXhwaXJlZCwgYW1vdW50LCByZWZlcmVuY2Upe1xyXG4gIHZhciBkaWdpdFZlcmlmeURhdGUgPSBhbGdvcml0aG1EYXRlKGRhdGVFeHBpcmVkKTtcclxuXHJcbiAgdmFyIGFtb3VudEZvcm1hdCA9IGNvbnZlcnRUb1BvdW5kcyhhbW91bnQpO1xyXG5cclxuICB2YXIgZGlnaXRWZXJpZnlBbW91bnQgPSBhbGdvcml0aG1BbW91bnQoYW1vdW50Rm9ybWF0KTtcclxuICB2YXIgcmVmZXJlbmNlOTQgPSByZWZlcmVuY2UgKyBkaWdpdFZlcmlmeURhdGUgKyBkaWdpdFZlcmlmeUFtb3VudCArIGRpZ2l0VmVyaWZ5Q29uc3RhbnQ7XHJcbiAgdmFyIGRpZ2l0VmVyaWZ5UmVmZXJlbmNlID0gYWxnb3JpdGhtUmVmZXJlbmNlKHJlZmVyZW5jZTk0LnRvVXBwZXJDYXNlKCkpO1xyXG4gIHJlZmVyZW5jZTk0ID0gcmVmZXJlbmNlOTQgKyBkaWdpdFZlcmlmeVJlZmVyZW5jZTtcclxuICByZXR1cm4gcmVmZXJlbmNlOTQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvbnZlcnRUb1BvdW5kcyhzdHIpIHtcdFxyXG5cdHZhciBuID0gTnVtYmVyLnBhcnNlRmxvYXQoc3RyKTtcclxuICBpZighc3RyIHx8IGlzTmFOKG4pIHx8IG4gPCAwKSByZXR1cm4gMDtcclxuICByZXR1cm4gbi50b0ZpeGVkKDIpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBhbGdvcml0aG1BbW91bnQoZGF0YSl7XHJcbiAgdmFyIGRhdGFUcmFuc2Zvcm0gPSBkYXRhLnNwbGl0KCcuJykuam9pbihcIlwiKTtcclxuICB2YXIgaXNQb3NpdGlvbiA9IDFcclxuICB2YXIgbWFwTXVsdGlwbHkgPSBuZXcgTWFwKFtbMSwgN10sIFsyLCAzXSwgWzMsIDFdXSk7XHJcbiAgdmFyIHN1bURhdGEgPSAwO1xyXG4gIGZvcih2YXIgaSA9IGRhdGFUcmFuc2Zvcm0ubGVuZ3RoLTE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICB2YXIgZGF0YU51bWJlciA9IE51bWJlcihkYXRhVHJhbnNmb3JtLmNoYXJBdChpKSk7XHJcbiAgICB2YXIgbnVtYmVyTXVsdGlwbHkgPSAwO1xyXG4gICAgaWYobWFwTXVsdGlwbHkuaGFzKGlzUG9zaXRpb24pKXtcclxuICAgICAgbnVtYmVyTXVsdGlwbHkgPSBtYXBNdWx0aXBseS5nZXQoaXNQb3NpdGlvbik7XHJcbiAgICB9ZWxzZXtcclxuICAgICAgaXNQb3NpdGlvbiA9IDE7XHJcbiAgICAgIG51bWJlck11bHRpcGx5ID0gbWFwTXVsdGlwbHkuZ2V0KGlzUG9zaXRpb24pO1xyXG4gICAgfVxyXG4gICAgaXNQb3NpdGlvbisrO1xyXG4gICAgdmFyIHJlc3VsdE11bHRpcGx5ID0gKG51bWJlck11bHRpcGx5ICogZGF0YU51bWJlcik7XHJcbiAgICBzdW1EYXRhICs9IHJlc3VsdE11bHRpcGx5O1xyXG4gIH1cclxuICB2YXIgbnVtYmVyQXV4ID0gMTA7XHJcbiAgdmFyIHJlc2lkdWUgPSAoKHN1bURhdGEgJSBudW1iZXJBdXgpICsgbnVtYmVyQXV4KSAlIG51bWJlckF1eDtcclxuXHJcbiAgcmV0dXJuIHJlc2lkdWUudG9TdHJpbmcoKS5jaGFyQXQocmVzaWR1ZS50b1N0cmluZygpLmxlbmd0aC0xKTtcclxufVxyXG5cclxuZnVuY3Rpb24gYWxnb3JpdGhtUmVmZXJlbmNlKGRhdGEpe1xyXG4gIHZhciBkYXRhUmVwbGFjZSA9IGRhdGE7XHJcbiAgdmFyIGlzUG9zaXRpb24gPSAxXHJcbiAgdmFyIG1hcE11bHRpcGx5ID0gbmV3IE1hcChbWzEsIDExXSwgWzIsIDEzXSwgWzMsIDE3XSwgWzQsIDE5XSwgWzUsIDIzXV0pO1xyXG4gIHZhciBzdW1EYXRhID0gMDtcclxuICBmb3IodmFyIGkgPSBkYXRhUmVwbGFjZS5sZW5ndGgtMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgIHZhciBkYXRhTnVtYmVyID0gTnVtYmVyKGRhdGFSZXBsYWNlLmNoYXJBdChpKSk7XHJcbiAgICB2YXIgbnVtYmVyTXVsdGlwbHkgPSAwO1xyXG4gICAgaWYobWFwTXVsdGlwbHkuaGFzKGlzUG9zaXRpb24pKXtcclxuICAgICAgbnVtYmVyTXVsdGlwbHkgPSBtYXBNdWx0aXBseS5nZXQoaXNQb3NpdGlvbik7XHJcbiAgICB9ZWxzZXtcclxuICAgICAgaXNQb3NpdGlvbiA9IDE7XHJcbiAgICAgIG51bWJlck11bHRpcGx5ID0gbWFwTXVsdGlwbHkuZ2V0KGlzUG9zaXRpb24pO1xyXG4gICAgfVxyXG4gICAgaXNQb3NpdGlvbisrO1xyXG4gICAgdmFyIHJlc3VsdE11bHRpcGx5ID0gKG51bWJlck11bHRpcGx5ICogZGF0YU51bWJlcik7XHJcbiAgICBzdW1EYXRhICs9IHJlc3VsdE11bHRpcGx5O1xyXG4gIH1cclxuICB2YXIgbnVtYmVyQXV4ID0gOTc7XHJcbiAgdmFyIHJlc2lkdWUgPSAoKHN1bURhdGEgJSBudW1iZXJBdXgpICsgbnVtYmVyQXV4KSAlIG51bWJlckF1eDtcclxuICB2YXIgZGlnaXRWZXJpZnlSZWZlcmVuY2UgPSByZXNpZHVlICsgMTtcclxuXHJcbiAgZGlnaXRWZXJpZnlSZWZlcmVuY2UgPSBkaWdpdFZlcmlmeVJlZmVyZW5jZS50b1N0cmluZygpO1xyXG5cclxuICByZXR1cm4gbWlzc2luZ0RhdGEoMiwgZGlnaXRWZXJpZnlSZWZlcmVuY2UudG9TdHJpbmcoKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFsZ29yaXRobURhdGUoZGF0YSl7XHJcbiAgdmFyIGRheURhdGEgPSBkYXRhLnN1YnN0cmluZygwLCAyKTtcclxuICB2YXIgbW9udGhEYXRhID0gZGF0YS5zdWJzdHJpbmcoMiwgNCk7XHJcbiAgdmFyIHllYXJEYXRhID0gZGF0YS5zdWJzdHJpbmcoNCwgOCk7XHJcblxyXG4gIHZhciB5ZWFyU3VidHJhY3Rpb24gPSB5ZWFyRGF0YSAtIHllYXJCYXNlO1xyXG5cclxuICB2YXIgeWVhcnJlc3VsdE11bHRpcGx5ID0geWVhclN1YnRyYWN0aW9uICogeWVhck11bHRpcGx5O1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRTdWJ0cmFjdGlvbiA9IE51bWJlcihtb250aERhdGEpIC0gdW5pdFN1YnRyYWN0aW9uO1xyXG5cclxuICB2YXIgbW9udGhSZXN1bHRNdWx0aXBseSA9IG1vbnRoUmVzdWx0U3VidHJhY3Rpb24gKiBtb250aE11bHRpcGx5O1xyXG5cclxuICB2YXIgZGF5UmVzdWx0U3VidHJhY3Rpb24gPSBOdW1iZXIoZGF5RGF0YSkgLSB1bml0U3VidHJhY3Rpb247XHJcblxyXG4gIHZhciBkaWdpdFZlcmlmeURhdGUgPSB5ZWFycmVzdWx0TXVsdGlwbHkgKyBtb250aFJlc3VsdE11bHRpcGx5ICsgZGF5UmVzdWx0U3VidHJhY3Rpb247XHJcblxyXG4gIHJldHVybiBtaXNzaW5nRGF0YSg0LCBkaWdpdFZlcmlmeURhdGUudG9TdHJpbmcoKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG1pc3NpbmdEYXRhKG1pbkxlbmd0aE1pc3NpbmcsIGRhdGEpe1xyXG4gIHZhciBtaXNzaW5nTGVmdCA9IG1pbkxlbmd0aE1pc3NpbmcgLSBkYXRhLmxlbmd0aDtcclxuICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdMZWZ0OyBpKyspIHtcclxuICAgIGRhdGEgPSBjb250YW50TGVmdCArIGRhdGE7XHJcbiAgfVxyXG4gIHJldHVybiBkYXRhO1xyXG59XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBDSUVDYWxjdWxhdG9yID0gZnVuY3Rpb24gKCkge1xyXG4gIHRoaXMuc3RyYXRlZ3kgPSAnJztcclxufTtcclxuXHJcbkNJRUNhbGN1bGF0b3IucHJvdG90eXBlID0ge1xyXG4gIHNldFN0cmF0ZWd5OiBmdW5jdGlvbihzdHJhdGVneSkge1xyXG4gICAgdGhpcy5zdHJhdGVneSA9IHN0cmF0ZWd5O1xyXG4gIH0sXHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24ocmVmZXJlbmNlKSB7XHJcbiAgICByZXR1cm4gdGhpcy5zdHJhdGVneS5leGVjdXRlKHJlZmVyZW5jZSk7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuQ0lFQ2FsY3VsYXRvciA9IENJRUNhbGN1bGF0b3I7XHJcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbnZhciBDSUVTdHJhdGVneSA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5DSUVTdHJhdGVneS5wcm90b3R5cGUgPSB7XHJcbiAgZXhlY3V0ZTogZnVuY3Rpb24oKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NJRVN0cmF0ZWd5I2V4ZWN1dGUgbmVlZHMgdG8gYmUgb3ZlcnJpZGRlbi4nKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5DSUVTdHJhdGVneSA9IENJRVN0cmF0ZWd5O1xyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcclxuXHJcbnZhciBDSUVVdGlscyA9IGZ1bmN0aW9uKCkge307XHJcblxyXG5DSUVVdGlscy5wcm90b3R5cGUgPSB7XHJcbiAgbmVhcmVzdE11bHRpcGxlT2Y6IGZ1bmN0aW9uKHZhbCwgYmFzZSkge1xyXG4gICAgcmV0dXJuICh2YWwgJSAxMCA9PSAwKSA/IHZhbCA6IChNYXRoLmZsb29yKHZhbC9iYXNlKSArIDEpKmJhc2U7XHJcbiAgfSxcclxuICBzZXF1ZW50aWFsQWRkOiAgIGZ1bmN0aW9uKGlucHV0KSB7XHJcbiAgICByZXR1cm4gXy5yZWR1Y2UoaW5wdXQudG9TdHJpbmcoKSwgZnVuY3Rpb24obWVtbyxudW0pIHsgcmV0dXJuIG1lbW8gKyBwYXJzZUludChudW0pOyB9LCAwKTtcclxuICB9LFxyXG4gIHJlcGxhY2VDaGFyV2l0aE51bTogZnVuY3Rpb24oaW5wdXQsIGNoYXJUb051bSkge1xyXG4gICAgcmV0dXJuIF8ubWFwKGlucHV0LCBmdW5jdGlvbih4KSB7IHJldHVybiBjaGFyVG9OdW1beF07fSk7XHJcbiAgfSxcclxuICBwYWQ6IGZ1bmN0aW9uKG4sIHdpZHRoLCB6KSB7XHJcbiAgICB6ID0geiB8fCAnMCc7XHJcbiAgICBuID0gbiArICcnO1xyXG4gICAgcmV0dXJuIG4ubGVuZ3RoID49IHdpZHRoID8gbiA6IG5ldyBBcnJheSh3aWR0aCAtIG4ubGVuZ3RoICsgMSkuam9pbih6KSArIG47XHJcbiAgfSxcclxuICB2YWxpZGF0ZUxlbmd0aDogZnVuY3Rpb24oZmllbGQsIG1pbiwgbWF4KSB7XHJcbiAgICByZXR1cm4gKGZpZWxkLmxlbmd0aCA+PSBtaW4gJiYgZmllbGQubGVuZ3RoIDw9IG1heCk7XHJcbiAgfSxcclxuICB3ZWlnaHRlZFJlZHVjZTogZnVuY3Rpb24oaW5wdXQsIHdlaWdodHMsIGRlYnVnKSB7XHJcbiAgICB2YXIgYWNjID0wO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoZGVidWcpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ2lucHV0OiAnICsgaW5wdXRbaV0gKyAnIHc6ICcgKyB3ZWlnaHRzW2kld2VpZ2h0cy5sZW5ndGhdICsgJyA9ICcgKyBwYXJzZUludChpbnB1dFtpXSAqIHdlaWdodHNbaSV3ZWlnaHRzLmxlbmd0aF0pKTtcclxuICAgICAgICB9XHJcbiAgICAgIGFjYyArPSBwYXJzZUludChpbnB1dFtpXSAqIHdlaWdodHNbaSV3ZWlnaHRzLmxlbmd0aF0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFjYztcclxuICB9LFxyXG4gIHNlcXVlbnRpYWxXZWlnaHRlZFJlZHVjZTogZnVuY3Rpb24oaW5wdXQsIHdlaWdodHMsIGRlYnVnKSB7XHJcbiAgICB2YXIgYWNjID0wO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoZGVidWcpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ2lucHV0OiAnICsgaW5wdXRbaV0gKyAnIHc6ICcgKyB3ZWlnaHRzW2kld2VpZ2h0cy5sZW5ndGhdICsgJyA9ICcgKyBDSUVVdGlscy5wcm90b3R5cGUuc2VxdWVudGlhbEFkZChwYXJzZUludChpbnB1dFtpXSAqIHdlaWdodHNbaSV3ZWlnaHRzLmxlbmd0aF0pKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgdmFyIHRtcCA9IENJRVV0aWxzLnByb3RvdHlwZS5zZXF1ZW50aWFsQWRkKHBhcnNlSW50KGlucHV0W2ldICogd2VpZ2h0c1tpJXdlaWdodHMubGVuZ3RoXSkpO1xyXG5cclxuICAgICAgd2hpbGUodG1wLnRvU3RyaW5nKCkubGVuZ3RoICE9PSAxKSB7XHJcbiAgICAgICAgdG1wID0gQ0lFVXRpbHMucHJvdG90eXBlLnNlcXVlbnRpYWxBZGQodG1wKTtcclxuICAgICAgfVxyXG4gICAgICBhY2MgKz0gdG1wO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFjYztcclxuICB9LFxyXG4gIHZhbGlkYXRlSW5wdXQ6ICBmdW5jdGlvbihpbnB1dCwgdmFsaWRhdGlvblJ1bGVzKSB7XHJcbiAgICB2YXIgdmFsaWRhdGVMZW5ndGhzID0gZnVuY3Rpb24oaW5wdXQsIHZhbGlkYXRpb25SdWxlcykge1xyXG4gICAgICByZXR1cm4gXy5yZWR1Y2UoXy5rZXlzKHZhbGlkYXRpb25SdWxlcyksIGZ1bmN0aW9uKG1lbW8sIGspIHtcclxuICAgICAgICByZXR1cm4gbWVtbyAmJiBDSUVVdGlscy5wcm90b3R5cGUudmFsaWRhdGVMZW5ndGgoaW5wdXRba10sIHZhbGlkYXRpb25SdWxlc1trXS5sZW5ndGgubWluLCB2YWxpZGF0aW9uUnVsZXNba10ubGVuZ3RoLm1heCk7XHJcbiAgICAgIH0sIHRydWUpO1xyXG4gICAgfTtcclxuICAgIHJldHVybiB2YWxpZGF0ZUxlbmd0aHMoaW5wdXQsdmFsaWRhdGlvblJ1bGVzKTtcclxuICB9XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cy5DSUVVdGlscyA9IENJRVV0aWxzO1xyXG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgQ0lFQ2FsY3VsYXRvciA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvY2llX2NhbGN1bGF0b3IuanMnKS5DSUVDYWxjdWxhdG9yO1xyXG52YXIgQWxnMDAgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzAwLmpzJykuQWxnMDA7XHJcbnZhciBBbGcwMiA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnMDIuanMnKS5BbGcwMjtcclxudmFyIEFsZzAzID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGcwMy5qcycpLkFsZzAzO1xyXG52YXIgQWxnMDQgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzA0LmpzJykuQWxnMDQ7XHJcbnZhciBBbGcwNiA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnMDYuanMnKS5BbGcwNjtcclxudmFyIEFsZzEwID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGcxMC5qcycpLkFsZzEwO1xyXG52YXIgQWxnMTEgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzExLmpzJykuQWxnMTE7XHJcbnZhciBBbGcxNCA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnMTQuanMnKS5BbGcxNDtcclxudmFyIEFsZzIxID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGcyMS5qcycpLkFsZzIxO1xyXG52YXIgQWxnMjcgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzI3LmpzJykuQWxnMjc7XHJcbnZhciBBbGczNSA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnMzUuanMnKS5BbGczNTtcclxudmFyIEFsZzM2ID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGczNi5qcycpLkFsZzM2O1xyXG52YXIgQWxnMzcgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzM3LmpzJykuQWxnMzc7XHJcbnZhciBBbGc0NSA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnNDUuanMnKS5BbGc0NTtcclxudmFyIEFsZzYyID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGc2Mi5qcycpLkFsZzYyO1xyXG52YXIgQWxnNzIgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzcyLmpzJykuQWxnNzI7XHJcbnZhciBBbGc3NyA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnNzcuanMnKS5BbGc3NztcclxudmFyIEFsZzgwID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGc4MC5qcycpLkFsZzgwO1xyXG52YXIgQWxnODEgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzgxLmpzJykuQWxnODE7XHJcbnZhciBBbGc4MiA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnODIuanMnKS5BbGc4MjtcclxudmFyIEFsZzg5ID0gcmVxdWlyZSgnLi9saWIvc3RyYXRlZ2llcy9hbGc4OS5qcycpLkFsZzg5O1xyXG52YXIgQWxnOTEgPSByZXF1aXJlKCcuL2xpYi9zdHJhdGVnaWVzL2FsZzkxLmpzJykuQWxnOTE7XHJcbnZhciBBbGc5NCA9IHJlcXVpcmUoJy4vbGliL3N0cmF0ZWdpZXMvYWxnOTQuanMnKS5BbGc5NDtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgdmFyIGNhbGN1bGF0b3IgPSBuZXcgQ0lFQ2FsY3VsYXRvcigpO1xyXG4gIGNhbGN1bGF0b3Iuc2V0U3RyYXRlZ3koZXZhbCgnbmV3IEFsZycrcGFyYW1zLmFsZysnKCknKSk7XHJcbiAgcmV0dXJuIGNhbGN1bGF0b3IuZXhlY3V0ZShwYXJhbXMpO1xyXG59XHJcbiIsIi8vICAgICBVbmRlcnNjb3JlLmpzIDEuOC4zXG4vLyAgICAgaHR0cDovL3VuZGVyc2NvcmVqcy5vcmdcbi8vICAgICAoYykgMjAwOS0yMDE1IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4vLyAgICAgVW5kZXJzY29yZSBtYXkgYmUgZnJlZWx5IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cblxuKGZ1bmN0aW9uKCkge1xuXG4gIC8vIEJhc2VsaW5lIHNldHVwXG4gIC8vIC0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gRXN0YWJsaXNoIHRoZSByb290IG9iamVjdCwgYHdpbmRvd2AgaW4gdGhlIGJyb3dzZXIsIG9yIGBleHBvcnRzYCBvbiB0aGUgc2VydmVyLlxuICB2YXIgcm9vdCA9IHRoaXM7XG5cbiAgLy8gU2F2ZSB0aGUgcHJldmlvdXMgdmFsdWUgb2YgdGhlIGBfYCB2YXJpYWJsZS5cbiAgdmFyIHByZXZpb3VzVW5kZXJzY29yZSA9IHJvb3QuXztcblxuICAvLyBTYXZlIGJ5dGVzIGluIHRoZSBtaW5pZmllZCAoYnV0IG5vdCBnemlwcGVkKSB2ZXJzaW9uOlxuICB2YXIgQXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZSwgT2JqUHJvdG8gPSBPYmplY3QucHJvdG90eXBlLCBGdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGU7XG5cbiAgLy8gQ3JlYXRlIHF1aWNrIHJlZmVyZW5jZSB2YXJpYWJsZXMgZm9yIHNwZWVkIGFjY2VzcyB0byBjb3JlIHByb3RvdHlwZXMuXG4gIHZhclxuICAgIHB1c2ggICAgICAgICAgICAgPSBBcnJheVByb3RvLnB1c2gsXG4gICAgc2xpY2UgICAgICAgICAgICA9IEFycmF5UHJvdG8uc2xpY2UsXG4gICAgdG9TdHJpbmcgICAgICAgICA9IE9ialByb3RvLnRvU3RyaW5nLFxuICAgIGhhc093blByb3BlcnR5ICAgPSBPYmpQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvLyBBbGwgKipFQ01BU2NyaXB0IDUqKiBuYXRpdmUgZnVuY3Rpb24gaW1wbGVtZW50YXRpb25zIHRoYXQgd2UgaG9wZSB0byB1c2VcbiAgLy8gYXJlIGRlY2xhcmVkIGhlcmUuXG4gIHZhclxuICAgIG5hdGl2ZUlzQXJyYXkgICAgICA9IEFycmF5LmlzQXJyYXksXG4gICAgbmF0aXZlS2V5cyAgICAgICAgID0gT2JqZWN0LmtleXMsXG4gICAgbmF0aXZlQmluZCAgICAgICAgID0gRnVuY1Byb3RvLmJpbmQsXG4gICAgbmF0aXZlQ3JlYXRlICAgICAgID0gT2JqZWN0LmNyZWF0ZTtcblxuICAvLyBOYWtlZCBmdW5jdGlvbiByZWZlcmVuY2UgZm9yIHN1cnJvZ2F0ZS1wcm90b3R5cGUtc3dhcHBpbmcuXG4gIHZhciBDdG9yID0gZnVuY3Rpb24oKXt9O1xuXG4gIC8vIENyZWF0ZSBhIHNhZmUgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgdXNlIGJlbG93LlxuICB2YXIgXyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogaW5zdGFuY2VvZiBfKSByZXR1cm4gb2JqO1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBfKSkgcmV0dXJuIG5ldyBfKG9iaik7XG4gICAgdGhpcy5fd3JhcHBlZCA9IG9iajtcbiAgfTtcblxuICAvLyBFeHBvcnQgdGhlIFVuZGVyc2NvcmUgb2JqZWN0IGZvciAqKk5vZGUuanMqKiwgd2l0aFxuICAvLyBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSBmb3IgdGhlIG9sZCBgcmVxdWlyZSgpYCBBUEkuIElmIHdlJ3JlIGluXG4gIC8vIHRoZSBicm93c2VyLCBhZGQgYF9gIGFzIGEgZ2xvYmFsIG9iamVjdC5cbiAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gXztcbiAgICB9XG4gICAgZXhwb3J0cy5fID0gXztcbiAgfSBlbHNlIHtcbiAgICByb290Ll8gPSBfO1xuICB9XG5cbiAgLy8gQ3VycmVudCB2ZXJzaW9uLlxuICBfLlZFUlNJT04gPSAnMS44LjMnO1xuXG4gIC8vIEludGVybmFsIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBlZmZpY2llbnQgKGZvciBjdXJyZW50IGVuZ2luZXMpIHZlcnNpb25cbiAgLy8gb2YgdGhlIHBhc3NlZC1pbiBjYWxsYmFjaywgdG8gYmUgcmVwZWF0ZWRseSBhcHBsaWVkIGluIG90aGVyIFVuZGVyc2NvcmVcbiAgLy8gZnVuY3Rpb25zLlxuICB2YXIgb3B0aW1pemVDYiA9IGZ1bmN0aW9uKGZ1bmMsIGNvbnRleHQsIGFyZ0NvdW50KSB7XG4gICAgaWYgKGNvbnRleHQgPT09IHZvaWQgMCkgcmV0dXJuIGZ1bmM7XG4gICAgc3dpdGNoIChhcmdDb3VudCA9PSBudWxsID8gMyA6IGFyZ0NvdW50KSB7XG4gICAgICBjYXNlIDE6IHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICByZXR1cm4gZnVuYy5jYWxsKGNvbnRleHQsIHZhbHVlKTtcbiAgICAgIH07XG4gICAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbih2YWx1ZSwgb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbChjb250ZXh0LCB2YWx1ZSwgb3RoZXIpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICByZXR1cm4gZnVuYy5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICB9O1xuICAgICAgY2FzZSA0OiByZXR1cm4gZnVuY3Rpb24oYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICByZXR1cm4gZnVuYy5jYWxsKGNvbnRleHQsIGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEEgbW9zdGx5LWludGVybmFsIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGNhbGxiYWNrcyB0aGF0IGNhbiBiZSBhcHBsaWVkXG4gIC8vIHRvIGVhY2ggZWxlbWVudCBpbiBhIGNvbGxlY3Rpb24sIHJldHVybmluZyB0aGUgZGVzaXJlZCByZXN1bHQg4oCUIGVpdGhlclxuICAvLyBpZGVudGl0eSwgYW4gYXJiaXRyYXJ5IGNhbGxiYWNrLCBhIHByb3BlcnR5IG1hdGNoZXIsIG9yIGEgcHJvcGVydHkgYWNjZXNzb3IuXG4gIHZhciBjYiA9IGZ1bmN0aW9uKHZhbHVlLCBjb250ZXh0LCBhcmdDb3VudCkge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gXy5pZGVudGl0eTtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKHZhbHVlKSkgcmV0dXJuIG9wdGltaXplQ2IodmFsdWUsIGNvbnRleHQsIGFyZ0NvdW50KTtcbiAgICBpZiAoXy5pc09iamVjdCh2YWx1ZSkpIHJldHVybiBfLm1hdGNoZXIodmFsdWUpO1xuICAgIHJldHVybiBfLnByb3BlcnR5KHZhbHVlKTtcbiAgfTtcbiAgXy5pdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb250ZXh0KSB7XG4gICAgcmV0dXJuIGNiKHZhbHVlLCBjb250ZXh0LCBJbmZpbml0eSk7XG4gIH07XG5cbiAgLy8gQW4gaW50ZXJuYWwgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIGFzc2lnbmVyIGZ1bmN0aW9ucy5cbiAgdmFyIGNyZWF0ZUFzc2lnbmVyID0gZnVuY3Rpb24oa2V5c0Z1bmMsIHVuZGVmaW5lZE9ubHkpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggPCAyIHx8IG9iaiA9PSBudWxsKSByZXR1cm4gb2JqO1xuICAgICAgZm9yICh2YXIgaW5kZXggPSAxOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2luZGV4XSxcbiAgICAgICAgICAgIGtleXMgPSBrZXlzRnVuYyhzb3VyY2UpLFxuICAgICAgICAgICAgbCA9IGtleXMubGVuZ3RoO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgICAgIGlmICghdW5kZWZpbmVkT25seSB8fCBvYmpba2V5XSA9PT0gdm9pZCAwKSBvYmpba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqO1xuICAgIH07XG4gIH07XG5cbiAgLy8gQW4gaW50ZXJuYWwgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIGEgbmV3IG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gYW5vdGhlci5cbiAgdmFyIGJhc2VDcmVhdGUgPSBmdW5jdGlvbihwcm90b3R5cGUpIHtcbiAgICBpZiAoIV8uaXNPYmplY3QocHJvdG90eXBlKSkgcmV0dXJuIHt9O1xuICAgIGlmIChuYXRpdmVDcmVhdGUpIHJldHVybiBuYXRpdmVDcmVhdGUocHJvdG90eXBlKTtcbiAgICBDdG9yLnByb3RvdHlwZSA9IHByb3RvdHlwZTtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IEN0b3I7XG4gICAgQ3Rvci5wcm90b3R5cGUgPSBudWxsO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIHByb3BlcnR5ID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIG9iaiA9PSBudWxsID8gdm9pZCAwIDogb2JqW2tleV07XG4gICAgfTtcbiAgfTtcblxuICAvLyBIZWxwZXIgZm9yIGNvbGxlY3Rpb24gbWV0aG9kcyB0byBkZXRlcm1pbmUgd2hldGhlciBhIGNvbGxlY3Rpb25cbiAgLy8gc2hvdWxkIGJlIGl0ZXJhdGVkIGFzIGFuIGFycmF5IG9yIGFzIGFuIG9iamVjdFxuICAvLyBSZWxhdGVkOiBodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aFxuICAvLyBBdm9pZHMgYSB2ZXJ5IG5hc3R5IGlPUyA4IEpJVCBidWcgb24gQVJNLTY0LiAjMjA5NFxuICB2YXIgTUFYX0FSUkFZX0lOREVYID0gTWF0aC5wb3coMiwgNTMpIC0gMTtcbiAgdmFyIGdldExlbmd0aCA9IHByb3BlcnR5KCdsZW5ndGgnKTtcbiAgdmFyIGlzQXJyYXlMaWtlID0gZnVuY3Rpb24oY29sbGVjdGlvbikge1xuICAgIHZhciBsZW5ndGggPSBnZXRMZW5ndGgoY29sbGVjdGlvbik7XG4gICAgcmV0dXJuIHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgJiYgbGVuZ3RoID49IDAgJiYgbGVuZ3RoIDw9IE1BWF9BUlJBWV9JTkRFWDtcbiAgfTtcblxuICAvLyBDb2xsZWN0aW9uIEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFRoZSBjb3JuZXJzdG9uZSwgYW4gYGVhY2hgIGltcGxlbWVudGF0aW9uLCBha2EgYGZvckVhY2hgLlxuICAvLyBIYW5kbGVzIHJhdyBvYmplY3RzIGluIGFkZGl0aW9uIHRvIGFycmF5LWxpa2VzLiBUcmVhdHMgYWxsXG4gIC8vIHNwYXJzZSBhcnJheS1saWtlcyBhcyBpZiB0aGV5IHdlcmUgZGVuc2UuXG4gIF8uZWFjaCA9IF8uZm9yRWFjaCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIHZhciBpLCBsZW5ndGg7XG4gICAgaWYgKGlzQXJyYXlMaWtlKG9iaikpIHtcbiAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IG9iai5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpdGVyYXRlZShvYmpbaV0sIGksIG9iaik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGl0ZXJhdGVlKG9ialtrZXlzW2ldXSwga2V5c1tpXSwgb2JqKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIHJlc3VsdHMgb2YgYXBwbHlpbmcgdGhlIGl0ZXJhdGVlIHRvIGVhY2ggZWxlbWVudC5cbiAgXy5tYXAgPSBfLmNvbGxlY3QgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgdmFyIGtleXMgPSAhaXNBcnJheUxpa2Uob2JqKSAmJiBfLmtleXMob2JqKSxcbiAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdHMgPSBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7XG4gICAgICByZXN1bHRzW2luZGV4XSA9IGl0ZXJhdGVlKG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIGEgcmVkdWNpbmcgZnVuY3Rpb24gaXRlcmF0aW5nIGxlZnQgb3IgcmlnaHQuXG4gIGZ1bmN0aW9uIGNyZWF0ZVJlZHVjZShkaXIpIHtcbiAgICAvLyBPcHRpbWl6ZWQgaXRlcmF0b3IgZnVuY3Rpb24gYXMgdXNpbmcgYXJndW1lbnRzLmxlbmd0aFxuICAgIC8vIGluIHRoZSBtYWluIGZ1bmN0aW9uIHdpbGwgZGVvcHRpbWl6ZSB0aGUsIHNlZSAjMTk5MS5cbiAgICBmdW5jdGlvbiBpdGVyYXRvcihvYmosIGl0ZXJhdGVlLCBtZW1vLCBrZXlzLCBpbmRleCwgbGVuZ3RoKSB7XG4gICAgICBmb3IgKDsgaW5kZXggPj0gMCAmJiBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gZGlyKSB7XG4gICAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7XG4gICAgICAgIG1lbW8gPSBpdGVyYXRlZShtZW1vLCBvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaik7XG4gICAgICB9XG4gICAgICByZXR1cm4gbWVtbztcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgbWVtbywgY29udGV4dCkge1xuICAgICAgaXRlcmF0ZWUgPSBvcHRpbWl6ZUNiKGl0ZXJhdGVlLCBjb250ZXh0LCA0KTtcbiAgICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksXG4gICAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGgsXG4gICAgICAgICAgaW5kZXggPSBkaXIgPiAwID8gMCA6IGxlbmd0aCAtIDE7XG4gICAgICAvLyBEZXRlcm1pbmUgdGhlIGluaXRpYWwgdmFsdWUgaWYgbm9uZSBpcyBwcm92aWRlZC5cbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykge1xuICAgICAgICBtZW1vID0gb2JqW2tleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4XTtcbiAgICAgICAgaW5kZXggKz0gZGlyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGl0ZXJhdG9yKG9iaiwgaXRlcmF0ZWUsIG1lbW8sIGtleXMsIGluZGV4LCBsZW5ndGgpO1xuICAgIH07XG4gIH1cblxuICAvLyAqKlJlZHVjZSoqIGJ1aWxkcyB1cCBhIHNpbmdsZSByZXN1bHQgZnJvbSBhIGxpc3Qgb2YgdmFsdWVzLCBha2EgYGluamVjdGAsXG4gIC8vIG9yIGBmb2xkbGAuXG4gIF8ucmVkdWNlID0gXy5mb2xkbCA9IF8uaW5qZWN0ID0gY3JlYXRlUmVkdWNlKDEpO1xuXG4gIC8vIFRoZSByaWdodC1hc3NvY2lhdGl2ZSB2ZXJzaW9uIG9mIHJlZHVjZSwgYWxzbyBrbm93biBhcyBgZm9sZHJgLlxuICBfLnJlZHVjZVJpZ2h0ID0gXy5mb2xkciA9IGNyZWF0ZVJlZHVjZSgtMSk7XG5cbiAgLy8gUmV0dXJuIHRoZSBmaXJzdCB2YWx1ZSB3aGljaCBwYXNzZXMgYSB0cnV0aCB0ZXN0LiBBbGlhc2VkIGFzIGBkZXRlY3RgLlxuICBfLmZpbmQgPSBfLmRldGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIGtleTtcbiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSkge1xuICAgICAga2V5ID0gXy5maW5kSW5kZXgob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBrZXkgPSBfLmZpbmRLZXkob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIH1cbiAgICBpZiAoa2V5ICE9PSB2b2lkIDAgJiYga2V5ICE9PSAtMSkgcmV0dXJuIG9ialtrZXldO1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgcGFzcyBhIHRydXRoIHRlc3QuXG4gIC8vIEFsaWFzZWQgYXMgYHNlbGVjdGAuXG4gIF8uZmlsdGVyID0gXy5zZWxlY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBsaXN0KSkgcmVzdWx0cy5wdXNoKHZhbHVlKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyBmb3Igd2hpY2ggYSB0cnV0aCB0ZXN0IGZhaWxzLlxuICBfLnJlamVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKG9iaiwgXy5uZWdhdGUoY2IocHJlZGljYXRlKSksIGNvbnRleHQpO1xuICB9O1xuXG4gIC8vIERldGVybWluZSB3aGV0aGVyIGFsbCBvZiB0aGUgZWxlbWVudHMgbWF0Y2ggYSB0cnV0aCB0ZXN0LlxuICAvLyBBbGlhc2VkIGFzIGBhbGxgLlxuICBfLmV2ZXJ5ID0gXy5hbGwgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgdmFyIGtleXMgPSAhaXNBcnJheUxpa2Uob2JqKSAmJiBfLmtleXMob2JqKSxcbiAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGg7XG4gICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgdmFyIGN1cnJlbnRLZXkgPSBrZXlzID8ga2V5c1tpbmRleF0gOiBpbmRleDtcbiAgICAgIGlmICghcHJlZGljYXRlKG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgaWYgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gdGhlIG9iamVjdCBtYXRjaGVzIGEgdHJ1dGggdGVzdC5cbiAgLy8gQWxpYXNlZCBhcyBgYW55YC5cbiAgXy5zb21lID0gXy5hbnkgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgdmFyIGtleXMgPSAhaXNBcnJheUxpa2Uob2JqKSAmJiBfLmtleXMob2JqKSxcbiAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGg7XG4gICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgdmFyIGN1cnJlbnRLZXkgPSBrZXlzID8ga2V5c1tpbmRleF0gOiBpbmRleDtcbiAgICAgIGlmIChwcmVkaWNhdGUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuXG4gIC8vIERldGVybWluZSBpZiB0aGUgYXJyYXkgb3Igb2JqZWN0IGNvbnRhaW5zIGEgZ2l2ZW4gaXRlbSAodXNpbmcgYD09PWApLlxuICAvLyBBbGlhc2VkIGFzIGBpbmNsdWRlc2AgYW5kIGBpbmNsdWRlYC5cbiAgXy5jb250YWlucyA9IF8uaW5jbHVkZXMgPSBfLmluY2x1ZGUgPSBmdW5jdGlvbihvYmosIGl0ZW0sIGZyb21JbmRleCwgZ3VhcmQpIHtcbiAgICBpZiAoIWlzQXJyYXlMaWtlKG9iaikpIG9iaiA9IF8udmFsdWVzKG9iaik7XG4gICAgaWYgKHR5cGVvZiBmcm9tSW5kZXggIT0gJ251bWJlcicgfHwgZ3VhcmQpIGZyb21JbmRleCA9IDA7XG4gICAgcmV0dXJuIF8uaW5kZXhPZihvYmosIGl0ZW0sIGZyb21JbmRleCkgPj0gMDtcbiAgfTtcblxuICAvLyBJbnZva2UgYSBtZXRob2QgKHdpdGggYXJndW1lbnRzKSBvbiBldmVyeSBpdGVtIGluIGEgY29sbGVjdGlvbi5cbiAgXy5pbnZva2UgPSBmdW5jdGlvbihvYmosIG1ldGhvZCkge1xuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHZhciBpc0Z1bmMgPSBfLmlzRnVuY3Rpb24obWV0aG9kKTtcbiAgICByZXR1cm4gXy5tYXAob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0Z1bmMgPyBtZXRob2QgOiB2YWx1ZVttZXRob2RdO1xuICAgICAgcmV0dXJuIGZ1bmMgPT0gbnVsbCA/IGZ1bmMgOiBmdW5jLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBtYXBgOiBmZXRjaGluZyBhIHByb3BlcnR5LlxuICBfLnBsdWNrID0gZnVuY3Rpb24ob2JqLCBrZXkpIHtcbiAgICByZXR1cm4gXy5tYXAob2JqLCBfLnByb3BlcnR5KGtleSkpO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbHRlcmA6IHNlbGVjdGluZyBvbmx5IG9iamVjdHNcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy53aGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIob2JqLCBfLm1hdGNoZXIoYXR0cnMpKTtcbiAgfTtcblxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBmaW5kYDogZ2V0dGluZyB0aGUgZmlyc3Qgb2JqZWN0XG4gIC8vIGNvbnRhaW5pbmcgc3BlY2lmaWMgYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8uZmluZFdoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xuICAgIHJldHVybiBfLmZpbmQob2JqLCBfLm1hdGNoZXIoYXR0cnMpKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG1heGltdW0gZWxlbWVudCAob3IgZWxlbWVudC1iYXNlZCBjb21wdXRhdGlvbikuXG4gIF8ubWF4ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHQgPSAtSW5maW5pdHksIGxhc3RDb21wdXRlZCA9IC1JbmZpbml0eSxcbiAgICAgICAgdmFsdWUsIGNvbXB1dGVkO1xuICAgIGlmIChpdGVyYXRlZSA9PSBudWxsICYmIG9iaiAhPSBudWxsKSB7XG4gICAgICBvYmogPSBpc0FycmF5TGlrZShvYmopID8gb2JqIDogXy52YWx1ZXMob2JqKTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFsdWUgPSBvYmpbaV07XG4gICAgICAgIGlmICh2YWx1ZSA+IHJlc3VsdCkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBsaXN0KTtcbiAgICAgICAgaWYgKGNvbXB1dGVkID4gbGFzdENvbXB1dGVkIHx8IGNvbXB1dGVkID09PSAtSW5maW5pdHkgJiYgcmVzdWx0ID09PSAtSW5maW5pdHkpIHtcbiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBtaW5pbXVtIGVsZW1lbnQgKG9yIGVsZW1lbnQtYmFzZWQgY29tcHV0YXRpb24pLlxuICBfLm1pbiA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0ID0gSW5maW5pdHksIGxhc3RDb21wdXRlZCA9IEluZmluaXR5LFxuICAgICAgICB2YWx1ZSwgY29tcHV0ZWQ7XG4gICAgaWYgKGl0ZXJhdGVlID09IG51bGwgJiYgb2JqICE9IG51bGwpIHtcbiAgICAgIG9iaiA9IGlzQXJyYXlMaWtlKG9iaikgPyBvYmogOiBfLnZhbHVlcyhvYmopO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG9iai5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICB2YWx1ZSA9IG9ialtpXTtcbiAgICAgICAgaWYgKHZhbHVlIDwgcmVzdWx0KSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGxpc3QpO1xuICAgICAgICBpZiAoY29tcHV0ZWQgPCBsYXN0Q29tcHV0ZWQgfHwgY29tcHV0ZWQgPT09IEluZmluaXR5ICYmIHJlc3VsdCA9PT0gSW5maW5pdHkpIHtcbiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gU2h1ZmZsZSBhIGNvbGxlY3Rpb24sIHVzaW5nIHRoZSBtb2Rlcm4gdmVyc2lvbiBvZiB0aGVcbiAgLy8gW0Zpc2hlci1ZYXRlcyBzaHVmZmxlXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlcuKAk1lhdGVzX3NodWZmbGUpLlxuICBfLnNodWZmbGUgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgc2V0ID0gaXNBcnJheUxpa2Uob2JqKSA/IG9iaiA6IF8udmFsdWVzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IHNldC5sZW5ndGg7XG4gICAgdmFyIHNodWZmbGVkID0gQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpbmRleCA9IDAsIHJhbmQ7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICByYW5kID0gXy5yYW5kb20oMCwgaW5kZXgpO1xuICAgICAgaWYgKHJhbmQgIT09IGluZGV4KSBzaHVmZmxlZFtpbmRleF0gPSBzaHVmZmxlZFtyYW5kXTtcbiAgICAgIHNodWZmbGVkW3JhbmRdID0gc2V0W2luZGV4XTtcbiAgICB9XG4gICAgcmV0dXJuIHNodWZmbGVkO1xuICB9O1xuXG4gIC8vIFNhbXBsZSAqKm4qKiByYW5kb20gdmFsdWVzIGZyb20gYSBjb2xsZWN0aW9uLlxuICAvLyBJZiAqKm4qKiBpcyBub3Qgc3BlY2lmaWVkLCByZXR1cm5zIGEgc2luZ2xlIHJhbmRvbSBlbGVtZW50LlxuICAvLyBUaGUgaW50ZXJuYWwgYGd1YXJkYCBhcmd1bWVudCBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBtYXBgLlxuICBfLnNhbXBsZSA9IGZ1bmN0aW9uKG9iaiwgbiwgZ3VhcmQpIHtcbiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSB7XG4gICAgICBpZiAoIWlzQXJyYXlMaWtlKG9iaikpIG9iaiA9IF8udmFsdWVzKG9iaik7XG4gICAgICByZXR1cm4gb2JqW18ucmFuZG9tKG9iai5sZW5ndGggLSAxKV07XG4gICAgfVxuICAgIHJldHVybiBfLnNodWZmbGUob2JqKS5zbGljZSgwLCBNYXRoLm1heCgwLCBuKSk7XG4gIH07XG5cbiAgLy8gU29ydCB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uIHByb2R1Y2VkIGJ5IGFuIGl0ZXJhdGVlLlxuICBfLnNvcnRCeSA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICByZXR1cm4gXy5wbHVjayhfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgIGNyaXRlcmlhOiBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGxpc3QpXG4gICAgICB9O1xuICAgIH0pLnNvcnQoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgICAgIHZhciBhID0gbGVmdC5jcml0ZXJpYTtcbiAgICAgIHZhciBiID0gcmlnaHQuY3JpdGVyaWE7XG4gICAgICBpZiAoYSAhPT0gYikge1xuICAgICAgICBpZiAoYSA+IGIgfHwgYSA9PT0gdm9pZCAwKSByZXR1cm4gMTtcbiAgICAgICAgaWYgKGEgPCBiIHx8IGIgPT09IHZvaWQgMCkgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxlZnQuaW5kZXggLSByaWdodC5pbmRleDtcbiAgICB9KSwgJ3ZhbHVlJyk7XG4gIH07XG5cbiAgLy8gQW4gaW50ZXJuYWwgZnVuY3Rpb24gdXNlZCBmb3IgYWdncmVnYXRlIFwiZ3JvdXAgYnlcIiBvcGVyYXRpb25zLlxuICB2YXIgZ3JvdXAgPSBmdW5jdGlvbihiZWhhdmlvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgICB2YXIga2V5ID0gaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBvYmopO1xuICAgICAgICBiZWhhdmlvcihyZXN1bHQsIHZhbHVlLCBrZXkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gR3JvdXBzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24uIFBhc3MgZWl0aGVyIGEgc3RyaW5nIGF0dHJpYnV0ZVxuICAvLyB0byBncm91cCBieSwgb3IgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIGNyaXRlcmlvbi5cbiAgXy5ncm91cEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgaWYgKF8uaGFzKHJlc3VsdCwga2V5KSkgcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSk7IGVsc2UgcmVzdWx0W2tleV0gPSBbdmFsdWVdO1xuICB9KTtcblxuICAvLyBJbmRleGVzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24sIHNpbWlsYXIgdG8gYGdyb3VwQnlgLCBidXQgZm9yXG4gIC8vIHdoZW4geW91IGtub3cgdGhhdCB5b3VyIGluZGV4IHZhbHVlcyB3aWxsIGJlIHVuaXF1ZS5cbiAgXy5pbmRleEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG5cbiAgLy8gQ291bnRzIGluc3RhbmNlcyBvZiBhbiBvYmplY3QgdGhhdCBncm91cCBieSBhIGNlcnRhaW4gY3JpdGVyaW9uLiBQYXNzXG4gIC8vIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGUgdG8gY291bnQgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZVxuICAvLyBjcml0ZXJpb24uXG4gIF8uY291bnRCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgIGlmIChfLmhhcyhyZXN1bHQsIGtleSkpIHJlc3VsdFtrZXldKys7IGVsc2UgcmVzdWx0W2tleV0gPSAxO1xuICB9KTtcblxuICAvLyBTYWZlbHkgY3JlYXRlIGEgcmVhbCwgbGl2ZSBhcnJheSBmcm9tIGFueXRoaW5nIGl0ZXJhYmxlLlxuICBfLnRvQXJyYXkgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIW9iaikgcmV0dXJuIFtdO1xuICAgIGlmIChfLmlzQXJyYXkob2JqKSkgcmV0dXJuIHNsaWNlLmNhbGwob2JqKTtcbiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSkgcmV0dXJuIF8ubWFwKG9iaiwgXy5pZGVudGl0eSk7XG4gICAgcmV0dXJuIF8udmFsdWVzKG9iaik7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYW4gb2JqZWN0LlxuICBfLnNpemUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiAwO1xuICAgIHJldHVybiBpc0FycmF5TGlrZShvYmopID8gb2JqLmxlbmd0aCA6IF8ua2V5cyhvYmopLmxlbmd0aDtcbiAgfTtcblxuICAvLyBTcGxpdCBhIGNvbGxlY3Rpb24gaW50byB0d28gYXJyYXlzOiBvbmUgd2hvc2UgZWxlbWVudHMgYWxsIHNhdGlzZnkgdGhlIGdpdmVuXG4gIC8vIHByZWRpY2F0ZSwgYW5kIG9uZSB3aG9zZSBlbGVtZW50cyBhbGwgZG8gbm90IHNhdGlzZnkgdGhlIHByZWRpY2F0ZS5cbiAgXy5wYXJ0aXRpb24gPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgdmFyIHBhc3MgPSBbXSwgZmFpbCA9IFtdO1xuICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iaikge1xuICAgICAgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBvYmopID8gcGFzcyA6IGZhaWwpLnB1c2godmFsdWUpO1xuICAgIH0pO1xuICAgIHJldHVybiBbcGFzcywgZmFpbF07XG4gIH07XG5cbiAgLy8gQXJyYXkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIEdldCB0aGUgZmlyc3QgZWxlbWVudCBvZiBhbiBhcnJheS4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiB0aGUgZmlyc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBBbGlhc2VkIGFzIGBoZWFkYCBhbmQgYHRha2VgLiBUaGUgKipndWFyZCoqIGNoZWNrXG4gIC8vIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5maXJzdCA9IF8uaGVhZCA9IF8udGFrZSA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xuICAgIGlmIChuID09IG51bGwgfHwgZ3VhcmQpIHJldHVybiBhcnJheVswXTtcbiAgICByZXR1cm4gXy5pbml0aWFsKGFycmF5LCBhcnJheS5sZW5ndGggLSBuKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGV2ZXJ5dGhpbmcgYnV0IHRoZSBsYXN0IGVudHJ5IG9mIHRoZSBhcnJheS4gRXNwZWNpYWxseSB1c2VmdWwgb25cbiAgLy8gdGhlIGFyZ3VtZW50cyBvYmplY3QuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gYWxsIHRoZSB2YWx1ZXMgaW5cbiAgLy8gdGhlIGFycmF5LCBleGNsdWRpbmcgdGhlIGxhc3QgTi5cbiAgXy5pbml0aWFsID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIE1hdGgubWF4KDAsIGFycmF5Lmxlbmd0aCAtIChuID09IG51bGwgfHwgZ3VhcmQgPyAxIDogbikpKTtcbiAgfTtcblxuICAvLyBHZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBhbiBhcnJheS4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiB0aGUgbGFzdCBOXG4gIC8vIHZhbHVlcyBpbiB0aGUgYXJyYXkuXG4gIF8ubGFzdCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xuICAgIGlmIChuID09IG51bGwgfHwgZ3VhcmQpIHJldHVybiBhcnJheVthcnJheS5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gXy5yZXN0KGFycmF5LCBNYXRoLm1heCgwLCBhcnJheS5sZW5ndGggLSBuKSk7XG4gIH07XG5cbiAgLy8gUmV0dXJucyBldmVyeXRoaW5nIGJ1dCB0aGUgZmlyc3QgZW50cnkgb2YgdGhlIGFycmF5LiBBbGlhc2VkIGFzIGB0YWlsYCBhbmQgYGRyb3BgLlxuICAvLyBFc3BlY2lhbGx5IHVzZWZ1bCBvbiB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyBhbiAqKm4qKiB3aWxsIHJldHVyblxuICAvLyB0aGUgcmVzdCBOIHZhbHVlcyBpbiB0aGUgYXJyYXkuXG4gIF8ucmVzdCA9IF8udGFpbCA9IF8uZHJvcCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCBuID09IG51bGwgfHwgZ3VhcmQgPyAxIDogbik7XG4gIH07XG5cbiAgLy8gVHJpbSBvdXQgYWxsIGZhbHN5IHZhbHVlcyBmcm9tIGFuIGFycmF5LlxuICBfLmNvbXBhY3QgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgXy5pZGVudGl0eSk7XG4gIH07XG5cbiAgLy8gSW50ZXJuYWwgaW1wbGVtZW50YXRpb24gb2YgYSByZWN1cnNpdmUgYGZsYXR0ZW5gIGZ1bmN0aW9uLlxuICB2YXIgZmxhdHRlbiA9IGZ1bmN0aW9uKGlucHV0LCBzaGFsbG93LCBzdHJpY3QsIHN0YXJ0SW5kZXgpIHtcbiAgICB2YXIgb3V0cHV0ID0gW10sIGlkeCA9IDA7XG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0SW5kZXggfHwgMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGlucHV0KTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdmFsdWUgPSBpbnB1dFtpXTtcbiAgICAgIGlmIChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgKF8uaXNBcnJheSh2YWx1ZSkgfHwgXy5pc0FyZ3VtZW50cyh2YWx1ZSkpKSB7XG4gICAgICAgIC8vZmxhdHRlbiBjdXJyZW50IGxldmVsIG9mIGFycmF5IG9yIGFyZ3VtZW50cyBvYmplY3RcbiAgICAgICAgaWYgKCFzaGFsbG93KSB2YWx1ZSA9IGZsYXR0ZW4odmFsdWUsIHNoYWxsb3csIHN0cmljdCk7XG4gICAgICAgIHZhciBqID0gMCwgbGVuID0gdmFsdWUubGVuZ3RoO1xuICAgICAgICBvdXRwdXQubGVuZ3RoICs9IGxlbjtcbiAgICAgICAgd2hpbGUgKGogPCBsZW4pIHtcbiAgICAgICAgICBvdXRwdXRbaWR4KytdID0gdmFsdWVbaisrXTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghc3RyaWN0KSB7XG4gICAgICAgIG91dHB1dFtpZHgrK10gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfTtcblxuICAvLyBGbGF0dGVuIG91dCBhbiBhcnJheSwgZWl0aGVyIHJlY3Vyc2l2ZWx5IChieSBkZWZhdWx0KSwgb3IganVzdCBvbmUgbGV2ZWwuXG4gIF8uZmxhdHRlbiA9IGZ1bmN0aW9uKGFycmF5LCBzaGFsbG93KSB7XG4gICAgcmV0dXJuIGZsYXR0ZW4oYXJyYXksIHNoYWxsb3csIGZhbHNlKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSB2ZXJzaW9uIG9mIHRoZSBhcnJheSB0aGF0IGRvZXMgbm90IGNvbnRhaW4gdGhlIHNwZWNpZmllZCB2YWx1ZShzKS5cbiAgXy53aXRob3V0ID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICByZXR1cm4gXy5kaWZmZXJlbmNlKGFycmF5LCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYSBkdXBsaWNhdGUtZnJlZSB2ZXJzaW9uIG9mIHRoZSBhcnJheS4gSWYgdGhlIGFycmF5IGhhcyBhbHJlYWR5XG4gIC8vIGJlZW4gc29ydGVkLCB5b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIHVzaW5nIGEgZmFzdGVyIGFsZ29yaXRobS5cbiAgLy8gQWxpYXNlZCBhcyBgdW5pcXVlYC5cbiAgXy51bmlxID0gXy51bmlxdWUgPSBmdW5jdGlvbihhcnJheSwgaXNTb3J0ZWQsIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaWYgKCFfLmlzQm9vbGVhbihpc1NvcnRlZCkpIHtcbiAgICAgIGNvbnRleHQgPSBpdGVyYXRlZTtcbiAgICAgIGl0ZXJhdGVlID0gaXNTb3J0ZWQ7XG4gICAgICBpc1NvcnRlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAoaXRlcmF0ZWUgIT0gbnVsbCkgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIHZhciBzZWVuID0gW107XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaV0sXG4gICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlLCBpLCBhcnJheSkgOiB2YWx1ZTtcbiAgICAgIGlmIChpc1NvcnRlZCkge1xuICAgICAgICBpZiAoIWkgfHwgc2VlbiAhPT0gY29tcHV0ZWQpIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgc2VlbiA9IGNvbXB1dGVkO1xuICAgICAgfSBlbHNlIGlmIChpdGVyYXRlZSkge1xuICAgICAgICBpZiAoIV8uY29udGFpbnMoc2VlbiwgY29tcHV0ZWQpKSB7XG4gICAgICAgICAgc2Vlbi5wdXNoKGNvbXB1dGVkKTtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIV8uY29udGFpbnMocmVzdWx0LCB2YWx1ZSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyB0aGUgdW5pb246IGVhY2ggZGlzdGluY3QgZWxlbWVudCBmcm9tIGFsbCBvZlxuICAvLyB0aGUgcGFzc2VkLWluIGFycmF5cy5cbiAgXy51bmlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfLnVuaXEoZmxhdHRlbihhcmd1bWVudHMsIHRydWUsIHRydWUpKTtcbiAgfTtcblxuICAvLyBQcm9kdWNlIGFuIGFycmF5IHRoYXQgY29udGFpbnMgZXZlcnkgaXRlbSBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlXG4gIC8vIHBhc3NlZC1pbiBhcnJheXMuXG4gIF8uaW50ZXJzZWN0aW9uID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgdmFyIGFyZ3NMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgoYXJyYXkpOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBpdGVtID0gYXJyYXlbaV07XG4gICAgICBpZiAoXy5jb250YWlucyhyZXN1bHQsIGl0ZW0pKSBjb250aW51ZTtcbiAgICAgIGZvciAodmFyIGogPSAxOyBqIDwgYXJnc0xlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmICghXy5jb250YWlucyhhcmd1bWVudHNbal0sIGl0ZW0pKSBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChqID09PSBhcmdzTGVuZ3RoKSByZXN1bHQucHVzaChpdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBUYWtlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gb25lIGFycmF5IGFuZCBhIG51bWJlciBvZiBvdGhlciBhcnJheXMuXG4gIC8vIE9ubHkgdGhlIGVsZW1lbnRzIHByZXNlbnQgaW4ganVzdCB0aGUgZmlyc3QgYXJyYXkgd2lsbCByZW1haW4uXG4gIF8uZGlmZmVyZW5jZSA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIHJlc3QgPSBmbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSwgMSk7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBmdW5jdGlvbih2YWx1ZSl7XG4gICAgICByZXR1cm4gIV8uY29udGFpbnMocmVzdCwgdmFsdWUpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFppcCB0b2dldGhlciBtdWx0aXBsZSBsaXN0cyBpbnRvIGEgc2luZ2xlIGFycmF5IC0tIGVsZW1lbnRzIHRoYXQgc2hhcmVcbiAgLy8gYW4gaW5kZXggZ28gdG9nZXRoZXIuXG4gIF8uemlwID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF8udW56aXAoYXJndW1lbnRzKTtcbiAgfTtcblxuICAvLyBDb21wbGVtZW50IG9mIF8uemlwLiBVbnppcCBhY2NlcHRzIGFuIGFycmF5IG9mIGFycmF5cyBhbmQgZ3JvdXBzXG4gIC8vIGVhY2ggYXJyYXkncyBlbGVtZW50cyBvbiBzaGFyZWQgaW5kaWNlc1xuICBfLnVuemlwID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgJiYgXy5tYXgoYXJyYXksIGdldExlbmd0aCkubGVuZ3RoIHx8IDA7XG4gICAgdmFyIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gXy5wbHVjayhhcnJheSwgaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIENvbnZlcnRzIGxpc3RzIGludG8gb2JqZWN0cy4gUGFzcyBlaXRoZXIgYSBzaW5nbGUgYXJyYXkgb2YgYFtrZXksIHZhbHVlXWBcbiAgLy8gcGFpcnMsIG9yIHR3byBwYXJhbGxlbCBhcnJheXMgb2YgdGhlIHNhbWUgbGVuZ3RoIC0tIG9uZSBvZiBrZXlzLCBhbmQgb25lIG9mXG4gIC8vIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgXy5vYmplY3QgPSBmdW5jdGlvbihsaXN0LCB2YWx1ZXMpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGdldExlbmd0aChsaXN0KTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodmFsdWVzKSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldXSA9IHZhbHVlc1tpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldWzBdXSA9IGxpc3RbaV1bMV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gR2VuZXJhdG9yIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgZmluZEluZGV4IGFuZCBmaW5kTGFzdEluZGV4IGZ1bmN0aW9uc1xuICBmdW5jdGlvbiBjcmVhdGVQcmVkaWNhdGVJbmRleEZpbmRlcihkaXIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICAgIHZhciBsZW5ndGggPSBnZXRMZW5ndGgoYXJyYXkpO1xuICAgICAgdmFyIGluZGV4ID0gZGlyID4gMCA/IDAgOiBsZW5ndGggLSAxO1xuICAgICAgZm9yICg7IGluZGV4ID49IDAgJiYgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IGRpcikge1xuICAgICAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH07XG4gIH1cblxuICAvLyBSZXR1cm5zIHRoZSBmaXJzdCBpbmRleCBvbiBhbiBhcnJheS1saWtlIHRoYXQgcGFzc2VzIGEgcHJlZGljYXRlIHRlc3RcbiAgXy5maW5kSW5kZXggPSBjcmVhdGVQcmVkaWNhdGVJbmRleEZpbmRlcigxKTtcbiAgXy5maW5kTGFzdEluZGV4ID0gY3JlYXRlUHJlZGljYXRlSW5kZXhGaW5kZXIoLTEpO1xuXG4gIC8vIFVzZSBhIGNvbXBhcmF0b3IgZnVuY3Rpb24gdG8gZmlndXJlIG91dCB0aGUgc21hbGxlc3QgaW5kZXggYXQgd2hpY2hcbiAgLy8gYW4gb2JqZWN0IHNob3VsZCBiZSBpbnNlcnRlZCBzbyBhcyB0byBtYWludGFpbiBvcmRlci4gVXNlcyBiaW5hcnkgc2VhcmNoLlxuICBfLnNvcnRlZEluZGV4ID0gZnVuY3Rpb24oYXJyYXksIG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0LCAxKTtcbiAgICB2YXIgdmFsdWUgPSBpdGVyYXRlZShvYmopO1xuICAgIHZhciBsb3cgPSAwLCBoaWdoID0gZ2V0TGVuZ3RoKGFycmF5KTtcbiAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgdmFyIG1pZCA9IE1hdGguZmxvb3IoKGxvdyArIGhpZ2gpIC8gMik7XG4gICAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbbWlkXSkgPCB2YWx1ZSkgbG93ID0gbWlkICsgMTsgZWxzZSBoaWdoID0gbWlkO1xuICAgIH1cbiAgICByZXR1cm4gbG93O1xuICB9O1xuXG4gIC8vIEdlbmVyYXRvciBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGluZGV4T2YgYW5kIGxhc3RJbmRleE9mIGZ1bmN0aW9uc1xuICBmdW5jdGlvbiBjcmVhdGVJbmRleEZpbmRlcihkaXIsIHByZWRpY2F0ZUZpbmQsIHNvcnRlZEluZGV4KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpdGVtLCBpZHgpIHtcbiAgICAgIHZhciBpID0gMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGFycmF5KTtcbiAgICAgIGlmICh0eXBlb2YgaWR4ID09ICdudW1iZXInKSB7XG4gICAgICAgIGlmIChkaXIgPiAwKSB7XG4gICAgICAgICAgICBpID0gaWR4ID49IDAgPyBpZHggOiBNYXRoLm1heChpZHggKyBsZW5ndGgsIGkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGVuZ3RoID0gaWR4ID49IDAgPyBNYXRoLm1pbihpZHggKyAxLCBsZW5ndGgpIDogaWR4ICsgbGVuZ3RoICsgMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChzb3J0ZWRJbmRleCAmJiBpZHggJiYgbGVuZ3RoKSB7XG4gICAgICAgIGlkeCA9IHNvcnRlZEluZGV4KGFycmF5LCBpdGVtKTtcbiAgICAgICAgcmV0dXJuIGFycmF5W2lkeF0gPT09IGl0ZW0gPyBpZHggOiAtMTtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVtICE9PSBpdGVtKSB7XG4gICAgICAgIGlkeCA9IHByZWRpY2F0ZUZpbmQoc2xpY2UuY2FsbChhcnJheSwgaSwgbGVuZ3RoKSwgXy5pc05hTik7XG4gICAgICAgIHJldHVybiBpZHggPj0gMCA/IGlkeCArIGkgOiAtMTtcbiAgICAgIH1cbiAgICAgIGZvciAoaWR4ID0gZGlyID4gMCA/IGkgOiBsZW5ndGggLSAxOyBpZHggPj0gMCAmJiBpZHggPCBsZW5ndGg7IGlkeCArPSBkaXIpIHtcbiAgICAgICAgaWYgKGFycmF5W2lkeF0gPT09IGl0ZW0pIHJldHVybiBpZHg7XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfTtcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgcG9zaXRpb24gb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYW4gaXRlbSBpbiBhbiBhcnJheSxcbiAgLy8gb3IgLTEgaWYgdGhlIGl0ZW0gaXMgbm90IGluY2x1ZGVkIGluIHRoZSBhcnJheS5cbiAgLy8gSWYgdGhlIGFycmF5IGlzIGxhcmdlIGFuZCBhbHJlYWR5IGluIHNvcnQgb3JkZXIsIHBhc3MgYHRydWVgXG4gIC8vIGZvciAqKmlzU29ydGVkKiogdG8gdXNlIGJpbmFyeSBzZWFyY2guXG4gIF8uaW5kZXhPZiA9IGNyZWF0ZUluZGV4RmluZGVyKDEsIF8uZmluZEluZGV4LCBfLnNvcnRlZEluZGV4KTtcbiAgXy5sYXN0SW5kZXhPZiA9IGNyZWF0ZUluZGV4RmluZGVyKC0xLCBfLmZpbmRMYXN0SW5kZXgpO1xuXG4gIC8vIEdlbmVyYXRlIGFuIGludGVnZXIgQXJyYXkgY29udGFpbmluZyBhbiBhcml0aG1ldGljIHByb2dyZXNzaW9uLiBBIHBvcnQgb2ZcbiAgLy8gdGhlIG5hdGl2ZSBQeXRob24gYHJhbmdlKClgIGZ1bmN0aW9uLiBTZWVcbiAgLy8gW3RoZSBQeXRob24gZG9jdW1lbnRhdGlvbl0oaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L2Z1bmN0aW9ucy5odG1sI3JhbmdlKS5cbiAgXy5yYW5nZSA9IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XG4gICAgaWYgKHN0b3AgPT0gbnVsbCkge1xuICAgICAgc3RvcCA9IHN0YXJ0IHx8IDA7XG4gICAgICBzdGFydCA9IDA7XG4gICAgfVxuICAgIHN0ZXAgPSBzdGVwIHx8IDE7XG5cbiAgICB2YXIgbGVuZ3RoID0gTWF0aC5tYXgoTWF0aC5jZWlsKChzdG9wIC0gc3RhcnQpIC8gc3RlcCksIDApO1xuICAgIHZhciByYW5nZSA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICBmb3IgKHZhciBpZHggPSAwOyBpZHggPCBsZW5ndGg7IGlkeCsrLCBzdGFydCArPSBzdGVwKSB7XG4gICAgICByYW5nZVtpZHhdID0gc3RhcnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJhbmdlO1xuICB9O1xuXG4gIC8vIEZ1bmN0aW9uIChhaGVtKSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gRGV0ZXJtaW5lcyB3aGV0aGVyIHRvIGV4ZWN1dGUgYSBmdW5jdGlvbiBhcyBhIGNvbnN0cnVjdG9yXG4gIC8vIG9yIGEgbm9ybWFsIGZ1bmN0aW9uIHdpdGggdGhlIHByb3ZpZGVkIGFyZ3VtZW50c1xuICB2YXIgZXhlY3V0ZUJvdW5kID0gZnVuY3Rpb24oc291cmNlRnVuYywgYm91bmRGdW5jLCBjb250ZXh0LCBjYWxsaW5nQ29udGV4dCwgYXJncykge1xuICAgIGlmICghKGNhbGxpbmdDb250ZXh0IGluc3RhbmNlb2YgYm91bmRGdW5jKSkgcmV0dXJuIHNvdXJjZUZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgdmFyIHNlbGYgPSBiYXNlQ3JlYXRlKHNvdXJjZUZ1bmMucHJvdG90eXBlKTtcbiAgICB2YXIgcmVzdWx0ID0gc291cmNlRnVuYy5hcHBseShzZWxmLCBhcmdzKTtcbiAgICBpZiAoXy5pc09iamVjdChyZXN1bHQpKSByZXR1cm4gcmVzdWx0O1xuICAgIHJldHVybiBzZWxmO1xuICB9O1xuXG4gIC8vIENyZWF0ZSBhIGZ1bmN0aW9uIGJvdW5kIHRvIGEgZ2l2ZW4gb2JqZWN0IChhc3NpZ25pbmcgYHRoaXNgLCBhbmQgYXJndW1lbnRzLFxuICAvLyBvcHRpb25hbGx5KS4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYEZ1bmN0aW9uLmJpbmRgIGlmXG4gIC8vIGF2YWlsYWJsZS5cbiAgXy5iaW5kID0gZnVuY3Rpb24oZnVuYywgY29udGV4dCkge1xuICAgIGlmIChuYXRpdmVCaW5kICYmIGZ1bmMuYmluZCA9PT0gbmF0aXZlQmluZCkgcmV0dXJuIG5hdGl2ZUJpbmQuYXBwbHkoZnVuYywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICBpZiAoIV8uaXNGdW5jdGlvbihmdW5jKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQmluZCBtdXN0IGJlIGNhbGxlZCBvbiBhIGZ1bmN0aW9uJyk7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgdmFyIGJvdW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZXhlY3V0ZUJvdW5kKGZ1bmMsIGJvdW5kLCBjb250ZXh0LCB0aGlzLCBhcmdzLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICB9O1xuICAgIHJldHVybiBib3VuZDtcbiAgfTtcblxuICAvLyBQYXJ0aWFsbHkgYXBwbHkgYSBmdW5jdGlvbiBieSBjcmVhdGluZyBhIHZlcnNpb24gdGhhdCBoYXMgaGFkIHNvbWUgb2YgaXRzXG4gIC8vIGFyZ3VtZW50cyBwcmUtZmlsbGVkLCB3aXRob3V0IGNoYW5naW5nIGl0cyBkeW5hbWljIGB0aGlzYCBjb250ZXh0LiBfIGFjdHNcbiAgLy8gYXMgYSBwbGFjZWhvbGRlciwgYWxsb3dpbmcgYW55IGNvbWJpbmF0aW9uIG9mIGFyZ3VtZW50cyB0byBiZSBwcmUtZmlsbGVkLlxuICBfLnBhcnRpYWwgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgdmFyIGJvdW5kQXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICB2YXIgYm91bmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwb3NpdGlvbiA9IDAsIGxlbmd0aCA9IGJvdW5kQXJncy5sZW5ndGg7XG4gICAgICB2YXIgYXJncyA9IEFycmF5KGxlbmd0aCk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFyZ3NbaV0gPSBib3VuZEFyZ3NbaV0gPT09IF8gPyBhcmd1bWVudHNbcG9zaXRpb24rK10gOiBib3VuZEFyZ3NbaV07XG4gICAgICB9XG4gICAgICB3aGlsZSAocG9zaXRpb24gPCBhcmd1bWVudHMubGVuZ3RoKSBhcmdzLnB1c2goYXJndW1lbnRzW3Bvc2l0aW9uKytdKTtcbiAgICAgIHJldHVybiBleGVjdXRlQm91bmQoZnVuYywgYm91bmQsIHRoaXMsIHRoaXMsIGFyZ3MpO1xuICAgIH07XG4gICAgcmV0dXJuIGJvdW5kO1xuICB9O1xuXG4gIC8vIEJpbmQgYSBudW1iZXIgb2YgYW4gb2JqZWN0J3MgbWV0aG9kcyB0byB0aGF0IG9iamVjdC4gUmVtYWluaW5nIGFyZ3VtZW50c1xuICAvLyBhcmUgdGhlIG1ldGhvZCBuYW1lcyB0byBiZSBib3VuZC4gVXNlZnVsIGZvciBlbnN1cmluZyB0aGF0IGFsbCBjYWxsYmFja3NcbiAgLy8gZGVmaW5lZCBvbiBhbiBvYmplY3QgYmVsb25nIHRvIGl0LlxuICBfLmJpbmRBbGwgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgaSwgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCwga2V5O1xuICAgIGlmIChsZW5ndGggPD0gMSkgdGhyb3cgbmV3IEVycm9yKCdiaW5kQWxsIG11c3QgYmUgcGFzc2VkIGZ1bmN0aW9uIG5hbWVzJyk7XG4gICAgZm9yIChpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBrZXkgPSBhcmd1bWVudHNbaV07XG4gICAgICBvYmpba2V5XSA9IF8uYmluZChvYmpba2V5XSwgb2JqKTtcbiAgICB9XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBNZW1vaXplIGFuIGV4cGVuc2l2ZSBmdW5jdGlvbiBieSBzdG9yaW5nIGl0cyByZXN1bHRzLlxuICBfLm1lbW9pemUgPSBmdW5jdGlvbihmdW5jLCBoYXNoZXIpIHtcbiAgICB2YXIgbWVtb2l6ZSA9IGZ1bmN0aW9uKGtleSkge1xuICAgICAgdmFyIGNhY2hlID0gbWVtb2l6ZS5jYWNoZTtcbiAgICAgIHZhciBhZGRyZXNzID0gJycgKyAoaGFzaGVyID8gaGFzaGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBrZXkpO1xuICAgICAgaWYgKCFfLmhhcyhjYWNoZSwgYWRkcmVzcykpIGNhY2hlW2FkZHJlc3NdID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIGNhY2hlW2FkZHJlc3NdO1xuICAgIH07XG4gICAgbWVtb2l6ZS5jYWNoZSA9IHt9O1xuICAgIHJldHVybiBtZW1vaXplO1xuICB9O1xuXG4gIC8vIERlbGF5cyBhIGZ1bmN0aW9uIGZvciB0aGUgZ2l2ZW4gbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgYW5kIHRoZW4gY2FsbHNcbiAgLy8gaXQgd2l0aCB0aGUgYXJndW1lbnRzIHN1cHBsaWVkLlxuICBfLmRlbGF5ID0gZnVuY3Rpb24oZnVuYywgd2FpdCkge1xuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBhcmdzKTtcbiAgICB9LCB3YWl0KTtcbiAgfTtcblxuICAvLyBEZWZlcnMgYSBmdW5jdGlvbiwgc2NoZWR1bGluZyBpdCB0byBydW4gYWZ0ZXIgdGhlIGN1cnJlbnQgY2FsbCBzdGFjayBoYXNcbiAgLy8gY2xlYXJlZC5cbiAgXy5kZWZlciA9IF8ucGFydGlhbChfLmRlbGF5LCBfLCAxKTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIHdoZW4gaW52b2tlZCwgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBhdCBtb3N0IG9uY2VcbiAgLy8gZHVyaW5nIGEgZ2l2ZW4gd2luZG93IG9mIHRpbWUuIE5vcm1hbGx5LCB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHdpbGwgcnVuXG4gIC8vIGFzIG11Y2ggYXMgaXQgY2FuLCB3aXRob3V0IGV2ZXIgZ29pbmcgbW9yZSB0aGFuIG9uY2UgcGVyIGB3YWl0YCBkdXJhdGlvbjtcbiAgLy8gYnV0IGlmIHlvdSdkIGxpa2UgdG8gZGlzYWJsZSB0aGUgZXhlY3V0aW9uIG9uIHRoZSBsZWFkaW5nIGVkZ2UsIHBhc3NcbiAgLy8gYHtsZWFkaW5nOiBmYWxzZX1gLiBUbyBkaXNhYmxlIGV4ZWN1dGlvbiBvbiB0aGUgdHJhaWxpbmcgZWRnZSwgZGl0dG8uXG4gIF8udGhyb3R0bGUgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgdmFyIGNvbnRleHQsIGFyZ3MsIHJlc3VsdDtcbiAgICB2YXIgdGltZW91dCA9IG51bGw7XG4gICAgdmFyIHByZXZpb3VzID0gMDtcbiAgICBpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fTtcbiAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHByZXZpb3VzID0gb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSA/IDAgOiBfLm5vdygpO1xuICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgaWYgKCF0aW1lb3V0KSBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbm93ID0gXy5ub3coKTtcbiAgICAgIGlmICghcHJldmlvdXMgJiYgb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSkgcHJldmlvdXMgPSBub3c7XG4gICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XG4gICAgICBjb250ZXh0ID0gdGhpcztcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBpZiAocmVtYWluaW5nIDw9IDAgfHwgcmVtYWluaW5nID4gd2FpdCkge1xuICAgICAgICBpZiAodGltZW91dCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBwcmV2aW91cyA9IG5vdztcbiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgaWYgKCF0aW1lb3V0KSBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICB9IGVsc2UgaWYgKCF0aW1lb3V0ICYmIG9wdGlvbnMudHJhaWxpbmcgIT09IGZhbHNlKSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCByZW1haW5pbmcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgYXMgbG9uZyBhcyBpdCBjb250aW51ZXMgdG8gYmUgaW52b2tlZCwgd2lsbCBub3RcbiAgLy8gYmUgdHJpZ2dlcmVkLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgaXQgc3RvcHMgYmVpbmcgY2FsbGVkIGZvclxuICAvLyBOIG1pbGxpc2Vjb25kcy4gSWYgYGltbWVkaWF0ZWAgaXMgcGFzc2VkLCB0cmlnZ2VyIHRoZSBmdW5jdGlvbiBvbiB0aGVcbiAgLy8gbGVhZGluZyBlZGdlLCBpbnN0ZWFkIG9mIHRoZSB0cmFpbGluZy5cbiAgXy5kZWJvdW5jZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGltbWVkaWF0ZSkge1xuICAgIHZhciB0aW1lb3V0LCBhcmdzLCBjb250ZXh0LCB0aW1lc3RhbXAsIHJlc3VsdDtcblxuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGxhc3QgPSBfLm5vdygpIC0gdGltZXN0YW1wO1xuXG4gICAgICBpZiAobGFzdCA8IHdhaXQgJiYgbGFzdCA+PSAwKSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0IC0gbGFzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgIGlmICghdGltZW91dCkgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHRpbWVzdGFtcCA9IF8ubm93KCk7XG4gICAgICB2YXIgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDtcbiAgICAgIGlmICghdGltZW91dCkgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQpO1xuICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyB0aGUgZmlyc3QgZnVuY3Rpb24gcGFzc2VkIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSBzZWNvbmQsXG4gIC8vIGFsbG93aW5nIHlvdSB0byBhZGp1c3QgYXJndW1lbnRzLCBydW4gY29kZSBiZWZvcmUgYW5kIGFmdGVyLCBhbmRcbiAgLy8gY29uZGl0aW9uYWxseSBleGVjdXRlIHRoZSBvcmlnaW5hbCBmdW5jdGlvbi5cbiAgXy53cmFwID0gZnVuY3Rpb24oZnVuYywgd3JhcHBlcikge1xuICAgIHJldHVybiBfLnBhcnRpYWwod3JhcHBlciwgZnVuYyk7XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIG5lZ2F0ZWQgdmVyc2lvbiBvZiB0aGUgcGFzc2VkLWluIHByZWRpY2F0ZS5cbiAgXy5uZWdhdGUgPSBmdW5jdGlvbihwcmVkaWNhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gIXByZWRpY2F0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgaXMgdGhlIGNvbXBvc2l0aW9uIG9mIGEgbGlzdCBvZiBmdW5jdGlvbnMsIGVhY2hcbiAgLy8gY29uc3VtaW5nIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGZ1bmN0aW9uIHRoYXQgZm9sbG93cy5cbiAgXy5jb21wb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgdmFyIHN0YXJ0ID0gYXJncy5sZW5ndGggLSAxO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBpID0gc3RhcnQ7XG4gICAgICB2YXIgcmVzdWx0ID0gYXJnc1tzdGFydF0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHdoaWxlIChpLS0pIHJlc3VsdCA9IGFyZ3NbaV0uY2FsbCh0aGlzLCByZXN1bHQpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgb25seSBiZSBleGVjdXRlZCBvbiBhbmQgYWZ0ZXIgdGhlIE50aCBjYWxsLlxuICBfLmFmdGVyID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS10aW1lcyA8IDEpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgb25seSBiZSBleGVjdXRlZCB1cCB0byAoYnV0IG5vdCBpbmNsdWRpbmcpIHRoZSBOdGggY2FsbC5cbiAgXy5iZWZvcmUgPSBmdW5jdGlvbih0aW1lcywgZnVuYykge1xuICAgIHZhciBtZW1vO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICgtLXRpbWVzID4gMCkge1xuICAgICAgICBtZW1vID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgaWYgKHRpbWVzIDw9IDEpIGZ1bmMgPSBudWxsO1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGF0IG1vc3Qgb25lIHRpbWUsIG5vIG1hdHRlciBob3dcbiAgLy8gb2Z0ZW4geW91IGNhbGwgaXQuIFVzZWZ1bCBmb3IgbGF6eSBpbml0aWFsaXphdGlvbi5cbiAgXy5vbmNlID0gXy5wYXJ0aWFsKF8uYmVmb3JlLCAyKTtcblxuICAvLyBPYmplY3QgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBLZXlzIGluIElFIDwgOSB0aGF0IHdvbid0IGJlIGl0ZXJhdGVkIGJ5IGBmb3Iga2V5IGluIC4uLmAgYW5kIHRodXMgbWlzc2VkLlxuICB2YXIgaGFzRW51bUJ1ZyA9ICF7dG9TdHJpbmc6IG51bGx9LnByb3BlcnR5SXNFbnVtZXJhYmxlKCd0b1N0cmluZycpO1xuICB2YXIgbm9uRW51bWVyYWJsZVByb3BzID0gWyd2YWx1ZU9mJywgJ2lzUHJvdG90eXBlT2YnLCAndG9TdHJpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsICdoYXNPd25Qcm9wZXJ0eScsICd0b0xvY2FsZVN0cmluZyddO1xuXG4gIGZ1bmN0aW9uIGNvbGxlY3ROb25FbnVtUHJvcHMob2JqLCBrZXlzKSB7XG4gICAgdmFyIG5vbkVudW1JZHggPSBub25FbnVtZXJhYmxlUHJvcHMubGVuZ3RoO1xuICAgIHZhciBjb25zdHJ1Y3RvciA9IG9iai5jb25zdHJ1Y3RvcjtcbiAgICB2YXIgcHJvdG8gPSAoXy5pc0Z1bmN0aW9uKGNvbnN0cnVjdG9yKSAmJiBjb25zdHJ1Y3Rvci5wcm90b3R5cGUpIHx8IE9ialByb3RvO1xuXG4gICAgLy8gQ29uc3RydWN0b3IgaXMgYSBzcGVjaWFsIGNhc2UuXG4gICAgdmFyIHByb3AgPSAnY29uc3RydWN0b3InO1xuICAgIGlmIChfLmhhcyhvYmosIHByb3ApICYmICFfLmNvbnRhaW5zKGtleXMsIHByb3ApKSBrZXlzLnB1c2gocHJvcCk7XG5cbiAgICB3aGlsZSAobm9uRW51bUlkeC0tKSB7XG4gICAgICBwcm9wID0gbm9uRW51bWVyYWJsZVByb3BzW25vbkVudW1JZHhdO1xuICAgICAgaWYgKHByb3AgaW4gb2JqICYmIG9ialtwcm9wXSAhPT0gcHJvdG9bcHJvcF0gJiYgIV8uY29udGFpbnMoa2V5cywgcHJvcCkpIHtcbiAgICAgICAga2V5cy5wdXNoKHByb3ApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFJldHJpZXZlIHRoZSBuYW1lcyBvZiBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcy5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYE9iamVjdC5rZXlzYFxuICBfLmtleXMgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIFtdO1xuICAgIGlmIChuYXRpdmVLZXlzKSByZXR1cm4gbmF0aXZlS2V5cyhvYmopO1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkga2V5cy5wdXNoKGtleSk7XG4gICAgLy8gQWhlbSwgSUUgPCA5LlxuICAgIGlmIChoYXNFbnVtQnVnKSBjb2xsZWN0Tm9uRW51bVByb3BzKG9iaiwga2V5cyk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG5cbiAgLy8gUmV0cmlldmUgYWxsIHRoZSBwcm9wZXJ0eSBuYW1lcyBvZiBhbiBvYmplY3QuXG4gIF8uYWxsS2V5cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBrZXlzLnB1c2goa2V5KTtcbiAgICAvLyBBaGVtLCBJRSA8IDkuXG4gICAgaWYgKGhhc0VudW1CdWcpIGNvbGxlY3ROb25FbnVtUHJvcHMob2JqLCBrZXlzKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfTtcblxuICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWVzIG9mIGFuIG9iamVjdCdzIHByb3BlcnRpZXMuXG4gIF8udmFsdWVzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIHZhbHVlcyA9IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFsdWVzW2ldID0gb2JqW2tleXNbaV1dO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWVzO1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIHJlc3VsdHMgb2YgYXBwbHlpbmcgdGhlIGl0ZXJhdGVlIHRvIGVhY2ggZWxlbWVudCBvZiB0aGUgb2JqZWN0XG4gIC8vIEluIGNvbnRyYXN0IHRvIF8ubWFwIGl0IHJldHVybnMgYW4gb2JqZWN0XG4gIF8ubWFwT2JqZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIHZhciBrZXlzID0gIF8ua2V5cyhvYmopLFxuICAgICAgICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdHMgPSB7fSxcbiAgICAgICAgICBjdXJyZW50S2V5O1xuICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICBjdXJyZW50S2V5ID0ga2V5c1tpbmRleF07XG4gICAgICAgIHJlc3VsdHNbY3VycmVudEtleV0gPSBpdGVyYXRlZShvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBDb252ZXJ0IGFuIG9iamVjdCBpbnRvIGEgbGlzdCBvZiBgW2tleSwgdmFsdWVdYCBwYWlycy5cbiAgXy5wYWlycyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciBwYWlycyA9IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgcGFpcnNbaV0gPSBba2V5c1tpXSwgb2JqW2tleXNbaV1dXTtcbiAgICB9XG4gICAgcmV0dXJuIHBhaXJzO1xuICB9O1xuXG4gIC8vIEludmVydCB0aGUga2V5cyBhbmQgdmFsdWVzIG9mIGFuIG9iamVjdC4gVGhlIHZhbHVlcyBtdXN0IGJlIHNlcmlhbGl6YWJsZS5cbiAgXy5pbnZlcnQgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0W29ialtrZXlzW2ldXV0gPSBrZXlzW2ldO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHNvcnRlZCBsaXN0IG9mIHRoZSBmdW5jdGlvbiBuYW1lcyBhdmFpbGFibGUgb24gdGhlIG9iamVjdC5cbiAgLy8gQWxpYXNlZCBhcyBgbWV0aG9kc2BcbiAgXy5mdW5jdGlvbnMgPSBfLm1ldGhvZHMgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgbmFtZXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAoXy5pc0Z1bmN0aW9uKG9ialtrZXldKSkgbmFtZXMucHVzaChrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gbmFtZXMuc29ydCgpO1xuICB9O1xuXG4gIC8vIEV4dGVuZCBhIGdpdmVuIG9iamVjdCB3aXRoIGFsbCB0aGUgcHJvcGVydGllcyBpbiBwYXNzZWQtaW4gb2JqZWN0KHMpLlxuICBfLmV4dGVuZCA9IGNyZWF0ZUFzc2lnbmVyKF8uYWxsS2V5cyk7XG5cbiAgLy8gQXNzaWducyBhIGdpdmVuIG9iamVjdCB3aXRoIGFsbCB0aGUgb3duIHByb3BlcnRpZXMgaW4gdGhlIHBhc3NlZC1pbiBvYmplY3QocylcbiAgLy8gKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9hc3NpZ24pXG4gIF8uZXh0ZW5kT3duID0gXy5hc3NpZ24gPSBjcmVhdGVBc3NpZ25lcihfLmtleXMpO1xuXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGtleSBvbiBhbiBvYmplY3QgdGhhdCBwYXNzZXMgYSBwcmVkaWNhdGUgdGVzdFxuICBfLmZpbmRLZXkgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKSwga2V5O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBrZXkgPSBrZXlzW2ldO1xuICAgICAgaWYgKHByZWRpY2F0ZShvYmpba2V5XSwga2V5LCBvYmopKSByZXR1cm4ga2V5O1xuICAgIH1cbiAgfTtcblxuICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgb25seSBjb250YWluaW5nIHRoZSB3aGl0ZWxpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLnBpY2sgPSBmdW5jdGlvbihvYmplY3QsIG9pdGVyYXRlZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHQgPSB7fSwgb2JqID0gb2JqZWN0LCBpdGVyYXRlZSwga2V5cztcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XG4gICAgaWYgKF8uaXNGdW5jdGlvbihvaXRlcmF0ZWUpKSB7XG4gICAgICBrZXlzID0gXy5hbGxLZXlzKG9iaik7XG4gICAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2Iob2l0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAga2V5cyA9IGZsYXR0ZW4oYXJndW1lbnRzLCBmYWxzZSwgZmFsc2UsIDEpO1xuICAgICAgaXRlcmF0ZWUgPSBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmopIHsgcmV0dXJuIGtleSBpbiBvYmo7IH07XG4gICAgICBvYmogPSBPYmplY3Qob2JqKTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgdmFyIHZhbHVlID0gb2JqW2tleV07XG4gICAgICBpZiAoaXRlcmF0ZWUodmFsdWUsIGtleSwgb2JqKSkgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IHdpdGhvdXQgdGhlIGJsYWNrbGlzdGVkIHByb3BlcnRpZXMuXG4gIF8ub21pdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKGl0ZXJhdGVlKSkge1xuICAgICAgaXRlcmF0ZWUgPSBfLm5lZ2F0ZShpdGVyYXRlZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBrZXlzID0gXy5tYXAoZmxhdHRlbihhcmd1bWVudHMsIGZhbHNlLCBmYWxzZSwgMSksIFN0cmluZyk7XG4gICAgICBpdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuICFfLmNvbnRhaW5zKGtleXMsIGtleSk7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gXy5waWNrKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpO1xuICB9O1xuXG4gIC8vIEZpbGwgaW4gYSBnaXZlbiBvYmplY3Qgd2l0aCBkZWZhdWx0IHByb3BlcnRpZXMuXG4gIF8uZGVmYXVsdHMgPSBjcmVhdGVBc3NpZ25lcihfLmFsbEtleXMsIHRydWUpO1xuXG4gIC8vIENyZWF0ZXMgYW4gb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGUgZ2l2ZW4gcHJvdG90eXBlIG9iamVjdC5cbiAgLy8gSWYgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIGFyZSBwcm92aWRlZCB0aGVuIHRoZXkgd2lsbCBiZSBhZGRlZCB0byB0aGVcbiAgLy8gY3JlYXRlZCBvYmplY3QuXG4gIF8uY3JlYXRlID0gZnVuY3Rpb24ocHJvdG90eXBlLCBwcm9wcykge1xuICAgIHZhciByZXN1bHQgPSBiYXNlQ3JlYXRlKHByb3RvdHlwZSk7XG4gICAgaWYgKHByb3BzKSBfLmV4dGVuZE93bihyZXN1bHQsIHByb3BzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIENyZWF0ZSBhIChzaGFsbG93LWNsb25lZCkgZHVwbGljYXRlIG9mIGFuIG9iamVjdC5cbiAgXy5jbG9uZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gb2JqO1xuICAgIHJldHVybiBfLmlzQXJyYXkob2JqKSA/IG9iai5zbGljZSgpIDogXy5leHRlbmQoe30sIG9iaik7XG4gIH07XG5cbiAgLy8gSW52b2tlcyBpbnRlcmNlcHRvciB3aXRoIHRoZSBvYmosIGFuZCB0aGVuIHJldHVybnMgb2JqLlxuICAvLyBUaGUgcHJpbWFyeSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiwgaW5cbiAgLy8gb3JkZXIgdG8gcGVyZm9ybSBvcGVyYXRpb25zIG9uIGludGVybWVkaWF0ZSByZXN1bHRzIHdpdGhpbiB0aGUgY2hhaW4uXG4gIF8udGFwID0gZnVuY3Rpb24ob2JqLCBpbnRlcmNlcHRvcikge1xuICAgIGludGVyY2VwdG9yKG9iaik7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm5zIHdoZXRoZXIgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHNldCBvZiBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5pc01hdGNoID0gZnVuY3Rpb24ob2JqZWN0LCBhdHRycykge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKGF0dHJzKSwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgaWYgKG9iamVjdCA9PSBudWxsKSByZXR1cm4gIWxlbmd0aDtcbiAgICB2YXIgb2JqID0gT2JqZWN0KG9iamVjdCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGtleSA9IGtleXNbaV07XG4gICAgICBpZiAoYXR0cnNba2V5XSAhPT0gb2JqW2tleV0gfHwgIShrZXkgaW4gb2JqKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuXG4gIC8vIEludGVybmFsIHJlY3Vyc2l2ZSBjb21wYXJpc29uIGZ1bmN0aW9uIGZvciBgaXNFcXVhbGAuXG4gIHZhciBlcSA9IGZ1bmN0aW9uKGEsIGIsIGFTdGFjaywgYlN0YWNrKSB7XG4gICAgLy8gSWRlbnRpY2FsIG9iamVjdHMgYXJlIGVxdWFsLiBgMCA9PT0gLTBgLCBidXQgdGhleSBhcmVuJ3QgaWRlbnRpY2FsLlxuICAgIC8vIFNlZSB0aGUgW0hhcm1vbnkgYGVnYWxgIHByb3Bvc2FsXShodHRwOi8vd2lraS5lY21hc2NyaXB0Lm9yZy9kb2t1LnBocD9pZD1oYXJtb255OmVnYWwpLlxuICAgIGlmIChhID09PSBiKSByZXR1cm4gYSAhPT0gMCB8fCAxIC8gYSA9PT0gMSAvIGI7XG4gICAgLy8gQSBzdHJpY3QgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkgYmVjYXVzZSBgbnVsbCA9PSB1bmRlZmluZWRgLlxuICAgIGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsKSByZXR1cm4gYSA9PT0gYjtcbiAgICAvLyBVbndyYXAgYW55IHdyYXBwZWQgb2JqZWN0cy5cbiAgICBpZiAoYSBpbnN0YW5jZW9mIF8pIGEgPSBhLl93cmFwcGVkO1xuICAgIGlmIChiIGluc3RhbmNlb2YgXykgYiA9IGIuX3dyYXBwZWQ7XG4gICAgLy8gQ29tcGFyZSBgW1tDbGFzc11dYCBuYW1lcy5cbiAgICB2YXIgY2xhc3NOYW1lID0gdG9TdHJpbmcuY2FsbChhKTtcbiAgICBpZiAoY2xhc3NOYW1lICE9PSB0b1N0cmluZy5jYWxsKGIpKSByZXR1cm4gZmFsc2U7XG4gICAgc3dpdGNoIChjbGFzc05hbWUpIHtcbiAgICAgIC8vIFN0cmluZ3MsIG51bWJlcnMsIHJlZ3VsYXIgZXhwcmVzc2lvbnMsIGRhdGVzLCBhbmQgYm9vbGVhbnMgYXJlIGNvbXBhcmVkIGJ5IHZhbHVlLlxuICAgICAgY2FzZSAnW29iamVjdCBSZWdFeHBdJzpcbiAgICAgIC8vIFJlZ0V4cHMgYXJlIGNvZXJjZWQgdG8gc3RyaW5ncyBmb3IgY29tcGFyaXNvbiAoTm90ZTogJycgKyAvYS9pID09PSAnL2EvaScpXG4gICAgICBjYXNlICdbb2JqZWN0IFN0cmluZ10nOlxuICAgICAgICAvLyBQcmltaXRpdmVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9iamVjdCB3cmFwcGVycyBhcmUgZXF1aXZhbGVudDsgdGh1cywgYFwiNVwiYCBpc1xuICAgICAgICAvLyBlcXVpdmFsZW50IHRvIGBuZXcgU3RyaW5nKFwiNVwiKWAuXG4gICAgICAgIHJldHVybiAnJyArIGEgPT09ICcnICsgYjtcbiAgICAgIGNhc2UgJ1tvYmplY3QgTnVtYmVyXSc6XG4gICAgICAgIC8vIGBOYU5gcyBhcmUgZXF1aXZhbGVudCwgYnV0IG5vbi1yZWZsZXhpdmUuXG4gICAgICAgIC8vIE9iamVjdChOYU4pIGlzIGVxdWl2YWxlbnQgdG8gTmFOXG4gICAgICAgIGlmICgrYSAhPT0gK2EpIHJldHVybiArYiAhPT0gK2I7XG4gICAgICAgIC8vIEFuIGBlZ2FsYCBjb21wYXJpc29uIGlzIHBlcmZvcm1lZCBmb3Igb3RoZXIgbnVtZXJpYyB2YWx1ZXMuXG4gICAgICAgIHJldHVybiArYSA9PT0gMCA/IDEgLyArYSA9PT0gMSAvIGIgOiArYSA9PT0gK2I7XG4gICAgICBjYXNlICdbb2JqZWN0IERhdGVdJzpcbiAgICAgIGNhc2UgJ1tvYmplY3QgQm9vbGVhbl0nOlxuICAgICAgICAvLyBDb2VyY2UgZGF0ZXMgYW5kIGJvb2xlYW5zIHRvIG51bWVyaWMgcHJpbWl0aXZlIHZhbHVlcy4gRGF0ZXMgYXJlIGNvbXBhcmVkIGJ5IHRoZWlyXG4gICAgICAgIC8vIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9ucy4gTm90ZSB0aGF0IGludmFsaWQgZGF0ZXMgd2l0aCBtaWxsaXNlY29uZCByZXByZXNlbnRhdGlvbnNcbiAgICAgICAgLy8gb2YgYE5hTmAgYXJlIG5vdCBlcXVpdmFsZW50LlxuICAgICAgICByZXR1cm4gK2EgPT09ICtiO1xuICAgIH1cblxuICAgIHZhciBhcmVBcnJheXMgPSBjbGFzc05hbWUgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gICAgaWYgKCFhcmVBcnJheXMpIHtcbiAgICAgIGlmICh0eXBlb2YgYSAhPSAnb2JqZWN0JyB8fCB0eXBlb2YgYiAhPSAnb2JqZWN0JykgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBPYmplY3RzIHdpdGggZGlmZmVyZW50IGNvbnN0cnVjdG9ycyBhcmUgbm90IGVxdWl2YWxlbnQsIGJ1dCBgT2JqZWN0YHMgb3IgYEFycmF5YHNcbiAgICAgIC8vIGZyb20gZGlmZmVyZW50IGZyYW1lcyBhcmUuXG4gICAgICB2YXIgYUN0b3IgPSBhLmNvbnN0cnVjdG9yLCBiQ3RvciA9IGIuY29uc3RydWN0b3I7XG4gICAgICBpZiAoYUN0b3IgIT09IGJDdG9yICYmICEoXy5pc0Z1bmN0aW9uKGFDdG9yKSAmJiBhQ3RvciBpbnN0YW5jZW9mIGFDdG9yICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXy5pc0Z1bmN0aW9uKGJDdG9yKSAmJiBiQ3RvciBpbnN0YW5jZW9mIGJDdG9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAmJiAoJ2NvbnN0cnVjdG9yJyBpbiBhICYmICdjb25zdHJ1Y3RvcicgaW4gYikpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBc3N1bWUgZXF1YWxpdHkgZm9yIGN5Y2xpYyBzdHJ1Y3R1cmVzLiBUaGUgYWxnb3JpdGhtIGZvciBkZXRlY3RpbmcgY3ljbGljXG4gICAgLy8gc3RydWN0dXJlcyBpcyBhZGFwdGVkIGZyb20gRVMgNS4xIHNlY3Rpb24gMTUuMTIuMywgYWJzdHJhY3Qgb3BlcmF0aW9uIGBKT2AuXG5cbiAgICAvLyBJbml0aWFsaXppbmcgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgLy8gSXQncyBkb25lIGhlcmUgc2luY2Ugd2Ugb25seSBuZWVkIHRoZW0gZm9yIG9iamVjdHMgYW5kIGFycmF5cyBjb21wYXJpc29uLlxuICAgIGFTdGFjayA9IGFTdGFjayB8fCBbXTtcbiAgICBiU3RhY2sgPSBiU3RhY2sgfHwgW107XG4gICAgdmFyIGxlbmd0aCA9IGFTdGFjay5sZW5ndGg7XG4gICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2ZcbiAgICAgIC8vIHVuaXF1ZSBuZXN0ZWQgc3RydWN0dXJlcy5cbiAgICAgIGlmIChhU3RhY2tbbGVuZ3RoXSA9PT0gYSkgcmV0dXJuIGJTdGFja1tsZW5ndGhdID09PSBiO1xuICAgIH1cblxuICAgIC8vIEFkZCB0aGUgZmlyc3Qgb2JqZWN0IHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICBhU3RhY2sucHVzaChhKTtcbiAgICBiU3RhY2sucHVzaChiKTtcblxuICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyBhbmQgYXJyYXlzLlxuICAgIGlmIChhcmVBcnJheXMpIHtcbiAgICAgIC8vIENvbXBhcmUgYXJyYXkgbGVuZ3RocyB0byBkZXRlcm1pbmUgaWYgYSBkZWVwIGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5LlxuICAgICAgbGVuZ3RoID0gYS5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoICE9PSBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgLy8gRGVlcCBjb21wYXJlIHRoZSBjb250ZW50cywgaWdub3Jpbmcgbm9uLW51bWVyaWMgcHJvcGVydGllcy5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoIWVxKGFbbGVuZ3RoXSwgYltsZW5ndGhdLCBhU3RhY2ssIGJTdGFjaykpIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVlcCBjb21wYXJlIG9iamVjdHMuXG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhhKSwga2V5O1xuICAgICAgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgICAvLyBFbnN1cmUgdGhhdCBib3RoIG9iamVjdHMgY29udGFpbiB0aGUgc2FtZSBudW1iZXIgb2YgcHJvcGVydGllcyBiZWZvcmUgY29tcGFyaW5nIGRlZXAgZXF1YWxpdHkuXG4gICAgICBpZiAoXy5rZXlzKGIpLmxlbmd0aCAhPT0gbGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgLy8gRGVlcCBjb21wYXJlIGVhY2ggbWVtYmVyXG4gICAgICAgIGtleSA9IGtleXNbbGVuZ3RoXTtcbiAgICAgICAgaWYgKCEoXy5oYXMoYiwga2V5KSAmJiBlcShhW2tleV0sIGJba2V5XSwgYVN0YWNrLCBiU3RhY2spKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBSZW1vdmUgdGhlIGZpcnN0IG9iamVjdCBmcm9tIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICBhU3RhY2sucG9wKCk7XG4gICAgYlN0YWNrLnBvcCgpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIC8vIFBlcmZvcm0gYSBkZWVwIGNvbXBhcmlzb24gdG8gY2hlY2sgaWYgdHdvIG9iamVjdHMgYXJlIGVxdWFsLlxuICBfLmlzRXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgcmV0dXJuIGVxKGEsIGIpO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gYXJyYXksIHN0cmluZywgb3Igb2JqZWN0IGVtcHR5P1xuICAvLyBBbiBcImVtcHR5XCIgb2JqZWN0IGhhcyBubyBlbnVtZXJhYmxlIG93bi1wcm9wZXJ0aWVzLlxuICBfLmlzRW1wdHkgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiB0cnVlO1xuICAgIGlmIChpc0FycmF5TGlrZShvYmopICYmIChfLmlzQXJyYXkob2JqKSB8fCBfLmlzU3RyaW5nKG9iaikgfHwgXy5pc0FyZ3VtZW50cyhvYmopKSkgcmV0dXJuIG9iai5sZW5ndGggPT09IDA7XG4gICAgcmV0dXJuIF8ua2V5cyhvYmopLmxlbmd0aCA9PT0gMDtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgRE9NIGVsZW1lbnQ/XG4gIF8uaXNFbGVtZW50ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuICEhKG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEpO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYW4gYXJyYXk/XG4gIC8vIERlbGVnYXRlcyB0byBFQ01BNSdzIG5hdGl2ZSBBcnJheS5pc0FycmF5XG4gIF8uaXNBcnJheSA9IG5hdGl2ZUlzQXJyYXkgfHwgZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIGFuIG9iamVjdD9cbiAgXy5pc09iamVjdCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciB0eXBlID0gdHlwZW9mIG9iajtcbiAgICByZXR1cm4gdHlwZSA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlID09PSAnb2JqZWN0JyAmJiAhIW9iajtcbiAgfTtcblxuICAvLyBBZGQgc29tZSBpc1R5cGUgbWV0aG9kczogaXNBcmd1bWVudHMsIGlzRnVuY3Rpb24sIGlzU3RyaW5nLCBpc051bWJlciwgaXNEYXRlLCBpc1JlZ0V4cCwgaXNFcnJvci5cbiAgXy5lYWNoKFsnQXJndW1lbnRzJywgJ0Z1bmN0aW9uJywgJ1N0cmluZycsICdOdW1iZXInLCAnRGF0ZScsICdSZWdFeHAnLCAnRXJyb3InXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIF9bJ2lzJyArIG5hbWVdID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCAnICsgbmFtZSArICddJztcbiAgICB9O1xuICB9KTtcblxuICAvLyBEZWZpbmUgYSBmYWxsYmFjayB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaW4gYnJvd3NlcnMgKGFoZW0sIElFIDwgOSksIHdoZXJlXG4gIC8vIHRoZXJlIGlzbid0IGFueSBpbnNwZWN0YWJsZSBcIkFyZ3VtZW50c1wiIHR5cGUuXG4gIGlmICghXy5pc0FyZ3VtZW50cyhhcmd1bWVudHMpKSB7XG4gICAgXy5pc0FyZ3VtZW50cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIF8uaGFzKG9iaiwgJ2NhbGxlZScpO1xuICAgIH07XG4gIH1cblxuICAvLyBPcHRpbWl6ZSBgaXNGdW5jdGlvbmAgaWYgYXBwcm9wcmlhdGUuIFdvcmsgYXJvdW5kIHNvbWUgdHlwZW9mIGJ1Z3MgaW4gb2xkIHY4LFxuICAvLyBJRSAxMSAoIzE2MjEpLCBhbmQgaW4gU2FmYXJpIDggKCMxOTI5KS5cbiAgaWYgKHR5cGVvZiAvLi8gIT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgSW50OEFycmF5ICE9ICdvYmplY3QnKSB7XG4gICAgXy5pc0Z1bmN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PSAnZnVuY3Rpb24nIHx8IGZhbHNlO1xuICAgIH07XG4gIH1cblxuICAvLyBJcyBhIGdpdmVuIG9iamVjdCBhIGZpbml0ZSBudW1iZXI/XG4gIF8uaXNGaW5pdGUgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gaXNGaW5pdGUob2JqKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChvYmopKTtcbiAgfTtcblxuICAvLyBJcyB0aGUgZ2l2ZW4gdmFsdWUgYE5hTmA/IChOYU4gaXMgdGhlIG9ubHkgbnVtYmVyIHdoaWNoIGRvZXMgbm90IGVxdWFsIGl0c2VsZikuXG4gIF8uaXNOYU4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gXy5pc051bWJlcihvYmopICYmIG9iaiAhPT0gK29iajtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgYm9vbGVhbj9cbiAgXy5pc0Jvb2xlYW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSB0cnVlIHx8IG9iaiA9PT0gZmFsc2UgfHwgdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBCb29sZWFuXSc7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBlcXVhbCB0byBudWxsP1xuICBfLmlzTnVsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IG51bGw7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSB1bmRlZmluZWQ/XG4gIF8uaXNVbmRlZmluZWQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSB2b2lkIDA7XG4gIH07XG5cbiAgLy8gU2hvcnRjdXQgZnVuY3Rpb24gZm9yIGNoZWNraW5nIGlmIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBwcm9wZXJ0eSBkaXJlY3RseVxuICAvLyBvbiBpdHNlbGYgKGluIG90aGVyIHdvcmRzLCBub3Qgb24gYSBwcm90b3R5cGUpLlxuICBfLmhhcyA9IGZ1bmN0aW9uKG9iaiwga2V5KSB7XG4gICAgcmV0dXJuIG9iaiAhPSBudWxsICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpO1xuICB9O1xuXG4gIC8vIFV0aWxpdHkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gUnVuIFVuZGVyc2NvcmUuanMgaW4gKm5vQ29uZmxpY3QqIG1vZGUsIHJldHVybmluZyB0aGUgYF9gIHZhcmlhYmxlIHRvIGl0c1xuICAvLyBwcmV2aW91cyBvd25lci4gUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QuXG4gIF8ubm9Db25mbGljdCA9IGZ1bmN0aW9uKCkge1xuICAgIHJvb3QuXyA9IHByZXZpb3VzVW5kZXJzY29yZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvLyBLZWVwIHRoZSBpZGVudGl0eSBmdW5jdGlvbiBhcm91bmQgZm9yIGRlZmF1bHQgaXRlcmF0ZWVzLlxuICBfLmlkZW50aXR5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH07XG5cbiAgLy8gUHJlZGljYXRlLWdlbmVyYXRpbmcgZnVuY3Rpb25zLiBPZnRlbiB1c2VmdWwgb3V0c2lkZSBvZiBVbmRlcnNjb3JlLlxuICBfLmNvbnN0YW50ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgfTtcblxuICBfLm5vb3AgPSBmdW5jdGlvbigpe307XG5cbiAgXy5wcm9wZXJ0eSA9IHByb3BlcnR5O1xuXG4gIC8vIEdlbmVyYXRlcyBhIGZ1bmN0aW9uIGZvciBhIGdpdmVuIG9iamVjdCB0aGF0IHJldHVybnMgYSBnaXZlbiBwcm9wZXJ0eS5cbiAgXy5wcm9wZXJ0eU9mID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PSBudWxsID8gZnVuY3Rpb24oKXt9IDogZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gb2JqW2tleV07XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgcHJlZGljYXRlIGZvciBjaGVja2luZyB3aGV0aGVyIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBzZXQgb2ZcbiAgLy8gYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8ubWF0Y2hlciA9IF8ubWF0Y2hlcyA9IGZ1bmN0aW9uKGF0dHJzKSB7XG4gICAgYXR0cnMgPSBfLmV4dGVuZE93bih7fSwgYXR0cnMpO1xuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBfLmlzTWF0Y2gob2JqLCBhdHRycyk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSdW4gYSBmdW5jdGlvbiAqKm4qKiB0aW1lcy5cbiAgXy50aW1lcyA9IGZ1bmN0aW9uKG4sIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgdmFyIGFjY3VtID0gQXJyYXkoTWF0aC5tYXgoMCwgbikpO1xuICAgIGl0ZXJhdGVlID0gb3B0aW1pemVDYihpdGVyYXRlZSwgY29udGV4dCwgMSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIGFjY3VtW2ldID0gaXRlcmF0ZWUoaSk7XG4gICAgcmV0dXJuIGFjY3VtO1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIGFuZCBtYXggKGluY2x1c2l2ZSkuXG4gIF8ucmFuZG9tID0gZnVuY3Rpb24obWluLCBtYXgpIHtcbiAgICBpZiAobWF4ID09IG51bGwpIHtcbiAgICAgIG1heCA9IG1pbjtcbiAgICAgIG1pbiA9IDA7XG4gICAgfVxuICAgIHJldHVybiBtaW4gKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpO1xuICB9O1xuXG4gIC8vIEEgKHBvc3NpYmx5IGZhc3Rlcikgd2F5IHRvIGdldCB0aGUgY3VycmVudCB0aW1lc3RhbXAgYXMgYW4gaW50ZWdlci5cbiAgXy5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gIH07XG5cbiAgIC8vIExpc3Qgb2YgSFRNTCBlbnRpdGllcyBmb3IgZXNjYXBpbmcuXG4gIHZhciBlc2NhcGVNYXAgPSB7XG4gICAgJyYnOiAnJmFtcDsnLFxuICAgICc8JzogJyZsdDsnLFxuICAgICc+JzogJyZndDsnLFxuICAgICdcIic6ICcmcXVvdDsnLFxuICAgIFwiJ1wiOiAnJiN4Mjc7JyxcbiAgICAnYCc6ICcmI3g2MDsnXG4gIH07XG4gIHZhciB1bmVzY2FwZU1hcCA9IF8uaW52ZXJ0KGVzY2FwZU1hcCk7XG5cbiAgLy8gRnVuY3Rpb25zIGZvciBlc2NhcGluZyBhbmQgdW5lc2NhcGluZyBzdHJpbmdzIHRvL2Zyb20gSFRNTCBpbnRlcnBvbGF0aW9uLlxuICB2YXIgY3JlYXRlRXNjYXBlciA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciBlc2NhcGVyID0gZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgIHJldHVybiBtYXBbbWF0Y2hdO1xuICAgIH07XG4gICAgLy8gUmVnZXhlcyBmb3IgaWRlbnRpZnlpbmcgYSBrZXkgdGhhdCBuZWVkcyB0byBiZSBlc2NhcGVkXG4gICAgdmFyIHNvdXJjZSA9ICcoPzonICsgXy5rZXlzKG1hcCkuam9pbignfCcpICsgJyknO1xuICAgIHZhciB0ZXN0UmVnZXhwID0gUmVnRXhwKHNvdXJjZSk7XG4gICAgdmFyIHJlcGxhY2VSZWdleHAgPSBSZWdFeHAoc291cmNlLCAnZycpO1xuICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHN0cmluZyA9PSBudWxsID8gJycgOiAnJyArIHN0cmluZztcbiAgICAgIHJldHVybiB0ZXN0UmVnZXhwLnRlc3Qoc3RyaW5nKSA/IHN0cmluZy5yZXBsYWNlKHJlcGxhY2VSZWdleHAsIGVzY2FwZXIpIDogc3RyaW5nO1xuICAgIH07XG4gIH07XG4gIF8uZXNjYXBlID0gY3JlYXRlRXNjYXBlcihlc2NhcGVNYXApO1xuICBfLnVuZXNjYXBlID0gY3JlYXRlRXNjYXBlcih1bmVzY2FwZU1hcCk7XG5cbiAgLy8gSWYgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBgcHJvcGVydHlgIGlzIGEgZnVuY3Rpb24gdGhlbiBpbnZva2UgaXQgd2l0aCB0aGVcbiAgLy8gYG9iamVjdGAgYXMgY29udGV4dDsgb3RoZXJ3aXNlLCByZXR1cm4gaXQuXG4gIF8ucmVzdWx0ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSwgZmFsbGJhY2spIHtcbiAgICB2YXIgdmFsdWUgPSBvYmplY3QgPT0gbnVsbCA/IHZvaWQgMCA6IG9iamVjdFtwcm9wZXJ0eV07XG4gICAgaWYgKHZhbHVlID09PSB2b2lkIDApIHtcbiAgICAgIHZhbHVlID0gZmFsbGJhY2s7XG4gICAgfVxuICAgIHJldHVybiBfLmlzRnVuY3Rpb24odmFsdWUpID8gdmFsdWUuY2FsbChvYmplY3QpIDogdmFsdWU7XG4gIH07XG5cbiAgLy8gR2VuZXJhdGUgYSB1bmlxdWUgaW50ZWdlciBpZCAodW5pcXVlIHdpdGhpbiB0aGUgZW50aXJlIGNsaWVudCBzZXNzaW9uKS5cbiAgLy8gVXNlZnVsIGZvciB0ZW1wb3JhcnkgRE9NIGlkcy5cbiAgdmFyIGlkQ291bnRlciA9IDA7XG4gIF8udW5pcXVlSWQgPSBmdW5jdGlvbihwcmVmaXgpIHtcbiAgICB2YXIgaWQgPSArK2lkQ291bnRlciArICcnO1xuICAgIHJldHVybiBwcmVmaXggPyBwcmVmaXggKyBpZCA6IGlkO1xuICB9O1xuXG4gIC8vIEJ5IGRlZmF1bHQsIFVuZGVyc2NvcmUgdXNlcyBFUkItc3R5bGUgdGVtcGxhdGUgZGVsaW1pdGVycywgY2hhbmdlIHRoZVxuICAvLyBmb2xsb3dpbmcgdGVtcGxhdGUgc2V0dGluZ3MgdG8gdXNlIGFsdGVybmF0aXZlIGRlbGltaXRlcnMuXG4gIF8udGVtcGxhdGVTZXR0aW5ncyA9IHtcbiAgICBldmFsdWF0ZSAgICA6IC88JShbXFxzXFxTXSs/KSU+L2csXG4gICAgaW50ZXJwb2xhdGUgOiAvPCU9KFtcXHNcXFNdKz8pJT4vZyxcbiAgICBlc2NhcGUgICAgICA6IC88JS0oW1xcc1xcU10rPyklPi9nXG4gIH07XG5cbiAgLy8gV2hlbiBjdXN0b21pemluZyBgdGVtcGxhdGVTZXR0aW5nc2AsIGlmIHlvdSBkb24ndCB3YW50IHRvIGRlZmluZSBhblxuICAvLyBpbnRlcnBvbGF0aW9uLCBldmFsdWF0aW9uIG9yIGVzY2FwaW5nIHJlZ2V4LCB3ZSBuZWVkIG9uZSB0aGF0IGlzXG4gIC8vIGd1YXJhbnRlZWQgbm90IHRvIG1hdGNoLlxuICB2YXIgbm9NYXRjaCA9IC8oLileLztcblxuICAvLyBDZXJ0YWluIGNoYXJhY3RlcnMgbmVlZCB0byBiZSBlc2NhcGVkIHNvIHRoYXQgdGhleSBjYW4gYmUgcHV0IGludG8gYVxuICAvLyBzdHJpbmcgbGl0ZXJhbC5cbiAgdmFyIGVzY2FwZXMgPSB7XG4gICAgXCInXCI6ICAgICAgXCInXCIsXG4gICAgJ1xcXFwnOiAgICAgJ1xcXFwnLFxuICAgICdcXHInOiAgICAgJ3InLFxuICAgICdcXG4nOiAgICAgJ24nLFxuICAgICdcXHUyMDI4JzogJ3UyMDI4JyxcbiAgICAnXFx1MjAyOSc6ICd1MjAyOSdcbiAgfTtcblxuICB2YXIgZXNjYXBlciA9IC9cXFxcfCd8XFxyfFxcbnxcXHUyMDI4fFxcdTIwMjkvZztcblxuICB2YXIgZXNjYXBlQ2hhciA9IGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgcmV0dXJuICdcXFxcJyArIGVzY2FwZXNbbWF0Y2hdO1xuICB9O1xuXG4gIC8vIEphdmFTY3JpcHQgbWljcm8tdGVtcGxhdGluZywgc2ltaWxhciB0byBKb2huIFJlc2lnJ3MgaW1wbGVtZW50YXRpb24uXG4gIC8vIFVuZGVyc2NvcmUgdGVtcGxhdGluZyBoYW5kbGVzIGFyYml0cmFyeSBkZWxpbWl0ZXJzLCBwcmVzZXJ2ZXMgd2hpdGVzcGFjZSxcbiAgLy8gYW5kIGNvcnJlY3RseSBlc2NhcGVzIHF1b3RlcyB3aXRoaW4gaW50ZXJwb2xhdGVkIGNvZGUuXG4gIC8vIE5COiBgb2xkU2V0dGluZ3NgIG9ubHkgZXhpc3RzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgXy50ZW1wbGF0ZSA9IGZ1bmN0aW9uKHRleHQsIHNldHRpbmdzLCBvbGRTZXR0aW5ncykge1xuICAgIGlmICghc2V0dGluZ3MgJiYgb2xkU2V0dGluZ3MpIHNldHRpbmdzID0gb2xkU2V0dGluZ3M7XG4gICAgc2V0dGluZ3MgPSBfLmRlZmF1bHRzKHt9LCBzZXR0aW5ncywgXy50ZW1wbGF0ZVNldHRpbmdzKTtcblxuICAgIC8vIENvbWJpbmUgZGVsaW1pdGVycyBpbnRvIG9uZSByZWd1bGFyIGV4cHJlc3Npb24gdmlhIGFsdGVybmF0aW9uLlxuICAgIHZhciBtYXRjaGVyID0gUmVnRXhwKFtcbiAgICAgIChzZXR0aW5ncy5lc2NhcGUgfHwgbm9NYXRjaCkuc291cmNlLFxuICAgICAgKHNldHRpbmdzLmludGVycG9sYXRlIHx8IG5vTWF0Y2gpLnNvdXJjZSxcbiAgICAgIChzZXR0aW5ncy5ldmFsdWF0ZSB8fCBub01hdGNoKS5zb3VyY2VcbiAgICBdLmpvaW4oJ3wnKSArICd8JCcsICdnJyk7XG5cbiAgICAvLyBDb21waWxlIHRoZSB0ZW1wbGF0ZSBzb3VyY2UsIGVzY2FwaW5nIHN0cmluZyBsaXRlcmFscyBhcHByb3ByaWF0ZWx5LlxuICAgIHZhciBpbmRleCA9IDA7XG4gICAgdmFyIHNvdXJjZSA9IFwiX19wKz0nXCI7XG4gICAgdGV4dC5yZXBsYWNlKG1hdGNoZXIsIGZ1bmN0aW9uKG1hdGNoLCBlc2NhcGUsIGludGVycG9sYXRlLCBldmFsdWF0ZSwgb2Zmc2V0KSB7XG4gICAgICBzb3VyY2UgKz0gdGV4dC5zbGljZShpbmRleCwgb2Zmc2V0KS5yZXBsYWNlKGVzY2FwZXIsIGVzY2FwZUNoYXIpO1xuICAgICAgaW5kZXggPSBvZmZzZXQgKyBtYXRjaC5sZW5ndGg7XG5cbiAgICAgIGlmIChlc2NhcGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBlc2NhcGUgKyBcIikpPT1udWxsPycnOl8uZXNjYXBlKF9fdCkpK1xcbidcIjtcbiAgICAgIH0gZWxzZSBpZiAoaW50ZXJwb2xhdGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBpbnRlcnBvbGF0ZSArIFwiKSk9PW51bGw/Jyc6X190KStcXG4nXCI7XG4gICAgICB9IGVsc2UgaWYgKGV2YWx1YXRlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIic7XFxuXCIgKyBldmFsdWF0ZSArIFwiXFxuX19wKz0nXCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkb2JlIFZNcyBuZWVkIHRoZSBtYXRjaCByZXR1cm5lZCB0byBwcm9kdWNlIHRoZSBjb3JyZWN0IG9mZmVzdC5cbiAgICAgIHJldHVybiBtYXRjaDtcbiAgICB9KTtcbiAgICBzb3VyY2UgKz0gXCInO1xcblwiO1xuXG4gICAgLy8gSWYgYSB2YXJpYWJsZSBpcyBub3Qgc3BlY2lmaWVkLCBwbGFjZSBkYXRhIHZhbHVlcyBpbiBsb2NhbCBzY29wZS5cbiAgICBpZiAoIXNldHRpbmdzLnZhcmlhYmxlKSBzb3VyY2UgPSAnd2l0aChvYmp8fHt9KXtcXG4nICsgc291cmNlICsgJ31cXG4nO1xuXG4gICAgc291cmNlID0gXCJ2YXIgX190LF9fcD0nJyxfX2o9QXJyYXkucHJvdG90eXBlLmpvaW4sXCIgK1xuICAgICAgXCJwcmludD1mdW5jdGlvbigpe19fcCs9X19qLmNhbGwoYXJndW1lbnRzLCcnKTt9O1xcblwiICtcbiAgICAgIHNvdXJjZSArICdyZXR1cm4gX19wO1xcbic7XG5cbiAgICB0cnkge1xuICAgICAgdmFyIHJlbmRlciA9IG5ldyBGdW5jdGlvbihzZXR0aW5ncy52YXJpYWJsZSB8fCAnb2JqJywgJ18nLCBzb3VyY2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGUuc291cmNlID0gc291cmNlO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICB2YXIgdGVtcGxhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgICByZXR1cm4gcmVuZGVyLmNhbGwodGhpcywgZGF0YSwgXyk7XG4gICAgfTtcblxuICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIHNvdXJjZSBhcyBhIGNvbnZlbmllbmNlIGZvciBwcmVjb21waWxhdGlvbi5cbiAgICB2YXIgYXJndW1lbnQgPSBzZXR0aW5ncy52YXJpYWJsZSB8fCAnb2JqJztcbiAgICB0ZW1wbGF0ZS5zb3VyY2UgPSAnZnVuY3Rpb24oJyArIGFyZ3VtZW50ICsgJyl7XFxuJyArIHNvdXJjZSArICd9JztcblxuICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgfTtcblxuICAvLyBBZGQgYSBcImNoYWluXCIgZnVuY3Rpb24uIFN0YXJ0IGNoYWluaW5nIGEgd3JhcHBlZCBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5jaGFpbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBpbnN0YW5jZSA9IF8ob2JqKTtcbiAgICBpbnN0YW5jZS5fY2hhaW4gPSB0cnVlO1xuICAgIHJldHVybiBpbnN0YW5jZTtcbiAgfTtcblxuICAvLyBPT1BcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXG4gIC8vIElmIFVuZGVyc2NvcmUgaXMgY2FsbGVkIGFzIGEgZnVuY3Rpb24sIGl0IHJldHVybnMgYSB3cmFwcGVkIG9iamVjdCB0aGF0XG4gIC8vIGNhbiBiZSB1c2VkIE9PLXN0eWxlLiBUaGlzIHdyYXBwZXIgaG9sZHMgYWx0ZXJlZCB2ZXJzaW9ucyBvZiBhbGwgdGhlXG4gIC8vIHVuZGVyc2NvcmUgZnVuY3Rpb25zLiBXcmFwcGVkIG9iamVjdHMgbWF5IGJlIGNoYWluZWQuXG5cbiAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGNvbnRpbnVlIGNoYWluaW5nIGludGVybWVkaWF0ZSByZXN1bHRzLlxuICB2YXIgcmVzdWx0ID0gZnVuY3Rpb24oaW5zdGFuY2UsIG9iaikge1xuICAgIHJldHVybiBpbnN0YW5jZS5fY2hhaW4gPyBfKG9iaikuY2hhaW4oKSA6IG9iajtcbiAgfTtcblxuICAvLyBBZGQgeW91ciBvd24gY3VzdG9tIGZ1bmN0aW9ucyB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QuXG4gIF8ubWl4aW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICBfLmVhY2goXy5mdW5jdGlvbnMob2JqKSwgZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBfW25hbWVdID0gb2JqW25hbWVdO1xuICAgICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbdGhpcy5fd3JhcHBlZF07XG4gICAgICAgIHB1c2guYXBwbHkoYXJncywgYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCh0aGlzLCBmdW5jLmFwcGx5KF8sIGFyZ3MpKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gQWRkIGFsbCBvZiB0aGUgVW5kZXJzY29yZSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIgb2JqZWN0LlxuICBfLm1peGluKF8pO1xuXG4gIC8vIEFkZCBhbGwgbXV0YXRvciBBcnJheSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIuXG4gIF8uZWFjaChbJ3BvcCcsICdwdXNoJywgJ3JldmVyc2UnLCAnc2hpZnQnLCAnc29ydCcsICdzcGxpY2UnLCAndW5zaGlmdCddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07XG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvYmogPSB0aGlzLl93cmFwcGVkO1xuICAgICAgbWV0aG9kLmFwcGx5KG9iaiwgYXJndW1lbnRzKTtcbiAgICAgIGlmICgobmFtZSA9PT0gJ3NoaWZ0JyB8fCBuYW1lID09PSAnc3BsaWNlJykgJiYgb2JqLmxlbmd0aCA9PT0gMCkgZGVsZXRlIG9ialswXTtcbiAgICAgIHJldHVybiByZXN1bHQodGhpcywgb2JqKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBBZGQgYWxsIGFjY2Vzc29yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgXy5lYWNoKFsnY29uY2F0JywgJ2pvaW4nLCAnc2xpY2UnXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xuICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcmVzdWx0KHRoaXMsIG1ldGhvZC5hcHBseSh0aGlzLl93cmFwcGVkLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBFeHRyYWN0cyB0aGUgcmVzdWx0IGZyb20gYSB3cmFwcGVkIGFuZCBjaGFpbmVkIG9iamVjdC5cbiAgXy5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fd3JhcHBlZDtcbiAgfTtcblxuICAvLyBQcm92aWRlIHVud3JhcHBpbmcgcHJveHkgZm9yIHNvbWUgbWV0aG9kcyB1c2VkIGluIGVuZ2luZSBvcGVyYXRpb25zXG4gIC8vIHN1Y2ggYXMgYXJpdGhtZXRpYyBhbmQgSlNPTiBzdHJpbmdpZmljYXRpb24uXG4gIF8ucHJvdG90eXBlLnZhbHVlT2YgPSBfLnByb3RvdHlwZS50b0pTT04gPSBfLnByb3RvdHlwZS52YWx1ZTtcblxuICBfLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAnJyArIHRoaXMuX3dyYXBwZWQ7XG4gIH07XG5cbiAgLy8gQU1EIHJlZ2lzdHJhdGlvbiBoYXBwZW5zIGF0IHRoZSBlbmQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBBTUQgbG9hZGVyc1xuICAvLyB0aGF0IG1heSBub3QgZW5mb3JjZSBuZXh0LXR1cm4gc2VtYW50aWNzIG9uIG1vZHVsZXMuIEV2ZW4gdGhvdWdoIGdlbmVyYWxcbiAgLy8gcHJhY3RpY2UgZm9yIEFNRCByZWdpc3RyYXRpb24gaXMgdG8gYmUgYW5vbnltb3VzLCB1bmRlcnNjb3JlIHJlZ2lzdGVyc1xuICAvLyBhcyBhIG5hbWVkIG1vZHVsZSBiZWNhdXNlLCBsaWtlIGpRdWVyeSwgaXQgaXMgYSBiYXNlIGxpYnJhcnkgdGhhdCBpc1xuICAvLyBwb3B1bGFyIGVub3VnaCB0byBiZSBidW5kbGVkIGluIGEgdGhpcmQgcGFydHkgbGliLCBidXQgbm90IGJlIHBhcnQgb2ZcbiAgLy8gYW4gQU1EIGxvYWQgcmVxdWVzdC4gVGhvc2UgY2FzZXMgY291bGQgZ2VuZXJhdGUgYW4gZXJyb3Igd2hlbiBhblxuICAvLyBhbm9ueW1vdXMgZGVmaW5lKCkgaXMgY2FsbGVkIG91dHNpZGUgb2YgYSBsb2FkZXIgcmVxdWVzdC5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZSgndW5kZXJzY29yZScsIFtdLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG59LmNhbGwodGhpcykpO1xuIl19