PageSourceSearch

https://muttermuseum.org/35fc8c20-35c7218b547019f519b8.js

js muttermuseum.org collected 2026-10-02 02:41:06 UTC 795,211 bytes, 1 lines download raw bytes

1(self.webpackChunkcpp_mutter=self.webpackChunkcpp_mutter||[]).push([[75],{6396:function(module,__unused_webpack_exports,__webpack_require__){eval("__webpack_require__(6910);\n__webpack_require__(8845);\n__webpack_require__(373);\n(function (global, factory) {\n   true ? module.exports = factory() : 0;\n})(this, function () {\n  'use strict';\n\n  var isTypedArray = function isTypedArray(x) {\n    return x instanceof Uint8Array || x instanceof Uint16Array || x instanceof Uint32Array || x instanceof Int8Array || x instanceof Int16Array || x instanceof Int32Array || x instanceof Float32Array || x instanceof Float64Array || x instanceof Uint8ClampedArray;\n  };\n  var extend = function extend(base, opts) {\n    var keys = Object.keys(opts);\n    for (var i = 0; i < keys.length; ++i) {\n      base[keys[i]] = opts[keys[i]];\n    }\n    return base;\n  };\n\n  // Error checking and parameter validation.\n  //\n  // Statements for the form `check.someProcedure(...)` get removed by\n  // a browserify transform for optimized/minified bundles.\n  //\n  /* globals atob */\n  var endl = '\\n';\n\n  // only used for extracting shader names.  if atob not present, then errors\n  // will be slightly crappier\n  function decodeB64(str) {\n    if (typeof atob !== 'undefined') {\n      return atob(str);\n    }\n    return 'base64:' + str;\n  }\n  function raise(message) {\n    var error = new Error('(regl) ' + message);\n    console.error(error);\n    throw error;\n  }\n  function check(pred, message) {\n    if (!pred) {\n      raise(message);\n    }\n  }\n  function encolon(message) {\n    if (message) {\n      return ': ' + message;\n    }\n    return '';\n  }\n  function checkParameter(param, possibilities, message) {\n    if (!(param in possibilities)) {\n      raise('unknown parameter (' + param + ')' + encolon(message) + '. possible values: ' + Object.keys(possibilities).join());\n    }\n  }\n  function checkIsTypedArray(data, message) {\n    if (!isTypedArray(data)) {\n      raise('invalid parameter type' + encolon(message) + '. must be a typed array');\n    }\n  }\n  function standardTypeEh(value, type) {\n    switch (type) {\n      case 'number':\n        return typeof value === 'number';\n      case 'object':\n        return typeof value === 'object';\n      case 'string':\n        return typeof value === 'string';\n      case 'boolean':\n        return typeof value === 'boolean';\n      case 'function':\n        return typeof value === 'function';\n      case 'undefined':\n        return typeof value === 'undefined';\n      case 'symbol':\n        return typeof value === 'symbol';\n    }\n  }\n  function checkTypeOf(value, type, message) {\n    if (!standardTypeEh(value, type)) {\n      raise('invalid parameter type' + encolon(message) + '. expected ' + type + ', got ' + typeof value);\n    }\n  }\n  function checkNonNegativeInt(value, message) {\n    if (!(value >= 0 && (value | 0) === value)) {\n      raise('invalid parameter type, (' + value + ')' + encolon(message) + '. must be a nonnegative integer');\n    }\n  }\n  function checkOneOf(value, list, message) {\n    if (list.indexOf(value) < 0) {\n      raise('invalid value' + encolon(message) + '. must be one of: ' + list);\n    }\n  }\n  var constructorKeys = ['gl', 'canvas', 'container', 'attributes', 'pixelRatio', 'extensions', 'optionalExtensions', 'profile', 'onDone'];\n  function checkConstructor(obj) {\n    Object.keys(obj).forEach(function (key) {\n      if (constructorKeys.indexOf(key) < 0) {\n        raise('invalid regl constructor argument \"' + key + '\". must be one of ' + constructorKeys);\n      }\n    });\n  }\n  function leftPad(str, n) {\n    str = str + '';\n    while (str.length < n) {\n      str = ' ' + str;\n    }\n    return str;\n  }\n  function ShaderFile() {\n    this.name = 'unknown';\n    this.lines = [];\n    this.index = {};\n    this.hasErrors = false;\n  }\n  function ShaderLine(number, line) {\n    this.number = number;\n    this.line = line;\n    this.errors = [];\n  }\n  function ShaderError(fileNumber, lineNumber, message) {\n    this.file = fileNumber;\n    this.line = lineNumber;\n    this.message = message;\n  }\n  function guessCommand() {\n    var error = new Error();\n    var stack = (error.stack || error).toString();\n    var pat = /compileProcedure.*\\n\\s*at.*\\((.*)\\)/.exec(stack);\n    if (pat) {\n      return pat[1];\n    }\n    var pat2 = /compileProcedure.*\\n\\s*at\\s+(.*)(\\n|$)/.exec(stack);\n    if (pat2) {\n      return pat2[1];\n    }\n    return 'unknown';\n  }\n  function guessCallSite() {\n    var error = new Error();\n    var stack = (error.stack || error).toString();\n    var pat = /at REGLCommand.*\\n\\s+at.*\\((.*)\\)/.exec(stack);\n    if (pat) {\n      return pat[1];\n    }\n    var pat2 = /at REGLCommand.*\\n\\s+at\\s+(.*)\\n/.exec(stack);\n    if (pat2) {\n      return pat2[1];\n    }\n    return 'unknown';\n  }\n  function parseSource(source, command) {\n    var lines = source.split('\\n');\n    var lineNumber = 1;\n    var fileNumber = 0;\n    var files = {\n      unknown: new ShaderFile(),\n      0: new ShaderFile()\n    };\n    files.unknown.name = files[0].name = command || guessCommand();\n    files.unknown.lines.push(new ShaderLine(0, ''));\n    for (var i = 0; i < lines.length; ++i) {\n      var line = lines[i];\n      var parts = /^\\s*#\\s*(\\w+)\\s+(.+)\\s*$/.exec(line);\n      if (parts) {\n        switch (parts[1]) {\n          case 'line':\n            var lineNumberInfo = /(\\d+)(\\s+\\d+)?/.exec(parts[2]);\n            if (lineNumberInfo) {\n              lineNumber = lineNumberInfo[1] | 0;\n              if (lineNumberInfo[2]) {\n                fileNumber = lineNumberInfo[2] | 0;\n                if (!(fileNumber in files)) {\n                  files[fileNumber] = new ShaderFile();\n                }\n              }\n            }\n            break;\n          case 'define':\n            var nameInfo = /SHADER_NAME(_B64)?\\s+(.*)$/.exec(parts[2]);\n            if (nameInfo) {\n              files[fileNumber].name = nameInfo[1] ? decodeB64(nameInfo[2]) : nameInfo[2];\n            }\n            break;\n        }\n      }\n      files[fileNumber].lines.push(new ShaderLine(lineNumber++, line));\n    }
1\n    Object.keys(files).forEach(function (fileNumber) {\n      var file = files[fileNumber];\n      file.lines.forEach(function (line) {\n        file.index[line.number] = line;\n      });\n    });\n    return files;\n  }\n  function parseErrorLog(errLog) {\n    var result = [];\n    errLog.split('\\n').forEach(function (errMsg) {\n      if (errMsg.length < 5) {\n        return;\n      }\n      var parts = /^ERROR:\\s+(\\d+):(\\d+):\\s*(.*)$/.exec(errMsg);\n      if (parts) {\n        result.push(new ShaderError(parts[1] | 0, parts[2] | 0, parts[3].trim()));\n      } else if (errMsg.length > 0) {\n        result.push(new ShaderError('unknown', 0, errMsg));\n      }\n    });\n    return result;\n  }\n  function annotateFiles(files, errors) {\n    errors.forEach(function (error) {\n      var file = files[error.file];\n      if (file) {\n        var line = file.index[error.line];\n        if (line) {\n          line.errors.push(error);\n          file.hasErrors = true;\n          return;\n        }\n      }\n      files.unknown.hasErrors = true;\n      files.unknown.lines[0].errors.push(error);\n    });\n  }\n  function checkShaderError(gl, shader, source, type, command) {\n    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n      var errLog = gl.getShaderInfoLog(shader);\n      var typeName = type === gl.FRAGMENT_SHADER ? 'fragment' : 'vertex';\n      checkCommandType(source, 'string', typeName + ' shader source must be a string', command);\n      var files = parseSource(source, command);\n      var errors = parseErrorLog(errLog);\n      annotateFiles(files, errors);\n      Object.keys(files).forEach(function (fileNumber) {\n        var file = files[fileNumber];\n        if (!file.hasErrors) {\n          return;\n        }\n        var strings = [''];\n        var styles = [''];\n        function push(str, style) {\n          strings.push(str);\n          styles.push(style || '');\n        }\n        push('file number ' + fileNumber + ': ' + file.name + '\\n', 'color:red;text-decoration:underline;font-weight:bold');\n        file.lines.forEach(function (line) {\n          if (line.errors.length > 0) {\n            push(leftPad(line.number, 4) + '|  ', 'background-color:yellow; font-weight:bold');\n            push(line.line + endl, 'color:red; background-color:yellow; font-weight:bold');\n\n            // try to guess token\n            var offset = 0;\n            line.errors.forEach(function (error) {\n              var message = error.message;\n              var token = /^\\s*'(.*)'\\s*:\\s*(.*)$/.exec(message);\n              if (token) {\n                var tokenPat = token[1];\n                message = token[2];\n                switch (tokenPat) {\n                  case 'assign':\n                    tokenPat = '=';\n                    break;\n                }\n                offset = Math.max(line.line.indexOf(tokenPat, offset), 0);\n              } else {\n                offset = 0;\n              }\n              push(leftPad('| ', 6));\n              push(leftPad('^^^', offset + 3) + endl, 'font-weight:bold');\n              push(leftPad('| ', 6));\n              push(message + endl, 'font-weight:bold');\n            });\n            push(leftPad('| ', 6) + endl);\n          } else {\n            push(leftPad(line.number, 4) + '|  ');\n            push(line.line + endl, 'color:red');\n          }\n        });\n        if (typeof document !== 'undefined' && !window.chrome) {\n          styles[0] = strings.join('%c');\n          console.log.apply(console, styles);\n        } else {\n          console.log(strings.join(''));\n        }\n      });\n      check.raise('Error compiling ' + typeName + ' shader, ' + files[0].name);\n    }\n  }\n  function checkLinkError(gl, program, fragShader, vertShader, command) {\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      var errLog = gl.getProgramInfoLog(program);\n      var fragParse = parseSource(fragShader, command);\n      var vertParse = parseSource(vertShader, command);\n      var header = 'Error linking program with vertex shader, \"' + vertParse[0].name + '\", and fragment shader \"' + fragParse[0].name + '\"';\n      if (typeof document !== 'undefined') {\n        console.log('%c' + header + endl + '%c' + errLog, 'color:red;text-decoration:underline;font-weight:bold', 'color:red');\n      } else {\n        console.log(header + endl + errLog);\n      }\n      check.raise(header);\n    }\n  }\n  function saveCommandRef(object) {\n    object._commandRef = guessCommand();\n  }\n  function saveDrawCommandInfo(opts, uniforms, attributes, str
1ingStore) {\n    saveCommandRef(opts);\n    function id(str) {\n      if (str) {\n        return stringStore.id(str);\n      }\n      return 0;\n    }\n    opts._fragId = id(opts.static.frag);\n    opts._vertId = id(opts.static.vert);\n    function addProps(dict, set) {\n      Object.keys(set).forEach(function (u) {\n        dict[stringStore.id(u)] = true;\n      });\n    }\n    var uniformSet = opts._uniformSet = {};\n    addProps(uniformSet, uniforms.static);\n    addProps(uniformSet, uniforms.dynamic);\n    var attributeSet = opts._attributeSet = {};\n    addProps(attributeSet, attributes.static);\n    addProps(attributeSet, attributes.dynamic);\n    opts._hasCount = 'count' in opts.static || 'count' in opts.dynamic || 'elements' in opts.static || 'elements' in opts.dynamic;\n  }\n  function commandRaise(message, command) {\n    var callSite = guessCallSite();\n    raise(message + ' in command ' + (command || guessCommand()) + (callSite === 'unknown' ? '' : ' called from ' + callSite));\n  }\n  function checkCommand(pred, message, command) {\n    if (!pred) {\n      commandRaise(message, command || guessCommand());\n    }\n  }\n  function checkParameterCommand(param, possibilities, message, command) {\n    if (!(param in possibilities)) {\n      commandRaise('unknown parameter (' + param + ')' + encolon(message) + '. possible values: ' + Object.keys(possibilities).join(), command || guessCommand());\n    }\n  }\n  function checkCommandType(value, type, message, command) {\n    if (!standardTypeEh(value, type)) {\n      commandRaise('invalid parameter type' + encolon(message) + '. expected ' + type + ', got ' + typeof value, command || guessCommand());\n    }\n  }\n  function checkOptional(block) {\n    block();\n  }\n  function checkFramebufferFormat(attachment, texFormats, rbFormats) {\n    if (attachment.texture) {\n      checkOneOf(attachment.texture._texture.internalformat, texFormats, 'unsupported texture format for attachment');\n    } else {\n      checkOneOf(attachment.renderbuffer._renderbuffer.format, rbFormats, 'unsupported renderbuffer format for attachment');\n    }\n  }\n  var GL_CLAMP_TO_EDGE = 0x812F;\n  var GL_NEAREST = 0x2600;\n  var GL_NEAREST_MIPMAP_NEAREST = 0x2700;\n  var GL_LINEAR_MIPMAP_NEAREST = 0x2701;\n  var GL_NEAREST_MIPMAP_LINEAR = 0x2702;\n  var GL_LINEAR_MIPMAP_LINEAR = 0x2703;\n  var GL_BYTE = 5120;\n  var GL_UNSIGNED_BYTE = 5121;\n  var GL_SHORT = 5122;\n  var GL_UNSIGNED_SHORT = 5123;\n  var GL_INT = 5124;\n  var GL_UNSIGNED_INT = 5125;\n  var GL_FLOAT = 5126;\n  var GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033;\n  var GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034;\n  var GL_UNSIGNED_SHORT_5_6_5 = 0x8363;\n  var GL_UNSIGNED_INT_24_8_WEBGL = 0x84FA;\n  var GL_HALF_FLOAT_OES = 0x8D61;\n  var TYPE_SIZE = {};\n  TYPE_SIZE[GL_BYTE] = TYPE_SIZE[GL_UNSIGNED_BYTE] = 1;\n  TYPE_SIZE[GL_SHORT] = TYPE_SIZE[GL_UNSIGNED_SHORT] = TYPE_SIZE[GL_HALF_FLOAT_OES] = TYPE_SIZE[GL_UNSIGNED_SHORT_5_6_5] = TYPE_SIZE[GL_UNSIGNED_SHORT_4_4_4_4] = TYPE_SIZE[GL_UNSIGNED_SHORT_5_5_5_1] = 2;\n  TYPE_SIZE[GL_INT] = TYPE_SIZE[GL_UNSIGNED_INT] = TYPE_SIZE[GL_FLOAT] = TYPE_SIZE[GL_UNSIGNED_INT_24_8_WEBGL] = 4;\n  function pixelSize(type, channels) {\n    if (type === GL_UNSIGNED_SHORT_5_5_5_1 || type === GL_UNSIGNED_SHORT_4_4_4_4 || type === GL_UNSIGNED_SHORT_5_6_5) {\n      return 2;\n    } else if (type === GL_UNSIGNED_INT_24_8_WEBGL) {\n      return 4;\n    } else {\n      return TYPE_SIZE[type] * channels;\n    }\n  }\n  function isPow2(v) {\n    return !(v & v - 1) && !!v;\n  }\n  function checkTexture2D(info, mipData, limits) {\n    var i;\n    var w = mipData.width;\n    var h = mipData.height;\n    var c = mipData.channels;\n\n    // Check texture shape\n    check(w > 0 && w <= limits.maxTextureSize && h > 0 && h <= limits.maxTextureSize, 'invalid texture shape');\n\n    // check wrap mode\n    if (info.wrapS !== GL_CLAMP_TO_EDGE || info.wrapT !== GL_CLAMP_TO_EDGE) {\n      check(isPow2(w) && isPow2(h), 'incompatible wrap mode for texture, both width and height must be power of 2');\n    }\n    if (mipData.mipmask === 1) {\n      if (w !== 1 && h !== 1) {\n        check(info.minFilter !== GL_NEAREST_MIPMAP_NEAREST && info.minFilter !== GL_NEAREST_MIPMAP_LINEAR && info.minFilter !== GL_LINEAR_MIPMAP_NEAREST && info.minFilter !== GL_LINEAR_MIPMAP_LINEAR, 'min filter requires mipmap');\n      }\n    } else {\n      // texture must be power of 2\n      check(isPow2(w) && isPow2(h), 'texture must be a square power of 2 to supp
1ort mipmapping');\n      check(mipData.mipmask === (w << 1) - 1, 'missing or incomplete mipmap data');\n    }\n    if (mipData.type === GL_FLOAT) {\n      if (limits.extensions.indexOf('oes_texture_float_linear') < 0) {\n        check(info.minFilter === GL_NEAREST && info.magFilter === GL_NEAREST, 'filter not supported, must enable oes_texture_float_linear');\n      }\n      check(!info.genMipmaps, 'mipmap generation not supported with float textures');\n    }\n\n    // check image complete\n    var mipimages = mipData.images;\n    for (i = 0; i < 16; ++i) {\n      if (mipimages[i]) {\n        var mw = w >> i;\n        var mh = h >> i;\n        check(mipData.mipmask & 1 << i, 'missing mipmap data');\n        var img = mipimages[i];\n        check(img.width === mw && img.height === mh, 'invalid shape for mip images');\n        check(img.format === mipData.format && img.internalformat === mipData.internalformat && img.type === mipData.type, 'incompatible type for mip image');\n        if (img.compressed) {\n          // TODO: check size for compressed images\n        } else if (img.data) {\n          // check(img.data.byteLength === mw * mh *\n          // Math.max(pixelSize(img.type, c), img.unpackAlignment),\n          var rowSize = Math.ceil(pixelSize(img.type, c) * mw / img.unpackAlignment) * img.unpackAlignment;\n          check(img.data.byteLength === rowSize * mh, 'invalid data for image, buffer size is inconsistent with image format');\n        } else if (img.element) {\n          // TODO: check element can be loaded\n        } else if (img.copy) {\n          // TODO: check compatible format and type\n        }\n      } else if (!info.genMipmaps) {\n        check((mipData.mipmask & 1 << i) === 0, 'extra mipmap data');\n      }\n    }\n    if (mipData.compressed) {\n      check(!info.genMipmaps, 'mipmap generation for compressed images not supported');\n    }\n  }\n  function checkTextureCube(texture, info, faces, limits) {\n    var w = texture.width;\n    var h = texture.height;\n    var c = texture.channels;\n\n    // Check texture shape\n    check(w > 0 && w <= limits.maxTextureSize && h > 0 && h <= limits.maxTextureSize, 'invalid texture shape');\n    check(w === h, 'cube map must be square');\n    check(info.wrapS === GL_CLAMP_TO_EDGE && info.wrapT === GL_CLAMP_TO_EDGE, 'wrap mode not supported by cube map');\n    for (var i = 0; i < faces.length; ++i) {\n      var face = faces[i];\n      check(face.width === w && face.height === h, 'inconsistent cube map face shape');\n      if (info.genMipmaps) {\n        check(!face.compressed, 'can not generate mipmap for compressed textures');\n        check(face.mipmask === 1, 'can not specify mipmaps and generate mipmaps');\n      } else {\n        // TODO: check mip and filter mode\n      }\n      var mipmaps = face.images;\n      for (var j = 0; j < 16; ++j) {\n        var img = mipmaps[j];\n        if (img) {\n          var mw = w >> j;\n          var mh = h >> j;\n          check(face.mipmask & 1 << j, 'missing mipmap data');\n          check(img.width === mw && img.height === mh, 'invalid shape for mip images');\n          check(img.format === texture.format && img.internalformat === texture.internalformat && img.type === texture.type, 'incompatible type for mip image');\n          if (img.compressed) {\n            // TODO: check size for compressed images\n          } else if (img.data) {\n            check(img.data.byteLength === mw * mh * Math.max(pixelSize(img.type, c), img.unpackAlignment), 'invalid data for image, buffer size is inconsistent with image format');\n          } else if (img.element) {\n            // TODO: check element can be loaded\n          } else if (img.copy) {\n            // TODO: check compatible format and type\n          }\n        }\n      }\n    }\n  }\n  var check$1 = extend(check, {\n    optional: checkOptional,\n    raise: raise,\n    commandRaise: commandRaise,\n    command: checkCommand,\n    parameter: checkParameter,\n    commandParameter: checkParameterCommand,\n    constructor: checkConstructor,\n    type: checkTypeOf,\n    commandType: checkCommandType,\n    isTypedArray: checkIsTypedArray,\n    nni: checkNonNegativeInt,\n    oneOf: checkOneOf,\n    shaderError: checkSha
1derError,\n    linkError: checkLinkError,\n    callSite: guessCallSite,\n    saveCommandRef: saveCommandRef,\n    saveDrawInfo: saveDrawCommandInfo,\n    framebufferFormat: checkFramebufferFormat,\n    guessCommand: guessCommand,\n    texture2D: checkTexture2D,\n    textureCube: checkTextureCube\n  });\n  var VARIABLE_COUNTER = 0;\n  var DYN_FUNC = 0;\n  var DYN_CONSTANT = 5;\n  var DYN_ARRAY = 6;\n  function DynamicVariable(type, data) {\n    this.id = VARIABLE_COUNTER++;\n    this.type = type;\n    this.data = data;\n  }\n  function escapeStr(str) {\n    return str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n  }\n  function splitParts(str) {\n    if (str.length === 0) {\n      return [];\n    }\n    var firstChar = str.charAt(0);\n    var lastChar = str.charAt(str.length - 1);\n    if (str.length > 1 && firstChar === lastChar && (firstChar === '\"' || firstChar === \"'\")) {\n      return ['\"' + escapeStr(str.substr(1, str.length - 2)) + '\"'];\n    }\n    var parts = /\\[(false|true|null|\\d+|'[^']*'|\"[^\"]*\")\\]/.exec(str);\n    if (parts) {\n      return splitParts(str.substr(0, parts.index)).concat(splitParts(parts[1])).concat(splitParts(str.substr(parts.index + parts[0].length)));\n    }\n    var subparts = str.split('.');\n    if (subparts.length === 1) {\n      return ['\"' + escapeStr(str) + '\"'];\n    }\n    var result = [];\n    for (var i = 0; i < subparts.length; ++i) {\n      result = result.concat(splitParts(subparts[i]));\n    }\n    return result;\n  }\n  function toAccessorString(str) {\n    return '[' + splitParts(str).join('][') + ']';\n  }\n  function defineDynamic(type, data) {\n    return new DynamicVariable(type, toAccessorString(data + ''));\n  }\n  function isDynamic(x) {\n    return typeof x === 'function' && !x._reglType || x instanceof DynamicVariable;\n  }\n  function unbox(x, path) {\n    if (typeof x === 'function') {\n      return new DynamicVariable(DYN_FUNC, x);\n    } else if (typeof x === 'number' || typeof x === 'boolean') {\n      return new DynamicVariable(DYN_CONSTANT, x);\n    } else if (Array.isArray(x)) {\n      return new DynamicVariable(DYN_ARRAY, x.map(function (y, i) {\n        return unbox(y, path + '[' + i + ']');\n      }));\n    } else if (x instanceof DynamicVariable) {\n      return x;\n    }\n    check$1(false, 'invalid option type in uniform ' + path);\n  }\n  var dynamic = {\n    DynamicVariable: DynamicVariable,\n    define: defineDynamic,\n    isDynamic: isDynamic,\n    unbox: unbox,\n    accessor: toAccessorString\n  };\n\n  /* globals requestAnimationFrame, cancelAnimationFrame */\n  var raf = {\n    next: typeof requestAnimationFrame === 'function' ? function (cb) {\n      return requestAnimationFrame(cb);\n    } : function (cb) {\n      return setTimeout(cb, 16);\n    },\n    cancel: typeof cancelAnimationFrame === 'function' ? function (raf) {\n      return cancelAnimationFrame(raf);\n    } : clearTimeout\n  };\n\n  /* globals performance */\n  var clock = typeof performance !== 'undefined' && performance.now ? function () {\n    return performance.now();\n  } : function () {\n    return +new Date();\n  };\n  function createStringStore() {\n    var stringIds = {\n      '': 0\n    };\n    var stringValues = [''];\n    return {\n      id: function id(str) {\n        var result = stringIds[str];\n        if (result) {\n          return result;\n        }\n        result = stringIds[str] = stringValues.length;\n        stringValues.push(str);\n        return result;\n      },\n      str: function str(id) {\n        return stringValues[id];\n      }\n    };\n  }\n\n  // Context and canvas creation helper functions\n  function createCanvas(element, onDone, pixelRatio) {\n    var canvas = document.createElement('canvas');\n    extend(canvas.style, {\n      border: 0,\n      margin: 0,\n      padding: 0,\n      top: 0,\n      left: 0,\n      width: '100%',\n      height: '100%'\n    });\n    element.appendChild(canvas);\n    if (element === document.body) {\n      canvas.style.position = 'absolute';\n      extend(element.style, {\n        margin: 0,\n        padding: 0\n      });\n    }\n    function resize() {\n      var w = window.innerWidth;\n      var h = window.innerHeight;
1\n      if (element !== document.body) {\n        var bounds = canvas.getBoundingClientRect();\n        w = bounds.right - bounds.left;\n        h = bounds.bottom - bounds.top;\n      }\n      canvas.width = pixelRatio * w;\n      canvas.height = pixelRatio * h;\n    }\n    var resizeObserver;\n    if (element !== document.body && typeof ResizeObserver === 'function') {\n      // ignore 'ResizeObserver' is not defined\n      // eslint-disable-next-line\n      resizeObserver = new ResizeObserver(function () {\n        // setTimeout to avoid flicker\n        setTimeout(resize);\n      });\n      resizeObserver.observe(element);\n    } else {\n      window.addEventListener('resize', resize, false);\n    }\n    function onDestroy() {\n      if (resizeObserver) {\n        resizeObserver.disconnect();\n      } else {\n        window.removeEventListener('resize', resize);\n      }\n      element.removeChild(canvas);\n    }\n    resize();\n    return {\n      canvas: canvas,\n      onDestroy: onDestroy\n    };\n  }\n  function createContext(canvas, contextAttributes) {\n    function get(name) {\n      try {\n        return canvas.getContext(name, contextAttributes);\n      } catch (e) {\n        return null;\n      }\n    }\n    return get('webgl') || get('experimental-webgl') || get('webgl-experimental');\n  }\n  function isHTMLElement(obj) {\n    return typeof obj.nodeName === 'string' && typeof obj.appendChild === 'function' && typeof obj.getBoundingClientRect === 'function';\n  }\n  function isWebGLContext(obj) {\n    return typeof obj.drawArrays === 'function' || typeof obj.drawElements === 'function';\n  }\n  function parseExtensions(input) {\n    if (typeof input === 'string') {\n      return input.split();\n    }\n    check$1(Array.isArray(input), 'invalid extension array');\n    return input;\n  }\n  function getElement(desc) {\n    if (typeof desc === 'string') {\n      check$1(typeof document !== 'undefined', 'not supported outside of DOM');\n      return document.querySelector(desc);\n    }\n    return desc;\n  }\n  function parseArgs(args_) {\n    var args = args_ || {};\n    var element, container, canvas, gl;\n    var contextAttributes = {};\n    var extensions = [];\n    var optionalExtensions = [];\n    var pixelRatio = typeof window === 'undefined' ? 1 : window.devicePixelRatio;\n    var profile = false;\n    var onDone = function onDone(err) {\n      if (err) {\n        check$1.raise(err);\n      }\n    };\n    var onDestroy = function onDestroy() {};\n    if (typeof args === 'string') {\n      check$1(typeof document !== 'undefined', 'selector queries only supported in DOM environments');\n      element = document.querySelector(args);\n      check$1(element, 'invalid query string for element');\n    } else if (typeof args === 'object') {\n      if (isHTMLElement(args)) {\n        element = args;\n      } else if (isWebGLContext(args)) {\n        gl = args;\n        canvas = gl.canvas;\n      } else {\n        check$1.constructor(args);\n        if ('gl' in args) {\n          gl = args.gl;\n        } else if ('canvas' in args) {\n          canvas = getElement(args.canvas);\n        } else if ('container' in args) {\n          container = getElement(args.container);\n        }\n        if ('attributes' in args) {\n          contextAttributes = args.attributes;\n          check$1.type(contextAttributes, 'object', 'invalid context attributes');\n        }\n        if ('extensions' in args) {\n          extensions = parseExtensions(args.extensions);\n        }\n        if ('optionalExtensions' in args) {\n          optionalExtensions = parseExtensions(args.optionalExtensions);\n        }\n        if ('onDone' in args) {\n          check$1.type(args.onDone, 'function', 'invalid or missing onDone callback');\n          onDone = args.onDone;\n        }\n        if ('profile' in args) {\n          profile = !!args.profile;\n        }\n        if ('pixelRatio' in args) {\n          pixelRatio = +args.pixelRatio;\n          check$1(pixelRatio > 0, 'invalid pixel ratio');\n        }\n      }\n    } else {\n      check$1.raise('invalid arguments to regl');\n    }\n    if (element) {\n      if (element.nodeName.toLowerCase() === 'canvas') {\n        canvas = element;\n      } else {\n        container = element;\n      }\n    }\n    if (!gl) {\n      if (!canvas) {\n        check$1(typeof document !== 'undefined', 'must manually specify webgl context outside of DOM environments');\n        var result = createCanvas(container || document.body, onDone, pixelRatio);\n        if (!result) {\n          return null;\n        }\n        canvas = result.canvas;\n        onDestroy = result.onDestroy;\n      }\n      // workaround for chromium bug, premultiplied alpha value is platform dependent\n      if (contextAttributes.premultipliedAlpha === undefined) contextAttributes.premultipliedAlpha = true;\n      gl = createContext(canvas, contextAttributes);\n    }\n    if (!gl) {\n      onDestroy();\n      onDone('webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org');\n      return null;\n    }\n    return {\n      gl: gl,\n      canvas: canvas,\n      container: container,\n      extensions: extensions,\n      optionalExtensions: optionalExtensions,\n      pixelRatio: pixelRatio,\n      profile: profile,\n      onDone: onDone,\n      onDestroy: onDestroy\n    };\n  }\n  function createExtensionCache(gl, config) {\n    var extensions = {};\n    function tryLoadExtension(name_) {\n      check$1.type(name_, 'string', 'extension name must be string');\n      var name = name_.toLowerCase();\n      var ext;
1\n      try {\n        ext = extensions[name] = gl.getExtension(name);\n      } catch (e) {}\n      return !!ext;\n    }\n    for (var i = 0; i < config.extensions.length; ++i) {\n      var name = config.extensions[i];\n      if (!tryLoadExtension(name)) {\n        config.onDestroy();\n        config.onDone('\"' + name + '\" extension is not supported by the current WebGL context, try upgrading your system or a different browser');\n        return null;\n      }\n    }\n    config.optionalExtensions.forEach(tryLoadExtension);\n    return {\n      extensions: extensions,\n      restore: function restore() {\n        Object.keys(extensions).forEach(function (name) {\n          if (extensions[name] && !tryLoadExtension(name)) {\n            throw new Error('(regl): error restoring extension ' + name);\n          }\n        });\n      }\n    };\n  }\n  function loop(n, f) {\n    var result = Array(n);\n    for (var i = 0; i < n; ++i) {\n      result[i] = f(i);\n    }\n    return result;\n  }\n  var GL_BYTE$1 = 5120;\n  var GL_UNSIGNED_BYTE$2 = 5121;\n  var GL_SHORT$1 = 5122;\n  var GL_UNSIGNED_SHORT$1 = 5123;\n  var GL_INT$1 = 5124;\n  var GL_UNSIGNED_INT$1 = 5125;\n  var GL_FLOAT$2 = 5126;\n  function nextPow16(v) {\n    for (var i = 16; i <= 1 << 28; i *= 16) {\n      if (v <= i) {\n        return i;\n      }\n    }\n    return 0;\n  }\n  function log2(v) {\n    var r, shift;\n    r = (v > 0xFFFF) << 4;\n    v >>>= r;\n    shift = (v > 0xFF) << 3;\n    v >>>= shift;\n    r |= shift;\n    shift = (v > 0xF) << 2;\n    v >>>= shift;\n    r |= shift;\n    shift = (v > 0x3) << 1;\n    v >>>= shift;\n    r |= shift;\n    return r | v >> 1;\n  }\n  function createPool() {\n    var bufferPool = loop(8, function () {\n      return [];\n    });\n    function alloc(n) {\n      var sz = nextPow16(n);\n      var bin = bufferPool[log2(sz) >> 2];\n      if (bin.length > 0) {\n        return bin.pop();\n      }\n      return new ArrayBuffer(sz);\n    }\n    function free(buf) {\n      bufferPool[log2(buf.byteLength) >> 2].push(buf);\n    }\n    function allocType(type, n) {\n      var result = null;\n      switch (type) {\n        case GL_BYTE$1:\n          result = new Int8Array(alloc(n), 0, n);\n          break;\n        case GL_UNSIGNED_BYTE$2:\n          result = new Uint8Array(alloc(n), 0, n);\n          break;\n        case GL_SHORT$1:\n          result = new Int16Array(alloc(2 * n), 0, n);\n          break;\n        case GL_UNSIGNED_SHORT$1:\n          result = new Uint16Array(alloc(2 * n), 0, n);\n          break;\n        case GL_INT$1:\n          result = new Int32Array(alloc(4 * n), 0, n);\n          break;\n        case GL_UNSIGNED_INT$1:\n          result = new Uint32Array(alloc(4 * n), 0, n);\n          break;\n        case GL_FLOAT$2:\n          result = new Float32Array(alloc(4 * n), 0, n);\n          break;\n        default:\n          return null;\n      }\n      if (result.length !== n) {\n        return result.subarray(0, n);\n      }\n      return result;\n    }\n    function freeType(array) {\n      free(array.buffer);\n    }\n    return {\n      alloc: alloc,\n      free: free,\n      allocType: allocType,\n      freeType: freeType\n    };\n  }\n  var pool = createPool();\n\n  // zero pool for initial zero data\n  pool.zero = createPool();\n  var GL_SUBPIXEL_BITS = 0x0D50;\n  var GL_RED_BITS = 0x0D52;\n  var GL_GREEN_BITS = 0x0D53;\n  var GL_BLUE_BITS = 0x0D54;\n  var GL_ALPHA_BITS = 0x0D55;\n  var GL_DEPTH_BITS = 0x0D56;\n  var GL_STENCIL_BITS = 0x0D57;\n  var GL_ALIASED_POINT_SIZE_RANGE = 0x846D;\n  var GL_ALIASED_LINE_WIDTH_RANGE = 0x846E;\n  var GL_MAX_TEXTURE_SIZE = 0x0D33;\n  var GL_MAX_VIEWPORT_DIMS = 0x0D3A;\n  var GL_MAX_VERTEX_ATTRIBS = 0x8869;\n  var GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;\n  var GL_MAX_VARYING_VECTORS = 0x8DFC;\n  var GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;\n  var GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;\n  var GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872;\n  var GL_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;\n  var GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;\n  var GL_MAX_RENDERBUFFER_SIZE = 0x84E8;\n  var GL_VENDOR = 0x1F00;\n  var GL_RENDERER = 0x1F01;\n  var GL_VERSION = 0x1F02;\n  var GL_SHADING_LANGUAGE_VERSION = 0x8B8C;\n  var GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;\n  var GL_MAX_COLOR_ATTACHMENTS_WEBGL = 0x8CDF;\n  var GL_MAX_DRAW_BUFFERS_WEBGL = 0x8824;\n  var GL_TEXTURE_2D = 0x0DE1;\n  var GL_TEXTURE_CUBE_MAP = 0x8513;\n  var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;\n  var GL_TEXTURE0 = 0x84C0;\n  var GL_RGBA = 0x1908;\n  var GL_FLOAT$1 = 0x1406;\n  var GL_UNSIGNED_BYTE$1 = 0x1401;\n  var GL_FRAMEBUFFER = 0x8D40;\n  var GL_FRAMEBUFFER_COMPLETE = 0x8CD5;\n  var GL_COLOR_ATTACHMENT0 = 0x8CE0;\n  var GL_COLOR_BUFFER_BIT$1 = 0x4000;\n  var wrapLimits = function wrapLimits(gl, extensions) {\n    var maxAnisotropic = 1;\n    if (extensions.ext_texture_filter_anisotropic) {\n      maxAnisotropic = gl.getParameter(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);\n    }\n    var maxDrawbuffers = 1;\n    var maxColorAttachments = 1;\n    if (extensions.webgl_draw_buffers) {\n      maxDrawbuffers = gl.getParameter(GL_MAX_DRAW_BUFFERS_WEBGL);\n      maxColorAttachments = gl.getParameter(GL_MAX_COLOR_ATTACHMENTS_WEBGL);\n    }\n\n    // detect if reading float textures is available (Safari doesn't support)\n    var readFloat = !!extensions.oes_texture_float;\n    if (readFloat) {\n      var readFloatTexture = gl.createTexture();\n      gl.bindTexture(GL_TEXTURE_2D, readFloatTexture);\n      gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT$1, null);\n      var fbo = gl.createFramebuffer();\n      gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);\n      gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readFloatTexture, 0);\n      gl.bindTexture(GL_TEXTURE_2D, null);\n      if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) !== GL_FRAMEBUFFER_COMPLETE) readFloat = false;else {\n        gl.viewport(0, 0, 1, 1);\n        gl.clearColor(1.0, 0.0, 0.0, 1.0);\n        gl.clear(GL_COLOR_BUFFER_BIT$1);\n        var pixels = pool.allocType(GL_FLOAT$1, 4);\n        gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT$1, pixels);\n        if (gl.getError()) readFloat = false;else {\n          gl.deleteFramebuffer(fbo);\n          gl.deleteTexture(readFloatTexture);\n          readFloat = pixels[0] === 1.0;\n        }\n        pool.freeType(pixels);\n      }\n    }\n\n    // detect non power of two cube textures support (IE doesn't support)\n    var isIE = typeof navigator !== 'undefined' && (/MSIE/.test(navigator.userAgent) || /Trident\\//.test(navigator.appVersion) || /Edge/.test(navigator.userAgent));\n    var npotTextureCube = true;\n    if (!isIE) {\n      var cubeTexture = gl.createTexture();\n      var data = pool.allocType(GL_UNSIGNED_BYTE$1, 36);\n      gl.activeTexture(GL_TEXTURE0);
1\n      gl.bindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture);\n      gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE$1, data);\n      pool.freeType(data);\n      gl.bindTexture(GL_TEXTURE_CUBE_MAP, null);\n      gl.deleteTexture(cubeTexture);\n      npotTextureCube = !gl.getError();\n    }\n    return {\n      // drawing buffer bit depth\n      colorBits: [gl.getParameter(GL_RED_BITS), gl.getParameter(GL_GREEN_BITS), gl.getParameter(GL_BLUE_BITS), gl.getParameter(GL_ALPHA_BITS)],\n      depthBits: gl.getParameter(GL_DEPTH_BITS),\n      stencilBits: gl.getParameter(GL_STENCIL_BITS),\n      subpixelBits: gl.getParameter(GL_SUBPIXEL_BITS),\n      // supported extensions\n      extensions: Object.keys(extensions).filter(function (ext) {\n        return !!extensions[ext];\n      }),\n      // max aniso samples\n      maxAnisotropic: maxAnisotropic,\n      // max draw buffers\n      maxDrawbuffers: maxDrawbuffers,\n      maxColorAttachments: maxColorAttachments,\n      // point and line size ranges\n      pointSizeDims: gl.getParameter(GL_ALIASED_POINT_SIZE_RANGE),\n      lineWidthDims: gl.getParameter(GL_ALIASED_LINE_WIDTH_RANGE),\n      maxViewportDims: gl.getParameter(GL_MAX_VIEWPORT_DIMS),\n      maxCombinedTextureUnits: gl.getParameter(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n      maxCubeMapSize: gl.getParameter(GL_MAX_CUBE_MAP_TEXTURE_SIZE),\n      maxRenderbufferSize: gl.getParameter(GL_MAX_RENDERBUFFER_SIZE),\n      maxTextureUnits: gl.getParameter(GL_MAX_TEXTURE_IMAGE_UNITS),\n      maxTextureSize: gl.getParameter(GL_MAX_TEXTURE_SIZE),\n      maxAttributes: gl.getParameter(GL_MAX_VERTEX_ATTRIBS),\n      maxVertexUniforms: gl.getParameter(GL_MAX_VERTEX_UNIFORM_VECTORS),\n      maxVertexTextureUnits: gl.getParameter(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS),\n      maxVaryingVectors: gl.getParameter(GL_MAX_VARYING_VECTORS),\n      maxFragmentUniforms: gl.getParameter(GL_MAX_FRAGMENT_UNIFORM_VECTORS),\n      // vendor info\n      glsl: gl.getParameter(GL_SHADING_LANGUAGE_VERSION),\n      renderer: gl.getParameter(GL_RENDERER),\n      vendor: gl.getParameter(GL_VENDOR),\n      version: gl.getParameter(GL_VERSION),\n      // quirks\n      readFloat: readFloat,\n      npotTextureCube: npotTextureCube\n    };\n  };\n  function isNDArrayLike(obj) {\n    return !!obj && typeof obj === 'object' && Array.isArray(obj.shape) && Array.isArray(obj.stride) && typeof obj.offset === 'number' && obj.shape.length === obj.stride.length && (Array.isArray(obj.data) || isTypedArray(obj.data));\n  }\n  var values = function values(obj) {\n    return Object.keys(obj).map(function (key) {\n      return obj[key];\n    });\n  };\n  var flattenUtils = {\n    shape: arrayShape$1,\n    flatten: flattenArray\n  };\n  function flatten1D(array, nx, out) {\n    for (var i = 0; i < nx; ++i) {\n      out[i] = array[i];\n    }\n  }\n  function flatten2D(array, nx, ny, out) {\n    var ptr = 0;\n    for (var i = 0; i < nx; ++i) {\n      var row = array[i];\n      for (var j = 0; j < ny; ++j) {\n        out[ptr++] = row[j];\n      }\n    }\n  }\n  function flatten3D(array, nx, ny, nz, out, ptr_) {\n    var ptr = ptr_;\n    for (var i = 0; i < nx; ++i) {\n      var row = array[i];\n      for (var j = 0; j < ny; ++j) {\n        var col = row[j];\n        for (var k = 0; k < nz; ++k) {\n          out[ptr++] = col[k];\n        }\n      }\n    }\n  }\n  function flattenRec(array, shape, level, out, ptr) {\n    var stride = 1;\n    for (var i = level + 1; i < shape.length; ++i) {\n      stride *= shape[i];\n    }\n    var n = shape[level];\n    if (shape.length - level === 4) {\n      var nx = shape[level + 1];\n      var ny = shape[level + 2];\n      var nz = shape[level + 3];\n      for (i = 0; i < n; ++i) {\n        flatten3D(array[i], nx, ny, nz, out, ptr);\n        ptr += stride;\n      }\n    } else {\n      for (i = 0; i < n; ++i) {\n        flattenRec(array[i], shape, level + 1, out, ptr);\n        ptr += stride;\n      }\n    }\n  }\n  function flattenArray(array, shape, type, out_) {\n    var sz = 1;\n    if (shape.length) {\n      for (var i = 0; i < shape.length; ++i) {\n        sz *= shape[i];\n      }\n    } else {\n      sz = 0;\n    }\n    var out = out_ || pool.allocType(type, sz);\n    switch (shape.length) {\n      case 0:\n        break;\n      case 1:\n        flatten1D(array, shape[0], out);\n        break;\n      case 2:\n        flatten2D(array, shape[0], shape[1], out);\n        break;\n      case 3:\n        flatten3D(array, shape[0], shape[1], shape[2], out, 0);\n        break;\n      default:\n        flattenRec(array, shape, 0, out, 0);\n    }\n    return out;\n  }\n  function arrayShape$1(array_) {\n    var shape = [];\n    for (var array = array_; array.length; array = array[0]) {\n      shape.push(array.length);\n    }\n    return shape;\n  }\n  var arrayTypes = {\n    \"[object Int8Array]\": 5120,\n    \"[object Int16Array]\": 5122,\n    \"[object Int32Array]\": 5124,\n    \"[object Uint8Array]\": 5121,\n    \"[object Uint8ClampedArray]\": 5121,\n    \"[object Uint16Array]\": 5123,\n    \"[object Uint32Array]\": 5125,\n    \"[object Float32Array]\": 5126,\n    \"[object Float64Array
1]\": 5121,\n    \"[object ArrayBuffer]\": 5121\n  };\n  var int8 = 5120;\n  var int16 = 5122;\n  var int32 = 5124;\n  var uint8 = 5121;\n  var uint16 = 5123;\n  var uint32 = 5125;\n  var float = 5126;\n  var float32 = 5126;\n  var glTypes = {\n    int8: int8,\n    int16: int16,\n    int32: int32,\n    uint8: uint8,\n    uint16: uint16,\n    uint32: uint32,\n    float: float,\n    float32: float32\n  };\n  var dynamic$1 = 35048;\n  var stream = 35040;\n  var usageTypes = {\n    dynamic: dynamic$1,\n    stream: stream,\n    \"static\": 35044\n  };\n  var arrayFlatten = flattenUtils.flatten;\n  var arrayShape = flattenUtils.shape;\n  var GL_STATIC_DRAW = 0x88E4;\n  var GL_STREAM_DRAW = 0x88E0;\n  var GL_UNSIGNED_BYTE$3 = 5121;\n  var GL_FLOAT$3 = 5126;\n  var DTYPES_SIZES = [];\n  DTYPES_SIZES[5120] = 1; // int8\n  DTYPES_SIZES[5122] = 2; // int16\n  DTYPES_SIZES[5124] = 4; // int32\n  DTYPES_SIZES[5121] = 1; // uint8\n  DTYPES_SIZES[5123] = 2; // uint16\n  DTYPES_SIZES[5125] = 4; // uint32\n  DTYPES_SIZES[5126] = 4; // float32\n\n  function typedArrayCode(data) {\n    return arrayTypes[Object.prototype.toString.call(data)] | 0;\n  }\n  function copyArray(out, inp) {\n    for (var i = 0; i < inp.length; ++i) {\n      out[i] = inp[i];\n    }\n  }\n  function transpose(result, data, shapeX, shapeY, strideX, strideY, offset) {\n    var ptr = 0;\n    for (var i = 0; i < shapeX; ++i) {\n      for (var j = 0; j < shapeY; ++j) {\n        result[ptr++] = data[strideX * i + strideY * j + offset];\n      }\n    }\n  }\n  function wrapBufferState(gl, stats, config, destroyBuffer) {\n    var bufferCount = 0;\n    var bufferSet = {};\n    function REGLBuffer(type) {\n      this.id = bufferCount++;\n      this.buffer = gl.createBuffer();\n      this.type = type;\n      this.usage = GL_STATIC_DRAW;\n      this.byteLength = 0;\n      this.dimension = 1;\n      this.dtype = GL_UNSIGNED_BYTE$3;\n      this.persistentData = null;\n      if (config.profile) {\n        this.stats = {\n          size: 0\n        };\n      }\n    }\n    REGLBuffer.prototype.bind = function () {\n      gl.bindBuffer(this.type, this.buffer);\n    };\n    REGLBuffer.prototype.destroy = function () {\n      destroy(this);\n    };\n    var streamPool = [];\n    function createStream(type, data) {\n      var buffer = streamPool.pop();\n      if (!buffer) {\n        buffer = new REGLBuffer(type);\n      }\n      buffer.bind();\n      initBufferFromData(buffer, data, GL_STREAM_DRAW, 0, 1, false);\n      return buffer;\n    }\n    function destroyStream(stream$$1) {\n      streamPool.push(stream$$1);\n    }\n    function initBufferFromTypedArray(buffer, data, usage) {\n      buffer.byteLength = data.byteLength;\n      gl.bufferData(buffer.type, data, usage);\n    }\n    function initBufferFromData(buffer, data, usage, dtype, dimension, persist) {\n      var shape;\n      buffer.usage = usage;\n      if (Array.isArray(data)) {\n        buffer.dtype = dtype || GL_FLOAT$3;\n        if (data.length > 0) {\n          var flatData;\n          if (Array.isArray(data[0])) {\n            shape = arrayShape(data);\n            var dim = 1;\n            for (var i = 1; i < shape.length; ++i) {\n              dim *= shape[i];\n            }\n            buffer.dimension = dim;\n            flatData = arrayFlatten(data, shape, buffer.dtype);\n            initBufferFromTypedArray(buffer, flatData, usage);\n            if (persist) {\n              buffer.persistentData = flatData;\n            } else {\n              pool.freeType(flatData);\n            }\n          } else if (typeof data[0] === 'number') {\n            buffer.dimension = dimension;\n            var typedData = pool.allocType(buffer.dtype, data.length);\n            copyArray(typedData, data);\n            initBufferFromTypedArray(buffer, typedData, usage);\n            if (persist) {\n              buffer.persistentData = typedData;\n            } else {\n              pool.freeType(typedData);\n            }\n          } else if (isTypedArray(data[0])) {\n            buffer.dimension = data[0].length;\n            buffer.dtype = dtype || typedArrayCode(data[0]) || GL_FLOAT$3;
1\n            flatData = arrayFlatten(data, [data.length, data[0].length], buffer.dtype);\n            initBufferFromTypedArray(buffer, flatData, usage);\n            if (persist) {\n              buffer.persistentData = flatData;\n            } else {\n              pool.freeType(flatData);\n            }\n          } else {\n            check$1.raise('invalid buffer data');\n          }\n        }\n      } else if (isTypedArray(data)) {\n        buffer.dtype = dtype || typedArrayCode(data);\n        buffer.dimension = dimension;\n        initBufferFromTypedArray(buffer, data, usage);\n        if (persist) {\n          buffer.persistentData = new Uint8Array(new Uint8Array(data.buffer));\n        }\n      } else if (isNDArrayLike(data)) {\n        shape = data.shape;\n        var stride = data.stride;\n        var offset = data.offset;\n        var shapeX = 0;\n        var shapeY = 0;\n        var strideX = 0;\n        var strideY = 0;\n        if (shape.length === 1) {\n          shapeX = shape[0];\n          shapeY = 1;\n          strideX = stride[0];\n          strideY = 0;\n        } else if (shape.length === 2) {\n          shapeX = shape[0];\n          shapeY = shape[1];\n          strideX = stride[0];\n          strideY = stride[1];\n        } else {\n          check$1.raise('invalid shape');\n        }\n        buffer.dtype = dtype || typedArrayCode(data.data) || GL_FLOAT$3;\n        buffer.dimension = shapeY;\n        var transposeData = pool.allocType(buffer.dtype, shapeX * shapeY);\n        transpose(transposeData, data.data, shapeX, shapeY, strideX, strideY, offset);\n        initBufferFromTypedArray(buffer, transposeData, usage);\n        if (persist) {\n          buffer.persistentData = transposeData;\n        } else {\n          pool.freeType(transposeData);\n        }\n      } else if (data instanceof ArrayBuffer) {\n        buffer.dtype = GL_UNSIGNED_BYTE$3;\n        buffer.dimension = dimension;\n        initBufferFromTypedArray(buffer, data, usage);\n        if (persist) {\n          buffer.persistentData = new Uint8Array(new Uint8Array(data));\n        }\n      } else {\n        check$1.raise('invalid buffer data');\n      }\n    }\n    function destroy(buffer) {\n      stats.bufferCount--;\n\n      // remove attribute link\n      destroyBuffer(buffer);\n      var handle = buffer.buffer;\n      check$1(handle, 'buffer must not be deleted already');\n      gl.deleteBuffer(handle);\n      buffer.buffer = null;\n      delete bufferSet[buffer.id];\n    }\n    function createBuffer(options, type, deferInit, persistent) {\n      stats.bufferCount++;\n      var buffer = new REGLBuffer(type);\n      bufferSet[buffer.id] = buffer;\n      function reglBuffer(options) {\n        var usage = GL_STATIC_DRAW;\n        var data = null;\n        var byteLength = 0;\n        var dtype = 0;\n        var dimension = 1;\n        if (Array.isArray(options) || isTypedArray(options) || isNDArrayLike(options) || options instanceof ArrayBuffer) {\n          data = options;\n        } else if (typeof options === 'number') {\n          byteLength = options | 0;\n        } else if (options) {\n          check$1.type(options, 'object', 'buffer arguments must be an object, a number or an array');\n          if ('data' in options) {\n            check$1(data === null || Array.isArray(data) || isTypedArray(data) || isNDArrayLike(data), 'invalid data for buffer');\n            data = options.data;\n          }\n          if ('usage' in options) {\n            check$1.parameter(options.usage, usageTypes, 'invalid buffer usage');\n            usage = usageTypes[options.usage];\n          }\n          if ('type' in options) {\n            check$1.parameter(options.type, glTypes, 'invalid buffer type');\n            dtype = glTypes[options.type];\n          }\n          if ('dimension' in options) {\n            check$1.type(options.dimension, 'number', 'invalid dimension');\n            dimension = options.dimension | 0;\n          }\n          if ('length' in options) {\n            check$1.nni(byteLength, 'buffer length must be a nonnegative integer');\n            byteLength = options.length | 0;\n          }\n        }\n        buffer.bind();
1\n        if (!data) {\n          // #475\n          if (byteLength) gl.bufferData(buffer.type, byteLength, usage);\n          buffer.dtype = dtype || GL_UNSIGNED_BYTE$3;\n          buffer.usage = usage;\n          buffer.dimension = dimension;\n          buffer.byteLength = byteLength;\n        } else {\n          initBufferFromData(buffer, data, usage, dtype, dimension, persistent);\n        }\n        if (config.profile) {\n          buffer.stats.size = buffer.byteLength * DTYPES_SIZES[buffer.dtype];\n        }\n        return reglBuffer;\n      }\n      function setSubData(data, offset) {\n        check$1(offset + data.byteLength <= buffer.byteLength, 'invalid buffer subdata call, buffer is too small. ' + ' Can\\'t write data of size ' + data.byteLength + ' starting from offset ' + offset + ' to a buffer of size ' + buffer.byteLength);\n        gl.bufferSubData(buffer.type, offset, data);\n      }\n      function subdata(data, offset_) {\n        var offset = (offset_ || 0) | 0;\n        var shape;\n        buffer.bind();\n        if (isTypedArray(data) || data instanceof ArrayBuffer) {\n          setSubData(data, offset);\n        } else if (Array.isArray(data)) {\n          if (data.length > 0) {\n            if (typeof data[0] === 'number') {\n              var converted = pool.allocType(buffer.dtype, data.length);\n              copyArray(converted, data);\n              setSubData(converted, offset);\n              pool.freeType(converted);\n            } else if (Array.isArray(data[0]) || isTypedArray(data[0])) {\n              shape = arrayShape(data);\n              var flatData = arrayFlatten(data, shape, buffer.dtype);\n              setSubData(flatData, offset);\n              pool.freeType(flatData);\n            } else {\n              check$1.raise('invalid buffer data');\n            }\n          }\n        } else if (isNDArrayLike(data)) {\n          shape = data.shape;\n          var stride = data.stride;\n          var shapeX = 0;\n          var shapeY = 0;\n          var strideX = 0;\n          var strideY = 0;\n          if (shape.length === 1) {\n            shapeX = shape[0];\n            shapeY = 1;\n            strideX = stride[0];\n            strideY = 0;\n          } else if (shape.length === 2) {\n            shapeX = shape[0];\n            shapeY = shape[1];\n            strideX = stride[0];\n            strideY = stride[1];\n          } else {\n            check$1.raise('invalid shape');\n          }\n          var dtype = Array.isArray(data.data) ? buffer.dtype : typedArrayCode(data.data);\n          var transposeData = pool.allocType(dtype, shapeX * shapeY);\n          transpose(transposeData, data.data, shapeX, shapeY, strideX, strideY, data.offset);\n          setSubData(transposeData, offset);\n          pool.freeType(transposeData);\n        } else {\n          check$1.raise('invalid data for buffer subdata');\n        }\n        return reglBuffer;\n      }\n      if (!deferInit) {\n        reglBuffer(options);\n      }\n      reglBuffer._reglType = 'buffer';\n      reglBuffer._buffer = buffer;\n      reglBuffer.subdata = subdata;\n      if (config.profile) {\n        reglBuffer.stats = buffer.stats;\n      }\n      reglBuffer.destroy = function () {\n        destroy(buffer);\n      };\n      return reglBuffer;\n    }\n    function restoreBuffers() {\n      values(bufferSet).forEach(function (buffer) {\n        buffer.buffer = gl.createBuffer();\n        gl.bindBuffer(buffer.type, buffer.buffer);\n        gl.bufferData(buffer.type, buffer.persistentData || buffer.byteLength, buffer.usage);\n      });\n    }\n    if (config.profile) {\n      stats.getTotalBufferSize = function () {\n        var total = 0;\n        // TODO: Right now, the streams are not part of the total count.\n        Object.keys(bufferSet).forEach(function (key) {\n          total += bufferSet[key].stats.size;\n        });\n        return total;\n      };\n    }\n    return {\n      create: createBuffer,\n      createStream: createStream,\n      destroyStream: destroyStream,\n      clear: function clear() {\n        values(bufferSet).forEach(destroy);\n        streamPool.forEach(destroy);\n      },\n      getBuffer: function getBuffer(wrapper) {\n        if (wrapper && wrapper._buffer instanceof REGLBuffer) {\n          return wrapper._buffer;\n        }\n        return null;\n      },\n      restore: restoreBuffers,\n      _initBuffer: initBufferFromData\n    };\n  }\n  var points = 0;\n  var point = 0;\n  var lines = 1;\n  var line = 1;\n  var triangles = 4;\n  var triangle = 4;\n  var primTypes = {\n    points: points,\n    point: point,\n    lines: lines,\n    line: line,\n    triangles: triangles,\n    triangle: triangle,\n    \"line loop\": 2,\n    \"line strip\": 3,\n    \"triangle str
1ip\": 5,\n    \"triangle fan\": 6\n  };\n  var GL_POINTS = 0;\n  var GL_LINES = 1;\n  var GL_TRIANGLES = 4;\n  var GL_BYTE$2 = 5120;\n  var GL_UNSIGNED_BYTE$4 = 5121;\n  var GL_SHORT$2 = 5122;\n  var GL_UNSIGNED_SHORT$2 = 5123;\n  var GL_INT$2 = 5124;\n  var GL_UNSIGNED_INT$2 = 5125;\n  var GL_ELEMENT_ARRAY_BUFFER = 34963;\n  var GL_STREAM_DRAW$1 = 0x88E0;\n  var GL_STATIC_DRAW$1 = 0x88E4;\n  function wrapElementsState(gl, extensions, bufferState, stats) {\n    var elementSet = {};\n    var elementCount = 0;\n    var elementTypes = {\n      'uint8': GL_UNSIGNED_BYTE$4,\n      'uint16': GL_UNSIGNED_SHORT$2\n    };\n    if (extensions.oes_element_index_uint) {\n      elementTypes.uint32 = GL_UNSIGNED_INT$2;\n    }\n    function REGLElementBuffer(buffer) {\n      this.id = elementCount++;\n      elementSet[this.id] = this;\n      this.buffer = buffer;\n      this.primType = GL_TRIANGLES;\n      this.vertCount = 0;\n      this.type = 0;\n    }\n    REGLElementBuffer.prototype.bind = function () {\n      this.buffer.bind();\n    };\n    var bufferPool = [];\n    function createElementStream(data) {\n      var result = bufferPool.pop();\n      if (!result) {\n        result = new REGLElementBuffer(bufferState.create(null, GL_ELEMENT_ARRAY_BUFFER, true, false)._buffer);\n      }\n      initElements(result, data, GL_STREAM_DRAW$1, -1, -1, 0, 0);\n      return result;\n    }\n    function destroyElementStream(elements) {\n      bufferPool.push(elements);\n    }\n    function initElements(elements, data, usage, prim, count, byteLength, type) {\n      elements.buffer.bind();\n      var dtype;\n      if (data) {\n        var predictedType = type;\n        if (!type && (!isTypedArray(data) || isNDArrayLike(data) && !isTypedArray(data.data))) {\n          predictedType = extensions.oes_element_index_uint ? GL_UNSIGNED_INT$2 : GL_UNSIGNED_SHORT$2;\n        }\n        bufferState._initBuffer(elements.buffer, data, usage, predictedType, 3);\n      } else {\n        gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, byteLength, usage);\n        elements.buffer.dtype = dtype || GL_UNSIGNED_BYTE$4;\n        elements.buffer.usage = usage;\n        elements.buffer.dimension = 3;\n        elements.buffer.byteLength = byteLength;\n      }\n      dtype = type;\n      if (!type) {\n        switch (elements.buffer.dtype) {\n          case GL_UNSIGNED_BYTE$4:\n          case GL_BYTE$2:\n            dtype = GL_UNSIGNED_BYTE$4;\n            break;\n          case GL_UNSIGNED_SHORT$2:\n          case GL_SHORT$2:\n            dtype = GL_UNSIGNED_SHORT$2;\n            break;\n          case GL_UNSIGNED_INT$2:\n          case GL_INT$2:\n            dtype = GL_UNSIGNED_INT$2;\n            break;\n          default:\n            check$1.raise('unsupported type for element array');\n        }\n        elements.buffer.dtype = dtype;\n      }\n      elements.type = dtype;\n\n      // Check oes_element_index_uint extension\n      check$1(dtype !== GL_UNSIGNED_INT$2 || !!extensions.oes_element_index_uint, '32 bit element buffers not supported, enable oes_element_index_uint first');\n\n      // try to guess default primitive type and arguments\n      var vertCount = count;\n      if (vertCount < 0) {\n        vertCount = elements.buffer.byteLength;\n        if (dtype === GL_UNSIGNED_SHORT$2) {\n          vertCount >>= 1;\n        } else if (dtype === GL_UNSIGNED_INT$2) {\n          vertCount >>= 2;\n        }\n      }\n      elements.vertCount = vertCount;\n\n      // try to guess primitive type from cell dimension\n      var primType = prim;\n      if (prim < 0) {\n        primType = GL_TRIANGLES;\n        var dimension = elements.buffer.dimension;\n        if (dimension === 1) primType = GL_POINTS;\n        if (dimension === 2) primType = GL_LINES;\n        if (dimension === 3) primType = GL_TRIANGLES;\n      }\n      elements.primType = primType;\n    }\n    function destroyElements(elements) {\n      stats.elementsCount--;\n      check$1(elements.buffer !== null, 'must not double destroy elements');\n      delete elementSet[elements.id];\n      elements.buffer.destroy();\n      elements.buffer = null;\n    }\n    function createElements(options, persistent) {\n      var buffer = bufferState.create(null, GL_ELEMENT_ARRAY_BUFFER, true);\n      var elements = new REGLElementBuffer(buffer._buffer);\n      stats.elementsCount++;\n      function reglElements(options) {\n        if (!options) {\n          buffer();\n          elements.primType = GL_TRIANGLES;\n          elements.vertCount = 0;\n          elements.type = GL_UNSIGNED_BYTE$4;\n        } else if (typeof options === 'number') {\n          buffer(options);\n          elements.primType = GL_TRIANGLES;\n          elements.vertCount = options | 0;\n          elements.type = GL_UNSIGNED_BYTE$4;\n        } else {\n          var data = null;\n          var usage = GL_STATIC_DRAW$1;\n          var primType = -1;\n          var vertCount = -1;\n          var byteLength = 0;\n          var dtype = 0;\n          if (Array.isArray(options) || isTypedArray(options) || isNDArrayLike(options)) {\n            data = options;\n          } else {\n            check$1.type(options, 'object', 'invalid arguments for elements');\n            if ('data' in options) {\n              data = options.data;\n              check$1(Array.isArray(data) || isTypedArray(data) || isNDArrayLike(data), 'invalid data for element buffer');\n            }\n            if ('usage' in options) {\n              check$1.parameter(options.usage, usageTypes, 'invalid element buffer usage');\n              usage = usageTypes[options.usage];\n            }\n            if ('primitive' in options) {\n              check$1.parameter(options.primitive, primTypes, 'invalid element buffer primitive');\n              primType = primTypes[options.primitive];\n            }
1\n            if ('count' in options) {\n              check$1(typeof options.count === 'number' && options.count >= 0, 'invalid vertex count for elements');\n              vertCount = options.count | 0;\n            }\n            if ('type' in options) {\n              check$1.parameter(options.type, elementTypes, 'invalid buffer type');\n              dtype = elementTypes[options.type];\n            }\n            if ('length' in options) {\n              byteLength = options.length | 0;\n            } else {\n              byteLength = vertCount;\n              if (dtype === GL_UNSIGNED_SHORT$2 || dtype === GL_SHORT$2) {\n                byteLength *= 2;\n              } else if (dtype === GL_UNSIGNED_INT$2 || dtype === GL_INT$2) {\n                byteLength *= 4;\n              }\n            }\n          }\n          initElements(elements, data, usage, primType, vertCount, byteLength, dtype);\n        }\n        return reglElements;\n      }\n      reglElements(options);\n      reglElements._reglType = 'elements';\n      reglElements._elements = elements;\n      reglElements.subdata = function (data, offset) {\n        buffer.subdata(data, offset);\n        return reglElements;\n      };\n      reglElements.destroy = function () {\n        destroyElements(elements);\n      };\n      return reglElements;\n    }\n    return {\n      create: createElements,\n      createStream: createElementStream,\n      destroyStream: destroyElementStream,\n      getElements: function getElements(elements) {\n        if (typeof elements === 'function' && elements._elements instanceof REGLElementBuffer) {\n          return elements._elements;\n        }\n        return null;\n      },\n      clear: function clear() {\n        values(elementSet).forEach(destroyElements);\n      }\n    };\n  }\n  var FLOAT = new Float32Array(1);\n  var INT = new Uint32Array(FLOAT.buffer);\n  var GL_UNSIGNED_SHORT$4 = 5123;\n  function convertToHalfFloat(array) {\n    var ushorts = pool.allocType(GL_UNSIGNED_SHORT$4, array.length);\n    for (var i = 0; i < array.length; ++i) {\n      if (isNaN(array[i])) {\n        ushorts[i] = 0xffff;\n      } else if (array[i] === Infinity) {\n        ushorts[i] = 0x7c00;\n      } else if (array[i] === -Infinity) {\n        ushorts[i] = 0xfc00;\n      } else {\n        FLOAT[0] = array[i];\n        var x = INT[0];\n        var sgn = x >>> 31 << 15;\n        var exp = (x << 1 >>> 24) - 127;\n        var frac = x >> 13 & (1 << 10) - 1;\n        if (exp < -24) {\n          // round non-representable denormals to 0\n          ushorts[i] = sgn;\n        } else if (exp < -14) {\n          // handle denormals\n          var s = -14 - exp;\n          ushorts[i] = sgn + (frac + (1 << 10) >> s);\n        } else if (exp > 15) {\n          // round overflow to +/- Infinity\n          ushorts[i] = sgn + 0x7c00;\n        } else {\n          // otherwise convert directly\n          ushorts[i] = sgn + (exp + 15 << 10) + frac;\n        }\n      }\n    }\n    return ushorts;\n  }\n  function isArrayLike(s) {\n    return Array.isArray(s) || isTypedArray(s);\n  }\n  var isPow2$1 = function isPow2$1(v) {\n    return !(v & v - 1) && !!v;\n  };\n  var GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3;\n  var GL_TEXTURE_2D$1 = 0x0DE1;\n  var GL_TEXTURE_CUBE_MAP$1 = 0x8513;\n  var GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 = 0x8515;\n  var GL_RGBA$1 = 0x1908;\n  var GL_ALPHA = 0x1906;\n  var GL_RGB = 0x1907;\n  var GL_LUMINANCE = 0x1909;\n  var GL_LUMINANCE_ALPHA = 0x190A;\n  var GL_RGBA4 = 0x8056;\n  var GL_RGB5_A1 = 0x8057;\n  var GL_RGB565 = 0x8D62;\n  var GL_UNSIGNED_SHORT_4_4_4_4$1 = 0x8033;\n  var GL_UNSIGNED_SHORT_5_5_5_1$1 = 0x8034;\n  var GL_UNSIGNED_SHORT_5_6_5$1 = 0x8363;\n  var GL_UNSIGNED_INT_24_8_WEBGL$1 = 0x84FA;\n  var GL_DEPTH_COMPONENT = 0x1902;\n  var GL_DEPTH_STENCIL = 0x84F9;\n  var GL_SRGB_EXT = 0x8C40;\n  var GL_SRGB_ALPHA_EXT = 0x8C42;\n  var GL_HALF_FLOAT_OES$1 = 0x8D61;\n  var GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;\n  var GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;\n  var GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;\n  var GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;\n  var GL_COMPRESSED_RGB_ATC_WEBGL = 0x8C92;\n  var GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;\n  var GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;\n  var GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;\n  var GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;\n  var GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;\n  var GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;\n  var GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64;\n  var GL_UNSIGNED_BYTE$5 = 0x1401;\n  var GL_UNSIGNED_SHORT$3 = 0x1403;\n  var GL_UNSIGNED_INT$3 = 0x1405;\n  var GL_FLOAT$4 = 0x1406;\n  var GL_TEXTURE_WRAP_S = 0x2802;
1\n  var GL_TEXTURE_WRAP_T = 0x2803;\n  var GL_REPEAT = 0x2901;\n  var GL_CLAMP_TO_EDGE$1 = 0x812F;\n  var GL_MIRRORED_REPEAT = 0x8370;\n  var GL_TEXTURE_MAG_FILTER = 0x2800;\n  var GL_TEXTURE_MIN_FILTER = 0x2801;\n  var GL_NEAREST$1 = 0x2600;\n  var GL_LINEAR = 0x2601;\n  var GL_NEAREST_MIPMAP_NEAREST$1 = 0x2700;\n  var GL_LINEAR_MIPMAP_NEAREST$1 = 0x2701;\n  var GL_NEAREST_MIPMAP_LINEAR$1 = 0x2702;\n  var GL_LINEAR_MIPMAP_LINEAR$1 = 0x2703;\n  var GL_GENERATE_MIPMAP_HINT = 0x8192;\n  var GL_DONT_CARE = 0x1100;\n  var GL_FASTEST = 0x1101;\n  var GL_NICEST = 0x1102;\n  var GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;\n  var GL_UNPACK_ALIGNMENT = 0x0CF5;\n  var GL_UNPACK_FLIP_Y_WEBGL = 0x9240;\n  var GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;\n  var GL_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;\n  var GL_BROWSER_DEFAULT_WEBGL = 0x9244;\n  var GL_TEXTURE0$1 = 0x84C0;\n  var MIPMAP_FILTERS = [GL_NEAREST_MIPMAP_NEAREST$1, GL_NEAREST_MIPMAP_LINEAR$1, GL_LINEAR_MIPMAP_NEAREST$1, GL_LINEAR_MIPMAP_LINEAR$1];\n  var CHANNELS_FORMAT = [0, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA$1];\n  var FORMAT_CHANNELS = {};\n  FORMAT_CHANNELS[GL_LUMINANCE] = FORMAT_CHANNELS[GL_ALPHA] = FORMAT_CHANNELS[GL_DEPTH_COMPONENT] = 1;\n  FORMAT_CHANNELS[GL_DEPTH_STENCIL] = FORMAT_CHANNELS[GL_LUMINANCE_ALPHA] = 2;\n  FORMAT_CHANNELS[GL_RGB] = FORMAT_CHANNELS[GL_SRGB_EXT] = 3;\n  FORMAT_CHANNELS[GL_RGBA$1] = FORMAT_CHANNELS[GL_SRGB_ALPHA_EXT] = 4;\n  function objectName(str) {\n    return '[object ' + str + ']';\n  }\n  var CANVAS_CLASS = objectName('HTMLCanvasElement');\n  var OFFSCREENCANVAS_CLASS = objectName('OffscreenCanvas');\n  var CONTEXT2D_CLASS = objectName('CanvasRenderingContext2D');\n  var BITMAP_CLASS = objectName('ImageBitmap');\n  var IMAGE_CLASS = objectName('HTMLImageElement');\n  var VIDEO_CLASS = objectName('HTMLVideoElement');\n  var PIXEL_CLASSES = Object.keys(arrayTypes).concat([CANVAS_CLASS, OFFSCREENCANVAS_CLASS, CONTEXT2D_CLASS, BITMAP_CLASS, IMAGE_CLASS, VIDEO_CLASS]);\n\n  // for every texture type, store\n  // the size in bytes.\n  var TYPE_SIZES = [];\n  TYPE_SIZES[GL_UNSIGNED_BYTE$5] = 1;\n  TYPE_SIZES[GL_FLOAT$4] = 4;\n  TYPE_SIZES[GL_HALF_FLOAT_OES$1] = 2;\n  TYPE_SIZES[GL_UNSIGNED_SHORT$3] = 2;\n  TYPE_SIZES[GL_UNSIGNED_INT$3] = 4;\n  var FORMAT_SIZES_SPECIAL = [];\n  FORMAT_SIZES_SPECIAL[GL_RGBA4] = 2;\n  FORMAT_SIZES_SPECIAL[GL_RGB5_A1] = 2;\n  FORMAT_SIZES_SPECIAL[GL_RGB565] = 2;\n  FORMAT_SIZES_SPECIAL[GL_DEPTH_STENCIL] = 4;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_S3TC_DXT1_EXT] = 0.5;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT1_EXT] = 0.5;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT3_EXT] = 1;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT5_EXT] = 1;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ATC_WEBGL] = 0.5;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL] = 1;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL] = 1;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG] = 0.5;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG] = 0.25;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG] = 0.5;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG] = 0.25;\n  FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ETC1_WEBGL] = 0.5;\n  function isNumericArray(arr) {\n    return Array.isArray(arr) && (arr.length === 0 || typeof arr[0] === 'number');\n  }\n  function isRectArray(arr) {\n    if (!Array.isArray(arr)) {\n      return false;\n    }\n    var width = arr.length;\n    if (width === 0 || !isArrayLike(arr[0])) {\n      return false;\n    }\n    return true;\n  }\n  function classString(x) {\n    return Object.prototype.toString.call(x);\n  }\n  function isCanvasElement(object) {\n    return classString(object) === CANVAS_CLASS;\n  }\n  function isOffscreenCanvas(object) {\n    return classString(object) === OFFSCREENCANVAS_CLASS;\n  }\n  function isContext2D(object) {\n    return classString(object) === CONTEXT2D_CLASS;\n  }\n  function isBitmap(object) {\n    return classString(object) === BITMAP_CLASS;\n  }\n  function isImageElement(object) {\n    return classString(object) === IMAGE_CLASS;\n  }\n  function isVideoElement(object) {\n    return classString(object) === VIDEO_CLASS;\n  }\n  function isPixelData(object) {\n    if (!object) {\n      return false;\n    }\n    var className = classString(object);\n    if (PIXEL_CLASSES.indexOf(className) >= 0) {\n      return true;\n    }\n    return isNumericArray(object) || isRectArray(object) || isNDArrayLike(object);\n  }
1\n  function typedArrayCode$1(data) {\n    return arrayTypes[Object.prototype.toString.call(data)] | 0;\n  }\n  function convertData(result, data) {\n    var n = data.length;\n    switch (result.type) {\n      case GL_UNSIGNED_BYTE$5:\n      case GL_UNSIGNED_SHORT$3:\n      case GL_UNSIGNED_INT$3:\n      case GL_FLOAT$4:\n        var converted = pool.allocType(result.type, n);\n        converted.set(data);\n        result.data = converted;\n        break;\n      case GL_HALF_FLOAT_OES$1:\n        result.data = convertToHalfFloat(data);\n        break;\n      default:\n        check$1.raise('unsupported texture type, must specify a typed array');\n    }\n  }\n  function preConvert(image, n) {\n    return pool.allocType(image.type === GL_HALF_FLOAT_OES$1 ? GL_FLOAT$4 : image.type, n);\n  }\n  function postConvert(image, data) {\n    if (image.type === GL_HALF_FLOAT_OES$1) {\n      image.data = convertToHalfFloat(data);\n      pool.freeType(data);\n    } else {\n      image.data = data;\n    }\n  }\n  function transposeData(image, array, strideX, strideY, strideC, offset) {\n    var w = image.width;\n    var h = image.height;\n    var c = image.channels;\n    var n = w * h * c;\n    var data = preConvert(image, n);\n    var p = 0;\n    for (var i = 0; i < h; ++i) {\n      for (var j = 0; j < w; ++j) {\n        for (var k = 0; k < c; ++k) {\n          data[p++] = array[strideX * j + strideY * i + strideC * k + offset];\n        }\n      }\n    }\n    postConvert(image, data);\n  }\n  function getTextureSize(format, type, width, height, isMipmap, isCube) {\n    var s;\n    if (typeof FORMAT_SIZES_SPECIAL[format] !== 'undefined') {\n      // we have a special array for dealing with weird color formats such as RGB5A1\n      s = FORMAT_SIZES_SPECIAL[format];\n    } else {\n      s = FORMAT_CHANNELS[format] * TYPE_SIZES[type];\n    }\n    if (isCube) {\n      s *= 6;\n    }\n    if (isMipmap) {\n      // compute the total size of all the mipmaps.\n      var total = 0;\n      var w = width;\n      while (w >= 1) {\n        // we can only use mipmaps on a square image,\n        // so we can simply use the width and ignore the height:\n        total += s * w * w;\n        w /= 2;\n      }\n      return total;\n    } else {\n      return s * width * height;\n    }\n  }\n  function createTextureSet(gl, extensions, limits, reglPoll, contextState, stats, config) {\n    // -------------------------------------------------------\n    // Initialize constants and parameter tables here\n    // -------------------------------------------------------\n    var mipmapHint = {\n      \"don't care\": GL_DONT_CARE,\n      'dont care': GL_DONT_CARE,\n      'nice': GL_NICEST,\n      'fast': GL_FASTEST\n    };\n    var wrapModes = {\n      'repeat': GL_REPEAT,\n      'clamp': GL_CLAMP_TO_EDGE$1,\n      'mirror': GL_MIRRORED_REPEAT\n    };\n    var magFilters = {\n      'nearest': GL_NEAREST$1,\n      'linear': GL_LINEAR\n    };\n    var minFilters = extend({\n      'mipmap': GL_LINEAR_MIPMAP_LINEAR$1,\n      'nearest mipmap nearest': GL_NEAREST_MIPMAP_NEAREST$1,\n      'linear mipmap nearest': GL_LINEAR_MIPMAP_NEAREST$1,\n      'nearest mipmap linear': GL_NEAREST_MIPMAP_LINEAR$1,\n      'linear mipmap linear': GL_LINEAR_MIPMAP_LINEAR$1\n    }, magFilters);\n    var colorSpace = {\n      'none': 0,\n      'browser': GL_BROWSER_DEFAULT_WEBGL\n    };\n    var textureTypes = {\n      'uint8': GL_UNSIGNED_BYTE$5,\n      'rgba4': GL_UNSIGNED_SHORT_4_4_4_4$1,\n      'rgb565': GL_UNSIGNED_SHORT_5_6_5$1,\n      'rgb5 a1': GL_UNSIGNED_SHORT_5_5_5_1$1\n    };\n    var textureFormats = {\n      'alpha': GL_ALPHA,\n      'luminance': GL_LUMINANCE,\n      'luminance alpha': GL_LUMINANCE_ALPHA,\n      'rgb': GL_RGB,\n      'rgba': GL_RGBA$1,\n      'rgba4': GL_RGBA4,\n      'rgb5 a1': GL_RGB5_A1,\n      'rgb565': GL_RGB565\n    };\n    var compressedTextureFormats = {};\n    if (extensions.ext_srgb) {\n      textureFormats.srgb = GL_SRGB_EXT;\n      textureFormats.srgba = GL_SRGB_ALPHA_EXT;\n    }\n    if (extensions.oes_texture_float) {\n      textureTypes.float32 = textureTypes.float = GL_FLOAT$4;\n    }\n    if (extensions.oes_texture_half_float) {\n      textureTypes['float16'] = textureTypes['half float'] = GL_HALF_FLOAT_OES$1;\n    }\n    if (extensions.webgl_depth_texture) {\n      extend(textureFormats, {\n        'depth': G
1L_DEPTH_COMPONENT,\n        'depth stencil': GL_DEPTH_STENCIL\n      });\n      extend(textureTypes, {\n        'uint16': GL_UNSIGNED_SHORT$3,\n        'uint32': GL_UNSIGNED_INT$3,\n        'depth stencil': GL_UNSIGNED_INT_24_8_WEBGL$1\n      });\n    }\n    if (extensions.webgl_compressed_texture_s3tc) {\n      extend(compressedTextureFormats, {\n        'rgb s3tc dxt1': GL_COMPRESSED_RGB_S3TC_DXT1_EXT,\n        'rgba s3tc dxt1': GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,\n        'rgba s3tc dxt3': GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,\n        'rgba s3tc dxt5': GL_COMPRESSED_RGBA_S3TC_DXT5_EXT\n      });\n    }\n    if (extensions.webgl_compressed_texture_atc) {\n      extend(compressedTextureFormats, {\n        'rgb atc': GL_COMPRESSED_RGB_ATC_WEBGL,\n        'rgba atc explicit alpha': GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL,\n        'rgba atc interpolated alpha': GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL\n      });\n    }\n    if (extensions.webgl_compressed_texture_pvrtc) {\n      extend(compressedTextureFormats, {\n        'rgb pvrtc 4bppv1': GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,\n        'rgb pvrtc 2bppv1': GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,\n        'rgba pvrtc 4bppv1': GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\n        'rgba pvrtc 2bppv1': GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG\n      });\n    }\n    if (extensions.webgl_compressed_texture_etc1) {\n      compressedTextureFormats['rgb etc1'] = GL_COMPRESSED_RGB_ETC1_WEBGL;\n    }\n\n    // Copy over all texture formats\n    var supportedCompressedFormats = Array.prototype.slice.call(gl.getParameter(GL_COMPRESSED_TEXTURE_FORMATS));\n    Object.keys(compressedTextureFormats).forEach(function (name) {\n      var format = compressedTextureFormats[name];\n      if (supportedCompressedFormats.indexOf(format) >= 0) {\n        textureFormats[name] = format;\n      }\n    });\n    var supportedFormats = Object.keys(textureFormats);\n    limits.textureFormats = supportedFormats;\n\n    // associate with every format string its\n    // corresponding GL-value.\n    var textureFormatsInvert = [];\n    Object.keys(textureFormats).forEach(function (key) {\n      var val = textureFormats[key];\n      textureFormatsInvert[val] = key;\n    });\n\n    // associate with every type string its\n    // corresponding GL-value.\n    var textureTypesInvert = [];\n    Object.keys(textureTypes).forEach(function (key) {\n      var val = textureTypes[key];\n      textureTypesInvert[val] = key;\n    });\n    var magFiltersInvert = [];\n    Object.keys(magFilters).forEach(function (key) {\n      var val = magFilters[key];\n      magFiltersInvert[val] = key;\n    });\n    var minFiltersInvert = [];\n    Object.keys(minFilters).forEach(function (key) {\n      var val = minFilters[key];\n      minFiltersInvert[val] = key;\n    });\n    var wrapModesInvert = [];\n    Object.keys(wrapModes).forEach(function (key) {\n      var val = wrapModes[key];\n      wrapModesInvert[val] = key;\n    });\n\n    // colorFormats[] gives the format (channels) associated to an\n    // internalformat\n    var colorFormats = supportedFormats.reduce(function (color, key) {\n      var glenum = textureFormats[key];\n      if (glenum === GL_LUMINANCE || glenum === GL_ALPHA || glenum === GL_LUMINANCE || glenum === GL_LUMINANCE_ALPHA || glenum === GL_DEPTH_COMPONENT || glenum === GL_DEPTH_STENCIL || extensions.ext_srgb && (glenum === GL_SRGB_EXT || glenum === GL_SRGB_ALPHA_EXT)) {\n        color[glenum] = glenum;\n      } else if (glenum === GL_RGB5_A1 || key.indexOf('rgba') >= 0) {\n        color[glenum] = GL_RGBA$1;\n      } else {\n        color[glenum] = GL_RGB;\n      }\n      return color;\n    }, {});\n    function TexFlags() {\n      // format info\n      this.internalformat = GL_RGBA$1;\n      this.format = GL_RGBA$1;\n      this.type = GL_UNSIGNED_BYTE$5;\n      this.compressed = false;\n\n      // pixel storage\n      this.premultiplyAlpha = false;\n      this.flipY = false;\n      this.unpackAlignment = 1;\n      this.colorSpace = GL_BROWSER_DEFAULT_WEBGL;\n\n      // shape info\n      this.width = 0;\n      this.height = 0;\n      this.channels = 0;\n    }\n    function copyFlags(result, other) {\n      result.internalformat = other.internalformat;\n      result.format = other.format;\n      result.type = other.type;\n      result.compressed = other.compressed;\n      result.premultiplyAlpha = other.premultiplyAlpha;\n      result.flipY = other.flipY;\n      result.unpackAlignment = other.unpackAlignment;\n      result.colorSpace = other.colorSpace;\n      result.width = other.width;\n      result.height = other.height;\n      result.channels = other.channels;\n    }\n    function parseFlags(flags, options) {\n      if (typeof options !== 'object' || !options) {\n        return;\n      }\n      if ('premultiplyAlpha' in options) {\n        check$1.type(options.premultiplyAlpha, 'boolean', 'invalid premultiplyAlpha');\n        flags.premultiplyAlpha = options.premultiplyAlpha;\n      }\n      if ('flipY' in options) {\n        check$1.type(options.flipY, 'boolean', 'invalid texture flip');\n        flags.flipY = options.flipY;\n      }\n      if ('alignment' in options) {\n        check$1.oneOf(options.alignment, [1, 2, 4, 8], 'invalid texture unpack alignment');\n        flags.unpackAlignment = options.alignment;\n      }
1\n      if ('colorSpace' in options) {\n        check$1.parameter(options.colorSpace, colorSpace, 'invalid colorSpace');\n        flags.colorSpace = colorSpace[options.colorSpace];\n      }\n      if ('type' in options) {\n        var type = options.type;\n        check$1(extensions.oes_texture_float || !(type === 'float' || type === 'float32'), 'you must enable the OES_texture_float extension in order to use floating point textures.');\n        check$1(extensions.oes_texture_half_float || !(type === 'half float' || type === 'float16'), 'you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures.');\n        check$1(extensions.webgl_depth_texture || !(type === 'uint16' || type === 'uint32' || type === 'depth stencil'), 'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.');\n        check$1.parameter(type, textureTypes, 'invalid texture type');\n        flags.type = textureTypes[type];\n      }\n      var w = flags.width;\n      var h = flags.height;\n      var c = flags.channels;\n      var hasChannels = false;\n      if ('shape' in options) {\n        check$1(Array.isArray(options.shape) && options.shape.length >= 2, 'shape must be an array');\n        w = options.shape[0];\n        h = options.shape[1];\n        if (options.shape.length === 3) {\n          c = options.shape[2];\n          check$1(c > 0 && c <= 4, 'invalid number of channels');\n          hasChannels = true;\n        }\n        check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid width');\n        check$1(h >= 0 && h <= limits.maxTextureSize, 'invalid height');\n      } else {\n        if ('radius' in options) {\n          w = h = options.radius;\n          check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid radius');\n        }\n        if ('width' in options) {\n          w = options.width;\n          check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid width');\n        }\n        if ('height' in options) {\n          h = options.height;\n          check$1(h >= 0 && h <= limits.maxTextureSize, 'invalid height');\n        }\n        if ('channels' in options) {\n          c = options.channels;\n          check$1(c > 0 && c <= 4, 'invalid number of channels');\n          hasChannels = true;\n        }\n      }\n      flags.width = w | 0;\n      flags.height = h | 0;\n      flags.channels = c | 0;\n      var hasFormat = false;\n      if ('format' in options) {\n        var formatStr = options.format;\n        check$1(extensions.webgl_depth_texture || !(formatStr === 'depth' || formatStr === 'depth stencil'), 'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.');\n        check$1.parameter(formatStr, textureFormats, 'invalid texture format');\n        var internalformat = flags.internalformat = textureFormats[formatStr];\n        flags.format = colorFormats[internalformat];\n        if (formatStr in textureTypes) {\n          if (!('type' in options)) {\n            flags.type = textureTypes[formatStr];\n          }\n        }\n        if (formatStr in compressedTextureFormats) {\n          flags.compressed = true;\n        }\n        hasFormat = true;\n      }\n\n      // Reconcile channels and format\n      if (!hasChannels && hasFormat) {\n        flags.channels = FORMAT_CHANNELS[flags.format];\n      } else if (hasChannels && !hasFormat) {\n        if (flags.channels !== CHANNELS_FORMAT[flags.format]) {\n          flags.format = flags.internalformat = CHANNELS_FORMAT[flags.channels];\n        }\n      } else if (hasFormat && hasChannels) {\n        check$1(flags.channels === FORMAT_CHANNELS[flags.format], 'number of channels inconsistent with specified format');\n      }\n    }\n    function setFlags(flags) {\n      gl.pixelStorei(GL_UNPACK_FLIP_Y_WEBGL, flags.flipY);\n      gl.pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL, flags.premultiplyAlpha);\n      gl.pixelStorei(GL_UNPACK_COLORSPACE_CONVERSION_WEBGL, flags.colorSpace);\n      gl.pixelStorei(GL_UNPACK_ALIGNMENT, flags.unpackAlignment);\n    }\n\n    // -------------------------------------------------------\n    // Tex image data\n    // -------------------------------------------------------\n    function TexImage() {\n      TexFlags.call(this);\n      this.xOffset = 0;\n      this.yOffset = 0;\n\n      // data\n      this.data = null;\n      this.needsFree = false;\n\n      // html element\n      this.element = null;\n\n      // copyTexImage info\n      this.needsCopy = false;\n    }\n    function parseImage(image, options) {\n      var data = null;\n      if (isPixelData(options)) {\n        data = options;\n      } else if (options) {\n        check$1.type(options, 'object', 'invalid pixel data type');\n        parseFlags(image, options);\n        if ('x' in options) {\n          image.xOffset = options.x | 0;\n        }
1\n        if ('y' in options) {\n          image.yOffset = options.y | 0;\n        }\n        if (isPixelData(options.data)) {\n          data = options.data;\n        }\n      }\n      check$1(!image.compressed || data instanceof Uint8Array, 'compressed texture data must be stored in a uint8array');\n      if (options.copy) {\n        check$1(!data, 'can not specify copy and data field for the same texture');\n        var viewW = contextState.viewportWidth;\n        var viewH = contextState.viewportHeight;\n        image.width = image.width || viewW - image.xOffset;\n        image.height = image.height || viewH - image.yOffset;\n        image.needsCopy = true;\n        check$1(image.xOffset >= 0 && image.xOffset < viewW && image.yOffset >= 0 && image.yOffset < viewH && image.width > 0 && image.width <= viewW && image.height > 0 && image.height <= viewH, 'copy texture read out of bounds');\n      } else if (!data) {\n        image.width = image.width || 1;\n        image.height = image.height || 1;\n        image.channels = image.channels || 4;\n      } else if (isTypedArray(data)) {\n        image.channels = image.channels || 4;\n        image.data = data;\n        if (!('type' in options) && image.type === GL_UNSIGNED_BYTE$5) {\n          image.type = typedArrayCode$1(data);\n        }\n      } else if (isNumericArray(data)) {\n        image.channels = image.channels || 4;\n        convertData(image, data);\n        image.alignment = 1;\n        image.needsFree = true;\n      } else if (isNDArrayLike(data)) {\n        var array = data.data;\n        if (!Array.isArray(array) && image.type === GL_UNSIGNED_BYTE$5) {\n          image.type = typedArrayCode$1(array);\n        }\n        var shape = data.shape;\n        var stride = data.stride;\n        var shapeX, shapeY, shapeC, strideX, strideY, strideC;\n        if (shape.length === 3) {\n          shapeC = shape[2];\n          strideC = stride[2];\n        } else {\n          check$1(shape.length === 2, 'invalid ndarray pixel data, must be 2 or 3D');\n          shapeC = 1;\n          strideC = 1;\n        }\n        shapeX = shape[0];\n        shapeY = shape[1];\n        strideX = stride[0];\n        strideY = stride[1];\n        image.alignment = 1;\n        image.width = shapeX;\n        image.height = shapeY;\n        image.channels = shapeC;\n        image.format = image.internalformat = CHANNELS_FORMAT[shapeC];\n        image.needsFree = true;\n        transposeData(image, array, strideX, strideY, strideC, data.offset);\n      } else if (isCanvasElement(data) || isOffscreenCanvas(data) || isContext2D(data)) {\n        if (isCanvasElement(data) || isOffscreenCanvas(data)) {\n          image.element = data;\n        } else {\n          image.element = data.canvas;\n        }\n        image.width = image.element.width;\n        image.height = image.element.height;\n        image.channels = 4;\n      } else if (isBitmap(data)) {\n        image.element = data;\n        image.width = data.width;\n        image.height = data.height;\n        image.channels = 4;\n      } else if (isImageElement(data)) {\n        image.element = data;\n        image.width = data.naturalWidth;\n        image.height = data.naturalHeight;\n        image.channels = 4;\n      } else if (isVideoElement(data)) {\n        image.element = data;\n        image.width = data.videoWidth;\n        image.height = data.videoHeight;\n        image.channels = 4;\n      } else if (isRectArray(data)) {\n        var w = image.width || data[0].length;\n        var h = image.height || data.length;\n        var c = image.channels;\n        if (isArrayLike(data[0][0])) {\n          c = c || data[0][0].length;\n        } else {\n          c = c || 1;\n        }\n        var arrayShape = flattenUtils.shape(data);\n        var n = 1;\n        for (var dd = 0; dd < arrayShape.length; ++dd) {\n          n *= arrayShape[dd];\n        }\n        var allocData = preConvert(image, n);\n        flattenUtils.flatten(data, arrayShape, '', allocData);\n        postConvert(image, allocData);\n        image.alignment = 1;\n        image.width = w;\n        image.height = h;\n        image.channels = c;\n        image.format = image.internalformat = CHANNELS_FORMAT[c];\n        image.needsFree = true;\n      }\n      if (image.type === GL_FLOAT$4) {\n        check$1(limits.extensions.indexOf('oes_texture_float') >= 0, 'oes_texture_float extension not enabled');\n      } else if (image.type === GL_HALF_FLOAT_OES$1) {\n        check$1(limits.extensions.indexOf('oes_texture_half_float') >= 0, 'oes_texture_half_float extension not enabled');\n      }\n\n      // do compressed texture  validation here.\n    }\n    function setImage(info, target, miplevel) {\n      var element = info.element;\n      var data = info.data;\n      var internalformat = info.internalformat;\n      var format = info.format;\n      var type = info.type;\n      var width = info.width;\n      var height = info.height;\n      setFlags(info);\n      if (element) {\n        gl.texImage2D(target, miplevel, format, format, type, element);\n      } else if (info.compressed) {\n        gl.compressedTexImage2D(target, miplevel, internalformat, width, height, 0, data);\n      }
1 else if (info.needsCopy) {\n        reglPoll();\n        gl.copyTexImage2D(target, miplevel, format, info.xOffset, info.yOffset, width, height, 0);\n      } else {\n        gl.texImage2D(target, miplevel, format, width, height, 0, format, type, data || null);\n      }\n    }\n    function setSubImage(info, target, x, y, miplevel) {\n      var element = info.element;\n      var data = info.data;\n      var internalformat = info.internalformat;\n      var format = info.format;\n      var type = info.type;\n      var width = info.width;\n      var height = info.height;\n      setFlags(info);\n      if (element) {\n        gl.texSubImage2D(target, miplevel, x, y, format, type, element);\n      } else if (info.compressed) {\n        gl.compressedTexSubImage2D(target, miplevel, x, y, internalformat, width, height, data);\n      } else if (info.needsCopy) {\n        reglPoll();\n        gl.copyTexSubImage2D(target, miplevel, x, y, info.xOffset, info.yOffset, width, height);\n      } else {\n        gl.texSubImage2D(target, miplevel, x, y, width, height, format, type, data);\n      }\n    }\n\n    // texImage pool\n    var imagePool = [];\n    function allocImage() {\n      return imagePool.pop() || new TexImage();\n    }\n    function freeImage(image) {\n      if (image.needsFree) {\n        pool.freeType(image.data);\n      }\n      TexImage.call(image);\n      imagePool.push(image);\n    }\n\n    // -------------------------------------------------------\n    // Mip map\n    // -------------------------------------------------------\n    function MipMap() {\n      TexFlags.call(this);\n      this.genMipmaps = false;\n      this.mipmapHint = GL_DONT_CARE;\n      this.mipmask = 0;\n      this.images = Array(16);\n    }\n    function parseMipMapFromShape(mipmap, width, height) {\n      var img = mipmap.images[0] = allocImage();\n      mipmap.mipmask = 1;\n      img.width = mipmap.width = width;\n      img.height = mipmap.height = height;\n      img.channels = mipmap.channels = 4;\n    }\n    function parseMipMapFromObject(mipmap, options) {\n      var imgData = null;\n      if (isPixelData(options)) {\n        imgData = mipmap.images[0] = allocImage();\n        copyFlags(imgData, mipmap);\n        parseImage(imgData, options);\n        mipmap.mipmask = 1;\n      } else {\n        parseFlags(mipmap, options);\n        if (Array.isArray(options.mipmap)) {\n          var mipData = options.mipmap;\n          for (var i = 0; i < mipData.length; ++i) {\n            imgData = mipmap.images[i] = allocImage();\n            copyFlags(imgData, mipmap);\n            imgData.width >>= i;\n            imgData.height >>= i;\n            parseImage(imgData, mipData[i]);\n            mipmap.mipmask |= 1 << i;\n          }\n        } else {\n          imgData = mipmap.images[0] = allocImage();\n          copyFlags(imgData, mipmap);\n          parseImage(imgData, options);\n          mipmap.mipmask = 1;\n        }\n      }\n      copyFlags(mipmap, mipmap.images[0]);\n\n      // For textures of the compressed format WEBGL_compressed_texture_s3tc\n      // we must have that\n      //\n      // \"When level equals zero width and height must be a multiple of 4.\n      // When level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4. \"\n      //\n      // but we do not yet support having multiple mipmap levels for compressed textures,\n      // so we only test for level zero.\n\n      if (mipmap.compressed && (mipmap.internalformat === GL_COMPRESSED_RGB_S3TC_DXT1_EXT || mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT3_EXT || mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) {\n        check$1(mipmap.width % 4 === 0 && mipmap.height % 4 === 0, 'for compressed texture formats, mipmap level 0 must have width and height that are a multiple of 4');\n      }\n    }\n    function setMipMap(mipmap, target) {\n      var images = mipmap.images;\n      for (var i = 0; i < images.length; ++i) {\n        if (!images[i]) {\n          return;\n        }\n        setImage(images[i], target, i);\n      }\n    }\n    var mipPool = [];\n    function allocMipMap() {\n      var result = mipPool.pop() || new MipMap();\n      TexFlags.call(result);\n      result.mipmask = 0;\n      for (var i = 0; i < 16; ++i) {\n        result.images[i] = null;\n      }\n      return result;\n    }\n    function freeMipMap(mipmap) {\n      var images = mipmap.images;\n      for (var i = 0; i < images.length; ++i) {\n        if (images[i]) {\n          freeImage(images[i]);\n        }\n        images[i] = null;\n      }
1\n      mipPool.push(mipmap);\n    }\n\n    // -------------------------------------------------------\n    // Tex info\n    // -------------------------------------------------------\n    function TexInfo() {\n      this.minFilter = GL_NEAREST$1;\n      this.magFilter = GL_NEAREST$1;\n      this.wrapS = GL_CLAMP_TO_EDGE$1;\n      this.wrapT = GL_CLAMP_TO_EDGE$1;\n      this.anisotropic = 1;\n      this.genMipmaps = false;\n      this.mipmapHint = GL_DONT_CARE;\n    }\n    function parseTexInfo(info, options) {\n      if ('min' in options) {\n        var minFilter = options.min;\n        check$1.parameter(minFilter, minFilters);\n        info.minFilter = minFilters[minFilter];\n        if (MIPMAP_FILTERS.indexOf(info.minFilter) >= 0 && !('faces' in options)) {\n          info.genMipmaps = true;\n        }\n      }\n      if ('mag' in options) {\n        var magFilter = options.mag;\n        check$1.parameter(magFilter, magFilters);\n        info.magFilter = magFilters[magFilter];\n      }\n      var wrapS = info.wrapS;\n      var wrapT = info.wrapT;\n      if ('wrap' in options) {\n        var wrap = options.wrap;\n        if (typeof wrap === 'string') {\n          check$1.parameter(wrap, wrapModes);\n          wrapS = wrapT = wrapModes[wrap];\n        } else if (Array.isArray(wrap)) {\n          check$1.parameter(wrap[0], wrapModes);\n          check$1.parameter(wrap[1], wrapModes);\n          wrapS = wrapModes[wrap[0]];\n          wrapT = wrapModes[wrap[1]];\n        }\n      } else {\n        if ('wrapS' in options) {\n          var optWrapS = options.wrapS;\n          check$1.parameter(optWrapS, wrapModes);\n          wrapS = wrapModes[optWrapS];\n        }\n        if ('wrapT' in options) {\n          var optWrapT = options.wrapT;\n          check$1.parameter(optWrapT, wrapModes);\n          wrapT = wrapModes[optWrapT];\n        }\n      }\n      info.wrapS = wrapS;\n      info.wrapT = wrapT;\n      if ('anisotropic' in options) {\n        var anisotropic = options.anisotropic;\n        check$1(typeof anisotropic === 'number' && anisotropic >= 1 && anisotropic <= limits.maxAnisotropic, 'aniso samples must be between 1 and ');\n        info.anisotropic = options.anisotropic;\n      }\n      if ('mipmap' in options) {\n        var hasMipMap = false;\n        switch (typeof options.mipmap) {\n          case 'string':\n            check$1.parameter(options.mipmap, mipmapHint, 'invalid mipmap hint');\n            info.mipmapHint = mipmapHint[options.mipmap];\n            info.genMipmaps = true;\n            hasMipMap = true;\n            break;\n          case 'boolean':\n            hasMipMap = info.genMipmaps = options.mipmap;\n            break;\n          case 'object':\n            check$1(Array.isArray(options.mipmap), 'invalid mipmap type');\n            info.genMipmaps = false;\n            hasMipMap = true;\n            break;\n          default:\n            check$1.raise('invalid mipmap type');\n        }\n        if (hasMipMap && !('min' in options)) {\n          info.minFilter = GL_NEAREST_MIPMAP_NEAREST$1;\n        }\n      }\n    }\n    function setTexInfo(info, target) {\n      gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, info.minFilter);\n      gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, info.magFilter);\n      gl.texParameteri(target, GL_TEXTURE_WRAP_S, info.wrapS);\n      gl.texParameteri(target, GL_TEXTURE_WRAP_T, info.wrapT);\n      if (extensions.ext_texture_filter_anisotropic) {\n        gl.texParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, info.anisotropic);\n      }\n      if (info.genMipmaps) {\n        gl.hint(GL_GENERATE_MIPMAP_HINT, info.mipmapHint);\n        gl.generateMipmap(target);\n      }\n    }\n\n    // -------------------------------------------------------\n    // Full texture object\n    // -------------------------------------------------------\n    var textureCount = 0;\n    var textureSet = {};\n    var numTexUnits = limits.maxTextureUnits;\n    var textureUnits = Array(numTexUnits).map(function () {\n      return null;\n    });\n    function REGLTexture(target) {\n      TexFlags.call(this);\n      this.mipmask = 0;\n      this.internalformat = GL_RGBA$1;\n      this.id = textureCount++;\n      this.refCount = 1;\n      this.target = target;\n      this.texture = gl.createTexture();\n      this.unit = -1;\n      this.bindCount = 0;\n      this.texInfo = new TexInfo();\n      if (config.profile) {\n        this.stats = {\n          size: 0\n        };\n      }\n    }\n    function tempBind(texture) {\n      gl.activeTexture(GL_TEXTURE0$1);\n      gl.bindTexture(texture.target, texture.texture);\n    }\n    function tempRestore() {\n      var prev = textureUnits[0];\n      if (prev) {\n        gl.bindTexture(prev.target, prev.texture);\n      } else {\n        gl.bindTexture(GL_TEXTURE_2D$1, null);\n      }\n    }\n    function destroy(texture) {\n      var handle = texture.texture;\n      check$1(handle, 'must not double destroy texture');\n      var unit = texture.unit;\n      var target = texture.target;\n      if (unit >= 0) {\n        gl.activeTexture(GL_TEXTURE0$1 + unit);\n        gl.bindTexture(target, null);\n        textureUnits[unit] = null;\n      }\n      gl.deleteTexture(handle);\n      texture.texture = null;\n      texture.params = null;\n      texture.pixels = null;\n      texture.refCount = 0;\n      delete textureSet[texture.id];\n      stats.textureCount--;\n    }\n    extend(REGLTexture.prototype, {\n      bind: function bind() {\n        var texture = this;\n        texture.bindCount += 1;\n        var unit = texture.unit;\n        if (unit < 0) {\n          for (var i = 0; i < numTexUnits; ++i) {\n            var other = textureUnits[i];\n            if (other) {\n              if (other.bindCount > 0) {\n                continue;\n              }\n              other.unit = -1;\n            }\n            textureUnits[i] = texture;\n            unit = i;\n            break;\n          }\n          if (unit >= numTexUnits) {\n            check$1.raise('insufficient number of texture units');\n          }\n          if (config.profile && stats.maxTextureUnits < unit + 1) {\n            stats.maxTextureUnits = unit + 1; // +1, since the units are zero-based\n          }\n          texture.unit = unit;\n          gl.activeTexture(GL_TEXTURE0$1 + unit);\n          gl.bindTexture(texture.target, texture.texture);\n        }\n        return unit;\n      },\n      unbind: function unbind() {\n        this.bindCount -= 1;\n      },\n      decRef: function decRef() {\n        if (--this.refCount <= 0) {\n          destroy(this);\n        }\n      }\n    });\n    function createTexture2D(a, b) {\n      var texture = new REGLTexture(GL_TEXTURE_2D$1);\n      textureSet[texture.id] = texture;\n      stats.textureCount++;\n      function reglTexture2D(a, b) {\n        var texInfo = texture.texInfo;\n        TexInfo.call(texInfo);\n        var mipData = allocMipMap();\n        if (typeof a === 'number') {\n          if (typeof b === 'number') {\n            parseMipMapFromShape(mipData, a | 0, b | 0);\n          } else {\n            parseMipMapFromShape(mipData, a | 0, a | 0);\n          }\n        } else if (a) {\n          check$1.type(a, 'object', 'invalid arguments to regl.texture');\n          parseTexInfo(texInfo, a);\n          parseMipMapFromObject(mipData, a);\n        } else {\n          // empty textures get assigned a default shape of 1x1\n          parseMipMapFromShape(mipData, 1, 1);\n        }
1\n        if (texInfo.genMipmaps) {\n          mipData.mipmask = (mipData.width << 1) - 1;\n        }\n        texture.mipmask = mipData.mipmask;\n        copyFlags(texture, mipData);\n        check$1.texture2D(texInfo, mipData, limits);\n        texture.internalformat = mipData.internalformat;\n        reglTexture2D.width = mipData.width;\n        reglTexture2D.height = mipData.height;\n        tempBind(texture);\n        setMipMap(mipData, GL_TEXTURE_2D$1);\n        setTexInfo(texInfo, GL_TEXTURE_2D$1);\n        tempRestore();\n        freeMipMap(mipData);\n        if (config.profile) {\n          texture.stats.size = getTextureSize(texture.internalformat, texture.type, mipData.width, mipData.height, texInfo.genMipmaps, false);\n        }\n        reglTexture2D.format = textureFormatsInvert[texture.internalformat];\n        reglTexture2D.type = textureTypesInvert[texture.type];\n        reglTexture2D.mag = magFiltersInvert[texInfo.magFilter];\n        reglTexture2D.min = minFiltersInvert[texInfo.minFilter];\n        reglTexture2D.wrapS = wrapModesInvert[texInfo.wrapS];\n        reglTexture2D.wrapT = wrapModesInvert[texInfo.wrapT];\n        return reglTexture2D;\n      }\n      function subimage(image, x_, y_, level_) {\n        check$1(!!image, 'must specify image data');\n        var x = x_ | 0;\n        var y = y_ | 0;\n        var level = level_ | 0;\n        var imageData = allocImage();\n        copyFlags(imageData, texture);\n        imageData.width = 0;\n        imageData.height = 0;\n        parseImage(imageData, image);\n        imageData.width = imageData.width || (texture.width >> level) - x;\n        imageData.height = imageData.height || (texture.height >> level) - y;\n        check$1(texture.type === imageData.type && texture.format === imageData.format && texture.internalformat === imageData.internalformat, 'incompatible format for texture.subimage');\n        check$1(x >= 0 && y >= 0 && x + imageData.width <= texture.width && y + imageData.height <= texture.height, 'texture.subimage write out of bounds');\n        check$1(texture.mipmask & 1 << level, 'missing mipmap data');\n        check$1(imageData.data || imageData.element || imageData.needsCopy, 'missing image data');\n        tempBind(texture);\n        setSubImage(imageData, GL_TEXTURE_2D$1, x, y, level);\n        tempRestore();\n        freeImage(imageData);\n        return reglTexture2D;\n      }\n      function resize(w_, h_) {\n        var w = w_ | 0;\n        var h = h_ | 0 || w;\n        if (w === texture.width && h === texture.height) {\n          return reglTexture2D;\n        }\n        reglTexture2D.width = texture.width = w;\n        reglTexture2D.height = texture.height = h;\n        tempBind(texture);\n        for (var i = 0; texture.mipmask >> i; ++i) {\n          var _w = w >> i;\n          var _h = h >> i;\n          if (!_w || !_h) break;\n          gl.texImage2D(GL_TEXTURE_2D$1, i, texture.format, _w, _h, 0, texture.format, texture.type, null);\n        }\n        tempRestore();\n\n        // also, recompute the texture size.\n        if (config.profile) {\n          texture.stats.size = getTextureSize(texture.internalformat, texture.type, w, h, false, false);\n        }\n        return reglTexture2D;\n      }\n      reglTexture2D(a, b);\n      reglTexture2D.subimage = subimage;\n      reglTexture2D.resize = resize;\n      reglTexture2D._reglType = 'texture2d';\n      reglTexture2D._texture = texture;\n      if (config.profile) {\n        reglTexture2D.stats = texture.stats;\n      }\n      reglTexture2D.destroy = function () {\n        texture.decRef();\n      };\n      return reglTexture2D;\n    }\n    function createTextureCube(a0, a1, a2, a3, a4, a5) {\n      var texture = new REGLTexture(GL_TEXTURE_CUBE_MAP$1);\n      textureSet[texture.id] = texture;\n      stats.cubeCount++;\n      var faces = new Array(6);\n      function reglTextureCube(a0, a1, a2, a3, a4, a5) {\n        var i;\n        var texInfo = texture.texInfo;\n        TexInfo.call(texInfo);\n        for (i = 0; i < 6; ++i) {\n          faces[i] = allocMipMap();\n        }\n        if (typeof a0 === 'number' || !a0) {\n          var s = a0 | 0 || 1;\n          for (i = 0; i < 6; ++i) {\n            parseMipMapFromShape(faces[i], s, s);\n          }\n        } else if (typeof a0 === 'object') {\n          if (a1) {\n            parseMipMapFromObject(faces[0], a0);\n            parseMipMapFromObject(faces[1], a1);\n            parseMipMapFromObject(faces[2], a2);\n            parseMipMapFromObject(faces[3], a3);\n            parseMipMapFromObject(faces[4], a4);\n            parseMipMapFromObject(faces[5], a5);\n          } else {\n            parseTexInfo(texInfo, a0);\n            parseFlags(texture, a0);\n            if ('faces' in a0) {\n              var faceInput = a0.faces;\n              check$1(Array.isArray(faceInput) && faceInput.length === 6, 'cube faces must be a length 6 array');\n              for (i = 0; i < 6; ++i) {\n                check$1(typeof faceInput[i] === 'object' && !!faceInput[i], 'invalid input for cube map face');\n                copyFlags(faces[i], texture);\n                parseMipMapFromObject(faces[i], faceInput[i]);\n              }\n            } else {\n              for (i = 0; i < 6; ++i) {\n                parseMipMapFromObject(faces[i], a0);\n              }\n            }\n          }\n        } else {\n          check$1.raise('invalid arguments to cube map');\n        }\n        copyFlags(texture, faces[0]);\n        check$1.optional(function () {\n          if (!limits.npotTextureCube) {\n            check$1(isPow2$1(texture.width) && isPow2$1(texture.height), 'your browser does not support non power or two texture dimensions');\n          }\n        });
1\n        if (texInfo.genMipmaps) {\n          texture.mipmask = (faces[0].width << 1) - 1;\n        } else {\n          texture.mipmask = faces[0].mipmask;\n        }\n        check$1.textureCube(texture, texInfo, faces, limits);\n        texture.internalformat = faces[0].internalformat;\n        reglTextureCube.width = faces[0].width;\n        reglTextureCube.height = faces[0].height;\n        tempBind(texture);\n        for (i = 0; i < 6; ++i) {\n          setMipMap(faces[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + i);\n        }\n        setTexInfo(texInfo, GL_TEXTURE_CUBE_MAP$1);\n        tempRestore();\n        if (config.profile) {\n          texture.stats.size = getTextureSize(texture.internalformat, texture.type, reglTextureCube.width, reglTextureCube.height, texInfo.genMipmaps, true);\n        }\n        reglTextureCube.format = textureFormatsInvert[texture.internalformat];\n        reglTextureCube.type = textureTypesInvert[texture.type];\n        reglTextureCube.mag = magFiltersInvert[texInfo.magFilter];\n        reglTextureCube.min = minFiltersInvert[texInfo.minFilter];\n        reglTextureCube.wrapS = wrapModesInvert[texInfo.wrapS];\n        reglTextureCube.wrapT = wrapModesInvert[texInfo.wrapT];\n        for (i = 0; i < 6; ++i) {\n          freeMipMap(faces[i]);\n        }\n        return reglTextureCube;\n      }\n      function subimage(face, image, x_, y_, level_) {\n        check$1(!!image, 'must specify image data');\n        check$1(typeof face === 'number' && face === (face | 0) && face >= 0 && face < 6, 'invalid face');\n        var x = x_ | 0;\n        var y = y_ | 0;\n        var level = level_ | 0;\n        var imageData = allocImage();\n        copyFlags(imageData, texture);\n        imageData.width = 0;\n        imageData.height = 0;\n        parseImage(imageData, image);\n        imageData.width = imageData.width || (texture.width >> level) - x;\n        imageData.height = imageData.height || (texture.height >> level) - y;\n        check$1(texture.type === imageData.type && texture.format === imageData.format && texture.internalformat === imageData.internalformat, 'incompatible format for texture.subimage');\n        check$1(x >= 0 && y >= 0 && x + imageData.width <= texture.width && y + imageData.height <= texture.height, 'texture.subimage write out of bounds');\n        check$1(texture.mipmask & 1 << level, 'missing mipmap data');\n        check$1(imageData.data || imageData.element || imageData.needsCopy, 'missing image data');\n        tempBind(texture);\n        setSubImage(imageData, GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + face, x, y, level);\n        tempRestore();\n        freeImage(imageData);\n        return reglTextureCube;\n      }\n      function resize(radius_) {\n        var radius = radius_ | 0;\n        if (radius === texture.width) {\n          return;\n        }\n        reglTextureCube.width = texture.width = radius;\n        reglTextureCube.height = texture.height = radius;\n        tempBind(texture);\n        for (var i = 0; i < 6; ++i) {\n          for (var j = 0; texture.mipmask >> j; ++j) {\n            gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + i, j, texture.format, radius >> j, radius >> j, 0, texture.format, texture.type, null);\n          }\n        }\n        tempRestore();\n        if (config.profile) {\n          texture.stats.size = getTextureSize(texture.internalformat, texture.type, reglTextureCube.width, reglTextureCube.height, false, true);\n        }\n        return reglTextureCube;\n      }\n      reglTextureCube(a0, a1, a2, a3, a4, a5);\n      reglTextureCube.subimage = subimage;\n      reglTextureCube.resize = resize;\n      reglTextureCube._reglType = 'textureCube';\n      reglTextureCube._texture = texture;\n      if (config.profile) {\n        reglTextureCube.stats = texture.stats;\n      }\n      reglTextureCube.destroy = function () {\n        texture.decRef();\n      };\n      return reglTextureCube;\n    }\n\n    // Called when regl is destroyed\n    function destroyTextures() {\n      for (var i = 0; i < numTexUnits; ++i) {\n        gl.activeTexture(GL_TEXTURE0$1 + i);\n        gl.bindTexture(GL_TEXTURE_2D$1, null);\n        textureUnits[i] = null;\n      }\n      values(textureSet).forEach(destroy);\n      stats.cubeCount = 0;\n      stats.textureCount = 0;\n    }\n    if (config.profile) {\n      stats.getTotalTextureSize = function () {\n        var total = 0;\n        Object.keys(textureSet).forEach(function (key) {\n          total += textureSet[key].stats.size;\n        });\n        return total;\n      };\n    }\n    function restoreTextures() {\n      for (var i = 0; i < numTexUnits; ++i) {\n        var tex = textureUnits[i];\n        if (tex) {\n          tex.bindCount = 0;\n          tex.unit = -1;\n          textureUnits[i] = null;\n        }\n      }\n      values(textureSet).forEach(function (texture) {\n        texture.texture = gl.createTexture();\n        gl.bindTexture(texture.target, texture.texture);\n        for (var i = 0; i < 32; ++i) {\n          if ((texture.mipmask & 1 << i) === 0) {\n            continue;\n          }\n          if (texture.target === GL_TEXTURE_2D$1) {\n            gl.texImage2D(GL_TEXTURE_2D$1, i, texture.internalformat, texture.width >> i, texture.height >> i, 0, texture.internalformat, texture.type, null);\n          } else {\n            for (var j = 0; j < 6; ++j) {\n              gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + j, i, texture.internalformat, texture.width >> i, texture.height >> i, 0, texture.internalformat, texture.type, null);\n            }\n          }\n        }\n        setTexInfo(texture.texInfo, texture.target);\n      });\n    }\n    function refreshTextures() {\n      for (var i = 0; i < numTexUnits; ++i) {\n        var tex = textureUnits[i];\n        if (tex) {\n          tex.bindCount = 0;\n          tex.unit = -1;\n          textureUnits[i] = null;\n        }\n        gl.activeTexture(GL_TEXTURE0$1 + i);\n        gl.bindTexture(GL_TEXTURE_2D$1, null);\n        gl.bindTexture(GL_TEXTURE_CUBE_MAP$1, null);\n      }\n    }\n    return {\n      create2D: createTexture2D,\n      createCube: createTextureCube,\n      clear: destroyTextures,\n      getTexture: function getTexture(wrapper) {\n        return null;\n      },\n      restore: restoreTextures,\n      refresh: refreshTextures\n    };\n  }\n  var GL_RENDERBUFFER = 0x8D41;\n  var GL_RGBA4$1 = 0x8056;\n  var GL_RGB5_A1$1 = 0x8057;\n  var GL_RGB565$1 = 0x8D62;\n  var GL_DEPTH_COMPONENT16 = 0x81A5;\n  var GL_STENCIL_INDEX8 = 0x8D48;\n  var GL_DEPTH_STENCIL$1 = 0x84F9;\n  var GL_SRGB8_ALPHA8_EXT = 0x8C43;\n  var GL_RGBA32F_EXT = 0x8814;\n  var GL_RGBA16F_EXT = 0x881A;\n  var GL_RGB16F_EXT = 0x881B;\n  var FORMAT_SIZES = [];\n  FORMAT_SIZES[GL_RGBA4$1] = 2;\n  FORMAT_SIZES[GL_RGB5_A1$1] = 2;\n  FORMAT_SIZES[GL_RGB565$1] = 2;\n  FORMAT_SIZES[GL_DEPTH_COMPONENT16] = 2;\n  FORMAT_SIZES[GL_STENCIL_INDEX8] = 1;\n  FORMAT_SIZES[GL_DEPTH_STENCIL$1] = 4;\n  FORMAT_SIZES[GL_SRGB8_ALPHA8_EXT] = 4;\n  FORMAT_SIZES[GL_RGBA32F_EXT] = 16;\n  FORMAT_SIZES[GL_RGBA16F_EXT] = 8;\n  FORMAT_SIZES[GL_RGB16F_EXT] = 6;\n  function getRenderbufferSize(format, width, height) {\n    return FORMAT_SIZES[format] * width * height;\n  }\n  var wrapRenderbuffers = function wrapRenderbuffers(gl, extensions, limits, stats, config) {\n    var formatTypes = {\n      'rgba4': GL_RGBA4$1,\n      'rgb565': GL_RGB565$1,\n      'rgb5 a1': GL_RGB5_A1$1,\n      'depth': G
1L_DEPTH_COMPONENT16,\n      'stencil': GL_STENCIL_INDEX8,\n      'depth stencil': GL_DEPTH_STENCIL$1\n    };\n    if (extensions.ext_srgb) {\n      formatTypes['srgba'] = GL_SRGB8_ALPHA8_EXT;\n    }\n    if (extensions.ext_color_buffer_half_float) {\n      formatTypes['rgba16f'] = GL_RGBA16F_EXT;\n      formatTypes['rgb16f'] = GL_RGB16F_EXT;\n    }\n    if (extensions.webgl_color_buffer_float) {\n      formatTypes['rgba32f'] = GL_RGBA32F_EXT;\n    }\n    var formatTypesInvert = [];\n    Object.keys(formatTypes).forEach(function (key) {\n      var val = formatTypes[key];\n      formatTypesInvert[val] = key;\n    });\n    var renderbufferCount = 0;\n    var renderbufferSet = {};\n    function REGLRenderbuffer(renderbuffer) {\n      this.id = renderbufferCount++;\n      this.refCount = 1;\n      this.renderbuffer = renderbuffer;\n      this.format = GL_RGBA4$1;\n      this.width = 0;\n      this.height = 0;\n      if (config.profile) {\n        this.stats = {\n          size: 0\n        };\n      }\n    }\n    REGLRenderbuffer.prototype.decRef = function () {\n      if (--this.refCount <= 0) {\n        destroy(this);\n      }\n    };\n    function destroy(rb) {\n      var handle = rb.renderbuffer;\n      check$1(handle, 'must not double destroy renderbuffer');\n      gl.bindRenderbuffer(GL_RENDERBUFFER, null);\n      gl.deleteRenderbuffer(handle);\n      rb.renderbuffer = null;\n      rb.refCount = 0;\n      delete renderbufferSet[rb.id];\n      stats.renderbufferCount--;\n    }\n    function createRenderbuffer(a, b) {\n      var renderbuffer = new REGLRenderbuffer(gl.createRenderbuffer());\n      renderbufferSet[renderbuffer.id] = renderbuffer;\n      stats.renderbufferCount++;\n      function reglRenderbuffer(a, b) {\n        var w = 0;\n        var h = 0;\n        var format = GL_RGBA4$1;\n        if (typeof a === 'object' && a) {\n          var options = a;\n          if ('shape' in options) {\n            var shape = options.shape;\n            check$1(Array.isArray(shape) && shape.length >= 2, 'invalid renderbuffer shape');\n            w = shape[0] | 0;\n            h = shape[1] | 0;\n          } else {\n            if ('radius' in options) {\n              w = h = options.radius | 0;\n            }\n            if ('width' in options) {\n              w = options.width | 0;\n            }\n            if ('height' in options) {\n              h = options.height | 0;\n            }\n          }\n          if ('format' in options) {\n            check$1.parameter(options.format, formatTypes, 'invalid renderbuffer format');\n            format = formatTypes[options.format];\n          }\n        } else if (typeof a === 'number') {\n          w = a | 0;\n          if (typeof b === 'number') {\n            h = b | 0;\n          } else {\n            h = w;\n          }\n        } else if (!a) {\n          w = h = 1;\n        } else {\n          check$1.raise('invalid arguments to renderbuffer constructor');\n        }\n\n        // check shape\n        check$1(w > 0 && h > 0 && w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize, 'invalid renderbuffer size');\n        if (w === renderbuffer.width && h === renderbuffer.height && format === renderbuffer.format) {\n          return;\n        }\n        reglRenderbuffer.width = renderbuffer.width = w;\n        reglRenderbuffer.height = renderbuffer.height = h;\n        renderbuffer.format = format;\n        gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer);\n        gl.renderbufferStorage(GL_RENDERBUFFER, format, w, h);\n        check$1(gl.getError() === 0, 'invalid render buffer format');\n        if (config.profile) {\n          renderbuffer.stats.size = getRenderbufferSize(renderbuffer.format, renderbuffer.width, renderbuffer.height);\n        }\n        reglRenderbuffer.format = formatTypesInvert[renderbuffer.format];\n        return reglRenderbuffer;\n      }\n      function resize(w_, h_) {\n        var w = w_ | 0;\n        var h = h_ | 0 || w;\n        if (w === renderbuffer.width && h === renderbuffer.height) {\n          return reglRenderbuffer;\n        }\n\n        // check shape\n        check$1(w > 0 && h > 0 && w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize, 'invalid renderbuffer size');\n        reglRenderbuffer.width = renderbuffer.width = w;
1\n        reglRenderbuffer.height = renderbuffer.height = h;\n        gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer);\n        gl.renderbufferStorage(GL_RENDERBUFFER, renderbuffer.format, w, h);\n        check$1(gl.getError() === 0, 'invalid render buffer format');\n\n        // also, recompute size.\n        if (config.profile) {\n          renderbuffer.stats.size = getRenderbufferSize(renderbuffer.format, renderbuffer.width, renderbuffer.height);\n        }\n        return reglRenderbuffer;\n      }\n      reglRenderbuffer(a, b);\n      reglRenderbuffer.resize = resize;\n      reglRenderbuffer._reglType = 'renderbuffer';\n      reglRenderbuffer._renderbuffer = renderbuffer;\n      if (config.profile) {\n        reglRenderbuffer.stats = renderbuffer.stats;\n      }\n      reglRenderbuffer.destroy = function () {\n        renderbuffer.decRef();\n      };\n      return reglRenderbuffer;\n    }\n    if (config.profile) {\n      stats.getTotalRenderbufferSize = function () {\n        var total = 0;\n        Object.keys(renderbufferSet).forEach(function (key) {\n          total += renderbufferSet[key].stats.size;\n        });\n        return total;\n      };\n    }\n    function restoreRenderbuffers() {\n      values(renderbufferSet).forEach(function (rb) {\n        rb.renderbuffer = gl.createRenderbuffer();\n        gl.bindRenderbuffer(GL_RENDERBUFFER, rb.renderbuffer);\n        gl.renderbufferStorage(GL_RENDERBUFFER, rb.format, rb.width, rb.height);\n      });\n      gl.bindRenderbuffer(GL_RENDERBUFFER, null);\n    }\n    return {\n      create: createRenderbuffer,\n      clear: function clear() {\n        values(renderbufferSet).forEach(destroy);\n      },\n      restore: restoreRenderbuffers\n    };\n  };\n\n  // We store these constants so that the minifier can inline them\n  var GL_FRAMEBUFFER$1 = 0x8D40;\n  var GL_RENDERBUFFER$1 = 0x8D41;\n  var GL_TEXTURE_2D$2 = 0x0DE1;\n  var GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 = 0x8515;\n  var GL_COLOR_ATTACHMENT0$1 = 0x8CE0;\n  var GL_DEPTH_ATTACHMENT = 0x8D00;\n  var GL_STENCIL_ATTACHMENT = 0x8D20;\n  var GL_DEPTH_STENCIL_ATTACHMENT = 0x821A;\n  var GL_FRAMEBUFFER_COMPLETE$1 = 0x8CD5;\n  var GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;\n  var GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;\n  var GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;\n  var GL_FRAMEBUFFER_UNSUPPORTED = 0x8CDD;\n  var GL_HALF_FLOAT_OES$2 = 0x8D61;\n  var GL_UNSIGNED_BYTE$6 = 0x1401;\n  var GL_FLOAT$5 = 0x1406;\n  var GL_RGB$1 = 0x1907;\n  var GL_RGBA$2 = 0x1908;\n  var GL_DEPTH_COMPONENT$1 = 0x1902;\n  var colorTextureFormatEnums = [GL_RGB$1, GL_RGBA$2];\n\n  // for every texture format, store\n  // the number of channels\n  var textureFormatChannels = [];\n  textureFormatChannels[GL_RGBA$2] = 4;\n  textureFormatChannels[GL_RGB$1] = 3;\n\n  // for every texture type, store\n  // the size in bytes.\n  var textureTypeSizes = [];\n  textureTypeSizes[GL_UNSIGNED_BYTE$6] = 1;\n  textureTypeSizes[GL_FLOAT$5] = 4;\n  textureTypeSizes[GL_HALF_FLOAT_OES$2] = 2;\n  var GL_RGBA4$2 = 0x8056;\n  var GL_RGB5_A1$2 = 0x8057;\n  var GL_RGB565$2 = 0x8D62;\n  var GL_DEPTH_COMPONENT16$1 = 0x81A5;\n  var GL_STENCIL_INDEX8$1 = 0x8D48;\n  var GL_DEPTH_STENCIL$2 = 0x84F9;\n  var GL_SRGB8_ALPHA8_EXT$1 = 0x8C43;\n  var GL_RGBA32F_EXT$1 = 0x8814;\n  var GL_RGBA16F_EXT$1 = 0x881A;\n  var GL_RGB16F_EXT$1 = 0x881B;\n  var colorRenderbufferFormatEnums = [GL_RGBA4$2, GL_RGB5_A1$2, GL_RGB565$2, GL_SRGB8_ALPHA8_EXT$1, GL_RGBA16F_EXT$1, GL_RGB16F_EXT$1, GL_RGBA32F_EXT$1];\n  var statusCode = {};\n  statusCode[GL_FRAMEBUFFER_COMPLETE$1] = 'complete';\n  statusCode[GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT] = 'incomplete attachment';\n  statusCode[GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS] = 'incomplete dimensions';\n  statusCode[GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT] = 'incomplete, missing attachment';\n  statusCode[GL_FRAMEBUFFER_UNSUPPORTED] = 'unsupported';\n  function wrapFBOState(gl, extensions, limits, textureState, renderbufferState, stats) {\n    var framebufferState = {\n      cur: null,\n      next: null,\n      dirty: false,\n      setFBO: null\n    };\n    var colorTextureFormats = ['rgba'];
1\n    var colorRenderbufferFormats = ['rgba4', 'rgb565', 'rgb5 a1'];\n    if (extensions.ext_srgb) {\n      colorRenderbufferFormats.push('srgba');\n    }\n    if (extensions.ext_color_buffer_half_float) {\n      colorRenderbufferFormats.push('rgba16f', 'rgb16f');\n    }\n    if (extensions.webgl_color_buffer_float) {\n      colorRenderbufferFormats.push('rgba32f');\n    }\n    var colorTypes = ['uint8'];\n    if (extensions.oes_texture_half_float) {\n      colorTypes.push('half float', 'float16');\n    }\n    if (extensions.oes_texture_float) {\n      colorTypes.push('float', 'float32');\n    }\n    function FramebufferAttachment(target, texture, renderbuffer) {\n      this.target = target;\n      this.texture = texture;\n      this.renderbuffer = renderbuffer;\n      var w = 0;\n      var h = 0;\n      if (texture) {\n        w = texture.width;\n        h = texture.height;\n      } else if (renderbuffer) {\n        w = renderbuffer.width;\n        h = renderbuffer.height;\n      }\n      this.width = w;\n      this.height = h;\n    }\n    function decRef(attachment) {\n      if (attachment) {\n        if (attachment.texture) {\n          attachment.texture._texture.decRef();\n        }\n        if (attachment.renderbuffer) {\n          attachment.renderbuffer._renderbuffer.decRef();\n        }\n      }\n    }\n    function incRefAndCheckShape(attachment, width, height) {\n      if (!attachment) {\n        return;\n      }\n      if (attachment.texture) {\n        var texture = attachment.texture._texture;\n        var tw = Math.max(1, texture.width);\n        var th = Math.max(1, texture.height);\n        check$1(tw === width && th === height, 'inconsistent width/height for supplied texture');\n        texture.refCount += 1;\n      } else {\n        var renderbuffer = attachment.renderbuffer._renderbuffer;\n        check$1(renderbuffer.width === width && renderbuffer.height === height, 'inconsistent width/height for renderbuffer');\n        renderbuffer.refCount += 1;\n      }\n    }\n    function attach(location, attachment) {\n      if (attachment) {\n        if (attachment.texture) {\n          gl.framebufferTexture2D(GL_FRAMEBUFFER$1, location, attachment.target, attachment.texture._texture.texture, 0);\n        } else {\n          gl.framebufferRenderbuffer(GL_FRAMEBUFFER$1, location, GL_RENDERBUFFER$1, attachment.renderbuffer._renderbuffer.renderbuffer);\n        }\n      }\n    }\n    function parseAttachment(attachment) {\n      var target = GL_TEXTURE_2D$2;\n      var texture = null;\n      var renderbuffer = null;\n      var data = attachment;\n      if (typeof attachment === 'object') {\n        data = attachment.data;\n        if ('target' in attachment) {\n          target = attachment.target | 0;\n        }\n      }\n      check$1.type(data, 'function', 'invalid attachment data');\n      var type = data._reglType;\n      if (type === 'texture2d') {\n        texture = data;\n        check$1(target === GL_TEXTURE_2D$2);\n      } else if (type === 'textureCube') {\n        texture = data;\n        check$1(target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 && target < GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 + 6, 'invalid cube map target');\n      } else if (type === 'renderbuffer') {\n        renderbuffer = data;\n        target = GL_RENDERBUFFER$1;\n      } else {\n        check$1.raise('invalid regl object for attachment');\n      }\n      return new FramebufferAttachment(target, texture, renderbuffer);\n    }\n    function allocAttachment(width, height, isTexture, format, type) {\n      if (isTexture) {\n        var texture = textureState.create2D({\n          width: width,\n          height: height,\n          format: format,\n          type: type\n        });\n        texture._texture.refCount = 0;\n        return new FramebufferAttachment(GL_TEXTURE_2D$2, texture, null);\n      } else {\n        var rb = renderbufferState.create({\n          width: width,\n          height: height,\n          format: format\n        });\n        rb._renderbuffer.refCount = 0;\n        return new FramebufferAttachment(GL_RENDERBUFFER$1, null, rb);\n      }\n    }\n    function unwrapAttachment(attachment) {\n      return attachment && (attachment.texture || attachment.renderbuffer);\n    }\n    function resizeAttachment(attachment, w, h) {\n      if (attachment) {\n        if (attachment.texture) {\n          attachment.texture.resize(w, h);\n        } else if (attachment.renderbuffer) {\n          attachment.renderbuffer.resize(w, h);\n        }\n        attachment.width = w;\n        attachment.height = h;\n      }\n    }\n    var framebufferCount = 0;\n    var framebufferSet = {};\n    function REGLFramebuffer() {\n      this.id = framebufferCount++;\n      framebufferSet[this.id] = this;\n      this.framebuffer = gl.createFramebuffer();\n      this.width = 0;\n      this.height = 0;\n      this.colorAttachments = [];\n      this.depthAttachment = null;\n      this.stencilAttachment = null;\n      this.depthStencilAttachment = null;\n    }\n    function decFBORefs(framebuffer) {\n      framebuffer.colorAttachments.forEac
1h(decRef);\n      decRef(framebuffer.depthAttachment);\n      decRef(framebuffer.stencilAttachment);\n      decRef(framebuffer.depthStencilAttachment);\n    }\n    function _destroy(framebuffer) {\n      var handle = framebuffer.framebuffer;\n      check$1(handle, 'must not double destroy framebuffer');\n      gl.deleteFramebuffer(handle);\n      framebuffer.framebuffer = null;\n      stats.framebufferCount--;\n      delete framebufferSet[framebuffer.id];\n    }\n    function updateFramebuffer(framebuffer) {\n      var i;\n      gl.bindFramebuffer(GL_FRAMEBUFFER$1, framebuffer.framebuffer);\n      var colorAttachments = framebuffer.colorAttachments;\n      for (i = 0; i < colorAttachments.length; ++i) {\n        attach(GL_COLOR_ATTACHMENT0$1 + i, colorAttachments[i]);\n      }\n      for (i = colorAttachments.length; i < limits.maxColorAttachments; ++i) {\n        gl.framebufferTexture2D(GL_FRAMEBUFFER$1, GL_COLOR_ATTACHMENT0$1 + i, GL_TEXTURE_2D$2, null, 0);\n      }\n      gl.framebufferTexture2D(GL_FRAMEBUFFER$1, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D$2, null, 0);\n      gl.framebufferTexture2D(GL_FRAMEBUFFER$1, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D$2, null, 0);\n      gl.framebufferTexture2D(GL_FRAMEBUFFER$1, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D$2, null, 0);\n      attach(GL_DEPTH_ATTACHMENT, framebuffer.depthAttachment);\n      attach(GL_STENCIL_ATTACHMENT, framebuffer.stencilAttachment);\n      attach(GL_DEPTH_STENCIL_ATTACHMENT, framebuffer.depthStencilAttachment);\n\n      // Check status code\n      var status = gl.checkFramebufferStatus(GL_FRAMEBUFFER$1);\n      if (!gl.isContextLost() && status !== GL_FRAMEBUFFER_COMPLETE$1) {\n        check$1.raise('framebuffer configuration not supported, status = ' + statusCode[status]);\n      }\n      gl.bindFramebuffer(GL_FRAMEBUFFER$1, framebufferState.next ? framebufferState.next.framebuffer : null);\n      framebufferState.cur = framebufferState.next;\n\n      // FIXME: Clear error code here.  This is a work around for a bug in\n      // headless-gl\n      gl.getError();\n    }\n    function createFBO(a0, a1) {\n      var framebuffer = new REGLFramebuffer();\n      stats.framebufferCount++;\n      function reglFramebuffer(a, b) {\n        var i;\n        check$1(framebufferState.next !== framebuffer, 'can not update framebuffer which is currently in use');\n        var width = 0;\n        var height = 0;\n        var needsDepth = true;\n        var needsStencil = true;\n        var colorBuffer = null;\n        var colorTexture = true;\n        var colorFormat = 'rgba';\n        var colorType = 'uint8';\n        var colorCount = 1;\n        var depthBuffer = null;\n        var stencilBuffer = null;\n        var depthStencilBuffer = null;\n        var depthStencilTexture = false;\n        if (typeof a === 'number') {\n          width = a | 0;\n          height = b | 0 || width;\n        } else if (!a) {\n          width = height = 1;\n        } else {\n          check$1.type(a, 'object', 'invalid arguments for framebuffer');\n          var options = a;\n          if ('shape' in options) {\n            var shape = options.shape;\n            check$1(Array.isArray(shape) && shape.length >= 2, 'invalid shape for framebuffer');\n            width = shape[0];\n            height = shape[1];\n          } else {\n            if ('radius' in options) {\n              width = height = options.radius;\n            }\n            if ('width' in options) {\n              width = options.width;\n            }\n            if ('height' in options) {\n              height = options.height;\n            }\n          }\n          if ('color' in options || 'colors' in options) {\n            colorBuffer = options.color || options.colors;\n            if (Array.isArray(colorBuffer)) {\n              check$1(colorBuffer.length === 1 || extensions.webgl_draw_buffers, 'multiple render targets not supported');\n            }\n          }\n          if (!colorBuffer) {\n            if ('colorCount' in options) {\n              colorCount = options.colorCount | 0;\n              check$1(colorCount > 0, 'invalid color buffer count');\n            }
1\n            if ('colorTexture' in options) {\n              colorTexture = !!options.colorTexture;\n              colorFormat = 'rgba4';\n            }\n            if ('colorType' in options) {\n              colorType = options.colorType;\n              if (!colorTexture) {\n                if (colorType === 'half float' || colorType === 'float16') {\n                  check$1(extensions.ext_color_buffer_half_float, 'you must enable EXT_color_buffer_half_float to use 16-bit render buffers');\n                  colorFormat = 'rgba16f';\n                } else if (colorType === 'float' || colorType === 'float32') {\n                  check$1(extensions.webgl_color_buffer_float, 'you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers');\n                  colorFormat = 'rgba32f';\n                }\n              } else {\n                check$1(extensions.oes_texture_float || !(colorType === 'float' || colorType === 'float32'), 'you must enable OES_texture_float in order to use floating point framebuffer objects');\n                check$1(extensions.oes_texture_half_float || !(colorType === 'half float' || colorType === 'float16'), 'you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects');\n              }\n              check$1.oneOf(colorType, colorTypes, 'invalid color type');\n            }\n            if ('colorFormat' in options) {\n              colorFormat = options.colorFormat;\n              if (colorTextureFormats.indexOf(colorFormat) >= 0) {\n                colorTexture = true;\n              } else if (colorRenderbufferFormats.indexOf(colorFormat) >= 0) {\n                colorTexture = false;\n              } else {\n                check$1.optional(function () {\n                  if (colorTexture) {\n                    check$1.oneOf(options.colorFormat, colorTextureFormats, 'invalid color format for texture');\n                  } else {\n                    check$1.oneOf(options.colorFormat, colorRenderbufferFormats, 'invalid color format for renderbuffer');\n                  }\n                });\n              }\n            }\n          }\n          if ('depthTexture' in options || 'depthStencilTexture' in options) {\n            depthStencilTexture = !!(options.depthTexture || options.depthStencilTexture);\n            check$1(!depthStencilTexture || extensions.webgl_depth_texture, 'webgl_depth_texture extension not supported');\n          }\n          if ('depth' in options) {\n            if (typeof options.depth === 'boolean') {\n              needsDepth = options.depth;\n            } else {\n              depthBuffer = options.depth;\n              needsStencil = false;\n            }\n          }\n          if ('stencil' in options) {\n            if (typeof options.stencil === 'boolean') {\n              needsStencil = options.stencil;\n            } else {\n              stencilBuffer = options.stencil;\n              needsDepth = false;\n            }\n          }\n          if ('depthStencil' in options) {\n            if (typeof options.depthStencil === 'boolean') {\n              needsDepth = needsStencil = options.depthStencil;\n            } else {\n              depthStencilBuffer = options.depthStencil;\n              needsDepth = false;\n              needsStencil = false;\n            }\n          }\n        }\n\n        // parse attachments\n        var colorAttachments = null;\n        var depthAttachment = null;\n        var stencilAttachment = null;\n        var depthStencilAttachment = null;\n\n        // Set up color attachments\n        if (Array.isArray(colorBuffer)) {\n          colorAttachments = colorBuffer.map(parseAttachment);\n        } else if (colorBuffer) {\n          colorAttachments = [parseAttachment(colorBuffer)];\n        } else {\n          colorAttachments = new Array(colorCount);\n          for (i = 0; i < colorCount; ++i) {\n            colorAttachments[i] = allocAttachment(width, height, colorTexture, colorFormat, colorType);\n          }\n        }\n        check$1(extensions.webgl_draw_buffers || colorAttachments.length <= 1, 'you must enable the WEBGL_draw_buffers extension in order to use multiple color buffers.');\n        check$1(colorAttachments.length <= limits.maxColorAttachments, 'too many color attachments, not supported');\n        width = width || colorAttachments[0].width;\n        height = height || colorAttachments[0].height;\n        if (depthBuffer) {\n          depthAttachment = parseAttachment(depthBuffer);\n        } else if (needsDepth && !needsStencil) {\n          depthAttachment = allocAttachment(width, height, depthStencilTexture, 'depth', 'uint32');\n        }\n        if (stencilBuffer) {\n          stencilAttachment = parseAttachment(stencilBuffer);\n        } else if (needsStencil && !needsDepth) {\n          stencilAttachment = allocAttachment(width, height, false, 'stencil', 'uint8');\n        }\n        if (depthStencilBuffer) {\n          depthStencilAttachment = parseAttachment(depthStencilBuffer);\n        } else if (!depthBuffer && !stencilBuffer && needsStencil && needsDepth) {\n          depthStencilAttachment = allocAttachment(width, height, depthStencilTexture, 'depth stencil', 'depth stencil');\n        }\n        check$1(!!depthBuffer + !!stencilBuffer + !!depthStencilBuffer <= 1, 'invalid framebuffer configuration, can specify exactly one depth/stencil attachment');\n        var commonColorAttachmentSize = null;\n        for (i = 0; i < colorAttachments.length; ++i) {\n          incRefAndCheckShape(colorAttachments[i], width, height);\n          check$1(!colorAttachments[i] || colorAttachments[i].texture && colorTextureFormatEnums.indexOf(colorAttachments[i].texture._texture.format) >
1= 0 || colorAttachments[i].renderbuffer && colorRenderbufferFormatEnums.indexOf(colorAttachments[i].renderbuffer._renderbuffer.format) >= 0, 'framebuffer color attachment ' + i + ' is invalid');\n          if (colorAttachments[i] && colorAttachments[i].texture) {\n            var colorAttachmentSize = textureFormatChannels[colorAttachments[i].texture._texture.format] * textureTypeSizes[colorAttachments[i].texture._texture.type];\n            if (commonColorAttachmentSize === null) {\n              commonColorAttachmentSize = colorAttachmentSize;\n            } else {\n              // We need to make sure that all color attachments have the same number of bitplanes\n              // (that is, the same numer of bits per pixel)\n              // This is required by the GLES2.0 standard. See the beginning of Chapter 4 in that document.\n              check$1(commonColorAttachmentSize === colorAttachmentSize, 'all color attachments much have the same number of bits per pixel.');\n            }\n          }\n        }\n        incRefAndCheckShape(depthAttachment, width, height);\n        check$1(!depthAttachment || depthAttachment.texture && depthAttachment.texture._texture.format === GL_DEPTH_COMPONENT$1 || depthAttachment.renderbuffer && depthAttachment.renderbuffer._renderbuffer.format === GL_DEPTH_COMPONENT16$1, 'invalid depth attachment for framebuffer object');\n        incRefAndCheckShape(stencilAttachment, width, height);\n        check$1(!stencilAttachment || stencilAttachment.renderbuffer && stencilAttachment.renderbuffer._renderbuffer.format === GL_STENCIL_INDEX8$1, 'invalid stencil attachment for framebuffer object');\n        incRefAndCheckShape(depthStencilAttachment, width, height);\n        check$1(!depthStencilAttachment || depthStencilAttachment.texture && depthStencilAttachment.texture._texture.format === GL_DEPTH_STENCIL$2 || depthStencilAttachment.renderbuffer && depthStencilAttachment.renderbuffer._renderbuffer.format === GL_DEPTH_STENCIL$2, 'invalid depth-stencil attachment for framebuffer object');\n\n        // decrement references\n        decFBORefs(framebuffer);\n        framebuffer.width = width;\n        framebuffer.height = height;\n        framebuffer.colorAttachments = colorAttachments;\n        framebuffer.depthAttachment = depthAttachment;\n        framebuffer.stencilAttachment = stencilAttachment;\n        framebuffer.depthStencilAttachment = depthStencilAttachment;\n        reglFramebuffer.color = colorAttachments.map(unwrapAttachment);\n        reglFramebuffer.depth = unwrapAttachment(depthAttachment);\n        reglFramebuffer.stencil = unwrapAttachment(stencilAttachment);\n        reglFramebuffer.depthStencil = unwrapAttachment(depthStencilAttachment);\n        reglFramebuffer.width = framebuffer.width;\n        reglFramebuffer.height = framebuffer.height;\n        updateFramebuffer(framebuffer);\n        return reglFramebuffer;\n      }\n      function resize(w_, h_) {\n        check$1(framebufferState.next !== framebuffer, 'can not resize a framebuffer which is currently in use');\n        var w = Math.max(w_ | 0, 1);\n        var h = Math.max(h_ | 0 || w, 1);\n        if (w === framebuffer.width && h === framebuffer.height) {\n          return reglFramebuffer;\n        }\n\n        // resize all buffers\n        var colorAttachments = framebuffer.colorAttachments;\n        for (var i = 0; i < colorAttachments.length; ++i) {\n          resizeAttachment(colorAttachments[i], w, h);\n        }\n        resizeAttachment(framebuffer.depthAttachment, w, h);\n        resizeAttachment(framebuffer.stencilAttachment, w, h);\n        resizeAttachment(framebuffer.depthStencilAttachment, w, h);\n        framebuffer.width = reglFramebuffer.width = w;\n        framebuffer.height = reglFramebuffer.height = h;\n        updateFramebuffer(framebuffer);\n        return reglFramebuffer;\n      }\n      reglFramebuffer(a0, a1);\n      return extend(reglFramebuffer, {\n        resize: resize,\n        _reglType: 'framebuffer',\n        _framebuffer: framebuffer,\n        destroy: function destroy() {\n          _destroy(framebuffer);\n          decFBORefs(framebuffer);\n        },\n        use: function use(block) {\n          framebufferState.setFBO({\n            framebuffer: reglFramebuffer\n          }, block);\n        }\n      });\n    }\n    function createCubeFBO(options) {\n      var faces = Array(6);\n      function reglFramebufferCube(a) {\n        var i;\n        check$1(faces.indexOf(framebufferState.next) < 0, 'can not update framebuffer which is currently in use');\n        var params = {\n          color: null\n        };\n        var radius = 0;\n        var colorBuffer = null;\n        var colorFormat = 'rgba';\n        var colorType = 'uint8';\n        var colorCount = 1;\n        if (typeof a === 'number') {\n          radius = a | 0;\n        } else if (!a) {\n          radius = 1;\n        } else {\n          check$1.type(a, 'object', 'invalid arguments for framebuffer');\n          var options = a;\n          if ('shape' in options) {\n            var shape = options.shape;\n            check$1(Array.isArray(shape) && shape.length >= 2, 'invalid shape for framebuffer');
1\n            check$1(shape[0] === shape[1], 'cube framebuffer must be square');\n            radius = shape[0];\n          } else {\n            if ('radius' in options) {\n              radius = options.radius | 0;\n            }\n            if ('width' in options) {\n              radius = options.width | 0;\n              if ('height' in options) {\n                check$1(options.height === radius, 'must be square');\n              }\n            } else if ('height' in options) {\n              radius = options.height | 0;\n            }\n          }\n          if ('color' in options || 'colors' in options) {\n            colorBuffer = options.color || options.colors;\n            if (Array.isArray(colorBuffer)) {\n              check$1(colorBuffer.length === 1 || extensions.webgl_draw_buffers, 'multiple render targets not supported');\n            }\n          }\n          if (!colorBuffer) {\n            if ('colorCount' in options) {\n              colorCount = options.colorCount | 0;\n              check$1(colorCount > 0, 'invalid color buffer count');\n            }\n            if ('colorType' in options) {\n              check$1.oneOf(options.colorType, colorTypes, 'invalid color type');\n              colorType = options.colorType;\n            }\n            if ('colorFormat' in options) {\n              colorFormat = options.colorFormat;\n              check$1.oneOf(options.colorFormat, colorTextureFormats, 'invalid color format for texture');\n            }\n          }\n          if ('depth' in options) {\n            params.depth = options.depth;\n          }\n          if ('stencil' in options) {\n            params.stencil = options.stencil;\n          }\n          if ('depthStencil' in options) {\n            params.depthStencil = options.depthStencil;\n          }\n        }\n        var colorCubes;\n        if (colorBuffer) {\n          if (Array.isArray(colorBuffer)) {\n            colorCubes = [];\n            for (i = 0; i < colorBuffer.length; ++i) {\n              colorCubes[i] = colorBuffer[i];\n            }\n          } else {\n            colorCubes = [colorBuffer];\n          }\n        } else {\n          colorCubes = Array(colorCount);\n          var cubeMapParams = {\n            radius: radius,\n            format: colorFormat,\n            type: colorType\n          };\n          for (i = 0; i < colorCount; ++i) {\n            colorCubes[i] = textureState.createCube(cubeMapParams);\n          }\n        }\n\n        // Check color cubes\n        params.color = Array(colorCubes.length);\n        for (i = 0; i < colorCubes.length; ++i) {\n          var cube = colorCubes[i];\n          check$1(typeof cube === 'function' && cube._reglType === 'textureCube', 'invalid cube map');\n          radius = radius || cube.width;\n          check$1(cube.width === radius && cube.height === radius, 'invalid cube map shape');\n          params.color[i] = {\n            target: GL_TEXTURE_CUBE_MAP_POSITIVE_X$2,\n            data: colorCubes[i]\n          };\n        }\n        for (i = 0; i < 6; ++i) {\n          for (var j = 0; j < colorCubes.length; ++j) {\n            params.color[j].target = GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 + i;\n          }\n          // reuse depth-stencil attachments across all cube maps\n          if (i > 0) {\n            params.depth = faces[0].depth;\n            params.stencil = faces[0].stencil;\n            params.depthStencil = faces[0].depthStencil;\n          }\n          if (faces[i]) {\n            faces[i](params);\n          } else {\n            faces[i] = createFBO(params);\n          }\n        }\n        return extend(reglFramebufferCube, {\n          width: radius,\n          height: radius,\n          color: colorCubes\n        });\n      }\n      function resize(radius_) {\n        var i;\n        var radius = radius_ | 0;\n        check$1(radius > 0 && radius <= limits.maxCubeMapSize, 'invalid radius for cube fbo');\n        if (radius === reglFramebufferCube.width) {\n          return reglFramebufferCube;\n        }\n        var colors = reglFramebufferCube.color;\n        for (i = 0; i < colors.length; ++i) {\n          colors[i].resize(radius);\n        }\n        for (i = 0; i < 6; ++i) {\n          faces[i].resize(radius);\n        }\n        reglFramebufferCube.width = reglFramebufferCube.height = radius;\n        return reglFramebufferCube;\n      }\n      reglFramebufferCube(options);\n      return extend(reglFramebufferCube, {\n        faces: faces,\n        resize: resize,\n        _reglType: 'framebufferCube',\n        destroy: function destroy() {\n          faces.forEac
1h(function (f) {\n            f.destroy();\n          });\n        }\n      });\n    }\n    function restoreFramebuffers() {\n      framebufferState.cur = null;\n      framebufferState.next = null;\n      framebufferState.dirty = true;\n      values(framebufferSet).forEach(function (fb) {\n        fb.framebuffer = gl.createFramebuffer();\n        updateFramebuffer(fb);\n      });\n    }\n    return extend(framebufferState, {\n      getFramebuffer: function getFramebuffer(object) {\n        if (typeof object === 'function' && object._reglType === 'framebuffer') {\n          var fbo = object._framebuffer;\n          if (fbo instanceof REGLFramebuffer) {\n            return fbo;\n          }\n        }\n        return null;\n      },\n      create: createFBO,\n      createCube: createCubeFBO,\n      clear: function clear() {\n        values(framebufferSet).forEach(_destroy);\n      },\n      restore: restoreFramebuffers\n    });\n  }\n  var GL_FLOAT$6 = 5126;\n  var GL_ARRAY_BUFFER$1 = 34962;\n  var GL_ELEMENT_ARRAY_BUFFER$1 = 34963;\n  var VAO_OPTIONS = ['attributes', 'elements', 'offset', 'count', 'primitive', 'instances'];\n  function AttributeRecord() {\n    this.state = 0;\n    this.x = 0.0;\n    this.y = 0.0;\n    this.z = 0.0;\n    this.w = 0.0;\n    this.buffer = null;\n    this.size = 0;\n    this.normalized = false;\n    this.type = GL_FLOAT$6;\n    this.offset = 0;\n    this.stride = 0;\n    this.divisor = 0;\n  }\n  function wrapAttributeState(gl, extensions, limits, stats, bufferState, elementState, drawState) {\n    var NUM_ATTRIBUTES = limits.maxAttributes;\n    var attributeBindings = new Array(NUM_ATTRIBUTES);\n    for (var i = 0; i < NUM_ATTRIBUTES; ++i) {\n      attributeBindings[i] = new AttributeRecord();\n    }\n    var vaoCount = 0;\n    var vaoSet = {};\n    var state = {\n      Record: AttributeRecord,\n      scope: {},\n      state: attributeBindings,\n      currentVAO: null,\n      targetVAO: null,\n      restore: extVAO() ? restoreVAO : function () {},\n      createVAO: createVAO,\n      getVAO: getVAO,\n      destroyBuffer: destroyBuffer,\n      setVAO: extVAO() ? setVAOEXT : setVAOEmulated,\n      clear: extVAO() ? destroyVAOEXT : function () {}\n    };\n    function destroyBuffer(buffer) {\n      for (var i = 0; i < attributeBindings.length; ++i) {\n        var record = attributeBindings[i];\n        if (record.buffer === buffer) {\n          gl.disableVertexAttribArray(i);\n          record.buffer = null;\n        }\n      }\n    }\n    function extVAO() {\n      return extensions.oes_vertex_array_object;\n    }\n    function extInstanced() {\n      return extensions.angle_instanced_arrays;\n    }\n    function getVAO(vao) {\n      if (typeof vao === 'function' && vao._vao) {\n        return vao._vao;\n      }\n      return null;\n    }\n    function setVAOEXT(vao) {\n      if (vao === state.currentVAO) {\n        return;\n      }\n      var ext = extVAO();\n      if (vao) {\n        ext.bindVertexArrayOES(vao.vao);\n      } else {\n        ext.bindVertexArrayOES(null);\n      }\n      state.currentVAO = vao;\n    }\n    function setVAOEmulated(vao) {\n      if (vao === state.currentVAO) {\n        return;\n      }\n      if (vao) {\n        vao.bindAttrs();\n      } else {\n        var exti = extInstanced();\n        for (var i = 0; i < attributeBindings.length; ++i) {\n          var binding = attributeBindings[i];\n          if (binding.buffer) {\n            gl.enableVertexAttribArray(i);\n            binding.buffer.bind();\n            gl.vertexAttribPointer(i, binding.size, binding.type, binding.normalized, binding.stride, binding.offfset);\n            if (exti && binding.divisor) {\n              exti.vertexAttribDivisorANGLE(i, binding.divisor);\n            }\n          } else {\n            gl.disableVertexAttribArray(i);\n            gl.vertexAttrib4f(i, binding.x, binding.y, binding.z, binding.w);\n          }\n        }\n        if (drawState.elements) {\n          gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER$1, drawState.elements.buffer.buffer);\n        } else {\n          gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER$1, null);\n        }\n      }\n      state.currentVAO = vao;\n    }\n    function destroyVAOEXT() {\n      values(vaoSet).forEach(function (vao) {\n        vao.destroy();\n      });\n    }\n    function REGLVAO() {\n      this.id = ++vaoCount;\n      this.attributes = [];\n      this.elements = null;\n      this.ownsElements = false;\n      this.count = 0;\n      this.offset = 0;\n      this.instances = -1;\n      this.primitive = 4;\n      var extension = extVAO();\n      if (extension) {\n        this.vao = extension.createVertexArrayOES();\n      } else {\n        this.vao = null;\n      }\n      vaoSet[this.id] = this;\n      this.buffers = [];\n    }\n    REGLVAO.prototype.bindAttrs = function () {\n      var exti = extInstanced();\n      var attributes = this.attributes;\n      for (var i = 0; i < attributes.length; ++i) {\n        var attr = attributes[i];\n        if (attr.buffer) {\n          gl.enableVertexAttribArray(i);\n          gl.bindBuffer(GL_ARRAY_BUFFER$1, attr.buffer.buffer);\n          gl.vertexAttribPointer(i, attr.size, attr.type, attr.normalized, attr.stride, attr.offset);\n          if (exti && attr.divisor) {\n            exti.vertexAttribDivisorANGLE(i, attr.divisor);\n          }\n        } else {\n          gl.disableVertexAttribArray(i);\n          gl.vertexAttrib4f(i, attr.x, attr.y, attr.z, attr.w);\n        }\n      }\n      for (var j = attributes.length; j < NUM_ATTRIBUTES; ++j) {\n        gl.disableVertexAttribArray(j);\n      }\n      var elements = elementState.getElements(this.elements);\n      if (elements) {\n        gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER$1, elements.buffer.buffer);\n      } else {\n        gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER$1, null);\n      }\n    };\n    REGLVAO.prototype.refresh = function () {\n      var ext = extVAO();\n      if (ext) {\n        ext.bindVertexArrayOES(this.vao);\n        this.bindAttrs();\n        state.currentVAO = null;\n        ext.bindVertexArrayOES(null);\n      }\n    };\n    REGLVAO.prototype.destroy = function () {\n      if (this.vao) {\n        var extension = extVAO();\n        if (this === state.currentVAO) {\n          state.currentVAO = null;\n          extension.bindVertexArrayOES(null);\n        }\n        extension.deleteVertexArrayOES(this.vao);\n        this.vao = null;\n      }\n      if (this.ownsElements) {\n        this.elements.destroy();\n        this.elements = null;\n        this.ownsElements = false;\n      }\n      if (vaoSet[this.id]) {\n        delete vaoSet[this.id];\n        stats.vaoCount -= 1;\n      }\n    };\n    function restoreVAO() {\n      var ext = extVAO();\n      if (ext) {\n        values(vaoSet).forEach(function (vao) {\n          vao.refresh();\n        });\n      }\n    }\n    function createVAO(_attr) {\n      var vao = new REGLVAO();\n      stats.vaoCount += 1;\n      function updateVAO(options) {\n        var attributes;\n        if (Array.isArray(options)) {\n          attributes = options;\n          if (vao.elements && vao.ownsElements) {\n            vao.elements.destroy();\n          }\n          vao.elements = null;\n          vao.ownsElements = false;\n          vao.offset = 0;\n          vao.count = 0;\n          vao.instances = -1;\n          vao.primitive = 4;\n        } else {\n          check$1(typeof options === 'object', 'invalid arguments for create vao');
1\n          check$1('attributes' in options, 'must specify attributes for vao');\n          if (options.elements) {\n            var elements = options.elements;\n            if (vao.ownsElements) {\n              if (typeof elements === 'function' && elements._reglType === 'elements') {\n                vao.elements.destroy();\n                vao.ownsElements = false;\n              } else {\n                vao.elements(elements);\n                vao.ownsElements = false;\n              }\n            } else if (elementState.getElements(options.elements)) {\n              vao.elements = options.elements;\n              vao.ownsElements = false;\n            } else {\n              vao.elements = elementState.create(options.elements);\n              vao.ownsElements = true;\n            }\n          } else {\n            vao.elements = null;\n            vao.ownsElements = false;\n          }\n          attributes = options.attributes;\n\n          // set default vao\n          vao.offset = 0;\n          vao.count = -1;\n          vao.instances = -1;\n          vao.primitive = 4;\n\n          // copy element properties\n          if (vao.elements) {\n            vao.count = vao.elements._elements.vertCount;\n            vao.primitive = vao.elements._elements.primType;\n          }\n          if ('offset' in options) {\n            vao.offset = options.offset | 0;\n          }\n          if ('count' in options) {\n            vao.count = options.count | 0;\n          }\n          if ('instances' in options) {\n            vao.instances = options.instances | 0;\n          }\n          if ('primitive' in options) {\n            check$1(options.primitive in primTypes, 'bad primitive type: ' + options.primitive);\n            vao.primitive = primTypes[options.primitive];\n          }\n          check$1.optional(function () {\n            var keys = Object.keys(options);\n            for (var i = 0; i < keys.length; ++i) {\n              check$1(VAO_OPTIONS.indexOf(keys[i]) >= 0, 'invalid option for vao: \"' + keys[i] + '\" valid options are ' + VAO_OPTIONS);\n            }\n          });\n          check$1(Array.isArray(attributes), 'attributes must be an array');\n        }\n        check$1(attributes.length < NUM_ATTRIBUTES, 'too many attributes');\n        check$1(attributes.length > 0, 'must specify at least one attribute');\n        var bufUpdated = {};\n        var nattributes = vao.attributes;\n        nattributes.length = attributes.length;\n        for (var i = 0; i < attributes.length; ++i) {\n          var spec = attributes[i];\n          var rec = nattributes[i] = new AttributeRecord();\n          var data = spec.data || spec;\n          if (Array.isArray(data) || isTypedArray(data) || isNDArrayLike(data)) {\n            var buf;\n            if (vao.buffers[i]) {\n              buf = vao.buffers[i];\n              if (isTypedArray(data) && buf._buffer.byteLength >= data.byteLength) {\n                buf.subdata(data);\n              } else {\n                buf.destroy();\n                vao.buffers[i] = null;\n              }\n            }\n            if (!vao.buffers[i]) {\n              buf = vao.buffers[i] = bufferState.create(spec, GL_ARRAY_BUFFER$1, false, true);\n            }\n            rec.buffer = bufferState.getBuffer(buf);\n            rec.size = rec.buffer.dimension | 0;\n            rec.normalized = false;\n            rec.type = rec.buffer.dtype;\n            rec.offset = 0;\n            rec.stride = 0;\n            rec.divisor = 0;\n            rec.state = 1;\n            bufUpdated[i] = 1;\n          } else if (bufferState.getBuffer(spec)) {\n            rec.buffer = bufferState.getBuffer(spec);\n            rec.size = rec.buffer.dimension | 0;\n            rec.normalized = false;\n            rec.type = rec.buffer.dtype;\n            rec.offset = 0;\n            rec.stride = 0;\n            rec.divisor = 0;\n            rec.state = 1;\n          } else if (bufferState.getBuffer(spec.buffer)) {\n            rec.buffer = bufferState.getBuffer(spec.buffer);\n            rec.size = (+spec.size || rec.buffer.dimension) | 0;\n            rec.normalized = !!spec.normalized || false;\n            if ('type' in spec) {\n              check$1.parameter(spec.type, glTypes, 'invalid buffer type');\n              rec.type = glTypes[spec.type];\n            } else {\n              rec.type = rec.buffer.dtype;\n            }\n            rec.offset = (spec.offset || 0) | 0;\n            rec.stride = (spec.stride || 0) | 0;\n            rec.divisor = (spec.divisor || 0) | 0;\n            rec.state = 1;\n            check$1(rec.size >= 1 && rec.size <= 4, 'size must be between 1 and 4');\n            check$1(rec.offset >= 0, 'invalid offset');\n            check$1(rec.stride >= 0 && rec.stride <= 255, 'stride must be between 0 and 255');\n            check$1(rec.divisor >= 0, 'divisor must be positive');\n            check$1(!rec.divisor || !!extensions.angle_instanced_arrays, 'ANGLE_instanced_arrays must be enabled to use divisor');\n          } else if ('x' in spec) {\n            check$1(i > 0, 'first attribute must not be a constant');\n            rec.x = +spec.x || 0;\n            rec.y = +spec.y || 0;\n            rec.z = +spec.z || 0;\n            rec.w = +spec.w || 0;\n            rec.state = 2;\n          } else {\n            check$1(false, 'invalid attribute spec for location ' + i);\n          }\n        }\n\n        // retire unused buffers\n        for (var j = 0; j < vao.buffers.length; ++j) {\n          if (!bufUpdated[j] && vao.buffers[j]) {\n            vao.buffers[j].destroy();\n            vao.buffers[j] = null;\n          }\n        }\n        vao.refresh();\n        return updateVAO;\n      }\n      updateVAO.destroy = function () {\n        for (var j = 0; j < vao.buffers.length; ++j) {\n          if (vao.buffers[j]) {\n            vao.buffers[j].destroy();\n          }\n        }\n        vao.buffers.length = 0;\n        if (vao.ownsElements) {\n          vao.elements.destroy();\n          vao.elements = null;\n          vao.ownsElements = false;\n        }\n        vao.destroy();\n      };\n      updateVAO._vao = vao;\n      updateVAO._reglType = 'vao';\n      return updateVAO(_attr);\n    }\n    return state;\n  }\n  var GL_FRAGMENT_SHADER = 35632;\n  var GL_VERTEX_SHADER = 35633;\n  var GL_ACTIVE_UNIFORMS = 0x8B86;\n  var GL_ACTIVE_ATTRIBUTES = 0x8B89;\n  function wrapShaderState(gl, stringStore, stats, config) {\n    // ===================================================\n    // glsl compilation and linking\n    // ===================================================\n    var fragShaders = {};\n    var vertShaders = {};\n    function ActiveInfo(name, id, location, info) {\n      this.name = name;\n      this.id = id;\n      this.location = location;\n      this.info = info;\n    }\n    function insertActiveInfo(list, info) {\n      for (var i = 0; i < list.length; ++i) {\n        if (list[i].id === info.id) {\n          list[i].location = info.location;\n          return;\n        }\n      }\n      list.push(info);\n    }\n    function getShader(type, id, command) {\n      var cache = type === GL_FRAGMENT_SHADER ? fragShaders : vertShaders;\n      var shader = cache[id];\n      if (!shader) {\n        var source = stringStore.str(id);\n        shader = gl.createShader(type);\n        gl.shaderSource(shader, source);\n        gl.compileShader(shader);\n        check$1.shaderError(gl, shader, source, type, command);\n        cache[id] = shader;\n      }\n      return shader;\n    }\n\n    // ===================================================\n    // program linking\n    // ===================================================\n    var programCache = {};\n    var programList = [];\n    var PROGRAM_COUNTER = 0;\n    function REGLProgram(fragId, vertId) {\n      this.id = PROGRAM_COUNTER++;\n      this.fragId = fragId;\n      this.vertId = vertId;\n      this.program = null;\n      this.uniforms = [];\n      this.attributes = [];\n      this.refCount = 1;\n      if (config.profile) {\n        this.stats = {\n          uniformsCount: 0,\n          attributesCount: 0\n        };\n      }\n    }\n    function linkProgram(desc, command, attributeLocations) {\n      var i, info;\n\n      // -------------------------------\n      // compile & link\n      // -------------------------------\n      var fragShader = getShader(GL_FRAGMENT_SHADER, desc.fragId);\n      var vertShader = getShader(GL_VERTEX_SHADER, desc.vertId);\n      var program = desc.program = gl.createProgram();\n      gl.attachShader(program, fragShader);\n      gl.attachShader(program, vertShader);\n      if (attributeLocations) {\n        for (i = 0; i < attributeLocations.length; ++i) {\n          var binding = attributeLocations[i];\n          gl.bindAttribLocation(program, binding[0], binding[1]);\n        }\n      }\n      gl.linkProgram(program);\n      check$1.linkError(gl, program, stringStore.str(desc.fragId), stringStore.str(desc.vertId), command);\n\n      // -------------------------------\n      // grab uniforms\n      // -------------------------------\n      var numUniforms = gl.getProgramParameter(program, GL_ACTIVE_UNIFORMS);\n      if (config.profile) {\n        desc.stats.uniformsCount = numUniforms;\n      }\n      var uniforms = desc.uniforms;\n      for (i = 0; i < numUniforms; ++i) {\n        info = gl.getActiveUniform(program, i);\n        if (info) {\n          if (info.size > 1) {\n            for (var j = 0; j < info.size; ++j) {\n              var name = info.name.replace('[0]', '[' + j + ']');\n              insertActiveInfo(uniforms, new ActiveInfo(name, stringStore.id(name), gl.getUniformLocation(program, name), info));\n            }\n          } else {\n            insertActiveInfo(uniforms, new ActiveInfo(info.name, stringStore.id(info.name), gl.getUniformLocation(program, info.name), info));\n          }\n        }\n      }\n\n      // -------------------------------\n      // grab attributes\n      // -------------------------------\n      var numAttributes = gl.getProgramParameter(program, GL_ACTIVE_ATTRIBUTES);\n      if (config.profile) {\n        desc.stats.attributesCount = numAttributes;\n      }\n      var attributes = desc.attributes;\n      for (i = 0; i < numAttributes; ++i) {\n        info = gl.getActiveAttrib(program, i);\n        if (info) {\n          insertActiveInfo(attributes, new ActiveInfo(info.name, stringStore.id(info.name), gl.getAttribLocation(program, info.name), info));\n        }\n      }\n    }\n    if (config.profile) {\n      stats.getMaxUniformsCount = function () {\n        var m = 0;\n        programList.forEach(function (desc) {\n          if (desc.stats.uniformsCount > m) {\n            m = desc.stats.uniformsCount;\n          }\n        });\n        return m;\n      };\n      stats.getMaxAttributesCount = function () {\n        var m = 0;\n        programList.forEach(function (desc) {\n          if (desc.stats.attributesCount > m) {\n            m = desc.stats.attributesCount;\n          }\n        });\n        return m;\n      };\n    }\n    function restoreShaders() {\n      fragShaders = {};\n      vertShaders = {};\n      for (var i = 0; i < programList.length; ++i) {\n        linkProgram(programList[i], null, programList[i].attributes.map(function (info) {\n          return [info.location, info.name];\n        }));\n      }\n    }\n    return {\n      clear: function clear() {\n        var deleteShader = gl.deleteShader.bind(gl);
1\n        values(fragShaders).forEach(deleteShader);\n        fragShaders = {};\n        values(vertShaders).forEach(deleteShader);\n        vertShaders = {};\n        programList.forEach(function (desc) {\n          gl.deleteProgram(desc.program);\n        });\n        programList.length = 0;\n        programCache = {};\n        stats.shaderCount = 0;\n      },\n      program: function program(vertId, fragId, command, attribLocations) {\n        check$1.command(vertId >= 0, 'missing vertex shader', command);\n        check$1.command(fragId >= 0, 'missing fragment shader', command);\n        var cache = programCache[fragId];\n        if (!cache) {\n          cache = programCache[fragId] = {};\n        }\n        var prevProgram = cache[vertId];\n        if (prevProgram) {\n          prevProgram.refCount++;\n          if (!attribLocations) {\n            return prevProgram;\n          }\n        }\n        var program = new REGLProgram(fragId, vertId);\n        stats.shaderCount++;\n        linkProgram(program, command, attribLocations);\n        if (!prevProgram) {\n          cache[vertId] = program;\n        }\n        programList.push(program);\n        return extend(program, {\n          destroy: function destroy() {\n            program.refCount--;\n            if (program.refCount <= 0) {\n              gl.deleteProgram(program.program);\n              var idx = programList.indexOf(program);\n              programList.splice(idx, 1);\n              stats.shaderCount--;\n            }\n            // no program is linked to this vert anymore\n            if (cache[program.vertId].refCount <= 0) {\n              gl.deleteShader(vertShaders[program.vertId]);\n              delete vertShaders[program.vertId];\n              delete programCache[program.fragId][program.vertId];\n            }\n            // no program is linked to this frag anymore\n            if (!Object.keys(programCache[program.fragId]).length) {\n              gl.deleteShader(fragShaders[program.fragId]);\n              delete fragShaders[program.fragId];\n              delete programCache[program.fragId];\n            }\n          }\n        });\n      },\n      restore: restoreShaders,\n      shader: getShader,\n      frag: -1,\n      vert: -1\n    };\n  }\n  var GL_RGBA$3 = 6408;\n  var GL_UNSIGNED_BYTE$7 = 5121;\n  var GL_PACK_ALIGNMENT = 0x0D05;\n  var GL_FLOAT$7 = 0x1406; // 5126\n\n  function wrapReadPixels(gl, framebufferState, reglPoll, context, glAttributes, extensions, limits) {\n    function readPixelsImpl(input) {\n      var type;\n      if (framebufferState.next === null) {\n        check$1(glAttributes.preserveDrawingBuffer, 'you must create a webgl context with \"preserveDrawingBuffer\":true in order to read pixels from the drawing buffer');\n        type = GL_UNSIGNED_BYTE$7;\n      } else {\n        check$1(framebufferState.next.colorAttachments[0].texture !== null, 'You cannot read from a renderbuffer');\n        type = framebufferState.next.colorAttachments[0].texture._texture.type;\n        check$1.optional(function () {\n          if (extensions.oes_texture_float) {\n            check$1(type === GL_UNSIGNED_BYTE$7 || type === GL_FLOAT$7, 'Reading from a framebuffer is only allowed for the types \\'uint8\\' and \\'float\\'');\n            if (type === GL_FLOAT$7) {\n              check$1(limits.readFloat, 'Reading \\'float\\' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float');\n            }\n          } else {\n            check$1(type === GL_UNSIGNED_BYTE$7, 'Reading from a framebuffer is only allowed for the type \\'uint8\\'');\n          }\n        });\n      }\n      var x = 0;\n      var y = 0;\n      var width = context.framebufferWidth;\n      var height = context.framebufferHeight;\n      var data = null;\n      if (isTypedArray(input)) {\n        data = input;\n      } else if (input) {\n        check$1.type(input, 'object', 'invalid arguments to regl.read()');\n        x = input.x | 0;\n        y = input.y | 0;\n        check$1(x >= 0 && x < context.framebufferWidth, 'invalid x offset for regl.read');\n        check$1(y >= 0 && y < context.framebufferHeight, 'invalid y offset for regl.read');\n        width = (input.width || context.framebufferWidth - x) | 0;\n        height = (input.height || context.framebufferHeight - y) | 0;\n        data = input.data || null;\n      }
1\n\n      // sanity check input.data\n      if (data) {\n        if (type === GL_UNSIGNED_BYTE$7) {\n          check$1(data instanceof Uint8Array, 'buffer must be \\'Uint8Array\\' when reading from a framebuffer of type \\'uint8\\'');\n        } else if (type === GL_FLOAT$7) {\n          check$1(data instanceof Float32Array, 'buffer must be \\'Float32Array\\' when reading from a framebuffer of type \\'float\\'');\n        }\n      }\n      check$1(width > 0 && width + x <= context.framebufferWidth, 'invalid width for read pixels');\n      check$1(height > 0 && height + y <= context.framebufferHeight, 'invalid height for read pixels');\n\n      // Update WebGL state\n      reglPoll();\n\n      // Compute size\n      var size = width * height * 4;\n\n      // Allocate data\n      if (!data) {\n        if (type === GL_UNSIGNED_BYTE$7) {\n          data = new Uint8Array(size);\n        } else if (type === GL_FLOAT$7) {\n          data = data || new Float32Array(size);\n        }\n      }\n\n      // Type check\n      check$1.isTypedArray(data, 'data buffer for regl.read() must be a typedarray');\n      check$1(data.byteLength >= size, 'data buffer for regl.read() too small');\n\n      // Run read pixels\n      gl.pixelStorei(GL_PACK_ALIGNMENT, 4);\n      gl.readPixels(x, y, width, height, GL_RGBA$3, type, data);\n      return data;\n    }\n    function readPixelsFBO(options) {\n      var result;\n      framebufferState.setFBO({\n        framebuffer: options.framebuffer\n      }, function () {\n        result = readPixelsImpl(options);\n      });\n      return result;\n    }\n    function readPixels(options) {\n      if (!options || !('framebuffer' in options)) {\n        return readPixelsImpl(options);\n      } else {\n        return readPixelsFBO(options);\n      }\n    }\n    return readPixels;\n  }\n  function slice(x) {\n    return Array.prototype.slice.call(x);\n  }\n  function join(x) {\n    return slice(x).join('');\n  }\n  function createEnvironment() {\n    // Unique variable id counter\n    var varCounter = 0;\n\n    // Linked values are passed from this scope into the generated code block\n    // Calling link() passes a value into the generated scope and returns\n    // the variable name which it is bound to\n    var linkedNames = [];\n    var linkedValues = [];\n    function link(value) {\n      for (var i = 0; i < linkedValues.length; ++i) {\n        if (linkedValues[i] === value) {\n          return linkedNames[i];\n        }\n      }\n      var name = 'g' + varCounter++;\n      linkedNames.push(name);\n      linkedValues.push(value);\n      return name;\n    }\n\n    // create a code block\n    function block() {\n      var code = [];\n      function push() {\n        code.push.apply(code, slice(arguments));\n      }\n      var vars = [];\n      function def() {\n        var name = 'v' + varCounter++;\n        vars.push(name);\n        if (arguments.length > 0) {\n          code.push(name, '=');\n          code.push.apply(code, slice(arguments));\n          code.push(';');\n        }\n        return name;\n      }\n      return extend(push, {\n        def: def,\n        toString: function toString() {\n          return join([vars.length > 0 ? 'var ' + vars.join(',') + ';' : '', join(code)]);\n        }\n      });\n    }\n    function scope() {\n      var entry = block();\n      var exit = block();\n      var entryToString = entry.toString;\n      var exitToString = exit.toString;\n      function save(object, prop) {\n        exit(object, prop, '=', entry.def(object, prop), ';');\n      }\n      return extend(function () {\n        entry.apply(entry, slice(arguments));\n      }, {\n        def: entry.def,\n        entry: entry,\n        exit: exit,\n        save: save,\n        set: function set(object, prop, value) {\n          save(object, prop);\n          entry(object, prop, '=', value, ';');\n        },\n        toString: function toString() {\n          return entryToString() + exitToString();\n        }\n      });\n    }\n    function conditional() {\n      var pred = join(arguments);\n      var thenBlock = scope();\n      var elseBlock = scope();\n      var thenToString = thenBlock.toString;\n      var elseToString = elseBlock.toString;\n      return extend(thenBlock, {\n        then: function then() {\n          thenBlock.apply(thenBlock, slice(arguments));\n          return this;\n        },\n        else: function _else() {\n          elseBlock.apply(elseBlock, slice(arguments));\n          return this;\n        },\n        toString: function toString() {\n          var elseClause = elseToString();\n          if (elseClause) {\n            elseClause = 'else{' + elseClause + '}';\n          }\n          return join(['if(', pred, '){', thenToString(), '}', elseClause]);\n        }\n      });\n    }\n\n    // procedure list\n    var globalBlock = block();\n    var procedures = {};\n    function proc(name, count) {\n      var args = [];\n      function arg() {\n        var name = 'a' + args.length;\n        args.push(name);\n        return name;\n      }\n      count = count || 0;\n      for (var i = 0; i < count; ++i) {\n        arg();\n      }\n      var body = scope();\n      var bodyToString = body.toString;\n      var result = procedures[name] = extend(body, {\n        arg: arg,\n        toString: function toString() {\n          return join(['function(', args.join(), '){', bodyToString(), '}']);\n        }\n      });\n      return result;\n    }\n    function compile() {\n      var code = ['\"use strict\";', globalBlock, 'return {'];
1\n      Object.keys(procedures).forEach(function (name) {\n        code.push('\"', name, '\":', procedures[name].toString(), ',');\n      });\n      code.push('}');\n      var src = join(code).replace(/;/g, ';\\n').replace(/}/g, '}\\n').replace(/{/g, '{\\n');\n      var proc = Function.apply(null, linkedNames.concat(src));\n      return proc.apply(null, linkedValues);\n    }\n    return {\n      global: globalBlock,\n      link: link,\n      block: block,\n      proc: proc,\n      scope: scope,\n      cond: conditional,\n      compile: compile\n    };\n  }\n\n  // \"cute\" names for vector components\n  var CUTE_COMPONENTS = 'xyzw'.split('');\n  var GL_UNSIGNED_BYTE$8 = 5121;\n  var ATTRIB_STATE_POINTER = 1;\n  var ATTRIB_STATE_CONSTANT = 2;\n  var DYN_FUNC$1 = 0;\n  var DYN_PROP$1 = 1;\n  var DYN_CONTEXT$1 = 2;\n  var DYN_STATE$1 = 3;\n  var DYN_THUNK = 4;\n  var DYN_CONSTANT$1 = 5;\n  var DYN_ARRAY$1 = 6;\n  var S_DITHER = 'dither';\n  var S_BLEND_ENABLE = 'blend.enable';\n  var S_BLEND_COLOR = 'blend.color';\n  var S_BLEND_EQUATION = 'blend.equation';\n  var S_BLEND_FUNC = 'blend.func';\n  var S_DEPTH_ENABLE = 'depth.enable';\n  var S_DEPTH_FUNC = 'depth.func';\n  var S_DEPTH_RANGE = 'depth.range';\n  var S_DEPTH_MASK = 'depth.mask';\n  var S_COLOR_MASK = 'colorMask';\n  var S_CULL_ENABLE = 'cull.enable';\n  var S_CULL_FACE = 'cull.face';\n  var S_FRONT_FACE = 'frontFace';\n  var S_LINE_WIDTH = 'lineWidth';\n  var S_POLYGON_OFFSET_ENABLE = 'polygonOffset.enable';\n  var S_POLYGON_OFFSET_OFFSET = 'polygonOffset.offset';\n  var S_SAMPLE_ALPHA = 'sample.alpha';\n  var S_SAMPLE_ENABLE = 'sample.enable';\n  var S_SAMPLE_COVERAGE = 'sample.coverage';\n  var S_STENCIL_ENABLE = 'stencil.enable';\n  var S_STENCIL_MASK = 'stencil.mask';\n  var S_STENCIL_FUNC = 'stencil.func';\n  var S_STENCIL_OPFRONT = 'stencil.opFront';\n  var S_STENCIL_OPBACK = 'stencil.opBack';\n  var S_SCISSOR_ENABLE = 'scissor.enable';\n  var S_SCISSOR_BOX = 'scissor.box';\n  var S_VIEWPORT = 'viewport';\n  var S_PROFILE = 'profile';\n  var S_FRAMEBUFFER = 'framebuffer';\n  var S_VERT = 'vert';\n  var S_FRAG = 'frag';\n  var S_ELEMENTS = 'elements';\n  var S_PRIMITIVE = 'primitive';\n  var S_COUNT = 'count';\n  var S_OFFSET = 'offset';\n  var S_INSTANCES = 'instances';\n  var S_VAO = 'vao';\n  var SUFFIX_WIDTH = 'Width';\n  var SUFFIX_HEIGHT = 'Height';\n  var S_FRAMEBUFFER_WIDTH = S_FRAMEBUFFER + SUFFIX_WIDTH;\n  var S_FRAMEBUFFER_HEIGHT = S_FRAMEBUFFER + SUFFIX_HEIGHT;\n  var S_VIEWPORT_WIDTH = S_VIEWPORT + SUFFIX_WIDTH;\n  var S_VIEWPORT_HEIGHT = S_VIEWPORT + SUFFIX_HEIGHT;\n  var S_DRAWINGBUFFER = 'drawingBuffer';\n  var S_DRAWINGBUFFER_WIDTH = S_DRAWINGBUFFER + SUFFIX_WIDTH;\n  var S_DRAWINGBUFFER_HEIGHT = S_DRAWINGBUFFER + SUFFIX_HEIGHT;\n  var NESTED_OPTIONS = [S_BLEND_FUNC, S_BLEND_EQUATION, S_STENCIL_FUNC, S_STENCIL_OPFRONT, S_STENCIL_OPBACK, S_SAMPLE_COVERAGE, S_VIEWPORT, S_SCISSOR_BOX, S_POLYGON_OFFSET_OFFSET];\n  var GL_ARRAY_BUFFER$2 = 34962;\n  var GL_ELEMENT_ARRAY_BUFFER$2 = 34963;\n  var GL_FRAGMENT_SHADER$1 = 35632;\n  var GL_VERTEX_SHADER$1 = 35633;\n  var GL_TEXTURE_2D$3 = 0x0DE1;\n  var GL_TEXTURE_CUBE_MAP$2 = 0x8513;\n  var GL_CULL_FACE = 0x0B44;\n  var GL_BLEND = 0x0BE2;\n  var GL_DITHER = 0x0BD0;\n  var GL_STENCIL_TEST = 0x0B90;\n  var GL_DEPTH_TEST = 0x0B71;\n  var GL_SCISSOR_TEST = 0x0C11;\n  var GL_POLYGON_OFFSET_FILL = 0x8037;\n  var GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809E;\n  var GL_SAMPLE_COVERAGE = 0x80A0;\n  var GL_FLOAT$8 = 5126;\n  var GL_FLOAT_VEC2 = 35664;\n  var GL_FLOAT_VEC3 = 35665;\n  var GL_FLOAT_VEC4 = 35666;\n  var GL_INT$3 = 5124;\n  var GL_INT_VEC2 = 35667;\n  var GL_INT_VEC3 = 35668;\n  var GL_INT_VEC4 = 35669;\n  var GL_BOOL = 35670;\n  var GL_BOOL_VEC2 = 35671;\n  var GL_BOOL_VEC3 = 35672;\n  var GL_BOOL_VEC4 = 35673;\n  var GL_FLOAT_MAT2 = 35674;\n  var GL_FLOAT_MAT3 = 35675;\n  var GL_FLOAT_MAT4 = 35676;\n  var GL_SAMPLER_2D = 35678;\n  var GL_SAMPLER_CUBE = 35680;\n  var GL_TRIANGLES$1 = 4;\n  var GL_FRONT = 1028;\n  var GL_BACK = 1029;\n  var GL_CW = 0x0900;\n  var GL_CCW = 0x0901;\n  var GL_MIN_EXT = 0x8007;\n  var GL_MAX_EXT = 0x8008;\n  var GL_ALWAYS = 519;\n  var GL_KEEP = 7680;\n  var GL_ZERO = 0;\n  var GL_ONE = 1;\n  var GL_FUNC_ADD = 0x8006;\n  var GL_LESS = 513;\n  var GL_FRAMEBUFFER$2 = 0x8D40;\n  var GL_COLOR_ATTACHMENT0$2 = 0x8CE0;\n  var blendFuncs = {\n    '0': 0,\n    '1': 1,\n    'zero': 0,\n    'one': 1,\n    'src color': 768,\n    'one minus src color': 769,\n    'src alpha': 770,\n    'one minus src alpha': 771,\n    'dst color': 774,\n    'one minus dst color': 775,\n    'dst alph
1a': 772,\n    'one minus dst alpha': 773,\n    'constant color': 32769,\n    'one minus constant color': 32770,\n    'constant alpha': 32771,\n    'one minus constant alpha': 32772,\n    'src alpha saturate': 776\n  };\n\n  // There are invalid values for srcRGB and dstRGB. See:\n  // https://www.khronos.org/registry/webgl/specs/1.0/#6.13\n  // https://github.com/KhronosGroup/WebGL/blob/0d3201f5f7ec3c0060bc1f04077461541f1987b9/conformance-suites/1.0.3/conformance/misc/webgl-specific.html#L56\n  var invalidBlendCombinations = ['constant color, constant alpha', 'one minus constant color, constant alpha', 'constant color, one minus constant alpha', 'one minus constant color, one minus constant alpha', 'constant alpha, constant color', 'constant alpha, one minus constant color', 'one minus constant alpha, constant color', 'one minus constant alpha, one minus constant color'];\n  var compareFuncs = {\n    'never': 512,\n    'less': 513,\n    '<': 513,\n    'equal': 514,\n    '=': 514,\n    '==': 514,\n    '===': 514,\n    'lequal': 515,\n    '<=': 515,\n    'greater': 516,\n    '>': 516,\n    'notequal': 517,\n    '!=': 517,\n    '!==': 517,\n    'gequal': 518,\n    '>=': 518,\n    'always': 519\n  };\n  var stencilOps = {\n    '0': 0,\n    'zero': 0,\n    'keep': 7680,\n    'replace': 7681,\n    'increment': 7682,\n    'decrement': 7683,\n    'increment wrap': 34055,\n    'decrement wrap': 34056,\n    'invert': 5386\n  };\n  var shaderType = {\n    'frag': GL_FRAGMENT_SHADER$1,\n    'vert': GL_VERTEX_SHADER$1\n  };\n  var orientationType = {\n    'cw': GL_CW,\n    'ccw': GL_CCW\n  };\n  function isBufferArgs(x) {\n    return Array.isArray(x) || isTypedArray(x) || isNDArrayLike(x);\n  }\n\n  // Make sure viewport is processed first\n  function sortState(state) {\n    return state.sort(function (a, b) {\n      if (a === S_VIEWPORT) {\n        return -1;\n      } else if (b === S_VIEWPORT) {\n        return 1;\n      }\n      return a < b ? -1 : 1;\n    });\n  }\n  function Declaration(thisDep, contextDep, propDep, append) {\n    this.thisDep = thisDep;\n    this.contextDep = contextDep;\n    this.propDep = propDep;\n    this.append = append;\n  }\n  function isStatic(decl) {\n    return decl && !(decl.thisDep || decl.contextDep || decl.propDep);\n  }\n  function createStaticDecl(append) {\n    return new Declaration(false, false, false, append);\n  }\n  function createDynamicDecl(dyn, append) {\n    var type = dyn.type;\n    if (type === DYN_FUNC$1) {\n      var numArgs = dyn.data.length;\n      return new Declaration(true, numArgs >= 1, numArgs >= 2, append);\n    } else if (type === DYN_THUNK) {\n      var data = dyn.data;\n      return new Declaration(data.thisDep, data.contextDep, data.propDep, append);\n    } else if (type === DYN_CONSTANT$1) {\n      return new Declaration(false, false, false, append);\n    } else if (type === DYN_ARRAY$1) {\n      var thisDep = false;\n      var contextDep = false;\n      var propDep = false;\n      for (var i = 0; i < dyn.data.length; ++i) {\n        var subDyn = dyn.data[i];\n        if (subDyn.type === DYN_PROP$1) {\n          propDep = true;\n        } else if (subDyn.type === DYN_CONTEXT$1) {\n          contextDep = true;\n        } else if (subDyn.type === DYN_STATE$1) {\n          thisDep = true;\n        } else if (subDyn.type === DYN_FUNC$1) {\n          thisDep = true;\n          var subArgs = subDyn.data;\n          if (subArgs >= 1) {\n            contextDep = true;\n          }\n          if (subArgs >= 2) {\n            propDep = true;\n          }\n        } else if (subDyn.type === DYN_THUNK) {\n          thisDep = thisDep || subDyn.data.thisDep;\n          contextDep = contextDep || subDyn.data.contextDep;\n          propDep = propDep || subDyn.data.propDep;\n        }\n      }\n      return new Declaration(thisDep, contextDep, propDep, append);\n    } else {\n      return new Declaration(type === DYN_STATE$1, type === DYN_CONTEXT$1, type === DYN_PROP$1, append);\n    }\n  }\n  var SCOPE_DECL = new Declaration(false, false, false, function () {});\n  function reglCore(gl, stringStore, extensions, limits, bufferState, elementState, textureState, framebufferState, uniformState, attributeState, shaderState, drawState, contextState, timer, config) {\n    var AttributeRecord = attributeState.Record;\n    var blendEquations = {\n      'add': 32774,\n      'subtract': 32778,\n      'reverse subtract': 32779\n    };\n    if (extensions.ext_blend_minmax) {\n      blendEquations.min = GL_MIN_EXT;\n      blendEquations.max = GL_MAX_EXT;\n    }\n    var extInstancing = extensions.angle_instanced_arrays;\n    var extDrawBuffers = extensions.webgl_draw_buffers;\n    var extVertexArrays = extensions.oes_vertex_array_object;\n\n    // ===================================================\n    // ===================================================\n    // WEBGL STATE\n    // ===================================================\n    // ===================================================\n    var currentState = {\n      dirty: true,\n      profile: config.profile\n    };\n    var nextState = {};\n    var GL_STATE_NAMES = [];\n    var GL_FLAGS = {};\n    var GL_VARIABLES = {};\n    function propName(name) {\n      return name.replace('.', '_');\n    }\n    function stateFlag(sname, cap, init) {\n      var name = propName(sname);\n      GL_STATE_NAMES.push(sname);\n      nextState[name] = currentState[name] = !!init;\n      GL_FLAGS[name] = cap;\n    }\n    function stateVariable(sname, func, init) {\n      var name = propName(sname);\n      GL_STATE_NAMES.push(sname);\n      if (Array.isArray(init)) {\n        currentState[name] = init.slice();\n        nextState[name] = init.slice();\n      } else {\n        currentState[name] = nextState[name] = init;\n      }\n      GL_VARIABLES[name] = func;\n    }\n\n    // Dithering\n    stateFlag(S_DITHER, GL_DITHER);\n\n    // Blending\n    stateFlag(S_BLEND_ENABLE, GL_BLEND);\n    stateVariable(S_BLEND_COLOR, 'blendColor', [0, 0, 0, 0]);\n    stateVariable(S_BLEND_EQUATION, 'blendEquationSeparate', [GL_FUNC_ADD, GL_FUNC_ADD]);\n    stateVariable(S_BLEND_FUNC, 'blendFuncSeparate', [GL_ONE, GL_ZERO, GL_ONE, GL_ZERO]);\n\n    // Depth\n    stateFlag(S_DEPTH_ENABLE, GL_DEPTH_TEST, true);\n    stateVariable(S_DEPTH_FUNC, 'depthFunc', GL_LESS);\n    stateVariable(S_DEPTH_RANGE, 'depthRange', [0, 1]);\n    stateVariable(S_DEPTH_MASK, 'depthMask', true);\n\n    // Color mask\n    stateVariable(S_COLOR_MASK, S_COLOR_MASK, [true, true, true, true]);\n\n    // Face culling\n    stateFlag(S_CULL_ENABLE, GL_CULL_FACE);\n    stateVariable(S_CULL_FACE, 'cullFace', GL_BACK);\n\n    // Front face orientation\n    stateVariable(S_FRONT_FACE, S_FRONT_FACE, GL_CCW);\n\n    // Line width\n    stateVariable(S_LINE_WIDTH, S_LINE_WIDTH, 1);\n\n    // Polygon offset\n    stateFlag(S_POLYGON_OFFSET_ENABLE, GL_POLYGON_OFFSET_FILL);\n    stateVariable(S_POLYGON_OFFSET_OFFSET, 'polygonOffset', [0, 0]);\n\n    // Sample coverage\n    stateFlag(S_SAMPLE_ALPHA, GL_SAMPLE_ALPHA_TO_COVERAGE);\n    stateFlag(S_SAMPLE_ENABLE, GL_SAMPLE_COVERAGE);
1\n    stateVariable(S_SAMPLE_COVERAGE, 'sampleCoverage', [1, false]);\n\n    // Stencil\n    stateFlag(S_STENCIL_ENABLE, GL_STENCIL_TEST);\n    stateVariable(S_STENCIL_MASK, 'stencilMask', -1);\n    stateVariable(S_STENCIL_FUNC, 'stencilFunc', [GL_ALWAYS, 0, -1]);\n    stateVariable(S_STENCIL_OPFRONT, 'stencilOpSeparate', [GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP]);\n    stateVariable(S_STENCIL_OPBACK, 'stencilOpSeparate', [GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP]);\n\n    // Scissor\n    stateFlag(S_SCISSOR_ENABLE, GL_SCISSOR_TEST);\n    stateVariable(S_SCISSOR_BOX, 'scissor', [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight]);\n\n    // Viewport\n    stateVariable(S_VIEWPORT, S_VIEWPORT, [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight]);\n\n    // ===================================================\n    // ===================================================\n    // ENVIRONMENT\n    // ===================================================\n    // ===================================================\n    var sharedState = {\n      gl: gl,\n      context: contextState,\n      strings: stringStore,\n      next: nextState,\n      current: currentState,\n      draw: drawState,\n      elements: elementState,\n      buffer: bufferState,\n      shader: shaderState,\n      attributes: attributeState.state,\n      vao: attributeState,\n      uniforms: uniformState,\n      framebuffer: framebufferState,\n      extensions: extensions,\n      timer: timer,\n      isBufferArgs: isBufferArgs\n    };\n    var sharedConstants = {\n      primTypes: primTypes,\n      compareFuncs: compareFuncs,\n      blendFuncs: blendFuncs,\n      blendEquations: blendEquations,\n      stencilOps: stencilOps,\n      glTypes: glTypes,\n      orientationType: orientationType\n    };\n    check$1.optional(function () {\n      sharedState.isArrayLike = isArrayLike;\n    });\n    if (extDrawBuffers) {\n      sharedConstants.backBuffer = [GL_BACK];\n      sharedConstants.drawBuffer = loop(limits.maxDrawbuffers, function (i) {\n        if (i === 0) {\n          return [0];\n        }\n        return loop(i, function (j) {\n          return GL_COLOR_ATTACHMENT0$2 + j;\n        });\n      });\n    }\n    var drawCallCounter = 0;\n    function createREGLEnvironment() {\n      var env = createEnvironment();\n      var link = env.link;\n      var global = env.global;\n      env.id = drawCallCounter++;\n      env.batchId = '0';\n\n      // link shared state\n      var SHARED = link(sharedState);\n      var shared = env.shared = {\n        props: 'a0'\n      };\n      Object.keys(sharedState).forEach(function (prop) {\n        shared[prop] = global.def(SHARED, '.', prop);\n      });\n\n      // Inject runtime assertion stuff for debug builds\n      check$1.optional(function () {\n        env.CHECK = link(check$1);\n        env.commandStr = check$1.guessCommand();\n        env.command = link(env.commandStr);\n        env.assert = function (block, pred, message) {\n          block('if(!(', pred, '))', this.CHECK, '.commandRaise(', link(message), ',', this.command, ');');\n        };\n        sharedConstants.invalidBlendCombinations = invalidBlendCombinations;\n      });\n\n      // Copy GL state variables over\n      var nextVars = env.next = {};\n      var currentVars = env.current = {};\n      Object.keys(GL_VARIABLES).forEach(function (variable) {\n        if (Array.isArray(currentState[variable])) {\n          nextVars[variable] = global.def(shared.next, '.', variable);\n          currentVars[variable] = global.def(shared.current, '.', variable);\n        }\n      });\n\n      // Initialize shared constants\n      var constants = env.constants = {};\n      Object.keys(sharedConstants).forEach(function (name) {\n        constants[name] = global.def(JSON.stringify(sharedConstants[name]));\n      });\n\n      // Helper function for calling a block\n      env.invoke = function (block, x) {\n        switch (x.type) {\n          case DYN_FUNC$1:\n            var argList = ['this', shared.context, shared.props, env.batchId];\n            return block.def(link(x.data), '.call(', argList.slice(0, Math.max(x.data.length + 1, 4)), ')');\n          case DYN_PROP$1:\n            return block.def(shared.props, x.data);\n          case DYN_CONTEXT$1:\n            return block.def(shared.context, x.data);\n          case DYN_STATE$1:\n            return block.def('this', x.data);\n          case DYN_THUNK:\n            x.data.append(env, block);\n            return x.data.ref;\n          case DYN_CONSTANT$1:\n            return x.data.toString();\n          case DYN_ARRAY$1:\n            return x.data.map(function (y) {\
1n              return env.invoke(block, y);\n            });\n        }\n      };\n      env.attribCache = {};\n      var scopeAttribs = {};\n      env.scopeAttrib = function (name) {\n        var id = stringStore.id(name);\n        if (id in scopeAttribs) {\n          return scopeAttribs[id];\n        }\n        var binding = attributeState.scope[id];\n        if (!binding) {\n          binding = attributeState.scope[id] = new AttributeRecord();\n        }\n        var result = scopeAttribs[id] = link(binding);\n        return result;\n      };\n      return env;\n    }\n\n    // ===================================================\n    // ===================================================\n    // PARSING\n    // ===================================================\n    // ===================================================\n    function parseProfile(options) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      var profileEnable;\n      if (S_PROFILE in staticOptions) {\n        var value = !!staticOptions[S_PROFILE];\n        profileEnable = createStaticDecl(function (env, scope) {\n          return value;\n        });\n        profileEnable.enable = value;\n      } else if (S_PROFILE in dynamicOptions) {\n        var dyn = dynamicOptions[S_PROFILE];\n        profileEnable = createDynamicDecl(dyn, function (env, scope) {\n          return env.invoke(scope, dyn);\n        });\n      }\n      return profileEnable;\n    }\n    function parseFramebuffer(options, env) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      if (S_FRAMEBUFFER in staticOptions) {\n        var framebuffer = staticOptions[S_FRAMEBUFFER];\n        if (framebuffer) {\n          framebuffer = framebufferState.getFramebuffer(framebuffer);\n          check$1.command(framebuffer, 'invalid framebuffer object');\n          return createStaticDecl(function (env, block) {\n            var FRAMEBUFFER = env.link(framebuffer);\n            var shared = env.shared;\n            block.set(shared.framebuffer, '.next', FRAMEBUFFER);\n            var CONTEXT = shared.context;\n            block.set(CONTEXT, '.' + S_FRAMEBUFFER_WIDTH, FRAMEBUFFER + '.width');\n            block.set(CONTEXT, '.' + S_FRAMEBUFFER_HEIGHT, FRAMEBUFFER + '.height');\n            return FRAMEBUFFER;\n          });\n        } else {\n          return createStaticDecl(function (env, scope) {\n            var shared = env.shared;\n            scope.set(shared.framebuffer, '.next', 'null');\n            var CONTEXT = shared.context;\n            scope.set(CONTEXT, '.' + S_FRAMEBUFFER_WIDTH, CONTEXT + '.' + S_DRAWINGBUFFER_WIDTH);\n            scope.set(CONTEXT, '.' + S_FRAMEBUFFER_HEIGHT, CONTEXT + '.' + S_DRAWINGBUFFER_HEIGHT);\n            return 'null';\n          });\n        }\n      } else if (S_FRAMEBUFFER in dynamicOptions) {\n        var dyn = dynamicOptions[S_FRAMEBUFFER];\n        return createDynamicDecl(dyn, function (env, scope) {\n          var FRAMEBUFFER_FUNC = env.invoke(scope, dyn);\n          var shared = env.shared;\n          var FRAMEBUFFER_STATE = shared.framebuffer;\n          var FRAMEBUFFER = scope.def(FRAMEBUFFER_STATE, '.getFramebuffer(', FRAMEBUFFER_FUNC, ')');\n          check$1.optional(function () {\n            env.assert(scope, '!' + FRAMEBUFFER_FUNC + '||' + FRAMEBUFFER, 'invalid framebuffer object');\n          });\n          scope.set(FRAMEBUFFER_STATE, '.next', FRAMEBUFFER);\n          var CONTEXT = shared.context;\n          scope.set(CONTEXT, '.' + S_FRAMEBUFFER_WIDTH, FRAMEBUFFER + '?' + FRAMEBUFFER + '.width:' + CONTEXT + '.' + S_DRAWINGBUFFER_WIDTH);\n          scope.set(CONTEXT, '.' + S_FRAMEBUFFER_HEIGHT, FRAMEBUFFER + '?' + FRAMEBUFFER + '.height:' + CONTEXT + '.' + S_DRAWINGBUFFER_HEIGHT);\n          return FRAMEBUFFER;\n        });\n      } else {\n        return null;\n      }\n    }\n    function parseViewportScissor(options, framebuffer, env) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      function parseBox(param) {\n        if (param in staticOptions) {\n          var box = staticOptions[param];\n          check$1.commandType(box, 'object', 'invalid ' + param, env.commandStr);\n          var isStatic = true;\n          var x = box.x | 0;\n          var y = box.y | 0;\n          var w, h;\n          if ('width' in box) {\n            w = box.width | 0;\n            check$1.command(w >= 0, 'invalid ' + param, env.commandStr);\n          } else {\n            isStatic = false;\n          }\n          if ('height' in box) {\n            h = box.height | 0;\n            check$1.command(h >= 0, 'invalid ' + param, env.commandStr);\n          } else {\n            isStatic = false;\n          }\n          return new Declaration(!isStatic && framebuffer && framebuffer.thisDep, !isStatic && framebuffer && framebuffer.contextDep, !isStatic && framebuffer && framebuffer.propDep, function (env, scope) {\n            var CONTEXT = env.shared.context;\n            var BOX_W = w;\n            if (!('width' in box)) {\n              BOX_W = scope.def(CONTEXT, '.', S_FRAMEBUFFER_WIDTH, '-', x);\n            }\n            var BOX_H = h;\n            if (!('height' in box)) {\n              BOX_H = scope.def(CONTEXT, '.', S_FRAMEBUFFER_HEIGHT, '-', y);\n            }\n            return [x, y, BOX_W, BOX_H];\n          });\n        } else if (param in dynamicOptions) {\n          var dynBox = dynamicOptions[param];\n          var result = createDynamicDecl(dynBox, function (env, scope) {\n            var BOX = env.invoke(scope, dynBox);\n            check$1.optional(function () {\n              env.assert(scope, BOX + '&&typeof ' + BOX + '===\"object\"', 'invalid ' + param);\n            });\n            var CONTEXT = env.shared.context;\n            var BOX_X = scope.def(BOX, '.x|0');\n            var BOX_Y = scope.def(BOX, '.y|0');\n            var BOX_W = scope.def('\"width\" in ', BOX, '?', BOX, '.width|0:', '(', CONTEXT, '.', S_FRAMEBUFFER_WIDTH, '-', BOX_X, ')');\n            var BOX_H = scope.def('\"height\" in ', BOX, '?', BOX, '.height|0:', '(', CONTEXT, '.', S_FRAMEBUFFER_HEIGHT, '-', BOX_Y, ')');\n            check$1.optional(function () {\n              env.assert(scope, BOX_W + '>=0&&' + BOX_H + '>=0', 'invalid ' + param);\n            });
1\n            return [BOX_X, BOX_Y, BOX_W, BOX_H];\n          });\n          if (framebuffer) {\n            result.thisDep = result.thisDep || framebuffer.thisDep;\n            result.contextDep = result.contextDep || framebuffer.contextDep;\n            result.propDep = result.propDep || framebuffer.propDep;\n          }\n          return result;\n        } else if (framebuffer) {\n          return new Declaration(framebuffer.thisDep, framebuffer.contextDep, framebuffer.propDep, function (env, scope) {\n            var CONTEXT = env.shared.context;\n            return [0, 0, scope.def(CONTEXT, '.', S_FRAMEBUFFER_WIDTH), scope.def(CONTEXT, '.', S_FRAMEBUFFER_HEIGHT)];\n          });\n        } else {\n          return null;\n        }\n      }\n      var viewport = parseBox(S_VIEWPORT);\n      if (viewport) {\n        var prevViewport = viewport;\n        viewport = new Declaration(viewport.thisDep, viewport.contextDep, viewport.propDep, function (env, scope) {\n          var VIEWPORT = prevViewport.append(env, scope);\n          var CONTEXT = env.shared.context;\n          scope.set(CONTEXT, '.' + S_VIEWPORT_WIDTH, VIEWPORT[2]);\n          scope.set(CONTEXT, '.' + S_VIEWPORT_HEIGHT, VIEWPORT[3]);\n          return VIEWPORT;\n        });\n      }\n      return {\n        viewport: viewport,\n        scissor_box: parseBox(S_SCISSOR_BOX)\n      };\n    }\n    function parseAttribLocations(options, attributes) {\n      var staticOptions = options.static;\n      var staticProgram = typeof staticOptions[S_FRAG] === 'string' && typeof staticOptions[S_VERT] === 'string';\n      if (staticProgram) {\n        if (Object.keys(attributes.dynamic).length > 0) {\n          return null;\n        }\n        var staticAttributes = attributes.static;\n        var sAttributes = Object.keys(staticAttributes);\n        if (sAttributes.length > 0 && typeof staticAttributes[sAttributes[0]] === 'number') {\n          var bindings = [];\n          for (var i = 0; i < sAttributes.length; ++i) {\n            check$1(typeof staticAttributes[sAttributes[i]] === 'number', 'must specify all vertex attribute locations when using vaos');\n            bindings.push([staticAttributes[sAttributes[i]] | 0, sAttributes[i]]);\n          }\n          return bindings;\n        }\n      }\n      return null;\n    }\n    function parseProgram(options, env, attribLocations) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      function parseShader(name) {\n        if (name in staticOptions) {\n          var id = stringStore.id(staticOptions[name]);\n          check$1.optional(function () {\n            shaderState.shader(shaderType[name], id, check$1.guessCommand());\n          });\n          var result = createStaticDecl(function () {\n            return id;\n          });\n          result.id = id;\n          return result;\n        } else if (name in dynamicOptions) {\n          var dyn = dynamicOptions[name];\n          return createDynamicDecl(dyn, function (env, scope) {\n            var str = env.invoke(scope, dyn);\n            var id = scope.def(env.shared.strings, '.id(', str, ')');\n            check$1.optional(function () {\n              scope(env.shared.shader, '.shader(', shaderType[name], ',', id, ',', env.command, ');');\n            });\n            return id;\n          });\n        }\n        return null;\n      }\n      var frag = parseShader(S_FRAG);\n      var vert = parseShader(S_VERT);\n      var program = null;\n      var progVar;\n      if (isStatic(frag) && isStatic(vert)) {\n        program = shaderState.program(vert.id, frag.id, null, attribLocations);\n        progVar = createStaticDecl(function (env, scope) {\n          return env.link(program);\n        });\n      } else {\n        progVar = new Declaration(frag && frag.thisDep || vert && vert.thisDep, frag && frag.contextDep || vert && vert.contextDep, frag && frag.propDep || vert && vert.propDep, function (env, scope) {\n          var SHADER_STATE = env.shared.shader;\n          var fragId;\n          if (frag) {\n            fragId = frag.append(env, scope);\n          } else {\n            fragId = scope.def(SHADER_STATE, '.', S_FRAG);\n          }\n          var vertId;\n          if (vert) {\n            vertId = vert.append(env, scope);\n          } else {\n            vertId = scope.def(SHADER_STATE, '.', S_VERT);\n          }\n          var progDef = SHADER_STATE + '.program(' + vertId + ',' + fragId;\n          check$1.optional(function () {\n            progDef += ',' + env.command;\n          });\n          return scope.def(progDef + ')');\n        });\n      }\n      return {\n        frag: frag,\n        vert: vert,\n        progVar: progVar,\n        program: program\n      };\n    }\n    function parseDraw(options, env) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n\n      // TODO: should use VAO to get default values for offset properties\n      // should move vao parse into here and out of the old stuff\n\n      var staticDraw = {};\n      var vaoActive = false;\n      function parseVAO() {\n        if (S_VAO in staticOptions) {\n          var vao = staticOptions[S_VAO];\n          if (vao !== null && attributeState.getVAO(vao) === null) {\n            vao = attributeState.createVAO(vao);\n          }\n          vaoActive = true;\n          staticDraw.vao = vao;\n          return createStaticDecl(function (env) {\n            var vaoRef = attributeState.getVAO(vao);\n            if (vaoRef) {\n              return env.link(vaoRef);\n            } else {\n              return 'null';\n            }\n          });\n        } else if (S_VAO in dynamicOptions) {\n          vaoActive = true;\n          var dyn = dynamicOptions[S_VAO];\n          return createDynamicDecl(dyn, function (env, scope) {\n            var vaoRef = env.invoke(scope, dyn);\n            return scope.def(env.shared.vao + '.getVAO(' + vaoRef + ')');\n          });\n        }\n        return null;\n      }\n      var vao = parseVAO();\n      var elementsActive = false;\n      function parseElements() {\n        if (S_ELEMENTS in staticOptions) {\n          var elements = staticOptions[S_ELEMENTS];\n          staticDraw.elements = elements;\n          if (isBufferArgs(elements)) {\n            var e = staticDraw.elements = elementState.create(elements, true);\n            elements = elementState.getElements(e);\n            elementsActive = true;\n          } else if (elements) {\n            elements = elementState.getElements(elements);\n            elementsActive = true;\n            check$1.command(elements, 'invalid elements', env.commandStr);\n          }\n          var result = createStaticDecl(function (env, scope) {\n            if (elements) {\n              var result = env.link(elements);\n              env.ELEMENTS = result;\n              return result;\n            }\n            env.ELEMENTS = null;\n            return null;\n          });\n          result.value = elements;\n          return result;\n        } else if (S_ELEMENTS in dynamicOptions) {\n          elementsActive = true;\n          var dyn = dynamicOptions[S_ELEMENTS];\n          return createDynamicDecl(dyn, function (env, scope) {\n            var shared = env.shared;\n            var IS_BUFFER_ARGS = shared.isBufferArgs;\n            var ELEMENT_STATE = shared.elements;\n            var elementDefn = env.invoke(scope, dyn);\n            var elements = scope.def('null');\n            var elementStream = scope.def(IS_BUFFER_ARGS, '(', elementDefn, ')');\n            var ifte = env.cond(elementStream).then(elements, '=', ELEMENT_STATE, '.createStream(', elementDefn, ');').else(elements, '=', ELEMENT_STATE, '.getElements(', elementDefn, ');');\n            check$1.optional(function () {\n              env.assert(ifte.else, '!' + elementDefn + '||' + elements, 'invalid elements');\n            });\n            scope.entry(ifte);\n            scope.exit(env.cond(elementStream).then(ELEMENT_STATE, '.destroyStream(', elements, ');'));\n            env.ELEMENTS = elements;\n            return elements;\n          });\n        } else if (vaoActive) {\n          return new Declaration(vao.thisDep, vao.contextDep, vao.propDep, function (env, scope) {\n            return scope.def(env.shared.vao + '.currentVAO?' + env.shared.elements + '.getElements(' + env.shared.vao + '.currentVAO.elements):null');\n          });\n        }\n        return null;\n      }\n      var elements = parseElements();\n      function parsePrimitive() {\n        if (S_PRIMITIVE in staticOptions) {\n          var primitive = staticOptions[S_PRIMITIVE];\n          staticDraw.primitive = primitive;\n          check$1.commandParameter(primitive, primTypes, 'invalid primitve', env.commandStr);\n          return createStaticDecl(function (env, scope) {\n            return primTypes[primitive];\n          });\n        } else if (S_PRIMITIVE in dynamicOptions) {\n          var dynPrimitive = dynamicOptions[S_PRIMITIVE];\n          return createDynamicDecl(dynPrimitive, function (env, scope) {\n            var PRIM_TYPES = env.constants.primTypes;\n            var prim = env.invoke(scope, dynPrimitive);\n            check$1.optional(function () {\n              env.assert(scope, prim + ' in ' + PRIM_TYPES, 'invalid primitive, must be one of ' + Object.keys(primTypes));\n            });\n            return scope.def(PRIM_TYPES, '[', prim, ']');\n          });\n        } else if (elementsActive) {\n          if (isStatic(elements)) {\n            if (elements.value) {\n              return createStaticDecl(function (env, scope) {\n                return scope.def(env.ELEMENTS, '.primType');\n              });\n            } else {\n              return createStaticDecl(function () {\n                return GL_TRIANGLES$1;\n              });\n            }\n          } else {\n            return new Declaration(elements.thisDep, elements.contextDep, elements.propDep, function (env, scope) {\n              var elements = env.ELEMENTS;\n              return scope.def(elements, '?', elements, '.primType:', GL_TRIANGLES$1);\n            });\n          }\n        } else if (vaoActive) {\n          return new Declaration(vao.thisDep, vao.contextDep, vao.propDep, function (env, scope) {\n            return scope.def(env.shared.vao + '.currentVAO?' + env.shared.vao + '.currentVAO.primitive:' + GL_TRIANGLES$1);\n          });\n        }\n        return null;\n      }\n      function parseParam(param, isOffset) {\n        if (param in staticOptions) {\n          var value = staticOptions[param] | 0;\n          if (isOffset) {\n            staticDraw.offset = value;\n          } else {\n            staticDraw.instances = value;\n          }\n          check$1.command(!isOffset || value >= 0, 'invalid ' + param, env.commandStr);\n          return createStaticDecl(function (env, scope) {\n            if (isOffset) {\n              env.OFFSET = value;\n            }\n            return value;\n          });\n        } else if (param in dynamicOptions) {\n          var dynValue = dynamicOptions[param];\n          return createDynamicDecl(dynValue, function (env, scope) {\n            var result = env.invoke(scope, dynValue);\n            if (isOffset) {\n              env.OFFSET = result;\n              check$1.optional(function () {\n                env.assert(scope, result + '>=0', 'invalid ' + param);\n              });\n            }\n            return result;\n          });\n        } else if (isOffset) {\n          if (elementsActive) {\n            return createStaticDecl(function (env, scope) {\n              env.OFFSET = 0;\n              return 0;\n            });\n          } else if (vaoActive) {\n            return new Declaration(vao.thisDep, vao.contextDep, vao.propDep, function (env, scope) {\n              return scope.def(env.shared.vao + '.currentVAO?' + env.shared.vao + '.currentVAO.offset:0');\n            });\n          }\n        } else if (vaoActive) {\n          return new Declaration(vao.thisDep, vao.contextDep, vao.propDep, function (env, scope) {\n            return scope.def(env.shared.vao + '.currentVAO?' + env.shared.vao + '.currentVAO.instances:-1');\n          });\n        }\n        return null;\n      }\n      var OFFSET = parseParam(S_OFFSET, true);\n      function parseVertCount() {\n        if (S_COUNT in staticOptions) {\n          var count = staticOptions[S_COUNT] | 0;\n          staticDraw.count = count;\n          check$1.command(typeof count === 'number' && count >= 0, 'invalid vertex count', env.commandStr);\n          return createStaticDecl(function () {\n            return count;\n          });\n        } else if (S_COUNT in dynamicOptions) {\n          var dynCount = dynamicOptions[S_COUNT];\n          return createDynamicDecl(dynCount, function (env, scope) {\n            var result = env.invoke(scope, dynCount);\n            check$1.optional(function () {\n              env.assert(scope, 'typeof ' + result + '===\"number\"&&' + result + '>=0&&' + result + '===(' + result + '|0)', 'invalid vertex count');\n            });\n            return result;\n          });\n        } else if (elementsActive) {\n          if (isStatic(elements)) {\n            if (elements) {\n              if (OFFSET) {\n                return new Declaration(OFFSET.thisDep, OFFSET.contextDep, OFFSET.propDep, function (env, scope) {\n                  var result = scope.def(env.ELEMENTS, '.vertCount-', env.OFFSET);\n                  check$1.optional(function () {\n                    env.assert(scope, result + '>=0', 'invalid vertex offset/element buffer too small');\n                  });\n                  return result;\n                });\n              } else {\n                return createStaticDecl(function (env, scope) {\n                  return scope.def(env.ELEMENTS, '.vertCount');\n                });\n              }\n            } else {\n              var result = createStaticDecl(function () {\n                return -1;\n              });\n              check$1.optional(function () {\n                result.MISSING = true;\n              });\n              return result;\n            }\n          } else {\n            var variable = new Declaration(elements.thisDep || OFFSET.thisDep, elements.contextDep || OFFSET.contextDep, elements.propDep || OFFSET.propDep, function (env, scope) {\n              var elements = env.ELEMENTS;\n              if (env.OFFSET) {\n                return scope.def(elements, '?', elements, '.vertCount-', env.OFFSET, ':-1');\n              }\n              return scope.def(elements, '?', elements, '.vertCount:-1');\n            });\n            check$1.optional(function () {\n              variable.DYNAMIC = true;\n            });\n            return variable;\n          }\n        } else if (vaoActive) {\n          var countVariable = new Declaration(vao.thisDep, vao.contextDep, vao.propDep, function (env, scope) {\n            return scope.def(env.shared.vao, '.currentVAO?', env.shared.vao, '.currentVAO.count:-1');\n          });\n          return countVariable;\n        }\n        return null;\n      }\n      var primitive = parsePrimitive();\n      var count = parseVertCount();\n      var instances = parseParam(S_INSTANCES, false);\n      return {\n        elements: elements,\n        primitive: primitive,\n        count: count,\n        instances: instances,\n        offset: OFFSET,\n        vao: vao,\n        vaoActive: vaoActive,\n        elementsActive: elementsActive,\n        // static draw props\n        static: staticDraw\n      };\n    }\n    function parseGLState(options, env) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      var STATE = {};\n      GL_STATE_NAMES.forEach(function (prop) {\n        var param = propName(prop);\n        function parseParam(parseStatic, parseDynamic) {\n          if (prop in staticOptions) {\n            var value = parseStatic(staticOptions[prop]);\n            STATE[param] = createStaticDecl(function () {\n              return value;\n            });\n          } else if (prop in dynamicOptions) {\n            var dyn = dynamicOptions[prop];\n            STATE[param] = createDynamicDecl(dyn, function (env, scope) {\n              return parseDynamic(env, scope, env.invoke(scope
1, dyn));\n            });\n          }\n        }\n        switch (prop) {\n          case S_CULL_ENABLE:\n          case S_BLEND_ENABLE:\n          case S_DITHER:\n          case S_STENCIL_ENABLE:\n          case S_DEPTH_ENABLE:\n          case S_SCISSOR_ENABLE:\n          case S_POLYGON_OFFSET_ENABLE:\n          case S_SAMPLE_ALPHA:\n          case S_SAMPLE_ENABLE:\n          case S_DEPTH_MASK:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'boolean', prop, env.commandStr);\n              return value;\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, 'typeof ' + value + '===\"boolean\"', 'invalid flag ' + prop, env.commandStr);\n              });\n              return value;\n            });\n          case S_DEPTH_FUNC:\n            return parseParam(function (value) {\n              check$1.commandParameter(value, compareFuncs, 'invalid ' + prop, env.commandStr);\n              return compareFuncs[value];\n            }, function (env, scope, value) {\n              var COMPARE_FUNCS = env.constants.compareFuncs;\n              check$1.optional(function () {\n                env.assert(scope, value + ' in ' + COMPARE_FUNCS, 'invalid ' + prop + ', must be one of ' + Object.keys(compareFuncs));\n              });\n              return scope.def(COMPARE_FUNCS, '[', value, ']');\n            });\n          case S_DEPTH_RANGE:\n            return parseParam(function (value) {\n              check$1.command(isArrayLike(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number' && value[0] <= value[1], 'depth range is 2d array', env.commandStr);\n              return value;\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, env.shared.isArrayLike + '(' + value + ')&&' + value + '.length===2&&' + 'typeof ' + value + '[0]===\"number\"&&' + 'typeof ' + value + '[1]===\"number\"&&' + value + '[0]<=' + value + '[1]', 'depth range must be a 2d array');\n              });\n              var Z_NEAR = scope.def('+', value, '[0]');\n              var Z_FAR = scope.def('+', value, '[1]');\n              return [Z_NEAR, Z_FAR];\n            });\n          case S_BLEND_FUNC:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'object', 'blend.func', env.commandStr);\n              var srcRGB = 'srcRGB' in value ? value.srcRGB : value.src;\n              var srcAlpha = 'srcAlpha' in value ? value.srcAlpha : value.src;\n              var dstRGB = 'dstRGB' in value ? value.dstRGB : value.dst;\n              var dstAlpha = 'dstAlpha' in value ? value.dstAlpha : value.dst;\n              check$1.commandParameter(srcRGB, blendFuncs, param + '.srcRGB', env.commandStr);\n              check$1.commandParameter(srcAlpha, blendFuncs, param + '.srcAlpha', env.commandStr);\n              check$1.commandParameter(dstRGB, blendFuncs, param + '.dstRGB', env.commandStr);\n              check$1.commandParameter(dstAlpha, blendFuncs, param + '.dstAlpha', env.commandStr);\n              check$1.command(invalidBlendCombinations.indexOf(srcRGB + ', ' + dstRGB) === -1, 'unallowed blending combination (srcRGB, dstRGB) = (' + srcRGB + ', ' + dstRGB + ')', env.commandStr);\n              return [blendFuncs[srcRGB], blendFuncs[dstRGB], blendFuncs[srcAlpha], blendFuncs[dstAlpha]];\n            }, function (env, scope, value) {\n              var BLEND_FUNCS = env.constants.blendFuncs;\n              check$1.optional(function () {\n                env.assert(scope, value + '&&typeof ' + value + '===\"object\"', 'invalid blend func, must be an object');\n              });\n              function read(prefix, suffix) {\n                var func = scope.def('\"', prefix, suffix, '\" in ', value, '?', value, '.', prefix, suffix, ':', value, '.', prefix);\n                check$1.optional(function () {\n                  env.assert(scope, func + ' in ' + BLEND_FUNCS, 'invalid ' + prop + '.' + prefix + suffix + ', must be one of ' + Object.keys(blendFuncs));\n                });\n                return func;\n              }\n              var srcRGB = read('src', 'RGB');\n              var dstRGB = read('dst', 'RGB');\n              check$1.optional(function () {\n                var INVALID_BLEND_COMBINATIONS = env.constants.invalidBlendCombinations;\n                env.assert(scope, INVALID_BLEND_COMBINATIONS + '.indexOf(' + srcRGB + '+\", \"+' + dstRGB + ') === -1 ', 'unallowed blending combination for (srcRGB, dstRGB)');\n              });\n              var SRC_RGB = scope.def(BLEND_FUNCS, '[', srcRGB, ']');\n              var SRC_ALPHA = scope.def(BLEND_FUNCS, '[', read('src', 'Alpha'), ']');\n              var DST_RGB = scope.def(BLEND_FUNCS, '[', dstRGB, ']');\n              var DST_ALPHA = scope.def(BLEND_FUNCS, '[', read('dst', 'Alpha'), ']');\n              return [SRC_RGB, DST_RGB, SRC_ALPHA, DST_ALPHA];\n            });\n          case S_BLEND_EQUATION:\n            return parseParam(function (value) {\n              if (typeof value === 'string') {\n                check$1.commandParameter(value, blendEquations, 'invalid ' + prop, env.commandStr);\n                return [blendEquations[value], blendEquations[value]];\n              } else if (typeof value === 'object') {\n                check$1.commandParameter(value.rgb, blendEquations, prop + '.rgb', env.commandStr);\n                check$1.commandParameter(value.alpha, blendEquations, prop + '.alpha', env.commandStr);\n                return [blendEquations[value.rgb], blendEquations[value.alpha]];\n              } else {\n                check$1.commandRaise('invalid blend.equation', env.commandStr);\n              }\n            }, function (env, scope, value) {\n              var BLEND_EQUATIONS = env.constants.blendEquations;\n              var RGB = scope.def();\n              var ALPHA = scope.def();\n              var ifte = env.cond('typeof ', value, '===\"string\"');\n              check$1.optional(function () {\n                function checkProp(block, name, value) {\n                  env.assert(block, value + ' in ' + BLEND_EQUATIONS, 'invalid ' + name + ', must be one of ' + Object.keys(blendEquations));\n                }\n                checkProp(ifte.then, prop, value);\n                env.assert(ifte.else, value + '&&typeof ' + value + '===\"object\"', 'invalid ' + prop);\n                checkProp(ifte.else, prop + '.rgb', value + '.rgb');\n                checkProp(ifte.else, prop + '.alpha', value + '.alpha');\n              });\n              ifte.then(RGB, '=', ALPHA, '=', BLEND_EQUATIONS, '[', value, '];');\n              ifte.else(RGB, '=', BLEND_EQUATIONS, '[', value, '.rgb];', ALPHA, '=', BLEND_EQUATIONS, '[', value, '.alpha];');\n              scope(ifte);\n              return [RGB, ALPHA];\n            });\n          case S_BLEND_COLOR:\n            return parseParam(function (value) {\n              check$1.command(isArrayLike(value) && value.length === 4, 'blend.color must be a 4d array', env.commandStr);\n              return loop(4, function (i) {\n                return +value[i];\n              });\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, env.shared.isArrayLike + '(' + value + ')&&' + value + '.length===4', 'blend.color must be a 4d array');\n              });\n              return loop(4, function (i) {\n                return scope.def('+', value, '[', i, ']');\n              });\n            });\n          case S_STENCIL_MASK:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'number', param, env.commandStr);\n              return value | 0;\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, 'typeof ' + value + '===\"number\"', 'invalid stencil.mask');\n              });\n              return scope.def(value, '|0');\n            });\n          case S_STENCIL_FUNC:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'object', param, env.commandStr);\n              var cmp = value.cmp || 'keep';\n              var ref = value.ref || 0;\n              var mask = 'mask' in value ? value.mask : -1;\n              check$1.commandParameter(cmp, compareFuncs, prop + '.cmp', env.commandStr);\n              check$1.commandType(ref, 'number', prop + '.ref', env.commandStr);\n              check$1.commandType(mask, 'number', prop + '.mask', env.commandStr);\n              return [compareFuncs[cmp], ref, mask];\n            }, function (env, scope, value) {\n              var COMPARE_FUNCS = env.constants.compareFuncs;\n              check$1.optional(function () {\n                function assert() {\n                  env.assert(scope, Array.prototype.join.call(arguments, ''), 'invalid stencil.func');\n                }\n                assert(value + '&&typeof ', value, '===\"object\"');\n                assert('!(\"cmp\" in ', value, ')||(', value, '.cmp in ', COMPARE_FUNCS, ')');\n              });\n              var cmp = scope.def('\"cmp\" in ', value, '?', COMPARE_FUNCS, '[', value, '.cmp]', ':', GL_KEEP);\n              var ref = scope.def(value, '.ref|0');\n              var mask = scope.def('\"mask\" in ', value, '?', value, '.mask|0:-1');\n              return [cmp, ref, mask];\n            });\n          case S_STENCIL_OPFRONT:\n          case S_STENCIL_OPBACK:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'object', param, env.commandStr);\n              var fail = value.fail || 'keep';\n              var zfail = value.zfail || 'keep';\n              var zpass = value.zpass || 'keep';\n              check$1.commandParameter(fail, stencilOps, prop + '.fail', env.commandStr);\n              check$1.commandParameter(zfail, stencilOps, prop + '.zfail', env.commandStr);\n              check$1.commandParameter(zpass, stencilOps, prop + '.zpass', env.commandStr);\n              return [prop === S_STENCIL_OPBACK ? GL_BACK : GL_FRONT, stencilOps[fail], stencilOps[zfail], stencilOps[zpass]];\n            }, function (env, scope, value) {\n              var STENCIL_OPS = env.constants.stencilOps;\n              check$1.optional(function () {\n                env.assert(scope, value + '&&typeof ' + value + '===\"object\"', 'invalid ' + prop);\n              });\n              function read(name) {\n                check$1.optional(function () {\n                  env.assert(scope, '!(\"' + name + '\" in ' + value + ')||' + '(' + value + '.' + name + ' in ' + STENCIL_OPS + ')', 'invalid ' + prop + '.' + name + ', must be one of ' + Object.keys(stencilOps));\n                });\n                return scope.def('\"', name, '\" in ', value, '?', STENCIL_OPS, '[', value, '.', name, ']:', GL_
1KEEP);\n              }\n              return [prop === S_STENCIL_OPBACK ? GL_BACK : GL_FRONT, read('fail'), read('zfail'), read('zpass')];\n            });\n          case S_POLYGON_OFFSET_OFFSET:\n            return parseParam(function (value) {\n              check$1.commandType(value, 'object', param, env.commandStr);\n              var factor = value.factor | 0;\n              var units = value.units | 0;\n              check$1.commandType(factor, 'number', param + '.factor', env.commandStr);\n              check$1.commandType(units, 'number', param + '.units', env.commandStr);\n              return [factor, units];\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, value + '&&typeof ' + value + '===\"object\"', 'invalid ' + prop);\n              });\n              var FACTOR = scope.def(value, '.factor|0');\n              var UNITS = scope.def(value, '.units|0');\n              return [FACTOR, UNITS];\n            });\n          case S_CULL_FACE:\n            return parseParam(function (value) {\n              var face = 0;\n              if (value === 'front') {\n                face = GL_FRONT;\n              } else if (value === 'back') {\n                face = GL_BACK;\n              }\n              check$1.command(!!face, param, env.commandStr);\n              return face;\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, value + '===\"front\"||' + value + '===\"back\"', 'invalid cull.face');\n              });\n              return scope.def(value, '===\"front\"?', GL_FRONT, ':', GL_BACK);\n            });\n          case S_LINE_WIDTH:\n            return parseParam(function (value) {\n              check$1.command(typeof value === 'number' && value >= limits.lineWidthDims[0] && value <= limits.lineWidthDims[1], 'invalid line width, must be a positive number between ' + limits.lineWidthDims[0] + ' and ' + limits.lineWidthDims[1], env.commandStr);\n              return value;\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, 'typeof ' + value + '===\"number\"&&' + value + '>=' + limits.lineWidthDims[0] + '&&' + value + '<=' + limits.lineWidthDims[1], 'invalid line width');\n              });\n              return value;\n            });\n          case S_FRONT_FACE:\n            return parseParam(function (value) {\n              check$1.commandParameter(value, orientationType, param, env.commandStr);\n              return orientationType[value];\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, value + '===\"cw\"||' + value + '===\"ccw\"', 'invalid frontFace, must be one of cw,ccw');\n              });\n              return scope.def(value + '===\"cw\"?' + GL_CW + ':' + GL_CCW);\n            });\n          case S_COLOR_MASK:\n            return parseParam(function (value) {\n              check$1.command(isArrayLike(value) && value.length === 4, 'color.mask must be length 4 array', env.commandStr);\n              return value.map(function (v) {\n                return !!v;\n              });\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, env.shared.isArrayLike + '(' + value + ')&&' + value + '.length===4', 'invalid color.mask');\n              });\n              return loop(4, function (i) {\n                return '!!' + value + '[' + i + ']';\n              });\n            });\n          case S_SAMPLE_COVERAGE:\n            return parseParam(function (value) {\n              check$1.command(typeof value === 'object' && value, param, env.commandStr);\n              var sampleValue = 'value' in value ? value.value : 1;\n              var sampleInvert = !!value.invert;\n              check$1.command(typeof sampleValue === 'number' && sampleValue >= 0 && sampleValue <= 1, 'sample.coverage.value must be a number between 0 and 1', env.commandStr);\n              return [sampleValue, sampleInvert];\n            }, function (env, scope, value) {\n              check$1.optional(function () {\n                env.assert(scope, value + '&&typeof ' + value + '===\"object\"', 'invalid sample.coverage');\n              });\n              var VALUE = scope.def('\"value\" in ', value, '?+', value, '.value:1');
1\n              var INVERT = scope.def('!!', value, '.invert');\n              return [VALUE, INVERT];\n            });\n        }\n      });\n      return STATE;\n    }\n    function parseUniforms(uniforms, env) {\n      var staticUniforms = uniforms.static;\n      var dynamicUniforms = uniforms.dynamic;\n      var UNIFORMS = {};\n      Object.keys(staticUniforms).forEach(function (name) {\n        var value = staticUniforms[name];\n        var result;\n        if (typeof value === 'number' || typeof value === 'boolean') {\n          result = createStaticDecl(function () {\n            return value;\n          });\n        } else if (typeof value === 'function') {\n          var reglType = value._reglType;\n          if (reglType === 'texture2d' || reglType === 'textureCube') {\n            result = createStaticDecl(function (env) {\n              return env.link(value);\n            });\n          } else if (reglType === 'framebuffer' || reglType === 'framebufferCube') {\n            check$1.command(value.color.length > 0, 'missing color attachment for framebuffer sent to uniform \"' + name + '\"', env.commandStr);\n            result = createStaticDecl(function (env) {\n              return env.link(value.color[0]);\n            });\n          } else {\n            check$1.commandRaise('invalid data for uniform \"' + name + '\"', env.commandStr);\n          }\n        } else if (isArrayLike(value)) {\n          result = createStaticDecl(function (env) {\n            var ITEM = env.global.def('[', loop(value.length, function (i) {\n              check$1.command(typeof value[i] === 'number' || typeof value[i] === 'boolean', 'invalid uniform ' + name, env.commandStr);\n              return value[i];\n            }), ']');\n            return ITEM;\n          });\n        } else {\n          check$1.commandRaise('invalid or missing data for uniform \"' + name + '\"', env.commandStr);\n        }\n        result.value = value;\n        UNIFORMS[name] = result;\n      });\n      Object.keys(dynamicUniforms).forEach(function (key) {\n        var dyn = dynamicUniforms[key];\n        UNIFORMS[key] = createDynamicDecl(dyn, function (env, scope) {\n          return env.invoke(scope, dyn);\n        });\n      });\n      return UNIFORMS;\n    }\n    function parseAttributes(attributes, env) {\n      var staticAttributes = attributes.static;\n      var dynamicAttributes = attributes.dynamic;\n      var attributeDefs = {};\n      Object.keys(staticAttributes).forEach(function (attribute) {\n        var value = staticAttributes[attribute];\n        var id = stringStore.id(attribute);\n        var record = new AttributeRecord();\n        if (isBufferArgs(value)) {\n          record.state = ATTRIB_STATE_POINTER;\n          record.buffer = bufferState.getBuffer(bufferState.create(value, GL_ARRAY_BUFFER$2, false, true));\n          record.type = 0;\n        } else {\n          var buffer = bufferState.getBuffer(value);\n          if (buffer) {\n            record.state = ATTRIB_STATE_POINTER;\n            record.buffer = buffer;\n            record.type = 0;\n          } else {\n            check$1.command(typeof value === 'object' && value, 'invalid data for attribute ' + attribute, env.commandStr);\n            if ('constant' in value) {\n              var constant = value.constant;\n              record.buffer = 'null';\n              record.state = ATTRIB_STATE_CONSTANT;\n              if (typeof constant === 'number') {\n                record.x = constant;\n              } else {\n                check$1.command(isArrayLike(constant) && constant.length > 0 && constant.length <= 4, 'invalid constant for attribute ' + attribute, env.commandStr);\n                CUTE_COMPONENTS.forEach(function (c, i) {\n                  if (i < constant.length) {\n                    record[c] = constant[i];\n                  }\n                });\n              }\n            } else {\n              if (isBufferArgs(value.buffer)) {\n                buffer = bufferState.getBuffer(bufferState.create(value.buffer, GL_ARRAY_BUFFER$2, false, true));\n              } else {\n                buffer = bufferState.getBuffer(value.buffer);\n              }\n              check$1.command(!!buffer, 'missing buffer for attribute \"' + attribute + '\"', env.commandStr);\n              var offset = value.offset | 0;\n              check$1.command(offset >= 0, 'invalid offset for attribute \"' + attribute + '\"', env.commandStr);\n              var stride = value.stride | 0;\n              check$1.command(stride >= 0 && stride < 256, 'invalid stride for attribute \"' + attribute + '\", must be integer betweeen [0, 255]', env.commandStr);\n              var size = value.size | 0;\n              check$1.command(!('size' in value) || size > 0 && size <= 4, 'invalid size for attribute \"' + attribute + '\", must be 1,2,3,4', env.commandStr);\n              var normalized = !!value.normalized;\n              var type = 0;\n              if ('type' in value) {\n                check$1.commandParameter(value.type, glTypes, 'invalid type for attribute ' + attribute, env.commandStr);\n                type = glTypes[value.type];\n              }\n              var divisor = value.divisor | 0;\n              check$1.optional(function () {\n                if ('divisor' in value) {\n                  check$1.command(divisor === 0 || extInstancing, 'cannot specify divisor for attribute \"' + attribute + '\", instancing not supported', env.commandStr);\n                  check$1.command(divisor >= 0, 'invalid divisor for attribute \"' + attribute + '\"', env.commandStr);\n                }\n                var command = env.commandStr;\n                var VALID_KEYS = ['buffer', 'offset', 'divisor', 'normalized', 'type', 'size', 'stride'];\n                Object.keys(value).forEach(function (prop) {\n                  check$1.command(VALID_KEYS.indexOf(prop) >= 0, 'unknown parameter \"' + prop + '\" for attribute pointer \"' + attribute + '\" (valid parameters are ' + VALID_KEYS + ')', command);\n                });\n              });\n              record.buffer = buffer;\n              record.state = ATTRIB_STATE_POINTER;\n              record.size = size;\n              record.normalized = normalized;\n              record.type = type || buffer.dtype;\n              record.offset = offset;\n              record.stride = stride;\n              record.divisor = divisor;\n            }\n          }\n        }\n        attributeDefs[attribute] = createStaticDecl(function (env, scope) {\n          var cache = env.attribCache;\n          if (id in cache) {\n            return cache[id];\n          }
1\n          var result = {\n            isStream: false\n          };\n          Object.keys(record).forEach(function (key) {\n            result[key] = record[key];\n          });\n          if (record.buffer) {\n            result.buffer = env.link(record.buffer);\n            result.type = result.type || result.buffer + '.dtype';\n          }\n          cache[id] = result;\n          return result;\n        });\n      });\n      Object.keys(dynamicAttributes).forEach(function (attribute) {\n        var dyn = dynamicAttributes[attribute];\n        function appendAttributeCode(env, block) {\n          var VALUE = env.invoke(block, dyn);\n          var shared = env.shared;\n          var constants = env.constants;\n          var IS_BUFFER_ARGS = shared.isBufferArgs;\n          var BUFFER_STATE = shared.buffer;\n\n          // Perform validation on attribute\n          check$1.optional(function () {\n            env.assert(block, VALUE + '&&(typeof ' + VALUE + '===\"object\"||typeof ' + VALUE + '===\"function\")&&(' + IS_BUFFER_ARGS + '(' + VALUE + ')||' + BUFFER_STATE + '.getBuffer(' + VALUE + ')||' + BUFFER_STATE + '.getBuffer(' + VALUE + '.buffer)||' + IS_BUFFER_ARGS + '(' + VALUE + '.buffer)||' + '(\"constant\" in ' + VALUE + '&&(typeof ' + VALUE + '.constant===\"number\"||' + shared.isArrayLike + '(' + VALUE + '.constant))))', 'invalid dynamic attribute \"' + attribute + '\"');\n          });\n\n          // allocate names for result\n          var result = {\n            isStream: block.def(false)\n          };\n          var defaultRecord = new AttributeRecord();\n          defaultRecord.state = ATTRIB_STATE_POINTER;\n          Object.keys(defaultRecord).forEach(function (key) {\n            result[key] = block.def('' + defaultRecord[key]);\n          });\n          var BUFFER = result.buffer;\n          var TYPE = result.type;\n          block('if(', IS_BUFFER_ARGS, '(', VALUE, ')){', result.isStream, '=true;', BUFFER, '=', BUFFER_STATE, '.createStream(', GL_ARRAY_BUFFER$2, ',', VALUE, ');', TYPE, '=', BUFFER, '.dtype;', '}else{', BUFFER, '=', BUFFER_STATE, '.getBuffer(', VALUE, ');', 'if(', BUFFER, '){', TYPE, '=', BUFFER, '.dtype;', '}else if(\"constant\" in ', VALUE, '){', result.state, '=', ATTRIB_STATE_CONSTANT, ';', 'if(typeof ' + VALUE + '.constant === \"number\"){', result[CUTE_COMPONENTS[0]], '=', VALUE, '.constant;', CUTE_COMPONENTS.slice(1).map(function (n) {\n            return result[n];\n          }).join('='), '=0;', '}else{', CUTE_COMPONENTS.map(function (name, i) {\n            return result[name] + '=' + VALUE + '.constant.length>' + i + '?' + VALUE + '.constant[' + i + ']:0;';\n          }).join(''), '}}else{', 'if(', IS_BUFFER_ARGS, '(', VALUE, '.buffer)){', BUFFER, '=', BUFFER_STATE, '.createStream(', GL_ARRAY_BUFFER$2, ',', VALUE, '.buffer);', '}else{', BUFFER, '=', BUFFER_STATE, '.getBuffer(', VALUE, '.buffer);', '}', TYPE, '=\"type\" in ', VALUE, '?', constants.glTypes, '[', VALUE, '.type]:', BUFFER, '.dtype;', result.normalized, '=!!', VALUE, '.normalized;');\n          function emitReadRecord(name) {\n            block(result[name], '=', VALUE, '.', name, '|0;');\n          }\n          emitReadRecord('size');\n          emitReadRecord('offset');\n          emitReadRecord('stride');\n          emitReadRecord('divisor');\n          block('}}');\n          block.exit('if(', result.isStream, '){', BUFFER_STATE, '.destroyStream(', BUFFER, ');', '}');\n          return result;\n        }\n        attributeDefs[attribute] = createDynamicDecl(dyn, appendAttributeCode);\n      });\n      return attributeDefs;\n    }\n    function parseContext(context) {\n      var staticContext = context.static;\n      var dynamicContext = context.dynamic;\n      var result = {};\n      Object.keys(staticContext).forEach(function (name) {\n        var value = staticContext[name];\n        result[name] = createStaticDecl(function (env, scope) {\n          if (typeof value === 'number' || typeof value === 'boolean') {\n            return '' + value;\n          } else {\n            return env.link(value);\n          }\n        });\n      });\n      Object.keys(dynamicContext).forEach(function (name) {\n        var dyn = dynamicContext[name];\n        result[name] = createDynamicDecl(dyn, function (env, scope) {\n          return env.invoke(scope, dyn);\n        });\n      });\n      return result;\n    }\n    function parseArguments(options, attributes, uniforms, context, env) {\n      var staticOptions = options.static;\n      var dynamicOptions = options.dynamic;\n      check$1.optional(function () {\n        var KEY_NAMES = [S_FRAMEBUFFER, S_VERT, S_FRAG, S_ELEMENTS, S_PRIMITIVE, S_OFFSET, S_COUNT, S_INSTANCES, S_PROFILE, S_VAO].concat(GL_STATE_NAMES);\n        function checkKeys(dict) {\n          Object.keys(dict).forEach(function (key) {\n            check$1.command(KEY_NAMES.indexOf(key) >= 0, 'unknown parameter \"' + key + '\"', env.commandStr);\n          });\n        }\n        checkKeys(staticOptions);\n        checkKeys(dynamicOptions);\n      });\n      var attribLocations = parseAttribLocations(options, attributes);\n      var framebuffer = parseFramebuffer(options, env);\n      var viewportAndScissor = parseViewportScissor(options, framebuffer, env);\n      var draw = parseDraw(options, env);
1\n      var state = parseGLState(options, env);\n      var shader = parseProgram(options, env, attribLocations);\n      function copyBox(name) {\n        var defn = viewportAndScissor[name];\n        if (defn) {\n          state[name] = defn;\n        }\n      }\n      copyBox(S_VIEWPORT);\n      copyBox(propName(S_SCISSOR_BOX));\n      var dirty = Object.keys(state).length > 0;\n      var result = {\n        framebuffer: framebuffer,\n        draw: draw,\n        shader: shader,\n        state: state,\n        dirty: dirty,\n        scopeVAO: null,\n        drawVAO: null,\n        useVAO: false,\n        attributes: {}\n      };\n      result.profile = parseProfile(options, env);\n      result.uniforms = parseUniforms(uniforms, env);\n      result.drawVAO = result.scopeVAO = draw.vao;\n      // special case: check if we can statically allocate a vertex array object for this program\n      if (!result.drawVAO && shader.program && !attribLocations && extensions.angle_instanced_arrays && draw.static.elements) {\n        var useVAO = true;\n        var staticBindings = shader.program.attributes.map(function (attr) {\n          var binding = attributes.static[attr];\n          useVAO = useVAO && !!binding;\n          return binding;\n        });\n        if (useVAO && staticBindings.length > 0) {\n          var vao = attributeState.getVAO(attributeState.createVAO({\n            attributes: staticBindings,\n            elements: draw.static.elements\n          }));\n          result.drawVAO = new Declaration(null, null, null, function (env, scope) {\n            return env.link(vao);\n          });\n          result.useVAO = true;\n        }\n      }\n      if (attribLocations) {\n        result.useVAO = true;\n      } else {\n        result.attributes = parseAttributes(attributes, env);\n      }\n      result.context = parseContext(context, env);\n      return result;\n    }\n\n    // ===================================================\n    // ===================================================\n    // COMMON UPDATE FUNCTIONS\n    // ===================================================\n    // ===================================================\n    function emitContext(env, scope, context) {\n      var shared = env.shared;\n      var CONTEXT = shared.context;\n      var contextEnter = env.scope();\n      Object.keys(context).forEach(function (name) {\n        scope.save(CONTEXT, '.' + name);\n        var defn = context[name];\n        var value = defn.append(env, scope);\n        if (Array.isArray(value)) {\n          contextEnter(CONTEXT, '.', name, '=[', value.join(), '];');\n        } else {\n          contextEnter(CONTEXT, '.', name, '=', value, ';');\n        }\n      });\n      scope(contextEnter);\n    }\n\n    // ===================================================\n    // ===================================================\n    // COMMON DRAWING FUNCTIONS\n    // ===================================================\n    // ===================================================\n    function emitPollFramebuffer(env, scope, framebuffer, skipCheck) {\n      var shared = env.shared;\n      var GL = shared.gl;\n      var FRAMEBUFFER_STATE = shared.framebuffer;\n      var EXT_DRAW_BUFFERS;\n      if (extDrawBuffers) {\n        EXT_DRAW_BUFFERS = scope.def(shared.extensions, '.webgl_draw_buffers');\n      }\n      var constants = env.constants;\n      var DRAW_BUFFERS = constants.drawBuffer;\n      var BACK_BUFFER = constants.backBuffer;\n      var NEXT;\n      if (framebuffer) {\n        NEXT = framebuffer.append(env, scope);\n      } else {\n        NEXT = scope.def(FRAMEBUFFER_STATE, '.next');\n      }\n      if (!skipCheck) {\n        scope('if(', NEXT, '!==', FRAMEBUFFER_STATE, '.cur){');\n      }\n      scope('if(', NEXT, '){', GL, '.bindFramebuffer(', GL_FRAMEBUFFER$2, ',', NEXT, '.framebuffer);');\n      if (extDrawBuffers) {\n        scope(EXT_DRAW_BUFFERS, '.drawBuffersWEBGL(', DRAW_BUFFERS, '[', NEXT, '.colorAttachments.length]);');\n      }\n      scope('}else{', GL, '.bindFramebuffer(', GL_FRAMEBUFFER$2, ',null);');\n      if (extDrawBuffers) {\n        scope(EXT_DRAW_BUFFERS, '.drawBuffersWEBGL(', BACK_BUFFER, ');');\n      }\n      scope('}', FRAMEBUFFER_STATE, '.cur=', NEXT, ';');\n      if (!skipCheck) {\n        scope('}');\n      }\n    }\n    function emitPollState(env, scope, args) {\n      var shared = env.shared;\n      var GL = shared.gl;\n      var CURRENT_VARS = env.current;\n      var NEXT_VARS = env.next;\n      var CURRENT_STATE = shared.current;\n      var NEXT_STATE = shared.next;\n      var block = env.cond(CURRENT_STATE, '.dirty');\n      GL_STATE_NAMES.forEach(function (prop) {\n        var param = propName(prop);\n        if (param in args.state) {\n          return;\n        }\n        var NEXT, CURRENT;\n        if (param in NEXT_VARS) {\n          NEXT = NEXT_VARS[param];\n          CURRENT = CURRENT_VARS[param];\n          var parts = loop(currentState[param].length, function (i) {\n            return block.def(NEXT, '[', i, ']');\n          });\n          block(env.cond(parts.map(function (p, i) {\n            return p + '!==' + CURRENT + '[' + i + ']';\n          }).join('||')).then(GL, '.', GL_VARIABLES[param], '(', parts, ');', parts.map(function (p, i) {\n            return CURRENT + '[' + i + ']=' + p;\n          }).join(';'), ';'));\n        } else {\n          NEXT = block.def(NEXT_STATE, '.', param);\n          var ifte = env.cond(NEXT, '!==', CURRENT_STATE, '.', param);\n          block(ifte);\n          if (param in GL_FLAGS) {\n            ifte(env.cond(NEXT).then(GL, '.enable(', GL_FLAGS[param], ');').else(GL, '.disable(', GL_FLAGS[param], ');'), CURRENT_STATE, '.', param, '=', NEXT, ';');\n          } else {\n            ifte(GL, '.', GL_VARIABLES[param], '(', NEXT, ');', CURRENT_STATE, '.', param, '=', NEXT, ';');\n          }\n        }\n      });\n      if (Object.keys(args.state).length === 0) {\n        block(CURRENT_STATE, '.dirty=false;');\n      }\n      scope(block);\n    }\n    function emitSetOptions(env, scope, options, filter) {\n      var shared = env.shared;\n      var CURRENT_VARS = env.current;\n      var CURRENT_STATE = shared.current;\n      var GL = shared.gl;
1\n      sortState(Object.keys(options)).forEach(function (param) {\n        var defn = options[param];\n        if (filter && !filter(defn)) {\n          return;\n        }\n        var variable = defn.append(env, scope);\n        if (GL_FLAGS[param]) {\n          var flag = GL_FLAGS[param];\n          if (isStatic(defn)) {\n            if (variable) {\n              scope(GL, '.enable(', flag, ');');\n            } else {\n              scope(GL, '.disable(', flag, ');');\n            }\n          } else {\n            scope(env.cond(variable).then(GL, '.enable(', flag, ');').else(GL, '.disable(', flag, ');'));\n          }\n          scope(CURRENT_STATE, '.', param, '=', variable, ';');\n        } else if (isArrayLike(variable)) {\n          var CURRENT = CURRENT_VARS[param];\n          scope(GL, '.', GL_VARIABLES[param], '(', variable, ');', variable.map(function (v, i) {\n            return CURRENT + '[' + i + ']=' + v;\n          }).join(';'), ';');\n        } else {\n          scope(GL, '.', GL_VARIABLES[param], '(', variable, ');', CURRENT_STATE, '.', param, '=', variable, ';');\n        }\n      });\n    }\n    function injectExtensions(env, scope) {\n      if (extInstancing) {\n        env.instancing = scope.def(env.shared.extensions, '.angle_instanced_arrays');\n      }\n    }\n    function emitProfile(env, scope, args, useScope, incrementCounter) {\n      var shared = env.shared;\n      var STATS = env.stats;\n      var CURRENT_STATE = shared.current;\n      var TIMER = shared.timer;\n      var profileArg = args.profile;\n      function perfCounter() {\n        if (typeof performance === 'undefined') {\n          return 'Date.now()';\n        } else {\n          return 'performance.now()';\n        }\n      }\n      var CPU_START, QUERY_COUNTER;\n      function emitProfileStart(block) {\n        CPU_START = scope.def();\n        block(CPU_START, '=', perfCounter(), ';');\n        if (typeof incrementCounter === 'string') {\n          block(STATS, '.count+=', incrementCounter, ';');\n        } else {\n          block(STATS, '.count++;');\n        }\n        if (timer) {\n          if (useScope) {\n            QUERY_COUNTER = scope.def();\n            block(QUERY_COUNTER, '=', TIMER, '.getNumPendingQueries();');\n          } else {\n            block(TIMER, '.beginQuery(', STATS, ');');\n          }\n        }\n      }\n      function emitProfileEnd(block) {\n        block(STATS, '.cpuTime+=', perfCounter(), '-', CPU_START, ';');\n        if (timer) {\n          if (useScope) {\n            block(TIMER, '.pushScopeStats(', QUERY_COUNTER, ',', TIMER, '.getNumPendingQueries(),', STATS, ');');\n          } else {\n            block(TIMER, '.endQuery();');\n          }\n        }\n      }\n      function scopeProfile(value) {\n        var prev = scope.def(CURRENT_STATE, '.profile');\n        scope(CURRENT_STATE, '.profile=', value, ';');\n        scope.exit(CURRENT_STATE, '.profile=', prev, ';');\n      }\n      var USE_PROFILE;\n      if (profileArg) {\n        if (isStatic(profileArg)) {\n          if (profileArg.enable) {\n            emitProfileStart(scope);\n            emitProfileEnd(scope.exit);\n            scopeProfile('true');\n          } else {\n            scopeProfile('false');\n          }\n          return;\n        }\n        USE_PROFILE = profileArg.append(env, scope);\n        scopeProfile(USE_PROFILE);\n      } else {\n        USE_PROFILE = scope.def(CURRENT_STATE, '.profile');\n      }\n      var start = env.block();\n      emitProfileStart(start);\n      scope('if(', USE_PROFILE, '){', start, '}');\n      var end = env.block();\n      emitProfileEnd(end);\n      scope.exit('if(', USE_PROFILE, '){', end, '}');\n    }\n    function emitAttributes(env, scope, args, attributes, filter) {\n      var shared = env.shared;\n      function typeLength(x) {\n        switch (x) {\n          case GL_FLOAT_VEC2:\n          case GL_INT_VEC2:\n          case GL_BOOL_VEC2:\n            return 2;\n          case GL_FLOAT_VEC3:\n          case GL_INT_VEC3:\n          case GL_BOOL_VEC3:\n            return 3;\n          case GL_FLOAT_VEC4:\n          case GL_INT_VEC4:\n          case GL_BOOL_VEC4:\n            return 4;\n          default:\n            return 1;\n        }\n      }\n      function emitBindAttribute(ATTRIBUTE, size, record) {\n        var GL = shared.gl;\n        var LOCATION = scope.def(ATTRIBUTE, '.location');\n        var BINDING = scope.def(shared.attributes, '[', LOCATION, ']');\n        var STATE = record.state;\n        var BUFFER = record.buffer;\n        var CONST_COMPONENTS = [record.x, record.y, record.z, record.w];\n        var COMMON_KEYS = ['buffer', 'normalized', 'offset', 'stride'];\n        function emitBuffer() {\n          scope('if(!', BINDING, '.buffer){', GL, '.enableVertexAttribArray(', LOCATION, ');}');\n          var TYPE = record.type;\n          var SIZE;\n          if (!record.size) {\n            SIZE = size;\n          } else {\n            SIZE = scope.def(record.size, '||', size);\n          }\n          scope('if(', BINDING, '.type!==', TYPE, '||', BINDING, '.size!==', SIZE, '||', COMMON_KEYS.map(function (key) {\n            return BINDING + '.' + key + '!==' + record[key];\n          }).join('||'), '){', GL, '.bindBuffer(', GL_ARRAY_BUFFER$2, ',', BUFFER, '.buffer);', GL, '.vertexAttribPointer(', [LOCATION, SIZE, TYPE, record.normalized, record.stride, record.offset], ');', BINDING, '.type=', TYPE, ';', BINDING, '.size=', SIZE, ';', COMMON_KEYS.map(function (key) {\n            return BINDING + '.' + key + '=' + record[key] + ';';\n          }).join(''), '}');\n          if (extInstancing) {\n            var DIVISOR = record.divisor;\n            scope('if(', BINDING, '.divisor!==', DIVISOR, '){', env.instancing, '.vertexAttribDivisorANGLE(', [LOCATION, DIVISOR], ');', BINDING, '.divisor=', DIVISOR, ';}');\n          }\n        }\n        function emitConstant() {\n          scope('if(', BINDING, '.buffer){', GL, '.disableVertexAttribArray(', LOCATION, ');', BINDING, '.buffer=null;', '}if(', CUTE_COMPONENTS.map(function (c, i) {\n            return BINDING + '.' + c + '!==' + CONST_COMPONENTS[i];\n          }).join('||'), '){', GL, '.vertexAttrib4f(', LOCATION, ',', CONST_COMPONENTS, ');', CUTE_COMPONENTS.map(function (c, i) {\n            return BINDING + '.' + c + '=' + CONST_COMPONENTS[i] + ';';\n          }).join(''), '}');\n        }\n        if (STATE === ATTRIB_STATE_POINTER) {\n          emitBuffer();\n        } else if (STATE === ATTRIB_STATE_CONSTANT) {\n          emitConstant();\n        } else {\n          scope('if(', STATE, '===', ATTRIB_STATE_POINTER, '){');\n          emitBuffer();\n          scope('}else{');\n          emitConstant();\n          scope('}');\n        }\n      }
1\n      attributes.forEach(function (attribute) {\n        var name = attribute.name;\n        var arg = args.attributes[name];\n        var record;\n        if (arg) {\n          if (!filter(arg)) {\n            return;\n          }\n          record = arg.append(env, scope);\n        } else {\n          if (!filter(SCOPE_DECL)) {\n            return;\n          }\n          var scopeAttrib = env.scopeAttrib(name);\n          check$1.optional(function () {\n            env.assert(scope, scopeAttrib + '.state', 'missing attribute ' + name);\n          });\n          record = {};\n          Object.keys(new AttributeRecord()).forEach(function (key) {\n            record[key] = scope.def(scopeAttrib, '.', key);\n          });\n        }\n        emitBindAttribute(env.link(attribute), typeLength(attribute.info.type), record);\n      });\n    }\n    function emitUniforms(env, scope, args, uniforms, filter, isBatchInnerLoop) {\n      var shared = env.shared;\n      var GL = shared.gl;\n      var infix;\n      for (var i = 0; i < uniforms.length; ++i) {\n        var uniform = uniforms[i];\n        var name = uniform.name;\n        var type = uniform.info.type;\n        var arg = args.uniforms[name];\n        var UNIFORM = env.link(uniform);\n        var LOCATION = UNIFORM + '.location';\n        var VALUE;\n        if (arg) {\n          if (!filter(arg)) {\n            continue;\n          }\n          if (isStatic(arg)) {\n            var value = arg.value;\n            check$1.command(value !== null && typeof value !== 'undefined', 'missing uniform \"' + name + '\"', env.commandStr);\n            if (type === GL_SAMPLER_2D || type === GL_SAMPLER_CUBE) {\n              check$1.command(typeof value === 'function' && (type === GL_SAMPLER_2D && (value._reglType === 'texture2d' || value._reglType === 'framebuffer') || type === GL_SAMPLER_CUBE && (value._reglType === 'textureCube' || value._reglType === 'framebufferCube')), 'invalid texture for uniform ' + name, env.commandStr);\n              var TEX_VALUE = env.link(value._texture || value.color[0]._texture);\n              scope(GL, '.uniform1i(', LOCATION, ',', TEX_VALUE + '.bind());');\n              scope.exit(TEX_VALUE, '.unbind();');\n            } else if (type === GL_FLOAT_MAT2 || type === GL_FLOAT_MAT3 || type === GL_FLOAT_MAT4) {\n              check$1.optional(function () {\n                check$1.command(isArrayLike(value), 'invalid matrix for uniform ' + name, env.commandStr);\n                check$1.command(type === GL_FLOAT_MAT2 && value.length === 4 || type === GL_FLOAT_MAT3 && value.length === 9 || type === GL_FLOAT_MAT4 && value.length === 16, 'invalid length for matrix uniform ' + name, env.commandStr);\n              });\n              var MAT_VALUE = env.global.def('new Float32Array([' + Array.prototype.slice.call(value) + '])');\n              var dim = 2;\n              if (type === GL_FLOAT_MAT3) {\n                dim = 3;\n              } else if (type === GL_FLOAT_MAT4) {\n                dim = 4;\n              }\n              scope(GL, '.uniformMatrix', dim, 'fv(', LOCATION, ',false,', MAT_VALUE, ');');\n            } else {\n              switch (type) {\n                case GL_FLOAT$8:\n                  check$1.commandType(value, 'number', 'uniform ' + name, env.commandStr);\n                  infix = '1f';\n                  break;\n                case GL_FLOAT_VEC2:\n                  check$1.command(isArrayLike(value) && value.length === 2, 'uniform ' + name, env.commandStr);\n                  infix = '2f';\n                  break;\n                case GL_FLOAT_VEC3:\n                  check$1.command(isArrayLike(value) && value.length === 3, 'uniform ' + name, env.commandStr);\n                  infix = '3f';\n                  break;\n                case GL_FLOAT_VEC4:\n                  check$1.command(isArrayLike(value) && value.length === 4, 'uniform ' + name, env.commandStr);\n                  infix = '4f';\n                  break;\n                case GL_BOOL:\n                  check$1.commandType(value, 'boolean', 'uniform ' + name, env.commandStr);\n                  infix = '1i';\n                  break;\n                case GL_INT$3:\n                  check$1.commandType(value, 'number', 'uniform ' + name, env.commandStr);\n                  infix = '1i';\n                  break;\n                case GL_BOOL_VEC2:\n                  check$1.command(isArrayLike(value) && value.length === 2, 'uniform ' + name, env.commandStr);\n                  infix = '2i';\n                  break;\n                case GL_INT_VEC2:\n                  check$1.command(isArrayLike(value) && value.length === 2, 'uniform ' + name, env.commandStr);\n                  infix = '2i';\n                  break;\n                case GL_BOOL_VEC3:\n                  check$1.command(isArrayLike(value) && value.length === 3, 'uniform ' + name, env.commandStr);\n                  infix = '3i';\n                  break;\n                case GL_INT_VEC3:\n                  check$1.command(isArrayLike(value) && value.length === 3, 'uniform ' + name, env.commandStr);\n                  infix = '3i';\n                  break;\n                case GL_BOOL_VEC4:\n                  check$1.command(isArrayLike(value) && value.length === 4, 'uniform ' + name, env.commandStr);\n                  infix = '4i';
1\n                  break;\n                case GL_INT_VEC4:\n                  check$1.command(isArrayLike(value) && value.length === 4, 'uniform ' + name, env.commandStr);\n                  infix = '4i';\n                  break;\n              }\n              scope(GL, '.uniform', infix, '(', LOCATION, ',', isArrayLike(value) ? Array.prototype.slice.call(value) : value, ');');\n            }\n            continue;\n          } else {\n            VALUE = arg.append(env, scope);\n          }\n        } else {\n          if (!filter(SCOPE_DECL)) {\n            continue;\n          }\n          VALUE = scope.def(shared.uniforms, '[', stringStore.id(name), ']');\n        }\n        if (type === GL_SAMPLER_2D) {\n          check$1(!Array.isArray(VALUE), 'must specify a scalar prop for textures');\n          scope('if(', VALUE, '&&', VALUE, '._reglType===\"framebuffer\"){', VALUE, '=', VALUE, '.color[0];', '}');\n        } else if (type === GL_SAMPLER_CUBE) {\n          check$1(!Array.isArray(VALUE), 'must specify a scalar prop for cube maps');\n          scope('if(', VALUE, '&&', VALUE, '._reglType===\"framebufferCube\"){', VALUE, '=', VALUE, '.color[0];', '}');\n        }\n\n        // perform type validation\n        check$1.optional(function () {\n          function emitCheck(pred, message) {\n            env.assert(scope, pred, 'bad data or missing for uniform \"' + name + '\".  ' + message);\n          }\n          function checkType(type) {\n            check$1(!Array.isArray(VALUE), 'must not specify an array type for uniform');\n            emitCheck('typeof ' + VALUE + '===\"' + type + '\"', 'invalid type, expected ' + type);\n          }\n          function checkVector(n, type) {\n            if (Array.isArray(VALUE)) {\n              check$1(VALUE.length === n, 'must have length ' + n);\n            } else {\n              emitCheck(shared.isArrayLike + '(' + VALUE + ')&&' + VALUE + '.length===' + n, 'invalid vector, should have length ' + n, env.commandStr);\n            }\n          }\n          function checkTexture(target) {\n            check$1(!Array.isArray(VALUE), 'must not specify a value type');\n            emitCheck('typeof ' + VALUE + '===\"function\"&&' + VALUE + '._reglType===\"texture' + (target === GL_TEXTURE_2D$3 ? '2d' : 'Cube') + '\"', 'invalid texture type', env.commandStr);\n          }\n          switch (type) {\n            case GL_INT$3:\n              checkType('number');\n              break;\n            case GL_INT_VEC2:\n              checkVector(2, 'number');\n              break;\n            case GL_INT_VEC3:\n              checkVector(3, 'number');\n              break;\n            case GL_INT_VEC4:\n              checkVector(4, 'number');\n              break;\n            case GL_FLOAT$8:\n              checkType('number');\n              break;\n            case GL_FLOAT_VEC2:\n              checkVector(2, 'number');\n              break;\n            case GL_FLOAT_VEC3:\n              checkVector(3, 'number');\n              break;\n            case GL_FLOAT_VEC4:\n              checkVector(4, 'number');\n              break;\n            case GL_BOOL:\n              checkType('boolean');\n              break;\n            case GL_BOOL_VEC2:\n              checkVector(2, 'boolean');\n              break;\n            case GL_BOOL_VEC3:\n              checkVector(3, 'boolean');\n              break;\n            case GL_BOOL_VEC4:\n              checkVector(4, 'boolean');\n              break;\n            case GL_FLOAT_MAT2:\n              checkVector(4, 'number');\n              break;\n            case GL_FLOAT_MAT3:\n              checkVector(9, 'number');\n              break;\n            case GL_FLOAT_MAT4:\n              checkVector(16, 'number');\n              break;\n            case GL_SAMPLER_2D:\n              checkTexture(GL_TEXTURE_2D$3);\n              break;\n            case GL_SAMPLER_CUBE:\n              checkTexture(GL_TEXTURE_CUBE_MAP$2);\n              break;\n          }\n        });\n        var unroll = 1;\n        switch (type) {\n          case GL_SAMPLER_2D:\n          case GL_SAMPLER_CUBE:\n            var TEX = scope.def(VALUE, '._texture');\n            scope(GL, '.uniform1i(', LOCATION, ',', TEX, '.bind());');\n            scope.exit(TEX, '.unbind();');\n            continue;\n          case GL_INT$3:\n          case GL_BOOL:\n            infix = '1i';\n            break;\n          case GL_INT_VEC2:\n          case GL_BOOL_VEC2:\n            infix = '2i';\n            unroll = 2;\n            break;\n          case GL_INT_VEC3:\n          case GL_BOOL_VEC3:\n            infix = '3i';\n            unroll = 3;\n            break;\n          case GL_INT_VEC4:\n          case GL_BOOL_VEC4:\n            infix = '4i';
1\n            unroll = 4;\n            break;\n          case GL_FLOAT$8:\n            infix = '1f';\n            break;\n          case GL_FLOAT_VEC2:\n            infix = '2f';\n            unroll = 2;\n            break;\n          case GL_FLOAT_VEC3:\n            infix = '3f';\n            unroll = 3;\n            break;\n          case GL_FLOAT_VEC4:\n            infix = '4f';\n            unroll = 4;\n            break;\n          case GL_FLOAT_MAT2:\n            infix = 'Matrix2fv';\n            break;\n          case GL_FLOAT_MAT3:\n            infix = 'Matrix3fv';\n            break;\n          case GL_FLOAT_MAT4:\n            infix = 'Matrix4fv';\n            break;\n        }\n        if (infix.charAt(0) === 'M') {\n          scope(GL, '.uniform', infix, '(', LOCATION, ',');\n          var matSize = Math.pow(type - GL_FLOAT_MAT2 + 2, 2);\n          var STORAGE = env.global.def('new Float32Array(', matSize, ')');\n          if (Array.isArray(VALUE)) {\n            scope('false,(', loop(matSize, function (i) {\n              return STORAGE + '[' + i + ']=' + VALUE[i];\n            }), ',', STORAGE, ')');\n          } else {\n            scope('false,(Array.isArray(', VALUE, ')||', VALUE, ' instanceof Float32Array)?', VALUE, ':(', loop(matSize, function (i) {\n              return STORAGE + '[' + i + ']=' + VALUE + '[' + i + ']';\n            }), ',', STORAGE, ')');\n          }\n          scope(');');\n        } else if (unroll > 1) {\n          var prev = [];\n          var cur = [];\n          for (var j = 0; j < unroll; ++j) {\n            if (Array.isArray(VALUE)) {\n              cur.push(VALUE[j]);\n            } else {\n              cur.push(scope.def(VALUE + '[' + j + ']'));\n            }\n            if (isBatchInnerLoop) {\n              prev.push(scope.def());\n            }\n          }\n          if (isBatchInnerLoop) {\n            scope('if(!', env.batchId, '||', prev.map(function (p, i) {\n              return p + '!==' + cur[i];\n            }).join('||'), '){', prev.map(function (p, i) {\n              return p + '=' + cur[i] + ';';\n            }).join(''));\n          }\n          scope(GL, '.uniform', infix, '(', LOCATION, ',', cur.join(','), ');');\n          if (isBatchInnerLoop) {\n            scope('}');\n          }\n        } else {\n          check$1(!Array.isArray(VALUE), 'uniform value must not be an array');\n          if (isBatchInnerLoop) {\n            var prevS = scope.def();\n            scope('if(!', env.batchId, '||', prevS, '!==', VALUE, '){', prevS, '=', VALUE, ';');\n          }\n          scope(GL, '.uniform', infix, '(', LOCATION, ',', VALUE, ');');\n          if (isBatchInnerLoop) {\n            scope('}');\n          }\n        }\n      }\n    }\n    function emitDraw(env, outer, inner, args) {\n      var shared = env.shared;\n      var GL = shared.gl;\n      var DRAW_STATE = shared.draw;\n      var drawOptions = args.draw;\n      function emitElements() {\n        var defn = drawOptions.elements;\n        var ELEMENTS;\n        var scope = outer;\n        if (defn) {\n          if (defn.contextDep && args.contextDynamic || defn.propDep) {\n            scope = inner;\n          }\n          ELEMENTS = defn.append(env, scope);\n          if (drawOptions.elementsActive) {\n            scope('if(' + ELEMENTS + ')' + GL + '.bindBuffer(' + GL_ELEMENT_ARRAY_BUFFER$2 + ',' + ELEMENTS + '.buffer.buffer);');\n          }\n        } else {\n          ELEMENTS = scope.def();\n          scope(ELEMENTS, '=', DRAW_STATE, '.', S_ELEMENTS, ';', 'if(', ELEMENTS, '){', GL, '.bindBuffer(', GL_ELEMENT_ARRAY_BUFFER$2, ',', ELEMENTS, '.buffer.buffer);}', 'else if(', shared.vao, '.currentVAO){', ELEMENTS, '=', env.shared.elements + '.getElements(' + shared.vao, '.currentVAO.elements);', !extVertexArrays ? 'if(' + ELEMENTS + ')' + GL + '.bindBuffer(' + GL_ELEMENT_ARRAY_BUFFER$2 + ',' + ELEMENTS + '.buffer.buffer);' : '', '}');\n        }\n        return ELEMENTS;\n      }\n      function emitCount() {\n        var defn = drawOptions.count;\n        var COUNT;\n        var scope = outer;\n        if (defn) {\n          if (defn.contextDep && args.contextDynamic || defn.propDep) {\n            scope = inner;\n          }\n          COUNT = defn.append(env, scope);\n          check$1.optional(function () {\n            if (defn.MISSING) {\n              env.assert(outer, 'false', 'missing vertex count');\n            }\n            if (defn.DYNAMIC) {\n              env.assert(scope, COUNT + '>=0', 'missing vertex count');\n            }\n          });\n        } else {\n          COUNT = scope.def(DRAW_STATE, '.', S_COUNT);\n          check$1.optional(function () {\n            env.assert(scope, COUNT + '>=0', 'missing vertex count');\n          });\n        }\n        return COUNT;\n      }\n      var ELEMENTS = emitElements();\n      function emitValue(name) {\n        var defn = drawOptions[name];\n        if (defn) {\n          if (defn.contextDep && args.contextDynamic || defn.propDep) {\n            return defn.append(env, inner);\n          } else {\n            return defn.append(env, outer);\n          }\n        } else {\n          return outer.def(DRAW_STATE, '.', name);\n        }\n      }\n      var PRIMITIVE = emitValue(S_PRIMITIVE);\n      var OFFSET = emitValue(S_OFFSET);\n      var COUNT = emitCount();\n      if (typeof COUNT === 'number') {\n        if (COUNT === 0) {\n          return;\n        }\n      } else {\n        inner('if(', COUNT, '){');\n        inner.exit('}');\n      }\n      var INSTANCES, EXT_INSTANCING;\n      if (extInstancing) {\n        INSTANCES = emitValue(S_INSTANCES);\n        EXT_INSTANCING = env.instancing;\n      }\n      var ELEMENT_TYPE = ELEMENTS + '.type';\n      var elementsStatic = drawOptions.elements && isStatic(drawOptions.elements) && !drawOptions.vaoActive;\n      function emitInstancing() {\n        function drawElements() {\n          inner(EXT_INSTANCING, '.drawElementsInstancedANGLE(', [PRIMITIVE, COUNT, ELEMENT_TYPE, OFFSET + '<<((' + ELEMENT_TYPE + '-' + GL_UNSIGNED_BYTE$8 + ')>>1)', INSTANCES], ');');\n        }\n        function drawArrays() {\n          inner(EXT_INSTANCING, '.drawArraysInstancedANGLE(', [PRIMITIVE, OFFSET, COUNT, INSTANCES], ');');\n        }\n        if (ELEMENTS && ELEMENTS !== 'null') {\n          if (!elementsStatic) {\n            inner('if(', ELEMENTS, '){');\n            drawElements();\n            inner('}else{');\n            drawArrays();\n            inner('}');\n          } else {\n            drawElements();\n          }\n        } else {\n          drawArrays();\n        }\n      }\n      function emitRegular() {\n        function drawElements() {\n          inner(GL + '.drawElements(' + [PRIMITIVE, COUNT, ELEMENT_TYPE, OFFSET + '<<((' + ELEMENT_TYPE + '-' + GL_UNSIGNED_BYTE$8 + ')>>1)'] + ');');\n        }\n        function drawArrays() {\n          inner(GL + '.drawArrays(' + [PRIMITIVE, OFFSET, COUNT] + ');');\n        }\n        if (ELEMENTS && ELEMENTS !== 'null') {\n          if (!elementsStatic) {\n            inner('if(', ELEMENTS, '){');\n            drawElements();\n            inner('}else{');\n            drawArrays();\n            inner('}');\n          } else {\n            drawElements();\n          }\n        } else {\n          drawArrays();\n        }\n      }\n      if (extInstancing && (typeof INSTANCES !== 'number' || INSTANCES >= 0)) {\n        if (typeof INSTANCES === 'string') {\n          inner('if(', INSTANCES, '>0){');\n          emitInstancing();\n          inner('}else if(', INSTANCES, '<0){');\n          emitRegular();\n          inner('}');\n        } else {\n          emitInstancing();\n        }\n      } else {\n        emitRegular();\n      }\n    }\n    function createBody(emitBody, parentEnv, args, program, count) {\n      var env = createREGLEnvironment();\n      var scope = env.proc('body', count);\n      check$1.optional(function () {\n        env.commandStr = parentEnv.commandStr;\n        env.command = env.link(parentEnv.commandStr);\n      });\n      if (extInstancing) {\n        env.instancing = scope.def(env.shared.extensions, '.angle_instanced_arrays');\n      }\n      emitBody(env, scope, args, program);\n      return env.compile().body;\n    }\n\n    // ===================================================\n    // ===================================================\n    // DRAW PROC\n    // ===================================================\n    // ===================================================\n    function emitDrawBody(env, draw, args, program) {\n      injectExtensions(env, draw);\n      if (args.useVAO) {\n        if (args.drawVAO) {\n          draw(env.shared.vao, '.setVAO(', args.drawVAO.append(env, draw), ');');\n        } else {\n          draw(env.shared.vao, '.setVAO(', env.shared.vao, '.targetVAO);');\n        }\n      } else {\n        draw(env.shared.vao, '.setVAO(null);');\n        emitAttributes(env, draw, args, program.attributes, function () {\n          return true;\n        });\n      }\n      emitUniforms(env, draw, args, program.uniforms, function () {\n        return true;\n      }, false);\n      emitDraw(env, draw, draw, args);\n    }\n    function emitDrawProc(env, args) {\n      var draw = env.proc('draw', 1);\n      injectExtensions(env, draw);\n      emitContext(env, draw, args.context);\n      emitPollFramebuffer(env, draw, args.framebuffer);\n      emitPollState(env, draw, args);\n      emitSetOptions(env, draw, args.state);\n      emitProfile(env, draw, args, false, true);\n      var program = args.shader.progVar.append(env, draw);\n      draw(env.shared.gl, '.useProgram(', program, '.program);');\n      if (args.shader.program) {\n        emitDrawBody(env, draw, args, args.shader.program);\n      } else {\n        draw(env.shared.vao, '.setVAO(null);');\n        var drawCache = env.global.def('{}');\n        var PROG_ID = draw.def(program, '.id');\n        var CACHED_PROC = draw.def(drawCache, '[', PROG_ID, ']');\n        draw(env.cond(CACHED_PROC).then(CACHED_PROC, '.call(this,a0);').else(CACHED_PROC, '=', drawCache, '[', PROG_ID, ']=', env.link(function (program) {\n          return createBody(emitDrawBody, env, args, program, 1);\n        }), '(', program, ');', CACHED_PROC, '.call(this,a0);'));\n      }\n      if (Object.keys(args.state).length > 0) {\n        draw(env.shared.current, '.dirty=true;');\n      }\n      if (env.shared.vao) {\n        draw(env.shared.vao, '.setVAO(null);');\n      }\n    }\n\n    // ===================================================\n    // ===================================================\n    // BATCH PROC\n    // ===================================================\n    // ===================================================\n\n    function emitBatchDynamicShaderBody(env, scope, args, program) {\n      env.batchId = 'a1';\n      injectExtensions(env, scope);\n      function all() {\n        return true;\n      }\n      emitAttributes(env, scope, args, program.attributes, all);\n      emitUniforms(env, scope, args, program.uniforms, all, false);\n      emitDraw(env, scope, scope, args);\n    }\n    function emitBatchBody(env, scope, args, program) {\n      injectExtensions(env, scope);\n      var contextDynamic = args.contextDep;\n      var BATCH_ID = scope.def();\n      var PROP_LIST = 'a0';\n      var NUM_PROPS = 'a1';\n      var PROPS = scope.def();\n      env.shared.props = PROPS;\n      env.batchId = BATCH_ID;\n      var outer = env.scope();\n      var inner = env.scope();\n      scope(outer.entry, 'for(', BATCH_ID, '=0;', BATCH_ID, '<', NUM_PROPS, ';++', BATCH_ID, '){', PROPS, '=', PROP_LIST, '[', BATCH_ID, '];', inner, '}', outer.exit);\n      function isInnerDefn(defn) {\n        return defn.contextDep && contextDynamic || defn.propDep;\n      }\n      function isOuterDefn(defn) {\n        return !isInnerDefn(defn);\n      }\n      if (args.needsContext) {\n        emitContext(env, inner, args.context);\n      }\n      if (args.needsFramebuffer) {\n        emitPollFramebuffer(env, inner, args.framebuffer);\n      }\n      emitSetOptions(env, inner, args.state, isInnerDefn);
1\n      if (args.profile && isInnerDefn(args.profile)) {\n        emitProfile(env, inner, args, false, true);\n      }\n      if (!program) {\n        var progCache = env.global.def('{}');\n        var PROGRAM = args.shader.progVar.append(env, inner);\n        var PROG_ID = inner.def(PROGRAM, '.id');\n        var CACHED_PROC = inner.def(progCache, '[', PROG_ID, ']');\n        inner(env.shared.gl, '.useProgram(', PROGRAM, '.program);', 'if(!', CACHED_PROC, '){', CACHED_PROC, '=', progCache, '[', PROG_ID, ']=', env.link(function (program) {\n          return createBody(emitBatchDynamicShaderBody, env, args, program, 2);\n        }), '(', PROGRAM, ');}', CACHED_PROC, '.call(this,a0[', BATCH_ID, '],', BATCH_ID, ');');\n      } else {\n        if (args.useVAO) {\n          if (args.drawVAO) {\n            if (isInnerDefn(args.drawVAO)) {\n              // vao is a prop\n              inner(env.shared.vao, '.setVAO(', args.drawVAO.append(env, inner), ');');\n            } else {\n              // vao is invariant\n              outer(env.shared.vao, '.setVAO(', args.drawVAO.append(env, outer), ');');\n            }\n          } else {\n            // scoped vao binding\n            outer(env.shared.vao, '.setVAO(', env.shared.vao, '.targetVAO);');\n          }\n        } else {\n          outer(env.shared.vao, '.setVAO(null);');\n          emitAttributes(env, outer, args, program.attributes, isOuterDefn);\n          emitAttributes(env, inner, args, program.attributes, isInnerDefn);\n        }\n        emitUniforms(env, outer, args, program.uniforms, isOuterDefn, false);\n        emitUniforms(env, inner, args, program.uniforms, isInnerDefn, true);\n        emitDraw(env, outer, inner, args);\n      }\n    }\n    function emitBatchProc(env, args) {\n      var batch = env.proc('batch', 2);\n      env.batchId = '0';\n      injectExtensions(env, batch);\n\n      // Check if any context variables depend on props\n      var contextDynamic = false;\n      var needsContext = true;\n      Object.keys(args.context).forEach(function (name) {\n        contextDynamic = contextDynamic || args.context[name].propDep;\n      });\n      if (!contextDynamic) {\n        emitContext(env, batch, args.context);\n        needsContext = false;\n      }\n\n      // framebuffer state affects framebufferWidth/height context vars\n      var framebuffer = args.framebuffer;\n      var needsFramebuffer = false;\n      if (framebuffer) {\n        if (framebuffer.propDep) {\n          contextDynamic = needsFramebuffer = true;\n        } else if (framebuffer.contextDep && contextDynamic) {\n          needsFramebuffer = true;\n        }\n        if (!needsFramebuffer) {\n          emitPollFramebuffer(env, batch, framebuffer);\n        }\n      } else {\n        emitPollFramebuffer(env, batch, null);\n      }\n\n      // viewport is weird because it can affect context vars\n      if (args.state.viewport && args.state.viewport.propDep) {\n        contextDynamic = true;\n      }\n      function isInnerDefn(defn) {\n        return defn.contextDep && contextDynamic || defn.propDep;\n      }\n\n      // set webgl options\n      emitPollState(env, batch, args);\n      emitSetOptions(env, batch, args.state, function (defn) {\n        return !isInnerDefn(defn);\n      });\n      if (!args.profile || !isInnerDefn(args.profile)) {\n        emitProfile(env, batch, args, false, 'a1');\n      }\n\n      // Save these values to args so that the batch body routine can use them\n      args.contextDep = contextDynamic;\n      args.needsContext = needsContext;\n      args.needsFramebuffer = needsFramebuffer;\n\n      // determine if shader is dynamic\n      var progDefn = args.shader.progVar;\n      if (progDefn.contextDep && contextDynamic || progDefn.propDep) {\n        emitBatchBody(env, batch, args, null);\n      } else {\n        var PROGRAM = progDefn.append(env, batch);\n        batch(env.shared.gl, '.useProgram(', PROGRAM, '.program);');\n        if (args.shader.program) {\n          emitBatchBody(env, batch, args, args.shader.program);\n        } else {\n          batch(env.shared.vao, '.setVAO(null);');\n          var batchCache = env.global.def('{}');\n          var PROG_ID = batch.def(PROGRAM, '.id');\n          var CACHED_PROC = batch.def(batchCache, '[', PROG_ID, ']');\n          batch(env.cond(CACHED_PROC).then(CACHED_PROC, '.call(this,a0,a1);').else(CACHED_PROC, '=', batchCache, '[', PROG_ID, ']=', env.link(function (program) {\n            return createBody(emitBatchBody, env, args, program, 2);\n          }), '(', PROGRAM, ');', CACHED_PROC, '.call(this,a0,a1);'));\n        }\n      }\n      if (Object.keys(args.state).length > 0) {\n        batch(env.shared.current, '.dirty=true;');\n      }\n      if (env.shared.vao) {\n        batch(env.shared.vao, '.setVAO(null);');\n      }\n    }\n\n    // ===================================================\n    // ===================================================\n    // SCOPE COMMAND\n    // ===================================================\n    // ===================================================\n    function emitScopeProc(env, args) {\n      var scope = env.proc('scope', 3);\n      env.batchId = 'a2';\n      var shared = env.shared;\n      var CURRENT_STATE = shared.current;\n      emitContext(env, scope, args.context);\n      if (args.framebuffer) {\n        args.framebuffer.append(env, scope);\n      }
1\n      sortState(Object.keys(args.state)).forEach(function (name) {\n        var defn = args.state[name];\n        var value = defn.append(env, scope);\n        if (isArrayLike(value)) {\n          value.forEach(function (v, i) {\n            scope.set(env.next[name], '[' + i + ']', v);\n          });\n        } else {\n          scope.set(shared.next, '.' + name, value);\n        }\n      });\n      emitProfile(env, scope, args, true, true);\n      [S_ELEMENTS, S_OFFSET, S_COUNT, S_INSTANCES, S_PRIMITIVE].forEach(function (opt) {\n        var variable = args.draw[opt];\n        if (!variable) {\n          return;\n        }\n        scope.set(shared.draw, '.' + opt, '' + variable.append(env, scope));\n      });\n      Object.keys(args.uniforms).forEach(function (opt) {\n        var value = args.uniforms[opt].append(env, scope);\n        if (Array.isArray(value)) {\n          value = '[' + value.join() + ']';\n        }\n        scope.set(shared.uniforms, '[' + stringStore.id(opt) + ']', value);\n      });\n      Object.keys(args.attributes).forEach(function (name) {\n        var record = args.attributes[name].append(env, scope);\n        var scopeAttrib = env.scopeAttrib(name);\n        Object.keys(new AttributeRecord()).forEach(function (prop) {\n          scope.set(scopeAttrib, '.' + prop, record[prop]);\n        });\n      });\n      if (args.scopeVAO) {\n        scope.set(shared.vao, '.targetVAO', args.scopeVAO.append(env, scope));\n      }\n      function saveShader(name) {\n        var shader = args.shader[name];\n        if (shader) {\n          scope.set(shared.shader, '.' + name, shader.append(env, scope));\n        }\n      }\n      saveShader(S_VERT);\n      saveShader(S_FRAG);\n      if (Object.keys(args.state).length > 0) {\n        scope(CURRENT_STATE, '.dirty=true;');\n        scope.exit(CURRENT_STATE, '.dirty=true;');\n      }\n      scope('a1(', env.shared.context, ',a0,', env.batchId, ');');\n    }\n    function isDynamicObject(object) {\n      if (typeof object !== 'object' || isArrayLike(object)) {\n        return;\n      }\n      var props = Object.keys(object);\n      for (var i = 0; i < props.length; ++i) {\n        if (dynamic.isDynamic(object[props[i]])) {\n          return true;\n        }\n      }\n      return false;\n    }\n    function splatObject(env, options, name) {\n      var object = options.static[name];\n      if (!object || !isDynamicObject(object)) {\n        return;\n      }\n      var globals = env.global;\n      var keys = Object.keys(object);\n      var thisDep = false;\n      var contextDep = false;\n      var propDep = false;\n      var objectRef = env.global.def('{}');\n      keys.forEach(function (key) {\n        var value = object[key];\n        if (dynamic.isDynamic(value)) {\n          if (typeof value === 'function') {\n            value = object[key] = dynamic.unbox(value);\n          }\n          var deps = createDynamicDecl(value, null);\n          thisDep = thisDep || deps.thisDep;\n          propDep = propDep || deps.propDep;\n          contextDep = contextDep || deps.contextDep;\n        } else {\n          globals(objectRef, '.', key, '=');\n          switch (typeof value) {\n            case 'number':\n              globals(value);\n              break;\n            case 'string':\n              globals('\"', value, '\"');\n              break;\n            case 'object':\n              if (Array.isArray(value)) {\n                globals('[', value.join(), ']');\n              }\n              break;\n            default:\n              globals(env.link(value));\n              break;\n          }\n          globals(';');\n        }\n      });\n      function appendBlock(env, block) {\n        keys.forEach(function (key) {\n          var value = object[key];\n          if (!dynamic.isDynamic(value)) {\n            return;\n          }\n          var ref = env.invoke(block, value);\n          block(objectRef, '.', key, '=', ref, ';');\n        });\n      }\n      options.dynamic[name] = new dynamic.DynamicVariable(DYN_THUNK, {\n        thisDep: thisDep,\n        contextDep: contextDep,\n        propDep: propDep,\n        ref: objectRef,\n        append: appendBlock\n      });\n      delete options.static[name];\n    }\n\n    // ===========================================================================\n    // ===========================================================================\n    // MAIN DRAW COMMAND\n    // ===========================================================================\n    // ===========================================================================\n    function compileCommand(options, attributes, uniforms, context, stats) {\n      var env = createREGLEnvironment();\n\n      // link stats, so that we can easily access it in the program.\n      env.stats = env.link(stats);\n\n      // splat options and attributes to allow for dynamic nested properties\n      Object.keys(attributes.static).forEac
1h(function (key) {\n        splatObject(env, attributes, key);\n      });\n      NESTED_OPTIONS.forEach(function (name) {\n        splatObject(env, options, name);\n      });\n      var args = parseArguments(options, attributes, uniforms, context, env);\n      emitDrawProc(env, args);\n      emitScopeProc(env, args);\n      emitBatchProc(env, args);\n      return extend(env.compile(), {\n        destroy: function destroy() {\n          args.shader.program.destroy();\n        }\n      });\n    }\n\n    // ===========================================================================\n    // ===========================================================================\n    // POLL / REFRESH\n    // ===========================================================================\n    // ===========================================================================\n    return {\n      next: nextState,\n      current: currentState,\n      procs: function () {\n        var env = createREGLEnvironment();\n        var poll = env.proc('poll');\n        var refresh = env.proc('refresh');\n        var common = env.block();\n        poll(common);\n        refresh(common);\n        var shared = env.shared;\n        var GL = shared.gl;\n        var NEXT_STATE = shared.next;\n        var CURRENT_STATE = shared.current;\n        common(CURRENT_STATE, '.dirty=false;');\n        emitPollFramebuffer(env, poll);\n        emitPollFramebuffer(env, refresh, null, true);\n\n        // Refresh updates all attribute state changes\n        var INSTANCING;\n        if (extInstancing) {\n          INSTANCING = env.link(extInstancing);\n        }\n\n        // update vertex array bindings\n        if (extensions.oes_vertex_array_object) {\n          refresh(env.link(extensions.oes_vertex_array_object), '.bindVertexArrayOES(null);');\n        }\n        for (var i = 0; i < limits.maxAttributes; ++i) {\n          var BINDING = refresh.def(shared.attributes, '[', i, ']');\n          var ifte = env.cond(BINDING, '.buffer');\n          ifte.then(GL, '.enableVertexAttribArray(', i, ');', GL, '.bindBuffer(', GL_ARRAY_BUFFER$2, ',', BINDING, '.buffer.buffer);', GL, '.vertexAttribPointer(', i, ',', BINDING, '.size,', BINDING, '.type,', BINDING, '.normalized,', BINDING, '.stride,', BINDING, '.offset);').else(GL, '.disableVertexAttribArray(', i, ');', GL, '.vertexAttrib4f(', i, ',', BINDING, '.x,', BINDING, '.y,', BINDING, '.z,', BINDING, '.w);', BINDING, '.buffer=null;');\n          refresh(ifte);\n          if (extInstancing) {\n            refresh(INSTANCING, '.vertexAttribDivisorANGLE(', i, ',', BINDING, '.divisor);');\n          }\n        }\n        refresh(env.shared.vao, '.currentVAO=null;', env.shared.vao, '.setVAO(', env.shared.vao, '.targetVAO);');\n        Object.keys(GL_FLAGS).forEach(function (flag) {\n          var cap = GL_FLAGS[flag];\n          var NEXT = common.def(NEXT_STATE, '.', flag);\n          var block = env.block();\n          block('if(', NEXT, '){', GL, '.enable(', cap, ')}else{', GL, '.disable(', cap, ')}', CURRENT_STATE, '.', flag, '=', NEXT, ';');\n          refresh(block);\n          poll('if(', NEXT, '!==', CURRENT_STATE, '.', flag, '){', block, '}');\n        });\n        Object.keys(GL_VARIABLES).forEach(function (name) {\n          var func = GL_VARIABLES[name];\n          var init = currentState[name];\n          var NEXT, CURRENT;\n          var block = env.block();\n          block(GL, '.', func, '(');\n          if (isArrayLike(init)) {\n            var n = init.length;\n            NEXT = env.global.def(NEXT_STATE, '.', name);\n            CURRENT = env.global.def(CURRENT_STATE, '.', name);\n            block(loop(n, function (i) {\n              return NEXT + '[' + i + ']';\n            }), ');', loop(n, function (i) {\n              return CURRENT + '[' + i + ']=' + NEXT + '[' + i + '];';\n            }).join(''));\n            poll('if(', loop(n, function (i) {\n              return NEXT + '[' + i + ']!==' + CURRENT + '[' + i + ']';\n            }).join('||'), '){', block, '}');\n          } else {\n            NEXT = common.def(NEXT_STATE, '.', name);\n            CURRENT = common.def(CURRENT_STATE, '.', name);\n            block(NEXT, ');', CURRENT_STATE, '.', name, '=', NEXT, ';');\n            poll('if(', NEXT, '!==', CURRENT, '){', block, '}');\n          }\n          refresh(block);\n        });\n        return env.compile();\n      }(),\n      compile: compileCommand\n    };\n  }\n  function stats() {\n    return {\n      vaoCount: 0,\n      bufferCount: 0,\n      elementsCount: 0,\n      framebufferCount: 0,\n      shaderCount: 0,\n      textureCount: 0,\n      cubeC
1ount: 0,\n      renderbufferCount: 0,\n      maxTextureUnits: 0\n    };\n  }\n  var GL_QUERY_RESULT_EXT = 0x8866;\n  var GL_QUERY_RESULT_AVAILABLE_EXT = 0x8867;\n  var GL_TIME_ELAPSED_EXT = 0x88BF;\n  var createTimer = function createTimer(gl, extensions) {\n    if (!extensions.ext_disjoint_timer_query) {\n      return null;\n    }\n\n    // QUERY POOL BEGIN\n    var queryPool = [];\n    function allocQuery() {\n      return queryPool.pop() || extensions.ext_disjoint_timer_query.createQueryEXT();\n    }\n    function freeQuery(query) {\n      queryPool.push(query);\n    }\n    // QUERY POOL END\n\n    var pendingQueries = [];\n    function beginQuery(stats) {\n      var query = allocQuery();\n      extensions.ext_disjoint_timer_query.beginQueryEXT(GL_TIME_ELAPSED_EXT, query);\n      pendingQueries.push(query);\n      pushScopeStats(pendingQueries.length - 1, pendingQueries.length, stats);\n    }\n    function endQuery() {\n      extensions.ext_disjoint_timer_query.endQueryEXT(GL_TIME_ELAPSED_EXT);\n    }\n\n    //\n    // Pending stats pool.\n    //\n    function PendingStats() {\n      this.startQueryIndex = -1;\n      this.endQueryIndex = -1;\n      this.sum = 0;\n      this.stats = null;\n    }\n    var pendingStatsPool = [];\n    function allocPendingStats() {\n      return pendingStatsPool.pop() || new PendingStats();\n    }\n    function freePendingStats(pendingStats) {\n      pendingStatsPool.push(pendingStats);\n    }\n    // Pending stats pool end\n\n    var pendingStats = [];\n    function pushScopeStats(start, end, stats) {\n      var ps = allocPendingStats();\n      ps.startQueryIndex = start;\n      ps.endQueryIndex = end;\n      ps.sum = 0;\n      ps.stats = stats;\n      pendingStats.push(ps);\n    }\n\n    // we should call this at the beginning of the frame,\n    // in order to update gpuTime\n    var timeSum = [];\n    var queryPtr = [];\n    function update() {\n      var ptr, i;\n      var n = pendingQueries.length;\n      if (n === 0) {\n        return;\n      }\n\n      // Reserve space\n      queryPtr.length = Math.max(queryPtr.length, n + 1);\n      timeSum.length = Math.max(timeSum.length, n + 1);\n      timeSum[0] = 0;\n      queryPtr[0] = 0;\n\n      // Update all pending timer queries\n      var queryTime = 0;\n      ptr = 0;\n      for (i = 0; i < pendingQueries.length; ++i) {\n        var query = pendingQueries[i];\n        if (extensions.ext_disjoint_timer_query.getQueryObjectEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT)) {\n          queryTime += extensions.ext_disjoint_timer_query.getQueryObjectEXT(query, GL_QUERY_RESULT_EXT);\n          freeQuery(query);\n        } else {\n          pendingQueries[ptr++] = query;\n        }\n        timeSum[i + 1] = queryTime;\n        queryPtr[i + 1] = ptr;\n      }\n      pendingQueries.length = ptr;\n\n      // Update all pending stat queries\n      ptr = 0;\n      for (i = 0; i < pendingStats.length; ++i) {\n        var stats = pendingStats[i];\n        var start = stats.startQueryIndex;\n        var end = stats.endQueryIndex;\n        stats.sum += timeSum[end] - timeSum[start];\n        var startPtr = queryPtr[start];\n        var endPtr = queryPtr[end];\n        if (endPtr === startPtr) {\n          stats.stats.gpuTime += stats.sum / 1e6;\n          freePendingStats(stats);\n        } else {\n          stats.startQueryIndex = startPtr;\n          stats.endQueryIndex = endPtr;\n          pendingStats[ptr++] = stats;\n        }\n      }\n      pendingStats.length = ptr;\n    }\n    return {\n      beginQuery: beginQuery,\n      endQuery: endQuery,\n      pushScopeStats: pushScopeStats,\n      update: update,\n      getNumPendingQueries: function getNumPendingQueries() {\n        return pendingQueries.length;\n      },\n      clear: function clear() {\n        queryPool.push.apply(queryPool, pendingQueries);\n        for (var i = 0; i < queryPool.length; i++) {\n          extensions.ext_disjoint_timer_query.deleteQueryEXT(queryPool[i]);\n        }\n        pendingQueries.length = 0;\n        queryPool.length = 0;\n      }
1,\n      restore: function restore() {\n        pendingQueries.length = 0;\n        queryPool.length = 0;\n      }\n    };\n  };\n  var GL_COLOR_BUFFER_BIT = 16384;\n  var GL_DEPTH_BUFFER_BIT = 256;\n  var GL_STENCIL_BUFFER_BIT = 1024;\n  var GL_ARRAY_BUFFER = 34962;\n  var CONTEXT_LOST_EVENT = 'webglcontextlost';\n  var CONTEXT_RESTORED_EVENT = 'webglcontextrestored';\n  var DYN_PROP = 1;\n  var DYN_CONTEXT = 2;\n  var DYN_STATE = 3;\n  function find(haystack, needle) {\n    for (var i = 0; i < haystack.length; ++i) {\n      if (haystack[i] === needle) {\n        return i;\n      }\n    }\n    return -1;\n  }\n  function wrapREGL(args) {\n    var config = parseArgs(args);\n    if (!config) {\n      return null;\n    }\n    var gl = config.gl;\n    var glAttributes = gl.getContextAttributes();\n    var contextLost = gl.isContextLost();\n    var extensionState = createExtensionCache(gl, config);\n    if (!extensionState) {\n      return null;\n    }\n    var stringStore = createStringStore();\n    var stats$$1 = stats();\n    var extensions = extensionState.extensions;\n    var timer = createTimer(gl, extensions);\n    var START_TIME = clock();\n    var WIDTH = gl.drawingBufferWidth;\n    var HEIGHT = gl.drawingBufferHeight;\n    var contextState = {\n      tick: 0,\n      time: 0,\n      viewportWidth: WIDTH,\n      viewportHeight: HEIGHT,\n      framebufferWidth: WIDTH,\n      framebufferHeight: HEIGHT,\n      drawingBufferWidth: WIDTH,\n      drawingBufferHeight: HEIGHT,\n      pixelRatio: config.pixelRatio\n    };\n    var uniformState = {};\n    var drawState = {\n      elements: null,\n      primitive: 4,\n      // GL_TRIANGLES\n      count: -1,\n      offset: 0,\n      instances: -1\n    };\n    var limits = wrapLimits(gl, extensions);\n    var bufferState = wrapBufferState(gl, stats$$1, config, destroyBuffer);\n    var elementState = wrapElementsState(gl, extensions, bufferState, stats$$1);\n    var attributeState = wrapAttributeState(gl, extensions, limits, stats$$1, bufferState, elementState, drawState);\n    function destroyBuffer(buffer) {\n      return attributeState.destroyBuffer(buffer);\n    }\n    var shaderState = wrapShaderState(gl, stringStore, stats$$1, config);\n    var textureState = createTextureSet(gl, extensions, limits, function () {\n      core.procs.poll();\n    }, contextState, stats$$1, config);\n    var renderbufferState = wrapRenderbuffers(gl, extensions, limits, stats$$1, config);\n    var framebufferState = wrapFBOState(gl, extensions, limits, textureState, renderbufferState, stats$$1);\n    var core = reglCore(gl, stringStore, extensions, limits, bufferState, elementState, textureState, framebufferState, uniformState, attributeState, shaderState, drawState, contextState, timer, config);\n    var readPixels = wrapReadPixels(gl, framebufferState, core.procs.poll, contextState, glAttributes, extensions, limits);\n    var nextState = core.next;\n    var canvas = gl.canvas;\n    var rafCallbacks = [];\n    var lossCallbacks = [];\n    var restoreCallbacks = [];\n    var destroyCallbacks = [config.onDestroy];\n    var activeRAF = null;\n    function handleRAF() {\n      if (rafCallbacks.length === 0) {\n        if (timer) {\n          timer.update(
1);\n        }\n        activeRAF = null;\n        return;\n      }\n\n      // schedule next animation frame\n      activeRAF = raf.next(handleRAF);\n\n      // poll for changes\n      _poll();\n\n      // fire a callback for all pending rafs\n      for (var i = rafCallbacks.length - 1; i >= 0; --i) {\n        var cb = rafCallbacks[i];\n        if (cb) {\n          cb(contextState, null, 0);\n        }\n      }\n\n      // flush all pending webgl calls\n      gl.flush();\n\n      // poll GPU timers *after* gl.flush so we don't delay command dispatch\n      if (timer) {\n        timer.update();\n      }\n    }\n    function startRAF() {\n      if (!activeRAF && rafCallbacks.length > 0) {\n        activeRAF = raf.next(handleRAF);\n      }\n    }\n    function stopRAF() {\n      if (activeRAF) {\n        raf.cancel(handleRAF);\n        activeRAF = null;\n      }\n    }\n    function handleContextLoss(event) {\n      event.preventDefault();\n\n      // set context lost flag\n      contextLost = true;\n\n      // pause request animation frame\n      stopRAF();\n\n      // lose context\n      lossCallbacks.forEach(function (cb) {\n        cb();\n      });\n    }\n    function handleContextRestored(event) {\n      // clear error code\n      gl.getError();\n\n      // clear context lost flag\n      contextLost = false;\n\n      // refresh state\n      extensionState.restore();\n      shaderState.restore();\n      bufferState.restore();\n      textureState.restore();\n      renderbufferState.restore();\n      framebufferState.restore();\n      attributeState.restore();\n      if (timer) {\n        timer.restore();\n      }\n\n      // refresh state\n      core.procs.refresh();\n\n      // restart RAF\n      startRAF();\n\n      // restore context\n      restoreCallbacks.forEach(function (cb) {\n        cb();\n      });\n    }\n    if (canvas) {\n      canvas.addEventListener(CONTEXT_LOST_EVENT, handleContextLoss, false);\n      canvas.addEventListener(CONTEXT_RESTORED_EVENT, handleContextRestored, false);\n    }\n    function destroy() {\n      rafCallbacks.length = 0;\n      stopRAF();\n      if (canvas) {\n        canvas.removeEventListener(CONTEXT_LOST_EVENT, handleContextLoss);\n        canvas.removeEventListener(CONTEXT_RESTORED_EVENT, handleContextRestored);\n      }\n      shaderState.clear();\n      framebufferState.clear();\n      renderbufferState.clear();\n      attributeState.clear();\n      textureState.clear();\n      elementState.clear();\n      bufferState.clear();\n      if (timer) {\n        timer.clear();\n      }\n      destroyCallbacks.forEach(function (cb) {\n        cb();\n      });\n    }\n    function compileProcedure(options) {\n      check$1(!!options, 'invalid args to regl({...})');\n      check$1.type(options, 'object', 'invalid args to regl({...})');\n      function flattenNestedOptions(options) {\n        var result = extend({}, options);\n        delete result.uniforms;\n        delete result.attributes;\n        delete result.context;\n        delete result.vao;\n        if ('stencil' in result && result.stencil.op) {\n          result.stencil.opBack = result.stencil.opFront = result.stencil.op;\n          delete result.stencil.op;\n        }\n        function merge(name) {\n          if (name in result) {\n            var child = result[name];\n            delete result[name];\n            Object.keys(child).forEach(function (prop) {\n              result[name + '.' + prop] = child[prop];\n            });\n          }\n        }\n        merge('blend');\n        merge('depth');\n        merge('cull');\n        merge('stencil');\n        merge('polygonOffset');\n        merge('scissor');\n        merge('sample');\n        if ('vao' in options) {\n          result.vao = options.vao;\n        }\n        return result;\n      }\n      function separateDynamic(object, useArrays) {\n        var staticItems = {};\n        var dynamicItems = {};\n        Object.keys(object).forEach(function (option) {\n          var value = object[option];\n          if (dynamic.isDynamic(value)) {\n            dynamicItems[option] = dynamic.unbox(value, option);\n            return;\n          } else if (useArrays && Array.isArray(value)) {\n            for (var i = 0; i < value.length; ++i) {\n              if (dynamic.isDynamic(value[i])) {\n                dynamicItems[option] = dynamic.unbox(value, option);\n                return;\n              }\n            }\n          }\n          staticItems[option] = value;\n        });\n        return {\n          dynamic: dynamicItems,\n          static: staticItems\n        };\n      }\n\n      // Treat context variables separate from other dynamic variables\n      var context = separateDynamic(options.context || {}, true);\n      var uniforms = separateDynamic(options.uniforms || {}, true);\n      var attributes = separateDynamic(options.attributes || {}, false);\n      var opts = separateDynamic(flattenNestedOptions(options), false);\n      var stats$$1 = {\n        gpuTime: 0.0,\n        cpuTime: 0.0,\n        count: 0\n      };\n      var compiled = core.compile(opts, attributes, uniforms, context, stats$$1);\n      var draw = compiled.draw;\n      var batch = compiled.batch;\n      var scope = compiled.scope;\n\n      // FIXME: we should modify code generation for batch commands so this\n      // isn't necessary\n      var EMPTY_ARRAY = [];\n      function reserve(count) {\n        while (EMPTY_ARRAY.length < count) {\n          EMPTY_ARRAY.push(null);\n        }\n        return EMPTY_ARRAY;\n      }
1\n      function REGLCommand(args, body) {\n        var i;\n        if (contextLost) {\n          check$1.raise('context lost');\n        }\n        if (typeof args === 'function') {\n          return scope.call(this, null, args, 0);\n        } else if (typeof body === 'function') {\n          if (typeof args === 'number') {\n            for (i = 0; i < args; ++i) {\n              scope.call(this, null, body, i);\n            }\n          } else if (Array.isArray(args)) {\n            for (i = 0; i < args.length; ++i) {\n              scope.call(this, args[i], body, i);\n            }\n          } else {\n            return scope.call(this, args, body, 0);\n          }\n        } else if (typeof args === 'number') {\n          if (args > 0) {\n            return batch.call(this, reserve(args | 0), args | 0);\n          }\n        } else if (Array.isArray(args)) {\n          if (args.length) {\n            return batch.call(this, args, args.length);\n          }\n        } else {\n          return draw.call(this, args);\n        }\n      }\n      return extend(REGLCommand, {\n        stats: stats$$1,\n        destroy: function destroy() {\n          compiled.destroy();\n        }\n      });\n    }\n    var setFBO = framebufferState.setFBO = compileProcedure({\n      framebuffer: dynamic.define.call(null, DYN_PROP, 'framebuffer')\n    });\n    function clearImpl(_, options) {\n      var clearFlags = 0;\n      core.procs.poll();\n      var c = options.color;\n      if (c) {\n        gl.clearColor(+c[0] || 0, +c[1] || 0, +c[2] || 0, +c[3] || 0);\n        clearFlags |= GL_COLOR_BUFFER_BIT;\n      }\n      if ('depth' in options) {\n        gl.clearDepth(+options.depth);\n        clearFlags |= GL_DEPTH_BUFFER_BIT;\n      }\n      if ('stencil' in options) {\n        gl.clearStencil(options.stencil | 0);\n        clearFlags |= GL_STENCIL_BUFFER_BIT;\n      }\n      check$1(!!clearFlags, 'called regl.clear with no buffer specified');\n      gl.clear(clearFlags);\n    }\n    function clear(options) {\n      check$1(typeof options === 'object' && options, 'regl.clear() takes an object as input');\n      if ('framebuffer' in options) {\n        if (options.framebuffer && options.framebuffer_reglType === 'framebufferCube') {\n          for (var i = 0; i < 6; ++i) {\n            setFBO(extend({\n              framebuffer: options.framebuffer.faces[i]\n            }, options), clearImpl);\n          }\n        } else {\n          setFBO(options, clearImpl);\n        }\n      } else {\n        clearImpl(null, options);\n      }\n    }\n    function frame(cb) {\n      check$1.type(cb, 'function', 'regl.frame() callback must be a function');\n      rafCallbacks.push(cb);\n      function cancel() {\n        // FIXME:  should we check something other than equals cb here?\n        // what if a user calls frame twice with the same callback...\n        //\n        var i = find(rafCallbacks, cb);\n        check$1(i >= 0, 'cannot cancel a frame twice');\n        function pendingCancel() {\n          var index = find(rafCallbacks, pendingCancel);\n          rafCallbacks[index] = rafCallbacks[rafCallbacks.length - 1];\n          rafCallbacks.length -= 1;\n          if (rafCallbacks.length <= 0) {\n            stopRAF();\n          }\n        }\n        rafCallbacks[i] = pendingCancel;\n      }\n      startRAF();\n      return {\n        cancel: cancel\n      };\n    }\n\n    // poll viewport\n    function pollViewport() {\n      var viewport = nextState.viewport;\n      var scissorBox = nextState.scissor_box;\n      viewport[0] = viewport[1] = scissorBox[0] = scissorBox[1] = 0;\n      contextState.viewportWidth = contextState.framebufferWidth = contextState.drawingBufferWidth = viewport[2] = scissorBox[2] = gl.drawingBufferWidth;\n      contextState.viewportHeight = contextState.framebufferHeight = contextState.drawingBufferHeight = viewport[3] = scissorBox[3] = gl.drawingBufferHeight;\n    }\n    function _poll() {\n      contextState.tick += 1;\n      contextState.time = now();\n      pollViewport();\n      core.procs.poll();\n    }\n    function refresh() {\n      textureState.refresh();\n      pollViewport();\n      core.procs.refresh();
1\n      if (timer) {\n        timer.update();\n      }\n    }\n    function now() {\n      return (clock() - START_TIME) / 1000.0;\n    }\n    refresh();\n    function addListener(event, callback) {\n      check$1.type(callback, 'function', 'listener callback must be a function');\n      var callbacks;\n      switch (event) {\n        case 'frame':\n          return frame(callback);\n        case 'lost':\n          callbacks = lossCallbacks;\n          break;\n        case 'restore':\n          callbacks = restoreCallbacks;\n          break;\n        case 'destroy':\n          callbacks = destroyCallbacks;\n          break;\n        default:\n          check$1.raise('invalid event, must be one of frame,lost,restore,destroy');\n      }\n      callbacks.push(callback);\n      return {\n        cancel: function cancel() {\n          for (var i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i] === callback) {\n              callbacks[i] = callbacks[callbacks.length - 1];\n              callbacks.pop();\n              return;\n            }\n          }\n        }\n      };\n    }\n    var regl = extend(compileProcedure, {\n      // Clear current FBO\n      clear: clear,\n      // Short cuts for dynamic variables\n      prop: dynamic.define.bind(null, DYN_PROP),\n      context: dynamic.define.bind(null, DYN_CONTEXT),\n      this: dynamic.define.bind(null, DYN_STATE),\n      // executes an empty draw command\n      draw: compileProcedure({}),\n      // Resources\n      buffer: function buffer(options) {\n        return bufferState.create(options, GL_ARRAY_BUFFER, false, false);\n      },\n      elements: function elements(options) {\n        return elementState.create(options, false);\n      },\n      texture: textureState.create2D,\n      cube: textureState.createCube,\n      renderbuffer: renderbufferState.create,\n      framebuffer: framebufferState.create,\n      framebufferCube: framebufferState.createCube,\n      vao: attributeState.createVAO,\n      // Expose context attributes\n      attributes: glAttributes,\n      // Frame rendering\n      frame: frame,\n      on: addListener,\n      // System limits\n      limits: limits,\n      hasExtension: function hasExtension(name) {\n        return limits.extensions.indexOf(name.toLowerCase()) >= 0;\n      },\n      // Read pixels\n      read: readPixels,\n      // Destroy regl and all associated resources\n      destroy: destroy,\n      // Direct GL state manipulation\n      _gl: gl,\n      _refresh: refresh,\n      poll: function poll() {\n        _poll();
1\n        if (timer) {\n          timer.update();\n        }\n      },\n      // Current time\n      now: now,\n      // regl Statistics Information\n      stats: stats$$1\n    });\n    config.onDone(null, regl);\n    return regl;\n  }\n  return wrapREGL;\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjM5Ni5qcyIsIm1hcHBpbmdzIjoiQUFBQSxtQkFBTyxDQUFDLElBQWtDO0FBQzFDLG1CQUFPLENBQUMsSUFBdUM7QUFDL0MsbUJBQU8sQ0FBQyxHQUF3QztBQUNoRDtBQUNBLEVBQUUsS0FBNEQsZ0NBQWdDLENBQTRGO0FBQzFMLENBQUM7QUFDRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLGlCQUFpQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0Isa0JBQWtCO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0VBQStFLDBCQUEwQjtBQUN6RztBQUNBO0FBQ0EsNEVBQTRFO0FBQzVFLCtDQUErQyx5QkFBeUI7O0FBRXhFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRSwwQkFBMEI7QUFDL0YsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLFFBQVE7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixrQkFBa0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsUUFBUTtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxZQUFZO0FBQ1o7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLHFCQUFxQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsT0FBTztBQUNQLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0F
1BRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQSxvQkFBb0IsOEJBQThCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLE9BQU87QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGNBQWM7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtR0FBbUc7QUFDbkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLFFBQVE7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixRQUFRO0FBQzVCO0FBQ0Esc0JBQXNCLFFBQVE7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLFFBQVE7QUFDNUI7QUFDQSxzQkFBc0IsUUFBUTtBQUM5QjtBQUNBLHdCQUF3QixRQUFRO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGtCQUFrQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixPQUFPO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixrQkFBa0IsT0FBTztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGtCQUFrQjtBQUN4QztBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLGNBQWM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCLDBCQUEwQjtBQUMxQiwwQkFBMEI7QUFDMUIsMEJBQTBCO0FBQzFCLDBCQUEwQjtBQUMxQiwwQkFBMEI7QUFDMUIsMEJBQTBCOztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixnQkFBZ0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixZQUFZO0FBQ2hDLHNCQUFzQixZQUFZO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGtCQUFrQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QU
1FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLGtCQUFrQjtBQUN0QztBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsT0FBTztBQUMzQixzQkFBc0IsT0FBTztBQUM3Qix3QkFBd0IsT0FBTztBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0F
1BRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxLQUFLLElBQUk7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsd0JBQXdCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsb0JBQW9CO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLFFBQVE7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QU
1FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLGlCQUFpQjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isc0JBQXNCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixPQUFPO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLE9BQU87QUFDN0I7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLE9BQU87QUFDakM7QU
1FDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2QsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixPQUFPO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLE9BQU87QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixPQUFPO0FBQy9CLDBCQUEwQixzQkFBc0I7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixpQkFBaUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsaUJBQWlCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLFFBQVE7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWiw0QkFBNEIsT0FBTztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxzQkFBc0IsaUJBQWlCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxVQUFVO0FBQ1Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQiw2QkFBNkI7QUFDL0M7QUFDQTtBQUNBLHdDQUF3QyxnQ0FBZ0M7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QU
1FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsVUFBVTtBQUNWO0FBQ0Esc0JBQXNCLGdCQUFnQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsNkJBQTZCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdCQUF3Qiw2QkFBNkI7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHdCQUF3QjtB
1QUNoRDtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGdCQUFnQjtBQUN0QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG9CQUFvQix1QkFBdUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLE9BQU87QUFDM0IsMEJBQTBCLHVCQUF1QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsbUJBQW1CO0FBQ3ZDO0FBQ0E7QUFDQSxvQkFBb0IsT0FBTztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLG9CQUFvQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLDhCQUE4QjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0Esd0JBQXdCLDhCQUE4QjtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsdUJBQXVCO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0Msb0JBQW9CO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixpQkFBaUI7QUFDN0M7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix1QkFBdUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdCQUF3Qix3QkFBd0I7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHdCQUF3QjtB
1QUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGlCQUFpQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLCtCQUErQjtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixpQkFBaUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGVBQWU7QUFDM0M7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLHdCQUF3QjtB
1QUM5QztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQix5QkFBeUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRDtBQUMzRDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDO0FBQzVDLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLG1CQUFtQjtBQUNsRDtBQUNBLHVDQUF1QyxxQkFBcUI7QUFDNUQ7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixXQUFXO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9ELHFCQUFxQjtBQUN6RTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0MseUJBQXlCO0FBQ3pEO0FBQ0E7QUFDQSxPQUFPO0FBQ1Asa0JBQWtCO0FBQ2xCLHFDQUFxQyxNQUFNLGVBQWUsTUFBTSxlQUFlLE1BQU07QUFDckY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLHFCQUFxQjtBQUMzQztBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0F
1BRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0dBQXdHO0FBQ3hHO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLHdCQUF3QjtB
1QUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1HQUFtRztBQUNuRyxhQUFhO0FBQ2I7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvSEFBb0gsdUVBQXVFO0FBQzNMO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxtR0FBbUc7QUFDbkc7QUFDQTtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxXQUFXO0FBQ1gsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGNBQWM7QUFDZDtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBLGlCQUFpQjtBQUNqQixnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZiw4RUFBOEU7QUFDOUUsc0VBQXNFLHFEQUFxRDtBQUMzSDtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsYUFBYTtBQUNiO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBLGVBQWU7QUFDZixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QU
1FDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGFBQWE7QUFDYjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixZQUFZO0FBQ1o7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSx1REFBdUQsMkJBQTJCLGtGQUFrRiw4QkFBOEIsS0FBSyxLQUFLLHVEQUF1RCxxQkFBcUIsOEJBQThCLEtBQUssbUNBQW1DLCtDQUErQyxtREFBbUQsc0RBQXNEO0FBQ3RmO0FBQ0EsV0FBVyxpQkFBaUIsS0FBSyxLQUFLO0FBQ3RDLGdIQUFnSDtBQUNoSCxXQUFXLGVBQWUsS0FBSyxpREFB
1aUQseUZBQXlGLEtBQUssS0FBSyw4REFBOEQsS0FBSyw4RkFBOEYsaURBQWlEO0FBQ3JZO0FBQ0EsMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkIsZ0RBQWdELCtDQUErQyxLQUFLO0FBQ3BHO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEUsVUFBVTtBQUNWLHlEQUF5RDtBQUN6RDtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBLDREQUE0RDtBQUM1RDtBQUNBLDRCQUE0Qix3RUFBd0U7QUFDcEc7QUFDQSwyR0FBMkc7QUFDM0c7QUFDQSxjQUFjLEtBQUssc0RBQXNEO0FBQ3pFO0FBQ0Esc0VBQXNFO0FBQ3RFO0FBQ0EsY0FBYyx1Q0FBdUM7QUFDckQ7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXLGdFQUFnRTtBQUMzRTtBQUNBLFdBQVcsU0FBUyxNQUFNO0FBQzFCLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlFQUF5RSw2Q0FBNkMsNENBQTRDO0FBQ2xLLFlBQVk7QUFDWiw2REFBNkQsMkNBQTJDO0FBQ3hHO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDLGNBQWM7QUFDZCw4Q0FBOEM7QUFDOUM7QUFDQSxZQUFZO0FBQ1osbUVBQW1FLGtDQUFrQztBQUNyRztBQUNBLDREQUE0RDtBQUM1RCxVQUFVO0FBQ1Y7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQSxXQUFXLFNBQVMsTUFBTTtBQUMxQixVQUFVO0FBQ1YsZ0VBQWdFLCtDQUErQztBQUMvRztBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0EsdURBQXVEO0FBQ3ZELFVBQVU7QUFDVixpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRUFBc0U7QUFDdEUsWUFBWTtBQUNaLG1EQUFtRDtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRTtBQUNwRTtBQUNBO0FBQ0EsOEdBQThHO0FBQzlHLFlBQVk7QUFDWixzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRDtBQUNuRCx1REFBdUQ7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsWUFBWTtBQUMvQztBQUNBO0FBQ0Esd0NBQXdDLFVBQVU7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLGtEQUFrRDtBQUM3RjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsaUJBQWlCLGlFQUFpRSw0R0FBNEcsOEJBQThCLDhCQUE4QjtBQUNyUSwrREFBK0Q7QUFDL0QsV0FBVyxjQUFjO0FBQ3pCO0FBQ0E7QUFDQSw2REFBNkQseUVBQXlFLHFDQUFxQztBQUMzSztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsa0RBQWtELDBCQUEwQixLQUFLO0FBQzNIO0FBQ0EsV0FBVyxpQkFBaUIsK0RBQStEO0FBQzNGLHFFQUFxRTtBQUNyRSxXQUFXLGNBQWM7QUFDekI7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsVUFBVTtBQUNWLDhEQUE4RDtBQUM5RDtBQUNBLGtCQUFrQixLQUFLO0FBQ3ZCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IscUJBQXFCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0RUFBNEU7QUFDNUUsK0NBQStDO0FBQy9DLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBLHlGQUF5RjtBQUN6RixjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtJQUFrSTtBQUNsSTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3RUFBd0UsaUNBQWlDLEtBQUs7QUFDOUcsVUFBVTtBQUNWO0FBQ0EsNEVBQTRFLGlD
1QUFpQyxLQUFLO0FBQ2xIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRTtBQUNuRSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxtQkFBbUI7QUFDbkIsVUFBVTtBQUNWO0FBQ0E7QUFDQSwwQkFBMEIsWUFBWTtBQUN0QztBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsaUJBQWlCO0FBQzlCLDBDQUEwQztBQUMxQyxhQUFhO0FBQ2I7QUFDQSw2RUFBNkU7QUFDN0U7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0EscUVBQXFFLHdCQUF3QjtB
1QUM3RjtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtIQUErSDtBQUMvSDtBQUNBLFVBQVU7QUFDVjtBQUNBLDhEQUE4RCx1QkFBdUIsbUZBQW1GLHlDQUF5Qyw2RkFBNkYsbUlBQW1JLFVBQVU7QUFDM2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUiwrQkFBK0I7QUFDL0IscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUxBQXFMO0FBQ3JMO0FBQ0E7QUFDQSx3R0FBd0c7QUFDeEc7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDO0FBQ0Esb0JBQW9CLEtBQUs7QUFDekI7QUFDQSxvQkFBb0I7QUFDcEIsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1KQUFtSjtBQUNuSjtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBLG9CQUFvQixLQUFLO0FBQ3pCO0FBQ0Esb0JBQW9CO0FBQ3BCLFlBQVk7QUFDWjtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSxrQkFBa0IsMkJBQTJCO0FBQzdDO0FBQ0Esa0JBQWtCO0FBQ2xCLFVBQVU7QUFDVjtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEVBQThFO0FBQzlFLFVBQVU7QUFDVix3RUFBd0U7QUFDeEU7QUFDQSxRQUFRO0FBQ1IsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQ7QUFDQTtBQUNBLFFBQVE7QUFDUiw0Q0FBNEM7QUFDNUMsMENBQTBDO0FBQzFDO0FBQ0E7QUFDQSxxRUFBcUU7QUFDckU7QUFDQSxTQUFTLG9CQUFvQixnQ0FBZ0M7QUFDN0Q7QUFDQTtBQUNBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0EsNENBQTRDO0FBQzVDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsK0JBQStCLGtCQUFrQiw0Q0FBNEMsWUFBWTtBQUN4SjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDO0FBQzFDO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRSwyQkFBMkI7QUFDNUY7QUFDQSxTQUFTLHFCQUFxQiwrREFBK0Q7QUFDN0YsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0ZBQW9GO0FBQ3BGLGNBQWM7QUFDZDtBQUNBLG9GQUFvRjtBQUNwRjtBQUNBLFlBQVk7QUFDWjtBQUNBLDJFQUEyRTtBQUMzRTtBQUNBLFVBQVU7QUFDViwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSxpRUFBaUU7QUFDakU7QUFDQTtBQUNBLFVBQVU7QUFDViwrQ0FBK0M7QUFDL0MsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQSwyRUFBMkU7QUFDM0U7QUFDQSxXQUFXLG9CQUFvQixtQ0FBbUM7QUFDbEU7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0E7QUFDQSw2Q0FBNkM7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFVBQVU7QUFDVjtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUMsK0NBQStDO0FBQy9DO0FBQ0EsK0RBQStEO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtB
1QUNwQjtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEM7QUFDNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyRkFBMkY7QUFDM0Y7QUFDQSx3QkFBd0IsMEJBQTBCO0FBQ2xEO0FBQ0E7QUFDQSwyREFBMkQseUVBQXlFLCtJQUErSSxnREFBZ0QsaUdBQWlHLDBCQUEwQjtBQUM5YjtBQUNBO0FBQ0EsMEZBQTBGO0FBQzFGO0FBQ0E7QUFDQSxrREFBa0QsNERBQTREO0FBQzlHO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLDJCQUEyQixLQUFLLDRCQUE0QiwwQ0FBMEM7QUFDdEk7QUFDQSxnRUFBZ0UsWUFBWTtBQUM1RSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLG9FQUFvRTtBQUNwRSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWEsaUJBQWlCLFlBQVk7QUFDMUMsWUFBWTtBQUNaO0FBQ0E7QUFDQSwyQkFBMkIsMENBQTBDO0FBQ3JFLGlEQUFpRCxZQUFZO0FBQzdEO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsMkJBQTJCO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLHlCQUF5QjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0Esd0JBQXdCLHNCQUFzQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixxQkFBcUI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsNENBQTRDLFFBQVE7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsZ0RBQWdELElBQUk7QUFDcEQsNkRBQTZELElBQUk7QUFDakU7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWiw0QkFBNEIsa0JBQWtCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5REFBeUQ7QUFDekQsMkRBQTJEO0FBQzNELCtEQUErRDtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBLHdCQUF3QixVQUFVO0FBQ2xDO0FBQ0E7QUFDQSxZQUFZO0FBQ1osd0JBQXdCLGlCQUFpQjtBQUN6QztBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtB
1QUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLHNCQUFzQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vY3BwLW11dHRlci8uL25vZGVfbW9kdWxlcy9yZWdsL2Rpc3QvcmVnbC5qcz9mMTJmIl0sInNvdXJjZXNDb250ZW50IjpbInJlcXVpcmUoXCJjb3JlLWpzL21vZHVsZXMvZXMuYXJyYXkuc29ydC5qc1wiKTtcbnJlcXVpcmUoXCJjb3JlLWpzL21vZHVsZXMvZXMudHlwZWQtYXJyYXkuc2V0LmpzXCIpO1xucmVxdWlyZShcImNvcmUtanMvbW9kdWxlcy9lcy50eXBlZC1hcnJheS5zb3J0LmpzXCIpO1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOiB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOiBnbG9iYWwuY3JlYXRlUkVHTCA9IGZhY3RvcnkoKTtcbn0pKHRoaXMsIGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBpc1R5cGVkQXJyYXkgPSBmdW5jdGlvbiBpc1R5cGVkQXJyYXkoeCkge1xuICAgIHJldHVybiB4IGluc3RhbmNlb2YgVWludDhBcnJheSB8fCB4IGluc3RhbmNlb2YgVWludDE2QXJyYXkgfHwgeCBpbnN0YW5jZW9mIFVpbnQzMkFycmF5IHx8IHggaW5zdGFuY2VvZiBJbnQ4QXJyYXkgfHwgeCBpbnN0YW5jZW9mIEludDE2QXJyYXkgfHwgeCBpbnN0YW5jZW9mIEludDMyQXJyYXkgfHwgeCBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSB8fCB4IGluc3RhbmNlb2YgRmxvYXQ2NEFycmF5IHx8IHggaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheTtcbiAgfTtcbiAgdmFyIGV4dGVuZCA9IGZ1bmN0aW9uIGV4dGVuZChiYXNlLCBvcHRzKSB7XG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvcHRzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGJhc2Vba2V5c1tpXV0gPSBvcHRzW2tleXNbaV1dO1xuICAgIH1cbiAgICByZXR1cm4gYmFzZTtcbiAgfTtcblxuICAvLyBFcnJvciBjaGVja2luZyBhbmQgcGFyYW1ldGVyIHZhbGlkYXRpb24uXG4gIC8vXG4gIC8vIFN0YXRlbWVudHMgZm9yIHRoZSBmb3JtIGBjaGVjay5zb21lUHJvY2VkdXJlKC4uLilgIGdldCByZW1vdmVkIGJ5XG4gIC8vIGEgYnJvd3NlcmlmeSB0cmFuc2Zvcm0gZm9yIG9wdGltaXplZC9taW5pZmllZCBidW5kbGVzLlxuICAvL1xuICAvKiBnbG9iYWxzIGF0b2IgKi9cbiAgdmFyIGVuZGwgPSAnXFxuJztcblxuICAvLyBvbmx5IHVzZWQgZm9yIGV4dHJhY3Rpbmcgc2hhZGVyIG5hbWVzLiAgaWYgYXRvYiBub3QgcHJlc2VudCwgdGhlbiBlcnJvcnNcbiAgLy8gd2lsbCBiZSBzbGlnaHRseSBjcmFwcGllclxuICBmdW5jdGlvbiBkZWNvZGVCNjQoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBhdG9iICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIGF0b2Ioc3RyKTtcbiAgICB9XG4gICAgcmV0dXJuICdiYXNlNjQ6JyArIHN0cjtcbiAgfVxuICBmdW5jdGlvbiByYWlzZShtZXNzYWdlKSB7XG4gICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCcocmVnbCkgJyArIG1lc3NhZ2UpO1xuICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG4gIGZ1bmN0aW9uIGNoZWNrKHByZWQsIG1lc3NhZ2UpIHtcbiAgICBpZiAoIXByZWQpIHtcbiAgICAgIHJhaXNlKG1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBlbmNvbG9uKG1lc3NhZ2UpIHtcbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgcmV0dXJuICc6ICcgKyBtZXNzYWdlO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cbiAgZnVuY3Rpb24gY2hlY2tQYXJhbWV0ZXIocGFyYW0sIHBvc3NpYmlsaXRpZXMsIG1lc3NhZ2UpIHtcbiAgICBpZiAoIShwYXJhbSBpbiBwb3NzaWJpbGl0aWVzKSkge1xuICAgICAgcmFpc2UoJ3Vua25vd24gcGFyYW1ldGVyICgnICsgcGFyYW0gKyAnKScgKyBlbmNvbG9uKG1lc3NhZ2UpICsgJy4gcG9zc2libGUgdmFsdWVzOiAnICsgT2JqZWN0LmtleXMocG9zc2liaWxpdGllcykuam9pbigpKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gY2hlY2tJc1R5cGVkQXJyYXkoZGF0YSwgbWVzc2FnZSkge1xuICAgIGlmICghaXNUeXBlZEFycmF5KGRhdGEpKSB7XG4gICAgICByYWlzZSgnaW52YWxpZCBwYXJhbWV0ZXIgdHlwZScgKyBlbmNvbG9uKG1lc3NhZ2UpICsgJy4gbXVzdCBiZSBhIHR5cGVkIGFycmF5Jyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHN0YW5kYXJkVHlwZUVoKHZhbHVlLCB0eXBlKSB7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbiAgICAgIGNhc2UgJ29iamVjdCc6XG4gICAgICAgI
1HJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG4gICAgICBjYXNlICdib29sZWFuJzpcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xuICAgICAgY2FzZSAnZnVuY3Rpb24nOlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nO1xuICAgICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICBjYXNlICdzeW1ib2wnOlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gY2hlY2tUeXBlT2YodmFsdWUsIHR5cGUsIG1lc3NhZ2UpIHtcbiAgICBpZiAoIXN0YW5kYXJkVHlwZUVoKHZhbHVlLCB0eXBlKSkge1xuICAgICAgcmFpc2UoJ2ludmFsaWQgcGFyYW1ldGVyIHR5cGUnICsgZW5jb2xvbihtZXNzYWdlKSArICcuIGV4cGVjdGVkICcgKyB0eXBlICsgJywgZ290ICcgKyB0eXBlb2YgdmFsdWUpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjaGVja05vbk5lZ2F0aXZlSW50KHZhbHVlLCBtZXNzYWdlKSB7XG4gICAgaWYgKCEodmFsdWUgPj0gMCAmJiAodmFsdWUgfCAwKSA9PT0gdmFsdWUpKSB7XG4gICAgICByYWlzZSgnaW52YWxpZCBwYXJhbWV0ZXIgdHlwZSwgKCcgKyB2YWx1ZSArICcpJyArIGVuY29sb24obWVzc2FnZSkgKyAnLiBtdXN0IGJlIGEgbm9ubmVnYXRpdmUgaW50ZWdlcicpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjaGVja09uZU9mKHZhbHVlLCBsaXN0LCBtZXNzYWdlKSB7XG4gICAgaWYgKGxpc3QuaW5kZXhPZih2YWx1ZSkgPCAwKSB7XG4gICAgICByYWlzZSgnaW52YWxpZCB2YWx1ZScgKyBlbmNvbG9uKG1lc3NhZ2UpICsgJy4gbXVzdCBiZSBvbmUgb2Y6ICcgKyBsaXN0KTtcbiAgICB9XG4gIH1cbiAgdmFyIGNvbnN0cnVjdG9yS2V5cyA9IFsnZ2wnLCAnY2FudmFzJywgJ2NvbnRhaW5lcicsICdhdHRyaWJ1dGVzJywgJ3BpeGVsUmF0aW8nLCAnZXh0ZW5zaW9ucycsICdvcHRpb25hbEV4dGVuc2lvbnMnLCAncHJvZmlsZScsICdvbkRvbmUnXTtcbiAgZnVuY3Rpb24gY2hlY2tDb25zdHJ1Y3RvcihvYmopIHtcbiAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgaWYgKGNvbnN0cnVjdG9yS2V5cy5pbmRleE9mKGtleSkgPCAwKSB7XG4gICAgICAgIHJhaXNlKCdpbnZhbGlkIHJlZ2wgY29uc3RydWN0b3IgYXJndW1lbnQgXCInICsga2V5ICsgJ1wiLiBtdXN0IGJlIG9uZSBvZiAnICsgY29uc3RydWN0b3JLZXlzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBsZWZ0UGFkKHN0ciwgbikge1xuICAgIHN0ciA9IHN0ciArICcnO1xuICAgIHdoaWxlIChzdHIubGVuZ3RoIDwgbikge1xuICAgICAgc3RyID0gJyAnICsgc3RyO1xuICAgIH1cbiAgICByZXR1cm4gc3RyO1xuICB9XG4gIGZ1bmN0aW9uIFNoYWRlckZpbGUoKSB7XG4gICAgdGhpcy5uYW1lID0gJ3Vua25vd24nO1xuICAgIHRoaXMubGluZXMgPSBbXTtcbiAgICB0aGlzLmluZGV4ID0ge307XG4gICAgdGhpcy5oYXNFcnJvcnMgPSBmYWxzZTtcbiAgfVxuICBmdW5jdGlvbiBTaGFkZXJMaW5lKG51bWJlciwgbGluZSkge1xuICAgIHRoaXMubnVtYmVyID0gbnVtYmVyO1xuICAgIHRoaXMubGluZSA9IGxpbmU7XG4gICAgdGhpcy5lcnJvcnMgPSBbXTtcbiAgfVxuICBmdW5jdGlvbiBTaGFkZXJFcnJvcihmaWxlTnVtYmVyLCBsaW5lTnVtYmVyLCBtZXNzYWdlKSB7XG4gICAgdGhpcy5maWxlID0gZmlsZU51bWJlcjtcbiAgICB0aGlzLmxpbmUgPSBsaW5lTnVtYmVyO1xuICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gIH1cbiAgZnVuY3Rpb24gZ3Vlc3NDb21tYW5kKCkge1xuICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIHZhciBzdGFjayA9IChlcnJvci5zdGFjayB8fCBlcnJvcikudG9TdHJpbmcoKTtcbiAgICB2YXIgcGF0ID0gL2NvbXBpbGVQcm9jZWR1cmUuKlxcblxccyphdC4qXFwoKC4qKVxcKS8uZXhlYyhzdGFjayk7XG4gICAgaWYgKHBhdCkge1xuICAgICAgcmV0dXJuIHBhdFsxXTtcbiAgICB9XG4gICAgdmFyIHBhdDIgPSAvY29tcGlsZVByb2NlZHVyZS4qXFxuXFxzKmF0XFxzKyguKikoXFxufCQpLy5leGVjKHN0YWNrKTtcbiAgICBpZiAocGF0Mikge1xuICAgICAgcmV0dXJuIHBhdDJbMV07XG4gICAgfVxuICAgIHJldHVybiAndW5rbm93bic7XG4gIH1cbiAgZnVuY3Rpb24gZ3Vlc3NDYWxsU2l0ZSgpIHtcbiAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICB2YXIgc3RhY2sgPSAoZXJyb3Iuc3RhY2sgfHwgZXJyb3IpLnRvU3RyaW5nKCk7XG4gICAgdmFyIHBhdCA9IC9hdCBSRUdMQ29tbWFuZC4qXFxuXFxzK2F0LipcXCgoLiopXFwpLy5leGVjKHN0YWNrKTtcbiAgICBpZiAocGF0KSB7XG4gICAgICByZXR1cm4gcGF0WzFdO1xuICAgIH1cbiAgICB2YXIgcGF0MiA9IC9hdCBSRUdMQ29tbWFuZC4qXFxuXFxzK2F0XFxzKyguKilcXG4vLmV4ZWMoc3RhY2spO1xuICAgIGlmIChwYXQyKSB7XG4gICAgICByZXR1cm4gcGF0MlsxXTtcbiAgICB9XG4gICAgcmV0dXJuICd1bmtub3duJztcbiAgfVxuICBmdW5jdGlvbiBwYXJzZVNvdXJjZShzb3VyY2UsIGNvbW1hbmQpIHtcbiAgICB2YXIgbGluZXMgPSBzb3VyY2Uuc3BsaXQoJ1xcbicpO1xuICAgIHZhciBsaW5lTnVtYmVyID0gMTtcbiAgICB2YXIgZmlsZU51bWJlciA9IDA7XG4gICAgdmFyIGZpbGVzID0ge1xuICAgICAgdW5rbm93bjogbmV3IFNoYWRlckZpbGUoKSxcbiAgICAgIDA6IG5ldyBTaGFkZXJGaWxlKClcbiAgICB9O1xuICAgIGZpbGVzLnVua25vd24ubmFtZSA9IGZpbGVzWzBdLm5hbWUgPSBjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpO1xuICAgIGZpbGVzLnVua25vd24ubGluZXMucHVzaChuZXcgU2hhZGVyTGluZSgwLCAnJykpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBsaW5lID0gbGluZXNbaV07XG4gICAgICB2Y
1XIgcGFydHMgPSAvXlxccyojXFxzKihcXHcrKVxccysoLispXFxzKiQvLmV4ZWMobGluZSk7XG4gICAgICBpZiAocGFydHMpIHtcbiAgICAgICAgc3dpdGNoIChwYXJ0c1sxXSkge1xuICAgICAgICAgIGNhc2UgJ2xpbmUnOlxuICAgICAgICAgICAgdmFyIGxpbmVOdW1iZXJJbmZvID0gLyhcXGQrKShcXHMrXFxkKyk/Ly5leGVjKHBhcnRzWzJdKTtcbiAgICAgICAgICAgIGlmIChsaW5lTnVtYmVySW5mbykge1xuICAgICAgICAgICAgICBsaW5lTnVtYmVyID0gbGluZU51bWJlckluZm9bMV0gfCAwO1xuICAgICAgICAgICAgICBpZiAobGluZU51bWJlckluZm9bMl0pIHtcbiAgICAgICAgICAgICAgICBmaWxlTnVtYmVyID0gbGluZU51bWJlckluZm9bMl0gfCAwO1xuICAgICAgICAgICAgICAgIGlmICghKGZpbGVOdW1iZXIgaW4gZmlsZXMpKSB7XG4gICAgICAgICAgICAgICAgICBmaWxlc1tmaWxlTnVtYmVyXSA9IG5ldyBTaGFkZXJGaWxlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdkZWZpbmUnOlxuICAgICAgICAgICAgdmFyIG5hbWVJbmZvID0gL1NIQURFUl9OQU1FKF9CNjQpP1xccysoLiopJC8uZXhlYyhwYXJ0c1syXSk7XG4gICAgICAgICAgICBpZiAobmFtZUluZm8pIHtcbiAgICAgICAgICAgICAgZmlsZXNbZmlsZU51bWJlcl0ubmFtZSA9IG5hbWVJbmZvWzFdID8gZGVjb2RlQjY0KG5hbWVJbmZvWzJdKSA6IG5hbWVJbmZvWzJdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZpbGVzW2ZpbGVOdW1iZXJdLmxpbmVzLnB1c2gobmV3IFNoYWRlckxpbmUobGluZU51bWJlcisrLCBsaW5lKSk7XG4gICAgfVxuICAgIE9iamVjdC5rZXlzKGZpbGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlTnVtYmVyKSB7XG4gICAgICB2Y
1XIgZmlsZSA9IGZpbGVzW2ZpbGVOdW1iZXJdO1xuICAgICAgZmlsZS5saW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIGZpbGUuaW5kZXhbbGluZS5udW1iZXJdID0gbGluZTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBmaWxlcztcbiAgfVxuICBmdW5jdGlvbiBwYXJzZUVycm9yTG9nKGVyckxvZykge1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICBlcnJMb2cuc3BsaXQoJ1xcbicpLmZvckVhY2goZnVuY3Rpb24gKGVyck1zZykge1xuICAgICAgaWYgKGVyck1zZy5sZW5ndGggPCA1KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBwYXJ0cyA9IC9eRVJST1I6XFxzKyhcXGQrKTooXFxkKyk6XFxzKiguKikkLy5leGVjKGVyck1zZyk7XG4gICAgICBpZiAocGFydHMpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gobmV3IFNoYWRlckVycm9yKHBhcnRzWzFdIHwgMCwgcGFydHNbMl0gfCAwLCBwYXJ0c1szXS50cmltKCkpKTtcbiAgICAgIH0gZWxzZSBpZiAoZXJyTXNnLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2gobmV3IFNoYWRlckVycm9yKCd1bmtub3duJywgMCwgZXJyTXNnKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBmdW5jdGlvbiBhbm5vdGF0ZUZpbGVzKGZpbGVzLCBlcnJvcnMpIHtcbiAgICBlcnJvcnMuZm9yRWFjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIHZhciBmaWxlID0gZmlsZXNbZXJyb3IuZmlsZV07XG4gICAgICBpZiAoZmlsZSkge1xuICAgICAgICB2Y
1XIgbGluZSA9IGZpbGUuaW5kZXhbZXJyb3IubGluZV07XG4gICAgICAgIGlmIChsaW5lKSB7XG4gICAgICAgICAgbGluZS5lcnJvcnMucHVzaChlcnJvcik7XG4gICAgICAgICAgZmlsZS5oYXNFcnJvcnMgPSB0cnVlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZmlsZXMudW5rbm93bi5oYXNFcnJvcnMgPSB0cnVlO1xuICAgICAgZmlsZXMudW5rbm93bi5saW5lc1swXS5lcnJvcnMucHVzaChlcnJvcik7XG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gY2hlY2tTaGFkZXJFcnJvcihnbCwgc2hhZGVyLCBzb3VyY2UsIHR5cGUsIGNvbW1hbmQpIHtcbiAgICBpZiAoIWdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIGdsLkNPTVBJTEVfU1RBVFVTKSkge1xuICAgICAgdmFyIGVyckxvZyA9IGdsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKTtcbiAgICAgIHZhciB0eXBlTmFtZSA9IHR5cGUgPT09IGdsLkZSQUdNRU5UX1NIQURFUiA/ICdmcmFnbWVudCcgOiAndmVydGV4JztcbiAgICAgIGNoZWNrQ29tbWFuZFR5cGUoc291cmNlLCAnc3RyaW5nJywgdHlwZU5hbWUgKyAnIHNoYWRlciBzb3VyY2UgbXVzdCBiZSBhIHN0cmluZycsIGNvbW1hbmQpO1xuICAgICAgdmFyIGZpbGVzID0gcGFyc2VTb3VyY2Uoc291cmNlLCBjb21tYW5kKTtcbiAgICAgIHZhciBlcnJvcnMgPSBwYXJzZUVycm9yTG9nKGVyckxvZyk7XG4gICAgICBhbm5vdGF0ZUZpbGVzKGZpbGVzLCBlcnJvcnMpO1xuICAgICAgT2JqZWN0LmtleXMoZmlsZXMpLmZvckVhY2goZnVuY3Rpb24gKGZpbGVOdW1iZXIpIHtcbiAgICAgICAgdmFyIGZpbGUgPSBmaWxlc1tmaWxlTnVtYmVyXTtcbiAgICAgICAgaWYgKCFmaWxlLmhhc0Vycm9ycykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Y
1XIgc3RyaW5ncyA9IFsnJ107XG4gICAgICAgIHZhciBzdHlsZXMgPSBbJyddO1xuICAgICAgICBmdW5jdGlvbiBwdXNoKHN0ciwgc3R5bGUpIHtcbiAgICAgICAgICBzdHJpbmdzLnB1c2goc3RyKTtcbiAgICAgICAgICBzdHlsZXMucHVzaChzdHlsZSB8fCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgcHVzaCgnZmlsZSBudW1iZXIgJyArIGZpbGVOdW1iZXIgKyAnOiAnICsgZmlsZS5uYW1lICsgJ1xcbicsICdjb2xvcjpyZWQ7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTtmb250LXdlaWdodDpib2xkJyk7XG4gICAgICAgIGZpbGUubGluZXMuZm9yRWFjaChmdW5jdGlvbiAobGluZSkge1xuICAgICAgICAgIGlmIChsaW5lLmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwdXNoKGxlZnRQYWQobGluZS5udW1iZXIsIDQpICsgJ3wgICcsICdiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgZm9udC13ZWlnaHQ6Ym9sZCcpO1xuICAgICAgICAgICAgcHVzaChsaW5lLmxpbmUgKyBlbmRsLCAnY29sb3I6cmVkOyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgZm9udC13ZWlnaHQ6Ym9sZCcpO1xuXG4gICAgICAgICAgICAvLyB0cnkgdG8gZ3Vlc3MgdG9rZW5cbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgbGluZS5lcnJvcnMuZm9yRWFjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICB2YXIgdG9rZW4gPSAvXlxccyonKC4qKSdcXHMqOlxccyooLiopJC8uZXhlYyhtZXNzYWdlKTtcbiAgICAgICAgICAgICAgaWYgKHRva2VuKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRva2VuUGF0ID0gdG9rZW5bMV07XG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IHRva2VuWzJdO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodG9rZW5QYXQpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgJ2Fzc2lnbic6XG4gICAgICAgICAgICAgICAgICAgIHRva2VuUGF0ID0gJz0nO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gTWF0aC5tYXgobGluZS5saW5lLmluZGV4T2YodG9rZW5QYXQsIG9mZnNldCksIDApO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcHVzaChsZWZ0UGFkKCd8ICcsIDYpKTtcbiAgICAgICAgICAgICAgcHVzaChsZWZ0UGFkKCdeXl4nLCBvZmZzZXQgKyAzKSArIGVuZGwsICdmb250LXdlaWdodDpib2xkJyk7XG4gICAgICAgICAgICAgIHB1c2gobGVmdFBhZCgnfCAnLCA2KSk7XG4gICAgICAgICAgICAgIHB1c2gobWVzc2FnZSArIGVuZGwsICdmb250LXdlaWdodDpib2xkJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHB1c2gobGVmdFBhZCgnfCAnLCA2KSArIGVuZGwpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwdXNoKGxlZnRQYWQobGluZS5udW1iZXIsIDQpICsgJ3wgICcpO1xuICAgICAgICAgICAgcHVzaChsaW5lLmxpbmUgKyBlbmRsLCAnY29sb3I6cmVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgIXdpbmRvdy5jaHJvbWUpIHtcbiAgICAgICAgICBzdHlsZXNbMF0gPSBzdHJpbmdzLmpvaW4oJyVjJyk7XG4gICAgICAgICAgY29uc29sZS5sb2cuYXBwbHkoY29uc29sZSwgc3R5bGVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhzdHJpbmdzLmpvaW4oJycpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBjaGVjay5yYWlzZSgnRXJyb3IgY29tcGlsaW5nICcgKyB0eXBlTmFtZSArICcgc2hhZGVyLCAnICsgZmlsZXNbMF0ubmFtZSk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGNoZWNrTGlua0Vycm9yKGdsLCBwcm9ncmFtLCBmcmFnU2hhZGVyLCB2ZXJ0U2hhZGVyLCBjb21tYW5kKSB7XG4gICAgaWYgKCFnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkxJTktfU1RBVFVTKSkge1xuICAgICAgdmFyIGVyckxvZyA9IGdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pO1xuICAgICAgdmFyIGZyYWdQYXJzZSA9IHBhcnNlU291cmNlKGZyYWdTaGFkZXIsIGNvbW1hbmQpO1xuICAgICAgdmFyIHZlcnRQYXJzZSA9IHBhcnNlU291cmNlKHZlcnRTaGFkZXIsIGNvbW1hbmQpO1xuICAgICAgdmFyIGhlYWRlciA9ICdFcnJvciBsaW5raW5nIHByb2dyYW0gd2l0aCB2ZXJ0ZXggc2hhZGVyLCBcIicgKyB2ZXJ0UGFyc2VbMF0ubmFtZSArICdcIiwgYW5kIGZyYWdtZW50IHNoYWRlciBcIicgKyBmcmFnUGFyc2VbMF0ubmFtZSArICdcIic7XG4gICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBjb25zb2xlLmxvZygnJWMnICsgaGVhZGVyICsgZW5kbCArICclYycgKyBlcnJMb2csICdjb2xvcjpyZWQ7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTtmb250LXdlaWdodDpib2xkJywgJ2NvbG9yOnJlZCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coaGVhZGVyICsgZW5kbCArIGVyckxvZyk7XG4gICAgICB9XG4gICAgICBjaGVjay5yYWlzZShoZWFkZXIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBzYXZlQ29tbWFuZFJlZihvYmplY3QpIHtcbiAgICBvYmplY3QuX2NvbW1hbmRSZWYgPSBndWVzc0NvbW1hbmQoKTtcbiAgfVxuICBmdW5jdGlvbiBzYXZlRHJhd0NvbW1hbmRJbmZvKG9wdHMsIHVuaWZvcm1zLCBhdHRyaWJ1dGVzLCBzdHJpbmdTdG9yZSkge1xuICAgIHNhdmVDb21tYW5kUmVmKG9wdHMpO1xuICAgIGZ1bmN0aW9uIGlkKHN0cikge1xuICAgICAgaWYgKHN0cikge1xuICAgICAgICByZXR1cm4gc3RyaW5nU3RvcmUuaWQoc3RyKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBvcHRzLl9mcmFnSWQgPSBpZChvcHRzLnN0YXRpYy5mcmFnKTtcbiAgICBvcHRzLl92ZXJ0SWQgPSBpZChvcHRzLnN0YXRpYy52ZXJ0KTtcbiAgICBmdW5jdGlvbiBhZGRQcm9wcyhkaWN0LCBzZXQpIHtcbiAgICAgIE9iamVjdC5rZXlzKHNldCkuZm9yRWFjaChmdW5jdGlvbiAodSkge1xuICAgICAgICBkaWN0W3N0cmluZ1N0b3JlLmlkKHUpXSA9IHRydWU7XG4gICAgICB9KTtcbiAgICB9XG4gICAgdmFyIHVuaWZvcm1TZXQgPSBvcHRzLl91bmlmb3JtU2V0ID0ge307XG4gICAgYWRkUHJvcHModW5pZm9ybVNldCwgdW5pZm9ybXMuc3RhdGljKTtcbiAgICBhZGRQcm9wcyh1bmlmb3JtU2V0LCB1bmlmb3Jtcy5keW5hbWljKTtcbiAgICB2YXIgYXR0cmlidXRlU2V0ID0gb3B0cy5fY
1XR0cmlidXRlU2V0ID0ge307XG4gICAgYWRkUHJvcHMoYXR0cmlidXRlU2V0LCBhdHRyaWJ1dGVzLnN0YXRpYyk7XG4gICAgYWRkUHJvcHMoYXR0cmlidXRlU2V0LCBhdHRyaWJ1dGVzLmR5bmFtaWMpO1xuICAgIG9wdHMuX2hhc0NvdW50ID0gJ2NvdW50JyBpbiBvcHRzLnN0YXRpYyB8fCAnY291bnQnIGluIG9wdHMuZHluYW1pYyB8fCAnZWxlbWVudHMnIGluIG9wdHMuc3RhdGljIHx8ICdlbGVtZW50cycgaW4gb3B0cy5keW5hbWljO1xuICB9XG4gIGZ1bmN0aW9uIGNvbW1hbmRSYWlzZShtZXNzYWdlLCBjb21tYW5kKSB7XG4gICAgdmFyIGNhbGxTaXRlID0gZ3Vlc3NDYWxsU2l0ZSgpO1xuICAgIHJhaXNlKG1lc3NhZ2UgKyAnIGluIGNvbW1hbmQgJyArIChjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpKSArIChjYWxsU2l0ZSA9PT0gJ3Vua25vd24nID8gJycgOiAnIGNhbGxlZCBmcm9tICcgKyBjYWxsU2l0ZSkpO1xuICB9XG4gIGZ1bmN0aW9uIGNoZWNrQ29tbWFuZChwcmVkLCBtZXNzYWdlLCBjb21tYW5kKSB7XG4gICAgaWYgKCFwcmVkKSB7XG4gICAgICBjb21tYW5kUmFpc2UobWVzc2FnZSwgY29tbWFuZCB8fCBndWVzc0NvbW1hbmQoKSk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGNoZWNrUGFyYW1ldGVyQ29tbWFuZChwYXJhbSwgcG9zc2liaWxpdGllcywgbWVzc2FnZSwgY29tbWFuZCkge1xuICAgIGlmICghKHBhcmFtIGluIHBvc3NpYmlsaXRpZXMpKSB7XG4gICAgICBjb21tYW5kUmFpc2UoJ3Vua25vd24gcGFyYW1ldGVyICgnICsgcGFyYW0gKyAnKScgKyBlbmNvbG9uKG1lc3NhZ2UpICsgJy4gcG9zc2libGUgdmFsdWVzOiAnICsgT2JqZWN0LmtleXMocG9zc2liaWxpdGllcykuam9pbigpLCBjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gY2hlY2tDb21tYW5kVHlwZSh2YWx1ZSwgdHlwZSwgbWVzc2FnZSwgY29tbWFuZCkge1xuICAgIGlmICghc3RhbmRhcmRUeXBlRWgodmFsdWUsIHR5cGUpKSB7XG4gICAgICBjb21tYW5kUmFpc2UoJ2ludmFsaWQgcGFyYW1ldGVyIHR5cGUnICsgZW5jb2xvbihtZXNzYWdlKSArICcuIGV4cGVjdGVkICcgKyB0eXBlICsgJywgZ290ICcgKyB0eXBlb2YgdmFsdWUsIGNvbW1hbmQgfHwgZ3Vlc3NDb21tYW5kKCkpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjaGVja09wdGlvbmFsKGJsb2NrKSB7XG4gICAgYmxvY2soKTtcbiAgfVxuICBmdW5jdGlvbiBjaGVja0ZyYW1lYnVmZmVyRm9ybWF0KGF0dGFjaG1lbnQsIHRleEZvcm1hdHMsIHJiRm9ybWF0cykge1xuICAgIGlmIChhdHRhY2htZW50LnRleHR1cmUpIHtcbiAgICAgIGNoZWNrT25lT2YoYXR0YWNobWVudC50ZXh0dXJlLl90ZXh0dXJlLmludGVybmFsZm9ybWF0LCB0ZXhGb3JtYXRzLCAndW5zdXBwb3J0ZWQgdGV4dHVyZSBmb3JtYXQgZm9yIGF0dGFjaG1lbnQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2hlY2tPbmVPZihhdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLmZvcm1hdCwgcmJGb3JtYXRzLCAndW5zdXBwb3J0ZWQgcmVuZGVyYnVmZmVyIGZvcm1hdCBmb3IgYXR0YWNobWVudCcpO1xuICAgIH1cbiAgfVxuICB2YXIgR0xfQ0xBTVBfVE9fRURHRSA9IDB4ODEyRjtcbiAgdmFyIEdMX05FQVJFU1QgPSAweDI2MDA7XG4gIHZhciBHTF9ORUFSRVNUX01JUE1BUF9ORUFSRVNUID0gMHgyNzAwO1xuICB2YXIgR0xfTElORUFSX01JUE1BUF9ORUFSRVNUID0gMHgyNzAxO1xuICB2YXIgR0xfTkVBUkVTVF9NSVBNQVBfTElORUFSID0gMHgyNzAyO1xuICB2YXIgR0xfTElORUFSX01JUE1BUF9MSU5FQVIgPSAweDI3MDM7XG4gIHZhciBHTF9CWVRFID0gNTEyMDtcbiAgdmFyIEdMX1VOU0lHTkVEX0JZVEUgPSA1MTIxO1xuICB2YXIgR0xfU0hPUlQgPSA1MTIyO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlQgPSA1MTIzO1xuICB2YXIgR0xfSU5UID0gNTEyNDtcbiAgdmFyIEdMX1VOU0lHTkVEX0lOVCA9IDUxMjU7XG4gIHZhciBHTF9GTE9BVCA9IDUxMjY7XG4gIHZhciBHTF9VTlNJR05FRF9TSE9SVF80XzRfNF80ID0gMHg4MDMzO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlRfNV81XzVfMSA9IDB4ODAzNDtcbiAgdmFyIEdMX1VOU0lHTkVEX1NIT1JUXzVfNl81ID0gMHg4MzYzO1xuICB2YXIgR0xfVU5TSUdORURfSU5UXzI0XzhfV0VCR0wgPSAweDg0RkE7XG4gIHZhciBHTF9IQUxGX0ZMT0FUX09FUyA9IDB4OEQ2MTtcbiAgdmFyIFRZUEVfU0laRSA9IHt9O1xuICBUWVBFX1NJWkVbR0xfQllURV0gPSBUWVBFX1NJWkVbR0xfVU5TSUdORURfQllURV0gPSAxO1xuICBUWVBFX1NJWkVbR0xfU0hPUlRdID0gVFlQRV9TSVpFW0dMX1VOU0lHTkVEX1NIT1JUXSA9IFRZUEVfU0laRVtHTF9IQUxGX0ZMT0FUX09FU10gPSBUWVBFX1NJWkVbR0xfVU5TSUdORURfU0hPUlRfNV82XzVdID0gVFlQRV9TSVpFW0dMX1VOU0lHTkVEX1NIT1JUXzRfNF80XzRdID0gVFlQRV9TSVpFW0dMX1VOU0lHTkVEX1NIT1JUXzVfNV81XzFdID0gMjtcbiAgVFlQRV9TSVpFW0dMX0lOVF0gPSBUWVBFX1NJWkVbR0xfVU5TSUdORURfSU5UXSA9IFRZUEVfU0laRVtHTF9GTE9BVF0gPSBUWVBFX1NJWkVbR0xfVU5TSUdORURfSU5UXzI0XzhfV0VCR0xdID0gNDtcbiAgZnVuY3Rpb24gcGl4ZWxTaXplKHR5cGUsIGNoYW5uZWxzKSB7XG4gICAgaWYgKHR5cGUgPT09IEdMX1VOU0lHTkVEX1NIT1JUXzVfNV81XzEgfHwgdHlwZSA9PT0gR0xfVU5TSUdORURfU0hPUlRfNF80XzRfNCB8fCB0eXBlID09PSBHTF9VTlNJR05FRF9TSE9SVF81XzZfNSkge1xuICAgICAgcmV0dXJuIDI7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9VTlNJR05FRF9JTlRfMjRfOF9XRUJHTCkge1xuICAgICAgcmV0dXJuIDQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBUWVBFX1NJWkVbdHlwZV0gKiBjaGFubmVscztcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gaXNQb3cyKHYpIHtcbiAgICByZXR1cm4gISh2ICYgdiAtIDEpICYmICEhdjtcbiAgfVxuICBmdW5jdGlvbiBjaGVja1RleHR1cmUyRChpbmZvLCBtaXBEYXRhLCBsaW1pdHMpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgdyA9IG1pcERhdGEud2lkdGg7XG4gICAgdmFyIGggPSBtaXBEYXRhLmhlaWdodDtcbiAgICB2YXIgYyA9IG1pcERhdGEuY2hhbm5lbHM7XG5cbiAgICAvLyBDaGVjayB0ZXh0dXJlIHNoYXBlXG4gICAgY2hlY2sodyA+IDAgJiYgdyA8PSBsaW1pdHMubWF4VGV4dHVyZVNpemUgJiYgaCA+IDAgJiYgaCA8PSBsaW1pdHMubWF4VGV4dHVyZVNpemUsICdpbnZhbGlkIHRleHR1cmUgc2hhcGUnKTtcblxuICAgIC8vIGNoZWNrIHdyYXAgbW9kZVxuICAgIGlmIChpbmZvLndyYXBTICE9PSBHTF9DTEFNUF9UT19FREdFIHx8IGluZm8ud3JhcFQgIT09IEdMX0NMQU1QX1RPX0VER0UpIHtcbiAgICAgIGNoZWNrKGlzUG93Mih3KSAmJiBpc1BvdzIoaCksICdpbmNvbXBhdGlibGUgd3JhcCBtb2RlIGZvciB0ZXh0dXJlLCBib3RoIHdpZHRoIGFuZCBoZWlnaHQgbXVzdCBiZSBwb3dlciBvZiAyJyk7XG4gICAgfVxuICAgIGlmIChtaXBEYXRhLm1pcG1hc2sgPT09IDEpIHtcbiAgICAgIGlmICh3ICE9PSAxICYmIGggIT09IDEpIHtcbiAgICAgICAgY2hlY2soaW5mby5taW5GaWx0ZXIgIT09IEdMX05FQVJFU1RfTUlQTUFQX05FQVJFU1QgJiYgaW5mby5taW5GaWx0ZXIgIT09IEdMX05FQVJFU1RfTUlQTUFQX0xJTkVBUiAmJiBpbmZvLm1pbkZpbHRlciAhPT0gR0xfTElORUFSX01JUE1BUF9ORUFSRVNUICYmIGluZm8ubWluRmlsdGVyICE9PSBHTF9MSU5FQVJfTUlQTUFQX0xJTkVBUiwgJ21pbiBmaWx0ZXIgcmVxdWlyZXMgbWlwbWFwJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHRleHR1cmUgbXVzdCBiZSBwb3dlciBvZiAyXG4gICAgICBjaGVjayhpc1BvdzIodykgJiYgaXNQb3cyKGgpLCAndGV4dHVyZSBtdXN0IGJlIGEgc3F1YXJlIHBvd2VyIG9mIDIgdG8gc3VwcG9ydCBtaXBtYXBwaW5nJyk7XG4gICAgICBjaGVjayhtaXBEYXRhLm1pcG1hc2sgPT09ICh3IDw8IDEpIC0gMSwgJ21pc3Npbmcgb3IgaW5jb21wbGV0ZSBtaXBtYXAgZGF0YScpO1xuICAgIH1cbiAgICBpZiAobWlwRGF0YS50eXBlID09PSBHTF9GTE9BVCkge1xuICAgICAgaWYgKGxpbWl0cy5leHRlbnNpb25zLmluZGV4T2YoJ29lc190ZXh0dXJlX2Zsb2F0X2xpbmVhcicpIDwgMCkge1xuICAgICAgICBjaGVjayhpbmZvLm1pbkZpbHRlciA9PT0gR0xfTkVBUkVTVCAmJiBpbmZvLm1hZ0ZpbHRlciA9PT0gR0xfTkVBUkVTVCwgJ2ZpbHRlciBub3Qgc3VwcG9ydGVkLCBtdXN0IGVuYWJsZSBvZXNfdGV4dHVyZV9mbG9hdF9saW5lYXInKTtcbiAgICAgIH1cbiAgICAgIGNoZWNrKCFpbmZvLmdlbk1pcG1hcHMsICdtaXBtYXAgZ2VuZXJhdGlvbiBub3Qgc3VwcG9ydGVkIHdpdGggZmxvYXQgdGV4dHVyZXMnKTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayBpbWFnZSBjb21wbGV0ZVxuICAgIHZhciBtaXBpbWFnZXMgPSBtaXBEYXRhLmltYWdlcztcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTY7ICsraSkge1xuICAgICAgaWYgKG1pcGltYWdlc1tpXSkge1xuICAgICAgICB2Y
1XIgbXcgPSB3ID4+IGk7XG4gICAgICAgIHZhciBtaCA9IGggPj4gaTtcbiAgICAgICAgY2hlY2sobWlwRGF0YS5taXBtYXNrICYgMSA8PCBpLCAnbWlzc2luZyBtaXBtYXAgZGF0YScpO1xuICAgICAgICB2YXIgaW1nID0gbWlwaW1hZ2VzW2ldO1xuICAgICAgICBjaGVjayhpbWcud2lkdGggPT09IG13ICYmIGltZy5oZWlnaHQgPT09IG1oLCAnaW52YWxpZCBzaGFwZSBmb3IgbWlwIGltYWdlcycpO1xuICAgICAgICBjaGVjayhpbWcuZm9ybWF0ID09PSBtaXBEYXRhLmZvcm1hdCAmJiBpbWcuaW50ZXJuYWxmb3JtYXQgPT09IG1pcERhdGEuaW50ZXJuYWxmb3JtYXQgJiYgaW1nLnR5cGUgPT09IG1pcERhdGEudHlwZSwgJ2luY29tcGF0aWJsZSB0eXBlIGZvciBtaXAgaW1hZ2UnKTtcbiAgICAgICAgaWYgKGltZy5jb21wcmVzc2VkKSB7XG4gICAgICAgICAgLy8gVE9ETzogY2hlY2sgc2l6ZSBmb3IgY29tcHJlc3NlZCBpbWFnZXNcbiAgICAgICAgfSBlbHNlIGlmIChpbWcuZGF0YSkge1xuICAgICAgICAgIC8vIGNoZWNrKGltZy5kYXRhLmJ5dGVMZW5ndGggPT09IG13ICogbWggKlxuICAgICAgICAgIC8vIE1hdGgubWF4KHBpeGVsU2l6ZShpbWcudHlwZSwgYyksIGltZy51bnBhY2tBbGlnbm1lbnQpLFxuICAgICAgICAgIHZhciByb3dTaXplID0gTWF0aC5jZWlsKHBpeGVsU2l6ZShpbWcudHlwZSwgYykgKiBtdyAvIGltZy51bnBhY2tBbGlnbm1lbnQpICogaW1nLnVucGFja0FsaWdubWVudDtcbiAgICAgICAgICBjaGVjayhpbWcuZGF0YS5ieXRlTGVuZ3RoID09PSByb3dTaXplICogbWgsICdpbnZhbGlkIGRhdGEgZm9yIGltYWdlLCBidWZmZXIgc2l6ZSBpcyBpbmNvbnNpc3RlbnQgd2l0aCBpbWFnZSBmb3JtYXQnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpbWcuZWxlbWVudCkge1xuICAgICAgICAgIC8vIFRPRE86IGNoZWNrIGVsZW1lbnQgY2FuIGJlIGxvYWRlZFxuICAgICAgICB9IGVsc2UgaWYgKGltZy5jb3B5KSB7XG4gICAgICAgICAgLy8gVE9ETzogY2hlY2sgY29tcGF0aWJsZSBmb3JtYXQgYW5kIHR5cGVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghaW5mby5nZW5NaXBtYXBzKSB7XG4gICAgICAgIGNoZWNrKChtaXBEYXRhLm1pcG1hc2sgJiAxIDw8IGkpID09PSAwLCAnZXh0cmEgbWlwbWFwIGRhdGEnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG1pcERhdGEuY29tcHJlc3NlZCkge1xuICAgICAgY2hlY2soIWluZm8uZ2VuTWlwbWFwcywgJ21pcG1hcCBnZW5lcmF0aW9uIGZvciBjb21wcmVzc2VkIGltYWdlcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGNoZWNrVGV4dHVyZUN1YmUodGV4dHVyZSwgaW5mbywgZmFjZXMsIGxpbWl0cykge1xuICAgIHZhciB3ID0gdGV4dHVyZS53aWR0aDtcbiAgICB2YXIgaCA9IHRleHR1cmUuaGVpZ2h0O1xuICAgIHZhciBjID0gdGV4dHVyZS5jaGFubmVscztcblxuICAgIC8vIENoZWNrIHRleHR1cmUgc2hhcGVcbiAgICBjaGVjayh3ID4gMCAmJiB3IDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSAmJiBoID4gMCAmJiBoIDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgdGV4dHVyZSBzaGFwZScpO1xuICAgIGNoZWNrKHcgPT09IGgsICdjdWJlIG1hcCBtdXN0IGJlIHNxdWFyZScpO1xuICAgIGNoZWNrKGluZm8ud3JhcFMgPT09IEdMX0NMQU1QX1RPX0VER0UgJiYgaW5mby53cmFwVCA9PT0gR0xfQ0xBTVBfVE9fRURHRSwgJ3dyYXAgbW9kZSBub3Qgc3VwcG9ydGVkIGJ5IGN1YmUgbWFwJyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmYWNlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGZhY2UgPSBmYWNlc1tpXTtcbiAgICAgIGNoZWNrKGZhY2Uud2lkdGggPT09IHcgJiYgZmFjZS5oZWlnaHQgPT09IGgsICdpbmNvbnNpc3RlbnQgY3ViZSBtYXAgZmFjZSBzaGFwZScpO1xuICAgICAgaWYgKGluZm8uZ2VuTWlwbWFwcykge1xuICAgICAgICBjaGVjayghZmFjZS5jb21wcmVzc2VkLCAnY2FuIG5vdCBnZW5lcmF0ZSBtaXBtYXAgZm9yIGNvbXByZXNzZWQgdGV4dHVyZXMnKTtcbiAgICAgICAgY2hlY2soZmFjZS5taXBtYXNrID09PSAxLCAnY2FuIG5vdCBzcGVjaWZ5IG1pcG1hcHMgYW5kIGdlbmVyYXRlIG1pcG1hcHMnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRPRE86IGNoZWNrIG1pcCBhbmQgZmlsdGVyIG1vZGVcbiAgICAgIH1cbiAgICAgIHZhciBtaXBtYXBzID0gZmFjZS5pbWFnZXM7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDE2OyArK2opIHtcbiAgICAgICAgdmFyIGltZyA9IG1pcG1hcHNbal07XG4gICAgICAgIGlmIChpbWcpIHtcbiAgICAgICAgICB2Y
1XIgbXcgPSB3ID4+IGo7XG4gICAgICAgICAgdmFyIG1oID0gaCA+PiBqO1xuICAgICAgICAgIGNoZWNrKGZhY2UubWlwbWFzayAmIDEgPDwgaiwgJ21pc3NpbmcgbWlwbWFwIGRhdGEnKTtcbiAgICAgICAgICBjaGVjayhpbWcud2lkdGggPT09IG13ICYmIGltZy5oZWlnaHQgPT09IG1oLCAnaW52YWxpZCBzaGFwZSBmb3IgbWlwIGltYWdlcycpO1xuICAgICAgICAgIGNoZWNrKGltZy5mb3JtYXQgPT09IHRleHR1cmUuZm9ybWF0ICYmIGltZy5pbnRlcm5hbGZvcm1hdCA9PT0gdGV4dHVyZS5pbnRlcm5hbGZvcm1hdCAmJiBpbWcudHlwZSA9PT0gdGV4dHVyZS50eXBlLCAnaW5jb21wYXRpYmxlIHR5cGUgZm9yIG1pcCBpbWFnZScpO1xuICAgICAgICAgIGlmIChpbWcuY29tcHJlc3NlZCkge1xuICAgICAgICAgICAgLy8gVE9ETzogY2hlY2sgc2l6ZSBmb3IgY29tcHJlc3NlZCBpbWFnZXNcbiAgICAgICAgICB9IGVsc2UgaWYgKGltZy5kYXRhKSB7XG4gICAgICAgICAgICBjaGVjayhpbWcuZGF0YS5ieXRlTGVuZ3RoID09PSBtdyAqIG1oICogTWF0aC5tYXgocGl4ZWxTaXplKGltZy50eXBlLCBjKSwgaW1nLnVucGFja0FsaWdubWVudCksICdpbnZhbGlkIGRhdGEgZm9yIGltYWdlLCBidWZmZXIgc2l6ZSBpcyBpbmNvbnNpc3RlbnQgd2l0aCBpbWFnZSBmb3JtYXQnKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGltZy5lbGVtZW50KSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBjaGVjayBlbGVtZW50IGNhbiBiZSBsb2FkZWRcbiAgICAgICAgICB9IGVsc2UgaWYgKGltZy5jb3B5KSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBjaGVjayBjb21wYXRpYmxlIGZvcm1hdCBhbmQgdHlwZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgY2hlY2skMSA9IGV4dGVuZChjaGVjaywge1xuICAgIG9wdGlvbmFsOiBjaGVja09wdGlvbmFsLFxuICAgIHJhaXNlOiByYWlzZSxcbiAgICBjb21tYW5kUmFpc2U6IGNvbW1hbmRSYWlzZSxcbiAgICBjb21tYW5kOiBjaGVja0NvbW1hbmQsXG4gICAgcGFyYW1ldGVyOiBjaGVja1BhcmFtZXRlcixcbiAgICBjb21tYW5kUGFyYW1ldGVyOiBjaGVja1BhcmFtZXRlckNvbW1hbmQsXG4gICAgY29uc3RydWN0b3I6IGNoZWNrQ29uc3RydWN0b3IsXG4gICAgdHlwZTogY2hlY2tUeXBlT2YsXG4gICAgY29tbWFuZFR5cGU6IGNoZWNrQ29tbWFuZFR5cGUsXG4gICAgaXNUeXBlZEFycmF5OiBjaGVja0lzVHlwZWRBcnJheSxcbiAgICBubmk6IGNoZWNrTm9uTmVnYXRpdmVJbnQsXG4gICAgb25lT2Y6IGNoZWNrT25lT2YsXG4gICAgc2hhZGVyRXJyb3I6IGNoZWNrU2hhZGVyRXJyb3IsXG4gICAgbGlua0Vycm9yOiBjaGVja0xpbmtFcnJvcixcbiAgICBjYWxsU2l0ZTogZ3Vlc3NDYWxsU2l0ZSxcbiAgICBzYXZlQ29tbWFuZFJlZjogc2F2ZUNvbW1hbmRSZWYsXG4gICAgc2F2ZURyYXdJbmZvOiBzYXZlRHJhd0NvbW1hbmRJbmZvLFxuICAgIGZyYW1lYnVmZmVyRm9ybWF0OiBjaGVja0ZyYW1lYnVmZmVyRm9ybWF0LFxuICAgIGd1ZXNzQ29tbWFuZDogZ3Vlc3NDb21tYW5kLFxuICAgIHRleHR1cmUyRDogY2hlY2tUZXh0dXJlMkQsXG4gICAgdGV4dHVyZUN1YmU6IGNoZWNrVGV4dHVyZUN1YmVcbiAgfSk7XG4gIHZhciBWQVJJQUJMRV9DT1VOVEVSID0gMDtcbiAgdmFyIERZTl9GVU5DID0gMDtcbiAgdmFyIERZTl9DT05TVEFOVCA9IDU7XG4gIHZhciBEWU5fQVJSQVkgPSA2O1xuICBmdW5jdGlvbiBEeW5hbWljVmFyaWFibGUodHlwZSwgZGF0YSkge1xuICAgIHRoaXMuaWQgPSBWQVJJQUJMRV9DT1VOVEVSKys7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICB9XG4gIGZ1bmN0aW9uIGVzY2FwZVN0cihzdHIpIHtcbiAgICByZXR1cm4gc3RyLnJlcGxhY2UoL1xcXFwvZywgJ1xcXFxcXFxcJykucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpO1xuICB9XG4gIGZ1bmN0aW9uIHNwbGl0UGFydHMoc3RyKSB7XG4gICAgaWYgKHN0ci5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdmFyIGZpcnN0Q2hhciA9IHN0ci5jaGFyQXQoMCk7XG4gICAgdmFyIGxhc3RDaGFyID0gc3RyLmNoYXJBdChzdHIubGVuZ3RoIC0gMSk7XG4gICAgaWYgKHN0ci5sZW5ndGggPiAxICYmIGZpcnN0Q2hhciA9PT0gbGFzdENoYXIgJiYgKGZpcnN0Q2hhciA9PT0gJ1wiJyB8fCBmaXJzdENoYXIgPT09IFwiJ1wiKSkge1xuICAgICAgcmV0dXJuIFsnXCInICsgZXNjYXBlU3RyKHN0ci5zdWJzdHIoMSwgc3RyLmxlbmd0aCAtIDIpKSArICdcIiddO1xuICAgIH1cbiAgICB2YXIgcGFydHMgPSAvXFxbKGZhbHNlfHRydWV8bnVsbHxcXGQrfCdbXiddKid8XCJbXlwiXSpcIilcXF0vLmV4ZWMoc3RyKTtcbiAgICBpZiAocGFydHMpIHtcbiAgICAgIHJldHVybiBzcGxpdFBhcnRzKHN0ci5zdWJzdHIoMCwgcGFydHMuaW5kZXgpKS5jb25jYXQoc3BsaXRQYXJ0cyhwYXJ0c1sxXSkpLmNvbmNhdChzcGxpdFBhcnRzKHN0ci5zdWJzdHIocGFydHMuaW5kZXggKyBwYXJ0c1swXS5sZW5ndGgpKSk7XG4gICAgfVxuICAgIHZhciBzdWJwYXJ0cyA9IHN0ci5zcGxpdCgnLicpO1xuICAgIGlmIChzdWJwYXJ0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBbJ1wiJyArIGVzY2FwZVN0cihzdHIpICsgJ1wiJ107XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1YnBhcnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHNwbGl0UGFydHMoc3VicGFydHNbaV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBmdW5jdGlvbiB0b0FjY2Vzc29yU3RyaW5nKHN0cikge1xuICAgIHJldHVybiAnWycgKyBzcGxpdFBhcnRzKHN0cikuam9pbignXVsnKSArICddJztcbiAgfVxuICBmdW5jdGlvbiBkZWZpbmVEeW5hbWljKHR5cGUsIGRhdGEpIHtcbiAgICByZXR1cm4gbmV3IER5bmFtaWNWYXJpYWJsZSh0eXBlLCB0b0FjY2Vzc29yU3RyaW5nKGRhdGEgKyAnJykpO1xuICB9XG4gIGZ1bmN0aW9uIGlzRHluYW1pYyh4KSB7XG4gICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nICYmICF4Ll9yZWdsVHlwZSB8fCB4IGluc3RhbmNlb2YgRHluYW1pY1ZhcmlhYmxlO1xuICB9XG4gIGZ1bmN0aW9uIHVuYm94KHgsIHBhdGgpIHtcbiAgICBpZiAodHlwZW9mIHggPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybi
1BuZXcgRHluYW1pY1ZhcmlhYmxlKERZTl9GVU5DLCB4KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB4ID09PSAnbnVtYmVyJyB8fCB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICByZXR1cm4gbmV3IER5bmFtaWNWYXJpYWJsZShEWU5fQ09OU1RBTlQsIHgpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh4KSkge1xuICAgICAgcmV0dXJuIG5ldyBEeW5hbWljVmFyaWFibGUoRFlOX0FSUkFZLCB4Lm1hcChmdW5jdGlvbiAoeSwgaSkge1xuICAgICAgICByZXR1cm4gdW5ib3goeSwgcGF0aCArICdbJyArIGkgKyAnXScpO1xuICAgICAgfSkpO1xuICAgIH0gZWxzZSBpZiAoeCBpbnN0YW5jZW9mIER5bmFtaWNWYXJpYWJsZSkge1xuICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICAgIGNoZWNrJDEoZmFsc2UsICdpbnZhbGlkIG9wdGlvbiB0eXBlIGluIHVuaWZvcm0gJyArIHBhdGgpO1xuICB9XG4gIHZhciBkeW5hbWljID0ge1xuICAgIER5bmFtaWNWYXJpYWJsZTogRHluYW1pY1ZhcmlhYmxlLFxuICAgIGRlZmluZTogZGVmaW5lRHluYW1pYyxcbiAgICBpc0R5bmFtaWM6IGlzRHluYW1pYyxcbiAgICB1bmJveDogdW5ib3gsXG4gICAgYWNjZXNzb3I6IHRvQWNjZXNzb3JTdHJpbmdcbiAgfTtcblxuICAvKiBnbG9iYWxzIHJlcXVlc3RBbmltYXRpb25GcmFtZSwgY2FuY2VsQW5pbWF0aW9uRnJhbWUgKi9cbiAgdmFyIHJhZiA9IHtcbiAgICBuZXh0OiB0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lID09PSAnZnVuY3Rpb24nID8gZnVuY3Rpb24gKGNiKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGNiKTtcbiAgICB9IDogZnVuY3Rpb24gKGNiKSB7XG4gICAgICByZXR1cm4gc2V0VGltZW91dChjYiwgMTYpO1xuICAgIH0sXG4gICAgY2FuY2VsOiB0eXBlb2YgY2FuY2VsQW5pbWF0aW9uRnJhbWUgPT09ICdmdW5jdGlvbicgPyBmdW5jdGlvbiAocmFmKSB7XG4gICAgICByZXR1cm4gY2FuY2VsQW5pbWF0aW9uRnJhbWUocmFmKTtcbiAgICB9IDogY2xlYXJUaW1lb3V0XG4gIH07XG5cbiAgLyogZ2xvYmFscyBwZXJmb3JtYW5jZSAqL1xuICB2YXIgY2xvY2sgPSB0eXBlb2YgcGVyZm9ybWFuY2UgIT09ICd1bmRlZmluZWQnICYmIHBlcmZvcm1hbmNlLm5vdyA/IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcGVyZm9ybWFuY2Uubm93KCk7XG4gIH0gOiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZSgpO1xuICB9O1xuICBmdW5jdGlvbiBjcmVhdGVTdHJpbmdTdG9yZSgpIHtcbiAgICB2YXIgc3RyaW5nSWRzID0ge1xuICAgICAgJyc6IDBcbiAgICB9O1xuICAgIHZhciBzdHJpbmdWYWx1ZXMgPSBbJyddO1xuICAgIHJldHVybiB7XG4gICAgICBpZDogZnVuY3Rpb24gaWQoc3RyKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBzdHJpbmdJZHNbc3RyXTtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gc3RyaW5nSWRzW3N0cl0gPSBzdHJpbmdWYWx1ZXMubGVuZ3RoO1xuICAgICAgICBzdHJpbmdWYWx1ZXMucHVzaChzdHIpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIHN0cjogZnVuY3Rpb24gc3RyKGlkKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmdWYWx1ZXNbaWRdO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvLyBDb250ZXh0IGFuZCBjYW52YXMgY3JlYXRpb24gaGVscGVyIGZ1bmN0aW9uc1xuICBmdW5jdGlvbiBjcmVhdGVDYW52YXMoZWxlbWVudCwgb25Eb25lLCBwaXhlbFJhdGlvKSB7XG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGV4dGVuZChjYW52YXMuc3R5bGUsIHtcbiAgICAgIGJvcmRlcjogMCxcbiAgICAgIG1hcmdpbjogMCxcbiAgICAgIHBhZGRpbmc6IDAsXG4gICAgICB0b3A6IDAsXG4gICAgICBsZWZ0OiAwLFxuICAgICAgd2lkdGg6ICcxMDAlJyxcbiAgICAgIGhlaWdodDogJzEwMCUnXG4gICAgfSk7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIGlmIChlbGVtZW50ID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICBjYW52YXMuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgZXh0ZW5kKGVsZW1lbnQuc3R5bGUsIHtcbiAgICAgICAgbWFyZ2luOiAwLFxuICAgICAgICBwYWRkaW5nOiAwXG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzaXplKCkge1xuICAgICAgdmFyIHcgPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgIHZhciBoID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgICAgaWYgKGVsZW1lbnQgIT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgdmFyIGJvdW5kcyA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdyA9IGJvdW5kcy5yaWdodCAtIGJvdW5kcy5sZWZ0O1xuICAgICAgICBoID0gYm91bmRzLmJvdHRvbSAtIGJvdW5kcy50b3A7XG4gICAgICB9XG4gICAgICBjYW52YXMud2lkdGggPSBwaXhlbFJhdGlvICogdztcbiAgICAgIGNhbnZhcy5oZWlnaHQgPSBwaXhlbFJhdGlvICogaDtcbiAgICB9XG4gICAgdmFyIHJlc2l6ZU9ic2VydmVyO1xuICAgIGlmIChlbGVtZW50ICE9PSBkb2N1bWVudC5ib2R5ICYmIHR5cGVvZiBSZXNpemVPYnNlcnZlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gaWdub3JlICdSZXNpemVPYnNlcnZlcicgaXMgbm90IGRlZmluZWRcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgcmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBzZXRUaW1lb3V0IHRvIGF2b2lkIGZsaWNrZXJcbiAgICAgICAgc2V0VGltZW91dChyZXNpemUpO1xuICAgICAgfSk7XG4gICAgICByZXNpemVPYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplLCBmYWxzZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIG9uRGVzdHJveSgpIHtcbiAgICAgIGlmIChyZXNpemVPYnNlcnZlcikge1xuICAgICAgICByZXNpemVPYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplKTtcbiAgICAgIH1cbiAgICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQoY2FudmFzKTtcbiAgICB9XG4gICAgcmVzaXplKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNhbnZhczogY2FudmFzLFxuICAgICAgb25EZXN0cm95OiBvbkRlc3Ryb3lcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGNyZWF0ZUNvbnRleHQoY2FudmFzLCBjb250ZXh0QXR0cmlidXRlcykge1xuICAgIGZ1bmN0aW9uIGdldChuYW1lKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gY2FudmFzLmdldENvbnRleHQobmFtZSwgY29udGV4dEF0dHJpYnV0ZXMpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGdldCgnd2ViZ2wnKSB8fCBnZXQoJ2V4cGVyaW1lbn
1RhbC13ZWJnbCcpIHx8IGdldCgnd2ViZ2wtZXhwZXJpbWVudGFsJyk7XG4gIH1cbiAgZnVuY3Rpb24gaXNIVE1MRWxlbWVudChvYmopIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iai5ub2RlTmFtZSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIG9iai5hcHBlbmRDaGlsZCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2Ygb2JqLmdldEJvdW5kaW5nQ2xpZW50UmVjdCA9PT0gJ2Z1bmN0aW9uJztcbiAgfVxuICBmdW5jdGlvbiBpc1dlYkdMQ29udGV4dChvYmopIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iai5kcmF3QXJyYXlzID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBvYmouZHJhd0VsZW1lbnRzID09PSAnZnVuY3Rpb24nO1xuICB9XG4gIGZ1bmN0aW9uIHBhcnNlRXh0ZW5zaW9ucyhpbnB1dCkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gaW5wdXQuc3BsaXQoKTtcbiAgICB9XG4gICAgY2hlY2skMShBcnJheS5pc0FycmF5KGlucHV0KSwgJ2ludmFsaWQgZXh0ZW5zaW9uIGFycmF5Jyk7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG4gIGZ1bmN0aW9uIGdldEVsZW1lbnQoZGVzYykge1xuICAgIGlmICh0eXBlb2YgZGVzYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNoZWNrJDEodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJywgJ25vdCBzdXBwb3J0ZWQgb3V0c2lkZSBvZiBET00nKTtcbiAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGRlc2MpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzYztcbiAgfVxuICBmdW5jdGlvbiBwYXJzZUFyZ3MoYXJnc18pIHtcbiAgICB2YXIgYXJncyA9IGFyZ3NfIHx8IHt9O1xuICAgIHZhciBlbGVtZW50LCBjb250YWluZXIsIGNhbnZhcywgZ2w7XG4gICAgdmFyIGNvbnRleHRBdHRyaWJ1dGVzID0ge307XG4gICAgdmFyIGV4dGVuc2lvbnMgPSBbXTtcbiAgICB2YXIgb3B0aW9uYWxFeHRlbnNpb25zID0gW107XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJyA/IDEgOiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB2YXIgcHJvZmlsZSA9IGZhbHNlO1xuICAgIHZhciBvbkRvbmUgPSBmdW5jdGlvbiBvbkRvbmUoZXJyKSB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGNoZWNrJDEucmFpc2UoZXJyKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHZhciBvbkRlc3Ryb3kgPSBmdW5jdGlvbiBvbkRlc3Ryb3koKSB7fTtcbiAgICBpZiAodHlwZW9mIGFyZ3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjaGVjayQxKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcsICdzZWxlY3RvciBxdWVyaWVzIG9ubHkgc3VwcG9ydGVkIGluIERPTSBlbnZpcm9ubWVudHMnKTtcbiAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZ3MpO1xuICAgICAgY2hlY2skMShlbGVtZW50LCAnaW52YWxpZCBxdWVyeSBzdHJpbmcgZm9yIGVsZW1lbnQnKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmdzID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKGlzSFRNTEVsZW1lbnQoYXJncykpIHtcbiAgICAgICAgZWxlbWVudCA9IGFyZ3M7XG4gICAgICB9IGVsc2UgaWYgKGlzV2ViR0xDb250ZXh0KGFyZ3MpKSB7XG4gICAgICAgIGdsID0gYXJncztcbiAgICAgICAgY2FudmFzID0gZ2wuY2FudmFzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5jb25zdHJ1Y3RvcihhcmdzKTtcbiAgICAgICAgaWYgKCdnbCcgaW4gYXJncykge1xuICAgICAgICAgIGdsID0gYXJncy5nbDtcbiAgICAgICAgfSBlbHNlIGlmICgnY2FudmFzJyBpbiBhcmdzKSB7XG4gICAgICAgICAgY2FudmFzID0gZ2V0RWxlbWVudChhcmdzLmNhbnZhcyk7XG4gICAgICAgIH0gZWxzZSBpZiAoJ2NvbnRhaW5lcicgaW4gYXJncykge1xuICAgICAgICAgIGNvbnRhaW5lciA9IGdldEVsZW1lbnQoYXJncy5jb250YWluZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnYXR0cmlidXRlcycgaW4gYXJncykge1xuICAgICAgICAgIGNvbnRleHRBdHRyaWJ1dGVzID0gYXJncy5hdHRyaWJ1dGVzO1xuICAgICAgICAgIGNoZWNrJDEudHlwZShjb250ZXh0QXR0cmlidXRlcywgJ29iamVjdCcsICdpbnZhbGlkIGNvbnRleHQgYXR0cmlidXRlcycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnZXh0ZW5zaW9ucycgaW4gYXJncykge1xuICAgICAgICAgIGV4dGVuc2lvbnMgPSBwYXJzZUV4dGVuc2lvbnMoYXJncy5leHRlbnNpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ29wdGlvbmFsRXh0ZW5zaW9ucycgaW4gYXJncykge1xuICAgICAgICAgIG9wdGlvbmFsRXh0ZW5zaW9ucyA9IHBhcnNlRXh0ZW5zaW9ucyhhcmdzLm9wdGlvbmFsRXh0ZW5zaW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdvbkRvbmUnIGluIGFyZ3MpIHtcbiAgICAgICAgICBjaGVjayQxLnR5cGUoYXJncy5vbkRvbmUsICdmdW5jdGlvbicsICdpbnZhbGlkIG9yIG1pc3Npbmcgb25Eb25lIGNhbGxiYWNrJyk7XG4gICAgICAgICAgb25Eb25lID0gYXJncy5vbkRvbmU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdwcm9maWxlJyBpbiBhcmdzKSB7XG4gICAgICAgICAgcHJvZmlsZSA9ICEhYXJncy5wcm9maWxlO1xuICAgICAgICB9XG4gICAgICAgIGlmICgncGl4ZWxSYXRpbycgaW4gYXJncykge1xuICAgICAgICAgIHBpeGVsUmF0aW8gPSArYXJncy5waXhlbFJhdGlvO1xuICAgICAgICAgIGNoZWNrJDEocGl4ZWxSYXRpbyA+IDAsICdpbnZhbGlkIHBpeGVsIHJhdGlvJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBhcmd1bWVudHMgdG8gcmVnbCcpO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudCkge1xuICAgICAgaWYgKGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2NhbnZhcycpIHtcbiAgICAgICAgY2FudmFzID0gZWxlbWVudDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGVsZW1lbnQ7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghZ2wpIHtcbiAgICAgIGlmICghY2FudmFzKSB7XG4gICAgICAgIGNoZWNrJDEodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJywgJ211c3QgbWFudWFsbHkgc3BlY2lmeSB3ZWJnbCBjb250ZXh0IG91dHNpZGUgb2YgRE9NIGVudmlyb25tZW50cycpO1xuICAgICAgICB2Y
1XIgcmVzdWx0ID0gY3JlYXRlQ2FudmFzKGNvbnRhaW5lciB8fCBkb2N1bWVudC5ib2R5LCBvbkRvbmUsIHBpeGVsUmF0aW8pO1xuICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNhbnZhcyA9IHJlc3VsdC5jYW52YXM7XG4gICAgICAgIG9uRGVzdHJveSA9IHJlc3VsdC5vbkRlc3Ryb3k7XG4gICAgICB9XG4gICAgICAvLyB3b3JrYXJvdW5kIGZvciBjaHJvbWl1bSBidWcsIHByZW11bHRpcGxpZWQgYWxwaGEgdmFsdWUgaXMgcGxhdGZvcm0gZGVwZW5kZW50XG4gICAgICBpZiAoY29udGV4dEF0dHJpYnV0ZXMucHJlbXVsdGlwbGllZEFscGhhID09PSB1bmRlZmluZWQpIGNvbnRleHRBdHRyaWJ1dGVzLnByZW11bHRpcGxpZWRBbHBoYSA9IHRydWU7XG4gICAgICBnbCA9IGNyZWF0ZUNvbnRleHQoY2FudmFzLCBjb250ZXh0QXR0cmlidXRlcyk7XG4gICAgfVxuICAgIGlmICghZ2wpIHtcbiAgICAgIG9uRGVzdHJveSgpO1xuICAgICAgb25Eb25lKCd3ZWJnbCBub3Qgc3VwcG9ydGVkLCB0cnkgdXBncmFkaW5nIHlvdXIgYnJvd3NlciBvciBncmFwaGljcyBkcml2ZXJzIGh0dHA6Ly9nZXQud2ViZ2wub3JnJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGdsOiBnbCxcbiAgICAgIGNhbnZhczogY2FudmFzLFxuICAgICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICBleHRlbnNpb25zOiBleHRlbnNpb25zLFxuICAgICAgb3B0aW9uYWxFeHRlbnNpb25zOiBvcHRpb25hbEV4dGVuc2lvbnMsXG4gICAgICBwaXhlbFJhdGlvOiBwaXhlbFJhdGlvLFxuICAgICAgcHJvZmlsZTogcHJvZmlsZSxcbiAgICAgIG9uRG9uZTogb25Eb25lLFxuICAgICAgb25EZXN0cm95OiBvbkRlc3Ryb3lcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGNyZWF0ZUV4dGVuc2lvbkNhY2hlKGdsLCBjb25maWcpIHtcbiAgICB2YXIgZXh0ZW5zaW9ucyA9IHt9O1xuICAgIGZ1bmN0aW9uIHRyeUxvYWRFeHRlbnNpb24obmFtZV8pIHtcbiAgICAgIGNoZWNrJDEudHlwZShuYW1lXywgJ3N0cmluZycsICdleHRlbnNpb24gbmFtZSBtdXN0IGJlIHN0cmluZycpO1xuICAgICAgdmFyIG5hbWUgPSBuYW1lXy50b0xvd2VyQ2FzZSgpO1xuICAgICAgdmFyIGV4dDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbnNbbmFtZV0gPSBnbC5nZXRFeHRlbnNpb24obmFtZSk7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgcmV0dXJuICEhZXh0O1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbmZpZy5leHRlbnNpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICB2Y
1XIgbmFtZSA9IGNvbmZpZy5leHRlbnNpb25zW2ldO1xuICAgICAgaWYgKCF0cnlMb2FkRXh0ZW5zaW9uKG5hbWUpKSB7XG4gICAgICAgIGNvbmZpZy5vbkRlc3Ryb3koKTtcbiAgICAgICAgY29uZmlnLm9uRG9uZSgnXCInICsgbmFtZSArICdcIiBleHRlbnNpb24gaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY3VycmVudCBXZWJHTCBjb250ZXh0LCB0cnkgdXBncmFkaW5nIHlvdXIgc3lzdGVtIG9yIGEgZGlmZmVyZW50IGJyb3dzZXInKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbmZpZy5vcHRpb25hbEV4dGVuc2lvbnMuZm9yRWFjaCh0cnlMb2FkRXh0ZW5zaW9uKTtcbiAgICByZXR1cm4ge1xuICAgICAgZXh0ZW5zaW9uczogZXh0ZW5zaW9ucyxcbiAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGV4dGVuc2lvbnMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tuYW1lXSAmJiAhdHJ5TG9hZEV4dGVuc2lvbihuYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCcocmVnbCk6IGVycm9yIHJlc3RvcmluZyBleHRlbnNpb24gJyArIG5hbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBsb29wKG4sIGYpIHtcbiAgICB2YXIgcmVzdWx0ID0gQXJyYXkobik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHJlc3VsdFtpXSA9IGYoaSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgdmFyIEdMX0JZVEUkMSA9IDUxMjA7XG4gIHZhciBHTF9VTlNJR05FRF9CWVRFJDIgPSA1MTIxO1xuICB2YXIgR0xfU0hPUlQkMSA9IDUxMjI7XG4gIHZhciBHTF9VTlNJR05FRF9TSE9SVCQxID0gNTEyMztcbiAgdmFyIEdMX0lOVCQxID0gNTEyNDtcbiAgdmFyIEdMX1VOU0lHTkVEX0lOVCQxID0gNTEyNTtcbiAgdmFyIEdMX0ZMT0FUJDIgPSA1MTI2O1xuICBmdW5jdGlvbiBuZXh0UG93MTYodikge1xuICAgIGZvciAodmFyIGkgPSAxNjsgaSA8PSAxIDw8IDI4OyBpICo9IDE2KSB7XG4gICAgICBpZiAodiA8PSBpKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfVxuICBmdW5jdGlvbiBsb2cyKHYpIHtcbiAgICB2YXIgciwgc2hpZnQ7XG4gICAgciA9ICh2ID4gMHhGRkZGKSA8PCA0O1xuICAgIHYgPj4+PSByO1xuICAgIHNoaWZ0ID0gKHYgPiAweEZGKSA8PCAzO1xuICAgIHYgPj4+PSBzaGlmdDtcbiAgICByIHw9IHNoaWZ0O1xuICAgIHNoaWZ0ID0gKHYgPiAweEYpIDw8IDI7XG4gICAgdiA+Pj49IHNoaWZ0O1xuICAgIHIgfD0gc2hpZnQ7XG4gICAgc2hpZnQgPSAodiA+IDB4MykgPDwgMTtcbiAgICB2ID4+Pj0gc2hpZnQ7XG4gICAgciB8PSBzaGlmdDtcbiAgICByZXR1cm4gciB8IHYgPj4gMTtcbiAgfVxuICBmdW5jdGlvbiBjcmVhdGVQb29sKCkge1xuICAgIHZhciBidWZmZXJQb29sID0gbG9vcCg4LCBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gYWxsb2Mobikge1xuICAgICAgdmFyIHN6ID0gbmV4dFBvdzE2KG4pO1xuICAgICAgdmFyIGJpbiA9IGJ1ZmZlclBvb2xbbG9nMihzeikgPj4gMl07XG4gICAgICBpZiAoYmluLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIGJpbi5wb3AoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgQXJyYXlCdWZmZXIoc3opO1xuICAgIH1cbiAgICBmdW5jdGlvbiBmcmVlKGJ1Zikge1xuICAgICAgYnVmZmVyUG9vbFtsb2cyKGJ1Zi5ieXRlTGVuZ3RoKSA+PiAyXS5wdXNoKGJ1Zik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFsbG9jVHlwZSh0eXBlLCBuKSB7XG4gICAgICB2Y
1XIgcmVzdWx0ID0gbnVsbDtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIEdMX0JZVEUkMTpcbiAgICAgICAgICByZXN1bHQgPSBuZXcgSW50OEFycmF5KGFsbG9jKG4pLCAwLCBuKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBHTF9VTlNJR05FRF9CWVRFJDI6XG4gICAgICAgICAgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoYWxsb2MobiksIDAsIG4pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEdMX1NIT1JUJDE6XG4gICAgICAgICAgcmVzdWx0ID0gbmV3IEludDE2QXJyYXkoYWxsb2MoMiAqIG4pLCAwLCBuKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBHTF9VTlNJR05FRF9TSE9SVCQxOlxuICAgICAgICAgIHJlc3VsdCA9IG5ldyBVaW50MTZBcnJheShhbGxvYygyICogbiksIDAsIG4pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEdMX0lOVCQxOlxuICAgICAgICAgIHJlc3VsdCA9IG5ldyBJbnQzMkFycmF5KGFsbG9jKDQgKiBuKSwgMCwgbik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgR0xfVU5TSUdORURfSU5UJDE6XG4gICAgICAgICAgcmVzdWx0ID0gbmV3IFVpbnQzMkFycmF5KGFsbG9jKDQgKiBuKSwgMCwgbik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgR0xfRkxPQVQkMjpcbiAgICAgICAgICByZXN1bHQgPSBuZXcgRmxvYXQzMkFycmF5KGFsbG9jKDQgKiBuKSwgMCwgbik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gbikge1xuICAgICAgICByZXR1cm4gcmVzdWx0LnN1YmFycmF5KDAsIG4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gZnJlZVR5cGUoYXJyYXkpIHtcbiAgICAgIGZyZWUoYXJyYXkuYnVmZmVyKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGFsbG9jOiBhbGxvYyxcbiAgICAgIGZyZWU6IGZyZWUsXG4gICAgICBhbGxvY1R5cGU6IGFsbG9jVHlwZSxcbiAgICAgIGZyZWVUeXBlOiBmcmVlVHlwZVxuICAgIH07XG4gIH1cbiAgdmFyIHBvb2wgPSBjcmVhdGVQb29sKCk7XG5cbiAgLy8gemVybyBwb29sIGZvciBpbml0aWFsIHplcm8gZGF0YVxuICBwb29sLnplcm8gPSBjcmVhdGVQb29sKCk7XG4gIHZhciBHTF9TVUJQSVhFTF9CSVRTID0gMHgwRDUwO1xuICB2YXIgR0xfUkVEX0JJVFMgPSAweDBENTI7XG4gIHZhciBHTF9HUkVFTl9CSVRTID0gMHgwRDUzO1xuICB2YXIgR0xfQkxVRV9CSVRTID0gMHgwRDU0O1xuICB2YXIgR0xfQUxQSEFfQklUUyA9IDB4MEQ1NTtcbiAgdmFyIEdMX0RFUFRIX0JJVFMgPSAweDBENTY7XG4gIHZhciBHTF9TVEVOQ0lMX0JJVFMgPSAweDBENTc7XG4gIHZhciBHTF9BTElBU0VEX1BPSU5UX1NJWkVfUkFOR0UgPSAweDg0NkQ7XG4gIHZhciBHTF9BTElBU0VEX0xJTkVfV0lEVEhfUkFOR0UgPSAweDg0NkU7XG4gIHZhciBHTF9NQVhfVEVYVFVSRV9TSVpFID0gMHgwRDMzO1xuICB2YXIgR0xfTUFYX1ZJRVdQT1JUX0RJTVMgPSAweDBEM0E7XG4gIHZhciBHTF9NQVhfVkVSVEVYX0FUVFJJQlMgPSAweDg4Njk7XG4gIHZhciBHTF9NQVhfVkVSVEVYX1VOSUZPUk1fVkVDVE9SUyA9IDB4OERGQjtcbiAgdmFyIEdMX01BWF9WQVJZSU5HX1ZFQ1RPUlMgPSAweDhERkM7XG4gIHZhciBHTF9NQVhfQ09NQklORURfVEVYVFVSRV9JTUFHRV9VTklUUyA9IDB4OEI0RDtcbiAgdmFyIEdMX01BWF9WRVJURVhfVEVYVFVSRV9JTUFHRV9VTklUUyA9IDB4OEI0QztcbiAgdmFyIEdMX01BWF9URVhUVVJFX0lNQUdFX1VOSVRTID0gMHg4ODcyO1xuICB2YXIgR0xfTUFYX0ZSQUdNRU5UX1VOSUZPUk1fVkVDVE9SUyA9IDB4OERGRDtcbiAgdmFyIEdMX01BWF9DVUJFX01BUF9URVhUVVJFX1NJWkUgPSAweDg1MUM7XG4gIHZhciBHTF9NQVhfUkVOREVSQlVGRkVSX1NJWkUgPSAweDg0RTg7XG4gIHZhciBHTF9WRU5ET1IgPSAweDFGMDA7XG4gIHZhciBHTF9SRU5ERVJFUiA9IDB4MUYwMTtcbiAgdmFyIEdMX1ZFUlNJT04gPSAweDFGMDI7XG4gIHZhciBHTF9TSEFESU5HX0xBTkdVQUdFX1ZFUlNJT04gPSAweDhCOEM7XG4gIHZhciBHTF9NQVhfVEVYVFVSRV9NQVhfQU5JU09UUk9QWV9FWFQgPSAweDg0RkY7XG4gIHZhciBHTF9NQVhfQ09MT1JfQVRUQUNITUVOVFNfV0VCR0wgPSAweDhDREY7XG4gIHZhciBHTF9NQVhfRFJBV19CVUZGRVJTX1dFQkdMID0gMHg4ODI0O1xuICB2YXIgR0xfVEVYVFVSRV8yRCA9IDB4MERFMTtcbiAgdmFyIEdMX1RFWFRVUkVfQ1VCRV9NQVAgPSAweDg1MTM7XG4gIHZhciBHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1ggPSAweDg1MTU7XG4gIHZhciBHTF9URVhUVVJFMCA9IDB4ODRDMDtcbiAgdmFyIEdMX1JHQkEgPSAweDE5MDg7XG4gIHZhciBHTF9GTE9BVCQxID0gMHgxNDA2O1xuICB2YXIgR0xfVU5TSUdORURfQllURSQxID0gMHgxNDAxO1xuICB2YXIgR0xfRlJBTUVCVUZGRVIgPSAweDhENDA7XG4gIHZhciBHTF9GUkFNRUJVRkZFUl9DT01QTEVURSA9IDB4OENENTtcbiAgdmFyIEdMX0NPTE9SX0FUVEFDSE1FTlQwID0gMHg4Q0UwO1xuICB2YXIgR0xfQ09MT1JfQlVGRkVSX0JJVCQxID0gMHg0MDAwO1xuICB2YXIgd3JhcExpbWl0cyA9IGZ1bmN0aW9uIHdyYXBMaW1pdHMoZ2wsIGV4dGVuc2lvbnMpIHtcbiAgICB2YXIgbWF4QW5pc290cm9waWMgPSAxO1xuICAgIGlmIChleHRlbnNpb25zLmV4dF90ZXh0dXJlX2ZpbHRlcl9hbmlzb3Ryb3BpYykge1xuICAgICAgbWF4QW5pc290cm9waWMgPSBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1RFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhUKTtcbiAgICB9XG4gICAgdmFyIG1heERyYXdidWZmZXJzID0gMTtcbiAgICB2YXIgbWF4Q29sb3JBdHRhY2htZW50cyA9IDE7XG4gICAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfZHJhd19idWZmZXJzKSB7XG4gICAgICBtYXhEcmF3YnVmZmVycyA9IGdsLmdldFBhcmFtZXRlcihHTF9NQVhfRFJBV19CVUZGRVJTX1dFQkdMKTtcbiAgICAgIG1heENvbG9yQXR0YWNobWVudHMgPSBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0NPTE9SX0FUVEFDSE1FTlRTX1dFQkdMKTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3QgaWYgcmVhZGluZyBmbG9hdCB0ZXh0dXJlcyBpcyBhdmFpbGFibGUgKFNhZmFyaSBkb2Vzbid0IHN1cHBvcnQpXG4gICAgdmFyIHJlYWRGbG9hdCA9ICEhZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9mbG9hdDt
1cbiAgICBpZiAocmVhZEZsb2F0KSB7XG4gICAgICB2YXIgcmVhZEZsb2F0VGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfMkQsIHJlYWRGbG9hdFRleHR1cmUpO1xuICAgICAgZ2wudGV4SW1hZ2UyRChHTF9URVhUVVJFXzJELCAwLCBHTF9SR0JBLCAxLCAxLCAwLCBHTF9SR0JBLCBHTF9GTE9BVCQxLCBudWxsKTtcbiAgICAgIHZhciBmYm8gPSBnbC5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKEdMX0ZSQU1FQlVGRkVSLCBmYm8pO1xuICAgICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoR0xfRlJBTUVCVUZGRVIsIEdMX0NPTE9SX0FUVEFDSE1FTlQwLCBHTF9URVhUVVJFXzJELCByZWFkRmxvYXRUZXh0dXJlLCAwKTtcbiAgICAgIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfMkQsIG51bGwpO1xuICAgICAgaWYgKGdsLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoR0xfRlJBTUVCVUZGRVIpICE9PSBHTF9GUkFNRUJVRkZFUl9DT01QTEVURSkgcmVhZEZsb2F0ID0gZmFsc2U7ZWxzZSB7XG4gICAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIDEsIDEpO1xuICAgICAgICBnbC5jbGVhckNvbG9yKDEuMCwgMC4wLCAwLjAsIDEuMCk7XG4gICAgICAgIGdsLmNsZWFyKEdMX0NPTE9SX0JVRkZFUl9CSVQkMSk7XG4gICAgICAgIHZhciBwaXhlbHMgPSBwb29sLmFsbG9jVHlwZShHTF9GTE9BVCQxLCA0KTtcbiAgICAgICAgZ2wucmVhZFBpeGVscygwLCAwLCAxLCAxLCBHTF9SR0JBLCBHTF9GTE9BVCQxLCBwaXhlbHMpO1xuICAgICAgICBpZiAoZ2wuZ2V0RXJyb3IoKSkgcmVhZEZsb2F0ID0gZmFsc2U7ZWxzZSB7XG4gICAgICAgICAgZ2wuZGVsZXRlRnJhbWVidWZmZXIoZmJvKTtcbiAgICAgICAgICBnbC5kZWxldGVUZXh0dXJlKHJlYWRGbG9hdFRleHR1cmUpO1xuICAgICAgICAgIHJlYWRGbG9hdCA9IHBpeGVsc1swXSA9PT0gMS4wO1xuICAgICAgICB9XG4gICAgICAgIHBvb2wuZnJlZVR5cGUocGl4ZWxzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkZXRlY3Qgbm9uIHBvd2VyIG9mIHR3byBjdWJlIHRleHR1cmVzIHN1cHBvcnQgKElFIGRvZXNuJ3Qgc3VwcG9ydClcbiAgICB2YXIgaXNJRSA9IHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmICgvTVNJRS8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSB8fCAvVHJpZGVudFxcLy8udGVzdChuYXZpZ2F0b3IuYXBwVmVyc2lvbikgfHwgL0VkZ2UvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpO1xuICAgIHZhciBucG90VGV4dHVyZUN1YmUgPSB0cnVlO1xuICAgIGlmICghaXNJRSkge1xuICAgICAgdmFyIGN1YmVUZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgdmFyIGRhdGEgPSBwb29sLmFsbG9jVHlwZShHTF9VTlNJR05FRF9CWVRFJDEsIDM2KTtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoR0xfVEVYVFVSRTApO1xuICAgICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV9DVUJFX01BUCwgY3ViZVRleHR1cmUpO1xuICAgICAgZ2wudGV4SW1hZ2UyRChHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gsIDAsIEdMX1JHQkEsIDMsIDMsIDAsIEdMX1JHQkEsIEdMX1VOU0lHTkVEX0JZVEUkMSwgZGF0YSk7XG4gICAgICBwb29sLmZyZWVUeXBlKGRhdGEpO1xuICAgICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV9DVUJFX01BUCwgbnVsbCk7XG4gICAgICBnbC5kZWxldGVUZXh0dXJlKGN1YmVUZXh0dXJlKTtcbiAgICAgIG5wb3RUZXh0dXJlQ3ViZSA9ICFnbC5nZXRFcnJvcigpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgLy8gZHJhd2luZyBidWZmZXIgYml0IGRlcHRoXG4gICAgICBjb2xvckJpdHM6IFtnbC5nZXRQYXJhbWV0ZXIoR0xfUkVEX0JJVFMpLCBnbC5nZXRQYXJhbWV0ZXIoR0xfR1JFRU5fQklUUyksIGdsLmdldFBhcmFtZXRlcihHTF9CTFVFX0JJVFMpLCBnbC5nZXRQYXJhbWV0ZXIoR0xfQUxQSEFfQklUUyldLFxuICAgICAgZGVwdGhCaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfREVQVEhfQklUUyksXG4gICAgICBzdGVuY2lsQml0czogZ2wuZ2V0UGFyYW1ldGVyKEdMX1NURU5DSUxfQklUUyksXG4gICAgICBzdWJwaXhlbEJpdHM6IGdsLmdldFBhcmFtZXRlcihHTF9TVUJQSVhFTF9CSVRTKSxcbiAgICAgIC8vIHN1cHBvcnRlZCBleHRlbnNpb25zXG4gICAgICBleHRlbnNpb25zOiBPYmplY3Qua2V5cyhleHRlbnNpb25zKS5maWx0ZXIoZnVuY3Rpb24gKGV4dCkge1xuICAgICAgICByZXR1cm4gISFleHRlbnNpb25zW2V4dF07XG4gICAgICB9KSxcbiAgICAgIC8vIG1heCBhbmlzbyBzYW1wbGVzXG4gICAgICBtYXhBbmlzb3Ryb3BpYzogbWF4QW5pc290cm9waWMsXG4gICAgICAvLyBtYXggZHJhdyBidWZmZXJzXG4gICAgICBtYXhEcmF3YnVmZmVyczogbWF4RHJhd2J1ZmZlcnMsXG4gICAgICBtYXhDb2xvckF0dGFjaG1lbnRzOiBtYXhDb2xvckF0dGFjaG1lbnRzLFxuICAgICAgLy8gcG9pbnQgYW5kIGxpbmUgc2l6ZSByYW5nZXNcbiAgICAgIHBvaW50U2l6ZURpbXM6IGdsLmdldFBhcmFtZXRlcihHTF9BTElBU0VEX1BPSU5UX1NJWkVfUkFOR0UpLFxuICAgICAgbGluZVdpZHRoRGltczogZ2wuZ2V0UGFyYW1ldGVyKEdMX0FMSUFTRURfTElORV9XSURUSF9SQU5HRSksXG4gICAgICBtYXhWaWV3cG9ydERpbXM6IGdsLmdldFBhcmFtZXRlcihHTF9NQVhfVklFV1BPUlRfRElNUyksXG4gICAgICBtYXhDb21iaW5lZFRleHR1cmVVbml0czogZ2wuZ2V0UGFyYW1ldGVyKEdMX01BWF9DT01CSU5FRF9URVhUVVJFX0lNQUdFX1VOSVRTKSxcbiAgICAgIG1heEN1YmVNYXBTaXplOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0NVQkVfTUFQX1RFWFRVUkVfU0laRSksXG4gICAgICBtYXhSZW5kZXJidWZmZXJTaXplOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1JFTkRFUkJVRkZFUl9TSVpFKSxcbiAgICAgIG1heFRleHR1cmVVbml0czogZ2wuZ2V0UGFyYW1ldGVyKEdMX01BWF9URVhUVVJFX0lNQUdFX1VOSVRTKSxcbiAgICAgIG1heFRleHR1cmVTaXplOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1RFWFRVUkVfU0laRSksXG4gICAgICBtYXhBdHRyaWJ1dGVzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZFUlRFWF9BVFRSSUJTKSxcbiAgICAgIG1heFZlcnRleFVuaWZvcm1zOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZFUlRFWF9VTklGT1JNX1ZFQ1RPUlMpLFxuICAgICAgbWF4VmVydGV4VGV4dHVyZVVuaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZFUlRFWF9URVhUVVJFX0lNQUdFX1VOSVRTKSxcbiAgICAgIG1heFZhcnlpbmdWZWN0b3JzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZBUllJTkdfVkVDVE9SUyksXG4gICAgICBtYXhGcmFnbWVudFVuaWZvcm1zOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0ZSQUdNRU5UX1VOSUZPUk1fVkVDVE9SUyksXG4gICAgICAvLyB2ZW5kb3IgaW5mb1xuICAgICAgZ2xzbDogZ2wuZ2V0UGFyYW1ldGVyKEdMX1NIQURJTkdfTEFOR1VBR0VfVkVSU0lPTiksXG4gICAgICByZW5kZXJlcjogZ2wuZ2V0UGFyYW1ldGVyKEdMX1JFTkRFUkVSKSxcbiAgICAgIHZlbmRvcjogZ2wuZ2V0UGFyYW1ldGVyKEdMX1ZFTkRPUiksXG4gICAgICB2ZXJzaW9uOiBnbC5nZXRQYXJhbWV0ZXIoR0xfVkVSU0lPTiksXG4gICAgICAvLyBxdWlya3NcbiAgICAgIHJlYWRGbG9hdDogcmVhZEZsb2F0LFxuICAgICAgbnBvdFRleHR1cmVDdWJlOiBucG90VGV4dHVyZUN1YmVcbiAgICB9O1xuICB9O1xuICBmdW5jdGlvbiBpc05EQXJyYXlMaWtlKG9iaikge1xuICAgIHJldHVybiAhIW9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBBcnJheS5pc0FycmF
15KG9iai5zaGFwZSkgJiYgQXJyYXkuaXNBcnJheShvYmouc3RyaWRlKSAmJiB0eXBlb2Ygb2JqLm9mZnNldCA9PT0gJ251bWJlcicgJiYgb2JqLnNoYXBlLmxlbmd0aCA9PT0gb2JqLnN0cmlkZS5sZW5ndGggJiYgKEFycmF5LmlzQXJyYXkob2JqLmRhdGEpIHx8IGlzVHlwZWRBcnJheShvYmouZGF0YSkpO1xuICB9XG4gIHZhciB2YWx1ZXMgPSBmdW5jdGlvbiB2YWx1ZXMob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHJldHVybiBvYmpba2V5XTtcbiAgICB9KTtcbiAgfTtcbiAgdmFyIGZsYXR0ZW5VdGlscyA9IHtcbiAgICBzaGFwZTogYXJyYXlTaGFwZSQxLFxuICAgIGZsYXR0ZW46IGZsYXR0ZW5BcnJheVxuICB9O1xuICBmdW5jdGlvbiBmbGF0dGVuMUQoYXJyYXksIG54LCBvdXQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG54OyArK2kpIHtcbiAgICAgIG91dFtpXSA9IGFycmF5W2ldO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBmbGF0dGVuMkQoYXJyYXksIG54LCBueSwgb3V0KSB7XG4gICAgdmFyIHB0ciA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBueDsgKytpKSB7XG4gICAgICB2YXIgcm93ID0gYXJyYXlbaV07XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG55OyArK2opIHtcbiAgICAgICAgb3V0W3B0cisrXSA9IHJvd1tqXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZmxhdHRlbjNEKGFycmF5LCBueCwgbnksIG56LCBvdXQsIHB0cl8pIHtcbiAgICB2YXIgcHRyID0gcHRyXztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG54OyArK2kpIHtcbiAgICAgIHZhciByb3cgPSBhcnJheVtpXTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbnk7ICsraikge1xuICAgICAgICB2Y
1XIgY29sID0gcm93W2pdO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IG56OyArK2spIHtcbiAgICAgICAgICBvdXRbcHRyKytdID0gY29sW2tdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGZsYXR0ZW5SZWMoYXJyYXksIHNoYXBlLCBsZXZlbCwgb3V0LCBwdHIpIHtcbiAgICB2YXIgc3RyaWRlID0gMTtcbiAgICBmb3IgKHZhciBpID0gbGV2ZWwgKyAxOyBpIDwgc2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN0cmlkZSAqPSBzaGFwZVtpXTtcbiAgICB9XG4gICAgdmFyIG4gPSBzaGFwZVtsZXZlbF07XG4gICAgaWYgKHNoYXBlLmxlbmd0aCAtIGxldmVsID09PSA0KSB7XG4gICAgICB2YXIgbnggPSBzaGFwZVtsZXZlbCArIDFdO1xuICAgICAgdmFyIG55ID0gc2hhcGVbbGV2ZWwgKyAyXTtcbiAgICAgIHZhciBueiA9IHNoYXBlW2xldmVsICsgM107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGZsYXR0ZW4zRChhcnJheVtpXSwgbngsIG55LCBueiwgb3V0LCBwdHIpO1xuICAgICAgICBwdHIgKz0gc3RyaWRlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGZsYXR0ZW5SZWMoYXJyYXlbaV0sIHNoYXBlLCBsZXZlbCArIDEsIG91dCwgcHRyKTtcbiAgICAgICAgcHRyICs9IHN0cmlkZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZmxhdHRlbkFycmF5KGFycmF5LCBzaGFwZSwgdHlwZSwgb3V0Xykge1xuICAgIHZhciBzeiA9IDE7XG4gICAgaWYgKHNoYXBlLmxlbmd0aCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaGFwZS5sZW5ndGg7ICsraSkge1xuICAgICAgICBzeiAqPSBzaGFwZVtpXTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3ogPSAwO1xuICAgIH1cbiAgICB2YXIgb3V0ID0gb3V0XyB8fCBwb29sLmFsbG9jVHlwZSh0eXBlLCBzeik7XG4gICAgc3dpdGNoIChzaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIGZsYXR0ZW4xRChhcnJheSwgc2hhcGVbMF0sIG91dCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICBmbGF0dGVuMkQoYXJyYXksIHNoYXBlWzBdLCBzaGFwZVsxXSwgb3V0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIGZsYXR0ZW4zRChhcnJheSwgc2hhcGVbMF0sIHNoYXBlWzFdLCBzaGFwZVsyXSwgb3V0LCAwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBmbGF0dGVuUmVjKGFycmF5LCBzaGFwZSwgMCwgb3V0LCAwKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuICBmdW5jdGlvbiBhcnJheVNoYXBlJDEoYXJyYXlfKSB7XG4gICAgdmFyIHNoYXBlID0gW107XG4gICAgZm9yICh2YXIgYXJyYXkgPSBhcnJheV87IGFycmF5Lmxlbmd0aDsgYXJyYXkgPSBhcnJheVswXSkge1xuICAgICAgc2hhcGUucHVzaChhcnJheS5sZW5ndGgpO1xuICAgIH1cbiAgICByZXR1cm4gc2hhcGU7XG4gIH1cbiAgdmFyIGFycmF5VHlwZXMgPSB7XG4gICAgXCJbb2JqZWN0IEludDhBcnJheV1cIjogNTEyMCxcbiAgICBcIltvYmplY3QgSW50MTZBcnJheV1cIjogNTEyMixcbiAgICBcIltvYmplY3QgSW50MzJBcnJheV1cIjogNTEyNCxcbiAgICBcIltvYmplY3QgVWludDhBcnJheV1cIjogNTEyMSxcbiAgICBcIltvYmplY3QgVWludDhDbGFtcGVkQXJyYXldXCI6IDUxMjEsXG4gICAgXCJbb2JqZWN0IFVpbnQxNkFycmF
15XVwiOiA1MTIzLFxuICAgIFwiW29iamVjdCBVaW50MzJBcnJheV1cIjogNTEyNSxcbiAgICBcIltvYmplY3QgRmxvYXQzMkFycmF5XVwiOiA1MTI2LFxuICAgIFwiW29iamVjdCBGbG9hdDY0QXJyYXldXCI6IDUxMjEsXG4gICAgXCJbb2JqZWN0IEFycmF5QnVmZmVyXVwiOiA1MTIxXG4gIH07XG4gIHZhciBpbnQ4ID0gNTEyMDtcbiAgdmFyIGludDE2ID0gNTEyMjtcbiAgdmFyIGludDMyID0gNTEyNDtcbiAgdmFyIHVpbnQ4ID0gNTEyMTtcbiAgdmFyIHVpbnQxNiA9IDUxMjM7XG4gIHZhciB1aW50MzIgPSA1MTI1O1xuICB2YXIgZmxvYXQgPSA1MTI2O1xuICB2YXIgZmxvYXQzMiA9IDUxMjY7XG4gIHZhciBnbFR5cGVzID0ge1xuICAgIGludDg6IGludDgsXG4gICAgaW50MTY6IGludDE2LFxuICAgIGludDMyOiBpbnQzMixcbiAgICB1aW50ODogdWludDgsXG4gICAgdWludDE2OiB1aW50MTYsXG4gICAgdWludDMyOiB1aW50MzIsXG4gICAgZmxvYXQ6IGZsb2F0LFxuICAgIGZsb2F0MzI6IGZsb2F0MzJcbiAgfTtcbiAgdmFyIGR5bmFtaWMkMSA9IDM1MDQ4O1xuICB2YXIgc3RyZWFtID0gMzUwNDA7XG4gIHZhciB1c2FnZVR5cGVzID0ge1xuICAgIGR5bmFtaWM6IGR5bmFtaWMkMSxcbiAgICBzdHJlYW06IHN0cmVhbSxcbiAgICBcInN0YXRpY1wiOiAzNTA0NFxuICB9O1xuICB2YXIgYXJyYXlGbGF0dGVuID0gZmxhdHRlblV0aWxzLmZsYXR0ZW47XG4gIHZhciBhcnJheVNoYXBlID0gZmxhdHRlblV0aWxzLnNoYXBlO1xuICB2YXIgR0xfU1RBVElDX0RSQVcgPSAweDg4RTQ7XG4gIHZhciBHTF9TVFJFQU1fRFJBVyA9IDB4ODhFMDtcbiAgdmFyIEdMX1VOU0lHTkVEX0JZVEUkMyA9IDUxMjE7XG4gIHZhciBHTF9GTE9BVCQzID0gNTEyNjtcbiAgdmFyIERUWVBFU19TSVpFUyA9IFtdO1xuICBEVFlQRVNfU0laRVNbNTEyMF0gPSAxOyAvLyBpbnQ4XG4gIERUWVBFU19TSVpFU1s1MTIyXSA9IDI7IC8vIGludDE2XG4gIERUWVBFU19TSVpFU1s1MTI0XSA9IDQ7IC8vIGludDMyXG4gIERUWVBFU19TSVpFU1s1MTIxXSA9IDE7IC8vIHVpbnQ4XG4gIERUWVBFU19TSVpFU1s1MTIzXSA9IDI7IC8vIHVpbnQxNlxuICBEVFlQRVNfU0laRVNbNTEyNV0gPSA0OyAvLyB1aW50MzJcbiAgRFRZUEVTX1NJWkVTWzUxMjZdID0gNDsgLy8gZmxvYXQzMlxuXG4gIGZ1bmN0aW9uIHR5cGVkQXJyYXlDb2RlKGRhdGEpIHtcbiAgICByZXR1cm4gYXJyYXlUeXBlc1tPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSldIHwgMDtcbiAgfVxuICBmdW5jdGlvbiBjb3B5QXJyYXkob3V0LCBpbnApIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlucC5sZW5ndGg7ICsraSkge1xuICAgICAgb3V0W2ldID0gaW5wW2ldO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiB0cmFuc3Bvc2UocmVzdWx0LCBkYXRhLCBzaGFwZVgsIHNoYXBlWSwgc3RyaWRlWCwgc3RyaWRlWSwgb2Zmc2V0KSB7XG4gICAgdmFyIHB0ciA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaGFwZVg7ICsraSkge1xuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzaGFwZVk7ICsraikge1xuICAgICAgICByZXN1bHRbcHRyKytdID0gZGF0YVtzdHJpZGVYICogaSArIHN0cmlkZVkgKiBqICsgb2Zmc2V0XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gd3JhcEJ1ZmZlclN0YXRlKGdsLCBzdGF0cywgY29uZmlnLCBkZXN0cm95QnVmZmVyKSB7XG4gICAgdmFyIGJ1ZmZlckNvdW50ID0gMDtcbiAgICB2YXIgYnVmZmVyU2V0ID0ge307XG4gICAgZnVuY3Rpb24gUkVHTEJ1ZmZlcih0eXBlKSB7XG4gICAgICB0aGlzLmlkID0gYnVmZmVyQ291bnQrKztcbiAgICAgIHRoaXMuYnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgdGhpcy51c2FnZSA9IEdMX1NUQVRJQ19EUkFXO1xuICAgICAgdGhpcy5ieXRlTGVuZ3RoID0gMDtcbiAgICAgIHRoaXMuZGltZW5zaW9uID0gMTtcbiAgICAgIHRoaXMuZHR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDM7XG4gICAgICB0aGlzLnBlcnNpc3RlbnREYXRhID0gbnVsbDtcbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICB0aGlzLnN0YXRzID0ge1xuICAgICAgICAgIHNpemU6IDBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgUkVHTEJ1ZmZlci5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGdsLmJpbmRCdWZmZXIodGhpcy50eXBlLCB0aGlzLmJ1ZmZlcik7XG4gICAgfTtcbiAgICBSRUdMQnVmZmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgZGVzdHJveSh0aGlzKTtcbiAgICB9O1xuICAgIHZhciBzdHJlYW1Qb29sID0gW107XG4gICAgZnVuY3Rpb24gY3JlYXRlU3RyZWFtKHR5cGUsIGRhdGEpIHtcbiAgICAgIHZhciBidWZmZXIgPSBzdHJlYW1Qb29sLnBvcCgpO1xuICAgICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgYnVmZmVyID0gbmV3IFJFR0xCdWZmZXIodHlwZSk7XG4gICAgICB9XG4gICAgICBidWZmZXIuYmluZCgpO1xuICAgICAgaW5pdEJ1ZmZlckZyb21EYXRhKGJ1ZmZlciwgZGF0YSwgR0xfU1RSRUFNX0RSQVcsIDAsIDEsIGZhbHNlKTtcbiAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlc3Ryb3lTdHJlYW0oc3RyZWFtJCQxKSB7XG4gICAgICBzdHJlYW1Qb29sLnB1c2goc3RyZWFtJCQxKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgZGF0YSwgdXNhZ2UpIHtcbiAgICAgIGJ1ZmZlci5ieXRlTGVuZ3RoID0gZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgZ2wuYnVmZmVyRGF0YShidWZmZXIudHlwZSwgZGF0YSwgdXNhZ2UpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbml0QnVmZmVyRnJvbURhdGEoYnVmZmVyLCBkYXRhLCB1c2FnZSwgZHR5cGUsIGRpbWVuc2lvbiwgcGVyc2lzdCkge1xuICAgICAgdmFyIHNoYXBlO1xuICAgICAgYnVmZmVyLnVzYWdlID0gdXNhZ2U7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICBidWZmZXIuZHR5cGUgPSBkdHlwZSB8fCBHTF9GTE9BVCQzO1xuICAgICAgICBpZiAoZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFyIGZsYXREYXRhO1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF
15KGRhdGFbMF0pKSB7XG4gICAgICAgICAgICBzaGFwZSA9IGFycmF5U2hhcGUoZGF0YSk7XG4gICAgICAgICAgICB2YXIgZGltID0gMTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgc2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgZGltICo9IHNoYXBlW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmZmVyLmRpbWVuc2lvbiA9IGRpbTtcbiAgICAgICAgICAgIGZsYXREYXRhID0gYXJyYXlGbGF0dGVuKGRhdGEsIHNoYXBlLCBidWZmZXIuZHR5cGUpO1xuICAgICAgICAgICAgaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgZmxhdERhdGEsIHVzYWdlKTtcbiAgICAgICAgICAgIGlmIChwZXJzaXN0KSB7XG4gICAgICAgICAgICAgIGJ1ZmZlci5wZXJzaXN0ZW50RGF0YSA9IGZsYXREYXRhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcG9vbC5mcmVlVHlwZShmbGF0RGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YVswXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGJ1ZmZlci5kaW1lbnNpb24gPSBkaW1lbnNpb247XG4gICAgICAgICAgICB2YXIgdHlwZWREYXRhID0gcG9vbC5hbGxvY1R5cGUoYnVmZmVyLmR0eXBlLCBkYXRhLmxlbmd0aCk7XG4gICAgICAgICAgICBjb3B5QXJyYXkodHlwZWREYXRhLCBkYXRhKTtcbiAgICAgICAgICAgIGluaXRCdWZmZXJGcm9tVHlwZWRBcnJheShidWZmZXIsIHR5cGVkRGF0YSwgdXNhZ2UpO1xuICAgICAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gdHlwZWREYXRhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcG9vbC5mcmVlVHlwZSh0eXBlZERhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoaXNUeXBlZEFycmF5KGRhdGFbMF0pKSB7XG4gICAgICAgICAgICBidWZmZXIuZGltZW5zaW9uID0gZGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgICBidWZmZXIuZHR5cGUgPSBkdHlwZSB8fCB0eXBlZEFycmF5Q29kZShkYXRhWzBdKSB8fCBHTF9GTE9BVCQzO1xuICAgICAgICAgICAgZmxh
1dERhdGEgPSBhcnJheUZsYXR0ZW4oZGF0YSwgW2RhdGEubGVuZ3RoLCBkYXRhWzBdLmxlbmd0aF0sIGJ1ZmZlci5kdHlwZSk7XG4gICAgICAgICAgICBpbml0QnVmZmVyRnJvbVR5cGVkQXJyYXkoYnVmZmVyLCBmbGF0RGF0YSwgdXNhZ2UpO1xuICAgICAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gZmxhdERhdGE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwb29sLmZyZWVUeXBlKGZsYXREYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBidWZmZXIgZGF0YScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpc1R5cGVkQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgYnVmZmVyLmR0eXBlID0gZHR5cGUgfHwgdHlwZWRBcnJheUNvZGUoZGF0YSk7XG4gICAgICAgIGJ1ZmZlci5kaW1lbnNpb24gPSBkaW1lbnNpb247XG4gICAgICAgIGluaXRCdWZmZXJGcm9tVHlwZWRBcnJheShidWZmZXIsIGRhdGEsIHVzYWdlKTtcbiAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICBidWZmZXIucGVyc2lzdGVudERhdGEgPSBuZXcgVWludDhBcnJheShuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlcikpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGlzTkRBcnJheUxpa2UoZGF0YSkpIHtcbiAgICAgICAgc2hhcGUgPSBkYXRhLnNoYXBlO1xuICAgICAgICB2YXIgc3RyaWRlID0gZGF0YS5zdHJpZGU7XG4gICAgICAgIHZhciBvZmZzZXQgPSBkYXRhLm9mZnNldDtcbiAgICAgICAgdmFyIHNoYXBlWCA9IDA7XG4gICAgICAgIHZhciBzaGFwZVkgPSAwO1xuICAgICAgICB2Y
1XIgc3RyaWRlWCA9IDA7XG4gICAgICAgIHZhciBzdHJpZGVZID0gMDtcbiAgICAgICAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIHNoYXBlWCA9IHNoYXBlWzBdO1xuICAgICAgICAgIHNoYXBlWSA9IDE7XG4gICAgICAgICAgc3RyaWRlWCA9IHN0cmlkZVswXTtcbiAgICAgICAgICBzdHJpZGVZID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICBzaGFwZVggPSBzaGFwZVswXTtcbiAgICAgICAgICBzaGFwZVkgPSBzaGFwZVsxXTtcbiAgICAgICAgICBzdHJpZGVYID0gc3RyaWRlWzBdO1xuICAgICAgICAgIHN0cmlkZVkgPSBzdHJpZGVbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBzaGFwZScpO1xuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlci5kdHlwZSA9IGR0eXBlIHx8IHR5cGVkQXJyYXlDb2RlKGRhdGEuZGF0YSkgfHwgR0xfRkxPQVQkMztcbiAgICAgICAgYnVmZmVyLmRpbWVuc2lvbiA9IHNoYXBlWTtcbiAgICAgICAgdmFyIHRyYW5zcG9zZURhdGEgPSBwb29sLmFsbG9jVHlwZShidWZmZXIuZHR5cGUsIHNoYXBlWCAqIHNoYXBlWSk7XG4gICAgICAgIHRyYW5zcG9zZSh0cmFuc3Bvc2VEYXRhLCBkYXRhLmRhdGEsIHNoYXBlWCwgc2hhcGVZLCBzdHJpZGVYLCBzdHJpZGVZLCBvZmZzZXQpO1xuICAgICAgICBpbml0QnVmZmVyRnJvbVR5cGVkQXJyYXkoYnVmZmVyLCB0cmFuc3Bvc2VEYXRhLCB1c2FnZSk7XG4gICAgICAgIGlmIChwZXJzaXN0KSB7XG4gICAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gdHJhbnNwb3NlRGF0YTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwb29sLmZyZWVUeXBlKHRyYW5zcG9zZURhdGEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBidWZmZXIuZHR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDM7XG4gICAgICAgIGJ1ZmZlci5kaW1lbnNpb24gPSBkaW1lbnNpb247XG4gICAgICAgIGluaXRCdWZmZXJGcm9tVHlwZWRBcnJheShidWZmZXIsIGRhdGEsIHVzYWdlKTtcbiAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICBidWZmZXIucGVyc2lzdGVudERhdGEgPSBuZXcgVWludDhBcnJheShuZXcgVWludDhBcnJheShkYXRhKSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgYnVmZmVyIGRhdGEnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gZGVzdHJveShidWZmZXIpIHtcbiAgICAgIHN0YXRzLmJ1ZmZlckNvdW50LS07XG5cbiAgICAgIC8vIHJlbW92ZSBhdHRyaWJ1dGUgbGlua1xuICAgICAgZGVzdHJveUJ1ZmZlcihidWZmZXIpO1xuICAgICAgdmFyIGhhbmRsZSA9IGJ1ZmZlci5idWZmZXI7XG4gICAgICBjaGVjayQxKGhhbmRsZSwgJ2J1ZmZlciBtdXN0IG5vdCBiZSBkZWxldGVkIGFscmVhZHknKTtcbiAgICAgIGdsLmRlbGV0ZUJ1ZmZlcihoYW5kbGUpO1xuICAgICAgYnVmZmVyLmJ1ZmZlciA9IG51bGw7XG4gICAgICBkZWxldGUgYnVmZmVyU2V0W2J1ZmZlci5pZF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlcihvcHRpb25zLCB0eXBlLCBkZWZlckluaXQsIHBlcnNpc3RlbnQpIHtcbiAgICAgIHN0YXRzLmJ1ZmZlckNvdW50Kys7XG4gICAgICB2Y
1XIgYnVmZmVyID0gbmV3IFJFR0xCdWZmZXIodHlwZSk7XG4gICAgICBidWZmZXJTZXRbYnVmZmVyLmlkXSA9IGJ1ZmZlcjtcbiAgICAgIGZ1bmN0aW9uIHJlZ2xCdWZmZXIob3B0aW9ucykge1xuICAgICAgICB2YXIgdXNhZ2UgPSBHTF9TVEFUSUNfRFJBVztcbiAgICAgICAgdmFyIGRhdGEgPSBudWxsO1xuICAgICAgICB2YXIgYnl0ZUxlbmd0aCA9IDA7XG4gICAgICAgIHZhciBkdHlwZSA9IDA7XG4gICAgICAgIHZhciBkaW1lbnNpb24gPSAxO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zKSB8fCBpc1R5cGVkQXJyYXkob3B0aW9ucykgfHwgaXNOREFycmF5TGlrZShvcHRpb25zKSB8fCBvcHRpb25zIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgICBkYXRhID0gb3B0aW9ucztcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBieXRlTGVuZ3RoID0gb3B0aW9ucyB8IDA7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucykge1xuICAgICAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLCAnb2JqZWN0JywgJ2J1ZmZlciBhcmd1bWVudHMgbXVzdCBiZSBhbiBvYmplY3QsIGEgbnVtYmVyIG9yIGFuIGFycmF5Jyk7XG4gICAgICAgICAgaWYgKCdkYXRhJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxKGRhdGEgPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheShkYXRhKSB8fCBpc1R5cGVkQXJyYXkoZGF0YSkgfHwgaXNOREFycmF5TGlrZShkYXRhKSwgJ2ludmFsaWQgZGF0YSBmb3IgYnVmZmVyJyk7XG4gICAgICAgICAgICBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ3VzYWdlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnVzYWdlLCB1c2FnZVR5cGVzLCAnaW52YWxpZCBidWZmZXIgdXNhZ2UnKTtcbiAgICAgICAgICAgIHVzYWdlID0gdXNhZ2VUeXBlc1tvcHRpb25zLnVzYWdlXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCd0eXBlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnR5cGUsIGdsVHlwZXMsICdpbnZhbGlkIGJ1ZmZlciB0eXBlJyk7XG4gICAgICAgICAgICBkdHlwZSA9IGdsVHlwZXNbb3B0aW9ucy50eXBlXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdkaW1lbnNpb24nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLmRpbWVuc2lvbiwgJ251bWJlcicsICdpbnZhbGlkIGRpbWVuc2lvbicpO1xuICAgICAgICAgICAgZGltZW5zaW9uID0gb3B0aW9ucy5kaW1lbnNpb24gfCAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2xlbmd0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY2hlY2skMS5ubmkoYnl0ZUxlbmd0aCwgJ2J1ZmZlciBsZW5ndGggbXVzdCBiZSBhIG5vbm5lZ2F0aXZlIGludGVnZXInKTtcbiAgICAgICAgICAgIGJ5dGVMZW5ndGggPSBvcHRpb25zLmxlbmd0aCB8IDA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlci5iaW5kKCk7XG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIC8vICM0NzVcbiAgICAgICAgICBpZiAoYnl0ZUxlbmd0aCkgZ2wuYnVmZmVyRGF0YShidWZmZXIudHlwZSwgYnl0ZUxlbmd0aCwgdXNhZ2UpO1xuICAgICAgICAgIGJ1ZmZlci5kdHlwZSA9IGR0eXBlIHx8IEdMX1VOU0lHTkVEX0JZVEUkMztcbiAgICAgICAgICBidWZmZXIudXNhZ2UgPSB1c2FnZTtcbiAgICAgICAgICBidWZmZXIuZGltZW5zaW9uID0gZGltZW5zaW9uO1xuICAgICAgICAgIGJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbml0QnVmZmVyRnJvbURhdGEoYnVmZmVyLCBkYXRhLCB1c2FnZSwgZHR5cGUsIGRpbWVuc2lvbiwgcGVyc2lzdGVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgICAgYnVmZmVyLnN0YXRzLnNpemUgPSBidWZmZXIuYnl0ZUxlbmd0aCAqIERUWVBFU19TSVpFU1tidWZmZXIuZHR5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWdsQnVmZmVyO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc2V0U3ViRGF0YShkYXRhLCBvZmZzZXQpIHtcbiAgICAgICAgY2hlY2skMShvZmZzZXQgKyBkYXRhLmJ5dGVMZW5ndGggPD0gYnVmZmVyLmJ5dGVMZW5ndGgsICdpbnZhbGlkIGJ1ZmZlciBzdWJkYXRhIGNhbGwsIGJ1ZmZlciBpcyB0b28gc21hbGwuICcgKyAnIENhblxcJ3Qgd3JpdGUgZGF0YSBvZiBzaXplICcgKyBkYXRhLmJ5dGVMZW5ndGggKyAnIHN0YXJ0aW5nIGZyb20gb2Zmc2V0ICcgKyBvZmZzZXQgKyAnIHRvIGEgYnVmZmVyIG9mIHNpemUgJyArIGJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgZ2wuYnVmZmVyU3ViRGF0YShidWZmZXIudHlwZSwgb2Zmc2V0LCBkYXRhKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHN1YmRhdGEoZGF0YSwgb2Zmc2V0Xykge1xuICAgICAgICB2Y
1XIgb2Zmc2V0ID0gKG9mZnNldF8gfHwgMCkgfCAwO1xuICAgICAgICB2YXIgc2hhcGU7XG4gICAgICAgIGJ1ZmZlci5iaW5kKCk7XG4gICAgICAgIGlmIChpc1R5cGVkQXJyYXkoZGF0YSkgfHwgZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgc2V0U3ViRGF0YShkYXRhLCBvZmZzZXQpO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbMF0gPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgIHZhciBjb252ZXJ0ZWQgPSBwb29sLmFsbG9jVHlwZShidWZmZXIuZHR5cGUsIGRhdGEubGVuZ3RoKTtcbiAgICAgICAgICAgICAgY29weUFycmF5KGNvbnZlcnRlZCwgZGF0YSk7XG4gICAgICAgICAgICAgIHNldFN1YkRhdGEoY29udmVydGVkLCBvZmZzZXQpO1xuICAgICAgICAgICAgICBwb29sLmZyZWVUeXBlKGNvbnZlcnRlZCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZGF0YVswXSkgfHwgaXNUeXBlZEFycmF5KGRhdGFbMF0pKSB7XG4gICAgICAgICAgICAgIHNoYXBlID0gYXJyYXlTaGFwZShkYXRhKTtcbiAgICAgICAgICAgICAgdmFyIGZsYXREYXRhID0gYXJyYXlGbGF0dGVuKGRhdGEsIHNoYXBlLCBidWZmZXIuZHR5cGUpO1xuICAgICAgICAgICAgICBzZXRTdWJEYXRhKGZsYXREYXRhLCBvZmZzZXQpO1xuICAgICAgICAgICAgICBwb29sLmZyZWVUeXBlKGZsYXREYXRhKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgYnVmZmVyIGRhdGEnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNOREFycmF5TGlrZShkYXRhKSkge1xuICAgICAgICAgIHNoYXBlID0gZGF0YS5zaGFwZTtcbiAgICAgICAgICB2Y
1XIgc3RyaWRlID0gZGF0YS5zdHJpZGU7XG4gICAgICAgICAgdmFyIHNoYXBlWCA9IDA7XG4gICAgICAgICAgdmFyIHNoYXBlWSA9IDA7XG4gICAgICAgICAgdmFyIHN0cmlkZVggPSAwO1xuICAgICAgICAgIHZhciBzdHJpZGVZID0gMDtcbiAgICAgICAgICBpZiAoc2hhcGUubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBzaGFwZVggPSBzaGFwZVswXTtcbiAgICAgICAgICAgIHNoYXBlWSA9IDE7XG4gICAgICAgICAgICBzdHJpZGVYID0gc3RyaWRlWzBdO1xuICAgICAgICAgICAgc3RyaWRlWSA9IDA7XG4gICAgICAgICAgfSBlbHNlIGlmIChzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIHNoYXBlWCA9IHNoYXBlWzBdO1xuICAgICAgICAgICAgc2hhcGVZID0gc2hhcGVbMV07XG4gICAgICAgICAgICBzdHJpZGVYID0gc3RyaWRlWzBdO1xuICAgICAgICAgICAgc3RyaWRlWSA9IHN0cmlkZVsxXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBzaGFwZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgZHR5cGUgPSBBcnJheS5pc0FycmF5KGRhdGEuZGF0YSkgPyBidWZmZXIuZHR5cGUgOiB0eXBlZEFycmF5Q29kZShkYXRhLmRhdGEpO1xuICAgICAgICAgIHZhciB0cmFuc3Bvc2VEYXRhID0gcG9vbC5hbGxvY1R5cGUoZHR5cGUsIHNoYXBlWCAqIHNoYXBlWSk7XG4gICAgICAgICAgdHJhbnNwb3NlKHRyYW5zcG9zZURhdGEsIGRhdGEuZGF0YSwgc2hhcGVYLCBzaGFwZVksIHN0cmlkZVgsIHN0cmlkZVksIGRhdGEub2Zmc2V0KTtcbiAgICAgICAgICBzZXRTdWJEYXRhKHRyYW5zcG9zZURhdGEsIG9mZnNldCk7XG4gICAgICAgICAgcG9vbC5mcmVlVHlwZSh0cmFuc3Bvc2VEYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIGRhdGEgZm9yIGJ1ZmZlciBzdWJkYXRhJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2xCdWZmZXI7XG4gICAgICB9XG4gICAgICBpZiAoIWRlZmVySW5pdCkge1xuICAgICAgICByZWdsQnVmZmVyKG9wdGlvbnMpO1xuICAgICAgfVxuICAgICAgcmVnbEJ1ZmZlci5fcmVnbFR5cGUgPSAnYnVmZmVyJztcbiAgICAgIHJlZ2xCdWZmZXIuX2J1ZmZlciA9IGJ1ZmZlcjtcbiAgICAgIHJlZ2xCdWZmZXIuc3ViZGF0YSA9IHN1YmRhdGE7XG4gICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgICAgcmVnbEJ1ZmZlci5zdGF0cyA9IGJ1ZmZlci5zdGF0cztcbiAgICAgIH1cbiAgICAgIHJlZ2xCdWZmZXIuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZGVzdHJveShidWZmZXIpO1xuICAgICAgfTtcbiAgICAgIHJldHVybiByZWdsQnVmZmVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXN0b3JlQnVmZmVycygpIHtcbiAgICAgIHZhbHVlcyhidWZmZXJTZXQpLmZvckVhY2goZnVuY3Rpb24gKGJ1ZmZlcikge1xuICAgICAgICBidWZmZXIuYnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoYnVmZmVyLnR5cGUsIGJ1ZmZlci5idWZmZXIpO1xuICAgICAgICBnbC5idWZmZXJEYXRhKGJ1ZmZlci50eXBlLCBidWZmZXIucGVyc2lzdGVudERhdGEgfHwgYnVmZmVyLmJ5dGVMZW5ndGgsIGJ1ZmZlci51c2FnZSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICBzdGF0cy5nZXRUb3RhbEJ1ZmZlclNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgIC8vIFRPRE86IFJpZ2h0IG5vdywgdGhlIHN0cmVhbXMgYXJlIG5vdCBwYXJ0IG9mIHRoZSB0b3RhbCBjb3VudC5cbiAgICAgICAgT2JqZWN0LmtleXMoYnVmZmVyU2V0KS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICB0b3RhbCArPSBidWZmZXJTZXRba2V5XS5zdGF0cy5zaXplO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRvdGFsO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGNyZWF0ZTogY3JlYXRlQnVmZmVyLFxuICAgICAgY3JlYXRlU3RyZWFtOiBjcmVhdGVTdHJlYW0sXG4gICAgICBkZXN0cm95U3RyZWFtOiBkZXN0cm95U3RyZWFtLFxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICB2YWx1ZXMoYnVmZmVyU2V0KS5mb3JFYWNoKGRlc3Ryb3kpO1xuICAgICAgICBzdHJlYW1Qb29sLmZvckVhY2goZGVzdHJveSk7XG4gICAgICB9LFxuICAgICAgZ2V0QnVmZmVyOiBmdW5jdGlvbiBnZXRCdWZmZXIod3JhcHBlcikge1xuICAgICAgICBpZiAod3JhcHBlciAmJiB3cmFwcGVyLl9idWZmZXIgaW5zdGFuY2VvZiBSRUdMQnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIHdyYXBwZXIuX2J1ZmZlcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0sXG4gICAgICByZXN0b3JlOiByZXN0b3JlQnVmZmVycyxcbiAgICAgIF9pbml0QnVmZmVyOiBpbml0QnVmZmVyRnJvbURhdGFcbiAgICB9O1xuICB9XG4gIHZhciBwb2ludHMgPSAwO1xuICB2YXIgcG9pbnQgPSAwO1xuICB2YXIgbGluZXMgPSAxO1xuICB2YXIgbGluZSA9IDE7XG4gIHZhciB0cmlhbmdsZXMgPSA0O1xuICB2YXIgdHJpYW5nbGUgPSA0O1xuICB2YXIgcHJpbVR5cGVzID0ge1xuICAgIHBvaW50czogcG9pbnRzLFxuICAgIHBvaW50OiBwb2ludCxcbiAgICBsaW5lczogbGluZXMsXG4gICAgbGluZTogbGluZSxcbiAgICB0cmlhbmdsZXM6IHRyaWFuZ2xlcyxcbiAgICB0cmlhbmdsZTogdHJpYW5nbGUsXG4gICAgXCJsaW5lIGxvb3BcIjogMixcbiAgICBcImxpbmUgc3RyaXBcIjogMyxcbiAgICBcInRyaWFuZ2xlIHN0cmlwXCI6IDUsXG4gICAgXCJ0cmlhbmdsZSBmYW5cIjogNlxuICB9O1xuICB2YXIgR0xfUE9JTlRTID0gMDtcbiAgdmFyIEdMX0xJTkVTID0gMTtcbiAgdmFyIEdMX1RSSUFOR0xFUyA9IDQ7XG4gIHZhciBHTF9CWVRFJDIgPSA1MTIwO1xuICB2YXIgR0xfVU5TSUdORURfQllURSQ0ID0gNTEyMTtcbiAgdmFyIEdMX1NIT1JUJDIgPSA1MTIyO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlQkMiA9IDUxMjM7XG4gIHZhciBHTF9JTlQkMiA9IDUxMjQ7XG4gIHZhciBHTF9VTlNJR05FRF9JTlQkMiA9IDUxMjU7XG4gIHZhciBHTF9FTEVNRU5UX0FSUkFZX0JVRkZFUiA9IDM0OTYzO1xuICB2YXIgR0xfU1RSRUFNX0RS
1QVckMSA9IDB4ODhFMDtcbiAgdmFyIEdMX1NUQVRJQ19EUkFXJDEgPSAweDg4RTQ7XG4gIGZ1bmN0aW9uIHdyYXBFbGVtZW50c1N0YXRlKGdsLCBleHRlbnNpb25zLCBidWZmZXJTdGF0ZSwgc3RhdHMpIHtcbiAgICB2YXIgZWxlbWVudFNldCA9IHt9O1xuICAgIHZhciBlbGVtZW50Q291bnQgPSAwO1xuICAgIHZhciBlbGVtZW50VHlwZXMgPSB7XG4gICAgICAndWludDgnOiBHTF9VTlNJR05FRF9CWVRFJDQsXG4gICAgICAndWludDE2JzogR0xfVU5TSUdORURfU0hPUlQkMlxuICAgIH07XG4gICAgaWYgKGV4dGVuc2lvbnMub2VzX2VsZW1lbnRfaW5kZXhfdWludCkge1xuICAgICAgZWxlbWVudFR5cGVzLnVpbnQzMiA9IEdMX1VOU0lHTkVEX0lOVCQyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBSRUdMRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICAgIHRoaXMuaWQgPSBlbGVtZW50Q291bnQrKztcbiAgICAgIGVsZW1lbnRTZXRbdGhpcy5pZF0gPSB0aGlzO1xuICAgICAgdGhpcy5idWZmZXIgPSBidWZmZXI7XG4gICAgICB0aGlzLnByaW1UeXBlID0gR0xfVFJJQU5HTEVTO1xuICAgICAgdGhpcy52ZXJ0Q291bnQgPSAwO1xuICAgICAgdGhpcy50eXBlID0gMDtcbiAgICB9XG4gICAgUkVHTEVsZW1lbnRCdWZmZXIucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB0aGlzLmJ1ZmZlci5iaW5kKCk7XG4gICAgfTtcbiAgICB2YXIgYnVmZmVyUG9vbCA9IFtdO1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnRTdHJlYW0oZGF0YSkge1xuICAgICAgdmFyIHJlc3VsdCA9IGJ1ZmZlclBvb2wucG9wKCk7XG4gICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICByZXN1bHQgPSBuZXcgUkVHTEVsZW1lbnRCdWZmZXIoYnVmZmVyU3RhdGUuY3JlYXRlKG51bGwsIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSLCB0cnVlLCBmYWxzZSkuX2J1ZmZlcik7XG4gICAgICB9XG4gICAgICBpbml0RWxlbWVudHMocmVzdWx0LCBkYXRhLCBHTF9TVFJFQU1fRFJBVyQxLCAtMSwgLTEsIDAsIDApO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVzdHJveUVsZW1lbnRTdHJlYW0oZWxlbWVudHMpIHtcbiAgICAgIGJ1ZmZlclBvb2wucHVzaChlbGVtZW50cyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGluaXRFbGVtZW50cyhlbGVtZW50cywgZGF0YSwgdXNhZ2UsIHByaW0sIGNvdW50LCBieXRlTGVuZ3RoLCB0eXBlKSB7XG4gICAgICBlbGVtZW50cy5idWZmZXIuYmluZCgpO1xuICAgICAgdmFyIGR0eXBlO1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgdmFyIHByZWRpY3RlZFR5cGUgPSB0eXBlO1xuICAgICAgICBpZiAoIXR5cGUgJiYgKCFpc1R5cGVkQXJyYXkoZGF0YSkgfHwgaXNOREFycmF5TGlrZShkYXRhKSAmJiAhaXNUeXBlZEFycmF5KGRhdGEuZGF0YSkpKSB7XG4gICAgICAgICAgcHJlZGljdGVkVHlwZSA9IGV4dGVuc2lvbnMub2VzX2VsZW1lbnRfaW5kZXhfdWludCA/IEdMX1VOU0lHTkVEX0lOVCQyIDogR0xfVU5TSUdORURfU0hPUlQkMjtcbiAgICAgICAgfVxuICAgICAgICBidWZmZXJTdGF0ZS5faW5pdEJ1ZmZlcihlbGVtZW50cy5idWZmZXIsIGRhdGEsIHVzYWdlLCBwcmVkaWN0ZWRUeXBlLCAzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJ1ZmZlckRhdGEoR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIsIGJ5dGVMZW5ndGgsIHVzYWdlKTtcbiAgICAgICAgZWxlbWVudHMuYnVmZmVyLmR0eXBlID0gZHR5cGUgfHwgR0xfVU5TSUdORURfQllURSQ0O1xuICAgICAgICBlbGVtZW50cy5idWZmZXIudXNhZ2UgPSB1c2FnZTtcbiAgICAgICAgZWxlbWVudHMuYnVmZmVyLmRpbWVuc2lvbiA9IDM7XG4gICAgICAgIGVsZW1lbnRzLmJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGR0eXBlID0gdHlwZTtcbiAgICAgIGlmICghdHlwZSkge1xuICAgICAgICBzd2l0Y2ggKGVsZW1lbnRzLmJ1ZmZlci5kdHlwZSkge1xuICAgICAgICAgIGNhc2UgR0xfVU5TSUdORURfQllURSQ0OlxuICAgICAgICAgIGNhc2UgR0xfQllURSQyOlxuICAgICAgICAgICAgZHR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIEdMX1VOU0lHTkVEX1NIT1JUJDI6XG4gICAgICAgICAgY2FzZSBHTF9TSE9SVCQyOlxuICAgICAgICAgICAgZHR5cGUgPSBHTF9VTlNJR05FRF9TSE9SVCQyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBHTF9VTlNJR05FRF9JTlQkMjpcbiAgICAgICAgICBjYXNlIEdMX0lOVCQyOlxuICAgICAgICAgICAgZHR5cGUgPSBHTF9VTlNJR05FRF9JTlQkMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjaGVjayQxLnJhaXNlKCd1bnN1cHBvcnRlZCB0eXBlIGZvciBlbGVtZW50IGFycmF5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudHMuYnVmZmVyLmR0eXBlID0gZHR5cGU7XG4gICAgICB9XG4gICAgICBlbGVtZW50cy50eXBlID0gZHR5cGU7XG5cbiAgICAgIC8vIENoZWNrIG9lc19lbGVtZW50X2luZGV4X3VpbnQgZXh0ZW5zaW9uXG4gICAgICBjaGVjayQxKGR0eXBlICE9PSBHTF9VTlNJR05FRF9JTlQkMiB8fCAhIWV4dGVuc2lvbnMub2VzX2VsZW1lbnRfaW5kZXhfdWludCwgJzMyIGJpdCBlbGVtZW50IGJ1ZmZlcnMgbm90IHN1cHBvcnRlZCwgZW5hYmxlIG9lc19lbGVtZW50X2luZGV4X3VpbnQgZmlyc3QnKTtcblxuICAgICAgLy8gdHJ5IHRvIGd1ZXNzIGRlZmF1bHQgcHJpbWl0aXZlIH
1R5cGUgYW5kIGFyZ3VtZW50c1xuICAgICAgdmFyIHZlcnRDb3VudCA9IGNvdW50O1xuICAgICAgaWYgKHZlcnRDb3VudCA8IDApIHtcbiAgICAgICAgdmVydENvdW50ID0gZWxlbWVudHMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChkdHlwZSA9PT0gR0xfVU5TSUdORURfU0hPUlQkMikge1xuICAgICAgICAgIHZlcnRDb3VudCA+Pj0gMTtcbiAgICAgICAgfSBlbHNlIGlmIChkdHlwZSA9PT0gR0xfVU5TSUdORURfSU5UJDIpIHtcbiAgICAgICAgICB2ZXJ0Q291bnQgPj49IDI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsZW1lbnRzLnZlcnRDb3VudCA9IHZlcnRDb3VudDtcblxuICAgICAgLy8gdHJ5IHRvIGd1ZXNzIHByaW1pdGl2ZSB0eXBlIGZyb20gY2VsbCBkaW1lbnNpb25cbiAgICAgIHZhciBwcmltVHlwZSA9IHByaW07XG4gICAgICBpZiAocHJpbSA8IDApIHtcbiAgICAgICAgcHJpbVR5cGUgPSBHTF9UUklBTkdMRVM7XG4gICAgICAgIHZhciBkaW1lbnNpb24gPSBlbGVtZW50cy5idWZmZXIuZGltZW5zaW9uO1xuICAgICAgICBpZiAoZGltZW5zaW9uID09PSAxKSBwcmltVHlwZSA9IEdMX1BPSU5UUztcbiAgICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gMikgcHJpbVR5cGUgPSBHTF9MSU5FUztcbiAgICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gMykgcHJpbVR5cGUgPSBHTF9UUklBTkdMRVM7XG4gICAgICB9XG4gICAgICBlbGVtZW50cy5wcmltVHlwZSA9IHByaW1UeXBlO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkZXN0cm95RWxlbWVudHMoZWxlbWVudHMpIHtcbiAgICAgIHN0YXRzLmVsZW1lbnRzQ291bnQtLTtcbiAgICAgIGNoZWNrJDEoZWxlbWVudHMuYnVmZmVyICE9PSBudWxsLCAnbXVzdCBub3QgZG91YmxlIGRlc3Ryb3kgZWxlbWVudHMnKTtcbiAgICAgIGRlbGV0ZSBlbGVtZW50U2V0W2VsZW1lbnRzLmlkXTtcbiAgICAgIGVsZW1lbnRzLmJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICBlbGVtZW50cy5idWZmZXIgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50cyhvcHRpb25zLCBwZXJzaXN0ZW50KSB7XG4gICAgICB2Y
1XIgYnVmZmVyID0gYnVmZmVyU3RhdGUuY3JlYXRlKG51bGwsIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSLCB0cnVlKTtcbiAgICAgIHZhciBlbGVtZW50cyA9IG5ldyBSRUdMRWxlbWVudEJ1ZmZlcihidWZmZXIuX2J1ZmZlcik7XG4gICAgICBzdGF0cy5lbGVtZW50c0NvdW50Kys7XG4gICAgICBmdW5jdGlvbiByZWdsRWxlbWVudHMob3B0aW9ucykge1xuICAgICAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgICAgICBidWZmZXIoKTtcbiAgICAgICAgICBlbGVtZW50cy5wcmltVHlwZSA9IEdMX1RSSUFOR0xFUztcbiAgICAgICAgICBlbGVtZW50cy52ZXJ0Q291bnQgPSAwO1xuICAgICAgICAgIGVsZW1lbnRzLnR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDQ7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgYnVmZmVyKG9wdGlvbnMpO1xuICAgICAgICAgIGVsZW1lbnRzLnByaW1UeXBlID0gR0xfVFJJQU5HTEVTO1xuICAgICAgICAgIGVsZW1lbnRzLnZlcnRDb3VudCA9IG9wdGlvbnMgfCAwO1xuICAgICAgICAgIGVsZW1lbnRzLnR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSBudWxsO1xuICAgICAgICAgIHZhciB1c2FnZSA9IEdMX1NUQVRJQ19EUkFXJDE7XG4gICAgICAgICAgdmFyIHByaW1UeXBlID0gLTE7XG4gICAgICAgICAgdmFyIHZlcnRDb3VudCA9IC0xO1xuICAgICAgICAgIHZhciBieXRlTGVuZ3RoID0gMDtcbiAgICAgICAgICB2Y
1XIgZHR5cGUgPSAwO1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbnMpIHx8IGlzVHlwZWRBcnJheShvcHRpb25zKSB8fCBpc05EQXJyYXlMaWtlKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICBkYXRhID0gb3B0aW9ucztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMS50eXBlKG9wdGlvbnMsICdvYmplY3QnLCAnaW52YWxpZCBhcmd1bWVudHMgZm9yIGVsZW1lbnRzJyk7XG4gICAgICAgICAgICBpZiAoJ2RhdGEnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgZGF0YSA9IG9wdGlvbnMuZGF0YTtcbiAgICAgICAgICAgICAgY2hlY2skMShBcnJheS5pc0FycmF5KGRhdGEpIHx8IGlzVHlwZWRBcnJheShkYXRhKSB8fCBpc05EQXJyYXlMaWtlKGRhdGEpLCAnaW52YWxpZCBkYXRhIGZvciBlbGVtZW50IGJ1ZmZlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCd1c2FnZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnVzYWdlLCB1c2FnZVR5cGVzLCAnaW52YWxpZCBlbGVtZW50IGJ1ZmZlciB1c2FnZScpO1xuICAgICAgICAgICAgICB1c2FnZSA9IHVzYWdlVHlwZXNbb3B0aW9ucy51c2FnZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ3ByaW1pdGl2ZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnByaW1pdGl2ZSwgcHJpbVR5cGVzLCAnaW52YWxpZCBlbGVtZW50IGJ1ZmZlciBwcmltaXRpdmUnKTtcbiAgICAgICAgICAgICAgcHJpbVR5cGUgPSBwcmltVHlwZXNbb3B0aW9ucy5wcmltaXRpdmVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCdjb3VudCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjaGVjayQxKHR5cGVvZiBvcHRpb25zLmNvdW50ID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLmNvdW50ID49IDAsICdpbnZhbGlkIHZlcnRleCBjb3VudCBmb3IgZWxlbWVudHMnKTtcbiAgICAgICAgICAgICAgdmVydENvdW50ID0gb3B0aW9ucy5jb3VudCB8IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ3R5cGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIob3B0aW9ucy50eXBlLCBlbGVtZW50VHlwZXMsICdpbnZhbGlkIGJ1ZmZlciB0eXBlJyk7XG4gICAgICAgICAgICAgIGR0eXBlID0gZWxlbWVudFR5cGVzW29wdGlvbnMudHlwZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ2xlbmd0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBieXRlTGVuZ3RoID0gb3B0aW9ucy5sZW5ndGggfCAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYnl0ZUxlbmd0aCA9IHZlcnRDb3VudDtcbiAgICAgICAgICAgICAgaWYgKGR0eXBlID09PSBHTF9VTlNJR05FRF9TSE9SVCQyIHx8IGR0eXBlID09PSBHTF9TSE9SVCQyKSB7XG4gICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCAqPSAyO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGR0eXBlID09PSBHTF9VTlNJR05FRF9JTlQkMiB8fCBkdHlwZSA9PT0gR0xfSU5UJDIpIHtcbiAgICAgICAgICAgICAgICBieXRlTGVuZ3RoICo9IDQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaW5pdEVsZW1lbnRzKGVsZW1lbnRzLCBkYXRhLCB1c2FnZSwgcHJpbVR5cGUsIHZlcnRDb3VudCwgYnl0ZUxlbmd0aCwgZHR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWdsRWxlbWVudHM7XG4gICAgICB9XG4gICAgICByZWdsRWxlbWVudHMob3B0aW9ucyk7XG4gICAgICByZWdsRWxlbWVudHMuX3JlZ2xUeXBlID0gJ2VsZW1lbnRzJztcbiAgICAgIHJlZ2xFbGVtZW50cy5fZWxlbWVudHMgPSBlbGVtZW50cztcbiAgICAgIHJlZ2xFbGVtZW50cy5zdWJkYXRhID0gZnVuY3Rpb24gKGRhdGEsIG9mZnNldCkge1xuICAgICAgICBidWZmZXIuc3ViZGF0YShkYXRhLCBvZmZzZXQpO1xuICAgICAgICByZXR1cm4gcmVnbEVsZW1lbnRzO1xuICAgICAgfTtcbiAgICAgIHJlZ2xFbGVtZW50cy5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBkZXN0cm95RWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgfTtcbiAgICAgIHJldHVybiByZWdsRWxlbWVudHM7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjcmVhdGU6IGNyZWF0ZUVsZW1lbnRzLFxuICAgICAgY3JlYXRlU3RyZWFtOiBjcmVhdGVFbGVtZW50U3RyZWFtLFxuICAgICAgZGVzdHJveVN0cmVhbTogZGVzdHJveUVsZW1lbnRTdHJlYW0sXG4gICAgICBnZXRFbGVtZW50czogZnVuY3Rpb24gZ2V0RWxlbWVudHMoZWxlbWVudHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlbGVtZW50cyA9PT0gJ2Z1bmN0aW9uJyAmJiBlbGVtZW50cy5fZWxlbWVudHMgaW5zdGFuY2VvZiBSRUdMRWxlbWVudEJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBlbGVtZW50cy5fZWxlbWVudHM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9LFxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICB2YWx1ZXMoZWxlbWVudFNldCkuZm9yRWFjaChkZXN0cm95RWxlbWVudHMpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgdmFyIEZMT0FUID0gbmV3IEZsb2F0MzJBcnJheSgxKTtcbiAgdmFyIElOVCA9IG5ldyBVaW50MzJBcnJheShGTE9BVC5idWZmZXIpO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlQkNCA9IDUxMjM7XG4gIGZ1bmN0aW9uIGNvbnZlcnRUb0hhbGZGbG9hdChhcnJheSkge1xuICAgIHZhciB1c2hvcnRzID0gcG9vbC5hbGxvY1R5cGUoR0xfVU5TSUdORURfU0hPUlQkNCwgYXJyYXkubGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoaXNOYU4oYXJyYXlbaV0pKSB7XG4gICAgICAgIHVzaG9ydHNbaV0gPSAweGZmZmY7XG4gICAgICB9IGVsc2UgaWYgKGFycmF5W2ldID09PSBJbmZpbml0eSkge1xuICAgICAgICB1c2hvcnRzW2ldID0gMHg3YzAwO1xuICAgICAgfSBlbHNlIGlmIChhcnJheVtpXSA9PT0gLUluZmluaXR5KSB7XG4gICAgICAgI
1HVzaG9ydHNbaV0gPSAweGZjMDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBGTE9BVFswXSA9IGFycmF5W2ldO1xuICAgICAgICB2YXIgeCA9IElOVFswXTtcbiAgICAgICAgdmFyIHNnbiA9IHggPj4+IDMxIDw8IDE1O1xuICAgICAgICB2YXIgZXhwID0gKHggPDwgMSA+Pj4gMjQpIC0gMTI3O1xuICAgICAgICB2YXIgZnJhYyA9IHggPj4gMTMgJiAoMSA8PCAxMCkgLSAxO1xuICAgICAgICBpZiAoZXhwIDwgLTI0KSB7XG4gICAgICAgICAgLy8gcm91bmQgbm9uLXJlcHJlc2VudGFibGUgZGVub3JtYWxzIHRvIDBcbiAgICAgICAgICB1c2hvcnRzW2ldID0gc2duO1xuICAgICAgICB9IGVsc2UgaWYgKGV4cCA8IC0xNCkge1xuICAgICAgICAgIC8vIGhhbmRsZSBkZW5vcm1hbHNcbiAgICAgICAgICB2YXIgcyA9IC0xNCAtIGV4cDtcbiAgICAgICAgICB1c2hvcnRzW2ldID0gc2duICsgKGZyYWMgKyAoMSA8PCAxMCkgPj4gcyk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXhwID4gMTUpIHtcbiAgICAgICAgICAvLyByb3VuZCBvdmVyZmxvdyB0byArLy0gSW5maW5pdHlcbiAgICAgICAgICB1c2hvcnRzW2ldID0gc2duICsgMHg3YzAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG90aGVyd2lzZSBjb252ZXJ0IGRpcmVjdGx5XG4gICAgICAgICAgdXNob3J0c1tpXSA9IHNnbiArIChleHAgKyAxNSA8PCAxMCkgKyBmcmFjO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1c2hvcnRzO1xuICB9XG4gIGZ1bmN0aW9uIGlzQXJyYXlMaWtlKHMpIHtcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShzKSB8fCBpc1R5cGVkQXJyYXkocyk7XG4gIH1cbiAgdmFyIGlzUG93MiQxID0gZnVuY3Rpb24gaXNQb3cyJDEodikge1xuICAgIHJldHVybiAhKHYgJiB2IC0gMSkgJiYgISF2O1xuICB9O1xuICB2YXIgR0xfQ09NUFJFU1NFRF9URVhUVVJFX0ZPUk1BVFMgPSAweDg2QTM7XG4gIHZhciBHTF9URVhUVVJFXzJEJDEgPSAweDBERTE7XG4gIHZhciBHTF9URVhUVVJFX0NVQkVfTUFQJDEgPSAweDg1MTM7XG4gIHZhciBHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gkMSA9IDB4ODUxNTtcbiAgdmFyIEdMX1JHQkEkMSA9IDB4MTkwODtcbiAgdmFyIEdMX0FMUEhBID0gMHgxOTA2O1xuICB2YXIgR0xfUkdCID0gMHgxOTA3O1xuICB2YXIgR0xfTFVNSU5BTkNFID0gMHgxOTA5O1xuICB2YXIgR0xfTFVNSU5BTkNFX0FMUEhBID0gMHgxOTBBO1xuICB2YXIgR0xfUkdCQTQgPSAweDgwNTY7XG4gIHZhciBHTF9SR0I1X0ExID0gMHg4MDU3O1xuICB2YXIgR0xfUkdCNTY1ID0gMHg4RDYyO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlRfNF80XzRfNCQxID0gMHg4MDMzO1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlRfNV81XzVfMSQxID0gMHg4MDM0O1xuICB2YXIgR0xfVU5TSUdORURfU0hPUlRfNV82XzUkMSA9IDB4ODM2MztcbiAgdmFyIEdMX1VOU0lHTkVEX0lOVF8yNF84X1dFQkdMJDEgPSAweDg0RkE7XG4gIHZhciBHTF9ERVBUSF9DT01QT05FTlQgPSAweDE5MDI7XG4gIHZhciBHTF9ERVBUSF9TVEVOQ0lMID0gMHg4NEY5O1xuICB2YXIgR0xfU1JHQl9FWFQgPSAweDhDNDA7XG4gIHZhciBHTF9TUkdCX0FMUEhBX0VYVCA9IDB4OEM0MjtcbiAgdmFyIEdMX0hBTEZfRkxPQVRfT0VTJDEgPSAweDhENjE7XG4gIHZhciBHTF9DT01QUkVTU0VEX1JHQl9TM1RDX0RYVDFfRVhUID0gMHg4M0YwO1xuICB2YXIgR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUMV9FWFQgPSAweDgzRjE7XG4gIHZhciBHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQzX0VYVCA9IDB4ODNGMjtcbiAgdmFyIEdMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDVfRVhUID0gMHg4M0YzO1xuICB2YXIgR0xfQ09NUFJFU1NFRF9SR0JfQVRDX1dFQkdMID0gMHg4QzkyO1xuICB2YXIgR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19FWFBMSUNJVF9BTFBIQV9XRUJHTCA9IDB4OEM5MztcbiAgdmFyIEdMX0NPTVBSRVNTRURfUkdCQV9BVENfSU5URVJQT0xBVEVEX0FMUEhBX1dFQkdMID0gMHg4N0VFO1xuICB2YXIgR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfNEJQUFYxX0lNRyA9IDB4OEMwMDtcbiAgdmFyIEdMX0NPTVBSRVNTRURfUkdCX1BWUlRDXzJCUFBWMV9JTUcgPSAweDhDMDE7XG4gIHZhciBHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfNEJQUFYxX0lNRyA9IDB4OEMwMjtcbiAgdmFyIEdMX0NPTVBSRVNTRURfUkdCQV9QVlJUQ18yQlBQVjFfSU1HID0gMHg4QzAzO1xuICB2YXIgR0xfQ09NUFJFU1NFRF9SR0JfRVRDMV9XRUJHTCA9IDB4OEQ2NDtcbiAgdmFyIEdMX1VOU0lHTkVEX0JZVEUkNSA9IDB4MTQwMTtcbiAgdmFyIEdMX1VOU0lHTkVEX1NIT1JUJDMgPSAweDE0MDM7XG4gIHZhciBHTF9VTlNJR05FRF9JTlQkMyA9IDB4MTQwNTtcbiAgdmFyIEdMX0ZMT0FUJDQgPSAweDE0MDY7XG4gIHZhciBHTF9URVhUVVJFX1dSQVBfUyA9IDB4MjgwMjtcbiAgdmFyIEdMX1RFWFRVUkVfV1JBUF9UID0gMHgyODAzO1xuICB2YXIgR0xfUkVQRUFUID0gMHgyOTAxO1xuICB2YXIgR0xfQ0xBTVBfVE9fRURHRSQxID0gMHg4MTJGO1xuICB2YXIgR0xfTUlSUk9SRURfUkVQRUFUID0gMHg4MzcwO1xuICB2YXIgR0xfVEVYVFVSRV9NQUdfRklMVEVSID0gMHgyODAwO1xuICB2YXIgR0xfVEVYVFVSRV9NSU5fRklMVEVSID0gMHgyODAxO1xuICB2YXIgR0xfTkVBUkVTVCQxID0gMHgyNjAwO1xuICB2YXIgR0xfTElORUFSID0gMHgyNjAxO1xuICB2YXIgR0xfTkVBUkVTVF9NSVBNQVBfTkVBUkVTVCQxID0gMHgyNzAwO1xuICB2YXIgR0xfTElORUFSX01JUE1BUF9ORUFSRVNUJDEgPSAweDI3MDE7XG4gIHZhciBHTF9ORUFSRVNUX01JUE1BUF9MSU5FQVIkMSA9IDB4MjcwMjtcbiAgdmFyIEdMX0xJTkVBUl9NSVBNQVBfTElORUFSJDEgPSAweDI3MDM7XG4gIHZhciBHTF9HRU5FUkFURV9NSVBNQVBfSElOVCA9IDB4ODE5MjtcbiAgdmFyIEdMX0RPTlRfQ0FSRSA9IDB4MTEwMDtcbiAgdmFyIEdMX0ZBU1RFU1QgPSAweDExMDE7XG4gIHZhciBHTF9OSUNFU1QgPSAweDExMDI7XG4gIHZhciBHTF9URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCA9IDB4ODRGRTtcbiAgdmFyIEdMX1VOUEFDS19BTElHTk1FTlQgPSAweDBDRjU7XG4gIHZhciBHTF9VTlBBQ0tfRkxJUF9ZX1dFQkdMID0gMHg5MjQwO1xuICB2YXIgR0xfVU5QQUNLX1BSRU1VTFRJUExZX0FMUEhBX1dFQkdMID0gMHg5MjQxO1xuICB2YXIgR0xfVU5QQUNLX0NPTE9SU1BBQ0VfQ09OVkVSU0lPTl9XRUJHTCA9IDB4OTI0MztcbiAgdmFyIEdMX0JST1dTRVJfREVGQVVMVF9XRUJHTCA9IDB4OTI0NDtcbiAgdmFyIEdMX1RFWFRVUkUwJDEgPSAweDg0QzA7XG4gIHZhciBNSVBNQVBfRklMVEVSUyA9IFtHTF9ORUFSRVNUX01JUE1BUF9ORUFSRVNUJDEsIEdMX05FQVJFU1RfTUlQTUFQX0xJTkVBUiQxLCBHTF9MSU5FQVJfTUlQTUFQX05FQVJFU1QkMSwgR0xfTElORUFSX01JUE1BUF9MSU5FQVIkMV07XG4gIHZhciBDSEFOTkVMU19GT1JNQVQgPSBbMCwgR0xfTFVNSU5BTkNFLCBHTF9MVU1JTkFOQ0VfQUxQSEEsIEdMX1JHQiwgR0xfUkdCQSQxXTtcbiAgdmFyIEZPUk1BVF9DSEFOTkVMUyA9IHt9O1xuICBGT1JNQVRfQ0hBTk5FTFNbR0xfTFVNSU5BTkNFXSA9IEZPUk1BVF9DSEFOTkVMU1tHTF9BTFBIQV0gPSBGT1JNQVRfQ0hBTk5FTFNbR0xfREVQVEhfQ09NUE9ORU5UXSA9IDE7XG4gIEZPUk1BVF9DSEFOTkVMU1tHTF9ERVBUSF9TVEVOQ0lMXSA9IEZPUk1BVF9DSEFOTkVMU1tHTF9MVU1JTkFOQ0VfQUxQSEFdID0gMjtcbiAgRk9STUFUX0NIQU5ORUxTW0dMX1JHQl0gPSBGT1JNQVRfQ0hBTk5FTFNbR0xfU1JHQl9FWFRdID0gMztcbiAgRk9STUFUX0NIQU5ORUxTW0dMX1JHQkEkMV0gPSBGT1JNQVRfQ0hBTk5FTFNbR0xfU1JHQl9BTFBIQV9FWFRdID0gNDtcbiAgZnVuY3Rpb24gb2JqZWN0TmFtZShzdHIpIHtcbiAgICByZXR1cm4gJ1tvYmplY3QgJyArIHN0ciArICddJztcbiAgfVxuICB2YXIgQ0FOVkFTX0NMQVNTID0gb2JqZWN0TmFtZSgnSFRNTENhbnZhc0VsZW1lbnQnKTtcbiAgdmFyIE9GRlNDUkVFTkNBTlZBU19DTEFTUyA9IG9iamVjdE5hbWUoJ09mZnNjcmVlbkNhbnZhcycpO1xuICB2YXIgQ09OVEVYVDJEX0NMQVNTID0gb2JqZWN0TmFtZSgnQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEJyk7XG4gIHZhciBCSVRNQVBfQ0xBU1MgPSBvYmplY3ROYW1lKCdJbWFnZUJpdG1hcCcpO1xuICB2YXIgSU1BR0VfQ0xBU1MgPSBvYmplY3ROYW1lKCdIVE1MSW1hZ2VFbGVtZW50Jyk7XG4gIHZhciBWSURFT19DTEFTUyA9IG9iamVjdE5hbWUoJ0hUTUxWaWRlb0VsZW1lbnQnKTtcbiAgdmFyIFBJWEVMX0NMQVNTRVMgPSBPYmplY3Qua2V5cyhhcnJheVR5cGVzKS5jb25jYXQoW0NBTlZBU19DTEFTUywgT0ZGU0NSRUVOQ0FOVkFTX0NMQVNTLCBDT05URVhUMkRfQ0xBU1MsIEJJVE1BUF9DTEFTUywgSU1BR0VfQ0xBU1MsIFZJREVPX0NMQVNTXSk7XG5cbiAgLy8gZm9yIGV2ZXJ5IHRleHR1cmUgdHlwZSwgc3RvcmVcbiAgLy8gdGhlIHNpemUgaW4gYnl0ZXMuXG4gIHZhciBUWVBFX1NJWkVTID0gW107XG4gIFRZUEVfU0laRVNbR0xfVU5TSUdORURfQllURSQ1XSA9IDE7XG4gIFRZUEVfU0laRVNbR0xfRkxPQVQkNF0gPSA0O1xuICBUWVBFX1NJWkVTW0dMX0hBTEZfRkxPQVRfT0VTJDFdID0gMjtcbiAgVFlQRV9TSVpFU1tHTF9VTlNJR05FRF9TSE9SVCQzXSA9IDI7XG4gIFRZUEVfU0laRVNbR0xfVU5TSUdORURfSU5UJDNdID0gNDtcbiAgdmFyIEZPUk1BVF9TSVpFU19TUEVDSUFMID0gW107XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX1JHQkE0XSA9IDI7XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX1JHQjVfQTFdID0gMjtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfUkdCNTY1XSA9IDI7XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0RFUFRIX1NURU5DSUxdID0gNDtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JfUzNUQ19EWFQxX0VYVF0gPSAwLjU7XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDFfRVhUXSA9IDAuNTtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUM19FWFRdID0gMTtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUNV9FWFRdID0gMTtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JfQVRDX1dFQkdMXSA9IDAuNTtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19FWFBMSUNJVF9BTFBIQV9XRUJHTF0gPSAxO1xuICBGT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQkFfQVRDX0lOVEVSUE9MQVRFRF9BTFBIQV9XRUJHTF0gPSAxO1xuICBGT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQl9QVlJUQ180QlBQVjFfSU1HXSA9IDAuNTtcbiAgRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfMkJQUFYxX0lNR10gPSAwLjI1O1xuICBGT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfNEJQUFYxX0lNR10gPSAwLjU7XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0NPTVBSRVNTRURfUkdCQV9QVlJUQ18yQlBQVjFfSU1HXSA9IDAuMjU7XG4gIEZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0NPTVBSRVNTRURfUkdCX0VUQzFfV0VCR0xdID0gMC41O1xuICBmdW5jdGlvbiBpc051bWVyaWNBcnJheShhcnIpIHtcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShhcnIpICYmIChhcnIubGVuZ3RoID09PSAwIHx8IHR5cGVvZiBhcnJbMF0gPT09ICdudW1iZXInKTtcbiAgfVxuICBmdW5jdGlvbiBpc1JlY3RBcnJheShhcnIpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB2YXIgd2lkdGggPSBhcnIubGVuZ3RoO1xuICAgIGlmICh3aWR0aCA9PT0gMCB8fCAhaXNBcnJheUxpa2UoYXJyWzBdKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBmdW5jdGlvbiBjbGFzc1N0cmluZyh4KSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KTtcbiAgfVxuICBmdW5jdGlvbiBpc0NhbnZhc0VsZW1lbnQob2JqZWN0KSB7XG4gICAgcmV0dXJuIGNsYXNzU3RyaW5nKG9iamVjdCkgPT09IENBTlZBU19DTEFTUztcbiAgfVxuICBmdW5jdGlvbiBpc09mZnNjcmVlbkNhbnZhcyhvYmplY3QpIHtcbiAgICByZXR1cm4gY2xhc3NTdHJpbmcob2JqZWN0KSA9PT0gT0ZGU0NSRUVOQ0FOVkFTX0NMQVNTO1xuICB9XG4gIGZ1bmN0aW9uIGlzQ29udGV4dDJEKG9iamVjdCkge1xuICAgIHJldHVybi
1BjbGFzc1N0cmluZyhvYmplY3QpID09PSBDT05URVhUMkRfQ0xBU1M7XG4gIH1cbiAgZnVuY3Rpb24gaXNCaXRtYXAob2JqZWN0KSB7XG4gICAgcmV0dXJuIGNsYXNzU3RyaW5nKG9iamVjdCkgPT09IEJJVE1BUF9DTEFTUztcbiAgfVxuICBmdW5jdGlvbiBpc0ltYWdlRWxlbWVudChvYmplY3QpIHtcbiAgICByZXR1cm4gY2xhc3NTdHJpbmcob2JqZWN0KSA9PT0gSU1BR0VfQ0xBU1M7XG4gIH1cbiAgZnVuY3Rpb24gaXNWaWRlb0VsZW1lbnQob2JqZWN0KSB7XG4gICAgcmV0dXJuIGNsYXNzU3RyaW5nKG9iamVjdCkgPT09IFZJREVPX0NMQVNTO1xuICB9XG4gIGZ1bmN0aW9uIGlzUGl4ZWxEYXRhKG9iamVjdCkge1xuICAgIGlmICghb2JqZWN0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHZhciBjbGFzc05hbWUgPSBjbGFzc1N0cmluZyhvYmplY3QpO1xuICAgIGlmIChQSVhFTF9DTEFTU0VTLmluZGV4T2YoY2xhc3NOYW1lKSA+PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGlzTnVtZXJpY0FycmF5KG9iamVjdCkgfHwgaXNSZWN0QXJyYXkob2JqZWN0KSB8fCBpc05EQXJyYXlMaWtlKG9iamVjdCk7XG4gIH1cbiAgZnVuY3Rpb24gdHlwZWRBcnJheUNvZGUkMShkYXRhKSB7XG4gICAgcmV0dXJuIGFycmF5VHlwZXNbT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGEpXSB8IDA7XG4gIH1cbiAgZnVuY3Rpb24gY29udmVydERhdGEocmVzdWx0LCBkYXRhKSB7XG4gICAgdmFyIG4gPSBkYXRhLmxlbmd0aDtcbiAgICBzd2l0Y2ggKHJlc3VsdC50eXBlKSB7XG4gICAgICBjYXNlIEdMX1VOU0lHTkVEX0JZVEUkNTpcbiAgICAgIGNhc2UgR0xfVU5TSUdORURfU0hPUlQkMzpcbiAgICAgIGNhc2UgR0xfVU5TSUdORURfSU5UJDM6XG4gICAgICBjYXNlIEdMX0ZMT0FUJDQ6XG4gICAgICAgIHZhciBjb252ZXJ0ZWQgPSBwb29sLmFsbG9jVHlwZShyZXN1bHQudHlwZSwgbik7XG4gICAgICAgIGNvbnZlcnRlZC5zZXQoZGF0YSk7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gY29udmVydGVkO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgR0xfSEFMRl9GTE9BVF9PRVMkMTpcbiAgICAgICAgcmVzdWx0LmRhdGEgPSBjb252ZXJ0VG9IYWxmRmxvYXQoZGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY2hlY2skMS5yYWlzZSgndW5zdXBwb3J0ZWQgdGV4dHVyZSB0eXBlLCBtdXN0IHNwZWNpZnkgYSB0eXBlZCBhcnJheScpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBwcmVDb252ZXJ0KGltYWdlLCBuKSB7XG4gICAgcmV0dXJuIHBvb2wuYWxsb2NUeXBlKGltYWdlLnR5cGUgPT09IEdMX0hBTEZfRkxPQVRfT0VTJDEgPyBHTF9GTE9BVCQ0IDogaW1hZ2UudHlwZSwgbik7XG4gIH1cbiAgZnVuY3Rpb24gcG9zdENvbnZlcnQoaW1hZ2UsIGRhdGEpIHtcbiAgICBpZiAoaW1hZ2UudHlwZSA9PT0gR0xfSEFMRl9GTE9BVF9PRVMkMSkge1xuICAgICAgaW1hZ2UuZGF0YSA9IGNvbnZlcnRUb0hhbGZGbG9hdChkYXRhKTtcbiAgICAgIHBvb2wuZnJlZVR5cGUoZGF0YSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGltYWdlLmRhdGEgPSBkYXRhO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiB0cmFuc3Bvc2VEYXRhKGltYWdlLCBhcnJheSwgc3RyaWRlWCwgc3RyaWRlWSwgc3RyaWRlQywgb2Zmc2V0KSB7XG4gICAgdmFyIHcgPSBpbWFnZS53aWR0aDtcbiAgICB2YXIgaCA9IGltYWdlLmhlaWdodDtcbiAgICB2YXIgYyA9IGltYWdlLmNoYW5uZWxzO1xuICAgIHZhciBuID0gdyAqIGggKiBjO1xuICAgIHZhciBkYXRhID0gcHJlQ29udmVydChpbWFnZSwgbik7XG4gICAgdmFyIHAgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaDsgKytpKSB7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHc7ICsraikge1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGM7ICsraykge1xuICAgICAgICAgIGRhdGFbcCsrXSA9IGFycmF5W3N0cmlkZVggKiBqICsgc3RyaWRlWSAqIGkgKyBzdHJpZGVDICogayArIG9mZnNldF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcG9zdENvbnZlcnQoaW1hZ2UsIGRhdGEpO1xuICB9XG4gIGZ1bmN0aW9uIGdldFRleHR1cmVTaXplKGZvcm1hdCwgdHlwZSwgd2lkdGgsIGhlaWdodCwgaXNNaXBtYXAsIGlzQ3ViZSkge1xuICAgIHZhciBzO1xuICAgIGlmICh0eXBlb2YgRk9STUFUX1NJWkVTX1NQRUNJQUxbZm9ybWF0XSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIC8vIHdlIGhhdmUgYSBzcGVjaWFsIGFycmF5IGZvciBkZWFsaW5nIHdpdGggd2VpcmQgY29sb3IgZm9ybWF0cyBzdWNoIGFzIFJHQjVBMVxuICAgICAgcyA9IEZPUk1BVF9TSVpFU19TUEVDSUFMW2Zvcm1hdF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHMgPSBGT1JNQVRfQ0hBTk5FTFNbZm9ybWF0XSAqIFRZUEVfU0laRVNbdHlwZV07XG4gICAgfVxuICAgIGlmIChpc0N1YmUpIHtcbiAgICAgIHMgKj0gNjtcbiAgICB9XG4gICAgaWYgKGlzTWlwbWFwKSB7XG4gICAgICAvLyBjb21wdXRlIHRoZSB0b3RhbCBzaXplIG9mIGFsbCB0aGUgbWlwbWFwcy5cbiAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICB2Y
1XIgdyA9IHdpZHRoO1xuICAgICAgd2hpbGUgKHcgPj0gMSkge1xuICAgICAgICAvLyB3ZSBjYW4gb25seSB1c2UgbWlwbWFwcyBvbiBhIHNxdWFyZSBpbWFnZSxcbiAgICAgICAgLy8gc28gd2UgY2FuIHNpbXBseSB1c2UgdGhlIHdpZHRoIGFuZCBpZ25vcmUgdGhlIGhlaWdodDpcbiAgICAgICAgdG90YWwgKz0gcyAqIHcgKiB3O1xuICAgICAgICB3IC89IDI7XG4gICAgICB9XG4gICAgICByZXR1cm4gdG90YWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzICogd2lkdGggKiBoZWlnaHQ7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVTZXQoZ2wsIGV4dGVuc2lvbnMsIGxpbWl0cywgcmVnbFBvbGwsIGNvbnRleHRTdGF0ZSwgc3RhdHMsIGNvbmZpZykge1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBJbml0aWFsaXplIGNvbnN0YW50cyBhbmQgcGFyYW1ldGVyIHRhYmxlcyBoZXJlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciBtaXBtYXBIaW50ID0ge1xuICAgICAgXCJkb24ndCBjYXJlXCI6IEdMX0RPTlRfQ0FSRSxcbiAgICAgICdkb250IGNhcmUnOiBHTF9ET05UX0NBUkUsXG4gICAgICAnbmljZSc6IEdMX05JQ0VTVCxcbiAgICAgICdmYXN0JzogR0xfRkFTVEVTVFxuICAgIH07XG4gICAgdmFyIHdyYXBNb2RlcyA9IHtcbiAgICAgICdyZXBlYXQnOiBHTF9SRVBFQVQsXG4gICAgICAnY2xhbXAnOiBHTF9DTEFNUF9UT19FREdFJDEsXG4gICAgICAnbWlycm9yJzogR0xfTUlSUk9SRURfUkVQRUFUXG4gICAgfTtcbiAgICB2YXIgbWFnRmlsdGVycyA9IHtcbiAgICAgICduZWFyZXN0JzogR0xfTkVBUkVTVCQxLFxuICAgICAgJ2xpbmVhcic6IEdMX0xJTkVBUlxuICAgIH07XG4gICAgdmFyIG1pbkZpbHRlcnMgPSBleHRlbmQoe1xuICAgICAgJ21pcG1hcCc6IEdMX0xJTkVBUl9NSVBNQVBfTElORUFSJDEsXG4gICAgICAnbmVhcmVzdCBtaXBtYXAgbmVhcmVzdCc6IEdMX05FQVJFU1RfTUlQTUFQX05FQVJFU1QkMSxcbiAgICAgICdsaW5lYXIgbWlwbWFwIG5lYXJlc3QnOiBHTF9MSU5FQVJfTUlQTUFQX05FQVJFU1QkMSxcbiAgICAgICduZWFyZXN0IG1pcG1hcCBsaW5lYXInOiBHTF9ORUFSRVNUX01JUE1BUF9MSU5FQVIkMSxcbiAgICAgICdsaW5lYXIgbWlwbWFwIGxpbmVhcic6IEdMX0xJTkVBUl9NSVBNQVBfTElORUFSJDFcbiAgICB9LCBtYWdGaWx0ZXJzKTtcbiAgICB2YXIgY29sb3JTcGFjZSA9IHtcbiAgICAgICdub25lJzogMCxcbiAgICAgICdicm93c2VyJzogR0xfQlJPV1NFUl9ERUZBVUxUX1dFQkdMXG4gICAgfTtcbiAgICB2YXIgdGV4dHVyZVR5cGVzID0ge1xuICAgICAgJ3VpbnQ4JzogR0xfVU5TSUdORURfQllURSQ1LFxuICAgICAgJ3JnYmE0JzogR0xfVU5TSUdORURfU0hPUlRfNF80XzRfNCQxLFxuICAgICAgJ3JnYjU2NSc6IEdMX1VOU0lHTkVEX1NIT1JUXzVfNl81JDEsXG4gICAgICAncmdiNSBhMSc6IEdMX1VOU0lHTkVEX1NIT1JUXzVfNV81XzEkMVxuICAgIH07XG4gICAgdmFyIHRleHR1cmVGb3JtYXRzID0ge1xuICAgICAgJ2FscGhhJzogR0xfQUxQSEEsXG4gICAgICAnbHVtaW5hbmNlJzogR0xfTFVNSU5BTkNFLFxuICAgICAgJ2x1bWluYW5jZSBhbHBoYSc6IEdMX0xVTUlOQU5DRV9BTFBIQSxcbiAgICAgICdyZ2InOiBHTF9SR0IsXG4gICAgICAncmdiYSc6IEdMX1JHQkEkMSxcbiAgICAgICdyZ2JhNCc6IEdMX1JHQkE0LFxuICAgICAgJ3JnYjUgYTEnOiBHTF9SR0I1X0ExLFxuICAgICAgJ3JnYjU2NSc6IEdMX1JHQjU2NVxuICAgIH07XG4gICAgdmFyIGNvbXByZXNzZWRUZXh0dXJlRm9ybWF0cyA9IHt9O1xuICAgIGlmIChleHRlbnNpb25zLmV4dF9zcmdiKSB7XG4gICAgICB0ZXh0dXJlRm9ybWF0cy5zcmdiID0gR0xfU1JHQl9FWFQ7XG4gICAgICB0ZXh0dXJlRm9ybWF0cy5zcmdiYSA9IEdMX1NSR0JfQUxQSEFfRVhUO1xuICAgIH1cbiAgICBpZiAoZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9mbG9hdCkge1xuICAgICAgdGV4dHVyZVR5cGVzLmZsb2F0MzIgPSB0ZXh0dXJlVHlwZXMuZmxvYXQgPSBHTF9GTE9BVCQ0O1xuICAgIH1cbiAgICBpZiAoZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9oYWxmX2Zsb2F0KSB7XG4gICAgICB0ZXh0dXJlVHlwZXNbJ2Zsb2F0MTYnXSA9IHRleHR1cmVUeXBlc1snaGFsZiBmbG9hdCddID0gR0xfSEFMRl9GTE9BVF9PRVMkMTtcbiAgICB9XG4gICAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfZGVwdGhfdGV4dHVyZSkge1xuICAgICAgZXh0ZW5kKHRleHR1cmVGb3JtYXRzLCB7XG4gICAgICAgICdkZXB0aCc6IEdMX0RFUFRIX0NPTVBPTkVOVCxcbiAgICAgICAgJ2RlcHRoIHN0ZW5jaWwnOiBHTF9ERVBUSF9TVEVOQ0lMXG4gICAgICB9KTtcbiAgICAgIGV4dGVuZCh0ZXh0dXJlVHlwZXMsIHtcbiAgICAgICAgJ3VpbnQxNic6IEdMX1VOU0lHTkVEX1NIT1JUJDMsXG4gICAgICAgICd1aW50MzInOiBHTF9VTlNJR05FRF9JTlQkMyxcbiAgICAgICAgJ2RlcHRoIHN0ZW5jaWwnOiBHTF9VTlNJR05FRF9JTlRfMjRfOF9XRUJHTCQxXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfY29tcHJlc3NlZF90ZXh0dXJlX3MzdGMpIHtcbiAgICAgIGV4dGVuZChjb21wcmVzc2VkVGV4dHVyZUZvcm1hdHMsIHtcbiAgICAgICAgJ3JnYiBzM3RjIGR4dDEnOiBHTF9DT01QUkVTU0VEX1JHQl9TM1RDX0RYVDFfRVhULFxuICAgICAgICAncmdiYSBzM3RjIGR4dDEnOiBHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQxX0VYVCxcbiAgICAgICAgJ3JnYmEgczN0YyBkeHQzJzogR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUM19FWFQsXG4gICAgICAgICdyZ2JhIHMzdGMgZHh0NSc6IEdMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDVfRVhUXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfY29tcHJlc3NlZF90ZXh0dXJlX2F0Yykge1xuICAgICAgZXh0ZW5kKGNvbXByZXNzZWRUZXh0dXJlRm9ybWF0cywge1xuICAgICAgICAncmdiIGF0Yyc6IEdMX0NPTVBSRVNTRURfUkdCX0FUQ19XRUJHTCxcbiAgICAgICAgJ3JnYmEgYXRjIGV4cGxpY2l0IGFscGhhJzogR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19FWFBMSUNJVF9BTFBIQV9XRUJHTCxcbiAgICAgICAgJ3JnYmEgYXRjIGludGVycG9sYXRlZCBhbHBoYSc6IEdMX0NPTVBSRVNTRURfUkdCQV9BVENfSU5URVJQT0xBVEVEX0FMUEhBX1dFQkdMXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfY29tcHJlc3NlZF90ZXh0dXJlX3B2cnRjKSB7XG4gICAgICBleHRlbmQoY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzLCB7XG4gICAgICAgICdyZ2IgcHZydGMgNGJwcHYxJzogR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfNEJQUFYxX0lNRyxcbiAgICAgICAgJ3JnYiBwdnJ0YyAyYnBwdjEnOiBHTF9DT01QUkVTU0VEX1JHQl9QVlJUQ18yQlBQVjFfSU1HLFxuICAgICAgICAncmdiYSBwdnJ0YyA0YnBwdjEnOiBHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfNEJQUFYxX0lNRyxcbiAgICAgICAgJ3JnYmEgcHZydGMgMmJwcHYxJzogR0xfQ09NUFJFU1NFRF9SR0JBX1BWUlRDXzJCUFBWMV9JTUdcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoZXh0ZW5zaW9ucy53ZWJnbF9jb21wcmVzc2VkX3RleHR1cmVfZXRjMSkge1xuICAgICAgY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzWydyZ2IgZXRjMSddID0gR0xfQ09NUFJFU1NFRF9SR0JfRVRDMV9XRUJHTDtcbiAgICB9XG5cbiAgICAvLyBDb3B5IG92ZXIgYWxsIHRleHR1cmUgZm9ybWF0c1xuICAgIHZhciBzdXBwb3J0ZWRDb21wcmVzc2VkRm9ybWF0cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGdsLmdldFBhcmFtZXRlcihHTF9DT01QUkVTU0VEX1RFWFRVUkVfRk9STUFUUykpO1xuICAgIE9iamVjdC5rZXlzKGNvbXByZXNzZWRUZXh0dXJlRm9ybWF0cykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIGZvcm1hdCA9IGNvbXByZXNzZWRUZXh0dXJlRm9ybWF0c1tuYW1lXTtcbiAgICAgIGlmIChzdXBwb3J0ZWRDb21wcmVzc2VkRm9ybWF0cy5pbmRleE9mKGZvcm1hdCkgPj0gMCkge1xuICAgICAgICB0ZXh0dXJlRm9ybWF0c1tuYW1lXSA9IGZvcm1hdDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB2YXIgc3VwcG9ydGVkRm9ybWF0cyA9IE9iamVjdC5rZXlzKHRleHR1cmVGb3JtYXRzKTtcbiAgICBsaW1pdHMudGV4dHVyZUZvcm1hdHMgPSBzdXBwb3J0ZWRGb3JtYXRzO1xuXG4gICAgLy8gYXNzb2NpYXRlIHdpdGggZXZlcnkgZm9ybWF0IHN0cmluZyBpdHNcbiAgICAvLyBjb3JyZXNwb25kaW5nIEdMLXZhbHVlLlxuICAgIHZhciB0ZXh0dXJlRm9ybWF0c0ludmVydCA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHRleHR1cmVGb3JtYXRzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHZhciB2YWwgPSB0ZXh0dXJlRm9ybWF0c1trZXldO1xuICAgICAgdGV4dHVyZUZvcm1hdHNJb
1nZlcnRbdmFsXSA9IGtleTtcbiAgICB9KTtcblxuICAgIC8vIGFzc29jaWF0ZSB3aXRoIGV2ZXJ5IHR5cGUgc3RyaW5nIGl0c1xuICAgIC8vIGNvcnJlc3BvbmRpbmcgR0wtdmFsdWUuXG4gICAgdmFyIHRleHR1cmVUeXBlc0ludmVydCA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHRleHR1cmVUeXBlcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICB2YXIgdmFsID0gdGV4dHVyZVR5cGVzW2tleV07XG4gICAgICB0ZXh0dXJlVHlwZXNJbnZlcnRbdmFsXSA9IGtleTtcbiAgICB9KTtcbiAgICB2YXIgbWFnRmlsdGVyc0ludmVydCA9IFtdO1xuICAgIE9iamVjdC5rZXlzKG1hZ0ZpbHRlcnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgdmFyIHZhbCA9IG1hZ0ZpbHRlcnNba2V5XTtcbiAgICAgIG1hZ0ZpbHRlcnNJbnZlcnRbdmFsXSA9IGtleTtcbiAgICB9KTtcbiAgICB2YXIgbWluRmlsdGVyc0ludmVydCA9IFtdO1xuICAgIE9iamVjdC5rZXlzKG1pbkZpbHRlcnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgdmFyIHZhbCA9IG1pbkZpbHRlcnNba2V5XTtcbiAgICAgIG1pbkZpbHRlcnNJbnZlcnRbdmFsXSA9IGtleTtcbiAgICB9KTtcbiAgICB2YXIgd3JhcE1vZGVzSW52ZXJ0ID0gW107XG4gICAgT2JqZWN0LmtleXMod3JhcE1vZGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHZhciB2YWwgPSB3cmFwTW9kZXNba2V5XTtcbiAgICAgIHdyYXBNb2Rlc0ludmVydFt2YWxdID0ga2V5O1xuICAgIH0pO1xuXG4gICAgLy8gY29sb3JGb3JtYXRzW10gZ2l2ZXMgdGhlIGZvcm1hdCAoY2hhbm5lbHMpIGFzc29jaWF0ZWQgdG8gYW5cbiAgICAvLyBpbnRlcm5hbGZvcm1hdFxuICAgIHZhciBjb2xvckZvcm1hdHMgPSBzdXBwb3J0ZWRGb3JtYXRzLnJlZHVjZShmdW5jdGlvbiAoY29sb3IsIGtleSkge1xuICAgICAgdmFyIGdsZW51bSA9IHRleHR1cmVGb3JtYXRzW2tleV07XG4gICAgICBpZiAoZ2xlbnVtID09PSBHTF9MVU1JTkFOQ0UgfHwgZ2xlbnVtID09PSBHTF9BTFBIQSB8fCBnbGVudW0gPT09IEdMX0xVTUlOQU5DRSB8fCBnbGVudW0gPT09IEdMX0xVTUlOQU5DRV9BTFBIQSB8fCBnbGVudW0gPT09IEdMX0RFUFRIX0NPTVBPTkVOVCB8fCBnbGVudW0gPT09IEdMX0RFUFRIX1NURU5DSUwgfHwgZXh0ZW5zaW9ucy5leHRfc3JnYiAmJiAoZ2xlbnVtID09PSBHTF9TUkdCX0VYVCB8fCBnbGVudW0gPT09IEdMX1NSR0JfQUxQSEFfRVhUKSkge1xuICAgICAgICBjb2xvcltnbGVudW1dID0gZ2xlbnVtO1xuICAgICAgfSBlbHNlIGlmIChnbGVudW0gPT09IEdMX1JHQjVfQTEgfHwga2V5LmluZGV4T2YoJ3JnYmEnKSA+PSAwKSB7XG4gICAgICAgIGNvbG9yW2dsZW51bV0gPSBHTF9SR0JBJDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2xvcltnbGVudW1dID0gR0xfUkdCO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNvbG9yO1xuICAgIH0sIHt9KTtcbiAgICBmdW5jdGlvbiBUZXhGbGFncygpIHtcbiAgICAgIC8vIGZvcm1hdCBpbmZvXG4gICAgICB0aGlzLmludGVybmFsZm9ybWF0ID0gR0xfUkdCQSQxO1xuICAgICAgdGhpcy5mb3JtYXQgPSBHTF9SR0JBJDE7XG4gICAgICB0aGlzLnR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDU7XG4gICAgICB0aGlzLmNvbXByZXNzZWQgPSBmYWxzZTtcblxuICAgICAgLy8gcGl4ZWwgc3RvcmFnZVxuICAgICAgdGhpcy5wcmVtdWx0aXBseUFscGhhID0gZmFsc2U7XG4gICAgICB0aGlzLmZsaXBZID0gZmFsc2U7XG4gICAgICB0aGlzLnVucGFja0FsaWdubWVudCA9IDE7XG4gICAgICB0aGlzLmNvbG9yU3BhY2UgPSBHTF9CUk9XU0VSX0RFRkFVTFRfV0VCR0w7XG5cbiAgICAgIC8vIHNoYXBlIGluZm9cbiAgICAgIHRoaXMud2lkdGggPSAwO1xuICAgICAgdGhpcy5oZWlnaHQgPSAwO1xuICAgICAgdGhpcy5jaGFubmVscyA9IDA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNvcHlGbGFncyhyZXN1bHQsIG90aGVyKSB7XG4gICAgICByZXN1bHQuaW50ZXJuYWxmb3JtYXQgPSBvdGhlci5pbnRlcm5hbGZvcm1hdDtcbiAgICAgIHJlc3VsdC5mb3JtYXQgPSBvdGhlci5mb3JtYXQ7XG4gICAgICByZXN1bHQudHlwZSA9IG90aGVyLnR5cGU7XG4gICAgICByZXN1bHQuY29tcHJlc3NlZCA9IG90aGVyLmNvbXByZXNzZWQ7XG4gICAgICByZXN1bHQucHJlbXVsdGlwbHlBbHBoYSA9IG90aGVyLnByZW11bHRpcGx5QWxwaGE7XG4gICAgICByZXN1bHQuZmxpcFkgPSBvdGhlci5mbGlwWTtcbiAgICAgIHJlc3VsdC51bnBhY2tBbGlnbm1lbnQgPSBvdGhlci51bnBhY2tBbGlnbm1lbnQ7XG4gICAgICByZXN1bHQuY29sb3JTcGFjZSA9IG90aGVyLmNvbG9yU3BhY2U7XG4gICAgICByZXN1bHQud2lkdGggPSBvdGhlci53aWR0aDtcbiAgICAgIHJlc3VsdC5oZWlnaHQgPSBvdGhlci5oZWlnaHQ7XG4gICAgICByZXN1bHQuY2hhbm5lbHMgPSBvdGhlci5jaGFubmVscztcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VGbGFncyhmbGFncywgb3B0aW9ucykge1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zICE9PSAnb2JqZWN0JyB8fCAhb3B0aW9ucykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoJ3ByZW11bHRpcGx5QWxwaGEnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgY2hlY2skMS50eXBlKG9wdGlvbnMucHJlbXVsdGlwbHlBbHBoYSwgJ2Jvb2xlYW4nLCAnaW52YWxpZCBwcmVtdWx0aXBseUFscGhhJyk7XG4gICAgICAgIGZsYWdzLnByZW11bHRpcGx5QWxwaGEgPSBvcHRpb25zLnByZW11bHRpcGx5QWxwaGE7XG4gICAgICB9XG4gICAgICBpZiAoJ2ZsaXBZJyBpbiBvcHRpb25zKSB7XG4gICAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLmZsaXBZLCAnYm9vbGVhbicsICdpbnZhbGlkIHRleHR1cmUgZmxpcCcpO1xuICAgICAgICBmbGFncy5mbGlwWSA9IG9wdGlvbnMuZmxpcFk7XG4gICAgICB9XG4gICAgICBpZiAoJ2FsaWdubWVudCcgaW4gb3B0aW9ucykge1xuICAgICAgICBjaGVjayQxLm9uZU9mKG9wdGlvbnMuYWxpZ25tZW50LCBbMSwgMiwgNCwgOF0sICdpbnZhbGlkIHRleHR1cmUgdW5wYWNrIGFsaWdubWVudCcpO1xuICAgICAgICBmbGFncy51bnBhY2tBbGlnbm1lbnQgPSBvcHRpb25zLmFsaWdubWVudDtcbiAgICAgIH1cbiAgICAgIGlmICgnY29sb3JTcGFjZScgaW4gb3B0aW9ucykge1xuICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLmNvbG9yU3BhY2UsIGNvbG9yU3BhY2UsICdpbnZhbGlkIGNvbG9yU3BhY2UnKTtcbiAgICAgICAgZmxhZ3MuY29sb3JTcGFjZSA9IGNvbG9yU3BhY2Vbb3B0aW9ucy5jb2xvclNwYWNlXTtcbiAgICAgIH1cbiAgICAgIGlmICgndHlwZScgaW4gb3B0aW9ucykge1xuICAgICAgICB2Y
1XIgdHlwZSA9IG9wdGlvbnMudHlwZTtcbiAgICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0IHx8ICEodHlwZSA9PT0gJ2Zsb2F0JyB8fCB0eXBlID09PSAnZmxvYXQzMicpLCAneW91IG11c3QgZW5hYmxlIHRoZSBPRVNfdGV4dHVyZV9mbG9hdCBleHRlbnNpb24gaW4gb3JkZXIgdG8gdXNlIGZsb2F0aW5nIHBvaW50IHRleHR1cmVzLicpO1xuICAgICAgICBjaGVjayQxKGV4dGVuc2lvbnMub2VzX3RleHR1cmVfaGFsZl9mbG9hdCB8fCAhKHR5cGUgPT09ICdoYWxmIGZsb2F0JyB8fCB0eXBlID09PSAnZmxvYXQxNicpLCAneW91IG11c3QgZW5hYmxlIHRoZSBPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0IGV4dGVuc2lvbiBpbiBvcmRlciB0byB1c2UgMTYtYml0IGZsb2F0aW5nIHBvaW50IHRleHR1cmVzLicpO1xuICAgICAgICBjaGVjayQxKGV4dGVuc2lvbnMud2ViZ2xfZGVwdGhfdGV4dHVyZSB8fCAhKHR5cGUgPT09ICd1aW50MTYnIHx8IHR5cGUgPT09ICd1aW50MzInIHx8IHR5cGUgPT09ICdkZXB0aCBzdGVuY2lsJyksICd5b3UgbXVzdCBlbmFibGUgdGhlIFdFQkdMX2RlcHRoX3RleHR1cmUgZXh0ZW5zaW9uIGluIG9yZGVyIHRvIHVzZSBkZXB0aC9zdGVuY2lsIHRleHR1cmVzLicpO1xuICAgICAgICBjaGVjayQxLnBhcmFtZXRlcih0eXBlLCB0ZXh0dXJlVHlwZXMsICdpbnZhbGlkIHRleHR1cmUgdHlwZScpO1xuICAgICAgICBmbGFncy50eXBlID0gdGV4dHVyZVR5cGVzW3R5cGVdO1xuICAgICAgfVxuICAgICAgdmFyIHcgPSBmbGFncy53aWR0aDtcbiAgICAgIHZhciBoID0gZmxhZ3MuaGVpZ2h0O1xuICAgICAgdmFyIGMgPSBmbGFncy5jaGFubmVscztcbiAgICAgIHZhciBoYXNDaGFubmVscyA9IGZhbHNlO1xuICAgICAgaWYgKCdzaGFwZScgaW4gb3B0aW9ucykge1xuICAgICAgICBjaGVjayQxKEFycmF5LmlzQXJyYXkob3B0aW9ucy5zaGFwZSkgJiYgb3B0aW9ucy5zaGFwZS5sZW5ndGggPj0gMiwgJ3NoYXBlIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgICAgICAgdyA9IG9wdGlvbnMuc2hhcGVbMF07XG4gICAgICAgIGggPSBvcHRpb25zLnNoYXBlWzFdO1xuICAgICAgICBpZiAob3B0aW9ucy5zaGFwZS5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBjID0gb3B0aW9ucy5zaGFwZVsyXTtcbiAgICAgICAgICBjaGVjayQxKGMgPiAwICYmIGMgPD0gNCwgJ2ludmFsaWQgbnVtYmVyIG9mIGNoYW5uZWxzJyk7XG4gICAgICAgICAgaGFzQ2hhbm5lbHMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoZWNrJDEodyA+PSAwICYmIHcgPD0gbGltaXRzLm1heFRleHR1cmVTaXplLCAnaW52YWxpZCB3aWR0aCcpO1xuICAgICAgICBjaGVjayQxKGggPj0gMCAmJiBoIDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgaGVpZ2h0Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoJ3JhZGl1cycgaW4gb3B0aW9ucykge1xuICAgICAgICAgIHcgPSBoID0gb3B0aW9ucy5yYWRpdXM7XG4gICAgICAgICAgY2hlY2skMSh3ID49IDAgJiYgdyA8PSBsaW1pdHMubWF4VGV4dHVyZVNpemUsICdpbnZhbGlkIHJhZGl1cycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnd2lkdGgnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICB3ID0gb3B0aW9ucy53aWR0aDtcbiAgICAgICAgICBjaGVjayQxKHcgPj0gMCAmJiB3IDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgd2lkdGgnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2hlaWdodCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgIGggPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgICBjaGVjayQxKGggPj0gMCAmJiBoIDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgaGVpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdjaGFubmVscycgaW4gb3B0aW9ucykge1xuICAgICAgICAgIGMgPSBvcHRpb25zLmNoYW5uZWxzO1xuICAgICAgICAgIGNoZWNrJDEoYyA+IDAgJiYgYyA8PSA0LCAnaW52YWxpZCBudW1iZXIgb2YgY2hhbm5lbHMnKTtcbiAgICAgICAgICBoYXNDaGFubmVscyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZsYWdzLndpZHRoID0gdyB8IDA7XG4gICAgICBmbGFncy5oZWlnaHQgPSBoIHwgMDtcbiAgICAgIGZsYWdzLmNoYW5uZWxzID0gYyB8IDA7XG4gICAgICB2Y
1XIgaGFzRm9ybWF0ID0gZmFsc2U7XG4gICAgICBpZiAoJ2Zvcm1hdCcgaW4gb3B0aW9ucykge1xuICAgICAgICB2YXIgZm9ybWF0U3RyID0gb3B0aW9ucy5mb3JtYXQ7XG4gICAgICAgIGNoZWNrJDEoZXh0ZW5zaW9ucy53ZWJnbF9kZXB0aF90ZXh0dXJlIHx8ICEoZm9ybWF0U3RyID09PSAnZGVwdGgnIHx8IGZvcm1hdFN0ciA9PT0gJ2RlcHRoIHN0ZW5jaWwnKSwgJ3lvdSBtdXN0IGVuYWJsZSB0aGUgV0VCR0xfZGVwdGhfdGV4dHVyZSBleHRlbnNpb24gaW4gb3JkZXIgdG8gdXNlIGRlcHRoL3N0ZW5jaWwgdGV4dHVyZXMuJyk7XG4gICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKGZvcm1hdFN0ciwgdGV4dHVyZUZvcm1hdHMsICdpbnZhbGlkIHRleHR1cmUgZm9ybWF0Jyk7XG4gICAgICAgIHZhciBpbnRlcm5hbGZvcm1hdCA9IGZsYWdzLmludGVybmFsZm9ybWF0ID0gdGV4dHVyZUZvcm1hdHNbZm9ybWF0U3RyXTtcbiAgICAgICAgZmxhZ3MuZm9ybWF0ID0gY29sb3JGb3JtYXRzW2ludGVybmFsZm9ybWF0XTtcbiAgICAgICAgaWYgKGZvcm1hdFN0ciBpbiB0ZXh0dXJlVHlwZXMpIHtcbiAgICAgICAgICBpZiAoISgndHlwZScgaW4gb3B0aW9ucykpIHtcbiAgICAgICAgICAgIGZsYWdzLnR5cGUgPSB0ZXh0dXJlVHlwZXNbZm9ybWF0U3RyXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdFN0ciBpbiBjb21wcmVzc2VkVGV4dHVyZUZvcm1hdHMpIHtcbiAgICAgICAgICBmbGFncy5jb21wcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBoYXNGb3JtYXQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWNvbmNpbGUgY2hhbm5lbHMgYW5kIGZvcm1hdFxuICAgICAgaWYgKCFoYXNDaGFubmVscyAmJiBoYXNGb3JtYXQpIHtcbiAgICAgICAgZmxhZ3MuY2hhbm5lbHMgPSBGT1JNQVRfQ0hBTk5FTFNbZmxhZ3MuZm9ybWF0XTtcbiAgICAgIH0gZWxzZSBpZiAoaGFzQ2hhbm5lbHMgJiYgIWhhc0Zvcm1hdCkge1xuICAgICAgICBpZiAoZmxhZ3MuY2hhbm5lbHMgIT09IENIQU5ORUxTX0ZPUk1BVFtmbGFncy5mb3JtYXRdKSB7XG4gICAgICAgICAgZmxhZ3MuZm9ybWF0ID0gZmxhZ3MuaW50ZXJuYWxmb3JtYXQgPSBDSEFOTkVMU19GT1JNQVRbZmxhZ3MuY2hhbm5lbHNdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGhhc0Zvcm1hdCAmJiBoYXNDaGFubmVscykge1xuICAgICAgICBjaGVjayQxKGZsYWdzLmNoYW5uZWxzID09PSBGT1JNQVRfQ0hBTk5FTFNbZmxhZ3MuZm9ybWF0XSwgJ251bWJlciBvZiBjaGFubmVscyBpbmNvbnNpc3RlbnQgd2l0aCBzcGVjaWZpZWQgZm9ybWF0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNldEZsYWdzKGZsYWdzKSB7XG4gICAgICBnbC5waXhlbFN0b3JlaShHTF9VTlBBQ0tfRkxJUF9ZX1dFQkdMLCBmbGFncy5mbGlwWSk7XG4gICAgICBnbC5waXhlbFN0b3JlaShHTF9VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsIGZsYWdzLnByZW11bHRpcGx5QWxwaGEpO1xuICAgICAgZ2wucGl4ZWxTdG9yZWkoR0xfVU5QQUNLX0NPTE9SU1BBQ0VfQ09OVkVSU0lPTl9XRUJHTCwgZmxhZ3MuY29sb3JTcGFjZSk7XG4gICAgICBnbC5waXhlbFN0b3JlaShHTF9VTlBBQ0tfQUxJR05NRU5ULCBmbGFncy51bnBhY2tBbGlnbm1lbnQpO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBUZXggaW1hZ2UgZGF0YVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBmdW5jdGlvbiBUZXhJbWFnZSgpIHtcbiAgICAgIFRleEZsYWdzLmNhbGwodGhpcyk7XG4gICAgICB0aGlzLnhPZmZzZXQgPSAwO1xuICAgICAgdGhpcy55T2Zmc2V0ID0gMDtcblxuICAgICAgLy8gZGF0YVxuICAgICAgdGhpcy5kYXRhID0gbnVsbDtcbiAgICAgIHRoaXMubmVlZHNGcmVlID0gZmFsc2U7XG5cbiAgICAgIC8vIGh0bWwgZWxlbWVudFxuICAgICAgdGhpcy5lbGVtZW50ID0gbnVsbDtcblxuICAgICAgLy8gY29weVRleEltYWdlIGluZm9cbiAgICAgIHRoaXMubmVlZHNDb3B5ID0gZmFsc2U7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBhcnNlSW1hZ2UoaW1hZ2UsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBkYXRhID0gbnVsbDtcbiAgICAgIGlmIChpc1BpeGVsRGF0YShvcHRpb25zKSkge1xuICAgICAgICBkYXRhID0gb3B0aW9ucztcbiAgICAgIH0gZWxzZSBpZiAob3B0aW9ucykge1xuICAgICAgICBjaGVjayQxLnR5cGUob3B0aW9ucywgJ29iamVjdCcsICdpbnZhbGlkIHBpeGVsIGRhdGEgdHlwZScpO1xuICAgICAgICBwYXJzZUZsYWdzKGltYWdlLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKCd4JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgaW1hZ2UueE9mZnNldCA9IG9wdGlvbnMueCB8IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCd5JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgaW1hZ2UueU9mZnNldCA9IG9wdGlvbnMueSB8IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzUGl4ZWxEYXRhKG9wdGlvbnMuZGF0YSkpIHtcbiAgICAgICAgICBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjaGVjayQxKCFpbWFnZS5jb21wcmVzc2VkIHx8IGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5LCAnY29tcHJlc3NlZCB0ZXh0dXJlIGRhdGEgbXVzdCBiZSBzdG9yZWQgaW4gYSB1aW50OGFycmF5Jyk7XG4gICAgICBpZiAob3B0aW9ucy5jb3B5KSB7XG4gICAgICAgIGNoZWNrJDEoIWRhdGEsICdjYW4gbm90IHNwZWNpZnkgY29weSBhbmQgZGF0YSBmaWVsZCBmb3IgdGhlIHNhbWUgdGV4dHVyZScpO1xuICAgICAgICB2Y
1XIgdmlld1cgPSBjb250ZXh0U3RhdGUudmlld3BvcnRXaWR0aDtcbiAgICAgICAgdmFyIHZpZXdIID0gY29udGV4dFN0YXRlLnZpZXdwb3J0SGVpZ2h0O1xuICAgICAgICBpbWFnZS53aWR0aCA9IGltYWdlLndpZHRoIHx8IHZpZXdXIC0gaW1hZ2UueE9mZnNldDtcbiAgICAgICAgaW1hZ2UuaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0IHx8IHZpZXdIIC0gaW1hZ2UueU9mZnNldDtcbiAgICAgICAgaW1hZ2UubmVlZHNDb3B5ID0gdHJ1ZTtcbiAgICAgICAgY2hlY2skMShpbWFnZS54T2Zmc2V0ID49IDAgJiYgaW1hZ2UueE9mZnNldCA8IHZpZXdXICYmIGltYWdlLnlPZmZzZXQgPj0gMCAmJiBpbWFnZS55T2Zmc2V0IDwgdmlld0ggJiYgaW1hZ2Uud2lkdGggPiAwICYmIGltYWdlLndpZHRoIDw9IHZpZXdXICYmIGltYWdlLmhlaWdodCA+IDAgJiYgaW1hZ2UuaGVpZ2h0IDw9IHZpZXdILCAnY29weSB0ZXh0dXJlIHJlYWQgb3V0IG9mIGJvdW5kcycpO1xuICAgICAgfSBlbHNlIGlmICghZGF0YSkge1xuICAgICAgICBpbWFnZS53aWR0aCA9IGltYWdlLndpZHRoIHx8IDE7XG4gICAgICAgIGltYWdlLmhlaWdodCA9IGltYWdlLmhlaWdodCB8fCAxO1xuICAgICAgICBpbWFnZS5jaGFubmVscyA9IGltYWdlLmNoYW5uZWxzIHx8IDQ7XG4gICAgICB9IGVsc2UgaWYgKGlzVHlwZWRBcnJheShkYXRhKSkge1xuICAgICAgICBpbWFnZS5jaGFubmVscyA9IGltYWdlLmNoYW5uZWxzIHx8IDQ7XG4gICAgICAgIGltYWdlLmRhdGEgPSBkYXRhO1xuICAgICAgICBpZiAoISgndHlwZScgaW4gb3B0aW9ucykgJiYgaW1hZ2UudHlwZSA9PT0gR0xfVU5TSUdORURfQllURSQ1KSB7XG4gICAgICAgICAgaW1hZ2UudHlwZSA9IHR5cGVkQXJyYXlDb2RlJDEoZGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoaXNOdW1lcmljQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgaW1hZ2UuY2hhbm5lbHMgPSBpbWFnZS5jaGFubmVscyB8fCA0O1xuICAgICAgICBjb252ZXJ0RGF0YShpbWFnZSwgZGF0YSk7XG4gICAgICAgIGltYWdlLmFsaWdubWVudCA9IDE7XG4gICAgICAgIGltYWdlLm5lZWRzRnJlZSA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGlzTkRBcnJheUxpa2UoZGF0YSkpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gZGF0YS5kYXRhO1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyYXkpICYmIGltYWdlLnR5cGUgPT09IEdMX1VOU0lHTkVEX0JZVEUkNSkge1xuICAgICAgICAgIGltYWdlLnR5cGUgPSB0eXBlZEFycmF5Q29kZSQxKGFycmF5KTtcbiAgICAgICAgfVxuICAgICAgICB2Y
1XIgc2hhcGUgPSBkYXRhLnNoYXBlO1xuICAgICAgICB2YXIgc3RyaWRlID0gZGF0YS5zdHJpZGU7XG4gICAgICAgIHZhciBzaGFwZVgsIHNoYXBlWSwgc2hhcGVDLCBzdHJpZGVYLCBzdHJpZGVZLCBzdHJpZGVDO1xuICAgICAgICBpZiAoc2hhcGUubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgc2hhcGVDID0gc2hhcGVbMl07XG4gICAgICAgICAgc3RyaWRlQyA9IHN0cmlkZVsyXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxKHNoYXBlLmxlbmd0aCA9PT0gMiwgJ2ludmFsaWQgbmRhcnJheSBwaXhlbCBkYXRhLCBtdXN0IGJlIDIgb3IgM0QnKTtcbiAgICAgICAgICBzaGFwZUMgPSAxO1xuICAgICAgICAgIHN0cmlkZUMgPSAxO1xuICAgICAgICB9XG4gICAgICAgIHNoYXBlWCA9IHNoYXBlWzBdO1xuICAgICAgICBzaGFwZVkgPSBzaGFwZVsxXTtcbiAgICAgICAgc3RyaWRlWCA9IHN0cmlkZVswXTtcbiAgICAgICAgc3RyaWRlWSA9IHN0cmlkZVsxXTtcbiAgICAgICAgaW1hZ2UuYWxpZ25tZW50ID0gMTtcbiAgICAgICAgaW1hZ2Uud2lkdGggPSBzaGFwZVg7XG4gICAgICAgIGltYWdlLmhlaWdodCA9IHNoYXBlWTtcbiAgICAgICAgaW1hZ2UuY2hhbm5lbHMgPSBzaGFwZUM7XG4gICAgICAgIGltYWdlLmZvcm1hdCA9IGltYWdlLmludGVybmFsZm9ybWF0ID0gQ0hBTk5FTFNfRk9STUFUW3NoYXBlQ107XG4gICAgICAgIGltYWdlLm5lZWRzRnJlZSA9IHRydWU7XG4gICAgICAgIHRyYW5zcG9zZURhdGEoaW1hZ2UsIGFycmF5LCBzdHJpZGVYLCBzdHJpZGVZLCBzdHJpZGVDLCBkYXRhLm9mZnNldCk7XG4gICAgICB9IGVsc2UgaWYgKGlzQ2FudmFzRWxlbWVudChkYXRhKSB8fCBpc09mZnNjcmVlbkNhbnZhcyhkYXRhKSB8fCBpc0NvbnRleHQyRChkYXRhKSkge1xuICAgICAgICBpZiAoaXNDYW52YXNFbGVtZW50KGRhdGEpIHx8IGlzT2Zmc2NyZWVuQ2FudmFzKGRhdGEpKSB7XG4gICAgICAgICAgaW1hZ2UuZWxlbWVudCA9IGRhdGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW1hZ2UuZWxlbWVudCA9IGRhdGEuY2FudmFzO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlLndpZHRoID0gaW1hZ2UuZWxlbWVudC53aWR0aDtcbiAgICAgICAgaW1hZ2UuaGVpZ2h0ID0gaW1hZ2UuZWxlbWVudC5oZWlnaHQ7XG4gICAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICAgIH0gZWxzZSBpZiAoaXNCaXRtYXAoZGF0YSkpIHtcbiAgICAgICAgaW1hZ2UuZWxlbWVudCA9IGRhdGE7XG4gICAgICAgIGltYWdlLndpZHRoID0gZGF0YS53aWR0aDtcbiAgICAgICAgaW1hZ2UuaGVpZ2h0ID0gZGF0YS5oZWlnaHQ7XG4gICAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICAgIH0gZWxzZSBpZiAoaXNJbWFnZUVsZW1lbnQoZGF0YSkpIHtcbiAgICAgICAgaW1hZ2UuZWxlbWVudCA9IGRhdGE7XG4gICAgICAgIGltYWdlLndpZHRoID0gZGF0YS5uYXR1cmFsV2lkdGg7XG4gICAgICAgIGltYWdlLmhlaWdodCA9IGRhdGEubmF0dXJhbEhlaWdodDtcbiAgICAgICAgaW1hZ2UuY2hhbm5lbHMgPSA0O1xuICAgICAgfSBlbHNlIGlmIChpc1ZpZGVvRWxlbWVudChkYXRhKSkge1xuICAgICAgICBpbWFnZS5lbGVtZW50ID0gZGF0YTtcbiAgICAgICAgaW1hZ2Uud2lkdGggPSBkYXRhLnZpZGVvV2lkdGg7XG4gICAgICAgIGltYWdlLmhlaWdodCA9IGRhdGEudmlkZW9IZWlnaHQ7XG4gICAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICAgIH0gZWxzZSBpZiAoaXNSZWN0QXJyYXkoZGF0YSkpIHtcbiAgICAgICAgdmFyIHcgPSBpbWFnZS53aWR0aCB8fCBkYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgdmFyIGggPSBpbWFnZS5oZWlnaHQgfHwgZGF0YS5sZW5ndGg7XG4gICAgICAgIHZhciBjID0gaW1hZ2UuY2hhbm5lbHM7XG4gICAgICAgIGlmIChpc0FycmF5TGlrZShkYXRhWzBdWzBdKSkge1xuICAgICAgICAgIGMgPSBjIHx8IGRhdGFbMF1bMF0ubGVuZ3RoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGMgPSBjIHx8IDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFycmF5U2hhcGUgPSBmbGF0dGVuVXRpbHMuc2hhcGUoZGF0YSk7XG4gICAgICAgIHZhciBuID0gMTtcbiAgICAgICAgZm9yICh2YXIgZGQgPSAwOyBkZCA8IGFycmF5U2hhcGUubGVuZ3RoOyArK2RkKSB7XG4gICAgICAgICAgbiAqPSBhcnJheVNoYXBlW2RkXTtcbiAgICAgICAgfVxuICAgICAgICB2Y
1XIgYWxsb2NEYXRhID0gcHJlQ29udmVydChpbWFnZSwgbik7XG4gICAgICAgIGZsYXR0ZW5VdGlscy5mbGF0dGVuKGRhdGEsIGFycmF5U2hhcGUsICcnLCBhbGxvY0RhdGEpO1xuICAgICAgICBwb3N0Q29udmVydChpbWFnZSwgYWxsb2NEYXRhKTtcbiAgICAgICAgaW1hZ2UuYWxpZ25tZW50ID0gMTtcbiAgICAgICAgaW1hZ2Uud2lkdGggPSB3O1xuICAgICAgICBpbWFnZS5oZWlnaHQgPSBoO1xuICAgICAgICBpbWFnZS5jaGFubmVscyA9IGM7XG4gICAgICAgIGltYWdlLmZvcm1hdCA9IGltYWdlLmludGVybmFsZm9ybWF0ID0gQ0hBTk5FTFNfRk9STUFUW2NdO1xuICAgICAgICBpbWFnZS5uZWVkc0ZyZWUgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKGltYWdlLnR5cGUgPT09IEdMX0ZMT0FUJDQpIHtcbiAgICAgICAgY2hlY2skMShsaW1pdHMuZXh0ZW5zaW9ucy5pbmRleE9mKCdvZXNfdGV4dHVyZV9mbG9hdCcpID49IDAsICdvZXNfdGV4dHVyZV9mbG9hdCBleHRlbnNpb24gbm90IGVuYWJsZWQnKTtcbiAgICAgIH0gZWxzZSBpZiAoaW1hZ2UudHlwZSA9PT0gR0xfSEFMRl9GTE9BVF9PRVMkMSkge1xuICAgICAgICBjaGVjayQxKGxpbWl0cy5leHRlbnNpb25zLmluZGV4T2YoJ29lc190ZXh0dXJlX2hhbGZfZmxvYXQnKSA+PSAwLCAnb2VzX3RleHR1cmVfaGFsZl9mbG9hdCBleHRlbnNpb24gbm90IGVuYWJsZWQnKTtcbiAgICAgIH1cblxuICAgICAgLy8gZG8gY29tcHJlc3NlZCB0ZXh0dXJlICB2YWxpZGF0aW9uIGhlcmUuXG4gICAgfVxuICAgIGZ1bmN0aW9uIHNldEltYWdlKGluZm8sIHRhcmdldCwgbWlwbGV2ZWwpIHtcbiAgICAgIHZhciBlbGVtZW50ID0gaW5mby5lbGVtZW50O1xuICAgICAgdmFyIGRhdGEgPSBpbmZvLmRhdGE7XG4gICAgICB2Y
1XIgaW50ZXJuYWxmb3JtYXQgPSBpbmZvLmludGVybmFsZm9ybWF0O1xuICAgICAgdmFyIGZvcm1hdCA9IGluZm8uZm9ybWF0O1xuICAgICAgdmFyIHR5cGUgPSBpbmZvLnR5cGU7XG4gICAgICB2YXIgd2lkdGggPSBpbmZvLndpZHRoO1xuICAgICAgdmFyIGhlaWdodCA9IGluZm8uaGVpZ2h0O1xuICAgICAgc2V0RmxhZ3MoaW5mbyk7XG4gICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICBnbC50ZXhJbWFnZTJEKHRhcmdldCwgbWlwbGV2ZWwsIGZvcm1hdCwgZm9ybWF0LCB0eXBlLCBlbGVtZW50KTtcbiAgICAgIH0gZWxzZSBpZiAoaW5mby5jb21wcmVzc2VkKSB7XG4gICAgICAgIGdsLmNvbXByZXNzZWRUZXhJbWFnZTJEKHRhcmdldCwgbWlwbGV2ZWwsIGludGVybmFsZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCAwLCBkYXRhKTtcbiAgICAgIH0gZWxzZSBpZiAoaW5mby5uZWVkc0NvcHkpIHtcbiAgICAgICAgcmVnbFBvbGwoKTtcbiAgICAgICAgZ2wuY29weVRleEltYWdlMkQodGFyZ2V0LCBtaXBsZXZlbCwgZm9ybWF0LCBpbmZvLnhPZmZzZXQsIGluZm8ueU9mZnNldCwgd2lkdGgsIGhlaWdodCwgMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbC50ZXhJbWFnZTJEKHRhcmdldCwgbWlwbGV2ZWwsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgMCwgZm9ybWF0LCB0eXBlLCBkYXRhIHx8IG51bGwpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBzZXRTdWJJbWFnZShpbmZvLCB0YXJnZXQsIHgsIHksIG1pcGxldmVsKSB7XG4gICAgICB2YXIgZWxlbWVudCA9IGluZm8uZWxlbWVudDtcbiAgICAgIHZhciBkYXRhID0gaW5mby5kYXRhO1xuICAgICAgdmFyIGludGVybmFsZm9ybWF0ID0gaW5mby5pbnRlcm5hbGZvcm1hdDtcbiAgICAgIHZhciBmb3JtYXQgPSBpbmZvLmZvcm1hdDtcbiAgICAgIHZhciB0eXBlID0gaW5mby50eXBlO1xuICAgICAgdmFyIHdpZHRoID0gaW5mby53aWR0aDtcbiAgICAgIHZhciBoZWlnaHQgPSBpbmZvLmhlaWdodDtcbiAgICAgIHNldEZsYWdzKGluZm8pO1xuICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRCh0YXJnZXQsIG1pcGxldmVsLCB4LCB5LCBmb3JtYXQsIHR5cGUsIGVsZW1lbnQpO1xuICAgICAgfSBlbHNlIGlmIChpbmZvLmNvbXByZXNzZWQpIHtcbiAgICAgICAgZ2wuY29tcHJlc3NlZFRleFN1YkltYWdlMkQodGFyZ2V0LCBtaXBsZXZlbCwgeCwgeSwgaW50ZXJuYWxmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIGRhdGEpO1xuICAgICAgfSBlbHNlIGlmIChpbmZvLm5lZWRzQ29weSkge1xuICAgICAgICByZWdsUG9sbCgpO1xuICAgICAgICBnbC5jb3B5VGV4U3ViSW1hZ2UyRCh0YXJnZXQsIG1pcGxldmVsLCB4LCB5LCBpbmZvLnhPZmZzZXQsIGluZm8ueU9mZnNldCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKHRhcmdldCwgbWlwbGV2ZWwsIHgsIHksIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSwgZGF0YSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGV4SW1hZ2UgcG9vbFxuICAgIHZhciBpbWFnZVBvb2wgPSBbXTtcbiAgICBmdW5jdGlvbiBhbGxvY0ltYWdlKCkge1xuICAgICAgcmV0dXJuIGltYWdlUG9vbC5wb3AoKSB8fCBuZXcgVGV4SW1hZ2UoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZnJlZUltYWdlKGltYWdlKSB7XG4gICAgICBpZiAoaW1hZ2UubmVlZHNGcmVlKSB7XG4gICAgICAgIHBvb2wuZnJlZVR5cGUoaW1hZ2UuZGF0YSk7XG4gICAgICB9XG4gICAgICBUZXhJbWFnZS5jYWxsKGltYWdlKTtcbiAgICAgIGltYWdlUG9vbC5wdXNoKGltYWdlKTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gTWlwIG1hcFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBmdW5jdGlvbiBNaXBNYXAoKSB7XG4gICAgICBUZXhGbGFncy5jYWxsKHRoaXMpO1xuICAgICAgdGhpcy5nZW5NaXBtYXBzID0gZmFsc2U7XG4gICAgICB0aGlzLm1pcG1hcEhpbnQgPSBHTF9ET05UX0NBUkU7XG4gICAgICB0aGlzLm1pcG1hc2sgPSAwO1xuICAgICAgdGhpcy5pbWFnZXMgPSBBcnJheSgxNik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBhcnNlTWlwTWFwRnJvbVNoYXBlKG1pcG1hcCwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgdmFyIGltZyA9IG1pcG1hcC5pbWFnZXNbMF0gPSBhbGxvY0ltYWdlKCk7XG4gICAgICBtaXBtYXAubWlwbWFzayA9IDE7XG4gICAgICBpbWcud2lkdGggPSBtaXBtYXAud2lkdGggPSB3aWR0aDtcbiAgICAgIGltZy5oZWlnaHQgPSBtaXBtYXAuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgaW1nLmNoYW5uZWxzID0gbWlwbWFwLmNoYW5uZWxzID0gNDtcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VNaXBNYXBGcm9tT2JqZWN0KG1pcG1hcCwgb3B0aW9ucykge1xuICAgICAgdmFyIGltZ0RhdGEgPSBudWxsO1xuICAgICAgaWYgKGlzUGl4ZWxEYXRhKG9wdGlvbnMpKSB7XG4gICAgICAgIGltZ0RhdGEgPSBtaXBtYXAuaW1hZ2VzWzBdID0gYWxsb2NJbWFnZSgpO1xuICAgICAgICBjb3B5
1RmxhZ3MoaW1nRGF0YSwgbWlwbWFwKTtcbiAgICAgICAgcGFyc2VJbWFnZShpbWdEYXRhLCBvcHRpb25zKTtcbiAgICAgICAgbWlwbWFwLm1pcG1hc2sgPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyc2VGbGFncyhtaXBtYXAsIG9wdGlvbnMpO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zLm1pcG1hcCkpIHtcbiAgICAgICAgICB2YXIgbWlwRGF0YSA9IG9wdGlvbnMubWlwbWFwO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWlwRGF0YS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaW1nRGF0YSA9IG1pcG1hcC5pbWFnZXNbaV0gPSBhbGxvY0ltYWdlKCk7XG4gICAgICAgICAgICBjb3B5RmxhZ3MoaW1nRGF0YSwgbWlwbWFwKTtcbiAgICAgICAgICAgIGltZ0RhdGEud2lkdGggPj49IGk7XG4gICAgICAgICAgICBpbWdEYXRhLmhlaWdodCA+Pj0gaTtcbiAgICAgICAgICAgIHBhcnNlSW1hZ2UoaW1nRGF0YSwgbWlwRGF0YVtpXSk7XG4gICAgICAgICAgICBtaXBtYXAubWlwbWFzayB8PSAxIDw8IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGltZ0RhdGEgPSBtaXBtYXAuaW1hZ2VzWzBdID0gYWxsb2NJbWFnZSgpO1xuICAgICAgICAgIGNvcHlGbGFncyhpbWdEYXRhLCBtaXBtYXApO1xuICAgICAgICAgIHBhcnNlSW1hZ2UoaW1nRGF0YSwgb3B0aW9ucyk7XG4gICAgICAgICAgbWlwbWFwLm1pcG1hc2sgPSAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb3B5RmxhZ3MobWlwbWFwLCBtaXBtYXAuaW1hZ2VzWzBdKTtcblxuICAgICAgLy8gRm9yIHRleHR1cmVzIG9mIHRoZSBjb21wcmVzc2VkIGZvcm1hdCBXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Y1xuICAgICAgLy8gd2UgbXVzdCBoYXZlIHRoYXRcbiAgICAgIC8vXG4gICAgICAvLyBcIldoZW4gbGV2ZWwgZXF1YWxzIHplcm8gd2lkdGggYW5kIGhlaWdodCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNC5cbiAgICAgIC8vIFdoZW4gbGV2ZWwgaXMgZ3JlYXRlciB0aGFuIDAgd2lkdGggYW5kIGhlaWdodCBtdXN0IGJlIDAsIDEsIDIgb3IgYSBtdWx0aXBsZSBvZiA0LiBcIlxuICAgICAgLy9cbiAgICAgIC8vIGJ1dCB3ZSBkbyBub3QgeWV0IHN1cHBvcnQgaGF2aW5nIG11bHRpcGxlIG1pcG1hcCBsZXZlbHMgZm9yIGNvbXByZXNzZWQgdGV4dHVyZXMsXG4gICAgICAvLyBzbyB3ZSBvbmx5IHRlc3QgZm9yIGxldmVsIHplcm8uXG5cbiAgICAgIGlmIChtaXBtYXAuY29tcHJlc3NlZCAmJiAobWlwbWFwLmludGVybmFsZm9ybWF0ID09PSBHTF9DT01QUkVTU0VEX1JHQl9TM1RDX0RYVDFfRVhUIHx8IG1pcG1hcC5pbnRlcm5hbGZvcm1hdCA9PT0gR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUMV9FWFQgfHwgbWlwbWFwLmludGVybmFsZm9ybWF0ID09PSBHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQzX0VYVCB8fCBtaXBtYXAuaW50ZXJuYWxmb3JtYXQgPT09IEdMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDVfRVhUKSkge1xuICAgICAgICBjaGVjayQxKG1pcG1hcC53aWR0aCAlIDQgPT09IDAgJiYgbWlwbWFwLmhlaWdodCAlIDQgPT09IDAsICdmb3IgY29tcHJlc3NlZCB0ZXh0dXJlIGZvcm1hdHMsIG1pcG1hcCBsZXZlbCAwIG11c3QgaGF2ZSB3aWR0aCBhbmQgaGVpZ2h0IHRoYXQgYXJlIGEgbXVsdGlwbGUgb2YgNCcpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBzZXRNaXBNYXAobWlwbWFwLCB0YXJnZXQpIHtcbiAgICAgIHZhciBpbWFnZXMgPSBtaXBtYXAuaW1hZ2VzO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKCFpbWFnZXNbaV0pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2V0SW1hZ2UoaW1hZ2VzW2ldLCB0YXJnZXQsIGkpO1xuICAgICAgfVxuICAgIH1cbiAgICB2YXIgbWlwUG9vbCA9IFtdO1xuICAgIGZ1bmN0aW9uIGFsbG9jTWlwTWFwKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IG1pcFBvb2wucG9wKCkgfHwgbmV3IE1pcE1hcCgpO1xuICAgICAgVGV4RmxhZ3MuY2FsbChyZXN1bHQpO1xuICAgICAgcmVzdWx0Lm1pcG1hc2sgPSAwO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgKytpKSB7XG4gICAgICAgIHJlc3VsdC5pbWFnZXNbaV0gPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gZnJlZU1pcE1hcChtaXBtYXApIHtcbiAgICAgIHZhciBpbWFnZXMgPSBtaXBtYXAuaW1hZ2VzO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKGltYWdlc1tpXSkge1xuICAgICAgICAgIGZyZWVJbWFnZShpbWFnZXNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlc1tpXSA9IG51bGw7XG4gICAgICB9XG4gICAgICBtaXBQb29sLnB1c2gobWlwbWFwKTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVGV4IGluZm9cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZnVuY3Rpb24gVGV4SW5mbygpIHtcbiAgICAgIHRoaXMubWluRmlsdGVyID0gR0xfTkVBUkVTVCQxO1xuICAgICAgdGhpcy5tYWdGaWx0ZXIgPSBHTF9ORUFSRVNUJDE7XG4gICAgICB0aGlzLndyYXBTID0gR0xfQ0xBTVBfVE9fRURHRSQxO1xuICAgICAgdGhpcy53cmFwVCA9IEdMX0NMQU1QX1RPX0VER0UkMTtcbiAgICAgIHRoaXMuYW5pc290cm9waWMgPSAxO1xuICAgICAgdGhpcy5nZW5NaXBtYXBzID0gZmFsc2U7XG4gICAgICB0aGlzLm1pcG1hcEhpbnQgPSBHTF9ET05UX0NBUkU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBhcnNlVGV4SW5mbyhpbmZvLCBvcHRpb25zKSB7XG4gICAgICBpZiAoJ21pbicgaW4gb3B0aW9ucykge1xuICAgICAgICB2Y
1XIgbWluRmlsdGVyID0gb3B0aW9ucy5taW47XG4gICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG1pbkZpbHRlciwgbWluRmlsdGVycyk7XG4gICAgICAgIGluZm8ubWluRmlsdGVyID0gbWluRmlsdGVyc1ttaW5GaWx0ZXJdO1xuICAgICAgICBpZiAoTUlQTUFQX0ZJTFRFUlMuaW5kZXhPZihpbmZvLm1pbkZpbHRlcikgPj0gMCAmJiAhKCdmYWNlcycgaW4gb3B0aW9ucykpIHtcbiAgICAgICAgICBpbmZvLmdlbk1pcG1hcHMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoJ21hZycgaW4gb3B0aW9ucykge1xuICAgICAgICB2YXIgbWFnRmlsdGVyID0gb3B0aW9ucy5tYWc7XG4gICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG1hZ0ZpbHRlciwgbWFnRmlsdGVycyk7XG4gICAgICAgIGluZm8ubWFnRmlsdGVyID0gbWFnRmlsdGVyc1ttYWdGaWx0ZXJdO1xuICAgICAgfVxuICAgICAgdmFyIHdyYXBTID0gaW5mby53cmFwUztcbiAgICAgIHZhciB3cmFwVCA9IGluZm8ud3JhcFQ7XG4gICAgICBpZiAoJ3dyYXAnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHdyYXAgPSBvcHRpb25zLndyYXA7XG4gICAgICAgIGlmICh0eXBlb2Ygd3JhcCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcih3cmFwLCB3cmFwTW9kZXMpO1xuICAgICAgICAgIHdyYXBTID0gd3JhcFQgPSB3cmFwTW9kZXNbd3JhcF07XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh3cmFwKSkge1xuICAgICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKHdyYXBbMF0sIHdyYXBNb2Rlcyk7XG4gICAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIod3JhcFsxXSwgd3JhcE1vZGVzKTtcbiAgICAgICAgICB3cmFwUyA9IHdyYXBNb2Rlc1t3cmFwWzBdXTtcbiAgICAgICAgICB3cmFwVCA9IHdyYXBNb2Rlc1t3cmFwWzFdXTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCd3cmFwUycgaW4gb3B0aW9ucykge1xuICAgICAgICAgIHZhciBvcHRXcmFwUyA9IG9wdGlvbnMud3JhcFM7XG4gICAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIob3B0V3JhcFMsIHdyYXBNb2Rlcyk7XG4gICAgICAgICAgd3JhcFMgPSB3cmFwTW9kZXNbb3B0V3JhcFNdO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnd3JhcFQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICB2Y
1XIgb3B0V3JhcFQgPSBvcHRpb25zLndyYXBUO1xuICAgICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG9wdFdyYXBULCB3cmFwTW9kZXMpO1xuICAgICAgICAgIHdyYXBUID0gd3JhcE1vZGVzW29wdFdyYXBUXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaW5mby53cmFwUyA9IHdyYXBTO1xuICAgICAgaW5mby53cmFwVCA9IHdyYXBUO1xuICAgICAgaWYgKCdhbmlzb3Ryb3BpYycgaW4gb3B0aW9ucykge1xuICAgICAgICB2YXIgYW5pc290cm9waWMgPSBvcHRpb25zLmFuaXNvdHJvcGljO1xuICAgICAgICBjaGVjayQxKHR5cGVvZiBhbmlzb3Ryb3BpYyA9PT0gJ251bWJlcicgJiYgYW5pc290cm9waWMgPj0gMSAmJiBhbmlzb3Ryb3BpYyA8PSBsaW1pdHMubWF4QW5pc290cm9waWMsICdhbmlzbyBzYW1wbGVzIG11c3QgYmUgYmV0d2VlbiAxIGFuZCAnKTtcbiAgICAgICAgaW5mby5hbmlzb3Ryb3BpYyA9IG9wdGlvbnMuYW5pc290cm9waWM7XG4gICAgICB9XG4gICAgICBpZiAoJ21pcG1hcCcgaW4gb3B0aW9ucykge1xuICAgICAgICB2YXIgaGFzTWlwTWFwID0gZmFsc2U7XG4gICAgICAgIHN3aXRjaCAodHlwZW9mIG9wdGlvbnMubWlwbWFwKSB7XG4gICAgICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG9wdGlvbnMubWlwbWFwLCBtaXBtYXBIaW50LCAnaW52YWxpZCBtaXBtYXAgaGludCcpO1xuICAgICAgICAgICAgaW5mby5taXBtYXBIaW50ID0gbWlwbWFwSGludFtvcHRpb25zLm1pcG1hcF07XG4gICAgICAgICAgICBpbmZvLmdlbk1pcG1hcHMgPSB0cnVlO1xuICAgICAgICAgICAgaGFzTWlwTWFwID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgICAgICAgaGFzTWlwTWFwID0gaW5mby5nZW5NaXBtYXBzID0gb3B0aW9ucy5taXBtYXA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICAgICAgY2hlY2skMShBcnJheS5pc0FycmF5KG9wdGlvbnMubWlwbWFwKSwgJ2ludmFsaWQgbWlwbWFwIHR5cGUnKTtcbiAgICAgICAgICAgIGluZm8uZ2VuTWlwbWFwcyA9IGZhbHNlO1xuICAgICAgICAgICAgaGFzTWlwTWFwID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIG1pcG1hcCB0eXBlJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc01pcE1hcCAmJiAhKCdtaW4nIGluIG9wdGlvbnMpKSB7XG4gICAgICAgICAgaW5mby5taW5GaWx0ZXIgPSBHTF9ORUFSRVNUX01JUE1BUF9ORUFSRVNUJDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gc2V0VGV4SW5mbyhpbmZvLCB0YXJnZXQpIHtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTF9URVhUVVJFX01JTl9GSUxURVIsIGluZm8ubWluRmlsdGVyKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTF9URVhUVVJFX01BR19GSUxURVIsIGluZm8ubWFnRmlsdGVyKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTF9URVhUVVJFX1dSQVBfUywgaW5mby53cmFwUyk7XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0xfVEVYVFVSRV9XUkFQX1QsIGluZm8ud3JhcFQpO1xuICAgICAgaWYgKGV4dGVuc2lvbnMuZXh0X3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljKSB7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTF9URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCwgaW5mby5hbmlzb3Ryb3BpYyk7XG4gICAgICB9XG4gICAgICBpZiAoaW5mby5nZW5NaXBtYXBzKSB7XG4gICAgICAgIGdsLmhpbnQoR0xfR0VORVJBVEVfTUlQTUFQX0hJTlQsIGluZm8ubWlwbWFwSGludCk7XG4gICAgICAgIGdsLmdlbmVyYXRlTWlwbWFwKHRhcmdldCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEZ1bGwgdGV4dHVyZSBvYmplY3RcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIHRleHR1cmVDb3VudCA9IDA7XG4gICAgdmFyIHRleHR1cmVTZXQgPSB7fTtcbiAgICB2YXIgbnVtVGV4VW5pdHMgPSBsaW1pdHMubWF4VGV4dHVyZVVuaXRzO1xuICAgIHZhciB0ZXh0dXJlVW5pdHMgPSBBcnJheShudW1UZXhVbml0cykubWFwKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0pO1xuICAgIGZ1bmN0aW9uIFJFR0xUZXh0dXJlKHRhcmdldCkge1xuICAgICAgVGV4RmxhZ3MuY2FsbCh0aGlzKTtcbiAgICAgIHRoaXMubWlwbWFzayA9IDA7XG4gICAgICB0aGlzLmludGVybmFsZm9ybWF0ID0gR0xfUkdCQSQxO1xuICAgICAgdGhpcy5pZCA9IHRleHR1cmVDb3VudCsrO1xuICAgICAgdGhpcy5yZWZDb3VudCA9IDE7XG4gICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgIHRoaXMudW5pdCA9IC0xO1xuICAgICAgdGhpcy5iaW5kQ291bnQgPSAwO1xuICAgICAgdGhpcy50ZXhJbmZvID0gbmV3IFRleEluZm8oKTtcbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICB0aGlzLnN0YXRzID0ge1xuICAgICAgICAgIHNpemU6IDBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gdGVtcEJpbmQodGV4dHVyZSkge1xuICAgICAgZ2wuYWN0aXZlVGV4dHVyZShHTF9URVhUVVJFMCQxKTtcbiAgICAgIGdsLmJpbmRUZXh0dXJlKHRleHR1cmUudGFyZ2V0LCB0ZXh0dXJlLnRleHR1cmUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0ZW1wUmVzdG9yZSgpIHtcbiAgICAgIHZhciBwcmV2ID0gdGV4dHVyZVVuaXRzWzBdO1xuICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUocHJldi50YXJnZXQsIHByZXYudGV4dHVyZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShHTF9URVhUVVJFXzJEJDEsIG51bGwpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBkZXN0cm95KHRleHR1cmUpIHtcbiAgICAgIHZhciBoYW5kbGUgPSB0ZXh0dXJlLnRleHR1cmU7XG4gICAgICBjaGVjayQxKGhhbmRsZSwgJ211c3Qgbm90IGRvdWJsZSBkZXN0cm95IHRleHR1cmUnKTtcbiAgICAgIHZhciB1bml0ID0gdGV4dHVyZS51bml0O1xuICAgICAgdmFyIHRhcmdldCA9IHRleHR1cmUudGFyZ2V0O1xuICAgICAgaWYgKHVuaXQgPj0gMCkge1xuICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKEdMX1RFWFRVUkUwJDEgKyB1bml0KTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUodGFyZ2V0LCBudWxsKTtcbiAgICAgICAgdGV4dHVyZVVuaXRzW3VuaXRdID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGdsLmRlbGV0ZVRleHR1cmUoaGFuZGxlKTtcbiAgICAgIHRleHR1cmUudGV4dHVyZSA9IG51bGw7XG4gICAgICB0ZXh0dXJlLnBhcmFtcyA9IG51bGw7XG4gICAgICB0ZXh0dXJlLnBpeGVscyA9IG51bGw7XG4gICAgICB0ZXh0dXJlLnJlZkNvdW50ID0gMDtcbiAgICAgIGRlbGV0ZSB0ZXh0dXJlU2V0W3RleHR1cmUuaWRdO1xuICAgICAgc3RhdHMudGV4dHVyZUNvdW50LS07XG4gICAgfVxuICAgIGV4dGVuZChSRUdMVGV4dHVyZS5wcm90b3R5cGUsIHtcbiAgICAgIGJpbmQ6IGZ1bmN0aW9uIGJpbmQoKSB7XG4gICAgICAgI
1HZhciB0ZXh0dXJlID0gdGhpcztcbiAgICAgICAgdGV4dHVyZS5iaW5kQ291bnQgKz0gMTtcbiAgICAgICAgdmFyIHVuaXQgPSB0ZXh0dXJlLnVuaXQ7XG4gICAgICAgIGlmICh1bml0IDwgMCkge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtVGV4VW5pdHM7ICsraSkge1xuICAgICAgICAgICAgdmFyIG90aGVyID0gdGV4dHVyZVVuaXRzW2ldO1xuICAgICAgICAgICAgaWYgKG90aGVyKSB7XG4gICAgICAgICAgICAgIGlmIChvdGhlci5iaW5kQ291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgb3RoZXIudW5pdCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGV4dHVyZVVuaXRzW2ldID0gdGV4dHVyZTtcbiAgICAgICAgICAgIHVuaXQgPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh1bml0ID49IG51bVRleFVuaXRzKSB7XG4gICAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnN1ZmZpY2llbnQgbnVtYmVyIG9mIHRleHR1cmUgdW5pdHMnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlICYmIHN0YXRzLm1heFRleHR1cmVVbml0cyA8IHVuaXQgKyAxKSB7XG4gICAgICAgICAgICBzdGF0cy5tYXhUZXh0dXJlVW5pdHMgPSB1bml0ICsgMTsgLy8gKzEsIHNpbmNlIHRoZSB1bml0cyBhcmUgemVyby1iYXNlZFxuICAgICAgICAgIH1cbiAgICAgICAgICB0ZXh0dXJlLnVuaXQgPSB1bml0O1xuICAgICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoR0xfVEVYVFVSRTAkMSArIHVuaXQpO1xuICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKHRleHR1cmUudGFyZ2V0LCB0ZXh0dXJlLnRleHR1cmUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bml0O1xuICAgICAgfSxcbiAgICAgIHVuYmluZDogZnVuY3Rpb24gdW5iaW5kKCkge1xuICAgICAgICB0aGlzLmJpbmRDb3VudCAtPSAxO1xuICAgICAgfSxcbiAgICAgIGRlY1JlZjogZnVuY3Rpb24gZGVjUmVmKCkge1xuICAgICAgICBpZiAoLS10aGlzLnJlZkNvdW50IDw9IDApIHtcbiAgICAgICAgICBkZXN0cm95KHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gY3JlYXRlVGV4dHVyZTJEKGEsIGIpIHtcbiAgICAgIHZhciB0ZXh0dXJlID0gbmV3IFJFR0xUZXh0dXJlKEdMX1RFWFRVUkVfMkQkMSk7XG4gICAgICB0ZXh0dXJlU2V0W3RleHR1cmUuaWRdID0gdGV4dHVyZTtcbiAgICAgIHN0YXRzLnRleHR1cmVDb3VudCsrO1xuICAgICAgZnVuY3Rpb24gcmVnbFRleHR1cmUyRChhLCBiKSB7XG4gICAgICAgIHZhciB0ZXhJbmZvID0gdGV4dHVyZS50ZXhJbmZvO1xuICAgICAgICBUZXhJbmZvLmNhbGwodGV4SW5mbyk7XG4gICAgICAgIHZhciBtaXBEYXRhID0gYWxsb2NNaXBNYXAoKTtcbiAgICAgICAgaWYgKHR5cGVvZiBhID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGlmICh0eXBlb2YgYiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbVNoYXBlKG1pcERhdGEsIGEgfCAwLCBiIHwgMCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbVNoYXBlKG1pcERhdGEsIGEgfCAwLCBhIHwgMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGEpIHtcbiAgICAgICAgICBjaGVjayQxLnR5cGUoYSwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyB0byByZWdsLnRleHR1cmUnKTtcbiAgICAgICAgICBwYXJzZVRleEluZm8odGV4SW5mbywgYSk7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KG1pcERhdGEsIGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGVtcHR5IHRleHR1cmVzIGdldCBhc3NpZ25lZCBhIGRlZmF1bHQgc2hhcGUgb2YgMXgxXG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tU2hhcGUobWlwRGF0YSwgMSwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRleEluZm8uZ2VuTWlwbWFwcykge1xuICAgICAgICAgIG1pcERhdGEubWlwbWFzayA9IChtaXBEYXRhLndpZHRoIDw8IDEpIC0gMTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0dXJlLm1pcG1hc2sgPSBtaXBEYXRhLm1pcG1hc2s7XG4gICAgICAgIGNvcHlGbGFncyh0ZXh0dXJlLCBtaXBEYXRhKTtcbiAgICAgICAgY2hlY2skMS50ZXh0dXJlMkQodGV4SW5mbywgbWlwRGF0YSwgbGltaXRzKTtcbiAgICAgICAgdGV4dHVyZS5pbnRlcm5hbGZvcm1hdCA9IG1pcERhdGEuaW50ZXJuYWxmb3JtYXQ7XG4gICAgICAgIHJlZ2xUZXh0dXJlMkQud2lkdGggPSBtaXBEYXRhLndpZHRoO1xuICAgICAgICByZWdsVGV4dHVyZTJELmhlaWdodCA9IG1pcERhdGEuaGVpZ2h0O1xuICAgICAgICB0ZW1wQmluZCh0ZXh0dXJlKTtcbiAgICAgICAgc2V0TWlwTWFwKG1pcERhdGEsIEdMX1RFWFRVUkVfMkQkMSk7XG4gICAgICAgIHNldFRleEluZm8odGV4SW5mbywgR0xfVEVYVFVSRV8yRCQxKTtcbiAgICAgICAgdGVtcFJlc3RvcmUoKTtcbiAgICAgICAgZnJlZU1pcE1hcChtaXBEYXRhKTtcbiAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgICAgdGV4dHVyZS5zdGF0cy5zaXplID0gZ2V0VGV4dHVyZVNpemUodGV4dHVyZS5pbnRlcm5hbGZvcm1hdCwgdGV4dHVyZS50eXBlLCBtaXBEYXRhLndpZHRoLCBtaXBEYXRhLmhlaWdodCwgdGV4SW5mby5nZW5NaXBtYXBzLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVnbFRleHR1cmUyRC5mb3JtYXQgPSB0ZXh0dXJlRm9ybWF0c0ludmVydFt0ZXh0dXJlLmludGVybmFsZm9ybWF0XTtcbiAgICAgICAgcmVnbFRleHR1cmUyRC50eXBlID0gdGV4dHVyZVR5cGVzSW52ZXJ0W3RleHR1cmUudHlwZV07XG4gICAgICAgIHJlZ2xUZXh0dXJlMkQubWFnID0gbWFnRmlsdGVyc0ludmVydFt0ZXhJbmZvLm1hZ0ZpbHRlcl07XG4gICAgICAgIHJlZ2xUZXh0dXJlMkQubWluID0gbWluRmlsdGVyc0ludmVydFt0ZXhJbmZvLm1pbkZpbHRlcl07XG4gICAgICAgIHJlZ2xUZXh0dXJlMkQud3JhcFMgPSB3cmFwTW9kZXNJbnZlcnRbdGV4SW5mby53cmFwU107XG4gICAgICAgI
1HJlZ2xUZXh0dXJlMkQud3JhcFQgPSB3cmFwTW9kZXNJbnZlcnRbdGV4SW5mby53cmFwVF07XG4gICAgICAgIHJldHVybiByZWdsVGV4dHVyZTJEO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc3ViaW1hZ2UoaW1hZ2UsIHhfLCB5XywgbGV2ZWxfKSB7XG4gICAgICAgIGNoZWNrJDEoISFpbWFnZSwgJ211c3Qgc3BlY2lmeSBpbWFnZSBkYXRhJyk7XG4gICAgICAgIHZhciB4ID0geF8gfCAwO1xuICAgICAgICB2YXIgeSA9IHlfIHwgMDtcbiAgICAgICAgdmFyIGxldmVsID0gbGV2ZWxfIHwgMDtcbiAgICAgICAgdmFyIGltYWdlRGF0YSA9IGFsbG9jSW1hZ2UoKTtcbiAgICAgICAgY29weUZsYWdzKGltYWdlRGF0YSwgdGV4dHVyZSk7XG4gICAgICAgIGltYWdlRGF0YS53aWR0aCA9IDA7XG4gICAgICAgIGltYWdlRGF0YS5oZWlnaHQgPSAwO1xuICAgICAgICBwYXJzZUltYWdlKGltYWdlRGF0YSwgaW1hZ2UpO1xuICAgICAgICBpbWFnZURhdGEud2lkdGggPSBpbWFnZURhdGEud2lkdGggfHwgKHRleHR1cmUud2lkdGggPj4gbGV2ZWwpIC0geDtcbiAgICAgICAgaW1hZ2VEYXRhLmhlaWdodCA9IGltYWdlRGF0YS5oZWlnaHQgfHwgKHRleHR1cmUuaGVpZ2h0ID4+IGxldmVsKSAtIHk7XG4gICAgICAgIGNoZWNrJDEodGV4dHVyZS50eXBlID09PSBpbWFnZURhdGEudHlwZSAmJiB0ZXh0dXJlLmZvcm1hdCA9PT0gaW1hZ2VEYXRhLmZvcm1hdCAmJiB0ZXh0dXJlLmludGVybmFsZm9ybWF0ID09PSBpbWFnZURhdGEuaW50ZXJuYWxmb3JtYXQsICdpbmNvbXBhdGlibGUgZm9ybWF0IGZvciB0ZXh0dXJlLnN1YmltYWdlJyk7XG4gICAgICAgIGNoZWNrJDEoeCA+PSAwICYmIHkgPj0gMCAmJiB4ICsgaW1hZ2VEYXRhLndpZHRoIDw9IHRleHR1cmUud2lkdGggJiYgeSArIGltYWdlRGF0YS5oZWlnaHQgPD0gdGV4dHVyZS5oZWlnaHQsICd0ZXh0dXJlLnN1YmltYWdlIHdyaXRlIG91dCBvZiBib3VuZHMnKTtcbiAgICAgICAgY2hlY2skMSh0ZXh0dXJlLm1pcG1hc2sgJiAxIDw8IGxldmVsLCAnbWlzc2luZyBtaXBtYXAgZGF0YScpO1xuICAgICAgICBjaGVjayQxKGltYWdlRGF0YS5kYXRhIHx8IGltYWdlRGF0YS5lbGVtZW50IHx8IGltYWdlRGF0YS5uZWVkc0NvcHksICdtaXNzaW5nIGltYWdlIGRhdGEnKTtcbiAgICAgICAgdGVtcEJpbmQodGV4dHVyZSk7XG4gICAgICAgIHNldFN1YkltYWdlKGltYWdlRGF0YSwgR0xfVEVYVFVSRV8yRCQxLCB4LCB5LCBsZXZlbCk7XG4gICAgICAgIHRlbXBSZXN0b3JlKCk7XG4gICAgICAgIGZyZWVJbWFnZShpbWFnZURhdGEpO1xuICAgICAgICByZXR1cm4gcmVnbFRleHR1cmUyRDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJlc2l6ZSh3XywgaF8pIHtcbiAgICAgICAgdmFyIHcgPSB3XyB8IDA7XG4gICAgICAgIHZhciBoID0gaF8gfCAwIHx8IHc7XG4gICAgICAgIGlmICh3ID09PSB0ZXh0dXJlLndpZHRoICYmIGggPT09IHRleHR1cmUuaGVpZ2h0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlMkQ7XG4gICAgICAgIH1cbiAgICAgICAgcmVnbFRleHR1cmUyRC53aWR0aCA9IHRleHR1cmUud2lkdGggPSB3O1xuICAgICAgICByZWdsVGV4dHVyZTJELmhlaWdodCA9IHRleHR1cmUuaGVpZ2h0ID0gaDtcbiAgICAgICAgdGVtcEJpbmQodGV4dHVyZSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyB0ZXh0dXJlLm1pcG1hc2sgPj4gaTsgKytpKSB7XG4gICAgICAgICAgdmFyIF93ID0gdyA+PiBpO1xuICAgICAgICAgIHZhciBfaCA9IGggPj4gaTtcbiAgICAgICAgICBpZiAoIV93IHx8ICFfaCkgYnJlYWs7XG4gICAgICAgICAgZ2wudGV4SW1hZ2UyRChHTF9URVhUVVJFXzJEJDEsIGksIHRleHR1cmUuZm9ybWF0LCBfdywgX2gsIDAsIHRleHR1cmUuZm9ybWF0LCB0ZXh0dXJlLnR5cGUsIG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIHRlbXBSZXN0b3JlKCk7XG5cbiAgICAgICAgLy8gYWxzbywgcmVjb21wdXRlIHRoZSB0ZXh0dXJlIHNpemUuXG4gICAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICAgIHRleHR1cmUuc3RhdHMuc2l6ZSA9IGdldFRleHR1cmVTaXplKHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsIHRleHR1cmUudHlwZSwgdywgaCwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVnbFRleHR1cmUyRDtcbiAgICAgIH1cbiAgICAgIHJlZ2xUZXh0dXJlMkQoYSwgYik7XG4gICAgICByZWdsVGV4dHVyZTJELnN1YmltYWdlID0gc3ViaW1hZ2U7XG4gICAgICByZWdsVGV4dHVyZTJELnJlc2l6ZSA9IHJlc2l6ZTtcbiAgICAgIHJlZ2xUZXh0dXJlMkQuX3JlZ2xUeXBlID0gJ3RleHR1cmUyZCc7XG4gICAgICByZWdsVGV4dHVyZTJELl90ZXh0dXJlID0gdGV4dHVyZTtcbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICByZWdsVGV4dHVyZTJELnN0YXRzID0gdGV4dHVyZS5zdGF0cztcbiAgICAgIH1cbiAgICAgIHJlZ2xUZXh0dXJlMkQuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGV4dHVyZS5kZWNSZWYoKTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmVnbFRleHR1cmUyRDtcbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlVGV4dHVyZUN1YmUoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSkge1xuICAgICAgdmFyIHRleHR1cmUgPSBuZXcgUkVHTFRleHR1cmUoR0xfVEVYVFVSRV9DVUJFX01BUCQxKTtcbiAgICAgIHRleHR1cmVTZXRbdGV4dHVyZS5pZF0gPSB0ZXh0dXJlO1xuICAgICAgc3RhdHMuY3ViZUNvdW50Kys7XG4gICAgICB2Y
1XIgZmFjZXMgPSBuZXcgQXJyYXkoNik7XG4gICAgICBmdW5jdGlvbiByZWdsVGV4dHVyZUN1YmUoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSkge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHRleEluZm8gPSB0ZXh0dXJlLnRleEluZm87XG4gICAgICAgIFRleEluZm8uY2FsbCh0ZXhJbmZvKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICAgIGZhY2VzW2ldID0gYWxsb2NNaXBNYXAoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGEwID09PSAnbnVtYmVyJyB8fCAhYTApIHtcbiAgICAgICAgICB2YXIgcyA9IGEwIHwgMCB8fCAxO1xuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbVNoYXBlKGZhY2VzW2ldLCBzLCBzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGEwID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGlmIChhMSkge1xuICAgICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzBdLCBhMCk7XG4gICAgICAgICAgICBwYXJzZU1pcE1hcEZyb21PYmplY3QoZmFjZXNbMV0sIGExKTtcbiAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbU9iamVjdChmYWNlc1syXSwgYTIpO1xuICAgICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzNdLCBhMyk7XG4gICAgICAgICAgICBwYXJzZU1pcE1hcEZyb21PYmplY3QoZmFjZXNbNF0sIGE0KTtcbiAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbU9iamVjdChmYWNlc1s1XSwgYTUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXJzZVRleEluZm8odGV4SW5mbywgYTApO1xuICAgICAgICAgICAgcGFyc2VGbGFncyh0ZXh0dXJlLCBhMCk7XG4gICAgICAgICAgICBpZiAoJ2ZhY2VzJyBpbiBhMCkge1xuICAgICAgICAgICAgICB2Y
1XIgZmFjZUlucHV0ID0gYTAuZmFjZXM7XG4gICAgICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShmYWNlSW5wdXQpICYmIGZhY2VJbnB1dC5sZW5ndGggPT09IDYsICdjdWJlIGZhY2VzIG11c3QgYmUgYSBsZW5ndGggNiBhcnJheScpO1xuICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMSh0eXBlb2YgZmFjZUlucHV0W2ldID09PSAnb2JqZWN0JyAmJiAhIWZhY2VJbnB1dFtpXSwgJ2ludmFsaWQgaW5wdXQgZm9yIGN1YmUgbWFwIGZhY2UnKTtcbiAgICAgICAgICAgICAgICBjb3B5RmxhZ3MoZmFjZXNbaV0sIHRleHR1cmUpO1xuICAgICAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbU9iamVjdChmYWNlc1tpXSwgZmFjZUlucHV0W2ldKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbU9iamVjdChmYWNlc1tpXSwgYTApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgYXJndW1lbnRzIHRvIGN1YmUgbWFwJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29weUZsYWdzKHRleHR1cmUsIGZhY2VzWzBdKTtcbiAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKCFsaW1pdHMubnBvdFRleHR1cmVDdWJlKSB7XG4gICAgICAgICAgICBjaGVjayQxKGlzUG93MiQxKHRleHR1cmUud2lkdGgpICYmIGlzUG93MiQxKHRleHR1cmUuaGVpZ2h0KSwgJ3lvdXIgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IG5vbiBwb3dlciBvciB0d28gdGV4dHVyZSBkaW1lbnNpb25zJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRleEluZm8uZ2VuTWlwbWFwcykge1xuICAgICAgICAgIHRleHR1cmUubWlwbWFzayA9IChmYWNlc1swXS53aWR0aCA8PCAxKSAtIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGV4dHVyZS5taXBtYXNrID0gZmFjZXNbMF0ubWlwbWFzaztcbiAgICAgICAgfVxuICAgICAgICBjaGVjayQxLnRleHR1cmVDdWJlKHRleHR1cmUsIHRleEluZm8sIGZhY2VzLCBsaW1pdHMpO1xuICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0ID0gZmFjZXNbMF0uaW50ZXJuYWxmb3JtYXQ7XG4gICAgICAgIHJlZ2xUZXh0dXJlQ3ViZS53aWR0aCA9IGZhY2VzWzBdLndpZHRoO1xuICAgICAgICByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0ID0gZmFjZXNbMF0uaGVpZ2h0O1xuICAgICAgICB0ZW1wQmluZCh0ZXh0dXJlKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICAgIHNldE1pcE1hcChmYWNlc1tpXSwgR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDEgKyBpKTtcbiAgICAgICAgfVxuICAgICAgICBzZXRUZXhJbmZvKHRleEluZm8sIEdMX1RFWFRVUkVfQ1VCRV9NQVAkMSk7XG4gICAgICAgIHRlbXBSZXN0b3JlKCk7XG4gICAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICAgIHRleHR1cmUuc3RhdHMuc2l6ZSA9IGdldFRleHR1cmVTaXplKHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsIHRleHR1cmUudHlwZSwgcmVnbFRleHR1cmVDdWJlLndpZHRoLCByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0LCB0ZXhJbmZvLmdlbk1pcG1hcHMsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHJlZ2xUZXh0dXJlQ3ViZS5mb3JtYXQgPSB0ZXh0dXJlRm9ybWF0c0ludmVydFt0ZXh0dXJlLmludGVybmFsZm9ybWF0XTtcbiAgICAgICAgcmVnbFRleHR1cmVDdWJlLnR5cGUgPSB0ZXh0dXJlVHlwZXNJbnZlcnRbdGV4dHVyZS50eXBlXTtcbiAgICAgICAgcmVnbFRleHR1cmVDdWJlLm1hZyA9IG1hZ0ZpbHRlcnNJbnZlcnRbdGV4SW5mby5tYWdGaWx0ZXJdO1xuICAgICAgICByZWdsVGV4dHVyZUN1YmUubWluID0gbWluRmlsdGVyc0ludmVydFt0ZXhJbmZvLm1pbkZpbHRlcl07XG4gICAgICAgIHJlZ2xUZXh0dXJlQ3ViZS53cmFwUyA9IHdyYXBNb2Rlc0ludmVydFt0ZXhJbmZvLndyYXBTXTtcbiAgICAgICAgcmVnbFRleHR1cmVDdWJlLndyYXBUID0gd3JhcE1vZGVzSW52ZXJ0W3RleEluZm8ud3JhcFRdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgZnJlZU1pcE1hcChmYWNlc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHN1YmltYWdlKGZhY2UsIGltYWdlLCB4XywgeV8sIGxldmVsXykge1xuICAgICAgICBjaGVjayQxKCEhaW1hZ2UsICdtdXN0IHNwZWNpZnkgaW1hZ2UgZGF0YScpO1xuICAgICAgICBjaGVjayQxKHR5cGVvZiBmYWNlID09PSAnbnVtYmVyJyAmJiBmYWNlID09PSAoZmFjZSB8IDApICYmIGZhY2UgPj0gMCAmJiBmYWNlIDwgNiwgJ2ludmFsaWQgZmFjZScpO1xuICAgICAgICB2Y
1XIgeCA9IHhfIHwgMDtcbiAgICAgICAgdmFyIHkgPSB5XyB8IDA7XG4gICAgICAgIHZhciBsZXZlbCA9IGxldmVsXyB8IDA7XG4gICAgICAgIHZhciBpbWFnZURhdGEgPSBhbGxvY0ltYWdlKCk7XG4gICAgICAgIGNvcHlGbGFncyhpbWFnZURhdGEsIHRleHR1cmUpO1xuICAgICAgICBpbWFnZURhdGEud2lkdGggPSAwO1xuICAgICAgICBpbWFnZURhdGEuaGVpZ2h0ID0gMDtcbiAgICAgICAgcGFyc2VJbWFnZShpbWFnZURhdGEsIGltYWdlKTtcbiAgICAgICAgaW1hZ2VEYXRhLndpZHRoID0gaW1hZ2VEYXRhLndpZHRoIHx8ICh0ZXh0dXJlLndpZHRoID4+IGxldmVsKSAtIHg7XG4gICAgICAgIGltYWdlRGF0YS5oZWlnaHQgPSBpbWFnZURhdGEuaGVpZ2h0IHx8ICh0ZXh0dXJlLmhlaWdodCA+PiBsZXZlbCkgLSB5O1xuICAgICAgICBjaGVjayQxKHRleHR1cmUudHlwZSA9PT0gaW1hZ2VEYXRhLnR5cGUgJiYgdGV4dHVyZS5mb3JtYXQgPT09IGltYWdlRGF0YS5mb3JtYXQgJiYgdGV4dHVyZS5pbnRlcm5hbGZvcm1hdCA9PT0gaW1hZ2VEYXRhLmludGVybmFsZm9ybWF0LCAnaW5jb21wYXRpYmxlIGZvcm1hdCBmb3IgdGV4dHVyZS5zdWJpbWFnZScpO1xuICAgICAgICBjaGVjayQxKHggPj0gMCAmJiB5ID49IDAgJiYgeCArIGltYWdlRGF0YS53aWR0aCA8PSB0ZXh0dXJlLndpZHRoICYmIHkgKyBpbWFnZURhdGEuaGVpZ2h0IDw9IHRleHR1cmUuaGVpZ2h0LCAndGV4dHVyZS5zdWJpbWFnZSB3cml0ZSBvdXQgb2YgYm91bmRzJyk7XG4gICAgICAgIGNoZWNrJDEodGV4dHVyZS5taXBtYXNrICYgMSA8PCBsZXZlbCwgJ21pc3NpbmcgbWlwbWFwIGRhdGEnKTtcbiAgICAgICAgY2hlY2skMShpbWFnZURhdGEuZGF0YSB8fCBpbWFnZURhdGEuZWxlbWVudCB8fCBpbWFnZURhdGEubmVlZHNDb3B5LCAnbWlzc2luZyBpbWFnZSBkYXRhJyk7XG4gICAgICAgIHRlbXBCaW5kKHRleHR1cmUpO1xuICAgICAgICBzZXRTdWJJbWFnZShpbWFnZURhdGEsIEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQxICsgZmFjZSwgeCwgeSwgbGV2ZWwpO1xuICAgICAgICB0ZW1wUmVzdG9yZSgpO1xuICAgICAgICBmcmVlSW1hZ2UoaW1hZ2VEYXRhKTtcbiAgICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJlc2l6ZShyYWRpdXNfKSB7XG4gICAgICAgIHZhciByYWRpdXMgPSByYWRpdXNfIHwgMDtcbiAgICAgICAgaWYgKHJhZGl1cyA9PT0gdGV4dHVyZS53aWR0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZWdsVGV4dHVyZUN1YmUud2lkdGggPSB0ZXh0dXJlLndpZHRoID0gcmFkaXVzO1xuICAgICAgICByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0ID0gdGV4dHVyZS5oZWlnaHQgPSByYWRpdXM7XG4gICAgICAgIHRlbXBCaW5kKHRleHR1cmUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICAgIGZvciAodmFyIGogPSAwOyB0ZXh0dXJlLm1pcG1hc2sgPj4gajsgKytqKSB7XG4gICAgICAgICAgICBnbC50ZXhJbWFnZTJEKEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQxICsgaSwgaiwgdGV4dHVyZS5mb3JtYXQsIHJhZGl1cyA+PiBqLCByYWRpdXMgPj4gaiwgMCwgdGV4dHVyZS5mb3JtYXQsIHRleHR1cmUudHlwZSwgbnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRlbXBSZXN0b3JlKCk7XG4gICAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICAgIHRleHR1cmUuc3RhdHMuc2l6ZSA9IGdldFRleHR1cmVTaXplKHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsIHRleHR1cmUudHlwZSwgcmVnbFRleHR1cmVDdWJlLndpZHRoLCByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZTtcbiAgICAgIH1cbiAgICAgIHJlZ2xUZXh0dXJlQ3ViZShhMCwgYTEsIGEyLCBhMywgYTQsIGE1KTtcbiAgICAgIHJlZ2xUZXh0dXJlQ3ViZS5zdWJpbWFnZSA9IHN1YmltYWdlO1xuICAgICAgcmVnbFRleHR1cmVDdWJlLnJlc2l6ZSA9IHJlc2l6ZTtcbiAgICAgIHJlZ2xUZXh0dXJlQ3ViZS5fcmVnbFR5cGUgPSAndGV4dHVyZUN1YmUnO1xuICAgICAgcmVnbFRleHR1cmVDdWJlLl90ZXh0dXJlID0gdGV4dHVyZTtcbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICByZWdsVGV4dHVyZUN1YmUuc3RhdHMgPSB0ZXh0dXJlLnN0YXRzO1xuICAgICAgfVxuICAgICAgcmVnbFRleHR1cmVDdWJlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRleHR1cmUuZGVjUmVmKCk7XG4gICAgICB9O1xuICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZTtcbiAgICB9XG5cbiAgICAvLyBDYWxsZWQgd2hlbiByZWdsIGlzIGRlc3Ryb3llZFxuICAgIGZ1bmN0aW9uIGRlc3Ryb3lUZXh0dXJlcygpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtVGV4VW5pdHM7ICsraSkge1xuICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKEdMX1RFWFRVUkUwJDEgKyBpKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV8yRCQxLCBudWxsKTtcbiAgICAgICAgdGV4dHVyZVVuaXRzW2ldID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhbHVlcyh0ZXh0dXJlU2V0KS5mb3JFYWNoKGRlc3Ryb3kpO1xuICAgICAgc3RhdHMuY3ViZUNvdW50ID0gMDtcbiAgICAgIHN0YXRzLnRleHR1cmVDb3VudCA9IDA7XG4gICAgfVxuICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgc3RhdHMuZ2V0VG90YWxUZXh0dXJlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgICAgT2JqZWN0LmtleXModGV4dHVyZVNldCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgdG90YWwgKz0gdGV4dHVyZVNldFtrZXldLnN0YXRzLnNpemU7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdG90YWw7XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXN0b3JlVGV4dHVyZXMoKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bVRleFVuaXRzOyArK2kpIHtcbiAgICAgICAgdmFyIHRleCA9IHRleHR1cmVVbml0c1tpXTtcbiAgICAgICAgaWYgKHRleCkge1xuICAgICAgICAgI
1HRleC5iaW5kQ291bnQgPSAwO1xuICAgICAgICAgIHRleC51bml0ID0gLTE7XG4gICAgICAgICAgdGV4dHVyZVVuaXRzW2ldID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFsdWVzKHRleHR1cmVTZXQpLmZvckVhY2goZnVuY3Rpb24gKHRleHR1cmUpIHtcbiAgICAgICAgdGV4dHVyZS50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZSh0ZXh0dXJlLnRhcmdldCwgdGV4dHVyZS50ZXh0dXJlKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAzMjsgKytpKSB7XG4gICAgICAgICAgaWYgKCh0ZXh0dXJlLm1pcG1hc2sgJiAxIDw8IGkpID09PSAwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHRleHR1cmUudGFyZ2V0ID09PSBHTF9URVhUVVJFXzJEJDEpIHtcbiAgICAgICAgICAgIGdsLnRleEltYWdlMkQoR0xfVEVYVFVSRV8yRCQxLCBpLCB0ZXh0dXJlLmludGVybmFsZm9ybWF0LCB0ZXh0dXJlLndpZHRoID4+IGksIHRleHR1cmUuaGVpZ2h0ID4+IGksIDAsIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsIHRleHR1cmUudHlwZSwgbnVsbCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgNjsgKytqKSB7XG4gICAgICAgICAgICAgIGdsLnRleEltYWdlMkQoR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDEgKyBqLCBpLCB0ZXh0dXJlLmludGVybmFsZm9ybWF0LCB0ZXh0dXJlLndpZHRoID4+IGksIHRleHR1cmUuaGVpZ2h0ID4+IGksIDAsIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsIHRleHR1cmUudHlwZSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNldFRleEluZm8odGV4dHVyZS50ZXhJbmZvLCB0ZXh0dXJlLnRhcmdldCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVmcmVzaFRleHR1cmVzKCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1UZXhVbml0czsgKytpKSB7XG4gICAgICAgIHZhciB0ZXggPSB0ZXh0dXJlVW5pdHNbaV07XG4gICAgICAgIGlmICh0ZXgpIHtcbiAgICAgICAgICB0ZXguYmluZENvdW50ID0gMDtcbiAgICAgICAgICB0ZXgudW5pdCA9IC0xO1xuICAgICAgICAgIHRleHR1cmVVbml0c1tpXSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZ2wuYWN0aXZlVGV4dHVyZShHTF9URVhUVVJFMCQxICsgaSk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfMkQkMSwgbnVsbCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfQ1VCRV9NQVAkMSwgbnVsbCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjcmVhdGUyRDogY3JlYXRlVGV4dHVyZTJELFxuICAgICAgY3JlYXRlQ3ViZTogY3JlYXRlVGV4dHVyZUN1YmUsXG4gICAgICBjbGVhcjogZGVzdHJveVRleHR1cmVzLFxuICAgICAgZ2V0VGV4dHVyZTogZnVuY3Rpb24gZ2V0VGV4dHVyZSh3cmFwcGVyKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSxcbiAgICAgIHJlc3RvcmU6IHJlc3RvcmVUZXh0dXJlcyxcbiAgICAgIHJlZnJlc2g6IHJlZnJlc2hUZXh0dXJlc1xuICAgIH07XG4gIH1cbiAgdmFyIEdMX1JFTkRFUkJVRkZFUiA9IDB4OEQ0MTtcbiAgdmFyIEdMX1JHQkE0JDEgPSAweDgwNTY7XG4gIHZhciBHTF9SR0I1X0ExJDEgPSAweDgwNTc7XG4gIHZhciBHTF9SR0I1NjUkMSA9IDB4OEQ2MjtcbiAgdmFyIEdMX0RFUFRIX0NPTVBPTkVOVDE2ID0gMHg4MUE1O1xuICB2YXIgR0xfU1RFTkNJTF9JTkRFWDggPSAweDhENDg7XG4gIHZhciBHTF9ERVBUSF9TVEVOQ0lMJDEgPSAweDg0Rjk7XG4gIHZhciBHTF9TUkdCOF9BTFBIQThfRVhUID0gMHg4QzQzO1xuICB2YXIgR0xfUkdCQTMyRl9FWFQgPSAweDg4MTQ7XG4gIHZhciBHTF9SR0JBMTZGX0VYVCA9IDB4ODgxQTtcbiAgdmFyIEdMX1JHQjE2Rl9FWFQgPSAweDg4MUI7XG4gIHZhciBGT1JNQVRfU0laRVMgPSBbXTtcbiAgRk9STUFUX1NJWkVTW0dMX1JHQkE0JDFdID0gMjtcbiAgRk9STUFUX1NJWkVTW0dMX1JHQjVfQTEkMV0gPSAyO1xuICBGT1JNQVRfU0laRVNbR0xfUkdCNTY1JDFdID0gMjtcbiAgRk9STUFUX1NJWkVTW0dMX0RFUFRIX0NPTVBPTkVOVDE2XSA9IDI7XG4gIEZPUk1BVF9TSVpFU1tHTF9TVEVOQ0lMX0lOREVYOF0gPSAxO1xuICBGT1JNQVRfU0laRVNbR0xfREVQVEhfU1RFTkNJTCQxXSA9IDQ7XG4gIEZPUk1BVF9TSVpFU1tHTF9TUkdCOF9BTFBIQThfRVhUXSA9IDQ7XG4gIEZPUk1BVF9TSVpFU1tHTF9SR0JBMzJGX0VYVF0gPSAxNjtcbiAgRk9STUFUX1NJWkVTW0dMX1JHQkExNkZfRVhUXSA9IDg7XG4gIEZPUk1BVF9TSVpFU1tHTF9SR0IxNkZfRVhUXSA9IDY7XG4gIGZ1bmN0aW9uIGdldFJlbmRlcmJ1ZmZlclNpemUoZm9ybWF0LCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgcmV0dXJuIEZPUk1BVF9TSVpFU1tmb3JtYXRdICogd2lkdGggKiBoZWlnaHQ7XG4gIH1cbiAgdmFyIHdyYXBSZW5kZXJidWZmZXJzID0gZnVuY3Rpb24gd3JhcFJlbmRlcmJ1ZmZlcnMoZ2wsIGV4dGVuc2lvbnMsIGxpbWl0cywgc3RhdHMsIGNvbmZpZykge1xuICAgIHZhciBmb3JtYXRUeXBlcyA9IHtcbiAgICAgICdyZ2JhNCc6IEdMX1JHQkE0JDEsXG4gICAgICAncmdiNTY1JzogR0xfUkdCNTY1JDEsXG4gICAgICAncmdiNSBhMSc6IEdMX1JHQjVfQTEkMSxcbiAgICAgICdkZXB0aCc6IEdMX0RFUFRIX0NPTVBPTkVOVDE2LFxuICAgICAgJ3N0ZW5jaWwnOiBHTF9TVEVOQ0lMX0lOREVYOCxcbiAgICAgICdkZXB0aCBzdGVuY2lsJzogR0xfREVQVEhfU1RFTkNJTCQxXG4gICAgfTtcbiAgICBpZiAoZXh0ZW5zaW9ucy5leHRfc3JnYikge1xuICAgICAgZm9ybWF0VHlwZXNbJ3NyZ2JhJ10gPSBHTF9TUkdCOF9BTFBIQThfRVhUO1xuICAgIH1cbiAgICBpZiAoZXh0ZW5zaW9ucy5leHRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQpIHtcbiAgICAgIGZvcm1hdFR5cGVzWydyZ2JhMTZmJ10gPSBHTF9SR0JBMTZGX0VYVDtcbiAgICAgIGZvcm1hdFR5cGVzWydyZ2IxNmYnXSA9IEdMX1JHQjE2Rl9FWFQ7XG4gICAgfVxuICAgIGlmIChleHRlbnNpb25zLndlYmdsX2NvbG9yX2J1ZmZlcl9mbG9hdCkge1xuICAgICAgZm9ybWF0VHlwZXNbJ3JnYmEzMmYnXSA9IEdMX1JHQkEzMkZfRVhUO1xuICAgIH1cbiAgICB2YXIgZm9ybWF0VHlwZXNJbnZlcnQgPSBbXTtcbiAgICBPYmplY3Qua2V5cyhmb3JtYXRUeXBlcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICB2Y
1XIgdmFsID0gZm9ybWF0VHlwZXNba2V5XTtcbiAgICAgIGZvcm1hdFR5cGVzSW52ZXJ0W3ZhbF0gPSBrZXk7XG4gICAgfSk7XG4gICAgdmFyIHJlbmRlcmJ1ZmZlckNvdW50ID0gMDtcbiAgICB2YXIgcmVuZGVyYnVmZmVyU2V0ID0ge307XG4gICAgZnVuY3Rpb24gUkVHTFJlbmRlcmJ1ZmZlcihyZW5kZXJidWZmZXIpIHtcbiAgICAgIHRoaXMuaWQgPSByZW5kZXJidWZmZXJDb3VudCsrO1xuICAgICAgdGhpcy5yZWZDb3VudCA9IDE7XG4gICAgICB0aGlzLnJlbmRlcmJ1ZmZlciA9IHJlbmRlcmJ1ZmZlcjtcbiAgICAgIHRoaXMuZm9ybWF0ID0gR0xfUkdCQTQkMTtcbiAgICAgIHRoaXMud2lkdGggPSAwO1xuICAgICAgdGhpcy5oZWlnaHQgPSAwO1xuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHRoaXMuc3RhdHMgPSB7XG4gICAgICAgICAgc2l6ZTogMFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICBSRUdMUmVuZGVyYnVmZmVyLnByb3RvdHlwZS5kZWNSZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoLS10aGlzLnJlZkNvdW50IDw9IDApIHtcbiAgICAgICAgZGVzdHJveSh0aGlzKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGZ1bmN0aW9uIGRlc3Ryb3kocmIpIHtcbiAgICAgIHZhciBoYW5kbGUgPSByYi5yZW5kZXJidWZmZXI7XG4gICAgICBjaGVjayQxKGhhbmRsZSwgJ211c3Qgbm90IGRvdWJsZSBkZXN0cm95IHJlbmRlcmJ1ZmZlcicpO1xuICAgICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihHTF9SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgICAgZ2wuZGVsZXRlUmVuZGVyYnVmZmVyKGhhbmRsZSk7XG4gICAgICByYi5yZW5kZXJidWZmZXIgPSBudWxsO1xuICAgICAgcmIucmVmQ291bnQgPSAwO1xuICAgICAgZGVsZXRlIHJlbmRlcmJ1ZmZlclNldFtyYi5pZF07XG4gICAgICBzdGF0cy5yZW5kZXJidWZmZXJDb3VudC0tO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVSZW5kZXJidWZmZXIoYSwgYikge1xuICAgICAgdmFyIHJlbmRlcmJ1ZmZlciA9IG5ldyBSRUdMUmVuZGVyYnVmZmVyKGdsLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpKTtcbiAgICAgIHJlbmRlcmJ1ZmZlclNldFtyZW5kZXJidWZmZXIuaWRdID0gcmVuZGVyYnVmZmVyO1xuICAgICAgc3RhdHMucmVuZGVyYnVmZmVyQ291bnQrKztcbiAgICAgIGZ1bmN0aW9uIHJlZ2xSZW5kZXJidWZmZXIoYSwgYikge1xuICAgICAgICB2Y
1XIgdyA9IDA7XG4gICAgICAgIHZhciBoID0gMDtcbiAgICAgICAgdmFyIGZvcm1hdCA9IEdMX1JHQkE0JDE7XG4gICAgICAgIGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcgJiYgYSkge1xuICAgICAgICAgIHZhciBvcHRpb25zID0gYTtcbiAgICAgICAgICBpZiAoJ3NoYXBlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB2YXIgc2hhcGUgPSBvcHRpb25zLnNoYXBlO1xuICAgICAgICAgICAgY2hlY2skMShBcnJheS5pc0FycmF5KHNoYXBlKSAmJiBzaGFwZS5sZW5ndGggPj0gMiwgJ2ludmFsaWQgcmVuZGVyYnVmZmVyIHNoYXBlJyk7XG4gICAgICAgICAgICB3ID0gc2hhcGVbMF0gfCAwO1xuICAgICAgICAgICAgaCA9IHNoYXBlWzFdIHwgMDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCdyYWRpdXMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgdyA9IGggPSBvcHRpb25zLnJhZGl1cyB8IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ3dpZHRoJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICAgIHcgPSBvcHRpb25zLndpZHRoIHwgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgnaGVpZ2h0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICAgIGggPSBvcHRpb25zLmhlaWdodCB8IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnZm9ybWF0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLmZvcm1hdCwgZm9ybWF0VHlwZXMsICdpbnZhbGlkIHJlbmRlcmJ1ZmZlciBmb3JtYXQnKTtcbiAgICAgICAgICAgIGZvcm1hdCA9IGZvcm1hdFR5cGVzW29wdGlvbnMuZm9ybWF0XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGEgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgdyA9IGEgfCAwO1xuICAgICAgICAgIGlmICh0eXBlb2YgYiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGggPSBiIHwgMDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaCA9IHc7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCFhKSB7XG4gICAgICAgICAgdyA9IGggPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgYXJndW1lbnRzIHRvIHJlbmRlcmJ1ZmZlciBjb25zdHJ1Y3RvcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2hlY2sgc2hhcGVcbiAgICAgICAgY2hlY2skMSh3ID4gMCAmJiBoID4gMCAmJiB3IDw9IGxpbWl0cy5tYXhSZW5kZXJidWZmZXJTaXplICYmIGggPD0gbGltaXRzLm1heFJlbmRlcmJ1ZmZlclNpemUsICdpbnZhbGlkIHJlbmRlcmJ1ZmZlciBzaXplJyk7XG4gICAgICAgIGlmICh3ID09PSByZW5kZXJidWZmZXIud2lkdGggJiYgaCA9PT0gcmVuZGVyYnVmZmVyLmhlaWdodCAmJiBmb3JtYXQgPT09IHJlbmRlcmJ1ZmZlci5mb3JtYXQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmVnbFJlbmRlcmJ1ZmZlci53aWR0aCA9IHJlbmRlcmJ1ZmZlci53aWR0aCA9IHc7XG4gICAgICAgIHJlZ2xSZW5kZXJidWZmZXIuaGVpZ2h0ID0gcmVuZGVyYnVmZmVyLmhlaWdodCA9IGg7XG4gICAgICAgIHJlbmRlcmJ1ZmZlci5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgICAgIGdsLmJpbmRSZW5kZXJidWZmZXIoR0xfUkVOREVSQlVGRkVSLCByZW5kZXJidWZmZXIucmVuZGVyYnVmZmVyKTtcbiAgICAgICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShHTF9SRU5ERVJCVUZGRVIsIGZvcm1hdCwgdywgaCk7XG4gICAgICAgIGNoZWNrJDEoZ2wuZ2V0RXJyb3IoKSA9PT0gMCwgJ2ludmFsaWQgcmVuZGVyIGJ1ZmZlciBmb3JtYXQnKTtcbiAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgICAgcmVuZGVyYnVmZmVyLnN0YXRzLnNpemUgPSBnZXRSZW5kZXJidWZmZXJTaXplKHJlbmRlcmJ1ZmZlci5mb3JtYXQsIHJlbmRlcmJ1ZmZlci53aWR0aCwgcmVuZGVyYnVmZmVyLmhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5mb3JtYXQgPSBmb3JtYXRUeXBlc0ludmVydFtyZW5kZXJidWZmZXIuZm9ybWF0XTtcbiAgICAgICAgcmV0dXJuIHJlZ2xSZW5kZXJidWZmZXI7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiByZXNpemUod18sIGhfKSB7XG4gICAgICAgIHZhciB3ID0gd18gfCAwO1xuICAgICAgICB2Y
1XIgaCA9IGhfIHwgMCB8fCB3O1xuICAgICAgICBpZiAodyA9PT0gcmVuZGVyYnVmZmVyLndpZHRoICYmIGggPT09IHJlbmRlcmJ1ZmZlci5oZWlnaHQpIHtcbiAgICAgICAgICByZXR1cm4gcmVnbFJlbmRlcmJ1ZmZlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHNoYXBlXG4gICAgICAgIGNoZWNrJDEodyA+IDAgJiYgaCA+IDAgJiYgdyA8PSBsaW1pdHMubWF4UmVuZGVyYnVmZmVyU2l6ZSAmJiBoIDw9IGxpbWl0cy5tYXhSZW5kZXJidWZmZXJTaXplLCAnaW52YWxpZCByZW5kZXJidWZmZXIgc2l6ZScpO1xuICAgICAgICByZWdsUmVuZGVyYnVmZmVyLndpZHRoID0gcmVuZGVyYnVmZmVyLndpZHRoID0gdztcbiAgICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5oZWlnaHQgPSByZW5kZXJidWZmZXIuaGVpZ2h0ID0gaDtcbiAgICAgICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihHTF9SRU5ERVJCVUZGRVIsIHJlbmRlcmJ1ZmZlci5yZW5kZXJidWZmZXIpO1xuICAgICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKEdMX1JFTkRFUkJVRkZFUiwgcmVuZGVyYnVmZmVyLmZvcm1hdCwgdywgaCk7XG4gICAgICAgIGNoZWNrJDEoZ2wuZ2V0RXJyb3IoKSA9PT0gMCwgJ2ludmFsaWQgcmVuZGVyIGJ1ZmZlciBmb3JtYXQnKTtcblxuICAgICAgICAvLyBhbHNvLCByZWNvbXB1dGUgc2l6ZS5cbiAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgICAgcmVuZGVyYnVmZmVyLnN0YXRzLnNpemUgPSBnZXRSZW5kZXJidWZmZXJTaXplKHJlbmRlcmJ1ZmZlci5mb3JtYXQsIHJlbmRlcmJ1ZmZlci53aWR0aCwgcmVuZGVyYnVmZmVyLmhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2xSZW5kZXJidWZmZXI7XG4gICAgICB9XG4gICAgICByZWdsUmVuZGVyYnVmZmVyKGEsIGIpO1xuICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5yZXNpemUgPSByZXNpemU7XG4gICAgICByZWdsUmVuZGVyYnVmZmVyLl9yZWdsVHlwZSA9ICdyZW5kZXJidWZmZXInO1xuICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyID0gcmVuZGVyYnVmZmVyO1xuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHJlZ2xSZW5kZXJidWZmZXIuc3RhdHMgPSByZW5kZXJidWZmZXIuc3RhdHM7XG4gICAgICB9XG4gICAgICByZWdsUmVuZGVyYnVmZmVyLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlbmRlcmJ1ZmZlci5kZWNSZWYoKTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmVnbFJlbmRlcmJ1ZmZlcjtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICBzdGF0cy5nZXRUb3RhbFJlbmRlcmJ1ZmZlclNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgIE9iamVjdC5rZXlzKHJlbmRlcmJ1ZmZlclNldCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgdG90YWwgKz0gcmVuZGVyYnVmZmVyU2V0W2tleV0uc3RhdHMuc2l6ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0b3RhbDtcbiAgICAgIH07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc3RvcmVSZW5kZXJidWZmZXJzKCkge1xuICAgICAgdmFsdWVzKHJlbmRlcmJ1ZmZlclNldCkuZm9yRWFjaChmdW5jdGlvbiAocmIpIHtcbiAgICAgICAgcmIucmVuZGVyYnVmZmVyID0gZ2wuY3JlYXRlUmVuZGVyYnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRSZW5kZXJidWZmZXIoR0xfUkVOREVSQlVGRkVSLCByYi5yZW5kZXJidWZmZXIpO1xuICAgICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKEdMX1JFTkRFUkJVRkZFUiwgcmIuZm9ybWF0LCByYi53aWR0aCwgcmIuaGVpZ2h0KTtcbiAgICAgIH0pO1xuICAgICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihHTF9SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgY3JlYXRlOiBjcmVhdGVSZW5kZXJidWZmZXIsXG4gICAgICBjbGVhcjogZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgIHZhbHVlcyhyZW5kZXJidWZmZXJTZXQpLmZvckVhY2goZGVzdHJveSk7XG4gICAgICB9LFxuICAgICAgcmVzdG9yZTogcmVzdG9yZVJlbmRlcmJ1ZmZlcnNcbiAgICB9O1xuICB9O1xuXG4gIC8vIFdlIHN0b3JlIHRoZXNlIGNvbnN0YW50cyBzbyB0aGF0IHRoZSBtaW5pZmllciBjYW4gaW5saW5lIHRoZW1cbiAgdmFyIEdMX0ZSQU1FQlVGRkVSJDEgPSAweDhENDA7XG4gIHZhciBHTF9SRU5ERVJCVUZGRVIkMSA9IDB4OEQ0MTtcbiAgdmFyIEdMX1RFWFRVUkVfMkQkMiA9IDB4MERFMTtcbiAgdmFyIEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQyID0gMHg4NTE1O1xuICB2YXIgR0xfQ09MT1JfQVRUQUNITUVOVDAkMSA9IDB4OENFMDtcbiAgdmFyIEdMX0RFUFRIX0FUVEFDSE1FTlQgPSAweDhEMDA7XG4gIHZhciBHTF9TVEVOQ0lMX0FUVEFDSE1FTlQgPSAweDhEMjA7XG4gIHZhciBHTF9ERVBUSF9TVEVOQ0lMX0FUVEFDSE1FTlQgPSAweDgyMUE7XG4gIHZhciBHTF9GUkFNRUJVRkZFUl9DT01QTEVURSQxID0gMHg4Q0Q1O1xuICB2YXIgR0xfRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UID0gMHg4Q0Q2O1xuICB2YXIgR0xfRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlQgPSAweDhDRDc7XG4gIHZhciBHTF9GUkFNRUJVRkZFUl9JTkNPTVBMRVRFX0RJTUVOU0lPTlMgPSAweDhDRDk7XG4gIHZhciBHTF9GUkFNRUJVRkZFUl9VTlNVUFBPUlRFRCA9IDB4OENERDtcbiAgdmFyIEdMX0hBTEZfRkxPQVRfT0VTJDIgPSAweDhENjE7XG4gIHZhciBHTF9VTlNJR05FRF9CWVRFJDYgPSAweDE0MDE7XG4gIHZhciBHTF9GTE9BVCQ1ID0gMHgxNDA2O1xuICB2YXIgR0xfUkdCJDEgPSAweDE5MDc7XG4gIHZhciBHTF9SR0JBJDIgPSAweDE5MDg7XG4gIHZhciBHTF9ERVBUSF9DT01QT05FTlQkMSA9IDB4MTkwMjtcbiAgdmFyIGNvbG9yVGV4dHVyZUZvcm1hdEVudW1zID0gW0dMX1JHQiQxLCBHTF9SR0JBJDJdO1xuXG4gIC8vIGZvciBldmVyeSB0ZXh0dXJlIGZvcm1hdCwgc3RvcmVcbiAgLy8gdGhlIG51bWJlciBvZiBjaGFubmVsc1xuICB2YXIgdGV4dHVyZUZvcm1hdENoYW5uZWxzID0gW107XG4gIHRleHR1cmVGb3JtYXRDaGFubmVsc1tHTF9SR0JBJDJdID0gNDtcbiAgdGV4dHVyZUZvcm1hdENoYW5uZWxzW0dMX1JHQiQxXSA9IDM7XG5cbiAgLy8gZm9yIGV2ZXJ5IHRleHR1cmUgdHlwZSwgc3RvcmVcbiAgLy8gdGhlIHNpemUgaW4gYnl0ZXMuXG4gIHZhciB0ZXh0dXJlVHlwZVNpemVzID0gW107XG4gIHRleHR1cmVUeXBlU2l6ZXNbR0xfVU5TSUdORURfQllURSQ2XSA9IDE7XG4gIHRleHR1cmVUeXBlU2l6ZXNbR0xfRkxPQVQkNV0gPSA0O1xuICB0ZXh0dXJlVHlwZVNpemVzW0dMX0hBTEZfRkxPQVRfT0VTJDJdID0gMjtcbiAgdmFyIEdMX1JHQkE0JDIgPSAweDgwNTY7XG4gIHZhciBHTF9SR0I1X0ExJDIgPSAweDgwNTc7XG4gIHZhciBHTF9SR0I1NjUkMiA9IDB4OEQ2MjtcbiAgdmFyIEdMX0RFUFRIX0NPTVBPTkVOVDE2JDEgPSAweDgxQTU7XG4gIHZhciBHTF9TVEVOQ0lMX0lOREVYOCQxID0gMHg4RDQ4O1xuICB2YXIgR0xfREVQVEhfU1RFTkNJTCQyID0gMHg4NEY5O1xuICB2YXIgR0xfU1JHQjhfQUxQSEE4X0VYVCQxID0gMHg4QzQzO1xuICB2YXIgR0xfUkdCQTMyRl9FWFQkMSA9IDB4ODgxNDtcbiAgdmFyIEdMX1JHQkExNkZfRVhUJDEgPSAweDg4MUE7XG4gIHZhciBHTF9SR0IxNkZfRVhUJDEgPSAweDg4MUI7XG4gIHZhciBjb2xvclJlbmRlcmJ1ZmZlckZvcm1hdEVudW1zID0gW0dMX1JHQkE0JDIsIEdMX1JHQjVfQTEkMiwgR0xfUkdCNTY1JDIsIEdMX1NSR0I4X0FMUEhBOF9FWFQkMSwgR0xfUkdCQTE2Rl9FWFQkMSwgR0xfUkdCMTZGX0VYVCQxLCBHTF9SR0JBMzJGX0VYVCQxXTtcbiAgdmFyIHN0YXR1c0NvZGUgPSB7fTtcbiAgc3RhdHVzQ29kZVtHTF9GUkFNRUJVRkZFUl9DT01QTEVURSQxXSA9ICdjb21wbGV0ZSc7XG4gIHN0YXR1c0NvZGVbR0xfRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UXSA9ICdpbmNvbXBsZXRlIGF0dGFjaG1lbnQnO1xuICBzdGF0dXNDb2RlW0dMX0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OU10gPSAnaW5jb21wbGV0ZSBkaW1lbnNpb25zJztcbiAgc3RhdHVzQ29kZVtHTF9GUkFNRUJVRkZFUl9JTkNPTVBMRVRFX01JU1NJTkdfQVRUQUNITUVOVF0gPSAnaW5jb21wbGV0ZSwgbWlzc2luZyBhdHRhY2htZW50JztcbiAgc3RhdHVzQ29kZVtHTF9GUkFNRUJVRkZFUl9VTlNVUFBPUlRFRF0gPSAndW5zdXBwb3J0ZWQnO1xuICBmdW5jdGlvbiB3cmFwRkJPU3RhdGUoZ2wsIGV4dGVuc2lvbnMsIGxpbWl0cywgdGV4dHVyZVN0YXRlLCByZW5kZXJidWZmZXJTdGF0ZSwgc3RhdHMpIHtcbiAgICB2YXIgZnJhbWVidWZmZXJTdGF0ZSA9IHtcbiAgICAgIGN1cjogbnVsbCxcbiAgICAgIG5leHQ6IG51bGwsXG4gICAgICBkaXJ0eTogZmFsc2UsXG4gICAgICBzZXRGQk86IG51bGxcbiAgICB9O1xuICAgIHZhciBjb2xvclRleHR1cmVGb3JtYXRzID0gWydyZ2JhJ107XG4gICAgdmFyIGNvbG9yUmVuZGVyYnVmZmVyRm9ybWF0cyA9IFsncmdiYTQnLCAncmdiNTY1JywgJ3JnYjUgYTEnXTtcbiAgICBpZiAoZXh0ZW5zaW9ucy5leHRfc3JnYikge1xuICAgICAgY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLnB1c2goJ3NyZ2JhJyk7XG4gICAgfVxuICAgIGlmIChleHRlbnNpb25zLmV4dF9jb2xvcl9idWZmZXJfaGFsZl9mbG9hdCkge1xuICAgICAgY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLnB1c2goJ3JnYmExNmYnLCAncmdiMTZmJyk7XG4gICAgfVxuICAgIGlmIChleHRlbnNpb25zLndlYmdsX2NvbG9yX2J1ZmZlcl9mbG9hdCkge1xuICAgICAgY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLnB1c2goJ3JnYmEzMmYnKTtcbiAgICB9XG4gICAgdmFyIGNvbG9yVHlwZXMgPSBbJ3VpbnQ4J107XG4gICAgaWYgKGV4dGVuc2lvbnMub2VzX3RleHR1cmVfaGFsZl9mbG9hdCkge1xuICAgICAgY29sb3JUeXBlcy5wdXNoKCdoYWxmIGZsb2F0JywgJ2Zsb2F0MTYnKTtcbiAgICB9XG4gICAgaWYgKGV4dGVuc2lvbnMub2VzX3RleHR1cmVfZmxvYXQpIHtcbiAgICAgIGNvbG9yVHlwZXMucHVzaCgnZmxvYXQnLCAnZmxvYXQzMicpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBGcmFtZWJ1ZmZlckF0dGFjaG1lbnQodGFyZ2V0LCB0ZXh0dXJlLCByZW5kZXJidWZmZXIpIHtcbiAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgdGhpcy50ZXh0dXJlID0gdGV4dHVyZTtcbiAgICAgIHRoaXMucmVuZGVyYnVmZmVyID0gcmVuZGVyYnVmZmVyO1xuICAgICAgdmFyIHcgPSAwO1xuICAgICAgdmFyIGggPSAwO1xuICAgICAgaWYgKHRleHR1cmUpIHtcbiAgICAgICAgdyA9IHRleHR1cmUud2lkdGg7XG4gICAgICAgIGggPSB0ZXh0dXJlLmhlaWdodDtcbiAgICAgIH0gZWxzZSBpZiAocmVuZGVyYnVmZmVyKSB7XG4gICAgICAgI
1HcgPSByZW5kZXJidWZmZXIud2lkdGg7XG4gICAgICAgIGggPSByZW5kZXJidWZmZXIuaGVpZ2h0O1xuICAgICAgfVxuICAgICAgdGhpcy53aWR0aCA9IHc7XG4gICAgICB0aGlzLmhlaWdodCA9IGg7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY1JlZihhdHRhY2htZW50KSB7XG4gICAgICBpZiAoYXR0YWNobWVudCkge1xuICAgICAgICBpZiAoYXR0YWNobWVudC50ZXh0dXJlKSB7XG4gICAgICAgICAgYXR0YWNobWVudC50ZXh0dXJlLl90ZXh0dXJlLmRlY1JlZigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhdHRhY2htZW50LnJlbmRlcmJ1ZmZlcikge1xuICAgICAgICAgIGF0dGFjaG1lbnQucmVuZGVyYnVmZmVyLl9yZW5kZXJidWZmZXIuZGVjUmVmKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gaW5jUmVmQW5kQ2hlY2tTaGFwZShhdHRhY2htZW50LCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICBpZiAoIWF0dGFjaG1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgICB2YXIgdGV4dHVyZSA9IGF0dGFjaG1lbnQudGV4dHVyZS5fdGV4dHVyZTtcbiAgICAgICAgdmFyIHR3ID0gTWF0aC5tYXgoMSwgdGV4dHVyZS53aWR0aCk7XG4gICAgICAgIHZhciB0aCA9IE1hdGgubWF4KDEsIHRleHR1cmUuaGVpZ2h0KTtcbiAgICAgICAgY2hlY2skMSh0dyA9PT0gd2lkdGggJiYgdGggPT09IGhlaWdodCwgJ2luY29uc2lzdGVudCB3aWR0aC9oZWlnaHQgZm9yIHN1cHBsaWVkIHRleHR1cmUnKTtcbiAgICAgICAgdGV4dHVyZS5yZWZDb3VudCArPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHJlbmRlcmJ1ZmZlciA9IGF0dGFjaG1lbnQucmVuZGVyYnVmZmVyLl9yZW5kZXJidWZmZXI7XG4gICAgICAgIGNoZWNrJDEocmVuZGVyYnVmZmVyLndpZHRoID09PSB3aWR0aCAmJi
1ByZW5kZXJidWZmZXIuaGVpZ2h0ID09PSBoZWlnaHQsICdpbmNvbnNpc3RlbnQgd2lkdGgvaGVpZ2h0IGZvciByZW5kZXJidWZmZXInKTtcbiAgICAgICAgcmVuZGVyYnVmZmVyLnJlZkNvdW50ICs9IDE7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGF0dGFjaChsb2NhdGlvbiwgYXR0YWNobWVudCkge1xuICAgICAgaWYgKGF0dGFjaG1lbnQpIHtcbiAgICAgICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgICAgIGdsLmZyYW1lYnVmZmVyVGV4dHVyZTJEKEdMX0ZSQU1FQlVGRkVSJDEsIGxvY2F0aW9uLCBhdHRhY2htZW50LnRhcmdldCwgYXR0YWNobWVudC50ZXh0dXJlLl90ZXh0dXJlLnRleHR1cmUsIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGdsLmZyYW1lYnVmZmVyUmVuZGVyYnVmZmVyKEdMX0ZSQU1FQlVGRkVSJDEsIGxvY2F0aW9uLCBHTF9SRU5ERVJCVUZGRVIkMSwgYXR0YWNobWVudC5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5yZW5kZXJidWZmZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBhcnNlQXR0YWNobWVudChhdHRhY2htZW50KSB7XG4gICAgICB2YXIgdGFyZ2V0ID0gR0xfVEVYVFVSRV8yRCQyO1xuICAgICAgdmFyIHRleHR1cmUgPSBudWxsO1xuICAgICAgdmFyIHJlbmRlcmJ1ZmZlciA9IG51bGw7XG4gICAgICB2YXIgZGF0YSA9IGF0dGFjaG1lbnQ7XG4gICAgICBpZiAodHlwZW9mIGF0dGFjaG1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGRhdGEgPSBhdHRhY2htZW50LmRhdGE7XG4gICAgICAgIGlmICgndGFyZ2V0JyBpbiBhdHRhY2htZW50KSB7XG4gICAgICAgICAgdGFyZ2V0ID0gYXR0YWNobWVudC50YXJnZXQgfCAwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjaGVjayQxLnR5cGUoZGF0YSwgJ2Z1bmN0aW9uJywgJ2ludmFsaWQgYXR0YWNobWVudCBkYXRhJyk7XG4gICAgICB2Y
1XIgdHlwZSA9IGRhdGEuX3JlZ2xUeXBlO1xuICAgICAgaWYgKHR5cGUgPT09ICd0ZXh0dXJlMmQnKSB7XG4gICAgICAgIHRleHR1cmUgPSBkYXRhO1xuICAgICAgICBjaGVjayQxKHRhcmdldCA9PT0gR0xfVEVYVFVSRV8yRCQyKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3RleHR1cmVDdWJlJykge1xuICAgICAgICB0ZXh0dXJlID0gZGF0YTtcbiAgICAgICAgY2hlY2skMSh0YXJnZXQgPj0gR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIgJiYgdGFyZ2V0IDwgR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIgKyA2LCAnaW52YWxpZCBjdWJlIG1hcCB0YXJnZXQnKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3JlbmRlcmJ1ZmZlcicpIHtcbiAgICAgICAgcmVuZGVyYnVmZmVyID0gZGF0YTtcbiAgICAgICAgdGFyZ2V0ID0gR0xfUkVOREVSQlVGRkVSJDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIHJlZ2wgb2JqZWN0IGZvciBhdHRhY2htZW50Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEZyYW1lYnVmZmVyQXR0YWNobWVudCh0YXJnZXQsIHRleHR1cmUsIHJlbmRlcmJ1ZmZlcik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFsbG9jQXR0YWNobWVudCh3aWR0aCwgaGVpZ2h0LCBpc1RleHR1cmUsIGZvcm1hdCwgdHlwZSkge1xuICAgICAgaWYgKGlzVGV4dHVyZSkge1xuICAgICAgICB2YXIgdGV4dHVyZSA9IHRleHR1cmVTdGF0ZS5jcmVhdGUyRCh7XG4gICAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgIGZvcm1hdDogZm9ybWF0LFxuICAgICAgICAgIHR5cGU6IHR5cGVcbiAgICAgICAgfSk7XG4gICAgICAgIHRleHR1cmUuX3RleHR1cmUucmVmQ291bnQgPSAwO1xuICAgICAgICByZXR1cm4gbmV3IEZyYW1lYnVmZmVyQXR0YWNobWVudChHTF9URVhUVVJFXzJEJDIsIHRleHR1cmUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHJiID0gcmVuZGVyYnVmZmVyU3RhdGUuY3JlYXRlKHtcbiAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgZm9ybWF0OiBmb3JtYXRcbiAgICAgICAgfSk7XG4gICAgICAgIHJiLl9yZW5kZXJidWZmZXIucmVmQ291bnQgPSAwO1xuICAgICAgICByZXR1cm4gbmV3IEZyYW1lYnVmZmVyQXR0YWNobWVudChHTF9SRU5ERVJCVUZGRVIkMSwgbnVsbCwgcmIpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiB1bndyYXBBdHRhY2htZW50KGF0dGFjaG1lbnQpIHtcbiAgICAgIHJldHVybiBhdHRhY2htZW50ICYmIChhdHRhY2htZW50LnRleHR1cmUgfHwgYXR0YWNobWVudC5yZW5kZXJidWZmZXIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNpemVBdHRhY2htZW50KGF0dGFjaG1lbnQsIHcsIGgpIHtcbiAgICAgIGlmIChhdHRhY2htZW50KSB7XG4gICAgICAgIGlmIChhdHRhY2htZW50LnRleHR1cmUpIHtcbiAgICAgICAgICBhdHRhY2htZW50LnRleHR1cmUucmVzaXplKHcsIGgpO1xuICAgICAgICB9IGVsc2UgaWYgKGF0dGFjaG1lbnQucmVuZGVyYnVmZmVyKSB7XG4gICAgICAgICAgYXR0YWNobWVudC5yZW5kZXJidWZmZXIucmVzaXplKHcsIGgpO1xuICAgICAgICB9XG4gICAgICAgIGF0dGFjaG1lbnQud2lkdGggPSB3O1xuICAgICAgICBhdHRhY2htZW50LmhlaWdodCA9IGg7XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBmcmFtZWJ1ZmZlckNvdW50ID0gMDtcbiAgICB2YXIgZnJhbWVidWZmZXJTZXQgPSB7fTtcbiAgICBmdW5jdGlvbiBSRUdMRnJhbWVidWZmZXIoKSB7XG4gICAgICB0aGlzLmlkID0gZnJhbWVidWZmZXJDb3VudCsrO1xuICAgICAgZnJhbWVidWZmZXJTZXRbdGhpcy5pZF0gPSB0aGlzO1xuICAgICAgdGhpcy5mcmFtZWJ1ZmZlciA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgICB0aGlzLndpZHRoID0gMDtcbiAgICAgIHRoaXMuaGVpZ2h0ID0gMDtcbiAgICAgIHRoaXMuY29sb3JBdHRhY2htZW50cyA9IFtdO1xuICAgICAgdGhpcy5kZXB0aEF0dGFjaG1lbnQgPSBudWxsO1xuICAgICAgdGhpcy5zdGVuY2lsQXR0YWNobWVudCA9IG51bGw7XG4gICAgICB0aGlzLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkZWNGQk9SZWZzKGZyYW1lYnVmZmVyKSB7XG4gICAgICBmcmFtZWJ1ZmZlci5jb2xvckF0dGFjaG1lbnRzLmZvckVhY2goZGVjUmVmKTtcbiAgICAgIGRlY1JlZihmcmFtZWJ1ZmZlci5kZXB0aEF0dGFjaG1lbnQpO1xuICAgICAgZGVjUmVmKGZyYW1lYnVmZmVyLnN0ZW5jaWxBdHRhY2htZW50KTtcbiAgICAgIGRlY1JlZihmcmFtZWJ1ZmZlci5kZXB0aFN0ZW5jaWxBdHRhY2htZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gX2Rlc3Ryb3koZnJhbWVidWZmZXIpIHtcbiAgICAgIHZhciBoYW5kbGUgPSBmcmFtZWJ1ZmZlci5mcmFtZWJ1ZmZlcjtcbiAgICAgIGNoZWNrJDEoaGFuZGxlLCAnbXVzdCBub3QgZG91YmxlIGRlc3Ryb3kgZnJhbWVidWZmZXInKTtcbiAgICAgIGdsLmRlbGV0ZUZyYW1lYnVmZmVyKGhhbmRsZSk7XG4gICAgICBmcmFtZWJ1ZmZlci5mcmFtZWJ1ZmZlciA9IG51bGw7XG4gICAgICBzdGF0cy5mcmFtZWJ1ZmZlckNvdW50LS07XG4gICAgICBkZWxldGUgZnJhbWVidWZmZXJTZXRbZnJhbWVidWZmZXIuaWRdO1xuICAgIH1cbiAgICBmdW5jdGlvbiB1cGRhdGVGcmFtZWJ1ZmZlcihmcmFtZWJ1ZmZlcikge1xuICAgICAgdmFyIGk7XG4gICAgICBnbC5iaW5kRnJhbWVidWZmZXIoR0xfRlJBTUVCVUZGRVIkMSwgZnJhbWVidWZmZXIuZnJhbWVidWZmZXIpO1xuICAgICAgdmFyIGNvbG9yQXR0YWNobWVudHMgPSBmcmFtZWJ1ZmZlci5jb2xvckF0dGFjaG1lbnRzO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQXR0YWNobWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgYXR0YWNoKEdMX0NPTE9SX0FUVEFDSE1FTlQwJDEgKyBpLCBjb2xvckF0dGFjaG1lbnRzW2ldKTtcbiAgICAgIH1cbiAgICAgIGZvciAoaSA9IGNvbG9yQXR0YWNobWVudHMubGVuZ3RoOyBpIDwgbGltaXRzLm1heENvbG9yQXR0YWNobWVudHM7ICsraSkge1xuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChHTF9GUkFNRUJVRkZFUiQxLCBHTF9DT0xPUl9BVFRBQ0hNRU5UMCQxICsgaSwgR0xfVEVYVFVSRV8yRCQyLCBudWxsLCAwKTtcbiAgICAgIH1cbiAgICAgIGdsLmZyYW1lYnVmZmVyVGV4dHVyZTJEKEd
1MX0ZSQU1FQlVGRkVSJDEsIEdMX0RFUFRIX1NURU5DSUxfQVRUQUNITUVOVCwgR0xfVEVYVFVSRV8yRCQyLCBudWxsLCAwKTtcbiAgICAgIGdsLmZyYW1lYnVmZmVyVGV4dHVyZTJEKEdMX0ZSQU1FQlVGRkVSJDEsIEdMX0RFUFRIX0FUVEFDSE1FTlQsIEdMX1RFWFRVUkVfMkQkMiwgbnVsbCwgMCk7XG4gICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChHTF9GUkFNRUJVRkZFUiQxLCBHTF9TVEVOQ0lMX0FUVEFDSE1FTlQsIEdMX1RFWFRVUkVfMkQkMiwgbnVsbCwgMCk7XG4gICAgICBhdHRhY2goR0xfREVQVEhfQVRUQUNITUVOVCwgZnJhbWVidWZmZXIuZGVwdGhBdHRhY2htZW50KTtcbiAgICAgIGF0dGFjaChHTF9TVEVOQ0lMX0FUVEFDSE1FTlQsIGZyYW1lYnVmZmVyLnN0ZW5jaWxBdHRhY2htZW50KTtcbiAgICAgIGF0dGFjaChHTF9ERVBUSF9TVEVOQ0lMX0FUVEFDSE1FTlQsIGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQpO1xuXG4gICAgICAvLyBDaGVjayBzdGF0dXMgY29kZVxuICAgICAgdmFyIHN0YXR1cyA9IGdsLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoR0xfRlJBTUVCVUZGRVIkMSk7XG4gICAgICBpZiAoIWdsLmlzQ29udGV4dExvc3QoKSAmJiBzdGF0dXMgIT09IEdMX0ZSQU1FQlVGRkVSX0NPTVBMRVRFJDEpIHtcbiAgICAgICAgY2hlY2skMS5yYWlzZSgnZnJhbWVidWZmZXIgY29uZmlndXJhdGlvbiBub3Qgc3VwcG9ydGVkLCBzdGF0dXMgPSAnICsgc3RhdHVzQ29kZVtzdGF0dXNdKTtcbiAgICAgIH1cbiAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihHTF9GUkFNRUJVRkZFUiQxLCBmcmFtZWJ1ZmZlclN0YXRlLm5leHQgPyBmcmFtZWJ1ZmZlclN0YXRlLm5leHQuZnJhbWVidWZmZXIgOiBudWxsKTtcbiAgICAgIGZyYW1lYnVmZmVyU3R
1hdGUuY3VyID0gZnJhbWVidWZmZXJTdGF0ZS5uZXh0O1xuXG4gICAgICAvLyBGSVhNRTogQ2xlYXIgZXJyb3IgY29kZSBoZXJlLiAgVGhpcyBpcyBhIHdvcmsgYXJvdW5kIGZvciBhIGJ1ZyBpblxuICAgICAgLy8gaGVhZGxlc3MtZ2xcbiAgICAgIGdsLmdldEVycm9yKCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZCTyhhMCwgYTEpIHtcbiAgICAgIHZhciBmcmFtZWJ1ZmZlciA9IG5ldyBSRUdMRnJhbWVidWZmZXIoKTtcbiAgICAgIHN0YXRzLmZyYW1lYnVmZmVyQ291bnQrKztcbiAgICAgIGZ1bmN0aW9uIHJlZ2xGcmFtZWJ1ZmZlcihhLCBiKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBjaGVjayQxKGZyYW1lYnVmZmVyU3RhdGUubmV4dCAhPT0gZnJhbWVidWZmZXIsICdjYW4gbm90IHVwZGF0ZSBmcmFtZWJ1ZmZlciB3aGljaCBpcyBjdXJyZW50bHkgaW4gdXNlJyk7XG4gICAgICAgIHZhciB3aWR0aCA9IDA7XG4gICAgICAgIHZhciBoZWlnaHQgPSAwO1xuICAgICAgICB2YXIgbmVlZHNEZXB0aCA9IHRydWU7XG4gICAgICAgIHZhciBuZWVkc1N0ZW5jaWwgPSB0cnVlO1xuICAgICAgICB2YXIgY29sb3JCdWZmZXIgPSBudWxsO1xuICAgICAgICB2YXIgY29sb3JUZXh0dXJlID0gdHJ1ZTtcbiAgICAgICAgdmFyIGNvbG9yRm9ybWF0ID0gJ3JnYmEnO1xuICAgICAgICB2YXIgY29sb3JUeXBlID0gJ3VpbnQ4JztcbiAgICAgICAgdmFyIGNvbG9yQ291bnQgPSAxO1xuICAgICAgICB2YXIgZGVwdGhCdWZmZXIgPSBudWxsO1xuICAgICAgICB2YXIgc3RlbmNpbEJ1ZmZlciA9IG51bGw7XG4gICAgICAgIHZhciBkZXB0aFN0ZW5jaWxCdWZmZXIgPSBudWxsO1xuICAgICAgICB2Y
1XIgZGVwdGhTdGVuY2lsVGV4dHVyZSA9IGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIGEgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgd2lkdGggPSBhIHwgMDtcbiAgICAgICAgICBoZWlnaHQgPSBiIHwgMCB8fCB3aWR0aDtcbiAgICAgICAgfSBlbHNlIGlmICghYSkge1xuICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ID0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxLnR5cGUoYSwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyBmb3IgZnJhbWVidWZmZXInKTtcbiAgICAgICAgICB2YXIgb3B0aW9ucyA9IGE7XG4gICAgICAgICAgaWYgKCdzaGFwZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIHNoYXBlID0gb3B0aW9ucy5zaGFwZTtcbiAgICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShzaGFwZSkgJiYgc2hhcGUubGVuZ3RoID49IDIsICdpbnZhbGlkIHNoYXBlIGZvciBmcmFtZWJ1ZmZlcicpO1xuICAgICAgICAgICAgd2lkdGggPSBzaGFwZVswXTtcbiAgICAgICAgICAgIGhlaWdodCA9IHNoYXBlWzFdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoJ3JhZGl1cycgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICB3aWR0aCA9IGhlaWdodCA9IG9wdGlvbnMucmFkaXVzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCd3aWR0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICB3aWR0aCA9IG9wdGlvbnMud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ2hlaWdodCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBoZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdjb2xvcicgaW4gb3B0aW9ucyB8fCAnY29sb3JzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjb2xvckJ1ZmZlciA9IG9wdGlvbnMuY29sb3IgfHwgb3B0aW9ucy5jb2xvcnM7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xvckJ1ZmZlcikpIHtcbiAgICAgICAgICAgICAgY2hlY2skMShjb2xvckJ1ZmZlci5sZW5ndGggPT09IDEgfHwgZXh0ZW5zaW9ucy53ZWJnbF9kcmF3X2J1ZmZlcnMsICdtdWx0aXBsZSByZW5kZXIgdGFyZ2V0cyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghY29sb3JCdWZmZXIpIHtcbiAgICAgICAgICAgIGlmICgnY29sb3JDb3VudCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjb2xvckNvdW50ID0gb3B0aW9ucy5jb2xvckNvdW50IHwgMDtcbiAgICAgICAgICAgICAgY2hlY2skMShjb2xvckNvdW50ID4gMCwgJ2ludmFsaWQgY29sb3IgYnVmZmVyIGNvdW50Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ2NvbG9yVGV4dHVyZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjb2xvclRleHR1cmUgPSAhIW9wdGlvbnMuY29sb3JUZXh0dXJlO1xuICAgICAgICAgICAgICBjb2xvckZvcm1hdCA9ICdyZ2JhNCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ2NvbG9yVHlwZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjb2xvclR5cGUgPSBvcHRpb25zLmNvbG9yVHlwZTtcbiAgICAgICAgICAgICAgaWYgKCFjb2xvclRleHR1cmUpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29sb3JUeXBlID09PSAnaGFsZiBmbG9hdCcgfHwgY29sb3JUeXBlID09PSAnZmxvYXQxNicpIHtcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEoZXh0ZW5zaW9ucy5leHRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQsICd5b3UgbXVzdCBlbmFibGUgRVhUX2NvbG9yX2J1ZmZlcl9oYWxmX2Zsb2F0IHRvIHVzZSAxNi1iaXQgcmVuZGVyIGJ1ZmZlcnMnKTtcbiAgICAgICAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gJ3JnYmExNmYnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29sb3JUeXBlID09PSAnZmxvYXQnIHx8IGNvbG9yVHlwZSA9PT0gJ2Zsb2F0MzInKSB7XG4gICAgICAgICAgICAgICAgICBjaGVjayQxKGV4dGVuc2lvbnMud2ViZ2xfY29sb3JfYnVmZmVyX2Zsb2F0LCAneW91IG11c3QgZW5hYmxlIFdFQkdMX2NvbG9yX2J1ZmZlcl9mbG9hdCBpbiBvcmRlciB0byB1c2UgMzItYml0IGZsb2F0aW5nIHBvaW50IHJlbmRlcmJ1ZmZlcnMnKTtcbiAgICAgICAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gJ3JnYmEzMmYnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxKGV4dGVuc2lvbnMub2VzX3RleHR1cmVfZmxvYXQgfHwgIShjb2xvclR5cGUgPT09ICdmbG9hdCcgfHwgY29sb3JUeXBlID09PSAnZmxvYXQzMicpLCAneW91IG11c3QgZW5hYmxlIE9FU190ZXh0dXJlX2Zsb2F0IGluIG9yZGVyIHRvIHVzZSBmbG9hdGluZyBwb2ludCBmcmFtZWJ1ZmZlciBvYmplY3RzJyk7XG4gICAgICAgICAgICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2hhbGZfZmxvYXQgfHwgIShjb2xvclR5cGUgPT09ICdoYWxmIGZsb2F0JyB8fCBjb2xvclR5cGUgPT09ICdmbG9hdDE2JyksICd5b3UgbXVzdCBlbmFibGUgT0VTX3RleHR1cmVfaGFsZl9mbG9hdCBpbiBvcmRlciB0byB1c2UgMTYtYml0IGZsb2F0aW5nIHBvaW50IGZyYW1lYnVmZmVyIG9iamVjdHMnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjaGVjayQxLm9uZU9mKGNvbG9yVHlwZSwgY29sb3JUeXBlcywgJ2ludmFsaWQgY29sb3IgdHlwZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCdjb2xvckZvcm1hdCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICBjb2xvckZvcm1hdCA9IG9wdGlvbnMuY29sb3JGb3JtYXQ7XG4gICAgICAgICAgICAgIGlmIChjb2xvclRleHR1cmVGb3JtYXRzLmluZGV4T2YoY29sb3JGb3JtYXQpID49IDApIHtcbiAgICAgICAgICAgICAgICBjb2xvclRleHR1cmUgPSB0cnVlO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvbG9yUmVuZGVyYnVmZmVyRm9ybWF0cy5pbmRleE9mKGNvbG9yRm9ybWF0KSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgY29sb3JUZXh0dXJlID0gZmFsc2U7XG4gICAgICAgICAgICAgI
1H0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoY29sb3JUZXh0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrJDEub25lT2Yob3B0aW9ucy5jb2xvckZvcm1hdCwgY29sb3JUZXh0dXJlRm9ybWF0cywgJ2ludmFsaWQgY29sb3IgZm9ybWF0IGZvciB0ZXh0dXJlJyk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjaGVjayQxLm9uZU9mKG9wdGlvbnMuY29sb3JGb3JtYXQsIGNvbG9yUmVuZGVyYnVmZmVyRm9ybWF0cywgJ2ludmFsaWQgY29sb3IgZm9ybWF0IGZvciByZW5kZXJidWZmZXInKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2RlcHRoVGV4dHVyZScgaW4gb3B0aW9ucyB8fCAnZGVwdGhTdGVuY2lsVGV4dHVyZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgZGVwdGhTdGVuY2lsVGV4dHVyZSA9ICEhKG9wdGlvbnMuZGVwdGhUZXh0dXJlIHx8IG9wdGlvbnMuZGVwdGhTdGVuY2lsVGV4dHVyZSk7XG4gICAgICAgICAgICBjaGVjayQxKCFkZXB0aFN0ZW5jaWxUZXh0dXJlIHx8IGV4dGVuc2lvbnMud2ViZ2xfZGVwdGhfdGV4dHVyZSwgJ3dlYmdsX2RlcHRoX3RleHR1cmUgZXh0ZW5zaW9uIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdkZXB0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmRlcHRoID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgbmVlZHNEZXB0aCA9IG9wdGlvbnMuZGVwdGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBkZXB0aEJ1ZmZlciA9IG9wdGlvbnMuZGVwdGg7XG4gICAgICAgICAgICAgIG5lZWRzU3RlbmNpbCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ3N0ZW5jaWwnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zdGVuY2lsID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgbmVlZHNTdGVuY2lsID0gb3B0aW9ucy5zdGVuY2lsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgc3RlbmNpbEJ1ZmZlciA9IG9wdGlvbnMuc3RlbmNpbDtcbiAgICAgICAgICAgICAgbmVlZHNEZXB0aCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2RlcHRoU3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmRlcHRoU3RlbmNpbCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgIG5lZWRzRGVwdGggPSBuZWVkc1N0ZW5jaWwgPSBvcHRpb25zLmRlcHRoU3RlbmNpbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGRlcHRoU3RlbmNpbEJ1ZmZlciA9IG9wdGlvbnMuZGVwdGhTdGVuY2lsO1xuICAgICAgICAgICAgICBuZWVkc0RlcHRoID0gZmFsc2U7XG4gICAgICAgICAgICAgIG5lZWRzU3RlbmNpbCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHBhcnNlIGF0dGFjaG1lbnRzXG4gICAgICAgIHZhciBjb2xvckF0dGFjaG1lbnRzID0gbnVsbDtcbiAgICAgICAgdmFyIGRlcHRoQXR0YWNobWVudCA9IG51bGw7XG4gICAgICAgIHZhciBzdGVuY2lsQXR0YWNobWVudCA9IG51bGw7XG4gICAgICAgIHZhciBkZXB0aFN0ZW5jaWxBdHRhY2htZW50ID0gbnVsbDtcblxuICAgICAgICAvLyBTZXQgdXAgY29sb3IgYXR0YWNobWVudHNcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3JCdWZmZXIpKSB7XG4gICAgICAgICAgY29sb3JBdHRhY2htZW50cyA9IGNvbG9yQnVmZmVyLm1hcChwYXJzZUF0dGFjaG1lbnQpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbG9yQnVmZmVyKSB7XG4gICAgICAgICAgY29sb3JBdHRhY2htZW50cyA9IFtwYXJzZUF0dGFjaG1lbnQoY29sb3JCdWZmZXIpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb2xvckF0dGFjaG1lbnRzID0gbmV3IEFycmF5KGNvbG9yQ291bnQpO1xuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2xvckNvdW50OyArK2kpIHtcbiAgICAgICAgICAgIGNvbG9yQXR0YWNobWVudHNbaV0gPSBhbGxvY0F0dGFjaG1lbnQod2lkdGgsIGhlaWdodCwgY29sb3JUZXh0dXJlLCBjb2xvckZvcm1hdCwgY29sb3JUeXBlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2skMShleHRlbnNpb25zLndlYmdsX2RyYXdfYnVmZmVycyB8fCBjb2xvckF0dGFjaG1lbnRzLmxlbmd0aCA8PSAxLCAneW91IG11c3QgZW5hYmxlIHRoZSBXRUJHTF9kcmF3X2J1ZmZlcnMgZXh0ZW5zaW9uIGluIG9yZGVyIHRvIHVzZSBtdWx0aXBsZSBjb2xvciBidWZmZXJzLicpO1xuICAgICAgICBjaGVjayQxKGNvbG9yQXR0YWNobWVudHMubGVuZ3RoIDw9IGxpbWl0cy5tYXhDb2xvckF0dGFjaG1lbnRzLCAndG9vIG1hbnkgY29sb3IgYXR0YWNobWVudHMsIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgd2lkdGggPSB3aWR0aCB8fCBjb2xvckF0dGFjaG1lbnRzWzBdLndpZHRoO1xuICAgICAgICBoZWlnaHQgPSBoZWlnaHQgfHwgY29sb3JBdHRhY2htZW50c1swXS5oZWlnaHQ7XG4gICAgICAgIGlmIChkZXB0aEJ1ZmZlcikge1xuICAgICAgICAgIGRlcHRoQXR0YWNobWVudCA9IHBhcnNlQXR0YWNobWVudChkZXB0aEJ1ZmZlcik7XG4gICAgICAgIH0gZWxzZSBpZiAobmVlZHNEZXB0aCAmJiAhbmVlZHNTdGVuY2lsKSB7XG4gICAgICAgICAgZGVwdGhBdHRhY2htZW50ID0gYWxsb2NBdHRhY2htZW50KHdpZHRoLCBoZWlnaHQsIGRlcHRoU3RlbmNpbFRleHR1cmUsICdkZXB0aCcsICd1aW50MzInKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RlbmNpbEJ1ZmZlcikge1xuICAgICAgICAgIHN0ZW5jaWxBdHRhY2htZW50ID0gcGFyc2VBdHRhY2htZW50KHN0ZW5jaWxCdWZmZXIpO1xuICAgICAgICB9IGVsc2UgaWYgKG5lZWRzU3RlbmNpbCAmJiAhbmVlZHNEZXB0aCkge1xuICAgICAgICAgI
1HN0ZW5jaWxBdHRhY2htZW50ID0gYWxsb2NBdHRhY2htZW50KHdpZHRoLCBoZWlnaHQsIGZhbHNlLCAnc3RlbmNpbCcsICd1aW50OCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZXB0aFN0ZW5jaWxCdWZmZXIpIHtcbiAgICAgICAgICBkZXB0aFN0ZW5jaWxBdHRhY2htZW50ID0gcGFyc2VBdHRhY2htZW50KGRlcHRoU3RlbmNpbEJ1ZmZlcik7XG4gICAgICAgIH0gZWxzZSBpZiAoIWRlcHRoQnVmZmVyICYmICFzdGVuY2lsQnVmZmVyICYmIG5lZWRzU3RlbmNpbCAmJiBuZWVkc0RlcHRoKSB7XG4gICAgICAgICAgZGVwdGhTdGVuY2lsQXR0YWNobWVudCA9IGFsbG9jQXR0YWNobWVudCh3aWR0aCwgaGVpZ2h0LCBkZXB0aFN0ZW5jaWxUZXh0dXJlLCAnZGVwdGggc3RlbmNpbCcsICdkZXB0aCBzdGVuY2lsJyk7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2skMSghIWRlcHRoQnVmZmVyICsgISFzdGVuY2lsQnVmZmVyICsgISFkZXB0aFN0ZW5jaWxCdWZmZXIgPD0gMSwgJ2ludmFsaWQgZnJhbWVidWZmZXIgY29uZmlndXJhdGlvbiwgY2FuIHNwZWNpZnkgZXhhY3RseSBvbmUgZGVwdGgvc3RlbmNpbCBhdHRhY2htZW50Jyk7XG4gICAgICAgIHZhciBjb21tb25Db2xvckF0dGFjaG1lbnRTaXplID0gbnVsbDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQXR0YWNobWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICBpbmNSZWZBbmRDaGVja1NoYXBlKGNvbG9yQXR0YWNobWVudHNbaV0sIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgIGNoZWNrJDEoIWNvbG9yQXR0YWNobWVudHNbaV0gfHwgY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlICYmIGNvbG9yVGV4dHVyZUZvcm1hdEVudW1zLmluZGV4T2YoY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlLl90ZXh0dXJlLmZvcm1hdCkgPj0gMCB8fCBjb2xvckF0dGFjaG1lbnRzW2ldLnJlbmRlcmJ1ZmZlciAmJiBjb2xvclJlbmRlcmJ1ZmZlckZvcm1hdEVudW1zLmluZGV4T2YoY29sb3JBdHRhY2htZW50c1tpXS5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5mb3JtYXQpID49IDAsICdmcmFtZWJ1ZmZlciBjb2xvciBhdHRhY2htZW50ICcgKyBpICsgJyBpcyBpbnZhbGlkJyk7XG4gICAgICAgICAgaWYgKGNvbG9yQXR0YWNobWVudHNbaV0gJiYgY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlKSB7XG4gICAgICAgICAgICB2Y
1XIgY29sb3JBdHRhY2htZW50U2l6ZSA9IHRleHR1cmVGb3JtYXRDaGFubmVsc1tjb2xvckF0dGFjaG1lbnRzW2ldLnRleHR1cmUuX3RleHR1cmUuZm9ybWF0XSAqIHRleHR1cmVUeXBlU2l6ZXNbY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlLl90ZXh0dXJlLnR5cGVdO1xuICAgICAgICAgICAgaWYgKGNvbW1vbkNvbG9yQXR0YWNobWVudFNpemUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgY29tbW9uQ29sb3JBdHRhY2htZW50U2l6ZSA9IGNvbG9yQXR0YWNobWVudFNpemU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbCBjb2xvciBhdHRhY2htZW50cyBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBiaXRwbGFuZXNcbiAgICAgICAgICAgICAgLy8gKHRoYXQgaXMsIHRoZSBzYW1lIG51bWVyIG9mIGJpdHMgcGVyIHBpeGVsKVxuICAgICAgICAgICAgICAvLyBUaGlzIGlzIHJlcXVpcmVkIGJ5IHRoZSBHTEVTMi4wIHN0YW5kYXJkLiBTZWUgdGhlIGJlZ2lubmluZyBvZiBDaGFwdGVyIDQgaW4gdGhhdCBkb2N1bWVudC5cbiAgICAgICAgICAgICAgY2hlY2skMShjb21tb25Db2xvckF0dGFjaG1lbnRTaXplID09PSBjb2xvckF0dGFjaG1lbnRTaXplLCAnYWxsIGNvbG9yIGF0dGFjaG1lbnRzIG11Y2ggaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgYml0cyBwZXIgcGl4ZWwuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGluY1JlZkFuZENoZWNrU2hhcGUoZGVwdGhBdHRhY2htZW50LCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgY2hlY2skMSghZGVwdGhBdHRhY2htZW50IHx8IGRlcHRoQXR0YWNobWVudC50ZXh0dXJlICYmIGRlcHRoQXR0YWNobWVudC50ZXh0dXJlLl90ZXh0dXJlLmZvcm1hdCA9PT0gR0xfREVQVEhfQ09NUE9ORU5UJDEgfHwgZGVwdGhBdHRhY2htZW50LnJlbmRlcmJ1ZmZlciAmJiBkZXB0aEF0dGFjaG1lbnQucmVuZGVyYnVmZmVyLl9yZW5kZXJidWZmZXIuZm9ybWF0ID09PSBHTF9ERVBUSF9DT01QT05FTlQxNiQxLCAnaW52YWxpZCBkZXB0aCBhdHRhY2htZW50IGZvciBmcmFtZWJ1ZmZlciBvYmplY3QnKTtcbiAgICAgICAgaW5jUmVmQW5kQ2hlY2tTaGFwZShzdGVuY2lsQXR0YWNobWVudCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGNoZWNrJDEoIXN0ZW5jaWxBdHRhY2htZW50IHx8IHN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlciAmJiBzdGVuY2lsQXR0YWNobWVudC5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5mb3JtYXQgPT09IEdMX1NURU5DSUxfSU5ERVg4JDEsICdpbnZhbGlkIHN0ZW5jaWwgYXR0YWNobWVudCBmb3IgZnJhbWVidWZmZXIgb2JqZWN0Jyk7XG4gICAgICAgIGluY1JlZkFuZENoZWNrU2hhcGUoZGVwdGhTdGVuY2lsQXR0YWNobWVudCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGNoZWNrJDEoIWRlcHRoU3RlbmNpbEF0dGFjaG1lbnQgfHwgZGVwdGhTdGVuY2lsQXR0YWNobWVudC50ZXh0dXJlICYmIGRlcHRoU3RlbmNpbEF0dGFjaG1lbnQudGV4dHVyZS5fdGV4dHVyZS5mb3JtYXQgPT09IEdMX0RFUFRIX1NURU5DSUwkMiB8fCBkZXB0aFN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlciAmJiBkZXB0aFN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLmZvcm1hdCA9PT0gR0xfREVQVEhfU1RFTkNJTCQyLCAnaW52YWxpZCBkZXB0aC1zdGVuY2lsIGF0dGFjaG1lbnQgZm9yIGZyYW1lYnVmZmVyIG9iamVjdCcpO1xuXG4gICAgICAgIC8vIGRlY3JlbWVudCByZWZlcmVuY2VzXG4gICAgICAgIGRlY0ZCT1JlZnMoZnJhbWVidWZmZXIpO1xuICAgICAgICBmcmFtZWJ1ZmZlci53aWR0aCA9IHdpZHRoO1xuICAgICAgICBmcmFtZWJ1ZmZlci5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGZyYW1lYnVmZmVyLmNvbG9yQXR0YWNobWVudHMgPSBjb2xvckF0dGFjaG1lbnRzO1xuICAgICAgICBmcmFtZWJ1ZmZlci5kZXB0aEF0dGFjaG1lbnQgPSBkZXB0aEF0dGFjaG1lbnQ7XG4gICAgICAgIGZyYW1lYnVmZmVyLnN0ZW5jaWxBdHRhY2htZW50ID0gc3RlbmNpbEF0dGFjaG1lbnQ7XG4gICAgICAgIGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQgPSBkZXB0aFN0ZW5jaWxBdHRhY2htZW50O1xuICAgICAgICByZWdsRnJhbWVidWZmZXIuY29sb3IgPSBjb2xvckF0dGFjaG1lbnRzLm1hcCh1bndyYXBBdHRhY2htZW50KTtcbiAgICAgICAgcmVnbEZyYW1lYnVmZmVyLmRlcHRoID0gdW53cmFwQXR0YWNobWVudChkZXB0aEF0dGFjaG1lbnQpO1xuICAgICAgICByZWdsRnJhbWVidWZmZXIuc3RlbmNpbCA9IHVud3JhcEF0dGFjaG1lbnQoc3RlbmNpbEF0dGFjaG1lbnQpO1xuICAgICAgICByZWdsRnJhbWVidWZmZXIuZGVwdGhTdGVuY2lsID0gdW53cmFwQXR0YWNobWVudChkZXB0aFN0ZW5jaWxBdHRhY2htZW50KTtcbiAgICAgICAgcmVnbEZyYW1lYnVmZmVyLndpZHRoID0gZnJhbWVidWZmZXIud2lkdGg7XG4gICAgICAgIHJlZ2xGcmFtZWJ1ZmZlci5oZWlnaHQgPSBmcmFtZWJ1ZmZlci5oZWlnaHQ7XG4gICAgICAgIHVwZGF0ZUZyYW1lYnVmZmVyKGZyYW1lYnVmZmVyKTtcbiAgICAgICAgcmV0dXJuIHJlZ2xGcmFtZWJ1ZmZlcjtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJlc2l6ZSh3XywgaF8pIHtcbiAgICAgICAgY2hlY2skMShmcmFtZWJ1ZmZlclN0YXRlLm5leHQgIT09IGZyYW1lYnVmZmVyLCAnY2FuIG5vdCByZXNpemUgYSBmcmFtZWJ1ZmZlciB3aGljaCBpcyBjdXJyZW50bHkgaW4gdXNlJyk7XG4gICAgICAgIHZhciB3ID0gTWF0aC5tYXgod18gfCAwLCAxKTtcbiAgICAgICAgdmFyIGggPSBNYXRoLm1heChoXyB8IDAgfHwgdywgMSk7XG4gICAgICAgIGlmICh3ID09PSBmcmFtZWJ1ZmZlci53aWR0aCAmJi
1BoID09PSBmcmFtZWJ1ZmZlci5oZWlnaHQpIHtcbiAgICAgICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVzaXplIGFsbCBidWZmZXJzXG4gICAgICAgIHZhciBjb2xvckF0dGFjaG1lbnRzID0gZnJhbWVidWZmZXIuY29sb3JBdHRhY2htZW50cztcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2xvckF0dGFjaG1lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgcmVzaXplQXR0YWNobWVudChjb2xvckF0dGFjaG1lbnRzW2ldLCB3LCBoKTtcbiAgICAgICAgfVxuICAgICAgICByZXNpemVBdHRhY2htZW50KGZyYW1lYnVmZmVyLmRlcHRoQXR0YWNobWVudCwgdywgaCk7XG4gICAgICAgIHJlc2l6ZUF0dGFjaG1lbnQoZnJhbWVidWZmZXIuc3RlbmNpbEF0dGFjaG1lbnQsIHcsIGgpO1xuICAgICAgICByZXNpemVBdHRhY2htZW50KGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQsIHcsIGgpO1xuICAgICAgICBmcmFtZWJ1ZmZlci53aWR0aCA9IHJlZ2xGcmFtZWJ1ZmZlci53aWR0aCA9IHc7XG4gICAgICAgIGZyYW1lYnVmZmVyLmhlaWdodCA9IHJlZ2xGcmFtZWJ1ZmZlci5oZWlnaHQgPSBoO1xuICAgICAgICB1cGRhdGVGcmFtZWJ1ZmZlcihmcmFtZWJ1ZmZlcik7XG4gICAgICAgIHJldHVybiByZWdsRnJhbWVidWZmZXI7XG4gICAgICB9XG4gICAgICByZWdsRnJhbWVidWZmZXIoYTAsIGExKTtcbiAgICAgIHJldHVybiBleHRlbmQocmVnbEZyYW1lYnVmZmVyLCB7XG4gICAgICAgIHJlc2l6ZTogcmVzaXplLFxuICAgICAgICBfcmVnbFR5cGU6ICdmcmFtZWJ1ZmZlcicsXG4gICAgICAgIF9mcmFtZWJ1ZmZlcjogZnJhbWVidWZmZXIsXG4gICAgICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgX2Rlc3Ryb3koZnJhbWVidWZmZXIpO1xuICAgICAgICAgIGRlY0ZCT1JlZnMoZnJhbWVidWZmZXIpO1xuICAgICAgICB9LFxuICAgICAgICB1c2U6IGZ1bmN0aW9uIHVzZShibG9jaykge1xuICAgICAgICAgIGZyYW1lYnVmZmVyU3R
1hdGUuc2V0RkJPKHtcbiAgICAgICAgICAgIGZyYW1lYnVmZmVyOiByZWdsRnJhbWVidWZmZXJcbiAgICAgICAgICB9LCBibG9jayk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVDdWJlRkJPKG9wdGlvbnMpIHtcbiAgICAgIHZhciBmYWNlcyA9IEFycmF5KDYpO1xuICAgICAgZnVuY3Rpb24gcmVnbEZyYW1lYnVmZmVyQ3ViZShhKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBjaGVjayQxKGZhY2VzLmluZGV4T2YoZnJhbWVidWZmZXJTdGF0ZS5uZXh0KSA8IDAsICdjYW4gbm90IHVwZGF0ZSBmcmFtZWJ1ZmZlciB3aGljaCBpcyBjdXJyZW50bHkgaW4gdXNlJyk7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgY29sb3I6IG51bGxcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHJhZGl1cyA9IDA7XG4gICAgICAgIHZhciBjb2xvckJ1ZmZlciA9IG51bGw7XG4gICAgICAgIHZhciBjb2xvckZvcm1hdCA9ICdyZ2JhJztcbiAgICAgICAgdmFyIGNvbG9yVHlwZSA9ICd1aW50OCc7XG4gICAgICAgIHZhciBjb2xvckNvdW50ID0gMTtcbiAgICAgICAgaWYgKHR5cGVvZiBhID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHJhZGl1cyA9IGEgfCAwO1xuICAgICAgICB9IGVsc2UgaWYgKCFhKSB7XG4gICAgICAgICAgcmFkaXVzID0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxLnR5cGUoYSwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyBmb3IgZnJhbWVidWZmZXInKTtcbiAgICAgICAgICB2Y
1XIgb3B0aW9ucyA9IGE7XG4gICAgICAgICAgaWYgKCdzaGFwZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIHNoYXBlID0gb3B0aW9ucy5zaGFwZTtcbiAgICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShzaGFwZSkgJiYgc2hhcGUubGVuZ3RoID49IDIsICdpbnZhbGlkIHNoYXBlIGZvciBmcmFtZWJ1ZmZlcicpO1xuICAgICAgICAgICAgY2hlY2skMShzaGFwZVswXSA9PT0gc2hhcGVbMV0sICdjdWJlIGZyYW1lYnVmZmVyIG11c3QgYmUgc3F1YXJlJyk7XG4gICAgICAgICAgICByYWRpdXMgPSBzaGFwZVswXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCdyYWRpdXMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXMgfCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCd3aWR0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICByYWRpdXMgPSBvcHRpb25zLndpZHRoIHwgMDtcbiAgICAgICAgICAgICAgaWYgKCdoZWlnaHQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxKG9wdGlvbnMuaGVpZ2h0ID09PSByYWRpdXMsICdtdXN0IGJlIHNxdWFyZScpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCdoZWlnaHQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgcmFkaXVzID0gb3B0aW9ucy5oZWlnaHQgfCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2NvbG9yJyBpbiBvcHRpb25zIHx8ICdjb2xvcnMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbG9yQnVmZmVyID0gb3B0aW9ucy5jb2xvciB8fCBvcHRpb25zLmNvbG9ycztcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9yQnVmZmVyKSkge1xuICAgICAgICAgICAgICBjaGVjayQxKGNvbG9yQnVmZmVyLmxlbmd0aCA9PT0gMSB8fCBleHRlbnNpb25zLndlYmdsX2RyYXdfYnVmZmVycywgJ211bHRpcGxlIHJlbmRlciB0YXJnZXRzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFjb2xvckJ1ZmZlcikge1xuICAgICAgICAgICAgaWYgKCdjb2xvckNvdW50JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICAgIGNvbG9yQ291bnQgPSBvcHRpb25zLmNvbG9yQ291bnQgfCAwO1xuICAgICAgICAgICAgICBjaGVjayQxKGNvbG9yQ291bnQgPiAwLCAnaW52YWxpZCBjb2xvciBidWZmZXIgY291bnQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgnY29sb3JUeXBlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEub25lT2Yob3B0aW9ucy5jb2xvclR5cGUsIGNvbG9yVHlwZXMsICdpbnZhbGlkIGNvbG9yIHR5cGUnKTtcbiAgICAgICAgICAgICAgY29sb3JUeXBlID0gb3B0aW9ucy5jb2xvclR5cGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ2NvbG9yRm9ybWF0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gb3B0aW9ucy5jb2xvckZvcm1hdDtcbiAgICAgICAgICAgICAgY2hlY2skMS5vbmVPZihvcHRpb25zLmNvbG9yRm9ybWF0LCBjb2xvclRleHR1cmVGb3JtYXRzLCAnaW52YWxpZCBjb2xvciBmb3JtYXQgZm9yIHRleHR1cmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdkZXB0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgcGFyYW1zLmRlcHRoID0gb3B0aW9ucy5kZXB0aDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdzdGVuY2lsJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBwYXJhbXMuc3RlbmNpbCA9IG9wdGlvbnMuc3RlbmNpbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdkZXB0aFN0ZW5jaWwnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHBhcmFtcy5kZXB0aFN0ZW5jaWwgPSBvcHRpb25zLmRlcHRoU3RlbmNpbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbG9yQ3ViZXM7XG4gICAgICAgIGlmIChjb2xvckJ1ZmZlcikge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9yQnVmZmVyKSkge1xuICAgICAgICAgICAgY29sb3JDdWJlcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQnVmZmVyLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgIGNvbG9yQ3ViZXNbaV0gPSBjb2xvckJ1ZmZlcltpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29sb3JDdWJlcyA9IFtjb2xvckJ1ZmZlcl07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbG9yQ3ViZXMgPSBBcnJheShjb2xvckNvdW50KTtcbiAgICAgICAgICB2Y
1XIgY3ViZU1hcFBhcmFtcyA9IHtcbiAgICAgICAgICAgIHJhZGl1czogcmFkaXVzLFxuICAgICAgICAgICAgZm9ybWF0OiBjb2xvckZvcm1hdCxcbiAgICAgICAgICAgIHR5cGU6IGNvbG9yVHlwZVxuICAgICAgICAgIH07XG4gICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQ291bnQ7ICsraSkge1xuICAgICAgICAgICAgY29sb3JDdWJlc1tpXSA9IHRleHR1cmVTdGF0ZS5jcmVhdGVDdWJlKGN1YmVNYXBQYXJhbXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGNvbG9yIGN1YmVzXG4gICAgICAgIHBhcmFtcy5jb2xvciA9IEFycmF5KGNvbG9yQ3ViZXMubGVuZ3RoKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQ3ViZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICB2YXIgY3ViZSA9IGNvbG9yQ3ViZXNbaV07XG4gICAgICAgICAgY2hlY2skMSh0eXBlb2YgY3ViZSA9PT0gJ2Z1bmN0aW9uJyAmJiBjdWJlLl9yZWdsVHlwZSA9PT0gJ3RleHR1cmVDdWJlJywgJ2ludmFsaWQgY3ViZSBtYXAnKTtcbiAgICAgICAgICByYWRpdXMgPSByYWRpdXMgfHwgY3ViZS53aWR0aDtcbiAgICAgICAgICBjaGVjayQxKGN1YmUud2lkdGggPT09IHJhZGl1cyAmJiBjdWJlLmhlaWdodCA9PT0gcmFkaXVzLCAnaW52YWxpZCBjdWJlIG1hcCBzaGFwZScpO1xuICAgICAgICAgIHBhcmFtcy5jb2xvcltpXSA9IHtcbiAgICAgICAgICAgIHRhcmdldDogR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIsXG4gICAgICAgICAgICBkYXRhOiBjb2xvckN1YmVzW2ldXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjb2xvckN1YmVzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBwYXJhbXMuY29sb3Jbal0udGFyZ2V0ID0gR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIgKyBpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyByZXVzZSBkZXB0aC1zdGVuY2lsIGF0dGFjaG1lbnRzIGFjcm9zcyBhbGwgY3ViZSBtYXBzXG4gICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICBwYXJhbXMuZGVwdGggPSBmYWNlc1swXS5kZXB0aDtcbiAgICAgICAgICAgIHBhcmFtcy5zdGVuY2lsID0gZmFjZXNbMF0uc3RlbmNpbDtcbiAgICAgICAgICAgIHBhcmFtcy5kZXB0aFN0ZW5jaWwgPSBmYWNlc1swXS5kZXB0aFN0ZW5jaWw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChmYWNlc1tpXSkge1xuICAgICAgICAgICAgZmFjZXNbaV0ocGFyYW1zKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmFjZXNbaV0gPSBjcmVhdGVGQk8ocGFyYW1zKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGV4dGVuZChyZWdsRnJhbWVidWZmZXJDdWJlLCB7XG4gICAgICAgICAgd2lkdGg6IHJhZGl1cyxcbiAgICAgICAgICBoZWlnaHQ6IHJhZGl1cyxcbiAgICAgICAgICBjb2xvcjogY29sb3JDdWJlc1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJlc2l6ZShyYWRpdXNfKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2Y
1XIgcmFkaXVzID0gcmFkaXVzXyB8IDA7XG4gICAgICAgIGNoZWNrJDEocmFkaXVzID4gMCAmJiByYWRpdXMgPD0gbGltaXRzLm1heEN1YmVNYXBTaXplLCAnaW52YWxpZCByYWRpdXMgZm9yIGN1YmUgZmJvJyk7XG4gICAgICAgIGlmIChyYWRpdXMgPT09IHJlZ2xGcmFtZWJ1ZmZlckN1YmUud2lkdGgpIHtcbiAgICAgICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyQ3ViZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sb3JzID0gcmVnbEZyYW1lYnVmZmVyQ3ViZS5jb2xvcjtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9ycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGNvbG9yc1tpXS5yZXNpemUocmFkaXVzKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgZmFjZXNbaV0ucmVzaXplKHJhZGl1cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmVnbEZyYW1lYnVmZmVyQ3ViZS53aWR0aCA9IHJlZ2xGcmFtZWJ1ZmZlckN1YmUuaGVpZ2h0ID0gcmFkaXVzO1xuICAgICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyQ3ViZTtcbiAgICAgIH1cbiAgICAgIHJlZ2xGcmFtZWJ1ZmZlckN1YmUob3B0aW9ucyk7XG4gICAgICByZXR1cm4gZXh0ZW5kKHJlZ2xGcmFtZWJ1ZmZlckN1YmUsIHtcbiAgICAgICAgZmFjZXM6IGZhY2VzLFxuICAgICAgICByZXNpemU6IHJlc2l6ZSxcbiAgICAgICAgX3JlZ2xUeXBlOiAnZnJhbWVidWZmZXJDdWJlJyxcbiAgICAgICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICBmYWNlcy5mb3JFYWNoKGZ1bmN0aW9uIChmKSB7XG4gICAgICAgICAgICBmLmRlc3Ryb3koKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc3RvcmVGcmFtZWJ1ZmZlcnMoKSB7XG4gICAgICBmcmFtZWJ1ZmZlclN0YXRlLmN1ciA9IG51bGw7XG4gICAgICBmcmFtZWJ1ZmZlclN0YXRlLm5leHQgPSBudWxsO1xuICAgICAgZnJhbWVidWZmZXJTdGF0ZS5kaXJ0eSA9IHRydWU7XG4gICAgICB2YWx1ZXMoZnJhbWVidWZmZXJTZXQpLmZvckVhY2goZnVuY3Rpb24gKGZiKSB7XG4gICAgICAgIGZiLmZyYW1lYnVmZmVyID0gZ2wuY3JlYXRlRnJhbWVidWZmZXIoKTtcbiAgICAgICAgdXBkYXRlRnJhbWVidWZmZXIoZmIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBleHRlbmQoZnJhbWVidWZmZXJTdGF0ZSwge1xuICAgICAgZ2V0RnJhbWVidWZmZXI6IGZ1bmN0aW9uIGdldEZyYW1lYnVmZmVyKG9iamVjdCkge1xuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gJ2Z1bmN0aW9uJyAmJiBvYmplY3QuX3JlZ2xUeXBlID09PSAnZnJhbWVidWZmZXInKSB7XG4gICAgICAgICAgdmFyIGZibyA9IG9iamVjdC5fZnJhbWVidWZmZXI7XG4gICAgICAgICAgaWYgKGZibyBpbnN0YW5jZW9mIFJFR0xGcmFtZWJ1ZmZlcikge1xuICAgICAgICAgICAgcmV0dXJuIGZibztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9LFxuICAgICAgY3JlYXRlOiBjcmVhdGVGQk8sXG4gICAgICBjcmVhdGVDdWJlOiBjcmVhdGVDdWJlRkJPLFxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICB2YWx1ZXMoZnJhbWVidWZmZXJTZXQpLmZvckVhY2goX2Rlc3Ryb3kpO1xuICAgICAgfSxcbiAgICAgIHJlc3RvcmU6IHJlc3RvcmVGcmFtZWJ1ZmZlcnNcbiAgICB9KTtcbiAgfVxuICB2YXIgR0xfRkxPQVQkNiA9IDUxMjY7XG4gIHZhciBHTF9BUlJBWV9CVUZGRVIkMSA9IDM0OTYyO1xuICB2YXIgR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMSA9IDM0OTYzO1xuICB2YXIgVkFPX09QVElPTlMgPSBbJ2F0dHJpYnV0ZXMnLCAnZWxlbWVudHMnLCAnb2Zmc2V0JywgJ2NvdW50JywgJ3ByaW1pdGl2ZScsICdpbnN0YW5jZXMnXTtcbiAgZnVuY3Rpb24gQXR0cmlidXRlUmVjb3JkKCkge1xuICAgIHRoaXMuc3RhdGUgPSAwO1xuICAgIHRoaXMueCA9IDAuMDtcbiAgICB0aGlzLnkgPSAwLjA7XG4gICAgdGhpcy56ID0gMC4wO1xuICAgIHRoaXMudyA9IDAuMDtcbiAgICB0aGlzLmJ1ZmZlciA9IG51bGw7XG4gICAgdGhpcy5zaXplID0gMDtcbiAgICB0aGlzLm5vcm1hbGl6ZWQgPSBmYWxzZTtcbiAgICB0aGlzLnR5cGUgPSBHTF9GTE9BVCQ2O1xuICAgIHRoaXMub2Zmc2V0ID0gMDtcbiAgICB0aGlzLnN0cmlkZSA9IDA7XG4gICAgdGhpcy5kaXZpc29yID0gMDtcbiAgfVxuICBmdW5jdGlvbiB3cmFwQXR0cmlidXRlU3RhdGUoZ2wsIGV4dGVuc2lvbnMsIGxpbWl0cywgc3RhdHMsIGJ1ZmZlclN0YXRlLCBlbGVtZW50U3RhdGUsIGRyYXdTdGF0ZSkge1xuICAgIHZhciBOVU1fQVRUUklCVVRFUyA9IGxpbWl0cy5tYXhBdHRyaWJ1dGVzO1xuICAgIHZhciBhdHRyaWJ1dGVCaW5kaW5ncyA9IG5ldyBBcnJheShOVU1fQVRUUklCVVRFUyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBOVU1fQVRUUklCVVRFUzsgKytpKSB7XG4gICAgICBhdHRyaWJ1dGVCaW5kaW5nc1tpXSA9IG5ldyBBdHRyaWJ1dGVSZWNvcmQoKTtcbiAgICB9XG4gICAgdmFyIHZhb0NvdW50ID0gMDtcbiAgICB2YXIgdmFvU2V0ID0ge307XG4gICAgdmFyIHN0YXRlID0ge1xuICAgICAgUmVjb3JkOiBBdHRyaWJ1dGVSZWNvcmQsXG4gICAgICBzY29wZToge30sXG4gICAgICBzdGF0ZTogYXR0cmlidXRlQmluZGluZ3MsXG4gICAgICBjdXJyZW50VkFPOiBudWxsLFxuICAgICAgdGFyZ2V0VkFPOiBudWxsLFxuICAgICAgcmVzdG9yZTogZXh0VkFPKCkgPyByZXN0b3JlVkFPIDogZnVuY3Rpb24gKCkge30sXG4gICAgICBjcmVhdGVWQU86IGNyZWF0ZVZBTyxcbiAgICAgIGdldFZBTzogZ2V0VkFPLFxuICAgICAgZGVzdHJveUJ1ZmZlcjogZGVzdHJveUJ1ZmZlcixcbiAgICAgIHNldFZBTzogZXh0VkFPKCkgPyBzZXRWQU9FWFQgOiBzZXRWQU9FbXVsYXRlZCxcbiAgICAgIGNsZWFyOiBleHRWQU8oKSA/IGRlc3Ryb3lWQU9FWFQgOiBmdW5jdGlvbiAoKSB7fVxuICAgIH07XG4gICAgZnVuY3Rpb24gZGVzdHJveUJ1ZmZlcihidWZmZXIpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cmlidXRlQmluZGluZ3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHJlY29yZCA9IGF0dHJpYnV0ZUJpbmRpbmdzW2ldO1xuICAgICAgICBpZiAocmVjb3JkLmJ1ZmZlciA9PT0gYnVmZmVyKSB7XG4gICAgICAgICAgZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpO1xuICAgICAgICAgI
1HJlY29yZC5idWZmZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGV4dFZBTygpIHtcbiAgICAgIHJldHVybiBleHRlbnNpb25zLm9lc192ZXJ0ZXhfYXJyYXlfb2JqZWN0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBleHRJbnN0YW5jZWQoKSB7XG4gICAgICByZXR1cm4gZXh0ZW5zaW9ucy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzO1xuICAgIH1cbiAgICBmdW5jdGlvbiBnZXRWQU8odmFvKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbyA9PT0gJ2Z1bmN0aW9uJyAmJiB2YW8uX3Zhbykge1xuICAgICAgICByZXR1cm4gdmFvLl92YW87XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2V0VkFPRVhUKHZhbykge1xuICAgICAgaWYgKHZhbyA9PT0gc3RhdGUuY3VycmVudFZBTykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgZXh0ID0gZXh0VkFPKCk7XG4gICAgICBpZiAodmFvKSB7XG4gICAgICAgIGV4dC5iaW5kVmVydGV4QXJyYXlPRVModmFvLnZhbyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleHQuYmluZFZlcnRleEFycmF5T0VTKG51bGwpO1xuICAgICAgfVxuICAgICAgc3RhdGUuY3VycmVudFZBTyA9IHZhbztcbiAgICB9XG4gICAgZnVuY3Rpb24gc2V0VkFPRW11bGF0ZWQodmFvKSB7XG4gICAgICBpZiAodmFvID09PSBzdGF0ZS5jdXJyZW50VkFPKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICh2YW8pIHtcbiAgICAgICAgdmFvLmJpbmRBdHRycygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGV4dGkgPSBleHRJbnN0YW5jZWQoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVCaW5kaW5ncy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlQmluZGluZ3NbaV07XG4gICAgICAgICAgaWYgKGJpbmRpbmcuYnVmZmVyKSB7XG4gICAgICAgICAgICBnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShpKTtcbiAgICAgICAgICAgIGJpbmRpbmcuYnVmZmVyLmJpbmQoKTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoaSwgYmluZGluZy5zaXplLCBiaW5kaW5nLnR5cGUsIGJpbmRpbmcubm9ybWFsaXplZCwgYmluZGluZy5zdHJpZGUsIGJpbmRpbmcub2ZmZnNldCk7XG4gICAgICAgICAgICBpZiAoZXh0aSAmJiBiaW5kaW5nLmRpdmlzb3IpIHtcbiAgICAgICAgICAgICAgZXh0aS52ZXJ0ZXhBdHRyaWJEaXZpc29yQU5HTEUoaSwgYmluZGluZy5kaXZpc29yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpO1xuICAgICAgICAgICAgZ2wudmVydGV4QXR0cmliNGYoaSwgYmluZGluZy54LCBiaW5kaW5nLnksIGJpbmRpbmcueiwgYmluZGluZy53KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRyYXdTdGF0ZS5lbGVtZW50cykge1xuICAgICAgICAgIGdsLmJpbmRCdWZmZXIoR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMSwgZHJhd1N0YXRlLmVsZW1lbnRzLmJ1ZmZlci5idWZmZXIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGdsLmJpbmRCdWZmZXIoR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YXRlLmN1cnJlbnRWQU8gPSB2YW87XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlc3Ryb3lWQU9FWFQoKSB7XG4gICAgICB2YWx1ZXModmFvU2V0KS5mb3JFYWNoKGZ1bmN0aW9uICh2YW8pIHtcbiAgICAgICAgdmFvLmRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBSRUdMVkFPKCkge1xuICAgICAgdGhpcy5pZCA9ICsrdmFvQ291bnQ7XG4gICAgICB0aGlzLmF0dHJpYnV0ZXMgPSBbXTtcbiAgICAgIHRoaXMuZWxlbWVudHMgPSBudWxsO1xuICAgICAgdGhpcy5vd25zRWxlbWVudHMgPSBmYWxzZTtcbiAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgdGhpcy5vZmZzZXQgPSAwO1xuICAgICAgdGhpcy5pbnN0YW5jZXMgPSAtMTtcbiAgICAgIHRoaXMucHJpbWl0aXZlID0gNDtcbiAgICAgIHZhciBleHRlbnNpb24gPSBleHRWQU8oKTtcbiAgICAgIGlmIChleHRlbnNpb24pIHtcbiAgICAgICAgdGhpcy52YW8gPSBleHRlbnNpb24uY3JlYXRlVmVydGV4QXJyYXlPRVMoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudmFvID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhb1NldFt0aGlzLmlkXSA9IHRoaXM7XG4gICAgICB0aGlzLmJ1ZmZlcnMgPSBbXTtcbiAgICB9XG4gICAgUkVHTFZBTy5wcm90b3R5cGUuYmluZEF0dHJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGV4dGkgPSBleHRJbnN0YW5jZWQoKTtcbiAgICAgIHZhciBhdHRyaWJ1dGVzID0gdGhpcy5hdHRyaWJ1dGVzO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBhdHRyID0gYXR0cmlidXRlc1tpXTtcbiAgICAgICAgaWYgKGF0dHIuYnVmZmVyKSB7XG4gICAgICAgICAgZ2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoaSk7XG4gICAgICAgICAgZ2wuYmluZEJ1ZmZlcihHTF9BUlJBWV9CVUZGRVIkMSwgYXR0ci5idWZmZXIuYnVmZmVyKTtcbiAgICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGksIGF0dHIuc2l6ZSwgYXR0ci50eXBlLCBhdHRyLm5vcm1hbGl6ZWQsIGF0dHIuc3RyaWRlLCBhdHRyLm9mZnNldCk7XG4gICAgICAgICAgaWYgKGV4dGkgJiYgYXR0ci5kaXZpc29yKSB7XG4gICAgICAgICAgICBleHRpLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRShpLCBhdHRyLmRpdmlzb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSk7XG4gICAgICAgICAgZ2wudmVydGV4QXR0cmliNGYoaSwgYXR0ci54LCBhdHRyLnksIGF0dHIueiwgYX
1R0ci53KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yICh2YXIgaiA9IGF0dHJpYnV0ZXMubGVuZ3RoOyBqIDwgTlVNX0FUVFJJQlVURVM7ICsraikge1xuICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaik7XG4gICAgICB9XG4gICAgICB2YXIgZWxlbWVudHMgPSBlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHModGhpcy5lbGVtZW50cyk7XG4gICAgICBpZiAoZWxlbWVudHMpIHtcbiAgICAgICAgZ2wuYmluZEJ1ZmZlcihHTF9FTEVNRU5UX0FSUkFZX0JVRkZFUiQxLCBlbGVtZW50cy5idWZmZXIuYnVmZmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMSwgbnVsbCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBSRUdMVkFPLnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGV4dCA9IGV4dFZBTygpO1xuICAgICAgaWYgKGV4dCkge1xuICAgICAgICBleHQuYmluZFZlcnRleEFycmF5T0VTKHRoaXMudmFvKTtcbiAgICAgICAgdGhpcy5iaW5kQXR0cnMoKTtcbiAgICAgICAgc3RhdGUuY3VycmVudFZBTyA9IG51bGw7XG4gICAgICAgIGV4dC5iaW5kVmVydGV4QXJyYXlPRVMobnVsbCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBSRUdMVkFPLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKHRoaXMudmFvKSB7XG4gICAgICAgIHZhciBleHRlbnNpb24gPSBleHRWQU8oKTtcbiAgICAgICAgaWYgKHRoaXMgPT09IHN0YXRlLmN1cnJlbnRWQU8pIHtcbiAgICAgICAgICBzdGF0ZS5jdXJyZW50VkFPID0gbnVsbDtcbiAgICAgICAgICBleHRlbnNpb24uYmluZFZlcnRleEFycmF5T0VTKG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIGV4dGVuc2lvbi5kZWxldGVWZXJ0ZXhBcnJheU9FUyh0aGlzLnZhbyk7XG4gICAgICAgIHRoaXMudmFvID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLm93bnNFbGVtZW50cykge1xuICAgICAgICB0aGlzLmVsZW1lbnRzLmRlc3Ryb3koKTtcbiAgICAgICAgdGhpcy5lbGVtZW50cyA9IG51bGw7XG4gICAgICAgIHRoaXMub3duc0VsZW1lbnRzID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAodmFvU2V0W3RoaXMuaWRdKSB7XG4gICAgICAgIGRlbGV0ZSB2YW9TZXRbdGhpcy5pZF07XG4gICAgICAgIHN0YXRzLnZhb0NvdW50IC09IDE7XG4gICAgICB9XG4gICAgfTtcbiAgICBmdW5jdGlvbiByZXN0b3JlVkFPKCkge1xuICAgICAgdmFyIGV4dCA9IGV4dFZBTygpO1xuICAgICAgaWYgKGV4dCkge1xuICAgICAgICB2YWx1ZXModmFvU2V0KS5mb3JFYWNoKGZ1bmN0aW9uICh2YW8pIHtcbiAgICAgICAgICB2YW8ucmVmcmVzaCgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlVkFPKF9hdHRyKSB7XG4gICAgICB2Y
1XIgdmFvID0gbmV3IFJFR0xWQU8oKTtcbiAgICAgIHN0YXRzLnZhb0NvdW50ICs9IDE7XG4gICAgICBmdW5jdGlvbiB1cGRhdGVWQU8ob3B0aW9ucykge1xuICAgICAgICB2YXIgYXR0cmlidXRlcztcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzID0gb3B0aW9ucztcbiAgICAgICAgICBpZiAodmFvLmVsZW1lbnRzICYmIHZhby5vd25zRWxlbWVudHMpIHtcbiAgICAgICAgICAgIHZhby5lbGVtZW50cy5kZXN0cm95KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhby5lbGVtZW50cyA9IG51bGw7XG4gICAgICAgICAgdmFvLm93bnNFbGVtZW50cyA9IGZhbHNlO1xuICAgICAgICAgIHZhby5vZmZzZXQgPSAwO1xuICAgICAgICAgIHZhby5jb3VudCA9IDA7XG4gICAgICAgICAgdmFvLmluc3RhbmNlcyA9IC0xO1xuICAgICAgICAgIHZhby5wcmltaXRpdmUgPSA0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoZWNrJDEodHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnLCAnaW52YWxpZCBhcmd1bWVudHMgZm9yIGNyZWF0ZSB2YW8nKTtcbiAgICAgICAgICBjaGVjayQxKCdhdHRyaWJ1dGVzJyBpbiBvcHRpb25zLCAnbXVzdCBzcGVjaWZ5IGF0dHJpYnV0ZXMgZm9yIHZhbycpO1xuICAgICAgICAgIGlmIChvcHRpb25zLmVsZW1lbnRzKSB7XG4gICAgICAgICAgICB2YXIgZWxlbWVudHMgPSBvcHRpb25zLmVsZW1lbnRzO1xuICAgICAgICAgICAgaWYgKHZhby5vd25zRWxlbWVudHMpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBlbGVtZW50cyA9PT0gJ2Z1bmN0aW9uJyAmJiBlbGVtZW50cy5fcmVnbFR5cGUgPT09ICdlbGVtZW50cycpIHtcbiAgICAgICAgICAgICAgICB2YW8uZWxlbWVudHMuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHZhby5vd25zRWxlbWVudHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YW8uZWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgICAgICAgICAgIHZhby5vd25zRWxlbWVudHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHMob3B0aW9ucy5lbGVtZW50cykpIHtcbiAgICAgICAgICAgICAgdmFvLmVsZW1lbnRzID0gb3B0aW9ucy5lbGVtZW50cztcbiAgICAgICAgICAgICAgdmFvLm93bnNFbGVtZW50cyA9IGZhbHNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmFvLmVsZW1lbnRzID0gZWxlbWVudFN0YXRlLmNyZWF0ZShvcHRpb25zLmVsZW1lbnRzKTtcbiAgICAgICAgICAgICAgdmFvLm93bnNFbGVtZW50cyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhby5lbGVtZW50cyA9IG51bGw7XG4gICAgICAgICAgICB2YW8ub3duc0VsZW1lbnRzID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF0dHJpYnV0ZXMgPSBvcHRpb25zLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgICAvLyBzZXQgZGVmYXVsdCB2YW9cbiAgICAgICAgICB2YW8ub2Zmc2V0ID0gMDtcbiAgICAgICAgICB2YW8uY291bnQgPSAtMTtcbiAgICAgICAgICB2YW8uaW5zdGFuY2VzID0gLTE7XG4gICAgICAgICAgdmFvLnByaW1pdGl2ZSA9IDQ7XG5cbiAgICAgICAgICAvLyBjb3B5IGVsZW1lbnQgcHJvcGVydGllc1xuICAgICAgICAgIGlmICh2YW8uZWxlbWVudHMpIHtcbiAgICAgICAgICAgIHZhby5jb3VudCA9IHZhby5lbGVtZW50cy5fZWxlbWVudHMudmVydENvdW50O1xuICAgICAgICAgICAgdmFvLnByaW1pdGl2ZSA9IHZhby5lbGVtZW50cy5fZWxlbWVudHMucHJpbVR5cGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnb2Zmc2V0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB2YW8ub2Zmc2V0ID0gb3B0aW9ucy5vZmZzZXQgfCAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2NvdW50JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB2YW8uY291bnQgPSBvcHRpb25zLmNvdW50IHwgMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCdpbnN0YW5jZXMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhby5pbnN0YW5jZXMgPSBvcHRpb25zLmluc3RhbmNlcyB8IDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgncHJpbWl0aXZlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxKG9wdGlvbnMucHJpbWl0aXZlIGluIHByaW1UeXBlcywgJ2JhZCBwcmltaXRpdmUgdHlwZTogJyArIG9wdGlvbnMucHJpbWl0aXZlKTtcbiAgICAgICAgICAgIHZhby5wcmltaXRpdmUgPSBwcmltVHlwZXNbb3B0aW9ucy5wcmltaXRpdmVdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob3B0aW9ucyk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgY2hlY2skMShWQU9fT1BUSU9OUy5pbmRleE9mKGtleXNbaV0pID49IDAsICdpbnZhbGlkIG9wdGlvbiBmb3IgdmFvOiBcIicgKyBrZXlzW2ldICsgJ1wiIHZhbGlkIG9wdGlvbnMgYXJlICcgKyBWQU9fT1BUSU9OUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY2hlY2skMShBcnJheS5pc0FycmF5KGF0dHJpYnV0ZXMpLCAnYXR0cmlidXRlcyBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2skMShhdHRyaWJ1dGVzLmxlbmd0aCA8IE5VTV9BVFRSSUJVVEVTLCAndG9vIG1hbnkgYXR0cmlidXRlcycpO1xuICAgICAgICBjaGVjayQxKGF0dHJpYnV0ZXMubGVuZ3RoID4gMCwgJ211c3Qgc3BlY2lmeSBhdCBsZWFzdCBvbmUgYXR0cmlidXRlJyk7XG4gICAgICAgIHZhciBidWZVcGRhdGVkID0ge307XG4gICAgICAgIHZhciBuYXR0cmlidXRlcyA9IHZhby5hdHRyaWJ1dGVzO1xuICAgICAgICBuYXR0cmlidXRlcy5sZW5ndGggPSBhdHRyaWJ1dGVzLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgdmFyIHNwZWMgPSBhdHRyaWJ1dGVzW2ldO1xuICAgICAgICAgI
1HZhciByZWMgPSBuYXR0cmlidXRlc1tpXSA9IG5ldyBBdHRyaWJ1dGVSZWNvcmQoKTtcbiAgICAgICAgICB2YXIgZGF0YSA9IHNwZWMuZGF0YSB8fCBzcGVjO1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpIHx8IGlzVHlwZWRBcnJheShkYXRhKSB8fCBpc05EQXJyYXlMaWtlKGRhdGEpKSB7XG4gICAgICAgICAgICB2YXIgYnVmO1xuICAgICAgICAgICAgaWYgKHZhby5idWZmZXJzW2ldKSB7XG4gICAgICAgICAgICAgIGJ1ZiA9IHZhby5idWZmZXJzW2ldO1xuICAgICAgICAgICAgICBpZiAoaXNUeXBlZEFycmF5KGRhdGEpICYmIGJ1Zi5fYnVmZmVyLmJ5dGVMZW5ndGggPj0gZGF0YS5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYnVmLnN1YmRhdGEoZGF0YSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnVmLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB2YW8uYnVmZmVyc1tpXSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdmFvLmJ1ZmZlcnNbaV0pIHtcbiAgICAgICAgICAgICAgYnVmID0gdmFvLmJ1ZmZlcnNbaV0gPSBidWZmZXJTdGF0ZS5jcmVhdGUoc3BlYywgR0xfQVJSQVlfQlVGRkVSJDEsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlYy5idWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIoYnVmKTtcbiAgICAgICAgICAgIHJlYy5zaXplID0gcmVjLmJ1ZmZlci5kaW1lbnNpb24gfCAwO1xuICAgICAgICAgICAgcmVjLm5vcm1hbGl6ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlYy50eXBlID0gcmVjLmJ1ZmZlci5kdHlwZTtcbiAgICAgICAgICAgIHJlYy5vZmZzZXQgPSAwO1xuICAgICAgICAgICAgcmVjLnN0cmlkZSA9IDA7XG4gICAgICAgICAgICByZWMuZGl2aXNvciA9IDA7XG4gICAgICAgICAgICByZWMuc3RhdGUgPSAxO1xuICAgICAgICAgICAgYnVmVXBkYXRlZFtpXSA9IDE7XG4gICAgICAgICAgfSBlbHNlIGlmIChidWZmZXJTdGF0ZS5nZXRCdWZmZXIoc3BlYykpIHtcbiAgICAgICAgICAgIHJlYy5idWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIoc3BlYyk7XG4gICAgICAgICAgICByZWMuc2l6ZSA9IHJlYy5idWZmZXIuZGltZW5zaW9uIHwgMDtcbiAgICAgICAgICAgIHJlYy5ub3JtYWxpemVkID0gZmFsc2U7XG4gICAgICAgICAgICByZWMudHlwZSA9IHJlYy5idWZmZXIuZHR5cGU7XG4gICAgICAgICAgICByZWMub2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIHJlYy5zdHJpZGUgPSAwO1xuICAgICAgICAgICAgcmVjLmRpdmlzb3IgPSAwO1xuICAgICAgICAgICAgcmVjLnN0YXRlID0gMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGJ1ZmZlclN0YXRlLmdldEJ1ZmZlcihzcGVjLmJ1ZmZlcikpIHtcbiAgICAgICAgICAgIHJlYy5idWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIoc3BlYy5idWZmZXIpO1xuICAgICAgICAgICAgcmVjLnNpemUgPSAoK3NwZWMuc2l6ZSB8fCByZWMuYnVmZmVyLmRpbWVuc2lvbikgfCAwO1xuICAgICAgICAgICAgcmVjLm5vcm1hbGl6ZWQgPSAhIXNwZWMubm9ybWFsaXplZCB8fCBmYWxzZTtcbiAgICAgICAgICAgIGlmICgndHlwZScgaW4gc3BlYykge1xuICAgICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihzcGVjLnR5cGUsIGdsVHlwZXMsICdpbnZhbGlkIGJ1ZmZlciB0eXBlJyk7XG4gICAgICAgICAgICAgIHJlYy50eXBlID0gZ2xUeXBlc1tzcGVjLnR5cGVdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmVjLnR5cGUgPSByZWMuYnVmZmVyLmR0eXBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVjLm9mZnNldCA9IChzcGVjLm9mZnNldCB8fCAwKSB8IDA7XG4gICAgICAgICAgICByZWMuc3RyaWRlID0gKHNwZWMuc3RyaWRlIHx8IDApIHwgMDtcbiAgICAgICAgICAgIHJlYy5kaXZpc29yID0gKHNwZWMuZGl2aXNvciB8fCAwKSB8IDA7XG4gICAgICAgICAgICByZWMuc3RhdGUgPSAxO1xuICAgICAgICAgICAgY2hlY2skMShyZWMuc2l6ZSA+PSAxICYmIHJlYy5zaXplIDw9IDQsICdzaXplIG11c3QgYmUgYmV0d2VlbiAxIGFuZCA0Jyk7XG4gICAgICAgICAgICBjaGVjayQxKHJlYy5vZmZzZXQgPj0gMCwgJ2ludmFsaWQgb2Zmc2V0Jyk7XG4gICAgICAgICAgICBjaGVjayQxKHJlYy5zdHJpZGUgPj0gMCAmJiByZWMuc3RyaWRlIDw9IDI1NSwgJ3N0cmlkZSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMjU1Jyk7XG4gICAgICAgICAgICBjaGVjayQxKHJlYy5kaXZpc29yID49IDAsICdkaXZpc29yIG11c3QgYmUgcG9zaXRpdmUnKTtcbiAgICAgICAgICAgIGNoZWNrJDEoIXJlYy5kaXZpc29yIHx8ICEhZXh0ZW5zaW9ucy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzLCAnQU5HTEVfaW5zdGFuY2VkX2FycmF5cyBtdXN0IGJlIGVuYWJsZWQgdG8gdXNlIGRpdmlzb3InKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKCd4JyBpbiBzcGVjKSB7XG4gICAgICAgICAgICBjaGVjayQxKGkgPiAwLCAnZmlyc3QgYXR0cmlidXRlIG11c3Qgbm90IGJlIGEgY29uc3RhbnQnKTtcbiAgICAgICAgICAgIHJlYy54ID0gK3NwZWMueCB8fCAwO1xuICAgICAgICAgICAgcmVjLnkgPSArc3BlYy55IHx8IDA7XG4gICAgICAgICAgICByZWMueiA9ICtzcGVjLnogfHwgMDtcbiAgICAgICAgICAgIHJlYy53ID0gK3NwZWMudyB8fCAwO1xuICAgICAgICAgICAgcmVjLnN0YXRlID0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMShmYWxzZSwgJ2ludmFsaWQgYXR0cmlidXRlIHNwZWMgZm9yIGxvY2F0aW9uICcgKyBpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZXRpcmUgdW51c2VkIGJ1ZmZlcnNcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCB2YW8uYnVmZmVycy5sZW5ndGg7ICsraikge1xuICAgICAgICAgIGlmICghYnVmVXBkYXRlZFtqXSAmJiB2YW8uYnVmZmVyc1tqXSkge1xuICAgICAgICAgICAgdmFvLmJ1ZmZlcnNbal0uZGVzdHJveSgpO1xuICAgICAgICAgICAgdmFvLmJ1ZmZlcnNbal0gPSBudWxsO1xuICAgICAgICAgI
1H1cbiAgICAgICAgfVxuICAgICAgICB2YW8ucmVmcmVzaCgpO1xuICAgICAgICByZXR1cm4gdXBkYXRlVkFPO1xuICAgICAgfVxuICAgICAgdXBkYXRlVkFPLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmFvLmJ1ZmZlcnMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICBpZiAodmFvLmJ1ZmZlcnNbal0pIHtcbiAgICAgICAgICAgIHZhby5idWZmZXJzW2pdLmRlc3Ryb3koKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFvLmJ1ZmZlcnMubGVuZ3RoID0gMDtcbiAgICAgICAgaWYgKHZhby5vd25zRWxlbWVudHMpIHtcbiAgICAgICAgICB2YW8uZWxlbWVudHMuZGVzdHJveSgpO1xuICAgICAgICAgIHZhby5lbGVtZW50cyA9IG51bGw7XG4gICAgICAgICAgdmFvLm93bnNFbGVtZW50cyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhby5kZXN0cm95KCk7XG4gICAgICB9O1xuICAgICAgdXBkYXRlVkFPLl92YW8gPSB2YW87XG4gICAgICB1cGRhdGVWQU8uX3JlZ2xUeXBlID0gJ3Zhbyc7XG4gICAgICByZXR1cm4gdXBkYXRlVkFPKF9hdHRyKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG4gIHZhciBHTF9GUkFHTUVOVF9TSEFERVIgPSAzNTYzMjtcbiAgdmFyIEdMX1ZFUlRFWF9TSEFERVIgPSAzNTYzMztcbiAgdmFyIEdMX0FDVElWRV9VTklGT1JNUyA9IDB4OEI4NjtcbiAgdmFyIEdMX0FDVElWRV9BVFRSSUJVVEVTID0gMHg4Qjg5O1xuICBmdW5jdGlvbiB3cmFwU2hhZGVyU3RhdGUoZ2wsIHN0cmluZ1N0b3JlLCBzdGF0cywgY29uZmlnKSB7XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gZ2xzbCBjb21waWxhdGlvbiBhbmQgbGlua2luZ1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIHZhciBmcmFnU2hhZGVycyA9IHt9O1xuICAgIHZhciB2ZXJ0U2hhZGVycyA9IHt9O1xuICAgIGZ1bmN0aW9uIEFjdGl2ZUluZm8obmFtZSwgaWQsIGxvY2F0aW9uLCBpbmZvKSB7XG4gICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgdGhpcy5sb2NhdGlvbiA9IGxvY2F0aW9uO1xuICAgICAgdGhpcy5pbmZvID0gaW5mbztcbiAgICB9XG4gICAgZnVuY3Rpb24gaW5zZXJ0QWN0aXZlSW5mbyhsaXN0LCBpbmZvKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKGxpc3RbaV0uaWQgPT09IGluZm8uaWQpIHtcbiAgICAgICAgICBsaXN0W2ldLmxvY2F0aW9uID0gaW5mby5sb2NhdGlvbjtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxpc3QucHVzaChpbmZvKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZ2V0U2hhZGVyKHR5cGUsIGlkLCBjb21tYW5kKSB7XG4gICAgICB2Y
1XIgY2FjaGUgPSB0eXBlID09PSBHTF9GUkFHTUVOVF9TSEFERVIgPyBmcmFnU2hhZGVycyA6IHZlcnRTaGFkZXJzO1xuICAgICAgdmFyIHNoYWRlciA9IGNhY2hlW2lkXTtcbiAgICAgIGlmICghc2hhZGVyKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBzdHJpbmdTdG9yZS5zdHIoaWQpO1xuICAgICAgICBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgIGdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNvdXJjZSk7XG4gICAgICAgIGdsLmNvbXBpbGVTaGFkZXIoc2hhZGVyKTtcbiAgICAgICAgY2hlY2skMS5zaGFkZXJFcnJvcihnbCwgc2hhZGVyLCBzb3VyY2UsIHR5cGUsIGNvbW1hbmQpO1xuICAgICAgICBjYWNoZVtpZF0gPSBzaGFkZXI7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIHByb2dyYW0gbGlua2luZ1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIHZhciBwcm9ncmFtQ2FjaGUgPSB7fTtcbiAgICB2YXIgcHJvZ3JhbUxpc3QgPSBbXTtcbiAgICB2YXIgUFJPR1JBTV9DT1VOVEVSID0gMDtcbiAgICBmdW5jdGlvbiBSRUdMUHJvZ3JhbShmcmFnSWQsIHZlcnRJZCkge1xuICAgICAgdGhpcy5pZCA9IFBST0dSQU1fQ09VTlRFUisrO1xuICAgICAgdGhpcy5mcmFnSWQgPSBmcmFnSWQ7XG4gICAgICB0aGlzLnZlcnRJZCA9IHZlcnRJZDtcbiAgICAgIHRoaXMucHJvZ3JhbSA9IG51bGw7XG4gICAgICB0aGlzLnVuaWZvcm1zID0gW107XG4gICAgICB0aGlzLmF0dHJpYnV0ZXMgPSBbXTtcbiAgICAgIHRoaXMucmVmQ291bnQgPSAxO1xuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHRoaXMuc3RhdHMgPSB7XG4gICAgICAgICAgdW5pZm9ybXNDb3VudDogMCxcbiAgICAgICAgICBhdHRyaWJ1dGVzQ291bnQ6IDBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gbGlua1Byb2dyYW0oZGVzYywgY29tbWFuZCwgYXR0cmlidXRlTG9jYXRpb25zKSB7XG4gICAgICB2Y
1XIgaSwgaW5mbztcblxuICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgLy8gY29tcGlsZSAmIGxpbmtcbiAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgIHZhciBmcmFnU2hhZGVyID0gZ2V0U2hhZGVyKEdMX0ZSQUdNRU5UX1NIQURFUiwgZGVzYy5mcmFnSWQpO1xuICAgICAgdmFyIHZlcnRTaGFkZXIgPSBnZXRTaGFkZXIoR0xfVkVSVEVYX1NIQURFUiwgZGVzYy52ZXJ0SWQpO1xuICAgICAgdmFyIHByb2dyYW0gPSBkZXNjLnByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnJhZ1NoYWRlcik7XG4gICAgICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgdmVydFNoYWRlcik7XG4gICAgICBpZiAoYXR0cmlidXRlTG9jYXRpb25zKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBhdHRyaWJ1dGVMb2NhdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICB2YXIgYmluZGluZyA9IGF0dHJpYnV0ZUxvY2F0aW9uc1tpXTtcbiAgICAgICAgICBnbC5iaW5kQXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgYmluZGluZ1swXSwgYmluZGluZ1sxXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuICAgICAgY2hlY2skMS5saW5rRXJyb3IoZ2wsIHByb2dyYW0sIHN0cmluZ1N0b3JlLnN0cihkZXNjLmZyYWdJZCksIHN0cmluZ1N0b3JlLnN0cihkZXNjLnZlcnRJZCksIGNvbW1hbmQpO1xuXG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAvLyBncmFiIHVuaWZvcm1zXG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICB2Y
1XIgbnVtVW5pZm9ybXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIEdMX0FDVElWRV9VTklGT1JNUyk7XG4gICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgICAgZGVzYy5zdGF0cy51bmlmb3Jtc0NvdW50ID0gbnVtVW5pZm9ybXM7XG4gICAgICB9XG4gICAgICB2YXIgdW5pZm9ybXMgPSBkZXNjLnVuaWZvcm1zO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG51bVVuaWZvcm1zOyArK2kpIHtcbiAgICAgICAgaW5mbyA9IGdsLmdldEFjdGl2ZVVuaWZvcm0ocHJvZ3JhbSwgaSk7XG4gICAgICAgIGlmIChpbmZvKSB7XG4gICAgICAgICAgaWYgKGluZm8uc2l6ZSA+IDEpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgaW5mby5zaXplOyArK2opIHtcbiAgICAgICAgICAgICAgdmFyIG5hbWUgPSBpbmZvLm5hbWUucmVwbGFjZSgnWzBdJywgJ1snICsgaiArICddJyk7XG4gICAgICAgICAgICAgIGluc2VydEFjdGl2ZUluZm8odW5pZm9ybXMsIG5ldyBBY3RpdmVJbmZvKG5hbWUsIHN0cmluZ1N0b3JlLmlkKG5hbWUpLCBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgbmFtZSksIGluZm8pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5zZXJ0QWN0aXZlSW5mbyh1bmlmb3JtcywgbmV3IEFjdGl2ZUluZm8oaW5mby5uYW1lLCBzdHJpbmdTdG9yZS5pZChpbmZvLm5hbWUpLCBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgaW5mby5uYW1lKSwgaW5mbykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAvLyBncmFiIGF0dHJpYnV0ZXNcbiAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgIHZhciBudW1BdHRyaWJ1dGVzID0gZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcihwcm9ncmFtLCBHTF9BQ1RJVkVfQVRUUklCVVRFUyk7XG4gICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgICAgZGVzYy5zdGF0cy5hdHRyaWJ1dGVzQ291bnQgPSBudW1BdHRyaWJ1dGVzO1xuICAgICAgfVxuICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBkZXNjLmF0dHJpYnV0ZXM7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQXR0cmlidXRlczsgKytpKSB7XG4gICAgICAgIGluZm8gPSBnbC5nZXRBY3RpdmVBdHRyaWIocHJvZ3JhbSwgaSk7XG4gICAgICAgIGlmIChpbmZvKSB7XG4gICAgICAgICAgaW5zZXJ0QWN0aXZlSW5mbyhhdHRyaWJ1dGVzLCBuZXcgQWN0aXZlSW5mbyhpbmZvLm5hbWUsIHN0cmluZ1N0b3JlLmlkKGluZm8ubmFtZSksIGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIGluZm8ubmFtZSksIGluZm8pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgIHN0YXRzLmdldE1heFVuaWZvcm1zQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtID0gMDtcbiAgICAgICAgcHJvZ3JhbUxpc3QuZm9yRWFjaChmdW5jdGlvbiAoZGVzYykge1xuICAgICAgICAgIGlmIChkZXNjLnN0YXRzLnVuaWZvcm1zQ291bnQgPiBtKSB7XG4gICAgICAgICAgICBtID0gZGVzYy5zdGF0cy51bmlmb3Jtc0NvdW50O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfTtcbiAgICAgIHN0YXRzLmdldE1heEF0dHJpYnV0ZXNDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG0gPSAwO1xuICAgICAgICBwcm9ncmFtTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChkZXNjKSB7XG4gICAgICAgICAgaWYgKGRlc2Muc3RhdHMuYXR0cmlidXRlc0NvdW50ID4gbSkge1xuICAgICAgICAgICAgbSA9IGRlc2Muc3RhdHMuYXR0cmlidXRlc0NvdW50O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzdG9yZVNoYWRlcnMoKSB7XG4gICAgICBmcmFnU2hhZGVycyA9IHt9O1xuICAgICAgdmVydFNoYWRlcnMgPSB7fTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvZ3JhbUxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgbGlua1Byb2dyYW0ocHJvZ3JhbUxpc3RbaV0sIG51bGwsIHByb2dyYW1MaXN0W2ldLmF0dHJpYnV0ZXMubWFwKGZ1bmN0aW9uIChpbmZvKSB7XG4gICAgICAgICAgcmV0dXJuIFtpbmZvLmxvY2F0aW9uLCBpbmZvLm5hbWVdO1xuICAgICAgICB9KSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjbGVhcjogZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgIHZhciBkZWxldGVTaGFkZXIgPSBnbC5kZWxldGVTaGFkZXIuYmluZChnbCk7XG4gICAgICAgIHZhbHVlcyhmcmFnU2hhZGVycykuZm9yRWFjaChkZWxldGVTaGFkZXIpO1xuICAgICAgICBmcmFnU2hhZGVycyA9IHt9O1xuICAgICAgICB2YWx1ZXModmVydFNoYWRlcnMpLmZvckVhY2goZGVsZXRlU2hhZGVyKTtcbiAgICAgICAgdmVydFNoYWRlcnMgPSB7fTtcbiAgICAgICAgcHJvZ3JhbUxpc3QuZm9yRWFjaChmdW5jdGlvbiAoZGVzYykge1xuICAgICAgICAgIGdsLmRlbGV0ZVByb2dyYW0oZGVzYy5wcm9ncmFtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHByb2dyYW1MaXN0Lmxlbmd0aCA9IDA7XG4gICAgICAgIHByb2dyYW1DYWNoZSA9IHt9O1xuICAgICAgICBzdGF0cy5zaGFkZXJDb3VudCA9IDA7XG4gICAgICB9LFxuICAgICAgcHJvZ3JhbTogZnVuY3Rpb24gcHJvZ3JhbSh2ZXJ0SWQsIGZyYWdJZCwgY29tbWFuZCwgYXR0cmliTG9jYXRpb25zKSB7XG4gICAgICAgIGNoZWNrJDEuY29tbWFuZCh2ZXJ0SWQgPj0gMCwgJ21pc3NpbmcgdmVydGV4IHNoYWRlcicsIGNvbW1hbmQpO1xuICAgICAgICBjaGVjayQxLmNvbW1hbmQoZnJhZ0lkID49IDAsICdtaXNzaW5nIGZyYWdtZW50IHNoYWRlcicsIGNvbW1hbmQpO1xuICAgICAgICB2Y
1XIgY2FjaGUgPSBwcm9ncmFtQ2FjaGVbZnJhZ0lkXTtcbiAgICAgICAgaWYgKCFjYWNoZSkge1xuICAgICAgICAgIGNhY2hlID0gcHJvZ3JhbUNhY2hlW2ZyYWdJZF0gPSB7fTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJldlByb2dyYW0gPSBjYWNoZVt2ZXJ0SWRdO1xuICAgICAgICBpZiAocHJldlByb2dyYW0pIHtcbiAgICAgICAgICBwcmV2UHJvZ3JhbS5yZWZDb3VudCsrO1xuICAgICAgICAgIGlmICghYXR0cmliTG9jYXRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJldlByb2dyYW07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBwcm9ncmFtID0gbmV3IFJFR0xQcm9ncmFtKGZyYWdJZCwgdmVydElkKTtcbiAgICAgICAgc3RhdHMuc2hhZGVyQ291bnQrKztcbiAgICAgICAgbGlua1Byb2dyYW0ocHJvZ3JhbSwgY29tbWFuZCwgYXR0cmliTG9jYXRpb25zKTtcbiAgICAgICAgaWYgKCFwcmV2UHJvZ3JhbSkge1xuICAgICAgICAgIGNhY2hlW3ZlcnRJZF0gPSBwcm9ncmFtO1xuICAgICAgICB9XG4gICAgICAgIHByb2dyYW1MaXN0LnB1c2gocHJvZ3JhbSk7XG4gICAgICAgIHJldHVybiBleHRlbmQocHJvZ3JhbSwge1xuICAgICAgICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgICBwcm9ncmFtLnJlZkNvdW50LS07XG4gICAgICAgICAgICBpZiAocHJvZ3JhbS5yZWZDb3VudCA8PSAwKSB7XG4gICAgICAgICAgICAgIGdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbS5wcm9ncmFtKTtcbiAgICAgICAgICAgICAgdmFyIGlkeCA9IHByb2dyYW1MaXN0LmluZGV4T2YocHJvZ3JhbSk7XG4gICAgICAgICAgICAgIHByb2dyYW1MaXN0LnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICBzdGF0cy5zaGFkZXJDb3VudC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbm8gcHJvZ3JhbSBpcyBsaW5rZWQgdG8gdGhpcyB2ZXJ0IGFueW1vcmVcbiAgICAgICAgICAgIGlmIChjYWNoZVtwcm9ncmFtLnZlcnRJZF0ucmVmQ291bnQgPD0gMCkge1xuICAgICAgICAgICAgICBnbC5kZWxldGVTaGFkZXIodmVydFNoYWRlcnNbcHJvZ3JhbS52ZXJ0SWRdKTtcbiAgICAgICAgICAgICAgZGVsZXRlIHZlcnRTaGFkZXJzW3Byb2dyYW0udmVydElkXTtcbiAgICAgICAgICAgICAgZGVsZXRlIHByb2dyYW1DYWNoZVtwcm9ncmFtLmZyYWdJZF1bcHJvZ3JhbS52ZXJ0SWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbm8gcHJvZ3JhbSBpcyBsaW5rZWQgdG8gdGhpcyBmcmFnIGFueW1vcmVcbiAgICAgICAgICAgIGlmICghT2JqZWN0LmtleXMocHJvZ3JhbUNhY2hlW3Byb2dyYW0uZnJhZ0lkXSkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGdsLmRlbGV0ZVNoYWRlcihmcmFnU2hhZGVyc1twcm9ncmFtLmZyYWdJZF0pO1xuICAgICAgICAgICAgICBkZWxldGUgZnJhZ1NoYWRlcnNbcHJvZ3JhbS5mcmFnSWRdO1xuICAgICAgICAgICAgICBkZWxldGUgcHJvZ3JhbUNhY2hlW3Byb2dyYW0uZnJhZ0lkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIHJlc3RvcmU6IHJlc3RvcmVTaGFkZXJzLFxuICAgICAgc2hhZGVyOiBnZXRTaGFkZXIsXG4gICAgICBmcmFnOiAtMSxcbiAgICAgIHZlcnQ6IC0xXG4gICAgfTtcbiAgfVxuICB2YXIgR0xfUkdCQSQzID0gNjQwODtcbiAgdmFyIEdMX1VOU0lHTkVEX0JZVEUkNyA9IDUxMjE7XG4gIHZhciBHTF9QQUNLX0FMSUdOTUVOVCA9IDB4MEQwNTtcbiAgdmFyIEdMX0ZMT0FUJDcgPSAweDE0MDY7IC8vIDUxMjZcblxuICBmdW5jdGlvbiB3cmFwUmVhZFBpeGVscyhnbCwgZnJhbWVidWZmZXJTdGF0ZSwgcmVnbFBvbGwsIGNvbnRleHQsIGdsQXR0cmlidXRlcywgZXh0ZW5zaW9ucywgbGltaXRzKSB7XG4gICAgZnVuY3Rpb24gcmVhZFBpeGVsc0ltcGwoaW5wdXQpIHtcbiAgICAgIHZhciB0eXBlO1xuICAgICAgaWYgKGZyYW1lYnVmZmVyU3R
1hdGUubmV4dCA9PT0gbnVsbCkge1xuICAgICAgICBjaGVjayQxKGdsQXR0cmlidXRlcy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXIsICd5b3UgbXVzdCBjcmVhdGUgYSB3ZWJnbCBjb250ZXh0IHdpdGggXCJwcmVzZXJ2ZURyYXdpbmdCdWZmZXJcIjp0cnVlIGluIG9yZGVyIHRvIHJlYWQgcGl4ZWxzIGZyb20gdGhlIGRyYXdpbmcgYnVmZmVyJyk7XG4gICAgICAgIHR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVjayQxKGZyYW1lYnVmZmVyU3RhdGUubmV4dC5jb2xvckF0dGFjaG1lbnRzWzBdLnRleHR1cmUgIT09IG51bGwsICdZb3UgY2Fubm90IHJlYWQgZnJvbSBhIHJlbmRlcmJ1ZmZlcicpO1xuICAgICAgICB0eXBlID0gZnJhbWVidWZmZXJTdGF0ZS5uZXh0LmNvbG9yQXR0YWNobWVudHNbMF0udGV4dHVyZS5fdGV4dHVyZS50eXBlO1xuICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9mbG9hdCkge1xuICAgICAgICAgICAgY2hlY2skMSh0eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDcgfHwgdHlwZSA9PT0gR0xfRkxPQVQkNywgJ1JlYWRpbmcgZnJvbSBhIGZyYW1lYnVmZmVyIGlzIG9ubHkgYWxsb3dlZCBmb3IgdGhlIHR5cGVzIFxcJ3VpbnQ4XFwnIGFuZCBcXCdmbG9hdFxcJycpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09IEdMX0ZMT0FUJDcpIHtcbiAgICAgICAgICAgICAgY2hlY2skMShsaW1pdHMucmVhZEZsb2F0LCAnUmVhZGluZyBcXCdmbG9hdFxcJyB2YWx1ZXMgaXMgbm90IHBlcm1pdHRlZCBpbiB5b3VyIGJyb3dzZXIuIEZvciBhIGZhbGxiYWNrLCBwbGVhc2Ugc2VlOiBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9nbHNsLXJlYWQtZmxvYXQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMSh0eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDcsICdSZWFkaW5nIGZyb20gYSBmcmFtZWJ1ZmZlciBpcyBvbmx5IGFsbG93ZWQgZm9yIHRoZSB0eXBlIFxcJ3VpbnQ4XFwnJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHZhciB4ID0gMDtcbiAgICAgIHZhciB5ID0gMDtcbiAgICAgIHZhciB3aWR0aCA9IGNvbnRleHQuZnJhbWVidWZmZXJXaWR0aDtcbiAgICAgIHZhciBoZWlnaHQgPSBjb250ZXh0LmZyYW1lYnVmZmVySGVpZ2h0O1xuICAgICAgdmFyIGRhdGEgPSBudWxsO1xuICAgICAgaWYgKGlzVHlwZWRBcnJheShpbnB1dCkpIHtcbiAgICAgICAgZGF0YSA9IGlucHV0O1xuICAgICAgfSBlbHNlIGlmIChpbnB1dCkge1xuICAgICAgICBjaGVjayQxLnR5cGUoaW5wdXQsICdvYmplY3QnLCAnaW52YWxpZCBhcmd1bWVudHMgdG8gcmVnbC5yZWFkKCknKTtcbiAgICAgICAgeCA9IGlucHV0LnggfCAwO1xuICAgICAgICB5ID0gaW5wdXQueSB8IDA7XG4gICAgICAgIGNoZWNrJDEoeCA+PSAwICYmIHggPCBjb250ZXh0LmZyYW1lYnVmZmVyV2lkdGgsICdpbnZhbGlkIHggb2Zmc2V0IGZvciByZWdsLnJlYWQnKTtcbiAgICAgICAgY2hlY2skMSh5ID49IDAgJiYgeSA8IGNvbnRleHQuZnJhbWVidWZmZXJIZWlnaHQsICdpbnZhbGlkIHkgb2Zmc2V0IGZvciByZWdsLnJlYWQnKTtcbiAgICAgICAgd2lkdGggPSAoaW5wdXQud2lkdGggfHwgY29udGV4dC5mcmFtZWJ1ZmZlcldpZHRoIC0geCkgfCAwO1xuICAgICAgICBoZWlnaHQgPSAoaW5wdXQuaGVpZ2h0IHx8IGNvbnRleHQuZnJhbWVidWZmZXJIZWlnaHQgLSB5KSB8IDA7XG4gICAgICAgIGRhdGEgPSBpbnB1dC5kYXRhIHx8IG51bGw7XG4gICAgICB9XG5cbiAgICAgIC8vIHNhbml0eSBjaGVjayBpbnB1dC5kYXRhXG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBpZiAodHlwZSA9PT0gR0xfVU5TSUdORURfQllURSQ3KSB7XG4gICAgICAgICAgY2hlY2skMShkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSwgJ2J1ZmZlciBtdXN0IGJlIFxcJ1VpbnQ4QXJyYXlcXCcgd2hlbiByZWFkaW5nIGZyb20gYSBmcmFtZWJ1ZmZlciBvZiB0eXBlIFxcJ3VpbnQ4XFwnJyk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gR0xfRkxPQVQkNykge1xuICAgICAgICAgIGNoZWNrJDEoZGF0YSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSwgJ2J1ZmZlciBtdXN0IGJlIFxcJ0Zsb2F0MzJBcnJheVxcJyB3aGVuIHJlYWRpbmcgZnJvbSBhIGZyYW1lYnVmZmVyIG9mIHR5cGUgXFwnZmxvYXRcXCcnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2hlY2skMSh3aWR0aCA+IDAgJiYgd2lkdGggKyB4IDw9IGNvbnRleHQuZnJhbWVidWZmZXJXaWR0aCwgJ2ludmFsaWQgd2lkdGggZm9yIHJlYWQgcGl4ZWxzJyk7XG4gICAgICBjaGVjayQxKGhlaWdodCA+IDAgJiYgaGVpZ2h0ICsgeSA8PSBjb250ZXh0LmZyYW1lYnVmZmVySGVpZ2h0LCAnaW52YWxpZCBoZWlnaHQgZm9yIHJlYWQgcGl4ZWxzJyk7XG5cbiAgICAgIC8vIFVwZGF0ZSBXZWJHTCBzdGF0ZVxuICAgICAgcmVnbFBvbGwoKTtcblxuICAgICAgLy8gQ29tcHV0ZSBzaXplXG4gICAgICB2Y
1XIgc2l6ZSA9IHdpZHRoICogaGVpZ2h0ICogNDtcblxuICAgICAgLy8gQWxsb2NhdGUgZGF0YVxuICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgIGlmICh0eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDcpIHtcbiAgICAgICAgICBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gR0xfRkxPQVQkNykge1xuICAgICAgICAgIGRhdGEgPSBkYXRhIHx8IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVHlwZSBjaGVja1xuICAgICAgY2hlY2skMS5pc1R5cGVkQXJyYXkoZGF0YSwgJ2RhdGEgYnVmZmVyIGZvciByZWdsLnJlYWQoKSBtdXN0IGJlIGEgdHlwZWRhcnJheScpO1xuICAgICAgY2hlY2skMShkYXRhLmJ5dGVMZW5ndGggPj0gc2l6ZSwgJ2RhdGEgYnVmZmVyIGZvciByZWdsLnJlYWQoKSB0b28gc21hbGwnKTtcblxuICAgICAgLy8gUnVuIHJlYWQgcGl4ZWxzXG4gICAgICBnbC5waXhlbFN0b3JlaShHTF9QQUNLX0FMSUdOTUVOVCwgNCk7XG4gICAgICBnbC5yZWFkUGl4ZWxzKHgsIHksIHdpZHRoLCBoZWlnaHQsIEdMX1JHQkEkMywgdHlwZSwgZGF0YSk7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVhZFBpeGVsc0ZCTyhvcHRpb25zKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgZnJhbWVidWZmZXJTdGF0ZS5zZXRGQk8oe1xuICAgICAgICBmcmFtZWJ1ZmZlcjogb3B0aW9ucy5mcmFtZWJ1ZmZlclxuICAgICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXN1bHQgPSByZWFkUGl4ZWxzSW1wbChvcHRpb25zKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVhZFBpeGVscyhvcHRpb25zKSB7XG4gICAgICBpZiAoIW9wdGlvbnMgfHwgISgnZnJhbWVidWZmZXInIGluIG9wdGlvbnMpKSB7XG4gICAgICAgIHJldHVybiByZWFkUGl4ZWxzSW1wbChvcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZWFkUGl4ZWxzRkJPKG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVhZFBpeGVscztcbiAgfVxuICBmdW5jdGlvbiBzbGljZSh4KSB7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHgpO1xuICB9XG4gIGZ1bmN0aW9uIGpvaW4oeCkge1xuICAgIHJldHVybiBzbGljZSh4KS5qb2luKCcnKTtcbiAgfVxuICBmdW5jdGlvbiBjcmVhdGVFbnZpcm9ubWVudCgpIHtcbiAgICAvLyBVbmlxdWUgdmFyaWFibGUgaWQgY291bnRlclxuICAgIHZhciB2YXJDb3VudGVyID0gMDtcblxuICAgIC8vIExpbmtlZCB2YWx1ZXMgYXJlIHBhc3NlZCBmcm9tIHRoaXMgc2NvcGUgaW50byB0aGUgZ2VuZXJhdGVkIGNvZGUgYmxvY2tcbiAgICAvLyBDYWxsaW5nIGxpbmsoKSBwYXNzZXMgYSB2YWx1ZSBpbnRvIHRoZSBnZW5lcmF0ZWQgc2NvcGUgYW5kIHJldHVybnNcbiAgICAvLyB0aGUgdmFyaWFibGUgbmFtZSB3aGljaCBpdCBpcyBib3VuZCB0b1xuICAgIHZhciBsaW5rZWROYW1lcyA9IFtdO1xuICAgIHZhciBsaW5rZWRWYWx1ZXMgPSBbXTtcbiAgICBmdW5jdGlvbiBsaW5rKHZhbHVlKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmtlZFZhbHVlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAobGlua2VkVmFsdWVzW2ldID09PSB2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBsaW5rZWROYW1lc1tpXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIG5hbWUgPSAnZycgKyB2YXJDb3VudGVyKys7XG4gICAgICBsaW5rZWROYW1lcy5wdXNoKG5hbWUpO1xuICAgICAgbGlua2VkVmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGEgY29kZSBibG9ja1xuICAgIGZ1bmN0aW9uIGJsb2NrKCkge1xuICAgICAgdmFyIGNvZGUgPSBbXTtcbiAgICAgIGZ1bmN0aW9uIHB1c2goKSB7XG4gICAgICAgIGNvZGUucHVzaC5hcHBseShjb2RlLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgIH1cbiAgICAgIHZhciB2YXJzID0gW107XG4gICAgICBmdW5jdGlvbiBkZWYoKSB7XG4gICAgICAgIHZhciBuYW1lID0gJ3YnICsgdmFyQ291bnRlcisrO1xuICAgICAgICB2Y
1XJzLnB1c2gobmFtZSk7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvZGUucHVzaChuYW1lLCAnPScpO1xuICAgICAgICAgIGNvZGUucHVzaC5hcHBseShjb2RlLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICBjb2RlLnB1c2goJzsnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBleHRlbmQocHVzaCwge1xuICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgIHJldHVybiBqb2luKFt2YXJzLmxlbmd0aCA+IDAgPyAndmFyICcgKyB2YXJzLmpvaW4oJywnKSArICc7JyA6ICcnLCBqb2luKGNvZGUpXSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzY29wZSgpIHtcbiAgICAgIHZhciBlbnRyeSA9IGJsb2NrKCk7XG4gICAgICB2YXIgZXhpdCA9IGJsb2NrKCk7XG4gICAgICB2YXIgZW50cnlUb1N0cmluZyA9IGVudHJ5LnRvU3RyaW5nO1xuICAgICAgdmFyIGV4aXRUb1N0cmluZyA9IGV4aXQudG9TdHJpbmc7XG4gICAgICBmdW5jdGlvbiBzYXZlKG9iamVjdCwgcHJvcCkge1xuICAgICAgICBleGl0KG9iamVjdCwgcHJvcCwgJz0nLCBlbnRyeS5kZWYob2JqZWN0LCBwcm9wKSwgJzsnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gKCkge1xuICAgICAgICBlbnRyeS5hcHBseShlbnRyeSwgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICB9LCB7XG4gICAgICAgIGRlZjogZW50cnkuZGVmLFxuICAgICAgICBlbnRyeTogZW50cnksXG4gICAgICAgIGV4aXQ6IGV4aXQsXG4gICAgICAgIHNhdmU6IHNhdmUsXG4gICAgICAgIHNldDogZnVuY3Rpb24gc2V0KG9iamVjdCwgcHJvcCwgdmFsdWUpIHtcbiAgICAgICAgICBzYXZlKG9iamVjdCwgcHJvcCk7XG4gICAgICAgICAgZW50cnkob2JqZWN0LCBwcm9wLCAnPScsIHZhbHVlLCAnOycpO1xuICAgICAgICB9LFxuICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgcmV0dXJuIGVudHJ5VG9TdHJpbmcoKSArIGV4aXRUb1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29uZGl0aW9uYWwoKSB7XG4gICAgICB2Y
1XIgcHJlZCA9IGpvaW4oYXJndW1lbnRzKTtcbiAgICAgIHZhciB0aGVuQmxvY2sgPSBzY29wZSgpO1xuICAgICAgdmFyIGVsc2VCbG9jayA9IHNjb3BlKCk7XG4gICAgICB2YXIgdGhlblRvU3RyaW5nID0gdGhlbkJsb2NrLnRvU3RyaW5nO1xuICAgICAgdmFyIGVsc2VUb1N0cmluZyA9IGVsc2VCbG9jay50b1N0cmluZztcbiAgICAgIHJldHVybiBleHRlbmQodGhlbkJsb2NrLCB7XG4gICAgICAgIHRoZW46IGZ1bmN0aW9uIHRoZW4oKSB7XG4gICAgICAgICAgdGhlbkJsb2NrLmFwcGx5KHRoZW5CbG9jaywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgIGVsc2U6IGZ1bmN0aW9uIF9lbHNlKCkge1xuICAgICAgICAgIGVsc2VCbG9jay5hcHBseShlbHNlQmxvY2ssIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgdmFyIGVsc2VDbGF1c2UgPSBlbHNlVG9TdHJpbmcoKTtcbiAgICAgICAgICBpZiAoZWxzZUNsYXVzZSkge1xuICAgICAgICAgICAgZWxzZUNsYXVzZSA9ICdlbHNleycgKyBlbHNlQ2xhdXNlICsgJ30nO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gam9pbihbJ2lmKCcsIHByZWQsICcpeycsIHRoZW5Ub1N0cmluZygpLCAnfScsIGVsc2VDbGF1c2VdKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gcHJvY2VkdXJlIGxpc3RcbiAgICB2YXIgZ2xvYmFsQmxvY2sgPSBibG9jaygpO1xuICAgIHZhciBwcm9jZWR1cmVzID0ge307XG4gICAgZnVuY3Rpb24gcHJvYyhuYW1lLCBjb3VudCkge1xuICAgICAgdmFyIGFyZ3MgPSBbXTtcbiAgICAgIGZ1bmN0aW9uIGFyZygpIHtcbiAgICAgICAgdmFyIG5hbWUgPSAnYScgKyBhcmdzLmxlbmd0aDtcbiAgICAgICAgYXJncy5wdXNoKG5hbWUpO1xuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgIH1cbiAgICAgIGNvdW50ID0gY291bnQgfHwgMDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7ICsraSkge1xuICAgICAgICBhcmcoKTtcbiAgICAgIH1cbiAgICAgIHZhciBib2R5ID0gc2NvcGUoKTtcbiAgICAgIHZhciBib2R5VG9TdHJpbmcgPSBib2R5LnRvU3RyaW5nO1xuICAgICAgdmFyIHJlc3VsdCA9IHByb2NlZHVyZXNbbmFtZV0gPSBleHRlbmQoYm9keSwge1xuICAgICAgICBhcmc6IGFyZyxcbiAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgIHJldHVybiBqb2luKFsnZnVuY3Rpb24oJywgYXJncy5qb2luKCksICcpeycsIGJvZHlUb1N0cmluZygpLCAnfSddKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb21waWxlKCkge1xuICAgICAgdmFyIGNvZGUgPSBbJ1widXNlIHN0cmljdFwiOycsIGdsb2JhbEJsb2NrLCAncmV0dXJuIHsnXTtcbiAgICAgIE9iamVjdC5rZXlzKHByb2NlZHVyZXMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgY29kZS5wdXNoKCdcIicsIG5hbWUsICdcIjonLCBwcm9jZWR1cmVzW25hbWVdLnRvU3RyaW5nKCksICcsJyk7XG4gICAgICB9KTtcbiAgICAgIGNvZGUucHVzaCgnfScpO1xuICAgICAgdmFyIHNyYyA9IGpvaW4oY29kZSkucmVwbGFjZSgvOy9nLCAnO1xcbicpLnJlcGxhY2UoL30vZywgJ31cXG4nKS5yZXBsYWNlKC97L2csICd7XFxuJyk7XG4gICAgICB2Y
1XIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KG51bGwsIGxpbmtlZE5hbWVzLmNvbmNhdChzcmMpKTtcbiAgICAgIHJldHVybiBwcm9jLmFwcGx5KG51bGwsIGxpbmtlZFZhbHVlcyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBnbG9iYWw6IGdsb2JhbEJsb2NrLFxuICAgICAgbGluazogbGluayxcbiAgICAgIGJsb2NrOiBibG9jayxcbiAgICAgIHByb2M6IHByb2MsXG4gICAgICBzY29wZTogc2NvcGUsXG4gICAgICBjb25kOiBjb25kaXRpb25hbCxcbiAgICAgIGNvbXBpbGU6IGNvbXBpbGVcbiAgICB9O1xuICB9XG5cbiAgLy8gXCJjdXRlXCIgbmFtZXMgZm9yIHZlY3RvciBjb21wb25lbnRzXG4gIHZhciBDVVRFX0NPTVBPTkVOVFMgPSAneHl6dycuc3BsaXQoJycpO1xuICB2YXIgR0xfVU5TSUdORURfQllURSQ4ID0gNTEyMTtcbiAgdmFyIEFUVFJJQl9TVEFURV9QT0lOVEVSID0gMTtcbiAgdmFyIEFUVFJJQl9TVEFURV9DT05TVEFOVCA9IDI7XG4gIHZhciBEWU5fRlVOQyQxID0gMDtcbiAgdmFyIERZTl9QUk9QJDEgPSAxO1xuICB2YXIgRFlOX0NPTlRFWFQkMSA9IDI7XG4gIHZhciBEWU5fU1RBVEUkMSA9IDM7XG4gIHZhciBEWU5fVEhVTksgPSA0O1xuICB2YXIgRFlOX0NPTlNUQU5UJDEgPSA1O1xuICB2YXIgRFlOX0FSUkFZJDEgPSA2O1xuICB2YXIgU19ESVRIRVIgPSAnZGl0aGVyJztcbiAgdmFyIFNfQkxFTkRfRU5BQkxFID0gJ2JsZW5kLmVuYWJsZSc7XG4gIHZhciBTX0JMRU5EX0NPTE9SID0gJ2JsZW5kLmNvbG9yJztcbiAgdmFyIFNfQkxFTkRfRVFVQVRJT04gPSAnYmxlbmQuZXF1YXRpb24nO1xuICB2YXIgU19CTEVORF9GVU5DID0gJ2JsZW5kLmZ1bmMnO1xuICB2YXIgU19ERVBUSF9FTkFCTEUgPSAnZGVwdGguZW5hYmxlJztcbiAgdmFyIFNfREVQVEhfRlVOQyA9ICdkZXB0aC5mdW5jJztcbiAgdmFyIFNfREVQVEhfUkFOR0UgPSAnZGVwdGgucmFuZ2UnO1xuICB2YXIgU19ERVBUSF9NQVNLID0gJ2RlcHRoLm1hc2snO1xuICB2YXIgU19DT0xPUl9NQVNLID0gJ2NvbG9yTWFzayc7XG4gIHZhciBTX0NVTExfRU5BQkxFID0gJ2N1bGwuZW5hYmxlJztcbiAgdmFyIFNfQ1VMTF9GQUNFID0gJ2N1bGwuZmFjZSc7XG4gIHZhciBTX0ZST05UX0ZBQ0UgPSAnZnJvbnRGYWNlJztcbiAgdmFyIFNfTElORV9XSURUSCA9ICdsaW5lV2lkdGgnO1xuICB2YXIgU19QT0xZR09OX09GRlNFVF9FTkFCTEUgPSAncG9seWdvbk9mZnNldC5lbmFibGUnO1xuICB2YXIgU19QT0xZR09OX09GRlNFVF9PRkZTRVQgPSAncG9seWdvbk9mZnNldC5vZmZzZXQnO1xuICB2YXIgU19TQU1QTEVfQUxQSEEgPSAnc2FtcGxlLmFscGhhJztcbiAgdmFyIFNfU0FNUExFX0VOQUJMRSA9ICdzYW1wbGUuZW5hYmxlJztcbiAgdmFyIFNfU0FNUExFX0NPVkVSQUdFID0gJ3NhbXBsZS5jb3ZlcmFnZSc7XG4gIHZhciBTX1NURU5DSUxfRU5BQkxFID0gJ3N0ZW5jaWwuZW5hYmxlJztcbiAgdmFyIFNfU1RFTkNJTF9NQVNLID0gJ3N0ZW5jaWwubWFzayc7XG4gIHZhciBTX1NURU5DSUxfRlVOQyA9ICdzdGVuY2lsLmZ1bmMnO1xuICB2YXIgU19TVEVOQ0lMX09QRlJPTlQgPSAnc3RlbmNpbC5vcEZyb250JztcbiAgdmFyIFNfU1RFTkNJTF9PUEJBQ0sgPSAnc3RlbmNpbC5vcEJhY2snO1xuICB2YXIgU19TQ0lTU09SX0VOQUJMRSA9ICdzY2lzc29yLmVuYWJsZSc7XG4gIHZhciBTX1NDSVNTT1JfQk9YID0gJ3NjaXNzb3IuYm94JztcbiAgdmFyIFNfVklFV1BPUlQgPSAndmlld3BvcnQnO1xuICB2YXIgU19QUk9GSUxFID0gJ3Byb2ZpbGUnO1xuICB2YXIgU19GUkFNRUJVRkZFUiA9ICdmcmFtZWJ1ZmZlcic7XG4gIHZhciBTX1ZFUlQgPSAndmVydCc7XG4gIHZhciBTX0ZSQUcgPSAnZnJhZyc7XG4gIHZhciBTX0VMRU1FTlRTID0gJ2VsZW1lbnRzJztcbiAgdmFyIFNfUFJJTUlUSVZFID0gJ3ByaW1pdGl2ZSc7XG4gIHZhciBTX0NPVU5UID0gJ2NvdW50JztcbiAgdmFyIFNfT0ZGU0VUID0gJ29mZnNldCc7XG4gIHZhciBTX0lOU1RBTkNFUyA9ICdpbnN0YW5jZXMnO1xuICB2YXIgU19WQU8gPSAndmFvJztcbiAgdmFyIFNVRkZJWF9XSURUSCA9ICdXaWR0aCc7XG4gIHZhciBTVUZGSVhfSEVJR0hUID0gJ0hlaWdodCc7XG4gIHZhciBTX0ZSQU1FQlVGRkVSX1dJRFRIID0gU19GUkFNRUJVRkZFUiArIFNVRkZJWF9XSURUSDtcbiAgdmFyIFNfRlJBTUVCVUZGRVJfSEVJR0hUID0gU19GUkFNRUJVRkZFUiArIFNVRkZJWF9IRUlHSFQ7XG4gIHZhciBTX1ZJRVdQT1JUX1dJRFRIID0gU19WSUVXUE9SVCArIFNVRkZJWF9XSURUSDtcbiAgdmFyIFNfVklFV1BPUlRfSEVJR0hUID0gU19WSUVXUE9SVCArIFNVRkZJWF9IRUlHSFQ7XG4gIHZhciBTX0RSQVdJTkdCVUZGRVIgPSAnZHJhd2luZ0J1ZmZlcic7XG4gIHZhciBTX0RSQVdJTkdCVUZGRVJfV0lEVEggPSBTX0RSQVdJTkdCVUZGRVIgKyBTVUZGSVhfV0lEVEg7XG4gIHZhciBTX0RSQVdJTkdCVUZGRVJfSEVJR0hUID0gU19EUkFXSU5HQlVGRkVSICsgU1VGRklYX0hFSUdIVDtcbiAgdmFyIE5FU1RFRF9PUFRJT05TID0gW1NfQkxFTkRfRlVOQywgU19CTEVORF9FUVVBVElPTiwgU19TVEVOQ0lMX0ZVTkMsIFNfU1RFTkNJTF9PUEZST05ULCBTX1NURU5DSUxfT1BCQUNLLCBTX1NBTVBMRV9DT1ZFUkFHRSwgU19WSUVXUE9SVCwgU19TQ0lTU09SX0JPWCwgU19QT0xZR09OX09GRlNFVF9PRkZTRVRdO1xuICB2YXIgR0xfQVJSQVlfQlVGRkVSJDIgPSAzNDk2MjtcbiAgdmFyIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSJDIgPSAzNDk2MztcbiAgdmFyIEdMX0ZSQUdNRU5UX1NIQURFUiQxID0gMzU2MzI7XG4gIHZhciBHTF9WRVJURVhfU0hBREVSJDEgPSAzNTYzMztcbiAgdmFyIEdMX1RFWFRVUkVfMkQkMyA9IDB4MERFMTtcbiAgdmFyIEdMX1RFWFRVUkVfQ1VCRV9NQVAkMiA9IDB4ODUxMztcbiAgdmFyIEdMX0NVTExfRkFDRSA9IDB4MEI0NDtcbiAgdmFyIEdMX0JMRU5EID0gMHgwQkUyO1xuICB2YXIgR0xfRElUSEVSID0gMHgwQkQwO1xuICB2YXIgR0xfU1RFTkNJTF9URVNUID0gMHgwQjkwO1xuICB2YXIgR0xfREVQVEhfVEVTVCA9IDB4MEI3MTtcbiAgdmFyIEdMX1NDSVNTT1JfVEVTVCA9IDB4MEMxMTtcbiAgdmFyIEdMX1BPTFlHT05fT0ZGU0VUX0ZJTEwgPSAweDgw
1Mzc7XG4gIHZhciBHTF9TQU1QTEVfQUxQSEFfVE9fQ09WRVJBR0UgPSAweDgwOUU7XG4gIHZhciBHTF9TQU1QTEVfQ09WRVJBR0UgPSAweDgwQTA7XG4gIHZhciBHTF9GTE9BVCQ4ID0gNTEyNjtcbiAgdmFyIEdMX0ZMT0FUX1ZFQzIgPSAzNTY2NDtcbiAgdmFyIEdMX0ZMT0FUX1ZFQzMgPSAzNTY2NTtcbiAgdmFyIEdMX0ZMT0FUX1ZFQzQgPSAzNTY2NjtcbiAgdmFyIEdMX0lOVCQzID0gNTEyNDtcbiAgdmFyIEdMX0lOVF9WRUMyID0gMzU2Njc7XG4gIHZhciBHTF9JTlRfVkVDMyA9IDM1NjY4O1xuICB2YXIgR0xfSU5UX1ZFQzQgPSAzNTY2OTtcbiAgdmFyIEdMX0JPT0wgPSAzNTY3MDtcbiAgdmFyIEdMX0JPT0xfVkVDMiA9IDM1NjcxO1xuICB2YXIgR0xfQk9PTF9WRUMzID0gMzU2NzI7XG4gIHZhciBHTF9CT09MX1ZFQzQgPSAzNTY3MztcbiAgdmFyIEdMX0ZMT0FUX01BVDIgPSAzNTY3NDtcbiAgdmFyIEdMX0ZMT0FUX01BVDMgPSAzNTY3NTtcbiAgdmFyIEdMX0ZMT0FUX01BVDQgPSAzNTY3NjtcbiAgdmFyIEdMX1NBTVBMRVJfMkQgPSAzNTY3ODtcbiAgdmFyIEdMX1NBTVBMRVJfQ1VCRSA9IDM1NjgwO1xuICB2YXIgR0xfVFJJQU5HTEVTJDEgPSA0O1xuICB2YXIgR0xfRlJPTlQgPSAxMDI4O1xuICB2YXIgR0xfQkFDSyA9IDEwMjk7XG4gIHZhciBHTF9DVyA9IDB4MDkwMDtcbiAgdmFyIEdMX0NDVyA9IDB4MDkwMTtcbiAgdmFyIEdMX01JTl9FWFQgPSAweDgwMDc7XG4gIHZhciBHTF9NQVhfRVhUID0gMHg4MDA4O1xuICB2YXIgR0xfQUxXQVlTID0gNTE5O1xuICB2YXIgR0xfS0VFUCA9IDc2ODA7XG4gIHZhciBHTF9aRVJPID0gMDtcbiAgdmFyIEdMX09ORSA9IDE7XG4gIHZhciBHTF9GVU5DX0FERCA9IDB4ODAwNjtcbiAgdmFyIEdMX0xFU1MgPSA1MTM7XG4gIHZhciBHTF9GUkFNRUJVRkZFUiQyID0gMHg4RDQwO1xuICB2YXIgR0xfQ09MT1JfQVRUQUNITUVOVDAkMiA9IDB4OENFMDtcbiAgdmFyIGJsZW5kRnVuY3MgPSB7XG4gICAgJzAnOiAwLFxuICAgICcxJzogMSxcbiAgICAnemVybyc6IDAsXG4gICAgJ29uZSc6IDEsXG4gICAgJ3NyYyBjb2xvcic6IDc2OCxcbiAgICAnb25lIG1pbnVzIHNyYyBjb2xvcic6IDc2OSxcbiAgICAnc3JjIGFscGhhJzogNzcwLFxuICAgICdvbmUgbWludXMgc3JjIGFscGhhJzogNzcxLFxuICAgICdkc3QgY29sb3InOiA3NzQsXG4gICAgJ29uZSBtaW51cyBkc3QgY29sb3InOiA3NzUsXG4gICAgJ2RzdCBhbHBoYSc6IDc3MixcbiAgICAnb25lIG1pbnVzIGRzdCBhbHBoYSc6IDc3MyxcbiAgICAnY29uc3RhbnQgY29sb3InOiAzMjc2OSxcbiAgICAnb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yJzogMzI3NzAsXG4gICAgJ2NvbnN0YW50IGFscGhhJzogMzI3NzEsXG4gICAgJ29uZSBtaW51cyBjb25zdGFudCBhbHBoYSc6IDMyNzcyLFxuICAgICdzcmMgYWxwaGEgc2F0dXJhdGUnOiA3NzZcbiAgfTtcblxuICAvLyBUaGVyZSBhcmUgaW52YWxpZCB2YWx1ZXMgZm9yIHNyY1JHQiBhbmQgZHN0UkdCLiBTZWU6XG4gIC8vIGh0dHBzOi8vd3d3Lmtocm9ub3Mub3JnL3JlZ2lzdHJ5L3dlYmdsL3NwZWNzLzEuMC8jNi4xM1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL1dlYkdML2Jsb2IvMGQzMjAxZjVmN2VjM2MwMDYwYmMxZjA0MDc3NDYxNTQxZjE5ODdiOS9jb25mb3JtYW5jZS1zdWl0ZXMvMS4wLjMvY29uZm9ybWFuY2UvbWlzYy93ZWJnbC1zcGVjaWZpYy5odG1sI0w1NlxuICB2YXIgaW52YWxpZEJsZW5kQ29tYmluYXRpb25zID0gWydjb25zdGFudCBjb2xvciwgY29uc3RhbnQgYWxwaGEnLCAnb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yLCBjb25zdGFudCBhbHBoYScsICdjb25zdGFudCBjb2xvciwgb25lIG1pbnVzIGNvbnN0YW50IGFscGhhJywgJ29uZSBtaW51cyBjb25zdGFudCBjb2xvciwgb25lIG1pbnVzIGNvbnN0YW50IGFscGhhJywgJ2NvbnN0YW50IGFscGhhLCBjb25zdGFudCBjb2xvcicsICdjb25zdGFudCBhbHBoYSwgb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yJywgJ29uZSBtaW51cyBjb25zdGFudCBhbHBoYSwgY29uc3RhbnQgY29sb3InLCAnb25lIG1pbnVzIGNvbnN0YW50IGFscGhhLCBvbmUgbWludXMgY29uc3RhbnQgY29sb3InXTtcbiAgdmFyIGNvbXBhcmVGdW5jcyA9IHtcbiAgICAnbmV2ZXInOiA1MTIsXG4gICAgJ2xlc3MnOiA1MTMsXG4gICAgJzwnOiA1MTMsXG4gICAgJ2VxdWFsJzogNTE0LFxuICAgICc9JzogNTE0LFxuICAgICc9PSc6IDUxNCxcbiAgICAnPT09JzogNTE0LFxuICAgICdsZXF1YWwnOiA1MTUsXG4gICAgJzw9JzogNTE1LFxuICAgICdncmVhdGVyJzogNTE2LFxuICAgICc+JzogNTE2LFxuICAgICdub3RlcXVhbCc6IDUxNyxcbiAgICAnIT0nOiA1MTcsXG4gICAgJyE9PSc6IDUxNyxcbiAgICAnZ2VxdWFsJzogNTE4LFxuICAgICc+PSc6IDUxOCxcbiAgICAnYWx3YXlzJzogNTE5XG4gIH07XG4gIHZhciBzdGVuY2lsT3BzID0ge1xuICAgICcwJzogMCxcbiAgICAnemVybyc6IDAsXG4gICAgJ2tlZXAnOiA3NjgwLFxuICAgICdyZXBsYWNlJzogNzY4MSxcbiAgICAnaW5jcmVtZW50JzogNzY4MixcbiAgICAnZGVjcmVtZW50JzogNzY4MyxcbiAgICAnaW5jcmVtZW50IHdyYXAnOiAzNDA1NSxcbiAgICAnZGVjcmVtZW50IHdyYXAnOiAzNDA1NixcbiAgICAnaW52ZXJ0JzogNTM4NlxuICB9O1xuICB2YXIgc2hhZGVyVHlwZSA9IHtcbiAgICAnZnJhZyc6IEdMX0ZSQUdNRU5UX1NIQURFUiQxLFxuICAgICd2ZXJ0JzogR0xfVkVSVEVYX1NIQURFUiQxXG4gIH07XG4gIHZhciBvcmllbnRhdGlvblR5cGUgPSB7XG4gICAgJ2N3JzogR0xfQ1csXG4gICAgJ2Njdyc6IEdMX0NDV1xuICB9O1xuICBmdW5jdGlvbiBpc0J1ZmZlckFyZ3MoeCkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHgpIHx8IGlzVHlwZWRBcnJheSh4KSB8fCBpc05EQXJyYXlMaWtlKHgpO1xuICB9XG5cbiAgLy8gTWFrZSBzdXJlIHZpZXdwb3J0IGlzIHByb2Nlc3NlZCBmaXJzdFxuICBmdW5jdGlvbiBzb3J0U3RhdGUoc3RhdGUpIHtcbiAgICByZXR1cm4gc3RhdGUuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgaWYgKGEgPT09IFNfVklFV1BPUlQpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIGlmIChiID09PSBTX1ZJRVdQT1JUKSB7XG4gICAgICAgI
1HJldHVybiAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGEgPCBiID8gLTEgOiAxO1xuICAgIH0pO1xuICB9XG4gIGZ1bmN0aW9uIERlY2xhcmF0aW9uKHRoaXNEZXAsIGNvbnRleHREZXAsIHByb3BEZXAsIGFwcGVuZCkge1xuICAgIHRoaXMudGhpc0RlcCA9IHRoaXNEZXA7XG4gICAgdGhpcy5jb250ZXh0RGVwID0gY29udGV4dERlcDtcbiAgICB0aGlzLnByb3BEZXAgPSBwcm9wRGVwO1xuICAgIHRoaXMuYXBwZW5kID0gYXBwZW5kO1xuICB9XG4gIGZ1bmN0aW9uIGlzU3RhdGljKGRlY2wpIHtcbiAgICByZXR1cm4gZGVjbCAmJiAhKGRlY2wudGhpc0RlcCB8fCBkZWNsLmNvbnRleHREZXAgfHwgZGVjbC5wcm9wRGVwKTtcbiAgfVxuICBmdW5jdGlvbiBjcmVhdGVTdGF0aWNEZWNsKGFwcGVuZCkge1xuICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24oZmFsc2UsIGZhbHNlLCBmYWxzZSwgYXBwZW5kKTtcbiAgfVxuICBmdW5jdGlvbiBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGFwcGVuZCkge1xuICAgIHZhciB0eXBlID0gZHluLnR5cGU7XG4gICAgaWYgKHR5cGUgPT09IERZTl9GVU5DJDEpIHtcbiAgICAgIHZhciBudW1BcmdzID0gZHluLmRhdGEubGVuZ3RoO1xuICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbih0cnVlLCBudW1BcmdzID49IDEsIG51bUFyZ3MgPj0gMiwgYXBwZW5kKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09IERZTl9USFVOSykge1xuICAgICAgdmFyIGRhdGEgPSBkeW4uZGF0YTtcbiAgICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24oZGF0YS50aGlzRGVwLCBkYXRhLmNvbnRleHREZXAsIGRhdGEucHJvcERlcCwgYXBwZW5kKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09IERZTl9DT05TVEFOVCQxKSB7XG4gICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGFwcGVuZCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSBEWU5fQVJSQVkkMSkge1xuICAgICAgdmFyIHRoaXNEZXAgPSBmYWxzZTtcbiAgICAgIHZhciBjb250ZXh0RGVwID0gZmFsc2U7XG4gICAgICB2Y
1XIgcHJvcERlcCA9IGZhbHNlO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkeW4uZGF0YS5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgc3ViRHluID0gZHluLmRhdGFbaV07XG4gICAgICAgIGlmIChzdWJEeW4udHlwZSA9PT0gRFlOX1BST1AkMSkge1xuICAgICAgICAgIHByb3BEZXAgPSB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKHN1YkR5bi50eXBlID09PSBEWU5fQ09OVEVYVCQxKSB7XG4gICAgICAgICAgY29udGV4dERlcCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoc3ViRHluLnR5cGUgPT09IERZTl9TVEFURSQxKSB7XG4gICAgICAgICAgdGhpc0RlcCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoc3ViRHluLnR5cGUgPT09IERZTl9GVU5DJDEpIHtcbiAgICAgICAgICB0aGlzRGVwID0gdHJ1ZTtcbiAgICAgICAgICB2YXIgc3ViQXJncyA9IHN1YkR5bi5kYXRhO1xuICAgICAgICAgIGlmIChzdWJBcmdzID49IDEpIHtcbiAgICAgICAgICAgIGNvbnRleHREZXAgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc3ViQXJncyA+PSAyKSB7XG4gICAgICAgICAgICBwcm9wRGVwID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc3ViRHluLnR5cGUgPT09IERZTl9USFVOSykge1xuICAgICAgICAgIHRoaXNEZXAgPSB0aGlzRGVwIHx8IHN1YkR5bi5kYXRhLnRoaXNEZXA7XG4gICAgICAgICAgY29udGV4dERlcCA9IGNvbnRleHREZXAgfHwgc3ViRHluLmRhdGEuY29udGV4dERlcDtcbiAgICAgICAgICBwcm9wRGVwID0gcHJvcERlcCB8fCBzdWJEeW4uZGF0YS5wcm9wRGVwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKHRoaXNEZXAsIGNvbnRleHREZXAsIHByb3BEZXAsIGFwcGVuZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24odHlwZSA9PT0gRFlOX1NUQVRFJDEsIHR5cGUgPT09IERZTl9DT05URVhUJDEsIHR5cGUgPT09IERZTl9QUk9QJDEsIGFwcGVuZCk7XG4gICAgfVxuICB9XG4gIHZhciBTQ09QRV9ERUNMID0gbmV3IERlY2xhcmF0aW9uKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZ1bmN0aW9uICgpIHt9KTtcbiAgZnVuY3Rpb24gcmVnbENvcmUoZ2wsIHN0cmluZ1N0b3JlLCBleHRlbnNpb25zLCBsaW1pdHMsIGJ1ZmZlclN0YXRlLCBlbGVtZW50U3RhdGUsIHRleHR1cmVTdGF0ZSwgZnJhbWVidWZmZXJTdGF0ZSwgdW5pZm9ybVN0YXRlLCBhdHRyaWJ1dGVTdGF0ZSwgc2hhZGVyU3RhdGUsIGRyYXdTdGF0ZSwgY29udGV4dFN0YXRlLCB0aW1lciwgY29uZmlnKSB7XG4gICAgdmFyIEF0dHJpYnV0ZVJlY29yZCA9IGF0dHJpYnV0ZVN0YXRlLlJlY29yZDtcbiAgICB2YXIgYmxlbmRFcXVhdGlvbnMgPSB7XG4gICAgICAnYWRkJzogMzI3NzQsXG4gICAgICAnc3VidHJhY3QnOiAzMjc3OCxcbiAgICAgICdyZXZlcnNlIHN1YnRyYWN0JzogMzI3NzlcbiAgICB9O1xuICAgIGlmIChleHRlbnNpb25zLmV4dF9ibGVuZF9taW5tYXgpIHtcbiAgICAgIGJsZW5kRXF1YXRpb25zLm1pbiA9IEdMX01JTl9FWFQ7XG4gICAgICBibGVuZEVxdWF0aW9ucy5tYXggPSBHTF9NQVhfRVhUO1xuICAgIH1cbiAgICB2YXIgZXh0SW5zdGFuY2luZyA9IGV4dGVuc2lvbnMuYW5nbGVfaW5zdGFuY2VkX2FycmF5cztcbiAgICB2YXIgZXh0RHJhd0J1ZmZlcnMgPSBleHRlbnNpb25zLndlYmdsX2RyYXdfYnVmZmVycztcbiAgICB2YXIgZXh0VmVydGV4QXJyYXlzID0gZXh0ZW5zaW9ucy5vZXNfdmVydGV4X2FycmF5X29iamVjdDtcblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFdFQkdMIFNUQVRFXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHtcbiAgICAgIGRpcnR5OiB0cnVlLFxuICAgICAgcHJvZmlsZTogY29uZmlnLnByb2ZpbGVcbiAgICB9O1xuICAgIHZhciBuZXh0U3RhdGUgPSB7fTtcbiAgICB2YXIgR0xfU1RBVEVfTkFNRVMgPSBbXTtcbiAgICB2YXIgR0xfRkxBR1MgPSB7fTtcbiAgICB2YXIgR0xfVkFSSUFCTEVTID0ge307XG4gICAgZnVuY3Rpb24gcHJvcE5hbWUobmFtZSkge1xuICAgICAgcmV0dXJuIG5hbWUucmVwbGFjZSgnLicsICdfJyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0YXRlRmxhZyhzbmFtZSwgY2FwLCBpbml0KSB7XG4gICAgICB2Y
1XIgbmFtZSA9IHByb3BOYW1lKHNuYW1lKTtcbiAgICAgIEdMX1NUQVRFX05BTUVTLnB1c2goc25hbWUpO1xuICAgICAgbmV4dFN0YXRlW25hbWVdID0gY3VycmVudFN0YXRlW25hbWVdID0gISFpbml0O1xuICAgICAgR0xfRkxBR1NbbmFtZV0gPSBjYXA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0YXRlVmFyaWFibGUoc25hbWUsIGZ1bmMsIGluaXQpIHtcbiAgICAgIHZhciBuYW1lID0gcHJvcE5hbWUoc25hbWUpO1xuICAgICAgR0xfU1RBVEVfTkFNRVMucHVzaChzbmFtZSk7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShpbml0KSkge1xuICAgICAgICBjdXJyZW50U3RhdGVbbmFtZV0gPSBpbml0LnNsaWNlKCk7XG4gICAgICAgIG5leHRTdGF0ZVtuYW1lXSA9IGluaXQuc2xpY2UoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN1cnJlbnRTdGF0ZVtuYW1lXSA9IG5leHRTdGF0ZVtuYW1lXSA9IGluaXQ7XG4gICAgICB9XG4gICAgICBHTF9WQVJJQUJMRVNbbmFtZV0gPSBmdW5jO1xuICAgIH1cblxuICAgIC8vIERpdGhlcmluZ1xuICAgIHN0YXRlRmxhZyhTX0RJVEhFUiwgR0xfRElUSEVSKTtcblxuICAgIC8vIEJsZW5kaW5nXG4gICAgc3RhdGVGbGFnKFNfQkxFTkRfRU5BQkxFLCBHTF9CTEVORCk7XG4gICAgc3RhdGVWYXJpYWJsZShTX0JMRU5EX0NPTE9SLCAnYmxlbmRDb2xvcicsIFswLCAwLCAwLCAwXSk7XG4gICAgc3RhdGVWYXJpYWJsZShTX0JMRU5EX0VRVUFUSU9OLCAnYmxlbmRFcXVhdGlvblNlcGFyYXRlJywgW0dMX0ZVTkNfQURELCBHTF9GVU5DX0FERF0pO1xuICAgIHN0YXRlVmFyaWFibGUoU19CTEVORF9GVU5DLCAnYmxlbmRGdW5jU2VwYXJhdGUnLCBbR0xfT05FLCBHTF9aRVJPLCBHTF9PTkUsIEdMX1pFUk9dKTtcblxuICAgIC8vIERlcHRoXG4gICAgc3RhdGVGbGFnKFNfREVQVEhfRU5BQkxFLCBHTF9ERVBUSF9URVNULCB0cnVlKTtcbiAgICBzdGF0ZVZhcmlhYmxlKFNfREVQVEhfRlVOQywgJ2RlcHRoRnVuYycsIEdMX0xFU1MpO1xuICAgIHN0YXRlVmFyaWFibGUoU19ERVBUSF9SQU5HRSwgJ2RlcHRoUmFuZ2UnLCBbMCwgMV0pO1xuICAgIHN0YXRlVmFyaWFibGUoU19ERVBUSF9NQVNLLCAnZGVwdGhNYXNrJywgdHJ1ZSk7XG5cbiAgICAvLyBDb2xvciBtYXNrXG4gICAgc3RhdGVWYXJpYWJsZShTX0NPTE9SX01BU0ssIFNfQ09MT1JfTUFTSywgW3RydWUsIHRydWUsIHRydWUsIHRydWVdKTtcblxuICAgIC8vIEZhY2UgY3VsbGluZ1xuICAgIHN0YXRlRmxhZyhTX0NVTExfRU5BQkxFLCBHTF9DVUxMX0ZBQ0UpO1xuICAgIHN0YXRlVmFyaWFibGUoU19DVUxMX0ZBQ0UsICdjdWxsRmFjZScsIEdMX0JBQ0spO1xuXG4gICAgLy8gRnJvbnQgZmFjZSBvcmllbnRhdGlvblxuICAgIHN0YXRlVmFyaWFibGUoU19GUk9OVF9GQUNFLCBTX0ZST05UX0ZBQ0UsIEdMX0NDVyk7XG5cbiAgICAvLyBMaW5lIHdpZHRoXG4gICAgc3RhdGVWYXJpYWJsZShTX0xJTkVfV0lEVEgsIFNfTElORV9XSURUSCwgMSk7XG5cbiAgICAvLyBQb2x5Z29uIG9mZnNldFxuICAgIHN0YXRlRmxhZyhTX1BPTFlHT05fT0ZGU0VUX0VOQUJMRSwgR0xfUE9MWUdPTl9PRkZTRVRfRklMTCk7XG4gICAgc3RhdGVWYXJpYWJsZShTX1BPTFlHT05fT0ZGU0VUX09GRlNFVCwgJ3BvbHlnb25PZmZzZXQnLCBbMCwgMF0pO1xuXG4gICAgLy8gU2FtcGxlIGNvdmVyYWdlXG4gICAgc3RhdGVGbGFnKFNfU0FNUExFX0FMUEhBLCBHTF9TQU1QTEVfQUxQSEFfVE9fQ09WRVJBR0UpO1xuICAgIHN0YXRlRmxhZyhTX1NBTVBMRV9FTkFCTEUsIEdMX1NBTVBMRV9DT1ZFUkFHRSk7XG4gICAgc3RhdGVWYXJpYWJsZShTX1NBTVBMRV9DT1ZFUkFHRSwgJ3NhbXBsZUNvdmVyYWdlJywgWzEsIGZhbHNlXSk7XG5cbiAgICAvLyBTdGVuY2lsXG4gICAgc3RhdGVGbGFnKFNfU1RFTkNJTF9FTkFCTEUsIEdMX1NURU5DSUxfVEVTVCk7XG4gICAgc3RhdGVWYXJpYWJsZShTX1NURU5DSUxfTUFTSywgJ3N0ZW5jaWxNYXNrJywgLTEpO1xuICAgIHN0YXRlVmFyaWFibGUoU19TVEVOQ0lMX0ZVTkMsICdzdGVuY2lsRnVuYycsIFtHTF9BTFdBWVMsIDAsIC0xXSk7XG4gICAgc3RhdGVWYXJpYWJsZShTX1NURU5DSUxfT1BGUk9OVCwgJ3N0ZW5jaWxPcFNlcGFyYXRlJywgW0dMX0ZST05ULCBHTF9LRUVQLCBHTF9LRUVQLCBHTF9LRUVQXSk7XG4gICAgc3RhdGVWYXJpYWJsZShTX1NURU5DSUxfT1BCQUNLLCAnc3RlbmNpbE9wU2VwYXJhdGUnLCBbR0xfQkFDSywgR0xfS0VFUCwgR0xfS0VFUCwgR0xfS0VFUF0pO1xuXG4gICAgLy8gU2Npc3NvclxuICAgIHN0YXRlRmxhZyhTX1NDSVNTT1JfRU5BQkxFLCBHTF9TQ0lTU09SX1RFU1QpO1xuICAgIHN0YXRlVmFyaWFibGUoU19TQ0lTU09SX0JPWCwgJ3NjaXNzb3InLCBbMCwgMCwgZ2wuZHJhd2luZ0J1ZmZlcldpZHRoLCBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XSk7XG5cbiAgICAvLyBWaWV3cG9ydFxuICAgIHN0YXRlVmFyaWFibGUoU19WSUVXUE9SVCwgU19WSUVXUE9SVCwgWzAsIDAsIGdsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0pO1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gRU5WSVJPTk1FTlRcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICB2YXIgc2hhcmVkU3RhdGUgPSB7XG4gICAgICBnbDogZ2wsXG4gICAgICBjb250ZXh0OiBjb250ZXh0U3RhdGUsXG4gICAgICBzdHJpbmdzOiBzdHJpbmdTdG9yZSxcbiAgICAgIG5leHQ6IG5leHRTdGF0ZSxcbiAgICAgIGN1cnJlbnQ6IGN1cnJlbnRTdGF0ZSxcbiAgICAgIGRyYXc6IGRyYXdTdGF0ZSxcbiAgICAgIGVsZW1lbnRzOiBlbGVtZW50U3RhdGUsXG4gICAgICBidWZmZXI6IGJ1ZmZlclN0YXRlLFxuICAgICAgc2hhZGVyOiBzaGFkZXJTdGF0ZSxcbiAgICAgIGF0dHJpYnV0ZXM6IGF0dHJpYnV0ZVN0YXRlLnN0YXRlLFxuICAgICAgdmFvOiBhdHRyaWJ1dGVTdGF0ZSxcbiAgICAgIHVuaWZvcm1zOiB1bmlmb3JtU3RhdGUsXG4gICAgICBmcmFtZWJ1ZmZlcjogZnJhbWVidWZmZXJTdGF0ZSxcbiAgICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnMsXG4gICAgICB0aW1lcjogdGltZXIsXG4gICAgICBpc0J1ZmZlckFyZ3M6IGlzQnVmZmVyQXJnc1xuICAgIH07XG4gICAgdmFyIHNoYXJlZENvbnN0YW50cyA9IHtcbiAgICAgIHByaW1UeXBlczogcHJpbVR5cGVzLFxuICAgICAgY29tcGFyZUZ1bmNzOiBjb21wYXJlRnVuY3MsXG4gICAgICBibGVuZEZ1bmNzOiBibGVuZEZ1bmNzLFxuICAgICAgYmxlbmRFcXVhdGlvbnM6IGJsZW5kRXF1YXRpb25zLFxuICAgICAgc3RlbmNpbE9wczogc3RlbmNpbE9wcyxcbiAgICAgIGdsVHlwZXM6IGdsVHlwZXMsXG4gICAgICBvcmllbnRhdGlvblR5cGU6IG9yaWVudGF0aW9uVHlwZVxuICAgIH07XG4gICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICBzaGFyZWRTdGF0ZS5pc0FycmF
15TGlrZSA9IGlzQXJyYXlMaWtlO1xuICAgIH0pO1xuICAgIGlmIChleHREcmF3QnVmZmVycykge1xuICAgICAgc2hhcmVkQ29uc3RhbnRzLmJhY2tCdWZmZXIgPSBbR0xfQkFDS107XG4gICAgICBzaGFyZWRDb25zdGFudHMuZHJhd0J1ZmZlciA9IGxvb3AobGltaXRzLm1heERyYXdidWZmZXJzLCBmdW5jdGlvbiAoaSkge1xuICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBbMF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvb3AoaSwgZnVuY3Rpb24gKGopIHtcbiAgICAgICAgICByZXR1cm4gR0xfQ09MT1JfQVRUQUNITUVOVDAkMiArIGo7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHZhciBkcmF3Q2FsbENvdW50ZXIgPSAwO1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVJFR0xFbnZpcm9ubWVudCgpIHtcbiAgICAgIHZhciBlbnYgPSBjcmVhdGVFbnZpcm9ubWVudCgpO1xuICAgICAgdmFyIGxpbmsgPSBlbnYubGluaztcbiAgICAgIHZhciBnbG9iYWwgPSBlbnYuZ2xvYmFsO1xuICAgICAgZW52LmlkID0gZHJhd0NhbGxDb3VudGVyKys7XG4gICAgICBlbnYuYmF0Y2hJZCA9ICcwJztcblxuICAgICAgLy8gbGluayBzaGFyZWQgc3RhdGVcbiAgICAgIHZhciBTSEFSRUQgPSBsaW5rKHNoYXJlZFN0YXRlKTtcbiAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkID0ge1xuICAgICAgICBwcm9wczogJ2EwJ1xuICAgICAgfTtcbiAgICAgIE9iamVjdC5rZXlzKHNoYXJlZFN0YXRlKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgIHNoYXJlZFtwcm9wXSA9IGdsb2JhbC5kZWYoU0hBUkVELCAnLicsIHByb3ApO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIEluamVjdCBydW50aW1lIGFzc2VydGlvbiBzdHVmZiBmb3IgZGVidWcgYnVpbGRzXG4gICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZW52LkNIRUNLID0gbGluayhjaGVjayQxKTtcbiAgICAgICAgZW52LmNvbW1hbmRTdHIgPSBjaGVjayQxLmd1ZXNzQ29tbWFuZCgpO1xuICAgICAgICBlbnYuY29tbWFuZCA9IGxpbmsoZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICBlbnYuYXNzZXJ0ID0gZnVuY3Rpb24gKGJsb2NrLCBwcmVkLCBtZXNzYWdlKSB7XG4gICAgICAgICAgYmxvY2soJ2lmKCEoJywgcHJlZCwgJykpJywgdGhpcy5DSEVDSywgJy5jb21tYW5kUmFpc2UoJywgbGluayhtZXNzYWdlKSwgJywnLCB0aGlzLmNvbW1hbmQsICcpOycpO1xuICAgICAgICB9O1xuICAgICAgICBzaGFyZWRDb25zdGFudHMuaW52YWxpZEJsZW5kQ29tYmluYXRpb25zID0gaW52YWxpZEJsZW5kQ29tYmluYXRpb25zO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIENvcHkgR0wgc3RhdGUgdmFyaWFibGVzIG92ZXJcbiAgICAgIHZhciBuZXh0VmFycyA9IGVudi5uZXh0ID0ge307XG4gICAgICB2Y
1XIgY3VycmVudFZhcnMgPSBlbnYuY3VycmVudCA9IHt9O1xuICAgICAgT2JqZWN0LmtleXMoR0xfVkFSSUFCTEVTKS5mb3JFYWNoKGZ1bmN0aW9uICh2YXJpYWJsZSkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50U3RhdGVbdmFyaWFibGVdKSkge1xuICAgICAgICAgIG5leHRWYXJzW3ZhcmlhYmxlXSA9IGdsb2JhbC5kZWYoc2hhcmVkLm5leHQsICcuJywgdmFyaWFibGUpO1xuICAgICAgICAgIGN1cnJlbnRWYXJzW3ZhcmlhYmxlXSA9IGdsb2JhbC5kZWYoc2hhcmVkLmN1cnJlbnQsICcuJywgdmFyaWFibGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gSW5pdGlhbGl6ZSBzaGFyZWQgY29uc3RhbnRzXG4gICAgICB2YXIgY29uc3RhbnRzID0gZW52LmNvbnN0YW50cyA9IHt9O1xuICAgICAgT2JqZWN0LmtleXMoc2hhcmVkQ29uc3RhbnRzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGNvbnN0YW50c1tuYW1lXSA9IGdsb2JhbC5kZWYoSlNPTi5zdHJpbmdpZnkoc2hhcmVkQ29uc3RhbnRzW25hbWVdKSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gSGVscGVyIGZ1bmN0aW9uIGZvciBjYWxsaW5nIGEgYmxvY2tcbiAgICAgIGVudi5pbnZva2UgPSBmdW5jdGlvbiAoYmxvY2ssIHgpIHtcbiAgICAgICAgc3dpdGNoICh4LnR5cGUpIHtcbiAgICAgICAgICBjYXNlIERZTl9GVU5DJDE6XG4gICAgICAgICAgICB2YXIgYXJnTGlzdCA9IFsndGhpcycsIHNoYXJlZC5jb250ZXh0LCBzaGFyZWQucHJvcHMsIGVudi5iYXRjaElkXTtcbiAgICAgICAgICAgIHJldHVybiBibG9jay5kZWYobGluayh4LmRhdGEpLCAnLmNhbGwoJywgYXJnTGlzdC5zbGljZSgwLCBNYXRoLm1heCh4LmRhdGEubGVuZ3RoICsgMSwgNCkpLCAnKScpO1xuICAgICAgICAgIGNhc2UgRFlOX1BST1AkMTpcbiAgICAgICAgICAgIHJldHVybiBibG9jay5kZWYoc2hhcmVkLnByb3BzLCB4LmRhdGEpO1xuICAgICAgICAgIGNhc2UgRFlOX0NPTlRFWFQkMTpcbiAgICAgICAgICAgIHJldHVybiBibG9jay5kZWYoc2hhcmVkLmNvbnRleHQsIHguZGF0YSk7XG4gICAgICAgICAgY2FzZSBEWU5fU1RBVEUkMTpcbiAgICAgICAgICAgIHJldHVybiBibG9jay5kZWYoJ3RoaXMnLCB4LmRhdGEpO1xuICAgICAgICAgIGNhc2UgRFlOX1RIVU5LOlxuICAgICAgICAgICAgeC5kYXRhLmFwcGVuZChlbnYsIGJsb2NrKTtcbiAgICAgICAgICAgIHJldHVybiB4LmRhdGEucmVmO1xuICAgICAgICAgIGNhc2UgRFlOX0NPTlNUQU5UJDE6XG4gICAgICAgICAgICByZXR1cm4geC5kYXRhLnRvU3RyaW5nKCk7XG4gICAgICAgICAgY2FzZSBEWU5fQVJSQVkkMTpcbiAgICAgICAgICAgIHJldHVybiB4LmRhdGEubWFwKGZ1bmN0aW9uICh5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBlbnYuaW52b2tlKGJsb2NrLCB5KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZW52LmF0dHJpYkNhY2hlID0ge307XG4gICAgICB2Y
1XIgc2NvcGVBdHRyaWJzID0ge307XG4gICAgICBlbnYuc2NvcGVBdHRyaWIgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgaWQgPSBzdHJpbmdTdG9yZS5pZChuYW1lKTtcbiAgICAgICAgaWYgKGlkIGluIHNjb3BlQXR0cmlicykge1xuICAgICAgICAgIHJldHVybiBzY29wZUF0dHJpYnNbaWRdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlU3RhdGUuc2NvcGVbaWRdO1xuICAgICAgICBpZiAoIWJpbmRpbmcpIHtcbiAgICAgICAgICBiaW5kaW5nID0gYXR0cmlidXRlU3RhdGUuc2NvcGVbaWRdID0gbmV3IEF0dHJpYnV0ZVJlY29yZCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSBzY29wZUF0dHJpYnNbaWRdID0gbGluayhiaW5kaW5nKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgICByZXR1cm4gZW52O1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFBBUlNJTkdcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICBmdW5jdGlvbiBwYXJzZVByb2ZpbGUob3B0aW9ucykge1xuICAgICAgdmFyIHN0YXRpY09wdGlvbnMgPSBvcHRpb25zLnN0YXRpYztcbiAgICAgIHZhciBkeW5hbWljT3B0aW9ucyA9IG9wdGlvbnMuZHluYW1pYztcbiAgICAgIHZhciBwcm9maWxlRW5hYmxlO1xuICAgICAgaWYgKFNfUFJPRklMRSBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9ICEhc3RhdGljT3B0aW9uc1tTX1BST0ZJTEVdO1xuICAgICAgICBwcm9maWxlRW5hYmxlID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHByb2ZpbGVFbmFibGUuZW5hYmxlID0gdmFsdWU7XG4gICAgICB9IGVsc2UgaWYgKFNfUFJPRklMRSBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICB2Y
1XIgZHluID0gZHluYW1pY09wdGlvbnNbU19QUk9GSUxFXTtcbiAgICAgICAgcHJvZmlsZUVuYWJsZSA9IGNyZWF0ZUR5bmFtaWNEZWNsKGR5biwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICByZXR1cm4gZW52Lmludm9rZShzY29wZSwgZHluKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvZmlsZUVuYWJsZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VGcmFtZWJ1ZmZlcihvcHRpb25zLCBlbnYpIHtcbiAgICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgICB2YXIgZHluYW1pY09wdGlvbnMgPSBvcHRpb25zLmR5bmFtaWM7XG4gICAgICBpZiAoU19GUkFNRUJVRkZFUiBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgIHZhciBmcmFtZWJ1ZmZlciA9IHN0YXRpY09wdGlvbnNbU19GUkFNRUJVRkZFUl07XG4gICAgICAgIGlmIChmcmFtZWJ1ZmZlcikge1xuICAgICAgICAgIGZyYW1lYnVmZmVyID0gZnJhbWVidWZmZXJTdGF0ZS5nZXRGcmFtZWJ1ZmZlcihmcmFtZWJ1ZmZlcik7XG4gICAgICAgICAgY2hlY2skMS5jb21tYW5kKGZyYW1lYnVmZmVyLCAnaW52YWxpZCBmcmFtZWJ1ZmZlciBvYmplY3QnKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52LCBibG9jaykge1xuICAgICAgICAgICAgdmFyIEZSQU1FQlVGRkVSID0gZW52LmxpbmsoZnJhbWVidWZmZXIpO1xuICAgICAgICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICAgICAgICBibG9jay5zZXQoc2hhcmVkLmZyYW1lYnVmZmVyLCAnLm5leHQnLCBGUkFNRUJVRkZFUik7XG4gICAgICAgICAgICB2Y
1XIgQ09OVEVYVCA9IHNoYXJlZC5jb250ZXh0O1xuICAgICAgICAgICAgYmxvY2suc2V0KENPTlRFWFQsICcuJyArIFNfRlJBTUVCVUZGRVJfV0lEVEgsIEZSQU1FQlVGRkVSICsgJy53aWR0aCcpO1xuICAgICAgICAgICAgYmxvY2suc2V0KENPTlRFWFQsICcuJyArIFNfRlJBTUVCVUZGRVJfSEVJR0hULCBGUkFNRUJVRkZFUiArICcuaGVpZ2h0Jyk7XG4gICAgICAgICAgICByZXR1cm4gRlJBTUVCVUZGRVI7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgICAgICAgc2NvcGUuc2V0KHNoYXJlZC5mcmFtZWJ1ZmZlciwgJy5uZXh0JywgJ251bGwnKTtcbiAgICAgICAgICAgIHZhciBDT05URVhUID0gc2hhcmVkLmNvbnRleHQ7XG4gICAgICAgICAgICBzY29wZS5zZXQoQ09OVEVYVCwgJy4nICsgU19GUkFNRUJVRkZFUl9XSURUSCwgQ09OVEVYVCArICcuJyArIFNfRFJBV0lOR0JVRkZFUl9XSURUSCk7XG4gICAgICAgICAgICBzY29wZS5zZXQoQ09OVEVYVCwgJy4nICsgU19GUkFNRUJVRkZFUl9IRUlHSFQsIENPTlRFWFQgKyAnLicgKyBTX0RSQVdJTkdCVUZGRVJfSEVJR0hUKTtcbiAgICAgICAgICAgIHJldHVybiAnbnVsbCc7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoU19GUkFNRUJVRkZFUiBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICB2Y
1XIgZHluID0gZHluYW1pY09wdGlvbnNbU19GUkFNRUJVRkZFUl07XG4gICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgdmFyIEZSQU1FQlVGRkVSX0ZVTkMgPSBlbnYuaW52b2tlKHNjb3BlLCBkeW4pO1xuICAgICAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgICAgIHZhciBGUkFNRUJVRkZFUl9TVEFURSA9IHNoYXJlZC5mcmFtZWJ1ZmZlcjtcbiAgICAgICAgICB2YXIgRlJBTUVCVUZGRVIgPSBzY29wZS5kZWYoRlJBTUVCVUZGRVJfU1RBVEUsICcuZ2V0RnJhbWVidWZmZXIoJywgRlJBTUVCVUZGRVJfRlVOQywgJyknKTtcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsICchJyArIEZSQU1FQlVGRkVSX0ZVTkMgKyAnfHwnICsgRlJBTUVCVUZGRVIsICdpbnZhbGlkIGZyYW1lYnVmZmVyIG9iamVjdCcpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHNjb3BlLnNldChGUkFNRUJVRkZFUl9TVEFURSwgJy5uZXh0JywgRlJBTUVCVUZGRVIpO1xuICAgICAgICAgIHZhciBDT05URVhUID0gc2hhcmVkLmNvbnRleHQ7XG4gICAgICAgICAgc2NvcGUuc2V0KENPTlRFWFQsICcuJyArIFNfRlJBTUVCVUZGRVJfV0lEVEgsIEZSQU1FQlVGRkVSICsgJz8nICsgRlJBTUVCVUZGRVIgKyAnLndpZHRoOicgKyBDT05URVhUICsgJy4nICsgU19EUkFXSU5HQlVGRkVSX1dJRFRIKTtcbiAgICAgICAgICBzY29wZS5zZXQoQ09OVEVYVCwgJy4nICsgU19GUkFNRUJVRkZFUl9IRUlHSFQsIEZSQU1FQlVGRkVSICsgJz8nICsgRlJBTUVCVUZGRVIgKyAnLmhlaWdodDonICsgQ09OVEVYVCArICcuJyArIFNfRFJBV0lOR0JVRkZFUl9IRUlHSFQpO1xuICAgICAgICAgIHJldHVybiBGUkFNRUJVRkZFUjtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VWaWV3cG9ydFNjaXNzb3Iob3B0aW9ucywgZnJhbWVidWZmZXIsIGVudikge1xuICAgICAgdmFyIHN0YXRpY09wdGlvbnMgPSBvcHRpb25zLnN0YXRpYztcbiAgICAgIHZhciBkeW5hbWljT3B0aW9ucyA9IG9wdGlvbnMuZHluYW1pYztcbiAgICAgIGZ1bmN0aW9uIHBhcnNlQm94KHBhcmFtKSB7XG4gICAgICAgIGlmIChwYXJhbSBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGJveCA9IHN0YXRpY09wdGlvbnNbcGFyYW1dO1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUoYm94LCAnb2JqZWN0JywgJ2ludmFsaWQgJyArIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgdmFyIGlzU3RhdGljID0gdHJ1ZTtcbiAgICAgICAgICB2Y
1XIgeCA9IGJveC54IHwgMDtcbiAgICAgICAgICB2YXIgeSA9IGJveC55IHwgMDtcbiAgICAgICAgICB2YXIgdywgaDtcbiAgICAgICAgICBpZiAoJ3dpZHRoJyBpbiBib3gpIHtcbiAgICAgICAgICAgIHcgPSBib3gud2lkdGggfCAwO1xuICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKHcgPj0gMCwgJ2ludmFsaWQgJyArIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlzU3RhdGljID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnaGVpZ2h0JyBpbiBib3gpIHtcbiAgICAgICAgICAgIGggPSBib3guaGVpZ2h0IHwgMDtcbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChoID49IDAsICdpbnZhbGlkICcgKyBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc1N0YXRpYyA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKCFpc1N0YXRpYyAmJiBmcmFtZWJ1ZmZlciAmJiBmcmFtZWJ1ZmZlci50aGlzRGVwLCAhaXNTdGF0aWMgJiYgZnJhbWVidWZmZXIgJiYgZnJhbWVidWZmZXIuY29udGV4dERlcCwgIWlzU3RhdGljICYmIGZyYW1lYnVmZmVyICYmIGZyYW1lYnVmZmVyLnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICB2YXIgQ09OVEVYVCA9IGVudi5zaGFyZWQuY29udGV4dDtcbiAgICAgICAgICAgIHZhciBCT1hfVyA9IHc7XG4gICAgICAgICAgICBpZiAoISgnd2lkdGgnIGluIGJveCkpIHtcbiAgICAgICAgICAgICAgQk9YX1cgPSBzY29wZS5kZWYoQ09OVEVYVCwgJy4nLCBTX0ZSQU1FQlVGRkVSX1dJRFRILCAnLScsIHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIEJPWF9IID0gaDtcbiAgICAgICAgICAgIGlmICghKCdoZWlnaHQnIGluIGJveCkpIHtcbiAgICAgICAgICAgICAgQk9YX0ggPSBzY29wZS5kZWYoQ09OVEVYVCwgJy4nLCBTX0ZSQU1FQlVGRkVSX0hFSUdIVCwgJy0nLCB5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbeCwgeSwgQk9YX1csIEJPWF9IXTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbSBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICAgIHZhciBkeW5Cb3ggPSBkeW5hbWljT3B0aW9uc1twYXJhbV07XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZUR5bmFtaWNEZWNsKGR5bkJveCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciBCT1ggPSBlbnYuaW52b2tlKHNjb3BlLCBkeW5Cb3gpO1xuICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIEJPWCArICcmJnR5cGVvZiAnICsgQk9YICsgJz09PVwib2JqZWN0XCInLCAnaW52YWxpZCAnICsgcGFyYW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2Y
1XIgQ09OVEVYVCA9IGVudi5zaGFyZWQuY29udGV4dDtcbiAgICAgICAgICAgIHZhciBCT1hfWCA9IHNjb3BlLmRlZihCT1gsICcueHwwJyk7XG4gICAgICAgICAgICB2YXIgQk9YX1kgPSBzY29wZS5kZWYoQk9YLCAnLnl8MCcpO1xuICAgICAgICAgICAgdmFyIEJPWF9XID0gc2NvcGUuZGVmKCdcIndpZHRoXCIgaW4gJywgQk9YLCAnPycsIEJPWCwgJy53aWR0aHwwOicsICcoJywgQ09OVEVYVCwgJy4nLCBTX0ZSQU1FQlVGRkVSX1dJRFRILCAnLScsIEJPWF9YLCAnKScpO1xuICAgICAgICAgICAgdmFyIEJPWF9IID0gc2NvcGUuZGVmKCdcImhlaWdodFwiIGluICcsIEJPWCwgJz8nLCBCT1gsICcuaGVpZ2h0fDA6JywgJygnLCBDT05URVhULCAnLicsIFNfRlJBTUVCVUZGRVJfSEVJR0hULCAnLScsIEJPWF9ZLCAnKScpO1xuICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIEJPWF9XICsgJz49MCYmJyArIEJPWF9IICsgJz49MCcsICdpbnZhbGlkICcgKyBwYXJhbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBbQk9YX1gsIEJPWF9ZLCBCT1hfVywgQk9YX0hdO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChmcmFtZWJ1ZmZlcikge1xuICAgICAgICAgICAgcmVzdWx0LnRoaXNEZXAgPSByZXN1bHQudGhpc0RlcCB8fCBmcmFtZWJ1ZmZlci50aGlzRGVwO1xuICAgICAgICAgICAgcmVzdWx0LmNvbnRleHREZXAgPSByZXN1bHQuY29udGV4dERlcCB8fCBmcmFtZWJ1ZmZlci5jb250ZXh0RGVwO1xuICAgICAgICAgICAgcmVzdWx0LnByb3BEZXAgPSByZXN1bHQucHJvcERlcCB8fCBmcmFtZWJ1ZmZlci5wcm9wRGVwO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9IGVsc2UgaWYgKGZyYW1lYnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihmcmFtZWJ1ZmZlci50aGlzRGVwLCBmcmFtZWJ1ZmZlci5jb250ZXh0RGVwLCBmcmFtZWJ1ZmZlci5wcm9wRGVwLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIENPTlRFWFQgPSBlbnYuc2hhcmVkLmNvbnRleHQ7XG4gICAgICAgICAgICByZXR1cm4gWzAsIDAsIHNjb3BlLmRlZihDT05URVhULCAnLicsIFNfRlJBTUVCVUZGRVJfV0lEVEgpLCBzY29wZS5kZWYoQ09OVEVYVCwgJy4nLCBTX0ZSQU1FQlVGRkVSX0hFSUdIVCldO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2Y
1XIgdmlld3BvcnQgPSBwYXJzZUJveChTX1ZJRVdQT1JUKTtcbiAgICAgIGlmICh2aWV3cG9ydCkge1xuICAgICAgICB2YXIgcHJldlZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgICAgIHZpZXdwb3J0ID0gbmV3IERlY2xhcmF0aW9uKHZpZXdwb3J0LnRoaXNEZXAsIHZpZXdwb3J0LmNvbnRleHREZXAsIHZpZXdwb3J0LnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgdmFyIFZJRVdQT1JUID0gcHJldlZpZXdwb3J0LmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgICAgICB2YXIgQ09OVEVYVCA9IGVudi5zaGFyZWQuY29udGV4dDtcbiAgICAgICAgICBzY29wZS5zZXQoQ09OVEVYVCwgJy4nICsgU19WSUVXUE9SVF9XSURUSCwgVklFV1BPUlRbMl0pO1xuICAgICAgICAgIHNjb3BlLnNldChDT05URVhULCAnLicgKyBTX1ZJRVdQT1JUX0hFSUdIVCwgVklFV1BPUlRbM10pO1xuICAgICAgICAgIHJldHVybiBWSUVXUE9SVDtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2aWV3cG9ydDogdmlld3BvcnQsXG4gICAgICAgIHNjaXNzb3JfYm94OiBwYXJzZUJveChTX1NDSVNTT1JfQk9YKVxuICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VBdHRyaWJMb2NhdGlvbnMob3B0aW9ucywgYXR0cmlidXRlcykge1xuICAgICAgdmFyIHN0YXRpY09wdGlvbnMgPSBvcHRpb25zLnN0YXRpYztcbiAgICAgIHZhciBzdGF0aWNQcm9ncmFtID0gdHlwZW9mIHN0YXRpY09wdGlvbnNbU19GUkFHXSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIHN0YXRpY09wdGlvbnNbU19WRVJUXSA9PT0gJ3N0cmluZyc7XG4gICAgICBpZiAoc3RhdGljUHJvZ3JhbSkge1xuICAgICAgICBpZiAoT2JqZWN0LmtleXMoYXR0cmlidXRlcy5keW5hbWljKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN0YXRpY0F0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLnN0YXRpYztcbiAgICAgICAgdmFyIHNBdHRyaWJ1dGVzID0gT2JqZWN0LmtleXMoc3RhdGljQXR0cmlidXRlcyk7XG4gICAgICAgIGlmIChzQXR0cmlidXRlcy5sZW5ndGggPiAwICYmIHR5cGVvZiBzdGF0aWNBdHRyaWJ1dGVzW3NBdHRyaWJ1dGVzWzBdXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICB2Y
1XIgYmluZGluZ3MgPSBbXTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNBdHRyaWJ1dGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBjaGVjayQxKHR5cGVvZiBzdGF0aWNBdHRyaWJ1dGVzW3NBdHRyaWJ1dGVzW2ldXSA9PT0gJ251bWJlcicsICdtdXN0IHNwZWNpZnkgYWxsIHZlcnRleCBhdHRyaWJ1dGUgbG9jYXRpb25zIHdoZW4gdXNpbmcgdmFvcycpO1xuICAgICAgICAgICAgYmluZGluZ3MucHVzaChbc3RhdGljQXR0cmlidXRlc1tzQXR0cmlidXRlc1tpXV0gfCAwLCBzQXR0cmlidXRlc1tpXV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYmluZGluZ3M7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJzZVByb2dyYW0ob3B0aW9ucywgZW52LCBhdHRyaWJMb2NhdGlvbnMpIHtcbiAgICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgICB2YXIgZHluYW1pY09wdGlvbnMgPSBvcHRpb25zLmR5bmFtaWM7XG4gICAgICBmdW5jdGlvbiBwYXJzZVNoYWRlcihuYW1lKSB7XG4gICAgICAgIGlmIChuYW1lIGluIHN0YXRpY09wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgaWQgPSBzdHJpbmdTdG9yZS5pZChzdGF0aWNPcHRpb25zW25hbWVdKTtcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNoYWRlclN0YXRlLnNoYWRlcihzaGFkZXJUeXBlW25hbWVdLCBpZCwgY2hlY2skMS5ndWVzc0NvbW1hbmQoKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIGlkO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSBpZiAobmFtZSBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICAgIHZhciBkeW4gPSBkeW5hbWljT3B0aW9uc1tuYW1lXTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlRHluYW1pY0RlY2woZHluLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIHN0ciA9IGVudi5pbnZva2Uoc2NvcGUsIGR5bik7XG4gICAgICAgICAgICB2Y
1XIgaWQgPSBzY29wZS5kZWYoZW52LnNoYXJlZC5zdHJpbmdzLCAnLmlkKCcsIHN0ciwgJyknKTtcbiAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBzY29wZShlbnYuc2hhcmVkLnNoYWRlciwgJy5zaGFkZXIoJywgc2hhZGVyVHlwZVtuYW1lXSwgJywnLCBpZCwgJywnLCBlbnYuY29tbWFuZCwgJyk7Jyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBpZDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhciBmcmFnID0gcGFyc2VTaGFkZXIoU19GUkFHKTtcbiAgICAgIHZhciB2ZXJ0ID0gcGFyc2VTaGFkZXIoU19WRVJUKTtcbiAgICAgIHZhciBwcm9ncmFtID0gbnVsbDtcbiAgICAgIHZhciBwcm9nVmFyO1xuICAgICAgaWYgKGlzU3RhdGljKGZyYWcpICYmIGlzU3RhdGljKHZlcnQpKSB7XG4gICAgICAgIHByb2dyYW0gPSBzaGFkZXJTdGF0ZS5wcm9ncmFtKHZlcnQuaWQsIGZyYWcuaWQsIG51bGwsIGF0dHJpYkxvY2F0aW9ucyk7XG4gICAgICAgIHByb2dWYXIgPSBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgcmV0dXJuIGVudi5saW5rKHByb2dyYW0pO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHByb2dWYXIgPSBuZXcgRGVjbGFyYXRpb24oZnJhZyAmJiBmcmFnLnRoaXNEZXAgfHwgdmVydCAmJiB2ZXJ0LnRoaXNEZXAsIGZyYWcgJiYgZnJhZy5jb250ZXh0RGVwIHx8IHZlcnQgJiYgdmVydC5jb250ZXh0RGVwLCBmcmFnICYmIGZyYWcucHJvcERlcCB8fCB2ZXJ0ICYmIHZlcnQucHJvcERlcCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2Y
1XIgU0hBREVSX1NUQVRFID0gZW52LnNoYXJlZC5zaGFkZXI7XG4gICAgICAgICAgdmFyIGZyYWdJZDtcbiAgICAgICAgICBpZiAoZnJhZykge1xuICAgICAgICAgICAgZnJhZ0lkID0gZnJhZy5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZyYWdJZCA9IHNjb3BlLmRlZihTSEFERVJfU1RBVEUsICcuJywgU19GUkFHKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHZlcnRJZDtcbiAgICAgICAgICBpZiAodmVydCkge1xuICAgICAgICAgICAgdmVydElkID0gdmVydC5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZlcnRJZCA9IHNjb3BlLmRlZihTSEFERVJfU1RBVEUsICcuJywgU19WRVJUKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHByb2dEZWYgPSBTSEFERVJfU1RBVEUgKyAnLnByb2dyYW0oJyArIHZlcnRJZCArICcsJyArIGZyYWdJZDtcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHByb2dEZWYgKz0gJywnICsgZW52LmNvbW1hbmQ7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihwcm9nRGVmICsgJyknKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBmcmFnOiBmcmFnLFxuICAgICAgICB2ZXJ0OiB2ZXJ0LFxuICAgICAgICBwcm9nVmFyOiBwcm9nVmFyLFxuICAgICAgICBwcm9ncmFtOiBwcm9ncmFtXG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJzZURyYXcob3B0aW9ucywgZW52KSB7XG4gICAgICB2Y
1XIgc3RhdGljT3B0aW9ucyA9IG9wdGlvbnMuc3RhdGljO1xuICAgICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuXG4gICAgICAvLyBUT0RPOiBzaG91bGQgdXNlIFZBTyB0byBnZXQgZGVmYXVsdCB2YWx1ZXMgZm9yIG9mZnNldCBwcm9wZXJ0aWVzXG4gICAgICAvLyBzaG91bGQgbW92ZSB2YW8gcGFyc2UgaW50byBoZXJlIGFuZCBvdXQgb2YgdGhlIG9sZCBzdHVmZlxuXG4gICAgICB2YXIgc3RhdGljRHJhdyA9IHt9O1xuICAgICAgdmFyIHZhb0FjdGl2ZSA9IGZhbHNlO1xuICAgICAgZnVuY3Rpb24gcGFyc2VWQU8oKSB7XG4gICAgICAgIGlmIChTX1ZBTyBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIHZhbyA9IHN0YXRpY09wdGlvbnNbU19WQU9dO1xuICAgICAgICAgIGlmICh2YW8gIT09IG51bGwgJiYgYXR0cmlidXRlU3RhdGUuZ2V0VkFPKHZhbykgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHZhbyA9IGF0dHJpYnV0ZVN0YXRlLmNyZWF0ZVZBTyh2YW8pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YW9BY3RpdmUgPSB0cnVlO1xuICAgICAgICAgIHN0YXRpY0RyYXcudmFvID0gdmFvO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYpIHtcbiAgICAgICAgICAgIHZhciB2YW9SZWYgPSBhdHRyaWJ1dGVTdGF0ZS5nZXRWQU8odmFvKTtcbiAgICAgICAgICAgIGlmICh2YW9SZWYpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGVudi5saW5rKHZhb1JlZik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKFNfVkFPIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFvQWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgICB2Y
1XIgZHluID0gZHluYW1pY09wdGlvbnNbU19WQU9dO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICB2YXIgdmFvUmVmID0gZW52Lmludm9rZShzY29wZSwgZHluKTtcbiAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoZW52LnNoYXJlZC52YW8gKyAnLmdldFZBTygnICsgdmFvUmVmICsgJyknKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhciB2YW8gPSBwYXJzZVZBTygpO1xuICAgICAgdmFyIGVsZW1lbnRzQWN0aXZlID0gZmFsc2U7XG4gICAgICBmdW5jdGlvbiBwYXJzZUVsZW1lbnRzKCkge1xuICAgICAgICBpZiAoU19FTEVNRU5UUyBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGVsZW1lbnRzID0gc3RhdGljT3B0aW9uc1tTX0VMRU1FTlRTXTtcbiAgICAgICAgICBzdGF0aWNEcmF3LmVsZW1lbnRzID0gZWxlbWVudHM7XG4gICAgICAgICAgaWYgKGlzQnVmZmVyQXJncyhlbGVtZW50cykpIHtcbiAgICAgICAgICAgIHZhciBlID0gc3RhdGljRHJhdy5lbGVtZW50cyA9IGVsZW1lbnRTdGF0ZS5jcmVhdGUoZWxlbWVudHMsIHRydWUpO1xuICAgICAgICAgICAgZWxlbWVudHMgPSBlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHMoZSk7XG4gICAgICAgICAgICBlbGVtZW50c0FjdGl2ZSA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIGlmIChlbGVtZW50cykge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgICAgICAgZWxlbWVudHNBY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGVsZW1lbnRzLCAnaW52YWxpZCBlbGVtZW50cycsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50cykge1xuICAgICAgICAgICAgICB2Y
1XIgcmVzdWx0ID0gZW52LmxpbmsoZWxlbWVudHMpO1xuICAgICAgICAgICAgICBlbnYuRUxFTUVOVFMgPSByZXN1bHQ7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbnYuRUxFTUVOVFMgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmVzdWx0LnZhbHVlID0gZWxlbWVudHM7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBlbHNlIGlmIChTX0VMRU1FTlRTIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICAgICAgZWxlbWVudHNBY3RpdmUgPSB0cnVlO1xuICAgICAgICAgIHZhciBkeW4gPSBkeW5hbWljT3B0aW9uc1tTX0VMRU1FTlRTXTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlRHluYW1pY0RlY2woZHluLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICAgICAgICB2YXIgSVNfQlVGRkVSX0FSR1MgPSBzaGFyZWQuaXNCdWZmZXJBcmdzO1xuICAgICAgICAgICAgdmFyIEVMRU1FTlRfU1RBVEUgPSBzaGFyZWQuZWxlbWVudHM7XG4gICAgICAgICAgICB2YXIgZWxlbWVudERlZm4gPSBlbnYuaW52b2tlKHNjb3BlLCBkeW4pO1xuICAgICAgICAgICAgdmFyIGVsZW1lbnRzID0gc2NvcGUuZGVmKCdudWxsJyk7XG4gICAgICAgICAgICB2YXIgZWxlbWVudFN0cmVhbSA9IHNjb3BlLmRlZihJU19CVUZGRVJfQVJHUywgJygnLCBlbGVtZW50RGVmbiwgJyknKTtcbiAgICAgICAgICAgIHZhciBpZnRlID0gZW52LmNvbmQoZWxlbWVudFN0cmVhbSkudGhlbihlbGVtZW50cywgJz0nLCBFTEVNRU5UX1NUQVRFLCAnLmNyZWF0ZVN0cmVhbSgnLCBlbGVtZW50RGVmbiwgJyk7JykuZWxzZShlbGVtZW50cywgJz0nLCBFTEVNRU5UX1NUQVRFLCAnLmdldEVsZW1lbnRzKCcsIGVsZW1lbnREZWZuLCAnKTsnKTtcbiAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBlbnYuYXNzZXJ0KGlmdGUuZWxzZSwgJyEnICsgZWxlbWVudERlZm4gKyAnfHwnICsgZWxlbWVudHMsICdpbnZhbGlkIGVsZW1lbnRzJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNjb3BlLmVudHJ5KGlmdGUpO1xuICAgICAgICAgICAgc2NvcGUuZXhpdChlbnYuY29uZChlbGVtZW50U3RyZWFtKS50aGVuKEVMRU1FTlRfU1RBVEUsICcuZGVzdHJveVN0cmVhbSgnLCBlbGVtZW50cywgJyk7JykpO1xuICAgICAgICAgICAgZW52LkVMRU1FTlRTID0gZWxlbWVudHM7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAodmFvQWN0aXZlKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbih2YW8udGhpc0RlcCwgdmFvLmNvbnRleHREZXAsIHZhby5wcm9wRGVwLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbnYuc2hhcmVkLnZhbyArICcuY3VycmVudFZBTz8nICsgZW52LnNoYXJlZC5lbGVtZW50cyArICcuZ2V0RWxlbWVudHMoJyArIGVudi5zaGFyZWQudmFvICsgJy5jdXJyZW50VkFPLmVsZW1lbnRzKTpudWxsJyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICB2Y
1XIgZWxlbWVudHMgPSBwYXJzZUVsZW1lbnRzKCk7XG4gICAgICBmdW5jdGlvbiBwYXJzZVByaW1pdGl2ZSgpIHtcbiAgICAgICAgaWYgKFNfUFJJTUlUSVZFIGluIHN0YXRpY09wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgcHJpbWl0aXZlID0gc3RhdGljT3B0aW9uc1tTX1BSSU1JVElWRV07XG4gICAgICAgICAgc3RhdGljRHJhdy5wcmltaXRpdmUgPSBwcmltaXRpdmU7XG4gICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHByaW1pdGl2ZSwgcHJpbVR5cGVzLCAnaW52YWxpZCBwcmltaXR2ZScsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgcmV0dXJuIHByaW1UeXBlc1twcmltaXRpdmVdO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKFNfUFJJTUlUSVZFIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGR5blByaW1pdGl2ZSA9IGR5bmFtaWNPcHRpb25zW1NfUFJJTUlUSVZFXTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlRHluYW1pY0RlY2woZHluUHJpbWl0aXZlLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIFBSSU1fVFlQRVMgPSBlbnYuY29uc3RhbnRzLnByaW1UeXBlcztcbiAgICAgICAgICAgIHZhciBwcmltID0gZW52Lmludm9rZShzY29wZSwgZHluUHJpbWl0aXZlKTtcbiAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCBwcmltICsgJyBpbiAnICsgUFJJTV9UWVBFUywgJ2ludmFsaWQgcHJpbWl0aXZlLCBtdXN0IGJlIG9uZSBvZiAnICsgT2JqZWN0LmtleXMocHJpbVR5cGVzKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoUFJJTV9UWVBFUywgJ1snLCBwcmltLCAnXScpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGVsZW1lbnRzQWN0aXZlKSB7XG4gICAgICAgICAgaWYgKGlzU3RhdGljKGVsZW1lbnRzKSkge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRzLnZhbHVlKSB7XG4gICAgICAgICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbnYuRUxFTUVOVFMsICcucHJpbVR5cGUnKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEdMX1RSSUFOR0xFUyQxO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihlbGVtZW50cy50aGlzRGVwLCBlbGVtZW50cy5jb250ZXh0RGVwLCBlbGVtZW50cy5wcm9wRGVwLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgICB2Y
1XIgZWxlbWVudHMgPSBlbnYuRUxFTUVOVFM7XG4gICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoZWxlbWVudHMsICc/JywgZWxlbWVudHMsICcucHJpbVR5cGU6JywgR0xfVFJJQU5HTEVTJDEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHZhb0FjdGl2ZSkge1xuICAgICAgICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24odmFvLnRoaXNEZXAsIHZhby5jb250ZXh0RGVwLCB2YW8ucHJvcERlcCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoZW52LnNoYXJlZC52YW8gKyAnLmN1cnJlbnRWQU8/JyArIGVudi5zaGFyZWQudmFvICsgJy5jdXJyZW50VkFPLnByaW1pdGl2ZTonICsgR0xfVFJJQU5HTEVTJDEpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcGFyc2VQYXJhbShwYXJhbSwgaXNPZmZzZXQpIHtcbiAgICAgICAgaWYgKHBhcmFtIGluIHN0YXRpY09wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBzdGF0aWNPcHRpb25zW3BhcmFtXSB8IDA7XG4gICAgICAgICAgaWYgKGlzT2Zmc2V0KSB7XG4gICAgICAgICAgICBzdGF0aWNEcmF3Lm9mZnNldCA9IHZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0aWNEcmF3Lmluc3RhbmNlcyA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoIWlzT2Zmc2V0IHx8IHZhbHVlID49IDAsICdpbnZhbGlkICcgKyBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICBpZiAoaXNPZmZzZXQpIHtcbiAgICAgICAgICAgICAgZW52Lk9GRlNFVCA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGR5blZhbHVlID0gZHluYW1pY09wdGlvbnNbcGFyYW1dO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW5WYWx1ZSwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBlbnYuaW52b2tlKHNjb3BlLCBkeW5WYWx1ZSk7XG4gICAgICAgICAgICBpZiAoaXNPZmZzZXQpIHtcbiAgICAgICAgICAgICAgZW52Lk9GRlNFVCA9IHJlc3VsdDtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgcmVzdWx0ICsgJz49MCcsICdpbnZhbGlkICcgKyBwYXJhbSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChpc09mZnNldCkge1xuICAgICAgICAgIGlmIChlbGVtZW50c0FjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgZW52Lk9GRlNFVCA9IDA7XG4gICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh2YW9BY3RpdmUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24odmFvLnRoaXNEZXAsIHZhby5jb250ZXh0RGVwLCB2YW8ucHJvcERlcCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbnYuc2hhcmVkLnZhbyArICcuY3VycmVudFZBTz8nICsgZW52LnNoYXJlZC52YW8gKyAnLmN1cnJlbnRWQU8ub2Zmc2V0OjAnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh2YW9BY3RpdmUpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKHZhby50aGlzRGVwLCB2YW8uY29udGV4dERlcCwgdmFvLnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVudi5zaGFyZWQudmFvICsgJy5jdXJyZW50VkFPPycgKyBlbnYuc2hhcmVkLnZhbyArICcuY3VycmVudFZBTy5pbnN0YW5jZXM6LTEnKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhciBPRkZTRVQgPSBwYXJzZVBhcmFtKFNfT0ZGU0VULCB0cnVlKTtcbiAgICAgIGZ1bmN0aW9uIHBhcnNlVmVydENvdW50KCkge1xuICAgICAgICBpZiAoU19DT1VOVCBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgICAgdmFyIGNvdW50ID0gc3RhdGljT3B0aW9uc1tTX0NPVU5UXSB8IDA7XG4gICAgICAgICAgc3RhdGljRHJhdy5jb3VudCA9IGNvdW50O1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2YgY291bnQgPT09ICdudW1iZXInICYmIGNvdW50ID49IDAsICdpbnZhbGlkIHZlcnRleCBjb3VudCcsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoU19DT1VOVCBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICAgIHZhciBkeW5Db3VudCA9IGR5bmFtaWNPcHRpb25zW1NfQ09VTlRdO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW5Db3VudCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBlbnYuaW52b2tlKHNjb3BlLCBkeW5Db3VudCk7XG4gICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgJ3R5cGVvZiAnICsgcmVzdWx0ICsgJz09PVwibnVtYmVyXCImJicgKyByZXN1bHQgKyAnPj0wJiYnICsgcmVzdWx0ICsgJz09PSgnICsgcmVzdWx0ICsgJ3wwKScsICdpbnZhbGlkIHZlcnRleCBjb3VudCcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgI
1H0pO1xuICAgICAgICB9IGVsc2UgaWYgKGVsZW1lbnRzQWN0aXZlKSB7XG4gICAgICAgICAgaWYgKGlzU3RhdGljKGVsZW1lbnRzKSkge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRzKSB7XG4gICAgICAgICAgICAgIGlmIChPRkZTRVQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKE9GRlNFVC50aGlzRGVwLCBPRkZTRVQuY29udGV4dERlcCwgT0ZGU0VULnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gc2NvcGUuZGVmKGVudi5FTEVNRU5UUywgJy52ZXJ0Q291bnQtJywgZW52Lk9GRlNFVCk7XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgcmVzdWx0ICsgJz49MCcsICdpbnZhbGlkIHZlcnRleCBvZmZzZXQvZWxlbWVudCBidWZmZXIgdG9vIHNtYWxsJyk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoZW52LkVMRU1FTlRTLCAnLnZlcnRDb3VudCcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2Y
1XIgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0Lk1JU1NJTkcgPSB0cnVlO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHZhcmlhYmxlID0gbmV3IERlY2xhcmF0aW9uKGVsZW1lbnRzLnRoaXNEZXAgfHwgT0ZGU0VULnRoaXNEZXAsIGVsZW1lbnRzLmNvbnRleHREZXAgfHwgT0ZGU0VULmNvbnRleHREZXAsIGVsZW1lbnRzLnByb3BEZXAgfHwgT0ZGU0VULnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgIHZhciBlbGVtZW50cyA9IGVudi5FTEVNRU5UUztcbiAgICAgICAgICAgICAgaWYgKGVudi5PRkZTRVQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVsZW1lbnRzLCAnPycsIGVsZW1lbnRzLCAnLnZlcnRDb3VudC0nLCBlbnYuT0ZGU0VULCAnOi0xJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbGVtZW50cywgJz8nLCBlbGVtZW50cywgJy52ZXJ0Q291bnQ6LTEnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHZhcmlhYmxlLkRZTkFNSUMgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gdmFyaWFibGU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHZhb0FjdGl2ZSkge1xuICAgICAgICAgIHZhciBjb3VudFZhcmlhYmxlID0gbmV3IERlY2xhcmF0aW9uKHZhby50aGlzRGVwLCB2YW8uY29udGV4dERlcCwgdmFvLnByb3BEZXAsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVudi5zaGFyZWQudmFvLCAnLmN1cnJlbnRWQU8/JywgZW52LnNoYXJlZC52YW8sICcuY3VycmVudFZBTy5jb3VudDotMScpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBjb3VudFZhcmlhYmxlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgdmFyIHByaW1pdGl2ZSA9IHBhcnNlUHJpbWl0aXZlKCk7XG4gICAgICB2Y
1XIgY291bnQgPSBwYXJzZVZlcnRDb3VudCgpO1xuICAgICAgdmFyIGluc3RhbmNlcyA9IHBhcnNlUGFyYW0oU19JTlNUQU5DRVMsIGZhbHNlKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICAgICAgcHJpbWl0aXZlOiBwcmltaXRpdmUsXG4gICAgICAgIGNvdW50OiBjb3VudCxcbiAgICAgICAgaW5zdGFuY2VzOiBpbnN0YW5jZXMsXG4gICAgICAgIG9mZnNldDogT0ZGU0VULFxuICAgICAgICB2YW86IHZhbyxcbiAgICAgICAgdmFvQWN0aXZlOiB2YW9BY3RpdmUsXG4gICAgICAgIGVsZW1lbnRzQWN0aXZlOiBlbGVtZW50c0FjdGl2ZSxcbiAgICAgICAgLy8gc3RhdGljIGRyYXcgcHJvcHNcbiAgICAgICAgc3RhdGljOiBzdGF0aWNEcmF3XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJzZUdMU3RhdGUob3B0aW9ucywgZW52KSB7XG4gICAgICB2YXIgc3RhdGljT3B0aW9ucyA9IG9wdGlvbnMuc3RhdGljO1xuICAgICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuICAgICAgdmFyIFNUQVRFID0ge307XG4gICAgICBHTF9TVEFURV9OQU1FUy5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgIHZhciBwYXJhbSA9IHByb3BOYW1lKHByb3ApO1xuICAgICAgICBmdW5jdGlvbiBwYXJzZVBhcmFtKHBhcnNlU3RhdGljLCBwYXJzZUR5bmFtaWMpIHtcbiAgICAgICAgICBpZiAocHJvcCBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBwYXJzZVN0YXRpYyhzdGF0aWNPcHRpb25zW3Byb3BdKTtcbiAgICAgICAgICAgIFNUQVRFW3BhcmFtXSA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHByb3AgaW4gZHluYW1pY09wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBkeW4gPSBkeW5hbWljT3B0aW9uc1twcm9wXTtcbiAgICAgICAgICAgIFNUQVRFW3BhcmFtXSA9IGNyZWF0ZUR5bmFtaWNEZWNsKGR5biwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlRHluYW1pYyhlbnYsIHNjb3BlLCBlbnYuaW52b2tlKHNjb3BlLCBkeW4pKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKHByb3ApIHtcbiAgICAgICAgICBjYXNlIFNfQ1VMTF9FTkFCTEU6XG4gICAgICAgICAgY2FzZSBTX0JMRU5EX0VOQUJMRTpcbiAgICAgICAgICBjYXNlIFNfRElUSEVSOlxuICAgICAgICAgIGNhc2UgU19TVEVOQ0lMX0VOQUJMRTpcbiAgICAgICAgICBjYXNlIFNfREVQVEhfRU5BQkxFOlxuICAgICAgICAgIGNhc2UgU19TQ0lTU09SX0VOQUJMRTpcbiAgICAgICAgICBjYXNlIFNfUE9MWUdPTl9PRkZTRVRfRU5BQkxFOlxuICAgICAgICAgIGNhc2UgU19TQU1QTEVfQUxQSEE6XG4gICAgICAgICAgY2FzZSBTX1NBTVBMRV9FTkFCTEU6XG4gICAgICAgICAgY2FzZSBTX0RFUFRIX01BU0s6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ2Jvb2xlYW4nLCBwcm9wLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCAndHlwZW9mICcgKyB2YWx1ZSArICc9PT1cImJvb2xlYW5cIicsICdpbnZhbGlkIGZsYWcgJyArIHByb3AsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhc2UgU19ERVBUSF9GVU5DOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcih2YWx1ZSwgY29tcGFyZUZ1bmNzLCAnaW52YWxpZCAnICsgcHJvcCwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gY29tcGFyZUZ1bmNzW3ZhbHVlXTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICB2Y
1XIgQ09NUEFSRV9GVU5DUyA9IGVudi5jb25zdGFudHMuY29tcGFyZUZ1bmNzO1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCB2YWx1ZSArICcgaW4gJyArIENPTVBBUkVfRlVOQ1MsICdpbnZhbGlkICcgKyBwcm9wICsgJywgbXVzdCBiZSBvbmUgb2YgJyArIE9iamVjdC5rZXlzKGNvbXBhcmVGdW5jcykpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihDT01QQVJFX0ZVTkNTLCAnWycsIHZhbHVlLCAnXScpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2FzZSBTX0RFUFRIX1JBTkdFOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAyICYmIHR5cGVvZiB2YWx1ZVswXSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIHZhbHVlWzFdID09PSAnbnVtYmVyJyAmJiB2YWx1ZVswXSA8PSB2YWx1ZVsxXSwgJ2RlcHRoIHJhbmdlIGlzIDJkIGFycmF5JywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgZW52LnNoYXJlZC5pc0FycmF5TGlrZSArICcoJyArIHZhbHVlICsgJykmJicgKyB2YWx1ZSArICcubGVuZ3RoPT09MiYmJyArICd0eXBlb2YgJyArIHZhbHVlICsgJ1swXT09PVwibnVtYmVyXCImJicgKyAndHlwZW9mICcgKyB2YWx1ZSArICdbMV09PT1cIm51bWJlclwiJiYnICsgdmFsdWUgKyAnWzBdPD0nICsgdmFsdWUgKyAnWzFdJywgJ2RlcHRoIHJhbmdlIG11c3QgYmUgYSAyZCBhcnJheScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdmFyIFpfTkVBUiA9IHNjb3BlLmRlZignKycsIHZhbHVlLCAnWzBdJyk7XG4gICAgICAgICAgICAgIHZhciBaX0ZBUiA9IHNjb3BlLmRlZignKycsIHZhbHVlLCAnWzFdJyk7XG4gICAgICAgICAgICAgIHJldHVybiBbWl9ORUFSLCBaX0ZBUl07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfQkxFTkRfRlVOQzpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnb2JqZWN0JywgJ2JsZW5kLmZ1bmMnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBzcmNSR0IgPSAnc3JjUkdCJyBpbiB2YWx1ZSA/IHZhbHVlLnNyY1JHQiA6IHZhbHVlLnNyYztcbiAgICAgICAgICAgICAgdmFyIHNyY0FscGhhID0gJ3NyY0FscGhhJyBpbiB2YWx1ZSA/IHZhbHVlLnNyY0FscGhhIDogdmFsdWUuc3JjO1xuICAgICAgICAgICAgICB2Y
1XIgZHN0UkdCID0gJ2RzdFJHQicgaW4gdmFsdWUgPyB2YWx1ZS5kc3RSR0IgOiB2YWx1ZS5kc3Q7XG4gICAgICAgICAgICAgIHZhciBkc3RBbHBoYSA9ICdkc3RBbHBoYScgaW4gdmFsdWUgPyB2YWx1ZS5kc3RBbHBoYSA6IHZhbHVlLmRzdDtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHNyY1JHQiwgYmxlbmRGdW5jcywgcGFyYW0gKyAnLnNyY1JHQicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHNyY0FscGhhLCBibGVuZEZ1bmNzLCBwYXJhbSArICcuc3JjQWxwaGEnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcihkc3RSR0IsIGJsZW5kRnVuY3MsIHBhcmFtICsgJy5kc3RSR0InLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcihkc3RBbHBoYSwgYmxlbmRGdW5jcywgcGFyYW0gKyAnLmRzdEFscGhhJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaW52YWxpZEJsZW5kQ29tYmluYXRpb25zLmluZGV4T2Yoc3JjUkdCICsgJywgJyArIGRzdFJHQikgPT09IC0xLCAndW5hbGxvd2VkIGJsZW5kaW5nIGNvbWJpbmF0aW9uIChzcmNSR0IsIGRzdFJHQikgPSAoJyArIHNyY1JHQiArICcsICcgKyBkc3RSR0IgKyAnKScsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtibGVuZEZ1bmNzW3NyY1JHQl0sIGJsZW5kRnVuY3NbZHN0UkdCXSwgYmxlbmRGdW5jc1tzcmNBbHBoYV0sIGJsZW5kRnVuY3NbZHN0QWxwaGFdXTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICB2Y
1XIgQkxFTkRfRlVOQ1MgPSBlbnYuY29uc3RhbnRzLmJsZW5kRnVuY3M7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJywgJ2ludmFsaWQgYmxlbmQgZnVuYywgbXVzdCBiZSBhbiBvYmplY3QnKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIGZ1bmN0aW9uIHJlYWQocHJlZml4LCBzdWZmaXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IHNjb3BlLmRlZignXCInLCBwcmVmaXgsIHN1ZmZpeCwgJ1wiIGluICcsIHZhbHVlLCAnPycsIHZhbHVlLCAnLicsIHByZWZpeCwgc3VmZml4LCAnOicsIHZhbHVlLCAnLicsIHByZWZpeCk7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCBmdW5jICsgJyBpbiAnICsgQkxFTkRfRlVOQ1MsICdpbnZhbGlkICcgKyBwcm9wICsgJy4nICsgcHJlZml4ICsgc3VmZml4ICsgJywgbXVzdCBiZSBvbmUgb2YgJyArIE9iamVjdC5rZXlzKGJsZW5kRnVuY3MpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuYztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2YXIgc3JjUkdCID0gcmVhZCgnc3JjJywgJ1JHQicpO1xuICAgICAgICAgICAgICB2YXIgZHN0UkdCID0gcmVhZCgnZHN0JywgJ1JHQicpO1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2Y
1XIgSU5WQUxJRF9CTEVORF9DT01CSU5BVElPTlMgPSBlbnYuY29uc3RhbnRzLmludmFsaWRCbGVuZENvbWJpbmF0aW9ucztcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCBJTlZBTElEX0JMRU5EX0NPTUJJTkFUSU9OUyArICcuaW5kZXhPZignICsgc3JjUkdCICsgJytcIiwgXCIrJyArIGRzdFJHQiArICcpID09PSAtMSAnLCAndW5hbGxvd2VkIGJsZW5kaW5nIGNvbWJpbmF0aW9uIGZvciAoc3JjUkdCLCBkc3RSR0IpJyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB2YXIgU1JDX1JHQiA9IHNjb3BlLmRlZihCTEVORF9GVU5DUywgJ1snLCBzcmNSR0IsICddJyk7XG4gICAgICAgICAgICAgIHZhciBTUkNfQUxQSEEgPSBzY29wZS5kZWYoQkxFTkRfRlVOQ1MsICdbJywgcmVhZCgnc3JjJywgJ0FscGhhJyksICddJyk7XG4gICAgICAgICAgICAgIHZhciBEU1RfUkdCID0gc2NvcGUuZGVmKEJMRU5EX0ZVTkNTLCAnWycsIGRzdFJHQiwgJ10nKTtcbiAgICAgICAgICAgICAgdmFyIERTVF9BTFBIQSA9IHNjb3BlLmRlZihCTEVORF9GVU5DUywgJ1snLCByZWFkKCdkc3QnLCAnQWxwaGEnKSwgJ10nKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtTUkNfUkdCLCBEU1RfUkdCLCBTUkNfQUxQSEEsIERTVF9BTFBIQV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfQkxFTkRfRVFVQVRJT046XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUsIGJsZW5kRXF1YXRpb25zLCAnaW52YWxpZCAnICsgcHJvcCwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbYmxlbmRFcXVhdGlvbnNbdmFsdWVdLCBibGVuZEVxdWF0aW9uc1t2YWx1ZV1dO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUucmdiLCBibGVuZEVxdWF0aW9ucywgcHJvcCArICcucmdiJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcih2YWx1ZS5hbHBoYSwgYmxlbmRFcXVhdGlvbnMsIHByb3AgKyAnLmFscGhhJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbYmxlbmRFcXVhdGlvbnNbdmFsdWUucmdiXSwgYmxlbmRFcXVhdGlvbnNbdmFsdWUuYWxwaGFdXTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRSYWlzZSgnaW52YWxpZCBibGVuZC5lcXVhdGlvbicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIHZhciBCTEVORF9FUVVBVElPTlMgPSBlbnYuY29uc3RhbnRzLmJsZW5kRXF1YXRpb25zO1xuICAgICAgICAgICAgICB2Y
1XIgUkdCID0gc2NvcGUuZGVmKCk7XG4gICAgICAgICAgICAgIHZhciBBTFBIQSA9IHNjb3BlLmRlZigpO1xuICAgICAgICAgICAgICB2YXIgaWZ0ZSA9IGVudi5jb25kKCd0eXBlb2YgJywgdmFsdWUsICc9PT1cInN0cmluZ1wiJyk7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNoZWNrUHJvcChibG9jaywgbmFtZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoYmxvY2ssIHZhbHVlICsgJyBpbiAnICsgQkxFTkRfRVFVQVRJT05TLCAnaW52YWxpZCAnICsgbmFtZSArICcsIG11c3QgYmUgb25lIG9mICcgKyBPYmplY3Qua2V5cyhibGVuZEVxdWF0aW9ucykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjaGVja1Byb3AoaWZ0ZS50aGVuLCBwcm9wLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChpZnRlLmVsc2UsIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJywgJ2ludmFsaWQgJyArIHByb3ApO1xuICAgICAgICAgICAgICAgIGNoZWNrUHJvcChpZnRlLmVsc2UsIHByb3AgKyAnLnJnYicsIHZhbHVlICsgJy5yZ2InKTtcbiAgICAgICAgICAgICAgICBjaGVja1Byb3AoaWZ0ZS5lbHNlLCBwcm9wICsgJy5hbHBoYScsIHZhbHVlICsgJy5hbHBoYScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgaWZ0ZS50aGVuKFJHQiwgJz0nLCBBTFBIQSwgJz0nLCBCTEVORF9FUVVBVElPTlMsICdbJywgdmFsdWUsICddOycpO1xuICAgICAgICAgICAgICBpZnRlLmVsc2UoUkdCLCAnPScsIEJMRU5EX0VRVUFUSU9OUywgJ1snLCB2YWx1ZSwgJy5yZ2JdOycsIEFMUEhBLCAnPScsIEJMRU5EX0VRVUFUSU9OUywgJ1snLCB2YWx1ZSwgJy5hbHBoYV07Jyk7XG4gICAgICAgICAgICAgIHNjb3BlKGlmdGUpO1xuICAgICAgICAgICAgICByZXR1cm4gW1JHQiwgQUxQSEFdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2FzZSBTX0JMRU5EX0NPTE9SOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LCAnYmxlbmQuY29sb3IgbXVzdCBiZSBhIDRkIGFycmF5JywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gbG9vcCg0LCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiArdmFsdWVbaV07XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIGVudi5zaGFyZWQuaXNBcnJheUxpa2UgKyAnKCcgKyB2YWx1ZSArICcpJiYnICsgdmFsdWUgKyAnLmxlbmd0aD09PTQnLCAnYmxlbmQuY29sb3IgbXVzdCBiZSBhIDRkIGFycmF5Jyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gbG9vcCg0LCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoJysnLCB2YWx1ZSwgJ1snLCBpLCAnXScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhc2UgU19TVEVOQ0lMX01BU0s6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ251bWJlcicsIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZSB8IDA7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgJ3R5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJudW1iZXJcIicsICdpbnZhbGlkIHN0ZW5jaWwubWFzaycpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZih2YWx1ZSwgJ3wwJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfU1RFTkNJTF9GVU5DOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdvYmplY3QnLCBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB2Y
1XIgY21wID0gdmFsdWUuY21wIHx8ICdrZWVwJztcbiAgICAgICAgICAgICAgdmFyIHJlZiA9IHZhbHVlLnJlZiB8fCAwO1xuICAgICAgICAgICAgICB2YXIgbWFzayA9ICdtYXNrJyBpbiB2YWx1ZSA/IHZhbHVlLm1hc2sgOiAtMTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKGNtcCwgY29tcGFyZUZ1bmNzLCBwcm9wICsgJy5jbXAnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUocmVmLCAnbnVtYmVyJywgcHJvcCArICcucmVmJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKG1hc2ssICdudW1iZXInLCBwcm9wICsgJy5tYXNrJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gW2NvbXBhcmVGdW5jc1tjbXBdLCByZWYsIG1hc2tdO1xuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIHZhciBDT01QQVJFX0ZVTkNTID0gZW52LmNvbnN0YW50cy5jb21wYXJlRnVuY3M7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGFzc2VydCgpIHtcbiAgICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIEFycmF5LnByb3RvdHlwZS5qb2luLmNhbGwoYXJndW1lbnRzLCAnJyksICdpbnZhbGlkIHN0ZW5jaWwuZnVuYycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhc3NlcnQodmFsdWUgKyAnJiZ0eXBlb2YgJywgdmFsdWUsICc9PT1cIm9iamVjdFwiJyk7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KCchKFwiY21wXCIgaW4gJywgdmFsdWUsICcpfHwoJywgdmFsdWUsICcuY21wIGluICcsIENPTVBBUkVfRlVOQ1MsICcpJyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB2Y
1XIgY21wID0gc2NvcGUuZGVmKCdcImNtcFwiIGluICcsIHZhbHVlLCAnPycsIENPTVBBUkVfRlVOQ1MsICdbJywgdmFsdWUsICcuY21wXScsICc6JywgR0xfS0VFUCk7XG4gICAgICAgICAgICAgIHZhciByZWYgPSBzY29wZS5kZWYodmFsdWUsICcucmVmfDAnKTtcbiAgICAgICAgICAgICAgdmFyIG1hc2sgPSBzY29wZS5kZWYoJ1wibWFza1wiIGluICcsIHZhbHVlLCAnPycsIHZhbHVlLCAnLm1hc2t8MDotMScpO1xuICAgICAgICAgICAgICByZXR1cm4gW2NtcCwgcmVmLCBtYXNrXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhc2UgU19TVEVOQ0lMX09QRlJPTlQ6XG4gICAgICAgICAgY2FzZSBTX1NURU5DSUxfT1BCQUNLOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdvYmplY3QnLCBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB2YXIgZmFpbCA9IHZhbHVlLmZhaWwgfHwgJ2tlZXAnO1xuICAgICAgICAgICAgICB2YXIgemZhaWwgPSB2YWx1ZS56ZmFpbCB8fCAna2VlcCc7XG4gICAgICAgICAgICAgIHZhciB6cGFzcyA9IHZhbHVlLnpwYXNzIHx8ICdrZWVwJztcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKGZhaWwsIHN0ZW5jaWxPcHMsIHByb3AgKyAnLmZhaWwnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcih6ZmFpbCwgc3RlbmNpbE9wcywgcHJvcCArICcuemZhaWwnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcih6cGFzcywgc3RlbmNpbE9wcywgcHJvcCArICcuenBhc3MnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiBbcHJvcCA9PT0gU19TVEVOQ0lMX09QQkFDSyA/IEdMX0JBQ0sgOiBHTF9GUk9OVCwgc3RlbmNpbE9wc1tmYWlsXSwgc3RlbmNpbE9wc1t6ZmFpbF0sIHN0ZW5jaWxPcHNbenBhc3NdXTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICB2Y
1XIgU1RFTkNJTF9PUFMgPSBlbnYuY29uc3RhbnRzLnN0ZW5jaWxPcHM7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJywgJ2ludmFsaWQgJyArIHByb3ApO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgZnVuY3Rpb24gcmVhZChuYW1lKSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCAnIShcIicgKyBuYW1lICsgJ1wiIGluICcgKyB2YWx1ZSArICcpfHwnICsgJygnICsgdmFsdWUgKyAnLicgKyBuYW1lICsgJyBpbiAnICsgU1RFTkNJTF9PUFMgKyAnKScsICdpbnZhbGlkICcgKyBwcm9wICsgJy4nICsgbmFtZSArICcsIG11c3QgYmUgb25lIG9mICcgKyBPYmplY3Qua2V5cyhzdGVuY2lsT3BzKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZignXCInLCBuYW1lLCAnXCIgaW4gJywgdmFsdWUsICc/JywgU1RFTkNJTF9PUFMsICdbJywgdmFsdWUsICcuJywgbmFtZSwgJ106JywgR0xfS0VFUCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIFtwcm9wID09PSBTX1NURU5DSUxfT1BCQUNLID8gR0xfQkFDSyA6IEdMX0ZST05ULCByZWFkKCdmYWlsJyksIHJlYWQoJ3pmYWlsJyksIHJlYWQoJ3pwYXNzJyldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2FzZSBTX1BPTFlHT05fT0ZGU0VUX09GRlNFVDpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnb2JqZWN0JywgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgdmFyIGZhY3RvciA9IHZhbHVlLmZhY3RvciB8IDA7XG4gICAgICAgICAgICAgIHZhciB1bml0cyA9IHZhbHVlLnVuaXRzIHwgMDtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZShmYWN0b3IsICdudW1iZXInLCBwYXJhbSArICcuZmFjdG9yJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHVuaXRzLCAnbnVtYmVyJywgcGFyYW0gKyAnLnVuaXRzJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gW2ZhY3RvciwgdW5pdHNdO1xuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJywgJ2ludmFsaWQgJyArIHByb3ApO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdmFyIEZBQ1RPUiA9IHNjb3BlLmRlZih2YWx1ZSwgJy5mYWN0b3J8MCcpO1xuICAgICAgICAgICAgICB2Y
1XIgVU5JVFMgPSBzY29wZS5kZWYodmFsdWUsICcudW5pdHN8MCcpO1xuICAgICAgICAgICAgICByZXR1cm4gW0ZBQ1RPUiwgVU5JVFNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2FzZSBTX0NVTExfRkFDRTpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICB2YXIgZmFjZSA9IDA7XG4gICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ2Zyb250Jykge1xuICAgICAgICAgICAgICAgIGZhY2UgPSBHTF9GUk9OVDtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2JhY2snKSB7XG4gICAgICAgICAgICAgICAgZmFjZSA9IEdMX0JBQ0s7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKCEhZmFjZSwgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhY2U7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgdmFsdWUgKyAnPT09XCJmcm9udFwifHwnICsgdmFsdWUgKyAnPT09XCJiYWNrXCInLCAnaW52YWxpZCBjdWxsLmZhY2UnKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYodmFsdWUsICc9PT1cImZyb250XCI/JywgR0xfRlJPTlQsICc6JywgR0xfQkFDSyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfTElORV9XSURUSDpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiB2YWx1ZSA+PSBsaW1pdHMubGluZVdpZHRoRGltc1swXSAmJiB2YWx1ZSA8PSBsaW1pdHMubGluZVdpZHRoRGltc1sxXSwgJ2ludmFsaWQgbGluZSB3aWR0aCwgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlciBiZXR3ZWVuICcgKyBsaW1pdHMubGluZVdpZHRoRGltc1swXSArICcgYW5kICcgKyBsaW1pdHMubGluZVdpZHRoRGltc1sxXSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgJ3R5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJudW1iZXJcIiYmJyArIHZhbHVlICsgJz49JyArIGxpbWl0cy5saW5lV2lkdGhEaW1zWzBdICsgJyYmJyArIHZhbHVlICsgJzw9JyArIGxpbWl0cy5saW5lV2lkdGhEaW1zWzFdLCAnaW52YWxpZCBsaW5lIHdpZHRoJyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfRlJPTlRfRkFDRTpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUsIG9yaWVudGF0aW9uVHlwZSwgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIG9yaWVudGF0aW9uVHlwZVt2YWx1ZV07XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgdmFsdWUgKyAnPT09XCJjd1wifHwnICsgdmFsdWUgKyAnPT09XCJjY3dcIicsICdpbnZhbGlkIGZyb250RmFjZSwgbXVzdCBiZSBvbmUgb2YgY3csY2N3Jyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKHZhbHVlICsgJz09PVwiY3dcIj8nICsgR0xfQ1cgKyAnOicgKyBHTF9DQ1cpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2FzZSBTX0NPTE9SX01BU0s6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDQsICdjb2xvci5tYXNrIG11c3QgYmUgbGVuZ3RoIDQgYXJyYXknLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gISF2O1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCBlbnYuc2hhcmVkLmlzQXJyYXlMaWtlICsgJygnICsgdmFsdWUgKyAnKSYmJyArIHZhbHVlICsgJy5sZW5ndGg9PT00JywgJ2ludmFsaWQgY29sb3IubWFzaycpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIGxvb3AoNCwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyEhJyArIHZhbHVlICsgJ1snICsgaSArICddJztcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBjYXNlIFNfU0FNUExFX0NPVkVSQUdFOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlLCBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB2Y
1XIgc2FtcGxlVmFsdWUgPSAndmFsdWUnIGluIHZhbHVlID8gdmFsdWUudmFsdWUgOiAxO1xuICAgICAgICAgICAgICB2YXIgc2FtcGxlSW52ZXJ0ID0gISF2YWx1ZS5pbnZlcnQ7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2Ygc2FtcGxlVmFsdWUgPT09ICdudW1iZXInICYmIHNhbXBsZVZhbHVlID49IDAgJiYgc2FtcGxlVmFsdWUgPD0gMSwgJ3NhbXBsZS5jb3ZlcmFnZS52YWx1ZSBtdXN0IGJlIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMScsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtzYW1wbGVWYWx1ZSwgc2FtcGxlSW52ZXJ0XTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCB2YWx1ZSArICcmJnR5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJvYmplY3RcIicsICdpbnZhbGlkIHNhbXBsZS5jb3ZlcmFnZScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdmFyIFZBTFVFID0gc2NvcGUuZGVmKCdcInZhbHVlXCIgaW4gJywgdmFsdWUsICc/KycsIHZhbHVlLCAnLnZhbHVlOjEnKTtcbiAgICAgICAgICAgICAgdmFyIElOVkVSVCA9IHNjb3BlLmRlZignISEnLCB2YWx1ZSwgJy5pbnZlcnQnKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtWQUxVRSwgSU5WRVJUXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBTVEFURTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VVbmlmb3Jtcyh1bmlmb3JtcywgZW52KSB7XG4gICAgICB2Y
1XIgc3RhdGljVW5pZm9ybXMgPSB1bmlmb3Jtcy5zdGF0aWM7XG4gICAgICB2YXIgZHluYW1pY1VuaWZvcm1zID0gdW5pZm9ybXMuZHluYW1pYztcbiAgICAgIHZhciBVTklGT1JNUyA9IHt9O1xuICAgICAgT2JqZWN0LmtleXMoc3RhdGljVW5pZm9ybXMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gc3RhdGljVW5pZm9ybXNbbmFtZV07XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdmFyIHJlZ2xUeXBlID0gdmFsdWUuX3JlZ2xUeXBlO1xuICAgICAgICAgIGlmIChyZWdsVHlwZSA9PT0gJ3RleHR1cmUyZCcgfHwgcmVnbFR5cGUgPT09ICd0ZXh0dXJlQ3ViZScpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudikge1xuICAgICAgICAgICAgICByZXR1cm4gZW52LmxpbmsodmFsdWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChyZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyJyB8fCByZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyQ3ViZScpIHtcbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh2YWx1ZS5jb2xvci5sZW5ndGggPiAwLCAnbWlzc2luZyBjb2xvciBhdHRhY2htZW50IGZvciBmcmFtZWJ1ZmZlciBzZW50IHRvIHVuaWZvcm0gXCInICsgbmFtZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudikge1xuICAgICAgICAgICAgICByZXR1cm4gZW52LmxpbmsodmFsdWUuY29sb3JbMF0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFJhaXNlKCdpbnZhbGlkIGRhdGEgZm9yIHVuaWZvcm0gXCInICsgbmFtZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheUxpa2UodmFsdWUpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52KSB7XG4gICAgICAgICAgICB2Y
1XIgSVRFTSA9IGVudi5nbG9iYWwuZGVmKCdbJywgbG9vcCh2YWx1ZS5sZW5ndGgsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2YgdmFsdWVbaV0gPT09ICdudW1iZXInIHx8IHR5cGVvZiB2YWx1ZVtpXSA9PT0gJ2Jvb2xlYW4nLCAnaW52YWxpZCB1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZVtpXTtcbiAgICAgICAgICAgIH0pLCAnXScpO1xuICAgICAgICAgICAgcmV0dXJuIElURU07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hlY2skMS5jb21tYW5kUmFpc2UoJ2ludmFsaWQgb3IgbWlzc2luZyBkYXRhIGZvciB1bmlmb3JtIFwiJyArIG5hbWUgKyAnXCInLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0LnZhbHVlID0gdmFsdWU7XG4gICAgICAgIFVOSUZPUk1TW25hbWVdID0gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgICBPYmplY3Qua2V5cyhkeW5hbWljVW5pZm9ybXMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgZHluID0gZHluYW1pY1VuaWZvcm1zW2tleV07XG4gICAgICAgIFVOSUZPUk1TW2tleV0gPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgcmV0dXJuIGVudi5pbnZva2Uoc2NvcGUsIGR5bik7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gVU5JRk9STVM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBhcnNlQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBlbnYpIHtcbiAgICAgIHZhciBzdGF0aWNBdHRyaWJ1dGVzID0gYXR0cmlidXRlcy5zdGF0aWM7XG4gICAgICB2Y
1XIgZHluYW1pY0F0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLmR5bmFtaWM7XG4gICAgICB2YXIgYXR0cmlidXRlRGVmcyA9IHt9O1xuICAgICAgT2JqZWN0LmtleXMoc3RhdGljQXR0cmlidXRlcykuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHN0YXRpY0F0dHJpYnV0ZXNbYXR0cmlidXRlXTtcbiAgICAgICAgdmFyIGlkID0gc3RyaW5nU3RvcmUuaWQoYXR0cmlidXRlKTtcbiAgICAgICAgdmFyIHJlY29yZCA9IG5ldyBBdHRyaWJ1dGVSZWNvcmQoKTtcbiAgICAgICAgaWYgKGlzQnVmZmVyQXJncyh2YWx1ZSkpIHtcbiAgICAgICAgICByZWNvcmQuc3RhdGUgPSBBVFRSSUJfU1RBVEVfUE9JTlRFUjtcbiAgICAgICAgICByZWNvcmQuYnVmZmVyID0gYnVmZmVyU3RhdGUuZ2V0QnVmZmVyKGJ1ZmZlclN0YXRlLmNyZWF0ZSh2YWx1ZSwgR0xfQVJSQVlfQlVGRkVSJDIsIGZhbHNlLCB0cnVlKSk7XG4gICAgICAgICAgcmVjb3JkLnR5cGUgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBidWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIodmFsdWUpO1xuICAgICAgICAgIGlmIChidWZmZXIpIHtcbiAgICAgICAgICAgIHJlY29yZC5zdGF0ZSA9IEFUVFJJQl9TVEFURV9QT0lOVEVSO1xuICAgICAgICAgICAgcmVjb3JkLmJ1ZmZlciA9IGJ1ZmZlcjtcbiAgICAgICAgICAgIHJlY29yZC50eXBlID0gMDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUsICdpbnZhbGlkIGRhdGEgZm9yIGF0dHJpYnV0ZSAnICsgYXR0cmlidXRlLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICBpZiAoJ2NvbnN0YW50JyBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgICB2Y
1XIgY29uc3RhbnQgPSB2YWx1ZS5jb25zdGFudDtcbiAgICAgICAgICAgICAgcmVjb3JkLmJ1ZmZlciA9ICdudWxsJztcbiAgICAgICAgICAgICAgcmVjb3JkLnN0YXRlID0gQVRUUklCX1NUQVRFX0NPTlNUQU5UO1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnN0YW50ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHJlY29yZC54ID0gY29uc3RhbnQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGlzQXJyYXlMaWtlKGNvbnN0YW50KSAmJiBjb25zdGFudC5sZW5ndGggPiAwICYmIGNvbnN0YW50Lmxlbmd0aCA8PSA0LCAnaW52YWxpZCBjb25zdGFudCBmb3IgYXR0cmlidXRlICcgKyBhdHRyaWJ1dGUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBDVVRFX0NPTVBPTkVOVFMuZm9yRWFjaChmdW5jdGlvbiAoYywgaSkge1xuICAgICAgICAgICAgICAgICAgaWYgKGkgPCBjb25zdGFudC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb3JkW2NdID0gY29uc3RhbnRbaV07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChpc0J1ZmZlckFyZ3ModmFsdWUuYnVmZmVyKSkge1xuICAgICAgICAgICAgICAgIGJ1ZmZlciA9IGJ1ZmZlclN0YXRlLmdldEJ1ZmZlcihidWZmZXJTdGF0ZS5jcmVhdGUodmFsdWUuYnVmZmVyLCBHTF9BUlJBWV9CVUZGRVIkMiwgZmFsc2UsIHRydWUpKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBidWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIodmFsdWUuYnVmZmVyKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoISFidWZmZXIsICdtaXNzaW5nIGJ1ZmZlciBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IHZhbHVlLm9mZnNldCB8IDA7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChvZmZzZXQgPj0gMCwgJ2ludmFsaWQgb2Zmc2V0IGZvciBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB2Y
1XIgc3RyaWRlID0gdmFsdWUuc3RyaWRlIHwgMDtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKHN0cmlkZSA+PSAwICYmIHN0cmlkZSA8IDI1NiwgJ2ludmFsaWQgc3RyaWRlIGZvciBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiLCBtdXN0IGJlIGludGVnZXIgYmV0d2VlZW4gWzAsIDI1NV0nLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBzaXplID0gdmFsdWUuc2l6ZSB8IDA7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCghKCdzaXplJyBpbiB2YWx1ZSkgfHwgc2l6ZSA+IDAgJiYgc2l6ZSA8PSA0LCAnaW52YWxpZCBzaXplIGZvciBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiLCBtdXN0IGJlIDEsMiwzLDQnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBub3JtYWxpemVkID0gISF2YWx1ZS5ub3JtYWxpemVkO1xuICAgICAgICAgICAgICB2YXIgdHlwZSA9IDA7XG4gICAgICAgICAgICAgIGlmICgndHlwZScgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUudHlwZSwgZ2xUeXBlcywgJ2ludmFsaWQgdHlwZSBmb3IgYXR0cmlidXRlICcgKyBhdHRyaWJ1dGUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICB0eXBlID0gZ2xUeXBlc1t2YWx1ZS50eXBlXTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2YXIgZGl2aXNvciA9IHZhbHVlLmRpdmlzb3IgfCAwO1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoJ2Rpdmlzb3InIGluIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoZGl2aXNvciA9PT0gMCB8fCBleHRJbnN0YW5jaW5nLCAnY2Fubm90IHNwZWNpZnkgZGl2aXNvciBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIiwgaW5zdGFuY2luZyBub3Qgc3VwcG9ydGVkJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGRpdmlzb3IgPj0gMCwgJ2ludmFsaWQgZGl2aXNvciBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGNvbW1hbmQgPSBlbnYuY29tbWFuZFN0cjtcbiAgICAgICAgICAgICAgICB2Y
1XIgVkFMSURfS0VZUyA9IFsnYnVmZmVyJywgJ29mZnNldCcsICdkaXZpc29yJywgJ25vcm1hbGl6ZWQnLCAndHlwZScsICdzaXplJywgJ3N0cmlkZSddO1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHZhbHVlKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoVkFMSURfS0VZUy5pbmRleE9mKHByb3ApID49IDAsICd1bmtub3duIHBhcmFtZXRlciBcIicgKyBwcm9wICsgJ1wiIGZvciBhdHRyaWJ1dGUgcG9pbnRlciBcIicgKyBhdHRyaWJ1dGUgKyAnXCIgKHZhbGlkIHBhcmFtZXRlcnMgYXJlICcgKyBWQUxJRF9LRVlTICsgJyknLCBjb21tYW5kKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJlY29yZC5idWZmZXIgPSBidWZmZXI7XG4gICAgICAgICAgICAgIHJlY29yZC5zdGF0ZSA9IEFUVFJJQl9TVEFURV9QT0lOVEVSO1xuICAgICAgICAgICAgICByZWNvcmQuc2l6ZSA9IHNpemU7XG4gICAgICAgICAgICAgIHJlY29yZC5ub3JtYWxpemVkID0gbm9ybWFsaXplZDtcbiAgICAgICAgICAgICAgcmVjb3JkLnR5cGUgPSB0eXBlIHx8IGJ1ZmZlci5kdHlwZTtcbiAgICAgICAgICAgICAgcmVjb3JkLm9mZnNldCA9IG9mZnNldDtcbiAgICAgICAgICAgICAgcmVjb3JkLnN0cmlkZSA9IHN0cmlkZTtcbiAgICAgICAgICAgICAgcmVjb3JkLmRpdmlzb3IgPSBkaXZpc29yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhdHRyaWJ1dGVEZWZzW2F0dHJpYnV0ZV0gPSBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgdmFyIGNhY2hlID0gZW52LmF0dHJpYkNhY2hlO1xuICAgICAgICAgIGlmIChpZCBpbiBjYWNoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlW2lkXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgICAgIGlzU3RyZWFtOiBmYWxzZVxuICAgICAgICAgIH07XG4gICAgICAgICAgT2JqZWN0LmtleXMocmVjb3JkKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJlc3VsdFtrZXldID0gcmVjb3JkW2tleV07XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHJlY29yZC5idWZmZXIpIHtcbiAgICAgICAgICAgIHJlc3VsdC5idWZmZXIgPSBlbnYubGluayhyZWNvcmQuYnVmZmVyKTtcbiAgICAgICAgICAgIHJlc3VsdC50eXBlID0gcmVzdWx0LnR5cGUgfHwgcmVzdWx0LmJ1ZmZlciArICcuZHR5cGUnO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjYWNoZVtpZF0gPSByZXN1bHQ7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5rZXlzKGR5bmFtaWNBdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChhdHRyaWJ1dGUpIHtcbiAgICAgICAgdmFyIGR5biA9IGR5bmFtaWNBdHRyaWJ1dGVzW2F0dHJpYnV0ZV07XG4gICAgICAgIGZ1bmN0aW9uIGFwcGVuZEF0dHJpYnV0ZUNvZGUoZW52LCBibG9jaykge1xuICAgICAgICAgIHZhciBWQUxVRSA9IGVudi5pbnZva2UoYmxvY2ssIGR5bik7XG4gICAgICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICAgICAgdmFyIGNvbnN0YW50cyA9IGVudi5jb25zdGFudHM7XG4gICAgICAgICAgdmFyIElTX0JVRkZFUl9BUkdTID0gc2hhcmVkLmlzQnVmZmVyQXJncztcbiAgICAgICAgICB2Y
1XIgQlVGRkVSX1NUQVRFID0gc2hhcmVkLmJ1ZmZlcjtcblxuICAgICAgICAgIC8vIFBlcmZvcm0gdmFsaWRhdGlvbiBvbiBhdHRyaWJ1dGVcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGVudi5hc3NlcnQoYmxvY2ssIFZBTFVFICsgJyYmKHR5cGVvZiAnICsgVkFMVUUgKyAnPT09XCJvYmplY3RcInx8dHlwZW9mICcgKyBWQUxVRSArICc9PT1cImZ1bmN0aW9uXCIpJiYoJyArIElTX0JVRkZFUl9BUkdTICsgJygnICsgVkFMVUUgKyAnKXx8JyArIEJVRkZFUl9TVEFURSArICcuZ2V0QnVmZmVyKCcgKyBWQUxVRSArICcpfHwnICsgQlVGRkVSX1NUQVRFICsgJy5nZXRCdWZmZXIoJyArIFZBTFVFICsgJy5idWZmZXIpfHwnICsgSVNfQlVGRkVSX0FSR1MgKyAnKCcgKyBWQUxVRSArICcuYnVmZmVyKXx8JyArICcoXCJjb25zdGFudFwiIGluICcgKyBWQUxVRSArICcmJih0eXBlb2YgJyArIFZBTFVFICsgJy5jb25zdGFudD09PVwibnVtYmVyXCJ8fCcgKyBzaGFyZWQuaXNBcnJheUxpa2UgKyAnKCcgKyBWQUxVRSArICcuY29uc3RhbnQpKSkpJywgJ2ludmFsaWQgZHluYW1pYyBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiJyk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBhbGxvY2F0ZSBuYW1lcyBmb3IgcmVzdWx0XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgICAgIGlzU3RyZWFtOiBibG9jay5kZWYoZmFsc2UpXG4gICAgICAgICAgfTtcbiAgICAgICAgICB2YXIgZGVmYXVsdFJlY29yZCA9IG5ldyBBdHRyaWJ1dGVSZWNvcmQoKTtcbiAgICAgICAgICBkZWZhdWx0UmVjb3JkLnN0YXRlID0gQVRUUklCX1NUQVRFX1BPSU5URVI7XG4gICAgICAgICAgT2JqZWN0LmtleXMoZGVmYXVsdFJlY29yZCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICByZXN1bHRba2V5XSA9IGJsb2NrLmRlZignJyArIGRlZmF1bHRSZWNvcmRba2V5XSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdmFyIEJVRkZFUiA9IHJlc3VsdC5idWZmZXI7XG4gICAgICAgICAgdmFyIFRZUEUgPSByZXN1bHQudHlwZTtcbiAgICAgICAgICBibG9jaygnaWYoJywgSVNfQlVGRkVSX0FSR1MsICcoJywgVkFMVUUsICcpKXsnLCByZXN1bHQuaXNTdHJlYW0sICc9dHJ1ZTsnLCBCVUZGRVIsICc9JywgQlVGRkVSX1NUQVRFLCAnLmNyZWF0ZVN0cmVhbSgnLCBHTF9BUlJBWV9CVUZGRVIkMiwgJywnLCBWQUxVRSwgJyk7JywgVFlQRSwgJz0nLCBCVUZGRVIsICcuZHR5cGU7JywgJ31lbHNleycsIEJVRkZFUiwgJz0nLCBCVUZGRVJfU1RBVEUsICcuZ2V0QnVmZmVyKCcsIFZBTFVFLCAnKTsnLCAnaWYoJywgQlVGRkVSLCAnKXsnLCBUWVBFLCAnPScsIEJVRkZFUiwgJy5kdHlwZTsnLCAnfWVsc2UgaWYoXCJjb25zdGFudFwiIGluICcsIFZBTFVFLCAnKXsnLCByZXN1bHQuc3RhdGUsICc9JywgQVRUUklCX1NUQVRFX0NPTlNUQU5ULCAnOycsICdpZih0eXBlb2YgJyArIFZBTFVFICsgJy5jb25zdGFudCA9PT0gXCJudW1iZXJcIil7JywgcmVzdWx0W0NVVEVfQ09NUE9ORU5UU1swXV0sICc9JywgVkFMVUUsICcuY29uc3RhbnQ7JywgQ1VURV9DT01QT05FTlRTLnNsaWNlKDEpLm1hcChmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFtuXTtcbiAgICAgICAgICB9KS5qb2luKCc9JyksICc9MDsnLCAnfWVsc2V7JywgQ1VURV9DT01QT05FTlRTLm1hcChmdW5jdGlvbiAobmFtZSwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFtuYW1lXSArICc9JyArIFZBTFVFICsgJy5jb25zdGFudC5sZW5ndGg+JyArIGkgKyAnPycgKyBWQUxVRSArICcuY29uc3RhbnRbJyArIGkgKyAnXTowOyc7XG4gICAgICAgICAgfSkuam9pbignJyksICd9fWVsc2V7JywgJ2lmKCcsIElTX0JVRkZFUl9BUkdTLCAnKCcsIFZBTFVFLCAnLmJ1ZmZlcikpeycsIEJVRkZFUiwgJz0nLCBCVUZGRVJfU1RBVEUsICcuY3JlYXRlU3RyZWFtKCcsIEdMX0FSUkFZX0JVRkZFUiQyLCAnLCcsIFZBTFVFLCAnLmJ1ZmZlcik7JywgJ31lbHNleycsIEJVRkZFUiwgJz0nLCBCVUZGRVJfU1RBVEUsICcuZ2V0QnVmZmVyKCcsIFZBTFVFLCAnLmJ1ZmZlcik7JywgJ30nLCBUWVBFLCAnPVwidHlwZVwiIGluICcsIFZBTFVFLCAnPycsIGNvbnN0YW50cy5nbFR5cGVzLCAnWycsIFZBTFVFLCAnLnR5cGVdOicsIEJVRkZFUiwgJy5kdHlwZTsnLCByZXN1bHQubm9ybWFsaXplZCwgJz0hIScsIFZBTFVFLCAnLm5vcm1hbGl6ZWQ7Jyk7XG4gICAgICAgICAgZnVuY3Rpb24gZW1pdFJlYWRSZWNvcmQobmFtZSkge1xuICAgICAgICAgICAgYmxvY2socmVzdWx0W25hbWVdLCAnPScsIFZBTFVFLCAnLicsIG5hbWUsICd8MDsnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZW1pdFJlYWRSZWNvcmQoJ3NpemUnKTtcbiAgICAgICAgICBlbWl0UmVhZFJlY29yZCgnb2Zmc2V0Jyk7XG4gICAgICAgICAgZW1pdFJlYWRSZWNvcmQoJ3N0cmlkZScpO1xuICAgICAgICAgIGVtaXRSZWFkUmVjb3JkKCdkaXZpc29yJyk7XG4gICAgICAgICAgYmxvY2soJ319Jyk7XG4gICAgICAgICAgYmxvY2suZXhpdCgnaWYoJywgcmVzdWx0LmlzU3RyZWFtLCAnKXsnLCBCVUZGRVJfU1RBVEUsICcuZGVzdHJveVN0cmVhbSgnLCBCVUZGRVIsICcpOycsICd9Jyk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBhdHRyaWJ1dGVEZWZzW2F0dHJpYnV0ZV0gPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGFwcGVuZEF0dHJpYnV0ZUNvZGUpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYXR0cmlidXRlRGVmcztcbiAgICB9XG4gICAgZnVuY3Rpb24gcGFyc2VDb250ZXh0KGNvbnRleHQpIHtcbiAgICAgIHZhciBzdGF0aWNDb250ZXh0ID0gY29udGV4dC5zdGF0aWM7XG4gICAgICB2Y
1XIgZHluYW1pY0NvbnRleHQgPSBjb250ZXh0LmR5bmFtaWM7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBPYmplY3Qua2V5cyhzdGF0aWNDb250ZXh0KS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHN0YXRpY0NvbnRleHRbbmFtZV07XG4gICAgICAgIHJlc3VsdFtuYW1lXSA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuICcnICsgdmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBlbnYubGluayh2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmtleXMoZHluYW1pY0NvbnRleHQpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIGR5biA9IGR5bmFtaWNDb250ZXh0W25hbWVdO1xuICAgICAgICByZXN1bHRbbmFtZV0gPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgcmV0dXJuIGVudi5pbnZva2Uoc2NvcGUsIGR5bik7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJzZUFyZ3VtZW50cyhvcHRpb25zLCBhdHRyaWJ1dGVzLCB1bmlmb3JtcywgY29udGV4dCwgZW52KSB7XG4gICAgICB2Y
1XIgc3RhdGljT3B0aW9ucyA9IG9wdGlvbnMuc3RhdGljO1xuICAgICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBLRVlfTkFNRVMgPSBbU19GUkFNRUJVRkZFUiwgU19WRVJULCBTX0ZSQUcsIFNfRUxFTUVOVFMsIFNfUFJJTUlUSVZFLCBTX09GRlNFVCwgU19DT1VOVCwgU19JTlNUQU5DRVMsIFNfUFJPRklMRSwgU19WQU9dLmNvbmNhdChHTF9TVEFURV9OQU1FUyk7XG4gICAgICAgIGZ1bmN0aW9uIGNoZWNrS2V5cyhkaWN0KSB7XG4gICAgICAgICAgT2JqZWN0LmtleXMoZGljdCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoS0VZX05BTUVTLmluZGV4T2Yoa2V5KSA+PSAwLCAndW5rbm93biBwYXJhbWV0ZXIgXCInICsga2V5ICsgJ1wiJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNoZWNrS2V5cyhzdGF0aWNPcHRpb25zKTtcbiAgICAgICAgY2hlY2tLZXlzKGR5bmFtaWNPcHRpb25zKTtcbiAgICAgIH0pO1xuICAgICAgdmFyIGF0dHJpYkxvY2F0aW9ucyA9IHBhcnNlQXR0cmliTG9jYXRpb25zKG9wdGlvbnMsIGF0dHJpYnV0ZXMpO1xuICAgICAgdmFyIGZyYW1lYnVmZmVyID0gcGFyc2VGcmFtZWJ1ZmZlcihvcHRpb25zLCBlbnYpO1xuICAgICAgdmFyIHZpZXdwb3J0QW5kU2Npc3NvciA9IHBhcnNlVmlld3BvcnRTY2lzc29yKG9wdGlvbnMsIGZyYW1lYnVmZmVyLCBlbnYpO1xuICAgICAgdmFyIGRyYXcgPSBwYXJzZURyYXcob3B0aW9ucywgZW52KTtcbiAgICAgIHZhciBzdGF0ZSA9IHBhcnNlR0xTdGF0ZShvcHRpb25zLCBlbnYpO1xuICAgICAgdmFyIHNoYWRlciA9IHBhcnNlUHJvZ3JhbShvcHRpb25zLCBlbnYsIGF0dHJpYkxvY2F0aW9ucyk7XG4gICAgICBmdW5jdGlvbiBjb3B5Qm94KG5hbWUpIHtcbiAgICAgICAgdmFyIGRlZm4gPSB2aWV3cG9ydEFuZFNjaXNzb3JbbmFtZV07XG4gICAgICAgIGlmIChkZWZuKSB7XG4gICAgICAgICAgc3RhdGVbbmFtZV0gPSBkZWZuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb3B5Qm94KFNfVklFV1BPUlQpO1xuICAgICAgY29weUJveChwcm9wTmFtZShTX1NDSVNTT1JfQk9YKSk7XG4gICAgICB2Y
1XIgZGlydHkgPSBPYmplY3Qua2V5cyhzdGF0ZSkubGVuZ3RoID4gMDtcbiAgICAgIHZhciByZXN1bHQgPSB7XG4gICAgICAgIGZyYW1lYnVmZmVyOiBmcmFtZWJ1ZmZlcixcbiAgICAgICAgZHJhdzogZHJhdyxcbiAgICAgICAgc2hhZGVyOiBzaGFkZXIsXG4gICAgICAgIHN0YXRlOiBzdGF0ZSxcbiAgICAgICAgZGlydHk6IGRpcnR5LFxuICAgICAgICBzY29wZVZBTzogbnVsbCxcbiAgICAgICAgZHJhd1ZBTzogbnVsbCxcbiAgICAgICAgdXNlVkFPOiBmYWxzZSxcbiAgICAgICAgYXR0cmlidXRlczoge31cbiAgICAgIH07XG4gICAgICByZXN1bHQucHJvZmlsZSA9IHBhcnNlUHJvZmlsZShvcHRpb25zLCBlbnYpO1xuICAgICAgcmVzdWx0LnVuaWZvcm1zID0gcGFyc2VVbmlmb3Jtcyh1bmlmb3JtcywgZW52KTtcbiAgICAgIHJlc3VsdC5kcmF3VkFPID0gcmVzdWx0LnNjb3BlVkFPID0gZHJhdy52YW87XG4gICAgICAvLyBzcGVjaWFsIGNhc2U6IGNoZWNrIGlmIHdlIGNhbiBzdGF0aWNhbGx5IGFsbG9jYXRlIGEgdmVydGV4IGFycmF5IG9iamVjdCBmb3IgdGhpcyBwcm9ncmFtXG4gICAgICBpZiAoIXJlc3VsdC5kcmF3VkFPICYmIHNoYWRlci5wcm9ncmFtICYmICFhdHRyaWJMb2NhdGlvbnMgJiYgZXh0ZW5zaW9ucy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzICYmIGRyYXcuc3RhdGljLmVsZW1lbnRzKSB7XG4gICAgICAgIHZhciB1c2VWQU8gPSB0cnVlO1xuICAgICAgICB2YXIgc3RhdGljQmluZGluZ3MgPSBzaGFkZXIucHJvZ3JhbS5hdHRyaWJ1dGVzLm1hcChmdW5jdGlvbiAoYXR0cikge1xuICAgICAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlcy5zdGF0aWNbYXR0cl07XG4gICAgICAgICAgdXNlVkFPID0gdXNlVkFPICYmICEhYmluZGluZztcbiAgICAgICAgICByZXR1cm4gYmluZGluZztcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh1c2VWQU8gJiYgc3RhdGljQmluZGluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHZhciB2YW8gPSBhdHRyaWJ1dGVTdGF0ZS5nZXRWQU8oYXR0cmlidXRlU3RhdGUuY3JlYXRlVkFPKHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHN0YXRpY0JpbmRpbmdzLFxuICAgICAgICAgICAgZWxlbWVudHM6IGRyYXcuc3RhdGljLmVsZW1lbnRzXG4gICAgICAgICAgfSkpO1xuICAgICAgICAgIHJlc3VsdC5kcmF3VkFPID0gbmV3IERlY2xhcmF0aW9uKG51bGwsIG51bGwsIG51bGwsIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICByZXR1cm4gZW52LmxpbmsodmFvKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXN1bHQudXNlVkFPID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGF0dHJpYkxvY2F0aW9ucykge1xuICAgICAgICByZXN1bHQudXNlVkFPID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdC5hdHRyaWJ1dGVzID0gcGFyc2VBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGVudik7XG4gICAgICB9XG4gICAgICByZXN1bHQuY29udGV4dCA9IHBhcnNlQ29udGV4dChjb250ZXh0LCBlbnYpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBDT01NT04gVVBEQVRFIEZVTkNUSU9OU1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIGZ1bmN0aW9uIGVtaXRDb250ZXh0KGVudiwgc2NvcGUsIGNvbnRleHQpIHtcbiAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgdmFyIENPTlRFWFQgPSBzaGFyZWQuY29udGV4dDtcbiAgICAgIHZhciBjb250ZXh0RW50ZXIgPSBlbnYuc2NvcGUoKTtcbiAgICAgIE9iamVjdC5rZXlzKGNvbnRleHQpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgc2NvcGUuc2F2ZShDT05URVhULCAnLicgKyBuYW1lKTtcbiAgICAgICAgdmFyIGRlZm4gPSBjb250ZXh0W25hbWVdO1xuICAgICAgICB2Y
1XIgdmFsdWUgPSBkZWZuLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgY29udGV4dEVudGVyKENPTlRFWFQsICcuJywgbmFtZSwgJz1bJywgdmFsdWUuam9pbigpLCAnXTsnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250ZXh0RW50ZXIoQ09OVEVYVCwgJy4nLCBuYW1lLCAnPScsIHZhbHVlLCAnOycpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNjb3BlKGNvbnRleHRFbnRlcik7XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ09NTU9OIERSQVdJTkcgRlVOQ1RJT05TXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgZnVuY3Rpb24gZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIHNjb3BlLCBmcmFtZWJ1ZmZlciwgc2tpcENoZWNrKSB7XG4gICAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICAgIHZhciBGUkFNRUJVRkZFUl9TVEFURSA9IHNoYXJlZC5mcmFtZWJ1ZmZlcjtcbiAgICAgIHZhciBFWFRfRFJBV19CVUZGRVJTO1xuICAgICAgaWYgKGV4dERyYXdCdWZmZXJzKSB7XG4gICAgICAgIEVYVF9EUkFXX0JVRkZFUlMgPSBzY29wZS5kZWYoc2hhcmVkLmV4dGVuc2lvbnMsICcud2ViZ2xfZHJhd19idWZmZXJzJyk7XG4gICAgICB9XG4gICAgICB2Y
1XIgY29uc3RhbnRzID0gZW52LmNvbnN0YW50cztcbiAgICAgIHZhciBEUkFXX0JVRkZFUlMgPSBjb25zdGFudHMuZHJhd0J1ZmZlcjtcbiAgICAgIHZhciBCQUNLX0JVRkZFUiA9IGNvbnN0YW50cy5iYWNrQnVmZmVyO1xuICAgICAgdmFyIE5FWFQ7XG4gICAgICBpZiAoZnJhbWVidWZmZXIpIHtcbiAgICAgICAgTkVYVCA9IGZyYW1lYnVmZmVyLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE5FWFQgPSBzY29wZS5kZWYoRlJBTUVCVUZGRVJfU1RBVEUsICcubmV4dCcpO1xuICAgICAgfVxuICAgICAgaWYgKCFza2lwQ2hlY2spIHtcbiAgICAgICAgc2NvcGUoJ2lmKCcsIE5FWFQsICchPT0nLCBGUkFNRUJVRkZFUl9TVEFURSwgJy5jdXIpeycpO1xuICAgICAgfVxuICAgICAgc2NvcGUoJ2lmKCcsIE5FWFQsICcpeycsIEdMLCAnLmJpbmRGcmFtZWJ1ZmZlcignLCBHTF9GUkFNRUJVRkZFUiQyLCAnLCcsIE5FWFQsICcuZnJhbWVidWZmZXIpOycpO1xuICAgICAgaWYgKGV4dERyYXdCdWZmZXJzKSB7XG4gICAgICAgIHNjb3BlKEVYVF9EUkFXX0JVRkZFUlMsICcuZHJhd0J1ZmZlcnNXRUJHTCgnLCBEUkFXX0JVRkZFUlMsICdbJywgTkVYVCwgJy5jb2xvckF0dGFjaG1lbnRzLmxlbmd0aF0pOycpO1xuICAgICAgfVxuICAgICAgc2NvcGUoJ31lbHNleycsIEdMLCAnLmJpbmRGcmFtZWJ1ZmZlcignLCBHTF9GUkFNRUJVRkZFUiQyLCAnLG51bGwpOycpO1xuICAgICAgaWYgKGV4dERyYXdCdWZmZXJzKSB7XG4gICAgICAgIHNjb3BlKEVYVF9EUkFXX0JVRkZFUlMsICcuZHJhd0J1ZmZlcnNXRUJHTCgnLCBCQUNLX0JVRkZFUiwgJyk7Jyk7XG4gICAgICB9XG4gICAgICBzY29wZSgnfScsIEZSQU1FQlVGRkVSX1NUQVRFLCAnLmN1cj0nLCBORVhULCAnOycpO1xuICAgICAgaWYgKCFza2lwQ2hlY2spIHtcbiAgICAgICAgc2NvcGUoJ30nKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gZW1pdFBvbGxTdGF0ZShlbnYsIHNjb3BlLCBhcmdzKSB7XG4gICAgICB2Y
1XIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICAgIHZhciBDVVJSRU5UX1ZBUlMgPSBlbnYuY3VycmVudDtcbiAgICAgIHZhciBORVhUX1ZBUlMgPSBlbnYubmV4dDtcbiAgICAgIHZhciBDVVJSRU5UX1NUQVRFID0gc2hhcmVkLmN1cnJlbnQ7XG4gICAgICB2YXIgTkVYVF9TVEFURSA9IHNoYXJlZC5uZXh0O1xuICAgICAgdmFyIGJsb2NrID0gZW52LmNvbmQoQ1VSUkVOVF9TVEFURSwgJy5kaXJ0eScpO1xuICAgICAgR0xfU1RBVEVfTkFNRVMuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgICB2YXIgcGFyYW0gPSBwcm9wTmFtZShwcm9wKTtcbiAgICAgICAgaWYgKHBhcmFtIGluIGFyZ3Muc3RhdGUpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIE5FWFQsIENVUlJFTlQ7XG4gICAgICAgIGlmIChwYXJhbSBpbiBORVhUX1ZBUlMpIHtcbiAgICAgICAgICBORVhUID0gTkVYVF9WQVJTW3BhcmFtXTtcbiAgICAgICAgICBDVVJSRU5UID0gQ1VSUkVOVF9WQVJTW3BhcmFtXTtcbiAgICAgICAgICB2YXIgcGFydHMgPSBsb29wKGN1cnJlbnRTdGF0ZVtwYXJhbV0ubGVuZ3RoLCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgcmV0dXJuIGJsb2NrLmRlZihORVhULCAnWycsIGksICddJyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYmxvY2soZW52LmNvbmQocGFydHMubWFwKGZ1bmN0aW9uIChwLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gcCArICchPT0nICsgQ1VSUkVOVCArICdbJyArIGkgKyAnXSc7XG4gICAgICAgICAgfSkuam9pbignfHwnKSkudGhlbihHTCwgJy4nLCBHTF9WQVJJQUJMRVNbcGFyYW1dLCAnKCcsIHBhcnRzLCAnKTsnLCBwYXJ0cy5tYXAoZnVuY3Rpb24gKHAsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiBDVVJSRU5UICsgJ1snICsgaSArICddPScgKyBwO1xuICAgICAgICAgIH0pLmpvaW4oJzsnKSwgJzsnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgTkVYVCA9IGJsb2NrLmRlZihORVhUX1NUQVRFLCAnLicsIHBhcmFtKTtcbiAgICAgICAgICB2Y
1XIgaWZ0ZSA9IGVudi5jb25kKE5FWFQsICchPT0nLCBDVVJSRU5UX1NUQVRFLCAnLicsIHBhcmFtKTtcbiAgICAgICAgICBibG9jayhpZnRlKTtcbiAgICAgICAgICBpZiAocGFyYW0gaW4gR0xfRkxBR1MpIHtcbiAgICAgICAgICAgIGlmdGUoZW52LmNvbmQoTkVYVCkudGhlbihHTCwgJy5lbmFibGUoJywgR0xfRkxBR1NbcGFyYW1dLCAnKTsnKS5lbHNlKEdMLCAnLmRpc2FibGUoJywgR0xfRkxBR1NbcGFyYW1dLCAnKTsnKSwgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCBORVhULCAnOycpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZnRlKEdMLCAnLicsIEdMX1ZBUklBQkxFU1twYXJhbV0sICcoJywgTkVYVCwgJyk7JywgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCBORVhULCAnOycpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoT2JqZWN0LmtleXMoYXJncy5zdGF0ZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGJsb2NrKENVUlJFTlRfU1RBVEUsICcuZGlydHk9ZmFsc2U7Jyk7XG4gICAgICB9XG4gICAgICBzY29wZShibG9jayk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVtaXRTZXRPcHRpb25zKGVudiwgc2NvcGUsIG9wdGlvbnMsIGZpbHRlcikge1xuICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICB2YXIgQ1VSUkVOVF9WQVJTID0gZW52LmN1cnJlbnQ7XG4gICAgICB2YXIgQ1VSUkVOVF9TVEFURSA9IHNoYXJlZC5jdXJyZW50O1xuICAgICAgdmFyIEdMID0gc2hhcmVkLmdsO1xuICAgICAgc29ydFN0YXRlKE9iamVjdC5rZXlzKG9wdGlvbnMpKS5mb3JFYWNoKGZ1bmN0aW9uIChwYXJhbSkge1xuICAgICAgICB2Y
1XIgZGVmbiA9IG9wdGlvbnNbcGFyYW1dO1xuICAgICAgICBpZiAoZmlsdGVyICYmICFmaWx0ZXIoZGVmbikpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZhcmlhYmxlID0gZGVmbi5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgIGlmIChHTF9GTEFHU1twYXJhbV0pIHtcbiAgICAgICAgICB2YXIgZmxhZyA9IEdMX0ZMQUdTW3BhcmFtXTtcbiAgICAgICAgICBpZiAoaXNTdGF0aWMoZGVmbikpIHtcbiAgICAgICAgICAgIGlmICh2YXJpYWJsZSkge1xuICAgICAgICAgICAgICBzY29wZShHTCwgJy5lbmFibGUoJywgZmxhZywgJyk7Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzY29wZShHTCwgJy5kaXNhYmxlKCcsIGZsYWcsICcpOycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzY29wZShlbnYuY29uZCh2YXJpYWJsZSkudGhlbihHTCwgJy5lbmFibGUoJywgZmxhZywgJyk7JykuZWxzZShHTCwgJy5kaXNhYmxlKCcsIGZsYWcsICcpOycpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2NvcGUoQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCB2YXJpYWJsZSwgJzsnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5TGlrZSh2YXJpYWJsZSkpIHtcbiAgICAgICAgICB2YXIgQ1VSUkVOVCA9IENVUlJFTlRfVkFSU1twYXJhbV07XG4gICAgICAgICAgc2NvcGUoR0wsICcuJywgR0xfVkFSSUFCTEVTW3BhcmFtXSwgJygnLCB2YXJpYWJsZSwgJyk7JywgdmFyaWFibGUubWFwKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gQ1VSUkVOVCArICdbJyArIGkgKyAnXT0nICsgdjtcbiAgICAgICAgICB9KS5qb2luKCc7JyksICc7Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2NvcGUoR0wsICcuJywgR0xfVkFSSUFCTEVTW3BhcmFtXSwgJygnLCB2YXJpYWJsZSwgJyk7JywgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCB2YXJpYWJsZSwgJzsnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGluamVjdEV4dGVuc2lvbnMoZW52LCBzY29wZSkge1xuICAgICAgaWYgKGV4dEluc3RhbmNpbmcpIHtcbiAgICAgICAgZW52Lmluc3RhbmNpbmcgPSBzY29wZS5kZWYoZW52LnNoYXJlZC5leHRlbnNpb25zLCAnLmFuZ2xlX2luc3RhbmNlZF9hcnJheXMnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gZW1pdFByb2ZpbGUoZW52LCBzY29wZSwgYXJncywgdXNlU2NvcGUsIGluY3JlbWVudENvdW50ZXIpIHtcbiAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgdmFyIFNUQVRTID0gZW52LnN0YXRzO1xuICAgICAgdmFyIENVUlJFTlRfU1RBVEUgPSBzaGFyZWQuY3VycmVudDtcbiAgICAgIHZhciBUSU1FUiA9IHNoYXJlZC50aW1lcjtcbiAgICAgIHZhciBwcm9maWxlQXJnID0gYXJncy5wcm9maWxlO1xuICAgICAgZnVuY3Rpb24gcGVyZkNvdW50ZXIoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcGVyZm9ybWFuY2UgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuICdEYXRlLm5vdygpJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gJ3BlcmZvcm1hbmNlLm5vdygpJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIENQVV9TVEFSVCwgUVVFUllfQ09VTlRFUjtcbiAgICAgIGZ1bmN0aW9uIGVtaXRQcm9maWxlU3RhcnQoYmxvY2spIHtcbiAgICAgICAgQ1BVX1NUQVJUID0gc2NvcGUuZGVmKCk7XG4gICAgICAgIGJsb2NrKENQVV9TVEFSVCwgJz0nLCBwZXJmQ291bnRlcigpLCAnOycpO1xuICAgICAgICBpZiAodHlwZW9mIGluY3JlbWVudENvdW50ZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgYmxvY2soU1RBVFMsICcuY291bnQrPScsIGluY3JlbWVudENvdW50ZXIsICc7Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmxvY2soU1RBVFMsICcuY291bnQrKzsnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgICBpZiAodXNlU2NvcGUpIHtcbiAgICAgICAgICAgIFFVRVJZX0NPVU5URVIgPSBzY29wZS5kZWYoKTtcbiAgICAgICAgICAgIGJsb2NrKFFVRVJZX0NPVU5URVIsICc9JywgVElNRVIsICcuZ2V0TnVtUGVuZGluZ1F1ZXJpZXMoKTsnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmxvY2soVElNRVIsICcuYmVnaW5RdWVyeSgnLCBTVEFUUywgJyk7Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBlbWl0UHJvZmlsZUVuZChibG9jaykge1xuICAgICAgICBibG9jayhTVEFUUywgJy5jcHVUaW1lKz0nLCBwZXJmQ291bnRlcigpLCAnLScsIENQVV9T
1VEFSVCwgJzsnKTtcbiAgICAgICAgaWYgKHRpbWVyKSB7XG4gICAgICAgICAgaWYgKHVzZVNjb3BlKSB7XG4gICAgICAgICAgICBibG9jayhUSU1FUiwgJy5wdXNoU2NvcGVTdGF0cygnLCBRVUVSWV9DT1VOVEVSLCAnLCcsIFRJTUVSLCAnLmdldE51bVBlbmRpbmdRdWVyaWVzKCksJywgU1RBVFMsICcpOycpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBibG9jayhUSU1FUiwgJy5lbmRRdWVyeSgpOycpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc2NvcGVQcm9maWxlKHZhbHVlKSB7XG4gICAgICAgIHZhciBwcmV2ID0gc2NvcGUuZGVmKENVUlJFTlRfU1RBVEUsICcucHJvZmlsZScpO1xuICAgICAgICBzY29wZShDVVJSRU5UX1NUQVRFLCAnLnByb2ZpbGU9JywgdmFsdWUsICc7Jyk7XG4gICAgICAgIHNjb3BlLmV4aXQoQ1VSUkVOVF9TVEFURSwgJy5wcm9maWxlPScsIHByZXYsICc7Jyk7XG4gICAgICB9XG4gICAgICB2YXIgVVNFX1BST0ZJTEU7XG4gICAgICBpZiAocHJvZmlsZUFyZykge1xuICAgICAgICBpZiAoaXNTdGF0aWMocHJvZmlsZUFyZykpIHtcbiAgICAgICAgICBpZiAocHJvZmlsZUFyZy5lbmFibGUpIHtcbiAgICAgICAgICAgIGVtaXRQcm9maWxlU3RhcnQoc2NvcGUpO1xuICAgICAgICAgICAgZW1pdFByb2ZpbGVFbmQoc2NvcGUuZXhpdCk7XG4gICAgICAgICAgICBzY29wZVByb2ZpbGUoJ3RydWUnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2NvcGVQcm9maWxlKCdmYWxzZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgVVNFX1BST0ZJTEUgPSBwcm9maWxlQXJnLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgICAgc2NvcGVQcm9maWxlKFVTRV9QUk9GSUxFKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFVTRV9QUk9GSUxFID0gc2NvcGUuZGVmKENVUlJFTlRfU1RBVEUsICcucHJvZmlsZScpO1xuICAgICAgfVxuICAgICAgdmFyIHN0YXJ0ID0gZW52LmJsb2NrKCk7XG4gICAgICBlbWl0UHJvZmlsZVN0YXJ0KHN0YXJ0KTtcbiAgICAgIHNjb3BlKCdpZignLCBVU0VfUFJPRklMRSwgJyl7Jywgc3RhcnQsICd9Jyk7XG4gICAgICB2Y
1XIgZW5kID0gZW52LmJsb2NrKCk7XG4gICAgICBlbWl0UHJvZmlsZUVuZChlbmQpO1xuICAgICAgc2NvcGUuZXhpdCgnaWYoJywgVVNFX1BST0ZJTEUsICcpeycsIGVuZCwgJ30nKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZW1pdEF0dHJpYnV0ZXMoZW52LCBzY29wZSwgYXJncywgYXR0cmlidXRlcywgZmlsdGVyKSB7XG4gICAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgIGZ1bmN0aW9uIHR5cGVMZW5ndGgoeCkge1xuICAgICAgICBzd2l0Y2ggKHgpIHtcbiAgICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzI6XG4gICAgICAgICAgY2FzZSBHTF9JTlRfVkVDMjpcbiAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMjpcbiAgICAgICAgICAgIHJldHVybiAyO1xuICAgICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDMzpcbiAgICAgICAgICBjYXNlIEdMX0lOVF9WRUMzOlxuICAgICAgICAgIGNhc2UgR0xfQk9PTF9WRUMzOlxuICAgICAgICAgICAgcmV0dXJuIDM7XG4gICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUM0OlxuICAgICAgICAgIGNhc2UgR0xfSU5UX1ZFQzQ6XG4gICAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzQ6XG4gICAgICAgICAgICByZXR1cm4gNDtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGVtaXRCaW5kQXR0cmlidXRlKEFUVFJJQlVURSwgc2l6ZSwgcmVjb3JkKSB7XG4gICAgICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICAgICAgdmFyIExPQ0FUSU9OID0gc2NvcGUuZGVmKEFUVFJJQlVURSwgJy5sb2NhdGlvbicpO1xuICAgICAgICB2Y
1XIgQklORElORyA9IHNjb3BlLmRlZihzaGFyZWQuYXR0cmlidXRlcywgJ1snLCBMT0NBVElPTiwgJ10nKTtcbiAgICAgICAgdmFyIFNUQVRFID0gcmVjb3JkLnN0YXRlO1xuICAgICAgICB2YXIgQlVGRkVSID0gcmVjb3JkLmJ1ZmZlcjtcbiAgICAgICAgdmFyIENPTlNUX0NPTVBPTkVOVFMgPSBbcmVjb3JkLngsIHJlY29yZC55LCByZWNvcmQueiwgcmVjb3JkLnddO1xuICAgICAgICB2YXIgQ09NTU9OX0tFWVMgPSBbJ2J1ZmZlcicsICdub3JtYWxpemVkJywgJ29mZnNldCcsICdzdHJpZGUnXTtcbiAgICAgICAgZnVuY3Rpb24gZW1pdEJ1ZmZlcigpIHtcbiAgICAgICAgICBzY29wZSgnaWYoIScsIEJJTkRJTkcsICcuYnVmZmVyKXsnLCBHTCwgJy5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSgnLCBMT0NBVElPTiwgJyk7fScpO1xuICAgICAgICAgIHZhciBUWVBFID0gcmVjb3JkLnR5cGU7XG4gICAgICAgICAgdmFyIFNJWkU7XG4gICAgICAgICAgaWYgKCFyZWNvcmQuc2l6ZSkge1xuICAgICAgICAgICAgU0laRSA9IHNpemU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFNJWkUgPSBzY29wZS5kZWYocmVjb3JkLnNpemUsICd8fCcsIHNpemUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzY29wZSgnaWYoJywgQklORElORywgJy50eXBlIT09JywgVFlQRSwgJ3x8JywgQklORElORywgJy5zaXplIT09JywgU0laRSwgJ3x8JywgQ09NTU9OX0tFWVMubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBCSU5ESU5HICsgJy4nICsga2V5ICsgJyE9PScgKyByZWNvcmRba2V5XTtcbiAgICAgICAgICB9KS5qb2luKCd8fCcpLCAnKXsnLCBHTCwgJy5iaW5kQnVmZmVyKCcsIEdMX0FSUkFZX0JVRkZFUiQyLCAnLCcsIEJVRkZFUiwgJy5idWZmZXIpOycsIEdMLCAnLnZlcnRleEF0dHJpYlBvaW50ZXIoJywgW0xPQ0FUSU9OLCBTSVpFLCBUWVBFLCByZWNvcmQubm9ybWFsaXplZCwgcmVjb3JkLnN0cmlkZSwgcmVjb3JkLm9mZnNldF0sICcpOycsIEJJTkRJTkcsICcudHlwZT0nLCBUWVBFLCAnOycsIEJJTkRJTkcsICcuc2l6ZT0nLCBTSVpFLCAnOycsIENPTU1PTl9LRVlTLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gQklORElORyArICcuJyArIGtleSArICc9JyArIHJlY29yZFtrZXldICsgJzsnO1xuICAgICAgICAgIH0pLmpvaW4oJycpLCAnfScpO1xuICAgICAgICAgIGlmIChleHRJbnN0YW5jaW5nKSB7XG4gICAgICAgICAgICB2Y
1XIgRElWSVNPUiA9IHJlY29yZC5kaXZpc29yO1xuICAgICAgICAgICAgc2NvcGUoJ2lmKCcsIEJJTkRJTkcsICcuZGl2aXNvciE9PScsIERJVklTT1IsICcpeycsIGVudi5pbnN0YW5jaW5nLCAnLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRSgnLCBbTE9DQVRJT04sIERJVklTT1JdLCAnKTsnLCBCSU5ESU5HLCAnLmRpdmlzb3I9JywgRElWSVNPUiwgJzt9Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGVtaXRDb25zdGFudCgpIHtcbiAgICAgICAgICBzY29wZSgnaWYoJywgQklORElORywgJy5idWZmZXIpeycsIEdMLCAnLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheSgnLCBMT0NBVElPTiwgJyk7JywgQklORElORywgJy5idWZmZXI9bnVsbDsnLCAnfWlmKCcsIENVVEVfQ09NUE9ORU5UUy5tYXAoZnVuY3Rpb24gKGMsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiBCSU5ESU5HICsgJy4nICsgYyArICchPT0nICsgQ09OU1RfQ09NUE9ORU5UU1tpXTtcbiAgICAgICAgICB9KS5qb2luKCd8fCcpLCAnKXsnLCBHTCwgJy52ZXJ0ZXhBdHRyaWI0ZignLCBMT0NBVElPTiwgJywnLCBDT05TVF9DT01QT05FTlRTLCAnKTsnLCBDVVRFX0NPTVBPTkVOVFMubWFwKGZ1bmN0aW9uIChjLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gQklORElORyArICcuJyArIGMgKyAnPScgKyBDT05TVF9DT01QT05FTlRTW2ldICsgJzsnO1xuICAgICAgICAgIH0pLmpvaW4oJycpLCAnfScpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChTVEFURSA9PT0gQVRUUklCX1NUQVRFX1BPSU5URVIpIHtcbiAgICAgICAgICBlbWl0QnVmZmVyKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoU1RBVEUgPT09IEFUVFJJQl9TVEFURV9DT05TVEFOVCkge1xuICAgICAgICAgIGVtaXRDb25zdGFudCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNjb3BlKCdpZignLCBTVEFURSwgJz09PScsIEFUVFJJQl9TVEFURV9QT0lOVEVSLCAnKXsnKTtcbiAgICAgICAgICBlbWl0QnVmZmVyKCk7XG4gICAgICAgICAgc2NvcGUoJ31lbHNleycpO1xuICAgICAgICAgIGVtaXRDb25zdGFudCgpO1xuICAgICAgICAgIHNjb3BlKCd9Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGF0dHJpYnV0ZXMuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgIHZhciBuYW1lID0gYXR0cmlidXRlLm5hbWU7XG4gICAgICAgIHZhciBhcmcgPSBhcmdzLmF0dHJpYnV0ZXNbbmFtZV07XG4gICAgICAgIHZhciByZWNvcmQ7XG4gICAgICAgIGlmIChhcmcpIHtcbiAgICAgICAgICBpZiAoIWZpbHRlcihhcmcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlY29yZCA9IGFyZy5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFmaWx0ZXIoU0NPUEVfREVDTCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHNjb3BlQXR0cmliID0gZW52LnNjb3BlQXR0cmliKG5hbWUpO1xuICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgc2NvcGVBdHRyaWIgKyAnLnN0YXRlJywgJ21pc3NpbmcgYXR0cmlidXRlICcgKyBuYW1lKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZWNvcmQgPSB7fTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhuZXcgQXR0cmlidXRlUmVjb3JkKCkpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgcmVjb3JkW2tleV0gPSBzY29wZS5kZWYoc2NvcGVBdHRyaWIsICcuJywga2V5KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbWl0QmluZEF0dHJpYnV0ZShlbnYubGluayhhdHRyaWJ1dGUpLCB0eXBlTGVuZ3RoKGF0dHJpYnV0ZS5pbmZvLnR5cGUpLCByZWNvcmQpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVtaXRVbmlmb3JtcyhlbnYsIHNjb3BlLCBhcmdzLCB1bmlmb3JtcywgZmlsdGVyLCBpc0JhdGNoSW5uZXJMb29wKSB7XG4gICAgICB2Y
1XIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICAgIHZhciBpbmZpeDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW5pZm9ybXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHVuaWZvcm0gPSB1bmlmb3Jtc1tpXTtcbiAgICAgICAgdmFyIG5hbWUgPSB1bmlmb3JtLm5hbWU7XG4gICAgICAgIHZhciB0eXBlID0gdW5pZm9ybS5pbmZvLnR5cGU7XG4gICAgICAgIHZhciBhcmcgPSBhcmdzLnVuaWZvcm1zW25hbWVdO1xuICAgICAgICB2YXIgVU5JRk9STSA9IGVudi5saW5rKHVuaWZvcm0pO1xuICAgICAgICB2YXIgTE9DQVRJT04gPSBVTklGT1JNICsgJy5sb2NhdGlvbic7XG4gICAgICAgIHZhciBWQUxVRTtcbiAgICAgICAgaWYgKGFyZykge1xuICAgICAgICAgIGlmICghZmlsdGVyKGFyZykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaXNTdGF0aWMoYXJnKSkge1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gYXJnLnZhbHVlO1xuICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcsICdtaXNzaW5nIHVuaWZvcm0gXCInICsgbmFtZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgIGlmICh0eXBlID09PSBHTF9TQU1QTEVSXzJEIHx8IHR5cGUgPT09IEdMX1NBTVBMRVJfQ1VCRSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nICYmICh0eXBlID09PSBHTF9TQU1QTEVSXzJEICYmICh2YWx1ZS5fcmVnbFR5cGUgPT09ICd0ZXh0dXJlMmQnIHx8IHZhbHVlLl9yZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyJykgfHwgdHlwZSA9PT0gR0xfU0FNUExFUl9DVUJFICYmICh2YWx1ZS5fcmVnbFR5cGUgPT09ICd0ZXh0dXJlQ3ViZScgfHwgdmFsdWUuX3JlZ2xUeXBlID09PSAnZnJhbWVidWZmZXJDdWJlJykpLCAnaW52YWxpZCB0ZXh0dXJlIGZvciB1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBURVhfVkFMVUUgPSBlbnYubGluayh2YWx1ZS5fdGV4dHVyZSB8fCB2YWx1ZS5jb2xvclswXS5fdGV4dHVyZSk7XG4gICAgICAgICAgICAgIHNjb3BlKEdMLCAnLnVuaWZvcm0xaSgnLCBMT0NBVElPTiwgJywnLCBURVhfVkFMVUUgKyAnLmJpbmQoKSk7Jyk7XG4gICAgICAgICAgICAgIHNjb3BlLmV4aXQoVEVYX1ZBTFVFLCAnLnVuYmluZCgpOycpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9GTE9BVF9NQVQyIHx8IHR5cGUgPT09IEdMX0ZMT0FUX01BVDMgfHwgdHlwZSA9PT0gR0xfRkxPQVRfTUFUNCkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaXNBcnJheUxpa2UodmFsdWUpLCAnaW52YWxpZCBtYXRyaXggZm9yIHVuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQodHlwZSA9PT0gR0xfRkxPQVRfTUFUMiAmJiB2YWx1ZS5sZW5ndGggPT09IDQgfHwgdHlwZSA9PT0gR0xfRkxPQVRfTUFUMyAmJiB2YWx1ZS5sZW5ndGggPT09IDkgfHwgdHlwZSA9PT0gR0xfRkxPQVRfTUFUNCAmJiB2YWx1ZS5sZW5ndGggPT09IDE2LCAnaW52YWxpZCBsZW5ndGggZm9yIG1hdHJpeCB1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB2Y
1XIgTUFUX1ZBTFVFID0gZW52Lmdsb2JhbC5kZWYoJ25ldyBGbG9hdDMyQXJyYXkoWycgKyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh2YWx1ZSkgKyAnXSknKTtcbiAgICAgICAgICAgICAgdmFyIGRpbSA9IDI7XG4gICAgICAgICAgICAgIGlmICh0eXBlID09PSBHTF9GTE9BVF9NQVQzKSB7XG4gICAgICAgICAgICAgICAgZGltID0gMztcbiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9GTE9BVF9NQVQ0KSB7XG4gICAgICAgICAgICAgICAgZGltID0gNDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBzY29wZShHTCwgJy51bmlmb3JtTWF0cml4JywgZGltLCAnZnYoJywgTE9DQVRJT04sICcsZmFsc2UsJywgTUFUX1ZBTFVFLCAnKTsnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgR0xfRkxPQVQkODpcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdudW1iZXInLCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnMWYnO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDIsICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgICBpbmZpeCA9ICcyZic7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzM6XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMywgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICAgIGluZml4ID0gJzNmJztcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDNDpcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnNGYnO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBHTF9CT09MOlxuICAgICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ2Jvb2xlYW4nLCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnMWknO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBHTF9JTlQkMzpcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdudW1iZXInLCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnMWknO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzI6XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMiwgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICAgIGluZml4ID0gJzJpJztcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgR0xfSU5UX1ZFQzI6XG4gICAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMiwgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICAgIGluZml4ID0gJzJpJztcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgR0xfQk9PTF9WRUMzOlxuICAgICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDMsICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgICBpbmZpeCA9ICczaSc7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEdMX0lOVF9WRUMzOlxuICAgICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDMsICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgICBpbmZpeCA9ICczaSc7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDNDpcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnNGknO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBHTF9JTlRfVkVDNDpcbiAgICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LCAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgICAgaW5maXggPSAnNGknO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc2NvcGUoR0wsICcudW5pZm9ybScsIGluZml4LCAnKCcsIExPQ0FUSU9OLCAnLCcsIGlzQXJyYXlMaWtlKHZhbHVlKSA/IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHZhbHVlKSA6IHZhbHVlLCAnKTsnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBWQUxVRSA9IGFyZy5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghZmlsdGVyKFNDT1BFX0RFQ0wpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgVkFMVUUgPSBzY29wZS5kZWYoc2hhcmVkLnVuaWZvcm1zLCAnWycsIHN0cmluZ1N0b3JlLmlkKG5hbWUpLCAnXScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSBHTF9TQU1QTEVSXzJEKSB7XG4gICAgICAgICAgY2hlY2skMSghQXJyYXkuaXNBcnJheShWQUxVRSksICdtdXN0IHNwZWNpZnkgYSBzY2FsYXIgcHJvcCBmb3IgdGV4dHVyZXMnKTtcbiAgICAgICAgICBzY29wZSgnaWYoJywgVkFMVUUsICcmJicsIFZBTFVFLCAnLl9yZWdsVHlwZT09PVwiZnJhbWVidWZmZXJcIil7JywgVkFMVUUsICc9JywgVkFMVUUsICcuY29sb3JbMF07JywgJ30nKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9TQU1QTEVSX0NVQkUpIHtcbiAgICAgICAgICBjaGVjayQxKCFBcnJheS5pc0FycmF
15KFZBTFVFKSwgJ211c3Qgc3BlY2lmeSBhIHNjYWxhciBwcm9wIGZvciBjdWJlIG1hcHMnKTtcbiAgICAgICAgICBzY29wZSgnaWYoJywgVkFMVUUsICcmJicsIFZBTFVFLCAnLl9yZWdsVHlwZT09PVwiZnJhbWVidWZmZXJDdWJlXCIpeycsIFZBTFVFLCAnPScsIFZBTFVFLCAnLmNvbG9yWzBdOycsICd9Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwZXJmb3JtIHR5cGUgdmFsaWRhdGlvblxuICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBmdW5jdGlvbiBlbWl0Q2hlY2socHJlZCwgbWVzc2FnZSkge1xuICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgcHJlZCwgJ2JhZCBkYXRhIG9yIG1pc3NpbmcgZm9yIHVuaWZvcm0gXCInICsgbmFtZSArICdcIi4gICcgKyBtZXNzYWdlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZnVuY3Rpb24gY2hlY2tUeXBlKHR5cGUpIHtcbiAgICAgICAgICAgIGNoZWNrJDEoIUFycmF5LmlzQXJyYXkoVkFMVUUpLCAnbXVzdCBub3Qgc3BlY2lmeSBhbiBhcnJheSB0eXBlIGZvciB1bmlmb3JtJyk7XG4gICAgICAgICAgICBlbWl0Q2hlY2soJ3R5cGVvZiAnICsgVkFMVUUgKyAnPT09XCInICsgdHlwZSArICdcIicsICdpbnZhbGlkIHR5cGUsIGV4cGVjdGVkICcgKyB0eXBlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZnVuY3Rpb24gY2hlY2tWZWN0b3IobiwgdHlwZSkge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoVkFMVUUpKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEoVkFMVUUubGVuZ3RoID09PSBuLCAnbXVzdCBoYXZlIGxlbmd0aCAnICsgbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlbWl0Q2hlY2soc2hhcmVkLmlzQXJyYXlMaWtlICsgJygnICsgVkFMVUUgKyAnKSYmJyArIFZBTFVFICsgJy5sZW5ndGg9PT0nICsgbiwgJ2ludmFsaWQgdmVjdG9yLCBzaG91bGQgaGF2ZSBsZW5ndGggJyArIG4sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgZnVuY3Rpb24gY2hlY2tUZXh0dXJlKHRhcmdldCkge1xuICAgICAgICAgICAgY2hlY2skMSghQXJyYXkuaXNBcnJheShWQUxVRSksICdtdXN0IG5vdCBzcGVjaWZ5IGEgdmFsdWUgdHlwZScpO1xuICAgICAgICAgICAgZW1pdENoZWNrKCd0eXBlb2YgJyArIFZBTFVFICsgJz09PVwiZnVuY3Rpb25cIiYmJyArIFZBTFVFICsgJy5fcmVnbFR5cGU9PT1cInRleHR1cmUnICsgKHRhcmdldCA9PT0gR0xfVEVYVFVSRV8yRCQzID8gJzJkJyA6ICdDdWJlJykgKyAnXCInLCAnaW52YWxpZCB0ZXh0dXJlIHR5cGUnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSBHTF9JTlQkMzpcbiAgICAgICAgICAgICAgY2hlY2tUeXBlKCdudW1iZXInKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0lOVF9WRUMyOlxuICAgICAgICAgICAgICBjaGVja1ZlY3RvcigyLCAnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9JTlRfVkVDMzpcbiAgICAgICAgICAgICAgY2hlY2tWZWN0b3IoMywgJ251bWJlcicpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgR0xfSU5UX1ZFQzQ6XG4gICAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdudW1iZXInKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0ZMT0FUJDg6XG4gICAgICAgICAgICAgIGNoZWNrVHlwZSgnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICAgICAgICBjaGVja1ZlY3RvcigyLCAnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMzOlxuICAgICAgICAgICAgICBjaGVja1ZlY3RvcigzLCAnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUM0OlxuICAgICAgICAgICAgICBjaGVja1ZlY3Rvcig0LCAnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9CT09MOlxuICAgICAgICAgICAgICBjaGVja1R5cGUoJ2Jvb2xlYW4nKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMjpcbiAgICAgICAgICAgICAgY2hlY2tWZWN0b3IoMiwgJ2Jvb2xlYW4nKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMzpcbiAgICAgICAgICAgICAgY2hlY2tWZWN0b3IoMywgJ2Jvb2xlYW4nKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDNDpcbiAgICAgICAgICAgICAgY2hlY2tWZWN0b3IoNCwgJ2Jvb2xlYW4nKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDI6XG4gICAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdudW1iZXInKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDM6XG4gICAgICAgICAgICAgIGNoZWNrVmVjdG9yKDksICdudW1iZXInKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDQ6XG4gICAgICAgICAgICAgIGNoZWNrVmVjdG9yKDE2LCAnbnVtYmVyJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBHTF9TQU1QTEVSXzJEOlxuICAgICAgICAgICAgICBjaGVja1RleHR1cmUoR0xfVEVYVFVSRV8yRCQzKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEdMX1NBTVBMRVJfQ1VCRTpcbiAgICAgICAgICAgICAgY2hlY2tUZXh0dXJlKEdMX1RFWFRVUkVfQ1VCRV9NQVAkMik7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciB1bnJvbGwgPSAxO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICBjYXNlIEdMX1NBTVBMRVJfMkQ6XG4gICAgICAgICAgY2FzZSBHTF9TQU1QTEVSX0NVQkU6XG4gICAgICAgICAgICB2Y
1XIgVEVYID0gc2NvcGUuZGVmKFZBTFVFLCAnLl90ZXh0dXJlJyk7XG4gICAgICAgICAgICBzY29wZShHTCwgJy51bmlmb3JtMWkoJywgTE9DQVRJT04sICcsJywgVEVYLCAnLmJpbmQoKSk7Jyk7XG4gICAgICAgICAgICBzY29wZS5leGl0KFRFWCwgJy51bmJpbmQoKTsnKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIGNhc2UgR0xfSU5UJDM6XG4gICAgICAgICAgY2FzZSBHTF9CT09MOlxuICAgICAgICAgICAgaW5maXggPSAnMWknO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBHTF9JTlRfVkVDMjpcbiAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMjpcbiAgICAgICAgICAgIGluZml4ID0gJzJpJztcbiAgICAgICAgICAgIHVucm9sbCA9IDI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIEdMX0lOVF9WRUMzOlxuICAgICAgICAgIGNhc2UgR0xfQk9PTF9WRUMzOlxuICAgICAgICAgICAgaW5maXggPSAnM2knO1xuICAgICAgICAgICAgdW5yb2xsID0gMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgR0xfSU5UX1ZFQzQ6XG4gICAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzQ6XG4gICAgICAgICAgICBpbmZpeCA9ICc0aSc7XG4gICAgICAgICAgICB1bnJvbGwgPSA0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBHTF9GTE9BVCQ4OlxuICAgICAgICAgICAgaW5maXggPSAnMWYnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICAgICAgaW5maXggPSAnMmYnO1xuICAgICAgICAgICAgdW5yb2xsID0gMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDMzpcbiAgICAgICAgICAgIGluZml4ID0gJzNmJztcbiAgICAgICAgICAgIHVucm9sbCA9IDM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzQ6XG4gICAgICAgICAgICBpbmZpeCA9ICc0Zic7XG4gICAgICAgICAgICB1bnJvbGwgPSA0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBHTF9GTE9BVF9NQVQyOlxuICAgICAgICAgICAgaW5maXggPSAnTWF0cml4MmZ2JztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgR0xfRkxPQVRfTUFUMzpcbiAgICAgICAgICAgIGluZml4ID0gJ01hdHJpeDNmdic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDQ6XG4gICAgICAgICAgICBpbmZpeCA9ICdNYXRyaXg0ZnYnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluZml4LmNoYXJBdCgwKSA9PT0gJ00nKSB7XG4gICAgICAgICAgc2NvcGUoR0wsICcudW5pZm9ybScsIGluZml4LCAnKCcsIExPQ0FUSU9OLCAnLCcpO1xuICAgICAgICAgIHZhciBtYXRTaXplID0gTWF0aC5wb3codHlwZSAtIEdMX0ZMT0FUX01BVDIgKyAyLCAyKTtcbiAgICAgICAgICB2Y
1XIgU1RPUkFHRSA9IGVudi5nbG9iYWwuZGVmKCduZXcgRmxvYXQzMkFycmF5KCcsIG1hdFNpemUsICcpJyk7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoVkFMVUUpKSB7XG4gICAgICAgICAgICBzY29wZSgnZmFsc2UsKCcsIGxvb3AobWF0U2l6ZSwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFNUT1JBR0UgKyAnWycgKyBpICsgJ109JyArIFZBTFVFW2ldO1xuICAgICAgICAgICAgfSksICcsJywgU1RPUkFHRSwgJyknKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2NvcGUoJ2ZhbHNlLChBcnJheS5pc0FycmF5KCcsIFZBTFVFLCAnKXx8JywgVkFMVUUsICcgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpPycsIFZBTFVFLCAnOignLCBsb29wKG1hdFNpemUsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBTVE9SQUdFICsgJ1snICsgaSArICddPScgKyBWQUxVRSArICdbJyArIGkgKyAnXSc7XG4gICAgICAgICAgICB9KSwgJywnLCBTVE9SQUdFLCAnKScpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzY29wZSgnKTsnKTtcbiAgICAgICAgfSBlbHNlIGlmICh1bnJvbGwgPiAxKSB7XG4gICAgICAgICAgdmFyIHByZXYgPSBbXTtcbiAgICAgICAgICB2YXIgY3VyID0gW107XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCB1bnJvbGw7ICsraikge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoVkFMVUUpKSB7XG4gICAgICAgICAgICAgIGN1ci5wdXNoKFZBTFVFW2pdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGN1ci5wdXNoKHNjb3BlLmRlZihWQUxVRSArICdbJyArIGogKyAnXScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0JhdGNoSW5uZXJMb29wKSB7XG4gICAgICAgICAgICAgIHByZXYucHVzaChzY29wZS5kZWYoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpc0JhdGNoSW5uZXJMb29wKSB7XG4gICAgICAgICAgICBzY29wZSgnaWYoIScsIGVudi5iYXRjaElkLCAnfHwnLCBwcmV2Lm1hcChmdW5jdGlvbiAocCwgaSkge1xuICAgICAgICAgICAgICByZXR1cm4gcCArICchPT0nICsgY3VyW2ldO1xuICAgICAgICAgICAgfSkuam9pbignfHwnKSwgJyl7JywgcHJldi5tYXAoZnVuY3Rpb24gKHAsIGkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHAgKyAnPScgKyBjdXJbaV0gKyAnOyc7XG4gICAgICAgICAgICB9KS5qb2luKCcnKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNjb3BlKEdMLCAnLnVuaWZvcm0nLCBpbmZpeCwgJygnLCBMT0NBVElPTiwgJywnLCBjdXIuam9pbignLCcpLCAnKTsnKTtcbiAgICAgICAgICBpZiAoaXNCYXRjaElubmVyTG9vcCkge1xuICAgICAgICAgICAgc2NvcGUoJ30nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hlY2skMSghQXJyYXkuaXNBcnJheShWQUxVRSksICd1bmlmb3JtIHZhbHVlIG11c3Qgbm90IGJlIGFuIGFycmF5Jyk7XG4gICAgICAgICAgaWYgKGlzQmF0Y2hJbm5lckxvb3ApIHtcbiAgICAgICAgICAgIHZhciBwcmV2UyA9IHNjb3BlLmRlZigpO1xuICAgICAgICAgICAgc2NvcGUoJ2lmKCEnLCBlbnYuYmF0Y2hJZCwgJ3x8JywgcHJldlMsICchPT0nLCBWQUxVRSwgJyl7JywgcHJldlMsICc9JywgVkFMVUUsICc7Jyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNjb3BlKEdMLCAnLnVuaWZvcm0nLCBpbmZpeCwgJygnLCBMT0NBVElPTiwgJywnLCBWQUxVRSwgJyk7Jyk7XG4gICAgICAgICAgaWYgKGlzQmF0Y2hJbm5lckxvb3ApIHtcbiAgICAgICAgICAgIHNjb3BlKCd9Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVtaXREcmF3KGVudiwgb3V0ZXIsIGlubmVyLCBhcmdzKSB7XG4gICAgICB2Y
1XIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICAgIHZhciBEUkFXX1NUQVRFID0gc2hhcmVkLmRyYXc7XG4gICAgICB2YXIgZHJhd09wdGlvbnMgPSBhcmdzLmRyYXc7XG4gICAgICBmdW5jdGlvbiBlbWl0RWxlbWVudHMoKSB7XG4gICAgICAgIHZhciBkZWZuID0gZHJhd09wdGlvbnMuZWxlbWVudHM7XG4gICAgICAgIHZhciBFTEVNRU5UUztcbiAgICAgICAgdmFyIHNjb3BlID0gb3V0ZXI7XG4gICAgICAgIGlmIChkZWZuKSB7XG4gICAgICAgICAgaWYgKGRlZm4uY29udGV4dERlcCAmJiBhcmdzLmNvbnRleHREeW5hbWljIHx8IGRlZm4ucHJvcERlcCkge1xuICAgICAgICAgICAgc2NvcGUgPSBpbm5lcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgRUxFTUVOVFMgPSBkZWZuLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgICAgICBpZiAoZHJhd09wdGlvbnMuZWxlbWVudHNBY3RpdmUpIHtcbiAgICAgICAgICAgIHNjb3BlKCdpZignICsgRUxFTUVOVFMgKyAnKScgKyBHTCArICcuYmluZEJ1ZmZlcignICsgR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMiArICcsJyArIEVMRU1FTlRTICsgJy5idWZmZXIuYnVmZmVyKTsnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgRUxFTUVOVFMgPSBzY29wZS5kZWYoKTtcbiAgICAgICAgICBzY29wZShFTEVNRU5UUywgJz0nLCBEUkFXX1NUQVRFLCAnLicsIFNfRUxFTUVOVFMsICc7JywgJ2lmKCcsIEVMRU1FTlRTLCAnKXsnLCBHTCwgJy5iaW5kQnVmZmVyKCcsIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSJDIsICcsJywgRUxFTUVOVFMsICcuYnVmZmVyLmJ1ZmZlcik7fScsICdlbHNlIGlmKCcsIHNoYXJlZC52YW8sICcuY3VycmVudFZBTyl7JywgRUxFTUVOVFMsICc9JywgZW52LnNoYXJlZC5lbGVtZW50cyArICcuZ2V0RWxlbWVudHMoJyArIHNoYXJlZC52YW8sICcuY3VycmVudFZBTy5lbGVtZW50cyk7JywgIWV4dFZlcnRleEFycmF5cyA/ICdpZignICsgRUxFTUVOVFMgKyAnKScgKyBHTCArICcuYmluZEJ1ZmZlcignICsgR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMiArICcsJyArIEVMRU1FTlRTICsgJy5idWZmZXIuYnVmZmVyKTsnIDogJycsICd9Jyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEVMRU1FTlRTO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gZW1pdENvdW50KCkge1xuICAgICAgICB2Y
1XIgZGVmbiA9IGRyYXdPcHRpb25zLmNvdW50O1xuICAgICAgICB2YXIgQ09VTlQ7XG4gICAgICAgIHZhciBzY29wZSA9IG91dGVyO1xuICAgICAgICBpZiAoZGVmbikge1xuICAgICAgICAgIGlmIChkZWZuLmNvbnRleHREZXAgJiYgYXJncy5jb250ZXh0RHluYW1pYyB8fCBkZWZuLnByb3BEZXApIHtcbiAgICAgICAgICAgIHNjb3BlID0gaW5uZXI7XG4gICAgICAgICAgfVxuICAgICAgICAgIENPVU5UID0gZGVmbi5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoZGVmbi5NSVNTSU5HKSB7XG4gICAgICAgICAgICAgIGVudi5hc3NlcnQob3V0ZXIsICdmYWxzZScsICdtaXNzaW5nIHZlcnRleCBjb3VudCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlZm4uRFlOQU1JQykge1xuICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLCBDT1VOVCArICc+PTAnLCAnbWlzc2luZyB2ZXJ0ZXggY291bnQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBDT1VOVCA9IHNjb3BlLmRlZihEUkFXX1NUQVRFLCAnLicsIFNfQ09VTlQpO1xuICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgQ09VTlQgKyAnPj0wJywgJ21pc3NpbmcgdmVydGV4IGNvdW50Jyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIENPVU5UO1xuICAgICAgfVxuICAgICAgdmFyIEVMRU1FTlRTID0gZW1pdEVsZW1lbnRzKCk7XG4gICAgICBmdW5jdGlvbiBlbWl0VmFsdWUobmFtZSkge1xuICAgICAgICB2Y
1XIgZGVmbiA9IGRyYXdPcHRpb25zW25hbWVdO1xuICAgICAgICBpZiAoZGVmbikge1xuICAgICAgICAgIGlmIChkZWZuLmNvbnRleHREZXAgJiYgYXJncy5jb250ZXh0RHluYW1pYyB8fCBkZWZuLnByb3BEZXApIHtcbiAgICAgICAgICAgIHJldHVybiBkZWZuLmFwcGVuZChlbnYsIGlubmVyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRlZm4uYXBwZW5kKGVudiwgb3V0ZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gb3V0ZXIuZGVmKERSQVdfU1RBVEUsICcuJywgbmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBQUklNSVRJVkUgPSBlbWl0VmFsdWUoU19QUklNSVRJVkUpO1xuICAgICAgdmFyIE9GRlNFVCA9IGVtaXRWYWx1ZShTX09GRlNFVCk7XG4gICAgICB2YXIgQ09VTlQgPSBlbWl0Q291bnQoKTtcbiAgICAgIGlmICh0eXBlb2YgQ09VTlQgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGlmIChDT1VOVCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5uZXIoJ2lmKCcsIENPVU5ULCAnKXsnKTtcbiAgICAgICAgaW5uZXIuZXhpdCgnfScpO1xuICAgICAgfVxuICAgICAgdmFyIElOU1RBTkNFUywgRVhUX0lOU1RBTkNJTkc7XG4gICAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgICBJTlNUQU5DRVMgPSBlbWl0VmFsdWUoU19JTlNUQU5DRVMpO1xuICAgICAgICBFWFRfSU5TVEFOQ0lORyA9IGVudi5pbnN0YW5jaW5nO1xuICAgICAgfVxuICAgICAgdmFyIEVMRU1FTlRfVFlQRSA9IEVMRU1FTlRTICsgJy50eXBlJztcbiAgICAgIHZhciBlbGVtZW50c1N0YXRpYyA9IGRyYXdPcHRpb25zLmVsZW1lbnRzICYmIGlzU3RhdGljKGRyYXdPcHRpb25zLmVsZW1lbnRzKSAmJiAhZHJhd09wdGlvbnMudmFvQWN0aXZlO1xuICAgICAgZnVuY3Rpb24gZW1pdEluc3RhbmNpbmcoKSB7XG4gICAgICAgIGZ1bmN0aW9uIGRyYXdFbGVtZW50cygpIHtcbiAgICAgICAgICBpbm5lcihFWFRfSU5TVEFOQ0lORywgJy5kcmF3RWxlbWVudHNJbnN0YW5jZWRBTkdMRSgnLCBbUFJJTUlUSVZFLCBDT1VOVCwgRUxFTUVOVF9UWVBFLCBPRkZTRVQgKyAnPDwoKCcgKyBFTEVNRU5UX1RZUEUgKyAnLScgKyBHTF9VTlNJR05FRF9CWVRFJDggKyAnKT4+MSknLCBJTlNUQU5DRVNdLCAnKTsnKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBkcmF3QXJyYXlzKCkge1xuICAgICAgICAgIGlubmVyKEVYVF9JTlNUQU5DSU5HLCAnLmRyYXdBcnJheXNJbnN0YW5jZWRBTkdMRSgnLCBbUFJJTUlUSVZFLCBPRkZTRVQsIENPVU5ULCBJTlNUQU5DRVNdLCAnKTsnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoRUxFTUVOVFMgJiYgRUxFTUVOVFMgIT09ICdudWxsJykge1xuICAgICAgICAgIGlmICghZWxlbWVudHNTdGF0aWMpIHtcbiAgICAgICAgICAgIGlubmVyKCdpZignLCBFTEVNRU5UUywgJyl7Jyk7XG4gICAgICAgICAgICBkcmF3RWxlbWVudHMoKTtcbiAgICAgICAgICAgIGlubmVyKCd9ZWxzZXsnKTtcbiAgICAgICAgICAgIGRyYXdBcnJheXMoKTtcbiAgICAgICAgICAgIGlubmVyKCd9Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRyYXdFbGVtZW50cygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkcmF3QXJyYXlzKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGVtaXRSZWd1bGFyKCkge1xuICAgICAgICBmdW5jdGlvbiBkcmF3RWxlbWVudHMoKSB7XG4gICAgICAgICAgaW5uZXIoR0wgKyAnLmRyYXdFbGVtZW50cygnICsgW1BSSU1JVElWRSwgQ09VTlQsIEVMRU1FTlRfVFlQRSwgT0ZGU0VUICsgJzw8KCgnICsgRUxFTUVOVF9UWVBFICsgJy0nICsgR0xfVU5TSUdORURfQllURSQ4ICsgJyk+PjEpJ10gKyAnKTsnKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBkcmF3QXJyYXlzKCkge1xuICAgICAgICAgIGlubmVyKEdMICsgJy5kcmF3QXJyYXlzKCcgKyBbUFJJTUlUSVZFLCBPRkZTRVQsIENPVU5UXSArICcpOycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChFTEVNRU5UUyAmJiBFTEVNRU5UUyAhPT0gJ251bGwnKSB7XG4gICAgICAgICAgaWYgKCFlbGVtZW50c1N0YXRpYykge1xuICAgICAgICAgICAgaW5uZXIoJ2lmKCcsIEVMRU1FTlRTLCAnKXsnKTtcbiAgICAgICAgICAgIGRyYXdFbGVtZW50cygpO1xuICAgICAgICAgICAgaW5uZXIoJ31lbHNleycpO1xuICAgICAgICAgICAgZHJhd0FycmF5cygpO1xuICAgICAgICAgICAgaW5uZXIoJ30nKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZHJhd0VsZW1lbnRzKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRyYXdBcnJheXMoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGV4dEluc3RhbmNpbmcgJiYgKHR5cGVvZiBJTlNUQU5DRVMgIT09ICdudW1iZXInIHx8IElOU1RBTkNFUyA+PSAwKSkge1xuICAgICAgICBpZiAodHlwZW9mIElOU1RBTkNFUyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpbm5lcignaWYoJywgSU5TVEFOQ0VTLCAnPjApeycpO1xuICAgICAgICAgIGVtaXRJbnN0YW5jaW5nKCk7XG4gICAgICAgICAgaW5uZXIoJ31lbHNlIGlmKCcsIElOU1RBTkNFUywgJzwwKXsnKTtcbiAgICAgICAgICBlbWl0UmVndWxhcigpO1xuICAgICAgICAgIGlubmVyKCd9Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW1pdEluc3RhbmNpbmcoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW1pdFJlZ3VsYXIoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlQm9keShlbWl0Qm9keSwgcGFyZW50RW52LCBhcmdzLCBwcm9ncmFtLCBjb3VudCkge1xuICAgICAgdmFyIGVudiA9IGNyZWF0ZVJFR0xFbnZpcm9ubWVudCgpO1xuICAgICAgdmFyIHNjb3BlID0gZW52LnByb2MoJ2JvZHknLCBjb3VudCk7XG4gICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZW52LmNvbW1hbmRTdHIgPSBwYXJlbnRFbnYuY29tbWFuZFN0cjtcbiAgICAgICAgZW52LmNvbW1hbmQgPSBlbnYubGluayhwYXJlbnRFbnYuY29tbWFuZFN0cik7XG4gICAgICB9KTtcbiAgICAgIGlmIChleHRJbnN0YW5jaW5nKSB7XG4gICAgICAgIGVudi5pbnN0YW5jaW5nID0gc2NvcGUuZGVmKGVudi5zaGFyZWQuZXh0ZW5zaW9ucywgJy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzJyk7XG4gICAgICB9XG4gICAgICBlbWl0Qm9keShlbnYsIHNjb3BlLCBhcmdzLCBwcm9ncmFtKTtcbiAgICAgIHJldHVybi
1BlbnYuY29tcGlsZSgpLmJvZHk7XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gRFJBVyBQUk9DXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgZnVuY3Rpb24gZW1pdERyYXdCb2R5KGVudiwgZHJhdywgYXJncywgcHJvZ3JhbSkge1xuICAgICAgaW5qZWN0RXh0ZW5zaW9ucyhlbnYsIGRyYXcpO1xuICAgICAgaWYgKGFyZ3MudXNlVkFPKSB7XG4gICAgICAgIGlmIChhcmdzLmRyYXdWQU8pIHtcbiAgICAgICAgICBkcmF3KGVudi5zaGFyZWQudmFvLCAnLnNldFZBTygnLCBhcmdzLmRyYXdWQU8uYXBwZW5kKGVudiwgZHJhdyksICcpOycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRyYXcoZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKCcsIGVudi5zaGFyZWQudmFvLCAnLnRhcmdldFZBTyk7Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRyYXcoZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKG51bGwpOycpO1xuICAgICAgICBlbWl0QXR0cmlidXRlcyhlbnYsIGRyYXcsIGFyZ3MsIHByb2dyYW0uYXR0cmlidXRlcywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGVtaXRVbmlmb3JtcyhlbnYsIGRyYXcsIGFyZ3MsIHByb2dyYW0udW5pZm9ybXMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9LCBmYWxzZSk7XG4gICAgICBlbWl0RHJhdyhlbnYsIGRyYXcsIGRyYXcsIGFyZ3MpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbWl0RHJhd1Byb2MoZW52LCBhcmdzKSB7XG4gICAgICB2Y
1XIgZHJhdyA9IGVudi5wcm9jKCdkcmF3JywgMSk7XG4gICAgICBpbmplY3RFeHRlbnNpb25zKGVudiwgZHJhdyk7XG4gICAgICBlbWl0Q29udGV4dChlbnYsIGRyYXcsIGFyZ3MuY29udGV4dCk7XG4gICAgICBlbWl0UG9sbEZyYW1lYnVmZmVyKGVudiwgZHJhdywgYXJncy5mcmFtZWJ1ZmZlcik7XG4gICAgICBlbWl0UG9sbFN0YXRlKGVudiwgZHJhdywgYXJncyk7XG4gICAgICBlbWl0U2V0T3B0aW9ucyhlbnYsIGRyYXcsIGFyZ3Muc3RhdGUpO1xuICAgICAgZW1pdFByb2ZpbGUoZW52LCBkcmF3LCBhcmdzLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICB2YXIgcHJvZ3JhbSA9IGFyZ3Muc2hhZGVyLnByb2dWYXIuYXBwZW5kKGVudiwgZHJhdyk7XG4gICAgICBkcmF3KGVudi5zaGFyZWQuZ2wsICcudXNlUHJvZ3JhbSgnLCBwcm9ncmFtLCAnLnByb2dyYW0pOycpO1xuICAgICAgaWYgKGFyZ3Muc2hhZGVyLnByb2dyYW0pIHtcbiAgICAgICAgZW1pdERyYXdCb2R5KGVudiwgZHJhdywgYXJncywgYXJncy5zaGFkZXIucHJvZ3JhbSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkcmF3KGVudi5zaGFyZWQudmFvLCAnLnNldFZBTyhudWxsKTsnKTtcbiAgICAgICAgdmFyIGRyYXdDYWNoZSA9IGVudi5nbG9iYWwuZGVmKCd7fScpO1xuICAgICAgICB2YXIgUFJPR19JRCA9IGRyYXcuZGVmKHByb2dyYW0sICcuaWQnKTtcbiAgICAgICAgdmFyIENBQ0hFRF9QUk9DID0gZHJhdy5kZWYoZHJhd0NhY2hlLCAnWycsIFBST0dfSUQsICddJyk7XG4gICAgICAgIGRyYXcoZW52LmNvbmQoQ0FDSEVEX1BST0MpLnRoZW4oQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwKTsnKS5lbHNlKENBQ0hFRF9QUk9DLCAnPScsIGRyYXdDYWNoZSwgJ1snLCBQUk9HX0lELCAnXT0nLCBlbnYubGluayhmdW5jdGlvbiAocHJvZ3JhbSkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVCb2R5KGVtaXREcmF3Qm9keSwgZW52LCBhcmdzLCBwcm9ncmFtLCAxKTtcbiAgICAgICAgfSksICcoJywgcHJvZ3JhbSwgJyk7JywgQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwKTsnKSk7XG4gICAgICB9XG4gICAgICBpZiAoT2JqZWN0LmtleXMoYXJncy5zdGF0ZSkubGVuZ3RoID4gMCkge1xuICAgICAgICBkcmF3KGVudi5zaGFyZWQuY3VycmVudCwgJy5kaXJ0eT10cnVlOycpO1xuICAgICAgfVxuICAgICAgaWYgKGVudi5zaGFyZWQudmFvKSB7XG4gICAgICAgIGRyYXcoZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKG51bGwpOycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIEJBVENIIFBST0NcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIGZ1bmN0aW9uIGVtaXRCYXRjaER5bmFtaWNTaGFkZXJCb2R5KGVudiwgc2NvcGUsIGFyZ3MsIHByb2dyYW0pIHtcbiAgICAgIGVudi5iYXRjaElkID0gJ2ExJztcbiAgICAgIGluamVjdEV4dGVuc2lvbnMoZW52LCBzY29wZSk7XG4gICAgICBmdW5jdGlvbiBhbGwoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgZW1pdEF0dHJpYnV0ZXMoZW52LCBzY29wZSwgYXJncywgcHJvZ3JhbS5hdHRyaWJ1dGVzLCBhbGwpO1xuICAgICAgZW1pdFVuaWZvcm1zKGVudiwgc2NvcGUsIGFyZ3MsIHByb2dyYW0udW5pZm9ybXMsIGFsbCwgZmFsc2UpO1xuICAgICAgZW1pdERyYXcoZW52LCBzY29wZSwgc2NvcGUsIGFyZ3MpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbWl0QmF0Y2hCb2R5KGVudiwgc2NvcGUsIGFyZ3MsIHByb2dyYW0pIHtcbiAgICAgIGluamVjdEV4dGVuc2lvbnMoZW52LCBzY29wZSk7XG4gICAgICB2Y
1XIgY29udGV4dER5bmFtaWMgPSBhcmdzLmNvbnRleHREZXA7XG4gICAgICB2YXIgQkFUQ0hfSUQgPSBzY29wZS5kZWYoKTtcbiAgICAgIHZhciBQUk9QX0xJU1QgPSAnYTAnO1xuICAgICAgdmFyIE5VTV9QUk9QUyA9ICdhMSc7XG4gICAgICB2YXIgUFJPUFMgPSBzY29wZS5kZWYoKTtcbiAgICAgIGVudi5zaGFyZWQucHJvcHMgPSBQUk9QUztcbiAgICAgIGVudi5iYXRjaElkID0gQkFUQ0hfSUQ7XG4gICAgICB2YXIgb3V0ZXIgPSBlbnYuc2NvcGUoKTtcbiAgICAgIHZhciBpbm5lciA9IGVudi5zY29wZSgpO1xuICAgICAgc2NvcGUob3V0ZXIuZW50cnksICdmb3IoJywgQkFUQ0hfSUQsICc9MDsnLCBCQVRDSF9JRCwgJzwnLCBOVU1fUFJPUFMsICc7KysnLCBCQVRDSF9JRCwgJyl7JywgUFJPUFMsICc9JywgUFJPUF9MSVNULCAnWycsIEJBVENIX0lELCAnXTsnLCBpbm5lciwgJ30nLCBvdXRlci5leGl0KTtcbiAgICAgIGZ1bmN0aW9uIGlzSW5uZXJEZWZuKGRlZm4pIHtcbiAgICAgICAgcmV0dXJuIGRlZm4uY29udGV4dERlcCAmJiBjb250ZXh0RHluYW1pYyB8fCBkZWZuLnByb3BEZXA7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBpc091dGVyRGVmbihkZWZuKSB7XG4gICAgICAgIHJldHVybiAhaXNJbm5lckRlZm4oZGVmbik7XG4gICAgICB9XG4gICAgICBpZiAoYXJncy5uZWVkc0NvbnRleHQpIHtcbiAgICAgICAgZW1pdENvbnRleHQoZW52LCBpbm5lciwgYXJncy5jb250ZXh0KTtcbiAgICAgIH1cbiAgICAgIGlmIChhcmdzLm5lZWRzRnJhbWVidWZmZXIpIHtcbiAgICAgICAgZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIGlubmVyLCBhcmdzLmZyYW1lYnVmZmVyKTtcbiAgICAgIH1cbiAgICAgIGVtaXRTZXRPcHRpb25zKGVudiwgaW5uZXIsIGFyZ3Muc3RhdGUsIGlzSW5uZXJEZWZuKTtcbiAgICAgIGlmIChhcmdzLnByb2ZpbGUgJiYgaXNJbm5lckRlZm4oYXJncy5wcm9maWxlKSkge1xuICAgICAgICBlbWl0UHJvZmlsZShlbnYsIGlubmVyLCBhcmdzLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICB9XG4gICAgICBpZiAoIXByb2dyYW0pIHtcbiAgICAgICAgdmFyIHByb2dDYWNoZSA9IGVudi5nbG9iYWwuZGVmKCd7fScpO1xuICAgICAgICB2Y
1XIgUFJPR1JBTSA9IGFyZ3Muc2hhZGVyLnByb2dWYXIuYXBwZW5kKGVudiwgaW5uZXIpO1xuICAgICAgICB2YXIgUFJPR19JRCA9IGlubmVyLmRlZihQUk9HUkFNLCAnLmlkJyk7XG4gICAgICAgIHZhciBDQUNIRURfUFJPQyA9IGlubmVyLmRlZihwcm9nQ2FjaGUsICdbJywgUFJPR19JRCwgJ10nKTtcbiAgICAgICAgaW5uZXIoZW52LnNoYXJlZC5nbCwgJy51c2VQcm9ncmFtKCcsIFBST0dSQU0sICcucHJvZ3JhbSk7JywgJ2lmKCEnLCBDQUNIRURfUFJPQywgJyl7JywgQ0FDSEVEX1BST0MsICc9JywgcHJvZ0NhY2hlLCAnWycsIFBST0dfSUQsICddPScsIGVudi5saW5rKGZ1bmN0aW9uIChwcm9ncmFtKSB7XG4gICAgICAgICAgcmV0dXJuIGNyZWF0ZUJvZHkoZW1pdEJhdGNoRHluYW1pY1NoYWRlckJvZHksIGVudiwgYXJncywgcHJvZ3JhbSwgMik7XG4gICAgICAgIH0pLCAnKCcsIFBST0dSQU0sICcpO30nLCBDQUNIRURfUFJPQywgJy5jYWxsKHRoaXMsYTBbJywgQkFUQ0hfSUQsICddLCcsIEJBVENIX0lELCAnKTsnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChhcmdzLnVzZVZBTykge1xuICAgICAgICAgIGlmIChhcmdzLmRyYXdWQU8pIHtcbiAgICAgICAgICAgIGlmIChpc0lubmVyRGVmbihhcmdzLmRyYXdWQU8pKSB7XG4gICAgICAgICAgICAgIC8vIHZhbyBpcyBhIHByb3BcbiAgICAgICAgICAgICAgaW5uZXIoZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKCcsIGFyZ3MuZHJhd1ZBTy5hcHBlbmQoZW52LCBpbm5lciksICcpOycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gdmFvIGlzIGludmFyaWFudFxuICAgICAgICAgICAgICBvdXRlcihlbnYuc2hhcmVkLnZhbywgJy5zZXRWQU8oJywgYXJncy5kcmF3VkFPLmFwcGVuZChlbnYsIG91dGVyKSwgJyk7Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHNjb3BlZCB2YW8gYmluZGluZ1xuICAgICAgICAgICAgb3V0ZXIoZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKCcsIGVudi5zaGFyZWQudmFvLCAnLnRhcmdldFZBTyk7Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dGVyKGVudi5zaGFyZWQudmFvLCAnLnNldFZBTyhudWxsKTsnKTtcbiAgICAgICAgICBlbWl0QXR0cmlidXRlcyhlbnYsIG91dGVyLCBhcmdzLCBwcm9ncmFtLmF0dHJpYnV0ZXMsIGlzT3V0ZXJEZWZuKTtcbiAgICAgICAgICBlbWl0QXR0cmlidXRlcyhlbnYsIGlubmVyLCBhcmdzLCBwcm9ncmFtLmF0dHJpYnV0ZXMsIGlzSW5uZXJEZWZuKTtcbiAgICAgICAgfVxuICAgICAgICBlbWl0VW5pZm9ybXMoZW52LCBvdXRlciwgYXJncywgcHJvZ3JhbS51bmlmb3JtcywgaXNPdXRlckRlZm4sIGZhbHNlKTtcbiAgICAgICAgZW1pdFVuaWZvcm1zKGVudiwgaW5uZXIsIGFyZ3MsIHByb2dyYW0udW5pZm9ybXMsIGlzSW5uZXJEZWZuLCB0cnVlKTtcbiAgICAgICAgZW1pdERyYXcoZW52LCBvdXRlciwgaW5uZXIsIGFyZ3MpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBlbWl0QmF0Y2hQcm9jKGVudiwgYXJncykge1xuICAgICAgdmFyIGJhdGNoID0gZW52LnByb2MoJ2JhdGNoJywgMik7XG4gICAgICBlbnYuYmF0Y2hJZCA9ICcwJztcbiAgICAgIGluamVjdEV4dGVuc2lvbnMoZW52LCBiYXRjaCk7XG5cbiAgICAgIC8vIENoZWNrIGlmIGFueSBjb250ZXh0IHZhcmlhYmxlcyBkZXBlbmQgb24gcHJvcHNcbiAgICAgIHZhciBjb250ZXh0RHluYW1pYyA9IGZhbHNlO1xuICAgICAgdmFyIG5lZWRzQ29udGV4dCA9IHRydWU7XG4gICAgICBPYmplY3Qua2V5cyhhcmdzLmNvbnRleHQpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgY29udGV4dER5bmFtaWMgPSBjb250ZXh0RHluYW1pYyB8fCBhcmdzLmNvbnRleHRbbmFtZV0ucHJvcERlcDtcbiAgICAgIH0pO1xuICAgICAgaWYgKCFjb250ZXh0RHluYW1pYykge1xuICAgICAgICBlbWl0Q29udGV4dChlbnYsIGJhdGNoLCBhcmdzLmNvbnRleHQpO1xuICAgICAgICBuZWVkc0NvbnRleHQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLy8gZnJhbWVidWZmZXIgc3RhdGUgYWZmZWN0cyBmcmFtZWJ1ZmZlcldpZHRoL2hlaWdodCBjb250ZXh0IHZhcnNcbiAgICAgIHZhciBmcmFtZWJ1ZmZlciA9IGFyZ3MuZnJhbWVidWZmZXI7XG4gICAgICB2Y
1XIgbmVlZHNGcmFtZWJ1ZmZlciA9IGZhbHNlO1xuICAgICAgaWYgKGZyYW1lYnVmZmVyKSB7XG4gICAgICAgIGlmIChmcmFtZWJ1ZmZlci5wcm9wRGVwKSB7XG4gICAgICAgICAgY29udGV4dER5bmFtaWMgPSBuZWVkc0ZyYW1lYnVmZmVyID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChmcmFtZWJ1ZmZlci5jb250ZXh0RGVwICYmIGNvbnRleHREeW5hbWljKSB7XG4gICAgICAgICAgbmVlZHNGcmFtZWJ1ZmZlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFuZWVkc0ZyYW1lYnVmZmVyKSB7XG4gICAgICAgICAgZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIGJhdGNoLCBmcmFtZWJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVtaXRQb2xsRnJhbWVidWZmZXIoZW52LCBiYXRjaCwgbnVsbCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHZpZXdwb3J0IGlzIHdlaXJkIGJlY2F1c2UgaXQgY2FuIGFmZmVjdCBjb250ZXh0IHZhcnNcbiAgICAgIGlmIChhcmdzLnN0YXRlLnZpZXdwb3J0ICYmIGFyZ3Muc3RhdGUudmlld3BvcnQucHJvcERlcCkge1xuICAgICAgICBjb250ZXh0RHluYW1pYyA9IHRydWU7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBpc0lubmVyRGVmbihkZWZuKSB7XG4gICAgICAgIHJldHVybiBkZWZuLmNvbnRleHREZXAgJiYgY29udGV4dER5bmFtaWMgfHwgZGVmbi5wcm9wRGVwO1xuICAgICAgfVxuXG4gICAgICAvLyBzZXQgd2ViZ2wgb3B0aW9uc1xuICAgICAgZW1pdFBvbGxTdGF0ZShlbnYsIGJhdGNoLCBhcmdzKTtcbiAgICAgIGVtaXRTZXRPcHRpb25zKGVudiwgYmF0Y2gsIGFyZ3Muc3RhdGUsIGZ1bmN0aW9uIChkZWZuKSB7XG4gICAgICAgIHJldHVybiAhaXNJbm5lckRlZm4oZGVmbik7XG4gICAgICB9KTtcbiAgICAgIGlmICghYXJncy5wcm9maWxlIHx8ICFpc0lubmVyRGVmbihhcmdzLnByb2ZpbGUpKSB7XG4gICAgICAgIGVtaXRQcm9maWxlKGVudiwgYmF0Y2gsIGFyZ3MsIGZhbHNlLCAnYTEnKTtcbiAgICAgIH1cblxuICAgICAgLy8gU2F2ZSB0aGVzZSB2YWx1ZXMgdG8gYXJncyBzbyB0aGF0IHRoZSBiYXRjaCBib2R5IHJvdXRpbmUgY2FuIHVzZSB0aGVtXG4gICAgICBhcmdzLmNvbnRleHREZXAgPSBjb250ZXh0RHluYW1pYztcbiAgICAgIGFyZ3MubmVlZHNDb250ZXh0ID0gbmVlZHNDb250ZXh0O1xuICAgICAgYXJncy5uZWVkc0ZyYW1lYnVmZmVyID0gbmVlZHNGcmFtZWJ1ZmZlcjtcblxuICAgICAgLy8gZGV0ZXJtaW5lIGlmIHNoYWRlciBpcyBkeW5hbWljXG4gICAgICB2Y
1XIgcHJvZ0RlZm4gPSBhcmdzLnNoYWRlci5wcm9nVmFyO1xuICAgICAgaWYgKHByb2dEZWZuLmNvbnRleHREZXAgJiYgY29udGV4dER5bmFtaWMgfHwgcHJvZ0RlZm4ucHJvcERlcCkge1xuICAgICAgICBlbWl0QmF0Y2hCb2R5KGVudiwgYmF0Y2gsIGFyZ3MsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIFBST0dSQU0gPSBwcm9nRGVmbi5hcHBlbmQoZW52LCBiYXRjaCk7XG4gICAgICAgIGJhdGNoKGVudi5zaGFyZWQuZ2wsICcudXNlUHJvZ3JhbSgnLCBQUk9HUkFNLCAnLnByb2dyYW0pOycpO1xuICAgICAgICBpZiAoYXJncy5zaGFkZXIucHJvZ3JhbSkge1xuICAgICAgICAgIGVtaXRCYXRjaEJvZHkoZW52LCBiYXRjaCwgYXJncywgYXJncy5zaGFkZXIucHJvZ3JhbSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmF0Y2goZW52LnNoYXJlZC52YW8sICcuc2V0VkFPKG51bGwpOycpO1xuICAgICAgICAgIHZhciBiYXRjaENhY2hlID0gZW52Lmdsb2JhbC5kZWYoJ3t9Jyk7XG4gICAgICAgICAgdmFyIFBST0dfSUQgPSBiYXRjaC5kZWYoUFJPR1JBTSwgJy5pZCcpO1xuICAgICAgICAgIHZhciBDQUNIRURfUFJPQyA9IGJhdGNoLmRlZihiYXRjaENhY2hlLCAnWycsIFBST0dfSUQsICddJyk7XG4gICAgICAgICAgYmF0Y2goZW52LmNvbmQoQ0FDSEVEX1BST0MpLnRoZW4oQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwLGExKTsnKS5lbHNlKENBQ0hFRF9QUk9DLCAnPScsIGJhdGNoQ2FjaGUsICdbJywgUFJPR19JRCwgJ109JywgZW52LmxpbmsoZnVuY3Rpb24gKHByb2dyYW0pIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVCb2R5KGVtaXRCYXRjaEJvZHksIGVudiwgYXJncywgcHJvZ3JhbSwgMik7XG4gICAgICAgICAgfSksICcoJywgUFJPR1JBTSwgJyk7JywgQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwLGExKTsnKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChPYmplY3Qua2V5cyhhcmdzLnN0YXRlKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGJhdGNoKGVudi5zaGFyZWQuY3VycmVudCwgJy5kaXJ0eT10cnVlOycpO1xuICAgICAgfVxuICAgICAgaWYgKGVudi5zaGFyZWQudmFvKSB7XG4gICAgICAgIGJhdGNoKGVudi5zaGFyZWQudmFvLCAnLnNldFZBTyhudWxsKTsnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBTQ09QRSBDT01NQU5EXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgZnVuY3Rpb24gZW1pdFNjb3BlUHJvYyhlbnYsIGFyZ3MpIHtcbiAgICAgIHZhciBzY29wZSA9IGVudi5wcm9jKCdzY29wZScsIDMpO1xuICAgICAgZW52LmJhdGNoSWQgPSAnYTInO1xuICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICB2Y
1XIgQ1VSUkVOVF9TVEFURSA9IHNoYXJlZC5jdXJyZW50O1xuICAgICAgZW1pdENvbnRleHQoZW52LCBzY29wZSwgYXJncy5jb250ZXh0KTtcbiAgICAgIGlmIChhcmdzLmZyYW1lYnVmZmVyKSB7XG4gICAgICAgIGFyZ3MuZnJhbWVidWZmZXIuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgfVxuICAgICAgc29ydFN0YXRlKE9iamVjdC5rZXlzKGFyZ3Muc3RhdGUpKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHZhciBkZWZuID0gYXJncy5zdGF0ZVtuYW1lXTtcbiAgICAgICAgdmFyIHZhbHVlID0gZGVmbi5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgIGlmIChpc0FycmF5TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZS5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICBzY29wZS5zZXQoZW52Lm5leHRbbmFtZV0sICdbJyArIGkgKyAnXScsIHYpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNjb3BlLnNldChzaGFyZWQubmV4dCwgJy4nICsgbmFtZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGVtaXRQcm9maWxlKGVudiwgc2NvcGUsIGFyZ3MsIHRydWUsIHRydWUpO1xuICAgICAgW1NfRUxFTUVOVFMsIFNfT0ZGU0VULCBTX0NPVU5ULCBTX0lOU1RBTkNFUywgU19QUklNSVRJVkVdLmZvckVhY2goZnVuY3Rpb24gKG9wdCkge1xuICAgICAgICB2YXIgdmFyaWFibGUgPSBhcmdzLmRyYXdbb3B0XTtcbiAgICAgICAgaWYgKCF2YXJpYWJsZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzY29wZS5zZXQoc2hhcmVkLmRyYXcsICcuJyArIG9wdCwgJycgKyB2YXJpYWJsZS5hcHBlbmQoZW52LCBzY29wZSkpO1xuICAgICAgfSk7XG4gICAgICBPYmplY3Qua2V5cyhhcmdzLnVuaWZvcm1zKS5mb3JFYWNoKGZ1bmN0aW9uIChvcHQpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJncy51bmlmb3Jtc1tvcHRdLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgdmFsdWUgPSAnWycgKyB2YWx1ZS5qb2luKCkgKyAnXSc7XG4gICAgICAgIH1cbiAgICAgICAgc2NvcGUuc2V0KHNoYXJlZC51bmlmb3JtcywgJ1snICsgc3RyaW5nU3RvcmUuaWQob3B0KSArICddJywgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgICBPYmplY3Qua2V5cyhhcmdzLmF0dHJpYnV0ZXMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIHJlY29yZCA9IGFyZ3MuYXR0cmlidXRlc1tuYW1lXS5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICAgIHZhciBzY29wZUF0dHJpYiA9IGVudi5zY29wZUF0dHJpYihuYW1lKTtcbiAgICAgICAgT2JqZWN0LmtleXMobmV3IEF0dHJpYnV0ZVJlY29yZCgpKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgc2NvcGUuc2V0KHNjb3BlQXR0cmliLCAnLicgKyBwcm9wLCByZWNvcmRbcHJvcF0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgaWYgKGFyZ3Muc2NvcGVWQU8pIHtcbiAgICAgICAgc2NvcGUuc2V0KHNoYXJlZC52YW8sICcudGFyZ2V0VkFPJywgYXJncy5zY29wZVZBTy5hcHBlbmQoZW52LCBzY29wZSkpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc2F2ZVNoYWRlcihuYW1lKSB7XG4gICAgICAgIHZhciBzaGFkZXIgPSBhcmdzLnNoYWRlcltuYW1lXTtcbiAgICAgICAgaWYgKHNoYWRlcikge1xuICAgICAgICAgIHNjb3BlLnNldChzaGFyZWQuc2hhZGVyLCAnLicgKyBuYW1lLCBzaGFkZXIuYXBwZW5kKGVudiwgc2NvcGUpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgc2F2ZVNoYWRlcihTX1ZFUlQpO1xuICAgICAgc2F2ZVNoYWRlcihTX0ZSQUcpO1xuICAgICAgaWYgKE9iamVjdC5rZXlzKGFyZ3Muc3RhdGUpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc2NvcGUoQ1VSUkVOVF9TVEFURSwgJy5kaXJ0eT10cnVlOycpO1xuICAgICAgICBzY29wZS5leGl0KENVUlJFTlRfU1RBVEUsICcuZGlydHk9dHJ1ZTsnKTtcbiAgICAgIH1cbiAgICAgIHNjb3BlKCdhMSgnLCBlbnYuc2hhcmVkLmNvbnRleHQsICcsYTAsJywgZW52LmJhdGNoSWQsICcpOycpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpc0R5bmFtaWNPYmplY3Qob2JqZWN0KSB7XG4gICAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcgfHwgaXNBcnJheUxpa2Uob2JqZWN0KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2Y
1XIgcHJvcHMgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAoZHluYW1pYy5pc0R5bmFtaWMob2JqZWN0W3Byb3BzW2ldXSkpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzcGxhdE9iamVjdChlbnYsIG9wdGlvbnMsIG5hbWUpIHtcbiAgICAgIHZhciBvYmplY3QgPSBvcHRpb25zLnN0YXRpY1tuYW1lXTtcbiAgICAgIGlmICghb2JqZWN0IHx8ICFpc0R5bmFtaWNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgZ2xvYmFscyA9IGVudi5nbG9iYWw7XG4gICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG4gICAgICB2YXIgdGhpc0RlcCA9IGZhbHNlO1xuICAgICAgdmFyIGNvbnRleHREZXAgPSBmYWxzZTtcbiAgICAgIHZhciBwcm9wRGVwID0gZmFsc2U7XG4gICAgICB2YXIgb2JqZWN0UmVmID0gZW52Lmdsb2JhbC5kZWYoJ3t9Jyk7XG4gICAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgICAgICAgaWYgKGR5bmFtaWMuaXNEeW5hbWljKHZhbHVlKSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhbHVlID0gb2JqZWN0W2tleV0gPSBkeW5hbWljLnVuYm94KHZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGRlcHMgPSBjcmVhdGVEeW5hbWljRGVjbCh2YWx1ZSwgbnVsbCk7XG4gICAgICAgICAgdGhpc0RlcCA9IHRoaXNEZXAgfHwgZGVwcy50aGlzRGVwO1xuICAgICAgICAgIHByb3BEZXAgPSBwcm9wRGVwIHx8IGRlcHMucHJvcERlcDtcbiAgICAgICAgICBjb250ZXh0RGVwID0gY29udGV4dERlcCB8fCBkZXBzLmNvbnRleHREZXA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZ2xvYmFscyhvYmplY3RSZWYsICcuJywga2V5LCAnPScpO1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7XG4gICAgICAgICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICAgICAgICBnbG9iYWxzKHZhbHVlKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgICBnbG9iYWxzKCdcIicsIHZhbHVlLCAnXCInKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBnbG9iYWxzKCdbJywgdmFsdWUuam9pbigpLCAnXScpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgZ2xvYmFscyhlbnYubGluayh2YWx1ZSkpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgZ2xvYmFscygnOycpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGZ1bmN0aW9uIGFwcGVuZEJsb2NrKGVudiwgYmxvY2spIHtcbiAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICB2Y
1XIgdmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgICAgICAgICBpZiAoIWR5bmFtaWMuaXNEeW5hbWljKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgcmVmID0gZW52Lmludm9rZShibG9jaywgdmFsdWUpO1xuICAgICAgICAgIGJsb2NrKG9iamVjdFJlZiwgJy4nLCBrZXksICc9JywgcmVmLCAnOycpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIG9wdGlvbnMuZHluYW1pY1tuYW1lXSA9IG5ldyBkeW5hbWljLkR5bmFtaWNWYXJpYWJsZShEWU5fVEhVTkssIHtcbiAgICAgICAgdGhpc0RlcDogdGhpc0RlcCxcbiAgICAgICAgY29udGV4dERlcDogY29udGV4dERlcCxcbiAgICAgICAgcHJvcERlcDogcHJvcERlcCxcbiAgICAgICAgcmVmOiBvYmplY3RSZWYsXG4gICAgICAgIGFwcGVuZDogYXBwZW5kQmxvY2tcbiAgICAgIH0pO1xuICAgICAgZGVsZXRlIG9wdGlvbnMuc3RhdGljW25hbWVdO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIE1BSU4gRFJBVyBDT01NQU5EXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgZnVuY3Rpb24gY29tcGlsZUNvbW1hbmQob3B0aW9ucywgYXR0cmlidXRlcywgdW5pZm9ybXMsIGNvbnRleHQsIHN0YXRzKSB7XG4gICAgICB2Y
1XIgZW52ID0gY3JlYXRlUkVHTEVudmlyb25tZW50KCk7XG5cbiAgICAgIC8vIGxpbmsgc3RhdHMsIHNvIHRoYXQgd2UgY2FuIGVhc2lseSBhY2Nlc3MgaXQgaW4gdGhlIHByb2dyYW0uXG4gICAgICBlbnYuc3RhdHMgPSBlbnYubGluayhzdGF0cyk7XG5cbiAgICAgIC8vIHNwbGF0IG9wdGlvbnMgYW5kIGF0dHJpYnV0ZXMgdG8gYWxsb3cgZm9yIGR5bmFtaWMgbmVzdGVkIHByb3BlcnRpZXNcbiAgICAgIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMuc3RhdGljKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgc3BsYXRPYmplY3QoZW52LCBhdHRyaWJ1dGVzLCBrZXkpO1xuICAgICAgfSk7XG4gICAgICBORVNURURfT1BUSU9OUy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHNwbGF0T2JqZWN0KGVudiwgb3B0aW9ucywgbmFtZSk7XG4gICAgICB9KTtcbiAgICAgIHZhciBhcmdzID0gcGFyc2VBcmd1bWVudHMob3B0aW9ucywgYXR0cmlidXRlcywgdW5pZm9ybXMsIGNvbnRleHQsIGVudik7XG4gICAgICBlbWl0RHJhd1Byb2MoZW52LCBhcmdzKTtcbiAgICAgIGVtaXRTY29wZVByb2MoZW52LCBhcmdzKTtcbiAgICAgIGVtaXRCYXRjaFByb2MoZW52LCBhcmdzKTtcbiAgICAgIHJldHVybiBleHRlbmQoZW52LmNvbXBpbGUoKSwge1xuICAgICAgICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgIGFyZ3Muc2hhZGVyLnByb2dyYW0uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBQT0xMIC8gUkVGUkVTSFxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIHJldHVybiB7XG4gICAgICBuZXh0OiBuZXh0U3RhdGUsXG4gICAgICBjdXJyZW50OiBjdXJyZW50U3RhdGUsXG4gICAgICBwcm9jczogZnVuY3Rpb24gKCkge1xuICAgICAgICB2Y
1XIgZW52ID0gY3JlYXRlUkVHTEVudmlyb25tZW50KCk7XG4gICAgICAgIHZhciBwb2xsID0gZW52LnByb2MoJ3BvbGwnKTtcbiAgICAgICAgdmFyIHJlZnJlc2ggPSBlbnYucHJvYygncmVmcmVzaCcpO1xuICAgICAgICB2YXIgY29tbW9uID0gZW52LmJsb2NrKCk7XG4gICAgICAgIHBvbGwoY29tbW9uKTtcbiAgICAgICAgcmVmcmVzaChjb21tb24pO1xuICAgICAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICAgICAgdmFyIEdMID0gc2hhcmVkLmdsO1xuICAgICAgICB2YXIgTkVYVF9TVEFURSA9IHNoYXJlZC5uZXh0O1xuICAgICAgICB2YXIgQ1VSUkVOVF9TVEFURSA9IHNoYXJlZC5jdXJyZW50O1xuICAgICAgICBjb21tb24oQ1VSUkVOVF9TVEFURSwgJy5kaXJ0eT1mYWxzZTsnKTtcbiAgICAgICAgZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIHBvbGwpO1xuICAgICAgICBlbWl0UG9sbEZyYW1lYnVmZmVyKGVudiwgcmVmcmVzaCwgbnVsbCwgdHJ1ZSk7XG5cbiAgICAgICAgLy8gUmVmcmVzaCB1cGRhdGVzIGFsbCBhdHRyaWJ1dGUgc3RhdGUgY2hhbmdlc1xuICAgICAgICB2YXIgSU5TVEFOQ0lORztcbiAgICAgICAgaWYgKGV4dEluc3RhbmNpbmcpIHtcbiAgICAgICAgICBJTlNUQU5DSU5HID0gZW52LmxpbmsoZXh0SW5zdGFuY2luZyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB1cGRhdGUgdmVydGV4IGFycmF5IGJpbmRpbmdzXG4gICAgICAgIGlmIChleHRlbnNpb25zLm9lc192ZXJ0ZXhfYXJyYXlfb2JqZWN0KSB7XG4gICAgICAgICAgcmVmcmVzaChlbnYubGluayhleHRlbnNpb25zLm9lc192ZXJ0ZXhfYXJyYXlfb2JqZWN0KSwgJy5iaW5kVmVydGV4QXJyYXlPRVMobnVsbCk7Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW1pdHMubWF4QXR0cmlidXRlczsgKytpKSB7XG4gICAgICAgICAgdmFyIEJJTkRJTkcgPSByZWZyZXNoLmRlZihzaGFyZWQuYXR0cmlidXRlcywgJ1snLCBpLCAnXScpO1xuICAgICAgICAgIHZhciBpZnRlID0gZW52LmNvbmQoQklORElORywgJy5idWZmZXInKTtcbiAgICAgICAgICBpZnRlLnRoZW4oR0wsICcuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoJywgaSwgJyk7JywgR0wsICcuYmluZEJ1ZmZlcignLCBHTF9BUlJBWV9CVUZGRVIkMiwgJywnLCBCSU5ESU5HLCAnLmJ1ZmZlci5idWZmZXIpOycsIEdMLCAnLnZlcnRleEF0dHJpYlBvaW50ZXIoJywgaSwgJywnLCBCSU5ESU5HLCAnLnNpemUsJywgQklORElORywgJy50eXBlLCcsIEJJTkRJTkcsICcubm9ybWFsaXplZCwnLCBCSU5ESU5HLCAnLnN0cmlkZSwnLCBCSU5ESU5HLCAnLm9mZnNldCk7JykuZWxzZShHTCwgJy5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoJywgaSwgJyk7JywgR0wsICcudmVydGV4QXR0cmliNGYoJywgaSwgJywnLCBCSU5ESU5HLCAnLngsJywgQklORElORywgJy55LCcsIEJJTkRJTkcsICcueiwnLCBCSU5ESU5HLCAnLncpOycsIEJJTkRJTkcsICcuYnVmZmVyPW51bGw7Jyk7XG4gICAgICAgICAgcmVmcmVzaChpZnRlKTtcbiAgICAgICAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgICAgICAgcmVmcmVzaChJTlNUQU5DSU5HLCAnLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRSgnLCBpLCAnLCcsIEJJTkRJTkcsICcuZGl2aXNvcik7Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlZnJlc2goZW52LnNoYXJlZC52YW8sICcuY3VycmVudFZBTz1udWxsOycsIGVudi5zaGFyZWQudmFvLCAnLnNldFZBTygnLCBlbnYuc2hhcmVkLnZhbywgJy50YXJnZXRWQU8pOycpO1xuICAgICAgICBPYmplY3Qua2V5cyhHTF9GTEFHUykuZm9yRWFjaChmdW5jdGlvbiAoZmxhZykge1xuICAgICAgICAgIHZhciBjYXAgPSBHTF9GTEFHU1tmbGFnXTtcbiAgICAgICAgICB2Y
1XIgTkVYVCA9IGNvbW1vbi5kZWYoTkVYVF9TVEFURSwgJy4nLCBmbGFnKTtcbiAgICAgICAgICB2YXIgYmxvY2sgPSBlbnYuYmxvY2soKTtcbiAgICAgICAgICBibG9jaygnaWYoJywgTkVYVCwgJyl7JywgR0wsICcuZW5hYmxlKCcsIGNhcCwgJyl9ZWxzZXsnLCBHTCwgJy5kaXNhYmxlKCcsIGNhcCwgJyl9JywgQ1VSUkVOVF9TVEFURSwgJy4nLCBmbGFnLCAnPScsIE5FWFQsICc7Jyk7XG4gICAgICAgICAgcmVmcmVzaChibG9jayk7XG4gICAgICAgICAgcG9sbCgnaWYoJywgTkVYVCwgJyE9PScsIENVUlJFTlRfU1RBVEUsICcuJywgZmxhZywgJyl7JywgYmxvY2ssICd9Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3Qua2V5cyhHTF9WQVJJQUJMRVMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICB2YXIgZnVuYyA9IEdMX1ZBUklBQkxFU1tuYW1lXTtcbiAgICAgICAgICB2YXIgaW5pdCA9IGN1cnJlbnRTdGF0ZVtuYW1lXTtcbiAgICAgICAgICB2YXIgTkVYVCwgQ1VSUkVOVDtcbiAgICAgICAgICB2YXIgYmxvY2sgPSBlbnYuYmxvY2soKTtcbiAgICAgICAgICBibG9jayhHTCwgJy4nLCBmdW5jLCAnKCcpO1xuICAgICAgICAgIGlmIChpc0FycmF5TGlrZShpbml0KSkge1xuICAgICAgICAgICAgdmFyIG4gPSBpbml0Lmxlbmd0aDtcbiAgICAgICAgICAgIE5FWFQgPSBlbnYuZ2xvYmFsLmRlZihORVhUX1NUQVRFLCAnLicsIG5hbWUpO1xuICAgICAgICAgICAgQ1VSUkVOVCA9IGVudi5nbG9iYWwuZGVmKENVUlJFTlRfU1RBVEUsICcuJywgbmFtZSk7XG4gICAgICAgICAgICBibG9jayhsb29wKG4sIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBORVhUICsgJ1snICsgaSArICddJztcbiAgICAgICAgICAgIH0pLCAnKTsnLCBsb29wKG4sIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBDVVJSRU5UICsgJ1snICsgaSArICddPScgKyBORVhUICsgJ1snICsgaSArICddOyc7XG4gICAgICAgICAgICB9KS5qb2luKCcnKSk7XG4gICAgICAgICAgICBwb2xsKCdpZignLCBsb29wKG4sIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBORVhUICsgJ1snICsgaSArICddIT09JyArIENVUlJFTlQgKyAnWycgKyBpICsgJ10nO1xuICAgICAgICAgICAgfSkuam9pbignfHwnKSwgJyl7JywgYmxvY2ssICd9Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIE5FWFQgPSBjb21tb24uZGVmKE5FWFRfU1RBVEUsICcuJywgbmFtZSk7XG4gICAgICAgICAgICBDVVJSRU5UID0gY29tbW9uLmRlZihDVVJSRU5UX1NUQVRFLCAnLicsIG5hbWUpO1xuICAgICAgICAgICAgYmxvY2soTkVYVCwgJyk7JywgQ1VSUkVOVF9TVEFURSwgJy4nLCBuYW1lLCAnPScsIE5FWFQsICc7Jyk7XG4gICAgICAgICAgICBwb2xsKCdpZignLCBORVhULCAnIT09JywgQ1VSUkVOVCwgJyl7JywgYmxvY2ssICd9Jyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlZnJlc2goYmxvY2spO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGVudi5jb21waWxlKCk7XG4gICAgICB9KCksXG4gICAgICBjb21waWxlOiBjb21waWxlQ29tbWFuZFxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gc3RhdHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhb0NvdW50OiAwLFxuICAgICAgYnVmZmVyQ291bnQ6IDAsXG4gICAgICBlbGVtZW50c0NvdW50OiAwLFxuICAgICAgZnJhbWVidWZmZXJDb3VudDogMCxcbiAgICAgIHNoYWRlckNvdW50OiAwLFxuICAgICAgdGV4dHVyZUNvdW50OiAwLFxuICAgICAgY3ViZUNvdW50OiAwLFxuICAgICAgcmVuZGVyYnVmZmVyQ291bnQ6IDAsXG4gICAgICBtYXhUZXh0dXJlVW5pdHM6IDBcbiAgICB9O1xuICB9XG4gIHZhciBHTF9RVUVSWV9SRVNVTFRfRVhUID0gMHg4ODY2O1xuICB2YXIgR0xfUVVFUllfUkVTVUxUX0FWQUlMQUJMRV9FWFQgPSAweDg4Njc7XG4gIHZhciBHTF9USU1FX0VMQVBTRURfRVhUID0gMHg4OEJGO1xuICB2YXIgY3JlYXRlVGltZXIgPSBmdW5jdGlvbiBjcmVhdGVUaW1lcihnbCwgZXh0ZW5zaW9ucykge1xuICAgIGlmICghZXh0ZW5zaW9ucy5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFFVRVJZIFBPT0wgQkVHSU5cbiAgICB2YXIgcXVlcnlQb29sID0gW107XG4gICAgZnVuY3Rpb24gYWxsb2NRdWVyeSgpIHtcbiAgICAgIHJldHVybiBxdWVyeVBvb2wucG9wKCkgfHwgZXh0ZW5zaW9ucy5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkuY3JlYXRlUXVlcnlFWFQoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZnJlZVF1ZXJ5KHF1ZXJ5KSB7XG4gICAgICBxdWVyeVBvb2wucHVzaChxdWVyeSk7XG4gICAgfVxuICAgIC8vIFFVRVJZIFBPT0wgRU5EXG5cbiAgICB2YXIgcGVuZGluZ1F1ZXJpZXMgPSBbXTtcbiAgICBmdW5jdGlvbiBiZWdpblF1ZXJ5KHN0YXRzKSB7XG4gICAgICB2Y
1XIgcXVlcnkgPSBhbGxvY1F1ZXJ5KCk7XG4gICAgICBleHRlbnNpb25zLmV4dF9kaXNqb2ludF90aW1lcl9xdWVyeS5iZWdpblF1ZXJ5RVhUKEdMX1RJTUVfRUxBUFNFRF9FWFQsIHF1ZXJ5KTtcbiAgICAgIHBlbmRpbmdRdWVyaWVzLnB1c2gocXVlcnkpO1xuICAgICAgcHVzaFNjb3BlU3RhdHMocGVuZGluZ1F1ZXJpZXMubGVuZ3RoIC0gMSwgcGVuZGluZ1F1ZXJpZXMubGVuZ3RoLCBzdGF0cyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVuZFF1ZXJ5KCkge1xuICAgICAgZXh0ZW5zaW9ucy5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkuZW5kUXVlcnlFWFQoR0xfVElNRV9FTEFQU0VEX0VYVCk7XG4gICAgfVxuXG4gICAgLy9cbiAgICAvLyBQZW5kaW5nIHN0YXRzIHBvb2wuXG4gICAgLy9cbiAgICBmdW5jdGlvbiBQZW5kaW5nU3RhdHMoKSB7XG4gICAgICB0aGlzLnN0YXJ0UXVlcnlJbmRleCA9IC0xO1xuICAgICAgdGhpcy5lbmRRdWVyeUluZGV4ID0gLTE7XG4gICAgICB0aGlzLnN1bSA9IDA7XG4gICAgICB0aGlzLnN0YXRzID0gbnVsbDtcbiAgICB9XG4gICAgdmFyIHBlbmRpbmdTdGF0c1Bvb2wgPSBbXTtcbiAgICBmdW5jdGlvbiBhbGxvY1BlbmRpbmdTdGF0cygpIHtcbiAgICAgIHJldHVybiBwZW5kaW5nU3RhdHNQb29sLnBvcCgpIHx8IG5ldyBQZW5kaW5nU3RhdHMoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZnJlZVBlbmRpbmdTdGF0cyhwZW5kaW5nU3RhdHMpIHtcbiAgICAgIHBlbmRpbmdTdGF0c1Bvb2wucHVzaChwZW5kaW5nU3RhdHMpO1xuICAgIH1cbiAgICAvLyBQZW5kaW5nIHN0YXRzIHBvb2wgZW5kXG5cbiAgICB2YXIgcGVuZGluZ1N0YXRzID0gW107XG4gICAgZnVuY3Rpb24gcHVzaFNjb3BlU3RhdHMoc3RhcnQsIGVuZCwgc3RhdHMpIHtcbiAgICAgIHZhciBwcyA9IGFsbG9jUGVuZGluZ1N0YXRzKCk7XG4gICAgICBwcy5zdGFydFF1ZXJ5SW5kZXggPSBzdGFydDtcbiAgICAgIHBzLmVuZFF1ZXJ5SW5kZXggPSBlbmQ7XG4gICAgICBwcy5zdW0gPSAwO1xuICAgICAgcHMuc3RhdHMgPSBzdGF0cztcbiAgICAgIHBlbmRpbmdTdGF0cy5wdXNoKHBzKTtcbiAgICB9XG5cbiAgICAvLyB3ZSBzaG91bGQgY2FsbCB0aGlzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGZyYW1lLFxuICAgIC8vIGluIG9yZGVyIHRvIHVwZGF0ZSBncHVUaW1lXG4gICAgdmFyIHRpbWVTdW0gPSBbXTtcbiAgICB2YXIgcXVlcnlQdHIgPSBbXTtcbiAgICBmdW5jdGlvbiB1cGRhdGUoKSB7XG4gICAgICB2Y
1XIgcHRyLCBpO1xuICAgICAgdmFyIG4gPSBwZW5kaW5nUXVlcmllcy5sZW5ndGg7XG4gICAgICBpZiAobiA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFJlc2VydmUgc3BhY2VcbiAgICAgIHF1ZXJ5UHRyLmxlbmd0aCA9IE1hdGgubWF4KHF1ZXJ5UHRyLmxlbmd0aCwgbiArIDEpO1xuICAgICAgdGltZVN1bS5sZW5ndGggPSBNYXRoLm1heCh0aW1lU3VtLmxlbmd0aCwgbiArIDEpO1xuICAgICAgdGltZVN1bVswXSA9IDA7XG4gICAgICBxdWVyeVB0clswXSA9IDA7XG5cbiAgICAgIC8vIFVwZGF0ZSBhbGwgcGVuZGluZyB0aW1lciBxdWVyaWVzXG4gICAgICB2YXIgcXVlcnlUaW1lID0gMDtcbiAgICAgIHB0ciA9IDA7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgcGVuZGluZ1F1ZXJpZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHF1ZXJ5ID0gcGVuZGluZ1F1ZXJpZXNbaV07XG4gICAgICAgIGlmIChleHRlbnNpb25zLmV4dF9kaXNqb2ludF90aW1lcl9xdWVyeS5nZXRRdWVyeU9iamVjdEVYVChxdWVyeSwgR0xfUVVFUllfUkVTVUxUX0FWQUlMQUJMRV9FWFQpKSB7XG4gICAgICAgICAgcXVlcnlUaW1lICs9IGV4dGVuc2lvbnMuZXh0X2Rpc2pvaW50X3RpbWVyX3F1ZXJ5LmdldFF1ZXJ5T2JqZWN0RVhUKHF1ZXJ5LCBHTF9RVUVSWV9SRVNVTFRfRVhUKTtcbiAgICAgICAgICBmcmVlUXVlcnkocXVlcnkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlbmRpbmdRdWVyaWVzW3B0cisrXSA9IHF1ZXJ5O1xuICAgICAgICB9XG4gICAgICAgIHRpbWVTdW1baSArIDFdID0gcXVlcnlUaW1lO1xuICAgICAgICBxdWVyeVB0cltpICsgMV0gPSBwdHI7XG4gICAgICB9XG4gICAgICBwZW5kaW5nUXVlcmllcy5sZW5ndGggPSBwdHI7XG5cbiAgICAgIC8vIFVwZGF0ZSBhbGwgcGVuZGluZyBzdGF0IHF1ZXJpZXNcbiAgICAgIHB0ciA9IDA7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgcGVuZGluZ1N0YXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBzdGF0cyA9IHBlbmRpbmdTdGF0c1tpXTtcbiAgICAgICAgdmFyIHN0YXJ0ID0gc3RhdHMuc3RhcnRRdWVyeUluZGV4O1xuICAgICAgICB2Y
1XIgZW5kID0gc3RhdHMuZW5kUXVlcnlJbmRleDtcbiAgICAgICAgc3RhdHMuc3VtICs9IHRpbWVTdW1bZW5kXSAtIHRpbWVTdW1bc3RhcnRdO1xuICAgICAgICB2YXIgc3RhcnRQdHIgPSBxdWVyeVB0cltzdGFydF07XG4gICAgICAgIHZhciBlbmRQdHIgPSBxdWVyeVB0cltlbmRdO1xuICAgICAgICBpZiAoZW5kUHRyID09PSBzdGFydFB0cikge1xuICAgICAgICAgIHN0YXRzLnN0YXRzLmdwdVRpbWUgKz0gc3RhdHMuc3VtIC8gMWU2O1xuICAgICAgICAgIGZyZWVQZW5kaW5nU3RhdHMoc3RhdHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YXRzLnN0YXJ0UXVlcnlJbmRleCA9IHN0YXJ0UHRyO1xuICAgICAgICAgIHN0YXRzLmVuZFF1ZXJ5SW5kZXggPSBlbmRQdHI7XG4gICAgICAgICAgcGVuZGluZ1N0YXRzW3B0cisrXSA9IHN0YXRzO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBwZW5kaW5nU3RhdHMubGVuZ3RoID0gcHRyO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgYmVnaW5RdWVyeTogYmVnaW5RdWVyeSxcbiAgICAgIGVuZFF1ZXJ5OiBlbmRRdWVyeSxcbiAgICAgIHB1c2hTY29wZVN0YXRzOiBwdXNoU2NvcGVTdGF0cyxcbiAgICAgIHVwZGF0ZTogdXBkYXRlLFxuICAgICAgZ2V0TnVtUGVuZGluZ1F1ZXJpZXM6IGZ1bmN0aW9uIGdldE51bVBlbmRpbmdRdWVyaWVzKCkge1xuICAgICAgICByZXR1cm4gcGVuZGluZ1F1ZXJpZXMubGVuZ3RoO1xuICAgICAgfSxcbiAgICAgIGNsZWFyOiBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgICAgcXVlcnlQb29sLnB1c2guYXBwbHkocXVlcnlQb29sLCBwZW5kaW5nUXVlcmllcyk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXVlcnlQb29sLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZXh0ZW5zaW9ucy5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkuZGVsZXRlUXVlcnlFWFQocXVlcnlQb29sW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBwZW5kaW5nUXVlcmllcy5sZW5ndGggPSAwO1xuICAgICAgICBxdWVyeVBvb2wubGVuZ3RoID0gMDtcbiAgICAgIH0sXG4gICAgICByZXN0b3JlOiBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICBwZW5kaW5nUXVlcmllcy5sZW5ndGggPSAwO1xuICAgICAgICBxdWVyeVBvb2wubGVuZ3RoID0gMDtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuICB2YXIgR0xfQ09MT1JfQlVGRkVSX0JJVCA9IDE2Mzg0O1xuICB2YXIgR0xfREVQVEhfQlVGRkVSX0JJVCA9IDI1NjtcbiAgdmFyIEdMX1NURU5DSUxfQlVGRkVSX0JJVCA9IDEwMjQ7XG4gIHZhciBHTF9BUlJBWV9CVUZGRVIgPSAzNDk2MjtcbiAgdmFyIENPTlRFWFRfTE9TVF9FVkVOVCA9ICd3ZWJnbGNvbnRleHRsb3N0JztcbiAgdmFyIENPTlRFWFRfUkVTVE9SRURfRVZFTlQgPSAnd2ViZ2xjb250ZXh0cmVzdG9yZWQnO1xuICB2YXIgRFlOX1BST1AgPSAxO1xuICB2YXIgRFlOX0NPTlRFWFQgPSAyO1xuICB2YXIgRFlOX1NUQVRFID0gMztcbiAgZnVuY3Rpb24gZmluZChoYXlzdGFjaywgbmVlZGxlKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXlzdGFjay5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKGhheXN0YWNrW2ldID09PSBuZWVkbGUpIHtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuICBmdW5jdGlvbiB3cmFwUkVHTChhcmdzKSB7XG4gICAgdmFyIGNvbmZpZyA9IHBhcnNlQXJncyhhcmdzKTtcbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciBnbCA9IGNvbmZpZy5nbDtcbiAgICB2YXIgZ2xBdHRyaWJ1dGVzID0gZ2wuZ2V0Q29udGV4dEF0dHJpYnV0ZXMoKTtcbiAgICB2YXIgY29udGV4dExvc3QgPSBnbC5pc0NvbnRleHRMb3N0KCk7XG4gICAgdmFyIGV4dGVuc2lvblN0YXRlID0gY3JlYXRlRXh0ZW5zaW9uQ2FjaGUoZ2wsIGNvbmZpZyk7XG4gICAgaWYgKCFleHRlbnNpb25TdGF0ZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciBzdHJpbmdTdG9yZSA9IGNyZWF0ZVN0cmluZ1N0b3JlKCk7XG4gICAgdmFyIHN0YXRzJCQxID0gc3RhdHMoKTtcbiAgICB2YXIgZXh0ZW5zaW9ucyA9IGV4dGVuc2lvblN0YXRlLmV4dGVuc2lvbnM7XG4gICAgdmFyIHRpbWVyID0gY3JlYXRlVGltZXIoZ2wsIGV4dGVuc2lvbnMpO1xuICAgIHZhciBTVEFSVF9USU1FID0gY2xvY2soKTtcbiAgICB2YXIgV0lEVEggPSBnbC5kcmF3aW5nQnVmZmVyV2lkdGg7XG4gICAgdmFyIEhFSUdIVCA9IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQ7XG4gICAgdmFyIGNvbnRleHRTdGF0ZSA9IHtcbiAgICAgIHRpY2s6IDAsXG4gICAgICB0aW1lOiAwLFxuICAgICAgdmlld3BvcnRXaWR0aDogV0lEVEgsXG4gICAgICB2aWV3cG9ydEhlaWdodDogSEVJR0hULFxuICAgICAgZnJhbWVidWZmZXJXaWR0aDogV0lEVEgsXG4gICAgICBmcmFtZWJ1ZmZlckhlaWdodDogSEVJR0hULFxuICAgICAgZHJhd2luZ0J1ZmZlcldpZHRoOiBXSURUSCxcbiAgICAgIGRyYXdpbmdCdWZmZXJIZWlnaHQ6IEhFSUdIVCxcbiAgICAgIHBpeGVsUmF0aW86IGNvbmZpZy5waXhlbFJhdGlvXG4gICAgfTtcbiAgICB2YXIgdW5pZm9ybVN0YXRlID0ge307XG4gICAgdmFyIGRyYXdTdGF0ZSA9IHtcbiAgICAgIGVsZW1lbnRzOiBudWxsLFxuICAgICAgcHJpbWl0aXZlOiA0LFxuICAgICAgLy8gR0xfVFJJQU5HTEVTXG4gICAgICBjb3VudDogLTEsXG4gICAgICBvZmZzZXQ6IDAsXG4gICAgICBpbnN0YW5jZXM6IC0xXG4gICAgfTtcbiAgICB2YXIgbGltaXRzID0gd3JhcExpbWl0cyhnbCwgZXh0ZW5zaW9ucyk7XG4gICAgdmFyIGJ1ZmZlclN0YXRlID0gd3JhcEJ1ZmZlclN0YXRlKGdsLCBzdGF0cyQkMSwgY29uZmlnLCBkZXN0cm95QnVmZmVyKTtcbiAgICB2YXIgZWxlbWVudFN0YXRlID0gd3JhcEVsZW1lbnRzU3RhdGUoZ2wsIGV4dGVuc2lvbnMsIGJ1ZmZlclN0YXRlLCBzdGF0cyQkMSk7XG4gICAgdmFyIGF0dHJpYnV0ZVN0YXRlID0gd3JhcEF0dHJpYnV0ZVN0YXRlKGdsLCBleHRlbnNpb25zLCBsaW1pdHMsIHN0YXRzJCQxLCBidWZmZXJTdGF0ZSwgZWxlbWVudFN0YXRlLCBkcmF3U3RhdGUpO1xuICAgIGZ1bmN0aW9uIGRlc3Ryb3lCdWZmZXIoYnVmZmVyKSB7XG4gICAgICByZXR1cm4gYXR0cmlidXRlU3RhdGUuZGVzdHJveUJ1ZmZlcihidWZmZXIpO1xuICAgIH1cbiAgICB2YXIgc2hhZGVyU3RhdGUgPSB3cmFwU2hhZGVyU3RhdGUoZ2wsIHN0cmluZ1N0b3JlLCBzdGF0cyQkMSwgY29uZmlnKTtcbiAgICB2YXIgdGV4dHVyZVN0YXRlID0gY3JlYXRlVGV4dHVyZVNldChnbCwgZXh0ZW5zaW9ucywgbGltaXRzLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb3JlLnByb2NzLnBvbGwoKTtcbiAgICB9LCBjb250ZXh0U3RhdGUsIHN0YXRzJCQxLCBjb25maWcpO1xuICAgIHZhciByZW5kZXJidWZmZXJTdGF0ZSA9IHdyYXBSZW5kZXJidWZmZXJzKGdsLCBleHRlbnNpb25zLCBsaW1pdHMsIHN0YXRzJCQxLCBjb25maWcpO1xuICAgIHZhciBmcmFtZWJ1ZmZlclN0YXRlID0gd3JhcEZCT1N0YXRl
1KGdsLCBleHRlbnNpb25zLCBsaW1pdHMsIHRleHR1cmVTdGF0ZSwgcmVuZGVyYnVmZmVyU3RhdGUsIHN0YXRzJCQxKTtcbiAgICB2YXIgY29yZSA9IHJlZ2xDb3JlKGdsLCBzdHJpbmdTdG9yZSwgZXh0ZW5zaW9ucywgbGltaXRzLCBidWZmZXJTdGF0ZSwgZWxlbWVudFN0YXRlLCB0ZXh0dXJlU3RhdGUsIGZyYW1lYnVmZmVyU3RhdGUsIHVuaWZvcm1TdGF0ZSwgYXR0cmlidXRlU3RhdGUsIHNoYWRlclN0YXRlLCBkcmF3U3RhdGUsIGNvbnRleHRTdGF0ZSwgdGltZXIsIGNvbmZpZyk7XG4gICAgdmFyIHJlYWRQaXhlbHMgPSB3cmFwUmVhZFBpeGVscyhnbCwgZnJhbWVidWZmZXJTdGF0ZSwgY29yZS5wcm9jcy5wb2xsLCBjb250ZXh0U3RhdGUsIGdsQXR0cmlidXRlcywgZXh0ZW5zaW9ucywgbGltaXRzKTtcbiAgICB2YXIgbmV4dFN0YXRlID0gY29yZS5uZXh0O1xuICAgIHZhciBjYW52YXMgPSBnbC5jYW52YXM7XG4gICAgdmFyIHJhZkNhbGxiYWNrcyA9IFtdO1xuICAgIHZhciBsb3NzQ2FsbGJhY2tzID0gW107XG4gICAgdmFyIHJlc3RvcmVDYWxsYmFja3MgPSBbXTtcbiAgICB2YXIgZGVzdHJveUNhbGxiYWNrcyA9IFtjb25maWcub25EZXN0cm95XTtcbiAgICB2YXIgYWN0aXZlUkFGID0gbnVsbDtcbiAgICBmdW5jdGlvbiBoYW5kbGVSQUYoKSB7XG4gICAgICBpZiAocmFmQ2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgICB0aW1lci51cGRhdGUoKTtcbiAgICAgICAgfVxuICAgICAgICBhY3RpdmVSQUYgPSBudWxsO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIHNjaGVkdWxlIG5leHQgYW5pbWF0aW9uIGZyYW1lXG4gICAgICBhY3RpdmVSQUYgPSByYWYubmV4dChoYW5kbGVSQUYpO1xuXG4gICAgICAvLyBwb2xsIGZvciBjaGFuZ2VzXG4gICAgICBfcG9sbCgpO1xuXG4gICAgICAvLyBmaXJlIGEgY2FsbGJhY2sgZm9yIGFsbCBwZW5kaW5nIHJhZnNcbiAgICAgIGZvciAodmFyIGkgPSByYWZDYWxsYmFja3MubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgdmFyIGNiID0gcmFmQ2FsbGJhY2tzW2ldO1xuICAgICAgICBpZiAoY2IpIHtcbiAgICAgICAgICBjYihjb250ZXh0U3RhdGUsIG51bGwsIDApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGZsdXNoIGFsbCBwZW5kaW5nIHdlYmdsIGNhbGxzXG4gICAgICBnbC5mbHVzaCgpO1xuXG4gICAgICAvLyBwb2xsIEdQVSB0aW1lcnMgKmFmdGVyKiBnbC5mbHVzaCBzbyB3ZSBkb24ndCBkZWxheSBjb21tYW5kIGRpc3BhdGNoXG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgdGltZXIudXBkYXRlKCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0YXJ0UkFGKCkge1xuICAgICAgaWYgKCFhY3RpdmVSQUYgJiYgcmFmQ2FsbGJhY2tzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYWN0aXZlUkFGID0gcmFmLm5leHQoaGFuZGxlUkFGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gc3RvcFJBRigpIHtcbiAgICAgIGlmIChhY3RpdmVSQUYpIHtcbiAgICAgICAgcmFmLmNhbmNlbChoYW5kbGVSQUYpO1xuICAgICAgICBhY3RpdmVSQUYgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBoYW5kbGVDb250ZXh0TG9zcyhldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgLy8gc2V0IGNvbnRleHQgbG9zdCBmbGFnXG4gICAgICBjb250ZXh0TG9zdCA9IHRydWU7XG5cbiAgICAgIC8vIHBhdXNlIHJlcXVlc3QgYW5pbWF0aW9uIGZyYW1lXG4gICAgICBzdG9wUkFGKCk7XG5cbiAgICAgIC8vIGxvc2UgY29udGV4dFxuICAgICAgbG9zc0NhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICBjYigpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGhhbmRsZUNvbnRleHRSZXN0b3JlZChldmVudCkge1xuICAgICAgLy8gY2xlYXIgZXJyb3IgY29kZVxuICAgICAgZ2wuZ2V0RXJyb3IoKTtcblxuICAgICAgLy8gY2xlYXIgY29udGV4dCBsb3N0IGZsYWdcbiAgICAgIGNvbnRleHRMb3N0ID0gZmFsc2U7XG5cbiAgICAgIC8vIHJlZnJlc2ggc3RhdGVcbiAgICAgIGV4dGVuc2lvblN0YXRlLnJlc3RvcmUoKTtcbiAgICAgIHNoYWRlclN0YXRlLnJlc3RvcmUoKTtcbiAgICAgIGJ1ZmZlclN0YXRlLnJlc3RvcmUoKTtcbiAgICAgIHRleHR1cmVTdGF0ZS5yZXN0b3JlKCk7XG4gICAgICByZW5kZXJidWZmZXJTdGF0ZS5yZXN0b3JlKCk7XG4gICAgICBmcmFtZWJ1ZmZlclN0YXRlLnJlc3RvcmUoKTtcbiAgICAgIGF0dHJpYnV0ZVN0YXRlLnJlc3RvcmUoKTtcbiAgICAgIGlmICh0aW1lcikge1xuICAgICAgICB0aW1lci5yZXN0b3JlKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHJlZnJlc2ggc3RhdGVcbiAgICAgIGNvcmUucHJvY3MucmVmcmVzaCgpO1xuXG4gICAgICAvLyByZXN0YXJ0IFJBRlxuICAgICAgc3RhcnRSQUYoKTtcblxuICAgICAgLy8gcmVzdG9yZSBjb250ZXh0XG4gICAgICByZXN0b3JlQ2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgIGNiKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGNhbnZhcykge1xuICAgICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoQ09OVEVYVF9MT1NUX0VWRU5ULCBoYW5kbGVDb250ZXh0TG9zcywgZmFsc2UpO1xuICAgICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoQ09OVEVYVF9SRVNUT1JFRF9FVkVOVCwgaGFuZGxlQ29udGV4dFJlc3RvcmVkLCBmYWxzZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICByYWZDYWxsYmFja3MubGVuZ3RoID0gMDtcbiAgICAgIHN0b3BSQUYoKTtcbiAgICAgIGlmIChjYW52YXMpIHtcbiAgICAgICAgY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoQ09OVEVYVF9MT1NUX0VWRU5ULCBoYW5kbGVDb250ZXh0TG9zcyk7XG4gICAgICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKENPTlRFWFRfUkVTVE9SRURfRVZFTlQsIGhhbmRsZUNvbnRleHRSZXN0b3JlZCk7XG4gICAgICB9XG4gICAgICBzaGFkZXJTdGF0ZS5jbGVhcigpO1xuICAgICAgZnJhbWVidWZmZXJTdGF0ZS5jbGVhcigpO1xuICAgICAgcmVuZGVyYnVmZmVyU3R
1hdGUuY2xlYXIoKTtcbiAgICAgIGF0dHJpYnV0ZVN0YXRlLmNsZWFyKCk7XG4gICAgICB0ZXh0dXJlU3RhdGUuY2xlYXIoKTtcbiAgICAgIGVsZW1lbnRTdGF0ZS5jbGVhcigpO1xuICAgICAgYnVmZmVyU3RhdGUuY2xlYXIoKTtcbiAgICAgIGlmICh0aW1lcikge1xuICAgICAgICB0aW1lci5jbGVhcigpO1xuICAgICAgfVxuICAgICAgZGVzdHJveUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICBjYigpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNvbXBpbGVQcm9jZWR1cmUob3B0aW9ucykge1xuICAgICAgY2hlY2skMSghIW9wdGlvbnMsICdpbnZhbGlkIGFyZ3MgdG8gcmVnbCh7Li4ufSknKTtcbiAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLCAnb2JqZWN0JywgJ2ludmFsaWQgYXJncyB0byByZWdsKHsuLi59KScpO1xuICAgICAgZnVuY3Rpb24gZmxhdHRlbk5lc3RlZE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZXh0ZW5kKHt9LCBvcHRpb25zKTtcbiAgICAgICAgZGVsZXRlIHJlc3VsdC51bmlmb3JtcztcbiAgICAgICAgZGVsZXRlIHJlc3VsdC5hdHRyaWJ1dGVzO1xuICAgICAgICBkZWxldGUgcmVzdWx0LmNvbnRleHQ7XG4gICAgICAgIGRlbGV0ZSByZXN1bHQudmFvO1xuICAgICAgICBpZiAoJ3N0ZW5jaWwnIGluIHJlc3VsdCAmJiByZXN1bHQuc3RlbmNpbC5vcCkge1xuICAgICAgICAgIHJlc3VsdC5zdGVuY2lsLm9wQmFjayA9IHJlc3VsdC5zdGVuY2lsLm9wRnJvbnQgPSByZXN1bHQuc3RlbmNpbC5vcDtcbiAgICAgICAgICBkZWxldGUgcmVzdWx0LnN0ZW5jaWwub3A7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbWVyZ2UobmFtZSkge1xuICAgICAgICAgIGlmIChuYW1lIGluIHJlc3VsdCkge1xuICAgICAgICAgICAgdmFyIGNoaWxkID0gcmVzdWx0W25hbWVdO1xuICAgICAgICAgICAgZGVsZXRlIHJlc3VsdFtuYW1lXTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKGNoaWxkKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgICAgIHJlc3VsdFtuYW1lICsgJy4nICsgcHJvcF0gPSBjaGlsZFtwcm9wXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtZXJnZSgnYmxlbmQnKTtcbiAgICAgICAgbWVyZ2UoJ2RlcHRoJyk7XG4gICAgICAgIG1lcmdlKCdjdWxsJyk7XG4gICAgICAgIG1lcmdlKCdzdGVuY2lsJyk7XG4gICAgICAgIG1lcmdlKCdwb2x5Z29uT2Zmc2V0Jyk7XG4gICAgICAgIG1lcmdlKCdzY2lzc29yJyk7XG4gICAgICAgIG1lcmdlKCdzYW1wbGUnKTtcbiAgICAgICAgaWYgKCd2YW8nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICByZXN1bHQudmFvID0gb3B0aW9ucy52YW87XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHNlcGFyYXRlRHluYW1pYyhvYmplY3QsIHVzZUFycmF5cykge1xuICAgICAgICB2Y
1XIgc3RhdGljSXRlbXMgPSB7fTtcbiAgICAgICAgdmFyIGR5bmFtaWNJdGVtcyA9IHt9O1xuICAgICAgICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goZnVuY3Rpb24gKG9wdGlvbikge1xuICAgICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdFtvcHRpb25dO1xuICAgICAgICAgIGlmIChkeW5hbWljLmlzRHluYW1pYyh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGR5bmFtaWNJdGVtc1tvcHRpb25dID0gZHluYW1pYy51bmJveCh2YWx1ZSwgb3B0aW9uKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IGVsc2UgaWYgKHVzZUFycmF5cyAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICBpZiAoZHluYW1pYy5pc0R5bmFtaWModmFsdWVbaV0pKSB7XG4gICAgICAgICAgICAgICAgZHluYW1pY0l0ZW1zW29wdGlvbl0gPSBkeW5hbWljLnVuYm94KHZhbHVlLCBvcHRpb24pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBzdGF0aWNJdGVtc1tvcHRpb25dID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGR5bmFtaWM6IGR5bmFtaWNJdGVtcyxcbiAgICAgICAgICBzdGF0aWM6IHN0YXRpY0l0ZW1zXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFRyZWF0IGNvbnRleHQgdmFyaWFibGVzIHNlcGFyYXRlIGZyb20gb3RoZXIgZHluYW1pYyB2YXJpYWJsZXNcbiAgICAgIHZhciBjb250ZXh0ID0gc2VwYXJhdGVEeW5hbWljKG9wdGlvbnMuY29udGV4dCB8fCB7fSwgdHJ1ZSk7XG4gICAgICB2Y
1XIgdW5pZm9ybXMgPSBzZXBhcmF0ZUR5bmFtaWMob3B0aW9ucy51bmlmb3JtcyB8fCB7fSwgdHJ1ZSk7XG4gICAgICB2YXIgYXR0cmlidXRlcyA9IHNlcGFyYXRlRHluYW1pYyhvcHRpb25zLmF0dHJpYnV0ZXMgfHwge30sIGZhbHNlKTtcbiAgICAgIHZhciBvcHRzID0gc2VwYXJhdGVEeW5hbWljKGZsYXR0ZW5OZXN0ZWRPcHRpb25zKG9wdGlvbnMpLCBmYWxzZSk7XG4gICAgICB2YXIgc3RhdHMkJDEgPSB7XG4gICAgICAgIGdwdVRpbWU6IDAuMCxcbiAgICAgICAgY3B1VGltZTogMC4wLFxuICAgICAgICBjb3VudDogMFxuICAgICAgfTtcbiAgICAgIHZhciBjb21waWxlZCA9IGNvcmUuY29tcGlsZShvcHRzLCBhdHRyaWJ1dGVzLCB1bmlmb3JtcywgY29udGV4dCwgc3RhdHMkJDEpO1xuICAgICAgdmFyIGRyYXcgPSBjb21waWxlZC5kcmF3O1xuICAgICAgdmFyIGJhdGNoID0gY29tcGlsZWQuYmF0Y2g7XG4gICAgICB2YXIgc2NvcGUgPSBjb21waWxlZC5zY29wZTtcblxuICAgICAgLy8gRklYTUU6IHdlIHNob3VsZCBtb2RpZnkgY29kZSBnZW5lcmF0aW9uIGZvciBiYXRjaCBjb21tYW5kcyBzbyB0aGlzXG4gICAgICAvLyBpc24ndCBuZWNlc3NhcnlcbiAgICAgIHZhciBFTVBUWV9BUlJBWSA9IFtdO1xuICAgICAgZnVuY3Rpb24gcmVzZXJ2ZShjb3VudCkge1xuICAgICAgICB3aGlsZSAoRU1QVFlfQVJSQVkubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgICAgICBFTVBUWV9BUlJBWS5wdXNoKG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBFTVBUWV9BUlJBWTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIFJFR0xDb21tYW5kKGFyZ3MsIGJvZHkpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGlmIChjb250ZXh0TG9zdCkge1xuICAgICAgICAgIGNoZWNrJDEucmFpc2UoJ2NvbnRleHQgbG9zdCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgYXJncyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHJldHVybiBzY29wZS5jYWxsKHRoaXMsIG51bGwsIGFyZ3MsIDApO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBib2R5ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmdzID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyZ3M7ICsraSkge1xuICAgICAgICAgICAgICBzY29wZS5jYWxsKHRoaXMsIG51bGwsIGJvZHksIGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmdzKSkge1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgc2NvcGUuY2FsbCh0aGlzLCBhcmdzW2ldLCBib2R5LCBpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmNhbGwodGhpcywgYXJncywgYm9keSwgMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmdzID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGlmIChhcmdzID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGJhdGNoLmNhbGwodGhpcywgcmVzZXJ2ZShhcmdzIHwgMCksIGFyZ3MgfCAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmdzKSkge1xuICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGJhdGNoLmNhbGwodGhpcywgYXJncywgYXJncy5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gZHJhdy5jYWxsKHRoaXMsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZXh0ZW5kKFJFR0xDb21tYW5kLCB7XG4gICAgICAgIHN0YXRzOiBzdGF0cyQkMSxcbiAgICAgICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICBjb21waWxlZC5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICB2YXIgc2V0RkJPID0gZnJhbWVidWZmZXJTdGF0ZS5zZXRGQk8gPSBjb21waWxlUHJvY2VkdXJlKHtcbiAgICAgIGZyYW1lYnVmZmVyOiBkeW5hbWljLmRlZmluZS5jYWxsKG51bGwsIERZTl9QUk9QLCAnZnJhbWVidWZmZXInKVxuICAgIH0pO1xuICAgIGZ1bmN0aW9uIGNsZWFySW1wbChfLCBvcHRpb25zKSB7XG4gICAgICB2Y
1XIgY2xlYXJGbGFncyA9IDA7XG4gICAgICBjb3JlLnByb2NzLnBvbGwoKTtcbiAgICAgIHZhciBjID0gb3B0aW9ucy5jb2xvcjtcbiAgICAgIGlmIChjKSB7XG4gICAgICAgIGdsLmNsZWFyQ29sb3IoK2NbMF0gfHwgMCwgK2NbMV0gfHwgMCwgK2NbMl0gfHwgMCwgK2NbM10gfHwgMCk7XG4gICAgICAgIGNsZWFyRmxhZ3MgfD0gR0xfQ09MT1JfQlVGRkVSX0JJVDtcbiAgICAgIH1cbiAgICAgIGlmICgnZGVwdGgnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgZ2wuY2xlYXJEZXB0aCgrb3B0aW9ucy5kZXB0aCk7XG4gICAgICAgIGNsZWFyRmxhZ3MgfD0gR0xfREVQVEhfQlVGRkVSX0JJVDtcbiAgICAgIH1cbiAgICAgIGlmICgnc3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgICAgICBnbC5jbGVhclN0ZW5jaWwob3B0aW9ucy5zdGVuY2lsIHwgMCk7XG4gICAgICAgIGNsZWFyRmxhZ3MgfD0gR0xfU1RFTkNJTF9CVUZGRVJfQklUO1xuICAgICAgfVxuICAgICAgY2hlY2skMSghIWNsZWFyRmxhZ3MsICdjYWxsZWQgcmVnbC5jbGVhciB3aXRoIG5vIGJ1ZmZlciBzcGVjaWZpZWQnKTtcbiAgICAgIGdsLmNsZWFyKGNsZWFyRmxhZ3MpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjbGVhcihvcHRpb25zKSB7XG4gICAgICBjaGVjayQxKHR5cGVvZiBvcHRpb25zID09PSAnb2JqZWN0JyAmJiBvcHRpb25zLCAncmVnbC5jbGVhcigpIHRha2VzIGFuIG9iamVjdCBhcyBpbnB1dCcpO1xuICAgICAgaWYgKCdmcmFtZWJ1ZmZlcicgaW4gb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucy5mcmFtZWJ1ZmZlciAmJiBvcHRpb25zLmZyYW1lYnVmZmVyX3JlZ2xUeXBlID09PSAnZnJhbWVidWZmZXJDdWJlJykge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgICBzZXRGQk8oZXh0ZW5kKHtcbiAgICAgICAgICAgICAgZnJhbWVidWZmZXI6IG9wdGlvbnMuZnJhbWVidWZmZXIuZmFjZXNbaV1cbiAgICAgICAgICAgIH0sIG9wdGlvbnMpLCBjbGVhckltcGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRGQk8ob3B0aW9ucywgY2xlYXJJbXBsKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2xlYXJJbXBsKG51bGwsIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBmcmFtZShjYikge1xuICAgICAgY2hlY2skMS50eXBlKGNiLCAnZnVuY3Rpb24nLCAncmVnbC5mcmFtZSgpIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgcmFmQ2FsbGJhY2tzLnB1c2goY2IpO1xuICAgICAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgICAgICAvLyBGSVhNRTogIHNob3VsZCB3ZSBjaGVjayBzb21ldGhpbmcgb3RoZXIgdGhhbiBlcXVhbHMgY2IgaGVyZT9cbiAgICAgICAgLy8gd2hhdCBpZiBhIHVzZXIgY2FsbHMgZnJhbWUgdHdpY2Ugd2l0aCB0aGUgc2FtZSBjYWxsYmFjay4uLlxuICAgICAgICAvL1xuICAgICAgICB2Y
1XIgaSA9IGZpbmQocmFmQ2FsbGJhY2tzLCBjYik7XG4gICAgICAgIGNoZWNrJDEoaSA+PSAwLCAnY2Fubm90IGNhbmNlbCBhIGZyYW1lIHR3aWNlJyk7XG4gICAgICAgIGZ1bmN0aW9uIHBlbmRpbmdDYW5jZWwoKSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gZmluZChyYWZDYWxsYmFja3MsIHBlbmRpbmdDYW5jZWwpO1xuICAgICAgICAgIHJhZkNhbGxiYWNrc1tpbmRleF0gPSByYWZDYWxsYmFja3NbcmFmQ2FsbGJhY2tzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgIHJhZkNhbGxiYWNrcy5sZW5ndGggLT0gMTtcbiAgICAgICAgICBpZiAocmFmQ2FsbGJhY2tzLmxlbmd0aCA8PSAwKSB7XG4gICAgICAgICAgICBzdG9wUkFGKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJhZkNhbGxiYWNrc1tpXSA9IHBlbmRpbmdDYW5jZWw7XG4gICAgICB9XG4gICAgICBzdGFydFJBRigpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2FuY2VsOiBjYW5jZWxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gcG9sbCB2aWV3cG9ydFxuICAgIGZ1bmN0aW9uIHBvbGxWaWV3cG9ydCgpIHtcbiAgICAgIHZhciB2aWV3cG9ydCA9IG5leHRTdGF0ZS52aWV3cG9ydDtcbiAgICAgIHZhciBzY2lzc29yQm94ID0gbmV4dFN0YXRlLnNjaXNzb3JfYm94O1xuICAgICAgdmlld3BvcnRbMF0gPSB2aWV3cG9ydFsxXSA9IHNjaXNzb3JCb3hbMF0gPSBzY2lzc29yQm94WzFdID0gMDtcbiAgICAgIGNvbnRleHRTdGF0ZS52aWV3cG9ydFdpZHRoID0gY29udGV4dFN0YXRlLmZyYW1lYnVmZmVyV2lkdGggPSBjb250ZXh0U3RhdGUuZHJhd2luZ0J1ZmZlcldpZHRoID0gdmlld3BvcnRbMl0gPSBzY2lzc29yQm94WzJdID0gZ2wuZHJhd2luZ0J1ZmZlcldpZHRoO1xuICAgICAgY29udGV4dFN0YXRlLnZpZXdwb3J0SGVpZ2h0ID0gY29udGV4dFN0YXRlLmZyYW1lYnVmZmVySGVpZ2h0ID0gY29udGV4dFN0YXRlLmRyYXdpbmdCdWZmZXJIZWlnaHQgPSB2aWV3cG9ydFszXSA9IHNjaXNzb3JCb3hbM10gPSBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBfcG9sbCgpIHtcbiAgICAgIGNvbnRleHRTdGF0ZS50aWNrICs9IDE7XG4gICAgICBjb250ZXh0U3RhdGUudGltZSA9IG5vdygpO1xuICAgICAgcG9sbFZpZXdwb3J0KCk7XG4gICAgICBjb3JlLnByb2NzLnBvbGwoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVmcmVzaCgpIHtcbiAgICAgIHRleHR1cmVTdGF0ZS5yZWZyZXNoKCk7XG4gICAgICBwb2xsVmlld3BvcnQoKTtcbiAgICAgIGNvcmUucHJvY3MucmVmcmVzaCgpO1xuICAgICAgaWYgKHRpbWVyKSB7XG4gICAgICAgIHRpbWVyLnVwZGF0ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBub3coKSB7XG4gICAgICByZXR1cm4gKGNsb2NrKCkgLSBTVEFSVF9USU1FKSAvIDEwMDAuMDtcbiAgICB9XG4gICAgcmVmcmVzaCgpO1xuICAgIGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2ZW50LCBjYWxsYmFjaykge1xuICAgICAgY2hlY2skMS50eXBlKGNhbGxiYWNrLCAnZnVuY3Rpb24nLCAnbGlzdGVuZXIgY2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICB2Y
1XIgY2FsbGJhY2tzO1xuICAgICAgc3dpdGNoIChldmVudCkge1xuICAgICAgICBjYXNlICdmcmFtZSc6XG4gICAgICAgICAgcmV0dXJuIGZyYW1lKGNhbGxiYWNrKTtcbiAgICAgICAgY2FzZSAnbG9zdCc6XG4gICAgICAgICAgY2FsbGJhY2tzID0gbG9zc0NhbGxiYWNrcztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmVzdG9yZSc6XG4gICAgICAgICAgY2FsbGJhY2tzID0gcmVzdG9yZUNhbGxiYWNrcztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZGVzdHJveSc6XG4gICAgICAgICAgY2FsbGJhY2tzID0gZGVzdHJveUNhbGxiYWNrcztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIGV2ZW50LCBtdXN0IGJlIG9uZSBvZiBmcmFtZSxsb3N0LHJlc3RvcmUsZGVzdHJveScpO1xuICAgICAgfVxuICAgICAgY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2FuY2VsOiBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChjYWxsYmFja3NbaV0gPT09IGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrc1tpXSA9IGNhbGxiYWNrc1tjYWxsYmFja3MubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgIGNhbGxiYWNrcy5wb3AoKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgdmFyIHJlZ2wgPSBleHRlbmQoY29tcGlsZVByb2NlZHVyZSwge1xuICAgICAgLy8gQ2xlYXIgY3VycmVudCBGQk9cbiAgICAgIGNsZWFyOiBjbGVhcixcbiAgICAgIC8vIFNob3J0IGN1dHMgZm9yIGR5bmFtaWMgdmFyaWFibGVzXG4gICAgICBwcm9wOiBkeW5hbWljLmRlZmluZS5iaW5kKG51bGwsIERZTl9QUk9QKSxcbiAgICAgIGNvbnRleHQ6IGR5bmFtaWMuZGVmaW5lLmJpbmQobnVsbCwgRFlOX0NPTlRFWFQpLFxuICAgICAgdGhpczogZHluYW1pYy5kZWZpbmUuYmluZChudWxsLCBEWU5fU1RBVEUpLFxuICAgICAgLy8gZXhlY3V0ZXMgYW4gZW1wdHkgZHJhdyBjb21tYW5kXG4gICAgICBkcmF3OiBjb21waWxlUHJvY2VkdXJlKHt9KSxcbiAgICAgIC8vIFJlc291cmNlc1xuICAgICAgYnVmZmVyOiBmdW5jdGlvbiBidWZmZXIob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gYnVmZmVyU3R
1hdGUuY3JlYXRlKG9wdGlvbnMsIEdMX0FSUkFZX0JVRkZFUiwgZmFsc2UsIGZhbHNlKTtcbiAgICAgIH0sXG4gICAgICBlbGVtZW50czogZnVuY3Rpb24gZWxlbWVudHMob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gZWxlbWVudFN0YXRlLmNyZWF0ZShvcHRpb25zLCBmYWxzZSk7XG4gICAgICB9LFxuICAgICAgdGV4dHVyZTogdGV4dHVyZVN0YXRlLmNyZWF0ZTJELFxuICAgICAgY3ViZTogdGV4dHVyZVN0YXRlLmNyZWF0ZUN1YmUsXG4gICAgICByZW5kZXJidWZmZXI6IHJlbmRlcmJ1ZmZlclN0YXRlLmNyZWF0ZSxcbiAgICAgIGZyYW1lYnVmZmVyOiBmcmFtZWJ1ZmZlclN0YXRlLmNyZWF0ZSxcbiAgICAgIGZyYW1lYnVmZmVyQ3ViZTogZnJhbWVidWZmZXJTdGF0ZS5jcmVhdGVDdWJlLFxuICAgICAgdmFvOiBhdHRyaWJ1dGVTdGF0ZS5jcmVhdGVWQU8sXG4gICAgICAvLyBFeHBvc2UgY29udGV4dCBhdHRyaWJ1dGVzXG4gICAgICBhdHRyaWJ1dGVzOiBnbEF0dHJpYnV0ZXMsXG4gICAgICAvLyBGcmFtZSByZW5kZXJpbmdcbiAgICAgIGZyYW1lOiBmcmFtZSxcbiAgICAgIG9uOiBhZGRMaXN0ZW5lcixcbiAgICAgIC8vIFN5c3RlbSBsaW1pdHNcbiAgICAgIGxpbWl0czogbGltaXRzLFxuICAgICAgaGFzRXh0ZW5zaW9uOiBmdW5jdGlvbiBoYXNFeHRlbnNpb24obmFtZSkge1xuICAgICAgICByZXR1cm4gbGltaXRzLmV4dGVuc2lvbnMuaW5kZXhPZihuYW1lLnRvTG93ZXJDYXNlKCkpID49IDA7XG4gICAgICB9LFxuICAgICAgLy8gUmVhZCBwaXhlbHNcbiAgICAgIHJlYWQ6IHJlYWRQaXhlbHMsXG4gICAgICAvLyBEZXN0cm95IHJlZ2wgYW5kIGFsbCBhc3NvY2lhdGVkIHJlc291cmNlc1xuICAgICAgZGVzdHJveTogZGVzdHJveSxcbiAgICAgIC8vIERpcmVjdCBHTCBzdGF0ZSBtYW5pcHVsYXRpb25cbiAgICAgIF9nbDogZ2wsXG4gICAgICBfcmVmcmVzaDogcmVmcmVzaCxcbiAgICAgIHBvbGw6IGZ1bmN0aW9uIHBvbGwoKSB7XG4gICAgICAgIF9wb2xsKCk7XG4gICAgICAgIGlmICh0aW1lcikge1xuICAgICAgICAgIHRpbWVyLnVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgLy8gQ3VycmVudCB0aW1lXG4gICAgICBub3c6IG5vdyxcbiAgICAgIC8vIHJlZ2wgU3RhdGlzdGljcyBJbmZvcm1hdGlvblxuICAgICAgc3RhdHM6IHN0YXRzJCQxXG4gICAgfSk7XG4gICAgY29uZmlnLm9uRG9uZShudWxsLCByZWdsKTtcbiAgICByZXR1cm4gcmVnbDtcbiAgfVxuICByZXR1cm4gd3JhcFJFR0w7XG59KTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///6396\n")}}]);

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