(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 65535) { this.current = new ElementGroup(this.vertexBuffer.index, this.elementBuffer && this.elementBuffer.index, this.secondElementBuffer && this.secondElementBuffer.index); this.groups.push(this.current); } }; function ElementGroup(vertexStartIndex, elementStartIndex, secondElementStartIndex) { // the offset into the vertex buffer of the first vertex in this group this.vertexStartIndex = vertexStartIndex; this.elementStartIndex = elementStartIndex; this.secondElementStartIndex = secondElementStartIndex; this.elementLength = 0; this.vertexLength = 0; this.secondElementLength = 0; } },{}],12:[function(require,module,exports){ 'use strict'; var rbush = require('rbush'), Point = require('point-geometry'); module.exports = FeatureTree; function FeatureTree(getGeometry, getType) { this.getGeometry = getGeometry; this.getType = getType; this.rtree = rbush(9); this.toBeInserted = []; } FeatureTree.prototype.insert = function(bbox, bucket_name, feature) { bbox.bucket = bucket_name; bbox.feature = feature; this.toBeInserted.push(bbox); }; // bulk insert into tree FeatureTree.prototype._load = function() { this.rtree.load(this.toBeInserted); this.toBeInserted = []; }; // Finds features in this tile at a particular position. FeatureTree.prototype.query = function(args, callback) { if (this.toBeInserted.length) this._load(); var radius = args.params && args.params.radius || 0; radius *= 4096 / args.scale; var x = args.x, y = args.y; var matching = this.rtree.search([ x - radius, y - radius, x + radius, y + radius ]); if (args.params.buckets) { this.queryBuckets(matching, x, y, radius, args.params, callback); } else { this.queryFeatures(matching, x, y, radius, args.params, callback); } }; FeatureTree.prototype.queryFeatures = function(matching, x, y, radius, params, callback) { var result = []; for (var i = 0; i < matching.length; i++) { var feature = matching[i].feature; var type = this.getType(feature); var geometry = this.getGeometry(feature); if (params.bucket && matching[i].bucket !== params.bucket) continue; if (params.type && type !== params.type) continue; if (geometryContainsPoint(geometry, type, new Point(x, y), radius)) { var props = { _bucket: matching[i].bucket, _type: type }; if (params.geometry) { props._geometry = geometry; } for (var key in feature) { if (feature.hasOwnProperty(key) && key[0] !== '_') { props[key] = feature[key]; } } result.push(props); } } callback(null, result); }; // Lists all buckets that at the position. FeatureTree.prototype.queryBuckets = function(matching, x, y, radius, params, callback) { var buckets = []; for (var i = 0; i < matching.length; i++) { if (buckets.indexOf(matching[i].bucket) >= 0) continue; var feature = matching[i].feature; var type = this.getType(feature); var geometry = this.getGeometry(feature); if (geometryContainsPoint(geometry, type, new Point(x, y), radius)) { buckets.push(matching[i].bucket); } } callback(null, buckets); }; function geometryContainsPoint(rings, type, p, radius) { if (type === 'Point') { return pointContainsPoint(rings, p, radius); } else if (type === 'LineString') { return lineContainsPoint(rings, p, radius); } else if (type === 'Polygon') { return polyContainsPoint(rings, p) ? true : lineContainsPoint(rings, p, radius); } else { return false; } } // Code from http://stackoverflow.com/a/1501725/331379. function distToSegmentSquared(p, v, w) { var l2 = v.distSqr(w); if (l2 === 0) return p.distSqr(v); var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; if (t < 0) return p.distSqr(v); if (t > 1) return p.distSqr(w); return p.distSqr(w.sub(v)._mult(t)._add(v)); } function lineContainsPoint(rings, p, radius) { var r = radius * radius; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 1; j < ring.length; j++) { // Find line segments that have a distance <= radius^2 to p // In that case, we treat the line as "containing point p". var v = ring[j-1], w = ring[j]; if (distToSegmentSquared(p, v, w) < r) return true; } } return false; } // point in polygon ray casting algorithm function polyContainsPoint(rings, p) { var c = false, ring, p1, p2; for (var k = 0; k < rings.length; k++) { ring = rings[k]; for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { p1 = ring[i]; p2 = ring[j]; if (((p1.y > p.y) != (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { c = !c; } } } return c; } function pointContainsPoint(rings, p, radius) { var r = radius * radius; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 0; j < ring.length; j++) { if (ring[j].distSqr(p) <= r) return true; } } return false; } },{"point-geometry":98,"rbush":100}],13:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./elementgroups.js'); module.exports = FillBucket; function FillBucket(info, buffers, placement, elementGroups) { this.info = info; this.buffers = buffers; this.elementGroups = elementGroups || new ElementGroups(buffers.fillVertex, buffers.fillElement, buffers.outlineElement); } FillBucket.prototype.addFeatures = function() { var features = this.features; for (var i = 0; i < features.length; i++) { var feature = features[i]; this.addFeature(feature.loadGeometry()); } }; FillBucket.prototype.addFeature = function(lines) { for (var i = 0; i < lines.length; i++) { this.addFill(lines[i]); } }; FillBucket.prototype.addFill = function(vertices) { if (vertices.length < 3) { //console.warn('a fill must have at least three vertices'); return; } // Calculate the total number of vertices we're going to produce so that we // can resize the buffer beforehand, or detect whether the current line // won't fit into the buffer anymore. // In order to be able to use the vertex buffer for drawing the antialiased // outlines, we separate all polygon vertices with a degenerate (out-of- // viewplane) vertex. var len = vertices.length; // Check whether this geometry buffer can hold all the required vertices. this.elementGroups.makeRoomFor(len + 1); var elementGroup = this.elementGroups.current; var fillVertex = this.buffers.fillVertex; var fillElement = this.buffers.fillElement; var outlineElement = this.buffers.outlineElement; // Start all lines with a degenerate vertex elementGroup.vertexLength++; // We're generating triangle fans, so we always start with the first coordinate in this polygon. var firstIndex = fillVertex.index - elementGroup.vertexStartIndex, prevIndex, currentIndex, currentVertex; for (var i = 0; i < vertices.length; i++) { currentIndex = fillVertex.index - elementGroup.vertexStartIndex; currentVertex = vertices[i]; fillVertex.add(currentVertex.x, currentVertex.y); elementGroup.vertexLength++; // Only add triangles that have distinct vertices. if (i >= 2 && (currentVertex.x !== vertices[0].x || currentVertex.y !== vertices[0].y)) { fillElement.add(firstIndex, prevIndex, currentIndex); elementGroup.elementLength++; } if (i >= 1) { outlineElement.add(prevIndex, currentIndex); elementGroup.secondElementLength++; } prevIndex = currentIndex; } }; FillBucket.prototype.hasData = function() { return !!this.elementGroups.current; }; },{"./elementgroups.js":11}],14:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./elementgroups.js'); module.exports = LineBucket; function LineBucket(info, buffers, placement, elementGroups) { this.info = info; this.buffers = buffers; this.elementGroups = elementGroups || new ElementGroups(buffers.lineVertex, buffers.lineElement); } LineBucket.prototype.addFeatures = function() { var features = this.features; for (var i = 0; i < features.length; i++) { var feature = features[i]; this.addFeature(feature.loadGeometry()); } }; LineBucket.prototype.addFeature = function(lines) { var info = this.info; for (var i = 0; i < lines.length; i++) { this.addLine(lines[i], info['line-join'], info['line-cap'], info['line-miter-limit'], info['line-round-limit']); } }; LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLimit) { if (vertices.length < 2) { //console.warn('a line must have at least two vertices'); return; } if (join === 'bevel') miterLimit = 1.05; var len = vertices.length, firstVertex = vertices[0], lastVertex = vertices[len - 1], closed = firstVertex.equals(lastVertex); var lineVertex = this.buffers.lineVertex; var lineElement = this.buffers.lineElement; // we could be more precies, but it would only save a negligible amount of space this.elementGroups.makeRoomFor(len * 4); var elementGroup = this.elementGroups.current; var vertexStartIndex = elementGroup.vertexStartIndex; if (len == 2 && closed) { // console.warn('a line may not have coincident points'); return; } var beginCap = cap, endCap = closed ? 'butt' : cap, flip = 1, distance = 0, currentVertex, prevVertex, nextVertex, prevNormal, nextNormal; // the last three vertices added var e1, e2, e3; if (closed) { currentVertex = vertices[len - 2]; nextNormal = firstVertex.sub(currentVertex)._unit()._perp(); } for (var i = 0; i < len; i++) { nextVertex = closed && i === len - 1 ? vertices[1] : // if the line is closed, we treat the last vertex like the first vertices[i + 1]; // just the next vertex // if two consecutive vertices exist, skip the current one if (nextVertex && vertices[i].equals(nextVertex)) continue; if (nextNormal) prevNormal = nextNormal; if (currentVertex) prevVertex = currentVertex; currentVertex = vertices[i]; // Calculate how far along the line the currentVertex is if (prevVertex) distance += currentVertex.dist(prevVertex); // Calculate the normal towards the next vertex in this line. In case // there is no next vertex, pretend that the line is continuing straight, // meaning that we are just using the previous normal. nextNormal = nextVertex ? nextVertex.sub(currentVertex)._unit()._perp() : prevNormal; // If we still don't have a previous normal, this is the beginning of a // non-closed line, so we're doing a straight "join". prevNormal = prevNormal || nextNormal; // Determine the normal of the join extrusion. It is the angle bisector // of the segments between the previous line and the next line. var joinNormal = prevNormal.add(nextNormal)._unit(); /* joinNormal prevNormal * ↖ ↑ * .________. prevVertex * | * nextNormal ← | currentVertex * | * nextVertex ! * */ // Calculate the length of the miter (the ratio of the miter to the width). // Find the cosine of the angle between the next and join normals // using dot product. The inverse of that is the miter length. var cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y; var miterLength = 1 / cosHalfAngle; // Whether any vertices have been var startOfLine = e1 === undefined || e2 === undefined; // The join if a middle vertex, otherwise the cap. var middleVertex = prevVertex && nextVertex; var currentJoin = middleVertex ? join : nextVertex ? beginCap : endCap; if (middleVertex && currentJoin === 'round' && miterLength < roundLimit) { currentJoin = 'miter'; } if (currentJoin === 'miter' && miterLength > miterLimit) { currentJoin = 'bevel'; } if (currentJoin === 'bevel') { // The maximum extrude length is 63 / 256 = 4 times the width of the line // so if miterLength >= 4 we need to draw a different type of bevel where. if (miterLength > 4) currentJoin = 'flipbevel'; // If the miterLength is really small and the line bevel wouldn't be visible, // just draw a miter join to save a triangle. if (miterLength < miterLimit) currentJoin = 'miter'; } // Mitered joins if (currentJoin === 'miter') { // scale the unit vector by the miter length joinNormal._mult(miterLength); addCurrentVertex(joinNormal, 0, 0, false); } else if (currentJoin === 'flipbevel') { // miter is too big, flip the direction to make a beveled join if (miterLength > 100) { // Almost parallel lines flip = -flip; joinNormal = nextNormal; } else { var bevelLength = miterLength * prevNormal.add(nextNormal).mag() / prevNormal.sub(nextNormal).mag(); joinNormal._perp()._mult(flip * bevelLength); flip = -flip; } addCurrentVertex(joinNormal, 0, 0, false); // All other types of joins } else { var offsetA, offsetB; if (currentJoin === 'bevel') { var dir = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x; var offset = -Math.sqrt(miterLength * miterLength - 1); if (flip * dir > 0) { offsetB = 0; offsetA = offset; } else { offsetA = 0; offsetB = offset; } } else if (currentJoin === 'square') { offsetA = offsetB = 1; } else { offsetA = offsetB = 0; } // Close previous segment with a butt or a square cap or bevel if (!startOfLine) { addCurrentVertex(prevNormal, offsetA, offsetB, false); } // Add round cap or linejoin at end of segment if (!startOfLine && currentJoin === 'round') { addCurrentVertex(prevNormal, 1, 1, true); } // Segment include cap are done, unset vertices to disconnect segments. // Or leave them to create a bevel. if (startOfLine || currentJoin !== 'bevel') { e1 = e2 = -1; flip = 1; } // Add round cap before first segment if (startOfLine && beginCap === 'round') { addCurrentVertex(nextNormal, -1, -1, true); } // Start next segment with a butt or square cap or bevel if (nextVertex) { addCurrentVertex(nextNormal, -offsetA, -offsetB, false); } } } /* * Adds two vertices to the buffer that are * normal and -normal from the currentVertex. * * endBox moves the extrude one unit in the direction of the line * to create square or round cap. * * endLeft and endRight shifts the extrude along the line * endLeft === 1 moves the extrude in the direction of the line * endLeft === -1 moves the extrude in the reverse direction */ function addCurrentVertex(normal, endLeft, endRight, round) { var tx = round ? 1 : 0; var extrude; extrude = normal.mult(flip); if (endLeft) extrude._sub(normal.perp()._mult(endLeft)); e3 = lineVertex.add(currentVertex, extrude, tx, 0, distance) - vertexStartIndex; if (e1 >= 0 && e2 >= 0) { lineElement.add(e1, e2, e3); elementGroup.elementLength++; } e1 = e2; e2 = e3; extrude = normal.mult(-flip); if (endRight) extrude._sub(normal.perp()._mult(endRight)); e3 = lineVertex.add(currentVertex, extrude, tx, 1, distance) - vertexStartIndex; if (e1 >= 0 && e2 >= 0) { lineElement.add(e1, e2, e3); elementGroup.elementLength++; } e1 = e2; e2 = e3; elementGroup.vertexLength += 2; } }; LineBucket.prototype.hasData = function() { return !!this.elementGroups.current; }; },{"./elementgroups.js":11}],15:[function(require,module,exports){ 'use strict'; module.exports = RasterBucket; function RasterBucket(info) { this.info = info; } },{}],16:[function(require,module,exports){ 'use strict'; var ElementGroups = require('./elementgroups.js'); var Anchor = require('../symbol/anchor.js'); var interpolate = require('../symbol/interpolate.js'); var Point = require('point-geometry'); var resolveTokens = require('../util/token.js'); var Placement = require('../symbol/placement.js'); var Shaping = require('../symbol/shaping.js'); var resolveText = require('../symbol/resolvetext.js'); module.exports = SymbolBucket; var fullRange = [2 * Math.PI , 0]; function SymbolBucket(info, buffers, collision, elementGroups) { this.info = info; this.buffers = buffers; this.collision = collision; if (info['symbol-placement'] === 'line') { if (!info.hasOwnProperty('text-rotation-alignment')) { info['text-rotation-alignment'] = 'map'; } if (!info.hasOwnProperty('icon-rotation-alignment')) { info['icon-rotation-alignment'] = 'map'; } info['symbol-avoid-edges'] = true; } if (elementGroups) { this.elementGroups = elementGroups; } else { this.elementGroups = { text: new ElementGroups(buffers.glyphVertex), icon: new ElementGroups(buffers.iconVertex) }; } } SymbolBucket.prototype.addFeatures = function() { var info = this.info; var features = this.features; var textFeatures = this.textFeatures; var horizontalAlign = 0.5; if (info['text-horizontal-align'] === 'right') horizontalAlign = 1; else if (info['text-horizontal-align'] === 'left') horizontalAlign = 0; var verticalAlign = 0.5; if (info['text-vertical-align'] === 'bottom') verticalAlign = 1; else if (info['text-vertical-align'] === 'top') verticalAlign = 0; var justify = 0.5; if (info['text-justify'] === 'right') justify = 1; else if (info['text-justify'] === 'left') justify = 0; var oneEm = 24; var lineHeight = info['text-line-height'] * oneEm; var maxWidth = info['symbol-placement'] !== 'line' && info['text-max-width'] * oneEm; var spacing = info['text-letter-spacing'] * oneEm; var fontstack = info['text-font']; var textOffset = [info['text-offset'][0] * oneEm, info['text-offset'][1] * oneEm]; for (var k = 0; k < features.length; k++) { var feature = features[k]; var text = textFeatures[k]; var lines = feature.loadGeometry(); var shaping = false; if (text) { shaping = Shaping.shape(text, fontstack, this.stacks, maxWidth, lineHeight, horizontalAlign, verticalAlign, justify, spacing, textOffset); } var image = false; if (this.sprite && this.info['icon-image']) { image = this.sprite[resolveTokens(feature.properties, info['icon-image'])]; if (image) { // match glyph tex object. TODO change image.w = image.width; image.h = image.height; if (image.sdf) this.elementGroups.sdfIcons = true; } } if (!shaping && !image) continue; this.addFeature(lines, this.stacks, shaping, image); } }; function byScale(a, b) { return a.scale - b.scale; } SymbolBucket.prototype.addFeature = function(lines, faces, shaping, image) { var info = this.info; var collision = this.collision; var minScale = 0.5; var glyphSize = 24; var horizontalText = info['text-rotation-alignment'] === 'viewport', horizontalIcon = info['icon-rotation-alignment'] === 'viewport', fontScale = info['text-max-size'] / glyphSize, textBoxScale = collision.tilePixelRatio * fontScale, iconBoxScale = collision.tilePixelRatio * info['icon-max-size'], iconWithoutText = info['text-optional'] || !shaping, textWithoutIcon = info['icon-optional'] || !image, avoidEdges = info['symbol-avoid-edges']; for (var i = 0; i < lines.length; i++) { var line = lines[i]; var anchors; if (info['symbol-placement'] === 'line') { // Line labels anchors = interpolate(line, info['symbol-min-distance'], minScale, collision.maxPlacementScale, collision.tilePixelRatio); // Sort anchors by segment so that we can start placement with the // anchors that can be shown at the lowest zoom levels. anchors.sort(byScale); } else { // Point labels anchors = [new Anchor(line[0].x, line[0].y, 0, minScale)]; } // TODO: figure out correct ascender height. var origin = new Point(0, -17); for (var j = 0, len = anchors.length; j < len; j++) { var anchor = anchors[j]; var inside = !(anchor.x < 0 || anchor.x > 4096 || anchor.y < 0 || anchor.y > 4096); if (avoidEdges && !inside) continue; // Calculate the scales at which the text and icons can be first shown without overlap var glyph; var icon; var glyphScale = null; var iconScale = null; if (shaping) { glyph = Placement.getGlyphs(anchor, origin, shaping, faces, textBoxScale, horizontalText, line, info); glyphScale = info['text-allow-overlap'] ? glyph.minScale : collision.getPlacementScale(glyph.boxes, glyph.minScale, avoidEdges); if (!glyphScale && !iconWithoutText) continue; } if (image) { icon = Placement.getIcon(anchor, image, iconBoxScale, line, info); iconScale = info['icon-allow-overlap'] ? icon.minScale : collision.getPlacementScale(icon.boxes, icon.minScale, avoidEdges); if (!iconScale && !textWithoutIcon) continue; } if (!iconWithoutText && !textWithoutIcon) { iconScale = glyphScale = Math.max(iconScale, glyphScale); } else if (!textWithoutIcon && glyphScale) { glyphScale = Math.max(iconScale, glyphScale); } else if (!iconWithoutText && iconScale) { iconScale = Math.max(iconScale, glyphScale); } // Get the rotation ranges it is safe to show the glyphs var glyphRange = (!glyphScale || info['text-allow-overlap']) ? fullRange : collision.getPlacementRange(glyph.boxes, glyphScale, horizontalText); var iconRange = (!iconScale || info['icon-allow-overlap']) ? fullRange : collision.getPlacementRange(icon.boxes, iconScale, horizontalIcon); var maxRange = [ Math.min(iconRange[0], glyphRange[0]), Math.max(iconRange[1], glyphRange[1])]; if (!iconWithoutText && !textWithoutIcon) { iconRange = glyphRange = maxRange; } else if (!textWithoutIcon) { glyphRange = maxRange; } else if (!iconWithoutText) { iconRange = maxRange; } // Insert final placement into collision tree and add glyphs/icons to buffers if (glyphScale) { if (!info['text-ignore-placement']) { collision.insert(glyph.boxes, anchor, glyphScale, glyphRange, horizontalText); } if (inside) this.addSymbols(this.buffers.glyphVertex, this.elementGroups.text, glyph.shapes, glyphScale, glyphRange); } if (iconScale) { if (!info['icon-ignore-placement']) { collision.insert(icon.boxes, anchor, iconScale, iconRange, horizontalIcon); } if (inside) this.addSymbols(this.buffers.iconVertex, this.elementGroups.icon, icon.shapes, iconScale, iconRange); } } } }; SymbolBucket.prototype.addSymbols = function(buffer, elementGroups, symbols, scale, placementRange) { var zoom = this.collision.zoom; elementGroups.makeRoomFor(0); var elementGroup = elementGroups.current; var placementZoom = Math.log(scale) / Math.LN2 + zoom; for (var k = 0; k < symbols.length; k++) { var symbol = symbols[k], tl = symbol.tl, tr = symbol.tr, bl = symbol.bl, br = symbol.br, tex = symbol.tex, angle = symbol.angle, anchor = symbol.anchor, minZoom = Math.max(zoom + Math.log(symbol.minScale) / Math.LN2, placementZoom), maxZoom = Math.min(zoom + Math.log(symbol.maxScale) / Math.LN2, 25); if (maxZoom <= minZoom) continue; // Lower min zoom so that while fading out the label it can be shown outside of collision-free zoom levels if (minZoom === placementZoom) minZoom = 0; // first triangle buffer.add(anchor.x, anchor.y, tl.x, tl.y, tex.x, tex.y, angle, minZoom, placementRange, maxZoom, placementZoom); buffer.add(anchor.x, anchor.y, tr.x, tr.y, tex.x + tex.w, tex.y, angle, minZoom, placementRange, maxZoom, placementZoom); buffer.add(anchor.x, anchor.y, bl.x, bl.y, tex.x, tex.y + tex.h, angle, minZoom, placementRange, maxZoom, placementZoom); // second triangle buffer.add(anchor.x, anchor.y, tr.x, tr.y, tex.x + tex.w, tex.y, angle, minZoom, placementRange, maxZoom, placementZoom); buffer.add(anchor.x, anchor.y, bl.x, bl.y, tex.x, tex.y + tex.h, angle, minZoom, placementRange, maxZoom, placementZoom); buffer.add(anchor.x, anchor.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, angle, minZoom, placementRange, maxZoom, placementZoom); elementGroup.vertexLength += 6; } }; SymbolBucket.prototype.getDependencies = function(tile, actor, callback) { var firstdone = false; var firsterr; this.getTextDependencies(tile, actor, done); this.getIconDependencies(tile, actor, done); function done(err) { if (err || firstdone) callback(err); firstdone = true; firsterr = err; } }; SymbolBucket.prototype.getIconDependencies = function(tile, actor, callback) { var bucket = this; if (this.info['icon-image']) { if (SymbolBucket.sprite) { this.sprite = SymbolBucket.sprite; callback(); } else { actor.send('get sprite json', {}, function(err, data) { SymbolBucket.sprite = bucket.sprite = data.sprite; callback(err); }); } } else { callback(); } }; SymbolBucket.prototype.getTextDependencies = function(tile, actor, callback) { var features = this.features; var info = this.info; if (tile.stacks === undefined) tile.stacks = {}; var stacks = this.stacks = tile.stacks; var fontstack = info['text-font']; if (stacks[fontstack] === undefined) { stacks[fontstack] = { glyphs: {}, rects: {} }; } var stack = stacks[fontstack]; var data = resolveText(features, info, stack.glyphs); this.textFeatures = data.textFeatures; actor.send('get glyphs', { id: tile.id, fontstack: fontstack, codepoints: data.codepoints }, function(err, newstack) { if (err) return callback(err); var newglyphs = newstack.glyphs; var newrects = newstack.rects; var glyphs = stack.glyphs; var rects = stack.rects; for (var codepoint in newglyphs) { glyphs[codepoint] = newglyphs[codepoint]; rects[codepoint] = newrects[codepoint]; } callback(); }); }; SymbolBucket.prototype.hasData = function() { return !!this.elementGroups.text.current || !!this.elementGroups.icon.current; }; },{"../symbol/anchor.js":57,"../symbol/interpolate.js":62,"../symbol/placement.js":63,"../symbol/resolvetext.js":64,"../symbol/shaping.js":66,"../util/token.js":85,"./elementgroups.js":11,"point-geometry":98}],17:[function(require,module,exports){ 'use strict'; module.exports = LatLng; function LatLng(lat, lng) { if (isNaN(lat) || isNaN(lng)) { throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); } this.lat = +lat; this.lng = +lng; } // constructs LatLng from an array if necessary LatLng.convert = function (a) { if (a instanceof LatLng) { return a; } if (Array.isArray(a)) { return new LatLng(a[0], a[1]); } return a; }; },{}],18:[function(require,module,exports){ 'use strict'; module.exports = LatLngBounds; var LatLng = require('./latlng.js'); function LatLngBounds(sw, ne) { if (!sw) return; var latlngs = ne ? [sw, ne] : sw; for (var i = 0, len = latlngs.length; i < len; i++) { this.extend(latlngs[i]); } } LatLngBounds.prototype = { // extend the bounds to contain the given point or bounds extend: function (obj) { var sw = this._sw, ne = this._ne, sw2, ne2; if (obj instanceof LatLng) { sw2 = obj; ne2 = obj; } else if (obj instanceof LatLngBounds) { sw2 = obj._sw; ne2 = obj._ne; if (!sw2 || !ne2) return this; } else { return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this; } if (!sw && !ne) { this._sw = new LatLng(sw2.lat, sw2.lng); this._ne = new LatLng(ne2.lat, ne2.lng); } else { sw.lat = Math.min(sw2.lat, sw.lat); sw.lng = Math.min(sw2.lng, sw.lng); ne.lat = Math.max(ne2.lat, ne.lat); ne.lng = Math.max(ne2.lng, ne.lng); } return this; }, getCenter: function () { return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2); }, getSouthWest: function () { return this._sw; }, getNorthEast: function () { return this._ne; }, getNorthWest: function () { return new LatLng(this.getNorth(), this.getWest()); }, getSouthEast: function () { return new LatLng(this.getSouth(), this.getEast()); }, getWest: function () { return this._sw.lng; }, getSouth: function () { return this._sw.lat; }, getEast: function () { return this._ne.lng; }, getNorth: function () { return this._ne.lat; } }; // constructs LatLngBounds from an array if necessary LatLngBounds.convert = function (a) { if (!a || a instanceof LatLngBounds) return a; return new LatLngBounds(a); }; },{"./latlng.js":17}],19:[function(require,module,exports){ 'use strict'; var LatLng = require('./latlng.js'), Point = require('point-geometry'); module.exports = Transform; // A single transform, generally used for a single tile to be scaled, rotated, and zoomed. function Transform(minZoom, maxZoom) { this.tileSize = 512; // constant this._minZoom = minZoom || 0; this._maxZoom = maxZoom || 22; this.latRange = [-85, 85]; this.width = 0; this.height = 0; this.zoom = 0; this.center = new LatLng(0, 0); this.angle = 0; } Transform.prototype = { get minZoom() { return this._minZoom; }, set minZoom(zoom) { this._minZoom = zoom; this.zoom = Math.max(this.zoom, zoom); }, get maxZoom() { return this._maxZoom; }, set maxZoom(zoom) { this._maxZoom = zoom; this.zoom = Math.min(this.zoom, zoom); }, get worldSize() { return this.tileSize * this.scale; }, get centerPoint() { return this.size._div(2); }, get size() { return new Point(this.width, this.height); }, get bearing() { return -this.angle / Math.PI * 180; }, set bearing(bearing) { // confine the angle to within [-180,180] bearing = ((((bearing + 180) % 360) + 360) % 360) - 180; this.angle = -bearing * Math.PI / 180; }, get zoom() { return this._zoom; }, set zoom(zoom) { zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom); this._zoom = zoom; this.scale = this.zoomScale(zoom); this.tileZoom = Math.floor(zoom); this.zoomFraction = zoom - this.tileZoom; this._constrain(); }, zoomScale: function(zoom) { return Math.pow(2, zoom); }, scaleZoom: function(scale) { return Math.log(scale) / Math.LN2; }, project: function(latlng, worldSize) { return new Point( this.lngX(latlng.lng, worldSize), this.latY(latlng.lat, worldSize)); }, unproject: function(point, worldSize) { return new LatLng( this.yLat(point.y, worldSize), this.xLng(point.x, worldSize)); }, get x() { return this.lngX(this.center.lng); }, get y() { return this.latY(this.center.lat); }, get point() { return new Point(this.x, this.y); }, // lat/lon <-> absolute pixel coords convertion lngX: function(lon, worldSize) { return (180 + lon) * (worldSize || this.worldSize) / 360; }, // latitude to absolute y coord latY: function(lat, worldSize) { var y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360)); return (180 - y) * (worldSize || this.worldSize) / 360; }, xLng: function(x, worldSize) { return x * 360 / (worldSize || this.worldSize) - 180; }, yLat: function(y, worldSize) { var y2 = 180 - y * 360 / (worldSize || this.worldSize); return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90; }, panBy: function(offset) { var point = this.centerPoint._add(offset); this.center = this.pointLocation(point); this._constrain(); }, setZoomAround: function(zoom, center) { var p = this.locationPoint(center), p1 = this.size._sub(p), latlng = this.pointLocation(p1); this.zoom = zoom; this.panBy(p1.sub(this.locationPoint(latlng))); }, setBearingAround: function(bearing, center) { var offset = this.locationPoint(center).sub(this.centerPoint); this.panBy(offset); this.bearing = bearing; this.panBy(offset.mult(-1)); }, locationPoint: function(latlng) { var p = this.project(latlng); return this.centerPoint._sub(this.point._sub(p)._rotate(this.angle)); }, pointLocation: function(p) { var p2 = this.centerPoint._sub(p)._rotate(-this.angle); return this.unproject(this.point.sub(p2)); }, locationCoordinate: function(latlng) { var k = this.zoomScale(this.tileZoom) / this.worldSize; return { column: this.lngX(latlng.lng) * k, row: this.latY(latlng.lat) * k, zoom: this.tileZoom }; }, pointCoordinate: function(tileCenter, p) { var zoomFactor = this.zoomScale(this.zoomFraction), kt = this.zoomScale(this.tileZoom - tileCenter.zoom), p2 = this.centerPoint._sub(p)._rotate(-this.angle)._div(this.tileSize * zoomFactor); return { column: tileCenter.column * kt - p2.x, row: tileCenter.row * kt - p2.y, zoom: this.tileZoom }; }, _constrain: function() { if (!this.center) return; var minY, maxY, minX, maxX, sy, sx, x2, y2, size = this.size; if (this.latRange) { minY = this.latY(this.latRange[1]); maxY = this.latY(this.latRange[0]); sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; } if (this.lngRange) { minX = this.lngX(this.lngRange[0]); maxX = this.lngX(this.lngRange[1]); sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; } // how much the map should scale to fit the screen into given latitude/longitude ranges var s = Math.max(sx || 0, sy || 0); if (s) { this.center = this.unproject(new Point( sx ? (maxX + minX) / 2 : this.x, sy ? (maxY + minY) / 2 : this.y)); this.zoom += this.scaleZoom(s); return; } if (this.latRange) { var y = this.y, h2 = size.y / 2; if (y - h2 < minY) y2 = minY + h2; if (y + h2 > maxY) y2 = maxY - h2; } if (this.lngRange) { var x = this.x, w2 = size.x / 2; if (x - w2 < minX) x2 = minX + w2; if (x + w2 > maxX) x2 = maxX - w2; } // pan the map if the screen goes off the range if (x2 !== undefined || y2 !== undefined) { this.center = this.unproject(new Point( x2 !== undefined ? x2 : this.x, y2 !== undefined ? y2 : this.y)); } } }; },{"./latlng.js":17,"point-geometry":98}],20:[function(require,module,exports){ // Font data From Hershey Simplex Font // http://paulbourke.net/dataformats/hershey/ var simplex_font = { " ": [16, []], "!": [10, [5, 21, 5, 7, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], "\"": [16, [4, 21, 4, 14, -1, -1, 12, 21, 12, 14]], "#": [21, [11, 25, 4, -7, -1, -1, 17, 25, 10, -7, -1, -1, 4, 12, 18, 12, -1, -1, 3, 6, 17, 6]], "$": [20, [8, 25, 8, -4, -1, -1, 12, 25, 12, -4, -1, -1, 17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]], "%": [24, [21, 21, 3, 0, -1, -1, 8, 21, 10, 19, 10, 17, 9, 15, 7, 14, 5, 14, 3, 16, 3, 18, 4, 20, 6, 21, 8, 21, 10, 20, 13, 19, 16, 19, 19, 20, 21, 21, -1, -1, 17, 7, 15, 6, 14, 4, 14, 2, 16, 0, 18, 0, 20, 1, 21, 3, 21, 5, 19, 7, 17, 7]], "&": [26, [23, 12, 23, 13, 22, 14, 21, 14, 20, 13, 19, 11, 17, 6, 15, 3, 13, 1, 11, 0, 7, 0, 5, 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9, 12, 13, 13, 14, 14, 16, 14, 18, 13, 20, 11, 21, 9, 20, 8, 18, 8, 16, 9, 13, 11, 10, 16, 3, 18, 1, 20, 0, 22, 0, 23, 1, 23, 2]], "'": [10, [5, 19, 4, 20, 5, 21, 6, 20, 6, 18, 5, 16, 4, 15]], "(": [14, [11, 25, 9, 23, 7, 20, 5, 16, 4, 11, 4, 7, 5, 2, 7, -2, 9, -5, 11, -7]], ")": [14, [3, 25, 5, 23, 7, 20, 9, 16, 10, 11, 10, 7, 9, 2, 7, -2, 5, -5, 3, -7]], "*": [16, [8, 21, 8, 9, -1, -1, 3, 18, 13, 12, -1, -1, 13, 18, 3, 12]], "+": [26, [13, 18, 13, 0, -1, -1, 4, 9, 22, 9]], ",": [10, [6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]], "-": [26, [4, 9, 22, 9]], ".": [10, [5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], "/": [22, [20, 25, 2, -7]], "0": [20, [9, 21, 6, 20, 4, 17, 3, 12, 3, 9, 4, 4, 6, 1, 9, 0, 11, 0, 14, 1, 16, 4, 17, 9, 17, 12, 16, 17, 14, 20, 11, 21, 9, 21]], "1": [20, [6, 17, 8, 18, 11, 21, 11, 0]], "2": [20, [4, 16, 4, 17, 5, 19, 6, 20, 8, 21, 12, 21, 14, 20, 15, 19, 16, 17, 16, 15, 15, 13, 13, 10, 3, 0, 17, 0]], "3": [20, [5, 21, 16, 21, 10, 13, 13, 13, 15, 12, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]], "4": [20, [13, 21, 3, 7, 18, 7, -1, -1, 13, 21, 13, 0]], "5": [20, [15, 21, 5, 21, 4, 12, 5, 13, 8, 14, 11, 14, 14, 13, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]], "6": [20, [16, 18, 15, 20, 12, 21, 10, 21, 7, 20, 5, 17, 4, 12, 4, 7, 5, 3, 7, 1, 10, 0, 11, 0, 14, 1, 16, 3, 17, 6, 17, 7, 16, 10, 14, 12, 11, 13, 10, 13, 7, 12, 5, 10, 4, 7]], "7": [20, [17, 21, 7, 0, -1, -1, 3, 21, 17, 21]], "8": [20, [8, 21, 5, 20, 4, 18, 4, 16, 5, 14, 7, 13, 11, 12, 14, 11, 16, 9, 17, 7, 17, 4, 16, 2, 15, 1, 12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6, 11, 9, 12, 13, 13, 15, 14, 16, 16, 16, 18, 15, 20, 12, 21, 8, 21]], "9": [20, [16, 14, 15, 11, 13, 9, 10, 8, 9, 8, 6, 9, 4, 11, 3, 14, 3, 15, 4, 18, 6, 20, 9, 21, 10, 21, 13, 20, 15, 18, 16, 14, 16, 9, 15, 4, 13, 1, 10, 0, 8, 0, 5, 1, 4, 3]], ":": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]], ";": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]], "<": [24, [20, 18, 4, 9, 20, 0]], "=": [26, [4, 12, 22, 12, -1, -1, 4, 6, 22, 6]], ">": [24, [4, 18, 20, 9, 4, 0]], "?": [18, [3, 16, 3, 17, 4, 19, 5, 20, 7, 21, 11, 21, 13, 20, 14, 19, 15, 17, 15, 15, 14, 13, 13, 12, 9, 10, 9, 7, -1, -1, 9, 2, 8, 1, 9, 0, 10, 1, 9, 2]], "@": [27, [18, 13, 17, 15, 15, 16, 12, 16, 10, 15, 9, 14, 8, 11, 8, 8, 9, 6, 11, 5, 14, 5, 16, 6, 17, 8, -1, -1, 12, 16, 10, 14, 9, 11, 9, 8, 10, 6, 11, 5, -1, -1, 18, 16, 17, 8, 17, 6, 19, 5, 21, 5, 23, 7, 24, 10, 24, 12, 23, 15, 22, 17, 20, 19, 18, 20, 15, 21, 12, 21, 9, 20, 7, 19, 5, 17, 4, 15, 3, 12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1, 12, 0, 15, 0, 18, 1, 20, 2, 21, 3, -1, -1, 19, 16, 18, 8, 18, 6, 19, 5]], "A": [18, [9, 21, 1, 0, -1, -1, 9, 21, 17, 0, -1, -1, 4, 7, 14, 7]], "B": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, -1, -1, 4, 11, 13, 11, 16, 10, 17, 9, 18, 7, 18, 4, 17, 2, 16, 1, 13, 0, 4, 0]], "C": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5]], "D": [21, [4, 21, 4, 0, -1, -1, 4, 21, 11, 21, 14, 20, 16, 18, 17, 16, 18, 13, 18, 8, 17, 5, 16, 3, 14, 1, 11, 0, 4, 0]], "E": [19, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11, -1, -1, 4, 0, 17, 0]], "F": [18, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11]], "G": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 18, 8, -1, -1, 13, 8, 18, 8]], "H": [22, [4, 21, 4, 0, -1, -1, 18, 21, 18, 0, -1, -1, 4, 11, 18, 11]], "I": [8, [4, 21, 4, 0]], "J": [16, [12, 21, 12, 5, 11, 2, 10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7]], "K": [21, [4, 21, 4, 0, -1, -1, 18, 21, 4, 7, -1, -1, 9, 12, 18, 0]], "L": [17, [4, 21, 4, 0, -1, -1, 4, 0, 16, 0]], "M": [24, [4, 21, 4, 0, -1, -1, 4, 21, 12, 0, -1, -1, 20, 21, 12, 0, -1, -1, 20, 21, 20, 0]], "N": [22, [4, 21, 4, 0, -1, -1, 4, 21, 18, 0, -1, -1, 18, 21, 18, 0]], "O": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21]], "P": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 14, 17, 12, 16, 11, 13, 10, 4, 10]], "Q": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, -1, -1, 12, 4, 18, -2]], "R": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, 4, 11, -1, -1, 11, 11, 18, 0]], "S": [20, [17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]], "T": [16, [8, 21, 8, 0, -1, -1, 1, 21, 15, 21]], "U": [22, [4, 21, 4, 6, 5, 3, 7, 1, 10, 0, 12, 0, 15, 1, 17, 3, 18, 6, 18, 21]], "V": [18, [1, 21, 9, 0, -1, -1, 17, 21, 9, 0]], "W": [24, [2, 21, 7, 0, -1, -1, 12, 21, 7, 0, -1, -1, 12, 21, 17, 0, -1, -1, 22, 21, 17, 0]], "X": [20, [3, 21, 17, 0, -1, -1, 17, 21, 3, 0]], "Y": [18, [1, 21, 9, 11, 9, 0, -1, -1, 17, 21, 9, 11]], "Z": [20, [17, 21, 3, 0, -1, -1, 3, 21, 17, 21, -1, -1, 3, 0, 17, 0]], "[": [14, [4, 25, 4, -7, -1, -1, 5, 25, 5, -7, -1, -1, 4, 25, 11, 25, -1, -1, 4, -7, 11, -7]], "\\": [14, [0, 21, 14, -3]], "]": [14, [9, 25, 9, -7, -1, -1, 10, 25, 10, -7, -1, -1, 3, 25, 10, 25, -1, -1, 3, -7, 10, -7]], "^": [16, [6, 15, 8, 18, 10, 15, -1, -1, 3, 12, 8, 17, 13, 12, -1, -1, 8, 17, 8, 0]], "_": [16, [0, -2, 16, -2]], "`": [10, [6, 21, 5, 20, 4, 18, 4, 16, 5, 15, 6, 16, 5, 17]], "a": [19, [15, 14, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "b": [19, [4, 21, 4, 0, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]], "c": [18, [15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "d": [19, [15, 21, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "e": [18, [3, 8, 15, 8, 15, 10, 14, 12, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "f": [12, [10, 21, 8, 21, 6, 20, 5, 17, 5, 0, -1, -1, 2, 14, 9, 14]], "g": [19, [15, 14, 15, -2, 14, -5, 13, -6, 11, -7, 8, -7, 6, -6, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "h": [19, [4, 21, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]], "i": [8, [3, 21, 4, 20, 5, 21, 4, 22, 3, 21, -1, -1, 4, 14, 4, 0]], "j": [10, [5, 21, 6, 20, 7, 21, 6, 22, 5, 21, -1, -1, 6, 14, 6, -3, 5, -6, 3, -7, 1, -7]], "k": [17, [4, 21, 4, 0, -1, -1, 14, 14, 4, 4, -1, -1, 8, 8, 15, 0]], "l": [8, [4, 21, 4, 0]], "m": [30, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, 15, 10, 18, 13, 20, 14, 23, 14, 25, 13, 26, 10, 26, 0]], "n": [19, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]], "o": [19, [8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, 16, 6, 16, 8, 15, 11, 13, 13, 11, 14, 8, 14]], "p": [19, [4, 14, 4, -7, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]], "q": [19, [15, 14, 15, -7, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]], "r": [13, [4, 14, 4, 0, -1, -1, 4, 8, 5, 11, 7, 13, 9, 14, 12, 14]], "s": [17, [14, 11, 13, 13, 10, 14, 7, 14, 4, 13, 3, 11, 4, 9, 6, 8, 11, 7, 13, 6, 14, 4, 14, 3, 13, 1, 10, 0, 7, 0, 4, 1, 3, 3]], "t": [12, [5, 21, 5, 4, 6, 1, 8, 0, 10, 0, -1, -1, 2, 14, 9, 14]], "u": [19, [4, 14, 4, 4, 5, 1, 7, 0, 10, 0, 12, 1, 15, 4, -1, -1, 15, 14, 15, 0]], "v": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0]], "w": [22, [3, 14, 7, 0, -1, -1, 11, 14, 7, 0, -1, -1, 11, 14, 15, 0, -1, -1, 19, 14, 15, 0]], "x": [17, [3, 14, 14, 0, -1, -1, 14, 14, 3, 0]], "y": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0, 6, -4, 4, -6, 2, -7, 1, -7]], "z": [17, [14, 14, 3, 0, -1, -1, 3, 14, 14, 14, -1, -1, 3, 0, 14, 0]], "{": [14, [9, 25, 7, 24, 6, 23, 5, 21, 5, 19, 6, 17, 7, 16, 8, 14, 8, 12, 6, 10, -1, -1, 7, 24, 6, 22, 6, 20, 7, 18, 8, 17, 9, 15, 9, 13, 8, 11, 4, 9, 8, 7, 9, 5, 9, 3, 8, 1, 7, 0, 6, -2, 6, -4, 7, -6, -1, -1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, -1, 5, -3, 6, -5, 7, -6, 9, -7]], "|": [8, [4, 25, 4, -7]], "}": [14, [5, 25, 7, 24, 8, 23, 9, 21, 9, 19, 8, 17, 7, 16, 6, 14, 6, 12, 8, 10, -1, -1, 7, 24, 8, 22, 8, 20, 7, 18, 6, 17, 5, 15, 5, 13, 6, 11, 10, 9, 6, 7, 5, 5, 5, 3, 6, 1, 7, 0, 8, -2, 8, -4, 7, -6, -1, -1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, -1, 9, -3, 8, -5, 7, -6, 5, -7]], "~": [24, [3, 6, 3, 8, 4, 11, 6, 12, 8, 12, 10, 11, 14, 8, 16, 7, 18, 7, 20, 8, 21, 10, -1, -1, 3, 8, 4, 10, 6, 11, 8, 11, 10, 10, 14, 7, 16, 6, 18, 6, 20, 7, 21, 10, 21, 12]], }; module.exports = function textVertices(text, left, baseline, scale) { scale = scale || 1; var strokes = [], i, len, j, len2, glyph, data, x, y, prev; for (i = 0, len = text.length; i < len; i++) { glyph = simplex_font[text[i]]; if (!glyph) continue; prev = null; for (j = 0, len2 = glyph[1].length; j < len2; j += 2) { if (glyph[1][j] === -1 && glyph[1][j + 1] === -1) { prev = null; } else { x = left + glyph[1][j] * scale; y = baseline - glyph[1][j + 1] * scale; if (prev) { strokes.push(prev.x, prev.y, x, y); } prev = {x: x, y: y}; } } left += glyph[0] * scale; } return strokes; }; },{}],21:[function(require,module,exports){ /** * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV * @version 2.2.0 */ /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function(e){"use strict";var t={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t.exports={},define(function(){return t.exports})):t.exports=typeof window!="undefined"?window:e:t.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;if(!r)var r=Math.random;var i={};i.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=i);var s={};s.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},s.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},s.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},s.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},s.set=function(e,t,n){return e[0]=t,e[1]=n,e},s.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},s.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},s.sub=s.subtract,s.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},s.mul=s.multiply,s.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},s.div=s.divide,s.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},s.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},s.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},s.scaleAndAdd=function(e,t,n,r){return e[0]=t[0]+n[0]*r,e[1]=t[1]+n[1]*r,e},s.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},s.dist=s.distance,s.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},s.sqrDist=s.squaredDistance,s.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},s.len=s.length,s.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},s.sqrLen=s.squaredLength,s.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},s.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},s.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},s.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},s.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},s.random=function(e,t){t=t||1;var n=r()*2*Math.PI;return e[0]=Math.cos(n)*t,e[1]=Math.sin(n)*t,e},s.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},s.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},s.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},s.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},s.forEach=function(){var e=s.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},o.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},o.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},o.random=function(e,t){t=t||1;var n=r()*2*Math.PI,i=r()*2-1,s=Math.sqrt(1-i*i)*t;return e[0]=Math.cos(n)*s,e[1]=Math.sin(n)*s,e[2]=i*t,e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12],e[1]=n[1]*r+n[5]*i+n[9]*s+n[13],e[2]=n[2]*r+n[6]*i+n[10]*s+n[14],e},o.transformMat3=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=r*n[0]+i*n[3]+s*n[6],e[1]=r*n[1]+i*n[4]+s*n[7],e[2]=r*n[2]+i*n[5]+s*n[8],e},o.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=3),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(o=1/Math.sqrt(o),e[0]=t[0]*o,e[1]=t[1]*o,e[2]=t[2]*o,e[3]=t[3]*o),e},u.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},u.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e[3]=u+r*(n[3]-u),e},u.random=function(e,t){return t=t||1,e[0]=r(),e[1]=r(),e[2]=r(),e[3]=r(),u.normalize(e,e),u.scale(e,e,t),e},u.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12]*o,e[1]=n[1]*r+n[5]*i+n[9]*s+n[13]*o,e[2]=n[2]*r+n[6]*i+n[10]*s+n[14]*o,e[3]=n[3]*r+n[7]*i+n[11]*s+n[15]*o,e},u.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},u.forEach=function(){var e=u.create();return function(t,n,r,i,s,o){var u,a;n||(n=4),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u.999999?(r[0]=0,r[1]=0,r[2]=0,r[3]=1,r):(o.cross(e,i,s),r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=1+u,h.normalize(r,r))}}(),h.setAxes=function(){var e=l.create();return function(t,n,r,i){return e[0]=r[0],e[3]=r[1],e[6]=r[2],e[1]=i[0],e[4]=i[1],e[7]=i[2],e[2]=n[0],e[5]=n[1],e[8]=n[2],h.normalize(t,h.fromMat3(t,e))}}(),h.clone=u.clone,h.fromValues=u.fromValues,h.copy=u.copy,h.set=u.set,h.identity=function(e){return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},h.setAxisAngle=function(e,t,n){n*=.5;var r=Math.sin(n);return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=Math.cos(n),e},h.add=u.add,h.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*l+o*u+i*f-s*a,e[1]=i*l+o*a+s*u-r*f,e[2]=s*l+o*f+r*a-i*u,e[3]=o*l-r*u-i*a-s*f,e},h.mul=h.multiply,h.scale=u.scale,h.rotateX=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+o*u,e[1]=i*a+s*u,e[2]=s*a-i*u,e[3]=o*a-r*u,e},h.rotateY=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a-s*u,e[1]=i*a+o*u,e[2]=s*a+r*u,e[3]=o*a-i*u,e},h.rotateZ=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=i*a-r*u,e[2]=s*a+o*u,e[3]=o*a-s*u,e},h.calculateW=function(e,t){var n=t[0],r=t[1],i=t[2];return e[0]=n,e[1]=r,e[2]=i,e[3]=-Math.sqrt(Math.abs(1-n*n-r*r-i*i)),e},h.dot=u.dot,h.lerp=u.lerp,h.slerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3],a=n[0],f=n[1],l=n[2],c=n[3],h,p,d,v,m;return p=i*a+s*f+o*l+u*c,p<0&&(p=-p,a=-a,f=-f,l=-l,c=-c),1-p>1e-6?(h=Math.acos(p),d=Math.sin(h),v=Math.sin((1-r)*h)/d,m=Math.sin(r*h)/d):(v=1-r,m=r),e[0]=v*i+m*a,e[1]=v*s+m*f,e[2]=v*o+m*l,e[3]=v*u+m*c,e},h.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s,u=o?1/o:0;return e[0]=-n*u,e[1]=-r*u,e[2]=-i*u,e[3]=s*u,e},h.conjugate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=t[3],e},h.length=u.length,h.len=h.length,h.squaredLength=u.squaredLength,h.sqrLen=h.squaredLength,h.normalize=u.normalize,h.fromMat3=function(){var e=typeof Int8Array!="undefined"?new Int8Array([1,2,0]):[1,2,0];return function(t,n){var r=n[0]+n[4]+n[8],i;if(r>0)i=Math.sqrt(r+1),t[3]=.5*i,i=.5/i,t[0]=(n[7]-n[5])*i,t[1]=(n[2]-n[6])*i,t[2]=(n[3]-n[1])*i;else{var s=0;n[4]>n[0]&&(s=1),n[8]>n[s*3+s]&&(s=2);var o=e[s],u=e[o];i=Math.sqrt(n[s*3+s]-n[o*3+o]-n[u*3+u]+1),t[s]=.5*i,i=.5/i,t[3]=(n[u*3+o]-n[o*3+u])*i,t[o]=(n[o*3+s]+n[s*3+o])*i,t[u]=(n[u*3+s]+n[s*3+u])*i}return t}}(),h.str=function(e){return"quat("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.quat=h)}(t.exports)})(this); },{}],22:[function(require,module,exports){ 'use strict'; if (typeof window === 'undefined') { new (require('./source/worker.js'))(self); } else { // jshint -W079 var mapboxgl = module.exports = window.mapboxgl = {}; mapboxgl.Map = require('./ui/map.js'); mapboxgl.Navigation = require('./ui/control/navigation.js'); mapboxgl.Attribution = require('./ui/control/attribution.js'); mapboxgl.Source = require('./source/source'); mapboxgl.GeoJSONSource = require('./source/geojsonsource'); mapboxgl.VideoSource = require('./source/videosource'); mapboxgl.Style = require('./style/style.js'); mapboxgl.LatLng = require('./geo/latlng.js'); mapboxgl.LatLngBounds = require('./geo/latlngbounds.js'); mapboxgl.Point = require('point-geometry'); mapboxgl.Evented = require('./util/evented.js'); mapboxgl.util = require('./util/util.js'); var browser = require('./util/browser.js'); mapboxgl.util.supported = browser.supported; var ajax = require('./util/ajax.js'); mapboxgl.util.getJSON = ajax.getJSON; mapboxgl.util.getArrayBuffer = ajax.getArrayBuffer; var config = require('./util/config.js'); mapboxgl.config = config; Object.defineProperty(mapboxgl, 'accessToken', { get: function() { return config.ACCESS_TOKEN; }, set: function(token) { config.ACCESS_TOKEN = token; } }); } },{"./geo/latlng.js":17,"./geo/latlngbounds.js":18,"./source/geojsonsource":36,"./source/source":40,"./source/videosource":45,"./source/worker.js":46,"./style/style.js":53,"./ui/control/attribution.js":67,"./ui/control/navigation.js":69,"./ui/map.js":74,"./util/ajax.js":76,"./util/browser.js":77,"./util/config.js":80,"./util/evented.js":82,"./util/util.js":87,"point-geometry":98}],23:[function(require,module,exports){ 'use strict'; var mat3 = require('../lib/glmatrix.js').mat3; module.exports = drawBackground; function drawBackground(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite) { var color = layerStyle['background-color']; var image = layerStyle['background-image']; var opacity = layerStyle['background-opacity'] || 1; var shader; if (image) { // Draw texture fill var imagePos = imageSprite.getPosition(image, true); if (!imagePos) return; shader = painter.patternShader; gl.switchShader(shader, posMatrix); gl.uniform1i(shader.u_image, 0); gl.uniform2fv(shader.u_pattern_tl, imagePos.tl); gl.uniform2fv(shader.u_pattern_br, imagePos.br); gl.uniform1f(shader.u_mix, painter.transform.zoomFraction); gl.uniform1f(shader.u_opacity, opacity); var transform = painter.transform; var size = imagePos.size; var center = transform.locationCoordinate(transform.center); var scale = 1 / Math.pow(2, transform.zoomFraction); var matrix = mat3.create(); mat3.scale(matrix, matrix, [1 / size[0], 1 / size[1], 1]); mat3.translate(matrix, matrix, [ (center.column * transform.tileSize) % size[0], (center.row * transform.tileSize) % size[1], 0 ]); mat3.rotate(matrix, matrix, -transform.angle); mat3.scale(matrix, matrix, [ scale * transform.width / 2, -scale * transform.height / 2, 1 ]); gl.uniformMatrix3fv(shader.u_patternmatrix, false, matrix); imageSprite.bind(gl, true); } else { // Draw filling rectangle. shader = painter.fillShader; gl.switchShader(shader, params.padded || posMatrix); gl.uniform4fv(shader.u_color, color); } gl.disable(gl.STENCIL_TEST); gl.bindBuffer(gl.ARRAY_BUFFER, painter.backgroundBuffer); gl.vertexAttribPointer(shader.a_pos, painter.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.backgroundBuffer.itemCount); gl.enable(gl.STENCIL_TEST); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } },{"../lib/glmatrix.js":21}],24:[function(require,module,exports){ 'use strict'; module.exports = drawComposited; function drawComposited (gl, painter, buckets, layerStyle, params, style, layer) { var texture = painter.namedRenderTextures[layer.id]; if (!texture) return console.warn('missing render texture ' + layer.id); gl.disable(gl.STENCIL_TEST); gl.stencilMask(0x00); gl.switchShader(painter.compositeShader, painter.identityMatrix); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture); gl.uniform1i(painter.compositeShader.u_image, 0); gl.uniform1f(painter.compositeShader.u_opacity, layerStyle['composite-opacity']); gl.bindBuffer(gl.ARRAY_BUFFER, painter.backgroundBuffer); gl.vertexAttribPointer(painter.compositeShader.a_pos, 2, gl.SHORT, false, 0, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); gl.enable(gl.STENCIL_TEST); painter.freeRenderTexture(layer.id); } },{}],25:[function(require,module,exports){ 'use strict'; var textVertices = require('../lib/debugtext.js'); var browser = require('../util/browser.js'); module.exports = drawDebug; function drawDebug(gl, painter, tile, params) { // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.switchShader(painter.debugShader, painter.tile.posMatrix, painter.tile.exMatrix); // draw bounding rectangle gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugBuffer); gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugBuffer.itemSize, gl.SHORT, false, 0, 0); gl.uniform4f(painter.debugShader.u_color, 1, 0, 0, 1); gl.lineWidth(4); gl.drawArrays(gl.LINE_STRIP, 0, painter.debugBuffer.itemCount); // draw tile coordinate var coord = params.z + '/' + params.x + '/' + params.y; var vertices = textVertices(coord, 50, 200, 5); gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugTextBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array(vertices), gl.STREAM_DRAW); gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugTextBuffer.itemSize, gl.SHORT, false, 0, 0); gl.lineWidth(8 * browser.devicePixelRatio); gl.uniform4f(painter.debugShader.u_color, 1, 1, 1, 1); gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize); gl.lineWidth(2 * browser.devicePixelRatio); gl.uniform4f(painter.debugShader.u_color, 0, 0, 0, 1); gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize); // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); } },{"../lib/debugtext.js":20,"../util/browser.js":77}],26:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser.js'); var mat3 = require('../lib/glmatrix.js').mat3; module.exports = drawFill; function drawFill(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite) { var translatedPosMatrix = painter.translateMatrix(posMatrix, params.z, layerStyle['fill-translate'], layerStyle['fill-translate-anchor']); var color = layerStyle['fill-color']; var vertex, elements, group, count; // Draw the stencil mask. // We're only drawing to the first seven bits (== support a maximum of // 127 overlapping polygons in one place before we get rendering errors). gl.stencilMask(0x3F); gl.clear(gl.STENCIL_BUFFER_BIT); // Draw front facing triangles. Wherever the 0x80 bit is 1, we are // increasing the lower 7 bits by one if the triangle is a front-facing // triangle. This means that all visible polygons should be in CCW // orientation, while all holes (see below) are in CW orientation. gl.stencilFunc(gl.NOTEQUAL, 0x80, 0x80); // When we do a nonzero fill, we count the number of times a pixel is // covered by a counterclockwise polygon, and subtract the number of // times it is "uncovered" by a clockwise polygon. gl.stencilOpSeparate(gl.FRONT, gl.INCR_WRAP, gl.KEEP, gl.KEEP); gl.stencilOpSeparate(gl.BACK, gl.DECR_WRAP, gl.KEEP, gl.KEEP); // When drawing a shape, we first draw all shapes to the stencil buffer // and incrementing all areas where polygons are gl.colorMask(false, false, false, false); // Draw the actual triangle fan into the stencil buffer. gl.switchShader(painter.fillShader, translatedPosMatrix, painter.tile.exMatrix); // Draw all buffers vertex = bucket.buffers.fillVertex; vertex.bind(gl); elements = bucket.buffers.fillElement; elements.bind(gl); var offset, elementOffset; for (var i = 0; i < bucket.elementGroups.groups.length; i++) { group = bucket.elementGroups.groups[i]; offset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(painter.fillShader.a_pos, 2, gl.SHORT, false, 4, offset + 0); count = group.elementLength * 3; elementOffset = group.elementStartIndex * elements.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } // Now that we have the stencil mask in the stencil buffer, we can start // writing to the color buffer. gl.colorMask(true, true, true, true); // From now on, we don't want to update the stencil buffer anymore. gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); gl.stencilMask(0x0); var strokeColor = layerStyle['fill-outline-color']; // Because we're drawing top-to-bottom, and we update the stencil mask // below, we have to draw the outline first (!) if (layerStyle['fill-antialias'] === true && params.antialiasing && !(layerStyle['fill-image'] && !strokeColor)) { gl.switchShader(painter.outlineShader, translatedPosMatrix, painter.tile.exMatrix); gl.lineWidth(2 * browser.devicePixelRatio); if (strokeColor) { // If we defined a different color for the fill outline, we are // going to ignore the bits in 0x3F and just care about the global // clipping mask. gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } else { // Otherwise, we only want to draw the antialiased parts that are // *outside* the current shape. This is important in case the fill // or stroke color is translucent. If we wouldn't clip to outside // the current shape, some pixels from the outline stroke overlapped // the (non-antialiased) fill. gl.stencilFunc(gl.EQUAL, 0x80, 0xBF); } gl.uniform2f(painter.outlineShader.u_world, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.uniform4fv(painter.outlineShader.u_color, strokeColor ? strokeColor : color); // Draw all buffers vertex = bucket.buffers.fillVertex; elements = bucket.buffers.outlineElement; elements.bind(gl); for (var k = 0; k < bucket.elementGroups.groups.length; k++) { group = bucket.elementGroups.groups[k]; offset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(painter.outlineShader.a_pos, 2, gl.SHORT, false, 4, offset + 0); count = group.secondElementLength * 2; elementOffset = group.secondElementStartIndex * elements.itemSize; gl.drawElements(gl.LINES, count, gl.UNSIGNED_SHORT, elementOffset); } } var image = layerStyle['fill-image']; var opacity = layerStyle['fill-opacity'] || 1; var shader; if (image) { // Draw texture fill var imagePos = imageSprite.getPosition(image, true); if (!imagePos) return; shader = painter.patternShader; gl.switchShader(shader, posMatrix); gl.uniform1i(shader.u_image, 0); gl.uniform2fv(shader.u_pattern_tl, imagePos.tl); gl.uniform2fv(shader.u_pattern_br, imagePos.br); gl.uniform1f(shader.u_mix, painter.transform.zoomFraction); gl.uniform1f(shader.u_opacity, opacity); var factor = 8 / Math.pow(2, painter.transform.tileZoom - params.z); var matrix = mat3.create(); mat3.scale(matrix, matrix, [ 1 / (imagePos.size[0] * factor), 1 / (imagePos.size[1] * factor), 1, 1 ]); gl.uniformMatrix3fv(shader.u_patternmatrix, false, matrix); imageSprite.bind(gl, true); } else { // Draw filling rectangle. shader = painter.fillShader; gl.switchShader(shader, params.padded || posMatrix); gl.uniform4fv(shader.u_color, color); } // Only draw regions that we marked gl.stencilFunc(gl.NOTEQUAL, 0x0, 0x3F); gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer); gl.vertexAttribPointer(shader.a_pos, painter.tileExtentBuffer.itemSize, gl.SHORT, false, 0, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.tileExtentBuffer.itemCount); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); } },{"../lib/glmatrix.js":21,"../util/browser.js":77}],27:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser.js'); module.exports = function drawLine(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite) { posMatrix = painter.translateMatrix(posMatrix, params.z, layerStyle['line-translate'], layerStyle['line-translate-anchor']); // don't draw zero-width lines if (layerStyle['line-width'] <= 0) return; var gamma = 1; var antialiasing = gamma / browser.devicePixelRatio; var lineOffset = layerStyle['line-offset'] / 2; var inset = Math.max(-1, lineOffset - layerStyle['line-width'] / 2 - antialiasing / 2) + 1; var outset = lineOffset + layerStyle['line-width'] / 2 + antialiasing / 2; var imagePos = layerStyle['line-image'] && imageSprite.getPosition(layerStyle['line-image']); var shader; if (imagePos) { var factor = 8 / Math.pow(2, painter.transform.tileZoom - params.z); imageSprite.bind(gl, true); //factor = Math.pow(2, 4 - painter.transform.tileZoom + params.z); shader = painter.linepatternShader; gl.switchShader(shader, posMatrix, painter.tile.exMatrix); gl.uniform2fv(shader.u_pattern_size, [imagePos.size[0] * factor, imagePos.size[1] ]); gl.uniform2fv(shader.u_pattern_tl, imagePos.tl); gl.uniform2fv(shader.u_pattern_br, imagePos.br); gl.uniform1f(shader.u_fade, painter.transform.zoomFraction); } else { shader = painter.lineShader; gl.switchShader(shader, posMatrix, painter.tile.exMatrix); gl.uniform2fv(shader.u_dasharray, layerStyle['line-dasharray']); gl.uniform4fv(shader.u_color, layerStyle['line-color']); } var tilePixelRatio = painter.transform.scale / (1 << params.z) / 8; gl.uniform2fv(shader.u_linewidth, [ outset, inset ]); gl.uniform1f(shader.u_ratio, tilePixelRatio); gl.uniform1f(shader.u_blur, layerStyle['line-blur'] + antialiasing); var vertex = bucket.buffers.lineVertex; vertex.bind(gl); var element = bucket.buffers.lineElement; element.bind(gl); var groups = bucket.elementGroups.groups; for (var i = 0; i < groups.length; i++) { var group = groups[i]; var offset = group.vertexStartIndex * vertex.itemSize; gl.vertexAttribPointer(shader.a_pos, 4, gl.SHORT, false, 8, offset + 0); gl.vertexAttribPointer(shader.a_extrude, 2, gl.BYTE, false, 8, offset + 6); gl.vertexAttribPointer(shader.a_linesofar, 2, gl.SHORT, false, 8, offset + 4); var count = group.elementLength * 3; var elementOffset = group.elementStartIndex * element.itemSize; gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset); } }; },{"../util/browser.js":77}],28:[function(require,module,exports){ 'use strict'; var TileCoord = require('../source/tilecoord.js'); var PrerenderedTexture = require('./prerendered.js'); var mat4 = require('../lib/glmatrix.js').mat4; module.exports = drawRaster; function drawRaster(gl, painter, bucket, layerStyle, params, style, layer, tile) { if (layer && layer.layers) { if (!bucket.prerendered) { bucket.prerendered = new PrerenderedTexture(gl, bucket.info, painter); bucket.prerendered.bindFramebuffer(); gl.clearStencil(0x80); gl.stencilMask(0xFF); gl.clear(gl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT); gl.stencilMask(0x00); gl.viewport(0, 0, bucket.prerendered.size, bucket.prerendered.size); var buffer = bucket.prerendered.buffer * 4096; var matrix = mat4.create(); mat4.ortho(matrix, -buffer, 4096 + buffer, -4096 - buffer, buffer, 0, 1); mat4.translate(matrix, matrix, [0, -4096, 0]); params.padded = mat4.create(); mat4.ortho(params.padded, 0, 4096, -4096, 0, 0, 1); mat4.translate(params.padded, params.padded, [0, -4096, 0]); painter.draw(tile, style, layer.layers, params, matrix); delete params.padded; if (bucket.info['raster-blur'] > 0) { bucket.prerendered.blur(painter, bucket.info['raster-blur']); } bucket.prerendered.unbindFramebuffer(); gl.viewport(0, 0, painter.width, painter.height); } } var texture = bucket.tile ? bucket.tile : bucket.prerendered; gl.disable(gl.STENCIL_TEST); var shader = painter.rasterShader; gl.switchShader(shader, painter.tile.posMatrix, painter.tile.exMatrix); // color parameters gl.uniform1f(shader.u_brightness_low, layerStyle['raster-brightness'][0]); gl.uniform1f(shader.u_brightness_high, layerStyle['raster-brightness'][1]); gl.uniform1f(shader.u_saturation_factor, saturationFactor(layerStyle['raster-saturation'])); gl.uniform1f(shader.u_contrast_factor, contrastFactor(layerStyle['raster-contrast'])); gl.uniform3fv(shader.u_spin_weights, spinWeights(layerStyle['raster-hue-rotate'])); var parentTile, opacities; if (layer && layer.layers) { parentTile = null; opacities = [layerStyle['raster-opacity'], 0]; } else { parentTile = findParent(texture); opacities = getOpacities(texture, parentTile); } var parentScaleBy, parentTL; gl.activeTexture(gl.TEXTURE0); texture.bind(gl); if (parentTile) { gl.activeTexture(gl.TEXTURE1); parentTile.bind(gl); var tilePos = TileCoord.fromID(texture.id); var parentPos = parentTile && TileCoord.fromID(parentTile.id); parentScaleBy = Math.pow(2, parentPos.z - tilePos.z); parentTL = [tilePos.x * parentScaleBy % 1, tilePos.y * parentScaleBy % 1]; } else { opacities[1] = 0; } var bufferScale = bucket.prerendered ? (4096 * (1 + 2 * bucket.prerendered.buffer)) / 4096 : 1; // cross-fade parameters gl.uniform2fv(shader.u_tl_parent, parentTL || [0, 0]); gl.uniform1f(shader.u_scale_parent, parentScaleBy || 1); gl.uniform1f(shader.u_buffer_scale, bufferScale); gl.uniform1f(shader.u_opacity0, opacities[0]); gl.uniform1f(shader.u_opacity1, opacities[1]); gl.uniform1i(shader.u_image0, 0); gl.uniform1i(shader.u_image1, 1); gl.bindBuffer(gl.ARRAY_BUFFER, texture.boundsBuffer || painter.tileExtentBuffer); gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, 0); gl.vertexAttribPointer(shader.a_texture_pos, 2, gl.SHORT, false, 8, 4); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); gl.enable(gl.STENCIL_TEST); } function findParent(tile) { var source = tile.source; if (!source) return; var parentTiles = {}; source._findLoadedParent(tile.id, source.options.minZoom, parentTiles); return source.tiles[Object.keys(parentTiles)[0]]; } function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); } function spinWeights(angle) { angle *= Math.PI / 180; var s = Math.sin(angle); var c = Math.cos(angle); return [ (2 * c + 1) / 3, (-Math.sqrt(3) * s - c + 1) / 3, (Math.sqrt(3) * s - c + 1) / 3 ]; } function contrastFactor(contrast) { return contrast > 0 ? 1 / (1 - contrast) : 1 + contrast; } function saturationFactor(saturation) { return saturation > 0 ? 1 - 1 / (1.001 - saturation) : -saturation; } function getOpacities(tile, parentTile) { if (!tile.source) return [1, 0]; var now = new Date().getTime(); var fadeDuration = tile.source.map.style.rasterFadeDuration; var sinceTile = (now - tile.timeAdded) / fadeDuration; var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1; var tilePos = TileCoord.fromID(tile.id); var parentPos = parentTile && TileCoord.fromID(parentTile.id); var idealZ = tile.source._coveringZoomLevel(tile.source._getZoom()); var parentFurther = parentTile ? Math.abs(parentPos.z - idealZ) > Math.abs(tilePos.z - idealZ) : false; var opacity = []; if (!parentTile || parentFurther) { // if no parent or parent is older opacity[0] = clamp(sinceTile, 0, 1); opacity[1] = 1 - opacity[0]; } else { // parent is younger, zooming out opacity[0] = clamp(1 - sinceParent, 0, 1); opacity[1] = 1 - opacity[0]; } return opacity; } },{"../lib/glmatrix.js":21,"../source/tilecoord.js":42,"./prerendered.js":34}],29:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser.js'); var mat4 = require('../lib/glmatrix.js').mat4; module.exports = drawSymbols; function drawSymbols(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite) { gl.disable(gl.STENCIL_TEST); if (bucket.elementGroups.text.groups.length) { drawSymbol(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, 'text'); } if (bucket.elementGroups.icon.groups.length) { drawSymbol(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, 'icon'); } gl.enable(gl.STENCIL_TEST); } var defaultSizes = { icon: 1, text: 24 }; function drawSymbol(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, prefix) { posMatrix = painter.translateMatrix(posMatrix, params.z, layerStyle[prefix + '-translate'], layerStyle[prefix + '-translate-anchor']); var info = bucket.info; var exMatrix = mat4.clone(painter.projectionMatrix); var alignedWithMap = info[prefix + '-rotation-alignment'] === 'map'; var angleOffset = (alignedWithMap ? painter.transform.angle : 0); if (angleOffset) { mat4.rotateZ(exMatrix, exMatrix, angleOffset); } // If layerStyle.size > info[prefix + '-max-size'] then labels may collide var fontSize = layerStyle[prefix + '-size'] || info[prefix + '-max-size']; var fontScale = fontSize / defaultSizes[prefix]; mat4.scale(exMatrix, exMatrix, [ fontScale, fontScale, 1 ]); var text = prefix === 'text'; var sdf = text || bucket.elementGroups.sdfIcons; var shader, buffer, texsize; if (!text && !imageSprite.loaded()) return; gl.activeTexture(gl.TEXTURE0); if (sdf) { shader = painter.sdfShader; } else { shader = painter.iconShader; } if (text) { painter.glyphAtlas.updateTexture(gl); buffer = bucket.buffers.glyphVertex; texsize = [painter.glyphAtlas.width / 4, painter.glyphAtlas.height / 4]; } else { imageSprite.bind(gl, alignedWithMap || params.rotating || params.zooming || fontScale != 1 || sdf); buffer = bucket.buffers.iconVertex; texsize = [imageSprite.img.width, imageSprite.img.height]; } gl.switchShader(shader, posMatrix, exMatrix); gl.uniform1i(shader.u_texture, 0); gl.uniform2fv(shader.u_texsize, texsize); buffer.bind(gl); var ubyte = gl.UNSIGNED_BYTE; var stride = text ? 16 : 20; gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, 0); gl.vertexAttribPointer(shader.a_offset, 2, gl.SHORT, false, stride, 4); gl.vertexAttribPointer(shader.a_labelminzoom, 1, ubyte, false, stride, 8); gl.vertexAttribPointer(shader.a_minzoom, 1, ubyte, false, stride, 9); gl.vertexAttribPointer(shader.a_maxzoom, 1, ubyte, false, stride, 10); gl.vertexAttribPointer(shader.a_angle, 1, ubyte, false, stride, 11); gl.vertexAttribPointer(shader.a_rangeend, 1, ubyte, false, stride, 12); gl.vertexAttribPointer(shader.a_rangestart, 1, ubyte, false, stride, 13); if (text) { gl.vertexAttribPointer(shader.a_tex, 2, ubyte, false, stride, 14); } else { gl.vertexAttribPointer(shader.a_tex, 2, gl.SHORT, false, stride, 16); } // Convert the -pi..pi to an int8 range. var angle = Math.round((painter.transform.angle) / Math.PI * 128); // adjust min/max zooms for variable font sies var zoomAdjust = Math.log(fontSize / info[prefix + '-max-size']) / Math.LN2 || 0; var flip = alignedWithMap && info[prefix + '-keep-upright']; gl.uniform1f(shader.u_flip, flip ? 1 : 0); gl.uniform1f(shader.u_angle, (angle + 256) % 256); gl.uniform1f(shader.u_zoom, (painter.transform.zoom - zoomAdjust) * 10); // current zoom level var f = painter.frameHistory.getFadeProperties(300); gl.uniform1f(shader.u_fadedist, f.fadedist * 10); gl.uniform1f(shader.u_minfadezoom, Math.floor(f.minfadezoom * 10)); gl.uniform1f(shader.u_maxfadezoom, Math.floor(f.maxfadezoom * 10)); gl.uniform1f(shader.u_fadezoom, (painter.transform.zoom + f.bump) * 10); if (!sdf) gl.uniform1f(shader.u_opacity, layerStyle['icon-opacity']); var sdfFontSize = text ? 24 : 1; var sdfPx = 8; var blurOffset = 1.19; var haloOffset = 6; if (sdf) { gl.uniform1f(shader.u_gamma, 0.105 * sdfFontSize / fontSize / browser.devicePixelRatio); gl.uniform4fv(shader.u_color, layerStyle[prefix + '-color']); gl.uniform1f(shader.u_buffer, (256 - 64) / 256); } var begin = bucket.elementGroups[prefix].groups[0].vertexStartIndex, len = bucket.elementGroups[prefix].groups[0].vertexLength; gl.drawArrays(gl.TRIANGLES, begin, len); if (sdf && layerStyle[prefix + '-halo-color']) { // Draw halo underneath the text. gl.uniform1f(shader.u_gamma, (layerStyle[prefix + '-halo-blur'] * blurOffset / (fontSize / sdfFontSize) / sdfPx) + (0.105 * sdfFontSize / fontSize) / browser.devicePixelRatio); gl.uniform4fv(shader.u_color, layerStyle[prefix + '-halo-color']); gl.uniform1f(shader.u_buffer, (haloOffset - layerStyle[prefix + '-halo-width'] / (fontSize / sdfFontSize)) / sdfPx); gl.drawArrays(gl.TRIANGLES, begin, len); } } },{"../lib/glmatrix.js":21,"../util/browser.js":77}],30:[function(require,module,exports){ 'use strict'; var browser = require('../util/browser.js'); var mat4 = require('../lib/glmatrix.js').mat4; module.exports = drawVertices; function drawVertices(gl, painter, bucket) { // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.switchShader(painter.dotShader, painter.tile.posMatrix, painter.tile.exMatrix); // // Draw debug points. gl.uniform1f(painter.dotShader.u_size, 4 * browser.devicePixelRatio); gl.uniform1f(painter.dotShader.u_blur, 0.25); gl.uniform4fv(painter.dotShader.u_color, [0.25, 0, 0, 0.25]); // Draw the actual triangle fan into the stencil buffer. var vertex, groups, group, begin, count; // Draw all buffers if (bucket.info.fill) { vertex = bucket.buffers.fillVertex; vertex.bind(gl); groups = bucket.elementGroups.groups; for (var i = 0; i < groups.length; i++) { group = groups[i]; begin = group.vertexStartIndex; count = group.vertexLength; gl.vertexAttribPointer(painter.dotShader.a_pos, 2, gl.SHORT, false, 0, 0); gl.drawArrays(gl.POINTS, begin, count); } } var newPosMatrix = mat4.clone(painter.tile.posMatrix); mat4.scale(newPosMatrix, newPosMatrix, [0.5, 0.5, 1]); gl.switchShader(painter.dotShader, newPosMatrix, painter.tile.exMatrix); // Draw all line buffers if (bucket.info.line) { vertex = bucket.buffers.lineVertex; vertex.bind(gl); groups = bucket.elementGroups.groups; for (var k = 0; k < groups.length; k++) { group = groups[k]; begin = group.vertexStartIndex; count = group.vertexLength; gl.vertexAttribPointer(painter.dotShader.a_pos, 2, gl.SHORT, false, 0, 0); gl.drawArrays(gl.POINTS, begin, count); } } // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); } },{"../lib/glmatrix.js":21,"../util/browser.js":77}],31:[function(require,module,exports){ 'use strict'; module.exports = FrameHistory; function FrameHistory() { } FrameHistory.prototype.getFadeProperties = function(duration) { if (duration === undefined) duration = 300; var currentTime = (new Date()).getTime(); // Remove frames until only one is outside the duration, or until there are only three while (frameHistory.length > 3 && frameHistory[1].time + duration < currentTime) { frameHistory.shift(); } if (frameHistory[1].time + duration < currentTime) { frameHistory[0].z = frameHistory[1].z; } var frameLen = frameHistory.length; if (frameLen < 3) console.warn('there should never be less than three frames in the history'); // Find the range of zoom levels we want to fade between var startingZ = frameHistory[0].z, lastFrame = frameHistory[frameLen - 1], endingZ = lastFrame.z, lowZ = Math.min(startingZ, endingZ), highZ = Math.max(startingZ, endingZ); // Calculate the speed of zooming, and how far it would zoom in terms of zoom levels in one duration var zoomDiff = lastFrame.z - frameHistory[1].z, timeDiff = lastFrame.time - frameHistory[1].time; var fadedist = zoomDiff / (timeDiff / duration); if (isNaN(fadedist)) console.warn('fadedist should never be NaN'); // At end of a zoom when the zoom stops changing continue pretending to zoom at that speed // bump is how much farther it would have been if it had continued zooming at the same rate var bump = (currentTime - lastFrame.time) / duration * fadedist; return { fadedist: fadedist, minfadezoom: lowZ, maxfadezoom: highZ, bump: bump }; }; // Store previous render times var frameHistory = []; // Record frame history that will be used to calculate fading params FrameHistory.prototype.record = function(zoom) { var currentTime = (new Date()).getTime(); // first frame ever if (!frameHistory.length) { frameHistory.push({time: 0, z: zoom }, {time: 0, z: zoom }); } if (frameHistory.length === 2 || frameHistory[frameHistory.length - 1].z !== zoom) { frameHistory.push({ time: currentTime, z: zoom }); } }; },{}],32:[function(require,module,exports){ 'use strict'; var shaders = require('./shaders.js'); exports.extend = function(context) { context.getShader = function(name, type) { var kind = type == this.FRAGMENT_SHADER ? 'fragment' : 'vertex'; if (!shaders[name] || !shaders[name][kind]) { throw new Error("Could not find shader " + name); } var shader = this.createShader(type); this.shaderSource(shader, shaders[name][kind]); this.compileShader(shader); if (!this.getShaderParameter(shader, this.COMPILE_STATUS)) { throw new Error(this.getShaderInfoLog(shader)); } return shader; }; context.initializeShader = function(name, attributes, uniforms) { var shader = { program: this.createProgram(), fragment: this.getShader(name, this.FRAGMENT_SHADER), vertex: this.getShader(name, this.VERTEX_SHADER), attributes: [] }; this.attachShader(shader.program, shader.vertex); this.attachShader(shader.program, shader.fragment); this.linkProgram(shader.program); if (!this.getProgramParameter(shader.program, this.LINK_STATUS)) { console.error(this.getProgramInfoLog(shader.program)); alert("Could not initialize shader " + name); } else { for (var i = 0; i < attributes.length; i++) { shader[attributes[i]] = this.getAttribLocation(shader.program, attributes[i]); shader.attributes.push(shader[attributes[i]]); } for (var k = 0; k < uniforms.length; k++) { shader[uniforms[k]] = this.getUniformLocation(shader.program, uniforms[k]); } } return shader; }; // Switches to a different shader program. context.switchShader = function(shader, posMatrix, exMatrix) { if (!posMatrix) { console.trace('posMatrix does not have required argument'); } if (this.currentShader !== shader) { this.useProgram(shader.program); // Disable all attributes from the existing shader that aren't used in // the new shader. Note: attribute indices are *not* program specific! var enabled = this.currentShader ? this.currentShader.attributes : []; var required = shader.attributes; for (var i = 0; i < enabled.length; i++) { if (required.indexOf(enabled[i]) < 0) { this.disableVertexAttribArray(enabled[i]); } } // Enable all attributes for the new shader. for (var j = 0; j < required.length; j++) { if (enabled.indexOf(required[j]) < 0) { this.enableVertexAttribArray(required[j]); } } this.currentShader = shader; } // Update the matrices if necessary. Note: This relies on object identity! // This means changing the matrix values without the actual matrix object // will FAIL to update the matrix properly. if (shader.posMatrix !== posMatrix) { this.uniformMatrix4fv(shader.u_posmatrix, false, posMatrix); shader.posMatrix = posMatrix; } if (exMatrix && shader.exMatrix !== exMatrix && shader.u_exmatrix) { this.uniformMatrix4fv(shader.u_exmatrix, false, exMatrix); shader.exMatrix = exMatrix; } }; return context; }; },{"./shaders.js":35}],33:[function(require,module,exports){ 'use strict'; var glutil = require('./glutil.js'); var browser = require('../util/browser.js'); var GlyphAtlas = require('../symbol/glyphatlas.js'); var glmatrix = require('../lib/glmatrix.js'); var FrameHistory = require('./framehistory.js'); var mat4 = glmatrix.mat4; var drawSymbol = require('./drawsymbol.js'); var drawLine = require('./drawline.js'); var drawFill = require('./drawfill.js'); var drawRaster = require('./drawraster.js'); var drawDebug = require('./drawdebug.js'); var drawBackground = require('./drawbackground.js'); var drawComposited = require('./drawcomposited.js'); var drawVertices = require('./drawvertices.js'); /* * Initialize a new painter object. * * @param {Canvas} gl an experimental-webgl drawing context */ module.exports = GLPainter; function GLPainter(gl, transform) { this.gl = glutil.extend(gl); this.transform = transform; this.framebufferObject = null; this.renderTextures = []; this.namedRenderTextures = {}; this.reusableTextures = {}; this.preFbos = {}; this.tileExtent = 4096; this.frameHistory = new FrameHistory(); this.setup(); } /* * Update the GL viewport, projection matrix, and transforms to compensate * for a new width and height value. */ GLPainter.prototype.resize = function(width, height) { var gl = this.gl; // Initialize projection matrix this.projectionMatrix = mat4.create(); mat4.ortho(this.projectionMatrix, 0, width, height, 0, 0, -1); this.width = width * browser.devicePixelRatio; this.height = height * browser.devicePixelRatio; gl.viewport(0, 0, this.width, this.height); for (var i = this.renderTextures.length - 1; i >= 0; i--) { gl.deleteTexture(this.renderTextures.pop()); } if (this.stencilBuffer) { gl.deleteRenderbuffer(this.stencilBuffer); delete this.stencilBuffer; } }; GLPainter.prototype.setup = function() { var gl = this.gl; gl.verbose = true; // We are blending the new pixels *behind* the existing pixels. That way we can // draw front-to-back and use then stencil buffer to cull opaque pixels early. gl.enable(gl.BLEND); gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); gl.enable(gl.STENCIL_TEST); this.glyphAtlas = new GlyphAtlas(1024, 1024); // this.glyphAtlas.debug = true; this.glyphAtlas.bind(gl); // Initialize shaders this.debugShader = gl.initializeShader('debug', ['a_pos'], ['u_posmatrix', 'u_pointsize', 'u_color']); this.compositeShader = gl.initializeShader('composite', ['a_pos'], ['u_posmatrix', 'u_opacity']); this.gaussianShader = gl.initializeShader('gaussian', ['a_pos'], ['u_posmatrix', 'u_opacity', 'u_image', 'u_offset']); this.rasterShader = gl.initializeShader('raster', ['a_pos', 'a_texture_pos'], ['u_posmatrix', 'u_brightness_low', 'u_brightness_high', 'u_saturation_factor', 'u_spin_weights', 'u_contrast_factor', 'u_opacity0', 'u_opacity1', 'u_image0', 'u_image1', 'u_tl_parent', 'u_scale_parent', 'u_buffer_scale']); this.lineShader = gl.initializeShader('line', ['a_pos', 'a_extrude', 'a_linesofar'], ['u_posmatrix', 'u_exmatrix', 'u_linewidth', 'u_color', 'u_debug', 'u_ratio', 'u_dasharray', 'u_blur']); this.linepatternShader = gl.initializeShader('linepattern', ['a_pos', 'a_extrude', 'a_linesofar'], ['u_posmatrix', 'u_exmatrix', 'u_linewidth', 'u_ratio', 'u_pattern_size', 'u_pattern_tl', 'u_pattern_br', 'u_point', 'u_blur', 'u_fade']); this.dotShader = gl.initializeShader('dot', ['a_pos'], ['u_posmatrix', 'u_size', 'u_color', 'u_blur']); this.sdfShader = gl.initializeShader('sdf', ['a_pos', 'a_tex', 'a_offset', 'a_angle', 'a_minzoom', 'a_maxzoom', 'a_rangeend', 'a_rangestart', 'a_labelminzoom'], ['u_posmatrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_color', 'u_gamma', 'u_buffer', 'u_angle', 'u_zoom', 'u_flip', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom']); this.iconShader = gl.initializeShader('icon', ['a_pos', 'a_tex', 'a_offset', 'a_angle', 'a_minzoom', 'a_maxzoom', 'a_rangeend', 'a_rangestart', 'a_labelminzoom'], ['u_posmatrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_angle', 'u_zoom', 'u_flip', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom', 'u_opacity']); this.outlineShader = gl.initializeShader('outline', ['a_pos'], ['u_posmatrix', 'u_color', 'u_world'] ); this.patternShader = gl.initializeShader('pattern', ['a_pos'], ['u_posmatrix', 'u_pattern_tl', 'u_pattern_br', 'u_mix', 'u_patternmatrix', 'u_opacity', 'u_image'] ); this.fillShader = gl.initializeShader('fill', ['a_pos'], ['u_posmatrix', 'u_color'] ); this.identityMatrix = mat4.create(); // The backgroundBuffer is used when drawing to the full *canvas* this.backgroundBuffer = gl.createBuffer(); this.backgroundBuffer.itemSize = 2; this.backgroundBuffer.itemCount = 4; gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW); // The tileExtentBuffer is used when drawing to a full *tile* this.tileExtentBuffer = gl.createBuffer(); this.tileExtentBuffer.itemSize = 4; this.tileExtentBuffer.itemCount = 4; gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([ // tile coord x, tile coord y, texture coord x, texture coord y 0, 0, 0, 0, this.tileExtent, 0, 32767, 0, 0, this.tileExtent, 0, 32767, this.tileExtent, this.tileExtent, 32767, 32767 ]), gl.STATIC_DRAW); // The debugBuffer is used to draw tile outlines for debugging this.debugBuffer = gl.createBuffer(); this.debugBuffer.itemSize = 2; this.debugBuffer.itemCount = 5; gl.bindBuffer(gl.ARRAY_BUFFER, this.debugBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([0, 0, 4095, 0, 4095, 4095, 0, 4095, 0, 0]), gl.STATIC_DRAW); // The debugTextBuffer is used to draw tile IDs for debugging this.debugTextBuffer = gl.createBuffer(); this.debugTextBuffer.itemSize = 2; }; /* * Reset the color buffers of the drawing canvas. */ GLPainter.prototype.clearColor = function() { var gl = this.gl; gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); }; /* * Reset the drawing canvas by clearing the stencil buffer so that we can draw * new tiles at the same location, while retaining previously drawn pixels. */ GLPainter.prototype.clearStencil = function() { var gl = this.gl; gl.clearStencil(0x0); gl.stencilMask(0xFF); gl.clear(gl.STENCIL_BUFFER_BIT); }; GLPainter.prototype.drawClippingMask = function() { var gl = this.gl; gl.switchShader(this.fillShader, this.tile.posMatrix, this.tile.exMatrix); gl.colorMask(false, false, false, false); // Clear the entire stencil buffer, except for the 7th bit, which stores // the global clipping mask that allows us to avoid drawing in regions of // tiles we've already painted in. gl.clearStencil(0x0); gl.stencilMask(0xBF); gl.clear(gl.STENCIL_BUFFER_BIT); // The stencil test will fail always, meaning we set all pixels covered // by this geometry to 0x80. We use the highest bit 0x80 to mark the regions // we want to draw in. All pixels that have this bit *not* set will never be // drawn in. gl.stencilFunc(gl.EQUAL, 0xC0, 0x40); gl.stencilMask(0xC0); gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP); // Draw the clipping mask gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer); gl.vertexAttribPointer(this.fillShader.a_pos, this.tileExtentBuffer.itemSize, gl.SHORT, false, 8, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.tileExtentBuffer.itemCount); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); gl.stencilMask(0x00); gl.colorMask(true, true, true, true); }; // Set up a texture that can be drawn into GLPainter.prototype.bindRenderTexture = function(name) { var gl = this.gl; if (name) { // Only create one framebuffer. Reuse it for every level. if (!this.framebufferObject) { this.framebufferObject = gl.createFramebuffer(); } gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebufferObject); // There's only one stencil buffer that we always attach. if (!this.stencilBuffer) { var stencil = this.stencilBuffer = gl.createRenderbuffer(); gl.bindRenderbuffer(gl.RENDERBUFFER, stencil); gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); } // We create a separate texture for every level. var texture = this.renderTextures.pop(); if (!texture) { texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } this.namedRenderTextures[name] = texture; gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); } else { gl.bindFramebuffer(gl.FRAMEBUFFER, null); } this.clearColor(); }; GLPainter.prototype.freeRenderTexture = function(name) { this.renderTextures.push(this.namedRenderTextures[name]); delete this.namedRenderTextures[name]; }; /* * Draw a new tile to the context, assuming that the viewport is * already correctly set. */ GLPainter.prototype.draw = function glPainterDraw(tile, style, layers, params, matrix) { this.tile = tile; // false when drawing a group of composited layers if (tile && !matrix) { // Draw the root clipping mask. this.drawClippingMask(); } if (!Array.isArray(layers)) console.warn('Layers is not an array'); this.frameHistory.record(this.transform.zoom); // Draw layers front-to-back. // Layers are already in reverse order from style.restructure() for (var i = 0, len = layers.length; i < len; i++) { this.applyStyle(layers[i], style, tile && tile.buckets, params, tile, matrix); } if (params.debug) { drawDebug(this.gl, this, tile, params); } }; GLPainter.prototype.applyStyle = function(layer, style, buckets, params, tile, matrix) { var gl = this.gl; var layerStyle = style.computed[layer.id]; if (!layerStyle || layerStyle.hidden) return; if (layer.layers) { if (layer.type === 'composite') { drawComposited(gl, this, buckets, layerStyle, params, style, layer); } else if (layer.type === 'raster') { drawRaster(gl, this, buckets[layer.bucket], layerStyle, params, style, layer, tile); } } else if (params.background) { drawBackground(gl, this, undefined, layerStyle, this.identityMatrix, params, style.sprite); } else { var bucket = buckets[layer.bucket]; // There are no vertices yet for this layer. if (!bucket || (bucket.hasData && !bucket.hasData())) return; var type = bucket.type; if (bucket.minZoom && this.transform.zoom < bucket.minZoom) return; if (bucket.maxZoom && this.transform.zoom >= bucket.maxZoom) return; var draw = type === 'symbol' ? drawSymbol : type === 'fill' ? drawFill : type === 'line' ? drawLine : type === 'raster' ? drawRaster : null; if (draw) { var useMatrix = matrix || this.tile.posMatrix; draw(gl, this, bucket, layerStyle, useMatrix, params, style.sprite); } else { console.warn('No bucket type specified'); } if (params.vertices && !layer.layers) { drawVertices(gl, this, bucket); } } }; // Draws non-opaque areas. This is for debugging purposes. GLPainter.prototype.drawStencilBuffer = function() { var gl = this.gl; gl.switchShader(this.fillShader, this.identityMatrix); // Blend to the front, not the back. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); // Drw the filling quad where the stencil buffer isn't set. gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer); gl.vertexAttribPointer(this.fillShader.a_pos, this.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0); gl.uniform4fv(this.fillShader.u_color, [0, 0, 0, 0.5]); gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.backgroundBuffer.itemCount); // Revert blending mode to blend to the back. gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE); }; GLPainter.prototype.translateMatrix = function(matrix, z, translate, anchor) { if (!translate[0] && !translate[1]) return matrix; if (anchor === 'viewport') { var sin_a = Math.sin(-this.transform.angle); var cos_a = Math.cos(-this.transform.angle); translate = [ translate[0] * cos_a - translate[1] * sin_a, translate[0] * sin_a + translate[1] * cos_a ]; } var tilePixelRatio = this.transform.scale / (1 << z) / 8; var translation = [ translate[0] / tilePixelRatio, translate[1] / tilePixelRatio, 0 ]; var translatedMatrix = new Float32Array(16); mat4.translate(translatedMatrix, matrix, translation); return translatedMatrix; }; GLPainter.prototype.saveTexture = function(texture) { var textures = this.reusableTextures[texture.size]; if (!textures) { this.reusableTextures[texture.size] = [texture]; } else { textures.push(texture); } }; GLPainter.prototype.getTexture = function(size) { var textures = this.reusableTextures[size]; return textures && textures.length > 0 ? textures.pop() : null; }; },{"../lib/glmatrix.js":21,"../symbol/glyphatlas.js":60,"../util/browser.js":77,"./drawbackground.js":23,"./drawcomposited.js":24,"./drawdebug.js":25,"./drawfill.js":26,"./drawline.js":27,"./drawraster.js":28,"./drawsymbol.js":29,"./drawvertices.js":30,"./framehistory.js":31,"./glutil.js":32}],34:[function(require,module,exports){ 'use strict'; var glmatrix = require('../lib/glmatrix.js'); var mat4 = glmatrix.mat4; module.exports = PrerenderedTexture; function PrerenderedTexture(gl, bucket, painter) { this.gl = gl; this.buffer = bucket['raster-buffer'] || (1/32); this.size = (bucket['raster-size'] || 512) * (1 + 2 * this.buffer); this.painter = painter; this.texture = null; this.fbo = null; this.fbos = this.painter.preFbos[this.size]; } PrerenderedTexture.prototype.bindFramebuffer = function() { var gl = this.gl; // try to reuse available raster textures this.texture = this.painter.getTexture(this.size); if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.size, this.size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); this.texture.size = this.size; } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } if (!this.fbos) { this.fbo = gl.createFramebuffer(); var stencil = gl.createRenderbuffer(); gl.bindRenderbuffer(gl.RENDERBUFFER, stencil); gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, this.size, this.size); gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); } else { this.fbo = this.fbos.pop(); gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); } }; PrerenderedTexture.prototype.unbindFramebuffer = function() { var gl = this.gl; gl.bindFramebuffer(gl.FRAMEBUFFER, null); if (this.fbos) this.fbos.push(this.fbo); else this.painter.preFbos[this.size] = [this.fbo]; }; PrerenderedTexture.prototype.bind = function() { if (!this.texture) throw('pre-rendered texture does not exist'); var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); }; PrerenderedTexture.prototype.blur = function(painter, passes) { var gl = this.gl; var originalTexture = this.texture; var secondaryTexture = this.painter.getTexture(this.size); if (!secondaryTexture) { secondaryTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, secondaryTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.size, this.size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); secondaryTexture.size = this.size; } else { gl.bindTexture(gl.TEXTURE_2D, secondaryTexture); } gl.bindTexture(gl.TEXTURE_2D, null); var matrix = mat4.create(); mat4.ortho(matrix, 0, 4096, -4096, 0, 0, 1); mat4.translate(matrix, matrix, [0, -4096, 0]); gl.switchShader(painter.gaussianShader, matrix); gl.activeTexture(gl.TEXTURE0); gl.uniform1i(painter.gaussianShader.u_image, 0); gl.uniform1f(painter.gaussianShader.u_opacity, 1); for (var i = 0; i < passes; i++) { // Render horizontal gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, secondaryTexture, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform2fv(painter.gaussianShader.u_offset, [1 / this.size, 0]); gl.bindTexture(gl.TEXTURE_2D, originalTexture); gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer); gl.vertexAttribPointer(painter.gaussianShader.a_pos, 2, gl.SHORT, false, 8, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Render vertical gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, originalTexture, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform2fv(painter.gaussianShader.u_offset, [0, 1 / this.size]); gl.bindTexture(gl.TEXTURE_2D, secondaryTexture); gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer); gl.vertexAttribPointer(painter.gaussianShader.a_pos, 2, gl.SHORT, false, 8, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } this.painter.saveTexture(secondaryTexture); }; },{"../lib/glmatrix.js":21}],35:[function(require,module,exports){ 'use strict'; var glify = undefined; module.exports = { "composite": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nuniform mat4 u_posmatrix;\nvarying highp vec2 a;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n vec4 tmpvar_2;\n tmpvar_2 = (u_posmatrix * tmpvar_1);\n gl_Position = tmpvar_2;\n a = ((tmpvar_2.xy / 2.0) + 0.5);\n}\n\n","fragment":"precision mediump float;\nuniform sampler2D u_image;\nuniform float u_opacity;\nvarying vec2 a;\nvoid main ()\n{\n lowp vec4 tmpvar_1;\n tmpvar_1 = (texture2D (u_image, a) * u_opacity);\n gl_FragColor = tmpvar_1;\n}\n\n"}, "debug": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nuniform float u_pointsize;\nuniform mat4 u_posmatrix;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xy = a_pos;\n tmpvar_1.z = float((a_pos.x >= 32767.0));\n gl_Position = (u_posmatrix * tmpvar_1);\n gl_PointSize = u_pointsize;\n}\n\n","fragment":"precision mediump float;\nuniform vec4 u_color;\nvoid main ()\n{\n gl_FragColor = u_color;\n}\n\n"}, "dot": {"vertex":"precision mediump float;\nuniform mat4 u_posmatrix;\nuniform float u_size;\nattribute vec2 a_pos;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_posmatrix * tmpvar_1);\n gl_PointSize = u_size;\n}\n\n","fragment":"precision mediump float;\nuniform vec4 u_color;\nuniform float u_blur;\nvoid main ()\n{\n mediump vec2 x_1;\n x_1 = (gl_PointCoord - 0.5);\n mediump float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 0.5) / (\n (0.5 - u_blur)\n - 0.5)), 0.0, 1.0);\n gl_FragColor = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n}\n\n"}, "fill": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nuniform mat4 u_posmatrix;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_posmatrix * tmpvar_1);\n gl_PointSize = 2.0;\n}\n\n","fragment":"precision mediump float;\nuniform vec4 u_color;\nvoid main ()\n{\n gl_FragColor = u_color;\n}\n\n"}, "gaussian": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nuniform mat4 u_posmatrix;\nuniform vec2 u_offset;\nvarying highp vec2 b[3];\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n vec4 tmpvar_2;\n tmpvar_2 = (u_posmatrix * tmpvar_1);\n gl_Position = tmpvar_2;\n highp vec2 tmpvar_3;\n tmpvar_3 = ((tmpvar_2.xy / 2.0) + 0.5);\n b[0] = tmpvar_3;\n vec2 cse_4;\n cse_4 = (u_offset * 1.18243);\n b[1] = (tmpvar_3 + cse_4);\n b[2] = (tmpvar_3 - cse_4);\n}\n\n","fragment":"precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 b[3];\nvoid main ()\n{\n lowp vec4 tmpvar_1;\n tmpvar_1 = (((texture2D (u_image, b[0]) * 0.40262) + (texture2D (u_image, b[1]) * 0.29869)) + (texture2D (u_image, b[2]) * 0.29869));\n gl_FragColor = tmpvar_1;\n}\n\n"}, "line": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\nuniform mat4 u_posmatrix;\nuniform mat4 u_exmatrix;\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n vec2 c_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n c_1.x = tmpvar_2.x;\n c_1.y = sign((tmpvar_2.y - 0.5));\n a = c_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 1.0);\n tmpvar_3.xy = floor((a_pos / 2.0));\n vec4 tmpvar_4;\n tmpvar_4.zw = vec2(0.0, 0.0);\n tmpvar_4.xy = (u_linewidth.x * (a_extrude / 63.0));\n gl_Position = ((u_posmatrix * tmpvar_3) + (u_exmatrix * tmpvar_4));\n b = (a_linesofar * u_ratio);\n}\n\n","fragment":"precision mediump float;\nuniform float u_debug;\nuniform float u_blur;\nuniform vec2 u_linewidth;\nuniform vec2 u_dasharray;\nuniform vec4 u_color;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n float tmpvar_1;\n tmpvar_1 = (sqrt(dot (a, a)) * u_linewidth.x);\n float tmpvar_2;\n tmpvar_2 = (float(mod (b, (u_dasharray.x + u_dasharray.y))));\n gl_FragColor = (u_color * (clamp (\n (min ((tmpvar_1 - (u_linewidth.y - u_blur)), (u_linewidth.x - tmpvar_1)) / u_blur)\n , 0.0, 1.0) * max (\n float((-(u_dasharray.y) >= 0.0))\n , \n clamp (min (tmpvar_2, (u_dasharray.x - tmpvar_2)), 0.0, 1.0)\n )));\n if ((u_debug > 0.0)) {\n gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n };\n}\n\n"}, "linepattern": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\nuniform mat4 u_posmatrix;\nuniform mat4 u_exmatrix;\nuniform float u_point;\nuniform vec2 u_linewidth;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n vec2 c_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n c_1.x = tmpvar_2.x;\n c_1.y = sign((tmpvar_2.y - 0.5));\n a = c_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 1.0);\n tmpvar_3.xy = floor((a_pos / 2.0));\n vec4 tmpvar_4;\n tmpvar_4.w = 0.0;\n tmpvar_4.xy = ((u_linewidth.x * (a_extrude / 63.0)) * (1.0 - u_point));\n tmpvar_4.z = (float((a_pos.x >= 32767.0)) + (u_point * float(\n (c_1.y >= 1.0)\n )));\n gl_Position = ((u_posmatrix * tmpvar_3) + (u_exmatrix * tmpvar_4));\n b = a_linesofar;\n gl_PointSize = ((2.0 * u_linewidth.x) - 1.0);\n}\n\n","fragment":"precision mediump float;\nuniform float u_point;\nuniform float u_blur;\nuniform float u_fade;\nuniform vec2 u_linewidth;\nuniform vec2 u_pattern_size;\nuniform vec2 u_pattern_tl;\nuniform vec2 u_pattern_br;\nuniform sampler2D u_image;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n lowp vec4 j_1;\n mediump vec2 x_2;\n x_2 = ((gl_PointCoord * 2.0) - 1.0);\n mediump float tmpvar_3;\n tmpvar_3 = (((\n sqrt(dot (a, a))\n * \n (1.0 - u_point)\n ) + (u_point * \n sqrt(dot (x_2, x_2))\n )) * u_linewidth.x);\n float tmpvar_4;\n tmpvar_4 = (float(mod ((b / u_pattern_size.x), 1.0)));\n float tmpvar_5;\n tmpvar_5 = (0.5 + ((a.y * u_linewidth.x) / u_pattern_size.y));\n vec2 tmpvar_6;\n tmpvar_6.x = tmpvar_4;\n tmpvar_6.y = tmpvar_5;\n vec2 tmpvar_7;\n tmpvar_7.x = (float(mod ((tmpvar_4 * 2.0), 1.0)));\n tmpvar_7.y = tmpvar_5;\n lowp vec4 tmpvar_8;\n tmpvar_8 = ((texture2D (u_image, mix (u_pattern_tl, u_pattern_br, tmpvar_6)) * (1.0 - u_fade)) + (u_fade * texture2D (u_image, mix (u_pattern_tl, u_pattern_br, tmpvar_7))));\n j_1.w = tmpvar_8.w;\n j_1.xyz = (tmpvar_8.xyz * tmpvar_8.w);\n gl_FragColor = (j_1 * clamp ((\n min ((tmpvar_3 - (u_linewidth.y - u_blur)), (u_linewidth.x - tmpvar_3))\n / u_blur), 0.0, 1.0));\n}\n\n"}, "outline": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nuniform mat4 u_posmatrix;\nuniform vec2 u_world;\nvarying highp vec2 a;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n vec4 tmpvar_2;\n tmpvar_2 = (u_posmatrix * tmpvar_1);\n gl_Position = tmpvar_2;\n a = (((tmpvar_2.xy + 1.0) / 2.0) * u_world);\n}\n\n","fragment":"precision mediump float;\nuniform vec4 u_color;\nvarying vec2 a;\nvoid main ()\n{\n highp vec2 x_1;\n x_1 = (a - gl_FragCoord.xy);\n highp float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 1.0) / -1.0), 0.0, 1.0);\n highp vec4 tmpvar_3;\n tmpvar_3 = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n gl_FragColor = tmpvar_3;\n}\n\n"}, "pattern": {"vertex":"precision mediump float;\nuniform mat4 u_posmatrix;\nuniform mat3 u_patternmatrix;\nattribute vec2 a_pos;\nvarying vec2 a;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_posmatrix * tmpvar_1);\n vec3 tmpvar_2;\n tmpvar_2.z = 1.0;\n tmpvar_2.xy = a_pos;\n a = (u_patternmatrix * tmpvar_2).xy;\n}\n\n","fragment":"precision mediump float;\nuniform float u_opacity;\nuniform float u_mix;\nuniform vec2 u_pattern_tl;\nuniform vec2 u_pattern_br;\nuniform sampler2D u_image;\nvarying vec2 a;\nvoid main ()\n{\n vec2 tmpvar_1;\n tmpvar_1 = (vec2(mod (a, 1.0)));\n lowp vec4 tmpvar_2;\n tmpvar_2 = (mix (texture2D (u_image, mix (u_pattern_tl, u_pattern_br, tmpvar_1)), texture2D (u_image, mix (u_pattern_tl, u_pattern_br, \n (vec2(mod ((tmpvar_1 * 2.0), 1.0)))\n )), u_mix) * u_opacity);\n gl_FragColor = tmpvar_2;\n}\n\n"}, "raster": {"vertex":"precision mediump float;\nuniform mat4 u_posmatrix;\nuniform vec2 u_tl_parent;\nuniform float u_scale_parent;\nuniform float u_buffer_scale;\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\nvarying vec2 a;\nvarying vec2 b;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_posmatrix * tmpvar_1);\n vec2 tmpvar_2;\n tmpvar_2 = (((\n (a_texture_pos / 32767.0)\n - 0.5) / u_buffer_scale) + 0.5);\n a = tmpvar_2;\n b = ((tmpvar_2 * u_scale_parent) + u_tl_parent);\n}\n\n","fragment":"precision mediump float;\nuniform float u_opacity0;\nuniform float u_opacity1;\nuniform float u_brightness_low;\nuniform float u_brightness_high;\nuniform float u_saturation_factor;\nuniform float u_contrast_factor;\nuniform sampler2D u_image0;\nuniform sampler2D u_image1;\nvarying vec2 a;\nvarying vec2 b;\nuniform vec3 u_spin_weights;\nvoid main ()\n{\n lowp vec4 tmpvar_1;\n tmpvar_1 = ((texture2D (u_image0, a) * u_opacity0) + (texture2D (u_image1, b) * u_opacity1));\n lowp vec3 tmpvar_2;\n tmpvar_2.x = dot (tmpvar_1.xyz, u_spin_weights);\n tmpvar_2.y = dot (tmpvar_1.xyz, u_spin_weights.zxy);\n tmpvar_2.z = dot (tmpvar_1.xyz, u_spin_weights.yzx);\n lowp vec4 tmpvar_3;\n tmpvar_3.xyz = mix (vec3(u_brightness_low), vec3(u_brightness_high), ((\n ((tmpvar_2 + ((\n (((tmpvar_1.x + tmpvar_1.y) + tmpvar_1.z) / 3.0)\n - tmpvar_2) * u_saturation_factor)) - 0.5)\n * u_contrast_factor) + 0.5));\n tmpvar_3.w = tmpvar_1.w;\n gl_FragColor = tmpvar_3;\n}\n\n"}, "icon": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nattribute vec2 a_offset;\nattribute vec2 a_tex;\nattribute float a_angle;\nattribute float a_minzoom;\nattribute float a_maxzoom;\nattribute float a_rangeend;\nattribute float a_rangestart;\nattribute float a_labelminzoom;\nuniform mat4 u_posmatrix;\nuniform mat4 u_exmatrix;\nuniform float u_angle;\nuniform float u_zoom;\nuniform float u_flip;\nuniform float u_fadedist;\nuniform float u_minfadezoom;\nuniform float u_maxfadezoom;\nuniform float u_fadezoom;\nuniform float u_opacity;\nuniform vec2 u_texsize;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n float d_1;\n d_1 = 0.0;\n float tmpvar_2;\n tmpvar_2 = (float(mod ((a_angle + u_angle), 256.0)));\n if ((((u_flip > 0.0) && (tmpvar_2 >= 64.0)) && (tmpvar_2 < 192.0))) {\n d_1 = 1.0;\n };\n float tmpvar_3;\n tmpvar_3 = (((2.0 - \n float((u_zoom >= a_minzoom))\n ) - (1.0 - \n float((u_zoom >= a_maxzoom))\n )) + d_1);\n float tmpvar_4;\n tmpvar_4 = clamp (((u_fadezoom - a_labelminzoom) / u_fadedist), 0.0, 1.0);\n if ((u_fadedist >= 0.0)) {\n b = tmpvar_4;\n } else {\n b = (1.0 - tmpvar_4);\n };\n if ((u_maxfadezoom < a_labelminzoom)) {\n b = 0.0;\n };\n if ((u_minfadezoom >= a_labelminzoom)) {\n b = 1.0;\n };\n vec4 tmpvar_5;\n tmpvar_5.zw = vec2(0.0, 1.0);\n tmpvar_5.xy = a_pos;\n vec4 tmpvar_6;\n tmpvar_6.w = 0.0;\n tmpvar_6.xy = (a_offset / 64.0);\n tmpvar_6.z = ((tmpvar_3 + float(\n (0.0 >= b)\n )) + (float(\n (u_angle >= a_rangeend)\n ) * (1.0 - \n float((u_angle >= a_rangestart))\n )));\n gl_Position = ((u_posmatrix * tmpvar_5) + (u_exmatrix * tmpvar_6));\n a = (a_tex / u_texsize);\n b = (b * u_opacity);\n}\n\n","fragment":"precision mediump float;\nuniform sampler2D u_texture;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n lowp vec4 tmpvar_1;\n tmpvar_1 = (texture2D (u_texture, a) * b);\n gl_FragColor = tmpvar_1;\n}\n\n"}, "sdf": {"vertex":"precision mediump float;\nattribute vec2 a_pos;\nattribute vec2 a_offset;\nattribute vec2 a_tex;\nattribute float a_angle;\nattribute float a_minzoom;\nattribute float a_maxzoom;\nattribute float a_rangeend;\nattribute float a_rangestart;\nattribute float a_labelminzoom;\nuniform mat4 u_posmatrix;\nuniform mat4 u_exmatrix;\nuniform float u_angle;\nuniform float u_zoom;\nuniform float u_flip;\nuniform float u_fadedist;\nuniform float u_minfadezoom;\nuniform float u_maxfadezoom;\nuniform float u_fadezoom;\nuniform vec2 u_texsize;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n float d_1;\n d_1 = 0.0;\n float tmpvar_2;\n tmpvar_2 = (float(mod ((a_angle + u_angle), 256.0)));\n if ((((u_flip > 0.0) && (tmpvar_2 >= 64.0)) && (tmpvar_2 < 192.0))) {\n d_1 = 1.0;\n };\n float tmpvar_3;\n tmpvar_3 = (((2.0 - \n float((u_zoom >= a_minzoom))\n ) - (1.0 - \n float((u_zoom >= a_maxzoom))\n )) + d_1);\n float tmpvar_4;\n tmpvar_4 = clamp (((u_fadezoom - a_labelminzoom) / u_fadedist), 0.0, 1.0);\n if ((u_fadedist >= 0.0)) {\n b = tmpvar_4;\n } else {\n b = (1.0 - tmpvar_4);\n };\n if ((u_maxfadezoom < a_labelminzoom)) {\n b = 0.0;\n };\n if ((u_minfadezoom >= a_labelminzoom)) {\n b = 1.0;\n };\n vec4 tmpvar_5;\n tmpvar_5.zw = vec2(0.0, 1.0);\n tmpvar_5.xy = a_pos;\n vec4 tmpvar_6;\n tmpvar_6.w = 0.0;\n tmpvar_6.xy = (a_offset / 64.0);\n tmpvar_6.z = ((tmpvar_3 + float(\n (0.0 >= b)\n )) + (float(\n (u_angle >= a_rangeend)\n ) * (1.0 - \n float((u_angle >= a_rangestart))\n )));\n gl_Position = ((u_posmatrix * tmpvar_5) + (u_exmatrix * tmpvar_6));\n a = (a_tex / u_texsize);\n}\n\n","fragment":"precision mediump float;\nuniform sampler2D u_texture;\nuniform vec4 u_color;\nuniform float u_buffer;\nuniform float u_gamma;\nvarying vec2 a;\nvarying float b;\nvoid main ()\n{\n float edge0_1;\n edge0_1 = (u_buffer - u_gamma);\n lowp float tmpvar_2;\n tmpvar_2 = clamp (((texture2D (u_texture, a).w - edge0_1) / (\n (u_buffer + u_gamma)\n - edge0_1)), 0.0, 1.0);\n lowp vec4 tmpvar_3;\n tmpvar_3 = (u_color * ((tmpvar_2 * \n (tmpvar_2 * (3.0 - (2.0 * tmpvar_2)))\n ) * b));\n gl_FragColor = tmpvar_3;\n}\n\n"} }; },{}],36:[function(require,module,exports){ 'use strict'; var Source = require('./source.js'); var GeoJSONTile = require('./geojsontile.js'); var GeoJSONSource = module.exports = function(options) { this.tiles = {}; this.alltiles = {}; this.enabled = true; this.zooms = [1, 5, 9, 13]; this.minTileZoom = this.zooms[0]; this.maxTileZoom = this.zooms[this.zooms.length - 1]; this.loadNewTiles = true; this.tileJSON = { minZoom: 1, maxZoom: 13 }; this.data = options.data; }; GeoJSONSource.prototype = Object.create(Source.prototype); GeoJSONSource.prototype.setData = function(data) { this.data = data; if (this.map) this._updateData(); return this; }; GeoJSONSource.prototype.onAdd = function(map) { this.map = map; this.painter = map.painter; if (this.map.style) this._updateData(); map.on('style.change', this._updateData.bind(this)); }; GeoJSONSource.prototype._updateData = function() { var source = this; this.workerID = this.map.dispatcher.send('parse geojson', { data: this.data, zooms: this.zooms, tileSize: 512, source: this.id }, function(err, tiles) { if (err) return; for (var i = 0; i < tiles.length; i++) { source.alltiles[tiles[i].id] = new GeoJSONTile(tiles[i].id, source, tiles[i]); } if (source.map) source.map.update(); }); return this; }; GeoJSONSource.prototype._addTile = function(id) { var tile = this.alltiles[id]; if (tile) { tile._load(); this.tiles[id] = tile; this.fire('tile.add', {tile: tile}); } return tile || {}; }; GeoJSONSource.prototype._coveringZoomLevel = function(zoom) { for (var i = this.zooms.length - 1; i >= 0; i--) { if (this.zooms[i] <= zoom) { var z = this.zooms[i]; return z; } } return 0; }; },{"./geojsontile.js":37,"./source.js":40}],37:[function(require,module,exports){ 'use strict'; var Tile = require('./tile.js'); var BufferSet = require('../data/buffer/bufferset.js'); var createBucket = require('../data/createbucket.js'); module.exports = GeoJSONTile; function GeoJSONTile(id, source, data) { this.id = id; this.source = source; this.data = data; this.workerID = source.workerID; } GeoJSONTile.prototype = Object.create(Tile.prototype); GeoJSONTile.prototype._load = function() { if (this.loaded) return; this.loaded = true; var data = this.data; this.buffers = new BufferSet(data.buffers); this.buckets = {}; for (var b in data.elementGroups) { this.buckets[b] = createBucket(this.source.map.style.buckets[b], this.buffers, undefined, data.elementGroups[b]); } }; // noops GeoJSONTile.prototype.abort = function() { }; GeoJSONTile.prototype.remove = function() { }; },{"../data/buffer/bufferset.js":2,"../data/createbucket.js":10,"./tile.js":41}],38:[function(require,module,exports){ 'use strict'; module.exports = Wrapper; // conform to vectortile api function Wrapper(features) { this.features = features; this.length = features.length; } Wrapper.prototype.feature = function(i) { return new FeatureWrapper(this.features[i]); }; var mapping = { 'Point': 1, 'LineString': 2, 'Polygon': 3 }; function FeatureWrapper(feature) { this.feature = feature; this._type = mapping[feature.type]; this.properties = feature.properties; } FeatureWrapper.prototype.loadGeometry = function() { return this.feature.coords; }; FeatureWrapper.prototype.bbox = function() { if (this._type === mapping.Point) { return [ this.feature.coords[0], this.feature.coords[1], this.feature.coords[0], this.feature.coords[1] ]; } var rings = this.feature.coords; var x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity; for (var i = 0; i < rings.length; i++) { var ring = rings[i]; for (var j = 0; j < ring.length; j++) { var coord = ring[j]; x1 = Math.min(x1, coord.x); x2 = Math.max(x2, coord.x); y1 = Math.min(y1, coord.y); y2 = Math.max(y2, coord.y); } } return [x1, y1, x2, y2]; }; },{}],39:[function(require,module,exports){ 'use strict'; var Tile = require('./tile.js'); var ajax = require('../util/ajax.js'); module.exports = RasterTile; function RasterTile(id, source, url, callback) { this.id = id; this.loaded = false; this.url = url; this.source = source; this.map = source.map; this._load(); this.callback = callback; this.uses = 1; // Todo finish figuring out what raster buckets are this.buckets = {}; this.info = { raster: true }; var buckets = this.map.style.buckets; for (var b in buckets) { var bucket = buckets[b]; var sourceid = bucket && bucket.source; if (source.id === sourceid) { this.buckets[b] = { info: bucket.render, type: 'raster', tile: this }; } } } RasterTile.prototype = Object.create(Tile.prototype); RasterTile.prototype._load = function() { var tile = this; ajax.getImage(this.url, function(err, img) { // @TODO handle errors. if (err) return; tile.img = img; if (tile.map) tile.onTileLoad(); }); }; RasterTile.prototype.onTileLoad = function() { // start texture upload this.bind(this.map.painter.gl); this.loaded = true; this.callback(); }; RasterTile.prototype.abort = function() { this.aborted = true; if (this.img) this.img.src = ''; delete this.img; }; RasterTile.prototype.bind = function(gl) { if (!this.texture) { // try to find reusable texture this.texture = this.map.painter.getTexture(this.img.width); if (this.texture) { gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.img); } else { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img); this.texture.size = this.img.width; } gl.generateMipmap(gl.TEXTURE_2D); } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } }; RasterTile.prototype.remove = function() { if (this.texture) this.map.painter.saveTexture(this.texture); delete this.map; }; RasterTile.prototype.featuresAt = function(pos, params, callback) { // noop callback(null, []); }; },{"../util/ajax.js":76,"./tile.js":41}],40:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'), ajax = require('../util/ajax.js'), tileJSON = require('../util/url.js').tileJSON, Evented = require('../util/evented.js'), Cache = require('../util/mrucache.js'), TileCoord = require('./tilecoord'), VectorTile = require('./vectortile'), RasterTile = require('./rastertile.js'), Point = require('point-geometry'); module.exports = Source; Source.protocols = { "mapbox": function(url, callback) { ajax.getJSON(tileJSON(url.split('://')[1]), callback); } }; function Source(options) { this.tiles = {}; this.enabled = false; this.type = options.type; if (this.type === 'vector' && options.tileSize && options.tileSize !== 512) { throw new Error('vector tile sources must have a tileSize of 512'); } this.Tile = this.type === 'vector' ? VectorTile : RasterTile; this.options = util.inherit(this.options, options); this.cache = new Cache(this.options.cacheSize, function(tile) { tile.remove(); }); var protocol = options.url.split(':')[0]; Source.protocols[protocol](options.url, function(err, tileJSON) { if (err) throw err; this.tileJSON = tileJSON; this.loadNewTiles = true; this.enabled = true; this.update(); if (this.map) this.map.fire('source.add', {source: this}); }.bind(this)); this._updateTiles = util.throttle(this._updateTiles, 50, this); } Source.prototype = util.inherit(Evented, { options: { tileSize: 512, cacheSize: 20 }, onAdd: function(map) { this.map = map; this.painter = map.painter; }, load: function() { for (var t in this.tiles) { this.tiles[t]._load(); } }, loaded: function() { for (var t in this.tiles) { if (!this.tiles[t].loaded) return false; } return true; }, update: function() { if (!this.enabled) return; this._updateTiles(); }, render: function(layers) { // Iteratively paint every tile. if (!this.enabled) return; var order = Object.keys(this.tiles); order.sort(this._z_order); for (var i = 0; i < order.length; i++) { var id = order[i]; var tile = this.tiles[id]; if (tile.loaded && !this.coveredTiles[id]) { this._renderTile(tile, id, layers); } } }, featuresAt: function(point, params, callback) { point = Point.convert(point); if (params.layer) { var style = this.map.style, layer = style.getLayer(params.layer); params.bucket = style.buckets[layer.ref || layer.id]; } var order = Object.keys(this.tiles); order.sort(this._z_order); for (var i = 0; i < order.length; i++) { var id = order[i]; var tile = this.tiles[id]; var pos = tile.positionAt(id, point); if (pos && pos.x >= 0 && pos.x < 4096 && pos.y >= 0 && pos.y < 4096) { // The click is within the viewport. There is only ever one tile in // a layer that has this property. return tile.featuresAt(pos, params, callback); } } callback(null, []); }, // get the zoom level adjusted for the difference in map and source tilesizes _getZoom: function() { var zOffset = Math.log(this.map.transform.tileSize/this.options.tileSize) / Math.LN2; return this.map.transform.zoom + zOffset; }, _coveringZoomLevel: function(zoom) { for (var z = this.tileJSON.maxzoom; z >= this.tileJSON.minzoom; z--) { if (z <= zoom) { if (this.type === 'raster') { // allow underscaling by rounding to the nearest zoom level if (z < this.tileJSON.maxzoom) { z += Math.round(zoom - z); } } return z; } } return 0; }, _childZoomLevel: function(zoom) { zoom = Math.max(this.tileJSON.minzoom, zoom + 1); return zoom <= this.tileJSON.maxzoom ? zoom : null; }, _getCoveringTiles: function(zoom) { if (zoom === undefined) zoom = this._getZoom(); var z = this._coveringZoomLevel(zoom), tiles = 1 << z, tr = this.map.transform, tileCenter = TileCoord.zoomTo(tr.locationCoordinate(tr.center), z); var points = [ TileCoord.zoomTo(tr.pointCoordinate(tileCenter, {x: 0, y: 0}), z), TileCoord.zoomTo(tr.pointCoordinate(tileCenter, {x: tr.width, y: 0}), z), TileCoord.zoomTo(tr.pointCoordinate(tileCenter, {x: tr.width, y: tr.height}), z), TileCoord.zoomTo(tr.pointCoordinate(tileCenter, {x: 0, y: tr.height}), z) ], t = {}; // Divide the screen up in two triangles and scan each of them: // +---/ // | / | // /---+ this._scanTriangle(points[0], points[1], points[2], 0, tiles, scanLine); this._scanTriangle(points[2], points[3], points[0], 0, tiles, scanLine); return Object.keys(t).sort(fromCenter); function fromCenter(a, b) { var ad = Math.abs(a.x - tileCenter.column) + Math.abs(a.y - tileCenter.row), bd = Math.abs(b.x - tileCenter.column) + Math.abs(b.y - tileCenter.row); return ad - bd; } function scanLine(x0, x1, y) { var x, wx; if (y >= 0 && y <= tiles) { for (x = x0; x < x1; x++) { wx = (x + tiles) % tiles; t[TileCoord.toID(z, wx, y, Math.floor(x/tiles))] = {x: wx, y: y}; } } } }, // Given a tile of data, its id, and a style layers, render the tile to the canvas _renderTile: function(tile, id, layers) { var pos = TileCoord.fromID(id); var z = pos.z, x = pos.x, y = pos.y, w = pos.w; x += w * (1 << z); tile.calculateMatrices(z, x, y, this.map.transform, this.painter); this.painter.draw(tile, this.map.style, layers, { z: z, x: x, y: y, debug: this.map.debug, antialiasing: this.map.antialiasing, vertices: this.map.vertices, rotating: this.map.rotating, zooming: this.map.zooming }); }, // Recursively find children of the given tile (up to maxCoveringZoom) that are already loaded; // adds found tiles to retain object; returns true if children completely cover the tile _findLoadedChildren: function(id, maxCoveringZoom, retain) { var complete = true; var z = TileCoord.fromID(id).z; var ids = TileCoord.children(id); for (var i = 0; i < ids.length; i++) { if (this.tiles[ids[i]] && this.tiles[ids[i]].loaded) { retain[ids[i]] = true; } else { complete = false; if (z < maxCoveringZoom) { // Go further down the hierarchy to find more unloaded children. this._findLoadedChildren(ids[i], maxCoveringZoom, retain); } } } return complete; }, // Find a loaded parent of the given tile (up to minCoveringZoom); // adds the found tile to retain object and returns true if a parent was found _findLoadedParent: function(id, minCoveringZoom, retain) { for (var z = TileCoord.fromID(id).z; z >= minCoveringZoom; z--) { id = TileCoord.parent(id); if (this.tiles[id] && this.tiles[id].loaded) { retain[id] = true; return true; } } return false; }, // Removes tiles that are outside the viewport and adds new tiles that are inside the viewport. _updateTiles: function() { if (!this.map || !this.map.loadNewTiles || !this.loadNewTiles || !this.map.style.sources[this.id]) return; var zoom = Math.floor(this._getZoom()); var required = this._getCoveringTiles().sort(this._centerOut.bind(this)); var i; var id; var complete; var tile; // Determine the overzooming/underzooming amounts. var minCoveringZoom = Math.max(this.tileJSON.minzoom, zoom - 10); var maxCoveringZoom = this.tileJSON.minzoom; while (maxCoveringZoom < zoom + 1) { var level = this._childZoomLevel(maxCoveringZoom); if (level === null) break; else maxCoveringZoom = level; } // Retain is a list of tiles that we shouldn't delete, even if they are not // the most ideal tile for the current viewport. This may include tiles like // parent or child tiles that are *already* loaded. var retain = {}; // Covered is a list of retained tiles who's areas are full covered by other, // better, retained tiles. They are not drawn separately. this.coveredTiles = {}; var fullyComplete = true; // Add existing child/parent tiles if the actual tile is not yet loaded for (i = 0; i < required.length; i++) { id = +required[i]; retain[id] = true; tile = this._addTile(id); if (!tile.loaded) { // The tile we require is not yet loaded. Try to find a parent or // child tile that we already have. // First, try to find existing child tiles that completely cover the // missing tile. complete = this._findLoadedChildren(id, maxCoveringZoom, retain); // Then, if there are no complete child tiles, try to find existing // parent tiles that completely cover the missing tile. if (!complete) { complete = this._findLoadedParent(id, minCoveringZoom, retain); } // The unloaded tile's area is not completely covered loaded tiles if (!complete) { fullyComplete = false; } } } var now = new Date().getTime(); var fadeDuration = this.type === 'raster' ? this.map.style.rasterFadeDuration : 0; for (id in retain) { tile = this.tiles[id]; if (tile && tile.timeAdded > now - fadeDuration) { // This tile is still fading in. Find tiles to cross-fade with it. complete = this._findLoadedChildren(id, maxCoveringZoom, retain); if (complete) { this.coveredTiles[id] = true; } else { this._findLoadedParent(id, minCoveringZoom, retain); } } } for (id in this.coveredTiles) retain[id] = true; // Remove the tiles we don't need anymore. var remove = util.keysDifference(this.tiles, retain); for (i = 0; i < remove.length; i++) { id = +remove[i]; this._removeTile(id); } }, _loadTile: function(id) { var layer = this; var map = this.map, pos = TileCoord.fromID(id), tile; if (pos.w === 0) { // console.time('loading ' + pos.z + '/' + pos.x + '/' + pos.y); var url = TileCoord.url(id, this.tileJSON.tiles); tile = this.tiles[id] = new this.Tile(id, this, url, tileComplete); } else { var wrapped = TileCoord.toID(pos.z, pos.x, pos.y, 0); tile = this.tiles[id] = this.tiles[wrapped] || this._addTile(wrapped); tile.uses++; } function tileComplete(err) { // console.timeEnd('loading ' + pos.z + '/' + pos.x + '/' + pos.y); if (err) { console.warn('failed to load tile %d/%d/%d: %s', pos.z, pos.x, pos.y, err.stack || err); } else { layer.fire('tile.load', {tile: tile}); map.update(); } } return tile; }, // Adds a vector tile to the map. It will trigger a rerender of the map and will // be part in all future renders of the map. The map object will handle copying // the tile data to the GPU if it is required to paint the current viewport. _addTile: function(id) { var tile = this.tiles[id]; if (!tile) { tile = this.cache.get(id); if (tile) { tile.uses = 1; this.tiles[id] = tile; } } if (!tile) { tile = this._loadTile(id); this.fire('tile.add', {tile: tile}); } if (tile && tile.loaded && !tile.timeAdded) { tile.timeAdded = new Date().getTime(); if (this.type === 'raster') { this.map.animationLoop.set(this.map.style.rasterFadeDuration); } } return tile; }, _removeTile: function(id) { var tile = this.tiles[id]; if (tile) { tile.uses--; delete this.tiles[id]; if (tile.uses <= 0) { delete tile.timeAdded; if (!tile.loaded) { tile.abort(); tile.remove(); } else { this.cache.add(id, tile); } this.fire('tile.remove', {tile: tile}); } } }, // Taken from polymaps src/Layer.js // https://github.com/simplegeo/polymaps/blob/master/src/Layer.js#L333-L383 // scan-line conversion _scanTriangle: function(a, b, c, ymin, ymax, scanLine) { var ab = this._edge(a, b), bc = this._edge(b, c), ca = this._edge(c, a); var t; // sort edges by y-length if (ab.dy > bc.dy) { t = ab; ab = bc; bc = t; } if (ab.dy > ca.dy) { t = ab; ab = ca; ca = t; } if (bc.dy > ca.dy) { t = bc; bc = ca; ca = t; } // scan span! scan span! if (ab.dy) this._scanSpans(ca, ab, ymin, ymax, scanLine); if (bc.dy) this._scanSpans(ca, bc, ymin, ymax, scanLine); }, // scan-line conversion _edge: function(a, b) { if (a.row > b.row) { var t = a; a = b; b = t; } return { x0: a.column, y0: a.row, x1: b.column, y1: b.row, dx: b.column - a.column, dy: b.row - a.row }; }, // scan-line conversion _scanSpans: function(e0, e1, ymin, ymax, scanLine) { var y0 = Math.max(ymin, Math.floor(e1.y0)), y1 = Math.min(ymax, Math.ceil(e1.y1)); // sort edges by x-coordinate if ((e0.x0 == e1.x0 && e0.y0 == e1.y0) ? (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) : (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) { var t = e0; e0 = e1; e1 = t; } // scan lines! var m0 = e0.dx / e0.dy, m1 = e1.dx / e1.dy, d0 = e0.dx > 0, // use y + 1 to compute x0 d1 = e1.dx < 0; // use y + 1 to compute x1 for (var y = y0; y < y1; y++) { var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0, x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0; scanLine(Math.floor(x1), Math.ceil(x0), y); } }, _z_order: function(a, b) { return (b % 32) - (a % 32); }, _centerOut: function(a, b) { var tr = this.map.transform; var aPos = TileCoord.fromID(a); var bPos = TileCoord.fromID(b); var c = TileCoord.zoomTo(tr.locationCoordinate(tr.center), aPos.z); var center = new Point(c.column - 0.5, c.row - 0.5); return center.dist(aPos) - center.dist(bPos); }, }); var sources = { vector: Source, raster: Source, geojson: require('./geojsonsource'), video: require('./videosource') }; Source.create = function(source) { return new sources[source.type](source); }; },{"../util/ajax.js":76,"../util/evented.js":82,"../util/mrucache.js":84,"../util/url.js":86,"../util/util.js":87,"./geojsonsource":36,"./rastertile.js":39,"./tilecoord":42,"./vectortile":44,"./videosource":45,"point-geometry":98}],41:[function(require,module,exports){ 'use strict'; var glmatrix = require('../lib/glmatrix.js'), mat2 = glmatrix.mat2, mat4 = glmatrix.mat4, vec2 = glmatrix.vec2; module.exports = Tile; function Tile() {} Tile.prototype = { // todo unhardcode tileExtent: 4096, calculateMatrices: function(z, x, y, transform, painter) { // Initialize model-view matrix that converts from the tile coordinates // to screen coordinates. var tileScale = Math.pow(2, z); var scale = transform.worldSize / tileScale; // TODO: remove this.scale = scale; // The position matrix this.posMatrix = mat4.create(); mat4.translate(this.posMatrix, this.posMatrix, [transform.centerPoint.x, transform.centerPoint.y, 0]); mat4.rotateZ(this.posMatrix, this.posMatrix, transform.angle); mat4.translate(this.posMatrix, this.posMatrix, [-transform.centerPoint.x, -transform.centerPoint.y, 0]); var pixelX = transform.width / 2 - transform.x, pixelY = transform.height / 2 - transform.y; mat4.translate(this.posMatrix, this.posMatrix, [pixelX + x * scale, pixelY + y * scale, 1]); // Create inverted matrix for interaction this.invPosMatrix = mat4.create(); mat4.invert(this.invPosMatrix, this.posMatrix); mat4.scale(this.posMatrix, this.posMatrix, [ scale / this.tileExtent, scale / this.tileExtent, 1 ]); mat4.multiply(this.posMatrix, painter.projectionMatrix, this.posMatrix); // The extrusion matrix. this.exMatrix = mat4.clone(painter.projectionMatrix); mat4.rotateZ(this.exMatrix, this.exMatrix, transform.angle); // 2x2 matrix for rotating points this.rotationMatrix = mat2.create(); mat2.rotate(this.rotationMatrix, this.rotationMatrix, transform.angle); }, positionAt: function(id, point) { // tile hasn't finished loading if (!this.invPosMatrix) return null; var pos = vec2.transformMat4([], [point.x, point.y], this.invPosMatrix); vec2.scale(pos, pos, 4096 / this.scale); return { x: pos[0], y: pos[1], scale: this.scale }; }, featuresAt: function(pos, params, callback) { this.source.map.dispatcher.send('query features', { id: this.id, x: pos.x, y: pos.y, scale: pos.scale, source: this.source.id, params: params }, callback, this.workerID); } }; },{"../lib/glmatrix.js":21}],42:[function(require,module,exports){ 'use strict'; /* * Tiles are generally represented as packed integer ids constructed by * `TileCoord.toID(x, y, z)` */ var TileCoord = exports; TileCoord.toID = function(z, x, y, w) { w = w || 0; w *= 2; if (w < 0) w = w * -1 -1; var dim = 1 << z; return ((dim * dim * w + dim * y + x) * 32) + z; }; TileCoord.asString = function(id) { var pos = TileCoord.fromID(id); return pos.z + "/" + pos.x + "/" + pos.y; }; /* * Parse a packed integer id into an object with x, y, and z properties */ TileCoord.fromID = function(id) { var z = id % 32, dim = 1 << z; var xy = ((id - z) / 32); var x = xy % dim, y = ((xy - x) / dim) % dim; var w = Math.floor(xy / (dim * dim)); if (w % 2 !== 0) w = w * -1 -1; w /= 2; return { z: z, x: x, y: y, w: w }; }; /* * Given a packed integer id, return its zoom level */ TileCoord.zoom = function(id) { return id % 32; }; // Given an id and a list of urls, choose a url template and return a tile URL TileCoord.url = function(id, urls) { var pos = TileCoord.fromID(id); return urls[Math.floor((pos.x + pos.y) % urls.length)] .replace('{h}', (pos.x % 16).toString(16) + (pos.y % 16).toString(16)) .replace('{z}', pos.z.toFixed(0)) .replace('{x}', pos.x.toFixed(0)) .replace('{y}', pos.y.toFixed(0)); }; /* * Given a packed integer id, return the id of its parent tile */ TileCoord.parent = function(id) { var pos = TileCoord.fromID(id); if (pos.z === 0) return id; else return TileCoord.toID(pos.z - 1, Math.floor(pos.x / 2), Math.floor(pos.y / 2)); }; TileCoord.parentWithZoom = function(id, zoom) { var pos = TileCoord.fromID(id); while (pos.z > zoom) { pos.z--; pos.x = Math.floor(pos.x / 2); pos.y = Math.floor(pos.y / 2); } return TileCoord.toID(pos.z, pos.x, pos.y); }; /* * Given a packed integer id, return an array of integer ids representing * its four children. */ TileCoord.children = function(id) { var pos = TileCoord.fromID(id); pos.z += 1; pos.x *= 2; pos.y *= 2; return [ TileCoord.toID(pos.z, pos.x, pos.y, pos.w), TileCoord.toID(pos.z, pos.x + 1, pos.y, pos.w), TileCoord.toID(pos.z, pos.x, pos.y + 1, pos.w), TileCoord.toID(pos.z, pos.x + 1, pos.y + 1, pos.w) ]; }; TileCoord.zoomTo = function(c, z) { c.column = c.column * Math.pow(2, z - c.zoom); c.row = c.row * Math.pow(2, z - c.zoom); c.zoom = z; return c; }; },{}],43:[function(require,module,exports){ 'use strict'; var rewind = require('geojson-rewind'); var TileCoord = require('./tilecoord.js'); var Transform = require('../geo/transform.js'); var Point = require('point-geometry'); var LatLng = require('../geo/latlng.js'); module.exports = tileGeoJSON; function tileGeoJSON(geojson, zoom) { var tiles = {}; var tileExtent = 4096; var transform = new Transform(); transform.zoom = zoom; geojson = rewind(geojson); if (geojson.type === 'FeatureCollection') { for (var i = 0; i < geojson.features.length; i++) { tileFeature(geojson.features[i], transform, tiles, tileExtent); } } else if (geojson.type === 'Feature') { tileFeature(geojson, transform, tiles, tileExtent); } else { throw('Unrecognized geojson type'); } return tiles; } function tileFeature(feature, transform, tiles, tileExtent) { var coords = feature.geometry.coordinates; var type = feature.geometry.type; var tiled; if (type === 'Point') { tiled = tileLineString([coords], transform, tileExtent); } else if (type === 'LineString' || type === 'MultiPoint') { tiled = tileLineString(coords, transform, tileExtent); } else if (type === 'Polygon' || type === 'MultiLineString') { tiled = {}; for (var i = 0; i < coords.length; i++) { var tiled_ = tileLineString(coords[i], transform, tileExtent, type === 'Polygon'); for (var tileID in tiled_) { if (!tiled[tileID]) tiled[tileID] = []; tiled[tileID] = (tiled[tileID] || []).concat(tiled_[tileID]); } } } else if (type === 'MultiPolygon') { throw("todo"); } else { throw("unrecognized geometry type"); } for (var id in tiled) { tiles[id] = tiles[id] || []; tiles[id].push({ properties: feature.properties, coords: tiled[id], type: feature.geometry.type }); } } function tileLineString(coords, transform, tileExtent, rejoin) { var padding = 0.01; var paddedExtent = tileExtent * (1 + 2 * padding); var coord = transform.locationCoordinate(new LatLng(coords[0][1], coords[0][0])); var prevCoord; var tiles = {}; for (var i = 0; i < coords.length; i++) { prevCoord = coord; coord = transform.locationCoordinate(new LatLng(coords[i][1], coords[i][0])); var dx = coord.column - prevCoord.column || Number.MIN_VALUE, dy = coord.row - prevCoord.row || Number.MIN_VALUE, dirX = dx / Math.abs(dx), dirY = dy / Math.abs(dy); // Find the rectangular bounding box, in tiles, of the polygon var startTileX = Math.floor(prevCoord.column - dirX * padding); var endTileX = Math.floor(coord.column + dirX * padding); var startTileY = Math.floor(prevCoord.row - dirY * padding); var endTileY = Math.floor(coord.row + dirY * padding); // Iterate over all tiles the segment might intersect // and split the segment across those tiles for (var x = startTileX; (x - endTileX) * dirX <= 0; x += dirX) { var leftX = (x - padding - prevCoord.column) / dx; var rightX = (x + 1 + padding - prevCoord.column) / dx; for (var y = startTileY; (y - endTileY) * dirY <= 0; y += dirY) { var topY = (y - padding - prevCoord.row) / dy; var bottomY = (y + 1 + padding - prevCoord.row) / dy; // fraction of the distance along the segment at which the segment // enters or exits the tile var enter = Math.max(Math.min(leftX, rightX), Math.min(topY, bottomY)); var exit = Math.min(Math.max(leftX, rightX), Math.max(topY, bottomY)); var tileID = TileCoord.toID(transform.tileZoom, x, y), tile = tiles[tileID], point; // segments starts outside the tile, add entry point if (0 <= enter && enter < 1) { point = new Point( ((prevCoord.column + enter * dx) - x) * tileExtent, ((prevCoord.row + enter * dy) - y) * tileExtent); point.continues = true; if (!tile) tiles[tileID] = tile = []; tile.push([point]); } // segments ends outside the tile, add exit point if (0 <= exit && exit < 1) { point = new Point( ((prevCoord.column + exit * dx) - x) * tileExtent, ((prevCoord.row + exit * dy) - y) * tileExtent); point.continues = true; tile[tile.length - 1].push(point); // add the point itself } else { point = new Point( (coord.column - x) * tileExtent, (coord.row - y) * tileExtent); if (!tile) tiles[tileID] = tile = [[point]]; else tile[tile.length - 1].push(point); } } } } if (rejoin) { // reassemble the disconnected segments into a linestring // sections of the linestring outside the tile are replaced with segments // that follow the tile's edge for (var id in tiles) { var segments = tiles[id]; if (!segments[0][0].continues && segments.length > 1) { // if the first segment is the beginning of the linestring // then join it with the last so that all segments start and // end at tile boundaries var last = segments.pop(); Array.prototype.unshift.apply(segments[0], last.slice(0, last.length - 1)); } var start = edgeDist(segments[0][0], tileExtent, padding); for (var k = 0; k < segments.length; k++) { // Add all tile corners along the path between the current segment's exit point // and the next segment's entry point var thisExit = edgeDist(segments[k][segments[k].length - 1], paddedExtent); var nextEntry = edgeDist(segments[(k + 1) % segments.length][0], paddedExtent); var startToExit = (thisExit - start + 4) % 4; var startToNextEntry = (nextEntry - start + 4) % 4; var direction = (thisExit === nextEntry || startToExit < startToNextEntry) ? 1 : -1; var roundFn = direction > 0 ? Math.ceil : Math.floor; for (var c = roundFn(thisExit) % 4; c != roundFn(nextEntry) % 4; c = (c + direction + 4) % 4) { var corner = corners[c]; segments[k].push(new Point( (corner.x + (corner.x - 0.5 > 0 ? 1 : -1) * padding) * tileExtent, (corner.y + (corner.y - 0.5 > 0 ? 1 : -1) * padding) * tileExtent)); } } // Join all segments tiles[id] = [Array.prototype.concat.apply([], segments)]; } } return tiles; } var corners = [ new Point(0, 0), new Point(1, 0), new Point(1, 1), new Point(0, 1)]; /* * Converts to a point to the distance along the edge of the tile (out of 4). * * 0.5 * 0 _______ 1 * | | * 3.5 | | 1.5 * | | * |_______| * 3 2.5 2 */ function edgeDist(point, extent) { var x = point.x / extent; var y = point.y / extent; var d; if (Math.abs(y - 0.5) >= Math.abs(x - 0.5)) { d = Math.round(y) * 2 + (y < 0.5 ? x : 1 - x); } else { d = Math.round(1 - x) * 2 + (x > 0.5 ? y : 1 - y) + 1; } return d % 4; } },{"../geo/latlng.js":17,"../geo/transform.js":19,"./tilecoord.js":42,"geojson-rewind":92,"point-geometry":98}],44:[function(require,module,exports){ 'use strict'; var Tile = require('./tile.js'), TileCoord = require('./tilecoord.js'), BufferSet = require('../data/buffer/bufferset.js'), util = require('../util/util.js'); var createBucket = require('../data/createbucket.js'); module.exports = VectorTile; function VectorTile(id, source, url, callback) { this.id = id; this.loaded = false; this.url = url; this.zoom = TileCoord.fromID(id).z; this.map = source.map; this.options = source.options; this.id = util.uniqueId(); this.callback = callback; this.source = source; if (this.zoom >= source.tileJSON.maxzoom) { this.depth = this.map.options.maxZoom - this.zoom; } else { this.depth = 1; } this.uses = 1; this._load(); } VectorTile.prototype = util.inherit(Tile, { _load: function() { var tile = this; this.workerID = this.map.dispatcher.send('load tile', { url: this.url, id: this.id, zoom: this.zoom, maxZoom: this.source.tileJSON.maxzoom, tileSize: this.options.tileSize, source: this.source.id, depth: this.depth }, function(err, data) { if (!err && data) { tile.onTileLoad(data); } tile.callback(err); }); }, onTileLoad: function(data) { // Tile has been removed from the map if (!this.map) return; this.buffers = new BufferSet(data.buffers); this.buckets = {}; for (var b in data.elementGroups) { this.buckets[b] = createBucket(this.map.style.buckets[b], this.buffers, undefined, data.elementGroups[b]); } this.loaded = true; }, remove: function() { // reuse prerendered textures for (var bucket in this.buckets) { if (this.buckets[bucket].prerendered) this.map.painter.saveTexture(this.buckets[bucket].prerendered.texture); } this.map.dispatcher.send('remove tile', { id: this.id, source: this.source.id }, null, this.workerID); this.map.painter.glyphAtlas.removeGlyphs(this.id); var gl = this.map.painter.gl; var buffers = this.buffers; if (buffers) { for (var b in buffers) { buffers[b].destroy(gl); } } delete this.map; }, abort: function() { this.map.dispatcher.send('abort tile', { id: this.id, source: this.source.id }, null, this.workerID); } }); },{"../data/buffer/bufferset.js":2,"../data/createbucket.js":10,"../util/util.js":87,"./tile.js":41,"./tilecoord.js":42}],45:[function(require,module,exports){ 'use strict'; var Tile = require('./tile.js'); var TileCoord = require('./tilecoord.js'); var LatLng = require('../geo/latlng.js'); var Point = require('point-geometry'); module.exports = VideoSource; function VideoSource(options) { this.video = document.createElement('video'); this.video.crossOrigin = 'Anonymous'; this.video.loop = true; var urls = (typeof options.url === 'string') ? [options.url] : options.url; for (var i = 0; i < urls.length; i++) { var s = document.createElement('source'); s.src = urls[i]; this.video.appendChild(s); } this.coordinates = options.coordinates; this.enabled = true; var loopID; var source = this; // start repainting when video starts playing this.video.addEventListener('playing', function() { loopID = source.map.style.animationLoop.set(Infinity); source.map._rerender(); }); // stop repainting when video stops this.video.addEventListener('pause', function() { source.map.style.animationLoop.cancel(loopID); }); } VideoSource.prototype.onAdd = function(map) { this.map = map; this.video.play(); this.createTile(); }; VideoSource.prototype.createTile = function() { /* * Calculate which mercator tile is suitable for rendering the video in * and create a buffer with the corner coordinates. These coordinates * may be outside the tile, because raster tiles aren't clipped when rendering. */ var map = this.map; var coords = this.coordinates.map(function(latlng) { var loc = LatLng.convert(latlng); return TileCoord.zoomTo(map.transform.locationCoordinate(loc), 0); }); var minX = Infinity; var minY = Infinity; var maxX = -Infinity; var maxY = -Infinity; for (var i = 0; i < coords.length; i++) { minX = Math.min(minX, coords[i].column); minY = Math.min(minY, coords[i].row); maxX = Math.max(maxX, coords[i].column); maxY = Math.max(maxY, coords[i].row); } var dx = maxX - minX; var dy = maxY - minY; var dMax = Math.max(dx, dy); var center = TileCoord.zoomTo({ column: (minX + maxX) / 2, row: (minY + maxY) / 2, zoom: 0 }, Math.floor(-Math.log(dMax) / Math.LN2)); var tileExtent = 4096; var tileCoords = coords.map(function(coord) { var zoomedCoord = TileCoord.zoomTo(coord, center.zoom); return new Point( Math.round((zoomedCoord.column - center.column) * tileExtent), Math.round((zoomedCoord.row - center.row) * tileExtent)); }); var gl = map.painter.gl; var maxInt16 = 32767; var array = new Int16Array([ tileCoords[0].x, tileCoords[0].y, 0, 0, tileCoords[1].x, tileCoords[1].y, maxInt16, 0, tileCoords[3].x, tileCoords[3].y, 0, maxInt16, tileCoords[2].x, tileCoords[2].y, maxInt16, maxInt16 ]); this.boundsBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.boundsBuffer); gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); this.tile = new Tile(); this.center = center; }; VideoSource.prototype.load = function() { // noop }; VideoSource.prototype.update = function() { // noop }; VideoSource.prototype.render = function(layers) { if (!this.enabled) return; if (this.video.readyState < 2) return; // not enough data for current position var layer = layers[0]; var bucket = { type: 'raster', tile: this, boundsBuffer: this.boundsBuffer, bind: this.bind.bind(this) }; var buckets = {}; buckets[layer.bucket] = bucket; var c = this.center; this.tile.calculateMatrices(c.zoom, c.column, c.row, this.map.transform, this.map.painter); this.map.painter.tile = this.tile; this.map.painter.applyStyle(layer, this.map.style, buckets, {}); }; VideoSource.prototype.bind = function(gl) { if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video); } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video); } }; VideoSource.prototype.featuresAt = function(point, params, callback) { // TODO return pixel? return callback(null, []); }; },{"../geo/latlng.js":17,"./tile.js":41,"./tilecoord.js":42,"point-geometry":98}],46:[function(require,module,exports){ 'use strict'; var Actor = require('../util/actor.js'), bucketFilter = require('../style/bucketfilter.js'), WorkerTile = require('./workertile.js'), tileGeoJSON = require('./tilegeojson.js'), Wrapper = require('./geojsonwrapper.js'), util = require('../util/util.js'), queue = require('queue-async'), ajax = require('../util/ajax.js'); module.exports = Worker; function Worker(self) { this.self = self; this.actor = new Actor(self, this); } util.extend(Worker.prototype, { alert: function() { this.self.postMessage({ type: 'alert message', data: [].slice.call(arguments) }); }, // Updates the style to use for this map. 'set buckets': function(data) { var buckets = WorkerTile.buckets = data; for (var i = 0; i < buckets.length; i++) { var bucket = buckets[i]; bucket.compare = bucketFilter(bucket.filter); } }, 'set glyphs': function(data) { WorkerTile.prototype.glyphs = data; }, /* * Load and parse a tile at `url`, and call `callback` with * (err, response) * * @param {string} url * @param {function} callback */ 'load tile': function(params, callback) { new WorkerTile(params.url, undefined, params.id, params.zoom, params.maxZoom, params.tileSize, params.source, params.depth, this.actor, callback); }, /* * Abort the request keyed under `url` * * @param {string} url */ 'abort tile': function(params) { WorkerTile.cancel(params.id, params.source); }, 'remove tile': function(params) { var id = params.id; var source = params.source; if (WorkerTile.loaded[source] && WorkerTile.loaded[source][id]) { delete WorkerTile.loaded[source][id]; } }, 'parse geojson': function(params, callback) { var data = params.data, zooms = params.zooms, len = zooms.length, maxZoom = zooms[len - 1], actor = this.actor, q = queue(); function worker(id, tile, zoom, callback) { new WorkerTile(undefined, new Wrapper(tile), id, zoom, maxZoom, params.tileSize, params.source, 4, actor, function(err, data) { if (err) return callback(err); data.id = id; callback(null, data); }); } function tileData(err, data) { if (err) throw err; for (var i = 0; i < len; i++) { var zoom = zooms[i]; var tiles = tileGeoJSON(data, zoom); for (var id in tiles) { q.defer(worker, id, tiles[id], zoom); } } q.awaitAll(callback); } if (typeof data === 'string') ajax.getJSON(data, tileData); else tileData(null, data); }, 'query features': function(params, callback) { var tile = WorkerTile.loaded[params.source] && WorkerTile.loaded[params.source][params.id]; if (tile) { tile.featureTree.query(params, callback); } else { callback(null, []); } } }); },{"../style/bucketfilter.js":49,"../util/actor.js":75,"../util/ajax.js":76,"../util/util.js":87,"./geojsonwrapper.js":38,"./tilegeojson.js":43,"./workertile.js":47,"queue-async":99}],47:[function(require,module,exports){ 'use strict'; var FeatureTree = require('../data/featuretree.js'); var Protobuf = require('pbf'); var vt = require('vector-tile'); var Collision = require('../symbol/collision.js'); var getArrayBuffer = require('../util/ajax.js').getArrayBuffer; var BufferSet = require('../data/buffer/bufferset.js'); var createBucket = require('../data/createbucket.js'); module.exports = WorkerTile; function WorkerTile(url, data, id, zoom, maxZoom, tileSize, source, depth, actor, callback) { var tile = this; this.id = id; this.zoom = zoom; this.maxZoom = maxZoom; this.tileSize = tileSize; this.source = source; this.depth = depth; this.buffers = new BufferSet(); function loaded(data) { WorkerTile.loaded[source] = WorkerTile.loaded[source] || {}; WorkerTile.loaded[source][id] = tile; tile.data = data; tile.parse(data, actor, callback); } if (url) { if (WorkerTile.loading[source] === undefined) WorkerTile.loading[source] = {}; WorkerTile.loading[source][id] = getArrayBuffer(url, function(err, data) { delete WorkerTile.loading[source][id]; if (err) { callback(err); } else { loaded(new vt.VectorTile(new Protobuf(new Uint8Array(data)))); } }); } else { loaded(data); } } WorkerTile.cancel = function(id, sourceID) { var source = WorkerTile.loading[sourceID]; if (source && source[id]) { source[id].abort(); delete source[id]; } }; // Stores tiles that are currently loading. WorkerTile.loading = {}; // Stores tiles that are currently loaded. WorkerTile.loaded = {}; // Stores the style information. WorkerTile.buckets = []; /* * Given tile data, parse raw vertices and data, create a vector * tile and parse it into ready-to-render vertices. * * @param {object} data * @param {function} respond */ WorkerTile.prototype.parse = function(data, actor, callback) { var tile = this; var bucketInfo = WorkerTile.buckets; this.callback = callback; var tileExtent = 4096; this.collision = new Collision(this.zoom, tileExtent, this.tileSize, this.depth); this.featureTree = new FeatureTree(getGeometry, getType); var buckets = this.buckets = sortTileIntoBuckets(this, data, bucketInfo); var key, bucket; var prevPlacementBucket; var remaining = WorkerTile.buckets.length; /* * The async parsing here is a bit tricky. * Some buckets depend on resources that may need to be loaded async (glyphs). * Some buckets need to be parsed in order (to get placement priorities right). * * Dependencies calls are initiated first to get those rolling. * Buckets that don't need to be parsed in order, aren't to save time. */ var orderedBuckets = WorkerTile.buckets; for (var i = 0; i < orderedBuckets.length; i++) { bucket = buckets[orderedBuckets[i].id]; if (!bucket) { remaining--; continue; // raster bucket, etc } var filter = bucket.info.filter; if (filter && filter.source !== this.source) continue; // Link buckets that need to be parsed in order if (bucket.collision) { if (prevPlacementBucket) { prevPlacementBucket.next = bucket; } else { bucket.previousPlaced = true; } prevPlacementBucket = bucket; } if (bucket.getDependencies) { bucket.getDependencies(this, actor, dependenciesDone(bucket)); } } // parse buckets where order doesn't matter and no dependencies for (key in buckets) { bucket = buckets[key]; if (!bucket.getDependencies && !bucket.collision) { parseBucket(tile, bucket); } } function dependenciesDone(bucket) { return function(err) { bucket.dependenciesLoaded = true; parseBucket(tile, bucket, err); }; } function parseBucket(tile, bucket, skip) { if (bucket.getDependencies && !bucket.dependenciesLoaded) return; if (bucket.collision && !bucket.previousPlaced) return; if (!skip) { var now = Date.now(); if (bucket.type !== 'raster') bucket.addFeatures(); var time = Date.now() - now; if (bucket.interactive) { for (var i = 0; i < bucket.features.length; i++) { var feature = bucket.features[i]; tile.featureTree.insert(feature.bbox(), bucket.name, feature); } } if (typeof self !== 'undefined') { self.bucketStats = self.bucketStats || {_total: 0}; self.bucketStats._total += time; self.bucketStats[bucket.name] = (self.bucketStats[bucket.name] || 0) + time; } } remaining--; if (!remaining) return tile.done(); // try parsing the next bucket, if it is ready if (bucket.next) { bucket.next.previousPlaced = true; parseBucket(tile, bucket.next); } } }; WorkerTile.prototype.done = function() { // Collect all buffers to mark them as transferable object. var buffers = []; for (var type in this.buffers) { buffers.push(this.buffers[type].array); } // Convert buckets to a transferable format var buckets = this.buckets; var elementGroups = {}; for (var b in buckets) elementGroups[b] = buckets[b].elementGroups; this.callback(null, { elementGroups: elementGroups, buffers: this.buffers }, buffers); // we don't need anything except featureTree at this point, so we mark it for GC this.buffers = null; this.collision = null; this.buckets = null; }; function sortTileIntoBuckets(tile, data, bucketInfo) { var sourceLayers = {}, buckets = {}, layerName; // For each source layer, find a list of buckets that use data from it for (var i = 0; i < bucketInfo.length; i++) { var info = bucketInfo[i]; var bucketName = info.id; var minZoom = info['min-zoom']; var maxZoom = info['max-zoom']; if (info.source !== tile.source) continue; if (minZoom && tile.zoom < minZoom && minZoom < tile.maxZoom) continue; if (maxZoom && tile.zoom >= maxZoom) continue; var bucket = createBucket(info, tile.buffers, tile.collision); if (!bucket) continue; bucket.features = []; bucket.name = bucketName; buckets[bucketName] = bucket; if (data.layers) { // vectortile layerName = info['source-layer']; if (!sourceLayers[layerName]) sourceLayers[layerName] = {}; sourceLayers[layerName][bucketName] = info; } else { // geojson tile sourceLayers[bucketName] = info; } } // read each layer, and sort its feature's into buckets if (data.layers) { // vectortile for (layerName in sourceLayers) { var layer = data.layers[layerName]; if (!layer) continue; sortLayerIntoBuckets(layer, sourceLayers[layerName], buckets); } } else { // geojson sortLayerIntoBuckets(data, sourceLayers, buckets); } return buckets; } /* * Sorts features in a layer into different buckets, according to the maping * * Layers in vector tiles contain many different features, and feature types, * e.g. the landuse layer has parks, industrial buildings, forests, playgrounds * etc. However, when styling, we need to separate these features so that we can * render them separately with different styles. * * @param {VectorTileLayer} layer * @param {Mapping} mapping */ function sortLayerIntoBuckets(layer, mapping, buckets) { for (var i = 0; i < layer.length; i++) { var feature = layer.feature(i); for (var key in mapping) { if (mapping[key].compare(feature)) { buckets[key].features.push(feature); } } } } function getGeometry(feature) { return feature.loadGeometry(); } function getType(feature) { return vt.VectorTileFeature.types[feature.type]; } },{"../data/buffer/bufferset.js":2,"../data/createbucket.js":10,"../data/featuretree.js":12,"../symbol/collision.js":59,"../util/ajax.js":76,"pbf":96,"vector-tile":102}],48:[function(require,module,exports){ 'use strict'; module.exports = AnimationLoop; function AnimationLoop() { this.n = 0; this.times = []; } // Are all animations done? AnimationLoop.prototype.stopped = function() { this.times = this.times.filter(function(t) { return t.time >= (new Date()).getTime(); }); return !this.times.length; }; // Add a new animation that will run t milliseconds // Returns an id that can be used to cancel it layer AnimationLoop.prototype.set = function(t) { this.times.push({ id: this.n, time: t + (new Date()).getTime() }); return this.n++; }; // Cancel an animation AnimationLoop.prototype.cancel = function(n) { this.times = this.times.filter(function(t) { return t.id != n; }); }; },{}],49:[function(require,module,exports){ 'use strict'; var VectorTileFeature = require('vector-tile').VectorTileFeature; function infix(operator) { return function(left, right) { return left + ' ' + operator + ' ' + right; }; } var infixOperators = { '==': infix('==='), '>': infix('>'), '$gt': infix('>'), '<': infix('<'), '$lt': infix('<'), '<=': infix('<='), '$lte': infix('<='), '>=': infix('>='), '$gte': infix('>='), '!=': infix('!=='), '$ne': infix('!=='), '$exists': function (value) { return value + ' !== undefined'; } }; function or(items) { return '(' + items.join(' || ') + ')'; } function and(items) { return '(' + items.join(' && ') + ')'; } function not(item) { return '!' + item; } function nor(items) { return not(or(items)); } var arrayOperators = { '||': or, '$or': or, '&&': and, '$and': and, '!': nor, '$nor': nor }; var objOperators = { '!': not, '$not': not }; module.exports = function (filter) { // simple key & value comparison function valueFilter(key, value, operator) { return operator('p[' + JSON.stringify(key) + ']', JSON.stringify(value)); } // compares key & value or key & or(values) function simpleFieldFilter(key, value, operator) { var operatorFn = infixOperators[operator || '==']; if (!operatorFn) throw new Error('Unknown operator: ' + operator); if (Array.isArray(value)) { return or(value.map(function (v) { return valueFilter(key, v, operatorFn); })); } else return valueFilter(key, value, operatorFn); } // handles any filter key/value pair function fieldFilter(key, value) { if (Array.isArray(value)) { if (key in arrayOperators) { // handle and/or operators return arrayOperators[key](value.map(fieldsFilter)); } } else if (typeof value === 'object') { // handle not operator if (key in objOperators) return objOperators[key](fieldsFilter(value)); // handle {key: {operator: value}} notation var filters = []; for (var op in value) { filters.push(simpleFieldFilter(key, value[op], op)); } return and(filters); } // handle simple key/value or key/values comparison return simpleFieldFilter(key, value); } function typeFilter(type) { return 'f.type === ' + VectorTileFeature.types.indexOf(type); } function fieldsFilter(obj) { var filters = []; for (var key in obj) { if (key === '$type') { filters.push(typeFilter(obj[key])); } else { filters.push(fieldFilter(key, obj[key])); } } return filters.length ? and(filters) : 'true'; } var filterStr = 'var p = f.properties || {}; return ' + fieldsFilter(filter || {}) + ';'; // jshint evil: true return new Function('f', filterStr); }; },{"vector-tile":102}],50:[function(require,module,exports){ 'use strict'; var reference = require('mapbox-gl-style-spec/reference/v4'); module.exports = {}; reference['class'].forEach(function(className) { var Calculated = function() {}; var style = reference[className]; for (var prop in style) { if (style[prop]['default'] === undefined) continue; Calculated.prototype[prop] = style[prop]['default']; } module.exports[className.replace('class_','')] = Calculated; }); },{"mapbox-gl-style-spec/reference/v4":95}],51:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented.js'); var ajax = require('../util/ajax.js'); var browser = require('../util/browser.js'); module.exports = ImageSprite; function ImageSprite(base) { var sprite = this; this.base = base; this.retina = browser.devicePixelRatio > 1; base = sprite.base + (sprite.retina ? '@2x' : ''); ajax.getJSON(base + '.json', function(err, data) { // @TODO handle errors via sprite event. if (err) return; sprite.data = data; if (sprite.img) sprite.fire('loaded'); }); ajax.getImage(base + '.png', function(err, img) { // @TODO handle errors via sprite event. if (err) return; // premultiply the sprite var data = img.getData(); var newdata = img.data = new Uint8Array(data.length); for (var i = 0; i < data.length; i+=4) { var alpha = data[i + 3] / 255; newdata[i + 0] = data[i + 0] * alpha; newdata[i + 1] = data[i + 1] * alpha; newdata[i + 2] = data[i + 2] * alpha; newdata[i + 3] = data[i + 3]; } sprite.img = img; if (sprite.data) sprite.fire('loaded'); }); } ImageSprite.prototype = Object.create(Evented); ImageSprite.prototype.toJSON = function() { return this.base; }; ImageSprite.prototype.loaded = function() { return !!(this.data && this.img); }; ImageSprite.prototype.resize = function(gl) { var sprite = this; if (browser.devicePixelRatio > 1 !== sprite.retina) { var newSprite = new ImageSprite(sprite.base); newSprite.on('loaded', function() { sprite.img = newSprite.img; sprite.data = newSprite.data; sprite.retina = newSprite.retina; if (sprite.texture) { gl.deleteTexture(sprite.texture); delete sprite.texture; } }); } }; ImageSprite.prototype.bind = function(gl, linear) { var sprite = this; if (!sprite.loaded()) return; if (!sprite.texture) { sprite.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, sprite.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); var img = sprite.img; gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, img.width, img.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, img.data); } else { gl.bindTexture(gl.TEXTURE_2D, sprite.texture); } var filter = linear ? gl.LINEAR : gl.NEAREST; if (filter !== sprite.filter) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter); } }; ImageSprite.prototype.getPosition = function(name, repeating) { // `repeating` indicates that the image will be used in a repeating pattern // repeating pattern images are assumed to have a 1px padding that mirrors the opposite edge // positions for repeating images are adjusted to exclude the edge repeating = repeating === true ? 1 : 0; var pos = this.data && this.data[name]; if (pos && this.img) { var width = this.img.width; var height = this.img.height; return { size: [pos.width / pos.pixelRatio, pos.height / pos.pixelRatio], tl: [(pos.x + repeating)/ width, (pos.y + repeating) / height], br: [(pos.x + pos.width - 2 * repeating) / width, (pos.y + pos.height - 2 * repeating) / height] }; } }; },{"../util/ajax.js":76,"../util/browser.js":77,"../util/evented.js":82}],52:[function(require,module,exports){ 'use strict'; var reference = require('mapbox-gl-style-spec/reference/v4'); module.exports = {}; reference.render.forEach(function(className) { var Properties = function(props) { for (var p in props) { this[p] = props[p]; } }; var properties = reference[className]; for (var prop in properties) { if (properties[prop]['default'] === undefined) continue; Properties.prototype[prop] = properties[prop]['default']; } module.exports[className.replace('render_','')] = Properties; }); },{"mapbox-gl-style-spec/reference/v4":95}],53:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented.js'); var StyleTransition = require('./styletransition.js'); var StyleDeclaration = require('./styledeclaration.js'); var StyleConstant = require('./styleconstant.js'); var CalculatedStyle = require('./calculatedstyle.js'); var ImageSprite = require('./imagesprite.js'); var util = require('../util/util.js'); module.exports = Style; /* * The map style's current state * * The stylesheet object is not modified. To change the style, just change * the the stylesheet object and trigger a cascade. */ function Style(stylesheet, animationLoop) { if (stylesheet.version !== 4) console.warn('Stylesheet version must be 4'); if (!Array.isArray(stylesheet.layers)) console.warn('Stylesheet must have layers'); this.classes = {}; this.stylesheet = stylesheet; this.animationLoop = animationLoop; this.buckets = {}; this.orderedBuckets = []; this.transitions = {}; this.computed = {}; this.sources = {}; this.cascade({transition: false}); if (stylesheet.sprite) this.setSprite(stylesheet.sprite); } Style.prototype = Object.create(Evented); function premultiplyLayer(layer, type) { var colorProp = type + '-color', haloProp = type + '-halo-color', outlineProp = type + '-outline-color', color = layer[colorProp], haloColor = layer[haloProp], outlineColor = layer[outlineProp], opacity = layer[type + '-opacity']; var colorOpacity = color && (opacity * color[3]); var haloOpacity = haloColor && (opacity * haloColor[3]); var outlineOpacity = outlineColor && (opacity * outlineColor[3]); if (colorOpacity !== undefined && colorOpacity < 1) { layer[colorProp] = util.premultiply([color[0], color[1], color[2], colorOpacity]); } if (haloOpacity !== undefined && haloOpacity < 1) { layer[haloProp] = util.premultiply([haloColor[0], haloColor[1], haloColor[2], haloOpacity]); } if (outlineOpacity !== undefined && outlineOpacity < 1) { layer[outlineProp] = util.premultiply([outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity]); } } // Formerly known as zoomed styles Style.prototype.recalculate = function(z) { if (typeof z !== 'number') console.warn('recalculate expects zoom level'); var transitions = this.transitions; var layerValues = {}; this.sources = {}; this.rasterFadeDuration = 300; for (var name in transitions) { var layer = transitions[name], bucket = this.buckets[layer.ref || name], layerType = this.layermap[name].type; if (!CalculatedStyle[layerType]) { console.warn('unknown layer type ' + layerType); continue; } var appliedLayer = layerValues[name] = new CalculatedStyle[layerType](); for (var rule in layer) { var transition = layer[rule]; appliedLayer[rule] = transition.at(z); } if (layerType === 'symbol') { appliedLayer.hidden = (appliedLayer['text-opacity'] === 0 || !bucket.render['text-field']) && (appliedLayer['icon-opacity'] === 0 || !bucket.render['icon-image']); if (!appliedLayer.hidden) { premultiplyLayer(appliedLayer, 'text'); premultiplyLayer(appliedLayer, 'icon'); } } else { appliedLayer.hidden = (appliedLayer[layerType + '-opacity'] === 0); if (!appliedLayer.hidden) { premultiplyLayer(appliedLayer, layerType); } } // Find all the sources that are currently being used // so that we can automatically enable/disable them as needed if (!appliedLayer.hidden) { var source = bucket && bucket.source; // mark source as used so that tiles are downloaded if (source) this.sources[source] = true; } if (appliedLayer['raster-fade']) { this.rasterFadeDuration = Math.max(this.rasterFadeDuration, appliedLayer['raster-fade']); } } this.computed = layerValues; this.z = z; this.fire('zoom'); }; Style.prototype._simpleLayer = function(layer) { var simple = {}; simple.id = layer.id; var bucket = this.buckets[layer.ref || layer.id]; if (bucket) simple.bucket = bucket.id; if (layer.type) simple.type = layer.type; if (layer.layers) { simple.layers = []; for (var i = 0; i < layer.layers.length; i++) { simple.layers.push(this._simpleLayer(layer.layers[i])); } } return simple; }; // Split the layers into groups of consecutive layers with the same datasource // For each group calculate its dependencies. Its dependencies are composited // layers that need to be rendered into textures before Style.prototype._groupLayers = function(layers) { var g = 0; var groups = []; var group; // loop over layers top down for (var i = layers.length - 1; i >= 0; i--) { var layer = layers[i]; var bucket = this.buckets[layer.ref || layer.id]; var source = bucket && bucket.source; // if the current layer is in a different source if (group && source !== group.source) g++; if (!groups[g]) { group = []; group.source = source; if (layer.layers) group.composited = true; groups[g] = group; } if (layer.layers && layer.type == 'composite') { // TODO if composited layer is opaque just inline the layers group.dependencies = group.dependencies || {}; group.dependencies[layer.id] = this._groupLayers(layer.layers); } group.push(this._simpleLayer(layer)); } return groups; }; /* * Take all the rules and declarations from the stylesheet, * and figure out which apply currently */ Style.prototype.cascade = function(options) { options = options || { transition: true }; var a, b; var id; var prop; var layer; var className; var styleName; var style; var styleTrans; var constants = this.stylesheet.constants; // derive buckets from layers this.orderedBuckets = []; this.buckets = getbuckets({}, this.orderedBuckets, this.stylesheet.layers); function getbuckets(buckets, ordered, layers) { for (var a = 0; a < layers.length; a++) { var layer = layers[a]; if (layer.layers) { buckets = getbuckets(buckets, ordered, layer.layers); } if (!layer.source || !layer.type) { continue; } var bucket = { id: layer.id }; for (var prop in layer) { if ((/^style/).test(prop)) continue; bucket[prop] = layer[prop]; } bucket.render = StyleConstant.resolve(bucket.render, constants); buckets[layer.id] = bucket; ordered.push(bucket); } return buckets; } // style class keys var styleNames = ['style']; for (className in this.classes) styleNames.push('style.' + className); // apply layer group inheritance resulting in a flattened array var flattened = flattenLayers(this.stylesheet.layers); // map layer ids to layer definitions for resolving refs var layermap = this.layermap = {}; for (a = 0; a < flattened.length; a++) { layer = flattened[a]; var newLayer = {}; for (var k in layer) { if (k === 'layers') continue; newLayer[k] = layer[k]; } layermap[layer.id] = newLayer; flattened[a] = newLayer; } for (a = 0; a < flattened.length; a++) { flattened[a] = resolveLayer(layermap, flattened[a]); } // Resolve layer references. function resolveLayer(layermap, layer) { if (!layer.ref || !layermap[layer.ref]) return layer; var parent = resolveLayer(layermap, layermap[layer.ref]); layer.render = parent.render; layer.type = parent.type; layer.filter = parent.filter; layer.source = parent.source; layer['source-layer'] = parent['source-layer']; layer['min-zoom'] = parent['min-zoom']; layer['max-zoom'] = parent['max-zoom']; return layer; } // Flatten composite layer structures. function flattenLayers(layers) { var flat = []; for (var i = 0; i < layers.length; i++) { flat.push(layers[i]); if (layers[i].layers) { flat.push.apply(flat, flattenLayers(layers[i].layers)); } } return flat; } var transitions = {}; var globalTrans = this.stylesheet.transition; for (a in flattened) { layer = flattened[a]; id = layer.id; style = {}; styleTrans = {}; // basic cascading of styles for (b = 0; b < styleNames.length; b++) { styleName = styleNames[b]; if (!layer[styleName]) continue; // set style properties for (prop in layer[styleName]) { if (prop.indexOf('transition-') === -1) { style[prop] = layer[styleName][prop]; } else { styleTrans[prop.replace('transition-', '')] = layer[styleName][prop]; } } } style = StyleConstant.resolve(style, constants); var renderType = layer.type; transitions[id] = {}; for (prop in style) { var newDeclaration = new StyleDeclaration(renderType, prop, style[prop]); var oldTransition = this.transitions[id] && this.transitions[id][prop]; var newStyleTrans = {}; newStyleTrans.duration = styleTrans[prop] && styleTrans[prop].duration ? styleTrans[prop].duration : globalTrans && globalTrans.duration ? globalTrans.duration : 300; newStyleTrans.delay = styleTrans[prop] && styleTrans[prop].delay ? styleTrans[prop].delay : globalTrans && globalTrans.delay ? globalTrans.delay : 0; if (!options.transition) { newStyleTrans.duration = 0; newStyleTrans.delay = 0; } // Only create a new transition if the declaration changed if (!oldTransition || oldTransition.declaration.json !== newDeclaration.json) { var newTransition = new StyleTransition(newDeclaration, oldTransition, newStyleTrans); transitions[id][prop] = newTransition; // Run the animation loop until the end of the transition if (!newTransition.instant()) { newTransition.loopID = this.animationLoop.set(newTransition.endTime - (new Date()).getTime()); } if (oldTransition) { this.animationLoop.cancel(oldTransition.loopID); } } else { transitions[id][prop] = oldTransition; } } } this.transitions = transitions; this.layerGroups = this._groupLayers(this.stylesheet.layers); this.fire('change'); }; /* This should be moved elsewhere. Localizing resources doesn't belong here */ Style.prototype.setSprite = function(sprite) { this.sprite = new ImageSprite(sprite); this.sprite.on('loaded', this.fire.bind(this, 'change')); }; // Modify classes Style.prototype.addClass = function(n, options) { if (this.classes[n]) return; // prevent unnecessary recalculation this.classes[n] = true; this.cascade(options); }; Style.prototype.removeClass = function(n, options) { if (!this.classes[n]) return; // prevent unnecessary recalculation delete this.classes[n]; this.cascade(options); }; Style.prototype.hasClass = function(n) { return !!this.classes[n]; }; Style.prototype.setClassList = function(l, options) { this.classes = {}; for (var i = 0; i < l.length; i++) { this.classes[l[i]] = true; } this.cascade(options); }; Style.prototype.getClassList = function() { return Object.keys(this.classes); }; Style.prototype.getLayer = function(id) { return this.layermap[id]; }; },{"../util/evented.js":82,"../util/util.js":87,"./calculatedstyle.js":50,"./imagesprite.js":51,"./styleconstant.js":54,"./styledeclaration.js":55,"./styletransition.js":56}],54:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'); module.exports.resolve = function (properties, constants) { if (!constants) return properties; var result = {}, i; function resolve(value) { return typeof value === 'string' && value[0] === '@' ? constants[value] : value; } for (var key in properties) { var value = resolve(properties[key]); if (Array.isArray(value)) { value = value.slice(); for (i = 0; i < value.length; i++) { if (value[i] in constants) { value[i] = resolve(value[i]); } } } if (value.stops) { value = util.extend({}, value); value.stops = value.stops.slice(); for (i = 0; i < value.stops.length; i++) { if (value.stops[i][1] in constants) { value.stops[i] = [ value.stops[i][0], resolve(value.stops[i][1]) ]; } } } result[key] = value; } return result; }; },{"../util/util.js":87}],55:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'), reference = require('mapbox-gl-style-spec/reference/v4'), parseCSSColor = require('csscolorparser').parseCSSColor; module.exports = StyleDeclaration; /* * A parsed representation of a property:value pair */ function StyleDeclaration(renderType, prop, value) { var className = 'class_' + renderType; var propReference = reference[className] && reference[className][prop]; if (!propReference) return; this.value = this.parseValue(value, propReference.type, propReference.values); this.prop = prop; this.type = propReference.type; // immuatable representation of value. used for comparison this.json = JSON.stringify(value); } StyleDeclaration.prototype.calculate = function(z) { return typeof this.value === 'function' ? this.value(z) : this.value; }; StyleDeclaration.prototype.parseValue = function(value, type, values) { if (type === 'color') { return parseColor(value); } else if (type === 'number') { return parseNumber(value); } else if (type === 'boolean') { return Boolean(value); } else if (type === 'image') { return String(value); } else if (type === 'string') { return String(value); } else if (type === 'array') { return parseNumberArray(value); } else if (type === 'enum' && Array.isArray(values)) { return values.indexOf(value) >= 0 ? value : undefined; } else { console.warn(type + ' is not a supported property type'); } }; function parseNumber(num) { if (num.stops) num = stopsFn(num); var value = +num; return !isNaN(value) ? value : num; } function parseNumberArray(array) { var widths = array.map(parseNumber); return function(z) { var result = []; for (var i = 0; i < widths.length; i++) { result.push(typeof widths[i] === 'function' ? widths[i](z) : widths[i]); } return result; }; } var colorCache = {}; function parseColor(value) { if (value.stops) { for (var i = 0; i < value.stops.length; i++) { // store the parsed color as the 3rd element in the array value.stops[i][2] = parseCSSColor(value.stops[i][1]); } return stopsFn(value, true); } if (colorCache[value]) { return colorCache[value]; } var color = prepareColor(parseCSSColor(value)); colorCache[value] = color; return color; } function stopsFn(params, color) { var stops = params.stops; var base = params.base || reference.function.base.default; return function(z) { // find the two stops which the current z is between var low = null; var high = null; for (var i = 0; i < stops.length; i++) { var stop = stops[i]; if (stop[0] <= z) low = stop; if (stop[0] > z) { high = stop; break; } } if (low && high) { var zoomDiff = high[0] - low[0]; var zoomProgress = z - low[0]; var t = 0; if (base == 1) { t = zoomProgress / zoomDiff; } else { t = (Math.pow(base, zoomProgress) - 1) / (Math.pow(base, zoomDiff) - 1); } if (color) return prepareColor(interpColor(low[2], high[2], t)); else return util.interp(low[1], high[1], t); } else if (low) { if (color) return prepareColor(low[2]); else return low[1]; } else if (high) { if (color) return prepareColor(high[2]); else return high[1]; } else { if (color) return [0, 0, 0, 1]; else return 1; } }; } function prepareColor(c) { return [c[0] / 255, c[1] / 255, c[2] / 255, c[3] / 1]; } function interpColor(from, to, t) { return [ util.interp(from[0], to[0], t), util.interp(from[1], to[1], t), util.interp(from[2], to[2], t), util.interp(from[3], to[3], t) ]; } },{"../util/util.js":87,"csscolorparser":91,"mapbox-gl-style-spec/reference/v4":95}],56:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'); module.exports = StyleTransition; /* * Represents a transition between two declarations */ function StyleTransition(declaration, oldTransition, value) { this.declaration = declaration; this.startTime = this.endTime = (new Date()).getTime(); var type = declaration.type; if (type === 'number') { this.interp = util.interp; } else if (type === 'color') { this.interp = interpColor; } else if (type === 'array') { this.interp = interpNumberArray; } this.oldTransition = oldTransition; this.duration = value.duration || 0; this.delay = value.delay || 0; if (!this.instant()) { this.endTime = this.startTime + this.duration + this.delay; this.ease = util.easeCubicInOut; } if (oldTransition && oldTransition.endTime <= this.startTime) { // Old transition is done running, so we can // delete its reference to its old transition. delete oldTransition.oldTransition; } } StyleTransition.prototype.instant = function() { return !this.oldTransition || !this.interp || (this.duration === 0 && this.delay === 0); }; /* * Return the value of the transitioning property at zoom level `z` and optional time `t` */ StyleTransition.prototype.at = function(z, t) { var value = this.declaration.calculate(z); if (this.instant()) return value; t = t || Date.now(); if (t < this.endTime) { var oldValue = this.oldTransition.at(z, this.startTime); var eased = this.ease((t - this.startTime - this.delay) / this.duration); value = this.interp(oldValue, value, eased); } return value; }; function interpNumberArray(from, to, t) { return from.map(function(d, i) { return util.interp(d, to[i], t); }); } function interpColor(from, to, t) { return [ util.interp(from[0], to[0], t), util.interp(from[1], to[1], t), util.interp(from[2], to[2], t), util.interp(from[3], to[3], t) ]; } },{"../util/util.js":87}],57:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = Anchor; function Anchor(x, y, angle, scale, segment) { this.x = x; this.y = y; this.angle = angle; this.scale = scale; if (segment !== undefined) { this.segment = segment; } } Anchor.prototype = Object.create(Point.prototype); Anchor.prototype.clone = function() { return new Anchor(this.x, this.y, this.angle, this.scale, this.segment); }; },{"point-geometry":98}],58:[function(require,module,exports){ 'use strict'; module.exports = BinPack; function BinPack(width, height) { this.width = width; this.height = height; this.free = [{ x: 0, y: 0, w: width, h: height }]; } BinPack.prototype.release = function(rect) { // Simple algorithm to recursively merge the newly released cell with its // neighbor. This doesn't merge more than two cells at a time, and fails // for complicated merges. for (var i = 0; i < this.free.length; i++) { var free = this.free[i]; if (free.y == rect.y && free.h == rect.h && free.x + free.w == rect.x) { free.w += rect.w; } else if (free.x == rect.x && free.w == rect.w && free.y + free.h == rect.y) { free.h += rect.h; } else if (rect.y == free.y && rect.h == free.h && rect.x + rect.w == free.x) { free.x = rect.x; free.w += rect.w; } else if (rect.x == free.x && rect.w == free.w && rect.y + rect.h == free.y) { free.y = rect.y; free.h += rect.h; } else { continue; } this.free.splice(i, 1); this.release(free); return; } this.free.push(rect); }; BinPack.prototype.allocate = function(width, height) { // Find the smallest free rect angle var rect = { x: Infinity, y: Infinity, w: Infinity, h: Infinity }; var smallest = -1; for (var i = 0; i < this.free.length; i++) { var ref = this.free[i]; if (width <= ref.w && height <= ref.h && ref.y <= rect.y && ref.x <= rect.x) { rect = ref; smallest = i; } } if (smallest < 0) { // There's no space left for this char. return { x: -1, y: -1 }; } else { this.free.splice(smallest, 1); // Shorter/Longer Axis Split Rule (SAS) // http://clb.demon.fi/files/RectangleBinPack.pdf p. 15 // Ignore the dimension of R and just split long the shorter dimension // See Also: http://www.cs.princeton.edu/~chazelle/pubs/blbinpacking.pdf if (rect.w < rect.h) { // split horizontally // +--+---+ // |__|___| <-- b1 // +------+ <-- b2 if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: height }); if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: rect.w, h: rect.h - height }); } else { // split vertically // +--+---+ // |__| | <-- b1 // +--|---+ <-- b2 if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: rect.h }); if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: width, h: rect.h - height }); } return { x: rect.x, y: rect.y, w: width, h: height }; } }; },{}],59:[function(require,module,exports){ 'use strict'; var rbush = require('rbush'), rotationRange = require('./rotationrange.js'), Point = require('point-geometry'); module.exports = Collision; function Collision(zoom, tileExtent, tileSize, placementDepth) { this.hTree = rbush(); // tree for horizontal labels this.cTree = rbush(); // tree for glyphs from curved labels // tile pixels per screen pixels at the tile's zoom level this.tilePixelRatio = tileExtent / tileSize; this.zoom = zoom; // Calculate the maximum scale we can go down in our fake-3d rtree so that // placement still makes sense. This is calculated so that the minimum // placement zoom can be at most 25.5 (we use an unsigned integer x10 to // store the minimum zoom). // // We don't want to place labels all the way to 25.5. This lets too many // glyphs be placed, slowing down collision checking. Only place labels if // they will show up within the intended zoom range of the tile. placementDepth = Math.min(3, placementDepth || 1, 25.5 - this.zoom); this.maxPlacementScale = Math.exp(Math.LN2 * placementDepth); var m = 4096; var edge = m * this.tilePixelRatio * 2; var fullRange = [Math.PI * 2, 0]; this.left = { anchor: new Point(0, 0), box: { x1: -edge, y1: -edge, x2: 0, y2: edge }, placementRange: fullRange, placementScale: 0.5, maxScale: Infinity, padding: 0 }; this.top = { anchor: new Point(0, 0), box: { x1: -edge, y1: -edge, x2: edge, y2: 0 }, placementRange: fullRange, placementScale: 0.5, maxScale: Infinity, padding: 0 }; this.bottom = { anchor: new Point(m, m), box: { x1: -edge, y1: 0, x2: edge, y2: edge }, placementRange: fullRange, placementScale: 0.5, maxScale: Infinity, padding: 0 }; this.right = { anchor: new Point(m, m), box: { x1: 0, y1: -edge, x2: edge, y2: edge }, placementRange: fullRange, placementScale: 0.5, maxScale: Infinity, padding: 0 }; } Collision.prototype.getPlacementScale = function(glyphs, minPlacementScale, avoidEdges) { var left = this.left; var right = this.right; var top = this.top; var bottom = this.bottom; for (var k = 0; k < glyphs.length; k++) { var glyph = glyphs[k]; var box = glyph.box; var bbox = glyph.hBox || box; var anchor = glyph.anchor; var pad = glyph.padding; var minScale = Math.max(minPlacementScale, glyph.minScale); var maxScale = glyph.maxScale || Infinity; if (minScale >= maxScale) continue; // Compute the scaled bounding box of the unrotated glyph var searchBox = this.getBox(anchor, bbox, minScale, maxScale); var blocking = this.hTree.search(searchBox).concat(this.cTree.search(searchBox)); if (avoidEdges) { if (searchBox[0] < 0) blocking.push(left); if (searchBox[1] < 0) blocking.push(top); if (searchBox[2] >= 4096) blocking.push(right); if (searchBox[3] >= 4096) blocking.push(bottom); } if (blocking.length) { var na = anchor; // new anchor var nb = box; // new box for (var l = 0; l < blocking.length; l++) { var oa = blocking[l].anchor; // old anchor var ob = blocking[l].box; // old box // If anchors are identical, we're going to skip the label. // NOTE: this isn't right because there can be glyphs with // the same anchor but differing box offsets. if (na.equals(oa)) { return null; } // todo: unhardcode the 8 = tileExtent/tileSize var padding = Math.max(pad, blocking[l].padding) * 8; // Original algorithm: var s1 = (ob.x1 - nb.x2 - padding) / (na.x - oa.x); // scale at which new box is to the left of old box var s2 = (ob.x2 - nb.x1 + padding) / (na.x - oa.x); // scale at which new box is to the right of old box var s3 = (ob.y1 - nb.y2 - padding) / (na.y - oa.y); // scale at which new box is to the top of old box var s4 = (ob.y2 - nb.y1 + padding) / (na.y - oa.y); // scale at which new box is to the bottom of old box if (isNaN(s1) || isNaN(s2)) s1 = s2 = 1; if (isNaN(s3) || isNaN(s4)) s3 = s4 = 1; var collisionFreeScale = Math.min(Math.max(s1, s2), Math.max(s3, s4)); // Only update label's min scale if the glyph was restricted by a collision if (collisionFreeScale > minPlacementScale && collisionFreeScale > minScale && collisionFreeScale < maxScale && collisionFreeScale < blocking[l].maxScale) { minPlacementScale = collisionFreeScale; } if (minPlacementScale > this.maxPlacementScale) { return null; } } } } return minPlacementScale; }; Collision.prototype.getPlacementRange = function(glyphs, placementScale, horizontal) { var placementRange = [2*Math.PI, 0]; for (var k = 0; k < glyphs.length; k++) { var glyph = glyphs[k]; var bbox = glyph.hBox || glyph.box; var anchor = glyph.anchor; var minPlacedX = anchor.x + bbox.x1 / placementScale; var minPlacedY = anchor.y + bbox.y1 / placementScale; var maxPlacedX = anchor.x + bbox.x2 / placementScale; var maxPlacedY = anchor.y + bbox.y2 / placementScale; var searchBox = [minPlacedX, minPlacedY, maxPlacedX, maxPlacedY]; var blocking = this.hTree.search(searchBox); if (horizontal) { blocking = blocking.concat(this.cTree.search(searchBox)); } for (var l = 0; l < blocking.length; l++) { var b = blocking[l]; var bbox2 = b.hBox || b.box; var x1, x2, y1, y2, intersectX, intersectY; // Adjust and compare bboxes to see if the glyphs might intersect if (placementScale > b.placementScale) { x1 = b.anchor.x + bbox2.x1 / placementScale; y1 = b.anchor.y + bbox2.y1 / placementScale; x2 = b.anchor.x + bbox2.x2 / placementScale; y2 = b.anchor.y + bbox2.y2 / placementScale; intersectX = x1 < maxPlacedX && x2 > minPlacedX; intersectY = y1 < maxPlacedY && y2 > minPlacedY; } else { x1 = anchor.x + bbox.x1 / b.placementScale; y1 = anchor.y + bbox.y1 / b.placementScale; x2 = anchor.x + bbox.x2 / b.placementScale; y2 = anchor.y + bbox.y2 / b.placementScale; intersectX = x1 < b[2] && x2 > b[0]; intersectY = y1 < b[3] && y2 > b[1]; } // If they can't intersect, skip more expensive rotation calculation if (!(intersectX && intersectY)) continue; var scale = Math.max(placementScale, b.placementScale); var range = rotationRange.rotationRange(glyph, b, scale); placementRange[0] = Math.min(placementRange[0], range[0]); placementRange[1] = Math.max(placementRange[1], range[1]); } } return placementRange; }; // Insert glyph placements into rtree. Collision.prototype.insert = function(glyphs, anchor, placementScale, placementRange, horizontal) { var allBounds = []; for (var k = 0; k < glyphs.length; k++) { var glyph = glyphs[k]; var bbox = glyph.hBox || glyph.box; var minScale = Math.max(placementScale, glyph.minScale); var maxScale = glyph.maxScale || Infinity; var bounds = this.getBox(anchor, bbox, minScale, maxScale); bounds.anchor = anchor; bounds.box = glyph.box; if (glyph.hBox) bounds.hBox = bbox; bounds.placementRange = placementRange; bounds.placementScale = minScale; bounds.maxScale = maxScale; bounds.padding = glyph.padding; allBounds.push(bounds); } (horizontal ? this.hTree : this.cTree).load(allBounds); }; Collision.prototype.getBox = function(anchor, bbox, minScale, maxScale) { return [ anchor.x + Math.min(bbox.x1 / minScale, bbox.x1 / maxScale), anchor.y + Math.min(bbox.y1 / minScale, bbox.y1 / maxScale), anchor.x + Math.max(bbox.x2 / minScale, bbox.x2 / maxScale), anchor.y + Math.max(bbox.y2 / minScale, bbox.y2 / maxScale)]; }; },{"./rotationrange.js":65,"point-geometry":98,"rbush":100}],60:[function(require,module,exports){ 'use strict'; var BinPack = require('./binpack.js'); module.exports = GlyphAtlas; function GlyphAtlas(width, height) { this.width = width; this.height = height; this.bin = new BinPack(width, height); this.index = {}; this.ids = {}; this.data = new Uint8Array(width * height); } GlyphAtlas.prototype = { get debug() { return 'canvas' in this; }, set debug(value) { if (value && !this.canvas) { this.canvas = document.createElement('canvas'); this.canvas.width = this.width; this.canvas.height = this.height; document.body.appendChild(this.canvas); this.ctx = this.canvas.getContext('2d'); } else if (!value && this.canvas) { this.canvas.parentNode.removeChild(this.canvas); delete this.ctx; delete this.canvas; } } }; GlyphAtlas.prototype.getGlyphs = function() { var glyphs = {}, split, name, id; for (var key in this.ids) { split = key.split('#'); name = split[0]; id = split[1]; if (!glyphs[name]) glyphs[name] = []; glyphs[name].push(id); } return glyphs; }; GlyphAtlas.prototype.getRects = function() { var rects = {}, split, name, id; for (var key in this.ids) { split = key.split('#'); name = split[0]; id = split[1]; if (!rects[name]) rects[name] = {}; rects[name][id] = this.index[key]; } return rects; }; GlyphAtlas.prototype.removeGlyphs = function(id) { for (var key in this.ids) { var ids = this.ids[key]; var pos = ids.indexOf(id); if (pos >= 0) ids.splice(pos, 1); this.ids[key] = ids; if (!ids.length) { var rect = this.index[key]; var target = this.data; for (var y = 0; y < rect.h; y++) { var y1 = this.width * (rect.y + y) + rect.x; for (var x = 0; x < rect.w; x++) { target[y1 + x] = 0; } } this.dirty = true; this.bin.release(rect); delete this.index[key]; delete this.ids[key]; } } this.updateTexture(this.gl); }; GlyphAtlas.prototype.addGlyph = function(id, name, glyph, buffer) { if (!glyph) { // console.warn('missing glyph', code, String.fromCharCode(code)); return null; } var key = name + "#" + glyph.id; // The glyph is already in this texture. if (this.index[key]) { if (this.ids[key].indexOf(id) < 0) { this.ids[key].push(id); } return this.index[key]; } // The glyph bitmap has zero width. if (!glyph.bitmap) { return null; } var buffered_width = glyph.width + buffer * 2; var buffered_height = glyph.height + buffer * 2; // Add a 1px border around every image. var pack_width = buffered_width; var pack_height = buffered_height; // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them // into 2 bytes rather than 4 bytes. pack_width += (4 - pack_width % 4); pack_height += (4 - pack_height % 4); var rect = this.bin.allocate(pack_width, pack_height); if (rect.x < 0) { console.warn('glyph bitmap overflow'); return { glyph: glyph, rect: null }; } // Add left and top glyph offsets to rect. rect.l = glyph.left; rect.t = glyph.top; this.index[key] = rect; this.ids[key] = [id]; var target = this.data; var source = glyph.bitmap; for (var y = 0; y < buffered_height; y++) { var y1 = this.width * (rect.y + y) + rect.x; var y2 = buffered_width * y; for (var x = 0; x < buffered_width; x++) { target[y1 + x] = source[y2 + x]; } } this.dirty = true; return rect; }; GlyphAtlas.prototype.bind = function(gl) { this.gl = gl; if (!this.texture) { this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, this.width, this.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null); } else { gl.bindTexture(gl.TEXTURE_2D, this.texture); } }; GlyphAtlas.prototype.updateTexture = function(gl) { this.bind(gl); if (this.dirty) { gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.ALPHA, gl.UNSIGNED_BYTE, this.data); // DEBUG if (this.ctx) { var data = this.ctx.getImageData(0, 0, this.width, this.height); for (var i = 0, j = 0; i < this.data.length; i++, j += 4) { data.data[j] = this.data[i]; data.data[j+1] = this.data[i]; data.data[j+2] = this.data[i]; data.data[j+3] = 255; } this.ctx.putImageData(data, 0, 0); this.ctx.strokeStyle = 'red'; for (var k = 0; k < this.bin.free.length; k++) { var free = this.bin.free[k]; this.ctx.strokeRect(free.x, free.y, free.w, free.h); } } // END DEBUG this.dirty = false; } }; },{"./binpack.js":58}],61:[function(require,module,exports){ 'use strict'; var getArrayBuffer = require('../util/ajax.js').getArrayBuffer; var Glyphs = require('../util/glyphs.js'); var Protobuf = require('pbf'); module.exports = GlyphSource; function GlyphSource(url, glyphAtlas) { this.url = url; this.glyphAtlas = glyphAtlas; this.stacks = {}; this.loading = {}; } GlyphSource.prototype.getRects = function(fontstack, glyphIDs, tileID, callback) { if (this.stacks[fontstack] === undefined) this.stacks[fontstack] = {}; var rects = {}; var glyphs = {}; var result = { rects: rects, glyphs: glyphs }; var stack = this.stacks[fontstack]; var glyphAtlas = this.glyphAtlas; var missing = {}; var remaining = 0; for (var i = 0; i < glyphIDs.length; i++) { var glyphID = glyphIDs[i]; var range = Math.floor(glyphID / 256); if (stack[range]) { var glyph = stack[range].glyphs[glyphID]; var buffer = 3; rects[glyphID] = glyphAtlas.addGlyph(tileID, fontstack, glyph, buffer); if (glyph) glyphs[glyphID] = simpleGlyph(glyph); } else { if (missing[range] === undefined) { missing[range] = []; remaining++; } missing[range].push(glyphID); } } if (!remaining) callback(undefined, result); var glyphSource = this; for (var r in missing) { this.loadRange(fontstack, r, onRangeLoaded); } function onRangeLoaded(err, range, data) { // TODO not be silent about errors if (!err) { var stack = glyphSource.stacks[fontstack][range] = data.stacks[fontstack]; for (var i = 0; i < missing[range].length; i++) { var glyphID = missing[range][i]; var glyph = stack.glyphs[glyphID]; var buffer = 3; rects[glyphID] = glyphAtlas.addGlyph(tileID, fontstack, glyph, buffer); if (glyph) glyphs[glyphID] = simpleGlyph(glyph); } } remaining--; if (!remaining) callback(undefined, result); } }; function simpleGlyph(glyph) { return { advance: glyph.advance, left: glyph.left, top: glyph.top }; } GlyphSource.prototype.loadRange = function(fontstack, range, callback) { if (range * 256 >= 65280) return callback('gyphs > 65280 not supported'); if (this.loading[fontstack] === undefined) this.loading[fontstack] = {}; var loading = this.loading[fontstack]; if (loading[range]) { loading[range].push(callback); } else { loading[range] = [callback]; var rangeName = (range * 256) + '-' + (range * 256 + 255); var url = glyphUrl(fontstack, rangeName, this.url); getArrayBuffer(url, function(err, data) { var glyphs = !err && new Glyphs(new Protobuf(new Uint8Array(data))); for (var i = 0; i < loading[range].length; i++) { loading[range][i](err, range, glyphs); } delete loading[range]; }); } }; function glyphUrl(fontstack, range, url, subdomains) { subdomains = subdomains || 'abc'; return url .replace('{s}', subdomains[fontstack.length % subdomains.length]) .replace('{fontstack}', fontstack) .replace('{range}', range); } },{"../util/ajax.js":76,"../util/glyphs.js":83,"pbf":96}],62:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'), Anchor = require('../symbol/anchor.js'); module.exports = interpolate; var minScale = 0.5; var minScaleArrays = { 1: [minScale], 2: [minScale, 2], 4: [minScale, 4, 2, 4], 8: [minScale, 8, 4, 8, 2, 8, 4, 8] }; function interpolate(vertices, spacing, minScale, maxScale, tilePixelRatio, start) { if (minScale === undefined) minScale = 0; maxScale = Math.round(Math.max(Math.min(8, maxScale / 2), 1)); spacing *= tilePixelRatio / maxScale; var minScales = minScaleArrays[maxScale]; var len = minScales.length; var distance = 0, markedDistance = 0, added = start || 0; var points = []; for (var i = 0; i < vertices.length - 1; i++) { var a = vertices[i], b = vertices[i + 1]; var segmentDist = a.dist(b), angle = b.angleTo(a); while (markedDistance + spacing < distance + segmentDist) { markedDistance += spacing; var t = (markedDistance - distance) / segmentDist, x = util.interp(a.x, b.x, t), y = util.interp(a.y, b.y, t), s = minScales[added % len]; if (x >= 0 && x < 4096 && y >= 0 && y < 4096) { points.push(new Anchor(x, y, angle, s, i)); } added++; } distance += segmentDist; } return points; } },{"../symbol/anchor.js":57,"../util/util.js":87}],63:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = { getIcon: getIcon, getGlyphs: getGlyphs }; var minScale = 0.5; // underscale by 1 zoom level function getIcon(anchor, image, boxScale, line, props) { var x = image.width / 2 / image.pixelRatio; var y = image.height / 2 / image.pixelRatio; var dx = props['icon-offset'][0]; var dy = props['icon-offset'][1]; var x1 = (dx - x); var x2 = (dx + x); var y1 = (dy - y); var y2 = (dy + y); var tl = new Point(x1, y1); var tr = new Point(x2, y1); var br = new Point(x2, y2); var bl = new Point(x1, y2); var angle = props['icon-rotate'] * Math.PI / 180; if (anchor.segment !== undefined && props['icon-rotation-alignment'] !== 'viewport') { var next = line[anchor.segment]; angle += -Math.atan2(next.x - anchor.x, next.y - anchor.y) + Math.PI / 2; } if (angle) { var sin = Math.sin(angle), cos = Math.cos(angle), matrix = [cos, -sin, sin, cos]; tl = tl.matMult(matrix); tr = tr.matMult(matrix); bl = bl.matMult(matrix); br = br.matMult(matrix); x1 = Math.min(tl.x, tr.x, bl.x, br.x); x2 = Math.max(tl.x, tr.x, bl.x, br.x); y1 = Math.min(tl.y, tr.y, bl.y, br.y); y2 = Math.max(tl.y, tr.y, bl.y, br.y); } var box = { x1: x1 * boxScale, x2: x2 * boxScale, y1: y1 * boxScale, y2: y2 * boxScale }; var iconBox = { box: box, anchor: anchor, minScale: minScale, maxScale: Infinity, padding: props['icon-padding'] }; var icon = { tl: tl, tr: tr, br: br, bl: bl, tex: image, angle: 0, anchor: anchor, minScale: minScale, maxScale: Infinity }; return { shapes: [icon], boxes: [iconBox], minScale: anchor.scale }; } function getGlyphs(anchor, origin, shaping, faces, boxScale, horizontal, line, props) { var maxAngleDelta = props['text-max-angle'] * Math.PI / 180; var rotate = props['text-rotate'] * Math.PI / 180; var padding = props['text-padding']; var alongLine = props['text-rotation-alignment'] !== 'viewport'; var keepUpright = props['text-keep-upright']; var glyphs = [], boxes = []; var buffer = 3; for (var k = 0; k < shaping.length; k++) { var shape = shaping[k]; var fontstack = faces[shape.fontstack]; var glyph = fontstack.glyphs[shape.glyph]; var rect = fontstack.rects[shape.glyph]; if (!glyph) continue; if (!(rect && rect.w > 0 && rect.h > 0)) continue; var x = (origin.x + shape.x + glyph.left - buffer + rect.w / 2) * boxScale; var glyphInstances; if (anchor.segment !== undefined && alongLine) { glyphInstances = []; getSegmentGlyphs(glyphInstances, anchor, x, line, anchor.segment, 1, maxAngleDelta); if (keepUpright) getSegmentGlyphs(glyphInstances, anchor, x, line, anchor.segment, -1, maxAngleDelta); } else { glyphInstances = [{ anchor: anchor, offset: 0, angle: 0, maxScale: Infinity, minScale: minScale }]; } var x1 = origin.x + shape.x + glyph.left - buffer, y1 = origin.y + shape.y - glyph.top - buffer, x2 = x1 + rect.w, y2 = y1 + rect.h, otl = new Point(x1, y1), otr = new Point(x2, y1), obl = new Point(x1, y2), obr = new Point(x2, y2); var obox = { x1: boxScale * x1, y1: boxScale * y1, x2: boxScale * x2, y2: boxScale * y2 }; for (var i = 0; i < glyphInstances.length; i++) { var instance = glyphInstances[i], tl = otl, tr = otr, bl = obl, br = obr, box = obox, // Clamp to -90/+90 degrees angle = instance.angle + rotate; if (angle) { // Compute the transformation matrix. var sin = Math.sin(angle), cos = Math.cos(angle), matrix = [cos, -sin, sin, cos]; tl = tl.matMult(matrix); tr = tr.matMult(matrix); bl = bl.matMult(matrix); br = br.matMult(matrix); } // Prevent label from extending past the end of the line var glyphMinScale = Math.max(instance.minScale, anchor.scale); // Remember the glyph for later insertion. glyphs.push({ tl: tl, tr: tr, bl: bl, br: br, tex: rect, angle: (anchor.angle + rotate + instance.offset + 2 * Math.PI) % (2 * Math.PI), anchor: instance.anchor, minScale: glyphMinScale, maxScale: instance.maxScale }); if (!instance.offset) { // not a flipped glyph if (angle) { // Calculate the rotated glyph's bounding box offsets from the anchor point. box = { x1: boxScale * Math.min(tl.x, tr.x, bl.x, br.x), y1: boxScale * Math.min(tl.y, tr.y, bl.y, br.y), x2: boxScale * Math.max(tl.x, tr.x, bl.x, br.x), y2: boxScale * Math.max(tl.y, tr.y, bl.y, br.y) }; } boxes.push({ box: box, anchor: instance.anchor, minScale: glyphMinScale, maxScale: instance.maxScale, padding: padding }); } } } // TODO avoid creating the boxes in the first place? if (horizontal) boxes = [getMergedBoxes(boxes, anchor)]; var minPlacementScale = anchor.scale; var minGlyphScale = Infinity; for (var m = 0; m < boxes.length; m++) { minGlyphScale = Math.min(minGlyphScale, boxes[m].minScale); } minGlyphScale = Math.max(minPlacementScale, minScale); return { boxes: boxes, shapes: glyphs, minScale: minGlyphScale }; } function getSegmentGlyphs(glyphs, anchor, offset, line, segment, direction, maxAngleDelta) { var upsideDown = direction < 0; if (offset < 0) direction *= -1; if (direction > 0) segment++; var newAnchor = anchor; var end = line[segment]; var prevscale = Infinity; var prevAngle; offset = Math.abs(offset); var placementScale = anchor.scale; segment_loop: while (true) { var dist = newAnchor.dist(end); var scale = offset/dist; var angle = -Math.atan2(end.x - newAnchor.x, end.y - newAnchor.y) + direction * Math.PI / 2; if (upsideDown) angle += Math.PI; // Don't place around sharp corners var angleDiff = (angle - prevAngle) % (2 * Math.PI); if (prevAngle && Math.abs(angleDiff) > maxAngleDelta) { anchor.scale = prevscale; break; } glyphs.push({ anchor: newAnchor, offset: upsideDown ? Math.PI : 0, minScale: scale, maxScale: prevscale, angle: (angle + 2 * Math.PI) % (2 * Math.PI) }); if (scale <= placementScale) break; newAnchor = end; // skip duplicate nodes while (newAnchor.equals(end)) { segment += direction; end = line[segment]; if (!end) { anchor.scale = scale; break segment_loop; } } var unit = end.sub(newAnchor)._unit(); newAnchor = newAnchor.sub(unit._mult(dist)); prevscale = scale; prevAngle = angle; } } function getMergedBoxes(glyphs, anchor) { // Collision checks between rotating and fixed labels are relatively expensive, // so we use one box per label, not per glyph for horizontal labels. var mergedglyphs = { box: { x1: Infinity, y1: Infinity, x2: -Infinity, y2: -Infinity }, anchor: anchor, minScale: 0, padding: -Infinity }; var box = mergedglyphs.box; for (var m = 0; m < glyphs.length; m++) { var gbox = glyphs[m].box; box.x1 = Math.min(box.x1, gbox.x1); box.y1 = Math.min(box.y1, gbox.y1); box.x2 = Math.max(box.x2, gbox.x2); box.y2 = Math.max(box.y2, gbox.y2); mergedglyphs.minScale = Math.max(mergedglyphs.minScale, glyphs[m].minScale); mergedglyphs.padding = Math.max(mergedglyphs.padding, glyphs[m].padding); } // for all horizontal labels, calculate bbox covering all rotated positions var x12 = box.x1 * box.x1, y12 = box.y1 * box.y1, x22 = box.x2 * box.x2, y22 = box.y2 * box.y2, diag = Math.sqrt(Math.max(x12 + y12, x12 + y22, x22 + y12, x22 + y22)); mergedglyphs.hBox = { x1: -diag, y1: -diag, x2: diag, y2: diag }; return mergedglyphs; } },{"point-geometry":98}],64:[function(require,module,exports){ 'use strict'; var resolveTokens = require('../util/token.js'); module.exports = resolveText; // For an array of features determine what glyph ranges need to be loaded // and apply any text preprocessing. The remaining users of text should // use the `textFeatures` key returned by this function rather than accessing // feature text directly. function resolveText(features, info, glyphs) { var textFeatures = []; var codepoints = []; for (var i = 0, fl = features.length; i < fl; i++) { var text = resolveTokens(features[i].properties, info['text-field']); var hastext = false; if (!text) continue; text = text.toString(); var transform = info['text-transform']; if (transform === 'uppercase') { text = text.toLocaleUpperCase(); } else if (transform === 'lowercase') { text = text.toLocaleLowerCase(); } for (var j = 0, jl = text.length; j < jl; j++) { if (text.charCodeAt(j) <= 65533) { codepoints.push(text.charCodeAt(j)); hastext = true; } } // Track indexes of features with text. if (hastext) { textFeatures[i] = text; } } // get a list of unique codepoints we are missing codepoints = uniq(codepoints, glyphs); return { textFeatures: textFeatures, codepoints: codepoints }; } function uniq(ids, alreadyHave) { var u = []; var last; ids.sort(sortNumbers); for (var i = 0; i < ids.length; i++) { if (ids[i] !== last) { last = ids[i]; if (!alreadyHave[last]) u.push(ids[i]); } } return u; } function sortNumbers(a, b) { return a - b; } },{"../util/token.js":85}],65:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'), Point = require('point-geometry'); module.exports = { rotationRange: rotationRange, mergeCollisions: mergeCollisions, rotatingFixedCollisions: rotatingFixedCollisions, rotatingRotatingCollisions: rotatingRotatingCollisions, cornerBoxCollisions: cornerBoxCollisions, circleEdgeCollisions: circleEdgeCollisions, getCorners: getCorners, }; /* * Calculate the range a box conflicts with a second box */ function rotationRange(inserting, blocker, scale) { var collisions, box; var a = inserting; var b = blocker; // Instead of scaling the boxes, we move the anchors var relativeAnchor = new Point( (b.anchor.x - a.anchor.x) * scale, (b.anchor.y - a.anchor.y) * scale); // Generate a list of collision interval if (a.hBox && b.hBox) { collisions = rotatingRotatingCollisions(a.box, b.box, relativeAnchor); } else if (a.hBox) { box = { x1: b.box.x1 + relativeAnchor.x, y1: b.box.y1 + relativeAnchor.y, x2: b.box.x2 + relativeAnchor.x, y2: b.box.y2 + relativeAnchor.y }; collisions = rotatingFixedCollisions(a.box, box); } else if (b.hBox) { box = { x1: a.box.x1 - relativeAnchor.x, y1: a.box.y1 - relativeAnchor.y, x2: a.box.x2 - relativeAnchor.x, y2: a.box.y2 - relativeAnchor.y }; collisions = rotatingFixedCollisions(b.box, box); } else { collisions = []; } // Find and return the continous are around 0 where there are no collisions return mergeCollisions(collisions, blocker.placementRange); } /* * Combine an array of collision ranges to form a continuous * range that includes 0. Collisions within the ignoreRange are ignored */ function mergeCollisions(collisions, ignoreRange) { // find continuous interval including 0 that doesn't have any collisions var min = 2 * Math.PI; var max = 0; for (var i = 0; i < collisions.length; i++) { var collision = collisions[i]; var entryOutside = ignoreRange[0] <= collision[0] && collision[0] <= ignoreRange[1]; var exitOutside = ignoreRange[0] <= collision[1] && collision[1] <= ignoreRange[1]; if (entryOutside && exitOutside) { // no collision, since blocker is out of range } else if (entryOutside) { min = Math.min(min, ignoreRange[1]); max = Math.max(max, collision[1]); } else if (exitOutside) { min = Math.min(min, collision[0]); max = Math.max(max, ignoreRange[0]); } else { min = Math.min(min, collision[0]); max = Math.max(max, collision[1]); } } return [min, max]; } /* * Calculate collision ranges for two rotating boxes. */ var horizontal = new Point(1, 0); function rotatingRotatingCollisions(a, b, anchorToAnchor) { var d = anchorToAnchor.mag(); var angleBetweenAnchors = anchorToAnchor.angleWith(horizontal); var c = [], collisions = [], k; // Calculate angles at which collisions may occur // top/bottom c[0] = Math.asin((a.y2 - b.y1) / d); c[1] = Math.asin((a.y2 - b.y1) / d) + Math.PI; c[2] = 2 * Math.PI - Math.asin((-a.y1 + b.y2) / d); c[3] = Math.PI - Math.asin((-a.y1 + b.y2) / d); // left/right c[4] = 2 * Math.PI - Math.acos((a.x2 - b.x1) / d); c[5] = Math.acos((a.x2 - b.x1) / d); c[6] = Math.PI - Math.acos((-a.x1 + b.x2) / d); c[7] = Math.PI + Math.acos((-a.x1 + b.x2) / d); var rl = a.x2 - b.x1; var lr = -a.x1 + b.x2; var tb = a.y2 - b.y1; var bt = -a.y1 + b.y2; // Calculate the distance squared of the diagonal which will be used // to check if the boxes are close enough for collisions to occur at each angle // todo, triple check these var e = []; // top/bottom e[0] = rl * rl + tb * tb; e[1] = lr * lr + tb * tb; e[2] = rl * rl + bt * bt; e[3] = lr * lr + bt * bt; // left/right e[4] = rl * rl + tb * tb; e[5] = rl * rl + bt * bt; e[6] = lr * lr + bt * bt; e[7] = lr * lr + tb * tb; c = c.filter(function(x, i) { // Check if they are close enough to collide return !isNaN(x) && d * d <= e[i]; }).map(function(x) { // So far, angles have been calulated as relative to the vector between anchors. // Convert the angles to angles from north. return (x + angleBetweenAnchors + 2 * Math.PI) % (2 * Math.PI); }); // Group the collision angles by two // each group represents a range where the two boxes collide c.sort(); for (k = 0; k < c.length; k+=2) { collisions.push([c[k], c[k+1]]); } return collisions; } /* * Calculate collision ranges for a rotating box and a fixed box; */ function rotatingFixedCollisions(rotating, fixed) { var cornersR = getCorners(rotating); var cornersF = getCorners(fixed); // A collision occurs when, and only at least one corner from one of the boxes // is within the other box. Calculate these ranges for each corner. var collisions = []; for (var i = 0; i < 4; i++ ) { cornerBoxCollisions(collisions, cornersR[i], cornersF); cornerBoxCollisions(collisions, cornersF[i], cornersR, true); } return collisions; } /* * Calculate the ranges for which the corner, * rotatated around the anchor, is within the box; */ function cornerBoxCollisions(collisions, corner, boxCorners, flip) { var radius = corner.mag(), angles = []; // Calculate the points at which the corners intersect with the edges for (var i = 0, j = 3; i < 4; j = i++) { circleEdgeCollisions(angles, corner, radius, boxCorners[j], boxCorners[i]); } if (angles.length % 2 !== 0) { // TODO fix // This could get hit when a point intersects very close to a corner // and floating point issues cause only one of the entry or exit to be counted throw('expecting an even number of intersections'); } angles.sort(); // Group by pairs, where each represents a range where a collision occurs for (var k = 0; k < angles.length; k+=2) { collisions[k/2] = flip ? [2 * Math.PI - angles[k+1], 2 * Math.PI - angles[k]] : // reflect an angle around 0 degrees [angles[k], angles[k+1]]; } return collisions; } /* * Return the intersection points of a circle and a line segment; */ function circleEdgeCollisions(angles, corner, radius, p1, p2) { var edgeX = p2.x - p1.x; var edgeY = p2.y - p1.y; var a = edgeX * edgeX + edgeY * edgeY; var b = (edgeX * p1.x + edgeY * p1.y) * 2; var c = p1.x * p1.x + p1.y * p1.y - radius * radius; var discriminant = b*b - 4*a*c; // a collision exists only if line intersects circle at two points if (discriminant > 0) { var x1 = (-b - Math.sqrt(discriminant)) / (2 * a); var x2 = (-b + Math.sqrt(discriminant)) / (2 * a); // only add points if within line segment // hack to handle floating point representations of 0 and 1 if (0 < x1 && x1 < 1) { angles.push(getAngle(p1, p2, x1, corner)); } if (0 < x2 && x2 < 1) { angles.push(getAngle(p1, p2, x2, corner)); } } return angles; } function getAngle(p1, p2, d, corner) { return (-corner.angleWithSep( util.interp(p1.x, p2.x, d), util.interp(p1.y, p2.y, d)) + 2 * Math.PI) % (2 * Math.PI); } function getCorners(a) { return [ new Point(a.x1, a.y1), new Point(a.x1, a.y2), new Point(a.x2, a.y2), new Point(a.x2, a.y1) ]; } },{"../util/util.js":87,"point-geometry":98}],66:[function(require,module,exports){ 'use strict'; module.exports = { shape: shape }; function shape(text, name, stacks, maxWidth, lineHeight, horizontalAlign, verticalAlign, justify, spacing, translate) { var glyphs = stacks[name].glyphs; var glyph; var shaping = []; var x = translate[0]; var y = translate[1]; var id; for (var i = 0; i < text.length; i++) { id = text.charCodeAt(i); glyph = glyphs[id]; if (id === 0 || !glyph) continue; shaping.push({ fontstack: name, glyph: id, x: x, y: y }); x += glyph.advance + spacing; } if (!shaping.length) return false; shaping = linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify); return shaping; } var breakable = { 32: true }; // Currently only breaks at regular spaces function linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify) { var lastSafeBreak = null; var lengthBeforeCurrentLine = 0; var lineStartIndex = 0; var line = 0; var maxLineLength = 0; if (maxWidth) { for (var i = 0; i < shaping.length; i++) { var shape = shaping[i]; shape.x -= lengthBeforeCurrentLine; shape.y += lineHeight * line; if (shape.x > maxWidth && lastSafeBreak !== null) { var lineLength = shaping[lastSafeBreak + 1].x; maxLineLength = Math.max(lineLength, maxLineLength); for (var k = lastSafeBreak + 1; k <= i; k++) { shaping[k].y += lineHeight; shaping[k].x -= lineLength; } if (justify) { justifyLine(shaping, glyphs, lineStartIndex, lastSafeBreak - 1, justify); } lineStartIndex = lastSafeBreak + 1; lastSafeBreak = null; lengthBeforeCurrentLine += lineLength; line++; } if (breakable[shape.glyph]) { lastSafeBreak = i; } } } maxLineLength = maxLineLength || shaping[shaping.length - 1].x; justifyLine(shaping, glyphs, lineStartIndex, shaping.length - 1, justify); align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line); return shaping; } function justifyLine(shaping, glyphs, start, end, justify) { var lastAdvance = glyphs[shaping[end].glyph].advance; var lineIndent = (shaping[end].x + lastAdvance) * justify; for (var j = start; j <= end; j++) { shaping[j].x -= lineIndent; } } function align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line) { var shiftX = (justify - horizontalAlign) * maxLineLength; var shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight; for (var j = 0; j < shaping.length; j++) { shaping[j].x += shiftX; shaping[j].y += shiftY; } } },{}],67:[function(require,module,exports){ 'use strict'; var Control = require('./control.js'), DOM = require('../../util/dom.js'), util = require('../../util/util.js'); module.exports = Attribution; function Attribution() {} Attribution.prototype = util.inherit(Control, { onAdd: function(map) { var className = 'mapboxgl-ctrl-attrib', container = this._container = DOM.create('div', className, map.container); this._update(); map.on('source.add', this._update.bind(this)); map.on('moveend', this._updateEditLink.bind(this)); return container; }, _update: function() { var attributions = []; for (var id in this._map.sources) { var source = this._map.sources[id]; if (source.tileJSON && source.tileJSON.attribution) { attributions.push(source.tileJSON.attribution); } } this._container.innerHTML = attributions.join(' | '); this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0]; this._updateEditLink(); }, _updateEditLink: function() { if (this._editLink) { var center = this._map.getCenter(); this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' + center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1); } } }); },{"../../util/dom.js":81,"../../util/util.js":87,"./control.js":68}],68:[function(require,module,exports){ 'use strict'; module.exports = Control; function Control() {} Control.prototype = { addTo: function(map) { this._map = map; this._container = this.onAdd(map); return this; }, remove: function () { this._container.parentNode.removeChild(this._container); if (this.onRemove) this.onRemove(this._map); this._map = null; return this; } }; },{}],69:[function(require,module,exports){ 'use strict'; var Control = require('./control.js'), DOM = require('../../util/dom.js'), util = require('../../util/util.js'); module.exports = Navigation; function Navigation() {} Navigation.prototype = util.inherit(Control, { onAdd: function(map) { var className = 'mapboxgl-ctrl-nav'; var container = this._container = DOM.create('div', className, map.container); this._zoomInButton = this._createButton(className + '-zoom-in', map.zoomIn.bind(map)); this._zoomOutButton = this._createButton(className + '-zoom-out', map.zoomOut.bind(map)); this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map)); var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass); compassCanvas.style.cssText = 'width:26px; height:26px;'; compassCanvas.width = 26 * 2; compassCanvas.height = 26 * 2; this._compass.addEventListener('mousedown', this._onCompassDown.bind(this)); this._onCompassMove = this._onCompassMove.bind(this); this._onCompassUp = this._onCompassUp.bind(this); this._compassCtx = compassCanvas.getContext('2d'); map.on('rotate', this._drawNorth.bind(this)); this._drawNorth(); return container; }, _onCompassDown: function(e) { DOM.disableDrag(); document.addEventListener('mousemove', this._onCompassMove); document.addEventListener('mouseup', this._onCompassUp); this._prevX = e.screenX; e.stopPropagation(); }, _onCompassMove: function(e) { var x = e.screenX, d = x < 2 ? -5 : // left edge of the screen, continue rotating x > window.screen.width - 2 ? 5 : // right edge (x - this._prevX) / 4; this._map.setBearing(this._map.getBearing() - d); this._prevX = e.screenX; e.preventDefault(); }, _onCompassUp: function() { document.removeEventListener('mousemove', this._onCompassMove); document.removeEventListener('mouseup', this._onCompassUp); DOM.enableDrag(); }, _createButton: function(className, fn) { var a = DOM.create('a', className, this._container); a.href = '#'; a.addEventListener('click', function (e) { fn(); e.preventDefault(); e.stopPropagation(); }); return a; }, _drawNorth: function() { var rad = 20, width = 8, center = 26, angle = this._map.transform.angle + (Math.PI / 2), ctx = this._compassCtx; this._compassCanvas.width = this._compassCanvas.width; ctx.translate(center, center); ctx.rotate(angle); ctx.beginPath(); ctx.fillStyle = '#000'; ctx.lineTo(0, -width); ctx.lineTo(-rad, 0); ctx.lineTo(0, width); ctx.fill(); ctx.beginPath(); ctx.fillStyle = '#bbb'; ctx.moveTo(0, 0); ctx.lineTo(0, width); ctx.lineTo(rad, 0); ctx.lineTo(0, -width); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = '#fff'; ctx.lineWidth = 4; ctx.moveTo(0, -width); ctx.lineTo(0, width); ctx.stroke(); } }); },{"../../util/dom.js":81,"../../util/util.js":87,"./control.js":68}],70:[function(require,module,exports){ 'use strict'; var util = require('../util/util.js'), browser = require('../util/browser.js'), LatLng = require('../geo/latlng.js'), LatLngBounds = require('../geo/latlngbounds.js'), Point = require('point-geometry'); util.extend(exports, { isEasing: function () { return !!this._stopFn; }, stop: function () { if (this._stopFn) { this._stopFn(); delete this._stopFn; } return this; }, panBy: function(offset, options) { this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options)); return this; }, panTo: function(latlng, options) { this.stop(); latlng = LatLng.convert(latlng); options = util.extend({ duration: 500, easing: util.ease, offset: [0, 0] }, options); var tr = this.transform, offset = Point.convert(options.offset).rotate(-tr.angle), from = tr.point, to = tr.project(latlng).sub(offset); if (!options.noMoveStart) { this.fire('movestart'); } this._stopFn = browser.timed(function(t) { tr.center = tr.unproject(from.add(to.sub(from).mult(options.easing(t)))); this._move(); if (t === 1) this.fire('moveend'); }, options.animate === false ? 0 : options.duration, this); return this; }, // Zooms to a certain zoom level with easing. zoomTo: function(zoom, options) { this.stop(); options = util.extend({ duration: 500 }, options); var tr = this.transform, around = tr.center, easing = this._updateEasing(options.duration, zoom, options.easing), startZoom = tr.zoom; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } if (options.animate === false) options.duration = 0; if (!this.zooming) { this.zooming = true; this.fire('movestart'); } this._stopFn = browser.timed(function(t) { tr.setZoomAround(util.interp(startZoom, zoom, easing(t)), around); this.style.animationLoop.set(300); // text fading this._move(true); if (t === 1) { this.ease = null; if (options.duration >= 200) { this.fire('moveend'); this.zooming = false; } } }, options.duration, this); if (options.duration < 200) { clearTimeout(this._onZoomEnd); this._onZoomEnd = setTimeout(function() { this.zooming = false; this._rerender(); this.fire('moveend'); }.bind(this), 200); } return this; }, zoomIn: function(options) { this.zoomTo(this.getZoom() + 1, options); }, zoomOut: function(options) { this.zoomTo(this.getZoom() - 1, options); }, rotateTo: function(bearing, options) { this.stop(); options = util.extend({ duration: 500, easing: util.ease }, options); var tr = this.transform, start = this.getBearing(), around = tr.center; if (options.around) { around = LatLng.convert(options.around); } else if (options.offset) { around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset))); } this.rotating = true; this.fire('movestart'); this._stopFn = browser.timed(function(t) { if (t === 1) { this.rotating = false; } tr.setBearingAround(util.interp(start, bearing, options.easing(t)), around); this._move(false, true).fire('moveend'); }, options.animate === false ? 0 : options.duration, this); return this; }, resetNorth: function(options) { return this.rotateTo(0, util.extend({duration: 1000}, options)); }, fitBounds: function(bounds, options) { options = util.extend({ padding: 0, offset: [0, 0], maxZoom: Infinity }, options); bounds = LatLngBounds.convert(bounds); var offset = Point.convert(options.offset), tr = this.transform, nw = tr.project(bounds.getNorthWest()), se = tr.project(bounds.getSouthEast()), size = se.sub(nw), center = tr.unproject(nw.add(se).div(2)), scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x, scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y, zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom); return options.linear ? this.easeTo(center, zoom, 0, options) : this.flyTo(center, zoom, 0, options); }, easeTo: function(latlng, zoom, bearing, options) { options = util.extend({ offset: [0, 0], duration: 500, easing: util.ease }, options); latlng = LatLng.convert(latlng); var offset = Point.convert(options.offset), tr = this.transform, startZoom = this.getZoom(), startBearing = this.getBearing(); zoom = zoom === undefined ? startZoom : zoom; bearing = bearing === undefined ? startBearing : bearing; var scale = tr.zoomScale(zoom - startZoom), from = tr.point, to = tr.project(latlng).sub(offset.div(scale)), around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale))); if (zoom !== startZoom) this.zooming = true; if (startBearing !== bearing) this.rotating = true; this.fire('movestart'); this._stopFn = browser.timed(function (t) { var k = options.easing(t); if (zoom !== startZoom) { tr.setZoomAround(startZoom + k * (zoom - startZoom), around); } if (bearing !== startBearing) { tr.bearing = util.interp(startBearing, bearing, k); } this.style.animationLoop.set(300); // text fading this._move(zoom !== startZoom, bearing !== startBearing); if (t === 1) { this.zooming = false; this.rotating = false; this.fire('moveend'); } }, options.animate === false ? 0 : options.duration, this); return this; }, flyTo: function(latlng, zoom, bearing, options) { options = util.extend({ offset: [0, 0], speed: 1.2, curve: 1.42, easing: util.ease }, options); latlng = LatLng.convert(latlng); var offset = Point.convert(options.offset), tr = this.transform, startZoom = this.getZoom(), startBearing = this.getBearing(); zoom = zoom === undefined ? startZoom : zoom; bearing = bearing === undefined ? startBearing : bearing; var scale = tr.zoomScale(zoom - startZoom), from = tr.point, to = tr.project(latlng).sub(offset.div(scale)); if (options.animate === false) { return this.setView(latlng, zoom, bearing); } var startWorldSize = tr.worldSize, rho = options.curve, V = options.speed, w0 = Math.max(tr.width, tr.height), w1 = w0 / scale, u1 = to.sub(from).mag(), rho2 = rho * rho; function r(i) { var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1); return Math.log(Math.sqrt(b * b + 1) - b); } function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; } function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; } function tanh(n) { return sinh(n) / cosh(n); } var r0 = r(0), w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); }, u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; }, S = (r(1) - r0) / rho; if (Math.abs(u1) < 0.000001) { if (Math.abs(w0 - w1) < 0.000001) return this; var k = w1 < w0 ? -1 : 1; S = Math.abs(Math.log(w1 / w0)) / rho; u = function() { return 0; }; w = function(s) { return Math.exp(k * rho * s); }; } var duration = 1000 * S / V; this.zooming = true; if (startBearing != bearing) this.rotating = true; this.fire('movestart'); this._stopFn = browser.timed(function (t) { var k = options.easing(t), s = k * S, us = u(s); tr.zoom = startZoom + tr.scaleZoom(1 / w(s)); tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize); if (bearing !== startBearing) { tr.bearing = util.interp(startBearing, bearing, k); } this.style.animationLoop.set(300); // text fading this._move(true, bearing !== startBearing); if (t === 1) { this.zooming = false; this.rotating = false; this.fire('moveend'); } }, duration, this); return this; }, _updateEasing: function(duration, zoom, bezier) { var easing; if (this.ease) { var ease = this.ease, t = (Date.now() - ease.start) / ease.duration, speed = ease.easing(t + 0.01) - ease.easing(t), // Quick hack to make new bezier that is continuous with last x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01, y = Math.sqrt(0.27 * 0.27 - x * x); easing = util.bezier(x, y, 0.25, 1); } else { easing = bezier ? util.bezier.apply(util, bezier) : util.ease; } // store information on current easing this.ease = { start: (new Date()).getTime(), to: Math.pow(2, zoom), duration: duration, easing: easing }; return easing; } }); },{"../geo/latlng.js":17,"../geo/latlngbounds.js":18,"../util/browser.js":77,"../util/util.js":87,"point-geometry":98}],71:[function(require,module,exports){ 'use strict'; var Interaction = require('./interaction.js'); var Point = require('point-geometry'); var util = require('../util/util.js'); module.exports = Handlers; function Handlers(map) { var rotateEnd; var inertiaLinearity = 0.2, inertiaEasing = util.bezier(0, 0, inertiaLinearity, 1); this.interaction = new Interaction(map.container) .on('click', function(e) { map.fire('click', e); }) .on('hover', function(e) { map.fire('hover', e); }) .on('down', function () { map.fire('movestart'); }) .on('resize', function() { map.stop(); map.resize(); map.update(); }) .on('pan', function(e) { map.stop(); map.transform.panBy(e.offset); map._move(); }) .on('panend', function(e) { if (!e.inertia) map.fire('moveend'); else { // convert velocity to px/s & adjust for increased initial animation speed when easing out var velocity = e.inertia.mult(1000 * inertiaLinearity), speed = velocity.mag(); var maxSpeed = 4000; // px/s if (speed >= maxSpeed) { speed = maxSpeed; velocity._unit()._mult(maxSpeed); } var deceleration = 8000, // px/s^2 duration = speed / (deceleration * inertiaLinearity), offset = velocity.mult(-duration / 2).round(); map.panBy(offset, { duration: duration * 1000, easing: inertiaEasing, noMoveStart: true }); } }) .on('zoom', function(e) { // Scale by sigmoid of scroll wheel delta. var scale = 2 / (1 + Math.exp(-Math.abs(e.delta / 100))); if (e.delta < 0 && scale !== 0) scale = 1 / scale; var fromScale = map.ease && isFinite(e.delta) ? map.ease.to : map.transform.scale, duration = !isFinite(e.delta) ? 800 : e.source == 'trackpad' ? 0 : 300; map.zoomTo(map.transform.scaleZoom(fromScale * scale), { duration: duration, around: map.unproject(e.point) }); }) .on('rotate', function(e) { var center = map.transform.centerPoint, // Center of rotation startToCenter = e.start.sub(center), startToCenterDist = startToCenter.mag(); // If the first click was too close to the center, move the center of rotation by 200 pixels // in the direction of the click. if (startToCenterDist < 200) { center = e.start.add(new Point(-200, 0)._rotate(startToCenter.angle())); } var bearingDiff = e.prev.sub(center).angleWith(e.current.sub(center)) / Math.PI * 180; map.transform.bearing = map.getBearing() - bearingDiff; map._move(false, true); window.clearTimeout(rotateEnd); rotateEnd = window.setTimeout(function() { map.rotating = false; map._rerender(); }, 200); }); } },{"../util/util.js":87,"./interaction.js":73,"point-geometry":98}],72:[function(require,module,exports){ 'use strict'; module.exports = Hash; var util = require('../util/util.js'); function Hash(map) { this.map = map; window.addEventListener('hashchange', this.onhash.bind(this), false); map.on('move', util.debounce(this.updateHash.bind(this), 100)); } Hash.prototype = { onhash: function() { var loc = location.hash.replace('#', '').split('/'); if (loc.length >= 3) { this.map.setView([+loc[1], +loc[2]], +loc[0], +(loc[3] || 0)); return true; } return false; }, updateHash: function() { var center = this.map.getCenter(), zoom = this.map.getZoom(), bearing = this.map.getBearing(), precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)), hash = '#' + (Math.round(zoom * 100) / 100) + '/' + center.lat.toFixed(precision) + '/' + center.lng.toFixed(precision) + (bearing ? '/' + (Math.round(bearing * 10) / 10) : ''); window.history.replaceState('', '', hash); } }; },{"../util/util.js":87}],73:[function(require,module,exports){ 'use strict'; var Evented = require('../util/evented.js'), browser = require('../util/browser.js'), Point = require('point-geometry'); module.exports = Interaction; function Interaction(el) { var interaction = this; if (!el) return; var rotating = false, panned = false, firstPos = null, pos = null, inertia = null, now; function mousePos(e) { var rect = el.getBoundingClientRect(); return new Point( e.clientX - rect.left - el.clientLeft, e.clientY - rect.top - el.clientTop); } el.addEventListener('contextmenu', function(ev) { rotating = true; firstPos = pos = mousePos(ev); ev.preventDefault(); }, false); el.addEventListener('mousedown', onmousedown, false); document.addEventListener('mouseup', onmouseup, false); document.addEventListener('mousemove', onmousemove, false); el.addEventListener('click', onclick, false); scrollwheel(zoom); el.addEventListener('dblclick', ondoubleclick, false); window.addEventListener('resize', resize, false); function zoom(type, delta, point) { interaction.fire('zoom', { source: type, delta: delta, point: point }); inertia = null; now = null; } function click(point) { interaction.fire('click', {point: point}); } function hover(point) { interaction.fire('hover', {point: point}); } function pan(point) { if (pos) { var offset = pos.sub(point); interaction.fire('pan', {offset: offset}); // add an averaged version of this movement to the inertia vector if (inertia) { var duration = Date.now() - now; // sometimes it's 0 after some erratic paning if (duration) { var time = duration + now; inertia.push([time, point]); while (inertia.length > 2 && time - inertia[0][0] > 100) inertia.shift(); } } else { inertia = []; } now = Date.now(); pos = point; } } function resize() { interaction.fire('resize'); } function rotate(point) { if (pos) { interaction.fire('rotate', { start: firstPos, prev: pos, current: point }); pos = point; } } function onmousedown(ev) { firstPos = pos = mousePos(ev); interaction.fire('down'); } function onmouseup() { panned = pos && firstPos && (pos.x != firstPos.x || pos.y != firstPos.y); rotating = false; pos = null; if (inertia && inertia.length >= 2 && now > Date.now() - 100) { var last = inertia[inertia.length - 1], first = inertia[0], velocity = last[1].sub(first[1]).div(last[0] - first[0]); interaction.fire('panend', {inertia: velocity}); } else interaction.fire('panend'); inertia = null; now = null; } function onmousemove(ev) { var point = mousePos(ev); if (rotating) { rotate(point); } else if (pos) pan(point); else { var target = ev.toElement; while (target && target != el && target.parentNode) target = target.parentNode; if (target == el) { hover(point); } } } function onclick(ev) { if (!panned) click(mousePos(ev)); } function ondoubleclick(ev) { zoom('wheel', Infinity * (ev.shiftKey ? -1 : 1), mousePos(ev)); ev.preventDefault(); } function scrollwheel(callback) { var firefox = /Firefox/i.test(navigator.userAgent); var safari = /Safari/i.test(navigator.userAgent) && !/Chrom(ium|e)/i.test(navigator.userAgent); var time = window.performance || Date; el.addEventListener('wheel', wheel, false); el.addEventListener('mousewheel', mousewheel, false); var lastEvent = 0; var type = null; var typeTimeout = null; var initialValue = null; function scroll(value, ev) { var stamp = time.now(); var timeDelta = stamp - lastEvent; lastEvent = stamp; var point = mousePos(ev); if (value !== 0 && (value % 4.000244140625) === 0) { // This one is definitely a mouse wheel event. type = 'wheel'; } else if (value !== 0 && Math.abs(value) < 4) { // This one is definitely a trackpad event because it is so small. type = 'trackpad'; } else if (timeDelta > 400) { // This is likely a new scroll action. type = null; initialValue = value; // Start a timeout in case this was a singular event, and dely it // by up to 40ms. typeTimeout = setTimeout(function() { type = 'wheel'; callback(type, -initialValue, point); }, 40); } else if (type === null) { // This is a repeating event, but we don't know the type of event // just yet. If the delta per time is small, we assume it's a // fast trackpad; otherwise we switch into wheel mode. type = (Math.abs(timeDelta * value) < 200) ? 'trackpad' : 'wheel'; // Make sure our delayed event isn't fired again, because we // accumulate the previous event (which was less than 40ms ago) into // this event. if (typeTimeout) { clearTimeout(typeTimeout); typeTimeout = null; value += initialValue; } } // Only fire the callback if we actually know what type of scrolling // device the user uses. if (type !== null) { callback(type, -value, point); } } function wheel(e) { var deltaY = e.deltaY; // Firefox doubles the values on retina screens... if (firefox && e.deltaMode == window.WheelEvent.DOM_DELTA_PIXEL) deltaY /= browser.devicePixelRatio; if (e.deltaMode == window.WheelEvent.DOM_DELTA_LINE) deltaY *= 40; scroll(deltaY, e); e.preventDefault(); } function mousewheel(e) { var deltaY = -e.wheelDeltaY; if (safari) deltaY = deltaY / 3; scroll(deltaY, e); e.preventDefault(); } } } Interaction.prototype = Object.create(Evented); },{"../util/browser.js":77,"../util/evented.js":82,"point-geometry":98}],74:[function(require,module,exports){ 'use strict'; var Dispatcher = require('../util/dispatcher.js'), Canvas = require('../util/canvas.js'), util = require('../util/util.js'), browser = require('../util/browser.js'), ajax = require('../util/ajax.js'), Evented = require('../util/evented.js'), Style = require('../style/style.js'), AnimationLoop = require('../style/animationloop.js'), GLPainter = require('../render/painter.js'), Transform = require('../geo/transform.js'), Hash = require('./hash.js'), Handlers = require('./handlers.js'), Source = require('../source/source.js'), Easings = require('./easings.js'), LatLng = require('../geo/latlng.js'), LatLngBounds = require('../geo/latlngbounds.js'), Point = require('point-geometry'), GlyphSource = require('../symbol/glyphsource.js'), Attribution = require('./control/attribution.js'); // allow redefining Map here (jshint thinks it's global) // jshint -W079 var Map = module.exports = function(options) { options = this.options = util.inherit(this.options, options); this.animationLoop = new AnimationLoop(); this.transform = new Transform(options.minZoom, options.maxZoom); this.hash = options.hash && new Hash(this); if (options.maxBounds) { var b = LatLngBounds.convert(options.maxBounds); this.transform.latRange = [b.getSouth(), b.getNorth()]; this.transform.lngRange = [b.getWest(), b.getEast()]; } this._onStyleChange = this._onStyleChange.bind(this); this._updateBuckets = this._updateBuckets.bind(this); this.render = this.render.bind(this); this._setupContainer(); this._setupPainter(); this.handlers = options.interactive && new Handlers(this); this.dispatcher = new Dispatcher(Math.max(options.numWorkers, 1), this); // don't set position from options if set through hash if (!this.hash || !this.hash.onhash()) { this.setView(options.center, options.zoom, options.bearing); } this.sources = {}; this.stacks = {}; this.resize(); if (typeof options.style === 'object') { this.setStyle(options.style); } else if (typeof options.style === 'string') { ajax.getJSON(options.style, function (err, data) { if (err) throw err; this.setStyle(data); }.bind(this)); } if (options.attributionControl) this.addControl(new Attribution()); }; util.extend(Map.prototype, Evented); util.extend(Map.prototype, Easings); util.extend(Map.prototype, { options: { center: [0, 0], zoom: 0, bearing: 0, minZoom: 0, maxZoom: 20, numWorkers: browser.hardwareConcurrency - 1, interactive: true, hash: false, attributionControl: true }, addSource: function(id, source) { this.sources[id] = source; source.id = id; if (source.onAdd) { source.onAdd(this); } if (source.enabled) source.fire('source.add', {source: source}); return this; }, removeSource: function(id) { var source = this.sources[id]; if (source.onRemove) { source.onRemove(this); } delete this.sources[id]; return this.fire('source.remove', {source: source}); }, addControl: function(control) { control.addTo(this); return this; }, // Set the map's center, zoom, and bearing setView: function(center, zoom, bearing) { this.stop(); var tr = this.transform, zoomChanged = tr.zoom !== +zoom, bearingChanged = tr.bearing !== +bearing; tr.center = LatLng.convert(center); tr.zoom = +zoom; tr.bearing = +bearing; return this .fire('movestart') ._move(zoomChanged, bearingChanged) .fire('moveend'); }, setCenter: function(center) { this.setView(center, this.getZoom(), this.getBearing()); }, setZoom: function(zoom) { this.setView(this.getCenter(), zoom, this.getBearing()); }, setBearing: function(bearing) { this.setView(this.getCenter(), this.getZoom(), bearing); }, getCenter: function() { return this.transform.center; }, getZoom: function() { return this.transform.zoom; }, getBearing: function() { return this.transform.bearing; }, // Detect the map's new width and height and resize it. resize: function() { var width = 0, height = 0; if (this.container) { width = this.container.offsetWidth || 400; height = this.container.offsetHeight || 300; } this.canvas.resize(width, height); this.transform.width = width; this.transform.height = height; this.transform._constrain(); if (this.style && this.style.sprite) { this.style.sprite.resize(this.painter.gl); } this.painter.resize(width, height); return this .fire('movestart') ._move() .fire('resize') .fire('moveend'); }, getBounds: function() { return new LatLngBounds( this.transform.pointLocation(new Point(0, 0)), this.transform.pointLocation(this.transform.size)); }, project: function(latlng) { return this.transform.locationPoint(LatLng.convert(latlng)); }, unproject: function(point) { return this.transform.pointLocation(Point.convert(point)); }, featuresAt: function(point, params, callback) { var features = []; var error = null; var map = this; point = Point.convert(point); util.asyncEach(Object.keys(this.sources), function(id, callback) { var source = map.sources[id]; source.featuresAt(point, params, function(err, result) { if (result) features = features.concat(result); if (err) error = err; callback(); }); }, function() { callback(error, features); }); return this; }, setStyle: function(style) { if (this.style) { this.style.off('change', this._onStyleChange); } if (style instanceof Style) { this.style = style; } else { this.style = new Style(style, this.animationLoop); } var sources = this.style.stylesheet.sources; for (var id in sources) { this.addSource(id, Source.create(sources[id])); } this.glyphSource = new GlyphSource(this.style.stylesheet.glyphs, this.painter.glyphAtlas); this.style.on('change', this._onStyleChange); this._styleDirty = true; this._tilesDirty = true; this._updateBuckets(); this._updateGlyphs(); this.fire('style.change'); return this; }, _move: function (zoom, rotate) { this.update(zoom).fire('move'); if (zoom) this.fire('zoom'); if (rotate) this.fire('rotate'); return this; }, // map setup code _setupContainer: function() { var id = this.options.container; var container = this.container = typeof id === 'string' ? document.getElementById(id) : id; if (container) container.classList.add('mapboxgl-map'); this.canvas = new Canvas(this, container); }, _setupPainter: function() { var gl = this.canvas.getWebGLContext(); if (!gl) { alert('Failed to initialize WebGL'); return; } this.painter = new GLPainter(gl, this.transform); }, _contextLost: function(event) { event.preventDefault(); if (this._frameId) { browser.cancelFrame(this._frameId); } }, _contextRestored: function() { this._setupPainter(); this.resize(); this.update(); }, // Callbacks from web workers 'debug message': function(data) { console.log.apply(console, data); }, 'alert message': function(data) { alert.apply(window, data); }, 'get sprite json': function(params, callback) { var sprite = this.style.sprite; if (sprite.loaded()) { callback(null, { sprite: sprite.data, retina: sprite.retina }); } else { sprite.on('loaded', function() { callback(null, { sprite: sprite.data, retina: sprite.retina }); }); } }, 'get glyphs': function(params, callback) { this.glyphSource.getRects(params.fontstack, params.codepoints, params.id, callback); }, // Rendering update: function(updateStyle) { if (!this.style) return this; this._styleDirty = this._styleDirty || updateStyle; this._tilesDirty = true; this._rerender(); return this; }, // Call when a (re-)render of the map is required, e.g. when the user panned or zoomed,f or new data is available. render: function() { if (this._styleDirty) { this._styleDirty = false; this._updateStyle(); } if (this._tilesDirty) { for (var id in this.sources) { this.sources[id].update(); } this._tilesDirty = false; } this._renderGroups(this.style.layerGroups); this.fire('render'); this._frameId = null; if (!this.animationLoop.stopped()) { this._styleDirty = true; } if (this._repaint || !this.animationLoop.stopped()) { this._rerender(); } return this; }, _renderGroups: function(groups, name) { var i, len, group, source, k; // Render all dependencies (composited layers) to textures for (i = 0, len = groups.length; i < len; i++) { group = groups[i]; for (k in group.dependencies) { this._renderGroups(group.dependencies[k], k); } } // attach render destination. if no name, main canvas. this.painter.bindRenderTexture(name); // Render the groups for (i = 0, len = groups.length; i < len; i++) { group = groups[i]; source = this.sources[group.source]; if (source) { this.painter.clearStencil(); source.render(group); } else if (group.composited) { this.painter.draw(undefined, this.style, group, {}); } else if (group.source === undefined) { this.painter.draw(undefined, this.style, group, { background: true }); } } }, _rerender: function() { if (!this._frameId) { this._frameId = browser.frame(this.render); } }, _onStyleChange: function () { this.update(true); }, _updateStyle: function() { if (!this.style) return; this.style.recalculate(this.transform.zoom); }, _updateGlyphs: function() { this.dispatcher.broadcast('set glyphs', this.style.stylesheet.glyphs); }, _updateBuckets: function() { // Transfer a stripped down version of the style to the workers. They only // need the bucket information to know what features to extract from the tile. this.dispatcher.broadcast('set buckets', this.style.orderedBuckets); // clears all tiles to recalculate geometries (for changes to linecaps, linejoins, ...) for (var s in this.sources) { this.sources[s].load(); } this.update(); } }); util.extendAll(Map.prototype, { // debug code _debug: false, get debug() { return this._debug; }, set debug(value) { this._debug = value; this._rerender(); }, // continuous repaint _repaint: false, get repaint() { return this._repaint; }, set repaint(value) { this._repaint = value; this._rerender(); }, // polygon antialiasing _antialiasing: true, get antialiasing() { return this._antialiasing; }, set antialiasing(value) { this._antialiasing = value; this._rerender(); }, // show vertices _vertices: false, get vertices() { return this._vertices; }, set vertices(value) { this._vertices = value; this._rerender(); }, // show vertices _loadNewTiles: true, get loadNewTiles() { return this._loadNewTiles; }, set loadNewTiles(value) { this._loadNewTiles = value; this.update(); } }); },{"../geo/latlng.js":17,"../geo/latlngbounds.js":18,"../geo/transform.js":19,"../render/painter.js":33,"../source/source.js":40,"../style/animationloop.js":48,"../style/style.js":53,"../symbol/glyphsource.js":61,"../util/ajax.js":76,"../util/browser.js":77,"../util/canvas.js":78,"../util/dispatcher.js":79,"../util/evented.js":82,"../util/util.js":87,"./control/attribution.js":67,"./easings.js":70,"./handlers.js":71,"./hash.js":72,"point-geometry":98}],75:[function(require,module,exports){ 'use strict'; module.exports = Actor; function Actor(target, parent) { this.target = target; this.parent = parent; this.callbacks = {}; this.callbackID = 0; this.receive = this.receive.bind(this); this.target.addEventListener('message', this.receive, false); } Actor.prototype.receive = function(message) { var data = message.data, callback; if (data.type == '') { callback = this.callbacks[data.id]; delete this.callbacks[data.id]; callback(data.error || null, data.data); } else if (typeof data.id !== 'undefined') { var id = data.id; this.parent[data.type](data.data, function response(err, data, buffers) { // console.warn('trying to clone', data, buffers, message.target); message.target.postMessage({ type: '', id: String(id), error: err ? String(err) : null, data: data }, buffers); }); } else { this.parent[data.type](data.data); } }; Actor.prototype.send = function(type, data, callback, buffers) { var id = null; if (callback) this.callbacks[id = this.callbackID++] = callback; this.target.postMessage({ type: type, id: String(id), data: data }, buffers); }; },{}],76:[function(require,module,exports){ 'use strict'; exports.getJSON = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { var data; try { data = JSON.parse(xhr.response); } catch (err) { return callback(err); } callback(null, data); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getArrayBuffer = function(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onerror = function(e) { callback(e); }; xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300 && xhr.response) { callback(null, xhr.response); } else { callback(new Error(xhr.statusText)); } }; xhr.send(); return xhr; }; exports.getImage = function(url, callback) { var img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = function() { callback(null, img); }; img.src = url; img.getData = function() { return getImageData(this); }; return img; }; function getImageData(img) { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); return context.getImageData(0, 0, img.width, img.height).data; } },{}],77:[function(require,module,exports){ 'use strict'; var frameName = (function() { if (window.requestAnimationFrame) return 'requestAnimationFrame'; if (window.mozRequestAnimationFrame) return 'mozRequestAnimationFrame'; if (window.webkitRequestAnimationFrame) return 'webkitRequestAnimationFrame'; if (window.msRequestAnimationFrame) return 'msRequestAnimationFrame'; })(); exports.frame = function(fn) { return window[frameName](fn); }; exports.cancelFrame = function(id) { (window.cancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame)(id); }; exports.timed = function (fn, dur, ctx) { if (!dur) { return fn.call(ctx, 1); } var abort = false, start = window.performance ? window.performance.now() : Date.now(); function tick(now) { if (abort) return; if (!window.performance) now = Date.now(); if (now > start + dur) { fn.call(ctx, 1); } else { fn.call(ctx, (now - start) / dur); exports.frame(tick); } } exports.frame(tick); return function() { abort = true; }; }; exports.supported = function() { var supports = [ function() { return typeof window !== 'undefined'; }, function() { return typeof document !== 'undefined'; }, function () { return !!(Array.prototype && Array.prototype.every && Array.prototype.filter && Array.prototype.forEach && Array.prototype.indexOf && Array.prototype.lastIndexOf && Array.prototype.map && Array.prototype.some && Array.prototype.reduce && Array.prototype.reduceRight && Array.isArray); }, function() { return !!(Function.prototype && Function.prototype.bind), !!(Object.keys && Object.create && Object.getPrototypeOf && Object.getOwnPropertyNames && Object.isSealed && Object.isFrozen && Object.isExtensible && Object.getOwnPropertyDescriptor && Object.defineProperty && Object.defineProperties && Object.seal && Object.freeze && Object.preventExtensions); }, function() { return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON; }, function() { var canvas = document.createElement('canvas'); if ('supportsContext' in canvas) { return canvas.supportsContext('webgl') || canvas.supportsContext('experimental-webgl'); } return !!window.WebGLRenderingContext && (!!canvas.getContext('webgl') || !!canvas.getContext('experimental-webgl')); }, function() { return 'Worker' in window; } ]; for (var i = 0; i < supports.length; i++) { if (!supports[i]()) return false; } return true; }; exports.hardwareConcurrency = navigator.hardwareConcurrency || 8; Object.defineProperty(exports, 'devicePixelRatio', { get: function() { return window.devicePixelRatio; } }); },{}],78:[function(require,module,exports){ 'use strict'; module.exports = Canvas; function Canvas(parent, container) { this.canvas = document.createElement('canvas'); this.canvas.style.position = 'absolute'; this.canvas.classList.add('mapboxgl-canvas'); this.canvas.addEventListener('webglcontextlost', parent._contextLost.bind(parent), false); this.canvas.addEventListener('webglcontextrestored', parent._contextRestored.bind(parent), false); container.appendChild(this.canvas); } Canvas.prototype.resize = function(width, height) { var pixelRatio = window.devicePixelRatio || 1; // Request the required canvas size taking the pixelratio into account. this.canvas.width = pixelRatio * width; this.canvas.height = pixelRatio * height; // Maintain the same canvas size, potentially downscaling it for HiDPI displays this.canvas.style.width = width + 'px'; this.canvas.style.height = height + 'px'; }; Canvas.prototype.getWebGLContext = function() { return this.canvas.getContext("experimental-webgl", { antialias: false, alpha: true, stencil: true, depth: false }); }; },{}],79:[function(require,module,exports){ 'use strict'; var Actor = require('../actor.js'); var scripts = document.getElementsByTagName("script"); var workerFile = scripts[scripts.length - 1].getAttribute('src'); var absolute = workerFile.indexOf('http') !== -1; // Manages the WebWorkers module.exports = Dispatcher; function Dispatcher(length, parent) { this.actors = []; this.currentActor = 0; var url, blob, i; for (i = 0; i < length; i++) { // due to cross domain issues we can't load it directly with the url, // so create a blob and object url and load that if (absolute) { blob = new Blob(['importScripts("' + workerFile + '");'], {type : 'application/javascript'}); url = window.URL.createObjectURL(blob); } else { url = workerFile; } var worker = new Worker(url); var actor = new Actor(worker, parent); actor.name = "Worker " + i; this.actors.push(actor); } } Dispatcher.prototype.broadcast = function(type, data) { for (var i = 0; i < this.actors.length; i++) { this.actors[i].send(type, data); } }; Dispatcher.prototype.send = function(type, data, callback, targetID, buffers) { if (typeof targetID !== 'number' || isNaN(targetID)) { // Use round robin to send requests to web workers. targetID = this.currentActor = (this.currentActor + 1) % this.actors.length; } this.actors[targetID].send(type, data, callback, buffers); return targetID; }; },{"../actor.js":75}],80:[function(require,module,exports){ 'use strict'; module.exports = { HTTP_URL: 'http://a.tiles.mapbox.com/v4', HTTPS_URL: 'https://a.tiles.mapbox.com/v4', FORCE_HTTPS: false, REQUIRE_ACCESS_TOKEN: true }; },{}],81:[function(require,module,exports){ 'use strict'; exports.create = function (tagName, className, container) { var el = document.createElement(tagName); if (className) el.className = className; if (container) container.appendChild(el); return el; }; function preventDefault(e) { e.preventDefault(); } var docEl = typeof document !== 'undefined' ? document.documentElement : {}, selectProp = 'userSelect' in docEl ? 'userSelect' : 'MozUserSelect' in docEl ? 'MozUserSelect' : 'WebkitUserSelect' in docEl ? 'WebkitUserSelect' : null, userSelect; exports.disableDrag = function () { window.addEventListener('dragstart', preventDefault); if ('onselectstart' in document) window.addEventListener('selectstart', preventDefault); else if (selectProp) { userSelect = docEl.style[selectProp]; docEl.style[selectProp] = 'none'; } }; exports.enableDrag = function () { window.removeEventListener('dragstart', preventDefault); if ('onselectstart' in document) window.removeEventListener('selectstart', preventDefault); else if (selectProp) docEl.style[selectProp] = userSelect; }; },{}],82:[function(require,module,exports){ 'use strict'; var util = require('./util.js'); module.exports = { on: function(type, fn) { this._events = this._events || {}; this._events[type] = this._events[type] || []; this._events[type].push(fn); return this; }, off: function(type, fn) { if (!type) { // clear all listeners if no arguments specified delete this._events; return this; } if (!this.listens(type)) return this; if (fn) { var idx = this._events[type].indexOf(fn); if (idx >= 0) { this._events[type].splice(idx, 1); } if (!this._events[type].length) { delete this._events[type]; } } else { delete this._events[type]; } return this; }, fire: function(type, data) { if (!this.listens(type)) return this; data = util.extend({}, data); util.extend(data, {type: type, target: this}); // make sure adding/removing listeners inside other listeners won't cause infinite loop var listeners = this._events[type].slice(); for (var i = 0; i < listeners.length; i++) { listeners[i].call(this, data); } return this; }, listens: function(type) { return !!(this._events && this._events[type]); } }; },{"./util.js":87}],83:[function(require,module,exports){ 'use strict'; module.exports = Glyphs; function Glyphs(buffer, end) { // Public this.stacks = {}; // Private this._buffer = buffer; var val, tag; if (typeof end === 'undefined') end = buffer.length; while (buffer.pos < end) { val = buffer.readVarint(); tag = val >> 3; if (tag == 1) { var fontstack = this.readFontstack(); this.stacks[fontstack.name] = fontstack; } else { // console.warn('skipping tile tag ' + tag); buffer.skip(val); } } } Glyphs.prototype.readFontstack = function() { var buffer = this._buffer; var fontstack = { glyphs: {} }; var bytes = buffer.readVarint(); var val, tag; var end = buffer.pos + bytes; while (buffer.pos < end) { val = buffer.readVarint(); tag = val >> 3; if (tag == 1) { fontstack.name = buffer.readString(); } else if (tag == 2) { var range = buffer.readString(); fontstack.range = range; } else if (tag == 3) { var glyph = this.readGlyph(); fontstack.glyphs[glyph.id] = glyph; } else { buffer.skip(val); } } return fontstack; }; Glyphs.prototype.readGlyph = function() { var buffer = this._buffer; var glyph = {}; var bytes = buffer.readVarint(); var val, tag; var end = buffer.pos + bytes; while (buffer.pos < end) { val = buffer.readVarint(); tag = val >> 3; if (tag == 1) { glyph.id = buffer.readVarint(); } else if (tag == 2) { glyph.bitmap = buffer.readBuffer(); } else if (tag == 3) { glyph.width = buffer.readVarint(); } else if (tag == 4) { glyph.height = buffer.readVarint(); } else if (tag == 5) { glyph.left = buffer.readSVarint(); } else if (tag == 6) { glyph.top = buffer.readSVarint(); } else if (tag == 7) { glyph.advance = buffer.readVarint(); } else { buffer.skip(val); } } return glyph; }; },{}],84:[function(require,module,exports){ 'use strict'; /* * A [most-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms) * with hash lookup made possible by keeping a list of keys in parallel to * an array of dictionary of values */ module.exports = MRUCache; function MRUCache(length, onRemove) { this.max = length; this.onRemove = onRemove; this.reset(); } /* * Clears the cache */ MRUCache.prototype.reset = function() { this.list = {}; this.order = []; return this; }; /* * Add a key, value combination to the cache, trimming its size if this pushes * it over max length. */ MRUCache.prototype.add = function(key, data) { this.list[key] = data; this.order.push(key); if (this.order.length > this.max) { var removedData = this.get(this.order[0]); if (removedData) this.onRemove(removedData); } return this; }; /* * Determine whether the value attached to `key` is present */ MRUCache.prototype.has = function(key) { return key in this.list; }; /* * List all keys in the cache */ MRUCache.prototype.keys = function() { return this.order; }; /* * Get the value attached to a specific key. If the key is not found, * returns `null` */ MRUCache.prototype.get = function(key) { if (!this.has(key)) { return null; } var data = this.list[key]; delete this.list[key]; this.order.splice(this.order.indexOf(key), 1); return data; }; },{}],85:[function(require,module,exports){ 'use strict'; module.exports = resolveTokens; var tokenPattern = /{([\w-]+)}/; function resolveTokens(properties, expression) { var match; var value; var text = expression; while ((match = text.match(tokenPattern))) { value = typeof properties[match[1]] === 'undefined' ? '' : properties[match[1]]; text = text.replace(match[0], value); } return text; } },{}],86:[function(require,module,exports){ 'use strict'; var config = require('./config'); module.exports = function(path, accessToken) { accessToken = accessToken || config.ACCESS_TOKEN; if (!accessToken && config.REQUIRE_ACCESS_TOKEN) { throw new Error('An API access token is required to use Mapbox GL. ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } var url = ((typeof document !== 'undefined' && 'https:' === document.location.protocol) || config.FORCE_HTTPS) ? config.HTTPS_URL : config.HTTP_URL; url += path; url += url.indexOf('?') !== -1 ? '&access_token=' : '?access_token='; if (config.REQUIRE_ACCESS_TOKEN) { if (accessToken[0] === 's') { throw new Error('Use a public access token (pk.*) with Mapbox GL JS, not a secret access token (sk.*). ' + 'See https://www.mapbox.com/developers/api/#access-tokens'); } url += accessToken; } return url; }; module.exports.tileJSON = function(mapID, accessToken) { var url = module.exports('/' + mapID + '.json', accessToken); // TileJSON requests need a secure flag appended to their URLs so // that the server knows to send SSL-ified resource references. if (url.indexOf('https') === 0) url += '&secure'; return url; }; },{"./config":80}],87:[function(require,module,exports){ 'use strict'; var UnitBezier = require('unitbezier'); exports.easeCubicInOut = function (t) { if (t <= 0) return 0; if (t >= 1) return 1; var t2 = t * t, t3 = t2 * t; return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75); }; exports.bezier = function(p1x, p1y, p2x, p2y) { var bezier = new UnitBezier(p1x, p1y, p2x, p2y); return function(t) { return bezier.solve(t); }; }; exports.ease = exports.bezier(0.25, 0.1, 0.25, 1); exports.interp = function (a, b, t) { return (a * (1 - t)) + (b * t); }; exports.premultiply = function (c) { c[0] *= c[3]; c[1] *= c[3]; c[2] *= c[3]; return c; }; exports.asyncEach = function (array, fn, callback) { var remaining = array.length; if (remaining === 0) return callback(); function check() { if (--remaining === 0) callback(); } for (var i = 0; i < array.length; i++) fn(array[i], check); }; exports.keysDifference = function (obj, other) { var difference = []; for (var i in obj) { if (!(i in other)) { difference.push(i); } } return difference; }; exports.extend = function (dest, src) { for (var i in src) { dest[i] = src[i]; } return dest; }; exports.extendAll = function (dest, src) { for (var i in src) { Object.defineProperty(dest, i, Object.getOwnPropertyDescriptor(src, i)); } return dest; }; exports.inherit = function (parent, props) { var parentProto = typeof parent === 'function' ? parent.prototype : parent, proto = Object.create(parentProto); exports.extendAll(proto, props); return proto; }; var id = 1; exports.uniqueId = function () { return id++; }; exports.throttle = function (fn, time, context) { var lock, args, wrapperFn, later; later = function () { // reset lock and call if queued lock = false; if (args) { wrapperFn.apply(context, args); args = false; } }; wrapperFn = function () { if (lock) { // called too soon, queue to call later args = arguments; } else { // call and lock until later fn.apply(context, arguments); setTimeout(later, time); lock = true; } }; return wrapperFn; }; exports.debounce = function(fn, time) { var timer, args; return function() { args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn.apply(null, args); }, time); }; }; },{"unitbezier":101}],88:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ var base64 = require('base64-js') var ieee754 = require('ieee754') exports.Buffer = Buffer exports.SlowBuffer = Buffer exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 /** * If `TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Note: * * - Implementation must support adding new properties to `Uint8Array` instances. * Firefox 4-29 lacked support, fixed in Firefox 30+. * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * * We detect these buggy browsers and set `TYPED_ARRAY_SUPPORT` to `false` so they will * get the Object implementation, which is slower but will work correctly. */ var TYPED_ARRAY_SUPPORT = (function () { try { var buf = new ArrayBuffer(0) var arr = new Uint8Array(buf) arr.foo = function () { return 42 } return 42 === arr.foo() && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } })() /** * Class: Buffer * ============= * * The Buffer constructor returns instances of `Uint8Array` that are augmented * with function properties for all the node `Buffer` API functions. We use * `Uint8Array` so that square bracket notation works as expected -- it returns * a single octet. * * By augmenting the instances, we can avoid modifying the `Uint8Array` * prototype. */ function Buffer (subject, encoding, noZero) { if (!(this instanceof Buffer)) return new Buffer(subject, encoding, noZero) var type = typeof subject // Find the length var length if (type === 'number') length = subject > 0 ? subject >>> 0 : 0 else if (type === 'string') { if (encoding === 'base64') subject = base64clean(subject) length = Buffer.byteLength(subject, encoding) } else if (type === 'object' && subject !== null) { // assume object is array-like if (subject.type === 'Buffer' && isArray(subject.data)) subject = subject.data length = +subject.length > 0 ? Math.floor(+subject.length) : 0 } else throw new Error('First argument needs to be a number, array or string.') var buf if (TYPED_ARRAY_SUPPORT) { // Preferred: Return an augmented `Uint8Array` instance for best performance buf = Buffer._augment(new Uint8Array(length)) } else { // Fallback: Return THIS instance of Buffer (created by `new`) buf = this buf.length = length buf._isBuffer = true } var i if (TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { // Speed optimization -- use set if we're copying from a typed array buf._set(subject) } else if (isArrayish(subject)) { // Treat array-ish objects as a byte array if (Buffer.isBuffer(subject)) { for (i = 0; i < length; i++) buf[i] = subject.readUInt8(i) } else { for (i = 0; i < length; i++) buf[i] = ((subject[i] % 256) + 256) % 256 } } else if (type === 'string') { buf.write(subject, 0, encoding) } else if (type === 'number' && !TYPED_ARRAY_SUPPORT && !noZero) { for (i = 0; i < length; i++) { buf[i] = 0 } } return buf } // STATIC METHODS // ============== Buffer.isEncoding = function (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'raw': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } } Buffer.isBuffer = function (b) { return !!(b != null && b._isBuffer) } Buffer.byteLength = function (str, encoding) { var ret str = str.toString() switch (encoding || 'utf8') { case 'hex': ret = str.length / 2 break case 'utf8': case 'utf-8': ret = utf8ToBytes(str).length break case 'ascii': case 'binary': case 'raw': ret = str.length break case 'base64': ret = base64ToBytes(str).length break case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = str.length * 2 break default: throw new Error('Unknown encoding') } return ret } Buffer.concat = function (list, totalLength) { assert(isArray(list), 'Usage: Buffer.concat(list[, length])') if (list.length === 0) { return new Buffer(0) } else if (list.length === 1) { return list[0] } var i if (totalLength === undefined) { totalLength = 0 for (i = 0; i < list.length; i++) { totalLength += list[i].length } } var buf = new Buffer(totalLength) var pos = 0 for (i = 0; i < list.length; i++) { var item = list[i] item.copy(buf, pos) pos += item.length } return buf } Buffer.compare = function (a, b) { assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers') var x = a.length var y = b.length for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} if (i !== len) { x = a[i] y = b[i] } if (x < y) { return -1 } if (y < x) { return 1 } return 0 } // BUFFER INSTANCE METHODS // ======================= function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 var remaining = buf.length - offset if (!length) { length = remaining } else { length = Number(length) if (length > remaining) { length = remaining } } // must be an even number of digits var strLen = string.length assert(strLen % 2 === 0, 'Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var byte = parseInt(string.substr(i * 2, 2), 16) assert(!isNaN(byte), 'Invalid hex string') buf[offset + i] = byte } return i } function utf8Write (buf, string, offset, length) { var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) return charsWritten } function asciiWrite (buf, string, offset, length) { var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) return charsWritten } function binaryWrite (buf, string, offset, length) { return asciiWrite(buf, string, offset, length) } function base64Write (buf, string, offset, length) { var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) return charsWritten } function utf16leWrite (buf, string, offset, length) { var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) return charsWritten } Buffer.prototype.write = function (string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length length = undefined } } else { // legacy var swap = encoding encoding = offset offset = length length = swap } offset = Number(offset) || 0 var remaining = this.length - offset if (!length) { length = remaining } else { length = Number(length) if (length > remaining) { length = remaining } } encoding = String(encoding || 'utf8').toLowerCase() var ret switch (encoding) { case 'hex': ret = hexWrite(this, string, offset, length) break case 'utf8': case 'utf-8': ret = utf8Write(this, string, offset, length) break case 'ascii': ret = asciiWrite(this, string, offset, length) break case 'binary': ret = binaryWrite(this, string, offset, length) break case 'base64': ret = base64Write(this, string, offset, length) break case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = utf16leWrite(this, string, offset, length) break default: throw new Error('Unknown encoding') } return ret } Buffer.prototype.toString = function (encoding, start, end) { var self = this encoding = String(encoding || 'utf8').toLowerCase() start = Number(start) || 0 end = (end === undefined) ? self.length : Number(end) // Fastpath empty strings if (end === start) return '' var ret switch (encoding) { case 'hex': ret = hexSlice(self, start, end) break case 'utf8': case 'utf-8': ret = utf8Slice(self, start, end) break case 'ascii': ret = asciiSlice(self, start, end) break case 'binary': ret = binarySlice(self, start, end) break case 'base64': ret = base64Slice(self, start, end) break case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = utf16leSlice(self, start, end) break default: throw new Error('Unknown encoding') } return ret } Buffer.prototype.toJSON = function () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } } Buffer.prototype.equals = function (b) { assert(Buffer.isBuffer(b), 'Argument must be a Buffer') return Buffer.compare(this, b) === 0 } Buffer.prototype.compare = function (b) { assert(Buffer.isBuffer(b), 'Argument must be a Buffer') return Buffer.compare(this, b) } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function (target, target_start, start, end) { var source = this if (!start) start = 0 if (!end && end !== 0) end = this.length if (!target_start) target_start = 0 // Copy 0 bytes; we're done if (end === start) return if (target.length === 0 || source.length === 0) return // Fatal error conditions assert(end >= start, 'sourceEnd < sourceStart') assert(target_start >= 0 && target_start < target.length, 'targetStart out of bounds') assert(start >= 0 && start < source.length, 'sourceStart out of bounds') assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length if (target.length - target_start < end - start) end = target.length - target_start + start var len = end - start if (len < 100 || !TYPED_ARRAY_SUPPORT) { for (var i = 0; i < len; i++) { target[i + target_start] = this[i + start] } } else { target._set(this.subarray(start, start + len), target_start) } } function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) } else { return base64.fromByteArray(buf.slice(start, end)) } } function utf8Slice (buf, start, end) { var res = '' var tmp = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { if (buf[i] <= 0x7F) { res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) tmp = '' } else { tmp += '%' + buf[i].toString(16) } } return res + decodeUtf8Char(tmp) } function asciiSlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { ret += String.fromCharCode(buf[i]) } return ret } function binarySlice (buf, start, end) { return asciiSlice(buf, start, end) } function hexSlice (buf, start, end) { var len = buf.length if (!start || start < 0) start = 0 if (!end || end < 0 || end > len) end = len var out = '' for (var i = start; i < end; i++) { out += toHex(buf[i]) } return out } function utf16leSlice (buf, start, end) { var bytes = buf.slice(start, end) var res = '' for (var i = 0; i < bytes.length; i += 2) { res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) } return res } Buffer.prototype.slice = function (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { start += len; if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len if (end < 0) end = 0 } else if (end > len) { end = len } if (end < start) end = start if (TYPED_ARRAY_SUPPORT) { return Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start var newBuf = new Buffer(sliceLen, undefined, true) for (var i = 0; i < sliceLen; i++) { newBuf[i] = this[i + start] } return newBuf } } // `get` will be removed in Node 0.13+ Buffer.prototype.get = function (offset) { console.log('.get() is deprecated. Access using array indexes instead.') return this.readUInt8(offset) } // `set` will be removed in Node 0.13+ Buffer.prototype.set = function (v, offset) { console.log('.set() is deprecated. Access using array indexes instead.') return this.writeUInt8(v, offset) } Buffer.prototype.readUInt8 = function (offset, noAssert) { if (!noAssert) { assert(offset !== undefined && offset !== null, 'missing offset') assert(offset < this.length, 'Trying to read beyond buffer length') } if (offset >= this.length) return return this[offset] } function readUInt16 (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length if (offset >= len) return var val if (littleEndian) { val = buf[offset] if (offset + 1 < len) val |= buf[offset + 1] << 8 } else { val = buf[offset] << 8 if (offset + 1 < len) val |= buf[offset + 1] } return val } Buffer.prototype.readUInt16LE = function (offset, noAssert) { return readUInt16(this, offset, true, noAssert) } Buffer.prototype.readUInt16BE = function (offset, noAssert) { return readUInt16(this, offset, false, noAssert) } function readUInt32 (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length if (offset >= len) return var val if (littleEndian) { if (offset + 2 < len) val = buf[offset + 2] << 16 if (offset + 1 < len) val |= buf[offset + 1] << 8 val |= buf[offset] if (offset + 3 < len) val = val + (buf[offset + 3] << 24 >>> 0) } else { if (offset + 1 < len) val = buf[offset + 1] << 16 if (offset + 2 < len) val |= buf[offset + 2] << 8 if (offset + 3 < len) val |= buf[offset + 3] val = val + (buf[offset] << 24 >>> 0) } return val } Buffer.prototype.readUInt32LE = function (offset, noAssert) { return readUInt32(this, offset, true, noAssert) } Buffer.prototype.readUInt32BE = function (offset, noAssert) { return readUInt32(this, offset, false, noAssert) } Buffer.prototype.readInt8 = function (offset, noAssert) { if (!noAssert) { assert(offset !== undefined && offset !== null, 'missing offset') assert(offset < this.length, 'Trying to read beyond buffer length') } if (offset >= this.length) return var neg = this[offset] & 0x80 if (neg) return (0xff - this[offset] + 1) * -1 else return this[offset] } function readInt16 (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length if (offset >= len) return var val = readUInt16(buf, offset, littleEndian, true) var neg = val & 0x8000 if (neg) return (0xffff - val + 1) * -1 else return val } Buffer.prototype.readInt16LE = function (offset, noAssert) { return readInt16(this, offset, true, noAssert) } Buffer.prototype.readInt16BE = function (offset, noAssert) { return readInt16(this, offset, false, noAssert) } function readInt32 (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length if (offset >= len) return var val = readUInt32(buf, offset, littleEndian, true) var neg = val & 0x80000000 if (neg) return (0xffffffff - val + 1) * -1 else return val } Buffer.prototype.readInt32LE = function (offset, noAssert) { return readInt32(this, offset, true, noAssert) } Buffer.prototype.readInt32BE = function (offset, noAssert) { return readInt32(this, offset, false, noAssert) } function readFloat (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } return ieee754.read(buf, offset, littleEndian, 23, 4) } Buffer.prototype.readFloatLE = function (offset, noAssert) { return readFloat(this, offset, true, noAssert) } Buffer.prototype.readFloatBE = function (offset, noAssert) { return readFloat(this, offset, false, noAssert) } function readDouble (buf, offset, littleEndian, noAssert) { if (!noAssert) { assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') } return ieee754.read(buf, offset, littleEndian, 52, 8) } Buffer.prototype.readDoubleLE = function (offset, noAssert) { return readDouble(this, offset, true, noAssert) } Buffer.prototype.readDoubleBE = function (offset, noAssert) { return readDouble(this, offset, false, noAssert) } Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset < this.length, 'trying to write beyond buffer length') verifuint(value, 0xff) } if (offset >= this.length) return this[offset] = value return offset + 1 } function writeUInt16 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'trying to write beyond buffer length') verifuint(value, 0xffff) } var len = buf.length if (offset >= len) return for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } return offset + 2 } Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { return writeUInt16(this, value, offset, true, noAssert) } Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { return writeUInt16(this, value, offset, false, noAssert) } function writeUInt32 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'trying to write beyond buffer length') verifuint(value, 0xffffffff) } var len = buf.length if (offset >= len) return for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } return offset + 4 } Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { return writeUInt32(this, value, offset, true, noAssert) } Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { return writeUInt32(this, value, offset, false, noAssert) } Buffer.prototype.writeInt8 = function (value, offset, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset < this.length, 'Trying to write beyond buffer length') verifsint(value, 0x7f, -0x80) } if (offset >= this.length) return if (value >= 0) this.writeUInt8(value, offset, noAssert) else this.writeUInt8(0xff + value + 1, offset, noAssert) return offset + 1 } function writeInt16 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') verifsint(value, 0x7fff, -0x8000) } var len = buf.length if (offset >= len) return if (value >= 0) writeUInt16(buf, value, offset, littleEndian, noAssert) else writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) return offset + 2 } Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { return writeInt16(this, value, offset, true, noAssert) } Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { return writeInt16(this, value, offset, false, noAssert) } function writeInt32 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') verifsint(value, 0x7fffffff, -0x80000000) } var len = buf.length if (offset >= len) return if (value >= 0) writeUInt32(buf, value, offset, littleEndian, noAssert) else writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) return offset + 4 } Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { return writeInt32(this, value, offset, true, noAssert) } Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { return writeInt32(this, value, offset, false, noAssert) } function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) } var len = buf.length if (offset >= len) return ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 7 < buf.length, 'Trying to write beyond buffer length') verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) } var len = buf.length if (offset >= len) return ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length assert(end >= start, 'end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return assert(start >= 0 && start < this.length, 'start out of bounds') assert(end >= 0 && end <= this.length, 'end out of bounds') var i if (typeof value === 'number') { for (i = start; i < end; i++) { this[i] = value } } else { var bytes = utf8ToBytes(value.toString()) var len = bytes.length for (i = start; i < end; i++) { this[i] = bytes[i % len] } } return this } Buffer.prototype.inspect = function () { var out = [] var len = this.length for (var i = 0; i < len; i++) { out[i] = toHex(this[i]) if (i === exports.INSPECT_MAX_BYTES) { out[i + 1] = '...' break } } return '' } /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. */ Buffer.prototype.toArrayBuffer = function () { if (typeof Uint8Array !== 'undefined') { if (TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer } else { var buf = new Uint8Array(this.length) for (var i = 0, len = buf.length; i < len; i += 1) { buf[i] = this[i] } return buf.buffer } } else { throw new Error('Buffer.toArrayBuffer not supported in this browser') } } // HELPER FUNCTIONS // ================ var BP = Buffer.prototype /** * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ Buffer._augment = function (arr) { arr._isBuffer = true // save reference to original Uint8Array get/set methods before overwriting arr._get = arr.get arr._set = arr.set // deprecated, will be removed in node 0.13+ arr.get = BP.get arr.set = BP.set arr.write = BP.write arr.toString = BP.toString arr.toLocaleString = BP.toString arr.toJSON = BP.toJSON arr.equals = BP.equals arr.compare = BP.compare arr.copy = BP.copy arr.slice = BP.slice arr.readUInt8 = BP.readUInt8 arr.readUInt16LE = BP.readUInt16LE arr.readUInt16BE = BP.readUInt16BE arr.readUInt32LE = BP.readUInt32LE arr.readUInt32BE = BP.readUInt32BE arr.readInt8 = BP.readInt8 arr.readInt16LE = BP.readInt16LE arr.readInt16BE = BP.readInt16BE arr.readInt32LE = BP.readInt32LE arr.readInt32BE = BP.readInt32BE arr.readFloatLE = BP.readFloatLE arr.readFloatBE = BP.readFloatBE arr.readDoubleLE = BP.readDoubleLE arr.readDoubleBE = BP.readDoubleBE arr.writeUInt8 = BP.writeUInt8 arr.writeUInt16LE = BP.writeUInt16LE arr.writeUInt16BE = BP.writeUInt16BE arr.writeUInt32LE = BP.writeUInt32LE arr.writeUInt32BE = BP.writeUInt32BE arr.writeInt8 = BP.writeInt8 arr.writeInt16LE = BP.writeInt16LE arr.writeInt16BE = BP.writeInt16BE arr.writeInt32LE = BP.writeInt32LE arr.writeInt32BE = BP.writeInt32BE arr.writeFloatLE = BP.writeFloatLE arr.writeFloatBE = BP.writeFloatBE arr.writeDoubleLE = BP.writeDoubleLE arr.writeDoubleBE = BP.writeDoubleBE arr.fill = BP.fill arr.inspect = BP.inspect arr.toArrayBuffer = BP.toArrayBuffer return arr } var INVALID_BASE64_RE = /[^+\/0-9A-z]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' } return str } function stringtrim (str) { if (str.trim) return str.trim() return str.replace(/^\s+|\s+$/g, '') } function isArray (subject) { return (Array.isArray || function (subject) { return Object.prototype.toString.call(subject) === '[object Array]' })(subject) } function isArrayish (subject) { return isArray(subject) || Buffer.isBuffer(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number' } function toHex (n) { if (n < 16) return '0' + n.toString(16) return n.toString(16) } function utf8ToBytes (str) { var byteArray = [] for (var i = 0; i < str.length; i++) { var b = str.charCodeAt(i) if (b <= 0x7F) { byteArray.push(b) } else { var start = i if (b >= 0xD800 && b <= 0xDFFF) i++ var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') for (var j = 0; j < h.length; j++) { byteArray.push(parseInt(h[j], 16)) } } } return byteArray } function asciiToBytes (str) { var byteArray = [] for (var i = 0; i < str.length; i++) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) } return byteArray } function utf16leToBytes (str) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; i++) { c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 byteArray.push(lo) byteArray.push(hi) } return byteArray } function base64ToBytes (str) { return base64.toByteArray(str) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; i++) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i } function decodeUtf8Char (str) { try { return decodeURIComponent(str) } catch (err) { return String.fromCharCode(0xFFFD) // UTF 8 invalid char } } /* * We have to make sure that the value is a valid integer. This means that it * is non-negative. It has no fractional component and that it does not * exceed the maximum allowed value. */ function verifuint (value, max) { assert(typeof value === 'number', 'cannot write a non-number as a number') assert(value >= 0, 'specified a negative value for writing an unsigned value') assert(value <= max, 'value is larger than maximum value for type') assert(Math.floor(value) === value, 'value has a fractional component') } function verifsint (value, max, min) { assert(typeof value === 'number', 'cannot write a non-number as a number') assert(value <= max, 'value larger than maximum allowed value') assert(value >= min, 'value smaller than minimum allowed value') assert(Math.floor(value) === value, 'value has a fractional component') } function verifIEEE754 (value, max, min) { assert(typeof value === 'number', 'cannot write a non-number as a number') assert(value <= max, 'value larger than maximum allowed value') assert(value >= min, 'value smaller than minimum allowed value') } function assert (test, message) { if (!test) throw new Error(message || 'Failed assertion') } },{"base64-js":89,"ieee754":90}],89:[function(require,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { 'use strict'; var Arr = (typeof Uint8Array !== 'undefined') ? Uint8Array : Array var PLUS = '+'.charCodeAt(0) var SLASH = '/'.charCodeAt(0) var NUMBER = '0'.charCodeAt(0) var LOWER = 'a'.charCodeAt(0) var UPPER = 'A'.charCodeAt(0) function decode (elt) { var code = elt.charCodeAt(0) if (code === PLUS) return 62 // '+' if (code === SLASH) return 63 // '/' if (code < NUMBER) return -1 //no match if (code < NUMBER + 10) return code - NUMBER + 26 + 26 if (code < UPPER + 26) return code - UPPER if (code < LOWER + 26) return code - LOWER + 26 } function b64ToByteArray (b64) { var i, j, l, tmp, placeHolders, arr if (b64.length % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice var len = b64.length placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 // base64 is 4/3 + up to two characters of the original data arr = new Arr(b64.length * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? b64.length - 4 : b64.length var L = 0 function push (v) { arr[L++] = v } for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) push((tmp & 0xFF0000) >> 16) push((tmp & 0xFF00) >> 8) push(tmp & 0xFF) } if (placeHolders === 2) { tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) push(tmp & 0xFF) } else if (placeHolders === 1) { tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) push((tmp >> 8) & 0xFF) push(tmp & 0xFF) } return arr } function uint8ToBase64 (uint8) { var i, extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes output = "", temp, length function encode (num) { return lookup.charAt(num) } function tripletToBase64 (num) { return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) } // go through the array every three bytes, we'll deal with trailing stuff later for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) output += tripletToBase64(temp) } // pad the end with zeros, but make sure to not forget the extra bytes switch (extraBytes) { case 1: temp = uint8[uint8.length - 1] output += encode(temp >> 2) output += encode((temp << 4) & 0x3F) output += '==' break case 2: temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) output += encode(temp >> 10) output += encode((temp >> 4) & 0x3F) output += encode((temp << 2) & 0x3F) output += '=' break } return output } exports.toByteArray = b64ToByteArray exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) },{}],90:[function(require,module,exports){ exports.read = function(buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, nBits = -7, i = isLE ? (nBytes - 1) : 0, d = isLE ? -1 : 1, s = buffer[offset + i]; i += d; e = s & ((1 << (-nBits)) - 1); s >>= (-nBits); nBits += eLen; for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); m = e & ((1 << (-nBits)) - 1); e >>= (-nBits); nBits += mLen; for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); if (e === 0) { e = 1 - eBias; } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity); } else { m = m + Math.pow(2, mLen); e = e - eBias; } return (s ? -1 : 1) * m * Math.pow(2, e - mLen); }; exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { var e, m, c, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), i = isLE ? 0 : (nBytes - 1), d = isLE ? 1 : -1, s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; value = Math.abs(value); if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0; e = eMax; } else { e = Math.floor(Math.log(value) / Math.LN2); if (value * (c = Math.pow(2, -e)) < 1) { e--; c *= 2; } if (e + eBias >= 1) { value += rt / c; } else { value += rt * Math.pow(2, 1 - eBias); } if (value * c >= 2) { e++; c /= 2; } if (e + eBias >= eMax) { m = 0; e = eMax; } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen); e = e + eBias; } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); e = 0; } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); e = (e << mLen) | m; eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); buffer[offset + i - d] |= s * 128; }; },{}],91:[function(require,module,exports){ // (c) Dean McNamee , 2012. // // https://github.com/deanm/css-color-parser-js // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // http://www.w3.org/TR/css3-color/ var kCSSColorTable = { "transparent": [0,0,0,0], "aliceblue": [240,248,255,1], "antiquewhite": [250,235,215,1], "aqua": [0,255,255,1], "aquamarine": [127,255,212,1], "azure": [240,255,255,1], "beige": [245,245,220,1], "bisque": [255,228,196,1], "black": [0,0,0,1], "blanchedalmond": [255,235,205,1], "blue": [0,0,255,1], "blueviolet": [138,43,226,1], "brown": [165,42,42,1], "burlywood": [222,184,135,1], "cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1], "chocolate": [210,105,30,1], "coral": [255,127,80,1], "cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1], "crimson": [220,20,60,1], "cyan": [0,255,255,1], "darkblue": [0,0,139,1], "darkcyan": [0,139,139,1], "darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1], "darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1], "darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1], "darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1], "darkorchid": [153,50,204,1], "darkred": [139,0,0,1], "darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1], "darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1], "darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1], "darkviolet": [148,0,211,1], "deeppink": [255,20,147,1], "deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1], "dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1], "firebrick": [178,34,34,1], "floralwhite": [255,250,240,1], "forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1], "gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1], "gold": [255,215,0,1], "goldenrod": [218,165,32,1], "gray": [128,128,128,1], "green": [0,128,0,1], "greenyellow": [173,255,47,1], "grey": [128,128,128,1], "honeydew": [240,255,240,1], "hotpink": [255,105,180,1], "indianred": [205,92,92,1], "indigo": [75,0,130,1], "ivory": [255,255,240,1], "khaki": [240,230,140,1], "lavender": [230,230,250,1], "lavenderblush": [255,240,245,1], "lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1], "lightblue": [173,216,230,1], "lightcoral": [240,128,128,1], "lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1], "lightgray": [211,211,211,1], "lightgreen": [144,238,144,1], "lightgrey": [211,211,211,1], "lightpink": [255,182,193,1], "lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1], "lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1], "lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1], "lightyellow": [255,255,224,1], "lime": [0,255,0,1], "limegreen": [50,205,50,1], "linen": [250,240,230,1], "magenta": [255,0,255,1], "maroon": [128,0,0,1], "mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1], "mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1], "mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1], "mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1], "mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1], "mintcream": [245,255,250,1], "mistyrose": [255,228,225,1], "moccasin": [255,228,181,1], "navajowhite": [255,222,173,1], "navy": [0,0,128,1], "oldlace": [253,245,230,1], "olive": [128,128,0,1], "olivedrab": [107,142,35,1], "orange": [255,165,0,1], "orangered": [255,69,0,1], "orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1], "palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1], "palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1], "peachpuff": [255,218,185,1], "peru": [205,133,63,1], "pink": [255,192,203,1], "plum": [221,160,221,1], "powderblue": [176,224,230,1], "purple": [128,0,128,1], "red": [255,0,0,1], "rosybrown": [188,143,143,1], "royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1], "salmon": [250,128,114,1], "sandybrown": [244,164,96,1], "seagreen": [46,139,87,1], "seashell": [255,245,238,1], "sienna": [160,82,45,1], "silver": [192,192,192,1], "skyblue": [135,206,235,1], "slateblue": [106,90,205,1], "slategray": [112,128,144,1], "slategrey": [112,128,144,1], "snow": [255,250,250,1], "springgreen": [0,255,127,1], "steelblue": [70,130,180,1], "tan": [210,180,140,1], "teal": [0,128,128,1], "thistle": [216,191,216,1], "tomato": [255,99,71,1], "turquoise": [64,224,208,1], "violet": [238,130,238,1], "wheat": [245,222,179,1], "white": [255,255,255,1], "whitesmoke": [245,245,245,1], "yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]} function clamp_css_byte(i) { // Clamp to integer 0 .. 255. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0. return f < 0 ? 0 : f > 1 ? 1 : f; } function parse_css_int(str) { // int or percentage. if (str[str.length - 1] === '%') return clamp_css_byte(parseFloat(str) / 100 * 255); return clamp_css_byte(parseInt(str)); } function parse_css_float(str) { // float or percentage. if (str[str.length - 1] === '%') return clamp_css_float(parseFloat(str) / 100); return clamp_css_float(parseFloat(str)); } function css_hue_to_rgb(m1, m2, h) { if (h < 0) h += 1; else if (h > 1) h -= 1; if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; return m1; } function parseCSSColor(css_str) { // Remove all whitespace, not compliant, but should just be more accepting. var str = css_str.replace(/ /g, '').toLowerCase(); // Color keywords (and transparent) lookup. if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup. // #abc and #abc123 syntax. if (str[0] === '#') { if (str.length === 4) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN. return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), 1]; } else if (str.length === 7) { var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN. return [(iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, 1]; } return null; } var op = str.indexOf('('), ep = str.indexOf(')'); if (op !== -1 && ep + 1 === str.length) { var fname = str.substr(0, op); var params = str.substr(op+1, ep-(op+1)).split(','); var alpha = 1; // To allow case fallthrough. switch (fname) { case 'rgba': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'rgb': if (params.length !== 3) return null; return [parse_css_int(params[0]), parse_css_int(params[1]), parse_css_int(params[2]), alpha]; case 'hsla': if (params.length !== 4) return null; alpha = parse_css_float(params.pop()); // Fall through. case 'hsl': if (params.length !== 3) return null; var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1 // NOTE(deanm): According to the CSS spec s/l should only be // percentages, but we don't bother and let float or percentage. var s = parse_css_float(params[1]); var l = parse_css_float(params[2]); var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; var m1 = l * 2 - m2; return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255), clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255), alpha]; default: return null; } } return null; } try { exports.parseCSSColor = parseCSSColor } catch(e) { } },{}],92:[function(require,module,exports){ var geojsonArea = require('geojson-area'); module.exports = rewind; function rewind(gj, outer) { switch ((gj && gj.type) || null) { case 'FeatureCollection': gj.features = gj.features.map(curryOuter(rewind, outer)); return gj; case 'Feature': gj.geometry = rewind(gj.geometry, outer); return gj; case 'Polygon': case 'MultiPolygon': return correct(gj, outer); default: return gj; } } function curryOuter(a, b) { return function(_) { return a(_, b); }; } function correct(_, outer) { if (_.type === 'Polygon') { _.coordinates = correctRings(_.coordinates, outer); } else if (_.type === 'MultiPolygon') { _.coordinates = _.coordinates.map(curryOuter(correctRings, outer)); } return _; } function correctRings(_, outer) { outer = !!outer; _[0] = wind(_[0], !outer); for (var i = 1; i < _.length; i++) { _[i] = wind(_[i], outer); } return _; } function wind(_, dir) { return cw(_) === dir ? _ : _.reverse(); } function cw(_) { return geojsonArea.ring(_) >= 0; } },{"geojson-area":93}],93:[function(require,module,exports){ var wgs84 = require('wgs84'); module.exports.geometry = geometry; module.exports.ring = ringArea; function geometry(_) { if (_.type === 'Polygon') return polygonArea(_.coordinates); else if (_.type === 'MultiPolygon') { var area = 0; for (var i = 0; i < _.coordinates.length; i++) { area += polygonArea(_.coordinates[i]); } return area; } else { return null; } } function polygonArea(coords) { var area = 0; if (coords && coords.length > 0) { area += Math.abs(ringArea(coords[0])); for (var i = 1; i < coords.length; i++) { area -= Math.abs(ringArea(coords[i])); } } return area; } /** * Calculate the approximate area of the polygon were it projected onto * the earth. Note that this area will be positive if ring is oriented * clockwise, otherwise it will be negative. * * Reference: * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409 * * Returns: * {float} The approximate signed geodesic area of the polygon in square * meters. */ function ringArea(coords) { var area = 0; if (coords.length > 2) { var p1, p2; for (var i = 0; i < coords.length - 1; i++) { p1 = coords[i]; p2 = coords[i + 1]; area += rad(p2[0] - p1[0]) * (2 + Math.sin(rad(p1[1])) + Math.sin(rad(p2[1]))); } area = area * wgs84.RADIUS * wgs84.RADIUS / 2; } return area; } function rad(_) { return _ * Math.PI / 180; } },{"wgs84":94}],94:[function(require,module,exports){ module.exports.RADIUS = 6378137; module.exports.FLATTENING = 1/298.257223563; module.exports.POLAR_RADIUS = 6356752.3142; },{}],95:[function(require,module,exports){ module.exports={ "$version": 4, "$root": { "version": { "required": true, "type": "enum", "values": [ 4 ], "doc": "Stylesheet version number. Must be 4." }, "constants": { "type": "constants", "doc": "An object of constants to be referenced in layers." }, "sources": { "required": true, "type": "sources", "doc": "Data source specifications for layers to pull from." }, "layers": { "required": true, "type": "array", "value": "layer", "doc": "An array of layers. The order of layers coincides with the order they will be drawn." }, "sprite": { "type": "sprite", "doc": "Sprite definition." }, "glyphs": { "type": "string", "doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}." }, "transition": { "type": "transition", "doc": "A global transition definition to use as a default across properties." } }, "sprite": [{ "type": "string", "doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended." }], "constants": { "*": { "type": "*", "doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol." } }, "sources": { "*": { "type": "source" } }, "source": { "type": { "required": true, "type": "enum", "values": [ "vector", "raster", "geojson", "video" ], "doc": "The data type of the source." }, "url": { "required": true, "type": "string", "doc": "A URL, or URL template to retrive the source data." }, "tileSize": { "type": "number", "default": 512, "doc": "The minimum visual size (in px) to display tiles for this layer. Only configurable for raster layers." }, "minZoom": { "type": "number", "default": 0, "doc": "Minimum zoom level for which tiles are available." }, "maxZoom": { "type": "number", "default": 22, "doc": "Maximum zoom level for which tiles are available. Data from tiles at the maxZoom are used when displaying the map at higher zoom levels." }, "*": { "type": "*", "doc": "Other keys to configure the data source." } }, "layer": { "id": { "type": "string", "doc": "Unique layer name." }, "type": { "type": "enum", "values": [ "fill", "line", "symbol", "raster", "background" ], "doc": "Rendering type of this layer." }, "ref": { "type": "string", "doc": "References another layer to copy `source`, `source_layer`, `filter`, and `render` properties from. This allows the layers to share processing and be more efficient." }, "source": { "type": "string", "doc": "Name of a source description to be used for this layer." }, "source-layer": { "type": "string", "doc": "Layer to use from a vector tile source. Required if the source supports multiple layers." }, "min-zoom": { "type": "number", "doc": "The minimum zoom level on which the layer gets parsed and appears on." }, "max-zoom": { "type": "number", "doc": "The maximum zoom level on which the layer gets parsed and appears on." }, "interactive": { "type": "boolean", "doc": "Enable querying of feature data from this layer for interactivity.", "default": false }, "render": { "type": "render", "doc": "Symbolizer type that should be used to visualize this layer. If unspecified or null, this layer is not treated as a symbolizer and only exists to have properties inherited to other layers using ref." }, "filter": { "type": "filter", "doc": "Array or object of filters or expressions." }, "layers": { "type": "array", "value": "layer", "doc": "If `type` is `raster`, the child layers are composited together onto the previous level layer level." }, "style": { "type": "class", "doc": "Default style properties for this layer." }, "style.*": { "type": "class", "doc": "Override style properties for this layer. The class name is the part after the first dot." } }, "render": [ "render_fill", "render_line", "render_symbol", "render_raster", "render_background" ], "render_background": { }, "render_fill": { }, "render_line": { "line-cap": { "type": "enum", "values": [ "butt", "round", "square" ], "default": "butt", "doc": "The display of line endings." }, "line-join": { "type": "enum", "values": [ "bevel", "round", "miter" ], "default": "miter", "doc": "The display of lines when joining." }, "line-miter-limit": { "type": "number", "default": 2, "doc": "Used to automatically convert miter joins to bevel joins for sharp angles." }, "line-round-limit": { "type": "number", "default": 1, "doc": "Used to automatically convert round joins to miter joins for shallow angles." } }, "render_symbol": { "symbol-placement": { "type": "enum", "values": [ "point", "line" ], "default": "point", "doc": "Placement of a label relative to its geometry. `Line` can only be used on LineStrings and Polygons." }, "symbol-min-distance": { "type": "number", "default": 250, "doc": "Minimum distance between two symbol anchors (px)" }, "symbol-avoid-edges": { "type": "boolean", "default": false, "doc": "If true, the symbols will not cross tile edges. Symbols that cross tile edges may cause collisions in some cases. This property should be set to true if the layer does not have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer." }, "icon-allow-overlap": { "type": "boolean", "default": false, "doc": "If true, the icon will be visible even if it collides with other icons and text." }, "icon-ignore-placement": { "type": "boolean", "default": false, "doc": "If true, the icon won't affect placement of other icons and text." }, "icon-optional": { "type": "boolean", "default": false, "doc": "If true, text can be shown without its corresponding icon." }, "icon-rotation-alignment": { "type": "enum", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon when map is rotated" }, "icon-max-size": { "type": "number", "default": 1, "doc": "The maximum amount to scale the icon by." }, "icon-image": { "type": "string", "doc": "A string with {tokens} replaced, referencing the data property to pull from." }, "icon-rotate": { "type": "number", "default": 0, "doc": "Rotates the icon clockwise by the specified number of degrees." }, "icon-padding": { "type": "number", "default": 2, "doc": "Padding value around icon bounding box to avoid icon collisions (px)." }, "icon-keep-upright": { "type": "boolean", "default": false, "doc": "If true, the icon may be flipped to prevent it from being rendered upside-down" }, "icon-offset": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "doc": "Icon's offset, in pixels. Values are [x, y] where negatives indicate left and up, respectively." }, "text-rotation-alignment": { "type": "enum", "values": [ "map", "viewport" ], "default": "viewport", "doc": "Orientation of icon or text when map is rotated" }, "text-field": { "type": "string", "default": "", "doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}." }, "text-font": { "type": "string", "doc": "Font stack to use for displaying text." }, "text-max-size": { "type": "number", "default": 16, "doc": "The maximum size text will be displayed." }, "text-max-width": { "type": "number", "default": 15, "doc": "The maximum line width for text wrapping (em)." }, "text-line-height": { "type": "number", "default": 1.2, "doc": "Text leading value for multi-line text." }, "text-letter-spacing": { "type": "number", "default": 0, "doc": "Text kerning value (em)." }, "text-justify": { "type": "enum", "values": [ "center", "left", "right" ], "default": "center", "doc": "Text justification options." }, "text-horizontal-align": { "type": "enum", "values": [ "left", "center", "right" ], "default": "center", "doc": "Horizontal alignment of the text relative to the anchor." }, "text-vertical-align": { "type": "enum", "values": [ "top", "center", "bottom" ], "default": "center", "doc": "Vertical alignment of the text relative to the anchor." }, "text-max-angle": { "type": "number", "default": 45, "doc": "The maximum angle change, in degrees, allowed between adjacent characters." }, "text-rotate": { "type": "number", "default": 0, "doc": "Rotates the text clockwise by the specified number of degrees." }, "text-padding": { "type": "number", "default": 2, "doc": "Padding value around text bounding box to avoid label collisions (px)." }, "text-keep-upright": { "type": "boolean", "default": true, "doc": "If true, the direction of the text may be flipped to prevent it from being rendered upside-down" }, "text-transform": { "type": "enum", "values": [ "none", "uppercase", "lowercase" ], "default": "none", "doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property." }, "text-offset": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ] }, "text-allow-overlap": { "type": "boolean", "default": false, "doc": "If true, the text will be visible even if it collides with other icons and labels." }, "text-ignore-placement": { "type": "boolean", "default": false, "doc": "If true, the text won't affect placement of other icons and labels." }, "text-optional": { "type": "boolean", "default": false, "doc": "If true, icons can be shown without their corresponding text." } }, "render_raster": { "raster-size": { "type": "number", "function": true, "default": 256, "doc": "The texture image size (in pixels) vector layers will be rasterized at. Will automatically by scaled to match the visual tile size." }, "raster-blur": { "type": "number", "function": true, "default": 0, "doc": "Blur radius to apply to the raster texture before display." } }, "filter": [ { "type": "filter_expression", "doc": "Various filter expressions. Unless overridden by parent, these are interpreted as `AND`." }, { "type": "array", "value": "filter_expression", "doc": "Various filter expressions. Unless overridden by parent, these are interpreted as `OR`." } ], "filter_expression": { "&": { "type": "filter", "doc": "AND operator." }, "|": { "type": "filter", "doc": "OR operator." }, "^": { "type": "filter", "doc": "XOR operator." }, "!": { "type": "filter", "doc": "NOR operator." }, "$type": { "type": "enum", "values": [ "Point", "LineString", "Polygon" ], "doc": "Geometry type that features must match." }, "*": [ { "type": "filter_comparison", "doc": "Arbitarily named feature member. A comparison object defining a filter expression." }, { "type": "filter_value", "doc": "Arbitarily named feature member. A filter_value implies the equality (string/number/boolean) or set membership operator (array)." } ] }, "filter_comparison": { "==": { "type": "filter_value", "doc": "Equality operator." }, "!=": { "type": "filter_value", "doc": "Inequality operator." }, ">": { "type": "filter_value", "doc": "Greater than operator." }, ">=": { "type": "filter_value", "doc": "Greater or equal than operator." }, "<": { "type": "filter_value", "doc": "Less than operator." }, "<=": { "type": "filter_value", "doc": "Less than or equal operator." }, "in": { "type": "array", "value": "filter_primitive", "doc": "Set member operator." }, "!in": { "type": "array", "value": "filter_primitive", "doc": "Not in set operator." } }, "filter_value": [ { "type": "filter_primitive" }, { "type": "array", "value": "filter_primitive" } ], "filter_primitive": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" } ], "function": { "stops": { "type": "array", "required": true, "doc": "An array of stops.", "value": "function_stop" }, "base": { "type": "number", "default": 1, "doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly." } }, "function_stop": { "type": "array", "value": ["number", "color"], "length": 2, "doc": "Zoom level and value pair." }, "class": [ "class_fill", "class_line", "class_symbol", "class_raster", "class_background" ], "class_fill": { "fill-antialias": { "type": "boolean", "default": true, "function": true, "doc": "Whether or not the fill should be antialiased." }, "fill-opacity": { "type": "number", "function": true, "default": 1, "transition": true }, "fill-color": { "type": "color", "default": [ 0, 0, 0, 1 ], "function": true, "transition": true }, "fill-outline-color": { "type": "color", "doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.", "function": true, "transition": true }, "fill-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": true, "transition": true, "doc": "The geometry's offset, in pixels. Values are [x, y] where negatives indicate left and up, respectively." }, "fill-translate-anchor": { "type": "enum", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map" }, "fill-image": { "type": "string", "doc": "Name of image in sprite to use for drawing image fills." } }, "class_line": { "line-opacity": { "type": "number", "function": true, "default": 1, "transition": true }, "line-color": { "type": "color", "default": [ 0, 0, 0, 1 ], "function": true, "transition": true }, "line-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": true, "transition": true, "doc": "The geometry's offset, in pixels. Values are [x, y] where negatives indicate left and up, respectively." }, "line-translate-anchor": { "type": "enum", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map" }, "line-width": { "type": "number", "default": 1, "function": true, "transition": true, "doc": "Line width (in px)" }, "line-offset": { "type": "number", "default": 0, "doc": "Line casing where `line-offset` indicates total width. @TODO rename?", "function": true, "transition": true }, "line-blur": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "Line blur, in pixels." }, "line-dasharray": { "type": "array", "value": "number", "length": 2, "default": [ 1, -1 ], "function": true, "transition": true }, "line-image": { "type": "string", "doc": "Name of image in sprite to use for drawing image lines." } }, "class_symbol": { "icon-opacity": { "type": "number", "default": 1, "function": true, "transition": true }, "icon-size": { "type": "number", "default": 1, "function": true, "transition": true, "doc": "The amount to scale the icon by. 1 is original size, 3 triples the size." }, "icon-color": { "type": "color", "default": [ 0, 0, 0, 1 ], "function": true, "transition": true, "doc": "The color of the icon. This can only be used with sdf icons." }, "icon-halo-color": { "type": "color", "default": [ 0, 0, 0, 0 ], "function": true, "transition": true, "doc": "The color of the icon's halo. Icon halos can only be used with sdf icons." }, "icon-halo-width": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "How far away the halo is from the icon outline, in pixels." }, "icon-halo-blur": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "Fade out the halo towards the outside, in pixels." }, "icon-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": true, "transition": true, "doc": "An icon's offset, in pixels. Values are [x, y] where negatives indicate left and up, respectively." }, "icon-translate-anchor": { "type": "enum", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map" }, "text-opacity": { "type": "number", "default": 1, "function": true, "transition": true }, "text-size": { "type": "number", "default": 16, "function": true, "transition": true, "doc": "Font size in pixels. If unspecified, the text will be as big as allowed by the layer definition." }, "text-color": { "type": "color", "default": [ 0, 0, 0, 1 ], "function": true, "transition": true }, "text-halo-color": { "type": "color", "default": [ 0, 0, 0, 0 ], "function": true, "transition": true }, "text-halo-width": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "How far away the halo is from the font outline, in pixels. Max text halo width is 1/4 of the font-size (px)." }, "text-halo-blur": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "Fade out the halo towards the outside, in pixels." }, "text-translate": { "type": "array", "value": "number", "length": 2, "default": [ 0, 0 ], "function": true, "transition": true, "doc": "A label's offset, in pixels. Values are [x, y] where negatives indicate left and up, respectively." }, "text-translate-anchor": { "type": "enum", "values": [ "map", "viewport" ], "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", "default": "map" } }, "class_raster": { "raster-opacity": { "type": "number", "default": 1, "transition": true }, "raster-hue-rotate": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "Rotates hues around the color wheel by the specified number of degrees." }, "raster-brightness": { "type": "array", "value": "number", "length": 2, "default": [ 0, 1 ], "function": true, "transition": true }, "raster-saturation": { "type": "number", "default": 0, "function": true, "transition": true }, "raster-contrast": { "type": "number", "default": 0, "function": true, "transition": true }, "raster-fade": { "type": "number", "default": 0, "function": true, "transition": true, "doc": "Duration of the fade when a new tile is added. @TODO rename?" } }, "class_background": { "background-color": { "type": "color", "default": [ 0, 0, 0, 1 ], "function": true, "transition": true }, "background-image": { "type": "string" } }, "transition": { "duration": { "type": "number", "default": 300, "doc": "Time in milliseconds that it takes for transitions to complete." }, "delay": { "type": "number", "default": 0, "doc": "Time in milliseconds before a transition begins." } } } },{}],96:[function(require,module,exports){ (function (Buffer){ 'use strict'; var ieee754 = require('ieee754'); module.exports = Protobuf; function Protobuf(buf) { this.buf = buf; this.pos = 0; } Protobuf.prototype = { get length() { return this.buf.length; } }; Protobuf.Varint = 0; Protobuf.Int64 = 1; Protobuf.Message = 2; Protobuf.String = 2; Protobuf.Packed = 2; Protobuf.Int32 = 5; Protobuf.prototype.destroy = function() { this.buf = null; }; // === READING ================================================================= Protobuf.prototype.readUInt32 = function() { var val = this.buf.readUInt32LE(this.pos); this.pos += 4; return val; }; Protobuf.prototype.readUInt64 = function() { var val = this.buf.readUInt64LE(this.pos); this.pos += 8; return val; }; Protobuf.prototype.readDouble = function() { var val = ieee754.read(this.buf, this.pos, true, 52, 8); this.pos += 8; return val; }; Protobuf.prototype.readVarint = function() { // TODO: bounds checking var pos = this.pos; if (this.buf[pos] <= 0x7f) { this.pos++; return this.buf[pos]; } else if (this.buf[pos + 1] <= 0x7f) { this.pos += 2; return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] << 7); } else if (this.buf[pos + 2] <= 0x7f) { this.pos += 3; return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2]) << 14; } else if (this.buf[pos + 3] <= 0x7f) { this.pos += 4; return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21; } else if (this.buf[pos + 4] <= 0x7f) { this.pos += 5; return ((this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21) + (this.buf[pos + 4] * 268435456); } else { this.skip(Protobuf.Varint); return 0; // throw new Error("TODO: Handle 6+ byte varints"); } }; Protobuf.prototype.readSVarint = function() { var num = this.readVarint(); if (num > 2147483647) throw new Error('TODO: Handle numbers >= 2^30'); // zigzag encoding return ((num >> 1) ^ -(num & 1)); }; Protobuf.prototype.readString = function() { var bytes = this.readVarint(); // TODO: bounds checking var chr = String.fromCharCode; var b = this.buf; var p = this.pos; var end = this.pos + bytes; var str = ''; while (p < end) { if (b[p] <= 0x7F) str += chr(b[p++]); else if (b[p] <= 0xBF) throw new Error('Invalid UTF-8 codepoint: ' + b[p]); else if (b[p] <= 0xDF) str += chr((b[p++] & 0x1F) << 6 | (b[p++] & 0x3F)); else if (b[p] <= 0xEF) str += chr((b[p++] & 0x1F) << 12 | (b[p++] & 0x3F) << 6 | (b[p++] & 0x3F)); else if (b[p] <= 0xF7) p += 4; // We can't handle these codepoints in JS, so skip. else if (b[p] <= 0xFB) p += 5; else if (b[p] <= 0xFD) p += 6; else throw new Error('Invalid UTF-8 codepoint: ' + b[p]); } this.pos += bytes; return str; }; Protobuf.prototype.readBuffer = function() { var bytes = this.readVarint(); var buffer = this.buf.subarray(this.pos, this.pos + bytes); this.pos += bytes; return buffer; }; Protobuf.prototype.readPacked = function(type) { // TODO: bounds checking var bytes = this.readVarint(); var end = this.pos + bytes; var array = []; while (this.pos < end) { array.push(this['read' + type]()); } return array; }; Protobuf.prototype.skip = function(val) { // TODO: bounds checking var type = val & 0x7; switch (type) { /* varint */ case Protobuf.Varint: while (this.buf[this.pos++] > 0x7f); break; /* 64 bit */ case Protobuf.Int64: this.pos += 8; break; /* length */ case Protobuf.Message: var bytes = this.readVarint(); this.pos += bytes; break; /* 32 bit */ case Protobuf.Int32: this.pos += 4; break; default: throw new Error('Unimplemented type: ' + type); } }; // === WRITING ================================================================= Protobuf.prototype.writeTag = function(tag, type) { this.writeVarint((tag << 3) | type); }; Protobuf.prototype.realloc = function(min) { var length = this.buf.length; while (length < this.pos + min) length *= 2; if (length != this.buf.length) { var buf = new Buffer(length); this.buf.copy(buf); this.buf = buf; } }; Protobuf.prototype.finish = function() { return this.buf.slice(0, this.pos); }; Protobuf.prototype.writePacked = function(type, tag, items) { if (!items.length) return; var message = new Protobuf(); for (var i = 0; i < items.length; i++) { message['write' + type](items[i]); } var data = message.finish(); this.writeTag(tag, Protobuf.Packed); this.writeBuffer(data); }; Protobuf.prototype.writeUInt32 = function(val) { this.realloc(4); this.buf.writeUInt32LE(val, this.pos); this.pos += 4; }; Protobuf.prototype.writeTaggedUInt32 = function(tag, val) { this.writeTag(tag, Protobuf.Int32); this.writeUInt32(val); }; Protobuf.prototype.writeVarint = function(val) { val = Number(val); if (isNaN(val)) { val = 0; } if (val <= 0x7f) { this.realloc(1); this.buf[this.pos++] = val; } else if (val <= 0x3fff) { this.realloc(2); this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f); this.buf[this.pos++] = 0x00 | ((val >>> 7) & 0x7f); } else if (val <= 0x1ffffff) { this.realloc(3); this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f); this.buf[this.pos++] = 0x80 | ((val >>> 7) & 0x7f); this.buf[this.pos++] = 0x00 | ((val >>> 14) & 0x7f); } else if (val <= 0xfffffff) { this.realloc(4); this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f); this.buf[this.pos++] = 0x80 | ((val >>> 7) & 0x7f); this.buf[this.pos++] = 0x80 | ((val >>> 14) & 0x7f); this.buf[this.pos++] = 0x00 | ((val >>> 21) & 0x7f); } else { while (val > 0) { var b = val & 0x7f; val = Math.floor(val / 128); if (val > 0) b |= 0x80 this.realloc(1); this.buf[this.pos++] = b; } } }; Protobuf.prototype.writeTaggedVarint = function(tag, val) { this.writeTag(tag, Protobuf.Varint); this.writeVarint(val); }; Protobuf.prototype.writeSVarint = function(val) { if (val >= 0) { this.writeVarint(val * 2); } else { this.writeVarint(val * -2 - 1); } }; Protobuf.prototype.writeTaggedSVarint = function(tag, val) { this.writeTag(tag, Protobuf.Varint); this.writeSVarint(val); }; Protobuf.prototype.writeBoolean = function(val) { this.writeVarint(Boolean(val)); }; Protobuf.prototype.writeTaggedBoolean = function(tag, val) { this.writeTaggedVarint(tag, Boolean(val)); }; Protobuf.prototype.writeString = function(str) { str = String(str); var bytes = Buffer.byteLength(str); this.writeVarint(bytes); this.realloc(bytes); this.buf.write(str, this.pos); this.pos += bytes; }; Protobuf.prototype.writeTaggedString = function(tag, str) { this.writeTag(tag, Protobuf.String); this.writeString(str); }; Protobuf.prototype.writeFloat = function(val) { this.realloc(4); this.buf.writeFloatLE(val, this.pos); this.pos += 4; }; Protobuf.prototype.writeTaggedFloat = function(tag, val) { this.writeTag(tag, Protobuf.Int32); this.writeFloat(val); }; Protobuf.prototype.writeDouble = function(val) { this.realloc(8); this.buf.writeDoubleLE(val, this.pos); this.pos += 8; }; Protobuf.prototype.writeTaggedDouble = function(tag, val) { this.writeTag(tag, Protobuf.Int64); this.writeDouble(val); }; Protobuf.prototype.writeBuffer = function(buffer) { var bytes = buffer.length; this.writeVarint(bytes); this.realloc(bytes); buffer.copy(this.buf, this.pos); this.pos += bytes; }; Protobuf.prototype.writeTaggedBuffer = function(tag, buffer) { this.writeTag(tag, Protobuf.String); this.writeBuffer(buffer); }; Protobuf.prototype.writeMessage = function(tag, protobuf) { var buffer = protobuf.finish(); this.writeTag(tag, Protobuf.Message); this.writeBuffer(buffer); }; }).call(this,require("buffer").Buffer) },{"buffer":88,"ieee754":97}],97:[function(require,module,exports){ module.exports=require(90) },{}],98:[function(require,module,exports){ 'use strict'; module.exports = Point; function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { clone: function() { return new Point(this.x, this.y); }, add: function(p) { return this.clone()._add(p); }, sub: function(p) { return this.clone()._sub(p); }, mult: function(k) { return this.clone()._mult(k); }, div: function(k) { return this.clone()._div(k); }, rotate: function(a) { return this.clone()._rotate(a); }, matMult: function(m) { return this.clone()._matMult(m); }, unit: function() { return this.clone()._unit(); }, perp: function() { return this.clone()._perp(); }, round: function() { return this.clone()._round(); }, mag: function() { return Math.sqrt(this.x * this.x + this.y * this.y); }, equals: function(p) { return this.x === p.x && this.y === p.y; }, dist: function(p) { return Math.sqrt(this.distSqr(p)); }, distSqr: function(p) { var dx = p.x - this.x, dy = p.y - this.y; return dx * dx + dy * dy; }, angle: function() { return Math.atan2(this.y, this.x); }, angleTo: function(b) { return Math.atan2(this.y - b.y, this.x - b.x); }, angleWith: function(b) { return this.angleWithSep(b.x, b.y); }, // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ. angleWithSep: function(x, y) { return Math.atan2( this.x * y - this.y * x, this.x * x + this.y * y); }, _matMult: function(m) { var x = m[0] * this.x + m[1] * this.y, y = m[2] * this.x + m[3] * this.y; this.x = x; this.y = y; return this; }, _add: function(p) { this.x += p.x; this.y += p.y; return this; }, _sub: function(p) { this.x -= p.x; this.y -= p.y; return this; }, _mult: function(k) { this.x *= k; this.y *= k; return this; }, _div: function(k) { this.x /= k; this.y /= k; return this; }, _unit: function() { this._div(this.mag()); return this; }, _perp: function() { var y = this.y; this.y = this.x; this.x = -y; return this; }, _rotate: function(angle) { var cos = Math.cos(angle), sin = Math.sin(angle), x = cos * this.x - sin * this.y, y = sin * this.x + cos * this.y; this.x = x; this.y = y; return this; }, _round: function() { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; } }; // constructs Point from an array if necessary Point.convert = function (a) { if (a instanceof Point) { return a; } if (Array.isArray(a)) { return new Point(a[0], a[1]); } return a; }; },{}],99:[function(require,module,exports){ (function() { var slice = [].slice; function queue(parallelism) { var q, tasks = [], started = 0, // number of tasks that have been started (and perhaps finished) active = 0, // number of tasks currently being executed (started but not finished) remaining = 0, // number of tasks not yet finished popping, // inside a synchronous task callback? error = null, await = noop, all; if (!parallelism) parallelism = Infinity; function pop() { while (popping = started < tasks.length && active < parallelism) { var i = started++, t = tasks[i], a = slice.call(t, 1); a.push(callback(i)); ++active; t[0].apply(null, a); } } function callback(i) { return function(e, r) { --active; if (error != null) return; if (e != null) { error = e; // ignore new tasks and squelch active callbacks started = remaining = NaN; // stop queued tasks from starting notify(); } else { tasks[i] = r; if (--remaining) popping || pop(); else notify(); } }; } function notify() { if (error != null) await(error); else if (all) await(error, tasks); else await.apply(null, [error].concat(tasks)); } return q = { defer: function() { if (!error) { tasks.push(arguments); ++remaining; pop(); } return q; }, await: function(f) { await = f; all = false; if (!remaining) notify(); return q; }, awaitAll: function(f) { await = f; all = true; if (!remaining) notify(); return q; } }; } function noop() {} queue.version = "1.0.7"; if (typeof define === "function" && define.amd) define(function() { return queue; }); else if (typeof module === "object" && module.exports) module.exports = queue; else this.queue = queue; })(); },{}],100:[function(require,module,exports){ /* (c) 2013, Vladimir Agafonkin RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles. https://github.com/mourner/rbush */ (function () { 'use strict'; function rbush(maxEntries, format) { // jshint newcap: false, validthis: true if (!(this instanceof rbush)) { return new rbush(maxEntries, format); } // max entries in a node is 9 by default; min node fill is 40% for best performance this._maxEntries = Math.max(4, maxEntries || 9); this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); if (format) { this._initFormat(format); } this.clear(); } rbush.prototype = { all: function () { return this._all(this.data, []); }, search: function (bbox) { var node = this.data, result = []; if (!this._intersects(bbox, node.bbox)) { return result; } var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? this.toBBox(child) : child.bbox; if (this._intersects(bbox, childBBox)) { if (node.leaf) { result.push(child); } else if (this._contains(bbox, childBBox)) { this._all(child, result); } else { nodesToSearch.push(child); } } } node = nodesToSearch.pop(); } return result; }, load: function (data) { if (!(data && data.length)) { return this; } if (data.length < this._minEntries) { for (var i = 0, len = data.length; i < len; i++) { this.insert(data[i]); } return this; } // recursively build the tree with the given data from stratch using OMT algorithm var node = this._build(data.slice(), 0); if (!this.data.children.length) { // save as is if tree is empty this.data = node; } else if (this.data.height === node.height) { // split root if trees have the same height this._splitRoot(this.data, node); } else { if (this.data.height < node.height) { // swap trees if inserted one is bigger var tmpNode = this.data; this.data = node; node = tmpNode; } // insert the small tree into the large tree at appropriate level this._insert(node, this.data.height - node.height - 1, true); } return this; }, insert: function (item) { if (item) { this._insert(item, this.data.height - 1); } return this; }, clear: function () { this.data = { children: [], leaf: true, bbox: this._empty(), height: 1 }; return this; }, remove: function (item) { if (!item) { return this; } var node = this.data, bbox = this.toBBox(item), path = [], indexes = [], i, parent, index, goingUp; // depth-first iterative tree traversal while (node || path.length) { if (!node) { // go up node = path.pop(); parent = path[path.length - 1]; i = indexes.pop(); goingUp = true; } if (node.leaf) { // check current node index = node.children.indexOf(item); if (index !== -1) { // item found, remove the item and condense tree upwards node.children.splice(index, 1); path.push(node); this._condense(path); return this; } } if (!goingUp && !node.leaf && this._contains(node.bbox, bbox)) { // go down path.push(node); indexes.push(i); i = 0; parent = node; node = node.children[0]; } else if (parent) { // go right i++; node = parent.children[i]; goingUp = false; } else { // nothing found node = null; } } return this; }, toBBox: function (item) { return item; }, compareMinX: function (a, b) { return a[0] - b[0]; }, compareMinY: function (a, b) { return a[1] - b[1]; }, toJSON: function () { return this.data; }, fromJSON: function (data) { this.data = data; return this; }, _all: function (node, result) { var nodesToSearch = []; while (node) { if (node.leaf) { result.push.apply(result, node.children); } else { nodesToSearch.push.apply(nodesToSearch, node.children); } node = nodesToSearch.pop(); } return result; }, _build: function (items, level, height) { var N = items.length, M = this._maxEntries, node; if (N <= M) { node = { children: items, leaf: true, height: 1 }; this._calcBBox(node); return node; } if (!level) { // target height of the bulk-loaded tree height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization M = Math.ceil(N / Math.pow(M, height - 1)); items.sort(this.compareMinX); } // TODO eliminate recursion? node = { children: [], height: height }; var N1 = Math.ceil(N / M) * Math.ceil(Math.sqrt(M)), N2 = Math.ceil(N / M), compare = level % 2 === 1 ? this.compareMinX : this.compareMinY, i, j, slice, sliceLen, childNode; // split the items into M mostly square tiles for (i = 0; i < N; i += N1) { slice = items.slice(i, i + N1).sort(compare); for (j = 0, sliceLen = slice.length; j < sliceLen; j += N2) { // pack each entry recursively childNode = this._build(slice.slice(j, j + N2), level + 1, height - 1); node.children.push(childNode); } } this._calcBBox(node); return node; }, _chooseSubtree: function (bbox, node, level, path) { var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; while (true) { path.push(node); if (node.leaf || path.length - 1 === level) { break; } minArea = minEnlargement = Infinity; for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; area = this._area(child.bbox); enlargement = this._enlargedArea(bbox, child.bbox) - area; // choose entry with the least area enlargement if (enlargement < minEnlargement) { minEnlargement = enlargement; minArea = area < minArea ? area : minArea; targetNode = child; } else if (enlargement === minEnlargement) { // otherwise choose one with the smallest area if (area < minArea) { minArea = area; targetNode = child; } } } node = targetNode; } return node; }, _insert: function (item, level, isNode) { var bbox = isNode ? item.bbox : this.toBBox(item), insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node node.children.push(item); this._extend(node.bbox, bbox); // split on node overflow; propagate upwards if necessary while (level >= 0) { if (insertPath[level].children.length > this._maxEntries) { this._split(insertPath, level); level--; } else { break; } } // adjust bboxes along the insertion path this._adjustParentBBoxes(bbox, insertPath, level); }, // split overflowed node into two _split: function (insertPath, level) { var node = insertPath[level], M = node.children.length, m = this._minEntries; this._chooseSplitAxis(node, m, M); var newNode = { children: node.children.splice(this._chooseSplitIndex(node, m, M)), height: node.height }; if (node.leaf) { newNode.leaf = true; } this._calcBBox(node); this._calcBBox(newNode); if (level) { insertPath[level - 1].children.push(newNode); } else { this._splitRoot(node, newNode); } }, _splitRoot: function (node, newNode) { // split root node this.data = {}; this.data.children = [node, newNode]; this.data.height = node.height + 1; this._calcBBox(this.data); }, _chooseSplitIndex: function (node, m, M) { var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; minOverlap = minArea = Infinity; for (i = m; i <= M - m; i++) { bbox1 = this._distBBox(node, 0, i); bbox2 = this._distBBox(node, i, M); overlap = this._intersectionArea(bbox1, bbox2); area = this._area(bbox1) + this._area(bbox2); // choose distribution with minimum overlap if (overlap < minOverlap) { minOverlap = overlap; index = i; minArea = area < minArea ? area : minArea; } else if (overlap === minOverlap) { // otherwise choose distribution with minimum area if (area < minArea) { minArea = area; index = i; } } } return index; }, // sorts node children by the best axis for split _chooseSplitAxis: function (node, m, M) { var compareMinX = node.leaf ? this.compareMinX : this._compareNodeMinX, compareMinY = node.leaf ? this.compareMinY : this._compareNodeMinY, xMargin = this._allDistMargin(node, m, M, compareMinX), yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX, // otherwise it's already sorted by minY if (xMargin < yMargin) { node.children.sort(compareMinX); } }, // total margin of all possible split distributions where each node is at least m full _allDistMargin: function (node, m, M, compare) { node.children.sort(compare); var leftBBox = this._distBBox(node, 0, m), rightBBox = this._distBBox(node, M - m, M), margin = this._margin(leftBBox) + this._margin(rightBBox), i, child; for (i = m; i < M - m; i++) { child = node.children[i]; this._extend(leftBBox, node.leaf ? this.toBBox(child) : child.bbox); margin += this._margin(leftBBox); } for (i = M - m - 1; i >= m; i--) { child = node.children[i]; this._extend(rightBBox, node.leaf ? this.toBBox(child) : child.bbox); margin += this._margin(rightBBox); } return margin; }, // min bounding rectangle of node children from k to p-1 _distBBox: function (node, k, p) { var bbox = this._empty(); for (var i = k, child; i < p; i++) { child = node.children[i]; this._extend(bbox, node.leaf ? this.toBBox(child) : child.bbox); } return bbox; }, // calculate node's bbox from bboxes of its children _calcBBox: function (node) { node.bbox = this._distBBox(node, 0, node.children.length); }, _adjustParentBBoxes: function (bbox, path, level) { // adjust bboxes along the given tree path for (var i = level; i >= 0; i--) { this._extend(path[i].bbox, bbox); } }, _condense: function (path) { // go through the path, removing empty nodes and updating bboxes for (var i = path.length - 1, parent; i >= 0; i--) { if (path[i].children.length === 0) { if (i > 0) { parent = path[i - 1].children; parent.splice(parent.indexOf(path[i]), 1); } else { this.clear(); } } else { this._calcBBox(path[i]); } } }, _contains: function(a, b) { return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3]; }, _intersects: function (a, b) { return b[0] <= a[2] && b[1] <= a[3] && b[2] >= a[0] && b[3] >= a[1]; }, _extend: function (a, b) { a[0] = Math.min(a[0], b[0]); a[1] = Math.min(a[1], b[1]); a[2] = Math.max(a[2], b[2]); a[3] = Math.max(a[3], b[3]); return a; }, _area: function (a) { return (a[2] - a[0]) * (a[3] - a[1]); }, _margin: function (a) { return (a[2] - a[0]) + (a[3] - a[1]); }, _enlargedArea: function (a, b) { return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) * (Math.max(b[3], a[3]) - Math.min(b[1], a[1])); }, _intersectionArea: function (a, b) { var minX = Math.max(a[0], b[0]), minY = Math.max(a[1], b[1]), maxX = Math.min(a[2], b[2]), maxY = Math.min(a[3], b[3]); return Math.max(0, maxX - minX) * Math.max(0, maxY - minY); }, _empty: function () { return [Infinity, Infinity, -Infinity, -Infinity]; }, _compareNodeMinX: function (a, b) { return a.bbox[0] - b.bbox[0]; }, _compareNodeMinY: function (a, b) { return a.bbox[1] - b.bbox[1]; }, _initFormat: function (format) { // data format (minX, minY, maxX, maxY accessors) // uses eval-type function compilation instead of just accepting a toBBox function // because the algorithms are very sensitive to sorting functions performance, // so they should be dead simple and without inner calls // jshint evil: true var compareArr = ['return a', ' - b', ';']; this.compareMinX = new Function('a', 'b', compareArr.join(format[0])); this.compareMinY = new Function('a', 'b', compareArr.join(format[1])); this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];'); } }; if (typeof define === 'function' && define.amd) { define(function() { return rbush; }); } else if (typeof module !== 'undefined') { module.exports = rbush; } else if (typeof self !== 'undefined') { self.rbush = rbush; } else { window.rbush = rbush; } })(); },{}],101:[function(require,module,exports){ /* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Ported from Webkit * http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h */ module.exports = UnitBezier; function UnitBezier(p1x, p1y, p2x, p2y) { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). this.cx = 3.0 * p1x; this.bx = 3.0 * (p2x - p1x) - this.cx; this.ax = 1.0 - this.cx - this.bx; this.cy = 3.0 * p1y; this.by = 3.0 * (p2y - p1y) - this.cy; this.ay = 1.0 - this.cy - this.by; this.p1x = p1x; this.p1y = p2y; this.p2x = p2x; this.p2y = p2y; } UnitBezier.prototype.sampleCurveX = function(t) { // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. return ((this.ax * t + this.bx) * t + this.cx) * t; }; UnitBezier.prototype.sampleCurveY = function(t) { return ((this.ay * t + this.by) * t + this.cy) * t; }; UnitBezier.prototype.sampleCurveDerivativeX = function(t) { return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx; }; UnitBezier.prototype.solveCurveX = function(x, epsilon) { if (typeof epsilon === 'undefined') epsilon = 1e-6; var t0, t1, t2, x2, i; // First try a few iterations of Newton's method -- normally very fast. for (t2 = x, i = 0; i < 8; i++) { x2 = this.sampleCurveX(t2) - x; if (Math.abs(x2) < epsilon) return t2; var d2 = this.sampleCurveDerivativeX(t2); if (Math.abs(d2) < 1e-6) break; t2 = t2 - x2 / d2; } // Fall back to the bisection method for reliability. t0 = 0.0; t1 = 1.0; t2 = x; if (t2 < t0) return t0; if (t2 > t1) return t1; while (t0 < t1) { x2 = this.sampleCurveX(t2); if (Math.abs(x2 - x) < epsilon) return t2; if (x > x2) { t0 = t2; } else { t1 = t2; } t2 = (t1 - t0) * 0.5 + t0; } // Failure. return t2; }; UnitBezier.prototype.solve = function(x, epsilon) { return this.sampleCurveY(this.solveCurveX(x, epsilon)); }; },{}],102:[function(require,module,exports){ module.exports.VectorTile = require('./lib/vectortile.js'); module.exports.VectorTileFeature = require('./lib/vectortilefeature.js'); module.exports.VectorTileLayer = require('./lib/vectortilelayer.js'); },{"./lib/vectortile.js":103,"./lib/vectortilefeature.js":104,"./lib/vectortilelayer.js":105}],103:[function(require,module,exports){ 'use strict'; var VectorTileLayer = require('./vectortilelayer'); module.exports = VectorTile; function VectorTile(buffer, end) { this.layers = {}; this._buffer = buffer; end = end || buffer.length; while (buffer.pos < end) { var val = buffer.readVarint(), tag = val >> 3; if (tag == 3) { var layer = this.readLayer(); if (layer.length) this.layers[layer.name] = layer; } else { buffer.skip(val); } } } VectorTile.prototype.readLayer = function() { var buffer = this._buffer, bytes = buffer.readVarint(), end = buffer.pos + bytes, layer = new VectorTileLayer(buffer, end); buffer.pos = end; return layer; }; },{"./vectortilelayer":105}],104:[function(require,module,exports){ 'use strict'; var Point = require('point-geometry'); module.exports = VectorTileFeature; function VectorTileFeature(buffer, end, extent, keys, values) { this.properties = {}; // Public this.extent = extent; this.type = 0; // Private this._buffer = buffer; this._geometry = -1; end = end || buffer.length; while (buffer.pos < end) { var val = buffer.readVarint(), tag = val >> 3; if (tag == 1) { this._id = buffer.readVarint(); } else if (tag == 2) { var tagEnd = buffer.pos + buffer.readVarint(); while (buffer.pos < tagEnd) { var key = keys[buffer.readVarint()]; var value = values[buffer.readVarint()]; this.properties[key] = value; } } else if (tag == 3) { this.type = buffer.readVarint(); } else if (tag == 4) { this._geometry = buffer.pos; buffer.skip(val); } else { buffer.skip(val); } } } VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon']; VectorTileFeature.prototype.loadGeometry = function() { var buffer = this._buffer; buffer.pos = this._geometry; var bytes = buffer.readVarint(), end = buffer.pos + bytes, cmd = 1, length = 0, x = 0, y = 0, lines = [], line; while (buffer.pos < end) { if (!length) { var cmd_length = buffer.readVarint(); cmd = cmd_length & 0x7; length = cmd_length >> 3; } length--; if (cmd === 1 || cmd === 2) { x += buffer.readSVarint(); y += buffer.readSVarint(); if (cmd === 1) { // moveTo if (line) { lines.push(line); } line = []; } line.push(new Point(x, y)); } else if (cmd === 7) { // closePolygon line.push(line[0].clone()); } else { throw new Error('unknown command ' + cmd); } } if (line) lines.push(line); return lines; }; VectorTileFeature.prototype.bbox = function() { var buffer = this._buffer; buffer.pos = this._geometry; var bytes = buffer.readVarint(), end = buffer.pos + bytes, cmd = 1, length = 0, x = 0, y = 0, x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity; while (buffer.pos < end) { if (!length) { var cmd_length = buffer.readVarint(); cmd = cmd_length & 0x7; length = cmd_length >> 3; } length--; if (cmd === 1 || cmd === 2) { x += buffer.readSVarint(); y += buffer.readSVarint(); if (x < x1) x1 = x; if (x > x2) x2 = x; if (y < y1) y1 = y; if (y > y2) y2 = y; } else if (cmd !== 7) { throw new Error('unknown command ' + cmd); } } return [x1, y1, x2, y2]; }; },{"point-geometry":98}],105:[function(require,module,exports){ 'use strict'; var VectorTileFeature = require('./vectortilefeature.js'); module.exports = VectorTileLayer; function VectorTileLayer(buffer, end) { // Public this.version = 1; this.name = null; this.extent = 4096; this.length = 0; // Private this._buffer = buffer; this._keys = []; this._values = []; this._features = []; var val, tag; end = end || buffer.length; while (buffer.pos < end) { val = buffer.readVarint(); tag = val >> 3; if (tag === 15) { this.version = buffer.readVarint(); } else if (tag === 1) { this.name = buffer.readString(); } else if (tag === 5) { this.extent = buffer.readVarint(); } else if (tag === 2) { this.length++; this._features.push(buffer.pos); buffer.skip(val); } else if (tag === 3) { this._keys.push(buffer.readString()); } else if (tag === 4) { this._values.push(this.readFeatureValue()); } else { buffer.skip(val); } } } VectorTileLayer.prototype.readFeatureValue = function() { var buffer = this._buffer, value = null, bytes = buffer.readVarint(), end = buffer.pos + bytes, val, tag; while (buffer.pos < end) { val = buffer.readVarint(); tag = val >> 3; if (tag == 1) { value = buffer.readString(); } else if (tag == 2) { throw new Error('read float'); } else if (tag == 3) { value = buffer.readDouble(); } else if (tag == 4) { value = buffer.readVarint(); } else if (tag == 5) { throw new Error('read uint'); } else if (tag == 6) { value = buffer.readSVarint(); } else if (tag == 7) { value = Boolean(buffer.readVarint()); } else { buffer.skip(val); } } return value; }; // return feature `i` from this layer as a `VectorTileFeature` VectorTileLayer.prototype.feature = function(i) { if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds'); this._buffer.pos = this._features[i]; var end = this._buffer.readVarint() + this._buffer.pos; return new VectorTileFeature(this._buffer, end, this.extent, this._keys, this._values); }; },{"./vectortilefeature.js":104}]},{},[22]) //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvZGF0YS9idWZmZXIvYnVmZmVyLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9kYXRhL2J1ZmZlci9idWZmZXJzZXQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvYnVmZmVyL2ZpbGxlbGVtZW50c2J1ZmZlci5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvZGF0YS9idWZmZXIvZmlsbHZlcnRleGJ1ZmZlci5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvZGF0YS9idWZmZXIvZ2x5cGh2ZXJ0ZXhidWZmZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvYnVmZmVyL2ljb252ZXJ0ZXhidWZmZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvYnVmZmVyL2xpbmVlbGVtZW50YnVmZmVyLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9kYXRhL2J1ZmZlci9saW5ldmVydGV4YnVmZmVyLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9kYXRhL2J1ZmZlci9vdXRsaW5lZWxlbWVudHNidWZmZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvY3JlYXRlYnVja2V0LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9kYXRhL2VsZW1lbnRncm91cHMuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvZmVhdHVyZXRyZWUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2RhdGEvZmlsbGJ1Y2tldC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvZGF0YS9saW5lYnVja2V0LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9kYXRhL3Jhc3RlcmJ1Y2tldC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvZGF0YS9zeW1ib2xidWNrZXQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2dlby9sYXRsbmcuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2dlby9sYXRsbmdib3VuZHMuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2dlby90cmFuc2Zvcm0uanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2xpYi9kZWJ1Z3RleHQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL2xpYi9nbG1hdHJpeC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvbWFwYm94LWdsLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9yZW5kZXIvZHJhd2JhY2tncm91bmQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3JlbmRlci9kcmF3Y29tcG9zaXRlZC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL2RyYXdkZWJ1Zy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL2RyYXdmaWxsLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9yZW5kZXIvZHJhd2xpbmUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3JlbmRlci9kcmF3cmFzdGVyLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9yZW5kZXIvZHJhd3N5bWJvbC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL2RyYXd2ZXJ0aWNlcy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL2ZyYW1laGlzdG9yeS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL2dsdXRpbC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL3BhaW50ZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3JlbmRlci9wcmVyZW5kZXJlZC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvcmVuZGVyL3NoYWRlcnMuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS9nZW9qc29uc291cmNlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zb3VyY2UvZ2VvanNvbnRpbGUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS9nZW9qc29ud3JhcHBlci5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvc291cmNlL3Jhc3RlcnRpbGUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS9zb3VyY2UuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS90aWxlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zb3VyY2UvdGlsZWNvb3JkLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zb3VyY2UvdGlsZWdlb2pzb24uanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS92ZWN0b3J0aWxlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zb3VyY2UvdmlkZW9zb3VyY2UuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS93b3JrZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3NvdXJjZS93b3JrZXJ0aWxlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zdHlsZS9hbmltYXRpb25sb29wLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zdHlsZS9idWNrZXRmaWx0ZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N0eWxlL2NhbGN1bGF0ZWRzdHlsZS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvc3R5bGUvaW1hZ2VzcHJpdGUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N0eWxlL3JlbmRlcnByb3BlcnRpZXMuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N0eWxlL3N0eWxlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zdHlsZS9zdHlsZWNvbnN0YW50LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zdHlsZS9zdHlsZWRlY2xhcmF0aW9uLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zdHlsZS9zdHlsZXRyYW5zaXRpb24uanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N5bWJvbC9hbmNob3IuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N5bWJvbC9iaW5wYWNrLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zeW1ib2wvY29sbGlzaW9uLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zeW1ib2wvZ2x5cGhhdGxhcy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvc3ltYm9sL2dseXBoc291cmNlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy9zeW1ib2wvaW50ZXJwb2xhdGUuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N5bWJvbC9wbGFjZW1lbnQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N5bWJvbC9yZXNvbHZldGV4dC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvc3ltYm9sL3JvdGF0aW9ucmFuZ2UuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3N5bWJvbC9zaGFwaW5nLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91aS9jb250cm9sL2NvbnRyb2wuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3VpL2NvbnRyb2wvbmF2aWdhdGlvbi5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdWkvZWFzaW5ncy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdWkvaGFuZGxlcnMuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3VpL2hhc2guanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3VpL2ludGVyYWN0aW9uLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91aS9tYXAuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3V0aWwvYWN0b3IuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3V0aWwvYnJvd3Nlci9hamF4LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91dGlsL2Jyb3dzZXIvYnJvd3Nlci5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC9icm93c2VyL2NhbnZhcy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC9icm93c2VyL2Rpc3BhdGNoZXIuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3V0aWwvY29uZmlnLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91dGlsL2RvbS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC9ldmVudGVkLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9qcy91dGlsL2dseXBocy5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC9tcnVjYWNoZS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC90b2tlbi5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvanMvdXRpbC91cmwuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL2pzL3V0aWwvdXRpbC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy9jc3Njb2xvcnBhcnNlci9jc3Njb2xvcnBhcnNlci5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL2dlb2pzb24tcmV3aW5kL2luZGV4LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9ub2RlX21vZHVsZXMvZ2VvanNvbi1yZXdpbmQvbm9kZV9tb2R1bGVzL2dlb2pzb24tYXJlYS9pbmRleC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL2dlb2pzb24tcmV3aW5kL25vZGVfbW9kdWxlcy9nZW9qc29uLWFyZWEvbm9kZV9tb2R1bGVzL3dnczg0L2luZGV4LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9ub2RlX21vZHVsZXMvbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL3Y0Lmpzb24iLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy9wYmYvaW5kZXguanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy9wb2ludC1nZW9tZXRyeS9pbmRleC5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL3F1ZXVlLWFzeW5jL3F1ZXVlLmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9ub2RlX21vZHVsZXMvcmJ1c2gvcmJ1c2guanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy91bml0YmV6aWVyL2luZGV4LmpzIiwiL1VzZXJzL25kb2lyb240MDQvRG9jdW1lbnRzL21hcGJveC1nbC1qcy9ub2RlX21vZHVsZXMvdmVjdG9yLXRpbGUvaW5kZXguanMiLCIvVXNlcnMvbmRvaXJvbjQwNC9Eb2N1bWVudHMvbWFwYm94LWdsLWpzL25vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL3ZlY3Rvci10aWxlL2xpYi92ZWN0b3J0aWxlZmVhdHVyZS5qcyIsIi9Vc2Vycy9uZG9pcm9uNDA0L0RvY3VtZW50cy9tYXBib3gtZ2wtanMvbm9kZV9tb2R1bGVzL3ZlY3Rvci10aWxlL2xpYi92ZWN0b3J0aWxlbGF5ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOVBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDak9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9RQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9UQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaGNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2xTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBhIHNpbXBsZSB3cmFwcGVyIGFyb3VuZCBhIHNpbmdsZSBhcnJheWJ1ZmZlclxuXG5tb2R1bGUuZXhwb3J0cyA9IEJ1ZmZlcjtcblxuZnVuY3Rpb24gQnVmZmVyKGJ1ZmZlcikge1xuICAgIGlmICghYnVmZmVyKSB7XG4gICAgICAgIHRoaXMuYXJyYXkgPSBuZXcgQXJyYXlCdWZmZXIodGhpcy5kZWZhdWx0TGVuZ3RoKTtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLmRlZmF1bHRMZW5ndGg7XG4gICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gd2Ugb25seSByZWNyZWF0ZSBidWZmZXJzIGFmdGVyIHJlY2VpdmluZyB0aGVtIGZyb20gd29ya2VycyBmb3IgYmluZGluZyB0byBnbCxcbiAgICAgICAgLy8gc28gd2Ugb25seSBuZWVkIHRoZXNlIDIgcHJvcGVydGllc1xuICAgICAgICB0aGlzLmFycmF5ID0gYnVmZmVyLmFycmF5O1xuICAgICAgICB0aGlzLnBvcyA9IGJ1ZmZlci5wb3M7XG4gICAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlID0ge1xuICAgIHBvczogMCxcbiAgICBpdGVtU2l6ZTogNCwgLy8gYnl0ZXMgaW4gb25lIGl0ZW1cbiAgICBkZWZhdWx0TGVuZ3RoOiA4MTkyLCAvLyBpbml0aWFsIGJ1ZmZlciBzaXplXG4gICAgYXJyYXlUeXBlOiAnQVJSQVlfQlVGRkVSJywgLy8gZ2wgYnVmZmVyIHR5cGVcblxuICAgIGdldCBpbmRleCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucG9zIC8gdGhpcy5pdGVtU2l6ZTtcbiAgICB9LFxuXG4gICAgc2V0dXBWaWV3czogZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIHNldCB1cCB2aWV3cyBmb3IgZWFjaCB0eXBlIHRvIGFkZCBkYXRhIG9mIGRpZmZlcmVudCB0eXBlcyB0byB0aGUgc2FtZSBidWZmZXJcbiAgICAgICAgdGhpcy51Ynl0ZXMgPSBuZXcgVWludDhBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy5ieXRlcyA9IG5ldyBJbnQ4QXJyYXkodGhpcy5hcnJheSk7XG4gICAgICAgIHRoaXMudXNob3J0cyA9IG5ldyBVaW50MTZBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy5zaG9ydHMgPSBuZXcgSW50MTZBcnJheSh0aGlzLmFycmF5KTtcbiAgICB9LFxuXG4gICAgLy8gYmluZHMgdGhlIGJ1ZmZlciB0byBhIHdlYmdsIGNvbnRleHRcbiAgICBiaW5kOiBmdW5jdGlvbihnbCkge1xuICAgICAgICB2YXIgdHlwZSA9IGdsW3RoaXMuYXJyYXlUeXBlXTtcbiAgICAgICAgaWYgKCF0aGlzLmJ1ZmZlcikge1xuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICAgICAgICAgIGdsLmJpbmRCdWZmZXIodHlwZSwgdGhpcy5idWZmZXIpO1xuICAgICAgICAgICAgZ2wuYnVmZmVyRGF0YSh0eXBlLCBuZXcgRGF0YVZpZXcodGhpcy5hcnJheSwgMCwgdGhpcy5wb3MpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgICAgIC8vIGR1bXAgYXJyYXkgYnVmZmVyIG9uY2UgaXQncyBib3VuZCB0byBnbFxuICAgICAgICAgICAgdGhpcy5hcnJheSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC5iaW5kQnVmZmVyKHR5cGUsIHRoaXMuYnVmZmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBkZXN0cm95OiBmdW5jdGlvbihnbCkge1xuICAgICAgICBpZiAodGhpcy5idWZmZXIpIHtcbiAgICAgICAgICAgIGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gaW5jcmVhc2UgdGhlIGJ1ZmZlciBzaXplIGJ5IDUwJSBpZiBhIG5ldyBpdGVtIGRvZXNuJ3QgZml0XG4gICAgcmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoIDwgdGhpcy5wb3MgKyB0aGlzLml0ZW1TaXplKSB7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmxlbmd0aCA8IHRoaXMucG9zICsgdGhpcy5pdGVtU2l6ZSkge1xuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBsZW5ndGggYnkgNTAlIGJ1dCBrZWVwIGl0IGV2ZW5cbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IE1hdGgucm91bmQodGhpcy5sZW5ndGggKiAxLjUgLyAyKSAqIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGFycmF5IGJ1ZmZlcnMgY2FuJ3QgYmUgcmVzaXplZCwgc28gd2UgY3JlYXRlIGEgbmV3IG9uZSBhbmQgcmVzZXQgYWxsIGJ5dGVzIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5QnVmZmVyKHRoaXMubGVuZ3RoKTtcblxuICAgICAgICAgICAgdmFyIHVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICAgICAgdWJ5dGVzLnNldCh0aGlzLnVieXRlcyk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExpbmVWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2xpbmV2ZXJ0ZXhidWZmZXIuanMnKTtcbnZhciBMaW5lRWxlbWVudEJ1ZmZlciA9IHJlcXVpcmUoJy4vbGluZWVsZW1lbnRidWZmZXIuanMnKTtcbnZhciBGaWxsVmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9maWxsdmVydGV4YnVmZmVyLmpzJyk7XG52YXIgRmlsbEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL2ZpbGxlbGVtZW50c2J1ZmZlci5qcycpO1xudmFyIE91dGxpbmVFbGVtZW50QnVmZmVyID0gcmVxdWlyZSgnLi9vdXRsaW5lZWxlbWVudHNidWZmZXIuanMnKTtcbnZhciBHbHlwaFZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vZ2x5cGh2ZXJ0ZXhidWZmZXIuanMnKTtcbnZhciBJY29uVmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9pY29udmVydGV4YnVmZmVyLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYnVmZmVyc2V0KSB7XG4gICAgYnVmZmVyc2V0ID0gYnVmZmVyc2V0IHx8IHt9O1xuICAgIHJldHVybiB7XG4gICAgICAgIGdseXBoVmVydGV4OiBuZXcgR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyc2V0LmdseXBoVmVydGV4KSxcbiAgICAgICAgaWNvblZlcnRleDogbmV3IEljb25WZXJ0ZXhCdWZmZXIoYnVmZmVyc2V0Lmljb25WZXJ0ZXgpLFxuICAgICAgICBmaWxsVmVydGV4OiBuZXcgRmlsbFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZmlsbFZlcnRleCksXG4gICAgICAgIGZpbGxFbGVtZW50OiBuZXcgRmlsbEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmZpbGxFbGVtZW50KSxcbiAgICAgICAgb3V0bGluZUVsZW1lbnQ6IG5ldyBPdXRsaW5lRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQub3V0bGluZUVsZW1lbnQpLFxuICAgICAgICBsaW5lVmVydGV4OiBuZXcgTGluZVZlcnRleEJ1ZmZlcihidWZmZXJzZXQubGluZVZlcnRleCksXG4gICAgICAgIGxpbmVFbGVtZW50OiBuZXcgTGluZUVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmxpbmVFbGVtZW50KVxuICAgIH07XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXIuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBGaWxsRWxlbWVudHNCdWZmZXI7XG5cbmZ1bmN0aW9uIEZpbGxFbGVtZW50c0J1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5GaWxsRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShCdWZmZXIucHJvdG90eXBlKTtcblxuRmlsbEVsZW1lbnRzQnVmZmVyLnByb3RvdHlwZS5pdGVtU2l6ZSA9IDY7IC8vIGJ5dGVzIHBlciB0cmlhbmdsZSAoMyAqIHVuc2lnbmVkIHNob3J0ID09IDYgYnl0ZXMpXG5GaWxsRWxlbWVudHNCdWZmZXIucHJvdG90eXBlLmFycmF5VHlwZSA9ICdFTEVNRU5UX0FSUkFZX0JVRkZFUic7XG5cbkZpbGxFbGVtZW50c0J1ZmZlci5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24oYSwgYiwgYykge1xuICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgdGhpcy5yZXNpemUoKTtcblxuICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuICAgIHRoaXMudXNob3J0c1twb3MyICsgMl0gPSBjO1xuXG4gICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlci5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZpbGxWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIEZpbGxWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuRmlsbFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEJ1ZmZlci5wcm90b3R5cGUpO1xuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZS5pdGVtU2l6ZSA9IDQ7IC8vIGJ5dGVzIHBlciB2ZXJ0ZXggKDIgKiBzaG9ydCA9PSA0IGJ5dGVzKVxuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgdGhpcy5zaG9ydHNbcG9zMiArIDBdID0geDtcbiAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSB5O1xuXG4gICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlci5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoVmVydGV4QnVmZmVyO1xuXG5mdW5jdGlvbiBHbHlwaFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEJ1ZmZlci5wcm90b3R5cGUpO1xuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUuZGVmYXVsdExlbmd0aCA9IDIwNDggKiAxNjtcbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZS5pdGVtU2l6ZSA9IDE2O1xuXG4vLyBDb252ZXJ0cyB0aGUgMC4uMnBpIHRvIGFuIGludDE2IHJhbmdlXG5HbHlwaFZlcnRleEJ1ZmZlci5hbmdsZUZhY3RvciA9IDEyOCAvIE1hdGguUEk7XG5cbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbih4LCB5LCBveCwgb3ksIHR4LCB0eSwgYW5nbGUsIG1pbnpvb20sIHJhbmdlLCBtYXh6b29tLCBsYWJlbG1pbnpvb20pIHtcbiAgICB2YXIgcG9zID0gdGhpcy5wb3MsXG4gICAgICAgIHBvczIgPSBwb3MgLyAyLFxuICAgICAgICBhbmdsZUZhY3RvciA9IEdseXBoVmVydGV4QnVmZmVyLmFuZ2xlRmFjdG9yO1xuXG4gICAgdGhpcy5yZXNpemUoKTtcblxuICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IHg7XG4gICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0geTtcbiAgICB0aGlzLnNob3J0c1twb3MyICsgMl0gPSBNYXRoLnJvdW5kKG94ICogNjQpOyAvLyB1c2UgMS82NCBwaXhlbHMgZm9yIHBsYWNlbWVudFxuICAgIHRoaXMuc2hvcnRzW3BvczIgKyAzXSA9IE1hdGgucm91bmQob3kgKiA2NCk7XG5cbiAgICB0aGlzLnVieXRlc1twb3MgKyA4XSA9IE1hdGguZmxvb3IoKGxhYmVsbWluem9vbSB8fCAwKSAqIDEwKTtcbiAgICB0aGlzLnVieXRlc1twb3MgKyA5XSA9IE1hdGguZmxvb3IoKG1pbnpvb20gfHwgMCkgKiAxMCk7IC8vIDEvMTAgem9vbSBsZXZlbHM6IHoxNiA9PSAxNjAuXG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgMTBdID0gTWF0aC5mbG9vcihNYXRoLm1pbihtYXh6b29tIHx8IDI1LCAyNSkgKiAxMCk7IC8vIDEvMTAgem9vbSBsZXZlbHM6IHoxNiA9PSAxNjAuXG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgMTFdID0gTWF0aC5yb3VuZChhbmdsZSAqIGFuZ2xlRmFjdG9yKSAlIDI1NjtcbiAgICB0aGlzLnVieXRlc1twb3MgKyAxMl0gPSBNYXRoLm1heChNYXRoLnJvdW5kKHJhbmdlWzBdICogYW5nbGVGYWN0b3IpLCAwKSAlIDI1NjtcbiAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gPSBNYXRoLm1pbihNYXRoLnJvdW5kKHJhbmdlWzFdICogYW5nbGVGYWN0b3IpLCAyNTUpICUgMjU2O1xuXG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgMTRdID0gTWF0aC5mbG9vcih0eCAvIDQpO1xuICAgIHRoaXMudWJ5dGVzW3BvcyArIDE1XSA9IE1hdGguZmxvb3IodHkgLyA0KTtcblxuICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXIuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuR2x5cGhWZXJ0ZXhCdWZmZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShCdWZmZXIucHJvdG90eXBlKTtcblxuR2x5cGhWZXJ0ZXhCdWZmZXIucHJvdG90eXBlLmRlZmF1bHRMZW5ndGggPSAyMDQ4ICogMjA7XG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUuaXRlbVNpemUgPSAyMDtcblxuLy8gQ29udmVydHMgdGhlIDAuLjJwaSB0byBhbiBpbnQxNiByYW5nZVxuR2x5cGhWZXJ0ZXhCdWZmZXIuYW5nbGVGYWN0b3IgPSAxMjggLyBNYXRoLlBJO1xuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24oeCwgeSwgb3gsIG95LCB0eCwgdHksIGFuZ2xlLCBtaW56b29tLCByYW5nZSwgbWF4em9vbSwgbGFiZWxtaW56b29tKSB7XG4gICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICBwb3MyID0gcG9zIC8gMixcbiAgICAgICAgYW5nbGVGYWN0b3IgPSBHbHlwaFZlcnRleEJ1ZmZlci5hbmdsZUZhY3RvcjtcblxuICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSB4O1xuICAgIHRoaXMuc2hvcnRzW3BvczIgKyAxXSA9IHk7XG4gICAgdGhpcy5zaG9ydHNbcG9zMiArIDJdID0gTWF0aC5yb3VuZChveCAqIDY0KTsgLy8gdXNlIDEvNjQgcGl4ZWxzIGZvciBwbGFjZW1lbnRcbiAgICB0aGlzLnNob3J0c1twb3MyICsgM10gPSBNYXRoLnJvdW5kKG95ICogNjQpO1xuXG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgOF0gPSBNYXRoLmZsb29yKChsYWJlbG1pbnpvb20gfHwgMCkgKiAxMCk7XG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gPSBNYXRoLmZsb29yKChtaW56b29tIHx8IDApICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgIHRoaXMudWJ5dGVzW3BvcyArIDEwXSA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSB8fCAyNSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgIHRoaXMudWJ5dGVzW3BvcyArIDExXSA9IE1hdGgucm91bmQoYW5nbGUgKiBhbmdsZUZhY3RvcikgJSAyNTY7XG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgMTJdID0gTWF0aC5tYXgoTWF0aC5yb3VuZChyYW5nZVswXSAqIGFuZ2xlRmFjdG9yKSwgMCkgJSAyNTY7XG4gICAgdGhpcy51Ynl0ZXNbcG9zICsgMTNdID0gTWF0aC5taW4oTWF0aC5yb3VuZChyYW5nZVsxXSAqIGFuZ2xlRmFjdG9yKSwgMjU1KSAlIDI1NjtcblxuICAgIHRoaXMuc2hvcnRzW3BvczIgKyA4XSA9IHR4O1xuICAgIHRoaXMuc2hvcnRzW3BvczIgKyA5XSA9IHR5O1xuXG4gICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlci5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVFbGVtZW50QnVmZmVyO1xuXG5mdW5jdGlvbiBMaW5lRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEJ1ZmZlci5wcm90b3R5cGUpO1xuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUuaXRlbVNpemUgPSA2OyAvLyBieXRlcyBwZXIgdHJpYW5nbGUgKDMgKiB1bnNpZ25lZCBzaG9ydCA9PSA2IGJ5dGVzKVxuTGluZUVsZW1lbnRCdWZmZXIucHJvdG90eXBlLmFycmF5VHlwZSA9ICdFTEVNRU5UX0FSUkFZX0JVRkZFUic7XG5cbkxpbmVFbGVtZW50QnVmZmVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgdGhpcy51c2hvcnRzW3BvczIgKyAxXSA9IGI7XG4gICAgdGhpcy51c2hvcnRzW3BvczIgKyAyXSA9IGM7XG5cbiAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZVZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gTGluZVZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG4vLyBzY2FsZSB0aGUgZXh0cnVzaW9uIHZlY3RvciBzbyB0aGF0IHRoZSBub3JtYWwgbGVuZ3RoIGlzIHRoaXMgdmFsdWUuXG4vLyBjb250YWlucyB0aGUgXCJ0ZXh0dXJlXCIgbm9ybWFscyAoLTEuLjEpLiB0aGlzIGlzIGRpc3RpbmN0IGZyb20gdGhlIGV4dHJ1ZGVcbi8vIG5vcm1hbHMgZm9yIGxpbmUgam9pbnMsIGJlY2F1c2UgdGhlIHgtdmFsdWUgcmVtYWlucyAwIGZvciB0aGUgdGV4dHVyZVxuLy8gbm9ybWFsIGFycmF5LCB3aGlsZSB0aGUgZXh0cnVkZSBub3JtYWwgYWN0dWFsbHkgbW92ZXMgdGhlIHZlcnRleCB0byBjcmVhdGVcbi8vIHRoZSBhY3V0ZS9iZXZlbGxlZCBsaW5lIGpvaW4uXG5MaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZSA9IDYzO1xuXG5MaW5lVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQnVmZmVyLnByb3RvdHlwZSk7XG5cbkxpbmVWZXJ0ZXhCdWZmZXIucHJvdG90eXBlLml0ZW1TaXplID0gODsgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuTGluZVZlcnRleEJ1ZmZlci5wcm90b3R5cGUuZGVmYXVsdExlbmd0aCA9IDMyNzY4O1xuXG4vLyBhZGQgYSB2ZXJ0ZXggdG8gdGhpcyBidWZmZXI7XG4vLyB4LCB5IC0gdmVydGV4IHBvc2l0aW9uXG4vLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuLy8gdHgsIHR5IC0gdGV4dHVyZSBub3JtYWxcblxuTGluZVZlcnRleEJ1ZmZlci5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24ocG9pbnQsIGV4dHJ1ZGUsIHR4LCB0eSwgbGluZXNvZmFyKSB7XG4gICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICBwb3MyID0gcG9zIC8gMixcbiAgICAgICAgaW5kZXggPSB0aGlzLmluZGV4LFxuICAgICAgICBleHRydWRlU2NhbGUgPSBMaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZTtcblxuICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSAoTWF0aC5mbG9vcihwb2ludC54KSAqIDIpIHwgdHg7XG4gICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0gKE1hdGguZmxvb3IocG9pbnQueSkgKiAyKSB8IHR5O1xuICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQobGluZXNvZmFyIHx8IDApO1xuICAgIHRoaXMuYnl0ZXNbcG9zICsgNl0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueCk7XG4gICAgdGhpcy5ieXRlc1twb3MgKyA3XSA9IE1hdGgucm91bmQoZXh0cnVkZVNjYWxlICogZXh0cnVkZS55KTtcblxuICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgcmV0dXJuIGluZGV4O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gT3V0bGluZUVsZW1lbnRzQnVmZmVyO1xuXG5mdW5jdGlvbiBPdXRsaW5lRWxlbWVudHNCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuT3V0bGluZUVsZW1lbnRzQnVmZmVyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQnVmZmVyLnByb3RvdHlwZSk7XG5cbk91dGxpbmVFbGVtZW50c0J1ZmZlci5wcm90b3R5cGUuaXRlbVNpemUgPSA0OyAvLyBieXRlcyBwZXIgbGluZSAoMiAqIHVuc2lnbmVkIHNob3J0ID09IDQgYnl0ZXMpXG5PdXRsaW5lRWxlbWVudHNCdWZmZXIucHJvdG90eXBlLmFycmF5VHlwZSA9ICdFTEVNRU5UX0FSUkFZX0JVRkZFUic7XG5cbk91dGxpbmVFbGVtZW50c0J1ZmZlci5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgdGhpcy5yZXNpemUoKTtcblxuICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuXG4gICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQnVja2V0O1xuXG52YXIgTGluZUJ1Y2tldCA9IHJlcXVpcmUoJy4vbGluZWJ1Y2tldC5qcycpO1xudmFyIEZpbGxCdWNrZXQgPSByZXF1aXJlKCcuL2ZpbGxidWNrZXQuanMnKTtcbnZhciBTeW1ib2xCdWNrZXQgPSByZXF1aXJlKCcuL3N5bWJvbGJ1Y2tldC5qcycpO1xudmFyIFJhc3RlckJ1Y2tldCA9IHJlcXVpcmUoJy4vcmFzdGVyYnVja2V0LmpzJyk7XG52YXIgUmVuZGVyUHJvcGVydGllcyA9IHJlcXVpcmUoJy4uL3N0eWxlL3JlbmRlcnByb3BlcnRpZXMuanMnKTtcblxuZnVuY3Rpb24gY3JlYXRlQnVja2V0KGxheWVyLCBidWZmZXJzLCBjb2xsaXNpb24sIGluZGljZXMpIHtcblxuICAgIGlmICghUmVuZGVyUHJvcGVydGllc1tsYXllci50eXBlXSkge1xuICAgICAgICAvL2NvbnNvbGUud2FybigndW5rbm93biBidWNrZXQgdHlwZScpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGluZm8gPSBuZXcgUmVuZGVyUHJvcGVydGllc1tsYXllci50eXBlXShsYXllci5yZW5kZXIpO1xuXG4gICAgdmFyIEJ1Y2tldENsYXNzID1cbiAgICAgICAgbGF5ZXIudHlwZSA9PT0gJ2xpbmUnID8gTGluZUJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdmaWxsJyA/IEZpbGxCdWNrZXQgOlxuICAgICAgICBsYXllci50eXBlID09PSAnc3ltYm9sJyA/IFN5bWJvbEJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdyYXN0ZXInID8gUmFzdGVyQnVja2V0IDogbnVsbDtcblxuICAgIHZhciBidWNrZXQgPSBuZXcgQnVja2V0Q2xhc3MoaW5mbywgYnVmZmVycywgY29sbGlzaW9uLCBpbmRpY2VzKTtcbiAgICBidWNrZXQudHlwZSA9IGxheWVyLnR5cGU7XG4gICAgYnVja2V0LmludGVyYWN0aXZlID0gbGF5ZXIuaW50ZXJhY3RpdmU7XG4gICAgYnVja2V0Lm1pblpvb20gPSBsYXllclsnbWluLXpvb20nXTtcbiAgICBidWNrZXQubWF4Wm9vbSA9IGxheWVyWydtYXgtem9vbSddO1xuXG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBFbGVtZW50R3JvdXBzO1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXBzKHZlcnRleEJ1ZmZlciwgZWxlbWVudEJ1ZmZlciwgc2Vjb25kRWxlbWVudEJ1ZmZlcikge1xuXG4gICAgdGhpcy52ZXJ0ZXhCdWZmZXIgPSB2ZXJ0ZXhCdWZmZXI7XG4gICAgdGhpcy5lbGVtZW50QnVmZmVyID0gZWxlbWVudEJ1ZmZlcjtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRCdWZmZXIgPSBzZWNvbmRFbGVtZW50QnVmZmVyO1xuICAgIHRoaXMuZ3JvdXBzID0gW107XG59XG5cbkVsZW1lbnRHcm91cHMucHJvdG90eXBlLm1ha2VSb29tRm9yID0gZnVuY3Rpb24obnVtVmVydGljZXMpIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudCB8fCB0aGlzLmN1cnJlbnQudmVydGV4TGVuZ3RoICsgbnVtVmVydGljZXMgPiA2NTUzNSkge1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuZXcgRWxlbWVudEdyb3VwKHRoaXMudmVydGV4QnVmZmVyLmluZGV4LFxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudEJ1ZmZlciAmJiB0aGlzLmVsZW1lbnRCdWZmZXIuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRFbGVtZW50QnVmZmVyICYmIHRoaXMuc2Vjb25kRWxlbWVudEJ1ZmZlci5pbmRleCk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXAodmVydGV4U3RhcnRJbmRleCwgZWxlbWVudFN0YXJ0SW5kZXgsIHNlY29uZEVsZW1lbnRTdGFydEluZGV4KSAge1xuICAgIC8vIHRoZSBvZmZzZXQgaW50byB0aGUgdmVydGV4IGJ1ZmZlciBvZiB0aGUgZmlyc3QgdmVydGV4IGluIHRoaXMgZ3JvdXBcbiAgICB0aGlzLnZlcnRleFN0YXJ0SW5kZXggPSB2ZXJ0ZXhTdGFydEluZGV4O1xuICAgIHRoaXMuZWxlbWVudFN0YXJ0SW5kZXggPSBlbGVtZW50U3RhcnRJbmRleDtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ID0gc2Vjb25kRWxlbWVudFN0YXJ0SW5kZXg7XG4gICAgdGhpcy5lbGVtZW50TGVuZ3RoID0gMDtcbiAgICB0aGlzLnZlcnRleExlbmd0aCA9IDA7XG4gICAgdGhpcy5zZWNvbmRFbGVtZW50TGVuZ3RoID0gMDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJidXNoID0gcmVxdWlyZSgncmJ1c2gnKSxcbiAgICBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmVhdHVyZVRyZWU7XG5cbmZ1bmN0aW9uIEZlYXR1cmVUcmVlKGdldEdlb21ldHJ5LCBnZXRUeXBlKSB7XG5cbiAgICB0aGlzLmdldEdlb21ldHJ5ID0gZ2V0R2VvbWV0cnk7XG4gICAgdGhpcy5nZXRUeXBlID0gZ2V0VHlwZTtcblxuICAgIHRoaXMucnRyZWUgPSByYnVzaCg5KTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufVxuXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24oYmJveCwgYnVja2V0X25hbWUsIGZlYXR1cmUpIHtcbiAgICBiYm94LmJ1Y2tldCA9IGJ1Y2tldF9uYW1lO1xuICAgIGJib3guZmVhdHVyZSA9IGZlYXR1cmU7XG4gICAgdGhpcy50b0JlSW5zZXJ0ZWQucHVzaChiYm94KTtcbn07XG5cbi8vIGJ1bGsgaW5zZXJ0IGludG8gdHJlZVxuRmVhdHVyZVRyZWUucHJvdG90eXBlLl9sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5ydHJlZS5sb2FkKHRoaXMudG9CZUluc2VydGVkKTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufTtcblxuLy8gRmluZHMgZmVhdHVyZXMgaW4gdGhpcyB0aWxlIGF0IGEgcGFydGljdWxhciBwb3NpdGlvbi5cbkZlYXR1cmVUcmVlLnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uKGFyZ3MsIGNhbGxiYWNrKSB7XG5cbiAgICBpZiAodGhpcy50b0JlSW5zZXJ0ZWQubGVuZ3RoKSB0aGlzLl9sb2FkKCk7XG5cbiAgICB2YXIgcmFkaXVzID0gYXJncy5wYXJhbXMgJiYgYXJncy5wYXJhbXMucmFkaXVzIHx8IDA7XG4gICAgcmFkaXVzICo9IDQwOTYgLyBhcmdzLnNjYWxlO1xuXG4gICAgdmFyIHggPSBhcmdzLngsXG4gICAgICAgIHkgPSBhcmdzLnk7XG5cbiAgICB2YXIgbWF0Y2hpbmcgPSB0aGlzLnJ0cmVlLnNlYXJjaChbIHggLSByYWRpdXMsIHkgLSByYWRpdXMsIHggKyByYWRpdXMsIHkgKyByYWRpdXMgXSk7XG5cbiAgICBpZiAoYXJncy5wYXJhbXMuYnVja2V0cykge1xuICAgICAgICB0aGlzLnF1ZXJ5QnVja2V0cyhtYXRjaGluZywgeCwgeSwgcmFkaXVzLCBhcmdzLnBhcmFtcywgY2FsbGJhY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucXVlcnlGZWF0dXJlcyhtYXRjaGluZywgeCwgeSwgcmFkaXVzLCBhcmdzLnBhcmFtcywgY2FsbGJhY2spO1xuICAgIH1cbn07XG5cbkZlYXR1cmVUcmVlLnByb3RvdHlwZS5xdWVyeUZlYXR1cmVzID0gZnVuY3Rpb24obWF0Y2hpbmcsIHgsIHksIHJhZGl1cywgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hdGNoaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gbWF0Y2hpbmdbaV0uZmVhdHVyZTtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLmdldFR5cGUoZmVhdHVyZSk7XG4gICAgICAgIHZhciBnZW9tZXRyeSA9IHRoaXMuZ2V0R2VvbWV0cnkoZmVhdHVyZSk7XG5cblxuICAgICAgICBpZiAocGFyYW1zLmJ1Y2tldCAmJiBtYXRjaGluZ1tpXS5idWNrZXQgIT09IHBhcmFtcy5idWNrZXQpIGNvbnRpbnVlO1xuICAgICAgICBpZiAocGFyYW1zLnR5cGUgJiYgdHlwZSAhPT0gcGFyYW1zLnR5cGUpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChnZW9tZXRyeUNvbnRhaW5zUG9pbnQoZ2VvbWV0cnksIHR5cGUsIG5ldyBQb2ludCh4LCB5KSwgcmFkaXVzKSkge1xuICAgICAgICAgICAgdmFyIHByb3BzID0ge1xuICAgICAgICAgICAgICAgIF9idWNrZXQ6IG1hdGNoaW5nW2ldLmJ1Y2tldCxcbiAgICAgICAgICAgICAgICBfdHlwZTogdHlwZVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5nZW9tZXRyeSkge1xuICAgICAgICAgICAgICAgIHByb3BzLl9nZW9tZXRyeSA9IGdlb21ldHJ5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgIGlmIChmZWF0dXJlLmhhc093blByb3BlcnR5KGtleSkgJiYga2V5WzBdICE9PSAnXycpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHNba2V5XSA9IGZlYXR1cmVba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQucHVzaChwcm9wcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCByZXN1bHQpO1xufTtcblxuLy8gTGlzdHMgYWxsIGJ1Y2tldHMgdGhhdCBhdCB0aGUgcG9zaXRpb24uXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUucXVlcnlCdWNrZXRzID0gZnVuY3Rpb24obWF0Y2hpbmcsIHgsIHksIHJhZGl1cywgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgIHZhciBidWNrZXRzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXRjaGluZy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYnVja2V0cy5pbmRleE9mKG1hdGNoaW5nW2ldLmJ1Y2tldCkgPj0gMCkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGZlYXR1cmUgPSBtYXRjaGluZ1tpXS5mZWF0dXJlO1xuICAgICAgICB2YXIgdHlwZSA9IHRoaXMuZ2V0VHlwZShmZWF0dXJlKTtcbiAgICAgICAgdmFyIGdlb21ldHJ5ID0gdGhpcy5nZXRHZW9tZXRyeShmZWF0dXJlKTtcbiAgICAgICAgaWYgKGdlb21ldHJ5Q29udGFpbnNQb2ludChnZW9tZXRyeSwgdHlwZSwgbmV3IFBvaW50KHgsIHkpLCByYWRpdXMpKSB7XG4gICAgICAgICAgICBidWNrZXRzLnB1c2gobWF0Y2hpbmdbaV0uYnVja2V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNhbGxiYWNrKG51bGwsIGJ1Y2tldHMpO1xufTtcblxuXG5mdW5jdGlvbiBnZW9tZXRyeUNvbnRhaW5zUG9pbnQocmluZ3MsIHR5cGUsIHAsIHJhZGl1cykge1xuICAgIGlmICh0eXBlID09PSAnUG9pbnQnKSB7XG4gICAgICAgIHJldHVybiBwb2ludENvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cyk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGxpbmVDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIHJldHVybiBwb2x5Q29udGFpbnNQb2ludChyaW5ncywgcCkgPyB0cnVlIDogbGluZUNvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLy8gQ29kZSBmcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE1MDE3MjUvMzMxMzc5LlxuZnVuY3Rpb24gZGlzdFRvU2VnbWVudFNxdWFyZWQocCwgdiwgdykge1xuICAgIHZhciBsMiA9IHYuZGlzdFNxcih3KTtcbiAgICBpZiAobDIgPT09IDApIHJldHVybiBwLmRpc3RTcXIodik7XG4gICAgdmFyIHQgPSAoKHAueCAtIHYueCkgKiAody54IC0gdi54KSArIChwLnkgLSB2LnkpICogKHcueSAtIHYueSkpIC8gbDI7XG4gICAgaWYgKHQgPCAwKSByZXR1cm4gcC5kaXN0U3FyKHYpO1xuICAgIGlmICh0ID4gMSkgcmV0dXJuIHAuZGlzdFNxcih3KTtcbiAgICByZXR1cm4gcC5kaXN0U3FyKHcuc3ViKHYpLl9tdWx0KHQpLl9hZGQodikpO1xufVxuXG5mdW5jdGlvbiBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSB7XG4gICAgdmFyIHIgPSByYWRpdXMgKiByYWRpdXM7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByaW5nID0gcmluZ3NbaV07XG4gICAgICAgIGZvciAodmFyIGogPSAxOyBqIDwgcmluZy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgLy8gRmluZCBsaW5lIHNlZ21lbnRzIHRoYXQgaGF2ZSBhIGRpc3RhbmNlIDw9IHJhZGl1c14yIHRvIHBcbiAgICAgICAgICAgIC8vIEluIHRoYXQgY2FzZSwgd2UgdHJlYXQgdGhlIGxpbmUgYXMgXCJjb250YWluaW5nIHBvaW50IHBcIi5cbiAgICAgICAgICAgIHZhciB2ID0gcmluZ1tqLTFdLCB3ID0gcmluZ1tqXTtcbiAgICAgICAgICAgIGlmIChkaXN0VG9TZWdtZW50U3F1YXJlZChwLCB2LCB3KSA8IHIpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLy8gcG9pbnQgaW4gcG9seWdvbiByYXkgY2FzdGluZyBhbGdvcml0aG1cbmZ1bmN0aW9uIHBvbHlDb250YWluc1BvaW50KHJpbmdzLCBwKSB7XG4gICAgdmFyIGMgPSBmYWxzZSxcbiAgICAgICAgcmluZywgcDEsIHAyO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCByaW5ncy5sZW5ndGg7IGsrKykge1xuICAgICAgICByaW5nID0gcmluZ3Nba107XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gcmluZy5sZW5ndGggLSAxOyBpIDwgcmluZy5sZW5ndGg7IGogPSBpKyspIHtcbiAgICAgICAgICAgIHAxID0gcmluZ1tpXTtcbiAgICAgICAgICAgIHAyID0gcmluZ1tqXTtcbiAgICAgICAgICAgIGlmICgoKHAxLnkgPiBwLnkpICE9IChwMi55ID4gcC55KSkgJiYgKHAueCA8IChwMi54IC0gcDEueCkgKiAocC55IC0gcDEueSkgLyAocDIueSAtIHAxLnkpICsgcDEueCkpIHtcbiAgICAgICAgICAgICAgICBjID0gIWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGM7XG59XG5cbmZ1bmN0aW9uIHBvaW50Q29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSB7XG4gICAgdmFyIHIgPSByYWRpdXMgKiByYWRpdXM7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByaW5nID0gcmluZ3NbaV07XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcmluZy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYgKHJpbmdbal0uZGlzdFNxcihwKSA8PSByKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cblxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudGdyb3Vwcy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZpbGxCdWNrZXQ7XG5cbmZ1bmN0aW9uIEZpbGxCdWNrZXQoaW5mbywgYnVmZmVycywgcGxhY2VtZW50LCBlbGVtZW50R3JvdXBzKSB7XG4gICAgdGhpcy5pbmZvID0gaW5mbztcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMuZWxlbWVudEdyb3VwcyA9IGVsZW1lbnRHcm91cHMgfHwgbmV3IEVsZW1lbnRHcm91cHMoYnVmZmVycy5maWxsVmVydGV4LCBidWZmZXJzLmZpbGxFbGVtZW50LCBidWZmZXJzLm91dGxpbmVFbGVtZW50KTtcbn1cblxuRmlsbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1tpXTtcbiAgICAgICAgdGhpcy5hZGRGZWF0dXJlKGZlYXR1cmUubG9hZEdlb21ldHJ5KCkpO1xuICAgIH1cbn07XG5cbkZpbGxCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmUgPSBmdW5jdGlvbihsaW5lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5hZGRGaWxsKGxpbmVzW2ldKTtcbiAgICB9XG59O1xuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5hZGRGaWxsID0gZnVuY3Rpb24odmVydGljZXMpIHtcbiAgICBpZiAodmVydGljZXMubGVuZ3RoIDwgMykge1xuICAgICAgICAvL2NvbnNvbGUud2FybignYSBmaWxsIG11c3QgaGF2ZSBhdCBsZWFzdCB0aHJlZSB2ZXJ0aWNlcycpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdmVydGljZXMgd2UncmUgZ29pbmcgdG8gcHJvZHVjZSBzbyB0aGF0IHdlXG4gICAgLy8gY2FuIHJlc2l6ZSB0aGUgYnVmZmVyIGJlZm9yZWhhbmQsIG9yIGRldGVjdCB3aGV0aGVyIHRoZSBjdXJyZW50IGxpbmVcbiAgICAvLyB3b24ndCBmaXQgaW50byB0aGUgYnVmZmVyIGFueW1vcmUuXG4gICAgLy8gSW4gb3JkZXIgdG8gYmUgYWJsZSB0byB1c2UgdGhlIHZlcnRleCBidWZmZXIgZm9yIGRyYXdpbmcgdGhlIGFudGlhbGlhc2VkXG4gICAgLy8gb3V0bGluZXMsIHdlIHNlcGFyYXRlIGFsbCBwb2x5Z29uIHZlcnRpY2VzIHdpdGggYSBkZWdlbmVyYXRlIChvdXQtb2YtXG4gICAgLy8gdmlld3BsYW5lKSB2ZXJ0ZXguXG5cbiAgICB2YXIgbGVuID0gdmVydGljZXMubGVuZ3RoO1xuXG4gICAgLy8gQ2hlY2sgd2hldGhlciB0aGlzIGdlb21ldHJ5IGJ1ZmZlciBjYW4gaG9sZCBhbGwgdGhlIHJlcXVpcmVkIHZlcnRpY2VzLlxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKyAxKTtcbiAgICB2YXIgZWxlbWVudEdyb3VwID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQ7XG5cbiAgICB2YXIgZmlsbFZlcnRleCA9IHRoaXMuYnVmZmVycy5maWxsVmVydGV4O1xuICAgIHZhciBmaWxsRWxlbWVudCA9IHRoaXMuYnVmZmVycy5maWxsRWxlbWVudDtcbiAgICB2YXIgb3V0bGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMub3V0bGluZUVsZW1lbnQ7XG5cbiAgICAvLyBTdGFydCBhbGwgbGluZXMgd2l0aCBhIGRlZ2VuZXJhdGUgdmVydGV4XG4gICAgZWxlbWVudEdyb3VwLnZlcnRleExlbmd0aCsrO1xuXG4gICAgLy8gV2UncmUgZ2VuZXJhdGluZyB0cmlhbmdsZSBmYW5zLCBzbyB3ZSBhbHdheXMgc3RhcnQgd2l0aCB0aGUgZmlyc3QgY29vcmRpbmF0ZSBpbiB0aGlzIHBvbHlnb24uXG4gICAgdmFyIGZpcnN0SW5kZXggPSBmaWxsVmVydGV4LmluZGV4IC0gZWxlbWVudEdyb3VwLnZlcnRleFN0YXJ0SW5kZXgsXG4gICAgICAgIHByZXZJbmRleCwgY3VycmVudEluZGV4LCBjdXJyZW50VmVydGV4O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2ZXJ0aWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjdXJyZW50SW5kZXggPSBmaWxsVmVydGV4LmluZGV4IC0gZWxlbWVudEdyb3VwLnZlcnRleFN0YXJ0SW5kZXg7XG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tpXTtcblxuICAgICAgICBmaWxsVmVydGV4LmFkZChjdXJyZW50VmVydGV4LngsIGN1cnJlbnRWZXJ0ZXgueSk7XG4gICAgICAgIGVsZW1lbnRHcm91cC52ZXJ0ZXhMZW5ndGgrKztcblxuICAgICAgICAvLyBPbmx5IGFkZCB0cmlhbmdsZXMgdGhhdCBoYXZlIGRpc3RpbmN0IHZlcnRpY2VzLlxuICAgICAgICBpZiAoaSA+PSAyICYmIChjdXJyZW50VmVydGV4LnggIT09IHZlcnRpY2VzWzBdLnggfHwgY3VycmVudFZlcnRleC55ICE9PSB2ZXJ0aWNlc1swXS55KSkge1xuICAgICAgICAgICAgZmlsbEVsZW1lbnQuYWRkKGZpcnN0SW5kZXgsIHByZXZJbmRleCwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoKys7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaSA+PSAxKSB7XG4gICAgICAgICAgICBvdXRsaW5lRWxlbWVudC5hZGQocHJldkluZGV4LCBjdXJyZW50SW5kZXgpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGgrKztcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZJbmRleCA9IGN1cnJlbnRJbmRleDtcbiAgICB9XG59O1xuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5oYXNEYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICEhdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudGdyb3Vwcy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVCdWNrZXQ7XG5cbmZ1bmN0aW9uIExpbmVCdWNrZXQoaW5mbywgYnVmZmVycywgcGxhY2VtZW50LCBlbGVtZW50R3JvdXBzKSB7XG4gICAgdGhpcy5pbmZvID0gaW5mbztcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMuZWxlbWVudEdyb3VwcyA9IGVsZW1lbnRHcm91cHMgfHwgbmV3IEVsZW1lbnRHcm91cHMoYnVmZmVycy5saW5lVmVydGV4LCBidWZmZXJzLmxpbmVFbGVtZW50KTtcbn1cblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1tpXTtcbiAgICAgICAgdGhpcy5hZGRGZWF0dXJlKGZlYXR1cmUubG9hZEdlb21ldHJ5KCkpO1xuICAgIH1cbn07XG5cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmUgPSBmdW5jdGlvbihsaW5lcykge1xuICAgIHZhciBpbmZvID0gdGhpcy5pbmZvO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5hZGRMaW5lKGxpbmVzW2ldLCBpbmZvWydsaW5lLWpvaW4nXSwgaW5mb1snbGluZS1jYXAnXSxcbiAgICAgICAgICAgICAgICBpbmZvWydsaW5lLW1pdGVyLWxpbWl0J10sIGluZm9bJ2xpbmUtcm91bmQtbGltaXQnXSk7XG4gICAgfVxufTtcblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkTGluZSA9IGZ1bmN0aW9uKHZlcnRpY2VzLCBqb2luLCBjYXAsIG1pdGVyTGltaXQsIHJvdW5kTGltaXQpIHtcbiAgICBpZiAodmVydGljZXMubGVuZ3RoIDwgMikge1xuICAgICAgICAvL2NvbnNvbGUud2FybignYSBsaW5lIG11c3QgaGF2ZSBhdCBsZWFzdCB0d28gdmVydGljZXMnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChqb2luID09PSAnYmV2ZWwnKSBtaXRlckxpbWl0ID0gMS4wNTtcblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGgsXG4gICAgICAgIGZpcnN0VmVydGV4ID0gdmVydGljZXNbMF0sXG4gICAgICAgIGxhc3RWZXJ0ZXggPSB2ZXJ0aWNlc1tsZW4gLSAxXSxcbiAgICAgICAgY2xvc2VkID0gZmlyc3RWZXJ0ZXguZXF1YWxzKGxhc3RWZXJ0ZXgpO1xuXG4gICAgdmFyIGxpbmVWZXJ0ZXggPSB0aGlzLmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2YXIgbGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMubGluZUVsZW1lbnQ7XG5cbiAgICAvLyB3ZSBjb3VsZCBiZSBtb3JlIHByZWNpZXMsIGJ1dCBpdCB3b3VsZCBvbmx5IHNhdmUgYSBuZWdsaWdpYmxlIGFtb3VudCBvZiBzcGFjZVxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKiA0KTtcbiAgICB2YXIgZWxlbWVudEdyb3VwID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQ7XG4gICAgdmFyIHZlcnRleFN0YXJ0SW5kZXggPSBlbGVtZW50R3JvdXAudmVydGV4U3RhcnRJbmRleDtcblxuICAgIGlmIChsZW4gPT0gMiAmJiBjbG9zZWQpIHtcbiAgICAgICAgLy8gY29uc29sZS53YXJuKCdhIGxpbmUgbWF5IG5vdCBoYXZlIGNvaW5jaWRlbnQgcG9pbnRzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgYmVnaW5DYXAgPSBjYXAsXG4gICAgICAgIGVuZENhcCA9IGNsb3NlZCA/ICdidXR0JyA6IGNhcCxcbiAgICAgICAgZmxpcCA9IDEsXG4gICAgICAgIGRpc3RhbmNlID0gMCxcbiAgICAgICAgY3VycmVudFZlcnRleCwgcHJldlZlcnRleCwgIG5leHRWZXJ0ZXgsIHByZXZOb3JtYWwsICBuZXh0Tm9ybWFsO1xuXG4gICAgLy8gdGhlIGxhc3QgdGhyZWUgdmVydGljZXMgYWRkZWRcbiAgICB2YXIgZTEsIGUyLCBlMztcblxuICAgIGlmIChjbG9zZWQpIHtcbiAgICAgICAgY3VycmVudFZlcnRleCA9IHZlcnRpY2VzW2xlbiAtIDJdO1xuICAgICAgICBuZXh0Tm9ybWFsID0gZmlyc3RWZXJ0ZXguc3ViKGN1cnJlbnRWZXJ0ZXgpLl91bml0KCkuX3BlcnAoKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgbmV4dFZlcnRleCA9IGNsb3NlZCAmJiBpID09PSBsZW4gLSAxID9cbiAgICAgICAgICAgIHZlcnRpY2VzWzFdIDogLy8gaWYgdGhlIGxpbmUgaXMgY2xvc2VkLCB3ZSB0cmVhdCB0aGUgbGFzdCB2ZXJ0ZXggbGlrZSB0aGUgZmlyc3RcbiAgICAgICAgICAgIHZlcnRpY2VzW2kgKyAxXTsgLy8ganVzdCB0aGUgbmV4dCB2ZXJ0ZXhcblxuICAgICAgICAvLyBpZiB0d28gY29uc2VjdXRpdmUgdmVydGljZXMgZXhpc3QsIHNraXAgdGhlIGN1cnJlbnQgb25lXG4gICAgICAgIGlmIChuZXh0VmVydGV4ICYmIHZlcnRpY2VzW2ldLmVxdWFscyhuZXh0VmVydGV4KSkgY29udGludWU7XG5cbiAgICAgICAgaWYgKG5leHROb3JtYWwpIHByZXZOb3JtYWwgPSBuZXh0Tm9ybWFsO1xuICAgICAgICBpZiAoY3VycmVudFZlcnRleCkgcHJldlZlcnRleCA9IGN1cnJlbnRWZXJ0ZXg7XG5cbiAgICAgICAgY3VycmVudFZlcnRleCA9IHZlcnRpY2VzW2ldO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSBob3cgZmFyIGFsb25nIHRoZSBsaW5lIHRoZSBjdXJyZW50VmVydGV4IGlzXG4gICAgICAgIGlmIChwcmV2VmVydGV4KSBkaXN0YW5jZSArPSBjdXJyZW50VmVydGV4LmRpc3QocHJldlZlcnRleCk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBub3JtYWwgdG93YXJkcyB0aGUgbmV4dCB2ZXJ0ZXggaW4gdGhpcyBsaW5lLiBJbiBjYXNlXG4gICAgICAgIC8vIHRoZXJlIGlzIG5vIG5leHQgdmVydGV4LCBwcmV0ZW5kIHRoYXQgdGhlIGxpbmUgaXMgY29udGludWluZyBzdHJhaWdodCxcbiAgICAgICAgLy8gbWVhbmluZyB0aGF0IHdlIGFyZSBqdXN0IHVzaW5nIHRoZSBwcmV2aW91cyBub3JtYWwuXG4gICAgICAgIG5leHROb3JtYWwgPSBuZXh0VmVydGV4ID8gbmV4dFZlcnRleC5zdWIoY3VycmVudFZlcnRleCkuX3VuaXQoKS5fcGVycCgpIDogcHJldk5vcm1hbDtcblxuICAgICAgICAvLyBJZiB3ZSBzdGlsbCBkb24ndCBoYXZlIGEgcHJldmlvdXMgbm9ybWFsLCB0aGlzIGlzIHRoZSBiZWdpbm5pbmcgb2YgYVxuICAgICAgICAvLyBub24tY2xvc2VkIGxpbmUsIHNvIHdlJ3JlIGRvaW5nIGEgc3RyYWlnaHQgXCJqb2luXCIuXG4gICAgICAgIHByZXZOb3JtYWwgPSBwcmV2Tm9ybWFsIHx8IG5leHROb3JtYWw7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBub3JtYWwgb2YgdGhlIGpvaW4gZXh0cnVzaW9uLiBJdCBpcyB0aGUgYW5nbGUgYmlzZWN0b3JcbiAgICAgICAgLy8gb2YgdGhlIHNlZ21lbnRzIGJldHdlZW4gdGhlIHByZXZpb3VzIGxpbmUgYW5kIHRoZSBuZXh0IGxpbmUuXG4gICAgICAgIHZhciBqb2luTm9ybWFsID0gcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkuX3VuaXQoKTtcblxuICAgICAgICAvKiAgam9pbk5vcm1hbCAgICAgcHJldk5vcm1hbFxuICAgICAgICAgKiAgICAgICAgICAgICDihpYgICAgICDihpFcbiAgICAgICAgICogICAgICAgICAgICAgICAgLl9fX19fX19fLiBwcmV2VmVydGV4XG4gICAgICAgICAqICAgICAgICAgICAgICAgIHxcbiAgICAgICAgICogbmV4dE5vcm1hbCAg4oaQICB8ICBjdXJyZW50VmVydGV4XG4gICAgICAgICAqICAgICAgICAgICAgICAgIHxcbiAgICAgICAgICogICAgIG5leHRWZXJ0ZXggIVxuICAgICAgICAgKlxuICAgICAgICAgKi9cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGxlbmd0aCBvZiB0aGUgbWl0ZXIgKHRoZSByYXRpbyBvZiB0aGUgbWl0ZXIgdG8gdGhlIHdpZHRoKS5cbiAgICAgICAgLy8gRmluZCB0aGUgY29zaW5lIG9mIHRoZSBhbmdsZSBiZXR3ZWVuIHRoZSBuZXh0IGFuZCBqb2luIG5vcm1hbHNcbiAgICAgICAgLy8gdXNpbmcgZG90IHByb2R1Y3QuIFRoZSBpbnZlcnNlIG9mIHRoYXQgaXMgdGhlIG1pdGVyIGxlbmd0aC5cbiAgICAgICAgdmFyIGNvc0hhbGZBbmdsZSA9IGpvaW5Ob3JtYWwueCAqIG5leHROb3JtYWwueCArIGpvaW5Ob3JtYWwueSAqIG5leHROb3JtYWwueTtcbiAgICAgICAgdmFyIG1pdGVyTGVuZ3RoID0gMSAvIGNvc0hhbGZBbmdsZTtcblxuICAgICAgICAvLyBXaGV0aGVyIGFueSB2ZXJ0aWNlcyBoYXZlIGJlZW5cbiAgICAgICAgdmFyIHN0YXJ0T2ZMaW5lID0gZTEgPT09IHVuZGVmaW5lZCB8fCBlMiA9PT0gdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIFRoZSBqb2luIGlmIGEgbWlkZGxlIHZlcnRleCwgb3RoZXJ3aXNlIHRoZSBjYXAuXG4gICAgICAgIHZhciBtaWRkbGVWZXJ0ZXggPSBwcmV2VmVydGV4ICYmIG5leHRWZXJ0ZXg7XG4gICAgICAgIHZhciBjdXJyZW50Sm9pbiA9IG1pZGRsZVZlcnRleCA/IGpvaW4gOiBuZXh0VmVydGV4ID8gYmVnaW5DYXAgOiBlbmRDYXA7XG5cbiAgICAgICAgaWYgKG1pZGRsZVZlcnRleCAmJiBjdXJyZW50Sm9pbiA9PT0gJ3JvdW5kJyAmJiBtaXRlckxlbmd0aCA8IHJvdW5kTGltaXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRKb2luID0gJ21pdGVyJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50Sm9pbiA9PT0gJ21pdGVyJyAmJiBtaXRlckxlbmd0aCA+IG1pdGVyTGltaXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRKb2luID0gJ2JldmVsJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50Sm9pbiA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgLy8gVGhlIG1heGltdW0gZXh0cnVkZSBsZW5ndGggaXMgNjMgLyAyNTYgPSA0IHRpbWVzIHRoZSB3aWR0aCBvZiB0aGUgbGluZVxuICAgICAgICAgICAgLy8gc28gaWYgbWl0ZXJMZW5ndGggPj0gNCB3ZSBuZWVkIHRvIGRyYXcgYSBkaWZmZXJlbnQgdHlwZSBvZiBiZXZlbCB3aGVyZS5cbiAgICAgICAgICAgIGlmIChtaXRlckxlbmd0aCA+IDQpIGN1cnJlbnRKb2luID0gJ2ZsaXBiZXZlbCc7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBtaXRlckxlbmd0aCBpcyByZWFsbHkgc21hbGwgYW5kIHRoZSBsaW5lIGJldmVsIHdvdWxkbid0IGJlIHZpc2libGUsXG4gICAgICAgICAgICAvLyBqdXN0IGRyYXcgYSBtaXRlciBqb2luIHRvIHNhdmUgYSB0cmlhbmdsZS5cbiAgICAgICAgICAgIGlmIChtaXRlckxlbmd0aCA8IG1pdGVyTGltaXQpIGN1cnJlbnRKb2luID0gJ21pdGVyJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1pdGVyZWQgam9pbnNcbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInKSB7XG4gICAgICAgICAgICAvLyBzY2FsZSB0aGUgdW5pdCB2ZWN0b3IgYnkgdGhlIG1pdGVyIGxlbmd0aFxuICAgICAgICAgICAgam9pbk5vcm1hbC5fbXVsdChtaXRlckxlbmd0aCk7XG4gICAgICAgICAgICBhZGRDdXJyZW50VmVydGV4KGpvaW5Ob3JtYWwsIDAsIDAsIGZhbHNlKTtcblxuICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRKb2luID09PSAnZmxpcGJldmVsJykge1xuICAgICAgICAgICAgLy8gbWl0ZXIgaXMgdG9vIGJpZywgZmxpcCB0aGUgZGlyZWN0aW9uIHRvIG1ha2UgYSBiZXZlbGVkIGpvaW5cblxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoID4gMTAwKSB7XG4gICAgICAgICAgICAgICAgLy8gQWxtb3N0IHBhcmFsbGVsIGxpbmVzXG4gICAgICAgICAgICAgICAgZmxpcCA9IC1mbGlwO1xuICAgICAgICAgICAgICAgIGpvaW5Ob3JtYWwgPSBuZXh0Tm9ybWFsO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBiZXZlbExlbmd0aCA9IG1pdGVyTGVuZ3RoICogcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkubWFnKCkgLyBwcmV2Tm9ybWFsLnN1YihuZXh0Tm9ybWFsKS5tYWcoKTtcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsLl9wZXJwKCkuX211bHQoZmxpcCAqIGJldmVsTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBmbGlwID0gLWZsaXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRDdXJyZW50VmVydGV4KGpvaW5Ob3JtYWwsIDAsIDAsIGZhbHNlKTtcblxuICAgICAgICAvLyBBbGwgb3RoZXIgdHlwZXMgb2Ygam9pbnNcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgdmFyIG9mZnNldEEsIG9mZnNldEI7XG4gICAgICAgICAgICBpZiAoY3VycmVudEpvaW4gPT09ICdiZXZlbCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlyID0gcHJldk5vcm1hbC54ICogbmV4dE5vcm1hbC55IC0gcHJldk5vcm1hbC55ICogbmV4dE5vcm1hbC54O1xuICAgICAgICAgICAgICAgIHZhciBvZmZzZXQgPSAtTWF0aC5zcXJ0KG1pdGVyTGVuZ3RoICogbWl0ZXJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICBpZiAoZmxpcCAqIGRpciA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0QiA9IDA7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0QSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldEIgPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Sm9pbiA9PT0gJ3NxdWFyZScpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXRBID0gb2Zmc2V0QiA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXRCID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2xvc2UgcHJldmlvdXMgc2VnbWVudCB3aXRoIGEgYnV0dCBvciBhIHNxdWFyZSBjYXAgb3IgYmV2ZWxcbiAgICAgICAgICAgIGlmICghc3RhcnRPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICBhZGRDdXJyZW50VmVydGV4KHByZXZOb3JtYWwsIG9mZnNldEEsIG9mZnNldEIsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIHJvdW5kIGNhcCBvciBsaW5lam9pbiBhdCBlbmQgb2Ygc2VnbWVudFxuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSAmJiBjdXJyZW50Sm9pbiA9PT0gJ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIGFkZEN1cnJlbnRWZXJ0ZXgocHJldk5vcm1hbCwgMSwgMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNlZ21lbnQgaW5jbHVkZSBjYXAgYXJlIGRvbmUsIHVuc2V0IHZlcnRpY2VzIHRvIGRpc2Nvbm5lY3Qgc2VnbWVudHMuXG4gICAgICAgICAgICAvLyBPciBsZWF2ZSB0aGVtIHRvIGNyZWF0ZSBhIGJldmVsLlxuICAgICAgICAgICAgaWYgKHN0YXJ0T2ZMaW5lIHx8IGN1cnJlbnRKb2luICE9PSAnYmV2ZWwnKSB7XG4gICAgICAgICAgICAgICAgZTEgPSBlMiA9IC0xO1xuICAgICAgICAgICAgICAgIGZsaXAgPSAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBZGQgcm91bmQgY2FwIGJlZm9yZSBmaXJzdCBzZWdtZW50XG4gICAgICAgICAgICBpZiAoc3RhcnRPZkxpbmUgJiYgYmVnaW5DYXAgPT09ICdyb3VuZCcpIHtcbiAgICAgICAgICAgICAgICBhZGRDdXJyZW50VmVydGV4KG5leHROb3JtYWwsIC0xLCAtMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudCB3aXRoIGEgYnV0dCBvciBzcXVhcmUgY2FwIG9yIGJldmVsXG4gICAgICAgICAgICBpZiAobmV4dFZlcnRleCkge1xuICAgICAgICAgICAgICAgIGFkZEN1cnJlbnRWZXJ0ZXgobmV4dE5vcm1hbCwgLW9mZnNldEEsIC1vZmZzZXRCLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuXG4gICAgLypcbiAgICAgKiBBZGRzIHR3byB2ZXJ0aWNlcyB0byB0aGUgYnVmZmVyIHRoYXQgYXJlXG4gICAgICogbm9ybWFsIGFuZCAtbm9ybWFsIGZyb20gdGhlIGN1cnJlbnRWZXJ0ZXguXG4gICAgICpcbiAgICAgKiBlbmRCb3ggbW92ZXMgdGhlIGV4dHJ1ZGUgb25lIHVuaXQgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgbGluZVxuICAgICAqIHRvIGNyZWF0ZSBzcXVhcmUgb3Igcm91bmQgY2FwLlxuICAgICAqXG4gICAgICogZW5kTGVmdCBhbmQgZW5kUmlnaHQgc2hpZnRzIHRoZSBleHRydWRlIGFsb25nIHRoZSBsaW5lXG4gICAgICogZW5kTGVmdCA9PT0gMSBtb3ZlcyB0aGUgZXh0cnVkZSBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBsaW5lXG4gICAgICogZW5kTGVmdCA9PT0gLTEgbW92ZXMgdGhlIGV4dHJ1ZGUgaW4gdGhlIHJldmVyc2UgZGlyZWN0aW9uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWRkQ3VycmVudFZlcnRleChub3JtYWwsIGVuZExlZnQsIGVuZFJpZ2h0LCByb3VuZCkge1xuXG4gICAgICAgIHZhciB0eCA9IHJvdW5kID8gMSA6IDA7XG4gICAgICAgIHZhciBleHRydWRlO1xuXG4gICAgICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdChmbGlwKTtcbiAgICAgICAgaWYgKGVuZExlZnQpIGV4dHJ1ZGUuX3N1Yihub3JtYWwucGVycCgpLl9tdWx0KGVuZExlZnQpKTtcbiAgICAgICAgZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMCwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgaWYgKGUxID49IDAgJiYgZTIgPj0gMCkge1xuICAgICAgICAgICAgbGluZUVsZW1lbnQuYWRkKGUxLCBlMiwgZTMpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICAgICAgfVxuICAgICAgICBlMSA9IGUyO1xuICAgICAgICBlMiA9IGUzO1xuXG4gICAgICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdCgtZmxpcCk7XG4gICAgICAgIGlmIChlbmRSaWdodCkgZXh0cnVkZS5fc3ViKG5vcm1hbC5wZXJwKCkuX211bHQoZW5kUmlnaHQpKTtcbiAgICAgICAgZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMSwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgaWYgKGUxID49IDAgJiYgZTIgPj0gMCkge1xuICAgICAgICAgICAgbGluZUVsZW1lbnQuYWRkKGUxLCBlMiwgZTMpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICAgICAgfVxuICAgICAgICBlMSA9IGUyO1xuICAgICAgICBlMiA9IGUzO1xuXG4gICAgICAgIGVsZW1lbnRHcm91cC52ZXJ0ZXhMZW5ndGggKz0gMjtcbiAgICB9XG59O1xuXG5MaW5lQnVja2V0LnByb3RvdHlwZS5oYXNEYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICEhdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhc3RlckJ1Y2tldDtcblxuZnVuY3Rpb24gUmFzdGVyQnVja2V0KGluZm8pIHtcbiAgICB0aGlzLmluZm8gPSBpbmZvO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudGdyb3Vwcy5qcycpO1xudmFyIEFuY2hvciA9IHJlcXVpcmUoJy4uL3N5bWJvbC9hbmNob3IuanMnKTtcbnZhciBpbnRlcnBvbGF0ZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9pbnRlcnBvbGF0ZS5qcycpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbi5qcycpO1xudmFyIFBsYWNlbWVudCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9wbGFjZW1lbnQuanMnKTtcbnZhciBTaGFwaW5nID0gcmVxdWlyZSgnLi4vc3ltYm9sL3NoYXBpbmcuanMnKTtcbnZhciByZXNvbHZlVGV4dCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9yZXNvbHZldGV4dC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN5bWJvbEJ1Y2tldDtcblxudmFyIGZ1bGxSYW5nZSA9IFsyICogTWF0aC5QSSAsIDBdO1xuXG5mdW5jdGlvbiBTeW1ib2xCdWNrZXQoaW5mbywgYnVmZmVycywgY29sbGlzaW9uLCBlbGVtZW50R3JvdXBzKSB7XG4gICAgdGhpcy5pbmZvID0gaW5mbztcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMuY29sbGlzaW9uID0gY29sbGlzaW9uO1xuXG4gICAgaWYgKGluZm9bJ3N5bWJvbC1wbGFjZW1lbnQnXSA9PT0gJ2xpbmUnKSB7XG4gICAgICAgIGlmICghaW5mby5oYXNPd25Qcm9wZXJ0eSgndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgaW5mb1sndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaW5mby5oYXNPd25Qcm9wZXJ0eSgnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgaW5mb1snaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5mb1snc3ltYm9sLWF2b2lkLWVkZ2VzJ10gPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50R3JvdXBzKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudEdyb3VwcyA9IGVsZW1lbnRHcm91cHM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzID0ge1xuICAgICAgICAgICAgdGV4dDogbmV3IEVsZW1lbnRHcm91cHMoYnVmZmVycy5nbHlwaFZlcnRleCksXG4gICAgICAgICAgICBpY29uOiBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmljb25WZXJ0ZXgpXG4gICAgICAgIH07XG4gICAgfVxufVxuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGluZm8gPSB0aGlzLmluZm87XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gdGhpcy50ZXh0RmVhdHVyZXM7XG5cbiAgICB2YXIgaG9yaXpvbnRhbEFsaWduID0gMC41O1xuICAgIGlmIChpbmZvWyd0ZXh0LWhvcml6b250YWwtYWxpZ24nXSA9PT0gJ3JpZ2h0JykgaG9yaXpvbnRhbEFsaWduID0gMTtcbiAgICBlbHNlIGlmIChpbmZvWyd0ZXh0LWhvcml6b250YWwtYWxpZ24nXSA9PT0gJ2xlZnQnKSBob3Jpem9udGFsQWxpZ24gPSAwO1xuXG4gICAgdmFyIHZlcnRpY2FsQWxpZ24gPSAwLjU7XG4gICAgaWYgKGluZm9bJ3RleHQtdmVydGljYWwtYWxpZ24nXSA9PT0gJ2JvdHRvbScpIHZlcnRpY2FsQWxpZ24gPSAxO1xuICAgIGVsc2UgaWYgKGluZm9bJ3RleHQtdmVydGljYWwtYWxpZ24nXSA9PT0gJ3RvcCcpIHZlcnRpY2FsQWxpZ24gPSAwO1xuXG4gICAgdmFyIGp1c3RpZnkgPSAwLjU7XG4gICAgaWYgKGluZm9bJ3RleHQtanVzdGlmeSddID09PSAncmlnaHQnKSBqdXN0aWZ5ID0gMTtcbiAgICBlbHNlIGlmIChpbmZvWyd0ZXh0LWp1c3RpZnknXSA9PT0gJ2xlZnQnKSBqdXN0aWZ5ID0gMDtcblxuICAgIHZhciBvbmVFbSA9IDI0O1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gaW5mb1sndGV4dC1saW5lLWhlaWdodCddICogb25lRW07XG4gICAgdmFyIG1heFdpZHRoID0gaW5mb1snc3ltYm9sLXBsYWNlbWVudCddICE9PSAnbGluZScgJiYgaW5mb1sndGV4dC1tYXgtd2lkdGgnXSAqIG9uZUVtO1xuICAgIHZhciBzcGFjaW5nID0gaW5mb1sndGV4dC1sZXR0ZXItc3BhY2luZyddICogb25lRW07XG4gICAgdmFyIGZvbnRzdGFjayA9IGluZm9bJ3RleHQtZm9udCddO1xuICAgIHZhciB0ZXh0T2Zmc2V0ID0gW2luZm9bJ3RleHQtb2Zmc2V0J11bMF0gKiBvbmVFbSwgaW5mb1sndGV4dC1vZmZzZXQnXVsxXSAqIG9uZUVtXTtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgZmVhdHVyZXMubGVuZ3RoOyBrKyspIHtcblxuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2tdO1xuICAgICAgICB2YXIgdGV4dCA9IHRleHRGZWF0dXJlc1trXTtcbiAgICAgICAgdmFyIGxpbmVzID0gZmVhdHVyZS5sb2FkR2VvbWV0cnkoKTtcblxuICAgICAgICB2YXIgc2hhcGluZyA9IGZhbHNlO1xuICAgICAgICBpZiAodGV4dCkge1xuICAgICAgICAgICAgc2hhcGluZyA9IFNoYXBpbmcuc2hhcGUodGV4dCwgZm9udHN0YWNrLCB0aGlzLnN0YWNrcywgbWF4V2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGxpbmVIZWlnaHQsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSwgc3BhY2luZywgdGV4dE9mZnNldCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuc3ByaXRlICYmIHRoaXMuaW5mb1snaWNvbi1pbWFnZSddKSB7XG4gICAgICAgICAgICBpbWFnZSA9IHRoaXMuc3ByaXRlW3Jlc29sdmVUb2tlbnMoZmVhdHVyZS5wcm9wZXJ0aWVzLCBpbmZvWydpY29uLWltYWdlJ10pXTtcblxuICAgICAgICAgICAgaWYgKGltYWdlKSB7XG4gICAgICAgICAgICAgICAgLy8gbWF0Y2ggZ2x5cGggdGV4IG9iamVjdC4gVE9ETyBjaGFuZ2VcbiAgICAgICAgICAgICAgICBpbWFnZS53ID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2UuaCA9IGltYWdlLmhlaWdodDtcblxuICAgICAgICAgICAgICAgIGlmIChpbWFnZS5zZGYpIHRoaXMuZWxlbWVudEdyb3Vwcy5zZGZJY29ucyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXNoYXBpbmcgJiYgIWltYWdlKSBjb250aW51ZTtcbiAgICAgICAgdGhpcy5hZGRGZWF0dXJlKGxpbmVzLCB0aGlzLnN0YWNrcywgc2hhcGluZywgaW1hZ2UpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGJ5U2NhbGUoYSwgYikge1xuICAgIHJldHVybiBhLnNjYWxlIC0gYi5zY2FsZTtcbn1cblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlID0gZnVuY3Rpb24obGluZXMsIGZhY2VzLCBzaGFwaW5nLCBpbWFnZSkge1xuICAgIHZhciBpbmZvID0gdGhpcy5pbmZvO1xuICAgIHZhciBjb2xsaXNpb24gPSB0aGlzLmNvbGxpc2lvbjtcblxuICAgIHZhciBtaW5TY2FsZSA9IDAuNTtcbiAgICB2YXIgZ2x5cGhTaXplID0gMjQ7XG5cbiAgICB2YXIgaG9yaXpvbnRhbFRleHQgPSBpbmZvWyd0ZXh0LXJvdGF0aW9uLWFsaWdubWVudCddID09PSAndmlld3BvcnQnLFxuICAgICAgICBob3Jpem9udGFsSWNvbiA9IGluZm9bJ2ljb24tcm90YXRpb24tYWxpZ25tZW50J10gPT09ICd2aWV3cG9ydCcsXG4gICAgICAgIGZvbnRTY2FsZSA9IGluZm9bJ3RleHQtbWF4LXNpemUnXSAvIGdseXBoU2l6ZSxcbiAgICAgICAgdGV4dEJveFNjYWxlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogZm9udFNjYWxlLFxuICAgICAgICBpY29uQm94U2NhbGUgPSBjb2xsaXNpb24udGlsZVBpeGVsUmF0aW8gKiBpbmZvWydpY29uLW1heC1zaXplJ10sXG4gICAgICAgIGljb25XaXRob3V0VGV4dCA9IGluZm9bJ3RleHQtb3B0aW9uYWwnXSB8fCAhc2hhcGluZyxcbiAgICAgICAgdGV4dFdpdGhvdXRJY29uID0gaW5mb1snaWNvbi1vcHRpb25hbCddIHx8ICFpbWFnZSxcbiAgICAgICAgYXZvaWRFZGdlcyA9IGluZm9bJ3N5bWJvbC1hdm9pZC1lZGdlcyddO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIHZhciBsaW5lID0gbGluZXNbaV07XG4gICAgICAgIHZhciBhbmNob3JzO1xuXG4gICAgICAgIGlmIChpbmZvWydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJykge1xuICAgICAgICAgICAgLy8gTGluZSBsYWJlbHNcbiAgICAgICAgICAgIGFuY2hvcnMgPSBpbnRlcnBvbGF0ZShsaW5lLCBpbmZvWydzeW1ib2wtbWluLWRpc3RhbmNlJ10sIG1pblNjYWxlLCBjb2xsaXNpb24ubWF4UGxhY2VtZW50U2NhbGUsIGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyk7XG5cbiAgICAgICAgICAgIC8vIFNvcnQgYW5jaG9ycyBieSBzZWdtZW50IHNvIHRoYXQgd2UgY2FuIHN0YXJ0IHBsYWNlbWVudCB3aXRoIHRoZVxuICAgICAgICAgICAgLy8gYW5jaG9ycyB0aGF0IGNhbiBiZSBzaG93biBhdCB0aGUgbG93ZXN0IHpvb20gbGV2ZWxzLlxuICAgICAgICAgICAgYW5jaG9ycy5zb3J0KGJ5U2NhbGUpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBQb2ludCBsYWJlbHNcbiAgICAgICAgICAgIGFuY2hvcnMgPSBbbmV3IEFuY2hvcihsaW5lWzBdLngsIGxpbmVbMF0ueSwgMCwgbWluU2NhbGUpXTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgLy8gVE9ETzogZmlndXJlIG91dCBjb3JyZWN0IGFzY2VuZGVyIGhlaWdodC5cbiAgICAgICAgdmFyIG9yaWdpbiA9IG5ldyBQb2ludCgwLCAtMTcpO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwLCBsZW4gPSBhbmNob3JzLmxlbmd0aDsgaiA8IGxlbjsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYW5jaG9yID0gYW5jaG9yc1tqXTtcbiAgICAgICAgICAgIHZhciBpbnNpZGUgPSAhKGFuY2hvci54IDwgMCB8fCBhbmNob3IueCA+IDQwOTYgfHwgYW5jaG9yLnkgPCAwIHx8IGFuY2hvci55ID4gNDA5Nik7XG5cbiAgICAgICAgICAgIGlmIChhdm9pZEVkZ2VzICYmICFpbnNpZGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNjYWxlcyBhdCB3aGljaCB0aGUgdGV4dCBhbmQgaWNvbnMgY2FuIGJlIGZpcnN0IHNob3duIHdpdGhvdXQgb3ZlcmxhcFxuICAgICAgICAgICAgdmFyIGdseXBoO1xuICAgICAgICAgICAgdmFyIGljb247XG4gICAgICAgICAgICB2YXIgZ2x5cGhTY2FsZSA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaWNvblNjYWxlID0gbnVsbDtcblxuICAgICAgICAgICAgaWYgKHNoYXBpbmcpIHtcbiAgICAgICAgICAgICAgICBnbHlwaCA9IFBsYWNlbWVudC5nZXRHbHlwaHMoYW5jaG9yLCBvcmlnaW4sIHNoYXBpbmcsIGZhY2VzLCB0ZXh0Qm94U2NhbGUsIGhvcml6b250YWxUZXh0LCBsaW5lLCBpbmZvKTtcbiAgICAgICAgICAgICAgICBnbHlwaFNjYWxlID0gaW5mb1sndGV4dC1hbGxvdy1vdmVybGFwJ10gPyBnbHlwaC5taW5TY2FsZVxuICAgICAgICAgICAgICAgICAgICA6IGNvbGxpc2lvbi5nZXRQbGFjZW1lbnRTY2FsZShnbHlwaC5ib3hlcywgZ2x5cGgubWluU2NhbGUsIGF2b2lkRWRnZXMpO1xuICAgICAgICAgICAgICAgIGlmICghZ2x5cGhTY2FsZSAmJiAhaWNvbldpdGhvdXRUZXh0KSBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGltYWdlKSB7XG4gICAgICAgICAgICAgICAgaWNvbiA9IFBsYWNlbWVudC5nZXRJY29uKGFuY2hvciwgaW1hZ2UsIGljb25Cb3hTY2FsZSwgbGluZSwgaW5mbyk7XG4gICAgICAgICAgICAgICAgaWNvblNjYWxlID0gaW5mb1snaWNvbi1hbGxvdy1vdmVybGFwJ10gPyBpY29uLm1pblNjYWxlXG4gICAgICAgICAgICAgICAgICAgIDogY29sbGlzaW9uLmdldFBsYWNlbWVudFNjYWxlKGljb24uYm94ZXMsIGljb24ubWluU2NhbGUsIGF2b2lkRWRnZXMpO1xuICAgICAgICAgICAgICAgIGlmICghaWNvblNjYWxlICYmICF0ZXh0V2l0aG91dEljb24pIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWljb25XaXRob3V0VGV4dCAmJiAhdGV4dFdpdGhvdXRJY29uKSB7XG4gICAgICAgICAgICAgICAgaWNvblNjYWxlID0gZ2x5cGhTY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0ZXh0V2l0aG91dEljb24gJiYgZ2x5cGhTY2FsZSkge1xuICAgICAgICAgICAgICAgIGdseXBoU2NhbGUgPSBNYXRoLm1heChpY29uU2NhbGUsIGdseXBoU2NhbGUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghaWNvbldpdGhvdXRUZXh0ICYmIGljb25TY2FsZSkge1xuICAgICAgICAgICAgICAgIGljb25TY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgcm90YXRpb24gcmFuZ2VzIGl0IGlzIHNhZmUgdG8gc2hvdyB0aGUgZ2x5cGhzXG4gICAgICAgICAgICB2YXIgZ2x5cGhSYW5nZSA9ICghZ2x5cGhTY2FsZSB8fCBpbmZvWyd0ZXh0LWFsbG93LW92ZXJsYXAnXSkgPyBmdWxsUmFuZ2VcbiAgICAgICAgICAgICAgICA6IGNvbGxpc2lvbi5nZXRQbGFjZW1lbnRSYW5nZShnbHlwaC5ib3hlcywgZ2x5cGhTY2FsZSwgaG9yaXpvbnRhbFRleHQpO1xuICAgICAgICAgICAgdmFyIGljb25SYW5nZSA9ICghaWNvblNjYWxlIHx8IGluZm9bJ2ljb24tYWxsb3ctb3ZlcmxhcCddKSA/IGZ1bGxSYW5nZVxuICAgICAgICAgICAgICAgIDogY29sbGlzaW9uLmdldFBsYWNlbWVudFJhbmdlKGljb24uYm94ZXMsIGljb25TY2FsZSwgaG9yaXpvbnRhbEljb24pO1xuXG4gICAgICAgICAgICB2YXIgbWF4UmFuZ2UgPSBbXG4gICAgICAgICAgICAgICAgTWF0aC5taW4oaWNvblJhbmdlWzBdLCBnbHlwaFJhbmdlWzBdKSxcbiAgICAgICAgICAgICAgICBNYXRoLm1heChpY29uUmFuZ2VbMV0sIGdseXBoUmFuZ2VbMV0pXTtcblxuICAgICAgICAgICAgaWYgKCFpY29uV2l0aG91dFRleHQgJiYgIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgICAgIGljb25SYW5nZSA9IGdseXBoUmFuZ2UgPSBtYXhSYW5nZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgICAgIGdseXBoUmFuZ2UgPSBtYXhSYW5nZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWljb25XaXRob3V0VGV4dCkge1xuICAgICAgICAgICAgICAgIGljb25SYW5nZSA9IG1heFJhbmdlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJbnNlcnQgZmluYWwgcGxhY2VtZW50IGludG8gY29sbGlzaW9uIHRyZWUgYW5kIGFkZCBnbHlwaHMvaWNvbnMgdG8gYnVmZmVyc1xuICAgICAgICAgICAgaWYgKGdseXBoU2NhbGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZm9bJ3RleHQtaWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbi5pbnNlcnQoZ2x5cGguYm94ZXMsIGFuY2hvciwgZ2x5cGhTY2FsZSwgZ2x5cGhSYW5nZSwgaG9yaXpvbnRhbFRleHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5zaWRlKSB0aGlzLmFkZFN5bWJvbHModGhpcy5idWZmZXJzLmdseXBoVmVydGV4LCB0aGlzLmVsZW1lbnRHcm91cHMudGV4dCwgZ2x5cGguc2hhcGVzLCBnbHlwaFNjYWxlLCBnbHlwaFJhbmdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGljb25TY2FsZSkge1xuICAgICAgICAgICAgICAgIGlmICghaW5mb1snaWNvbi1pZ25vcmUtcGxhY2VtZW50J10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydChpY29uLmJveGVzLCBhbmNob3IsIGljb25TY2FsZSwgaWNvblJhbmdlLCBob3Jpem9udGFsSWNvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbnNpZGUpIHRoaXMuYWRkU3ltYm9scyh0aGlzLmJ1ZmZlcnMuaWNvblZlcnRleCwgdGhpcy5lbGVtZW50R3JvdXBzLmljb24sIGljb24uc2hhcGVzLCBpY29uU2NhbGUsIGljb25SYW5nZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuYWRkU3ltYm9scyA9IGZ1bmN0aW9uKGJ1ZmZlciwgZWxlbWVudEdyb3Vwcywgc3ltYm9scywgc2NhbGUsIHBsYWNlbWVudFJhbmdlKSB7XG5cbiAgICB2YXIgem9vbSA9IHRoaXMuY29sbGlzaW9uLnpvb207XG5cbiAgICBlbGVtZW50R3JvdXBzLm1ha2VSb29tRm9yKDApO1xuICAgIHZhciBlbGVtZW50R3JvdXAgPSBlbGVtZW50R3JvdXBzLmN1cnJlbnQ7XG5cbiAgICB2YXIgcGxhY2VtZW50Wm9vbSA9IE1hdGgubG9nKHNjYWxlKSAvIE1hdGguTE4yICsgem9vbTtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgc3ltYm9scy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBzeW1ib2xzW2tdLFxuICAgICAgICAgICAgdGwgPSBzeW1ib2wudGwsXG4gICAgICAgICAgICB0ciA9IHN5bWJvbC50cixcbiAgICAgICAgICAgIGJsID0gc3ltYm9sLmJsLFxuICAgICAgICAgICAgYnIgPSBzeW1ib2wuYnIsXG4gICAgICAgICAgICB0ZXggPSBzeW1ib2wudGV4LFxuICAgICAgICAgICAgYW5nbGUgPSBzeW1ib2wuYW5nbGUsXG4gICAgICAgICAgICBhbmNob3IgPSBzeW1ib2wuYW5jaG9yLFxuXG5cbiAgICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heCh6b29tICsgTWF0aC5sb2coc3ltYm9sLm1pblNjYWxlKSAvIE1hdGguTE4yLCBwbGFjZW1lbnRab29tKSxcbiAgICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbih6b29tICsgTWF0aC5sb2coc3ltYm9sLm1heFNjYWxlKSAvIE1hdGguTE4yLCAyNSk7XG5cbiAgICAgICAgaWYgKG1heFpvb20gPD0gbWluWm9vbSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTG93ZXIgbWluIHpvb20gc28gdGhhdCB3aGlsZSBmYWRpbmcgb3V0IHRoZSBsYWJlbCBpdCBjYW4gYmUgc2hvd24gb3V0c2lkZSBvZiBjb2xsaXNpb24tZnJlZSB6b29tIGxldmVsc1xuICAgICAgICBpZiAobWluWm9vbSA9PT0gcGxhY2VtZW50Wm9vbSkgbWluWm9vbSA9IDA7XG5cbiAgICAgICAgLy8gZmlyc3QgdHJpYW5nbGVcbiAgICAgICAgYnVmZmVyLmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRsLngsIHRsLnksIHRleC54LCB0ZXgueSwgYW5nbGUsIG1pblpvb20sIHBsYWNlbWVudFJhbmdlLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgYnVmZmVyLmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRyLngsIHRyLnksIHRleC54ICsgdGV4LncsIHRleC55LCBhbmdsZSwgbWluWm9vbSwgcGxhY2VtZW50UmFuZ2UsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBidWZmZXIuYWRkKGFuY2hvci54LCBhbmNob3IueSwgYmwueCwgYmwueSwgdGV4LngsIHRleC55ICsgdGV4LmgsIGFuZ2xlLCBtaW5ab29tLCBwbGFjZW1lbnRSYW5nZSwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG5cbiAgICAgICAgLy8gc2Vjb25kIHRyaWFuZ2xlXG4gICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLngsIGFuY2hvci55LCB0ci54LCB0ci55LCB0ZXgueCArIHRleC53LCB0ZXgueSwgYW5nbGUsIG1pblpvb20sIHBsYWNlbWVudFJhbmdlLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgYnVmZmVyLmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJsLngsIGJsLnksIHRleC54LCB0ZXgueSArIHRleC5oLCBhbmdsZSwgbWluWm9vbSwgcGxhY2VtZW50UmFuZ2UsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBidWZmZXIuYWRkKGFuY2hvci54LCBhbmNob3IueSwgYnIueCwgYnIueSwgdGV4LnggKyB0ZXgudywgdGV4LnkgKyB0ZXguaCwgYW5nbGUsIG1pblpvb20sIHBsYWNlbWVudFJhbmdlLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcblxuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDY7XG4gICAgfVxuXG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmaXJzdGRvbmUgPSBmYWxzZTtcbiAgICB2YXIgZmlyc3RlcnI7XG4gICAgdGhpcy5nZXRUZXh0RGVwZW5kZW5jaWVzKHRpbGUsIGFjdG9yLCBkb25lKTtcbiAgICB0aGlzLmdldEljb25EZXBlbmRlbmNpZXModGlsZSwgYWN0b3IsIGRvbmUpO1xuICAgIGZ1bmN0aW9uIGRvbmUoZXJyKSB7XG4gICAgICAgIGlmIChlcnIgfHwgZmlyc3Rkb25lKSBjYWxsYmFjayhlcnIpO1xuICAgICAgICBmaXJzdGRvbmUgPSB0cnVlO1xuICAgICAgICBmaXJzdGVyciA9IGVycjtcbiAgICB9XG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldEljb25EZXBlbmRlbmNpZXMgPSBmdW5jdGlvbih0aWxlLCBhY3RvciwgY2FsbGJhY2spIHtcbiAgICB2YXIgYnVja2V0ID0gdGhpcztcbiAgICBpZiAodGhpcy5pbmZvWydpY29uLWltYWdlJ10pIHtcbiAgICAgICAgaWYgKFN5bWJvbEJ1Y2tldC5zcHJpdGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3ByaXRlID0gU3ltYm9sQnVja2V0LnNwcml0ZTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhY3Rvci5zZW5kKCdnZXQgc3ByaXRlIGpzb24nLCB7fSwgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgU3ltYm9sQnVja2V0LnNwcml0ZSA9IGJ1Y2tldC5zcHJpdGUgPSBkYXRhLnNwcml0ZTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuZ2V0VGV4dERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmZWF0dXJlcyA9IHRoaXMuZmVhdHVyZXM7XG4gICAgdmFyIGluZm8gPSB0aGlzLmluZm87XG5cbiAgICBpZiAodGlsZS5zdGFja3MgPT09IHVuZGVmaW5lZCkgdGlsZS5zdGFja3MgPSB7fTtcbiAgICB2YXIgc3RhY2tzID0gdGhpcy5zdGFja3MgPSB0aWxlLnN0YWNrcztcbiAgICB2YXIgZm9udHN0YWNrID0gaW5mb1sndGV4dC1mb250J107XG4gICAgaWYgKHN0YWNrc1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc3RhY2tzW2ZvbnRzdGFja10gPSB7IGdseXBoczoge30sIHJlY3RzOiB7fSB9O1xuICAgIH1cbiAgICB2YXIgc3RhY2sgPSBzdGFja3NbZm9udHN0YWNrXTtcblxuICAgIHZhciBkYXRhID0gcmVzb2x2ZVRleHQoZmVhdHVyZXMsIGluZm8sIHN0YWNrLmdseXBocyk7XG4gICAgdGhpcy50ZXh0RmVhdHVyZXMgPSBkYXRhLnRleHRGZWF0dXJlcztcblxuICAgIGFjdG9yLnNlbmQoJ2dldCBnbHlwaHMnLCB7XG4gICAgICAgIGlkOiB0aWxlLmlkLFxuICAgICAgICBmb250c3RhY2s6IGZvbnRzdGFjayxcbiAgICAgICAgY29kZXBvaW50czogZGF0YS5jb2RlcG9pbnRzXG4gICAgfSwgZnVuY3Rpb24oZXJyLCBuZXdzdGFjaykge1xuICAgICAgICBpZiAoZXJyKSByZXR1cm4gY2FsbGJhY2soZXJyKTtcblxuICAgICAgICB2YXIgbmV3Z2x5cGhzID0gbmV3c3RhY2suZ2x5cGhzO1xuICAgICAgICB2YXIgbmV3cmVjdHMgPSBuZXdzdGFjay5yZWN0cztcbiAgICAgICAgdmFyIGdseXBocyA9IHN0YWNrLmdseXBocztcbiAgICAgICAgdmFyIHJlY3RzID0gc3RhY2sucmVjdHM7XG5cbiAgICAgICAgZm9yICh2YXIgY29kZXBvaW50IGluIG5ld2dseXBocykge1xuICAgICAgICAgICAgZ2x5cGhzW2NvZGVwb2ludF0gPSBuZXdnbHlwaHNbY29kZXBvaW50XTtcbiAgICAgICAgICAgIHJlY3RzW2NvZGVwb2ludF0gPSBuZXdyZWN0c1tjb2RlcG9pbnRdO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9KTtcbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuaGFzRGF0YSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAhIXRoaXMuZWxlbWVudEdyb3Vwcy50ZXh0LmN1cnJlbnQgfHwgISF0aGlzLmVsZW1lbnRHcm91cHMuaWNvbi5jdXJyZW50O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBMYXRMbmc7XG5cbmZ1bmN0aW9uIExhdExuZyhsYXQsIGxuZykge1xuICAgIGlmIChpc05hTihsYXQpIHx8IGlzTmFOKGxuZykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIExhdExuZyBvYmplY3Q6ICgnICsgbGF0ICsgJywgJyArIGxuZyArICcpJyk7XG4gICAgfVxuICAgIHRoaXMubGF0ID0gK2xhdDtcbiAgICB0aGlzLmxuZyA9ICtsbmc7XG59XG5cblxuLy8gY29uc3RydWN0cyBMYXRMbmcgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblxuTGF0TG5nLmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZyhhWzBdLCBhWzFdKTtcbiAgICB9XG4gICAgcmV0dXJuIGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExhdExuZ0JvdW5kcztcblxudmFyIExhdExuZyA9IHJlcXVpcmUoJy4vbGF0bG5nLmpzJyk7XG5cbmZ1bmN0aW9uIExhdExuZ0JvdW5kcyhzdywgbmUpIHtcbiAgICBpZiAoIXN3KSByZXR1cm47XG5cbiAgICB2YXIgbGF0bG5ncyA9IG5lID8gW3N3LCBuZV0gOiBzdztcblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHRoaXMuZXh0ZW5kKGxhdGxuZ3NbaV0pO1xuICAgIH1cbn1cblxuTGF0TG5nQm91bmRzLnByb3RvdHlwZSA9IHtcblxuICAgIC8vIGV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50IG9yIGJvdW5kc1xuICAgIGV4dGVuZDogZnVuY3Rpb24gKG9iaikge1xuICAgICAgICB2YXIgc3cgPSB0aGlzLl9zdyxcbiAgICAgICAgICAgIG5lID0gdGhpcy5fbmUsXG4gICAgICAgICAgICBzdzIsIG5lMjtcblxuICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgICAgICBzdzIgPSBvYmo7XG4gICAgICAgICAgICBuZTIgPSBvYmo7XG5cbiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcbiAgICAgICAgICAgIHN3MiA9IG9iai5fc3c7XG4gICAgICAgICAgICBuZTIgPSBvYmouX25lO1xuXG4gICAgICAgICAgICBpZiAoIXN3MiB8fCAhbmUyKSByZXR1cm4gdGhpcztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKExhdExuZy5jb252ZXJ0KG9iaikgfHwgTGF0TG5nQm91bmRzLmNvbnZlcnQob2JqKSkgOiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzdyAmJiAhbmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N3ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcbiAgICAgICAgICAgIHRoaXMuX25lID0gbmV3IExhdExuZyhuZTIubGF0LCBuZTIubG5nKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcbiAgICAgICAgICAgIHN3LmxuZyA9IE1hdGgubWluKHN3Mi5sbmcsIHN3LmxuZyk7XG4gICAgICAgICAgICBuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xuICAgICAgICAgICAgbmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBnZXRDZW50ZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmcoKHRoaXMuX3N3LmxhdCArIHRoaXMuX25lLmxhdCkgLyAyLCAodGhpcy5fc3cubG5nICsgdGhpcy5fbmUubG5nKSAvIDIpO1xuICAgIH0sXG5cbiAgICBnZXRTb3V0aFdlc3Q6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N3OyB9LFxuICAgIGdldE5vcnRoRWFzdDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fbmU7IH0sXG4gICAgZ2V0Tm9ydGhXZXN0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBuZXcgTGF0TG5nKHRoaXMuZ2V0Tm9ydGgoKSwgdGhpcy5nZXRXZXN0KCkpOyB9LFxuICAgIGdldFNvdXRoRWFzdDogZnVuY3Rpb24gKCkgeyByZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldFNvdXRoKCksIHRoaXMuZ2V0RWFzdCgpKTsgfSxcblxuICAgIGdldFdlc3Q6ICBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9zdy5sbmc7IH0sXG4gICAgZ2V0U291dGg6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N3LmxhdDsgfSxcbiAgICBnZXRFYXN0OiAgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fbmUubG5nOyB9LFxuICAgIGdldE5vcnRoOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9uZS5sYXQ7IH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgTGF0TG5nQm91bmRzIGZyb20gYW4gYXJyYXkgaWYgbmVjZXNzYXJ5XG5MYXRMbmdCb3VuZHMuY29udmVydCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgaWYgKCFhIHx8IGEgaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHJldHVybiBhO1xuICAgIHJldHVybiBuZXcgTGF0TG5nQm91bmRzKGEpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExhdExuZyA9IHJlcXVpcmUoJy4vbGF0bG5nLmpzJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFRyYW5zZm9ybTtcblxuLy8gQSBzaW5nbGUgdHJhbnNmb3JtLCBnZW5lcmFsbHkgdXNlZCBmb3IgYSBzaW5nbGUgdGlsZSB0byBiZSBzY2FsZWQsIHJvdGF0ZWQsIGFuZCB6b29tZWQuXG5cbmZ1bmN0aW9uIFRyYW5zZm9ybShtaW5ab29tLCBtYXhab29tKSB7XG4gICAgdGhpcy50aWxlU2l6ZSA9IDUxMjsgLy8gY29uc3RhbnRcblxuICAgIHRoaXMuX21pblpvb20gPSBtaW5ab29tIHx8IDA7XG4gICAgdGhpcy5fbWF4Wm9vbSA9IG1heFpvb20gfHwgMjI7XG5cbiAgICB0aGlzLmxhdFJhbmdlID0gWy04NSwgODVdO1xuXG4gICAgdGhpcy53aWR0aCA9IDA7XG4gICAgdGhpcy5oZWlnaHQgPSAwO1xuICAgIHRoaXMuem9vbSA9IDA7XG4gICAgdGhpcy5jZW50ZXIgPSBuZXcgTGF0TG5nKDAsIDApO1xuICAgIHRoaXMuYW5nbGUgPSAwO1xufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlID0ge1xuICAgIGdldCBtaW5ab29tKCkgeyByZXR1cm4gdGhpcy5fbWluWm9vbTsgfSxcbiAgICBzZXQgbWluWm9vbSh6b29tKSB7XG4gICAgICAgIHRoaXMuX21pblpvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnpvb20gPSBNYXRoLm1heCh0aGlzLnpvb20sIHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXQgbWF4Wm9vbSgpIHsgcmV0dXJuIHRoaXMuX21heFpvb207IH0sXG4gICAgc2V0IG1heFpvb20oem9vbSkge1xuICAgICAgICB0aGlzLl9tYXhab29tID0gem9vbTtcbiAgICAgICAgdGhpcy56b29tID0gTWF0aC5taW4odGhpcy56b29tLCB6b29tKTtcbiAgICB9LFxuXG4gICAgZ2V0IHdvcmxkU2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUgKiB0aGlzLnNjYWxlO1xuICAgIH0sXG5cbiAgICBnZXQgY2VudGVyUG9pbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemUuX2RpdigyKTtcbiAgICB9LFxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuICAgIH0sXG5cbiAgICBnZXQgYmVhcmluZygpIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLmFuZ2xlIC8gTWF0aC5QSSAqIDE4MDtcbiAgICB9LFxuICAgIHNldCBiZWFyaW5nKGJlYXJpbmcpIHtcbiAgICAgICAgLy8gY29uZmluZSB0aGUgYW5nbGUgdG8gd2l0aGluIFstMTgwLDE4MF1cbiAgICAgICAgYmVhcmluZyA9ICgoKChiZWFyaW5nICsgMTgwKSAlIDM2MCkgKyAzNjApICUgMzYwKSAtIDE4MDtcbiAgICAgICAgdGhpcy5hbmdsZSA9IC1iZWFyaW5nICogTWF0aC5QSSAvIDE4MDtcbiAgICB9LFxuXG4gICAgZ2V0IHpvb20oKSB7IHJldHVybiB0aGlzLl96b29tOyB9LFxuICAgIHNldCB6b29tKHpvb20pIHtcbiAgICAgICAgem9vbSA9IE1hdGgubWluKE1hdGgubWF4KHpvb20sIHRoaXMubWluWm9vbSksIHRoaXMubWF4Wm9vbSk7XG4gICAgICAgIHRoaXMuX3pvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnNjYWxlID0gdGhpcy56b29tU2NhbGUoem9vbSk7XG4gICAgICAgIHRoaXMudGlsZVpvb20gPSBNYXRoLmZsb29yKHpvb20pO1xuICAgICAgICB0aGlzLnpvb21GcmFjdGlvbiA9IHpvb20gLSB0aGlzLnRpbGVab29tO1xuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgem9vbVNjYWxlOiBmdW5jdGlvbih6b29tKSB7IHJldHVybiBNYXRoLnBvdygyLCB6b29tKTsgfSxcbiAgICBzY2FsZVpvb206IGZ1bmN0aW9uKHNjYWxlKSB7IHJldHVybiBNYXRoLmxvZyhzY2FsZSkgLyBNYXRoLkxOMjsgfSxcblxuICAgIHByb2plY3Q6IGZ1bmN0aW9uKGxhdGxuZywgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICB0aGlzLmxuZ1gobGF0bG5nLmxuZywgd29ybGRTaXplKSxcbiAgICAgICAgICAgIHRoaXMubGF0WShsYXRsbmcubGF0LCB3b3JsZFNpemUpKTtcbiAgICB9LFxuXG4gICAgdW5wcm9qZWN0OiBmdW5jdGlvbihwb2ludCwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKFxuICAgICAgICAgICAgdGhpcy55TGF0KHBvaW50LnksIHdvcmxkU2l6ZSksXG4gICAgICAgICAgICB0aGlzLnhMbmcocG9pbnQueCwgd29ybGRTaXplKSk7XG4gICAgfSxcblxuICAgIGdldCB4KCkgeyByZXR1cm4gdGhpcy5sbmdYKHRoaXMuY2VudGVyLmxuZyk7IH0sXG4gICAgZ2V0IHkoKSB7IHJldHVybiB0aGlzLmxhdFkodGhpcy5jZW50ZXIubGF0KTsgfSxcblxuICAgIGdldCBwb2ludCgpIHsgcmV0dXJuIG5ldyBQb2ludCh0aGlzLngsIHRoaXMueSk7IH0sXG5cbiAgICAvLyBsYXQvbG9uIDwtPiBhYnNvbHV0ZSBwaXhlbCBjb29yZHMgY29udmVydGlvblxuICAgIGxuZ1g6IGZ1bmN0aW9uKGxvbiwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiAoMTgwICsgbG9uKSAqICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpIC8gMzYwO1xuICAgIH0sXG4gICAgLy8gbGF0aXR1ZGUgdG8gYWJzb2x1dGUgeSBjb29yZFxuICAgIGxhdFk6IGZ1bmN0aW9uKGxhdCwgd29ybGRTaXplKSB7XG4gICAgICAgIHZhciB5ID0gMTgwIC8gTWF0aC5QSSAqIE1hdGgubG9nKE1hdGgudGFuKE1hdGguUEkgLyA0ICsgbGF0ICogTWF0aC5QSSAvIDM2MCkpO1xuICAgICAgICByZXR1cm4gKDE4MCAtIHkpICogKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLyAzNjA7XG4gICAgfSxcblxuICAgIHhMbmc6IGZ1bmN0aW9uKHgsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4geCAqIDM2MCAvICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpIC0gMTgwO1xuICAgIH0sXG4gICAgeUxhdDogZnVuY3Rpb24oeSwgd29ybGRTaXplKSB7XG4gICAgICAgIHZhciB5MiA9IDE4MCAtIHkgKiAzNjAgLyAod29ybGRTaXplIHx8IHRoaXMud29ybGRTaXplKTtcbiAgICAgICAgcmV0dXJuIDM2MCAvIE1hdGguUEkgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIgKiBNYXRoLlBJIC8gMTgwKSkgLSA5MDtcbiAgICB9LFxuXG4gICAgcGFuQnk6IGZ1bmN0aW9uKG9mZnNldCkge1xuICAgICAgICB2YXIgcG9pbnQgPSB0aGlzLmNlbnRlclBvaW50Ll9hZGQob2Zmc2V0KTtcbiAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnBvaW50TG9jYXRpb24ocG9pbnQpO1xuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgc2V0Wm9vbUFyb3VuZDogZnVuY3Rpb24oem9vbSwgY2VudGVyKSB7XG4gICAgICAgIHZhciBwID0gdGhpcy5sb2NhdGlvblBvaW50KGNlbnRlciksXG4gICAgICAgICAgICBwMSA9IHRoaXMuc2l6ZS5fc3ViKHApLFxuICAgICAgICAgICAgbGF0bG5nID0gdGhpcy5wb2ludExvY2F0aW9uKHAxKTtcbiAgICAgICAgdGhpcy56b29tID0gem9vbTtcbiAgICAgICAgdGhpcy5wYW5CeShwMS5zdWIodGhpcy5sb2NhdGlvblBvaW50KGxhdGxuZykpKTtcbiAgICB9LFxuXG4gICAgc2V0QmVhcmluZ0Fyb3VuZDogZnVuY3Rpb24oYmVhcmluZywgY2VudGVyKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLmxvY2F0aW9uUG9pbnQoY2VudGVyKS5zdWIodGhpcy5jZW50ZXJQb2ludCk7XG4gICAgICAgIHRoaXMucGFuQnkob2Zmc2V0KTtcbiAgICAgICAgdGhpcy5iZWFyaW5nID0gYmVhcmluZztcbiAgICAgICAgdGhpcy5wYW5CeShvZmZzZXQubXVsdCgtMSkpO1xuICAgIH0sXG5cbiAgICBsb2NhdGlvblBvaW50OiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdmFyIHAgPSB0aGlzLnByb2plY3QobGF0bG5nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VudGVyUG9pbnQuX3N1Yih0aGlzLnBvaW50Ll9zdWIocCkuX3JvdGF0ZSh0aGlzLmFuZ2xlKSk7XG4gICAgfSxcblxuICAgIHBvaW50TG9jYXRpb246IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdmFyIHAyID0gdGhpcy5jZW50ZXJQb2ludC5fc3ViKHApLl9yb3RhdGUoLXRoaXMuYW5nbGUpO1xuICAgICAgICByZXR1cm4gdGhpcy51bnByb2plY3QodGhpcy5wb2ludC5zdWIocDIpKTtcbiAgICB9LFxuXG4gICAgbG9jYXRpb25Db29yZGluYXRlOiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdmFyIGsgPSB0aGlzLnpvb21TY2FsZSh0aGlzLnRpbGVab29tKSAvIHRoaXMud29ybGRTaXplO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmxuZ1gobGF0bG5nLmxuZykgKiBrLFxuICAgICAgICAgICAgcm93OiB0aGlzLmxhdFkobGF0bG5nLmxhdCkgKiBrLFxuICAgICAgICAgICAgem9vbTogdGhpcy50aWxlWm9vbVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICBwb2ludENvb3JkaW5hdGU6IGZ1bmN0aW9uKHRpbGVDZW50ZXIsIHApIHtcbiAgICAgICAgdmFyIHpvb21GYWN0b3IgPSB0aGlzLnpvb21TY2FsZSh0aGlzLnpvb21GcmFjdGlvbiksXG4gICAgICAgICAgICBrdCA9IHRoaXMuem9vbVNjYWxlKHRoaXMudGlsZVpvb20gLSB0aWxlQ2VudGVyLnpvb20pLFxuICAgICAgICAgICAgcDIgPSB0aGlzLmNlbnRlclBvaW50Ll9zdWIocCkuX3JvdGF0ZSgtdGhpcy5hbmdsZSkuX2Rpdih0aGlzLnRpbGVTaXplICogem9vbUZhY3Rvcik7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbHVtbjogdGlsZUNlbnRlci5jb2x1bW4gKiBrdCAtIHAyLngsXG4gICAgICAgICAgICByb3c6IHRpbGVDZW50ZXIucm93ICoga3QgLSBwMi55LFxuICAgICAgICAgICAgem9vbTogdGhpcy50aWxlWm9vbVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICBfY29uc3RyYWluOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNlbnRlcikgcmV0dXJuO1xuXG4gICAgICAgIHZhciBtaW5ZLCBtYXhZLCBtaW5YLCBtYXhYLCBzeSwgc3gsIHgyLCB5MixcbiAgICAgICAgICAgIHNpemUgPSB0aGlzLnNpemU7XG5cbiAgICAgICAgaWYgKHRoaXMubGF0UmFuZ2UpIHtcbiAgICAgICAgICAgIG1pblkgPSB0aGlzLmxhdFkodGhpcy5sYXRSYW5nZVsxXSk7XG4gICAgICAgICAgICBtYXhZID0gdGhpcy5sYXRZKHRoaXMubGF0UmFuZ2VbMF0pO1xuICAgICAgICAgICAgc3kgPSBtYXhZIC0gbWluWSA8IHNpemUueSA/IHNpemUueSAvIChtYXhZIC0gbWluWSkgOiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubG5nUmFuZ2UpIHtcbiAgICAgICAgICAgIG1pblggPSB0aGlzLmxuZ1godGhpcy5sbmdSYW5nZVswXSk7XG4gICAgICAgICAgICBtYXhYID0gdGhpcy5sbmdYKHRoaXMubG5nUmFuZ2VbMV0pO1xuICAgICAgICAgICAgc3ggPSBtYXhYIC0gbWluWCA8IHNpemUueCA/IHNpemUueCAvIChtYXhYIC0gbWluWCkgOiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaG93IG11Y2ggdGhlIG1hcCBzaG91bGQgc2NhbGUgdG8gZml0IHRoZSBzY3JlZW4gaW50byBnaXZlbiBsYXRpdHVkZS9sb25naXR1ZGUgcmFuZ2VzXG4gICAgICAgIHZhciBzID0gTWF0aC5tYXgoc3ggfHwgMCwgc3kgfHwgMCk7XG5cbiAgICAgICAgaWYgKHMpIHtcbiAgICAgICAgICAgIHRoaXMuY2VudGVyID0gdGhpcy51bnByb2plY3QobmV3IFBvaW50KFxuICAgICAgICAgICAgICAgIHN4ID8gKG1heFggKyBtaW5YKSAvIDIgOiB0aGlzLngsXG4gICAgICAgICAgICAgICAgc3kgPyAobWF4WSArIG1pblkpIC8gMiA6IHRoaXMueSkpO1xuICAgICAgICAgICAgdGhpcy56b29tICs9IHRoaXMuc2NhbGVab29tKHMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubGF0UmFuZ2UpIHtcbiAgICAgICAgICAgIHZhciB5ID0gdGhpcy55LFxuICAgICAgICAgICAgICAgIGgyID0gc2l6ZS55IC8gMjtcblxuICAgICAgICAgICAgaWYgKHkgLSBoMiA8IG1pblkpIHkyID0gbWluWSArIGgyO1xuICAgICAgICAgICAgaWYgKHkgKyBoMiA+IG1heFkpIHkyID0gbWF4WSAtIGgyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubG5nUmFuZ2UpIHtcbiAgICAgICAgICAgIHZhciB4ID0gdGhpcy54LFxuICAgICAgICAgICAgICAgIHcyID0gc2l6ZS54IC8gMjtcblxuICAgICAgICAgICAgaWYgKHggLSB3MiA8IG1pblgpIHgyID0gbWluWCArIHcyO1xuICAgICAgICAgICAgaWYgKHggKyB3MiA+IG1heFgpIHgyID0gbWF4WCAtIHcyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcGFuIHRoZSBtYXAgaWYgdGhlIHNjcmVlbiBnb2VzIG9mZiB0aGUgcmFuZ2VcbiAgICAgICAgaWYgKHgyICE9PSB1bmRlZmluZWQgfHwgeTIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnVucHJvamVjdChuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgeDIgIT09IHVuZGVmaW5lZCA/IHgyIDogdGhpcy54LFxuICAgICAgICAgICAgICAgIHkyICE9PSB1bmRlZmluZWQgPyB5MiA6IHRoaXMueSkpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8vIEZvbnQgZGF0YSBGcm9tIEhlcnNoZXkgU2ltcGxleCBGb250XG4vLyBodHRwOi8vcGF1bGJvdXJrZS5uZXQvZGF0YWZvcm1hdHMvaGVyc2hleS9cbnZhciBzaW1wbGV4X2ZvbnQgPSB7XG4gICAgXCIgXCI6IFsxNiwgW11dLFxuICAgIFwiIVwiOiBbMTAsIFs1LCAyMSwgNSwgNywgLTEsIC0xLCA1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCJcXFwiXCI6IFsxNiwgWzQsIDIxLCA0LCAxNCwgLTEsIC0xLCAxMiwgMjEsIDEyLCAxNF1dLFxuICAgIFwiI1wiOiBbMjEsIFsxMSwgMjUsIDQsIC03LCAtMSwgLTEsIDE3LCAyNSwgMTAsIC03LCAtMSwgLTEsIDQsIDEyLCAxOCwgMTIsIC0xLCAtMSwgMywgNiwgMTcsIDZdXSxcbiAgICBcIiRcIjogWzIwLCBbOCwgMjUsIDgsIC00LCAtMSwgLTEsIDEyLCAyNSwgMTIsIC00LCAtMSwgLTEsIDE3LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxLCA1LCAyMCwgMywgMTgsIDMsIDE2LCA0LCAxNCwgNSwgMTMsIDcsIDEyLCAxMywgMTAsIDE1LCA5LCAxNiwgOCwgMTcsIDYsIDE3LCAzLCAxNSwgMSwgMTIsIDAsIDgsIDAsIDUsIDEsIDMsIDNdXSxcbiAgICBcIiVcIjogWzI0LCBbMjEsIDIxLCAzLCAwLCAtMSwgLTEsIDgsIDIxLCAxMCwgMTksIDEwLCAxNywgOSwgMTUsIDcsIDE0LCA1LCAxNCwgMywgMTYsIDMsIDE4LCA0LCAyMCwgNiwgMjEsIDgsIDIxLCAxMCwgMjAsIDEzLCAxOSwgMTYsIDE5LCAxOSwgMjAsIDIxLCAyMSwgLTEsIC0xLCAxNywgNywgMTUsIDYsIDE0LCA0LCAxNCwgMiwgMTYsIDAsIDE4LCAwLCAyMCwgMSwgMjEsIDMsIDIxLCA1LCAxOSwgNywgMTcsIDddXSxcbiAgICBcIiZcIjogWzI2LCBbMjMsIDEyLCAyMywgMTMsIDIyLCAxNCwgMjEsIDE0LCAyMCwgMTMsIDE5LCAxMSwgMTcsIDYsIDE1LCAzLCAxMywgMSwgMTEsIDAsIDcsIDAsIDUsIDEsIDQsIDIsIDMsIDQsIDMsIDYsIDQsIDgsIDUsIDksIDEyLCAxMywgMTMsIDE0LCAxNCwgMTYsIDE0LCAxOCwgMTMsIDIwLCAxMSwgMjEsIDksIDIwLCA4LCAxOCwgOCwgMTYsIDksIDEzLCAxMSwgMTAsIDE2LCAzLCAxOCwgMSwgMjAsIDAsIDIyLCAwLCAyMywgMSwgMjMsIDJdXSxcbiAgICBcIidcIjogWzEwLCBbNSwgMTksIDQsIDIwLCA1LCAyMSwgNiwgMjAsIDYsIDE4LCA1LCAxNiwgNCwgMTVdXSxcbiAgICBcIihcIjogWzE0LCBbMTEsIDI1LCA5LCAyMywgNywgMjAsIDUsIDE2LCA0LCAxMSwgNCwgNywgNSwgMiwgNywgLTIsIDksIC01LCAxMSwgLTddXSxcbiAgICBcIilcIjogWzE0LCBbMywgMjUsIDUsIDIzLCA3LCAyMCwgOSwgMTYsIDEwLCAxMSwgMTAsIDcsIDksIDIsIDcsIC0yLCA1LCAtNSwgMywgLTddXSxcbiAgICBcIipcIjogWzE2LCBbOCwgMjEsIDgsIDksIC0xLCAtMSwgMywgMTgsIDEzLCAxMiwgLTEsIC0xLCAxMywgMTgsIDMsIDEyXV0sXG4gICAgXCIrXCI6IFsyNiwgWzEzLCAxOCwgMTMsIDAsIC0xLCAtMSwgNCwgOSwgMjIsIDldXSxcbiAgICBcIixcIjogWzEwLCBbNiwgMSwgNSwgMCwgNCwgMSwgNSwgMiwgNiwgMSwgNiwgLTEsIDUsIC0zLCA0LCAtNF1dLFxuICAgIFwiLVwiOiBbMjYsIFs0LCA5LCAyMiwgOV1dLFxuICAgIFwiLlwiOiBbMTAsIFs1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCIvXCI6IFsyMiwgWzIwLCAyNSwgMiwgLTddXSxcbiAgICBcIjBcIjogWzIwLCBbOSwgMjEsIDYsIDIwLCA0LCAxNywgMywgMTIsIDMsIDksIDQsIDQsIDYsIDEsIDksIDAsIDExLCAwLCAxNCwgMSwgMTYsIDQsIDE3LCA5LCAxNywgMTIsIDE2LCAxNywgMTQsIDIwLCAxMSwgMjEsIDksIDIxXV0sXG4gICAgXCIxXCI6IFsyMCwgWzYsIDE3LCA4LCAxOCwgMTEsIDIxLCAxMSwgMF1dLFxuICAgIFwiMlwiOiBbMjAsIFs0LCAxNiwgNCwgMTcsIDUsIDE5LCA2LCAyMCwgOCwgMjEsIDEyLCAyMSwgMTQsIDIwLCAxNSwgMTksIDE2LCAxNywgMTYsIDE1LCAxNSwgMTMsIDEzLCAxMCwgMywgMCwgMTcsIDBdXSxcbiAgICBcIjNcIjogWzIwLCBbNSwgMjEsIDE2LCAyMSwgMTAsIDEzLCAxMywgMTMsIDE1LCAxMiwgMTYsIDExLCAxNywgOCwgMTcsIDYsIDE2LCAzLCAxNCwgMSwgMTEsIDAsIDgsIDAsIDUsIDEsIDQsIDIsIDMsIDRdXSxcbiAgICBcIjRcIjogWzIwLCBbMTMsIDIxLCAzLCA3LCAxOCwgNywgLTEsIC0xLCAxMywgMjEsIDEzLCAwXV0sXG4gICAgXCI1XCI6IFsyMCwgWzE1LCAyMSwgNSwgMjEsIDQsIDEyLCA1LCAxMywgOCwgMTQsIDExLCAxNCwgMTQsIDEzLCAxNiwgMTEsIDE3LCA4LCAxNywgNiwgMTYsIDMsIDE0LCAxLCAxMSwgMCwgOCwgMCwgNSwgMSwgNCwgMiwgMywgNF1dLFxuICAgIFwiNlwiOiBbMjAsIFsxNiwgMTgsIDE1LCAyMCwgMTIsIDIxLCAxMCwgMjEsIDcsIDIwLCA1LCAxNywgNCwgMTIsIDQsIDcsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMSwgMCwgMTQsIDEsIDE2LCAzLCAxNywgNiwgMTcsIDcsIDE2LCAxMCwgMTQsIDEyLCAxMSwgMTMsIDEwLCAxMywgNywgMTIsIDUsIDEwLCA0LCA3XV0sXG4gICAgXCI3XCI6IFsyMCwgWzE3LCAyMSwgNywgMCwgLTEsIC0xLCAzLCAyMSwgMTcsIDIxXV0sXG4gICAgXCI4XCI6IFsyMCwgWzgsIDIxLCA1LCAyMCwgNCwgMTgsIDQsIDE2LCA1LCAxNCwgNywgMTMsIDExLCAxMiwgMTQsIDExLCAxNiwgOSwgMTcsIDcsIDE3LCA0LCAxNiwgMiwgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCA0LCAyLCAzLCA0LCAzLCA3LCA0LCA5LCA2LCAxMSwgOSwgMTIsIDEzLCAxMywgMTUsIDE0LCAxNiwgMTYsIDE2LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxXV0sXG4gICAgXCI5XCI6IFsyMCwgWzE2LCAxNCwgMTUsIDExLCAxMywgOSwgMTAsIDgsIDksIDgsIDYsIDksIDQsIDExLCAzLCAxNCwgMywgMTUsIDQsIDE4LCA2LCAyMCwgOSwgMjEsIDEwLCAyMSwgMTMsIDIwLCAxNSwgMTgsIDE2LCAxNCwgMTYsIDksIDE1LCA0LCAxMywgMSwgMTAsIDAsIDgsIDAsIDUsIDEsIDQsIDNdXSxcbiAgICBcIjpcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDUsIDIsIDQsIDEsIDUsIDAsIDYsIDEsIDUsIDJdXSxcbiAgICBcIjtcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDYsIDEsIDUsIDAsIDQsIDEsIDUsIDIsIDYsIDEsIDYsIC0xLCA1LCAtMywgNCwgLTRdXSxcbiAgICBcIjxcIjogWzI0LCBbMjAsIDE4LCA0LCA5LCAyMCwgMF1dLFxuICAgIFwiPVwiOiBbMjYsIFs0LCAxMiwgMjIsIDEyLCAtMSwgLTEsIDQsIDYsIDIyLCA2XV0sXG4gICAgXCI+XCI6IFsyNCwgWzQsIDE4LCAyMCwgOSwgNCwgMF1dLFxuICAgIFwiP1wiOiBbMTgsIFszLCAxNiwgMywgMTcsIDQsIDE5LCA1LCAyMCwgNywgMjEsIDExLCAyMSwgMTMsIDIwLCAxNCwgMTksIDE1LCAxNywgMTUsIDE1LCAxNCwgMTMsIDEzLCAxMiwgOSwgMTAsIDksIDcsIC0xLCAtMSwgOSwgMiwgOCwgMSwgOSwgMCwgMTAsIDEsIDksIDJdXSxcbiAgICBcIkBcIjogWzI3LCBbMTgsIDEzLCAxNywgMTUsIDE1LCAxNiwgMTIsIDE2LCAxMCwgMTUsIDksIDE0LCA4LCAxMSwgOCwgOCwgOSwgNiwgMTEsIDUsIDE0LCA1LCAxNiwgNiwgMTcsIDgsIC0xLCAtMSwgMTIsIDE2LCAxMCwgMTQsIDksIDExLCA5LCA4LCAxMCwgNiwgMTEsIDUsIC0xLCAtMSwgMTgsIDE2LCAxNywgOCwgMTcsIDYsIDE5LCA1LCAyMSwgNSwgMjMsIDcsIDI0LCAxMCwgMjQsIDEyLCAyMywgMTUsIDIyLCAxNywgMjAsIDE5LCAxOCwgMjAsIDE1LCAyMSwgMTIsIDIxLCA5LCAyMCwgNywgMTksIDUsIDE3LCA0LCAxNSwgMywgMTIsIDMsIDksIDQsIDYsIDUsIDQsIDcsIDIsIDksIDEsIDEyLCAwLCAxNSwgMCwgMTgsIDEsIDIwLCAyLCAyMSwgMywgLTEsIC0xLCAxOSwgMTYsIDE4LCA4LCAxOCwgNiwgMTksIDVdXSxcbiAgICBcIkFcIjogWzE4LCBbOSwgMjEsIDEsIDAsIC0xLCAtMSwgOSwgMjEsIDE3LCAwLCAtMSwgLTEsIDQsIDcsIDE0LCA3XV0sXG4gICAgXCJCXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgLTEsIC0xLCA0LCAxMSwgMTMsIDExLCAxNiwgMTAsIDE3LCA5LCAxOCwgNywgMTgsIDQsIDE3LCAyLCAxNiwgMSwgMTMsIDAsIDQsIDBdXSxcbiAgICBcIkNcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1XV0sXG4gICAgXCJEXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMSwgMjEsIDE0LCAyMCwgMTYsIDE4LCAxNywgMTYsIDE4LCAxMywgMTgsIDgsIDE3LCA1LCAxNiwgMywgMTQsIDEsIDExLCAwLCA0LCAwXV0sXG4gICAgXCJFXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxNywgMjEsIC0xLCAtMSwgNCwgMTEsIDEyLCAxMSwgLTEsIC0xLCA0LCAwLCAxNywgMF1dLFxuICAgIFwiRlwiOiBbMTgsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTcsIDIxLCAtMSwgLTEsIDQsIDExLCAxMiwgMTFdXSxcbiAgICBcIkdcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOCwgOCwgLTEsIC0xLCAxMywgOCwgMTgsIDhdXSxcbiAgICBcIkhcIjogWzIyLCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMCwgLTEsIC0xLCA0LCAxMSwgMTgsIDExXV0sXG4gICAgXCJJXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIkpcIjogWzE2LCBbMTIsIDIxLCAxMiwgNSwgMTEsIDIsIDEwLCAxLCA4LCAwLCA2LCAwLCA0LCAxLCAzLCAyLCAyLCA1LCAyLCA3XV0sXG4gICAgXCJLXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDE4LCAyMSwgNCwgNywgLTEsIC0xLCA5LCAxMiwgMTgsIDBdXSxcbiAgICBcIkxcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMCwgMTYsIDBdXSxcbiAgICBcIk1cIjogWzI0LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMjEsIDEyLCAwLCAtMSwgLTEsIDIwLCAyMSwgMTIsIDAsIC0xLCAtMSwgMjAsIDIxLCAyMCwgMF1dLFxuICAgIFwiTlwiOiBbMjIsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTgsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMF1dLFxuICAgIFwiT1wiOiBbMjIsIFs5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOSwgOCwgMTksIDEzLCAxOCwgMTYsIDE3LCAxOCwgMTUsIDIwLCAxMywgMjEsIDksIDIxXV0sXG4gICAgXCJQXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNCwgMTcsIDEyLCAxNiwgMTEsIDEzLCAxMCwgNCwgMTBdXSxcbiAgICBcIlFcIjogWzIyLCBbOSwgMjEsIDcsIDIwLCA1LCAxOCwgNCwgMTYsIDMsIDEzLCAzLCA4LCA0LCA1LCA1LCAzLCA3LCAxLCA5LCAwLCAxMywgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNSwgMTksIDgsIDE5LCAxMywgMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgLTEsIC0xLCAxMiwgNCwgMTgsIC0yXV0sXG4gICAgXCJSXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgNCwgMTEsIC0xLCAtMSwgMTEsIDExLCAxOCwgMF1dLFxuICAgIFwiU1wiOiBbMjAsIFsxNywgMTgsIDE1LCAyMCwgMTIsIDIxLCA4LCAyMSwgNSwgMjAsIDMsIDE4LCAzLCAxNiwgNCwgMTQsIDUsIDEzLCA3LCAxMiwgMTMsIDEwLCAxNSwgOSwgMTYsIDgsIDE3LCA2LCAxNywgMywgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCAzLCAzXV0sXG4gICAgXCJUXCI6IFsxNiwgWzgsIDIxLCA4LCAwLCAtMSwgLTEsIDEsIDIxLCAxNSwgMjFdXSxcbiAgICBcIlVcIjogWzIyLCBbNCwgMjEsIDQsIDYsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMiwgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNiwgMTgsIDIxXV0sXG4gICAgXCJWXCI6IFsxOCwgWzEsIDIxLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMF1dLFxuICAgIFwiV1wiOiBbMjQsIFsyLCAyMSwgNywgMCwgLTEsIC0xLCAxMiwgMjEsIDcsIDAsIC0xLCAtMSwgMTIsIDIxLCAxNywgMCwgLTEsIC0xLCAyMiwgMjEsIDE3LCAwXV0sXG4gICAgXCJYXCI6IFsyMCwgWzMsIDIxLCAxNywgMCwgLTEsIC0xLCAxNywgMjEsIDMsIDBdXSxcbiAgICBcIllcIjogWzE4LCBbMSwgMjEsIDksIDExLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMTFdXSxcbiAgICBcIlpcIjogWzIwLCBbMTcsIDIxLCAzLCAwLCAtMSwgLTEsIDMsIDIxLCAxNywgMjEsIC0xLCAtMSwgMywgMCwgMTcsIDBdXSxcbiAgICBcIltcIjogWzE0LCBbNCwgMjUsIDQsIC03LCAtMSwgLTEsIDUsIDI1LCA1LCAtNywgLTEsIC0xLCA0LCAyNSwgMTEsIDI1LCAtMSwgLTEsIDQsIC03LCAxMSwgLTddXSxcbiAgICBcIlxcXFxcIjogWzE0LCBbMCwgMjEsIDE0LCAtM11dLFxuICAgIFwiXVwiOiBbMTQsIFs5LCAyNSwgOSwgLTcsIC0xLCAtMSwgMTAsIDI1LCAxMCwgLTcsIC0xLCAtMSwgMywgMjUsIDEwLCAyNSwgLTEsIC0xLCAzLCAtNywgMTAsIC03XV0sXG4gICAgXCJeXCI6IFsxNiwgWzYsIDE1LCA4LCAxOCwgMTAsIDE1LCAtMSwgLTEsIDMsIDEyLCA4LCAxNywgMTMsIDEyLCAtMSwgLTEsIDgsIDE3LCA4LCAwXV0sXG4gICAgXCJfXCI6IFsxNiwgWzAsIC0yLCAxNiwgLTJdXSxcbiAgICBcImBcIjogWzEwLCBbNiwgMjEsIDUsIDIwLCA0LCAxOCwgNCwgMTYsIDUsIDE1LCA2LCAxNiwgNSwgMTddXSxcbiAgICBcImFcIjogWzE5LCBbMTUsIDE0LCAxNSwgMCwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJiXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDExLCA2LCAxMywgOCwgMTQsIDExLCAxNCwgMTMsIDEzLCAxNSwgMTEsIDE2LCA4LCAxNiwgNiwgMTUsIDMsIDEzLCAxLCAxMSwgMCwgOCwgMCwgNiwgMSwgNCwgM11dLFxuICAgIFwiY1wiOiBbMTgsIFsxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJkXCI6IFsxOSwgWzE1LCAyMSwgMTUsIDAsIC0xLCAtMSwgMTUsIDExLCAxMywgMTMsIDExLCAxNCwgOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgM11dLFxuICAgIFwiZVwiOiBbMTgsIFszLCA4LCAxNSwgOCwgMTUsIDEwLCAxNCwgMTIsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJmXCI6IFsxMiwgWzEwLCAyMSwgOCwgMjEsIDYsIDIwLCA1LCAxNywgNSwgMCwgLTEsIC0xLCAyLCAxNCwgOSwgMTRdXSxcbiAgICBcImdcIjogWzE5LCBbMTUsIDE0LCAxNSwgLTIsIDE0LCAtNSwgMTMsIC02LCAxMSwgLTcsIDgsIC03LCA2LCAtNiwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJoXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDEwLCA3LCAxMywgOSwgMTQsIDEyLCAxNCwgMTQsIDEzLCAxNSwgMTAsIDE1LCAwXV0sXG4gICAgXCJpXCI6IFs4LCBbMywgMjEsIDQsIDIwLCA1LCAyMSwgNCwgMjIsIDMsIDIxLCAtMSwgLTEsIDQsIDE0LCA0LCAwXV0sXG4gICAgXCJqXCI6IFsxMCwgWzUsIDIxLCA2LCAyMCwgNywgMjEsIDYsIDIyLCA1LCAyMSwgLTEsIC0xLCA2LCAxNCwgNiwgLTMsIDUsIC02LCAzLCAtNywgMSwgLTddXSxcbiAgICBcImtcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTQsIDE0LCA0LCA0LCAtMSwgLTEsIDgsIDgsIDE1LCAwXV0sXG4gICAgXCJsXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIm1cIjogWzMwLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDAsIC0xLCAtMSwgMTUsIDEwLCAxOCwgMTMsIDIwLCAxNCwgMjMsIDE0LCAyNSwgMTMsIDI2LCAxMCwgMjYsIDBdXSxcbiAgICBcIm5cIjogWzE5LCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDBdXSxcbiAgICBcIm9cIjogWzE5LCBbOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgMywgMTYsIDYsIDE2LCA4LCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNF1dLFxuICAgIFwicFwiOiBbMTksIFs0LCAxNCwgNCwgLTcsIC0xLCAtMSwgNCwgMTEsIDYsIDEzLCA4LCAxNCwgMTEsIDE0LCAxMywgMTMsIDE1LCAxMSwgMTYsIDgsIDE2LCA2LCAxNSwgMywgMTMsIDEsIDExLCAwLCA4LCAwLCA2LCAxLCA0LCAzXV0sXG4gICAgXCJxXCI6IFsxOSwgWzE1LCAxNCwgMTUsIC03LCAtMSwgLTEsIDE1LCAxMSwgMTMsIDEzLCAxMSwgMTQsIDgsIDE0LCA2LCAxMywgNCwgMTEsIDMsIDgsIDMsIDYsIDQsIDMsIDYsIDEsIDgsIDAsIDExLCAwLCAxMywgMSwgMTUsIDNdXSxcbiAgICBcInJcIjogWzEzLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgOCwgNSwgMTEsIDcsIDEzLCA5LCAxNCwgMTIsIDE0XV0sXG4gICAgXCJzXCI6IFsxNywgWzE0LCAxMSwgMTMsIDEzLCAxMCwgMTQsIDcsIDE0LCA0LCAxMywgMywgMTEsIDQsIDksIDYsIDgsIDExLCA3LCAxMywgNiwgMTQsIDQsIDE0LCAzLCAxMywgMSwgMTAsIDAsIDcsIDAsIDQsIDEsIDMsIDNdXSxcbiAgICBcInRcIjogWzEyLCBbNSwgMjEsIDUsIDQsIDYsIDEsIDgsIDAsIDEwLCAwLCAtMSwgLTEsIDIsIDE0LCA5LCAxNF1dLFxuICAgIFwidVwiOiBbMTksIFs0LCAxNCwgNCwgNCwgNSwgMSwgNywgMCwgMTAsIDAsIDEyLCAxLCAxNSwgNCwgLTEsIC0xLCAxNSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ2XCI6IFsxNiwgWzIsIDE0LCA4LCAwLCAtMSwgLTEsIDE0LCAxNCwgOCwgMF1dLFxuICAgIFwid1wiOiBbMjIsIFszLCAxNCwgNywgMCwgLTEsIC0xLCAxMSwgMTQsIDcsIDAsIC0xLCAtMSwgMTEsIDE0LCAxNSwgMCwgLTEsIC0xLCAxOSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ4XCI6IFsxNywgWzMsIDE0LCAxNCwgMCwgLTEsIC0xLCAxNCwgMTQsIDMsIDBdXSxcbiAgICBcInlcIjogWzE2LCBbMiwgMTQsIDgsIDAsIC0xLCAtMSwgMTQsIDE0LCA4LCAwLCA2LCAtNCwgNCwgLTYsIDIsIC03LCAxLCAtN11dLFxuICAgIFwielwiOiBbMTcsIFsxNCwgMTQsIDMsIDAsIC0xLCAtMSwgMywgMTQsIDE0LCAxNCwgLTEsIC0xLCAzLCAwLCAxNCwgMF1dLFxuICAgIFwie1wiOiBbMTQsIFs5LCAyNSwgNywgMjQsIDYsIDIzLCA1LCAyMSwgNSwgMTksIDYsIDE3LCA3LCAxNiwgOCwgMTQsIDgsIDEyLCA2LCAxMCwgLTEsIC0xLCA3LCAyNCwgNiwgMjIsIDYsIDIwLCA3LCAxOCwgOCwgMTcsIDksIDE1LCA5LCAxMywgOCwgMTEsIDQsIDksIDgsIDcsIDksIDUsIDksIDMsIDgsIDEsIDcsIDAsIDYsIC0yLCA2LCAtNCwgNywgLTYsIC0xLCAtMSwgNiwgOCwgOCwgNiwgOCwgNCwgNywgMiwgNiwgMSwgNSwgLTEsIDUsIC0zLCA2LCAtNSwgNywgLTYsIDksIC03XV0sXG4gICAgXCJ8XCI6IFs4LCBbNCwgMjUsIDQsIC03XV0sXG4gICAgXCJ9XCI6IFsxNCwgWzUsIDI1LCA3LCAyNCwgOCwgMjMsIDksIDIxLCA5LCAxOSwgOCwgMTcsIDcsIDE2LCA2LCAxNCwgNiwgMTIsIDgsIDEwLCAtMSwgLTEsIDcsIDI0LCA4LCAyMiwgOCwgMjAsIDcsIDE4LCA2LCAxNywgNSwgMTUsIDUsIDEzLCA2LCAxMSwgMTAsIDksIDYsIDcsIDUsIDUsIDUsIDMsIDYsIDEsIDcsIDAsIDgsIC0yLCA4LCAtNCwgNywgLTYsIC0xLCAtMSwgOCwgOCwgNiwgNiwgNiwgNCwgNywgMiwgOCwgMSwgOSwgLTEsIDksIC0zLCA4LCAtNSwgNywgLTYsIDUsIC03XV0sXG4gICAgXCJ+XCI6IFsyNCwgWzMsIDYsIDMsIDgsIDQsIDExLCA2LCAxMiwgOCwgMTIsIDEwLCAxMSwgMTQsIDgsIDE2LCA3LCAxOCwgNywgMjAsIDgsIDIxLCAxMCwgLTEsIC0xLCAzLCA4LCA0LCAxMCwgNiwgMTEsIDgsIDExLCAxMCwgMTAsIDE0LCA3LCAxNiwgNiwgMTgsIDYsIDIwLCA3LCAyMSwgMTAsIDIxLCAxMl1dLFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0ZXh0VmVydGljZXModGV4dCwgbGVmdCwgYmFzZWxpbmUsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxO1xuXG4gICAgdmFyIHN0cm9rZXMgPSBbXSxcbiAgICAgICAgaSwgbGVuLCBqLCBsZW4yLCBnbHlwaCwgZGF0YSwgeCwgeSwgcHJldjtcblxuICAgIGZvciAoaSA9IDAsIGxlbiA9IHRleHQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgZ2x5cGggPSBzaW1wbGV4X2ZvbnRbdGV4dFtpXV07XG4gICAgICAgIGlmICghZ2x5cGgpIGNvbnRpbnVlO1xuICAgICAgICBwcmV2ID0gbnVsbDtcblxuICAgICAgICBmb3IgKGogPSAwLCBsZW4yID0gZ2x5cGhbMV0ubGVuZ3RoOyBqIDwgbGVuMjsgaiArPSAyKSB7XG4gICAgICAgICAgICBpZiAoZ2x5cGhbMV1bal0gPT09IC0xICYmIGdseXBoWzFdW2ogKyAxXSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBwcmV2ID0gbnVsbDtcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB4ID0gbGVmdCArIGdseXBoWzFdW2pdICogc2NhbGU7XG4gICAgICAgICAgICAgICAgeSA9IGJhc2VsaW5lIC0gZ2x5cGhbMV1baiArIDFdICogc2NhbGU7XG4gICAgICAgICAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlcy5wdXNoKHByZXYueCwgcHJldi55LCB4LCB5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJldiA9IHt4OiB4LCB5OiB5fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZWZ0ICs9IGdseXBoWzBdICogc2NhbGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0cm9rZXM7XG59O1xuIiwiLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IGdsLW1hdHJpeCAtIEhpZ2ggcGVyZm9ybWFuY2UgbWF0cml4IGFuZCB2ZWN0b3Igb3BlcmF0aW9uc1xuICogQGF1dGhvciBCcmFuZG9uIEpvbmVzXG4gKiBAYXV0aG9yIENvbGluIE1hY0tlbnppZSBJVlxuICogQHZlcnNpb24gMi4yLjBcbiAqL1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG4oZnVuY3Rpb24oZSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIHQ9e307dHlwZW9mIGV4cG9ydHM9PVwidW5kZWZpbmVkXCI/dHlwZW9mIGRlZmluZT09XCJmdW5jdGlvblwiJiZ0eXBlb2YgZGVmaW5lLmFtZD09XCJvYmplY3RcIiYmZGVmaW5lLmFtZD8odC5leHBvcnRzPXt9LGRlZmluZShmdW5jdGlvbigpe3JldHVybiB0LmV4cG9ydHN9KSk6dC5leHBvcnRzPXR5cGVvZiB3aW5kb3chPVwidW5kZWZpbmVkXCI/d2luZG93OmU6dC5leHBvcnRzPWV4cG9ydHMsZnVuY3Rpb24oZSl7aWYoIXQpdmFyIHQ9MWUtNjtpZighbil2YXIgbj10eXBlb2YgRmxvYXQzMkFycmF5IT1cInVuZGVmaW5lZFwiP0Zsb2F0MzJBcnJheTpBcnJheTtpZighcil2YXIgcj1NYXRoLnJhbmRvbTt2YXIgaT17fTtpLnNldE1hdHJpeEFycmF5VHlwZT1mdW5jdGlvbihlKXtuPWV9LHR5cGVvZiBlIT1cInVuZGVmaW5lZFwiJiYoZS5nbE1hdHJpeD1pKTt2YXIgcz17fTtzLmNyZWF0ZT1mdW5jdGlvbigpe3ZhciBlPW5ldyBuKDIpO3JldHVybiBlWzBdPTAsZVsxXT0wLGV9LHMuY2xvbmU9ZnVuY3Rpb24oZSl7dmFyIHQ9bmV3IG4oMik7cmV0dXJuIHRbMF09ZVswXSx0WzFdPWVbMV0sdH0scy5mcm9tVmFsdWVzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9bmV3IG4oMik7cmV0dXJuIHJbMF09ZSxyWzFdPXQscn0scy5jb3B5PWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF09dFswXSxlWzFdPXRbMV0sZX0scy5zZXQ9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXQsZVsxXT1uLGV9LHMuYWRkPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZVswXT10WzBdK25bMF0sZVsxXT10WzFdK25bMV0sZX0scy5zdWJ0cmFjdD1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXS1uWzBdLGVbMV09dFsxXS1uWzFdLGV9LHMuc3ViPXMuc3VidHJhY3Qscy5tdWx0aXBseT1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXSpuWzBdLGVbMV09dFsxXSpuWzFdLGV9LHMubXVsPXMubXVsdGlwbHkscy5kaXZpZGU9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXRbMF0vblswXSxlWzFdPXRbMV0vblsxXSxlfSxzLmRpdj1zLmRpdmlkZSxzLm1pbj1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09TWF0aC5taW4odFswXSxuWzBdKSxlWzFdPU1hdGgubWluKHRbMV0sblsxXSksZX0scy5tYXg9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPU1hdGgubWF4KHRbMF0sblswXSksZVsxXT1NYXRoLm1heCh0WzFdLG5bMV0pLGV9LHMuc2NhbGU9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXRbMF0qbixlWzFdPXRbMV0qbixlfSxzLnNjYWxlQW5kQWRkPWZ1bmN0aW9uKGUsdCxuLHIpe3JldHVybiBlWzBdPXRbMF0rblswXSpyLGVbMV09dFsxXStuWzFdKnIsZX0scy5kaXN0YW5jZT1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0tZVswXSxyPXRbMV0tZVsxXTtyZXR1cm4gTWF0aC5zcXJ0KG4qbityKnIpfSxzLmRpc3Q9cy5kaXN0YW5jZSxzLnNxdWFyZWREaXN0YW5jZT1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0tZVswXSxyPXRbMV0tZVsxXTtyZXR1cm4gbipuK3Iqcn0scy5zcXJEaXN0PXMuc3F1YXJlZERpc3RhbmNlLHMubGVuZ3RoPWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdO3JldHVybiBNYXRoLnNxcnQodCp0K24qbil9LHMubGVuPXMubGVuZ3RoLHMuc3F1YXJlZExlbmd0aD1mdW5jdGlvbihlKXt2YXIgdD1lWzBdLG49ZVsxXTtyZXR1cm4gdCp0K24qbn0scy5zcXJMZW49cy5zcXVhcmVkTGVuZ3RoLHMubmVnYXRlPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF09LXRbMF0sZVsxXT0tdFsxXSxlfSxzLm5vcm1hbGl6ZT1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9bipuK3IqcjtyZXR1cm4gaT4wJiYoaT0xL01hdGguc3FydChpKSxlWzBdPXRbMF0qaSxlWzFdPXRbMV0qaSksZX0scy5kb3Q9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gZVswXSp0WzBdK2VbMV0qdFsxXX0scy5jcm9zcz1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSpuWzFdLXRbMV0qblswXTtyZXR1cm4gZVswXT1lWzFdPTAsZVsyXT1yLGV9LHMubGVycD1mdW5jdGlvbihlLHQsbixyKXt2YXIgaT10WzBdLHM9dFsxXTtyZXR1cm4gZVswXT1pK3IqKG5bMF0taSksZVsxXT1zK3IqKG5bMV0tcyksZX0scy5yYW5kb209ZnVuY3Rpb24oZSx0KXt0PXR8fDE7dmFyIG49cigpKjIqTWF0aC5QSTtyZXR1cm4gZVswXT1NYXRoLmNvcyhuKSp0LGVbMV09TWF0aC5zaW4obikqdCxlfSxzLnRyYW5zZm9ybU1hdDI9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdO3JldHVybiBlWzBdPW5bMF0qcituWzJdKmksZVsxXT1uWzFdKnIrblszXSppLGV9LHMudHJhbnNmb3JtTWF0MmQ9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdO3JldHVybiBlWzBdPW5bMF0qcituWzJdKmkrbls0XSxlWzFdPW5bMV0qcituWzNdKmkrbls1XSxlfSxzLnRyYW5zZm9ybU1hdDM9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdO3JldHVybiBlWzBdPW5bMF0qcituWzNdKmkrbls2XSxlWzFdPW5bMV0qcituWzRdKmkrbls3XSxlfSxzLnRyYW5zZm9ybU1hdDQ9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdO3JldHVybiBlWzBdPW5bMF0qcituWzRdKmkrblsxMl0sZVsxXT1uWzFdKnIrbls1XSppK25bMTNdLGV9LHMuZm9yRWFjaD1mdW5jdGlvbigpe3ZhciBlPXMuY3JlYXRlKCk7cmV0dXJuIGZ1bmN0aW9uKHQsbixyLGkscyxvKXt2YXIgdSxhO258fChuPTIpLHJ8fChyPTApLGk/YT1NYXRoLm1pbihpKm4rcix0Lmxlbmd0aCk6YT10Lmxlbmd0aDtmb3IodT1yO3U8YTt1Kz1uKWVbMF09dFt1XSxlWzFdPXRbdSsxXSxzKGUsZSxvKSx0W3VdPWVbMF0sdFt1KzFdPWVbMV07cmV0dXJuIHR9fSgpLHMuc3RyPWZ1bmN0aW9uKGUpe3JldHVyblwidmVjMihcIitlWzBdK1wiLCBcIitlWzFdK1wiKVwifSx0eXBlb2YgZSE9XCJ1bmRlZmluZWRcIiYmKGUudmVjMj1zKTt2YXIgbz17fTtvLmNyZWF0ZT1mdW5jdGlvbigpe3ZhciBlPW5ldyBuKDMpO3JldHVybiBlWzBdPTAsZVsxXT0wLGVbMl09MCxlfSxvLmNsb25lPWZ1bmN0aW9uKGUpe3ZhciB0PW5ldyBuKDMpO3JldHVybiB0WzBdPWVbMF0sdFsxXT1lWzFdLHRbMl09ZVsyXSx0fSxvLmZyb21WYWx1ZXM9ZnVuY3Rpb24oZSx0LHIpe3ZhciBpPW5ldyBuKDMpO3JldHVybiBpWzBdPWUsaVsxXT10LGlbMl09cixpfSxvLmNvcHk9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gZVswXT10WzBdLGVbMV09dFsxXSxlWzJdPXRbMl0sZX0sby5zZXQ9ZnVuY3Rpb24oZSx0LG4scil7cmV0dXJuIGVbMF09dCxlWzFdPW4sZVsyXT1yLGV9LG8uYWRkPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZVswXT10WzBdK25bMF0sZVsxXT10WzFdK25bMV0sZVsyXT10WzJdK25bMl0sZX0sby5zdWJ0cmFjdD1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXS1uWzBdLGVbMV09dFsxXS1uWzFdLGVbMl09dFsyXS1uWzJdLGV9LG8uc3ViPW8uc3VidHJhY3Qsby5tdWx0aXBseT1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXSpuWzBdLGVbMV09dFsxXSpuWzFdLGVbMl09dFsyXSpuWzJdLGV9LG8ubXVsPW8ubXVsdGlwbHksby5kaXZpZGU9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXRbMF0vblswXSxlWzFdPXRbMV0vblsxXSxlWzJdPXRbMl0vblsyXSxlfSxvLmRpdj1vLmRpdmlkZSxvLm1pbj1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09TWF0aC5taW4odFswXSxuWzBdKSxlWzFdPU1hdGgubWluKHRbMV0sblsxXSksZVsyXT1NYXRoLm1pbih0WzJdLG5bMl0pLGV9LG8ubWF4PWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZVswXT1NYXRoLm1heCh0WzBdLG5bMF0pLGVbMV09TWF0aC5tYXgodFsxXSxuWzFdKSxlWzJdPU1hdGgubWF4KHRbMl0sblsyXSksZX0sby5zY2FsZT1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXSpuLGVbMV09dFsxXSpuLGVbMl09dFsyXSpuLGV9LG8uc2NhbGVBbmRBZGQ9ZnVuY3Rpb24oZSx0LG4scil7cmV0dXJuIGVbMF09dFswXStuWzBdKnIsZVsxXT10WzFdK25bMV0qcixlWzJdPXRbMl0rblsyXSpyLGV9LG8uZGlzdGFuY2U9ZnVuY3Rpb24oZSx0KXt2YXIgbj10WzBdLWVbMF0scj10WzFdLWVbMV0saT10WzJdLWVbMl07cmV0dXJuIE1hdGguc3FydChuKm4rcipyK2kqaSl9LG8uZGlzdD1vLmRpc3RhbmNlLG8uc3F1YXJlZERpc3RhbmNlPWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXS1lWzBdLHI9dFsxXS1lWzFdLGk9dFsyXS1lWzJdO3JldHVybiBuKm4rcipyK2kqaX0sby5zcXJEaXN0PW8uc3F1YXJlZERpc3RhbmNlLG8ubGVuZ3RoPWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdLHI9ZVsyXTtyZXR1cm4gTWF0aC5zcXJ0KHQqdCtuKm4rcipyKX0sby5sZW49by5sZW5ndGgsby5zcXVhcmVkTGVuZ3RoPWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdLHI9ZVsyXTtyZXR1cm4gdCp0K24qbityKnJ9LG8uc3FyTGVuPW8uc3F1YXJlZExlbmd0aCxvLm5lZ2F0ZT1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdPS10WzBdLGVbMV09LXRbMV0sZVsyXT0tdFsyXSxlfSxvLm5vcm1hbGl6ZT1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPW4qbityKnIraSppO3JldHVybiBzPjAmJihzPTEvTWF0aC5zcXJ0KHMpLGVbMF09dFswXSpzLGVbMV09dFsxXSpzLGVbMl09dFsyXSpzKSxlfSxvLmRvdD1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdKnRbMF0rZVsxXSp0WzFdK2VbMl0qdFsyXX0sby5jcm9zcz1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89blswXSx1PW5bMV0sYT1uWzJdO3JldHVybiBlWzBdPWkqYS1zKnUsZVsxXT1zKm8tciphLGVbMl09cip1LWkqbyxlfSxvLmxlcnA9ZnVuY3Rpb24oZSx0LG4scil7dmFyIGk9dFswXSxzPXRbMV0sbz10WzJdO3JldHVybiBlWzBdPWkrciooblswXS1pKSxlWzFdPXMrciooblsxXS1zKSxlWzJdPW8rciooblsyXS1vKSxlfSxvLnJhbmRvbT1mdW5jdGlvbihlLHQpe3Q9dHx8MTt2YXIgbj1yKCkqMipNYXRoLlBJLGk9cigpKjItMSxzPU1hdGguc3FydCgxLWkqaSkqdDtyZXR1cm4gZVswXT1NYXRoLmNvcyhuKSpzLGVbMV09TWF0aC5zaW4obikqcyxlWzJdPWkqdCxlfSxvLnRyYW5zZm9ybU1hdDQ9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdLHM9dFsyXTtyZXR1cm4gZVswXT1uWzBdKnIrbls0XSppK25bOF0qcytuWzEyXSxlWzFdPW5bMV0qcituWzVdKmkrbls5XSpzK25bMTNdLGVbMl09blsyXSpyK25bNl0qaStuWzEwXSpzK25bMTRdLGV9LG8udHJhbnNmb3JtTWF0Mz1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdO3JldHVybiBlWzBdPXIqblswXStpKm5bM10rcypuWzZdLGVbMV09cipuWzFdK2kqbls0XStzKm5bN10sZVsyXT1yKm5bMl0raSpuWzVdK3Mqbls4XSxlfSxvLnRyYW5zZm9ybVF1YXQ9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdLHM9dFsyXSxvPW5bMF0sdT1uWzFdLGE9blsyXSxmPW5bM10sbD1mKnIrdSpzLWEqaSxjPWYqaSthKnItbypzLGg9ZipzK28qaS11KnIscD0tbypyLXUqaS1hKnM7cmV0dXJuIGVbMF09bCpmK3AqLW8rYyotYS1oKi11LGVbMV09YypmK3AqLXUraCotby1sKi1hLGVbMl09aCpmK3AqLWErbCotdS1jKi1vLGV9LG8uZm9yRWFjaD1mdW5jdGlvbigpe3ZhciBlPW8uY3JlYXRlKCk7cmV0dXJuIGZ1bmN0aW9uKHQsbixyLGkscyxvKXt2YXIgdSxhO258fChuPTMpLHJ8fChyPTApLGk/YT1NYXRoLm1pbihpKm4rcix0Lmxlbmd0aCk6YT10Lmxlbmd0aDtmb3IodT1yO3U8YTt1Kz1uKWVbMF09dFt1XSxlWzFdPXRbdSsxXSxlWzJdPXRbdSsyXSxzKGUsZSxvKSx0W3VdPWVbMF0sdFt1KzFdPWVbMV0sdFt1KzJdPWVbMl07cmV0dXJuIHR9fSgpLG8uc3RyPWZ1bmN0aW9uKGUpe3JldHVyblwidmVjMyhcIitlWzBdK1wiLCBcIitlWzFdK1wiLCBcIitlWzJdK1wiKVwifSx0eXBlb2YgZSE9XCJ1bmRlZmluZWRcIiYmKGUudmVjMz1vKTt2YXIgdT17fTt1LmNyZWF0ZT1mdW5jdGlvbigpe3ZhciBlPW5ldyBuKDQpO3JldHVybiBlWzBdPTAsZVsxXT0wLGVbMl09MCxlWzNdPTAsZX0sdS5jbG9uZT1mdW5jdGlvbihlKXt2YXIgdD1uZXcgbig0KTtyZXR1cm4gdFswXT1lWzBdLHRbMV09ZVsxXSx0WzJdPWVbMl0sdFszXT1lWzNdLHR9LHUuZnJvbVZhbHVlcz1mdW5jdGlvbihlLHQscixpKXt2YXIgcz1uZXcgbig0KTtyZXR1cm4gc1swXT1lLHNbMV09dCxzWzJdPXIsc1szXT1pLHN9LHUuY29weT1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdPXRbMF0sZVsxXT10WzFdLGVbMl09dFsyXSxlWzNdPXRbM10sZX0sdS5zZXQ9ZnVuY3Rpb24oZSx0LG4scixpKXtyZXR1cm4gZVswXT10LGVbMV09bixlWzJdPXIsZVszXT1pLGV9LHUuYWRkPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZVswXT10WzBdK25bMF0sZVsxXT10WzFdK25bMV0sZVsyXT10WzJdK25bMl0sZVszXT10WzNdK25bM10sZX0sdS5zdWJ0cmFjdD1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXS1uWzBdLGVbMV09dFsxXS1uWzFdLGVbMl09dFsyXS1uWzJdLGVbM109dFszXS1uWzNdLGV9LHUuc3ViPXUuc3VidHJhY3QsdS5tdWx0aXBseT1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09dFswXSpuWzBdLGVbMV09dFsxXSpuWzFdLGVbMl09dFsyXSpuWzJdLGVbM109dFszXSpuWzNdLGV9LHUubXVsPXUubXVsdGlwbHksdS5kaXZpZGU9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXRbMF0vblswXSxlWzFdPXRbMV0vblsxXSxlWzJdPXRbMl0vblsyXSxlWzNdPXRbM10vblszXSxlfSx1LmRpdj11LmRpdmlkZSx1Lm1pbj1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09TWF0aC5taW4odFswXSxuWzBdKSxlWzFdPU1hdGgubWluKHRbMV0sblsxXSksZVsyXT1NYXRoLm1pbih0WzJdLG5bMl0pLGVbM109TWF0aC5taW4odFszXSxuWzNdKSxlfSx1Lm1heD1mdW5jdGlvbihlLHQsbil7cmV0dXJuIGVbMF09TWF0aC5tYXgodFswXSxuWzBdKSxlWzFdPU1hdGgubWF4KHRbMV0sblsxXSksZVsyXT1NYXRoLm1heCh0WzJdLG5bMl0pLGVbM109TWF0aC5tYXgodFszXSxuWzNdKSxlfSx1LnNjYWxlPWZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gZVswXT10WzBdKm4sZVsxXT10WzFdKm4sZVsyXT10WzJdKm4sZVszXT10WzNdKm4sZX0sdS5zY2FsZUFuZEFkZD1mdW5jdGlvbihlLHQsbixyKXtyZXR1cm4gZVswXT10WzBdK25bMF0qcixlWzFdPXRbMV0rblsxXSpyLGVbMl09dFsyXStuWzJdKnIsZVszXT10WzNdK25bM10qcixlfSx1LmRpc3RhbmNlPWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXS1lWzBdLHI9dFsxXS1lWzFdLGk9dFsyXS1lWzJdLHM9dFszXS1lWzNdO3JldHVybiBNYXRoLnNxcnQobipuK3IqcitpKmkrcypzKX0sdS5kaXN0PXUuZGlzdGFuY2UsdS5zcXVhcmVkRGlzdGFuY2U9ZnVuY3Rpb24oZSx0KXt2YXIgbj10WzBdLWVbMF0scj10WzFdLWVbMV0saT10WzJdLWVbMl0scz10WzNdLWVbM107cmV0dXJuIG4qbityKnIraSppK3Mqc30sdS5zcXJEaXN0PXUuc3F1YXJlZERpc3RhbmNlLHUubGVuZ3RoPWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdLHI9ZVsyXSxpPWVbM107cmV0dXJuIE1hdGguc3FydCh0KnQrbipuK3IqcitpKmkpfSx1Lmxlbj11Lmxlbmd0aCx1LnNxdWFyZWRMZW5ndGg9ZnVuY3Rpb24oZSl7dmFyIHQ9ZVswXSxuPWVbMV0scj1lWzJdLGk9ZVszXTtyZXR1cm4gdCp0K24qbityKnIraSppfSx1LnNxckxlbj11LnNxdWFyZWRMZW5ndGgsdS5uZWdhdGU9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gZVswXT0tdFswXSxlWzFdPS10WzFdLGVbMl09LXRbMl0sZVszXT0tdFszXSxlfSx1Lm5vcm1hbGl6ZT1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPXRbM10sbz1uKm4rcipyK2kqaStzKnM7cmV0dXJuIG8+MCYmKG89MS9NYXRoLnNxcnQobyksZVswXT10WzBdKm8sZVsxXT10WzFdKm8sZVsyXT10WzJdKm8sZVszXT10WzNdKm8pLGV9LHUuZG90PWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF0qdFswXStlWzFdKnRbMV0rZVsyXSp0WzJdK2VbM10qdFszXX0sdS5sZXJwPWZ1bmN0aW9uKGUsdCxuLHIpe3ZhciBpPXRbMF0scz10WzFdLG89dFsyXSx1PXRbM107cmV0dXJuIGVbMF09aStyKihuWzBdLWkpLGVbMV09cytyKihuWzFdLXMpLGVbMl09bytyKihuWzJdLW8pLGVbM109dStyKihuWzNdLXUpLGV9LHUucmFuZG9tPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIHQ9dHx8MSxlWzBdPXIoKSxlWzFdPXIoKSxlWzJdPXIoKSxlWzNdPXIoKSx1Lm5vcm1hbGl6ZShlLGUpLHUuc2NhbGUoZSxlLHQpLGV9LHUudHJhbnNmb3JtTWF0ND1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXTtyZXR1cm4gZVswXT1uWzBdKnIrbls0XSppK25bOF0qcytuWzEyXSpvLGVbMV09blsxXSpyK25bNV0qaStuWzldKnMrblsxM10qbyxlWzJdPW5bMl0qcituWzZdKmkrblsxMF0qcytuWzE0XSpvLGVbM109blszXSpyK25bN10qaStuWzExXSpzK25bMTVdKm8sZX0sdS50cmFuc2Zvcm1RdWF0PWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz1uWzBdLHU9blsxXSxhPW5bMl0sZj1uWzNdLGw9ZipyK3Uqcy1hKmksYz1mKmkrYSpyLW8qcyxoPWYqcytvKmktdSpyLHA9LW8qci11KmktYSpzO3JldHVybiBlWzBdPWwqZitwKi1vK2MqLWEtaCotdSxlWzFdPWMqZitwKi11K2gqLW8tbCotYSxlWzJdPWgqZitwKi1hK2wqLXUtYyotbyxlfSx1LmZvckVhY2g9ZnVuY3Rpb24oKXt2YXIgZT11LmNyZWF0ZSgpO3JldHVybiBmdW5jdGlvbih0LG4scixpLHMsbyl7dmFyIHUsYTtufHwobj00KSxyfHwocj0wKSxpP2E9TWF0aC5taW4oaSpuK3IsdC5sZW5ndGgpOmE9dC5sZW5ndGg7Zm9yKHU9cjt1PGE7dSs9billWzBdPXRbdV0sZVsxXT10W3UrMV0sZVsyXT10W3UrMl0sZVszXT10W3UrM10scyhlLGUsbyksdFt1XT1lWzBdLHRbdSsxXT1lWzFdLHRbdSsyXT1lWzJdLHRbdSszXT1lWzNdO3JldHVybiB0fX0oKSx1LnN0cj1mdW5jdGlvbihlKXtyZXR1cm5cInZlYzQoXCIrZVswXStcIiwgXCIrZVsxXStcIiwgXCIrZVsyXStcIiwgXCIrZVszXStcIilcIn0sdHlwZW9mIGUhPVwidW5kZWZpbmVkXCImJihlLnZlYzQ9dSk7dmFyIGE9e307YS5jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgZT1uZXcgbig0KTtyZXR1cm4gZVswXT0xLGVbMV09MCxlWzJdPTAsZVszXT0xLGV9LGEuY2xvbmU9ZnVuY3Rpb24oZSl7dmFyIHQ9bmV3IG4oNCk7cmV0dXJuIHRbMF09ZVswXSx0WzFdPWVbMV0sdFsyXT1lWzJdLHRbM109ZVszXSx0fSxhLmNvcHk9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gZVswXT10WzBdLGVbMV09dFsxXSxlWzJdPXRbMl0sZVszXT10WzNdLGV9LGEuaWRlbnRpdHk9ZnVuY3Rpb24oZSl7cmV0dXJuIGVbMF09MSxlWzFdPTAsZVsyXT0wLGVbM109MSxlfSxhLnRyYW5zcG9zZT1mdW5jdGlvbihlLHQpe2lmKGU9PT10KXt2YXIgbj10WzFdO2VbMV09dFsyXSxlWzJdPW59ZWxzZSBlWzBdPXRbMF0sZVsxXT10WzJdLGVbMl09dFsxXSxlWzNdPXRbM107cmV0dXJuIGV9LGEuaW52ZXJ0PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXSxyPXRbMV0saT10WzJdLHM9dFszXSxvPW4qcy1pKnI7cmV0dXJuIG8/KG89MS9vLGVbMF09cypvLGVbMV09LXIqbyxlWzJdPS1pKm8sZVszXT1uKm8sZSk6bnVsbH0sYS5hZGpvaW50PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXTtyZXR1cm4gZVswXT10WzNdLGVbMV09LXRbMV0sZVsyXT0tdFsyXSxlWzNdPW4sZX0sYS5kZXRlcm1pbmFudD1mdW5jdGlvbihlKXtyZXR1cm4gZVswXSplWzNdLWVbMl0qZVsxXX0sYS5tdWx0aXBseT1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PW5bMF0sYT1uWzFdLGY9blsyXSxsPW5bM107cmV0dXJuIGVbMF09cip1K2kqZixlWzFdPXIqYStpKmwsZVsyXT1zKnUrbypmLGVbM109cyphK28qbCxlfSxhLm11bD1hLm11bHRpcGx5LGEucm90YXRlPWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz10WzNdLHU9TWF0aC5zaW4obiksYT1NYXRoLmNvcyhuKTtyZXR1cm4gZVswXT1yKmEraSp1LGVbMV09ciotdStpKmEsZVsyXT1zKmErbyp1LGVbM109cyotdStvKmEsZX0sYS5zY2FsZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PW5bMF0sYT1uWzFdO3JldHVybiBlWzBdPXIqdSxlWzFdPWkqYSxlWzJdPXMqdSxlWzNdPW8qYSxlfSxhLnN0cj1mdW5jdGlvbihlKXtyZXR1cm5cIm1hdDIoXCIrZVswXStcIiwgXCIrZVsxXStcIiwgXCIrZVsyXStcIiwgXCIrZVszXStcIilcIn0sdHlwZW9mIGUhPVwidW5kZWZpbmVkXCImJihlLm1hdDI9YSk7dmFyIGY9e307Zi5jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgZT1uZXcgbig2KTtyZXR1cm4gZVswXT0xLGVbMV09MCxlWzJdPTAsZVszXT0xLGVbNF09MCxlWzVdPTAsZX0sZi5jbG9uZT1mdW5jdGlvbihlKXt2YXIgdD1uZXcgbig2KTtyZXR1cm4gdFswXT1lWzBdLHRbMV09ZVsxXSx0WzJdPWVbMl0sdFszXT1lWzNdLHRbNF09ZVs0XSx0WzVdPWVbNV0sdH0sZi5jb3B5PWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF09dFswXSxlWzFdPXRbMV0sZVsyXT10WzJdLGVbM109dFszXSxlWzRdPXRbNF0sZVs1XT10WzVdLGV9LGYuaWRlbnRpdHk9ZnVuY3Rpb24oZSl7cmV0dXJuIGVbMF09MSxlWzFdPTAsZVsyXT0wLGVbM109MSxlWzRdPTAsZVs1XT0wLGV9LGYuaW52ZXJ0PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXSxyPXRbMV0saT10WzJdLHM9dFszXSxvPXRbNF0sdT10WzVdLGE9bipzLXIqaTtyZXR1cm4gYT8oYT0xL2EsZVswXT1zKmEsZVsxXT0tciphLGVbMl09LWkqYSxlWzNdPW4qYSxlWzRdPShpKnUtcypvKSphLGVbNV09KHIqby1uKnUpKmEsZSk6bnVsbH0sZi5kZXRlcm1pbmFudD1mdW5jdGlvbihlKXtyZXR1cm4gZVswXSplWzNdLWVbMV0qZVsyXX0sZi5tdWx0aXBseT1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PXRbNF0sYT10WzVdLGY9blswXSxsPW5bMV0sYz1uWzJdLGg9blszXSxwPW5bNF0sZD1uWzVdO3JldHVybiBlWzBdPXIqZitpKmMsZVsxXT1yKmwraSpoLGVbMl09cypmK28qYyxlWzNdPXMqbCtvKmgsZVs0XT1mKnUrYyphK3AsZVs1XT1sKnUraCphK2QsZX0sZi5tdWw9Zi5tdWx0aXBseSxmLnJvdGF0ZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PXRbNF0sYT10WzVdLGY9TWF0aC5zaW4obiksbD1NYXRoLmNvcyhuKTtyZXR1cm4gZVswXT1yKmwraSpmLGVbMV09LXIqZitpKmwsZVsyXT1zKmwrbypmLGVbM109LXMqZitsKm8sZVs0XT1sKnUrZiphLGVbNV09bCphLWYqdSxlfSxmLnNjYWxlPWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1uWzBdLGk9blsxXTtyZXR1cm4gZVswXT10WzBdKnIsZVsxXT10WzFdKmksZVsyXT10WzJdKnIsZVszXT10WzNdKmksZVs0XT10WzRdKnIsZVs1XT10WzVdKmksZX0sZi50cmFuc2xhdGU9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBlWzBdPXRbMF0sZVsxXT10WzFdLGVbMl09dFsyXSxlWzNdPXRbM10sZVs0XT10WzRdK25bMF0sZVs1XT10WzVdK25bMV0sZX0sZi5zdHI9ZnVuY3Rpb24oZSl7cmV0dXJuXCJtYXQyZChcIitlWzBdK1wiLCBcIitlWzFdK1wiLCBcIitlWzJdK1wiLCBcIitlWzNdK1wiLCBcIitlWzRdK1wiLCBcIitlWzVdK1wiKVwifSx0eXBlb2YgZSE9XCJ1bmRlZmluZWRcIiYmKGUubWF0MmQ9Zik7dmFyIGw9e307bC5jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgZT1uZXcgbig5KTtyZXR1cm4gZVswXT0xLGVbMV09MCxlWzJdPTAsZVszXT0wLGVbNF09MSxlWzVdPTAsZVs2XT0wLGVbN109MCxlWzhdPTEsZX0sbC5mcm9tTWF0ND1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdPXRbMF0sZVsxXT10WzFdLGVbMl09dFsyXSxlWzNdPXRbNF0sZVs0XT10WzVdLGVbNV09dFs2XSxlWzZdPXRbOF0sZVs3XT10WzldLGVbOF09dFsxMF0sZX0sbC5jbG9uZT1mdW5jdGlvbihlKXt2YXIgdD1uZXcgbig5KTtyZXR1cm4gdFswXT1lWzBdLHRbMV09ZVsxXSx0WzJdPWVbMl0sdFszXT1lWzNdLHRbNF09ZVs0XSx0WzVdPWVbNV0sdFs2XT1lWzZdLHRbN109ZVs3XSx0WzhdPWVbOF0sdH0sbC5jb3B5PWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF09dFswXSxlWzFdPXRbMV0sZVsyXT10WzJdLGVbM109dFszXSxlWzRdPXRbNF0sZVs1XT10WzVdLGVbNl09dFs2XSxlWzddPXRbN10sZVs4XT10WzhdLGV9LGwuaWRlbnRpdHk9ZnVuY3Rpb24oZSl7cmV0dXJuIGVbMF09MSxlWzFdPTAsZVsyXT0wLGVbM109MCxlWzRdPTEsZVs1XT0wLGVbNl09MCxlWzddPTAsZVs4XT0xLGV9LGwudHJhbnNwb3NlPWZ1bmN0aW9uKGUsdCl7aWYoZT09PXQpe3ZhciBuPXRbMV0scj10WzJdLGk9dFs1XTtlWzFdPXRbM10sZVsyXT10WzZdLGVbM109bixlWzVdPXRbN10sZVs2XT1yLGVbN109aX1lbHNlIGVbMF09dFswXSxlWzFdPXRbM10sZVsyXT10WzZdLGVbM109dFsxXSxlWzRdPXRbNF0sZVs1XT10WzddLGVbNl09dFsyXSxlWzddPXRbNV0sZVs4XT10WzhdO3JldHVybiBlfSxsLmludmVydD1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPXRbM10sbz10WzRdLHU9dFs1XSxhPXRbNl0sZj10WzddLGw9dFs4XSxjPWwqby11KmYsaD0tbCpzK3UqYSxwPWYqcy1vKmEsZD1uKmMrcipoK2kqcDtyZXR1cm4gZD8oZD0xL2QsZVswXT1jKmQsZVsxXT0oLWwqcitpKmYpKmQsZVsyXT0odSpyLWkqbykqZCxlWzNdPWgqZCxlWzRdPShsKm4taSphKSpkLGVbNV09KC11Km4raSpzKSpkLGVbNl09cCpkLGVbN109KC1mKm4rciphKSpkLGVbOF09KG8qbi1yKnMpKmQsZSk6bnVsbH0sbC5hZGpvaW50PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXSxyPXRbMV0saT10WzJdLHM9dFszXSxvPXRbNF0sdT10WzVdLGE9dFs2XSxmPXRbN10sbD10WzhdO3JldHVybiBlWzBdPW8qbC11KmYsZVsxXT1pKmYtcipsLGVbMl09cip1LWkqbyxlWzNdPXUqYS1zKmwsZVs0XT1uKmwtaSphLGVbNV09aSpzLW4qdSxlWzZdPXMqZi1vKmEsZVs3XT1yKmEtbipmLGVbOF09bipvLXIqcyxlfSxsLmRldGVybWluYW50PWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdLHI9ZVsyXSxpPWVbM10scz1lWzRdLG89ZVs1XSx1PWVbNl0sYT1lWzddLGY9ZVs4XTtyZXR1cm4gdCooZipzLW8qYSkrbiooLWYqaStvKnUpK3IqKGEqaS1zKnUpfSxsLm11bHRpcGx5PWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz10WzNdLHU9dFs0XSxhPXRbNV0sZj10WzZdLGw9dFs3XSxjPXRbOF0saD1uWzBdLHA9blsxXSxkPW5bMl0sdj1uWzNdLG09bls0XSxnPW5bNV0seT1uWzZdLGI9bls3XSx3PW5bOF07cmV0dXJuIGVbMF09aCpyK3AqbytkKmYsZVsxXT1oKmkrcCp1K2QqbCxlWzJdPWgqcytwKmErZCpjLGVbM109dipyK20qbytnKmYsZVs0XT12KmkrbSp1K2cqbCxlWzVdPXYqcyttKmErZypjLGVbNl09eSpyK2Iqbyt3KmYsZVs3XT15KmkrYip1K3cqbCxlWzhdPXkqcytiKmErdypjLGV9LGwubXVsPWwubXVsdGlwbHksbC50cmFuc2xhdGU9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdLHM9dFsyXSxvPXRbM10sdT10WzRdLGE9dFs1XSxmPXRbNl0sbD10WzddLGM9dFs4XSxoPW5bMF0scD1uWzFdO3JldHVybiBlWzBdPXIsZVsxXT1pLGVbMl09cyxlWzNdPW8sZVs0XT11LGVbNV09YSxlWzZdPWgqcitwKm8rZixlWzddPWgqaStwKnUrbCxlWzhdPWgqcytwKmErYyxlfSxsLnJvdGF0ZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PXRbNF0sYT10WzVdLGY9dFs2XSxsPXRbN10sYz10WzhdLGg9TWF0aC5zaW4obikscD1NYXRoLmNvcyhuKTtyZXR1cm4gZVswXT1wKnIraCpvLGVbMV09cCppK2gqdSxlWzJdPXAqcytoKmEsZVszXT1wKm8taCpyLGVbNF09cCp1LWgqaSxlWzVdPXAqYS1oKnMsZVs2XT1mLGVbN109bCxlWzhdPWMsZX0sbC5zY2FsZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9blswXSxpPW5bMV07cmV0dXJuIGVbMF09cip0WzBdLGVbMV09cip0WzFdLGVbMl09cip0WzJdLGVbM109aSp0WzNdLGVbNF09aSp0WzRdLGVbNV09aSp0WzVdLGVbNl09dFs2XSxlWzddPXRbN10sZVs4XT10WzhdLGV9LGwuZnJvbU1hdDJkPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGVbMF09dFswXSxlWzFdPXRbMV0sZVsyXT0wLGVbM109dFsyXSxlWzRdPXRbM10sZVs1XT0wLGVbNl09dFs0XSxlWzddPXRbNV0sZVs4XT0xLGV9LGwuZnJvbVF1YXQ9ZnVuY3Rpb24oZSx0KXt2YXIgbj10WzBdLHI9dFsxXSxpPXRbMl0scz10WzNdLG89bituLHU9cityLGE9aStpLGY9bipvLGw9bip1LGM9biphLGg9cip1LHA9ciphLGQ9aSphLHY9cypvLG09cyp1LGc9cyphO3JldHVybiBlWzBdPTEtKGgrZCksZVszXT1sK2csZVs2XT1jLW0sZVsxXT1sLWcsZVs0XT0xLShmK2QpLGVbN109cCt2LGVbMl09YyttLGVbNV09cC12LGVbOF09MS0oZitoKSxlfSxsLm5vcm1hbEZyb21NYXQ0PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXSxyPXRbMV0saT10WzJdLHM9dFszXSxvPXRbNF0sdT10WzVdLGE9dFs2XSxmPXRbN10sbD10WzhdLGM9dFs5XSxoPXRbMTBdLHA9dFsxMV0sZD10WzEyXSx2PXRbMTNdLG09dFsxNF0sZz10WzE1XSx5PW4qdS1yKm8sYj1uKmEtaSpvLHc9bipmLXMqbyxFPXIqYS1pKnUsUz1yKmYtcyp1LHg9aSpmLXMqYSxUPWwqdi1jKmQsTj1sKm0taCpkLEM9bCpnLXAqZCxrPWMqbS1oKnYsTD1jKmctcCp2LEE9aCpnLXAqbSxPPXkqQS1iKkwrdyprK0UqQy1TKk4reCpUO3JldHVybiBPPyhPPTEvTyxlWzBdPSh1KkEtYSpMK2YqaykqTyxlWzFdPShhKkMtbypBLWYqTikqTyxlWzJdPShvKkwtdSpDK2YqVCkqTyxlWzNdPShpKkwtcipBLXMqaykqTyxlWzRdPShuKkEtaSpDK3MqTikqTyxlWzVdPShyKkMtbipMLXMqVCkqTyxlWzZdPSh2KngtbSpTK2cqRSkqTyxlWzddPShtKnctZCp4LWcqYikqTyxlWzhdPShkKlMtdip3K2cqeSkqTyxlKTpudWxsfSxsLnN0cj1mdW5jdGlvbihlKXtyZXR1cm5cIm1hdDMoXCIrZVswXStcIiwgXCIrZVsxXStcIiwgXCIrZVsyXStcIiwgXCIrZVszXStcIiwgXCIrZVs0XStcIiwgXCIrZVs1XStcIiwgXCIrZVs2XStcIiwgXCIrZVs3XStcIiwgXCIrZVs4XStcIilcIn0sdHlwZW9mIGUhPVwidW5kZWZpbmVkXCImJihlLm1hdDM9bCk7dmFyIGM9e307Yy5jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgZT1uZXcgbigxNik7cmV0dXJuIGVbMF09MSxlWzFdPTAsZVsyXT0wLGVbM109MCxlWzRdPTAsZVs1XT0xLGVbNl09MCxlWzddPTAsZVs4XT0wLGVbOV09MCxlWzEwXT0xLGVbMTFdPTAsZVsxMl09MCxlWzEzXT0wLGVbMTRdPTAsZVsxNV09MSxlfSxjLmNsb25lPWZ1bmN0aW9uKGUpe3ZhciB0PW5ldyBuKDE2KTtyZXR1cm4gdFswXT1lWzBdLHRbMV09ZVsxXSx0WzJdPWVbMl0sdFszXT1lWzNdLHRbNF09ZVs0XSx0WzVdPWVbNV0sdFs2XT1lWzZdLHRbN109ZVs3XSx0WzhdPWVbOF0sdFs5XT1lWzldLHRbMTBdPWVbMTBdLHRbMTFdPWVbMTFdLHRbMTJdPWVbMTJdLHRbMTNdPWVbMTNdLHRbMTRdPWVbMTRdLHRbMTVdPWVbMTVdLHR9LGMuY29weT1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdPXRbMF0sZVsxXT10WzFdLGVbMl09dFsyXSxlWzNdPXRbM10sZVs0XT10WzRdLGVbNV09dFs1XSxlWzZdPXRbNl0sZVs3XT10WzddLGVbOF09dFs4XSxlWzldPXRbOV0sZVsxMF09dFsxMF0sZVsxMV09dFsxMV0sZVsxMl09dFsxMl0sZVsxM109dFsxM10sZVsxNF09dFsxNF0sZVsxNV09dFsxNV0sZX0sYy5pZGVudGl0eT1mdW5jdGlvbihlKXtyZXR1cm4gZVswXT0xLGVbMV09MCxlWzJdPTAsZVszXT0wLGVbNF09MCxlWzVdPTEsZVs2XT0wLGVbN109MCxlWzhdPTAsZVs5XT0wLGVbMTBdPTEsZVsxMV09MCxlWzEyXT0wLGVbMTNdPTAsZVsxNF09MCxlWzE1XT0xLGV9LGMudHJhbnNwb3NlPWZ1bmN0aW9uKGUsdCl7aWYoZT09PXQpe3ZhciBuPXRbMV0scj10WzJdLGk9dFszXSxzPXRbNl0sbz10WzddLHU9dFsxMV07ZVsxXT10WzRdLGVbMl09dFs4XSxlWzNdPXRbMTJdLGVbNF09bixlWzZdPXRbOV0sZVs3XT10WzEzXSxlWzhdPXIsZVs5XT1zLGVbMTFdPXRbMTRdLGVbMTJdPWksZVsxM109byxlWzE0XT11fWVsc2UgZVswXT10WzBdLGVbMV09dFs0XSxlWzJdPXRbOF0sZVszXT10WzEyXSxlWzRdPXRbMV0sZVs1XT10WzVdLGVbNl09dFs5XSxlWzddPXRbMTNdLGVbOF09dFsyXSxlWzldPXRbNl0sZVsxMF09dFsxMF0sZVsxMV09dFsxNF0sZVsxMl09dFszXSxlWzEzXT10WzddLGVbMTRdPXRbMTFdLGVbMTVdPXRbMTVdO3JldHVybiBlfSxjLmludmVydD1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPXRbM10sbz10WzRdLHU9dFs1XSxhPXRbNl0sZj10WzddLGw9dFs4XSxjPXRbOV0saD10WzEwXSxwPXRbMTFdLGQ9dFsxMl0sdj10WzEzXSxtPXRbMTRdLGc9dFsxNV0seT1uKnUtcipvLGI9biphLWkqbyx3PW4qZi1zKm8sRT1yKmEtaSp1LFM9cipmLXMqdSx4PWkqZi1zKmEsVD1sKnYtYypkLE49bCptLWgqZCxDPWwqZy1wKmQsaz1jKm0taCp2LEw9YypnLXAqdixBPWgqZy1wKm0sTz15KkEtYipMK3cqaytFKkMtUypOK3gqVDtyZXR1cm4gTz8oTz0xL08sZVswXT0odSpBLWEqTCtmKmspKk8sZVsxXT0oaSpMLXIqQS1zKmspKk8sZVsyXT0odip4LW0qUytnKkUpKk8sZVszXT0oaCpTLWMqeC1wKkUpKk8sZVs0XT0oYSpDLW8qQS1mKk4pKk8sZVs1XT0obipBLWkqQytzKk4pKk8sZVs2XT0obSp3LWQqeC1nKmIpKk8sZVs3XT0obCp4LWgqdytwKmIpKk8sZVs4XT0obypMLXUqQytmKlQpKk8sZVs5XT0ocipDLW4qTC1zKlQpKk8sZVsxMF09KGQqUy12KncrZyp5KSpPLGVbMTFdPShjKnctbCpTLXAqeSkqTyxlWzEyXT0odSpOLW8qay1hKlQpKk8sZVsxM109KG4qay1yKk4raSpUKSpPLGVbMTRdPSh2KmItZCpFLW0qeSkqTyxlWzE1XT0obCpFLWMqYitoKnkpKk8sZSk6bnVsbH0sYy5hZGpvaW50PWZ1bmN0aW9uKGUsdCl7dmFyIG49dFswXSxyPXRbMV0saT10WzJdLHM9dFszXSxvPXRbNF0sdT10WzVdLGE9dFs2XSxmPXRbN10sbD10WzhdLGM9dFs5XSxoPXRbMTBdLHA9dFsxMV0sZD10WzEyXSx2PXRbMTNdLG09dFsxNF0sZz10WzE1XTtyZXR1cm4gZVswXT11KihoKmctcCptKS1jKihhKmctZiptKSt2KihhKnAtZipoKSxlWzFdPS0ociooaCpnLXAqbSktYyooaSpnLXMqbSkrdiooaSpwLXMqaCkpLGVbMl09ciooYSpnLWYqbSktdSooaSpnLXMqbSkrdiooaSpmLXMqYSksZVszXT0tKHIqKGEqcC1mKmgpLXUqKGkqcC1zKmgpK2MqKGkqZi1zKmEpKSxlWzRdPS0obyooaCpnLXAqbSktbCooYSpnLWYqbSkrZCooYSpwLWYqaCkpLGVbNV09biooaCpnLXAqbSktbCooaSpnLXMqbSkrZCooaSpwLXMqaCksZVs2XT0tKG4qKGEqZy1mKm0pLW8qKGkqZy1zKm0pK2QqKGkqZi1zKmEpKSxlWzddPW4qKGEqcC1mKmgpLW8qKGkqcC1zKmgpK2wqKGkqZi1zKmEpLGVbOF09byooYypnLXAqdiktbCoodSpnLWYqdikrZCoodSpwLWYqYyksZVs5XT0tKG4qKGMqZy1wKnYpLWwqKHIqZy1zKnYpK2QqKHIqcC1zKmMpKSxlWzEwXT1uKih1KmctZip2KS1vKihyKmctcyp2KStkKihyKmYtcyp1KSxlWzExXT0tKG4qKHUqcC1mKmMpLW8qKHIqcC1zKmMpK2wqKHIqZi1zKnUpKSxlWzEyXT0tKG8qKGMqbS1oKnYpLWwqKHUqbS1hKnYpK2QqKHUqaC1hKmMpKSxlWzEzXT1uKihjKm0taCp2KS1sKihyKm0taSp2KStkKihyKmgtaSpjKSxlWzE0XT0tKG4qKHUqbS1hKnYpLW8qKHIqbS1pKnYpK2QqKHIqYS1pKnUpKSxlWzE1XT1uKih1KmgtYSpjKS1vKihyKmgtaSpjKStsKihyKmEtaSp1KSxlfSxjLmRldGVybWluYW50PWZ1bmN0aW9uKGUpe3ZhciB0PWVbMF0sbj1lWzFdLHI9ZVsyXSxpPWVbM10scz1lWzRdLG89ZVs1XSx1PWVbNl0sYT1lWzddLGY9ZVs4XSxsPWVbOV0sYz1lWzEwXSxoPWVbMTFdLHA9ZVsxMl0sZD1lWzEzXSx2PWVbMTRdLG09ZVsxNV0sZz10Km8tbipzLHk9dCp1LXIqcyxiPXQqYS1pKnMsdz1uKnUtcipvLEU9biphLWkqbyxTPXIqYS1pKnUseD1mKmQtbCpwLFQ9Zip2LWMqcCxOPWYqbS1oKnAsQz1sKnYtYypkLGs9bCptLWgqZCxMPWMqbS1oKnY7cmV0dXJuIGcqTC15KmsrYipDK3cqTi1FKlQrUyp4fSxjLm11bHRpcGx5PWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz10WzNdLHU9dFs0XSxhPXRbNV0sZj10WzZdLGw9dFs3XSxjPXRbOF0saD10WzldLHA9dFsxMF0sZD10WzExXSx2PXRbMTJdLG09dFsxM10sZz10WzE0XSx5PXRbMTVdLGI9blswXSx3PW5bMV0sRT1uWzJdLFM9blszXTtyZXR1cm4gZVswXT1iKnIrdyp1K0UqYytTKnYsZVsxXT1iKmkrdyphK0UqaCtTKm0sZVsyXT1iKnMrdypmK0UqcCtTKmcsZVszXT1iKm8rdypsK0UqZCtTKnksYj1uWzRdLHc9bls1XSxFPW5bNl0sUz1uWzddLGVbNF09YipyK3cqdStFKmMrUyp2LGVbNV09YippK3cqYStFKmgrUyptLGVbNl09YipzK3cqZitFKnArUypnLGVbN109YipvK3cqbCtFKmQrUyp5LGI9bls4XSx3PW5bOV0sRT1uWzEwXSxTPW5bMTFdLGVbOF09YipyK3cqdStFKmMrUyp2LGVbOV09YippK3cqYStFKmgrUyptLGVbMTBdPWIqcyt3KmYrRSpwK1MqZyxlWzExXT1iKm8rdypsK0UqZCtTKnksYj1uWzEyXSx3PW5bMTNdLEU9blsxNF0sUz1uWzE1XSxlWzEyXT1iKnIrdyp1K0UqYytTKnYsZVsxM109YippK3cqYStFKmgrUyptLGVbMTRdPWIqcyt3KmYrRSpwK1MqZyxlWzE1XT1iKm8rdypsK0UqZCtTKnksZX0sYy5tdWw9Yy5tdWx0aXBseSxjLnRyYW5zbGF0ZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9blswXSxpPW5bMV0scz1uWzJdLG8sdSxhLGYsbCxjLGgscCxkLHYsbSxnO3JldHVybiB0PT09ZT8oZVsxMl09dFswXSpyK3RbNF0qaSt0WzhdKnMrdFsxMl0sZVsxM109dFsxXSpyK3RbNV0qaSt0WzldKnMrdFsxM10sZVsxNF09dFsyXSpyK3RbNl0qaSt0WzEwXSpzK3RbMTRdLGVbMTVdPXRbM10qcit0WzddKmkrdFsxMV0qcyt0WzE1XSk6KG89dFswXSx1PXRbMV0sYT10WzJdLGY9dFszXSxsPXRbNF0sYz10WzVdLGg9dFs2XSxwPXRbN10sZD10WzhdLHY9dFs5XSxtPXRbMTBdLGc9dFsxMV0sZVswXT1vLGVbMV09dSxlWzJdPWEsZVszXT1mLGVbNF09bCxlWzVdPWMsZVs2XT1oLGVbN109cCxlWzhdPWQsZVs5XT12LGVbMTBdPW0sZVsxMV09ZyxlWzEyXT1vKnIrbCppK2Qqcyt0WzEyXSxlWzEzXT11KnIrYyppK3Yqcyt0WzEzXSxlWzE0XT1hKnIraCppK20qcyt0WzE0XSxlWzE1XT1mKnIrcCppK2cqcyt0WzE1XSksZX0sYy5zY2FsZT1mdW5jdGlvbihlLHQsbil7dmFyIHI9blswXSxpPW5bMV0scz1uWzJdO3JldHVybiBlWzBdPXRbMF0qcixlWzFdPXRbMV0qcixlWzJdPXRbMl0qcixlWzNdPXRbM10qcixlWzRdPXRbNF0qaSxlWzVdPXRbNV0qaSxlWzZdPXRbNl0qaSxlWzddPXRbN10qaSxlWzhdPXRbOF0qcyxlWzldPXRbOV0qcyxlWzEwXT10WzEwXSpzLGVbMTFdPXRbMTFdKnMsZVsxMl09dFsxMl0sZVsxM109dFsxM10sZVsxNF09dFsxNF0sZVsxNV09dFsxNV0sZX0sYy5yb3RhdGU9ZnVuY3Rpb24oZSxuLHIsaSl7dmFyIHM9aVswXSxvPWlbMV0sdT1pWzJdLGE9TWF0aC5zcXJ0KHMqcytvKm8rdSp1KSxmLGwsYyxoLHAsZCx2LG0sZyx5LGIsdyxFLFMseCxULE4sQyxrLEwsQSxPLE0sXztyZXR1cm4gTWF0aC5hYnMoYSk8dD9udWxsOihhPTEvYSxzKj1hLG8qPWEsdSo9YSxmPU1hdGguc2luKHIpLGw9TWF0aC5jb3MociksYz0xLWwsaD1uWzBdLHA9blsxXSxkPW5bMl0sdj1uWzNdLG09bls0XSxnPW5bNV0seT1uWzZdLGI9bls3XSx3PW5bOF0sRT1uWzldLFM9blsxMF0seD1uWzExXSxUPXMqcypjK2wsTj1vKnMqYyt1KmYsQz11KnMqYy1vKmYsaz1zKm8qYy11KmYsTD1vKm8qYytsLEE9dSpvKmMrcypmLE89cyp1KmMrbypmLE09byp1KmMtcypmLF89dSp1KmMrbCxlWzBdPWgqVCttKk4rdypDLGVbMV09cCpUK2cqTitFKkMsZVsyXT1kKlQreSpOK1MqQyxlWzNdPXYqVCtiKk4reCpDLGVbNF09aCprK20qTCt3KkEsZVs1XT1wKmsrZypMK0UqQSxlWzZdPWQqayt5KkwrUypBLGVbN109diprK2IqTCt4KkEsZVs4XT1oKk8rbSpNK3cqXyxlWzldPXAqTytnKk0rRSpfLGVbMTBdPWQqTyt5Kk0rUypfLGVbMTFdPXYqTytiKk0reCpfLG4hPT1lJiYoZVsxMl09blsxMl0sZVsxM109blsxM10sZVsxNF09blsxNF0sZVsxNV09blsxNV0pLGUpfSxjLnJvdGF0ZVg9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPU1hdGguc2luKG4pLGk9TWF0aC5jb3Mobikscz10WzRdLG89dFs1XSx1PXRbNl0sYT10WzddLGY9dFs4XSxsPXRbOV0sYz10WzEwXSxoPXRbMTFdO3JldHVybiB0IT09ZSYmKGVbMF09dFswXSxlWzFdPXRbMV0sZVsyXT10WzJdLGVbM109dFszXSxlWzEyXT10WzEyXSxlWzEzXT10WzEzXSxlWzE0XT10WzE0XSxlWzE1XT10WzE1XSksZVs0XT1zKmkrZipyLGVbNV09byppK2wqcixlWzZdPXUqaStjKnIsZVs3XT1hKmkraCpyLGVbOF09ZippLXMqcixlWzldPWwqaS1vKnIsZVsxMF09YyppLXUqcixlWzExXT1oKmktYSpyLGV9LGMucm90YXRlWT1mdW5jdGlvbihlLHQsbil7dmFyIHI9TWF0aC5zaW4obiksaT1NYXRoLmNvcyhuKSxzPXRbMF0sbz10WzFdLHU9dFsyXSxhPXRbM10sZj10WzhdLGw9dFs5XSxjPXRbMTBdLGg9dFsxMV07cmV0dXJuIHQhPT1lJiYoZVs0XT10WzRdLGVbNV09dFs1XSxlWzZdPXRbNl0sZVs3XT10WzddLGVbMTJdPXRbMTJdLGVbMTNdPXRbMTNdLGVbMTRdPXRbMTRdLGVbMTVdPXRbMTVdKSxlWzBdPXMqaS1mKnIsZVsxXT1vKmktbCpyLGVbMl09dSppLWMqcixlWzNdPWEqaS1oKnIsZVs4XT1zKnIrZippLGVbOV09bypyK2wqaSxlWzEwXT11KnIrYyppLGVbMTFdPWEqcitoKmksZX0sYy5yb3RhdGVaPWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1NYXRoLnNpbihuKSxpPU1hdGguY29zKG4pLHM9dFswXSxvPXRbMV0sdT10WzJdLGE9dFszXSxmPXRbNF0sbD10WzVdLGM9dFs2XSxoPXRbN107cmV0dXJuIHQhPT1lJiYoZVs4XT10WzhdLGVbOV09dFs5XSxlWzEwXT10WzEwXSxlWzExXT10WzExXSxlWzEyXT10WzEyXSxlWzEzXT10WzEzXSxlWzE0XT10WzE0XSxlWzE1XT10WzE1XSksZVswXT1zKmkrZipyLGVbMV09byppK2wqcixlWzJdPXUqaStjKnIsZVszXT1hKmkraCpyLGVbNF09ZippLXMqcixlWzVdPWwqaS1vKnIsZVs2XT1jKmktdSpyLGVbN109aCppLWEqcixlfSxjLmZyb21Sb3RhdGlvblRyYW5zbGF0aW9uPWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz10WzNdLHU9cityLGE9aStpLGY9cytzLGw9cip1LGM9ciphLGg9cipmLHA9aSphLGQ9aSpmLHY9cypmLG09byp1LGc9byphLHk9bypmO3JldHVybiBlWzBdPTEtKHArdiksZVsxXT1jK3ksZVsyXT1oLWcsZVszXT0wLGVbNF09Yy15LGVbNV09MS0obCt2KSxlWzZdPWQrbSxlWzddPTAsZVs4XT1oK2csZVs5XT1kLW0sZVsxMF09MS0obCtwKSxlWzExXT0wLGVbMTJdPW5bMF0sZVsxM109blsxXSxlWzE0XT1uWzJdLGVbMTVdPTEsZX0sYy5mcm9tUXVhdD1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPXRbM10sbz1uK24sdT1yK3IsYT1pK2ksZj1uKm8sbD1uKnUsYz1uKmEsaD1yKnUscD1yKmEsZD1pKmEsdj1zKm8sbT1zKnUsZz1zKmE7cmV0dXJuIGVbMF09MS0oaCtkKSxlWzFdPWwrZyxlWzJdPWMtbSxlWzNdPTAsZVs0XT1sLWcsZVs1XT0xLShmK2QpLGVbNl09cCt2LGVbN109MCxlWzhdPWMrbSxlWzldPXAtdixlWzEwXT0xLShmK2gpLGVbMTFdPTAsZVsxMl09MCxlWzEzXT0wLGVbMTRdPTAsZVsxNV09MSxlfSxjLmZydXN0dW09ZnVuY3Rpb24oZSx0LG4scixpLHMsbyl7dmFyIHU9MS8obi10KSxhPTEvKGktciksZj0xLyhzLW8pO3JldHVybiBlWzBdPXMqMip1LGVbMV09MCxlWzJdPTAsZVszXT0wLGVbNF09MCxlWzVdPXMqMiphLGVbNl09MCxlWzddPTAsZVs4XT0obit0KSp1LGVbOV09KGkrcikqYSxlWzEwXT0obytzKSpmLGVbMTFdPS0xLGVbMTJdPTAsZVsxM109MCxlWzE0XT1vKnMqMipmLGVbMTVdPTAsZX0sYy5wZXJzcGVjdGl2ZT1mdW5jdGlvbihlLHQsbixyLGkpe3ZhciBzPTEvTWF0aC50YW4odC8yKSxvPTEvKHItaSk7cmV0dXJuIGVbMF09cy9uLGVbMV09MCxlWzJdPTAsZVszXT0wLGVbNF09MCxlWzVdPXMsZVs2XT0wLGVbN109MCxlWzhdPTAsZVs5XT0wLGVbMTBdPShpK3IpKm8sZVsxMV09LTEsZVsxMl09MCxlWzEzXT0wLGVbMTRdPTIqaSpyKm8sZVsxNV09MCxlfSxjLm9ydGhvPWZ1bmN0aW9uKGUsdCxuLHIsaSxzLG8pe3ZhciB1PTEvKHQtbiksYT0xLyhyLWkpLGY9MS8ocy1vKTtyZXR1cm4gZVswXT0tMip1LGVbMV09MCxlWzJdPTAsZVszXT0wLGVbNF09MCxlWzVdPS0yKmEsZVs2XT0wLGVbN109MCxlWzhdPTAsZVs5XT0wLGVbMTBdPTIqZixlWzExXT0wLGVbMTJdPSh0K24pKnUsZVsxM109KGkrcikqYSxlWzE0XT0obytzKSpmLGVbMTVdPTEsZX0sYy5sb29rQXQ9ZnVuY3Rpb24oZSxuLHIsaSl7dmFyIHMsbyx1LGEsZixsLGgscCxkLHYsbT1uWzBdLGc9blsxXSx5PW5bMl0sYj1pWzBdLHc9aVsxXSxFPWlbMl0sUz1yWzBdLHg9clsxXSxUPXJbMl07cmV0dXJuIE1hdGguYWJzKG0tUyk8dCYmTWF0aC5hYnMoZy14KTx0JiZNYXRoLmFicyh5LVQpPHQ/Yy5pZGVudGl0eShlKTooaD1tLVMscD1nLXgsZD15LVQsdj0xL01hdGguc3FydChoKmgrcCpwK2QqZCksaCo9dixwKj12LGQqPXYscz13KmQtRSpwLG89RSpoLWIqZCx1PWIqcC13Kmgsdj1NYXRoLnNxcnQocypzK28qbyt1KnUpLHY/KHY9MS92LHMqPXYsbyo9dix1Kj12KToocz0wLG89MCx1PTApLGE9cCp1LWQqbyxmPWQqcy1oKnUsbD1oKm8tcCpzLHY9TWF0aC5zcXJ0KGEqYStmKmYrbCpsKSx2Pyh2PTEvdixhKj12LGYqPXYsbCo9dik6KGE9MCxmPTAsbD0wKSxlWzBdPXMsZVsxXT1hLGVbMl09aCxlWzNdPTAsZVs0XT1vLGVbNV09ZixlWzZdPXAsZVs3XT0wLGVbOF09dSxlWzldPWwsZVsxMF09ZCxlWzExXT0wLGVbMTJdPS0ocyptK28qZyt1KnkpLGVbMTNdPS0oYSptK2YqZytsKnkpLGVbMTRdPS0oaCptK3AqZytkKnkpLGVbMTVdPTEsZSl9LGMuc3RyPWZ1bmN0aW9uKGUpe3JldHVyblwibWF0NChcIitlWzBdK1wiLCBcIitlWzFdK1wiLCBcIitlWzJdK1wiLCBcIitlWzNdK1wiLCBcIitlWzRdK1wiLCBcIitlWzVdK1wiLCBcIitlWzZdK1wiLCBcIitlWzddK1wiLCBcIitlWzhdK1wiLCBcIitlWzldK1wiLCBcIitlWzEwXStcIiwgXCIrZVsxMV0rXCIsIFwiK2VbMTJdK1wiLCBcIitlWzEzXStcIiwgXCIrZVsxNF0rXCIsIFwiK2VbMTVdK1wiKVwifSx0eXBlb2YgZSE9XCJ1bmRlZmluZWRcIiYmKGUubWF0ND1jKTt2YXIgaD17fTtoLmNyZWF0ZT1mdW5jdGlvbigpe3ZhciBlPW5ldyBuKDQpO3JldHVybiBlWzBdPTAsZVsxXT0wLGVbMl09MCxlWzNdPTEsZX0saC5yb3RhdGlvblRvPWZ1bmN0aW9uKCl7dmFyIGU9by5jcmVhdGUoKSx0PW8uZnJvbVZhbHVlcygxLDAsMCksbj1vLmZyb21WYWx1ZXMoMCwxLDApO3JldHVybiBmdW5jdGlvbihyLGkscyl7dmFyIHU9by5kb3QoaSxzKTtyZXR1cm4gdTwtMC45OTk5OTk/KG8uY3Jvc3MoZSx0LGkpLG8ubGVuZ3RoKGUpPDFlLTYmJm8uY3Jvc3MoZSxuLGkpLG8ubm9ybWFsaXplKGUsZSksaC5zZXRBeGlzQW5nbGUocixlLE1hdGguUEkpLHIpOnU+Ljk5OTk5OT8oclswXT0wLHJbMV09MCxyWzJdPTAsclszXT0xLHIpOihvLmNyb3NzKGUsaSxzKSxyWzBdPWVbMF0sclsxXT1lWzFdLHJbMl09ZVsyXSxyWzNdPTErdSxoLm5vcm1hbGl6ZShyLHIpKX19KCksaC5zZXRBeGVzPWZ1bmN0aW9uKCl7dmFyIGU9bC5jcmVhdGUoKTtyZXR1cm4gZnVuY3Rpb24odCxuLHIsaSl7cmV0dXJuIGVbMF09clswXSxlWzNdPXJbMV0sZVs2XT1yWzJdLGVbMV09aVswXSxlWzRdPWlbMV0sZVs3XT1pWzJdLGVbMl09blswXSxlWzVdPW5bMV0sZVs4XT1uWzJdLGgubm9ybWFsaXplKHQsaC5mcm9tTWF0Myh0LGUpKX19KCksaC5jbG9uZT11LmNsb25lLGguZnJvbVZhbHVlcz11LmZyb21WYWx1ZXMsaC5jb3B5PXUuY29weSxoLnNldD11LnNldCxoLmlkZW50aXR5PWZ1bmN0aW9uKGUpe3JldHVybiBlWzBdPTAsZVsxXT0wLGVbMl09MCxlWzNdPTEsZX0saC5zZXRBeGlzQW5nbGU9ZnVuY3Rpb24oZSx0LG4pe24qPS41O3ZhciByPU1hdGguc2luKG4pO3JldHVybiBlWzBdPXIqdFswXSxlWzFdPXIqdFsxXSxlWzJdPXIqdFsyXSxlWzNdPU1hdGguY29zKG4pLGV9LGguYWRkPXUuYWRkLGgubXVsdGlwbHk9ZnVuY3Rpb24oZSx0LG4pe3ZhciByPXRbMF0saT10WzFdLHM9dFsyXSxvPXRbM10sdT1uWzBdLGE9blsxXSxmPW5bMl0sbD1uWzNdO3JldHVybiBlWzBdPXIqbCtvKnUraSpmLXMqYSxlWzFdPWkqbCtvKmErcyp1LXIqZixlWzJdPXMqbCtvKmYrciphLWkqdSxlWzNdPW8qbC1yKnUtaSphLXMqZixlfSxoLm11bD1oLm11bHRpcGx5LGguc2NhbGU9dS5zY2FsZSxoLnJvdGF0ZVg9ZnVuY3Rpb24oZSx0LG4pe24qPS41O3ZhciByPXRbMF0saT10WzFdLHM9dFsyXSxvPXRbM10sdT1NYXRoLnNpbihuKSxhPU1hdGguY29zKG4pO3JldHVybiBlWzBdPXIqYStvKnUsZVsxXT1pKmErcyp1LGVbMl09cyphLWkqdSxlWzNdPW8qYS1yKnUsZX0saC5yb3RhdGVZPWZ1bmN0aW9uKGUsdCxuKXtuKj0uNTt2YXIgcj10WzBdLGk9dFsxXSxzPXRbMl0sbz10WzNdLHU9TWF0aC5zaW4obiksYT1NYXRoLmNvcyhuKTtyZXR1cm4gZVswXT1yKmEtcyp1LGVbMV09aSphK28qdSxlWzJdPXMqYStyKnUsZVszXT1vKmEtaSp1LGV9LGgucm90YXRlWj1mdW5jdGlvbihlLHQsbil7bio9LjU7dmFyIHI9dFswXSxpPXRbMV0scz10WzJdLG89dFszXSx1PU1hdGguc2luKG4pLGE9TWF0aC5jb3Mobik7cmV0dXJuIGVbMF09ciphK2kqdSxlWzFdPWkqYS1yKnUsZVsyXT1zKmErbyp1LGVbM109byphLXMqdSxlfSxoLmNhbGN1bGF0ZVc9ZnVuY3Rpb24oZSx0KXt2YXIgbj10WzBdLHI9dFsxXSxpPXRbMl07cmV0dXJuIGVbMF09bixlWzFdPXIsZVsyXT1pLGVbM109LU1hdGguc3FydChNYXRoLmFicygxLW4qbi1yKnItaSppKSksZX0saC5kb3Q9dS5kb3QsaC5sZXJwPXUubGVycCxoLnNsZXJwPWZ1bmN0aW9uKGUsdCxuLHIpe3ZhciBpPXRbMF0scz10WzFdLG89dFsyXSx1PXRbM10sYT1uWzBdLGY9blsxXSxsPW5bMl0sYz1uWzNdLGgscCxkLHYsbTtyZXR1cm4gcD1pKmErcypmK28qbCt1KmMscDwwJiYocD0tcCxhPS1hLGY9LWYsbD0tbCxjPS1jKSwxLXA+MWUtNj8oaD1NYXRoLmFjb3MocCksZD1NYXRoLnNpbihoKSx2PU1hdGguc2luKCgxLXIpKmgpL2QsbT1NYXRoLnNpbihyKmgpL2QpOih2PTEtcixtPXIpLGVbMF09dippK20qYSxlWzFdPXYqcyttKmYsZVsyXT12Km8rbSpsLGVbM109dip1K20qYyxlfSxoLmludmVydD1mdW5jdGlvbihlLHQpe3ZhciBuPXRbMF0scj10WzFdLGk9dFsyXSxzPXRbM10sbz1uKm4rcipyK2kqaStzKnMsdT1vPzEvbzowO3JldHVybiBlWzBdPS1uKnUsZVsxXT0tcip1LGVbMl09LWkqdSxlWzNdPXMqdSxlfSxoLmNvbmp1Z2F0ZT1mdW5jdGlvbihlLHQpe3JldHVybiBlWzBdPS10WzBdLGVbMV09LXRbMV0sZVsyXT0tdFsyXSxlWzNdPXRbM10sZX0saC5sZW5ndGg9dS5sZW5ndGgsaC5sZW49aC5sZW5ndGgsaC5zcXVhcmVkTGVuZ3RoPXUuc3F1YXJlZExlbmd0aCxoLnNxckxlbj1oLnNxdWFyZWRMZW5ndGgsaC5ub3JtYWxpemU9dS5ub3JtYWxpemUsaC5mcm9tTWF0Mz1mdW5jdGlvbigpe3ZhciBlPXR5cGVvZiBJbnQ4QXJyYXkhPVwidW5kZWZpbmVkXCI/bmV3IEludDhBcnJheShbMSwyLDBdKTpbMSwyLDBdO3JldHVybiBmdW5jdGlvbih0LG4pe3ZhciByPW5bMF0rbls0XStuWzhdLGk7aWYocj4wKWk9TWF0aC5zcXJ0KHIrMSksdFszXT0uNSppLGk9LjUvaSx0WzBdPShuWzddLW5bNV0pKmksdFsxXT0oblsyXS1uWzZdKSppLHRbMl09KG5bM10tblsxXSkqaTtlbHNle3ZhciBzPTA7bls0XT5uWzBdJiYocz0xKSxuWzhdPm5bcyozK3NdJiYocz0yKTt2YXIgbz1lW3NdLHU9ZVtvXTtpPU1hdGguc3FydChuW3MqMytzXS1uW28qMytvXS1uW3UqMyt1XSsxKSx0W3NdPS41KmksaT0uNS9pLHRbM109KG5bdSozK29dLW5bbyozK3VdKSppLHRbb109KG5bbyozK3NdK25bcyozK29dKSppLHRbdV09KG5bdSozK3NdK25bcyozK3VdKSppfXJldHVybiB0fX0oKSxoLnN0cj1mdW5jdGlvbihlKXtyZXR1cm5cInF1YXQoXCIrZVswXStcIiwgXCIrZVsxXStcIiwgXCIrZVsyXStcIiwgXCIrZVszXStcIilcIn0sdHlwZW9mIGUhPVwidW5kZWZpbmVkXCImJihlLnF1YXQ9aCl9KHQuZXhwb3J0cyl9KSh0aGlzKTtcbiIsIid1c2Ugc3RyaWN0JztcblxuaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgbmV3IChyZXF1aXJlKCcuL3NvdXJjZS93b3JrZXIuanMnKSkoc2VsZik7XG59IGVsc2Uge1xuICAgIC8vIGpzaGludCAtVzA3OVxuICAgIHZhciBtYXBib3hnbCA9IG1vZHVsZS5leHBvcnRzID0gd2luZG93Lm1hcGJveGdsID0ge307XG5cbiAgICBtYXBib3hnbC5NYXAgPSByZXF1aXJlKCcuL3VpL21hcC5qcycpO1xuICAgIG1hcGJveGdsLk5hdmlnYXRpb24gPSByZXF1aXJlKCcuL3VpL2NvbnRyb2wvbmF2aWdhdGlvbi5qcycpO1xuICAgIG1hcGJveGdsLkF0dHJpYnV0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzJyk7XG5cbiAgICBtYXBib3hnbC5Tb3VyY2UgPSByZXF1aXJlKCcuL3NvdXJjZS9zb3VyY2UnKTtcbiAgICBtYXBib3hnbC5HZW9KU09OU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UvZ2VvanNvbnNvdXJjZScpO1xuICAgIG1hcGJveGdsLlZpZGVvU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UvdmlkZW9zb3VyY2UnKTtcblxuICAgIG1hcGJveGdsLlN0eWxlID0gcmVxdWlyZSgnLi9zdHlsZS9zdHlsZS5qcycpO1xuXG4gICAgbWFwYm94Z2wuTGF0TG5nID0gcmVxdWlyZSgnLi9nZW8vbGF0bG5nLmpzJyk7XG4gICAgbWFwYm94Z2wuTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi9nZW8vbGF0bG5nYm91bmRzLmpzJyk7XG4gICAgbWFwYm94Z2wuUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG4gICAgbWFwYm94Z2wuRXZlbnRlZCA9IHJlcXVpcmUoJy4vdXRpbC9ldmVudGVkLmpzJyk7XG4gICAgbWFwYm94Z2wudXRpbCA9IHJlcXVpcmUoJy4vdXRpbC91dGlsLmpzJyk7XG5cbiAgICB2YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4vdXRpbC9icm93c2VyLmpzJyk7XG4gICAgbWFwYm94Z2wudXRpbC5zdXBwb3J0ZWQgPSBicm93c2VyLnN1cHBvcnRlZDtcblxuICAgIHZhciBhamF4ID0gcmVxdWlyZSgnLi91dGlsL2FqYXguanMnKTtcbiAgICBtYXBib3hnbC51dGlsLmdldEpTT04gPSBhamF4LmdldEpTT047XG4gICAgbWFwYm94Z2wudXRpbC5nZXRBcnJheUJ1ZmZlciA9IGFqYXguZ2V0QXJyYXlCdWZmZXI7XG5cbiAgICB2YXIgY29uZmlnID0gcmVxdWlyZSgnLi91dGlsL2NvbmZpZy5qcycpO1xuICAgIG1hcGJveGdsLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtYXBib3hnbCwgJ2FjY2Vzc1Rva2VuJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnLkFDQ0VTU19UT0tFTjsgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbih0b2tlbikgeyBjb25maWcuQUNDRVNTX1RPS0VOID0gdG9rZW47IH1cbiAgICB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG1hdDMgPSByZXF1aXJlKCcuLi9saWIvZ2xtYXRyaXguanMnKS5tYXQzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdCYWNrZ3JvdW5kO1xuXG5mdW5jdGlvbiBkcmF3QmFja2dyb3VuZChnbCwgcGFpbnRlciwgYnVja2V0LCBsYXllclN0eWxlLCBwb3NNYXRyaXgsIHBhcmFtcywgaW1hZ2VTcHJpdGUpIHtcbiAgICB2YXIgY29sb3IgPSBsYXllclN0eWxlWydiYWNrZ3JvdW5kLWNvbG9yJ107XG4gICAgdmFyIGltYWdlID0gbGF5ZXJTdHlsZVsnYmFja2dyb3VuZC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXJTdHlsZVsnYmFja2dyb3VuZC1vcGFjaXR5J10gfHwgMTtcbiAgICB2YXIgc2hhZGVyO1xuXG4gICAgaWYgKGltYWdlKSB7XG4gICAgICAgIC8vIERyYXcgdGV4dHVyZSBmaWxsXG4gICAgICAgIHZhciBpbWFnZVBvcyA9IGltYWdlU3ByaXRlLmdldFBvc2l0aW9uKGltYWdlLCB0cnVlKTtcbiAgICAgICAgaWYgKCFpbWFnZVBvcykgcmV0dXJuO1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIucGF0dGVyblNoYWRlcjtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4KTtcbiAgICAgICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlLCAwKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsLCBpbWFnZVBvcy50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9iciwgaW1hZ2VQb3MuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBwYWludGVyLnRyYW5zZm9ybS56b29tRnJhY3Rpb24pO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eSwgb3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgICAgICB2YXIgc2l6ZSA9IGltYWdlUG9zLnNpemU7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0cmFuc2Zvcm0ubG9jYXRpb25Db29yZGluYXRlKHRyYW5zZm9ybS5jZW50ZXIpO1xuICAgICAgICB2YXIgc2NhbGUgPSAxIC8gTWF0aC5wb3coMiwgdHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG4gICAgICAgIHZhciBtYXRyaXggPSBtYXQzLmNyZWF0ZSgpO1xuXG4gICAgICAgIG1hdDMuc2NhbGUobWF0cml4LCBtYXRyaXgsIFsxIC8gc2l6ZVswXSwgMSAvIHNpemVbMV0sIDFdKTtcbiAgICAgICAgbWF0My50cmFuc2xhdGUobWF0cml4LCBtYXRyaXgsIFtcbiAgICAgICAgICAgIChjZW50ZXIuY29sdW1uICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIHNpemVbMF0sXG4gICAgICAgICAgICAoY2VudGVyLnJvdyAgICAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSBzaXplWzFdLFxuICAgICAgICAgICAgMFxuICAgICAgICBdKTtcbiAgICAgICAgbWF0My5yb3RhdGUobWF0cml4LCBtYXRyaXgsIC10cmFuc2Zvcm0uYW5nbGUpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeCwgbWF0cml4LCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMixcbiAgICAgICAgICAgIDFcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4LCBmYWxzZSwgbWF0cml4KTtcblxuICAgICAgICBpbWFnZVNwcml0ZS5iaW5kKGdsLCB0cnVlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIERyYXcgZmlsbGluZyByZWN0YW5nbGUuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIuZmlsbFNoYWRlcjtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcGFyYW1zLnBhZGRlZCB8fCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgZ2wuZGlzYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgcGFpbnRlci5iYWNrZ3JvdW5kQnVmZmVyLml0ZW1Db3VudCk7XG4gICAgZ2wuZW5hYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICBnbC5zdGVuY2lsTWFzaygweDAwKTtcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0NvbXBvc2l0ZWQ7XG5cbmZ1bmN0aW9uIGRyYXdDb21wb3NpdGVkIChnbCwgcGFpbnRlciwgYnVja2V0cywgbGF5ZXJTdHlsZSwgcGFyYW1zLCBzdHlsZSwgbGF5ZXIpIHtcbiAgICB2YXIgdGV4dHVyZSA9IHBhaW50ZXIubmFtZWRSZW5kZXJUZXh0dXJlc1tsYXllci5pZF07XG4gICAgaWYgKCF0ZXh0dXJlKSByZXR1cm4gY29uc29sZS53YXJuKCdtaXNzaW5nIHJlbmRlciB0ZXh0dXJlICcgKyBsYXllci5pZCk7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5jb21wb3NpdGVTaGFkZXIsIHBhaW50ZXIuaWRlbnRpdHlNYXRyaXgpO1xuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuICAgIGdsLnVuaWZvcm0xaShwYWludGVyLmNvbXBvc2l0ZVNoYWRlci51X2ltYWdlLCAwKTtcblxuICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmNvbXBvc2l0ZVNoYWRlci51X29wYWNpdHksIGxheWVyU3R5bGVbJ2NvbXBvc2l0ZS1vcGFjaXR5J10pO1xuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmNvbXBvc2l0ZVNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuXG4gICAgcGFpbnRlci5mcmVlUmVuZGVyVGV4dHVyZShsYXllci5pZCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB0ZXh0VmVydGljZXMgPSByZXF1aXJlKCcuLi9saWIvZGVidWd0ZXh0LmpzJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3Nlci5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdEZWJ1ZztcblxuZnVuY3Rpb24gZHJhd0RlYnVnKGdsLCBwYWludGVyLCB0aWxlLCBwYXJhbXMpIHtcbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIGdsLnN3aXRjaFNoYWRlcihwYWludGVyLmRlYnVnU2hhZGVyLCBwYWludGVyLnRpbGUucG9zTWF0cml4LCBwYWludGVyLnRpbGUuZXhNYXRyaXgpO1xuXG4gICAgLy8gZHJhdyBib3VuZGluZyByZWN0YW5nbGVcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci5kZWJ1Z0J1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmRlYnVnU2hhZGVyLmFfcG9zLCBwYWludGVyLmRlYnVnQnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDAsIDAsIDEpO1xuICAgIGdsLmxpbmVXaWR0aCg0KTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLkxJTkVfU1RSSVAsIDAsIHBhaW50ZXIuZGVidWdCdWZmZXIuaXRlbUNvdW50KTtcblxuICAgIC8vIGRyYXcgdGlsZSBjb29yZGluYXRlXG4gICAgdmFyIGNvb3JkID0gcGFyYW1zLnogKyAnLycgKyBwYXJhbXMueCArICcvJyArIHBhcmFtcy55O1xuXG4gICAgdmFyIHZlcnRpY2VzID0gdGV4dFZlcnRpY2VzKGNvb3JkLCA1MCwgMjAwLCA1KTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmRlYnVnVGV4dEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KHZlcnRpY2VzKSwgZ2wuU1RSRUFNX0RSQVcpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wubGluZVdpZHRoKDggKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDEsIDEsIDEpO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHZlcnRpY2VzLmxlbmd0aCAvIHBhaW50ZXIuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplKTtcbiAgICBnbC5saW5lV2lkdGgoMiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgZ2wudW5pZm9ybTRmKHBhaW50ZXIuZGVidWdTaGFkZXIudV9jb2xvciwgMCwgMCwgMCwgMSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdmVydGljZXMubGVuZ3RoIC8gcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyLmpzJyk7XG52YXIgbWF0MyA9IHJlcXVpcmUoJy4uL2xpYi9nbG1hdHJpeC5qcycpLm1hdDM7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0ZpbGw7XG5cbmZ1bmN0aW9uIGRyYXdGaWxsKGdsLCBwYWludGVyLCBidWNrZXQsIGxheWVyU3R5bGUsIHBvc01hdHJpeCwgcGFyYW1zLCBpbWFnZVNwcml0ZSkge1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRQb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHBhcmFtcy56LCBsYXllclN0eWxlWydmaWxsLXRyYW5zbGF0ZSddLCBsYXllclN0eWxlWydmaWxsLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgY29sb3IgPSBsYXllclN0eWxlWydmaWxsLWNvbG9yJ107XG5cbiAgICB2YXIgdmVydGV4LCBlbGVtZW50cywgZ3JvdXAsIGNvdW50O1xuXG4gICAgLy8gRHJhdyB0aGUgc3RlbmNpbCBtYXNrLlxuXG4gICAgLy8gV2UncmUgb25seSBkcmF3aW5nIHRvIHRoZSBmaXJzdCBzZXZlbiBiaXRzICg9PSBzdXBwb3J0IGEgbWF4aW11bSBvZlxuICAgIC8vIDEyNyBvdmVybGFwcGluZyBwb2x5Z29ucyBpbiBvbmUgcGxhY2UgYmVmb3JlIHdlIGdldCByZW5kZXJpbmcgZXJyb3JzKS5cbiAgICBnbC5zdGVuY2lsTWFzaygweDNGKTtcbiAgICBnbC5jbGVhcihnbC5TVEVOQ0lMX0JVRkZFUl9CSVQpO1xuXG4gICAgLy8gRHJhdyBmcm9udCBmYWNpbmcgdHJpYW5nbGVzLiBXaGVyZXZlciB0aGUgMHg4MCBiaXQgaXMgMSwgd2UgYXJlXG4gICAgLy8gaW5jcmVhc2luZyB0aGUgbG93ZXIgNyBiaXRzIGJ5IG9uZSBpZiB0aGUgdHJpYW5nbGUgaXMgYSBmcm9udC1mYWNpbmdcbiAgICAvLyB0cmlhbmdsZS4gVGhpcyBtZWFucyB0aGF0IGFsbCB2aXNpYmxlIHBvbHlnb25zIHNob3VsZCBiZSBpbiBDQ1dcbiAgICAvLyBvcmllbnRhdGlvbiwgd2hpbGUgYWxsIGhvbGVzIChzZWUgYmVsb3cpIGFyZSBpbiBDVyBvcmllbnRhdGlvbi5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHg4MCwgMHg4MCk7XG5cbiAgICAvLyBXaGVuIHdlIGRvIGEgbm9uemVybyBmaWxsLCB3ZSBjb3VudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGEgcGl4ZWwgaXNcbiAgICAvLyBjb3ZlcmVkIGJ5IGEgY291bnRlcmNsb2Nrd2lzZSBwb2x5Z29uLCBhbmQgc3VidHJhY3QgdGhlIG51bWJlciBvZlxuICAgIC8vIHRpbWVzIGl0IGlzIFwidW5jb3ZlcmVkXCIgYnkgYSBjbG9ja3dpc2UgcG9seWdvbi5cbiAgICBnbC5zdGVuY2lsT3BTZXBhcmF0ZShnbC5GUk9OVCwgZ2wuSU5DUl9XUkFQLCBnbC5LRUVQLCBnbC5LRUVQKTtcbiAgICBnbC5zdGVuY2lsT3BTZXBhcmF0ZShnbC5CQUNLLCBnbC5ERUNSX1dSQVAsIGdsLktFRVAsIGdsLktFRVApO1xuXG4gICAgLy8gV2hlbiBkcmF3aW5nIGEgc2hhcGUsIHdlIGZpcnN0IGRyYXcgYWxsIHNoYXBlcyB0byB0aGUgc3RlbmNpbCBidWZmZXJcbiAgICAvLyBhbmQgaW5jcmVtZW50aW5nIGFsbCBhcmVhcyB3aGVyZSBwb2x5Z29ucyBhcmVcbiAgICBnbC5jb2xvck1hc2soZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuXG4gICAgLy8gRHJhdyB0aGUgYWN0dWFsIHRyaWFuZ2xlIGZhbiBpbnRvIHRoZSBzdGVuY2lsIGJ1ZmZlci5cbiAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5maWxsU2hhZGVyLCB0cmFuc2xhdGVkUG9zTWF0cml4LCBwYWludGVyLnRpbGUuZXhNYXRyaXgpO1xuXG4gICAgLy8gRHJhdyBhbGwgYnVmZmVyc1xuICAgIHZlcnRleCA9IGJ1Y2tldC5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgIGVsZW1lbnRzID0gYnVja2V0LmJ1ZmZlcnMuZmlsbEVsZW1lbnQ7XG4gICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICB2YXIgb2Zmc2V0LCBlbGVtZW50T2Zmc2V0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0LmVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdyb3VwID0gYnVja2V0LmVsZW1lbnRHcm91cHMuZ3JvdXBzW2ldO1xuICAgICAgICBvZmZzZXQgPSBncm91cC52ZXJ0ZXhTdGFydEluZGV4ICogdmVydGV4Lml0ZW1TaXplO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHBhaW50ZXIuZmlsbFNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCA0LCBvZmZzZXQgKyAwKTtcblxuICAgICAgICBjb3VudCA9IGdyb3VwLmVsZW1lbnRMZW5ndGggKiAzO1xuICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICB9XG5cbiAgICAvLyBOb3cgdGhhdCB3ZSBoYXZlIHRoZSBzdGVuY2lsIG1hc2sgaW4gdGhlIHN0ZW5jaWwgYnVmZmVyLCB3ZSBjYW4gc3RhcnRcbiAgICAvLyB3cml0aW5nIHRvIHRoZSBjb2xvciBidWZmZXIuXG4gICAgZ2wuY29sb3JNYXNrKHRydWUsIHRydWUsIHRydWUsIHRydWUpO1xuXG4gICAgLy8gRnJvbSBub3cgb24sIHdlIGRvbid0IHdhbnQgdG8gdXBkYXRlIHRoZSBzdGVuY2lsIGJ1ZmZlciBhbnltb3JlLlxuICAgIGdsLnN0ZW5jaWxPcChnbC5LRUVQLCBnbC5LRUVQLCBnbC5LRUVQKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweDApO1xuXG4gICAgdmFyIHN0cm9rZUNvbG9yID0gbGF5ZXJTdHlsZVsnZmlsbC1vdXRsaW5lLWNvbG9yJ107XG5cbiAgICAvLyBCZWNhdXNlIHdlJ3JlIGRyYXdpbmcgdG9wLXRvLWJvdHRvbSwgYW5kIHdlIHVwZGF0ZSB0aGUgc3RlbmNpbCBtYXNrXG4gICAgLy8gYmVsb3csIHdlIGhhdmUgdG8gZHJhdyB0aGUgb3V0bGluZSBmaXJzdCAoISlcbiAgICBpZiAobGF5ZXJTdHlsZVsnZmlsbC1hbnRpYWxpYXMnXSA9PT0gdHJ1ZSAmJiBwYXJhbXMuYW50aWFsaWFzaW5nICYmICEobGF5ZXJTdHlsZVsnZmlsbC1pbWFnZSddICYmICFzdHJva2VDb2xvcikpIHtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIub3V0bGluZVNoYWRlciwgdHJhbnNsYXRlZFBvc01hdHJpeCwgcGFpbnRlci50aWxlLmV4TWF0cml4KTtcbiAgICAgICAgZ2wubGluZVdpZHRoKDIgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuXG4gICAgICAgIGlmIChzdHJva2VDb2xvcikge1xuICAgICAgICAgICAgLy8gSWYgd2UgZGVmaW5lZCBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGZpbGwgb3V0bGluZSwgd2UgYXJlXG4gICAgICAgICAgICAvLyBnb2luZyB0byBpZ25vcmUgdGhlIGJpdHMgaW4gMHgzRiBhbmQganVzdCBjYXJlIGFib3V0IHRoZSBnbG9iYWxcbiAgICAgICAgICAgIC8vIGNsaXBwaW5nIG1hc2suXG4gICAgICAgICAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIG9ubHkgd2FudCB0byBkcmF3IHRoZSBhbnRpYWxpYXNlZCBwYXJ0cyB0aGF0IGFyZVxuICAgICAgICAgICAgLy8gKm91dHNpZGUqIHRoZSBjdXJyZW50IHNoYXBlLiBUaGlzIGlzIGltcG9ydGFudCBpbiBjYXNlIHRoZSBmaWxsXG4gICAgICAgICAgICAvLyBvciBzdHJva2UgY29sb3IgaXMgdHJhbnNsdWNlbnQuIElmIHdlIHdvdWxkbid0IGNsaXAgdG8gb3V0c2lkZVxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2hhcGUsIHNvbWUgcGl4ZWxzIGZyb20gdGhlIG91dGxpbmUgc3Ryb2tlIG92ZXJsYXBwZWRcbiAgICAgICAgICAgIC8vIHRoZSAobm9uLWFudGlhbGlhc2VkKSBmaWxsLlxuICAgICAgICAgICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4QkYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmKHBhaW50ZXIub3V0bGluZVNoYWRlci51X3dvcmxkLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHBhaW50ZXIub3V0bGluZVNoYWRlci51X2NvbG9yLCBzdHJva2VDb2xvciA/IHN0cm9rZUNvbG9yIDogY29sb3IpO1xuXG4gICAgICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICAgICAgdmVydGV4ID0gYnVja2V0LmJ1ZmZlcnMuZmlsbFZlcnRleDtcbiAgICAgICAgZWxlbWVudHMgPSBidWNrZXQuYnVmZmVycy5vdXRsaW5lRWxlbWVudDtcbiAgICAgICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBidWNrZXQuZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgIGdyb3VwID0gYnVja2V0LmVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDQsIG9mZnNldCArIDApO1xuXG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGggKiAyO1xuICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICBnbC5kcmF3RWxlbWVudHMoZ2wuTElORVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBsYXllclN0eWxlWydmaWxsLWltYWdlJ107XG4gICAgdmFyIG9wYWNpdHkgPSBsYXllclN0eWxlWydmaWxsLW9wYWNpdHknXSB8fCAxO1xuICAgIHZhciBzaGFkZXI7XG5cbiAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgLy8gRHJhdyB0ZXh0dXJlIGZpbGxcbiAgICAgICAgdmFyIGltYWdlUG9zID0gaW1hZ2VTcHJpdGUuZ2V0UG9zaXRpb24oaW1hZ2UsIHRydWUpO1xuICAgICAgICBpZiAoIWltYWdlUG9zKSByZXR1cm47XG5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5wYXR0ZXJuU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtMWkoc2hhZGVyLnVfaW1hZ2UsIDApO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGwsIGltYWdlUG9zLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyLCBpbWFnZVBvcy5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9taXgsIHBhaW50ZXIudHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBvcGFjaXR5KTtcblxuICAgICAgICB2YXIgZmFjdG9yID0gOCAvIE1hdGgucG93KDIsIHBhaW50ZXIudHJhbnNmb3JtLnRpbGVab29tIC0gcGFyYW1zLnopO1xuXG4gICAgICAgIHZhciBtYXRyaXggPSBtYXQzLmNyZWF0ZSgpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeCwgbWF0cml4LCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zLnNpemVbMF0gKiBmYWN0b3IpLFxuICAgICAgICAgICAgMSAvIChpbWFnZVBvcy5zaXplWzFdICogZmFjdG9yKSxcbiAgICAgICAgICAgIDEsIDFcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4LCBmYWxzZSwgbWF0cml4KTtcblxuICAgICAgICBpbWFnZVNwcml0ZS5iaW5kKGdsLCB0cnVlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIERyYXcgZmlsbGluZyByZWN0YW5nbGUuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIuZmlsbFNoYWRlcjtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcGFyYW1zLnBhZGRlZCB8fCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgLy8gT25seSBkcmF3IHJlZ2lvbnMgdGhhdCB3ZSBtYXJrZWRcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHgwLCAweDNGKTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4ODApO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3Nlci5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXdMaW5lKGdsLCBwYWludGVyLCBidWNrZXQsIGxheWVyU3R5bGUsIHBvc01hdHJpeCwgcGFyYW1zLCBpbWFnZVNwcml0ZSkge1xuXG4gICAgcG9zTWF0cml4ID0gcGFpbnRlci50cmFuc2xhdGVNYXRyaXgocG9zTWF0cml4LCBwYXJhbXMueiwgbGF5ZXJTdHlsZVsnbGluZS10cmFuc2xhdGUnXSwgbGF5ZXJTdHlsZVsnbGluZS10cmFuc2xhdGUtYW5jaG9yJ10pO1xuXG4gICAgLy8gZG9uJ3QgZHJhdyB6ZXJvLXdpZHRoIGxpbmVzXG4gICAgaWYgKGxheWVyU3R5bGVbJ2xpbmUtd2lkdGgnXSA8PSAwKSByZXR1cm47XG5cbiAgICB2YXIgZ2FtbWEgPSAxO1xuICAgIHZhciBhbnRpYWxpYXNpbmcgPSBnYW1tYSAvIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcblxuICAgIHZhciBsaW5lT2Zmc2V0ID0gbGF5ZXJTdHlsZVsnbGluZS1vZmZzZXQnXSAvIDI7XG4gICAgdmFyIGluc2V0ID0gTWF0aC5tYXgoLTEsIGxpbmVPZmZzZXQgLSBsYXllclN0eWxlWydsaW5lLXdpZHRoJ10gLyAyIC0gYW50aWFsaWFzaW5nIC8gMikgKyAxO1xuICAgIHZhciBvdXRzZXQgPSBsaW5lT2Zmc2V0ICsgbGF5ZXJTdHlsZVsnbGluZS13aWR0aCddIC8gMiArIGFudGlhbGlhc2luZyAvIDI7XG5cbiAgICB2YXIgaW1hZ2VQb3MgPSBsYXllclN0eWxlWydsaW5lLWltYWdlJ10gJiYgaW1hZ2VTcHJpdGUuZ2V0UG9zaXRpb24obGF5ZXJTdHlsZVsnbGluZS1pbWFnZSddKTtcbiAgICB2YXIgc2hhZGVyO1xuXG4gICAgaWYgKGltYWdlUG9zKSB7XG4gICAgICAgIHZhciBmYWN0b3IgPSA4IC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gLSBwYXJhbXMueik7XG5cbiAgICAgICAgaW1hZ2VTcHJpdGUuYmluZChnbCwgdHJ1ZSk7XG5cbiAgICAgICAgLy9mYWN0b3IgPSBNYXRoLnBvdygyLCA0IC0gcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gKyBwYXJhbXMueik7XG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCwgcGFpbnRlci50aWxlLmV4TWF0cml4KTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3NpemUsIFtpbWFnZVBvcy5zaXplWzBdICogZmFjdG9yLCBpbWFnZVBvcy5zaXplWzFdIF0pO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGwsIGltYWdlUG9zLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyLCBpbWFnZVBvcy5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlLCBwYWludGVyLnRyYW5zZm9ybS56b29tRnJhY3Rpb24pO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5saW5lU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgsIHBhaW50ZXIudGlsZS5leE1hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfZGFzaGFycmF5LCBsYXllclN0eWxlWydsaW5lLWRhc2hhcnJheSddKTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgbGF5ZXJTdHlsZVsnbGluZS1jb2xvciddKTtcbiAgICB9XG5cbiAgICB2YXIgdGlsZVBpeGVsUmF0aW8gPSBwYWludGVyLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHBhcmFtcy56KSAvIDg7XG4gICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfcmF0aW8sIHRpbGVQaXhlbFJhdGlvKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYmx1ciwgbGF5ZXJTdHlsZVsnbGluZS1ibHVyJ10gKyBhbnRpYWxpYXNpbmcpO1xuXG5cbiAgICB2YXIgdmVydGV4ID0gYnVja2V0LmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2ZXJ0ZXguYmluZChnbCk7XG4gICAgdmFyIGVsZW1lbnQgPSBidWNrZXQuYnVmZmVycy5saW5lRWxlbWVudDtcbiAgICBlbGVtZW50LmJpbmQoZ2wpO1xuXG4gICAgdmFyIGdyb3VwcyA9IGJ1Y2tldC5lbGVtZW50R3JvdXBzLmdyb3VwcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXAgPSBncm91cHNbaV07XG4gICAgICAgIHZhciBvZmZzZXQgPSBncm91cC52ZXJ0ZXhTdGFydEluZGV4ICogdmVydGV4Lml0ZW1TaXplO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgNCwgZ2wuU0hPUlQsIGZhbHNlLCA4LCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9leHRydWRlLCAyLCBnbC5CWVRFLCBmYWxzZSwgOCwgb2Zmc2V0ICsgNik7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfbGluZXNvZmFyLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIG9mZnNldCArIDQpO1xuXG4gICAgICAgIHZhciBjb3VudCA9IGdyb3VwLmVsZW1lbnRMZW5ndGggKiAzO1xuICAgICAgICB2YXIgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudC5pdGVtU2l6ZTtcbiAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICB9XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuLi9zb3VyY2UvdGlsZWNvb3JkLmpzJyk7XG52YXIgUHJlcmVuZGVyZWRUZXh0dXJlID0gcmVxdWlyZSgnLi9wcmVyZW5kZXJlZC5qcycpO1xudmFyIG1hdDQgPSByZXF1aXJlKCcuLi9saWIvZ2xtYXRyaXguanMnKS5tYXQ0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdSYXN0ZXI7XG5cbmZ1bmN0aW9uIGRyYXdSYXN0ZXIoZ2wsIHBhaW50ZXIsIGJ1Y2tldCwgbGF5ZXJTdHlsZSwgcGFyYW1zLCBzdHlsZSwgbGF5ZXIsIHRpbGUpIHtcblxuICAgIGlmIChsYXllciAmJiBsYXllci5sYXllcnMpIHtcblxuICAgICAgICBpZiAoIWJ1Y2tldC5wcmVyZW5kZXJlZCkge1xuICAgICAgICAgICAgYnVja2V0LnByZXJlbmRlcmVkID0gbmV3IFByZXJlbmRlcmVkVGV4dHVyZShnbCwgYnVja2V0LmluZm8sIHBhaW50ZXIpO1xuICAgICAgICAgICAgYnVja2V0LnByZXJlbmRlcmVkLmJpbmRGcmFtZWJ1ZmZlcigpO1xuXG4gICAgICAgICAgICBnbC5jbGVhclN0ZW5jaWwoMHg4MCk7XG4gICAgICAgICAgICBnbC5zdGVuY2lsTWFzaygweEZGKTtcbiAgICAgICAgICAgIGdsLmNsZWFyKGdsLlNURU5DSUxfQlVGRkVSX0JJVCB8IGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xuICAgICAgICAgICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG5cbiAgICAgICAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIGJ1Y2tldC5wcmVyZW5kZXJlZC5zaXplLCBidWNrZXQucHJlcmVuZGVyZWQuc2l6ZSk7XG5cbiAgICAgICAgICAgIHZhciBidWZmZXIgPSBidWNrZXQucHJlcmVuZGVyZWQuYnVmZmVyICogNDA5NjtcblxuICAgICAgICAgICAgdmFyIG1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgICAgICBtYXQ0Lm9ydGhvKG1hdHJpeCwgLWJ1ZmZlciwgNDA5NiArIGJ1ZmZlciwgLTQwOTYgLSBidWZmZXIsIGJ1ZmZlciwgMCwgMSk7XG4gICAgICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtYXRyaXgsIG1hdHJpeCwgWzAsIC00MDk2LCAwXSk7XG5cbiAgICAgICAgICAgIHBhcmFtcy5wYWRkZWQgPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICAgICAgbWF0NC5vcnRobyhwYXJhbXMucGFkZGVkLCAwLCA0MDk2LCAtNDA5NiwgMCwgMCwgMSk7XG4gICAgICAgICAgICBtYXQ0LnRyYW5zbGF0ZShwYXJhbXMucGFkZGVkLCBwYXJhbXMucGFkZGVkLCBbMCwgLTQwOTYsIDBdKTtcblxuICAgICAgICAgICAgcGFpbnRlci5kcmF3KHRpbGUsIHN0eWxlLCBsYXllci5sYXllcnMsIHBhcmFtcywgbWF0cml4KTtcblxuICAgICAgICAgICAgZGVsZXRlIHBhcmFtcy5wYWRkZWQ7XG5cbiAgICAgICAgICAgIGlmIChidWNrZXQuaW5mb1sncmFzdGVyLWJsdXInXSA+IDApIHtcbiAgICAgICAgICAgICAgICBidWNrZXQucHJlcmVuZGVyZWQuYmx1cihwYWludGVyLCBidWNrZXQuaW5mb1sncmFzdGVyLWJsdXInXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJ1Y2tldC5wcmVyZW5kZXJlZC51bmJpbmRGcmFtZWJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wudmlld3BvcnQoMCwgMCwgcGFpbnRlci53aWR0aCwgcGFpbnRlci5oZWlnaHQpO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICB2YXIgdGV4dHVyZSA9IGJ1Y2tldC50aWxlID8gYnVja2V0LnRpbGUgOiBidWNrZXQucHJlcmVuZGVyZWQ7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICB2YXIgc2hhZGVyID0gcGFpbnRlci5yYXN0ZXJTaGFkZXI7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcGFpbnRlci50aWxlLnBvc01hdHJpeCwgcGFpbnRlci50aWxlLmV4TWF0cml4KTtcblxuICAgIC8vIGNvbG9yIHBhcmFtZXRlcnNcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnJpZ2h0bmVzc19sb3csIGxheWVyU3R5bGVbJ3Jhc3Rlci1icmlnaHRuZXNzJ11bMF0pO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9icmlnaHRuZXNzX2hpZ2gsIGxheWVyU3R5bGVbJ3Jhc3Rlci1icmlnaHRuZXNzJ11bMV0pO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9zYXR1cmF0aW9uX2ZhY3Rvciwgc2F0dXJhdGlvbkZhY3RvcihsYXllclN0eWxlWydyYXN0ZXItc2F0dXJhdGlvbiddKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2NvbnRyYXN0X2ZhY3RvciwgY29udHJhc3RGYWN0b3IobGF5ZXJTdHlsZVsncmFzdGVyLWNvbnRyYXN0J10pKTtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlci51X3NwaW5fd2VpZ2h0cywgc3BpbldlaWdodHMobGF5ZXJTdHlsZVsncmFzdGVyLWh1ZS1yb3RhdGUnXSkpO1xuXG5cbiAgICB2YXIgcGFyZW50VGlsZSwgb3BhY2l0aWVzO1xuICAgIGlmIChsYXllciAmJiBsYXllci5sYXllcnMpIHtcbiAgICAgICAgcGFyZW50VGlsZSA9IG51bGw7XG4gICAgICAgIG9wYWNpdGllcyA9IFtsYXllclN0eWxlWydyYXN0ZXItb3BhY2l0eSddLCAwXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwYXJlbnRUaWxlID0gZmluZFBhcmVudCh0ZXh0dXJlKTtcbiAgICAgICAgb3BhY2l0aWVzID0gZ2V0T3BhY2l0aWVzKHRleHR1cmUsIHBhcmVudFRpbGUpO1xuICAgIH1cbiAgICB2YXIgcGFyZW50U2NhbGVCeSwgcGFyZW50VEw7XG5cbiAgICBnbC5hY3RpdmVUZXh0dXJlKGdsLlRFWFRVUkUwKTtcbiAgICB0ZXh0dXJlLmJpbmQoZ2wpO1xuXG4gICAgaWYgKHBhcmVudFRpbGUpIHtcbiAgICAgICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMSk7XG4gICAgICAgIHBhcmVudFRpbGUuYmluZChnbCk7XG5cbiAgICAgICAgdmFyIHRpbGVQb3MgPSBUaWxlQ29vcmQuZnJvbUlEKHRleHR1cmUuaWQpO1xuICAgICAgICB2YXIgcGFyZW50UG9zID0gcGFyZW50VGlsZSAmJiBUaWxlQ29vcmQuZnJvbUlEKHBhcmVudFRpbGUuaWQpO1xuICAgICAgICBwYXJlbnRTY2FsZUJ5ID0gTWF0aC5wb3coMiwgcGFyZW50UG9zLnogLSB0aWxlUG9zLnopO1xuICAgICAgICBwYXJlbnRUTCA9IFt0aWxlUG9zLnggKiBwYXJlbnRTY2FsZUJ5ICUgMSwgdGlsZVBvcy55ICogcGFyZW50U2NhbGVCeSAlIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wYWNpdGllc1sxXSA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGJ1ZmZlclNjYWxlID0gYnVja2V0LnByZXJlbmRlcmVkID8gKDQwOTYgKiAoMSArIDIgKiBidWNrZXQucHJlcmVuZGVyZWQuYnVmZmVyKSkgLyA0MDk2IDogMTtcblxuICAgIC8vIGNyb3NzLWZhZGUgcGFyYW1ldGVyc1xuICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfdGxfcGFyZW50LCBwYXJlbnRUTCB8fCBbMCwgMF0pO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9zY2FsZV9wYXJlbnQsIHBhcmVudFNjYWxlQnkgfHwgMSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlcl9zY2FsZSwgYnVmZmVyU2NhbGUpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5MCwgb3BhY2l0aWVzWzBdKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eTEsIG9wYWNpdGllc1sxXSk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlMCwgMCk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlMSwgMSk7XG5cbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGV4dHVyZS5ib3VuZHNCdWZmZXIgfHwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcblxuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAgICAgICAgIDIsIGdsLlNIT1JULCBmYWxzZSwgOCwgMCk7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV90ZXh0dXJlX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCA4LCA0KTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xufVxuXG5mdW5jdGlvbiBmaW5kUGFyZW50KHRpbGUpIHtcbiAgICB2YXIgc291cmNlID0gdGlsZS5zb3VyY2U7XG4gICAgaWYgKCFzb3VyY2UpIHJldHVybjtcbiAgICB2YXIgcGFyZW50VGlsZXMgPSB7fTtcbiAgICBzb3VyY2UuX2ZpbmRMb2FkZWRQYXJlbnQodGlsZS5pZCwgc291cmNlLm9wdGlvbnMubWluWm9vbSwgcGFyZW50VGlsZXMpO1xuICAgIHJldHVybiBzb3VyY2UudGlsZXNbT2JqZWN0LmtleXMocGFyZW50VGlsZXMpWzBdXTtcbn1cblxuZnVuY3Rpb24gY2xhbXAobiwgbWluLCBtYXgpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihtYXgsIG4pKTtcbn1cblxuZnVuY3Rpb24gc3BpbldlaWdodHMoYW5nbGUpIHtcbiAgICBhbmdsZSAqPSBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBzID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIHZhciBjID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHJldHVybiBbXG4gICAgICAgICgyICogYyArIDEpIC8gMyxcbiAgICAgICAgKC1NYXRoLnNxcnQoMykgKiBzIC0gYyArIDEpIC8gMyxcbiAgICAgICAgKE1hdGguc3FydCgzKSAqIHMgLSBjICsgMSkgLyAzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY29udHJhc3RGYWN0b3IoY29udHJhc3QpIHtcbiAgICByZXR1cm4gY29udHJhc3QgPiAwID9cbiAgICAgICAgMSAvICgxIC0gY29udHJhc3QpIDpcbiAgICAgICAgMSArIGNvbnRyYXN0O1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0aW9uRmFjdG9yKHNhdHVyYXRpb24pIHtcbiAgICByZXR1cm4gc2F0dXJhdGlvbiA+IDAgP1xuICAgICAgICAxIC0gMSAvICgxLjAwMSAtIHNhdHVyYXRpb24pIDpcbiAgICAgICAgLXNhdHVyYXRpb247XG59XG5cbmZ1bmN0aW9uIGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlKSB7XG4gICAgaWYgKCF0aWxlLnNvdXJjZSkgcmV0dXJuIFsxLCAwXTtcblxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICB2YXIgZmFkZUR1cmF0aW9uID0gdGlsZS5zb3VyY2UubWFwLnN0eWxlLnJhc3RlckZhZGVEdXJhdGlvbjtcblxuICAgIHZhciBzaW5jZVRpbGUgPSAobm93IC0gdGlsZS50aW1lQWRkZWQpIC8gZmFkZUR1cmF0aW9uO1xuICAgIHZhciBzaW5jZVBhcmVudCA9IHBhcmVudFRpbGUgPyAobm93IC0gcGFyZW50VGlsZS50aW1lQWRkZWQpIC8gZmFkZUR1cmF0aW9uIDogLTE7XG5cbiAgICB2YXIgdGlsZVBvcyA9IFRpbGVDb29yZC5mcm9tSUQodGlsZS5pZCk7XG4gICAgdmFyIHBhcmVudFBvcyA9IHBhcmVudFRpbGUgJiYgVGlsZUNvb3JkLmZyb21JRChwYXJlbnRUaWxlLmlkKTtcblxuICAgIHZhciBpZGVhbFogPSB0aWxlLnNvdXJjZS5fY292ZXJpbmdab29tTGV2ZWwodGlsZS5zb3VyY2UuX2dldFpvb20oKSk7XG4gICAgdmFyIHBhcmVudEZ1cnRoZXIgPSBwYXJlbnRUaWxlID8gTWF0aC5hYnMocGFyZW50UG9zLnogLSBpZGVhbFopID4gTWF0aC5hYnModGlsZVBvcy56IC0gaWRlYWxaKSA6IGZhbHNlO1xuXG4gICAgdmFyIG9wYWNpdHkgPSBbXTtcbiAgICBpZiAoIXBhcmVudFRpbGUgfHwgcGFyZW50RnVydGhlcikge1xuICAgICAgICAvLyBpZiBubyBwYXJlbnQgb3IgcGFyZW50IGlzIG9sZGVyXG4gICAgICAgIG9wYWNpdHlbMF0gPSBjbGFtcChzaW5jZVRpbGUsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIHlvdW5nZXIsIHpvb21pbmcgb3V0XG4gICAgICAgIG9wYWNpdHlbMF0gPSBjbGFtcCgxIC0gc2luY2VQYXJlbnQsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wYWNpdHk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyLmpzJyk7XG52YXIgbWF0NCA9IHJlcXVpcmUoJy4uL2xpYi9nbG1hdHJpeC5qcycpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd1N5bWJvbHM7XG5cbmZ1bmN0aW9uIGRyYXdTeW1ib2xzKGdsLCBwYWludGVyLCBidWNrZXQsIGxheWVyU3R5bGUsIHBvc01hdHJpeCwgcGFyYW1zLCBpbWFnZVNwcml0ZSkge1xuICAgIGdsLmRpc2FibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgICBpZiAoYnVja2V0LmVsZW1lbnRHcm91cHMudGV4dC5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2woZ2wsIHBhaW50ZXIsIGJ1Y2tldCwgbGF5ZXJTdHlsZSwgcG9zTWF0cml4LCBwYXJhbXMsIGltYWdlU3ByaXRlLCAndGV4dCcpO1xuICAgIH1cbiAgICBpZiAoYnVja2V0LmVsZW1lbnRHcm91cHMuaWNvbi5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2woZ2wsIHBhaW50ZXIsIGJ1Y2tldCwgbGF5ZXJTdHlsZSwgcG9zTWF0cml4LCBwYXJhbXMsIGltYWdlU3ByaXRlLCAnaWNvbicpO1xuICAgIH1cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbn1cblxudmFyIGRlZmF1bHRTaXplcyA9IHtcbiAgICBpY29uOiAxLFxuICAgIHRleHQ6IDI0XG59O1xuXG5mdW5jdGlvbiBkcmF3U3ltYm9sKGdsLCBwYWludGVyLCBidWNrZXQsIGxheWVyU3R5bGUsIHBvc01hdHJpeCwgcGFyYW1zLCBpbWFnZVNwcml0ZSwgcHJlZml4KSB7XG5cbiAgICBwb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHBhcmFtcy56LCBsYXllclN0eWxlW3ByZWZpeCArICctdHJhbnNsYXRlJ10sIGxheWVyU3R5bGVbcHJlZml4ICsgJy10cmFuc2xhdGUtYW5jaG9yJ10pO1xuXG4gICAgdmFyIGluZm8gPSBidWNrZXQuaW5mbztcblxuICAgIHZhciBleE1hdHJpeCA9IG1hdDQuY2xvbmUocGFpbnRlci5wcm9qZWN0aW9uTWF0cml4KTtcbiAgICB2YXIgYWxpZ25lZFdpdGhNYXAgPSBpbmZvW3ByZWZpeCArICctcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnO1xuICAgIHZhciBhbmdsZU9mZnNldCA9IChhbGlnbmVkV2l0aE1hcCA/IHBhaW50ZXIudHJhbnNmb3JtLmFuZ2xlIDogMCk7XG5cbiAgICBpZiAoYW5nbGVPZmZzZXQpIHtcbiAgICAgICAgbWF0NC5yb3RhdGVaKGV4TWF0cml4LCBleE1hdHJpeCwgYW5nbGVPZmZzZXQpO1xuICAgIH1cblxuICAgIC8vIElmIGxheWVyU3R5bGUuc2l6ZSA+IGluZm9bcHJlZml4ICsgJy1tYXgtc2l6ZSddIHRoZW4gbGFiZWxzIG1heSBjb2xsaWRlXG4gICAgdmFyIGZvbnRTaXplID0gbGF5ZXJTdHlsZVtwcmVmaXggKyAnLXNpemUnXSB8fCBpbmZvW3ByZWZpeCArICctbWF4LXNpemUnXTtcbiAgICB2YXIgZm9udFNjYWxlID0gZm9udFNpemUgLyBkZWZhdWx0U2l6ZXNbcHJlZml4XTtcbiAgICBtYXQ0LnNjYWxlKGV4TWF0cml4LCBleE1hdHJpeCwgWyBmb250U2NhbGUsIGZvbnRTY2FsZSwgMSBdKTtcblxuICAgIHZhciB0ZXh0ID0gcHJlZml4ID09PSAndGV4dCc7XG4gICAgdmFyIHNkZiA9IHRleHQgfHwgYnVja2V0LmVsZW1lbnRHcm91cHMuc2RmSWNvbnM7XG4gICAgdmFyIHNoYWRlciwgYnVmZmVyLCB0ZXhzaXplO1xuXG4gICAgaWYgKCF0ZXh0ICYmICFpbWFnZVNwcml0ZS5sb2FkZWQoKSlcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG5cbiAgICBpZiAoc2RmKSB7XG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIuc2RmU2hhZGVyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIuaWNvblNoYWRlcjtcbiAgICB9XG5cbiAgICBpZiAodGV4dCkge1xuICAgICAgICBwYWludGVyLmdseXBoQXRsYXMudXBkYXRlVGV4dHVyZShnbCk7XG4gICAgICAgIGJ1ZmZlciA9IGJ1Y2tldC5idWZmZXJzLmdseXBoVmVydGV4O1xuICAgICAgICB0ZXhzaXplID0gW3BhaW50ZXIuZ2x5cGhBdGxhcy53aWR0aCAvIDQsIHBhaW50ZXIuZ2x5cGhBdGxhcy5oZWlnaHQgLyA0XTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpbWFnZVNwcml0ZS5iaW5kKGdsLCBhbGlnbmVkV2l0aE1hcCB8fCBwYXJhbXMucm90YXRpbmcgfHwgcGFyYW1zLnpvb21pbmcgfHwgZm9udFNjYWxlICE9IDEgfHwgc2RmKTtcbiAgICAgICAgYnVmZmVyID0gYnVja2V0LmJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgdGV4c2l6ZSA9IFtpbWFnZVNwcml0ZS5pbWcud2lkdGgsIGltYWdlU3ByaXRlLmltZy5oZWlnaHRdO1xuICAgIH1cblxuICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCwgZXhNYXRyaXgpO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV90ZXh0dXJlLCAwKTtcbiAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3RleHNpemUsIHRleHNpemUpO1xuXG4gICAgYnVmZmVyLmJpbmQoZ2wpO1xuXG4gICAgdmFyIHVieXRlID0gZ2wuVU5TSUdORURfQllURTtcblxuICAgIHZhciBzdHJpZGUgPSB0ZXh0ID8gMTYgOiAyMDtcblxuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAgICAgICAgICAyLCBnbC5TSE9SVCwgZmFsc2UsIHN0cmlkZSwgMCk7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsICAgICAgIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCA0KTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2xhYmVsbWluem9vbSwgMSwgdWJ5dGUsICAgIGZhbHNlLCBzdHJpZGUsIDgpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfbWluem9vbSwgICAgICAxLCB1Ynl0ZSwgICAgZmFsc2UsIHN0cmlkZSwgOSk7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9tYXh6b29tLCAgICAgIDEsIHVieXRlLCAgICBmYWxzZSwgc3RyaWRlLCAxMCk7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9hbmdsZSwgICAgICAgIDEsIHVieXRlLCAgICBmYWxzZSwgc3RyaWRlLCAxMSk7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9yYW5nZWVuZCwgICAgIDEsIHVieXRlLCAgICBmYWxzZSwgc3RyaWRlLCAxMik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9yYW5nZXN0YXJ0LCAgIDEsIHVieXRlLCAgICBmYWxzZSwgc3RyaWRlLCAxMyk7XG5cbiAgICBpZiAodGV4dCkge1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3RleCwgICAgICAgICAgMiwgdWJ5dGUsICAgICBmYWxzZSwgc3RyaWRlLCAxNCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV90ZXgsICAgICAgICAgIDIsIGdsLlNIT1JULCAgZmFsc2UsIHN0cmlkZSwgMTYpO1xuICAgIH1cblxuICAgIC8vIENvbnZlcnQgdGhlIC1waS4ucGkgdG8gYW4gaW50OCByYW5nZS5cbiAgICB2YXIgYW5nbGUgPSBNYXRoLnJvdW5kKChwYWludGVyLnRyYW5zZm9ybS5hbmdsZSkgLyBNYXRoLlBJICogMTI4KTtcblxuICAgIC8vIGFkanVzdCBtaW4vbWF4IHpvb21zIGZvciB2YXJpYWJsZSBmb250IHNpZXNcbiAgICB2YXIgem9vbUFkanVzdCA9IE1hdGgubG9nKGZvbnRTaXplIC8gaW5mb1twcmVmaXggKyAnLW1heC1zaXplJ10pIC8gTWF0aC5MTjIgfHwgMDtcblxuICAgIHZhciBmbGlwID0gYWxpZ25lZFdpdGhNYXAgJiYgaW5mb1twcmVmaXggKyAnLWtlZXAtdXByaWdodCddO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mbGlwLCBmbGlwID8gMSA6IDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9hbmdsZSwgKGFuZ2xlICsgMjU2KSAlIDI1Nik7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3pvb20sIChwYWludGVyLnRyYW5zZm9ybS56b29tIC0gem9vbUFkanVzdCkgKiAxMCk7IC8vIGN1cnJlbnQgem9vbSBsZXZlbFxuXG4gICAgdmFyIGYgPSBwYWludGVyLmZyYW1lSGlzdG9yeS5nZXRGYWRlUHJvcGVydGllcygzMDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlZGlzdCwgZi5mYWRlZGlzdCAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWluZmFkZXpvb20sIE1hdGguZmxvb3IoZi5taW5mYWRlem9vbSAqIDEwKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21heGZhZGV6b29tLCBNYXRoLmZsb29yKGYubWF4ZmFkZXpvb20gKiAxMCkpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlem9vbSwgKHBhaW50ZXIudHJhbnNmb3JtLnpvb20gKyBmLmJ1bXApICogMTApO1xuXG4gICAgaWYgKCFzZGYpIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBsYXllclN0eWxlWydpY29uLW9wYWNpdHknXSk7XG5cbiAgICB2YXIgc2RmRm9udFNpemUgPSB0ZXh0ID8gMjQgOiAxO1xuICAgIHZhciBzZGZQeCA9IDg7XG4gICAgdmFyIGJsdXJPZmZzZXQgPSAxLjE5O1xuICAgIHZhciBoYWxvT2Zmc2V0ID0gNjtcblxuICAgIGlmIChzZGYpIHtcblxuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZ2FtbWEsIDAuMTA1ICogc2RmRm9udFNpemUgLyBmb250U2l6ZSAvIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm00ZnYoc2hhZGVyLnVfY29sb3IsIGxheWVyU3R5bGVbcHJlZml4ICsgJy1jb2xvciddKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKDI1NiAtIDY0KSAvIDI1Nik7XG4gICAgfVxuXG4gICAgdmFyIGJlZ2luID0gYnVja2V0LmVsZW1lbnRHcm91cHNbcHJlZml4XS5ncm91cHNbMF0udmVydGV4U3RhcnRJbmRleCxcbiAgICAgICAgbGVuID0gYnVja2V0LmVsZW1lbnRHcm91cHNbcHJlZml4XS5ncm91cHNbMF0udmVydGV4TGVuZ3RoO1xuXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIGJlZ2luLCBsZW4pO1xuXG4gICAgaWYgKHNkZiAmJiBsYXllclN0eWxlW3ByZWZpeCArICctaGFsby1jb2xvciddKSB7XG4gICAgICAgIC8vIERyYXcgaGFsbyB1bmRlcm5lYXRoIHRoZSB0ZXh0LlxuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZ2FtbWEsIChsYXllclN0eWxlW3ByZWZpeCArICctaGFsby1ibHVyJ10gKiBibHVyT2Zmc2V0IC8gKGZvbnRTaXplIC8gc2RmRm9udFNpemUpIC8gc2RmUHgpICsgKDAuMTA1ICogc2RmRm9udFNpemUgLyBmb250U2l6ZSkgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBsYXllclN0eWxlW3ByZWZpeCArICctaGFsby1jb2xvciddKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKGhhbG9PZmZzZXQgLSBsYXllclN0eWxlW3ByZWZpeCArICctaGFsby13aWR0aCddIC8gKGZvbnRTaXplIC8gc2RmRm9udFNpemUpKSAvIHNkZlB4KTtcblxuICAgICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgYmVnaW4sIGxlbik7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3Nlci5qcycpO1xudmFyIG1hdDQgPSByZXF1aXJlKCcuLi9saWIvZ2xtYXRyaXguanMnKS5tYXQ0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdWZXJ0aWNlcztcblxuZnVuY3Rpb24gZHJhd1ZlcnRpY2VzKGdsLCBwYWludGVyLCBidWNrZXQpIHtcbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIGdsLnN3aXRjaFNoYWRlcihwYWludGVyLmRvdFNoYWRlciwgcGFpbnRlci50aWxlLnBvc01hdHJpeCwgcGFpbnRlci50aWxlLmV4TWF0cml4KTtcblxuICAgIC8vIC8vIERyYXcgZGVidWcgcG9pbnRzLlxuICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X3NpemUsIDQgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X2JsdXIsIDAuMjUpO1xuICAgIGdsLnVuaWZvcm00ZnYocGFpbnRlci5kb3RTaGFkZXIudV9jb2xvciwgWzAuMjUsIDAsIDAsIDAuMjVdKTtcblxuICAgIC8vIERyYXcgdGhlIGFjdHVhbCB0cmlhbmdsZSBmYW4gaW50byB0aGUgc3RlbmNpbCBidWZmZXIuXG5cbiAgICB2YXIgdmVydGV4LCBncm91cHMsIGdyb3VwLCBiZWdpbiwgY291bnQ7XG5cbiAgICAvLyBEcmF3IGFsbCBidWZmZXJzXG4gICAgaWYgKGJ1Y2tldC5pbmZvLmZpbGwpIHtcbiAgICAgICAgdmVydGV4ID0gYnVja2V0LmJ1ZmZlcnMuZmlsbFZlcnRleDtcbiAgICAgICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgICAgICBncm91cHMgPSBidWNrZXQuZWxlbWVudEdyb3Vwcy5ncm91cHM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBncm91cCA9IGdyb3Vwc1tpXTtcbiAgICAgICAgICAgIGJlZ2luID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAudmVydGV4TGVuZ3RoO1xuICAgICAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmRvdFNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCBiZWdpbiwgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG5ld1Bvc01hdHJpeCA9IG1hdDQuY2xvbmUocGFpbnRlci50aWxlLnBvc01hdHJpeCk7XG4gICAgbWF0NC5zY2FsZShuZXdQb3NNYXRyaXgsIG5ld1Bvc01hdHJpeCwgWzAuNSwgMC41LCAxXSk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5kb3RTaGFkZXIsIG5ld1Bvc01hdHJpeCwgcGFpbnRlci50aWxlLmV4TWF0cml4KTtcblxuICAgIC8vIERyYXcgYWxsIGxpbmUgYnVmZmVyc1xuICAgIGlmIChidWNrZXQuaW5mby5saW5lKSB7XG4gICAgICAgIHZlcnRleCA9IGJ1Y2tldC5idWZmZXJzLmxpbmVWZXJ0ZXg7XG4gICAgICAgIHZlcnRleC5iaW5kKGdsKTtcbiAgICAgICAgZ3JvdXBzID0gYnVja2V0LmVsZW1lbnRHcm91cHMuZ3JvdXBzO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGdyb3Vwcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgZ3JvdXAgPSBncm91cHNba107XG4gICAgICAgICAgICBiZWdpbiA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnZlcnRleExlbmd0aDtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kb3RTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgICAgICAgICBnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgYmVnaW4sIGNvdW50KTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gRnJhbWVIaXN0b3J5O1xuXG5mdW5jdGlvbiBGcmFtZUhpc3RvcnkoKSB7XG59XG5cbkZyYW1lSGlzdG9yeS5wcm90b3R5cGUuZ2V0RmFkZVByb3BlcnRpZXMgPSBmdW5jdGlvbihkdXJhdGlvbikge1xuICAgIGlmIChkdXJhdGlvbiA9PT0gdW5kZWZpbmVkKSBkdXJhdGlvbiA9IDMwMDtcbiAgICB2YXIgY3VycmVudFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgLy8gUmVtb3ZlIGZyYW1lcyB1bnRpbCBvbmx5IG9uZSBpcyBvdXRzaWRlIHRoZSBkdXJhdGlvbiwgb3IgdW50aWwgdGhlcmUgYXJlIG9ubHkgdGhyZWVcbiAgICB3aGlsZSAoZnJhbWVIaXN0b3J5Lmxlbmd0aCA+IDMgJiYgZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIGZyYW1lSGlzdG9yeS5zaGlmdCgpO1xuICAgIH1cblxuICAgIGlmIChmcmFtZUhpc3RvcnlbMV0udGltZSArIGR1cmF0aW9uIDwgY3VycmVudFRpbWUpIHtcbiAgICAgICAgZnJhbWVIaXN0b3J5WzBdLnogPSBmcmFtZUhpc3RvcnlbMV0uejtcbiAgICB9XG5cbiAgICB2YXIgZnJhbWVMZW4gPSBmcmFtZUhpc3RvcnkubGVuZ3RoO1xuICAgIGlmIChmcmFtZUxlbiA8IDMpIGNvbnNvbGUud2FybigndGhlcmUgc2hvdWxkIG5ldmVyIGJlIGxlc3MgdGhhbiB0aHJlZSBmcmFtZXMgaW4gdGhlIGhpc3RvcnknKTtcblxuICAgIC8vIEZpbmQgdGhlIHJhbmdlIG9mIHpvb20gbGV2ZWxzIHdlIHdhbnQgdG8gZmFkZSBiZXR3ZWVuXG4gICAgdmFyIHN0YXJ0aW5nWiA9IGZyYW1lSGlzdG9yeVswXS56LFxuICAgICAgICBsYXN0RnJhbWUgPSBmcmFtZUhpc3RvcnlbZnJhbWVMZW4gLSAxXSxcbiAgICAgICAgZW5kaW5nWiA9IGxhc3RGcmFtZS56LFxuICAgICAgICBsb3daID0gTWF0aC5taW4oc3RhcnRpbmdaLCBlbmRpbmdaKSxcbiAgICAgICAgaGlnaFogPSBNYXRoLm1heChzdGFydGluZ1osIGVuZGluZ1opO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBzcGVlZCBvZiB6b29taW5nLCBhbmQgaG93IGZhciBpdCB3b3VsZCB6b29tIGluIHRlcm1zIG9mIHpvb20gbGV2ZWxzIGluIG9uZSBkdXJhdGlvblxuICAgIHZhciB6b29tRGlmZiA9IGxhc3RGcmFtZS56IC0gZnJhbWVIaXN0b3J5WzFdLnosXG4gICAgICAgIHRpbWVEaWZmID0gbGFzdEZyYW1lLnRpbWUgLSBmcmFtZUhpc3RvcnlbMV0udGltZTtcbiAgICB2YXIgZmFkZWRpc3QgPSB6b29tRGlmZiAvICh0aW1lRGlmZiAvIGR1cmF0aW9uKTtcblxuICAgIGlmIChpc05hTihmYWRlZGlzdCkpIGNvbnNvbGUud2FybignZmFkZWRpc3Qgc2hvdWxkIG5ldmVyIGJlIE5hTicpO1xuXG4gICAgLy8gQXQgZW5kIG9mIGEgem9vbSB3aGVuIHRoZSB6b29tIHN0b3BzIGNoYW5naW5nIGNvbnRpbnVlIHByZXRlbmRpbmcgdG8gem9vbSBhdCB0aGF0IHNwZWVkXG4gICAgLy8gYnVtcCBpcyBob3cgbXVjaCBmYXJ0aGVyIGl0IHdvdWxkIGhhdmUgYmVlbiBpZiBpdCBoYWQgY29udGludWVkIHpvb21pbmcgYXQgdGhlIHNhbWUgcmF0ZVxuICAgIHZhciBidW1wID0gKGN1cnJlbnRUaW1lIC0gbGFzdEZyYW1lLnRpbWUpIC8gZHVyYXRpb24gKiBmYWRlZGlzdDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhZGVkaXN0OiBmYWRlZGlzdCxcbiAgICAgICAgbWluZmFkZXpvb206IGxvd1osXG4gICAgICAgIG1heGZhZGV6b29tOiBoaWdoWixcbiAgICAgICAgYnVtcDogYnVtcFxuICAgIH07XG59O1xuXG4vLyBTdG9yZSBwcmV2aW91cyByZW5kZXIgdGltZXNcbnZhciBmcmFtZUhpc3RvcnkgPSBbXTtcblxuLy8gUmVjb3JkIGZyYW1lIGhpc3RvcnkgdGhhdCB3aWxsIGJlIHVzZWQgdG8gY2FsY3VsYXRlIGZhZGluZyBwYXJhbXNcbkZyYW1lSGlzdG9yeS5wcm90b3R5cGUucmVjb3JkID0gZnVuY3Rpb24oem9vbSkge1xuICAgIHZhciBjdXJyZW50VGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBmaXJzdCBmcmFtZSBldmVyXG4gICAgaWYgKCFmcmFtZUhpc3RvcnkubGVuZ3RoKSB7XG4gICAgICAgIGZyYW1lSGlzdG9yeS5wdXNoKHt0aW1lOiAwLCB6OiB6b29tIH0sIHt0aW1lOiAwLCB6OiB6b29tIH0pO1xuICAgIH1cblxuICAgIGlmIChmcmFtZUhpc3RvcnkubGVuZ3RoID09PSAyIHx8IGZyYW1lSGlzdG9yeVtmcmFtZUhpc3RvcnkubGVuZ3RoIC0gMV0ueiAhPT0gem9vbSkge1xuICAgICAgICBmcmFtZUhpc3RvcnkucHVzaCh7XG4gICAgICAgICAgICB0aW1lOiBjdXJyZW50VGltZSxcbiAgICAgICAgICAgIHo6IHpvb21cbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycy5qcycpO1xuXG5leHBvcnRzLmV4dGVuZCA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgICBjb250ZXh0LmdldFNoYWRlciA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUpIHtcbiAgICAgICAgdmFyIGtpbmQgPSB0eXBlID09IHRoaXMuRlJBR01FTlRfU0hBREVSID8gJ2ZyYWdtZW50JyA6ICd2ZXJ0ZXgnO1xuICAgICAgICBpZiAoIXNoYWRlcnNbbmFtZV0gfHwgIXNoYWRlcnNbbmFtZV1ba2luZF0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBmaW5kIHNoYWRlciBcIiArIG5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNoYWRlciA9IHRoaXMuY3JlYXRlU2hhZGVyKHR5cGUpO1xuICAgICAgICB0aGlzLnNoYWRlclNvdXJjZShzaGFkZXIsIHNoYWRlcnNbbmFtZV1ba2luZF0pO1xuICAgICAgICB0aGlzLmNvbXBpbGVTaGFkZXIoc2hhZGVyKTtcbiAgICAgICAgaWYgKCF0aGlzLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIHRoaXMuQ09NUElMRV9TVEFUVVMpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5nZXRTaGFkZXJJbmZvTG9nKHNoYWRlcikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfTtcblxuICAgIGNvbnRleHQuaW5pdGlhbGl6ZVNoYWRlciA9IGZ1bmN0aW9uKG5hbWUsIGF0dHJpYnV0ZXMsIHVuaWZvcm1zKSB7XG4gICAgICAgIHZhciBzaGFkZXIgPSB7XG4gICAgICAgICAgICBwcm9ncmFtOiB0aGlzLmNyZWF0ZVByb2dyYW0oKSxcbiAgICAgICAgICAgIGZyYWdtZW50OiB0aGlzLmdldFNoYWRlcihuYW1lLCB0aGlzLkZSQUdNRU5UX1NIQURFUiksXG4gICAgICAgICAgICB2ZXJ0ZXg6IHRoaXMuZ2V0U2hhZGVyKG5hbWUsIHRoaXMuVkVSVEVYX1NIQURFUiksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiBbXVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmF0dGFjaFNoYWRlcihzaGFkZXIucHJvZ3JhbSwgc2hhZGVyLnZlcnRleCk7XG4gICAgICAgIHRoaXMuYXR0YWNoU2hhZGVyKHNoYWRlci5wcm9ncmFtLCBzaGFkZXIuZnJhZ21lbnQpO1xuICAgICAgICB0aGlzLmxpbmtQcm9ncmFtKHNoYWRlci5wcm9ncmFtKTtcblxuICAgICAgICBpZiAoIXRoaXMuZ2V0UHJvZ3JhbVBhcmFtZXRlcihzaGFkZXIucHJvZ3JhbSwgdGhpcy5MSU5LX1NUQVRVUykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IodGhpcy5nZXRQcm9ncmFtSW5mb0xvZyhzaGFkZXIucHJvZ3JhbSkpO1xuICAgICAgICAgICAgYWxlcnQoXCJDb3VsZCBub3QgaW5pdGlhbGl6ZSBzaGFkZXIgXCIgKyBuYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNoYWRlclthdHRyaWJ1dGVzW2ldXSA9IHRoaXMuZ2V0QXR0cmliTG9jYXRpb24oc2hhZGVyLnByb2dyYW0sIGF0dHJpYnV0ZXNbaV0pO1xuICAgICAgICAgICAgICAgIHNoYWRlci5hdHRyaWJ1dGVzLnB1c2goc2hhZGVyW2F0dHJpYnV0ZXNbaV1dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdW5pZm9ybXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJbdW5pZm9ybXNba11dID0gdGhpcy5nZXRVbmlmb3JtTG9jYXRpb24oc2hhZGVyLnByb2dyYW0sIHVuaWZvcm1zW2tdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfTtcblxuICAgIC8vIFN3aXRjaGVzIHRvIGEgZGlmZmVyZW50IHNoYWRlciBwcm9ncmFtLlxuICAgIGNvbnRleHQuc3dpdGNoU2hhZGVyID0gZnVuY3Rpb24oc2hhZGVyLCBwb3NNYXRyaXgsIGV4TWF0cml4KSB7XG4gICAgICAgIGlmICghcG9zTWF0cml4KSB7XG4gICAgICAgICAgICBjb25zb2xlLnRyYWNlKCdwb3NNYXRyaXggZG9lcyBub3QgaGF2ZSByZXF1aXJlZCBhcmd1bWVudCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuY3VycmVudFNoYWRlciAhPT0gc2hhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLnVzZVByb2dyYW0oc2hhZGVyLnByb2dyYW0pO1xuXG4gICAgICAgICAgICAvLyBEaXNhYmxlIGFsbCBhdHRyaWJ1dGVzIGZyb20gdGhlIGV4aXN0aW5nIHNoYWRlciB0aGF0IGFyZW4ndCB1c2VkIGluXG4gICAgICAgICAgICAvLyB0aGUgbmV3IHNoYWRlci4gTm90ZTogYXR0cmlidXRlIGluZGljZXMgYXJlICpub3QqIHByb2dyYW0gc3BlY2lmaWMhXG4gICAgICAgICAgICB2YXIgZW5hYmxlZCA9IHRoaXMuY3VycmVudFNoYWRlciA/IHRoaXMuY3VycmVudFNoYWRlci5hdHRyaWJ1dGVzIDogW107XG4gICAgICAgICAgICB2YXIgcmVxdWlyZWQgPSBzaGFkZXIuYXR0cmlidXRlcztcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbmFibGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlcXVpcmVkLmluZGV4T2YoZW5hYmxlZFtpXSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGVuYWJsZWRbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRW5hYmxlIGFsbCBhdHRyaWJ1dGVzIGZvciB0aGUgbmV3IHNoYWRlci5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcmVxdWlyZWQubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZW5hYmxlZC5pbmRleE9mKHJlcXVpcmVkW2pdKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShyZXF1aXJlZFtqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRTaGFkZXIgPSBzaGFkZXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgdGhlIG1hdHJpY2VzIGlmIG5lY2Vzc2FyeS4gTm90ZTogVGhpcyByZWxpZXMgb24gb2JqZWN0IGlkZW50aXR5IVxuICAgICAgICAvLyBUaGlzIG1lYW5zIGNoYW5naW5nIHRoZSBtYXRyaXggdmFsdWVzIHdpdGhvdXQgdGhlIGFjdHVhbCBtYXRyaXggb2JqZWN0XG4gICAgICAgIC8vIHdpbGwgRkFJTCB0byB1cGRhdGUgdGhlIG1hdHJpeCBwcm9wZXJseS5cbiAgICAgICAgaWYgKHNoYWRlci5wb3NNYXRyaXggIT09IHBvc01hdHJpeCkge1xuICAgICAgICAgICAgdGhpcy51bmlmb3JtTWF0cml4NGZ2KHNoYWRlci51X3Bvc21hdHJpeCwgZmFsc2UsIHBvc01hdHJpeCk7XG4gICAgICAgICAgICBzaGFkZXIucG9zTWF0cml4ID0gcG9zTWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChleE1hdHJpeCAmJiBzaGFkZXIuZXhNYXRyaXggIT09IGV4TWF0cml4ICYmIHNoYWRlci51X2V4bWF0cml4KSB7XG4gICAgICAgICAgICB0aGlzLnVuaWZvcm1NYXRyaXg0ZnYoc2hhZGVyLnVfZXhtYXRyaXgsIGZhbHNlLCBleE1hdHJpeCk7XG4gICAgICAgICAgICBzaGFkZXIuZXhNYXRyaXggPSBleE1hdHJpeDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gY29udGV4dDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbHV0aWwgPSByZXF1aXJlKCcuL2dsdXRpbC5qcycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXIuanMnKTtcbnZhciBHbHlwaEF0bGFzID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoYXRsYXMuanMnKTtcbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJy4uL2xpYi9nbG1hdHJpeC5qcycpO1xudmFyIEZyYW1lSGlzdG9yeSA9IHJlcXVpcmUoJy4vZnJhbWVoaXN0b3J5LmpzJyk7XG5cbnZhciBtYXQ0ID0gZ2xtYXRyaXgubWF0NDtcblxudmFyIGRyYXdTeW1ib2wgPSByZXF1aXJlKCcuL2RyYXdzeW1ib2wuanMnKTtcbnZhciBkcmF3TGluZSA9IHJlcXVpcmUoJy4vZHJhd2xpbmUuanMnKTtcbnZhciBkcmF3RmlsbCA9IHJlcXVpcmUoJy4vZHJhd2ZpbGwuanMnKTtcbnZhciBkcmF3UmFzdGVyID0gcmVxdWlyZSgnLi9kcmF3cmFzdGVyLmpzJyk7XG52YXIgZHJhd0RlYnVnID0gcmVxdWlyZSgnLi9kcmF3ZGVidWcuanMnKTtcbnZhciBkcmF3QmFja2dyb3VuZCA9IHJlcXVpcmUoJy4vZHJhd2JhY2tncm91bmQuanMnKTtcbnZhciBkcmF3Q29tcG9zaXRlZCA9IHJlcXVpcmUoJy4vZHJhd2NvbXBvc2l0ZWQuanMnKTtcbnZhciBkcmF3VmVydGljZXMgPSByZXF1aXJlKCcuL2RyYXd2ZXJ0aWNlcy5qcycpO1xuXG4vKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBwYWludGVyIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0NhbnZhc30gZ2wgYW4gZXhwZXJpbWVudGFsLXdlYmdsIGRyYXdpbmcgY29udGV4dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEdMUGFpbnRlcjtcbmZ1bmN0aW9uIEdMUGFpbnRlcihnbCwgdHJhbnNmb3JtKSB7XG4gICAgdGhpcy5nbCA9IGdsdXRpbC5leHRlbmQoZ2wpO1xuICAgIHRoaXMudHJhbnNmb3JtID0gdHJhbnNmb3JtO1xuXG4gICAgdGhpcy5mcmFtZWJ1ZmZlck9iamVjdCA9IG51bGw7XG4gICAgdGhpcy5yZW5kZXJUZXh0dXJlcyA9IFtdO1xuICAgIHRoaXMubmFtZWRSZW5kZXJUZXh0dXJlcyA9IHt9O1xuICAgIHRoaXMucmV1c2FibGVUZXh0dXJlcyA9IHt9O1xuICAgIHRoaXMucHJlRmJvcyA9IHt9O1xuXG4gICAgdGhpcy50aWxlRXh0ZW50ID0gNDA5NjtcbiAgICB0aGlzLmZyYW1lSGlzdG9yeSA9IG5ldyBGcmFtZUhpc3RvcnkoKTtcblxuICAgIHRoaXMuc2V0dXAoKTtcbn1cblxuLypcbiAqIFVwZGF0ZSB0aGUgR0wgdmlld3BvcnQsIHByb2plY3Rpb24gbWF0cml4LCBhbmQgdHJhbnNmb3JtcyB0byBjb21wZW5zYXRlXG4gKiBmb3IgYSBuZXcgd2lkdGggYW5kIGhlaWdodCB2YWx1ZS5cbiAqL1xuR0xQYWludGVyLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICAvLyBJbml0aWFsaXplIHByb2plY3Rpb24gbWF0cml4XG4gICAgdGhpcy5wcm9qZWN0aW9uTWF0cml4ID0gbWF0NC5jcmVhdGUoKTtcbiAgICBtYXQ0Lm9ydGhvKHRoaXMucHJvamVjdGlvbk1hdHJpeCwgMCwgd2lkdGgsIGhlaWdodCwgMCwgMCwgLTEpO1xuXG4gICAgdGhpcy53aWR0aCA9IHdpZHRoICogYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0ICogYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvO1xuICAgIGdsLnZpZXdwb3J0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcblxuICAgIGZvciAodmFyIGkgPSB0aGlzLnJlbmRlclRleHR1cmVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGdsLmRlbGV0ZVRleHR1cmUodGhpcy5yZW5kZXJUZXh0dXJlcy5wb3AoKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnN0ZW5jaWxCdWZmZXIpIHtcbiAgICAgICAgZ2wuZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMuc3RlbmNpbEJ1ZmZlcik7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0ZW5jaWxCdWZmZXI7XG4gICAgfVxufTtcblxuXG5HTFBhaW50ZXIucHJvdG90eXBlLnNldHVwID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcblxuICAgIGdsLnZlcmJvc2UgPSB0cnVlO1xuXG4gICAgLy8gV2UgYXJlIGJsZW5kaW5nIHRoZSBuZXcgcGl4ZWxzICpiZWhpbmQqIHRoZSBleGlzdGluZyBwaXhlbHMuIFRoYXQgd2F5IHdlIGNhblxuICAgIC8vIGRyYXcgZnJvbnQtdG8tYmFjayBhbmQgdXNlIHRoZW4gc3RlbmNpbCBidWZmZXIgdG8gY3VsbCBvcGFxdWUgcGl4ZWxzIGVhcmx5LlxuICAgIGdsLmVuYWJsZShnbC5CTEVORCk7XG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG5cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcblxuICAgIHRoaXMuZ2x5cGhBdGxhcyA9IG5ldyBHbHlwaEF0bGFzKDEwMjQsIDEwMjQpO1xuICAgIC8vIHRoaXMuZ2x5cGhBdGxhcy5kZWJ1ZyA9IHRydWU7XG4gICAgdGhpcy5nbHlwaEF0bGFzLmJpbmQoZ2wpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFkZXJzXG4gICAgdGhpcy5kZWJ1Z1NoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2RlYnVnJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfcG9zbWF0cml4JywgJ3VfcG9pbnRzaXplJywgJ3VfY29sb3InXSk7XG5cbiAgICB0aGlzLmNvbXBvc2l0ZVNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2NvbXBvc2l0ZScsXG4gICAgICAgIFsnYV9wb3MnXSxcbiAgICAgICAgWyd1X3Bvc21hdHJpeCcsICd1X29wYWNpdHknXSk7XG5cbiAgICB0aGlzLmdhdXNzaWFuU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZ2F1c3NpYW4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9wb3NtYXRyaXgnLCAndV9vcGFjaXR5JywgJ3VfaW1hZ2UnLCAndV9vZmZzZXQnXSk7XG5cbiAgICB0aGlzLnJhc3RlclNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ3Jhc3RlcicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV90ZXh0dXJlX3BvcyddLFxuICAgICAgICBbJ3VfcG9zbWF0cml4JywgJ3VfYnJpZ2h0bmVzc19sb3cnLCAndV9icmlnaHRuZXNzX2hpZ2gnLCAndV9zYXR1cmF0aW9uX2ZhY3RvcicsICd1X3NwaW5fd2VpZ2h0cycsICd1X2NvbnRyYXN0X2ZhY3RvcicsICd1X29wYWNpdHkwJywgJ3Vfb3BhY2l0eTEnLCAndV9pbWFnZTAnLCAndV9pbWFnZTEnLCAndV90bF9wYXJlbnQnLCAndV9zY2FsZV9wYXJlbnQnLCAndV9idWZmZXJfc2NhbGUnXSk7XG5cbiAgICB0aGlzLmxpbmVTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lJyxcbiAgICAgICAgWydhX3BvcycsICdhX2V4dHJ1ZGUnLCAnYV9saW5lc29mYXInXSxcbiAgICAgICAgWyd1X3Bvc21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfbGluZXdpZHRoJywgJ3VfY29sb3InLCAndV9kZWJ1ZycsICd1X3JhdGlvJywgJ3VfZGFzaGFycmF5JywgJ3VfYmx1ciddKTtcblxuICAgIHRoaXMubGluZXBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9leHRydWRlJywgJ2FfbGluZXNvZmFyJ10sXG4gICAgICAgIFsndV9wb3NtYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X3JhdGlvJywgJ3VfcGF0dGVybl9zaXplJywgJ3VfcGF0dGVybl90bCcsICd1X3BhdHRlcm5fYnInLCAndV9wb2ludCcsICd1X2JsdXInLCAndV9mYWRlJ10pO1xuXG4gICAgdGhpcy5kb3RTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdkb3QnLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9wb3NtYXRyaXgnLCAndV9zaXplJywgJ3VfY29sb3InLCAndV9ibHVyJ10pO1xuXG4gICAgdGhpcy5zZGZTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdzZGYnLFxuICAgICAgICBbJ2FfcG9zJywgJ2FfdGV4JywgJ2Ffb2Zmc2V0JywgJ2FfYW5nbGUnLCAnYV9taW56b29tJywgJ2FfbWF4em9vbScsICdhX3JhbmdlZW5kJywgJ2FfcmFuZ2VzdGFydCcsICdhX2xhYmVsbWluem9vbSddLFxuICAgICAgICBbJ3VfcG9zbWF0cml4JywgJ3VfZXhtYXRyaXgnLCAndV90ZXh0dXJlJywgJ3VfdGV4c2l6ZScsICd1X2NvbG9yJywgJ3VfZ2FtbWEnLCAndV9idWZmZXInLCAndV9hbmdsZScsICd1X3pvb20nLCAndV9mbGlwJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nXSk7XG5cbiAgICB0aGlzLmljb25TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdpY29uJyxcbiAgICAgICAgWydhX3BvcycsICdhX3RleCcsICdhX29mZnNldCcsICdhX2FuZ2xlJywgJ2FfbWluem9vbScsICdhX21heHpvb20nLCAnYV9yYW5nZWVuZCcsICdhX3Jhbmdlc3RhcnQnLCAnYV9sYWJlbG1pbnpvb20nXSxcbiAgICAgICAgWyd1X3Bvc21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV9hbmdsZScsICd1X3pvb20nLCAndV9mbGlwJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nLCAndV9vcGFjaXR5J10pO1xuXG4gICAgdGhpcy5vdXRsaW5lU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignb3V0bGluZScsXG4gICAgICAgIFsnYV9wb3MnXSxcbiAgICAgICAgWyd1X3Bvc21hdHJpeCcsICd1X2NvbG9yJywgJ3Vfd29ybGQnXVxuICAgICk7XG5cbiAgICB0aGlzLnBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdwYXR0ZXJuJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfcG9zbWF0cml4JywgJ3VfcGF0dGVybl90bCcsICd1X3BhdHRlcm5fYnInLCAndV9taXgnLCAndV9wYXR0ZXJubWF0cml4JywgJ3Vfb3BhY2l0eScsICd1X2ltYWdlJ11cbiAgICApO1xuXG4gICAgdGhpcy5maWxsU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZmlsbCcsXG4gICAgICAgIFsnYV9wb3MnXSxcbiAgICAgICAgWyd1X3Bvc21hdHJpeCcsICd1X2NvbG9yJ11cbiAgICApO1xuXG4gICAgdGhpcy5pZGVudGl0eU1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG5cbiAgICAvLyBUaGUgYmFja2dyb3VuZEJ1ZmZlciBpcyB1c2VkIHdoZW4gZHJhd2luZyB0byB0aGUgZnVsbCAqY2FudmFzKlxuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSA9IDI7XG4gICAgdGhpcy5iYWNrZ3JvdW5kQnVmZmVyLml0ZW1Db3VudCA9IDQ7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KFstMSwgLTEsIDEsIC0xLCAtMSwgMSwgMSwgMV0pLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAvLyBUaGUgdGlsZUV4dGVudEJ1ZmZlciBpcyB1c2VkIHdoZW4gZHJhd2luZyB0byBhIGZ1bGwgKnRpbGUqXG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplID0gNDtcbiAgICB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbUNvdW50ID0gNDtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGhpcy50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC5idWZmZXJEYXRhKGdsLkFSUkFZX0JVRkZFUiwgbmV3IEludDE2QXJyYXkoW1xuICAgICAgICAvLyB0aWxlIGNvb3JkIHgsIHRpbGUgY29vcmQgeSwgdGV4dHVyZSBjb29yZCB4LCB0ZXh0dXJlIGNvb3JkIHlcbiAgICAgICAgICAgICAgICAgICAgICAwLCAwLCAgICAgICAgICAgICAgICAgICAgMCwgMCxcbiAgICAgICAgdGhpcy50aWxlRXh0ZW50LCAwLCAgICAgICAgICAgICAgICAzMjc2NywgMCxcbiAgICAgICAgICAgICAgICAgICAgICAwLCB0aGlzLnRpbGVFeHRlbnQsICAgICAgMCwgMzI3NjcsXG4gICAgICAgIHRoaXMudGlsZUV4dGVudCwgdGhpcy50aWxlRXh0ZW50LCAgMzI3NjcsIDMyNzY3XG4gICAgXSksIGdsLlNUQVRJQ19EUkFXKTtcblxuICAgIC8vIFRoZSBkZWJ1Z0J1ZmZlciBpcyB1c2VkIHRvIGRyYXcgdGlsZSBvdXRsaW5lcyBmb3IgZGVidWdnaW5nXG4gICAgdGhpcy5kZWJ1Z0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMuZGVidWdCdWZmZXIuaXRlbVNpemUgPSAyO1xuICAgIHRoaXMuZGVidWdCdWZmZXIuaXRlbUNvdW50ID0gNTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGhpcy5kZWJ1Z0J1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KFswLCAwLCA0MDk1LCAwLCA0MDk1LCA0MDk1LCAwLCA0MDk1LCAwLCAwXSksIGdsLlNUQVRJQ19EUkFXKTtcblxuICAgIC8vIFRoZSBkZWJ1Z1RleHRCdWZmZXIgaXMgdXNlZCB0byBkcmF3IHRpbGUgSURzIGZvciBkZWJ1Z2dpbmdcbiAgICB0aGlzLmRlYnVnVGV4dEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplID0gMjtcbn07XG5cbi8qXG4gKiBSZXNldCB0aGUgY29sb3IgYnVmZmVycyBvZiB0aGUgZHJhd2luZyBjYW52YXMuXG4gKi9cbkdMUGFpbnRlci5wcm90b3R5cGUuY2xlYXJDb2xvciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJDb2xvcigwLCAwLCAwLCAwKTtcbiAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKTtcbn07XG5cbi8qXG4gKiBSZXNldCB0aGUgZHJhd2luZyBjYW52YXMgYnkgY2xlYXJpbmcgdGhlIHN0ZW5jaWwgYnVmZmVyIHNvIHRoYXQgd2UgY2FuIGRyYXdcbiAqIG5ldyB0aWxlcyBhdCB0aGUgc2FtZSBsb2NhdGlvbiwgd2hpbGUgcmV0YWluaW5nIHByZXZpb3VzbHkgZHJhd24gcGl4ZWxzLlxuICovXG5HTFBhaW50ZXIucHJvdG90eXBlLmNsZWFyU3RlbmNpbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhGRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcbn07XG5cbkdMUGFpbnRlci5wcm90b3R5cGUuZHJhd0NsaXBwaW5nTWFzayA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHRoaXMuZmlsbFNoYWRlciwgdGhpcy50aWxlLnBvc01hdHJpeCwgdGhpcy50aWxlLmV4TWF0cml4KTtcbiAgICBnbC5jb2xvck1hc2soZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuXG4gICAgLy8gQ2xlYXIgdGhlIGVudGlyZSBzdGVuY2lsIGJ1ZmZlciwgZXhjZXB0IGZvciB0aGUgN3RoIGJpdCwgd2hpY2ggc3RvcmVzXG4gICAgLy8gdGhlIGdsb2JhbCBjbGlwcGluZyBtYXNrIHRoYXQgYWxsb3dzIHVzIHRvIGF2b2lkIGRyYXdpbmcgaW4gcmVnaW9ucyBvZlxuICAgIC8vIHRpbGVzIHdlJ3ZlIGFscmVhZHkgcGFpbnRlZCBpbi5cbiAgICBnbC5jbGVhclN0ZW5jaWwoMHgwKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweEJGKTtcbiAgICBnbC5jbGVhcihnbC5TVEVOQ0lMX0JVRkZFUl9CSVQpO1xuXG4gICAgLy8gVGhlIHN0ZW5jaWwgdGVzdCB3aWxsIGZhaWwgYWx3YXlzLCBtZWFuaW5nIHdlIHNldCBhbGwgcGl4ZWxzIGNvdmVyZWRcbiAgICAvLyBieSB0aGlzIGdlb21ldHJ5IHRvIDB4ODAuIFdlIHVzZSB0aGUgaGlnaGVzdCBiaXQgMHg4MCB0byBtYXJrIHRoZSByZWdpb25zXG4gICAgLy8gd2Ugd2FudCB0byBkcmF3IGluLiBBbGwgcGl4ZWxzIHRoYXQgaGF2ZSB0aGlzIGJpdCAqbm90KiBzZXQgd2lsbCBuZXZlciBiZVxuICAgIC8vIGRyYXduIGluLlxuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweEMwLCAweDQwKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweEMwKTtcbiAgICBnbC5zdGVuY2lsT3AoZ2wuUkVQTEFDRSwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG5cbiAgICAvLyBEcmF3IHRoZSBjbGlwcGluZyBtYXNrXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudGlsZUV4dGVudEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLmZpbGxTaGFkZXIuYV9wb3MsIHRoaXMudGlsZUV4dGVudEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCA4LCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbUNvdW50KTtcblxuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcbiAgICBnbC5zdGVuY2lsT3AoZ2wuS0VFUCwgZ2wuS0VFUCwgZ2wuUkVQTEFDRSk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuY29sb3JNYXNrKHRydWUsIHRydWUsIHRydWUsIHRydWUpO1xufTtcblxuLy8gU2V0IHVwIGEgdGV4dHVyZSB0aGF0IGNhbiBiZSBkcmF3biBpbnRvXG5HTFBhaW50ZXIucHJvdG90eXBlLmJpbmRSZW5kZXJUZXh0dXJlID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgaWYgKG5hbWUpIHtcblxuICAgICAgICAvLyBPbmx5IGNyZWF0ZSBvbmUgZnJhbWVidWZmZXIuIFJldXNlIGl0IGZvciBldmVyeSBsZXZlbC5cbiAgICAgICAgaWYgKCF0aGlzLmZyYW1lYnVmZmVyT2JqZWN0KSB7XG4gICAgICAgICAgICB0aGlzLmZyYW1lYnVmZmVyT2JqZWN0ID0gZ2wuY3JlYXRlRnJhbWVidWZmZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgdGhpcy5mcmFtZWJ1ZmZlck9iamVjdCk7XG5cbiAgICAgICAgLy8gVGhlcmUncyBvbmx5IG9uZSBzdGVuY2lsIGJ1ZmZlciB0aGF0IHdlIGFsd2F5cyBhdHRhY2guXG4gICAgICAgIGlmICghdGhpcy5zdGVuY2lsQnVmZmVyKSB7XG4gICAgICAgICAgICB2YXIgc3RlbmNpbCA9IHRoaXMuc3RlbmNpbEJ1ZmZlciA9IGdsLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIHN0ZW5jaWwpO1xuICAgICAgICAgICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGdsLlNURU5DSUxfSU5ERVg4LCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICAgICAgZ2wuZnJhbWVidWZmZXJSZW5kZXJidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGdsLlNURU5DSUxfQVRUQUNITUVOVCwgZ2wuUkVOREVSQlVGRkVSLCB0aGlzLnN0ZW5jaWxCdWZmZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgY3JlYXRlIGEgc2VwYXJhdGUgdGV4dHVyZSBmb3IgZXZlcnkgbGV2ZWwuXG4gICAgICAgIHZhciB0ZXh0dXJlID0gdGhpcy5yZW5kZXJUZXh0dXJlcy5wb3AoKTtcbiAgICAgICAgaWYgKCF0ZXh0dXJlKSB7XG4gICAgICAgICAgICB0ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1QsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5uYW1lZFJlbmRlclRleHR1cmVzW25hbWVdID0gdGV4dHVyZTtcblxuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIHRleHR1cmUsIDApO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcbiAgICB9XG5cbiAgICB0aGlzLmNsZWFyQ29sb3IoKTtcbn07XG5cbkdMUGFpbnRlci5wcm90b3R5cGUuZnJlZVJlbmRlclRleHR1cmUgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgdGhpcy5yZW5kZXJUZXh0dXJlcy5wdXNoKHRoaXMubmFtZWRSZW5kZXJUZXh0dXJlc1tuYW1lXSk7XG4gICAgZGVsZXRlIHRoaXMubmFtZWRSZW5kZXJUZXh0dXJlc1tuYW1lXTtcbn07XG5cbi8qXG4gKiBEcmF3IGEgbmV3IHRpbGUgdG8gdGhlIGNvbnRleHQsIGFzc3VtaW5nIHRoYXQgdGhlIHZpZXdwb3J0IGlzXG4gKiBhbHJlYWR5IGNvcnJlY3RseSBzZXQuXG4gKi9cbkdMUGFpbnRlci5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uIGdsUGFpbnRlckRyYXcodGlsZSwgc3R5bGUsIGxheWVycywgcGFyYW1zLCBtYXRyaXgpIHtcbiAgICB0aGlzLnRpbGUgPSB0aWxlO1xuXG4gICAgLy8gZmFsc2Ugd2hlbiBkcmF3aW5nIGEgZ3JvdXAgb2YgY29tcG9zaXRlZCBsYXllcnNcbiAgICBpZiAodGlsZSAmJiAhbWF0cml4KSB7XG4gICAgICAgIC8vIERyYXcgdGhlIHJvb3QgY2xpcHBpbmcgbWFzay5cbiAgICAgICAgdGhpcy5kcmF3Q2xpcHBpbmdNYXNrKCk7XG4gICAgfVxuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxheWVycykpIGNvbnNvbGUud2FybignTGF5ZXJzIGlzIG5vdCBhbiBhcnJheScpO1xuXG4gICAgdGhpcy5mcmFtZUhpc3RvcnkucmVjb3JkKHRoaXMudHJhbnNmb3JtLnpvb20pO1xuXG4gICAgLy8gRHJhdyBsYXllcnMgZnJvbnQtdG8tYmFjay5cbiAgICAvLyBMYXllcnMgYXJlIGFscmVhZHkgaW4gcmV2ZXJzZSBvcmRlciBmcm9tIHN0eWxlLnJlc3RydWN0dXJlKClcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHRoaXMuYXBwbHlTdHlsZShsYXllcnNbaV0sIHN0eWxlLCB0aWxlICYmIHRpbGUuYnVja2V0cywgcGFyYW1zLCB0aWxlLCBtYXRyaXgpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuZGVidWcpIHtcbiAgICAgICAgZHJhd0RlYnVnKHRoaXMuZ2wsIHRoaXMsIHRpbGUsIHBhcmFtcyk7XG4gICAgfVxufTtcblxuR0xQYWludGVyLnByb3RvdHlwZS5hcHBseVN0eWxlID0gZnVuY3Rpb24obGF5ZXIsIHN0eWxlLCBidWNrZXRzLCBwYXJhbXMsIHRpbGUsIG1hdHJpeCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG5cbiAgICB2YXIgbGF5ZXJTdHlsZSA9IHN0eWxlLmNvbXB1dGVkW2xheWVyLmlkXTtcbiAgICBpZiAoIWxheWVyU3R5bGUgfHwgbGF5ZXJTdHlsZS5oaWRkZW4pIHJldHVybjtcblxuICAgIGlmIChsYXllci5sYXllcnMpIHtcbiAgICAgICAgaWYgKGxheWVyLnR5cGUgPT09ICdjb21wb3NpdGUnKSB7XG4gICAgICAgICAgICBkcmF3Q29tcG9zaXRlZChnbCwgdGhpcywgYnVja2V0cywgbGF5ZXJTdHlsZSwgcGFyYW1zLCBzdHlsZSwgbGF5ZXIpO1xuICAgICAgICB9IGVsc2UgaWYgKGxheWVyLnR5cGUgPT09ICdyYXN0ZXInKSB7XG4gICAgICAgICAgICBkcmF3UmFzdGVyKGdsLCB0aGlzLCBidWNrZXRzW2xheWVyLmJ1Y2tldF0sIGxheWVyU3R5bGUsIHBhcmFtcywgc3R5bGUsIGxheWVyLCB0aWxlKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW1zLmJhY2tncm91bmQpIHtcbiAgICAgICAgZHJhd0JhY2tncm91bmQoZ2wsIHRoaXMsIHVuZGVmaW5lZCwgbGF5ZXJTdHlsZSwgdGhpcy5pZGVudGl0eU1hdHJpeCwgcGFyYW1zLCBzdHlsZS5zcHJpdGUpO1xuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNbbGF5ZXIuYnVja2V0XTtcbiAgICAgICAgLy8gVGhlcmUgYXJlIG5vIHZlcnRpY2VzIHlldCBmb3IgdGhpcyBsYXllci5cbiAgICAgICAgaWYgKCFidWNrZXQgfHwgKGJ1Y2tldC5oYXNEYXRhICYmICFidWNrZXQuaGFzRGF0YSgpKSkgcmV0dXJuO1xuXG4gICAgICAgIHZhciB0eXBlID0gYnVja2V0LnR5cGU7XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5taW5ab29tICYmIHRoaXMudHJhbnNmb3JtLnpvb20gPCBidWNrZXQubWluWm9vbSkgcmV0dXJuO1xuICAgICAgICBpZiAoYnVja2V0Lm1heFpvb20gJiYgdGhpcy50cmFuc2Zvcm0uem9vbSA+PSBidWNrZXQubWF4Wm9vbSkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBkcmF3ID0gdHlwZSA9PT0gJ3N5bWJvbCcgPyBkcmF3U3ltYm9sIDpcbiAgICAgICAgICAgICAgICAgICB0eXBlID09PSAnZmlsbCcgPyBkcmF3RmlsbCA6XG4gICAgICAgICAgICAgICAgICAgdHlwZSA9PT0gJ2xpbmUnID8gZHJhd0xpbmUgOlxuICAgICAgICAgICAgICAgICAgIHR5cGUgPT09ICdyYXN0ZXInID8gZHJhd1Jhc3RlciA6IG51bGw7XG5cbiAgICAgICAgaWYgKGRyYXcpIHtcbiAgICAgICAgICAgIHZhciB1c2VNYXRyaXggPSBtYXRyaXggfHwgdGhpcy50aWxlLnBvc01hdHJpeDtcbiAgICAgICAgICAgIGRyYXcoZ2wsIHRoaXMsIGJ1Y2tldCwgbGF5ZXJTdHlsZSwgdXNlTWF0cml4LCBwYXJhbXMsIHN0eWxlLnNwcml0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vIGJ1Y2tldCB0eXBlIHNwZWNpZmllZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcy52ZXJ0aWNlcyAmJiAhbGF5ZXIubGF5ZXJzKSB7XG4gICAgICAgICAgICBkcmF3VmVydGljZXMoZ2wsIHRoaXMsIGJ1Y2tldCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBEcmF3cyBub24tb3BhcXVlIGFyZWFzLiBUaGlzIGlzIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG5HTFBhaW50ZXIucHJvdG90eXBlLmRyYXdTdGVuY2lsQnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5zd2l0Y2hTaGFkZXIodGhpcy5maWxsU2hhZGVyLCB0aGlzLmlkZW50aXR5TWF0cml4KTtcblxuICAgIC8vIEJsZW5kIHRvIHRoZSBmcm9udCwgbm90IHRoZSBiYWNrLlxuICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcblxuICAgIC8vIERydyB0aGUgZmlsbGluZyBxdWFkIHdoZXJlIHRoZSBzdGVuY2lsIGJ1ZmZlciBpc24ndCBzZXQuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLmZpbGxTaGFkZXIuYV9wb3MsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC51bmlmb3JtNGZ2KHRoaXMuZmlsbFNoYWRlci51X2NvbG9yLCBbMCwgMCwgMCwgMC41XSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgdGhpcy5iYWNrZ3JvdW5kQnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICAvLyBSZXZlcnQgYmxlbmRpbmcgbW9kZSB0byBibGVuZCB0byB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FX01JTlVTX0RTVF9BTFBIQSwgZ2wuT05FKTtcbn07XG5cbkdMUGFpbnRlci5wcm90b3R5cGUudHJhbnNsYXRlTWF0cml4ID0gZnVuY3Rpb24obWF0cml4LCB6LCB0cmFuc2xhdGUsIGFuY2hvcikge1xuICAgIGlmICghdHJhbnNsYXRlWzBdICYmICF0cmFuc2xhdGVbMV0pIHJldHVybiBtYXRyaXg7XG5cbiAgICBpZiAoYW5jaG9yID09PSAndmlld3BvcnQnKSB7XG4gICAgICAgIHZhciBzaW5fYSA9IE1hdGguc2luKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHZhciBjb3NfYSA9IE1hdGguY29zKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHRyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVswXSAqIGNvc19hIC0gdHJhbnNsYXRlWzFdICogc2luX2EsXG4gICAgICAgICAgICB0cmFuc2xhdGVbMF0gKiBzaW5fYSArIHRyYW5zbGF0ZVsxXSAqIGNvc19hXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgdmFyIHRpbGVQaXhlbFJhdGlvID0gdGhpcy50cmFuc2Zvcm0uc2NhbGUgLyAoMSA8PCB6KSAvIDg7XG4gICAgdmFyIHRyYW5zbGF0aW9uID0gW1xuICAgICAgICB0cmFuc2xhdGVbMF0gLyB0aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdHJhbnNsYXRlWzFdIC8gdGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIDBcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBtYXQ0LnRyYW5zbGF0ZSh0cmFuc2xhdGVkTWF0cml4LCBtYXRyaXgsIHRyYW5zbGF0aW9uKTtcbiAgICByZXR1cm4gdHJhbnNsYXRlZE1hdHJpeDtcbn07XG5cbkdMUGFpbnRlci5wcm90b3R5cGUuc2F2ZVRleHR1cmUgPSBmdW5jdGlvbih0ZXh0dXJlKSB7XG4gICAgdmFyIHRleHR1cmVzID0gdGhpcy5yZXVzYWJsZVRleHR1cmVzW3RleHR1cmUuc2l6ZV07XG4gICAgaWYgKCF0ZXh0dXJlcykge1xuICAgICAgICB0aGlzLnJldXNhYmxlVGV4dHVyZXNbdGV4dHVyZS5zaXplXSA9IFt0ZXh0dXJlXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0dXJlcy5wdXNoKHRleHR1cmUpO1xuICAgIH1cbn07XG5cblxuR0xQYWludGVyLnByb3RvdHlwZS5nZXRUZXh0dXJlID0gZnVuY3Rpb24oc2l6ZSkge1xuICAgIHZhciB0ZXh0dXJlcyA9IHRoaXMucmV1c2FibGVUZXh0dXJlc1tzaXplXTtcbiAgICByZXR1cm4gdGV4dHVyZXMgJiYgdGV4dHVyZXMubGVuZ3RoID4gMCA/IHRleHR1cmVzLnBvcCgpIDogbnVsbDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJy4uL2xpYi9nbG1hdHJpeC5qcycpO1xudmFyIG1hdDQgPSBnbG1hdHJpeC5tYXQ0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByZXJlbmRlcmVkVGV4dHVyZTtcblxuZnVuY3Rpb24gUHJlcmVuZGVyZWRUZXh0dXJlKGdsLCBidWNrZXQsIHBhaW50ZXIpIHtcbiAgICB0aGlzLmdsID0gZ2w7XG4gICAgdGhpcy5idWZmZXIgPSBidWNrZXRbJ3Jhc3Rlci1idWZmZXInXSB8fCAoMS8zMik7XG4gICAgdGhpcy5zaXplID0gKGJ1Y2tldFsncmFzdGVyLXNpemUnXSB8fCA1MTIpICogKDEgKyAyICogdGhpcy5idWZmZXIpO1xuICAgIHRoaXMucGFpbnRlciA9IHBhaW50ZXI7XG5cbiAgICB0aGlzLnRleHR1cmUgPSBudWxsO1xuICAgIHRoaXMuZmJvID0gbnVsbDtcbiAgICB0aGlzLmZib3MgPSB0aGlzLnBhaW50ZXIucHJlRmJvc1t0aGlzLnNpemVdO1xufVxuXG5QcmVyZW5kZXJlZFRleHR1cmUucHJvdG90eXBlLmJpbmRGcmFtZWJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG5cbiAgICAvLyB0cnkgdG8gcmV1c2UgYXZhaWxhYmxlIHJhc3RlciB0ZXh0dXJlc1xuICAgIHRoaXMudGV4dHVyZSA9IHRoaXMucGFpbnRlci5nZXRUZXh0dXJlKHRoaXMuc2l6ZSk7XG5cbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIHRoaXMuc2l6ZSwgdGhpcy5zaXplLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBudWxsKTtcbiAgICAgICAgdGhpcy50ZXh0dXJlLnNpemUgPSB0aGlzLnNpemU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuZmJvcykge1xuICAgICAgICB0aGlzLmZibyA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgICAgIHZhciBzdGVuY2lsID0gZ2wuY3JlYXRlUmVuZGVyYnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRSZW5kZXJidWZmZXIoZ2wuUkVOREVSQlVGRkVSLCBzdGVuY2lsKTtcbiAgICAgICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGdsLlNURU5DSUxfSU5ERVg4LCB0aGlzLnNpemUsIHRoaXMuc2l6ZSk7XG4gICAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgdGhpcy5mYm8pO1xuICAgICAgICBnbC5mcmFtZWJ1ZmZlclJlbmRlcmJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgZ2wuU1RFTkNJTF9BVFRBQ0hNRU5ULCBnbC5SRU5ERVJCVUZGRVIsIHN0ZW5jaWwpO1xuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5mYm8gPSB0aGlzLmZib3MucG9wKCk7XG4gICAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgdGhpcy5mYm8pO1xuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSwgMCk7XG4gICAgfVxufTtcblxuUHJlcmVuZGVyZWRUZXh0dXJlLnByb3RvdHlwZS51bmJpbmRGcmFtZWJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcbiAgICBpZiAodGhpcy5mYm9zKSB0aGlzLmZib3MucHVzaCh0aGlzLmZibyk7IGVsc2UgdGhpcy5wYWludGVyLnByZUZib3NbdGhpcy5zaXplXSA9IFt0aGlzLmZib107XG59O1xuXG5QcmVyZW5kZXJlZFRleHR1cmUucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkgdGhyb3coJ3ByZS1yZW5kZXJlZCB0ZXh0dXJlIGRvZXMgbm90IGV4aXN0Jyk7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xufTtcblxuUHJlcmVuZGVyZWRUZXh0dXJlLnByb3RvdHlwZS5ibHVyID0gZnVuY3Rpb24ocGFpbnRlciwgcGFzc2VzKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICB2YXIgb3JpZ2luYWxUZXh0dXJlID0gdGhpcy50ZXh0dXJlO1xuICAgIHZhciBzZWNvbmRhcnlUZXh0dXJlID0gdGhpcy5wYWludGVyLmdldFRleHR1cmUodGhpcy5zaXplKTtcbiAgICBpZiAoIXNlY29uZGFyeVRleHR1cmUpIHtcbiAgICAgICAgc2Vjb25kYXJ5VGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgc2Vjb25kYXJ5VGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIHRoaXMuc2l6ZSwgdGhpcy5zaXplLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBudWxsKTtcbiAgICAgICAgc2Vjb25kYXJ5VGV4dHVyZS5zaXplID0gdGhpcy5zaXplO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHNlY29uZGFyeVRleHR1cmUpO1xuICAgIH1cbiAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBudWxsKTtcblxuICAgIHZhciBtYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuICAgIG1hdDQub3J0aG8obWF0cml4LCAwLCA0MDk2LCAtNDA5NiwgMCwgMCwgMSk7XG4gICAgbWF0NC50cmFuc2xhdGUobWF0cml4LCBtYXRyaXgsIFswLCAtNDA5NiwgMF0pO1xuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZ2F1c3NpYW5TaGFkZXIsIG1hdHJpeCk7XG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG4gICAgZ2wudW5pZm9ybTFpKHBhaW50ZXIuZ2F1c3NpYW5TaGFkZXIudV9pbWFnZSwgMCk7XG4gICAgZ2wudW5pZm9ybTFmKHBhaW50ZXIuZ2F1c3NpYW5TaGFkZXIudV9vcGFjaXR5LCAxKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFzc2VzOyBpKyspIHtcblxuICAgICAgICAvLyBSZW5kZXIgaG9yaXpvbnRhbFxuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIHNlY29uZGFyeVRleHR1cmUsIDApO1xuICAgICAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihwYWludGVyLmdhdXNzaWFuU2hhZGVyLnVfb2Zmc2V0LCBbMSAvIHRoaXMuc2l6ZSwgMF0pO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBvcmlnaW5hbFRleHR1cmUpO1xuICAgICAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmdhdXNzaWFuU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KTtcblxuXG4gICAgICAgIC8vIFJlbmRlciB2ZXJ0aWNhbFxuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChnbC5GUkFNRUJVRkZFUiwgZ2wuQ09MT1JfQVRUQUNITUVOVDAsIGdsLlRFWFRVUkVfMkQsIG9yaWdpbmFsVGV4dHVyZSwgMCk7XG4gICAgICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHBhaW50ZXIuZ2F1c3NpYW5TaGFkZXIudV9vZmZzZXQsIFswLCAxIC8gdGhpcy5zaXplXSk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHNlY29uZGFyeVRleHR1cmUpO1xuICAgICAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmdhdXNzaWFuU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KTtcbiAgICB9XG5cbiAgICB0aGlzLnBhaW50ZXIuc2F2ZVRleHR1cmUoc2Vjb25kYXJ5VGV4dHVyZSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2xpZnkgPSB1bmRlZmluZWQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFwiY29tcG9zaXRlXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxudW5pZm9ybSBtYXQ0IHVfcG9zbWF0cml4O1xcbnZhcnlpbmcgaGlnaHAgdmVjMiBhO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIHZlYzQgdG1wdmFyXzE7XFxuICB0bXB2YXJfMS56dyA9IHZlYzIoMC4wLCAxLjApO1xcbiAgdG1wdmFyXzEueHkgPSBhX3BvcztcXG4gIHZlYzQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9ICh1X3Bvc21hdHJpeCAqIHRtcHZhcl8xKTtcXG4gIGdsX1Bvc2l0aW9uID0gdG1wdmFyXzI7XFxuICBhID0gKCh0bXB2YXJfMi54eSAvIDIuMCkgKyAwLjUpO1xcbn1cXG5cXG5cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbnVuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O1xcbnZhcnlpbmcgdmVjMiBhO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIGxvd3AgdmVjNCB0bXB2YXJfMTtcXG4gIHRtcHZhcl8xID0gKHRleHR1cmUyRCAodV9pbWFnZSwgYSkgKiB1X29wYWNpdHkpO1xcbiAgZ2xfRnJhZ0NvbG9yID0gdG1wdmFyXzE7XFxufVxcblxcblwifSxcbiAgICBcImRlYnVnXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxudW5pZm9ybSBmbG9hdCB1X3BvaW50c2l6ZTtcXG51bmlmb3JtIG1hdDQgdV9wb3NtYXRyaXg7XFxudm9pZCBtYWluICgpXFxue1xcbiAgdmVjNCB0bXB2YXJfMTtcXG4gIHRtcHZhcl8xLncgPSAxLjA7XFxuICB0bXB2YXJfMS54eSA9IGFfcG9zO1xcbiAgdG1wdmFyXzEueiA9IGZsb2F0KChhX3Bvcy54ID49IDMyNzY3LjApKTtcXG4gIGdsX1Bvc2l0aW9uID0gKHVfcG9zbWF0cml4ICogdG1wdmFyXzEpO1xcbiAgZ2xfUG9pbnRTaXplID0gdV9wb2ludHNpemU7XFxufVxcblxcblwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gdmVjNCB1X2NvbG9yO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIGdsX0ZyYWdDb2xvciA9IHVfY29sb3I7XFxufVxcblxcblwifSxcbiAgICBcImRvdFwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gbWF0NCB1X3Bvc21hdHJpeDtcXG51bmlmb3JtIGZsb2F0IHVfc2l6ZTtcXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG52b2lkIG1haW4gKClcXG57XFxuICB2ZWM0IHRtcHZhcl8xO1xcbiAgdG1wdmFyXzEuencgPSB2ZWMyKDAuMCwgMS4wKTtcXG4gIHRtcHZhcl8xLnh5ID0gYV9wb3M7XFxuICBnbF9Qb3NpdGlvbiA9ICh1X3Bvc21hdHJpeCAqIHRtcHZhcl8xKTtcXG4gIGdsX1BvaW50U2l6ZSA9IHVfc2l6ZTtcXG59XFxuXFxuXCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxudW5pZm9ybSB2ZWM0IHVfY29sb3I7XFxudW5pZm9ybSBmbG9hdCB1X2JsdXI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgbWVkaXVtcCB2ZWMyIHhfMTtcXG4gIHhfMSA9IChnbF9Qb2ludENvb3JkIC0gMC41KTtcXG4gIG1lZGl1bXAgZmxvYXQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9IGNsYW1wICgoKFxcbiAgICBzcXJ0KGRvdCAoeF8xLCB4XzEpKVxcbiAgIC0gMC41KSAvIChcXG4gICAgKDAuNSAtIHVfYmx1cilcXG4gICAtIDAuNSkpLCAwLjAsIDEuMCk7XFxuICBnbF9GcmFnQ29sb3IgPSAodV9jb2xvciAqICh0bXB2YXJfMiAqICh0bXB2YXJfMiAqIFxcbiAgICAoMy4wIC0gKDIuMCAqIHRtcHZhcl8yKSlcXG4gICkpKTtcXG59XFxuXFxuXCJ9LFxuICAgIFwiZmlsbFwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcbnVuaWZvcm0gbWF0NCB1X3Bvc21hdHJpeDtcXG52b2lkIG1haW4gKClcXG57XFxuICB2ZWM0IHRtcHZhcl8xO1xcbiAgdG1wdmFyXzEuencgPSB2ZWMyKDAuMCwgMS4wKTtcXG4gIHRtcHZhcl8xLnh5ID0gYV9wb3M7XFxuICBnbF9Qb3NpdGlvbiA9ICh1X3Bvc21hdHJpeCAqIHRtcHZhcl8xKTtcXG4gIGdsX1BvaW50U2l6ZSA9IDIuMDtcXG59XFxuXFxuXCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxudW5pZm9ybSB2ZWM0IHVfY29sb3I7XFxudm9pZCBtYWluICgpXFxue1xcbiAgZ2xfRnJhZ0NvbG9yID0gdV9jb2xvcjtcXG59XFxuXFxuXCJ9LFxuICAgIFwiZ2F1c3NpYW5cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG51bmlmb3JtIG1hdDQgdV9wb3NtYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfb2Zmc2V0O1xcbnZhcnlpbmcgaGlnaHAgdmVjMiBiWzNdO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIHZlYzQgdG1wdmFyXzE7XFxuICB0bXB2YXJfMS56dyA9IHZlYzIoMC4wLCAxLjApO1xcbiAgdG1wdmFyXzEueHkgPSBhX3BvcztcXG4gIHZlYzQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9ICh1X3Bvc21hdHJpeCAqIHRtcHZhcl8xKTtcXG4gIGdsX1Bvc2l0aW9uID0gdG1wdmFyXzI7XFxuICBoaWdocCB2ZWMyIHRtcHZhcl8zO1xcbiAgdG1wdmFyXzMgPSAoKHRtcHZhcl8yLnh5IC8gMi4wKSArIDAuNSk7XFxuICBiWzBdID0gdG1wdmFyXzM7XFxuICB2ZWMyIGNzZV80O1xcbiAgY3NlXzQgPSAodV9vZmZzZXQgKiAxLjE4MjQzKTtcXG4gIGJbMV0gPSAodG1wdmFyXzMgKyBjc2VfNCk7XFxuICBiWzJdID0gKHRtcHZhcl8zIC0gY3NlXzQpO1xcbn1cXG5cXG5cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbnZhcnlpbmcgdmVjMiBiWzNdO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIGxvd3AgdmVjNCB0bXB2YXJfMTtcXG4gIHRtcHZhcl8xID0gKCgodGV4dHVyZTJEICh1X2ltYWdlLCBiWzBdKSAqIDAuNDAyNjIpICsgKHRleHR1cmUyRCAodV9pbWFnZSwgYlsxXSkgKiAwLjI5ODY5KSkgKyAodGV4dHVyZTJEICh1X2ltYWdlLCBiWzJdKSAqIDAuMjk4NjkpKTtcXG4gIGdsX0ZyYWdDb2xvciA9IHRtcHZhcl8xO1xcbn1cXG5cXG5cIn0sXG4gICAgXCJsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuYXR0cmlidXRlIHZlYzIgYV9leHRydWRlO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX2xpbmVzb2ZhcjtcXG51bmlmb3JtIG1hdDQgdV9wb3NtYXRyaXg7XFxudW5pZm9ybSBtYXQ0IHVfZXhtYXRyaXg7XFxudW5pZm9ybSBmbG9hdCB1X3JhdGlvO1xcbnVuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgdmVjMiBjXzE7XFxuICB2ZWMyIHRtcHZhcl8yO1xcbiAgdG1wdmFyXzIgPSAodmVjMihtb2QgKGFfcG9zLCAyLjApKSk7XFxuICBjXzEueCA9IHRtcHZhcl8yLng7XFxuICBjXzEueSA9IHNpZ24oKHRtcHZhcl8yLnkgLSAwLjUpKTtcXG4gIGEgPSBjXzE7XFxuICB2ZWM0IHRtcHZhcl8zO1xcbiAgdG1wdmFyXzMuencgPSB2ZWMyKDAuMCwgMS4wKTtcXG4gIHRtcHZhcl8zLnh5ID0gZmxvb3IoKGFfcG9zIC8gMi4wKSk7XFxuICB2ZWM0IHRtcHZhcl80O1xcbiAgdG1wdmFyXzQuencgPSB2ZWMyKDAuMCwgMC4wKTtcXG4gIHRtcHZhcl80Lnh5ID0gKHVfbGluZXdpZHRoLnggKiAoYV9leHRydWRlIC8gNjMuMCkpO1xcbiAgZ2xfUG9zaXRpb24gPSAoKHVfcG9zbWF0cml4ICogdG1wdmFyXzMpICsgKHVfZXhtYXRyaXggKiB0bXB2YXJfNCkpO1xcbiAgYiA9IChhX2xpbmVzb2ZhciAqIHVfcmF0aW8pO1xcbn1cXG5cXG5cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG51bmlmb3JtIGZsb2F0IHVfZGVidWc7XFxudW5pZm9ybSBmbG9hdCB1X2JsdXI7XFxudW5pZm9ybSB2ZWMyIHVfbGluZXdpZHRoO1xcbnVuaWZvcm0gdmVjMiB1X2Rhc2hhcnJheTtcXG51bmlmb3JtIHZlYzQgdV9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgZmxvYXQgdG1wdmFyXzE7XFxuICB0bXB2YXJfMSA9IChzcXJ0KGRvdCAoYSwgYSkpICogdV9saW5ld2lkdGgueCk7XFxuICBmbG9hdCB0bXB2YXJfMjtcXG4gIHRtcHZhcl8yID0gKGZsb2F0KG1vZCAoYiwgKHVfZGFzaGFycmF5LnggKyB1X2Rhc2hhcnJheS55KSkpKTtcXG4gIGdsX0ZyYWdDb2xvciA9ICh1X2NvbG9yICogKGNsYW1wIChcXG4gICAgKG1pbiAoKHRtcHZhcl8xIC0gKHVfbGluZXdpZHRoLnkgLSB1X2JsdXIpKSwgKHVfbGluZXdpZHRoLnggLSB0bXB2YXJfMSkpIC8gdV9ibHVyKVxcbiAgLCAwLjAsIDEuMCkgKiBtYXggKFxcbiAgICBmbG9hdCgoLSh1X2Rhc2hhcnJheS55KSA+PSAwLjApKVxcbiAgLCBcXG4gICAgY2xhbXAgKG1pbiAodG1wdmFyXzIsICh1X2Rhc2hhcnJheS54IC0gdG1wdmFyXzIpKSwgMC4wLCAxLjApXFxuICApKSk7XFxuICBpZiAoKHVfZGVidWcgPiAwLjApKSB7XFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wLCAwLjAsIDAuMCwgMS4wKTtcXG4gIH07XFxufVxcblxcblwifSxcbiAgICBcImxpbmVwYXR0ZXJuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuYXR0cmlidXRlIHZlYzIgYV9leHRydWRlO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX2xpbmVzb2ZhcjtcXG51bmlmb3JtIG1hdDQgdV9wb3NtYXRyaXg7XFxudW5pZm9ybSBtYXQ0IHVfZXhtYXRyaXg7XFxudW5pZm9ybSBmbG9hdCB1X3BvaW50O1xcbnVuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgdmVjMiBjXzE7XFxuICB2ZWMyIHRtcHZhcl8yO1xcbiAgdG1wdmFyXzIgPSAodmVjMihtb2QgKGFfcG9zLCAyLjApKSk7XFxuICBjXzEueCA9IHRtcHZhcl8yLng7XFxuICBjXzEueSA9IHNpZ24oKHRtcHZhcl8yLnkgLSAwLjUpKTtcXG4gIGEgPSBjXzE7XFxuICB2ZWM0IHRtcHZhcl8zO1xcbiAgdG1wdmFyXzMuencgPSB2ZWMyKDAuMCwgMS4wKTtcXG4gIHRtcHZhcl8zLnh5ID0gZmxvb3IoKGFfcG9zIC8gMi4wKSk7XFxuICB2ZWM0IHRtcHZhcl80O1xcbiAgdG1wdmFyXzQudyA9IDAuMDtcXG4gIHRtcHZhcl80Lnh5ID0gKCh1X2xpbmV3aWR0aC54ICogKGFfZXh0cnVkZSAvIDYzLjApKSAqICgxLjAgLSB1X3BvaW50KSk7XFxuICB0bXB2YXJfNC56ID0gKGZsb2F0KChhX3Bvcy54ID49IDMyNzY3LjApKSArICh1X3BvaW50ICogZmxvYXQoXFxuICAgIChjXzEueSA+PSAxLjApXFxuICApKSk7XFxuICBnbF9Qb3NpdGlvbiA9ICgodV9wb3NtYXRyaXggKiB0bXB2YXJfMykgKyAodV9leG1hdHJpeCAqIHRtcHZhcl80KSk7XFxuICBiID0gYV9saW5lc29mYXI7XFxuICBnbF9Qb2ludFNpemUgPSAoKDIuMCAqIHVfbGluZXdpZHRoLngpIC0gMS4wKTtcXG59XFxuXFxuXCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxudW5pZm9ybSBmbG9hdCB1X3BvaW50O1xcbnVuaWZvcm0gZmxvYXQgdV9ibHVyO1xcbnVuaWZvcm0gZmxvYXQgdV9mYWRlO1xcbnVuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3NpemU7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl90bDtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyO1xcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxudmFyeWluZyB2ZWMyIGE7XFxudmFyeWluZyBmbG9hdCBiO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIGxvd3AgdmVjNCBqXzE7XFxuICBtZWRpdW1wIHZlYzIgeF8yO1xcbiAgeF8yID0gKChnbF9Qb2ludENvb3JkICogMi4wKSAtIDEuMCk7XFxuICBtZWRpdW1wIGZsb2F0IHRtcHZhcl8zO1xcbiAgdG1wdmFyXzMgPSAoKChcXG4gICAgc3FydChkb3QgKGEsIGEpKVxcbiAgICogXFxuICAgICgxLjAgLSB1X3BvaW50KVxcbiAgKSArICh1X3BvaW50ICogXFxuICAgIHNxcnQoZG90ICh4XzIsIHhfMikpXFxuICApKSAqIHVfbGluZXdpZHRoLngpO1xcbiAgZmxvYXQgdG1wdmFyXzQ7XFxuICB0bXB2YXJfNCA9IChmbG9hdChtb2QgKChiIC8gdV9wYXR0ZXJuX3NpemUueCksIDEuMCkpKTtcXG4gIGZsb2F0IHRtcHZhcl81O1xcbiAgdG1wdmFyXzUgPSAoMC41ICsgKChhLnkgKiB1X2xpbmV3aWR0aC54KSAvIHVfcGF0dGVybl9zaXplLnkpKTtcXG4gIHZlYzIgdG1wdmFyXzY7XFxuICB0bXB2YXJfNi54ID0gdG1wdmFyXzQ7XFxuICB0bXB2YXJfNi55ID0gdG1wdmFyXzU7XFxuICB2ZWMyIHRtcHZhcl83O1xcbiAgdG1wdmFyXzcueCA9IChmbG9hdChtb2QgKCh0bXB2YXJfNCAqIDIuMCksIDEuMCkpKTtcXG4gIHRtcHZhcl83LnkgPSB0bXB2YXJfNTtcXG4gIGxvd3AgdmVjNCB0bXB2YXJfODtcXG4gIHRtcHZhcl84ID0gKCh0ZXh0dXJlMkQgKHVfaW1hZ2UsIG1peCAodV9wYXR0ZXJuX3RsLCB1X3BhdHRlcm5fYnIsIHRtcHZhcl82KSkgKiAoMS4wIC0gdV9mYWRlKSkgKyAodV9mYWRlICogdGV4dHVyZTJEICh1X2ltYWdlLCBtaXggKHVfcGF0dGVybl90bCwgdV9wYXR0ZXJuX2JyLCB0bXB2YXJfNykpKSk7XFxuICBqXzEudyA9IHRtcHZhcl84Lnc7XFxuICBqXzEueHl6ID0gKHRtcHZhcl84Lnh5eiAqIHRtcHZhcl84LncpO1xcbiAgZ2xfRnJhZ0NvbG9yID0gKGpfMSAqIGNsYW1wICgoXFxuICAgIG1pbiAoKHRtcHZhcl8zIC0gKHVfbGluZXdpZHRoLnkgLSB1X2JsdXIpKSwgKHVfbGluZXdpZHRoLnggLSB0bXB2YXJfMykpXFxuICAgLyB1X2JsdXIpLCAwLjAsIDEuMCkpO1xcbn1cXG5cXG5cIn0sXG4gICAgXCJvdXRsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxudW5pZm9ybSBtYXQ0IHVfcG9zbWF0cml4O1xcbnVuaWZvcm0gdmVjMiB1X3dvcmxkO1xcbnZhcnlpbmcgaGlnaHAgdmVjMiBhO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIHZlYzQgdG1wdmFyXzE7XFxuICB0bXB2YXJfMS56dyA9IHZlYzIoMC4wLCAxLjApO1xcbiAgdG1wdmFyXzEueHkgPSBhX3BvcztcXG4gIHZlYzQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9ICh1X3Bvc21hdHJpeCAqIHRtcHZhcl8xKTtcXG4gIGdsX1Bvc2l0aW9uID0gdG1wdmFyXzI7XFxuICBhID0gKCgodG1wdmFyXzIueHkgKyAxLjApIC8gMi4wKSAqIHVfd29ybGQpO1xcbn1cXG5cXG5cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG51bmlmb3JtIHZlYzQgdV9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgYTtcXG52b2lkIG1haW4gKClcXG57XFxuICBoaWdocCB2ZWMyIHhfMTtcXG4gIHhfMSA9IChhIC0gZ2xfRnJhZ0Nvb3JkLnh5KTtcXG4gIGhpZ2hwIGZsb2F0IHRtcHZhcl8yO1xcbiAgdG1wdmFyXzIgPSBjbGFtcCAoKChcXG4gICAgc3FydChkb3QgKHhfMSwgeF8xKSlcXG4gICAtIDEuMCkgLyAtMS4wKSwgMC4wLCAxLjApO1xcbiAgaGlnaHAgdmVjNCB0bXB2YXJfMztcXG4gIHRtcHZhcl8zID0gKHVfY29sb3IgKiAodG1wdmFyXzIgKiAodG1wdmFyXzIgKiBcXG4gICAgKDMuMCAtICgyLjAgKiB0bXB2YXJfMikpXFxuICApKSk7XFxuICBnbF9GcmFnQ29sb3IgPSB0bXB2YXJfMztcXG59XFxuXFxuXCJ9LFxuICAgIFwicGF0dGVyblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gbWF0NCB1X3Bvc21hdHJpeDtcXG51bmlmb3JtIG1hdDMgdV9wYXR0ZXJubWF0cml4O1xcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcbnZhcnlpbmcgdmVjMiBhO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIHZlYzQgdG1wdmFyXzE7XFxuICB0bXB2YXJfMS56dyA9IHZlYzIoMC4wLCAxLjApO1xcbiAgdG1wdmFyXzEueHkgPSBhX3BvcztcXG4gIGdsX1Bvc2l0aW9uID0gKHVfcG9zbWF0cml4ICogdG1wdmFyXzEpO1xcbiAgdmVjMyB0bXB2YXJfMjtcXG4gIHRtcHZhcl8yLnogPSAxLjA7XFxuICB0bXB2YXJfMi54eSA9IGFfcG9zO1xcbiAgYSA9ICh1X3BhdHRlcm5tYXRyaXggKiB0bXB2YXJfMikueHk7XFxufVxcblxcblwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O1xcbnVuaWZvcm0gZmxvYXQgdV9taXg7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl90bDtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyO1xcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxudmFyeWluZyB2ZWMyIGE7XFxudm9pZCBtYWluICgpXFxue1xcbiAgdmVjMiB0bXB2YXJfMTtcXG4gIHRtcHZhcl8xID0gKHZlYzIobW9kIChhLCAxLjApKSk7XFxuICBsb3dwIHZlYzQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9IChtaXggKHRleHR1cmUyRCAodV9pbWFnZSwgbWl4ICh1X3BhdHRlcm5fdGwsIHVfcGF0dGVybl9iciwgdG1wdmFyXzEpKSwgdGV4dHVyZTJEICh1X2ltYWdlLCBtaXggKHVfcGF0dGVybl90bCwgdV9wYXR0ZXJuX2JyLCBcXG4gICAgKHZlYzIobW9kICgodG1wdmFyXzEgKiAyLjApLCAxLjApKSlcXG4gICkpLCB1X21peCkgKiB1X29wYWNpdHkpO1xcbiAgZ2xfRnJhZ0NvbG9yID0gdG1wdmFyXzI7XFxufVxcblxcblwifSxcbiAgICBcInJhc3RlclwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gbWF0NCB1X3Bvc21hdHJpeDtcXG51bmlmb3JtIHZlYzIgdV90bF9wYXJlbnQ7XFxudW5pZm9ybSBmbG9hdCB1X3NjYWxlX3BhcmVudDtcXG51bmlmb3JtIGZsb2F0IHVfYnVmZmVyX3NjYWxlO1xcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcbmF0dHJpYnV0ZSB2ZWMyIGFfdGV4dHVyZV9wb3M7XFxudmFyeWluZyB2ZWMyIGE7XFxudmFyeWluZyB2ZWMyIGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgdmVjNCB0bXB2YXJfMTtcXG4gIHRtcHZhcl8xLnp3ID0gdmVjMigwLjAsIDEuMCk7XFxuICB0bXB2YXJfMS54eSA9IGFfcG9zO1xcbiAgZ2xfUG9zaXRpb24gPSAodV9wb3NtYXRyaXggKiB0bXB2YXJfMSk7XFxuICB2ZWMyIHRtcHZhcl8yO1xcbiAgdG1wdmFyXzIgPSAoKChcXG4gICAgKGFfdGV4dHVyZV9wb3MgLyAzMjc2Ny4wKVxcbiAgIC0gMC41KSAvIHVfYnVmZmVyX3NjYWxlKSArIDAuNSk7XFxuICBhID0gdG1wdmFyXzI7XFxuICBiID0gKCh0bXB2YXJfMiAqIHVfc2NhbGVfcGFyZW50KSArIHVfdGxfcGFyZW50KTtcXG59XFxuXFxuXCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxudW5pZm9ybSBmbG9hdCB1X29wYWNpdHkwO1xcbnVuaWZvcm0gZmxvYXQgdV9vcGFjaXR5MTtcXG51bmlmb3JtIGZsb2F0IHVfYnJpZ2h0bmVzc19sb3c7XFxudW5pZm9ybSBmbG9hdCB1X2JyaWdodG5lc3NfaGlnaDtcXG51bmlmb3JtIGZsb2F0IHVfc2F0dXJhdGlvbl9mYWN0b3I7XFxudW5pZm9ybSBmbG9hdCB1X2NvbnRyYXN0X2ZhY3RvcjtcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlMDtcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlMTtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIHZlYzIgYjtcXG51bmlmb3JtIHZlYzMgdV9zcGluX3dlaWdodHM7XFxudm9pZCBtYWluICgpXFxue1xcbiAgbG93cCB2ZWM0IHRtcHZhcl8xO1xcbiAgdG1wdmFyXzEgPSAoKHRleHR1cmUyRCAodV9pbWFnZTAsIGEpICogdV9vcGFjaXR5MCkgKyAodGV4dHVyZTJEICh1X2ltYWdlMSwgYikgKiB1X29wYWNpdHkxKSk7XFxuICBsb3dwIHZlYzMgdG1wdmFyXzI7XFxuICB0bXB2YXJfMi54ID0gZG90ICh0bXB2YXJfMS54eXosIHVfc3Bpbl93ZWlnaHRzKTtcXG4gIHRtcHZhcl8yLnkgPSBkb3QgKHRtcHZhcl8xLnh5eiwgdV9zcGluX3dlaWdodHMuenh5KTtcXG4gIHRtcHZhcl8yLnogPSBkb3QgKHRtcHZhcl8xLnh5eiwgdV9zcGluX3dlaWdodHMueXp4KTtcXG4gIGxvd3AgdmVjNCB0bXB2YXJfMztcXG4gIHRtcHZhcl8zLnh5eiA9IG1peCAodmVjMyh1X2JyaWdodG5lc3NfbG93KSwgdmVjMyh1X2JyaWdodG5lc3NfaGlnaCksICgoXFxuICAgICgodG1wdmFyXzIgKyAoKFxcbiAgICAgICgoKHRtcHZhcl8xLnggKyB0bXB2YXJfMS55KSArIHRtcHZhcl8xLnopIC8gMy4wKVxcbiAgICAgLSB0bXB2YXJfMikgKiB1X3NhdHVyYXRpb25fZmFjdG9yKSkgLSAwLjUpXFxuICAgKiB1X2NvbnRyYXN0X2ZhY3RvcikgKyAwLjUpKTtcXG4gIHRtcHZhcl8zLncgPSB0bXB2YXJfMS53O1xcbiAgZ2xfRnJhZ0NvbG9yID0gdG1wdmFyXzM7XFxufVxcblxcblwifSxcbiAgICBcImljb25cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5hdHRyaWJ1dGUgdmVjMiBhX29mZnNldDtcXG5hdHRyaWJ1dGUgdmVjMiBhX3RleDtcXG5hdHRyaWJ1dGUgZmxvYXQgYV9hbmdsZTtcXG5hdHRyaWJ1dGUgZmxvYXQgYV9taW56b29tO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX21heHpvb207XFxuYXR0cmlidXRlIGZsb2F0IGFfcmFuZ2VlbmQ7XFxuYXR0cmlidXRlIGZsb2F0IGFfcmFuZ2VzdGFydDtcXG5hdHRyaWJ1dGUgZmxvYXQgYV9sYWJlbG1pbnpvb207XFxudW5pZm9ybSBtYXQ0IHVfcG9zbWF0cml4O1xcbnVuaWZvcm0gbWF0NCB1X2V4bWF0cml4O1xcbnVuaWZvcm0gZmxvYXQgdV9hbmdsZTtcXG51bmlmb3JtIGZsb2F0IHVfem9vbTtcXG51bmlmb3JtIGZsb2F0IHVfZmxpcDtcXG51bmlmb3JtIGZsb2F0IHVfZmFkZWRpc3Q7XFxudW5pZm9ybSBmbG9hdCB1X21pbmZhZGV6b29tO1xcbnVuaWZvcm0gZmxvYXQgdV9tYXhmYWRlem9vbTtcXG51bmlmb3JtIGZsb2F0IHVfZmFkZXpvb207XFxudW5pZm9ybSBmbG9hdCB1X29wYWNpdHk7XFxudW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgZmxvYXQgZF8xO1xcbiAgZF8xID0gMC4wO1xcbiAgZmxvYXQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9IChmbG9hdChtb2QgKChhX2FuZ2xlICsgdV9hbmdsZSksIDI1Ni4wKSkpO1xcbiAgaWYgKCgoKHVfZmxpcCA+IDAuMCkgJiYgKHRtcHZhcl8yID49IDY0LjApKSAmJiAodG1wdmFyXzIgPCAxOTIuMCkpKSB7XFxuICAgIGRfMSA9IDEuMDtcXG4gIH07XFxuICBmbG9hdCB0bXB2YXJfMztcXG4gIHRtcHZhcl8zID0gKCgoMi4wIC0gXFxuICAgIGZsb2F0KCh1X3pvb20gPj0gYV9taW56b29tKSlcXG4gICkgLSAoMS4wIC0gXFxuICAgIGZsb2F0KCh1X3pvb20gPj0gYV9tYXh6b29tKSlcXG4gICkpICsgZF8xKTtcXG4gIGZsb2F0IHRtcHZhcl80O1xcbiAgdG1wdmFyXzQgPSBjbGFtcCAoKCh1X2ZhZGV6b29tIC0gYV9sYWJlbG1pbnpvb20pIC8gdV9mYWRlZGlzdCksIDAuMCwgMS4wKTtcXG4gIGlmICgodV9mYWRlZGlzdCA+PSAwLjApKSB7XFxuICAgIGIgPSB0bXB2YXJfNDtcXG4gIH0gZWxzZSB7XFxuICAgIGIgPSAoMS4wIC0gdG1wdmFyXzQpO1xcbiAgfTtcXG4gIGlmICgodV9tYXhmYWRlem9vbSA8IGFfbGFiZWxtaW56b29tKSkge1xcbiAgICBiID0gMC4wO1xcbiAgfTtcXG4gIGlmICgodV9taW5mYWRlem9vbSA+PSBhX2xhYmVsbWluem9vbSkpIHtcXG4gICAgYiA9IDEuMDtcXG4gIH07XFxuICB2ZWM0IHRtcHZhcl81O1xcbiAgdG1wdmFyXzUuencgPSB2ZWMyKDAuMCwgMS4wKTtcXG4gIHRtcHZhcl81Lnh5ID0gYV9wb3M7XFxuICB2ZWM0IHRtcHZhcl82O1xcbiAgdG1wdmFyXzYudyA9IDAuMDtcXG4gIHRtcHZhcl82Lnh5ID0gKGFfb2Zmc2V0IC8gNjQuMCk7XFxuICB0bXB2YXJfNi56ID0gKCh0bXB2YXJfMyArIGZsb2F0KFxcbiAgICAoMC4wID49IGIpXFxuICApKSArIChmbG9hdChcXG4gICAgKHVfYW5nbGUgPj0gYV9yYW5nZWVuZClcXG4gICkgKiAoMS4wIC0gXFxuICAgIGZsb2F0KCh1X2FuZ2xlID49IGFfcmFuZ2VzdGFydCkpXFxuICApKSk7XFxuICBnbF9Qb3NpdGlvbiA9ICgodV9wb3NtYXRyaXggKiB0bXB2YXJfNSkgKyAodV9leG1hdHJpeCAqIHRtcHZhcl82KSk7XFxuICBhID0gKGFfdGV4IC8gdV90ZXhzaXplKTtcXG4gIGIgPSAoYiAqIHVfb3BhY2l0eSk7XFxufVxcblxcblwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgbG93cCB2ZWM0IHRtcHZhcl8xO1xcbiAgdG1wdmFyXzEgPSAodGV4dHVyZTJEICh1X3RleHR1cmUsIGEpICogYik7XFxuICBnbF9GcmFnQ29sb3IgPSB0bXB2YXJfMTtcXG59XFxuXFxuXCJ9LFxuICAgIFwic2RmXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuYXR0cmlidXRlIHZlYzIgYV9vZmZzZXQ7XFxuYXR0cmlidXRlIHZlYzIgYV90ZXg7XFxuYXR0cmlidXRlIGZsb2F0IGFfYW5nbGU7XFxuYXR0cmlidXRlIGZsb2F0IGFfbWluem9vbTtcXG5hdHRyaWJ1dGUgZmxvYXQgYV9tYXh6b29tO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX3JhbmdlZW5kO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX3Jhbmdlc3RhcnQ7XFxuYXR0cmlidXRlIGZsb2F0IGFfbGFiZWxtaW56b29tO1xcbnVuaWZvcm0gbWF0NCB1X3Bvc21hdHJpeDtcXG51bmlmb3JtIG1hdDQgdV9leG1hdHJpeDtcXG51bmlmb3JtIGZsb2F0IHVfYW5nbGU7XFxudW5pZm9ybSBmbG9hdCB1X3pvb207XFxudW5pZm9ybSBmbG9hdCB1X2ZsaXA7XFxudW5pZm9ybSBmbG9hdCB1X2ZhZGVkaXN0O1xcbnVuaWZvcm0gZmxvYXQgdV9taW5mYWRlem9vbTtcXG51bmlmb3JtIGZsb2F0IHVfbWF4ZmFkZXpvb207XFxudW5pZm9ybSBmbG9hdCB1X2ZhZGV6b29tO1xcbnVuaWZvcm0gdmVjMiB1X3RleHNpemU7XFxudmFyeWluZyB2ZWMyIGE7XFxudmFyeWluZyBmbG9hdCBiO1xcbnZvaWQgbWFpbiAoKVxcbntcXG4gIGZsb2F0IGRfMTtcXG4gIGRfMSA9IDAuMDtcXG4gIGZsb2F0IHRtcHZhcl8yO1xcbiAgdG1wdmFyXzIgPSAoZmxvYXQobW9kICgoYV9hbmdsZSArIHVfYW5nbGUpLCAyNTYuMCkpKTtcXG4gIGlmICgoKCh1X2ZsaXAgPiAwLjApICYmICh0bXB2YXJfMiA+PSA2NC4wKSkgJiYgKHRtcHZhcl8yIDwgMTkyLjApKSkge1xcbiAgICBkXzEgPSAxLjA7XFxuICB9O1xcbiAgZmxvYXQgdG1wdmFyXzM7XFxuICB0bXB2YXJfMyA9ICgoKDIuMCAtIFxcbiAgICBmbG9hdCgodV96b29tID49IGFfbWluem9vbSkpXFxuICApIC0gKDEuMCAtIFxcbiAgICBmbG9hdCgodV96b29tID49IGFfbWF4em9vbSkpXFxuICApKSArIGRfMSk7XFxuICBmbG9hdCB0bXB2YXJfNDtcXG4gIHRtcHZhcl80ID0gY2xhbXAgKCgodV9mYWRlem9vbSAtIGFfbGFiZWxtaW56b29tKSAvIHVfZmFkZWRpc3QpLCAwLjAsIDEuMCk7XFxuICBpZiAoKHVfZmFkZWRpc3QgPj0gMC4wKSkge1xcbiAgICBiID0gdG1wdmFyXzQ7XFxuICB9IGVsc2Uge1xcbiAgICBiID0gKDEuMCAtIHRtcHZhcl80KTtcXG4gIH07XFxuICBpZiAoKHVfbWF4ZmFkZXpvb20gPCBhX2xhYmVsbWluem9vbSkpIHtcXG4gICAgYiA9IDAuMDtcXG4gIH07XFxuICBpZiAoKHVfbWluZmFkZXpvb20gPj0gYV9sYWJlbG1pbnpvb20pKSB7XFxuICAgIGIgPSAxLjA7XFxuICB9O1xcbiAgdmVjNCB0bXB2YXJfNTtcXG4gIHRtcHZhcl81Lnp3ID0gdmVjMigwLjAsIDEuMCk7XFxuICB0bXB2YXJfNS54eSA9IGFfcG9zO1xcbiAgdmVjNCB0bXB2YXJfNjtcXG4gIHRtcHZhcl82LncgPSAwLjA7XFxuICB0bXB2YXJfNi54eSA9IChhX29mZnNldCAvIDY0LjApO1xcbiAgdG1wdmFyXzYueiA9ICgodG1wdmFyXzMgKyBmbG9hdChcXG4gICAgKDAuMCA+PSBiKVxcbiAgKSkgKyAoZmxvYXQoXFxuICAgICh1X2FuZ2xlID49IGFfcmFuZ2VlbmQpXFxuICApICogKDEuMCAtIFxcbiAgICBmbG9hdCgodV9hbmdsZSA+PSBhX3Jhbmdlc3RhcnQpKVxcbiAgKSkpO1xcbiAgZ2xfUG9zaXRpb24gPSAoKHVfcG9zbWF0cml4ICogdG1wdmFyXzUpICsgKHVfZXhtYXRyaXggKiB0bXB2YXJfNikpO1xcbiAgYSA9IChhX3RleCAvIHVfdGV4c2l6ZSk7XFxufVxcblxcblwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbnVuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTtcXG51bmlmb3JtIHZlYzQgdV9jb2xvcjtcXG51bmlmb3JtIGZsb2F0IHVfYnVmZmVyO1xcbnVuaWZvcm0gZmxvYXQgdV9nYW1tYTtcXG52YXJ5aW5nIHZlYzIgYTtcXG52YXJ5aW5nIGZsb2F0IGI7XFxudm9pZCBtYWluICgpXFxue1xcbiAgZmxvYXQgZWRnZTBfMTtcXG4gIGVkZ2UwXzEgPSAodV9idWZmZXIgLSB1X2dhbW1hKTtcXG4gIGxvd3AgZmxvYXQgdG1wdmFyXzI7XFxuICB0bXB2YXJfMiA9IGNsYW1wICgoKHRleHR1cmUyRCAodV90ZXh0dXJlLCBhKS53IC0gZWRnZTBfMSkgLyAoXFxuICAgICh1X2J1ZmZlciArIHVfZ2FtbWEpXFxuICAgLSBlZGdlMF8xKSksIDAuMCwgMS4wKTtcXG4gIGxvd3AgdmVjNCB0bXB2YXJfMztcXG4gIHRtcHZhcl8zID0gKHVfY29sb3IgKiAoKHRtcHZhcl8yICogXFxuICAgICh0bXB2YXJfMiAqICgzLjAgLSAoMi4wICogdG1wdmFyXzIpKSlcXG4gICkgKiBiKSk7XFxuICBnbF9GcmFnQ29sb3IgPSB0bXB2YXJfMztcXG59XFxuXFxuXCJ9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UuanMnKTtcbnZhciBHZW9KU09OVGlsZSA9IHJlcXVpcmUoJy4vZ2VvanNvbnRpbGUuanMnKTtcblxudmFyIEdlb0pTT05Tb3VyY2UgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICB0aGlzLnRpbGVzID0ge307XG4gICAgdGhpcy5hbGx0aWxlcyA9IHt9O1xuICAgIHRoaXMuZW5hYmxlZCA9IHRydWU7XG5cbiAgICB0aGlzLnpvb21zID0gWzEsIDUsIDksIDEzXTtcbiAgICB0aGlzLm1pblRpbGVab29tID0gdGhpcy56b29tc1swXTtcbiAgICB0aGlzLm1heFRpbGVab29tID0gdGhpcy56b29tc1t0aGlzLnpvb21zLmxlbmd0aCAtIDFdO1xuXG4gICAgdGhpcy5sb2FkTmV3VGlsZXMgPSB0cnVlO1xuICAgIHRoaXMudGlsZUpTT04gPSB7XG4gICAgICAgIG1pblpvb206IDEsXG4gICAgICAgIG1heFpvb206IDEzXG4gICAgfTtcblxuICAgIHRoaXMuZGF0YSA9IG9wdGlvbnMuZGF0YTtcbn07XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShTb3VyY2UucHJvdG90eXBlKTtcblxuR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUuc2V0RGF0YSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIGlmICh0aGlzLm1hcCkgdGhpcy5fdXBkYXRlRGF0YSgpO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUub25BZGQgPSBmdW5jdGlvbihtYXApIHtcbiAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB0aGlzLnBhaW50ZXIgPSBtYXAucGFpbnRlcjtcblxuICAgIGlmICh0aGlzLm1hcC5zdHlsZSkgdGhpcy5fdXBkYXRlRGF0YSgpO1xuICAgIG1hcC5vbignc3R5bGUuY2hhbmdlJywgdGhpcy5fdXBkYXRlRGF0YS5iaW5kKHRoaXMpKTtcbn07XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlLl91cGRhdGVEYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHNvdXJjZSA9IHRoaXM7XG4gICAgdGhpcy53b3JrZXJJRCA9IHRoaXMubWFwLmRpc3BhdGNoZXIuc2VuZCgncGFyc2UgZ2VvanNvbicsIHtcbiAgICAgICAgZGF0YTogdGhpcy5kYXRhLFxuICAgICAgICB6b29tczogdGhpcy56b29tcyxcbiAgICAgICAgdGlsZVNpemU6IDUxMixcbiAgICAgICAgc291cmNlOiB0aGlzLmlkXG4gICAgfSwgZnVuY3Rpb24oZXJyLCB0aWxlcykge1xuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNvdXJjZS5hbGx0aWxlc1t0aWxlc1tpXS5pZF0gPSBuZXcgR2VvSlNPTlRpbGUodGlsZXNbaV0uaWQsIHNvdXJjZSwgdGlsZXNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzb3VyY2UubWFwKSBzb3VyY2UubWFwLnVwZGF0ZSgpO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUuX2FkZFRpbGUgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciB0aWxlID0gdGhpcy5hbGx0aWxlc1tpZF07XG4gICAgaWYgKHRpbGUpIHtcbiAgICAgICAgdGlsZS5fbG9hZCgpO1xuICAgICAgICB0aGlzLnRpbGVzW2lkXSA9IHRpbGU7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH1cbiAgICByZXR1cm4gdGlsZSB8fCB7fTtcbn07XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlLl9jb3ZlcmluZ1pvb21MZXZlbCA9IGZ1bmN0aW9uKHpvb20pIHtcbiAgICBmb3IgKHZhciBpID0gdGhpcy56b29tcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBpZiAodGhpcy56b29tc1tpXSA8PSB6b29tKSB7XG4gICAgICAgICAgICB2YXIgeiA9IHRoaXMuem9vbXNbaV07XG4gICAgICAgICAgICByZXR1cm4gejtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUaWxlID0gcmVxdWlyZSgnLi90aWxlLmpzJyk7XG52YXIgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyc2V0LmpzJyk7XG52YXIgY3JlYXRlQnVja2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9jcmVhdGVidWNrZXQuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHZW9KU09OVGlsZTtcblxuZnVuY3Rpb24gR2VvSlNPTlRpbGUoaWQsIHNvdXJjZSwgZGF0YSkge1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIHRoaXMud29ya2VySUQgPSBzb3VyY2Uud29ya2VySUQ7XG59XG5cbkdlb0pTT05UaWxlLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoVGlsZS5wcm90b3R5cGUpO1xuXG5HZW9KU09OVGlsZS5wcm90b3R5cGUuX2xvYWQgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5sb2FkZWQpIHJldHVybjtcbiAgICB0aGlzLmxvYWRlZCA9IHRydWU7XG5cbiAgICB2YXIgZGF0YSA9IHRoaXMuZGF0YTtcbiAgICB0aGlzLmJ1ZmZlcnMgPSBuZXcgQnVmZmVyU2V0KGRhdGEuYnVmZmVycyk7XG5cbiAgICB0aGlzLmJ1Y2tldHMgPSB7fTtcbiAgICBmb3IgKHZhciBiIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICB0aGlzLmJ1Y2tldHNbYl0gPSBjcmVhdGVCdWNrZXQodGhpcy5zb3VyY2UubWFwLnN0eWxlLmJ1Y2tldHNbYl0sIHRoaXMuYnVmZmVycywgdW5kZWZpbmVkLCBkYXRhLmVsZW1lbnRHcm91cHNbYl0pO1xuICAgIH1cblxuXG59O1xuXG4vLyBub29wc1xuR2VvSlNPTlRpbGUucHJvdG90eXBlLmFib3J0ID0gZnVuY3Rpb24oKSB7IH07XG5HZW9KU09OVGlsZS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24oKSB7IH07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gV3JhcHBlcjtcblxuLy8gY29uZm9ybSB0byB2ZWN0b3J0aWxlIGFwaVxuZnVuY3Rpb24gV3JhcHBlcihmZWF0dXJlcykge1xuICAgIHRoaXMuZmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICB0aGlzLmxlbmd0aCA9IGZlYXR1cmVzLmxlbmd0aDtcbn1cblxuV3JhcHBlci5wcm90b3R5cGUuZmVhdHVyZSA9IGZ1bmN0aW9uKGkpIHtcbiAgICByZXR1cm4gbmV3IEZlYXR1cmVXcmFwcGVyKHRoaXMuZmVhdHVyZXNbaV0pO1xufTtcblxudmFyIG1hcHBpbmcgPSB7XG4gICAgJ1BvaW50JzogMSxcbiAgICAnTGluZVN0cmluZyc6IDIsXG4gICAgJ1BvbHlnb24nOiAzXG59O1xuXG5mdW5jdGlvbiBGZWF0dXJlV3JhcHBlcihmZWF0dXJlKSB7XG4gICAgdGhpcy5mZWF0dXJlID0gZmVhdHVyZTtcbiAgICB0aGlzLl90eXBlID0gbWFwcGluZ1tmZWF0dXJlLnR5cGVdO1xuICAgIHRoaXMucHJvcGVydGllcyA9IGZlYXR1cmUucHJvcGVydGllcztcbn1cblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmZlYXR1cmUuY29vcmRzO1xufTtcblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmJib3ggPSBmdW5jdGlvbigpIHtcblxuICAgIGlmICh0aGlzLl90eXBlID09PSBtYXBwaW5nLlBvaW50KSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLmZlYXR1cmUuY29vcmRzWzBdLFxuICAgICAgICAgICAgdGhpcy5mZWF0dXJlLmNvb3Jkc1sxXSxcbiAgICAgICAgICAgIHRoaXMuZmVhdHVyZS5jb29yZHNbMF0sXG4gICAgICAgICAgICB0aGlzLmZlYXR1cmUuY29vcmRzWzFdXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgdmFyIHJpbmdzID0gdGhpcy5mZWF0dXJlLmNvb3JkcztcblxuICAgIHZhciB4MSA9IEluZmluaXR5LFxuICAgICAgICB4MiA9IC1JbmZpbml0eSxcbiAgICAgICAgeTEgPSBJbmZpbml0eSxcbiAgICAgICAgeTIgPSAtSW5maW5pdHk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByaW5nID0gcmluZ3NbaV07XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY29vcmQgPSByaW5nW2pdO1xuXG4gICAgICAgICAgICB4MSA9IE1hdGgubWluKHgxLCBjb29yZC54KTtcbiAgICAgICAgICAgIHgyID0gTWF0aC5tYXgoeDIsIGNvb3JkLngpO1xuICAgICAgICAgICAgeTEgPSBNYXRoLm1pbih5MSwgY29vcmQueSk7XG4gICAgICAgICAgICB5MiA9IE1hdGgubWF4KHkyLCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbeDEsIHkxLCB4MiwgeTJdO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUuanMnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4LmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gUmFzdGVyVGlsZTtcblxuZnVuY3Rpb24gUmFzdGVyVGlsZShpZCwgc291cmNlLCB1cmwsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMubG9hZGVkID0gZmFsc2U7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2U7XG4gICAgdGhpcy5tYXAgPSBzb3VyY2UubWFwO1xuICAgIHRoaXMuX2xvYWQoKTtcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgdGhpcy51c2VzID0gMTtcblxuICAgIC8vIFRvZG8gZmluaXNoIGZpZ3VyaW5nIG91dCB3aGF0IHJhc3RlciBidWNrZXRzIGFyZVxuICAgIHRoaXMuYnVja2V0cyA9IHt9O1xuICAgIHRoaXMuaW5mbyA9IHsgcmFzdGVyOiB0cnVlIH07XG4gICAgdmFyIGJ1Y2tldHMgPSB0aGlzLm1hcC5zdHlsZS5idWNrZXRzO1xuICAgIGZvciAodmFyIGIgaW4gYnVja2V0cykge1xuICAgICAgICB2YXIgYnVja2V0ID0gYnVja2V0c1tiXTtcbiAgICAgICAgdmFyIHNvdXJjZWlkID0gYnVja2V0ICYmIGJ1Y2tldC5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2UuaWQgPT09IHNvdXJjZWlkKSB7XG4gICAgICAgICAgICB0aGlzLmJ1Y2tldHNbYl0gPSB7XG4gICAgICAgICAgICAgICAgaW5mbzogYnVja2V0LnJlbmRlcixcbiAgICAgICAgICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgICAgICAgICB0aWxlOiB0aGlzXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxufVxuXG5SYXN0ZXJUaWxlLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoVGlsZS5wcm90b3R5cGUpO1xuXG5SYXN0ZXJUaWxlLnByb3RvdHlwZS5fbG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0aWxlID0gdGhpcztcbiAgICBhamF4LmdldEltYWdlKHRoaXMudXJsLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICAvLyBAVE9ETyBoYW5kbGUgZXJyb3JzLlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG4gICAgICAgIHRpbGUuaW1nID0gaW1nO1xuICAgICAgICBpZiAodGlsZS5tYXApIHRpbGUub25UaWxlTG9hZCgpO1xuICAgIH0pO1xufTtcblxuUmFzdGVyVGlsZS5wcm90b3R5cGUub25UaWxlTG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIHN0YXJ0IHRleHR1cmUgdXBsb2FkXG4gICAgdGhpcy5iaW5kKHRoaXMubWFwLnBhaW50ZXIuZ2wpO1xuXG4gICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgIHRoaXMuY2FsbGJhY2soKTtcbn07XG5cblJhc3RlclRpbGUucHJvdG90eXBlLmFib3J0ID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5hYm9ydGVkID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5pbWcpIHRoaXMuaW1nLnNyYyA9ICcnO1xuICAgIGRlbGV0ZSB0aGlzLmltZztcbn07XG5cblJhc3RlclRpbGUucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihnbCkge1xuICAgIGlmICghdGhpcy50ZXh0dXJlKSB7XG4gICAgICAgIC8vIHRyeSB0byBmaW5kIHJldXNhYmxlIHRleHR1cmVcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gdGhpcy5tYXAucGFpbnRlci5nZXRUZXh0dXJlKHRoaXMuaW1nLndpZHRoKTtcbiAgICAgICAgaWYgKHRoaXMudGV4dHVyZSkge1xuICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy5pbWcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVJfTUlQTUFQX05FQVJFU1QpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1QsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLmltZyk7XG4gICAgICAgICAgICB0aGlzLnRleHR1cmUuc2l6ZSA9IHRoaXMuaW1nLndpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGdsLmdlbmVyYXRlTWlwbWFwKGdsLlRFWFRVUkVfMkQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgfVxufTtcblxuUmFzdGVyVGlsZS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMudGV4dHVyZSkgdGhpcy5tYXAucGFpbnRlci5zYXZlVGV4dHVyZSh0aGlzLnRleHR1cmUpO1xuICAgIGRlbGV0ZSB0aGlzLm1hcDtcbn07XG5cblJhc3RlclRpbGUucHJvdG90eXBlLmZlYXR1cmVzQXQgPSBmdW5jdGlvbihwb3MsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAvLyBub29wXG4gICAgY2FsbGJhY2sobnVsbCwgW10pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwuanMnKSxcbiAgICBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4LmpzJyksXG4gICAgdGlsZUpTT04gPSByZXF1aXJlKCcuLi91dGlsL3VybC5qcycpLnRpbGVKU09OLFxuICAgIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQuanMnKSxcbiAgICBDYWNoZSA9IHJlcXVpcmUoJy4uL3V0aWwvbXJ1Y2FjaGUuanMnKSxcbiAgICBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVjb29yZCcpLFxuICAgIFZlY3RvclRpbGUgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGUnKSxcbiAgICBSYXN0ZXJUaWxlID0gcmVxdWlyZSgnLi9yYXN0ZXJ0aWxlLmpzJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNvdXJjZTtcblxuU291cmNlLnByb3RvY29scyA9IHtcbiAgICBcIm1hcGJveFwiOiBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTih0aWxlSlNPTih1cmwuc3BsaXQoJzovLycpWzFdKSwgY2FsbGJhY2spO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIFNvdXJjZShvcHRpb25zKSB7XG4gICAgdGhpcy50aWxlcyA9IHt9O1xuICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuICAgIHRoaXMudHlwZSA9IG9wdGlvbnMudHlwZTtcbiAgICBpZiAodGhpcy50eXBlID09PSAndmVjdG9yJyAmJiBvcHRpb25zLnRpbGVTaXplICYmIG9wdGlvbnMudGlsZVNpemUgIT09IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyJyk7XG4gICAgfVxuICAgIHRoaXMuVGlsZSA9IHRoaXMudHlwZSA9PT0gJ3ZlY3RvcicgPyBWZWN0b3JUaWxlIDogUmFzdGVyVGlsZTtcbiAgICB0aGlzLm9wdGlvbnMgPSB1dGlsLmluaGVyaXQodGhpcy5vcHRpb25zLCBvcHRpb25zKTtcbiAgICB0aGlzLmNhY2hlID0gbmV3IENhY2hlKHRoaXMub3B0aW9ucy5jYWNoZVNpemUsIGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS5yZW1vdmUoKTtcbiAgICB9KTtcblxuICAgIHZhciBwcm90b2NvbCA9IG9wdGlvbnMudXJsLnNwbGl0KCc6JylbMF07XG4gICAgU291cmNlLnByb3RvY29sc1twcm90b2NvbF0ob3B0aW9ucy51cmwsIGZ1bmN0aW9uKGVyciwgdGlsZUpTT04pIHtcbiAgICAgICAgaWYgKGVycikgdGhyb3cgZXJyO1xuICAgICAgICB0aGlzLnRpbGVKU09OID0gdGlsZUpTT047XG4gICAgICAgIHRoaXMubG9hZE5ld1RpbGVzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy51cGRhdGUoKTtcblxuICAgICAgICBpZiAodGhpcy5tYXApIHRoaXMubWFwLmZpcmUoJ3NvdXJjZS5hZGQnLCB7c291cmNlOiB0aGlzfSk7XG4gICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuX3VwZGF0ZVRpbGVzID0gdXRpbC50aHJvdHRsZSh0aGlzLl91cGRhdGVUaWxlcywgNTAsIHRoaXMpO1xufVxuXG5Tb3VyY2UucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEV2ZW50ZWQsIHtcbiAgICBvcHRpb25zOiB7XG4gICAgICAgIHRpbGVTaXplOiA1MTIsXG4gICAgICAgIGNhY2hlU2l6ZTogMjBcbiAgICB9LFxuXG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICAgICAgdGhpcy5wYWludGVyID0gbWFwLnBhaW50ZXI7XG4gICAgfSxcblxuICAgIGxvYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMudGlsZXMpIHtcbiAgICAgICAgICAgIHRoaXMudGlsZXNbdF0uX2xvYWQoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBsb2FkZWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMudGlsZXMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy50aWxlc1t0XS5sb2FkZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICB1cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICB0aGlzLl91cGRhdGVUaWxlcygpO1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uKGxheWVycykge1xuICAgICAgICAvLyBJdGVyYXRpdmVseSBwYWludCBldmVyeSB0aWxlLlxuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICB2YXIgb3JkZXIgPSBPYmplY3Qua2V5cyh0aGlzLnRpbGVzKTtcbiAgICAgICAgb3JkZXIuc29ydCh0aGlzLl96X29yZGVyKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGlkID0gb3JkZXJbaV07XG4gICAgICAgICAgICB2YXIgdGlsZSA9IHRoaXMudGlsZXNbaWRdO1xuICAgICAgICAgICAgaWYgKHRpbGUubG9hZGVkICYmICF0aGlzLmNvdmVyZWRUaWxlc1tpZF0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW5kZXJUaWxlKHRpbGUsIGlkLCBsYXllcnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHBvaW50ID0gUG9pbnQuY29udmVydChwb2ludCk7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5sYXllcikge1xuICAgICAgICAgICAgdmFyIHN0eWxlID0gdGhpcy5tYXAuc3R5bGUsXG4gICAgICAgICAgICAgICAgbGF5ZXIgPSBzdHlsZS5nZXRMYXllcihwYXJhbXMubGF5ZXIpO1xuICAgICAgICAgICAgcGFyYW1zLmJ1Y2tldCA9IHN0eWxlLmJ1Y2tldHNbbGF5ZXIucmVmIHx8IGxheWVyLmlkXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBvcmRlciA9IE9iamVjdC5rZXlzKHRoaXMudGlsZXMpO1xuICAgICAgICBvcmRlci5zb3J0KHRoaXMuX3pfb3JkZXIpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBvcmRlcltpXTtcbiAgICAgICAgICAgIHZhciB0aWxlID0gdGhpcy50aWxlc1tpZF07XG4gICAgICAgICAgICB2YXIgcG9zID0gdGlsZS5wb3NpdGlvbkF0KGlkLCBwb2ludCk7XG5cbiAgICAgICAgICAgIGlmIChwb3MgJiYgcG9zLnggPj0gMCAmJiBwb3MueCA8IDQwOTYgJiYgcG9zLnkgPj0gMCAmJiBwb3MueSA8IDQwOTYpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgY2xpY2sgaXMgd2l0aGluIHRoZSB2aWV3cG9ydC4gVGhlcmUgaXMgb25seSBldmVyIG9uZSB0aWxlIGluXG4gICAgICAgICAgICAgICAgLy8gYSBsYXllciB0aGF0IGhhcyB0aGlzIHByb3BlcnR5LlxuICAgICAgICAgICAgICAgIHJldHVybiB0aWxlLmZlYXR1cmVzQXQocG9zLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICB9LFxuXG4gICAgLy8gZ2V0IHRoZSB6b29tIGxldmVsIGFkanVzdGVkIGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtYXAgYW5kIHNvdXJjZSB0aWxlc2l6ZXNcbiAgICBfZ2V0Wm9vbTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB6T2Zmc2V0ID0gTWF0aC5sb2codGhpcy5tYXAudHJhbnNmb3JtLnRpbGVTaXplL3RoaXMub3B0aW9ucy50aWxlU2l6ZSkgLyBNYXRoLkxOMjtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLnRyYW5zZm9ybS56b29tICsgek9mZnNldDtcbiAgICB9LFxuXG4gICAgX2NvdmVyaW5nWm9vbUxldmVsOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIGZvciAodmFyIHogPSB0aGlzLnRpbGVKU09OLm1heHpvb207IHogPj0gdGhpcy50aWxlSlNPTi5taW56b29tOyB6LS0pIHtcbiAgICAgICAgICAgIGlmICh6IDw9IHpvb20pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50eXBlID09PSAncmFzdGVyJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBhbGxvdyB1bmRlcnNjYWxpbmcgYnkgcm91bmRpbmcgdG8gdGhlIG5lYXJlc3Qgem9vbSBsZXZlbFxuICAgICAgICAgICAgICAgICAgICBpZiAoeiA8IHRoaXMudGlsZUpTT04ubWF4em9vbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeiArPSBNYXRoLnJvdW5kKHpvb20gLSB6KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gejtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9LFxuXG4gICAgX2NoaWxkWm9vbUxldmVsOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHpvb20gPSBNYXRoLm1heCh0aGlzLnRpbGVKU09OLm1pbnpvb20sIHpvb20gKyAxKTtcbiAgICAgICAgcmV0dXJuIHpvb20gPD0gdGhpcy50aWxlSlNPTi5tYXh6b29tID8gem9vbSA6IG51bGw7XG4gICAgfSxcblxuICAgIF9nZXRDb3ZlcmluZ1RpbGVzOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIGlmICh6b29tID09PSB1bmRlZmluZWQpIHpvb20gPSB0aGlzLl9nZXRab29tKCk7XG4gICAgICAgIHZhciB6ID0gdGhpcy5fY292ZXJpbmdab29tTGV2ZWwoem9vbSksXG4gICAgICAgICAgICB0aWxlcyA9IDEgPDwgeixcbiAgICAgICAgICAgIHRyID0gdGhpcy5tYXAudHJhbnNmb3JtLFxuICAgICAgICAgICAgdGlsZUNlbnRlciA9IFRpbGVDb29yZC56b29tVG8odHIubG9jYXRpb25Db29yZGluYXRlKHRyLmNlbnRlciksIHopO1xuXG4gICAgICAgIHZhciBwb2ludHMgPSBbXG4gICAgICAgICAgICBUaWxlQ29vcmQuem9vbVRvKHRyLnBvaW50Q29vcmRpbmF0ZSh0aWxlQ2VudGVyLCB7eDogMCwgeTogMH0pLCB6KSxcbiAgICAgICAgICAgIFRpbGVDb29yZC56b29tVG8odHIucG9pbnRDb29yZGluYXRlKHRpbGVDZW50ZXIsIHt4OiB0ci53aWR0aCwgeTogMH0pLCB6KSxcbiAgICAgICAgICAgIFRpbGVDb29yZC56b29tVG8odHIucG9pbnRDb29yZGluYXRlKHRpbGVDZW50ZXIsIHt4OiB0ci53aWR0aCwgeTogdHIuaGVpZ2h0fSksIHopLFxuICAgICAgICAgICAgVGlsZUNvb3JkLnpvb21Ubyh0ci5wb2ludENvb3JkaW5hdGUodGlsZUNlbnRlciwge3g6IDAsIHk6IHRyLmhlaWdodH0pLCB6KVxuICAgICAgICBdLCB0ID0ge307XG5cbiAgICAgICAgLy8gRGl2aWRlIHRoZSBzY3JlZW4gdXAgaW4gdHdvIHRyaWFuZ2xlcyBhbmQgc2NhbiBlYWNoIG9mIHRoZW06XG4gICAgICAgIC8vICstLS0vXG4gICAgICAgIC8vIHwgLyB8XG4gICAgICAgIC8vIC8tLS0rXG4gICAgICAgIHRoaXMuX3NjYW5UcmlhbmdsZShwb2ludHNbMF0sIHBvaW50c1sxXSwgcG9pbnRzWzJdLCAwLCB0aWxlcywgc2NhbkxpbmUpO1xuICAgICAgICB0aGlzLl9zY2FuVHJpYW5nbGUocG9pbnRzWzJdLCBwb2ludHNbM10sIHBvaW50c1swXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcblxuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModCkuc29ydChmcm9tQ2VudGVyKTtcblxuICAgICAgICBmdW5jdGlvbiBmcm9tQ2VudGVyKGEsIGIpIHtcbiAgICAgICAgICAgIHZhciBhZCA9IE1hdGguYWJzKGEueCAtIHRpbGVDZW50ZXIuY29sdW1uKSArXG4gICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKGEueSAtIHRpbGVDZW50ZXIucm93KSxcbiAgICAgICAgICAgICAgICBiZCA9IE1hdGguYWJzKGIueCAtIHRpbGVDZW50ZXIuY29sdW1uKSArXG4gICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKGIueSAtIHRpbGVDZW50ZXIucm93KTtcblxuICAgICAgICAgICAgcmV0dXJuIGFkIC0gYmQ7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzY2FuTGluZSh4MCwgeDEsIHkpIHtcbiAgICAgICAgICAgIHZhciB4LCB3eDtcbiAgICAgICAgICAgIGlmICh5ID49IDAgJiYgeSA8PSB0aWxlcykge1xuICAgICAgICAgICAgICAgIGZvciAoeCA9IHgwOyB4IDwgeDE7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICB3eCA9ICh4ICsgdGlsZXMpICUgdGlsZXM7XG4gICAgICAgICAgICAgICAgICAgIHRbVGlsZUNvb3JkLnRvSUQoeiwgd3gsIHksIE1hdGguZmxvb3IoeC90aWxlcykpXSA9IHt4OiB3eCwgeTogeX07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8vIEdpdmVuIGEgdGlsZSBvZiBkYXRhLCBpdHMgaWQsIGFuZCBhIHN0eWxlIGxheWVycywgcmVuZGVyIHRoZSB0aWxlIHRvIHRoZSBjYW52YXNcbiAgICBfcmVuZGVyVGlsZTogZnVuY3Rpb24odGlsZSwgaWQsIGxheWVycykge1xuICAgICAgICB2YXIgcG9zID0gVGlsZUNvb3JkLmZyb21JRChpZCk7XG4gICAgICAgIHZhciB6ID0gcG9zLnosIHggPSBwb3MueCwgeSA9IHBvcy55LCB3ID0gcG9zLnc7XG4gICAgICAgIHggKz0gdyAqICgxIDw8IHopO1xuXG4gICAgICAgIHRpbGUuY2FsY3VsYXRlTWF0cmljZXMoeiwgeCwgeSwgdGhpcy5tYXAudHJhbnNmb3JtLCB0aGlzLnBhaW50ZXIpO1xuXG4gICAgICAgIHRoaXMucGFpbnRlci5kcmF3KHRpbGUsIHRoaXMubWFwLnN0eWxlLCBsYXllcnMsIHtcbiAgICAgICAgICAgIHo6IHosIHg6IHgsIHk6IHksXG4gICAgICAgICAgICBkZWJ1ZzogdGhpcy5tYXAuZGVidWcsXG4gICAgICAgICAgICBhbnRpYWxpYXNpbmc6IHRoaXMubWFwLmFudGlhbGlhc2luZyxcbiAgICAgICAgICAgIHZlcnRpY2VzOiB0aGlzLm1hcC52ZXJ0aWNlcyxcbiAgICAgICAgICAgIHJvdGF0aW5nOiB0aGlzLm1hcC5yb3RhdGluZyxcbiAgICAgICAgICAgIHpvb21pbmc6IHRoaXMubWFwLnpvb21pbmdcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIC8vIFJlY3Vyc2l2ZWx5IGZpbmQgY2hpbGRyZW4gb2YgdGhlIGdpdmVuIHRpbGUgKHVwIHRvIG1heENvdmVyaW5nWm9vbSkgdGhhdCBhcmUgYWxyZWFkeSBsb2FkZWQ7XG4gICAgLy8gYWRkcyBmb3VuZCB0aWxlcyB0byByZXRhaW4gb2JqZWN0OyByZXR1cm5zIHRydWUgaWYgY2hpbGRyZW4gY29tcGxldGVseSBjb3ZlciB0aGUgdGlsZVxuXG4gICAgX2ZpbmRMb2FkZWRDaGlsZHJlbjogZnVuY3Rpb24oaWQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IHRydWU7XG4gICAgICAgIHZhciB6ID0gVGlsZUNvb3JkLmZyb21JRChpZCkuejtcbiAgICAgICAgdmFyIGlkcyA9IFRpbGVDb29yZC5jaGlsZHJlbihpZCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50aWxlc1tpZHNbaV1dICYmIHRoaXMudGlsZXNbaWRzW2ldXS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICByZXRhaW5baWRzW2ldXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKHogPCBtYXhDb3ZlcmluZ1pvb20pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gR28gZnVydGhlciBkb3duIHRoZSBoaWVyYXJjaHkgdG8gZmluZCBtb3JlIHVubG9hZGVkIGNoaWxkcmVuLlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9maW5kTG9hZGVkQ2hpbGRyZW4oaWRzW2ldLCBtYXhDb3ZlcmluZ1pvb20sIHJldGFpbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb21wbGV0ZTtcbiAgICB9LFxuXG4gICAgLy8gRmluZCBhIGxvYWRlZCBwYXJlbnQgb2YgdGhlIGdpdmVuIHRpbGUgKHVwIHRvIG1pbkNvdmVyaW5nWm9vbSk7XG4gICAgLy8gYWRkcyB0aGUgZm91bmQgdGlsZSB0byByZXRhaW4gb2JqZWN0IGFuZCByZXR1cm5zIHRydWUgaWYgYSBwYXJlbnQgd2FzIGZvdW5kXG5cbiAgICBfZmluZExvYWRlZFBhcmVudDogZnVuY3Rpb24oaWQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIGZvciAodmFyIHogPSBUaWxlQ29vcmQuZnJvbUlEKGlkKS56OyB6ID49IG1pbkNvdmVyaW5nWm9vbTsgei0tKSB7XG4gICAgICAgICAgICBpZCA9IFRpbGVDb29yZC5wYXJlbnQoaWQpO1xuICAgICAgICAgICAgaWYgKHRoaXMudGlsZXNbaWRdICYmIHRoaXMudGlsZXNbaWRdLmxvYWRlZCkge1xuICAgICAgICAgICAgICAgIHJldGFpbltpZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgLy8gUmVtb3ZlcyB0aWxlcyB0aGF0IGFyZSBvdXRzaWRlIHRoZSB2aWV3cG9ydCBhbmQgYWRkcyBuZXcgdGlsZXMgdGhhdCBhcmUgaW5zaWRlIHRoZSB2aWV3cG9ydC5cbiAgICBfdXBkYXRlVGlsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMubWFwIHx8ICF0aGlzLm1hcC5sb2FkTmV3VGlsZXMgfHwgIXRoaXMubG9hZE5ld1RpbGVzIHx8ICF0aGlzLm1hcC5zdHlsZS5zb3VyY2VzW3RoaXMuaWRdKSByZXR1cm47XG5cbiAgICAgICAgdmFyIHpvb20gPSBNYXRoLmZsb29yKHRoaXMuX2dldFpvb20oKSk7XG4gICAgICAgIHZhciByZXF1aXJlZCA9IHRoaXMuX2dldENvdmVyaW5nVGlsZXMoKS5zb3J0KHRoaXMuX2NlbnRlck91dC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBpZDtcbiAgICAgICAgdmFyIGNvbXBsZXRlO1xuICAgICAgICB2YXIgdGlsZTtcblxuICAgICAgICAvLyBEZXRlcm1pbmUgdGhlIG92ZXJ6b29taW5nL3VuZGVyem9vbWluZyBhbW91bnRzLlxuICAgICAgICB2YXIgbWluQ292ZXJpbmdab29tID0gTWF0aC5tYXgodGhpcy50aWxlSlNPTi5taW56b29tLCB6b29tIC0gMTApO1xuICAgICAgICB2YXIgbWF4Q292ZXJpbmdab29tID0gdGhpcy50aWxlSlNPTi5taW56b29tO1xuICAgICAgICB3aGlsZSAobWF4Q292ZXJpbmdab29tIDwgem9vbSArIDEpIHtcbiAgICAgICAgICAgIHZhciBsZXZlbCA9IHRoaXMuX2NoaWxkWm9vbUxldmVsKG1heENvdmVyaW5nWm9vbSk7XG4gICAgICAgICAgICBpZiAobGV2ZWwgPT09IG51bGwpIGJyZWFrO1xuICAgICAgICAgICAgZWxzZSBtYXhDb3ZlcmluZ1pvb20gPSBsZXZlbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldGFpbiBpcyBhIGxpc3Qgb2YgdGlsZXMgdGhhdCB3ZSBzaG91bGRuJ3QgZGVsZXRlLCBldmVuIGlmIHRoZXkgYXJlIG5vdFxuICAgICAgICAvLyB0aGUgbW9zdCBpZGVhbCB0aWxlIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydC4gVGhpcyBtYXkgaW5jbHVkZSB0aWxlcyBsaWtlXG4gICAgICAgIC8vIHBhcmVudCBvciBjaGlsZCB0aWxlcyB0aGF0IGFyZSAqYWxyZWFkeSogbG9hZGVkLlxuICAgICAgICB2YXIgcmV0YWluID0ge307XG4gICAgICAgIC8vIENvdmVyZWQgaXMgYSBsaXN0IG9mIHJldGFpbmVkIHRpbGVzIHdobydzIGFyZWFzIGFyZSBmdWxsIGNvdmVyZWQgYnkgb3RoZXIsXG4gICAgICAgIC8vIGJldHRlciwgcmV0YWluZWQgdGlsZXMuIFRoZXkgYXJlIG5vdCBkcmF3biBzZXBhcmF0ZWx5LlxuICAgICAgICB0aGlzLmNvdmVyZWRUaWxlcyA9IHt9O1xuXG4gICAgICAgIHZhciBmdWxseUNvbXBsZXRlID0gdHJ1ZTtcblxuICAgICAgICAvLyBBZGQgZXhpc3RpbmcgY2hpbGQvcGFyZW50IHRpbGVzIGlmIHRoZSBhY3R1YWwgdGlsZSBpcyBub3QgeWV0IGxvYWRlZFxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVxdWlyZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlkID0gK3JlcXVpcmVkW2ldO1xuICAgICAgICAgICAgcmV0YWluW2lkXSA9IHRydWU7XG4gICAgICAgICAgICB0aWxlID0gdGhpcy5fYWRkVGlsZShpZCk7XG5cbiAgICAgICAgICAgIGlmICghdGlsZS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgdGlsZSB3ZSByZXF1aXJlIGlzIG5vdCB5ZXQgbG9hZGVkLiBUcnkgdG8gZmluZCBhIHBhcmVudCBvclxuICAgICAgICAgICAgICAgIC8vIGNoaWxkIHRpbGUgdGhhdCB3ZSBhbHJlYWR5IGhhdmUuXG5cbiAgICAgICAgICAgICAgICAvLyBGaXJzdCwgdHJ5IHRvIGZpbmQgZXhpc3RpbmcgY2hpbGQgdGlsZXMgdGhhdCBjb21wbGV0ZWx5IGNvdmVyIHRoZVxuICAgICAgICAgICAgICAgIC8vIG1pc3NpbmcgdGlsZS5cbiAgICAgICAgICAgICAgICBjb21wbGV0ZSA9IHRoaXMuX2ZpbmRMb2FkZWRDaGlsZHJlbihpZCwgbWF4Q292ZXJpbmdab29tLCByZXRhaW4pO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlbiwgaWYgdGhlcmUgYXJlIG5vIGNvbXBsZXRlIGNoaWxkIHRpbGVzLCB0cnkgdG8gZmluZCBleGlzdGluZ1xuICAgICAgICAgICAgICAgIC8vIHBhcmVudCB0aWxlcyB0aGF0IGNvbXBsZXRlbHkgY292ZXIgdGhlIG1pc3NpbmcgdGlsZS5cbiAgICAgICAgICAgICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gdGhpcy5fZmluZExvYWRlZFBhcmVudChpZCwgbWluQ292ZXJpbmdab29tLCByZXRhaW4pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFRoZSB1bmxvYWRlZCB0aWxlJ3MgYXJlYSBpcyBub3QgY29tcGxldGVseSBjb3ZlcmVkIGxvYWRlZCB0aWxlc1xuICAgICAgICAgICAgICAgIGlmICghY29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbHlDb21wbGV0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgdmFyIGZhZGVEdXJhdGlvbiA9IHRoaXMudHlwZSA9PT0gJ3Jhc3RlcicgPyB0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24gOiAwO1xuXG4gICAgICAgIGZvciAoaWQgaW4gcmV0YWluKSB7XG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF07XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aWxlLnRpbWVBZGRlZCA+IG5vdyAtIGZhZGVEdXJhdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgdGlsZSBpcyBzdGlsbCBmYWRpbmcgaW4uIEZpbmQgdGlsZXMgdG8gY3Jvc3MtZmFkZSB3aXRoIGl0LlxuXG4gICAgICAgICAgICAgICAgY29tcGxldGUgPSB0aGlzLl9maW5kTG9hZGVkQ2hpbGRyZW4oaWQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKTtcblxuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvdmVyZWRUaWxlc1tpZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbmRMb2FkZWRQYXJlbnQoaWQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGlkIGluIHRoaXMuY292ZXJlZFRpbGVzKSByZXRhaW5baWRdID0gdHJ1ZTtcblxuICAgICAgICAvLyBSZW1vdmUgdGhlIHRpbGVzIHdlIGRvbid0IG5lZWQgYW55bW9yZS5cbiAgICAgICAgdmFyIHJlbW92ZSA9IHV0aWwua2V5c0RpZmZlcmVuY2UodGhpcy50aWxlcywgcmV0YWluKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJlbW92ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWQgPSArcmVtb3ZlW2ldO1xuICAgICAgICAgICAgdGhpcy5fcmVtb3ZlVGlsZShpZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2xvYWRUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgbGF5ZXIgPSB0aGlzO1xuICAgICAgICB2YXIgbWFwID0gdGhpcy5tYXAsXG4gICAgICAgICAgICBwb3MgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKSxcbiAgICAgICAgICAgIHRpbGU7XG5cbiAgICAgICAgaWYgKHBvcy53ID09PSAwKSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLnRpbWUoJ2xvYWRpbmcgJyArIHBvcy56ICsgJy8nICsgcG9zLnggKyAnLycgKyBwb3MueSk7XG4gICAgICAgICAgICB2YXIgdXJsID0gVGlsZUNvb3JkLnVybChpZCwgdGhpcy50aWxlSlNPTi50aWxlcyk7XG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF0gPSBuZXcgdGhpcy5UaWxlKGlkLCB0aGlzLCB1cmwsIHRpbGVDb21wbGV0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgd3JhcHBlZCA9IFRpbGVDb29yZC50b0lEKHBvcy56LCBwb3MueCwgcG9zLnksIDApO1xuICAgICAgICAgICAgdGlsZSA9IHRoaXMudGlsZXNbaWRdID0gdGhpcy50aWxlc1t3cmFwcGVkXSB8fCB0aGlzLl9hZGRUaWxlKHdyYXBwZWQpO1xuICAgICAgICAgICAgdGlsZS51c2VzKys7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB0aWxlQ29tcGxldGUoZXJyKSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLnRpbWVFbmQoJ2xvYWRpbmcgJyArIHBvcy56ICsgJy8nICsgcG9zLnggKyAnLycgKyBwb3MueSk7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdmYWlsZWQgdG8gbG9hZCB0aWxlICVkLyVkLyVkOiAlcycsIHBvcy56LCBwb3MueCwgcG9zLnksIGVyci5zdGFjayB8fCBlcnIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsYXllci5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgIH0sXG5cbiAgICAvLyBBZGRzIGEgdmVjdG9yIHRpbGUgdG8gdGhlIG1hcC4gSXQgd2lsbCB0cmlnZ2VyIGEgcmVyZW5kZXIgb2YgdGhlIG1hcCBhbmQgd2lsbFxuICAgIC8vIGJlIHBhcnQgaW4gYWxsIGZ1dHVyZSByZW5kZXJzIG9mIHRoZSBtYXAuIFRoZSBtYXAgb2JqZWN0IHdpbGwgaGFuZGxlIGNvcHlpbmdcbiAgICAvLyB0aGUgdGlsZSBkYXRhIHRvIHRoZSBHUFUgaWYgaXQgaXMgcmVxdWlyZWQgdG8gcGFpbnQgdGhlIGN1cnJlbnQgdmlld3BvcnQuXG4gICAgX2FkZFRpbGU6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciB0aWxlID0gdGhpcy50aWxlc1tpZF07XG5cbiAgICAgICAgaWYgKCF0aWxlKSB7XG4gICAgICAgICAgICB0aWxlID0gdGhpcy5jYWNoZS5nZXQoaWQpO1xuICAgICAgICAgICAgaWYgKHRpbGUpIHtcbiAgICAgICAgICAgICAgICB0aWxlLnVzZXMgPSAxO1xuICAgICAgICAgICAgICAgIHRoaXMudGlsZXNbaWRdID0gdGlsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGlsZSkge1xuICAgICAgICAgICAgdGlsZSA9IHRoaXMuX2xvYWRUaWxlKGlkKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRpbGUgJiYgdGlsZS5sb2FkZWQgJiYgIXRpbGUudGltZUFkZGVkKSB7XG4gICAgICAgICAgICB0aWxlLnRpbWVBZGRlZCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3Jhc3RlcicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hcC5hbmltYXRpb25Mb29wLnNldCh0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgfSxcblxuICAgIF9yZW1vdmVUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMudGlsZXNbaWRdO1xuICAgICAgICBpZiAodGlsZSkge1xuICAgICAgICAgICAgdGlsZS51c2VzLS07XG4gICAgICAgICAgICBkZWxldGUgdGhpcy50aWxlc1tpZF07XG5cbiAgICAgICAgICAgIGlmICh0aWxlLnVzZXMgPD0gMCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aWxlLnRpbWVBZGRlZDtcbiAgICAgICAgICAgICAgICBpZiAoIXRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRpbGUuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGlsZS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhY2hlLmFkZChpZCwgdGlsZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5maXJlKCd0aWxlLnJlbW92ZScsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gVGFrZW4gZnJvbSBwb2x5bWFwcyBzcmMvTGF5ZXIuanNcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vc2ltcGxlZ2VvL3BvbHltYXBzL2Jsb2IvbWFzdGVyL3NyYy9MYXllci5qcyNMMzMzLUwzODNcblxuICAgIC8vIHNjYW4tbGluZSBjb252ZXJzaW9uXG4gICAgX3NjYW5UcmlhbmdsZTogZnVuY3Rpb24oYSwgYiwgYywgeW1pbiwgeW1heCwgc2NhbkxpbmUpIHtcbiAgICAgICAgdmFyIGFiID0gdGhpcy5fZWRnZShhLCBiKSxcbiAgICAgICAgICAgIGJjID0gdGhpcy5fZWRnZShiLCBjKSxcbiAgICAgICAgICAgIGNhID0gdGhpcy5fZWRnZShjLCBhKTtcblxuICAgICAgICB2YXIgdDtcblxuICAgICAgICAvLyBzb3J0IGVkZ2VzIGJ5IHktbGVuZ3RoXG4gICAgICAgIGlmIChhYi5keSA+IGJjLmR5KSB7IHQgPSBhYjsgYWIgPSBiYzsgYmMgPSB0OyB9XG4gICAgICAgIGlmIChhYi5keSA+IGNhLmR5KSB7IHQgPSBhYjsgYWIgPSBjYTsgY2EgPSB0OyB9XG4gICAgICAgIGlmIChiYy5keSA+IGNhLmR5KSB7IHQgPSBiYzsgYmMgPSBjYTsgY2EgPSB0OyB9XG5cbiAgICAgICAgLy8gc2NhbiBzcGFuISBzY2FuIHNwYW4hXG4gICAgICAgIGlmIChhYi5keSkgdGhpcy5fc2NhblNwYW5zKGNhLCBhYiwgeW1pbiwgeW1heCwgc2NhbkxpbmUpO1xuICAgICAgICBpZiAoYmMuZHkpIHRoaXMuX3NjYW5TcGFucyhjYSwgYmMsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbiAgICB9LFxuXG4gICAgLy8gc2Nhbi1saW5lIGNvbnZlcnNpb25cbiAgICBfZWRnZTogZnVuY3Rpb24oYSwgYikge1xuICAgICAgICBpZiAoYS5yb3cgPiBiLnJvdykgeyB2YXIgdCA9IGE7IGEgPSBiOyBiID0gdDsgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDA6IGEuY29sdW1uLFxuICAgICAgICAgICAgeTA6IGEucm93LFxuICAgICAgICAgICAgeDE6IGIuY29sdW1uLFxuICAgICAgICAgICAgeTE6IGIucm93LFxuICAgICAgICAgICAgZHg6IGIuY29sdW1uIC0gYS5jb2x1bW4sXG4gICAgICAgICAgICBkeTogYi5yb3cgLSBhLnJvd1xuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvLyBzY2FuLWxpbmUgY29udmVyc2lvblxuICAgIF9zY2FuU3BhbnM6IGZ1bmN0aW9uKGUwLCBlMSwgeW1pbiwgeW1heCwgc2NhbkxpbmUpIHtcbiAgICAgICAgdmFyIHkwID0gTWF0aC5tYXgoeW1pbiwgTWF0aC5mbG9vcihlMS55MCkpLFxuICAgICAgICAgICAgeTEgPSBNYXRoLm1pbih5bWF4LCBNYXRoLmNlaWwoZTEueTEpKTtcblxuICAgICAgICAvLyBzb3J0IGVkZ2VzIGJ5IHgtY29vcmRpbmF0ZVxuICAgICAgICBpZiAoKGUwLngwID09IGUxLngwICYmIGUwLnkwID09IGUxLnkwKSA/XG4gICAgICAgICAgICAoZTAueDAgKyBlMS5keSAvIGUwLmR5ICogZTAuZHggPCBlMS54MSkgOlxuICAgICAgICAgICAgKGUwLngxIC0gZTEuZHkgLyBlMC5keSAqIGUwLmR4IDwgZTEueDApKSB7XG4gICAgICAgICAgICB2YXIgdCA9IGUwOyBlMCA9IGUxOyBlMSA9IHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzY2FuIGxpbmVzIVxuICAgICAgICB2YXIgbTAgPSBlMC5keCAvIGUwLmR5LFxuICAgICAgICAgICAgbTEgPSBlMS5keCAvIGUxLmR5LFxuICAgICAgICAgICAgZDAgPSBlMC5keCA+IDAsIC8vIHVzZSB5ICsgMSB0byBjb21wdXRlIHgwXG4gICAgICAgICAgICBkMSA9IGUxLmR4IDwgMDsgLy8gdXNlIHkgKyAxIHRvIGNvbXB1dGUgeDFcbiAgICAgICAgZm9yICh2YXIgeSA9IHkwOyB5IDwgeTE7IHkrKykge1xuICAgICAgICAgICAgdmFyIHgwID0gbTAgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMC5keSwgeSArIGQwIC0gZTAueTApKSArIGUwLngwLFxuICAgICAgICAgICAgICAgIHgxID0gbTEgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMS5keSwgeSArIGQxIC0gZTEueTApKSArIGUxLngwO1xuICAgICAgICAgICAgc2NhbkxpbmUoTWF0aC5mbG9vcih4MSksIE1hdGguY2VpbCh4MCksIHkpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF96X29yZGVyOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiAoYiAlIDMyKSAtIChhICUgMzIpO1xuICAgIH0sXG5cbiAgICBfY2VudGVyT3V0OiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHZhciB0ciA9IHRoaXMubWFwLnRyYW5zZm9ybTtcbiAgICAgICAgdmFyIGFQb3MgPSBUaWxlQ29vcmQuZnJvbUlEKGEpO1xuICAgICAgICB2YXIgYlBvcyA9IFRpbGVDb29yZC5mcm9tSUQoYik7XG4gICAgICAgIHZhciBjID0gVGlsZUNvb3JkLnpvb21Ubyh0ci5sb2NhdGlvbkNvb3JkaW5hdGUodHIuY2VudGVyKSwgYVBvcy56KTtcbiAgICAgICAgdmFyIGNlbnRlciA9IG5ldyBQb2ludChjLmNvbHVtbiAtIDAuNSwgYy5yb3cgLSAwLjUpO1xuICAgICAgICByZXR1cm4gY2VudGVyLmRpc3QoYVBvcykgLSBjZW50ZXIuZGlzdChiUG9zKTtcbiAgICB9LFxufSk7XG5cbnZhciBzb3VyY2VzID0ge1xuICAgIHZlY3RvcjogU291cmNlLFxuICAgIHJhc3RlcjogU291cmNlLFxuICAgIGdlb2pzb246IHJlcXVpcmUoJy4vZ2VvanNvbnNvdXJjZScpLFxuICAgIHZpZGVvOiByZXF1aXJlKCcuL3ZpZGVvc291cmNlJylcbn07XG5cblNvdXJjZS5jcmVhdGUgPSBmdW5jdGlvbihzb3VyY2UpIHtcbiAgICByZXR1cm4gbmV3IHNvdXJjZXNbc291cmNlLnR5cGVdKHNvdXJjZSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2xtYXRyaXggPSByZXF1aXJlKCcuLi9saWIvZ2xtYXRyaXguanMnKSxcbiAgICBtYXQyID0gZ2xtYXRyaXgubWF0MixcbiAgICBtYXQ0ID0gZ2xtYXRyaXgubWF0NCxcbiAgICB2ZWMyID0gZ2xtYXRyaXgudmVjMjtcblxubW9kdWxlLmV4cG9ydHMgPSBUaWxlO1xuXG5mdW5jdGlvbiBUaWxlKCkge31cblxuVGlsZS5wcm90b3R5cGUgPSB7XG4gICAgLy8gdG9kbyB1bmhhcmRjb2RlXG4gICAgdGlsZUV4dGVudDogNDA5NixcblxuICAgIGNhbGN1bGF0ZU1hdHJpY2VzOiBmdW5jdGlvbih6LCB4LCB5LCB0cmFuc2Zvcm0sIHBhaW50ZXIpIHtcblxuICAgICAgICAvLyBJbml0aWFsaXplIG1vZGVsLXZpZXcgbWF0cml4IHRoYXQgY29udmVydHMgZnJvbSB0aGUgdGlsZSBjb29yZGluYXRlc1xuICAgICAgICAvLyB0byBzY3JlZW4gY29vcmRpbmF0ZXMuXG4gICAgICAgIHZhciB0aWxlU2NhbGUgPSBNYXRoLnBvdygyLCB6KTtcbiAgICAgICAgdmFyIHNjYWxlID0gdHJhbnNmb3JtLndvcmxkU2l6ZSAvIHRpbGVTY2FsZTtcblxuICAgICAgICAvLyBUT0RPOiByZW1vdmVcbiAgICAgICAgdGhpcy5zY2FsZSA9IHNjYWxlO1xuXG4gICAgICAgIC8vIFRoZSBwb3NpdGlvbiBtYXRyaXhcbiAgICAgICAgdGhpcy5wb3NNYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZSh0aGlzLnBvc01hdHJpeCwgdGhpcy5wb3NNYXRyaXgsIFt0cmFuc2Zvcm0uY2VudGVyUG9pbnQueCwgdHJhbnNmb3JtLmNlbnRlclBvaW50LnksIDBdKTtcbiAgICAgICAgbWF0NC5yb3RhdGVaKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0NC50cmFuc2xhdGUodGhpcy5wb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4LCBbLXRyYW5zZm9ybS5jZW50ZXJQb2ludC54LCAtdHJhbnNmb3JtLmNlbnRlclBvaW50LnksIDBdKTtcblxuICAgICAgICB2YXIgcGl4ZWxYID0gdHJhbnNmb3JtLndpZHRoIC8gMiAtIHRyYW5zZm9ybS54LFxuICAgICAgICAgICAgcGl4ZWxZID0gdHJhbnNmb3JtLmhlaWdodCAvIDIgLSB0cmFuc2Zvcm0ueTtcblxuICAgICAgICBtYXQ0LnRyYW5zbGF0ZSh0aGlzLnBvc01hdHJpeCwgdGhpcy5wb3NNYXRyaXgsIFtwaXhlbFggKyB4ICogc2NhbGUsIHBpeGVsWSArIHkgKiBzY2FsZSwgMV0pO1xuXG4gICAgICAgIC8vIENyZWF0ZSBpbnZlcnRlZCBtYXRyaXggZm9yIGludGVyYWN0aW9uXG4gICAgICAgIHRoaXMuaW52UG9zTWF0cml4ID0gbWF0NC5jcmVhdGUoKTtcbiAgICAgICAgbWF0NC5pbnZlcnQodGhpcy5pbnZQb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4KTtcblxuICAgICAgICBtYXQ0LnNjYWxlKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgWyBzY2FsZSAvIHRoaXMudGlsZUV4dGVudCwgc2NhbGUgLyB0aGlzLnRpbGVFeHRlbnQsIDEgXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkodGhpcy5wb3NNYXRyaXgsIHBhaW50ZXIucHJvamVjdGlvbk1hdHJpeCwgdGhpcy5wb3NNYXRyaXgpO1xuXG4gICAgICAgIC8vIFRoZSBleHRydXNpb24gbWF0cml4LlxuICAgICAgICB0aGlzLmV4TWF0cml4ID0gbWF0NC5jbG9uZShwYWludGVyLnByb2plY3Rpb25NYXRyaXgpO1xuICAgICAgICBtYXQ0LnJvdGF0ZVoodGhpcy5leE1hdHJpeCwgdGhpcy5leE1hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcblxuICAgICAgICAvLyAyeDIgbWF0cml4IGZvciByb3RhdGluZyBwb2ludHNcbiAgICAgICAgdGhpcy5yb3RhdGlvbk1hdHJpeCA9IG1hdDIuY3JlYXRlKCk7XG4gICAgICAgIG1hdDIucm90YXRlKHRoaXMucm90YXRpb25NYXRyaXgsIHRoaXMucm90YXRpb25NYXRyaXgsIHRyYW5zZm9ybS5hbmdsZSk7XG4gICAgfSxcblxuICAgIHBvc2l0aW9uQXQ6IGZ1bmN0aW9uKGlkLCBwb2ludCkge1xuICAgICAgICAvLyB0aWxlIGhhc24ndCBmaW5pc2hlZCBsb2FkaW5nXG4gICAgICAgIGlmICghdGhpcy5pbnZQb3NNYXRyaXgpIHJldHVybiBudWxsO1xuXG4gICAgICAgIHZhciBwb3MgPSB2ZWMyLnRyYW5zZm9ybU1hdDQoW10sIFtwb2ludC54LCBwb2ludC55XSwgdGhpcy5pbnZQb3NNYXRyaXgpO1xuICAgICAgICB2ZWMyLnNjYWxlKHBvcywgcG9zLCA0MDk2IC8gdGhpcy5zY2FsZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiBwb3NbMF0sXG4gICAgICAgICAgICB5OiBwb3NbMV0sXG4gICAgICAgICAgICBzY2FsZTogdGhpcy5zY2FsZVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihwb3MsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5zb3VyY2UubWFwLmRpc3BhdGNoZXIuc2VuZCgncXVlcnkgZmVhdHVyZXMnLCB7XG4gICAgICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgICAgIHg6IHBvcy54LFxuICAgICAgICAgICAgeTogcG9zLnksXG4gICAgICAgICAgICBzY2FsZTogcG9zLnNjYWxlLFxuICAgICAgICAgICAgc291cmNlOiB0aGlzLnNvdXJjZS5pZCxcbiAgICAgICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgICAgIH0sIGNhbGxiYWNrLCB0aGlzLndvcmtlcklEKTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogVGlsZXMgYXJlIGdlbmVyYWxseSByZXByZXNlbnRlZCBhcyBwYWNrZWQgaW50ZWdlciBpZHMgY29uc3RydWN0ZWQgYnlcbiAqIGBUaWxlQ29vcmQudG9JRCh4LCB5LCB6KWBcbiAqL1xuXG52YXIgVGlsZUNvb3JkID0gZXhwb3J0cztcblxuVGlsZUNvb3JkLnRvSUQgPSBmdW5jdGlvbih6LCB4LCB5LCB3KSB7XG4gICAgdyA9IHcgfHwgMDtcbiAgICB3ICo9IDI7XG4gICAgaWYgKHcgPCAwKSB3ID0gdyAqIC0xIC0xO1xuICAgIHZhciBkaW0gPSAxIDw8IHo7XG4gICAgcmV0dXJuICgoZGltICogZGltICogdyArIGRpbSAqIHkgKyB4KSAqIDMyKSArIHo7XG59O1xuXG5UaWxlQ29vcmQuYXNTdHJpbmcgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciBwb3MgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICByZXR1cm4gcG9zLnogKyBcIi9cIiArIHBvcy54ICsgXCIvXCIgKyBwb3MueTtcbn07XG5cbi8qXG4gKiBQYXJzZSBhIHBhY2tlZCBpbnRlZ2VyIGlkIGludG8gYW4gb2JqZWN0IHdpdGggeCwgeSwgYW5kIHogcHJvcGVydGllc1xuICovXG5UaWxlQ29vcmQuZnJvbUlEID0gZnVuY3Rpb24oaWQpIHtcbiAgICB2YXIgeiA9IGlkICUgMzIsIGRpbSA9IDEgPDwgejtcbiAgICB2YXIgeHkgPSAoKGlkIC0geikgLyAzMik7XG4gICAgdmFyIHggPSB4eSAlIGRpbSwgeSA9ICgoeHkgLSB4KSAvIGRpbSkgJSBkaW07XG4gICAgdmFyIHcgPSBNYXRoLmZsb29yKHh5IC8gKGRpbSAqIGRpbSkpO1xuICAgIGlmICh3ICUgMiAhPT0gMCkgdyA9IHcgKiAtMSAtMTtcbiAgICB3IC89IDI7XG4gICAgcmV0dXJuIHsgejogeiwgeDogeCwgeTogeSwgdzogdyB9O1xufTtcblxuLypcbiAqIEdpdmVuIGEgcGFja2VkIGludGVnZXIgaWQsIHJldHVybiBpdHMgem9vbSBsZXZlbFxuICovXG5UaWxlQ29vcmQuem9vbSA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgcmV0dXJuIGlkICUgMzI7XG59O1xuXG4vLyBHaXZlbiBhbiBpZCBhbmQgYSBsaXN0IG9mIHVybHMsIGNob29zZSBhIHVybCB0ZW1wbGF0ZSBhbmQgcmV0dXJuIGEgdGlsZSBVUkxcblRpbGVDb29yZC51cmwgPSBmdW5jdGlvbihpZCwgdXJscykge1xuICAgIHZhciBwb3MgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcblxuICAgIHJldHVybiB1cmxzW01hdGguZmxvb3IoKHBvcy54ICsgcG9zLnkpICUgdXJscy5sZW5ndGgpXVxuICAgICAgICAucmVwbGFjZSgne2h9JywgKHBvcy54ICUgMTYpLnRvU3RyaW5nKDE2KSArIChwb3MueSAlIDE2KS50b1N0cmluZygxNikpXG4gICAgICAgIC5yZXBsYWNlKCd7en0nLCBwb3Muei50b0ZpeGVkKDApKVxuICAgICAgICAucmVwbGFjZSgne3h9JywgcG9zLngudG9GaXhlZCgwKSlcbiAgICAgICAgLnJlcGxhY2UoJ3t5fScsIHBvcy55LnRvRml4ZWQoMCkpO1xufTtcblxuLypcbiAqIEdpdmVuIGEgcGFja2VkIGludGVnZXIgaWQsIHJldHVybiB0aGUgaWQgb2YgaXRzIHBhcmVudCB0aWxlXG4gKi9cblRpbGVDb29yZC5wYXJlbnQgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciBwb3MgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICBpZiAocG9zLnogPT09IDApIHJldHVybiBpZDtcbiAgICBlbHNlIHJldHVybiBUaWxlQ29vcmQudG9JRChwb3MueiAtIDEsIE1hdGguZmxvb3IocG9zLnggLyAyKSwgTWF0aC5mbG9vcihwb3MueSAvIDIpKTtcbn07XG5cblRpbGVDb29yZC5wYXJlbnRXaXRoWm9vbSA9IGZ1bmN0aW9uKGlkLCB6b29tKSB7XG4gICAgdmFyIHBvcyA9IFRpbGVDb29yZC5mcm9tSUQoaWQpO1xuICAgIHdoaWxlIChwb3MueiA+IHpvb20pIHtcbiAgICAgICAgcG9zLnotLTtcbiAgICAgICAgcG9zLnggPSBNYXRoLmZsb29yKHBvcy54IC8gMik7XG4gICAgICAgIHBvcy55ID0gTWF0aC5mbG9vcihwb3MueSAvIDIpO1xuICAgIH1cbiAgICByZXR1cm4gVGlsZUNvb3JkLnRvSUQocG9zLnosIHBvcy54LCBwb3MueSk7XG59O1xuXG4vKlxuICogR2l2ZW4gYSBwYWNrZWQgaW50ZWdlciBpZCwgcmV0dXJuIGFuIGFycmF5IG9mIGludGVnZXIgaWRzIHJlcHJlc2VudGluZ1xuICogaXRzIGZvdXIgY2hpbGRyZW4uXG4gKi9cblRpbGVDb29yZC5jaGlsZHJlbiA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgdmFyIHBvcyA9IFRpbGVDb29yZC5mcm9tSUQoaWQpO1xuICAgIHBvcy56ICs9IDE7XG4gICAgcG9zLnggKj0gMjtcbiAgICBwb3MueSAqPSAyO1xuICAgIHJldHVybiBbXG4gICAgICAgIFRpbGVDb29yZC50b0lEKHBvcy56LCBwb3MueCwgcG9zLnksIHBvcy53KSxcbiAgICAgICAgVGlsZUNvb3JkLnRvSUQocG9zLnosIHBvcy54ICsgMSwgcG9zLnksIHBvcy53KSxcbiAgICAgICAgVGlsZUNvb3JkLnRvSUQocG9zLnosIHBvcy54LCBwb3MueSArIDEsIHBvcy53KSxcbiAgICAgICAgVGlsZUNvb3JkLnRvSUQocG9zLnosIHBvcy54ICsgMSwgcG9zLnkgKyAxLCBwb3MudylcbiAgICBdO1xufTtcblxuVGlsZUNvb3JkLnpvb21UbyA9IGZ1bmN0aW9uKGMsIHopIHtcbiAgICBjLmNvbHVtbiA9IGMuY29sdW1uICogTWF0aC5wb3coMiwgeiAtIGMuem9vbSk7XG4gICAgYy5yb3cgPSBjLnJvdyAqIE1hdGgucG93KDIsIHogLSBjLnpvb20pO1xuICAgIGMuem9vbSA9IHo7XG4gICAgcmV0dXJuIGM7XG59O1xuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXdpbmQgPSByZXF1aXJlKCdnZW9qc29uLXJld2luZCcpO1xuXG52YXIgVGlsZUNvb3JkID0gcmVxdWlyZSgnLi90aWxlY29vcmQuanMnKTtcbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuLi9nZW8vdHJhbnNmb3JtLmpzJyk7XG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xudmFyIExhdExuZyA9IHJlcXVpcmUoJy4uL2dlby9sYXRsbmcuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB0aWxlR2VvSlNPTjtcblxuZnVuY3Rpb24gdGlsZUdlb0pTT04oZ2VvanNvbiwgem9vbSkge1xuICAgIHZhciB0aWxlcyA9IHt9O1xuICAgIHZhciB0aWxlRXh0ZW50ID0gNDA5NjtcbiAgICB2YXIgdHJhbnNmb3JtID0gbmV3IFRyYW5zZm9ybSgpO1xuICAgIHRyYW5zZm9ybS56b29tID0gem9vbTtcblxuICAgIGdlb2pzb24gPSByZXdpbmQoZ2VvanNvbik7XG5cbiAgICBpZiAoZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvanNvbi5mZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGlsZUZlYXR1cmUoZ2VvanNvbi5mZWF0dXJlc1tpXSwgdHJhbnNmb3JtLCB0aWxlcywgdGlsZUV4dGVudCk7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScpIHtcbiAgICAgICAgdGlsZUZlYXR1cmUoZ2VvanNvbiwgdHJhbnNmb3JtLCB0aWxlcywgdGlsZUV4dGVudCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdygnVW5yZWNvZ25pemVkIGdlb2pzb24gdHlwZScpO1xuICAgIH1cblxuICAgIHJldHVybiB0aWxlcztcbn1cblxuZnVuY3Rpb24gdGlsZUZlYXR1cmUoZmVhdHVyZSwgdHJhbnNmb3JtLCB0aWxlcywgdGlsZUV4dGVudCkge1xuICAgIHZhciBjb29yZHMgPSBmZWF0dXJlLmdlb21ldHJ5LmNvb3JkaW5hdGVzO1xuICAgIHZhciB0eXBlID0gZmVhdHVyZS5nZW9tZXRyeS50eXBlO1xuXG4gICAgdmFyIHRpbGVkO1xuICAgIGlmICh0eXBlID09PSAnUG9pbnQnKSB7XG4gICAgICAgIHRpbGVkID0gdGlsZUxpbmVTdHJpbmcoW2Nvb3Jkc10sIHRyYW5zZm9ybSwgdGlsZUV4dGVudCk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdMaW5lU3RyaW5nJyB8fCB0eXBlID09PSAnTXVsdGlQb2ludCcpIHtcbiAgICAgICAgdGlsZWQgPSB0aWxlTGluZVN0cmluZyhjb29yZHMsIHRyYW5zZm9ybSwgdGlsZUV4dGVudCk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdQb2x5Z29uJyB8fCB0eXBlID09PSAnTXVsdGlMaW5lU3RyaW5nJykge1xuICAgICAgICB0aWxlZCA9IHt9O1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRpbGVkXyA9IHRpbGVMaW5lU3RyaW5nKGNvb3Jkc1tpXSwgdHJhbnNmb3JtLCB0aWxlRXh0ZW50LCB0eXBlID09PSAnUG9seWdvbicpO1xuICAgICAgICAgICAgZm9yICh2YXIgdGlsZUlEIGluIHRpbGVkXykge1xuICAgICAgICAgICAgICAgIGlmICghdGlsZWRbdGlsZUlEXSkgdGlsZWRbdGlsZUlEXSA9IFtdO1xuICAgICAgICAgICAgICAgIHRpbGVkW3RpbGVJRF0gPSAodGlsZWRbdGlsZUlEXSB8fCBbXSkuY29uY2F0KHRpbGVkX1t0aWxlSURdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICB0aHJvdyhcInRvZG9cIik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3coXCJ1bnJlY29nbml6ZWQgZ2VvbWV0cnkgdHlwZVwiKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpZCBpbiB0aWxlZCkge1xuICAgICAgICB0aWxlc1tpZF0gPSB0aWxlc1tpZF0gfHwgW107XG4gICAgICAgIHRpbGVzW2lkXS5wdXNoKHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IGZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgICAgIGNvb3JkczogdGlsZWRbaWRdLFxuICAgICAgICAgICAgdHlwZTogZmVhdHVyZS5nZW9tZXRyeS50eXBlXG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdGlsZUxpbmVTdHJpbmcoY29vcmRzLCB0cmFuc2Zvcm0sIHRpbGVFeHRlbnQsIHJlam9pbikge1xuXG4gICAgdmFyIHBhZGRpbmcgPSAwLjAxO1xuICAgIHZhciBwYWRkZWRFeHRlbnQgPSB0aWxlRXh0ZW50ICogKDEgKyAyICogcGFkZGluZyk7XG4gICAgdmFyIGNvb3JkID0gdHJhbnNmb3JtLmxvY2F0aW9uQ29vcmRpbmF0ZShuZXcgTGF0TG5nKGNvb3Jkc1swXVsxXSwgY29vcmRzWzBdWzBdKSk7XG4gICAgdmFyIHByZXZDb29yZDtcblxuICAgIHZhciB0aWxlcyA9IHt9O1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcHJldkNvb3JkID0gY29vcmQ7XG4gICAgICAgIGNvb3JkID0gdHJhbnNmb3JtLmxvY2F0aW9uQ29vcmRpbmF0ZShuZXcgTGF0TG5nKGNvb3Jkc1tpXVsxXSwgY29vcmRzW2ldWzBdKSk7XG5cbiAgICAgICAgdmFyIGR4ID0gY29vcmQuY29sdW1uIC0gcHJldkNvb3JkLmNvbHVtbiB8fCBOdW1iZXIuTUlOX1ZBTFVFLFxuICAgICAgICAgICAgZHkgPSBjb29yZC5yb3cgLSBwcmV2Q29vcmQucm93IHx8IE51bWJlci5NSU5fVkFMVUUsXG4gICAgICAgICAgICBkaXJYID0gZHggLyBNYXRoLmFicyhkeCksXG4gICAgICAgICAgICBkaXJZID0gZHkgLyBNYXRoLmFicyhkeSk7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgcmVjdGFuZ3VsYXIgYm91bmRpbmcgYm94LCBpbiB0aWxlcywgb2YgdGhlIHBvbHlnb25cbiAgICAgICAgdmFyIHN0YXJ0VGlsZVggPSBNYXRoLmZsb29yKHByZXZDb29yZC5jb2x1bW4gLSBkaXJYICogcGFkZGluZyk7XG4gICAgICAgIHZhciBlbmRUaWxlWCA9IE1hdGguZmxvb3IoY29vcmQuY29sdW1uICsgZGlyWCAqIHBhZGRpbmcpO1xuICAgICAgICB2YXIgc3RhcnRUaWxlWSA9IE1hdGguZmxvb3IocHJldkNvb3JkLnJvdyAtIGRpclkgKiBwYWRkaW5nKTtcbiAgICAgICAgdmFyIGVuZFRpbGVZID0gTWF0aC5mbG9vcihjb29yZC5yb3cgKyBkaXJZICogcGFkZGluZyk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCB0aWxlcyB0aGUgc2VnbWVudCBtaWdodCBpbnRlcnNlY3RcbiAgICAgICAgLy8gYW5kIHNwbGl0IHRoZSBzZWdtZW50IGFjcm9zcyB0aG9zZSB0aWxlc1xuICAgICAgICBmb3IgKHZhciB4ID0gc3RhcnRUaWxlWDsgKHggLSBlbmRUaWxlWCkgKiBkaXJYIDw9IDA7IHggKz0gZGlyWCkge1xuICAgICAgICAgICAgdmFyIGxlZnRYID0gKHggLSBwYWRkaW5nIC0gcHJldkNvb3JkLmNvbHVtbikgLyBkeDtcbiAgICAgICAgICAgIHZhciByaWdodFggPSAoeCArIDEgKyBwYWRkaW5nIC0gcHJldkNvb3JkLmNvbHVtbikgLyBkeDtcblxuICAgICAgICAgICAgZm9yICh2YXIgeSA9IHN0YXJ0VGlsZVk7ICh5IC0gZW5kVGlsZVkpICogZGlyWSA8PSAwOyB5ICs9IGRpclkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wWSA9ICh5IC0gcGFkZGluZyAtIHByZXZDb29yZC5yb3cpIC8gZHk7XG4gICAgICAgICAgICAgICAgdmFyIGJvdHRvbVkgPSAoeSArIDEgKyBwYWRkaW5nIC0gcHJldkNvb3JkLnJvdykgLyBkeTtcblxuICAgICAgICAgICAgICAgIC8vIGZyYWN0aW9uIG9mIHRoZSBkaXN0YW5jZSBhbG9uZyB0aGUgc2VnbWVudCBhdCB3aGljaCB0aGUgc2VnbWVudFxuICAgICAgICAgICAgICAgIC8vIGVudGVycyBvciBleGl0cyB0aGUgdGlsZVxuICAgICAgICAgICAgICAgIHZhciBlbnRlciA9IE1hdGgubWF4KE1hdGgubWluKGxlZnRYLCByaWdodFgpLCBNYXRoLm1pbih0b3BZLCBib3R0b21ZKSk7XG4gICAgICAgICAgICAgICAgdmFyIGV4aXQgPSBNYXRoLm1pbihNYXRoLm1heChsZWZ0WCwgcmlnaHRYKSwgTWF0aC5tYXgodG9wWSwgYm90dG9tWSkpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRpbGVJRCA9IFRpbGVDb29yZC50b0lEKHRyYW5zZm9ybS50aWxlWm9vbSwgeCwgeSksXG4gICAgICAgICAgICAgICAgICAgIHRpbGUgPSB0aWxlc1t0aWxlSURdLFxuICAgICAgICAgICAgICAgICAgICBwb2ludDtcblxuICAgICAgICAgICAgICAgIC8vIHNlZ21lbnRzIHN0YXJ0cyBvdXRzaWRlIHRoZSB0aWxlLCBhZGQgZW50cnkgcG9pbnRcbiAgICAgICAgICAgICAgICBpZiAoMCA8PSBlbnRlciAmJiBlbnRlciA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnQgPSBuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAoKHByZXZDb29yZC5jb2x1bW4gKyBlbnRlciAqIGR4KSAtIHgpICogdGlsZUV4dGVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICgocHJldkNvb3JkLnJvdyArIGVudGVyICogZHkpIC0geSkgKiB0aWxlRXh0ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICBwb2ludC5jb250aW51ZXMgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGlsZSkgdGlsZXNbdGlsZUlEXSA9IHRpbGUgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGlsZS5wdXNoKFtwb2ludF0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHNlZ21lbnRzIGVuZHMgb3V0c2lkZSB0aGUgdGlsZSwgYWRkIGV4aXQgcG9pbnRcbiAgICAgICAgICAgICAgICBpZiAoMCA8PSBleGl0ICYmIGV4aXQgPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50ID0gbmV3IFBvaW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgKChwcmV2Q29vcmQuY29sdW1uICsgZXhpdCAqIGR4KSAtIHgpICogdGlsZUV4dGVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICgocHJldkNvb3JkLnJvdyArIGV4aXQgKiBkeSkgLSB5KSAqIHRpbGVFeHRlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgIHBvaW50LmNvbnRpbnVlcyA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgdGlsZVt0aWxlLmxlbmd0aCAtIDFdLnB1c2gocG9pbnQpO1xuXG4gICAgICAgICAgICAgICAgLy8gYWRkIHRoZSBwb2ludCBpdHNlbGZcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb2ludCA9IG5ldyBQb2ludChcbiAgICAgICAgICAgICAgICAgICAgICAgIChjb29yZC5jb2x1bW4gLSB4KSAqIHRpbGVFeHRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAoY29vcmQucm93IC0geSkgKiB0aWxlRXh0ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRpbGUpIHRpbGVzW3RpbGVJRF0gPSB0aWxlID0gW1twb2ludF1dO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIHRpbGVbdGlsZS5sZW5ndGggLSAxXS5wdXNoKHBvaW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocmVqb2luKSB7XG4gICAgICAgIC8vIHJlYXNzZW1ibGUgdGhlIGRpc2Nvbm5lY3RlZCBzZWdtZW50cyBpbnRvIGEgbGluZXN0cmluZ1xuICAgICAgICAvLyBzZWN0aW9ucyBvZiB0aGUgbGluZXN0cmluZyBvdXRzaWRlIHRoZSB0aWxlIGFyZSByZXBsYWNlZCB3aXRoIHNlZ21lbnRzXG4gICAgICAgIC8vIHRoYXQgZm9sbG93IHRoZSB0aWxlJ3MgZWRnZVxuICAgICAgICBmb3IgKHZhciBpZCBpbiB0aWxlcykge1xuXG4gICAgICAgICAgICB2YXIgc2VnbWVudHMgPSB0aWxlc1tpZF07XG5cbiAgICAgICAgICAgIGlmICghc2VnbWVudHNbMF1bMF0uY29udGludWVzICYmIHNlZ21lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgZmlyc3Qgc2VnbWVudCBpcyB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lc3RyaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlbiBqb2luIGl0IHdpdGggdGhlIGxhc3Qgc28gdGhhdCBhbGwgc2VnbWVudHMgc3RhcnQgYW5kXG4gICAgICAgICAgICAgICAgLy8gZW5kIGF0IHRpbGUgYm91bmRhcmllc1xuICAgICAgICAgICAgICAgIHZhciBsYXN0ID0gc2VnbWVudHMucG9wKCk7XG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnVuc2hpZnQuYXBwbHkoc2VnbWVudHNbMF0sIGxhc3Quc2xpY2UoMCwgbGFzdC5sZW5ndGggLSAxKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBzdGFydCA9IGVkZ2VEaXN0KHNlZ21lbnRzWzBdWzBdLCB0aWxlRXh0ZW50LCBwYWRkaW5nKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBzZWdtZW50cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIC8vIEFkZCBhbGwgdGlsZSBjb3JuZXJzIGFsb25nIHRoZSBwYXRoIGJldHdlZW4gdGhlIGN1cnJlbnQgc2VnbWVudCdzIGV4aXQgcG9pbnRcbiAgICAgICAgICAgICAgICAvLyBhbmQgdGhlIG5leHQgc2VnbWVudCdzIGVudHJ5IHBvaW50XG5cbiAgICAgICAgICAgICAgICB2YXIgdGhpc0V4aXQgPSBlZGdlRGlzdChzZWdtZW50c1trXVtzZWdtZW50c1trXS5sZW5ndGggLSAxXSwgcGFkZGVkRXh0ZW50KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dEVudHJ5ID0gZWRnZURpc3Qoc2VnbWVudHNbKGsgKyAxKSAlIHNlZ21lbnRzLmxlbmd0aF1bMF0sIHBhZGRlZEV4dGVudCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgc3RhcnRUb0V4aXQgPSAodGhpc0V4aXQgLSBzdGFydCArIDQpICUgNDtcbiAgICAgICAgICAgICAgICB2YXIgc3RhcnRUb05leHRFbnRyeSA9IChuZXh0RW50cnkgLSBzdGFydCArIDQpICUgNDtcbiAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gKHRoaXNFeGl0ID09PSBuZXh0RW50cnkgfHwgc3RhcnRUb0V4aXQgPCBzdGFydFRvTmV4dEVudHJ5KSA/IDEgOiAtMTtcbiAgICAgICAgICAgICAgICB2YXIgcm91bmRGbiA9IGRpcmVjdGlvbiA+IDAgPyBNYXRoLmNlaWwgOiBNYXRoLmZsb29yO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYyA9IHJvdW5kRm4odGhpc0V4aXQpICUgNDsgYyAhPSByb3VuZEZuKG5leHRFbnRyeSkgJSA0OyBjID0gKGMgKyBkaXJlY3Rpb24gKyA0KSAlIDQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvcm5lciA9IGNvcm5lcnNbY107XG4gICAgICAgICAgICAgICAgICAgIHNlZ21lbnRzW2tdLnB1c2gobmV3IFBvaW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgKGNvcm5lci54ICsgKGNvcm5lci54IC0gMC41ID4gMCA/IDEgOiAtMSkgKiBwYWRkaW5nKSAqIHRpbGVFeHRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAoY29ybmVyLnkgKyAoY29ybmVyLnkgLSAwLjUgPiAwID8gMSA6IC0xKSAqIHBhZGRpbmcpICogdGlsZUV4dGVudCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSm9pbiBhbGwgc2VnbWVudHNcbiAgICAgICAgICAgIHRpbGVzW2lkXSA9IFtBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KFtdLCBzZWdtZW50cyldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbGVzO1xuXG59XG5cbnZhciBjb3JuZXJzID0gW1xuICAgIG5ldyBQb2ludCgwLCAwKSxcbiAgICBuZXcgUG9pbnQoMSwgMCksXG4gICAgbmV3IFBvaW50KDEsIDEpLFxuICAgIG5ldyBQb2ludCgwLCAxKV07XG5cbi8qXG4gKiBDb252ZXJ0cyB0byBhIHBvaW50IHRvIHRoZSBkaXN0YW5jZSBhbG9uZyB0aGUgZWRnZSBvZiB0aGUgdGlsZSAob3V0IG9mIDQpLlxuICpcbiAqICAgICAgICAgMC41XG4gKiAgICAgMCBfX19fX19fIDFcbiAqICAgICAgfCAgICAgICB8XG4gKiAgMy41IHwgICAgICAgfCAxLjVcbiAqICAgICAgfCAgICAgICB8XG4gKiAgICAgIHxfX19fX19ffFxuICogICAgIDMgICAyLjUgICAyXG4gKi9cbmZ1bmN0aW9uIGVkZ2VEaXN0KHBvaW50LCBleHRlbnQpIHtcbiAgICB2YXIgeCA9IHBvaW50LnggLyBleHRlbnQ7XG4gICAgdmFyIHkgPSBwb2ludC55IC8gZXh0ZW50O1xuICAgIHZhciBkO1xuICAgIGlmIChNYXRoLmFicyh5IC0gMC41KSA+PSBNYXRoLmFicyh4IC0gMC41KSkge1xuICAgICAgICBkID0gTWF0aC5yb3VuZCh5KSAqIDIgKyAoeSA8IDAuNSA/IHggOiAxIC0geCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZCA9IE1hdGgucm91bmQoMSAtIHgpICogMiArICh4ID4gMC41ID8geSA6IDEgLSB5KSArIDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIGQgJSA0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVGlsZSA9IHJlcXVpcmUoJy4vdGlsZS5qcycpLFxuICAgIFRpbGVDb29yZCA9IHJlcXVpcmUoJy4vdGlsZWNvb3JkLmpzJyksXG4gICAgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyc2V0LmpzJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbC5qcycpO1xuXG52YXIgY3JlYXRlQnVja2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9jcmVhdGVidWNrZXQuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlKGlkLCBzb3VyY2UsIHVybCwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmlkID0gaWQ7XG4gICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB0aGlzLnVybCA9IHVybDtcbiAgICB0aGlzLnpvb20gPSBUaWxlQ29vcmQuZnJvbUlEKGlkKS56O1xuICAgIHRoaXMubWFwID0gc291cmNlLm1hcDtcbiAgICB0aGlzLm9wdGlvbnMgPSBzb3VyY2Uub3B0aW9ucztcbiAgICB0aGlzLmlkID0gdXRpbC51bmlxdWVJZCgpO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcblxuICAgIGlmICh0aGlzLnpvb20gPj0gc291cmNlLnRpbGVKU09OLm1heHpvb20pIHtcbiAgICAgICAgdGhpcy5kZXB0aCA9IHRoaXMubWFwLm9wdGlvbnMubWF4Wm9vbSAtIHRoaXMuem9vbTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmRlcHRoID0gMTtcbiAgICB9XG4gICAgdGhpcy51c2VzID0gMTtcbiAgICB0aGlzLl9sb2FkKCk7XG59XG5cblZlY3RvclRpbGUucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KFRpbGUsIHtcblxuICAgIF9sb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzO1xuICAgICAgICB0aGlzLndvcmtlcklEID0gdGhpcy5tYXAuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIHRpbGUnLCB7XG4gICAgICAgICAgICB1cmw6IHRoaXMudXJsLFxuICAgICAgICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICAgICAgICB6b29tOiB0aGlzLnpvb20sXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLnNvdXJjZS50aWxlSlNPTi5tYXh6b29tLFxuICAgICAgICAgICAgdGlsZVNpemU6IHRoaXMub3B0aW9ucy50aWxlU2l6ZSxcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5zb3VyY2UuaWQsXG4gICAgICAgICAgICBkZXB0aDogdGhpcy5kZXB0aFxuICAgICAgICB9LCBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZXJyICYmIGRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aWxlLm9uVGlsZUxvYWQoZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aWxlLmNhbGxiYWNrKGVycik7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBvblRpbGVMb2FkOiBmdW5jdGlvbihkYXRhKSB7XG5cbiAgICAgICAgLy8gVGlsZSBoYXMgYmVlbiByZW1vdmVkIGZyb20gdGhlIG1hcFxuICAgICAgICBpZiAoIXRoaXMubWFwKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXJzID0gbmV3IEJ1ZmZlclNldChkYXRhLmJ1ZmZlcnMpO1xuXG4gICAgICAgIHRoaXMuYnVja2V0cyA9IHt9O1xuICAgICAgICBmb3IgKHZhciBiIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5idWNrZXRzW2JdID0gY3JlYXRlQnVja2V0KHRoaXMubWFwLnN0eWxlLmJ1Y2tldHNbYl0sIHRoaXMuYnVmZmVycywgdW5kZWZpbmVkLCBkYXRhLmVsZW1lbnRHcm91cHNbYl0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgIH0sXG5cbiAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8vIHJldXNlIHByZXJlbmRlcmVkIHRleHR1cmVzXG4gICAgICAgIGZvciAodmFyIGJ1Y2tldCBpbiB0aGlzLmJ1Y2tldHMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1Y2tldHNbYnVja2V0XS5wcmVyZW5kZXJlZCkgdGhpcy5tYXAucGFpbnRlci5zYXZlVGV4dHVyZSh0aGlzLmJ1Y2tldHNbYnVja2V0XS5wcmVyZW5kZXJlZC50ZXh0dXJlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWFwLmRpc3BhdGNoZXIuc2VuZCgncmVtb3ZlIHRpbGUnLCB7IGlkOiB0aGlzLmlkLCBzb3VyY2U6IHRoaXMuc291cmNlLmlkIH0sIG51bGwsIHRoaXMud29ya2VySUQpO1xuICAgICAgICB0aGlzLm1hcC5wYWludGVyLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRoaXMuaWQpO1xuXG4gICAgICAgIHZhciBnbCA9IHRoaXMubWFwLnBhaW50ZXIuZ2w7XG4gICAgICAgIHZhciBidWZmZXJzID0gdGhpcy5idWZmZXJzO1xuICAgICAgICBpZiAoYnVmZmVycykge1xuICAgICAgICAgICAgZm9yICh2YXIgYiBpbiBidWZmZXJzKSB7XG4gICAgICAgICAgICAgICAgYnVmZmVyc1tiXS5kZXN0cm95KGdsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgdGhpcy5tYXA7XG4gICAgfSxcblxuICAgIGFib3J0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5tYXAuZGlzcGF0Y2hlci5zZW5kKCdhYm9ydCB0aWxlJywgeyBpZDogdGhpcy5pZCwgc291cmNlOiB0aGlzLnNvdXJjZS5pZCB9LCBudWxsLCB0aGlzLndvcmtlcklEKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUuanMnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVjb29yZC5qcycpO1xudmFyIExhdExuZyA9IHJlcXVpcmUoJy4uL2dlby9sYXRsbmcuanMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmlkZW9Tb3VyY2U7XG5cbmZ1bmN0aW9uIFZpZGVvU291cmNlKG9wdGlvbnMpIHtcblxuICAgIHRoaXMudmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgIHRoaXMudmlkZW8uY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICB0aGlzLnZpZGVvLmxvb3AgPSB0cnVlO1xuXG4gICAgdmFyIHVybHMgPSAodHlwZW9mIG9wdGlvbnMudXJsID09PSAnc3RyaW5nJykgPyBbb3B0aW9ucy51cmxdIDogb3B0aW9ucy51cmw7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzb3VyY2UnKTtcbiAgICAgICAgcy5zcmMgPSB1cmxzW2ldO1xuICAgICAgICB0aGlzLnZpZGVvLmFwcGVuZENoaWxkKHMpO1xuICAgIH1cblxuICAgIHRoaXMuY29vcmRpbmF0ZXMgPSBvcHRpb25zLmNvb3JkaW5hdGVzO1xuICAgIHRoaXMuZW5hYmxlZCA9IHRydWU7XG5cbiAgICB2YXIgbG9vcElEO1xuICAgIHZhciBzb3VyY2UgPSB0aGlzO1xuXG4gICAgLy8gc3RhcnQgcmVwYWludGluZyB3aGVuIHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gICAgdGhpcy52aWRlby5hZGRFdmVudExpc3RlbmVyKCdwbGF5aW5nJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvb3BJRCA9IHNvdXJjZS5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoSW5maW5pdHkpO1xuICAgICAgICBzb3VyY2UubWFwLl9yZXJlbmRlcigpO1xuICAgIH0pO1xuXG4gICAgLy8gc3RvcCByZXBhaW50aW5nIHdoZW4gdmlkZW8gc3RvcHNcbiAgICB0aGlzLnZpZGVvLmFkZEV2ZW50TGlzdGVuZXIoJ3BhdXNlJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHNvdXJjZS5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5jYW5jZWwobG9vcElEKTtcbiAgICB9KTtcblxufVxuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUub25BZGQgPSBmdW5jdGlvbihtYXApIHtcbiAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB0aGlzLnZpZGVvLnBsYXkoKTtcbiAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbn07XG5cblZpZGVvU291cmNlLnByb3RvdHlwZS5jcmVhdGVUaWxlID0gZnVuY3Rpb24oKSB7XG4gICAgLypcbiAgICAgKiBDYWxjdWxhdGUgd2hpY2ggbWVyY2F0b3IgdGlsZSBpcyBzdWl0YWJsZSBmb3IgcmVuZGVyaW5nIHRoZSB2aWRlbyBpblxuICAgICAqIGFuZCBjcmVhdGUgYSBidWZmZXIgd2l0aCB0aGUgY29ybmVyIGNvb3JkaW5hdGVzLiBUaGVzZSBjb29yZGluYXRlc1xuICAgICAqIG1heSBiZSBvdXRzaWRlIHRoZSB0aWxlLCBiZWNhdXNlIHJhc3RlciB0aWxlcyBhcmVuJ3QgY2xpcHBlZCB3aGVuIHJlbmRlcmluZy5cbiAgICAgKi9cbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG4gICAgdmFyIGNvb3JkcyA9IHRoaXMuY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uKGxhdGxuZykge1xuICAgICAgICB2YXIgbG9jID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcbiAgICAgICAgcmV0dXJuIFRpbGVDb29yZC56b29tVG8obWFwLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUobG9jKSwgMCk7XG4gICAgfSk7XG5cbiAgICB2YXIgbWluWCA9IEluZmluaXR5O1xuICAgIHZhciBtaW5ZID0gSW5maW5pdHk7XG4gICAgdmFyIG1heFggPSAtSW5maW5pdHk7XG4gICAgdmFyIG1heFkgPSAtSW5maW5pdHk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtaW5YID0gTWF0aC5taW4obWluWCwgY29vcmRzW2ldLmNvbHVtbik7XG4gICAgICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCBjb29yZHNbaV0ucm93KTtcbiAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgY29vcmRzW2ldLnJvdyk7XG4gICAgfVxuXG4gICAgdmFyIGR4ID0gbWF4WCAtIG1pblg7XG4gICAgdmFyIGR5ID0gbWF4WSAtIG1pblk7XG4gICAgdmFyIGRNYXggPSBNYXRoLm1heChkeCwgZHkpO1xuICAgIHZhciBjZW50ZXIgPSBUaWxlQ29vcmQuem9vbVRvKHtcbiAgICAgICAgY29sdW1uOiAobWluWCArIG1heFgpIC8gMixcbiAgICAgICAgcm93OiAobWluWSArIG1heFkpIC8gMixcbiAgICAgICAgem9vbTogMFxuICAgIH0sIE1hdGguZmxvb3IoLU1hdGgubG9nKGRNYXgpIC8gTWF0aC5MTjIpKTtcblxuICAgIHZhciB0aWxlRXh0ZW50ID0gNDA5NjtcbiAgICB2YXIgdGlsZUNvb3JkcyA9IGNvb3Jkcy5tYXAoZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIHpvb21lZENvb3JkID0gVGlsZUNvb3JkLnpvb21Ubyhjb29yZCwgY2VudGVyLnpvb20pO1xuICAgICAgICByZXR1cm4gbmV3IFBvaW50KFxuICAgICAgICAgICAgTWF0aC5yb3VuZCgoem9vbWVkQ29vcmQuY29sdW1uIC0gY2VudGVyLmNvbHVtbikgKiB0aWxlRXh0ZW50KSxcbiAgICAgICAgICAgIE1hdGgucm91bmQoKHpvb21lZENvb3JkLnJvdyAtIGNlbnRlci5yb3cpICogdGlsZUV4dGVudCkpO1xuICAgIH0pO1xuXG4gICAgdmFyIGdsID0gbWFwLnBhaW50ZXIuZ2w7XG4gICAgdmFyIG1heEludDE2ID0gMzI3Njc7XG4gICAgdmFyIGFycmF5ID0gbmV3IEludDE2QXJyYXkoW1xuICAgICAgICB0aWxlQ29vcmRzWzBdLngsIHRpbGVDb29yZHNbMF0ueSwgMCwgMCxcbiAgICAgICAgdGlsZUNvb3Jkc1sxXS54LCB0aWxlQ29vcmRzWzFdLnksIG1heEludDE2LCAwLFxuICAgICAgICB0aWxlQ29vcmRzWzNdLngsIHRpbGVDb29yZHNbM10ueSwgMCwgbWF4SW50MTYsXG4gICAgICAgIHRpbGVDb29yZHNbMl0ueCwgdGlsZUNvb3Jkc1syXS55LCBtYXhJbnQxNiwgbWF4SW50MTZcbiAgICBdKTtcbiAgICB0aGlzLmJvdW5kc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJvdW5kc0J1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGFycmF5LCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICB0aGlzLnRpbGUgPSBuZXcgVGlsZSgpO1xuICAgIHRoaXMuY2VudGVyID0gY2VudGVyO1xufTtcblxuVmlkZW9Tb3VyY2UucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAvLyBub29wXG59O1xuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgLy8gbm9vcFxufTtcblxuVmlkZW9Tb3VyY2UucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uKGxheWVycykge1xuICAgIGlmICghdGhpcy5lbmFibGVkKSByZXR1cm47XG4gICAgaWYgKHRoaXMudmlkZW8ucmVhZHlTdGF0ZSA8IDIpIHJldHVybjsgLy8gbm90IGVub3VnaCBkYXRhIGZvciBjdXJyZW50IHBvc2l0aW9uXG5cbiAgICB2YXIgbGF5ZXIgPSBsYXllcnNbMF07XG5cbiAgICB2YXIgYnVja2V0ID0ge1xuICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgdGlsZTogdGhpcyxcbiAgICAgICAgYm91bmRzQnVmZmVyOiB0aGlzLmJvdW5kc0J1ZmZlcixcbiAgICAgICAgYmluZDogdGhpcy5iaW5kLmJpbmQodGhpcylcbiAgICB9O1xuXG4gICAgdmFyIGJ1Y2tldHMgPSB7fTtcbiAgICBidWNrZXRzW2xheWVyLmJ1Y2tldF0gPSBidWNrZXQ7XG5cbiAgICB2YXIgYyA9IHRoaXMuY2VudGVyO1xuICAgIHRoaXMudGlsZS5jYWxjdWxhdGVNYXRyaWNlcyhjLnpvb20sIGMuY29sdW1uLCBjLnJvdywgdGhpcy5tYXAudHJhbnNmb3JtLCB0aGlzLm1hcC5wYWludGVyKTtcbiAgICB0aGlzLm1hcC5wYWludGVyLnRpbGUgPSB0aGlzLnRpbGU7XG4gICAgdGhpcy5tYXAucGFpbnRlci5hcHBseVN0eWxlKGxheWVyLCB0aGlzLm1hcC5zdHlsZSwgYnVja2V0cywge30pO1xufTtcblxuVmlkZW9Tb3VyY2UucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihnbCkge1xuXG4gICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLnZpZGVvKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy52aWRlbyk7XG4gICAgfVxuXG59O1xuXG5cblZpZGVvU291cmNlLnByb3RvdHlwZS5mZWF0dXJlc0F0ID0gZnVuY3Rpb24ocG9pbnQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAvLyBUT0RPIHJldHVybiBwaXhlbD9cbiAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFjdG9yID0gcmVxdWlyZSgnLi4vdXRpbC9hY3Rvci5qcycpLFxuICAgIGJ1Y2tldEZpbHRlciA9IHJlcXVpcmUoJy4uL3N0eWxlL2J1Y2tldGZpbHRlci5qcycpLFxuICAgIFdvcmtlclRpbGUgPSByZXF1aXJlKCcuL3dvcmtlcnRpbGUuanMnKSxcbiAgICB0aWxlR2VvSlNPTiA9IHJlcXVpcmUoJy4vdGlsZWdlb2pzb24uanMnKSxcbiAgICBXcmFwcGVyID0gcmVxdWlyZSgnLi9nZW9qc29ud3JhcHBlci5qcycpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwuanMnKSxcbiAgICBxdWV1ZSA9IHJlcXVpcmUoJ3F1ZXVlLWFzeW5jJyksXG4gICAgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlcjtcblxuZnVuY3Rpb24gV29ya2VyKHNlbGYpIHtcbiAgICB0aGlzLnNlbGYgPSBzZWxmO1xuICAgIHRoaXMuYWN0b3IgPSBuZXcgQWN0b3Ioc2VsZiwgdGhpcyk7XG59XG5cbnV0aWwuZXh0ZW5kKFdvcmtlci5wcm90b3R5cGUsIHtcbiAgICBhbGVydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuc2VsZi5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICB0eXBlOiAnYWxlcnQgbWVzc2FnZScsXG4gICAgICAgICAgICBkYXRhOiBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cylcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIC8vIFVwZGF0ZXMgdGhlIHN0eWxlIHRvIHVzZSBmb3IgdGhpcyBtYXAuXG4gICAgJ3NldCBidWNrZXRzJzogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICB2YXIgYnVja2V0cyA9IFdvcmtlclRpbGUuYnVja2V0cyA9IGRhdGE7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNbaV07XG4gICAgICAgICAgICBidWNrZXQuY29tcGFyZSA9IGJ1Y2tldEZpbHRlcihidWNrZXQuZmlsdGVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAnc2V0IGdseXBocyc6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgV29ya2VyVGlsZS5wcm90b3R5cGUuZ2x5cGhzID0gZGF0YTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBMb2FkIGFuZCBwYXJzZSBhIHRpbGUgYXQgYHVybGAsIGFuZCBjYWxsIGBjYWxsYmFja2Agd2l0aFxuICAgICAqIChlcnIsIHJlc3BvbnNlKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHVybFxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICovXG4gICAgJ2xvYWQgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgbmV3IFdvcmtlclRpbGUocGFyYW1zLnVybCwgdW5kZWZpbmVkLCBwYXJhbXMuaWQsIHBhcmFtcy56b29tLCBwYXJhbXMubWF4Wm9vbSwgcGFyYW1zLnRpbGVTaXplLCBwYXJhbXMuc291cmNlLCBwYXJhbXMuZGVwdGgsIHRoaXMuYWN0b3IsIGNhbGxiYWNrKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBBYm9ydCB0aGUgcmVxdWVzdCBrZXllZCB1bmRlciBgdXJsYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHVybFxuICAgICAqL1xuICAgICdhYm9ydCB0aWxlJzogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICAgIFdvcmtlclRpbGUuY2FuY2VsKHBhcmFtcy5pZCwgcGFyYW1zLnNvdXJjZSk7XG4gICAgfSxcblxuICAgICdyZW1vdmUgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcykge1xuICAgICAgICB2YXIgaWQgPSBwYXJhbXMuaWQ7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwYXJhbXMuc291cmNlO1xuICAgICAgICBpZiAoV29ya2VyVGlsZS5sb2FkZWRbc291cmNlXSAmJiBXb3JrZXJUaWxlLmxvYWRlZFtzb3VyY2VdW2lkXSkge1xuICAgICAgICAgICAgZGVsZXRlIFdvcmtlclRpbGUubG9hZGVkW3NvdXJjZV1baWRdO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgICdwYXJzZSBnZW9qc29uJzogZnVuY3Rpb24ocGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZGF0YSA9IHBhcmFtcy5kYXRhLFxuICAgICAgICAgICAgem9vbXMgPSBwYXJhbXMuem9vbXMsXG4gICAgICAgICAgICBsZW4gPSB6b29tcy5sZW5ndGgsXG4gICAgICAgICAgICBtYXhab29tID0gem9vbXNbbGVuIC0gMV0sXG4gICAgICAgICAgICBhY3RvciA9IHRoaXMuYWN0b3IsXG4gICAgICAgICAgICBxID0gcXVldWUoKTtcblxuICAgICAgICBmdW5jdGlvbiB3b3JrZXIoaWQsIHRpbGUsIHpvb20sIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBuZXcgV29ya2VyVGlsZSh1bmRlZmluZWQsIG5ldyBXcmFwcGVyKHRpbGUpLCBpZCwgem9vbSwgbWF4Wm9vbSwgcGFyYW1zLnRpbGVTaXplLCBwYXJhbXMuc291cmNlLCA0LCBhY3RvciwgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICAgICAgZGF0YS5pZCA9IGlkO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRhdGEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB0aWxlRGF0YShlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHRocm93IGVycjtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgem9vbSA9IHpvb21zW2ldO1xuICAgICAgICAgICAgICAgIHZhciB0aWxlcyA9IHRpbGVHZW9KU09OKGRhdGEsIHpvb20pO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHEuZGVmZXIod29ya2VyLCBpZCwgdGlsZXNbaWRdLCB6b29tKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBxLmF3YWl0QWxsKGNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIGFqYXguZ2V0SlNPTihkYXRhLCB0aWxlRGF0YSk7XG4gICAgICAgIGVsc2UgdGlsZURhdGEobnVsbCwgZGF0YSk7XG4gICAgfSxcblxuICAgICdxdWVyeSBmZWF0dXJlcyc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHRpbGUgPSBXb3JrZXJUaWxlLmxvYWRlZFtwYXJhbXMuc291cmNlXSAmJiBXb3JrZXJUaWxlLmxvYWRlZFtwYXJhbXMuc291cmNlXVtwYXJhbXMuaWRdO1xuICAgICAgICBpZiAodGlsZSkge1xuICAgICAgICAgICAgdGlsZS5mZWF0dXJlVHJlZS5xdWVyeShwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRmVhdHVyZVRyZWUgPSByZXF1aXJlKCcuLi9kYXRhL2ZlYXR1cmV0cmVlLmpzJyk7XG52YXIgUHJvdG9idWYgPSByZXF1aXJlKCdwYmYnKTtcbnZhciB2dCA9IHJlcXVpcmUoJ3ZlY3Rvci10aWxlJyk7XG52YXIgQ29sbGlzaW9uID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbi5qcycpO1xudmFyIGdldEFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4LmpzJykuZ2V0QXJyYXlCdWZmZXI7XG5cbnZhciBCdWZmZXJTZXQgPSByZXF1aXJlKCcuLi9kYXRhL2J1ZmZlci9idWZmZXJzZXQuanMnKTtcbnZhciBjcmVhdGVCdWNrZXQgPSByZXF1aXJlKCcuLi9kYXRhL2NyZWF0ZWJ1Y2tldC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlclRpbGU7XG5mdW5jdGlvbiBXb3JrZXJUaWxlKHVybCwgZGF0YSwgaWQsIHpvb20sIG1heFpvb20sIHRpbGVTaXplLCBzb3VyY2UsIGRlcHRoLCBhY3RvciwgY2FsbGJhY2spIHtcbiAgICB2YXIgdGlsZSA9IHRoaXM7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgdGhpcy5tYXhab29tID0gbWF4Wm9vbTtcbiAgICB0aGlzLnRpbGVTaXplID0gdGlsZVNpemU7XG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2U7XG4gICAgdGhpcy5kZXB0aCA9IGRlcHRoO1xuICAgIHRoaXMuYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoKTtcblxuICAgIGZ1bmN0aW9uIGxvYWRlZChkYXRhKSB7XG4gICAgICAgIFdvcmtlclRpbGUubG9hZGVkW3NvdXJjZV0gPSBXb3JrZXJUaWxlLmxvYWRlZFtzb3VyY2VdIHx8IHt9O1xuICAgICAgICBXb3JrZXJUaWxlLmxvYWRlZFtzb3VyY2VdW2lkXSA9IHRpbGU7XG4gICAgICAgIHRpbGUuZGF0YSA9IGRhdGE7XG4gICAgICAgIHRpbGUucGFyc2UoZGF0YSwgYWN0b3IsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBpZiAodXJsKSB7XG4gICAgICAgIGlmIChXb3JrZXJUaWxlLmxvYWRpbmdbc291cmNlXSA9PT0gdW5kZWZpbmVkKSBXb3JrZXJUaWxlLmxvYWRpbmdbc291cmNlXSA9IHt9O1xuICAgICAgICBXb3JrZXJUaWxlLmxvYWRpbmdbc291cmNlXVtpZF0gPSBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgZGVsZXRlIFdvcmtlclRpbGUubG9hZGluZ1tzb3VyY2VdW2lkXTtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2FkZWQobmV3IHZ0LlZlY3RvclRpbGUobmV3IFByb3RvYnVmKG5ldyBVaW50OEFycmF5KGRhdGEpKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkZWQoZGF0YSk7XG4gICAgfVxufVxuXG5Xb3JrZXJUaWxlLmNhbmNlbCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2VJRCkge1xuICAgIHZhciBzb3VyY2UgPSBXb3JrZXJUaWxlLmxvYWRpbmdbc291cmNlSURdO1xuICAgIGlmIChzb3VyY2UgJiYgc291cmNlW2lkXSkge1xuICAgICAgICBzb3VyY2VbaWRdLmFib3J0KCk7XG4gICAgICAgIGRlbGV0ZSBzb3VyY2VbaWRdO1xuICAgIH1cbn07XG5cbi8vIFN0b3JlcyB0aWxlcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGluZy5cbldvcmtlclRpbGUubG9hZGluZyA9IHt9O1xuXG4vLyBTdG9yZXMgdGlsZXMgdGhhdCBhcmUgY3VycmVudGx5IGxvYWRlZC5cbldvcmtlclRpbGUubG9hZGVkID0ge307XG5cbi8vIFN0b3JlcyB0aGUgc3R5bGUgaW5mb3JtYXRpb24uXG5Xb3JrZXJUaWxlLmJ1Y2tldHMgPSBbXTtcblxuLypcbiAqIEdpdmVuIHRpbGUgZGF0YSwgcGFyc2UgcmF3IHZlcnRpY2VzIGFuZCBkYXRhLCBjcmVhdGUgYSB2ZWN0b3JcbiAqIHRpbGUgYW5kIHBhcnNlIGl0IGludG8gcmVhZHktdG8tcmVuZGVyIHZlcnRpY2VzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBkYXRhXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSByZXNwb25kXG4gKi9cbldvcmtlclRpbGUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oZGF0YSwgYWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHRpbGUgPSB0aGlzO1xuICAgIHZhciBidWNrZXRJbmZvID0gV29ya2VyVGlsZS5idWNrZXRzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHZhciB0aWxlRXh0ZW50ID0gNDA5NjtcbiAgICB0aGlzLmNvbGxpc2lvbiA9IG5ldyBDb2xsaXNpb24odGhpcy56b29tLCB0aWxlRXh0ZW50LCB0aGlzLnRpbGVTaXplLCB0aGlzLmRlcHRoKTtcbiAgICB0aGlzLmZlYXR1cmVUcmVlID0gbmV3IEZlYXR1cmVUcmVlKGdldEdlb21ldHJ5LCBnZXRUeXBlKTtcblxuICAgIHZhciBidWNrZXRzID0gdGhpcy5idWNrZXRzID0gc29ydFRpbGVJbnRvQnVja2V0cyh0aGlzLCBkYXRhLCBidWNrZXRJbmZvKTtcblxuICAgIHZhciBrZXksIGJ1Y2tldDtcbiAgICB2YXIgcHJldlBsYWNlbWVudEJ1Y2tldDtcblxuICAgIHZhciByZW1haW5pbmcgPSBXb3JrZXJUaWxlLmJ1Y2tldHMubGVuZ3RoO1xuXG4gICAgLypcbiAgICAgKiAgVGhlIGFzeW5jIHBhcnNpbmcgaGVyZSBpcyBhIGJpdCB0cmlja3kuXG4gICAgICogIFNvbWUgYnVja2V0cyBkZXBlbmQgb24gcmVzb3VyY2VzIHRoYXQgbWF5IG5lZWQgdG8gYmUgbG9hZGVkIGFzeW5jIChnbHlwaHMpLlxuICAgICAqICBTb21lIGJ1Y2tldHMgbmVlZCB0byBiZSBwYXJzZWQgaW4gb3JkZXIgKHRvIGdldCBwbGFjZW1lbnQgcHJpb3JpdGllcyByaWdodCkuXG4gICAgICpcbiAgICAgKiAgRGVwZW5kZW5jaWVzIGNhbGxzIGFyZSBpbml0aWF0ZWQgZmlyc3QgdG8gZ2V0IHRob3NlIHJvbGxpbmcuXG4gICAgICogIEJ1Y2tldHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlciwgYXJlbid0IHRvIHNhdmUgdGltZS5cbiAgICAgKi9cblxuICAgIHZhciBvcmRlcmVkQnVja2V0cyA9IFdvcmtlclRpbGUuYnVja2V0cztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyZWRCdWNrZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJ1Y2tldCA9IGJ1Y2tldHNbb3JkZXJlZEJ1Y2tldHNbaV0uaWRdO1xuICAgICAgICBpZiAoIWJ1Y2tldCkge1xuICAgICAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgICAgICBjb250aW51ZTsgLy8gcmFzdGVyIGJ1Y2tldCwgZXRjXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZmlsdGVyID0gYnVja2V0LmluZm8uZmlsdGVyO1xuICAgICAgICBpZiAoZmlsdGVyICYmIGZpbHRlci5zb3VyY2UgIT09IHRoaXMuc291cmNlKSBjb250aW51ZTtcblxuICAgICAgICAvLyBMaW5rIGJ1Y2tldHMgdGhhdCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlclxuICAgICAgICBpZiAoYnVja2V0LmNvbGxpc2lvbikge1xuICAgICAgICAgICAgaWYgKHByZXZQbGFjZW1lbnRCdWNrZXQpIHtcbiAgICAgICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0Lm5leHQgPSBidWNrZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Y2tldC5wcmV2aW91c1BsYWNlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0ID0gYnVja2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5nZXREZXBlbmRlbmNpZXModGhpcywgYWN0b3IsIGRlcGVuZGVuY2llc0RvbmUoYnVja2V0KSk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIC8vIHBhcnNlIGJ1Y2tldHMgd2hlcmUgb3JkZXIgZG9lc24ndCBtYXR0ZXIgYW5kIG5vIGRlcGVuZGVuY2llc1xuICAgIGZvciAoa2V5IGluIGJ1Y2tldHMpIHtcbiAgICAgICAgYnVja2V0ID0gYnVja2V0c1trZXldO1xuICAgICAgICBpZiAoIWJ1Y2tldC5nZXREZXBlbmRlbmNpZXMgJiYgIWJ1Y2tldC5jb2xsaXNpb24pIHtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZXBlbmRlbmNpZXNEb25lKGJ1Y2tldCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICBidWNrZXQuZGVwZW5kZW5jaWVzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldCwgZXJyKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQsIHNraXApIHtcbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMgJiYgIWJ1Y2tldC5kZXBlbmRlbmNpZXNMb2FkZWQpIHJldHVybjtcbiAgICAgICAgaWYgKGJ1Y2tldC5jb2xsaXNpb24gJiYgIWJ1Y2tldC5wcmV2aW91c1BsYWNlZCkgcmV0dXJuO1xuXG4gICAgICAgIGlmICghc2tpcCkge1xuICAgICAgICAgICAgdmFyIG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBpZiAoYnVja2V0LnR5cGUgIT09ICdyYXN0ZXInKSBidWNrZXQuYWRkRmVhdHVyZXMoKTtcbiAgICAgICAgICAgIHZhciB0aW1lID0gRGF0ZS5ub3coKSAtIG5vdztcbiAgICAgICAgICAgIGlmIChidWNrZXQuaW50ZXJhY3RpdmUpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ1Y2tldC5mZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZmVhdHVyZSA9IGJ1Y2tldC5mZWF0dXJlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgdGlsZS5mZWF0dXJlVHJlZS5pbnNlcnQoZmVhdHVyZS5iYm94KCksIGJ1Y2tldC5uYW1lLCBmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0cyA9IHNlbGYuYnVja2V0U3RhdHMgfHwge190b3RhbDogMH07XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0cy5fdG90YWwgKz0gdGltZTtcbiAgICAgICAgICAgICAgICBzZWxmLmJ1Y2tldFN0YXRzW2J1Y2tldC5uYW1lXSA9IChzZWxmLmJ1Y2tldFN0YXRzW2J1Y2tldC5uYW1lXSB8fCAwKSArIHRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZW1haW5pbmctLTtcbiAgICAgICAgaWYgKCFyZW1haW5pbmcpIHJldHVybiB0aWxlLmRvbmUoKTtcblxuICAgICAgICAvLyB0cnkgcGFyc2luZyB0aGUgbmV4dCBidWNrZXQsIGlmIGl0IGlzIHJlYWR5XG4gICAgICAgIGlmIChidWNrZXQubmV4dCkge1xuICAgICAgICAgICAgYnVja2V0Lm5leHQucHJldmlvdXNQbGFjZWQgPSB0cnVlO1xuICAgICAgICAgICAgcGFyc2VCdWNrZXQodGlsZSwgYnVja2V0Lm5leHQpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuV29ya2VyVGlsZS5wcm90b3R5cGUuZG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIENvbGxlY3QgYWxsIGJ1ZmZlcnMgdG8gbWFyayB0aGVtIGFzIHRyYW5zZmVyYWJsZSBvYmplY3QuXG4gICAgdmFyIGJ1ZmZlcnMgPSBbXTtcblxuICAgIGZvciAodmFyIHR5cGUgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgIGJ1ZmZlcnMucHVzaCh0aGlzLmJ1ZmZlcnNbdHlwZV0uYXJyYXkpO1xuICAgIH1cblxuICAgIC8vIENvbnZlcnQgYnVja2V0cyB0byBhIHRyYW5zZmVyYWJsZSBmb3JtYXRcbiAgICB2YXIgYnVja2V0cyA9IHRoaXMuYnVja2V0cztcbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHt9O1xuICAgIGZvciAodmFyIGIgaW4gYnVja2V0cykgZWxlbWVudEdyb3Vwc1tiXSA9IGJ1Y2tldHNbYl0uZWxlbWVudEdyb3VwcztcblxuICAgIHRoaXMuY2FsbGJhY2sobnVsbCwge1xuICAgICAgICBlbGVtZW50R3JvdXBzOiBlbGVtZW50R3JvdXBzLFxuICAgICAgICBidWZmZXJzOiB0aGlzLmJ1ZmZlcnNcbiAgICB9LCBidWZmZXJzKTtcblxuICAgIC8vIHdlIGRvbid0IG5lZWQgYW55dGhpbmcgZXhjZXB0IGZlYXR1cmVUcmVlIGF0IHRoaXMgcG9pbnQsIHNvIHdlIG1hcmsgaXQgZm9yIEdDXG4gICAgdGhpcy5idWZmZXJzID0gbnVsbDtcbiAgICB0aGlzLmNvbGxpc2lvbiA9IG51bGw7XG4gICAgdGhpcy5idWNrZXRzID0gbnVsbDtcbn07XG5cbmZ1bmN0aW9uIHNvcnRUaWxlSW50b0J1Y2tldHModGlsZSwgZGF0YSwgYnVja2V0SW5mbykge1xuXG4gICAgdmFyIHNvdXJjZUxheWVycyA9IHt9LFxuICAgICAgICBidWNrZXRzID0ge30sXG4gICAgICAgIGxheWVyTmFtZTtcblxuICAgIC8vIEZvciBlYWNoIHNvdXJjZSBsYXllciwgZmluZCBhIGxpc3Qgb2YgYnVja2V0cyB0aGF0IHVzZSBkYXRhIGZyb20gaXRcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ1Y2tldEluZm8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGluZm8gPSBidWNrZXRJbmZvW2ldO1xuICAgICAgICB2YXIgYnVja2V0TmFtZSA9IGluZm8uaWQ7XG5cbiAgICAgICAgdmFyIG1pblpvb20gPSBpbmZvWydtaW4tem9vbSddO1xuICAgICAgICB2YXIgbWF4Wm9vbSA9IGluZm9bJ21heC16b29tJ107XG5cbiAgICAgICAgaWYgKGluZm8uc291cmNlICE9PSB0aWxlLnNvdXJjZSkgY29udGludWU7XG4gICAgICAgIGlmIChtaW5ab29tICYmIHRpbGUuem9vbSA8IG1pblpvb20gJiYgbWluWm9vbSA8IHRpbGUubWF4Wm9vbSkgY29udGludWU7XG4gICAgICAgIGlmIChtYXhab29tICYmIHRpbGUuem9vbSA+PSBtYXhab29tKSBjb250aW51ZTtcblxuICAgICAgICB2YXIgYnVja2V0ID0gY3JlYXRlQnVja2V0KGluZm8sIHRpbGUuYnVmZmVycywgdGlsZS5jb2xsaXNpb24pO1xuICAgICAgICBpZiAoIWJ1Y2tldCkgY29udGludWU7XG4gICAgICAgIGJ1Y2tldC5mZWF0dXJlcyA9IFtdO1xuICAgICAgICBidWNrZXQubmFtZSA9IGJ1Y2tldE5hbWU7XG4gICAgICAgIGJ1Y2tldHNbYnVja2V0TmFtZV0gPSBidWNrZXQ7XG5cbiAgICAgICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgICAgICBsYXllck5hbWUgPSBpbmZvWydzb3VyY2UtbGF5ZXInXTtcbiAgICAgICAgICAgIGlmICghc291cmNlTGF5ZXJzW2xheWVyTmFtZV0pIHNvdXJjZUxheWVyc1tsYXllck5hbWVdID0ge307XG4gICAgICAgICAgICBzb3VyY2VMYXllcnNbbGF5ZXJOYW1lXVtidWNrZXROYW1lXSA9IGluZm87XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBnZW9qc29uIHRpbGVcbiAgICAgICAgICAgIHNvdXJjZUxheWVyc1tidWNrZXROYW1lXSA9IGluZm87XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZWFkIGVhY2ggbGF5ZXIsIGFuZCBzb3J0IGl0cyBmZWF0dXJlJ3MgaW50byBidWNrZXRzXG4gICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgIC8vIHZlY3RvcnRpbGVcbiAgICAgICAgZm9yIChsYXllck5hbWUgaW4gc291cmNlTGF5ZXJzKSB7XG4gICAgICAgICAgICB2YXIgbGF5ZXIgPSBkYXRhLmxheWVyc1tsYXllck5hbWVdO1xuICAgICAgICAgICAgaWYgKCFsYXllcikgY29udGludWU7XG4gICAgICAgICAgICBzb3J0TGF5ZXJJbnRvQnVja2V0cyhsYXllciwgc291cmNlTGF5ZXJzW2xheWVyTmFtZV0sIGJ1Y2tldHMpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZ2VvanNvblxuICAgICAgICBzb3J0TGF5ZXJJbnRvQnVja2V0cyhkYXRhLCBzb3VyY2VMYXllcnMsIGJ1Y2tldHMpO1xuICAgIH1cblxuICAgIHJldHVybiBidWNrZXRzO1xufVxuXG4vKlxuICogU29ydHMgZmVhdHVyZXMgaW4gYSBsYXllciBpbnRvIGRpZmZlcmVudCBidWNrZXRzLCBhY2NvcmRpbmcgdG8gdGhlIG1hcGluZ1xuICpcbiAqIExheWVycyBpbiB2ZWN0b3IgdGlsZXMgY29udGFpbiBtYW55IGRpZmZlcmVudCBmZWF0dXJlcywgYW5kIGZlYXR1cmUgdHlwZXMsXG4gKiBlLmcuIHRoZSBsYW5kdXNlIGxheWVyIGhhcyBwYXJrcywgaW5kdXN0cmlhbCBidWlsZGluZ3MsIGZvcmVzdHMsIHBsYXlncm91bmRzXG4gKiBldGMuIEhvd2V2ZXIsIHdoZW4gc3R5bGluZywgd2UgbmVlZCB0byBzZXBhcmF0ZSB0aGVzZSBmZWF0dXJlcyBzbyB0aGF0IHdlIGNhblxuICogcmVuZGVyIHRoZW0gc2VwYXJhdGVseSB3aXRoIGRpZmZlcmVudCBzdHlsZXMuXG4gKlxuICogQHBhcmFtIHtWZWN0b3JUaWxlTGF5ZXJ9IGxheWVyXG4gKiBAcGFyYW0ge01hcHBpbmd9IG1hcHBpbmdcbiAqL1xuZnVuY3Rpb24gc29ydExheWVySW50b0J1Y2tldHMobGF5ZXIsIG1hcHBpbmcsIGJ1Y2tldHMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxheWVyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gbGF5ZXIuZmVhdHVyZShpKTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG1hcHBpbmcpIHtcbiAgICAgICAgICAgIGlmIChtYXBwaW5nW2tleV0uY29tcGFyZShmZWF0dXJlKSkge1xuICAgICAgICAgICAgICAgIGJ1Y2tldHNba2V5XS5mZWF0dXJlcy5wdXNoKGZlYXR1cmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRHZW9tZXRyeShmZWF0dXJlKSB7XG4gICAgcmV0dXJuIGZlYXR1cmUubG9hZEdlb21ldHJ5KCk7XG59XG5cbmZ1bmN0aW9uIGdldFR5cGUoZmVhdHVyZSkge1xuICAgIHJldHVybiB2dC5WZWN0b3JUaWxlRmVhdHVyZS50eXBlc1tmZWF0dXJlLnR5cGVdO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuaW1hdGlvbkxvb3A7XG5cbmZ1bmN0aW9uIEFuaW1hdGlvbkxvb3AoKSB7XG4gICAgdGhpcy5uID0gMDtcbiAgICB0aGlzLnRpbWVzID0gW107XG59XG5cbi8vIEFyZSBhbGwgYW5pbWF0aW9ucyBkb25lP1xuQW5pbWF0aW9uTG9vcC5wcm90b3R5cGUuc3RvcHBlZCA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMudGltZXMgPSB0aGlzLnRpbWVzLmZpbHRlcihmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiB0LnRpbWUgPj0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcbiAgICB9KTtcbiAgICByZXR1cm4gIXRoaXMudGltZXMubGVuZ3RoO1xufTtcblxuLy8gQWRkIGEgbmV3IGFuaW1hdGlvbiB0aGF0IHdpbGwgcnVuIHQgbWlsbGlzZWNvbmRzXG4vLyBSZXR1cm5zIGFuIGlkIHRoYXQgY2FuIGJlIHVzZWQgdG8gY2FuY2VsIGl0IGxheWVyXG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbih0KSB7XG4gICAgdGhpcy50aW1lcy5wdXNoKHsgaWQ6IHRoaXMubiwgdGltZTogdCArIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgfSk7XG4gICAgcmV0dXJuIHRoaXMubisrO1xufTtcblxuLy8gQ2FuY2VsIGFuIGFuaW1hdGlvblxuQW5pbWF0aW9uTG9vcC5wcm90b3R5cGUuY2FuY2VsID0gZnVuY3Rpb24obikge1xuICAgIHRoaXMudGltZXMgPSB0aGlzLnRpbWVzLmZpbHRlcihmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiB0LmlkICE9IG47XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCd2ZWN0b3ItdGlsZScpLlZlY3RvclRpbGVGZWF0dXJlO1xuXG5mdW5jdGlvbiBpbmZpeChvcGVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihsZWZ0LCByaWdodCkgeyByZXR1cm4gbGVmdCArICcgJyArIG9wZXJhdG9yICsgJyAnICsgcmlnaHQ7IH07XG59XG5cbnZhciBpbmZpeE9wZXJhdG9ycyA9IHtcbiAgICAnPT0nOiBpbmZpeCgnPT09JyksXG4gICAgJz4nOiBpbmZpeCgnPicpLCAnJGd0JzogaW5maXgoJz4nKSxcbiAgICAnPCc6IGluZml4KCc8JyksICckbHQnOiBpbmZpeCgnPCcpLFxuICAgICc8PSc6IGluZml4KCc8PScpLCAnJGx0ZSc6IGluZml4KCc8PScpLFxuICAgICc+PSc6IGluZml4KCc+PScpLCAnJGd0ZSc6IGluZml4KCc+PScpLFxuICAgICchPSc6IGluZml4KCchPT0nKSwgJyRuZSc6IGluZml4KCchPT0nKSxcbiAgICAnJGV4aXN0cyc6IGZ1bmN0aW9uICh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgKyAnICE9PSB1bmRlZmluZWQnOyB9XG59O1xuXG5mdW5jdGlvbiBvcihpdGVtcykgIHsgcmV0dXJuICcoJyArIGl0ZW1zLmpvaW4oJyB8fCAnKSArICcpJzsgfVxuZnVuY3Rpb24gYW5kKGl0ZW1zKSB7IHJldHVybiAnKCcgKyBpdGVtcy5qb2luKCcgJiYgJykgKyAnKSc7IH1cbmZ1bmN0aW9uIG5vdChpdGVtKSAgeyByZXR1cm4gJyEnICsgaXRlbTsgfVxuZnVuY3Rpb24gbm9yKGl0ZW1zKSB7IHJldHVybiBub3Qob3IoaXRlbXMpKTsgfVxuXG52YXIgYXJyYXlPcGVyYXRvcnMgPSB7XG4gICAgJ3x8Jzogb3IsICckb3InOiBvcixcbiAgICAnJiYnOiBhbmQsICckYW5kJzogYW5kLFxuICAgICchJzogbm9yLCAnJG5vcic6IG5vclxufTtcblxudmFyIG9iak9wZXJhdG9ycyA9IHtcbiAgICAnISc6IG5vdCwgJyRub3QnOiBub3Rcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZpbHRlcikge1xuICAgIC8vIHNpbXBsZSBrZXkgJiB2YWx1ZSBjb21wYXJpc29uXG4gICAgZnVuY3Rpb24gdmFsdWVGaWx0ZXIoa2V5LCB2YWx1ZSwgb3BlcmF0b3IpIHtcbiAgICAgICAgcmV0dXJuIG9wZXJhdG9yKCdwWycgKyBKU09OLnN0cmluZ2lmeShrZXkpICsgJ10nLCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8vIGNvbXBhcmVzIGtleSAmIHZhbHVlIG9yIGtleSAmIG9yKHZhbHVlcylcbiAgICBmdW5jdGlvbiBzaW1wbGVGaWVsZEZpbHRlcihrZXksIHZhbHVlLCBvcGVyYXRvcikge1xuICAgICAgICB2YXIgb3BlcmF0b3JGbiA9IGluZml4T3BlcmF0b3JzW29wZXJhdG9yIHx8ICc9PSddO1xuICAgICAgICBpZiAoIW9wZXJhdG9yRm4pIHRocm93IG5ldyBFcnJvcignVW5rbm93biBvcGVyYXRvcjogJyArIG9wZXJhdG9yKTtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvcih2YWx1ZS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWVGaWx0ZXIoa2V5LCB2LCBvcGVyYXRvckZuKTtcbiAgICAgICAgICAgIH0pKTtcblxuICAgICAgICB9IGVsc2UgcmV0dXJuIHZhbHVlRmlsdGVyKGtleSwgdmFsdWUsIG9wZXJhdG9yRm4pO1xuICAgIH1cblxuICAgIC8vIGhhbmRsZXMgYW55IGZpbHRlciBrZXkvdmFsdWUgcGFpclxuICAgIGZ1bmN0aW9uIGZpZWxkRmlsdGVyKGtleSwgdmFsdWUpIHtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmIChrZXkgaW4gYXJyYXlPcGVyYXRvcnMpIHsgLy8gaGFuZGxlIGFuZC9vciBvcGVyYXRvcnNcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlPcGVyYXRvcnNba2V5XSh2YWx1ZS5tYXAoZmllbGRzRmlsdGVyKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG5cbiAgICAgICAgICAgIC8vIGhhbmRsZSBub3Qgb3BlcmF0b3JcbiAgICAgICAgICAgIGlmIChrZXkgaW4gb2JqT3BlcmF0b3JzKSByZXR1cm4gb2JqT3BlcmF0b3JzW2tleV0oZmllbGRzRmlsdGVyKHZhbHVlKSk7XG5cbiAgICAgICAgICAgIC8vIGhhbmRsZSB7a2V5OiB7b3BlcmF0b3I6IHZhbHVlfX0gbm90YXRpb25cbiAgICAgICAgICAgIHZhciBmaWx0ZXJzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBvcCBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGZpbHRlcnMucHVzaChzaW1wbGVGaWVsZEZpbHRlcihrZXksIHZhbHVlW29wXSwgb3ApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhbmQoZmlsdGVycyk7XG5cbiAgICAgICAgfVxuICAgICAgICAvLyBoYW5kbGUgc2ltcGxlIGtleS92YWx1ZSBvciBrZXkvdmFsdWVzIGNvbXBhcmlzb25cbiAgICAgICAgcmV0dXJuIHNpbXBsZUZpZWxkRmlsdGVyKGtleSwgdmFsdWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHR5cGVGaWx0ZXIodHlwZSkge1xuICAgICAgICByZXR1cm4gJ2YudHlwZSA9PT0gJyArIFZlY3RvclRpbGVGZWF0dXJlLnR5cGVzLmluZGV4T2YodHlwZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZmllbGRzRmlsdGVyKG9iaikge1xuICAgICAgICB2YXIgZmlsdGVycyA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJzLnB1c2godHlwZUZpbHRlcihvYmpba2V5XSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJzLnB1c2goZmllbGRGaWx0ZXIoa2V5LCBvYmpba2V5XSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbHRlcnMubGVuZ3RoID8gYW5kKGZpbHRlcnMpIDogJ3RydWUnO1xuICAgIH1cblxuICAgIHZhciBmaWx0ZXJTdHIgPSAndmFyIHAgPSBmLnByb3BlcnRpZXMgfHwge307IHJldHVybiAnICsgZmllbGRzRmlsdGVyKGZpbHRlciB8fCB7fSkgKyAnOyc7XG5cbiAgICAvLyBqc2hpbnQgZXZpbDogdHJ1ZVxuICAgIHJldHVybiBuZXcgRnVuY3Rpb24oJ2YnLCBmaWx0ZXJTdHIpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJ21hcGJveC1nbC1zdHlsZS1zcGVjL3JlZmVyZW5jZS92NCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5yZWZlcmVuY2VbJ2NsYXNzJ10uZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgQ2FsY3VsYXRlZCA9IGZ1bmN0aW9uKCkge307XG4gICAgdmFyIHN0eWxlID0gcmVmZXJlbmNlW2NsYXNzTmFtZV07XG4gICAgZm9yICh2YXIgcHJvcCBpbiBzdHlsZSkge1xuICAgICAgICBpZiAoc3R5bGVbcHJvcF1bJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICAgICAgQ2FsY3VsYXRlZC5wcm90b3R5cGVbcHJvcF0gPSBzdHlsZVtwcm9wXVsnZGVmYXVsdCddO1xuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgnY2xhc3NfJywnJyldID0gQ2FsY3VsYXRlZDtcbn0pO1xuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkLmpzJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheC5qcycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXIuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbWFnZVNwcml0ZTtcblxuZnVuY3Rpb24gSW1hZ2VTcHJpdGUoYmFzZSkge1xuXG4gICAgdmFyIHNwcml0ZSA9IHRoaXM7XG4gICAgdGhpcy5iYXNlID0gYmFzZTtcbiAgICB0aGlzLnJldGluYSA9IGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyA+IDE7XG5cbiAgICBiYXNlID0gc3ByaXRlLmJhc2UgKyAoc3ByaXRlLnJldGluYSA/ICdAMngnIDogJycpO1xuXG4gICAgYWpheC5nZXRKU09OKGJhc2UgKyAnLmpzb24nLCBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgLy8gQFRPRE8gaGFuZGxlIGVycm9ycyB2aWEgc3ByaXRlIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG4gICAgICAgIHNwcml0ZS5kYXRhID0gZGF0YTtcbiAgICAgICAgaWYgKHNwcml0ZS5pbWcpIHNwcml0ZS5maXJlKCdsb2FkZWQnKTtcbiAgICB9KTtcblxuICAgIGFqYXguZ2V0SW1hZ2UoYmFzZSArICcucG5nJywgZnVuY3Rpb24oZXJyLCBpbWcpIHtcbiAgICAgICAgLy8gQFRPRE8gaGFuZGxlIGVycm9ycyB2aWEgc3ByaXRlIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG5cbiAgICAgICAgLy8gcHJlbXVsdGlwbHkgdGhlIHNwcml0ZVxuICAgICAgICB2YXIgZGF0YSA9IGltZy5nZXREYXRhKCk7XG4gICAgICAgIHZhciBuZXdkYXRhID0gaW1nLmRhdGEgPSBuZXcgVWludDhBcnJheShkYXRhLmxlbmd0aCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrPTQpIHtcbiAgICAgICAgICAgIHZhciBhbHBoYSA9IGRhdGFbaSArIDNdIC8gMjU1O1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMF0gPSBkYXRhW2kgKyAwXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMV0gPSBkYXRhW2kgKyAxXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMl0gPSBkYXRhW2kgKyAyXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgM10gPSBkYXRhW2kgKyAzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNwcml0ZS5pbWcgPSBpbWc7XG4gICAgICAgIGlmIChzcHJpdGUuZGF0YSkgc3ByaXRlLmZpcmUoJ2xvYWRlZCcpO1xuICAgIH0pO1xufVxuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5sb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gISEodGhpcy5kYXRhICYmIHRoaXMuaW1nKTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbihnbCkge1xuICAgIHZhciBzcHJpdGUgPSB0aGlzO1xuICAgIGlmIChicm93c2VyLmRldmljZVBpeGVsUmF0aW8gPiAxICE9PSBzcHJpdGUucmV0aW5hKSB7XG5cbiAgICAgICAgdmFyIG5ld1Nwcml0ZSA9IG5ldyBJbWFnZVNwcml0ZShzcHJpdGUuYmFzZSk7XG4gICAgICAgIG5ld1Nwcml0ZS5vbignbG9hZGVkJywgZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgICAgIHNwcml0ZS5pbWcgPSBuZXdTcHJpdGUuaW1nO1xuICAgICAgICAgICAgc3ByaXRlLmRhdGEgPSBuZXdTcHJpdGUuZGF0YTtcbiAgICAgICAgICAgIHNwcml0ZS5yZXRpbmEgPSBuZXdTcHJpdGUucmV0aW5hO1xuXG4gICAgICAgICAgICBpZiAoc3ByaXRlLnRleHR1cmUpIHtcbiAgICAgICAgICAgICAgICBnbC5kZWxldGVUZXh0dXJlKHNwcml0ZS50ZXh0dXJlKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgc3ByaXRlLnRleHR1cmU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxuSW1hZ2VTcHJpdGUucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihnbCwgbGluZWFyKSB7XG4gICAgdmFyIHNwcml0ZSA9IHRoaXM7XG5cbiAgICBpZiAoIXNwcml0ZS5sb2FkZWQoKSlcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgaWYgKCFzcHJpdGUudGV4dHVyZSkge1xuICAgICAgICBzcHJpdGUudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgc3ByaXRlLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIHZhciBpbWcgPSBzcHJpdGUuaW1nO1xuICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGltZy53aWR0aCwgaW1nLmhlaWdodCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgaW1nLmRhdGEpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgc3ByaXRlLnRleHR1cmUpO1xuICAgIH1cblxuICAgIHZhciBmaWx0ZXIgPSBsaW5lYXIgPyBnbC5MSU5FQVIgOiBnbC5ORUFSRVNUO1xuICAgIGlmIChmaWx0ZXIgIT09IHNwcml0ZS5maWx0ZXIpIHtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGZpbHRlcik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBmaWx0ZXIpO1xuICAgIH1cbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKG5hbWUsIHJlcGVhdGluZykge1xuXG4gICAgLy8gYHJlcGVhdGluZ2AgaW5kaWNhdGVzIHRoYXQgdGhlIGltYWdlIHdpbGwgYmUgdXNlZCBpbiBhIHJlcGVhdGluZyBwYXR0ZXJuXG4gICAgLy8gcmVwZWF0aW5nIHBhdHRlcm4gaW1hZ2VzIGFyZSBhc3N1bWVkIHRvIGhhdmUgYSAxcHggcGFkZGluZyB0aGF0IG1pcnJvcnMgdGhlIG9wcG9zaXRlIGVkZ2VcbiAgICAvLyBwb3NpdGlvbnMgZm9yIHJlcGVhdGluZyBpbWFnZXMgYXJlIGFkanVzdGVkIHRvIGV4Y2x1ZGUgdGhlIGVkZ2VcbiAgICByZXBlYXRpbmcgPSByZXBlYXRpbmcgPT09IHRydWUgPyAxIDogMDtcblxuICAgIHZhciBwb3MgPSB0aGlzLmRhdGEgJiYgdGhpcy5kYXRhW25hbWVdO1xuICAgIGlmIChwb3MgJiYgdGhpcy5pbWcpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gdGhpcy5pbWcud2lkdGg7XG4gICAgICAgIHZhciBoZWlnaHQgPSB0aGlzLmltZy5oZWlnaHQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzaXplOiBbcG9zLndpZHRoIC8gcG9zLnBpeGVsUmF0aW8sIHBvcy5oZWlnaHQgLyBwb3MucGl4ZWxSYXRpb10sXG4gICAgICAgICAgICB0bDogWyhwb3MueCArIHJlcGVhdGluZykvIHdpZHRoLCAocG9zLnkgKyByZXBlYXRpbmcpIC8gaGVpZ2h0XSxcbiAgICAgICAgICAgIGJyOiBbKHBvcy54ICsgcG9zLndpZHRoIC0gMiAqIHJlcGVhdGluZykgLyB3aWR0aCwgKHBvcy55ICsgcG9zLmhlaWdodCAtIDIgKiByZXBlYXRpbmcpIC8gaGVpZ2h0XVxuICAgICAgICB9O1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZWZlcmVuY2UgPSByZXF1aXJlKCdtYXBib3gtZ2wtc3R5bGUtc3BlYy9yZWZlcmVuY2UvdjQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucmVmZXJlbmNlLnJlbmRlci5mb3JFYWNoKGZ1bmN0aW9uKGNsYXNzTmFtZSkge1xuICAgIHZhciBQcm9wZXJ0aWVzID0gZnVuY3Rpb24ocHJvcHMpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBwcm9wcykge1xuICAgICAgICAgICAgdGhpc1twXSA9IHByb3BzW3BdO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBwcm9wZXJ0aWVzID0gcmVmZXJlbmNlW2NsYXNzTmFtZV07XG4gICAgZm9yICh2YXIgcHJvcCBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzW3Byb3BdWydkZWZhdWx0J10gPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgICAgIFByb3BlcnRpZXMucHJvdG90eXBlW3Byb3BdID0gcHJvcGVydGllc1twcm9wXVsnZGVmYXVsdCddO1xuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgncmVuZGVyXycsJycpXSA9IFByb3BlcnRpZXM7XG59KTtcblxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZC5qcycpO1xuXG52YXIgU3R5bGVUcmFuc2l0aW9uID0gcmVxdWlyZSgnLi9zdHlsZXRyYW5zaXRpb24uanMnKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uID0gcmVxdWlyZSgnLi9zdHlsZWRlY2xhcmF0aW9uLmpzJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVjb25zdGFudC5qcycpO1xudmFyIENhbGN1bGF0ZWRTdHlsZSA9IHJlcXVpcmUoJy4vY2FsY3VsYXRlZHN0eWxlLmpzJyk7XG52YXIgSW1hZ2VTcHJpdGUgPSByZXF1aXJlKCcuL2ltYWdlc3ByaXRlLmpzJyk7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU3R5bGU7XG5cbi8qXG4gKiBUaGUgbWFwIHN0eWxlJ3MgY3VycmVudCBzdGF0ZVxuICpcbiAqIFRoZSBzdHlsZXNoZWV0IG9iamVjdCBpcyBub3QgbW9kaWZpZWQuIFRvIGNoYW5nZSB0aGUgc3R5bGUsIGp1c3QgY2hhbmdlXG4gKiB0aGUgdGhlIHN0eWxlc2hlZXQgb2JqZWN0IGFuZCB0cmlnZ2VyIGEgY2FzY2FkZS5cbiAqL1xuZnVuY3Rpb24gU3R5bGUoc3R5bGVzaGVldCwgYW5pbWF0aW9uTG9vcCkge1xuICAgIGlmIChzdHlsZXNoZWV0LnZlcnNpb24gIT09IDQpIGNvbnNvbGUud2FybignU3R5bGVzaGVldCB2ZXJzaW9uIG11c3QgYmUgNCcpO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShzdHlsZXNoZWV0LmxheWVycykpIGNvbnNvbGUud2FybignU3R5bGVzaGVldCBtdXN0IGhhdmUgbGF5ZXJzJyk7XG5cbiAgICB0aGlzLmNsYXNzZXMgPSB7fTtcbiAgICB0aGlzLnN0eWxlc2hlZXQgPSBzdHlsZXNoZWV0O1xuICAgIHRoaXMuYW5pbWF0aW9uTG9vcCA9IGFuaW1hdGlvbkxvb3A7XG5cbiAgICB0aGlzLmJ1Y2tldHMgPSB7fTtcbiAgICB0aGlzLm9yZGVyZWRCdWNrZXRzID0gW107XG4gICAgdGhpcy50cmFuc2l0aW9ucyA9IHt9O1xuICAgIHRoaXMuY29tcHV0ZWQgPSB7fTtcbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcblxuICAgIHRoaXMuY2FzY2FkZSh7dHJhbnNpdGlvbjogZmFsc2V9KTtcblxuICAgIGlmIChzdHlsZXNoZWV0LnNwcml0ZSkgdGhpcy5zZXRTcHJpdGUoc3R5bGVzaGVldC5zcHJpdGUpO1xufVxuXG5TdHlsZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5mdW5jdGlvbiBwcmVtdWx0aXBseUxheWVyKGxheWVyLCB0eXBlKSB7XG4gICAgdmFyIGNvbG9yUHJvcCA9IHR5cGUgKyAnLWNvbG9yJyxcbiAgICAgICAgaGFsb1Byb3AgPSB0eXBlICsgJy1oYWxvLWNvbG9yJyxcbiAgICAgICAgb3V0bGluZVByb3AgPSB0eXBlICsgJy1vdXRsaW5lLWNvbG9yJyxcbiAgICAgICAgY29sb3IgPSBsYXllcltjb2xvclByb3BdLFxuICAgICAgICBoYWxvQ29sb3IgPSBsYXllcltoYWxvUHJvcF0sXG4gICAgICAgIG91dGxpbmVDb2xvciA9IGxheWVyW291dGxpbmVQcm9wXSxcbiAgICAgICAgb3BhY2l0eSA9IGxheWVyW3R5cGUgKyAnLW9wYWNpdHknXTtcblxuICAgIHZhciBjb2xvck9wYWNpdHkgPSBjb2xvciAmJiAob3BhY2l0eSAqIGNvbG9yWzNdKTtcbiAgICB2YXIgaGFsb09wYWNpdHkgPSBoYWxvQ29sb3IgJiYgKG9wYWNpdHkgKiBoYWxvQ29sb3JbM10pO1xuICAgIHZhciBvdXRsaW5lT3BhY2l0eSA9IG91dGxpbmVDb2xvciAmJiAob3BhY2l0eSAqIG91dGxpbmVDb2xvclszXSk7XG5cbiAgICBpZiAoY29sb3JPcGFjaXR5ICE9PSB1bmRlZmluZWQgJiYgY29sb3JPcGFjaXR5IDwgMSkge1xuICAgICAgICBsYXllcltjb2xvclByb3BdID0gdXRpbC5wcmVtdWx0aXBseShbY29sb3JbMF0sIGNvbG9yWzFdLCBjb2xvclsyXSwgY29sb3JPcGFjaXR5XSk7XG4gICAgfVxuICAgIGlmIChoYWxvT3BhY2l0eSAhPT0gdW5kZWZpbmVkICYmIGhhbG9PcGFjaXR5IDwgMSkge1xuICAgICAgICBsYXllcltoYWxvUHJvcF0gPSB1dGlsLnByZW11bHRpcGx5KFtoYWxvQ29sb3JbMF0sIGhhbG9Db2xvclsxXSwgaGFsb0NvbG9yWzJdLCBoYWxvT3BhY2l0eV0pO1xuICAgIH1cbiAgICBpZiAob3V0bGluZU9wYWNpdHkgIT09IHVuZGVmaW5lZCAmJiBvdXRsaW5lT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbb3V0bGluZVByb3BdID0gdXRpbC5wcmVtdWx0aXBseShbb3V0bGluZUNvbG9yWzBdLCBvdXRsaW5lQ29sb3JbMV0sIG91dGxpbmVDb2xvclsyXSwgb3V0bGluZU9wYWNpdHldKTtcbiAgICB9XG59XG5cbi8vIEZvcm1lcmx5IGtub3duIGFzIHpvb21lZCBzdHlsZXNcblN0eWxlLnByb3RvdHlwZS5yZWNhbGN1bGF0ZSA9IGZ1bmN0aW9uKHopIHtcbiAgICBpZiAodHlwZW9mIHogIT09ICdudW1iZXInKSBjb25zb2xlLndhcm4oJ3JlY2FsY3VsYXRlIGV4cGVjdHMgem9vbSBsZXZlbCcpO1xuXG4gICAgdmFyIHRyYW5zaXRpb25zID0gdGhpcy50cmFuc2l0aW9ucztcbiAgICB2YXIgbGF5ZXJWYWx1ZXMgPSB7fTtcblxuICAgIHRoaXMuc291cmNlcyA9IHt9O1xuXG4gICAgdGhpcy5yYXN0ZXJGYWRlRHVyYXRpb24gPSAzMDA7XG5cbiAgICBmb3IgKHZhciBuYW1lIGluIHRyYW5zaXRpb25zKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRyYW5zaXRpb25zW25hbWVdLFxuICAgICAgICAgICAgYnVja2V0ID0gdGhpcy5idWNrZXRzW2xheWVyLnJlZiB8fCBuYW1lXSxcbiAgICAgICAgICAgIGxheWVyVHlwZSA9IHRoaXMubGF5ZXJtYXBbbmFtZV0udHlwZTtcblxuICAgICAgICBpZiAoIUNhbGN1bGF0ZWRTdHlsZVtsYXllclR5cGVdKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ3Vua25vd24gbGF5ZXIgdHlwZSAnICsgbGF5ZXJUeXBlKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhcHBsaWVkTGF5ZXIgPSBsYXllclZhbHVlc1tuYW1lXSA9IG5ldyBDYWxjdWxhdGVkU3R5bGVbbGF5ZXJUeXBlXSgpO1xuICAgICAgICBmb3IgKHZhciBydWxlIGluIGxheWVyKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IGxheWVyW3J1bGVdO1xuICAgICAgICAgICAgYXBwbGllZExheWVyW3J1bGVdID0gdHJhbnNpdGlvbi5hdCh6KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsYXllclR5cGUgPT09ICdzeW1ib2wnKSB7XG4gICAgICAgICAgICBhcHBsaWVkTGF5ZXIuaGlkZGVuID1cbiAgICAgICAgICAgICAgICAoYXBwbGllZExheWVyWyd0ZXh0LW9wYWNpdHknXSA9PT0gMCB8fCAhYnVja2V0LnJlbmRlclsndGV4dC1maWVsZCddKSAmJlxuICAgICAgICAgICAgICAgIChhcHBsaWVkTGF5ZXJbJ2ljb24tb3BhY2l0eSddID09PSAwIHx8ICFidWNrZXQucmVuZGVyWydpY29uLWltYWdlJ10pO1xuICAgICAgICAgICAgaWYgKCFhcHBsaWVkTGF5ZXIuaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihhcHBsaWVkTGF5ZXIsICd0ZXh0Jyk7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihhcHBsaWVkTGF5ZXIsICdpY29uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcHBsaWVkTGF5ZXIuaGlkZGVuID0gKGFwcGxpZWRMYXllcltsYXllclR5cGUgKyAnLW9wYWNpdHknXSA9PT0gMCk7XG4gICAgICAgICAgICBpZiAoIWFwcGxpZWRMYXllci5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICBwcmVtdWx0aXBseUxheWVyKGFwcGxpZWRMYXllciwgbGF5ZXJUeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmQgYWxsIHRoZSBzb3VyY2VzIHRoYXQgYXJlIGN1cnJlbnRseSBiZWluZyB1c2VkXG4gICAgICAgIC8vIHNvIHRoYXQgd2UgY2FuIGF1dG9tYXRpY2FsbHkgZW5hYmxlL2Rpc2FibGUgdGhlbSBhcyBuZWVkZWRcbiAgICAgICAgaWYgKCFhcHBsaWVkTGF5ZXIuaGlkZGVuKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gYnVja2V0ICYmIGJ1Y2tldC5zb3VyY2U7XG5cbiAgICAgICAgICAgIC8vIG1hcmsgc291cmNlIGFzIHVzZWQgc28gdGhhdCB0aWxlcyBhcmUgZG93bmxvYWRlZFxuICAgICAgICAgICAgaWYgKHNvdXJjZSkgdGhpcy5zb3VyY2VzW3NvdXJjZV0gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFwcGxpZWRMYXllclsncmFzdGVyLWZhZGUnXSkge1xuICAgICAgICAgICAgdGhpcy5yYXN0ZXJGYWRlRHVyYXRpb24gPSBNYXRoLm1heCh0aGlzLnJhc3RlckZhZGVEdXJhdGlvbiwgYXBwbGllZExheWVyWydyYXN0ZXItZmFkZSddKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY29tcHV0ZWQgPSBsYXllclZhbHVlcztcblxuICAgIHRoaXMueiA9IHo7XG4gICAgdGhpcy5maXJlKCd6b29tJyk7XG59O1xuXG5TdHlsZS5wcm90b3R5cGUuX3NpbXBsZUxheWVyID0gZnVuY3Rpb24obGF5ZXIpIHtcbiAgICB2YXIgc2ltcGxlID0ge307XG4gICAgc2ltcGxlLmlkID0gbGF5ZXIuaWQ7XG5cbiAgICB2YXIgYnVja2V0ID0gdGhpcy5idWNrZXRzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKGJ1Y2tldCkgc2ltcGxlLmJ1Y2tldCA9IGJ1Y2tldC5pZDtcbiAgICBpZiAobGF5ZXIudHlwZSkgc2ltcGxlLnR5cGUgPSBsYXllci50eXBlO1xuXG4gICAgaWYgKGxheWVyLmxheWVycykge1xuICAgICAgICBzaW1wbGUubGF5ZXJzID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXIubGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzaW1wbGUubGF5ZXJzLnB1c2godGhpcy5fc2ltcGxlTGF5ZXIobGF5ZXIubGF5ZXJzW2ldKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNpbXBsZTtcbn07XG5cbi8vIFNwbGl0IHRoZSBsYXllcnMgaW50byBncm91cHMgb2YgY29uc2VjdXRpdmUgbGF5ZXJzIHdpdGggdGhlIHNhbWUgZGF0YXNvdXJjZVxuLy8gRm9yIGVhY2ggZ3JvdXAgY2FsY3VsYXRlIGl0cyBkZXBlbmRlbmNpZXMuIEl0cyBkZXBlbmRlbmNpZXMgYXJlIGNvbXBvc2l0ZWRcbi8vIGxheWVycyB0aGF0IG5lZWQgdG8gYmUgcmVuZGVyZWQgaW50byB0ZXh0dXJlcyBiZWZvcmVcblN0eWxlLnByb3RvdHlwZS5fZ3JvdXBMYXllcnMgPSBmdW5jdGlvbihsYXllcnMpIHtcbiAgICB2YXIgZyA9IDA7XG4gICAgdmFyIGdyb3VwcyA9IFtdO1xuICAgIHZhciBncm91cDtcblxuICAgIC8vIGxvb3Agb3ZlciBsYXllcnMgdG9wIGRvd25cbiAgICBmb3IgKHZhciBpID0gbGF5ZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHZhciBsYXllciA9IGxheWVyc1tpXTtcblxuICAgICAgICB2YXIgYnVja2V0ID0gdGhpcy5idWNrZXRzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgICAgIHZhciBzb3VyY2UgPSBidWNrZXQgJiYgYnVja2V0LnNvdXJjZTtcblxuICAgICAgICAvLyBpZiB0aGUgY3VycmVudCBsYXllciBpcyBpbiBhIGRpZmZlcmVudCBzb3VyY2VcbiAgICAgICAgaWYgKGdyb3VwICYmIHNvdXJjZSAhPT0gZ3JvdXAuc291cmNlKSBnKys7XG5cbiAgICAgICAgaWYgKCFncm91cHNbZ10pIHtcbiAgICAgICAgICAgIGdyb3VwID0gW107XG4gICAgICAgICAgICBncm91cC5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICAgICAgICBpZiAobGF5ZXIubGF5ZXJzKSBncm91cC5jb21wb3NpdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGdyb3Vwc1tnXSA9IGdyb3VwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxheWVyLmxheWVycyAmJiBsYXllci50eXBlID09ICdjb21wb3NpdGUnKSB7XG4gICAgICAgICAgICAvLyBUT0RPIGlmIGNvbXBvc2l0ZWQgbGF5ZXIgaXMgb3BhcXVlIGp1c3QgaW5saW5lIHRoZSBsYXllcnNcbiAgICAgICAgICAgIGdyb3VwLmRlcGVuZGVuY2llcyA9IGdyb3VwLmRlcGVuZGVuY2llcyB8fCB7fTtcbiAgICAgICAgICAgIGdyb3VwLmRlcGVuZGVuY2llc1tsYXllci5pZF0gPSB0aGlzLl9ncm91cExheWVycyhsYXllci5sYXllcnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ3JvdXAucHVzaCh0aGlzLl9zaW1wbGVMYXllcihsYXllcikpO1xuICAgIH1cblxuICAgIHJldHVybiBncm91cHM7XG59O1xuXG4vKlxuICogVGFrZSBhbGwgdGhlIHJ1bGVzIGFuZCBkZWNsYXJhdGlvbnMgZnJvbSB0aGUgc3R5bGVzaGVldCxcbiAqIGFuZCBmaWd1cmUgb3V0IHdoaWNoIGFwcGx5IGN1cnJlbnRseVxuICovXG5TdHlsZS5wcm90b3R5cGUuY2FzY2FkZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7XG4gICAgICAgIHRyYW5zaXRpb246IHRydWVcbiAgICB9O1xuXG4gICAgdmFyIGEsIGI7XG4gICAgdmFyIGlkO1xuICAgIHZhciBwcm9wO1xuICAgIHZhciBsYXllcjtcbiAgICB2YXIgY2xhc3NOYW1lO1xuICAgIHZhciBzdHlsZU5hbWU7XG4gICAgdmFyIHN0eWxlO1xuICAgIHZhciBzdHlsZVRyYW5zO1xuICAgIHZhciBjb25zdGFudHMgPSB0aGlzLnN0eWxlc2hlZXQuY29uc3RhbnRzO1xuXG4gICAgLy8gZGVyaXZlIGJ1Y2tldHMgZnJvbSBsYXllcnNcbiAgICB0aGlzLm9yZGVyZWRCdWNrZXRzID0gW107XG4gICAgdGhpcy5idWNrZXRzID0gZ2V0YnVja2V0cyh7fSwgdGhpcy5vcmRlcmVkQnVja2V0cywgdGhpcy5zdHlsZXNoZWV0LmxheWVycyk7XG4gICAgZnVuY3Rpb24gZ2V0YnVja2V0cyhidWNrZXRzLCBvcmRlcmVkLCBsYXllcnMpIHtcbiAgICAgICAgZm9yICh2YXIgYSA9IDA7IGEgPCBsYXllcnMubGVuZ3RoOyBhKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IGxheWVyc1thXTtcbiAgICAgICAgICAgIGlmIChsYXllci5sYXllcnMpIHtcbiAgICAgICAgICAgICAgICBidWNrZXRzID0gZ2V0YnVja2V0cyhidWNrZXRzLCBvcmRlcmVkLCBsYXllci5sYXllcnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFsYXllci5zb3VyY2UgfHwgIWxheWVyLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBidWNrZXQgPSB7IGlkOiBsYXllci5pZCB9O1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBsYXllcikge1xuICAgICAgICAgICAgICAgIGlmICgoL15zdHlsZS8pLnRlc3QocHJvcCkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGJ1Y2tldFtwcm9wXSA9IGxheWVyW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVja2V0LnJlbmRlciA9IFN0eWxlQ29uc3RhbnQucmVzb2x2ZShidWNrZXQucmVuZGVyLCBjb25zdGFudHMpO1xuICAgICAgICAgICAgYnVja2V0c1tsYXllci5pZF0gPSBidWNrZXQ7XG4gICAgICAgICAgICBvcmRlcmVkLnB1c2goYnVja2V0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYnVja2V0cztcbiAgICB9XG5cbiAgICAvLyBzdHlsZSBjbGFzcyBrZXlzXG4gICAgdmFyIHN0eWxlTmFtZXMgPSBbJ3N0eWxlJ107XG4gICAgZm9yIChjbGFzc05hbWUgaW4gdGhpcy5jbGFzc2VzKSBzdHlsZU5hbWVzLnB1c2goJ3N0eWxlLicgKyBjbGFzc05hbWUpO1xuXG4gICAgLy8gYXBwbHkgbGF5ZXIgZ3JvdXAgaW5oZXJpdGFuY2UgcmVzdWx0aW5nIGluIGEgZmxhdHRlbmVkIGFycmF5XG4gICAgdmFyIGZsYXR0ZW5lZCA9IGZsYXR0ZW5MYXllcnModGhpcy5zdHlsZXNoZWV0LmxheWVycyk7XG5cbiAgICAvLyBtYXAgbGF5ZXIgaWRzIHRvIGxheWVyIGRlZmluaXRpb25zIGZvciByZXNvbHZpbmcgcmVmc1xuICAgIHZhciBsYXllcm1hcCA9IHRoaXMubGF5ZXJtYXAgPSB7fTtcbiAgICBmb3IgKGEgPSAwOyBhIDwgZmxhdHRlbmVkLmxlbmd0aDsgYSsrKSB7XG4gICAgICAgIGxheWVyID0gZmxhdHRlbmVkW2FdO1xuXG4gICAgICAgIHZhciBuZXdMYXllciA9IHt9O1xuICAgICAgICBmb3IgKHZhciBrIGluIGxheWVyKSB7XG4gICAgICAgICAgICBpZiAoayA9PT0gJ2xheWVycycpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbmV3TGF5ZXJba10gPSBsYXllcltrXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxheWVybWFwW2xheWVyLmlkXSA9IG5ld0xheWVyO1xuICAgICAgICBmbGF0dGVuZWRbYV0gPSBuZXdMYXllcjtcbiAgICB9XG5cbiAgICBmb3IgKGEgPSAwOyBhIDwgZmxhdHRlbmVkLmxlbmd0aDsgYSsrKSB7XG4gICAgICAgIGZsYXR0ZW5lZFthXSA9IHJlc29sdmVMYXllcihsYXllcm1hcCwgZmxhdHRlbmVkW2FdKTtcbiAgICB9XG5cbiAgICAvLyBSZXNvbHZlIGxheWVyIHJlZmVyZW5jZXMuXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUxheWVyKGxheWVybWFwLCBsYXllcikge1xuICAgICAgICBpZiAoIWxheWVyLnJlZiB8fCAhbGF5ZXJtYXBbbGF5ZXIucmVmXSkgcmV0dXJuIGxheWVyO1xuXG4gICAgICAgIHZhciBwYXJlbnQgPSByZXNvbHZlTGF5ZXIobGF5ZXJtYXAsIGxheWVybWFwW2xheWVyLnJlZl0pO1xuICAgICAgICBsYXllci5yZW5kZXIgPSBwYXJlbnQucmVuZGVyO1xuICAgICAgICBsYXllci50eXBlID0gcGFyZW50LnR5cGU7XG4gICAgICAgIGxheWVyLmZpbHRlciA9IHBhcmVudC5maWx0ZXI7XG4gICAgICAgIGxheWVyLnNvdXJjZSA9IHBhcmVudC5zb3VyY2U7XG4gICAgICAgIGxheWVyWydzb3VyY2UtbGF5ZXInXSA9IHBhcmVudFsnc291cmNlLWxheWVyJ107XG4gICAgICAgIGxheWVyWydtaW4tem9vbSddID0gcGFyZW50WydtaW4tem9vbSddO1xuICAgICAgICBsYXllclsnbWF4LXpvb20nXSA9IHBhcmVudFsnbWF4LXpvb20nXTtcblxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuXG4gICAgLy8gRmxhdHRlbiBjb21wb3NpdGUgbGF5ZXIgc3RydWN0dXJlcy5cbiAgICBmdW5jdGlvbiBmbGF0dGVuTGF5ZXJzKGxheWVycykge1xuICAgICAgICB2YXIgZmxhdCA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZmxhdC5wdXNoKGxheWVyc1tpXSk7XG4gICAgICAgICAgICBpZiAobGF5ZXJzW2ldLmxheWVycykge1xuICAgICAgICAgICAgICAgIGZsYXQucHVzaC5hcHBseShmbGF0LCBmbGF0dGVuTGF5ZXJzKGxheWVyc1tpXS5sYXllcnMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmxhdDtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNpdGlvbnMgPSB7fTtcbiAgICB2YXIgZ2xvYmFsVHJhbnMgPSB0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbjtcblxuICAgIGZvciAoYSBpbiBmbGF0dGVuZWQpIHtcbiAgICAgICAgbGF5ZXIgPSBmbGF0dGVuZWRbYV07XG5cbiAgICAgICAgaWQgPSBsYXllci5pZDtcbiAgICAgICAgc3R5bGUgPSB7fTtcbiAgICAgICAgc3R5bGVUcmFucyA9IHt9O1xuXG4gICAgICAgIC8vIGJhc2ljIGNhc2NhZGluZyBvZiBzdHlsZXNcbiAgICAgICAgZm9yIChiID0gMDsgYiA8IHN0eWxlTmFtZXMubGVuZ3RoOyBiKyspIHtcbiAgICAgICAgICAgIHN0eWxlTmFtZSA9IHN0eWxlTmFtZXNbYl07XG4gICAgICAgICAgICBpZiAoIWxheWVyW3N0eWxlTmFtZV0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgLy8gc2V0IHN0eWxlIHByb3BlcnRpZXNcbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBsYXllcltzdHlsZU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb3AuaW5kZXhPZigndHJhbnNpdGlvbi0nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgc3R5bGVbcHJvcF0gPSBsYXllcltzdHlsZU5hbWVdW3Byb3BdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlVHJhbnNbcHJvcC5yZXBsYWNlKCd0cmFuc2l0aW9uLScsICcnKV0gPSBsYXllcltzdHlsZU5hbWVdW3Byb3BdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0eWxlID0gU3R5bGVDb25zdGFudC5yZXNvbHZlKHN0eWxlLCBjb25zdGFudHMpO1xuXG4gICAgICAgIHZhciByZW5kZXJUeXBlID0gbGF5ZXIudHlwZTtcbiAgICAgICAgdHJhbnNpdGlvbnNbaWRdID0ge307XG5cbiAgICAgICAgZm9yIChwcm9wIGluIHN0eWxlKSB7XG4gICAgICAgICAgICB2YXIgbmV3RGVjbGFyYXRpb24gPSBuZXcgU3R5bGVEZWNsYXJhdGlvbihyZW5kZXJUeXBlLCBwcm9wLCBzdHlsZVtwcm9wXSk7XG4gICAgICAgICAgICB2YXIgb2xkVHJhbnNpdGlvbiA9IHRoaXMudHJhbnNpdGlvbnNbaWRdICYmIHRoaXMudHJhbnNpdGlvbnNbaWRdW3Byb3BdO1xuICAgICAgICAgICAgdmFyIG5ld1N0eWxlVHJhbnMgPSB7fTtcbiAgICAgICAgICAgIG5ld1N0eWxlVHJhbnMuZHVyYXRpb24gPSBzdHlsZVRyYW5zW3Byb3BdICYmIHN0eWxlVHJhbnNbcHJvcF0uZHVyYXRpb24gPyBzdHlsZVRyYW5zW3Byb3BdLmR1cmF0aW9uIDogZ2xvYmFsVHJhbnMgJiYgZ2xvYmFsVHJhbnMuZHVyYXRpb24gPyBnbG9iYWxUcmFucy5kdXJhdGlvbiA6IDMwMDtcbiAgICAgICAgICAgIG5ld1N0eWxlVHJhbnMuZGVsYXkgPSBzdHlsZVRyYW5zW3Byb3BdICYmIHN0eWxlVHJhbnNbcHJvcF0uZGVsYXkgPyBzdHlsZVRyYW5zW3Byb3BdLmRlbGF5IDogZ2xvYmFsVHJhbnMgJiYgZ2xvYmFsVHJhbnMuZGVsYXkgPyBnbG9iYWxUcmFucy5kZWxheSA6IDA7XG5cbiAgICAgICAgICAgIGlmICghb3B0aW9ucy50cmFuc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgbmV3U3R5bGVUcmFucy5kdXJhdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgbmV3U3R5bGVUcmFucy5kZWxheSA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IHRyYW5zaXRpb24gaWYgdGhlIGRlY2xhcmF0aW9uIGNoYW5nZWRcbiAgICAgICAgICAgIGlmICghb2xkVHJhbnNpdGlvbiB8fCBvbGRUcmFuc2l0aW9uLmRlY2xhcmF0aW9uLmpzb24gIT09IG5ld0RlY2xhcmF0aW9uLmpzb24pIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IG5ldyBTdHlsZVRyYW5zaXRpb24obmV3RGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIG5ld1N0eWxlVHJhbnMpO1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25zW2lkXVtwcm9wXSA9IG5ld1RyYW5zaXRpb247XG5cbiAgICAgICAgICAgICAgICAvLyBSdW4gdGhlIGFuaW1hdGlvbiBsb29wIHVudGlsIHRoZSBlbmQgb2YgdGhlIHRyYW5zaXRpb25cbiAgICAgICAgICAgICAgICBpZiAoIW5ld1RyYW5zaXRpb24uaW5zdGFudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1RyYW5zaXRpb24ubG9vcElEID0gdGhpcy5hbmltYXRpb25Mb29wLnNldChuZXdUcmFuc2l0aW9uLmVuZFRpbWUgLSAobmV3IERhdGUoKSkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob2xkVHJhbnNpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3AuY2FuY2VsKG9sZFRyYW5zaXRpb24ubG9vcElEKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25zW2lkXVtwcm9wXSA9IG9sZFRyYW5zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnRyYW5zaXRpb25zID0gdHJhbnNpdGlvbnM7XG4gICAgdGhpcy5sYXllckdyb3VwcyA9IHRoaXMuX2dyb3VwTGF5ZXJzKHRoaXMuc3R5bGVzaGVldC5sYXllcnMpO1xuXG4gICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbn07XG5cbi8qIFRoaXMgc2hvdWxkIGJlIG1vdmVkIGVsc2V3aGVyZS4gTG9jYWxpemluZyByZXNvdXJjZXMgZG9lc24ndCBiZWxvbmcgaGVyZSAqL1xuU3R5bGUucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gbmV3IEltYWdlU3ByaXRlKHNwcml0ZSk7XG4gICAgdGhpcy5zcHJpdGUub24oJ2xvYWRlZCcsIHRoaXMuZmlyZS5iaW5kKHRoaXMsICdjaGFuZ2UnKSk7XG59O1xuXG4vLyBNb2RpZnkgY2xhc3Nlc1xuU3R5bGUucHJvdG90eXBlLmFkZENsYXNzID0gZnVuY3Rpb24obiwgb3B0aW9ucykge1xuICAgIGlmICh0aGlzLmNsYXNzZXNbbl0pIHJldHVybjsgLy8gcHJldmVudCB1bm5lY2Vzc2FyeSByZWNhbGN1bGF0aW9uXG4gICAgdGhpcy5jbGFzc2VzW25dID0gdHJ1ZTtcbiAgICB0aGlzLmNhc2NhZGUob3B0aW9ucyk7XG59O1xuXG5TdHlsZS5wcm90b3R5cGUucmVtb3ZlQ2xhc3MgPSBmdW5jdGlvbihuLCBvcHRpb25zKSB7XG4gICAgaWYgKCF0aGlzLmNsYXNzZXNbbl0pIHJldHVybjsgLy8gcHJldmVudCB1bm5lY2Vzc2FyeSByZWNhbGN1bGF0aW9uXG4gICAgZGVsZXRlIHRoaXMuY2xhc3Nlc1tuXTtcbiAgICB0aGlzLmNhc2NhZGUob3B0aW9ucyk7XG59O1xuXG5TdHlsZS5wcm90b3R5cGUuaGFzQ2xhc3MgPSBmdW5jdGlvbihuKSB7XG4gICAgcmV0dXJuICEhdGhpcy5jbGFzc2VzW25dO1xufTtcblxuU3R5bGUucHJvdG90eXBlLnNldENsYXNzTGlzdCA9IGZ1bmN0aW9uKGwsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmNsYXNzZXMgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGwubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5jbGFzc2VzW2xbaV1dID0gdHJ1ZTtcbiAgICB9XG4gICAgdGhpcy5jYXNjYWRlKG9wdGlvbnMpO1xufTtcblxuU3R5bGUucHJvdG90eXBlLmdldENsYXNzTGlzdCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLmNsYXNzZXMpO1xufTtcblxuU3R5bGUucHJvdG90eXBlLmdldExheWVyID0gZnVuY3Rpb24oaWQpIHtcbiAgICByZXR1cm4gdGhpcy5sYXllcm1hcFtpZF07XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cy5yZXNvbHZlID0gZnVuY3Rpb24gKHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIGlmICghY29uc3RhbnRzKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcblxuICAgIHZhciByZXN1bHQgPSB7fSwgaTtcblxuICAgIGZ1bmN0aW9uIHJlc29sdmUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWVbMF0gPT09ICdAJyA/IGNvbnN0YW50c1t2YWx1ZV0gOiB2YWx1ZTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gcHJvcGVydGllcykge1xuICAgICAgICB2YXIgdmFsdWUgPSByZXNvbHZlKHByb3BlcnRpZXNba2V5XSk7XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKCk7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZVtpXSBpbiBjb25zdGFudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVbaV0gPSByZXNvbHZlKHZhbHVlW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUuc3RvcHMpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdXRpbC5leHRlbmQoe30sIHZhbHVlKTtcbiAgICAgICAgICAgIHZhbHVlLnN0b3BzID0gdmFsdWUuc3RvcHMuc2xpY2UoKTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHZhbHVlLnN0b3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlLnN0b3BzW2ldWzFdIGluIGNvbnN0YW50cykge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuc3RvcHNbaV1bMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHZhbHVlLnN0b3BzW2ldWzFdKVxuICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsLmpzJyksXG4gICAgcmVmZXJlbmNlID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL3Y0JyksXG4gICAgcGFyc2VDU1NDb2xvciA9IHJlcXVpcmUoJ2Nzc2NvbG9ycGFyc2VyJykucGFyc2VDU1NDb2xvcjtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZURlY2xhcmF0aW9uO1xuXG4vKlxuICogQSBwYXJzZWQgcmVwcmVzZW50YXRpb24gb2YgYSBwcm9wZXJ0eTp2YWx1ZSBwYWlyXG4gKi9cbmZ1bmN0aW9uIFN0eWxlRGVjbGFyYXRpb24ocmVuZGVyVHlwZSwgcHJvcCwgdmFsdWUpIHtcbiAgICB2YXIgY2xhc3NOYW1lID0gJ2NsYXNzXycgKyByZW5kZXJUeXBlO1xuICAgIHZhciBwcm9wUmVmZXJlbmNlID0gcmVmZXJlbmNlW2NsYXNzTmFtZV0gJiYgcmVmZXJlbmNlW2NsYXNzTmFtZV1bcHJvcF07XG4gICAgaWYgKCFwcm9wUmVmZXJlbmNlKSByZXR1cm47XG5cbiAgICB0aGlzLnZhbHVlID0gdGhpcy5wYXJzZVZhbHVlKHZhbHVlLCBwcm9wUmVmZXJlbmNlLnR5cGUsIHByb3BSZWZlcmVuY2UudmFsdWVzKTtcbiAgICB0aGlzLnByb3AgPSBwcm9wO1xuICAgIHRoaXMudHlwZSA9IHByb3BSZWZlcmVuY2UudHlwZTtcblxuICAgIC8vIGltbXVhdGFibGUgcmVwcmVzZW50YXRpb24gb2YgdmFsdWUuIHVzZWQgZm9yIGNvbXBhcmlzb25cbiAgICB0aGlzLmpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbn1cblxuU3R5bGVEZWNsYXJhdGlvbi5wcm90b3R5cGUuY2FsY3VsYXRlID0gZnVuY3Rpb24oeikge1xuICAgIHJldHVybiB0eXBlb2YgdGhpcy52YWx1ZSA9PT0gJ2Z1bmN0aW9uJyA/IHRoaXMudmFsdWUoeikgOiB0aGlzLnZhbHVlO1xufTtcblxuU3R5bGVEZWNsYXJhdGlvbi5wcm90b3R5cGUucGFyc2VWYWx1ZSA9IGZ1bmN0aW9uKHZhbHVlLCB0eXBlLCB2YWx1ZXMpIHtcbiAgICBpZiAodHlwZSA9PT0gJ2NvbG9yJykge1xuICAgICAgICByZXR1cm4gcGFyc2VDb2xvcih2YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gcGFyc2VOdW1iZXIodmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHJldHVybiBCb29sZWFuKHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbWFnZScpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlTnVtYmVyQXJyYXkodmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2VudW0nICYmIEFycmF5LmlzQXJyYXkodmFsdWVzKSkge1xuICAgICAgICByZXR1cm4gdmFsdWVzLmluZGV4T2YodmFsdWUpID49IDAgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4odHlwZSArICcgaXMgbm90IGEgc3VwcG9ydGVkIHByb3BlcnR5IHR5cGUnKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBwYXJzZU51bWJlcihudW0pIHtcbiAgICBpZiAobnVtLnN0b3BzKSBudW0gPSBzdG9wc0ZuKG51bSk7XG4gICAgdmFyIHZhbHVlID0gK251bTtcbiAgICByZXR1cm4gIWlzTmFOKHZhbHVlKSA/IHZhbHVlIDogbnVtO1xufVxuXG5mdW5jdGlvbiBwYXJzZU51bWJlckFycmF5KGFycmF5KSB7XG4gICAgdmFyIHdpZHRocyA9IGFycmF5Lm1hcChwYXJzZU51bWJlcik7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oeikge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgd2lkdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh0eXBlb2Ygd2lkdGhzW2ldID09PSAnZnVuY3Rpb24nID8gd2lkdGhzW2ldKHopIDogd2lkdGhzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG59XG5cbnZhciBjb2xvckNhY2hlID0ge307XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3IodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc3RvcHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZS5zdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gc3RvcmUgdGhlIHBhcnNlZCBjb2xvciBhcyB0aGUgM3JkIGVsZW1lbnQgaW4gdGhlIGFycmF5XG4gICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXVsyXSA9IHBhcnNlQ1NTQ29sb3IodmFsdWUuc3RvcHNbaV1bMV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdG9wc0ZuKHZhbHVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBpZiAoY29sb3JDYWNoZVt2YWx1ZV0pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yQ2FjaGVbdmFsdWVdO1xuICAgIH1cbiAgICB2YXIgY29sb3IgPSBwcmVwYXJlQ29sb3IocGFyc2VDU1NDb2xvcih2YWx1ZSkpO1xuICAgIGNvbG9yQ2FjaGVbdmFsdWVdID0gY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBzdG9wc0ZuKHBhcmFtcywgY29sb3IpIHtcbiAgICB2YXIgc3RvcHMgPSBwYXJhbXMuc3RvcHM7XG4gICAgdmFyIGJhc2UgPSBwYXJhbXMuYmFzZSB8fCByZWZlcmVuY2UuZnVuY3Rpb24uYmFzZS5kZWZhdWx0O1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHopIHtcblxuICAgICAgICAvLyBmaW5kIHRoZSB0d28gc3RvcHMgd2hpY2ggdGhlIGN1cnJlbnQgeiBpcyBiZXR3ZWVuXG4gICAgICAgIHZhciBsb3cgPSBudWxsO1xuICAgICAgICB2YXIgaGlnaCA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzdG9wID0gc3RvcHNbaV07XG4gICAgICAgICAgICBpZiAoc3RvcFswXSA8PSB6KSBsb3cgPSBzdG9wO1xuICAgICAgICAgICAgaWYgKHN0b3BbMF0gPiB6KSB7XG4gICAgICAgICAgICAgICAgaGlnaCA9IHN0b3A7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobG93ICYmIGhpZ2gpIHtcbiAgICAgICAgICAgIHZhciB6b29tRGlmZiA9IGhpZ2hbMF0gLSBsb3dbMF07XG4gICAgICAgICAgICB2YXIgem9vbVByb2dyZXNzID0geiAtIGxvd1swXTtcbiAgICAgICAgICAgIHZhciB0ID0gMDtcbiAgICAgICAgICAgIGlmIChiYXNlID09IDEpIHtcbiAgICAgICAgICAgICAgICB0ID0gem9vbVByb2dyZXNzIC8gem9vbURpZmY7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHQgPSAoTWF0aC5wb3coYmFzZSwgem9vbVByb2dyZXNzKSAtIDEpIC8gKE1hdGgucG93KGJhc2UsIHpvb21EaWZmKSAtIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbG9yKSByZXR1cm4gcHJlcGFyZUNvbG9yKGludGVycENvbG9yKGxvd1syXSwgaGlnaFsyXSwgdCkpO1xuICAgICAgICAgICAgZWxzZSByZXR1cm4gdXRpbC5pbnRlcnAobG93WzFdLCBoaWdoWzFdLCB0KTtcblxuICAgICAgICB9IGVsc2UgaWYgKGxvdykge1xuICAgICAgICAgICAgaWYgKGNvbG9yKSByZXR1cm4gcHJlcGFyZUNvbG9yKGxvd1syXSk7XG4gICAgICAgICAgICBlbHNlIHJldHVybiBsb3dbMV07XG5cbiAgICAgICAgfSBlbHNlIGlmIChoaWdoKSB7XG4gICAgICAgICAgICBpZiAoY29sb3IpIHJldHVybiBwcmVwYXJlQ29sb3IoaGlnaFsyXSk7XG4gICAgICAgICAgICBlbHNlIHJldHVybiBoaWdoWzFdO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29sb3IpIHJldHVybiBbMCwgMCwgMCwgMV07XG4gICAgICAgICAgICBlbHNlIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcHJlcGFyZUNvbG9yKGMpIHtcbiAgICByZXR1cm4gW2NbMF0gLyAyNTUsIGNbMV0gLyAyNTUsIGNbMl0gLyAyNTUsIGNbM10gLyAxXTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwQ29sb3IoZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICB1dGlsLmludGVycChmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIHV0aWwuaW50ZXJwKGZyb21bMV0sIHRvWzFdLCB0KSxcbiAgICAgICAgdXRpbC5pbnRlcnAoZnJvbVsyXSwgdG9bMl0sIHQpLFxuICAgICAgICB1dGlsLmludGVycChmcm9tWzNdLCB0b1szXSwgdClcbiAgICBdO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlVHJhbnNpdGlvbjtcblxuLypcbiAqIFJlcHJlc2VudHMgYSB0cmFuc2l0aW9uIGJldHdlZW4gdHdvIGRlY2xhcmF0aW9uc1xuICovXG5mdW5jdGlvbiBTdHlsZVRyYW5zaXRpb24oZGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIHZhbHVlKSB7XG5cbiAgICB0aGlzLmRlY2xhcmF0aW9uID0gZGVjbGFyYXRpb247XG4gICAgdGhpcy5zdGFydFRpbWUgPSB0aGlzLmVuZFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgdmFyIHR5cGUgPSBkZWNsYXJhdGlvbi50eXBlO1xuICAgIGlmICh0eXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICB0aGlzLmludGVycCA9IHV0aWwuaW50ZXJwO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2NvbG9yJykge1xuICAgICAgICB0aGlzLmludGVycCA9IGludGVycENvbG9yO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICB0aGlzLmludGVycCA9IGludGVycE51bWJlckFycmF5O1xuICAgIH1cblxuICAgIHRoaXMub2xkVHJhbnNpdGlvbiA9IG9sZFRyYW5zaXRpb247XG4gICAgdGhpcy5kdXJhdGlvbiA9IHZhbHVlLmR1cmF0aW9uIHx8IDA7XG4gICAgdGhpcy5kZWxheSA9IHZhbHVlLmRlbGF5IHx8IDA7XG5cbiAgICBpZiAoIXRoaXMuaW5zdGFudCgpKSB7XG4gICAgICAgIHRoaXMuZW5kVGltZSA9IHRoaXMuc3RhcnRUaW1lICsgdGhpcy5kdXJhdGlvbiArIHRoaXMuZGVsYXk7XG4gICAgICAgIHRoaXMuZWFzZSA9IHV0aWwuZWFzZUN1YmljSW5PdXQ7XG4gICAgfVxuXG4gICAgaWYgKG9sZFRyYW5zaXRpb24gJiYgb2xkVHJhbnNpdGlvbi5lbmRUaW1lIDw9IHRoaXMuc3RhcnRUaW1lKSB7XG4gICAgICAgIC8vIE9sZCB0cmFuc2l0aW9uIGlzIGRvbmUgcnVubmluZywgc28gd2UgY2FuXG4gICAgICAgIC8vIGRlbGV0ZSBpdHMgcmVmZXJlbmNlIHRvIGl0cyBvbGQgdHJhbnNpdGlvbi5cblxuICAgICAgICBkZWxldGUgb2xkVHJhbnNpdGlvbi5vbGRUcmFuc2l0aW9uO1xuICAgIH1cbn1cblxuU3R5bGVUcmFuc2l0aW9uLnByb3RvdHlwZS5pbnN0YW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICF0aGlzLm9sZFRyYW5zaXRpb24gfHwgIXRoaXMuaW50ZXJwIHx8ICh0aGlzLmR1cmF0aW9uID09PSAwICYmIHRoaXMuZGVsYXkgPT09IDApO1xufTtcblxuLypcbiAqIFJldHVybiB0aGUgdmFsdWUgb2YgdGhlIHRyYW5zaXRpb25pbmcgcHJvcGVydHkgYXQgem9vbSBsZXZlbCBgemAgYW5kIG9wdGlvbmFsIHRpbWUgYHRgXG4gKi9cblN0eWxlVHJhbnNpdGlvbi5wcm90b3R5cGUuYXQgPSBmdW5jdGlvbih6LCB0KSB7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLmRlY2xhcmF0aW9uLmNhbGN1bGF0ZSh6KTtcblxuICAgIGlmICh0aGlzLmluc3RhbnQoKSkgcmV0dXJuIHZhbHVlO1xuXG4gICAgdCA9IHQgfHwgRGF0ZS5ub3coKTtcblxuICAgIGlmICh0IDwgdGhpcy5lbmRUaW1lKSB7XG4gICAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMub2xkVHJhbnNpdGlvbi5hdCh6LCB0aGlzLnN0YXJ0VGltZSk7XG4gICAgICAgIHZhciBlYXNlZCA9IHRoaXMuZWFzZSgodCAtIHRoaXMuc3RhcnRUaW1lIC0gdGhpcy5kZWxheSkgLyB0aGlzLmR1cmF0aW9uKTtcbiAgICAgICAgdmFsdWUgPSB0aGlzLmludGVycChvbGRWYWx1ZSwgdmFsdWUsIGVhc2VkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG5cbn07XG5cbmZ1bmN0aW9uIGludGVycE51bWJlckFycmF5KGZyb20sIHRvLCB0KSB7XG4gICAgcmV0dXJuIGZyb20ubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIHV0aWwuaW50ZXJwKGQsIHRvW2ldLCB0KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwQ29sb3IoZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICB1dGlsLmludGVycChmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIHV0aWwuaW50ZXJwKGZyb21bMV0sIHRvWzFdLCB0KSxcbiAgICAgICAgdXRpbC5pbnRlcnAoZnJvbVsyXSwgdG9bMl0sIHQpLFxuICAgICAgICB1dGlsLmludGVycChmcm9tWzNdLCB0b1szXSwgdClcbiAgICBdO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuY2hvcjtcblxuZnVuY3Rpb24gQW5jaG9yKHgsIHksIGFuZ2xlLCBzY2FsZSwgc2VnbWVudCkge1xuICAgIHRoaXMueCA9IHg7XG4gICAgdGhpcy55ID0geTtcbiAgICB0aGlzLmFuZ2xlID0gYW5nbGU7XG4gICAgdGhpcy5zY2FsZSA9IHNjYWxlO1xuXG4gICAgaWYgKHNlZ21lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50O1xuICAgIH1cbn1cblxuQW5jaG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoUG9pbnQucHJvdG90eXBlKTtcblxuQW5jaG9yLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgQW5jaG9yKHRoaXMueCwgdGhpcy55LCB0aGlzLmFuZ2xlLCB0aGlzLnNjYWxlLCB0aGlzLnNlZ21lbnQpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBCaW5QYWNrO1xuZnVuY3Rpb24gQmluUGFjayh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuZnJlZSA9IFt7IHg6IDAsIHk6IDAsIHc6IHdpZHRoLCBoOiBoZWlnaHQgfV07XG59XG5cbkJpblBhY2sucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbihyZWN0KSB7XG4gICAgLy8gU2ltcGxlIGFsZ29yaXRobSB0byByZWN1cnNpdmVseSBtZXJnZSB0aGUgbmV3bHkgcmVsZWFzZWQgY2VsbCB3aXRoIGl0c1xuICAgIC8vIG5laWdoYm9yLiBUaGlzIGRvZXNuJ3QgbWVyZ2UgbW9yZSB0aGFuIHR3byBjZWxscyBhdCBhIHRpbWUsIGFuZCBmYWlsc1xuICAgIC8vIGZvciBjb21wbGljYXRlZCBtZXJnZXMuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmZyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmZyZWVbaV07XG4gICAgICAgIGlmIChmcmVlLnkgPT0gcmVjdC55ICYmIGZyZWUuaCA9PSByZWN0LmggJiYgZnJlZS54ICsgZnJlZS53ID09IHJlY3QueCkge1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChmcmVlLnggPT0gcmVjdC54ICYmIGZyZWUudyA9PSByZWN0LncgJiYgZnJlZS55ICsgZnJlZS5oID09IHJlY3QueSkge1xuICAgICAgICAgICAgZnJlZS5oICs9IHJlY3QuaDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZWN0LnkgPT0gZnJlZS55ICYmIHJlY3QuaCA9PSBmcmVlLmggJiYgcmVjdC54ICsgcmVjdC53ID09IGZyZWUueCkge1xuICAgICAgICAgICAgZnJlZS54ID0gcmVjdC54O1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZWN0LnggPT0gZnJlZS54ICYmIHJlY3QudyA9PSBmcmVlLncgJiYgcmVjdC55ICsgcmVjdC5oID09IGZyZWUueSkge1xuICAgICAgICAgICAgZnJlZS55ID0gcmVjdC55O1xuICAgICAgICAgICAgZnJlZS5oICs9IHJlY3QuaDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5mcmVlLnNwbGljZShpLCAxKTtcbiAgICAgICAgdGhpcy5yZWxlYXNlKGZyZWUpO1xuICAgICAgICByZXR1cm47XG5cbiAgICB9XG4gICAgdGhpcy5mcmVlLnB1c2gocmVjdCk7XG59O1xuXG5CaW5QYWNrLnByb3RvdHlwZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAvLyBGaW5kIHRoZSBzbWFsbGVzdCBmcmVlIHJlY3QgYW5nbGVcbiAgICB2YXIgcmVjdCA9IHsgeDogSW5maW5pdHksIHk6IEluZmluaXR5LCB3OiBJbmZpbml0eSwgaDogSW5maW5pdHkgfTtcbiAgICB2YXIgc21hbGxlc3QgPSAtMTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZnJlZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmVmID0gdGhpcy5mcmVlW2ldO1xuICAgICAgICBpZiAod2lkdGggPD0gcmVmLncgJiYgaGVpZ2h0IDw9IHJlZi5oICYmIHJlZi55IDw9IHJlY3QueSAmJiByZWYueCA8PSByZWN0LngpIHtcbiAgICAgICAgICAgIHJlY3QgPSByZWY7XG4gICAgICAgICAgICBzbWFsbGVzdCA9IGk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc21hbGxlc3QgPCAwKSB7XG4gICAgICAgIC8vIFRoZXJlJ3Mgbm8gc3BhY2UgbGVmdCBmb3IgdGhpcyBjaGFyLlxuICAgICAgICByZXR1cm4geyB4OiAtMSwgeTogLTEgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmZyZWUuc3BsaWNlKHNtYWxsZXN0LCAxKTtcblxuICAgICAgICAvLyBTaG9ydGVyL0xvbmdlciBBeGlzIFNwbGl0IFJ1bGUgKFNBUylcbiAgICAgICAgLy8gaHR0cDovL2NsYi5kZW1vbi5maS9maWxlcy9SZWN0YW5nbGVCaW5QYWNrLnBkZiBwLiAxNVxuICAgICAgICAvLyBJZ25vcmUgdGhlIGRpbWVuc2lvbiBvZiBSIGFuZCBqdXN0IHNwbGl0IGxvbmcgdGhlIHNob3J0ZXIgZGltZW5zaW9uXG4gICAgICAgIC8vIFNlZSBBbHNvOiBodHRwOi8vd3d3LmNzLnByaW5jZXRvbi5lZHUvfmNoYXplbGxlL3B1YnMvYmxiaW5wYWNraW5nLnBkZlxuICAgICAgICBpZiAocmVjdC53IDwgcmVjdC5oKSB7XG4gICAgICAgICAgICAvLyBzcGxpdCBob3Jpem9udGFsbHlcbiAgICAgICAgICAgIC8vICstLSstLS0rXG4gICAgICAgICAgICAvLyB8X198X19ffCAgPC0tIGIxXG4gICAgICAgICAgICAvLyArLS0tLS0tKyAgPC0tIGIyXG4gICAgICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IGhlaWdodCB9KTtcbiAgICAgICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHJlY3QudywgaDogcmVjdC5oIC0gaGVpZ2h0IH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gc3BsaXQgdmVydGljYWxseVxuICAgICAgICAgICAgLy8gKy0tKy0tLStcbiAgICAgICAgICAgIC8vIHxfX3wgICB8IDwtLSBiMVxuICAgICAgICAgICAgLy8gKy0tfC0tLSsgPC0tIGIyXG4gICAgICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IHJlY3QuaCB9KTtcbiAgICAgICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHdpZHRoLCBoOiByZWN0LmggLSBoZWlnaHQgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyB4OiByZWN0LngsIHk6IHJlY3QueSwgdzogd2lkdGgsIGg6IGhlaWdodCB9O1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByYnVzaCA9IHJlcXVpcmUoJ3JidXNoJyksXG4gICAgcm90YXRpb25SYW5nZSA9IHJlcXVpcmUoJy4vcm90YXRpb25yYW5nZS5qcycpLFxuICAgIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb247XG5cbmZ1bmN0aW9uIENvbGxpc2lvbih6b29tLCB0aWxlRXh0ZW50LCB0aWxlU2l6ZSwgcGxhY2VtZW50RGVwdGgpIHtcbiAgICB0aGlzLmhUcmVlID0gcmJ1c2goKTsgLy8gdHJlZSBmb3IgaG9yaXpvbnRhbCBsYWJlbHNcbiAgICB0aGlzLmNUcmVlID0gcmJ1c2goKTsgLy8gdHJlZSBmb3IgZ2x5cGhzIGZyb20gY3VydmVkIGxhYmVsc1xuXG4gICAgLy8gdGlsZSBwaXhlbHMgcGVyIHNjcmVlbiBwaXhlbHMgYXQgdGhlIHRpbGUncyB6b29tIGxldmVsXG4gICAgdGhpcy50aWxlUGl4ZWxSYXRpbyA9IHRpbGVFeHRlbnQgLyB0aWxlU2l6ZTtcblxuICAgIHRoaXMuem9vbSA9IHpvb207XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIG1heGltdW0gc2NhbGUgd2UgY2FuIGdvIGRvd24gaW4gb3VyIGZha2UtM2QgcnRyZWUgc28gdGhhdFxuICAgIC8vIHBsYWNlbWVudCBzdGlsbCBtYWtlcyBzZW5zZS4gVGhpcyBpcyBjYWxjdWxhdGVkIHNvIHRoYXQgdGhlIG1pbmltdW1cbiAgICAvLyBwbGFjZW1lbnQgem9vbSBjYW4gYmUgYXQgbW9zdCAyNS41ICh3ZSB1c2UgYW4gdW5zaWduZWQgaW50ZWdlciB4MTAgdG9cbiAgICAvLyBzdG9yZSB0aGUgbWluaW11bSB6b29tKS5cbiAgICAvL1xuICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcGxhY2UgbGFiZWxzIGFsbCB0aGUgd2F5IHRvIDI1LjUuIFRoaXMgbGV0cyB0b28gbWFueVxuICAgIC8vIGdseXBocyBiZSBwbGFjZWQsIHNsb3dpbmcgZG93biBjb2xsaXNpb24gY2hlY2tpbmcuIE9ubHkgcGxhY2UgbGFiZWxzIGlmXG4gICAgLy8gdGhleSB3aWxsIHNob3cgdXAgd2l0aGluIHRoZSBpbnRlbmRlZCB6b29tIHJhbmdlIG9mIHRoZSB0aWxlLlxuICAgIHBsYWNlbWVudERlcHRoID0gTWF0aC5taW4oMywgcGxhY2VtZW50RGVwdGggfHwgMSwgMjUuNSAtIHRoaXMuem9vbSk7XG4gICAgdGhpcy5tYXhQbGFjZW1lbnRTY2FsZSA9IE1hdGguZXhwKE1hdGguTE4yICogcGxhY2VtZW50RGVwdGgpO1xuXG4gICAgdmFyIG0gPSA0MDk2O1xuICAgIHZhciBlZGdlID0gbSAqIHRoaXMudGlsZVBpeGVsUmF0aW8gKiAyO1xuXG4gICAgdmFyIGZ1bGxSYW5nZSA9IFtNYXRoLlBJICogMiwgMF07XG5cbiAgICB0aGlzLmxlZnQgPSB7XG4gICAgICAgIGFuY2hvcjogbmV3IFBvaW50KDAsIDApLFxuICAgICAgICBib3g6IHsgeDE6IC1lZGdlLCB5MTogLWVkZ2UsIHgyOiAwLCB5MjogZWRnZSB9LFxuICAgICAgICBwbGFjZW1lbnRSYW5nZTogZnVsbFJhbmdlLFxuICAgICAgICBwbGFjZW1lbnRTY2FsZTogMC41LFxuICAgICAgICBtYXhTY2FsZTogSW5maW5pdHksXG4gICAgICAgIHBhZGRpbmc6IDBcbiAgICB9O1xuXG4gICAgdGhpcy50b3AgPSB7XG4gICAgICAgIGFuY2hvcjogbmV3IFBvaW50KDAsIDApLFxuICAgICAgICBib3g6IHsgeDE6IC1lZGdlLCB5MTogLWVkZ2UsIHgyOiBlZGdlLCB5MjogMCB9LFxuICAgICAgICBwbGFjZW1lbnRSYW5nZTogZnVsbFJhbmdlLFxuICAgICAgICBwbGFjZW1lbnRTY2FsZTogMC41LFxuICAgICAgICBtYXhTY2FsZTogSW5maW5pdHksXG4gICAgICAgIHBhZGRpbmc6IDBcbiAgICB9O1xuXG4gICAgdGhpcy5ib3R0b20gPSB7XG4gICAgICAgIGFuY2hvcjogbmV3IFBvaW50KG0sIG0pLFxuICAgICAgICBib3g6IHsgeDE6IC1lZGdlLCB5MTogMCwgeDI6IGVkZ2UsIHkyOiBlZGdlIH0sXG4gICAgICAgIHBsYWNlbWVudFJhbmdlOiBmdWxsUmFuZ2UsXG4gICAgICAgIHBsYWNlbWVudFNjYWxlOiAwLjUsXG4gICAgICAgIG1heFNjYWxlOiBJbmZpbml0eSxcbiAgICAgICAgcGFkZGluZzogMFxuICAgIH07XG5cbiAgICB0aGlzLnJpZ2h0ID0ge1xuICAgICAgICBhbmNob3I6IG5ldyBQb2ludChtLCBtKSxcbiAgICAgICAgYm94OiB7IHgxOiAwLCB5MTogLWVkZ2UsIHgyOiBlZGdlLCB5MjogZWRnZSB9LFxuICAgICAgICBwbGFjZW1lbnRSYW5nZTogZnVsbFJhbmdlLFxuICAgICAgICBwbGFjZW1lbnRTY2FsZTogMC41LFxuICAgICAgICBtYXhTY2FsZTogSW5maW5pdHksXG4gICAgICAgIHBhZGRpbmc6IDBcbiAgICB9O1xuXG59XG5cbkNvbGxpc2lvbi5wcm90b3R5cGUuZ2V0UGxhY2VtZW50U2NhbGUgPSBmdW5jdGlvbihnbHlwaHMsIG1pblBsYWNlbWVudFNjYWxlLCBhdm9pZEVkZ2VzKSB7XG5cbiAgICB2YXIgbGVmdCA9IHRoaXMubGVmdDtcbiAgICB2YXIgcmlnaHQgPSB0aGlzLnJpZ2h0O1xuICAgIHZhciB0b3AgPSB0aGlzLnRvcDtcbiAgICB2YXIgYm90dG9tID0gdGhpcy5ib3R0b207XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGdseXBocy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBnbHlwaCA9IGdseXBoc1trXTtcbiAgICAgICAgdmFyIGJveCA9IGdseXBoLmJveDtcbiAgICAgICAgdmFyIGJib3ggPSBnbHlwaC5oQm94IHx8IGJveDtcbiAgICAgICAgdmFyIGFuY2hvciA9IGdseXBoLmFuY2hvcjtcbiAgICAgICAgdmFyIHBhZCA9IGdseXBoLnBhZGRpbmc7XG5cbiAgICAgICAgdmFyIG1pblNjYWxlID0gTWF0aC5tYXgobWluUGxhY2VtZW50U2NhbGUsIGdseXBoLm1pblNjYWxlKTtcbiAgICAgICAgdmFyIG1heFNjYWxlID0gZ2x5cGgubWF4U2NhbGUgfHwgSW5maW5pdHk7XG5cbiAgICAgICAgaWYgKG1pblNjYWxlID49IG1heFNjYWxlKSBjb250aW51ZTtcblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBzY2FsZWQgYm91bmRpbmcgYm94IG9mIHRoZSB1bnJvdGF0ZWQgZ2x5cGhcbiAgICAgICAgdmFyIHNlYXJjaEJveCA9IHRoaXMuZ2V0Qm94KGFuY2hvciwgYmJveCwgbWluU2NhbGUsIG1heFNjYWxlKTtcblxuICAgICAgICB2YXIgYmxvY2tpbmcgPSB0aGlzLmhUcmVlLnNlYXJjaChzZWFyY2hCb3gpLmNvbmNhdCh0aGlzLmNUcmVlLnNlYXJjaChzZWFyY2hCb3gpKTtcblxuICAgICAgICBpZiAoYXZvaWRFZGdlcykge1xuICAgICAgICAgICAgaWYgKHNlYXJjaEJveFswXSA8IDApIGJsb2NraW5nLnB1c2gobGVmdCk7XG4gICAgICAgICAgICBpZiAoc2VhcmNoQm94WzFdIDwgMCkgYmxvY2tpbmcucHVzaCh0b3ApO1xuICAgICAgICAgICAgaWYgKHNlYXJjaEJveFsyXSA+PSA0MDk2KSBibG9ja2luZy5wdXNoKHJpZ2h0KTtcbiAgICAgICAgICAgIGlmIChzZWFyY2hCb3hbM10gPj0gNDA5NikgYmxvY2tpbmcucHVzaChib3R0b20pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJsb2NraW5nLmxlbmd0aCkge1xuXG4gICAgICAgICAgICB2YXIgbmEgPSBhbmNob3I7IC8vIG5ldyBhbmNob3JcbiAgICAgICAgICAgIHZhciBuYiA9IGJveDsgLy8gbmV3IGJveFxuXG4gICAgICAgICAgICBmb3IgKHZhciBsID0gMDsgbCA8IGJsb2NraW5nLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9hID0gYmxvY2tpbmdbbF0uYW5jaG9yOyAvLyBvbGQgYW5jaG9yXG4gICAgICAgICAgICAgICAgdmFyIG9iID0gYmxvY2tpbmdbbF0uYm94OyAvLyBvbGQgYm94XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBhbmNob3JzIGFyZSBpZGVudGljYWwsIHdlJ3JlIGdvaW5nIHRvIHNraXAgdGhlIGxhYmVsLlxuICAgICAgICAgICAgICAgIC8vIE5PVEU6IHRoaXMgaXNuJ3QgcmlnaHQgYmVjYXVzZSB0aGVyZSBjYW4gYmUgZ2x5cGhzIHdpdGhcbiAgICAgICAgICAgICAgICAvLyB0aGUgc2FtZSBhbmNob3IgYnV0IGRpZmZlcmluZyBib3ggb2Zmc2V0cy5cbiAgICAgICAgICAgICAgICBpZiAobmEuZXF1YWxzKG9hKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyB0b2RvOiB1bmhhcmRjb2RlIHRoZSA4ID0gdGlsZUV4dGVudC90aWxlU2l6ZVxuICAgICAgICAgICAgICAgIHZhciBwYWRkaW5nID0gTWF0aC5tYXgocGFkLCBibG9ja2luZ1tsXS5wYWRkaW5nKSAqIDg7XG5cbiAgICAgICAgICAgICAgICAvLyBPcmlnaW5hbCBhbGdvcml0aG06XG4gICAgICAgICAgICAgICAgdmFyIHMxID0gKG9iLngxIC0gbmIueDIgLSBwYWRkaW5nKSAvIChuYS54IC0gb2EueCk7IC8vIHNjYWxlIGF0IHdoaWNoIG5ldyBib3ggaXMgdG8gdGhlIGxlZnQgb2Ygb2xkIGJveFxuICAgICAgICAgICAgICAgIHZhciBzMiA9IChvYi54MiAtIG5iLngxICsgcGFkZGluZykgLyAobmEueCAtIG9hLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSByaWdodCBvZiBvbGQgYm94XG4gICAgICAgICAgICAgICAgdmFyIHMzID0gKG9iLnkxIC0gbmIueTIgLSBwYWRkaW5nKSAvIChuYS55IC0gb2EueSk7IC8vIHNjYWxlIGF0IHdoaWNoIG5ldyBib3ggaXMgdG8gdGhlIHRvcCBvZiBvbGQgYm94XG4gICAgICAgICAgICAgICAgdmFyIHM0ID0gKG9iLnkyIC0gbmIueTEgKyBwYWRkaW5nKSAvIChuYS55IC0gb2EueSk7IC8vIHNjYWxlIGF0IHdoaWNoIG5ldyBib3ggaXMgdG8gdGhlIGJvdHRvbSBvZiBvbGQgYm94XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNOYU4oczEpIHx8IGlzTmFOKHMyKSkgczEgPSBzMiA9IDE7XG4gICAgICAgICAgICAgICAgaWYgKGlzTmFOKHMzKSB8fCBpc05hTihzNCkpIHMzID0gczQgPSAxO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvbGxpc2lvbkZyZWVTY2FsZSA9IE1hdGgubWluKE1hdGgubWF4KHMxLCBzMiksIE1hdGgubWF4KHMzLCBzNCkpO1xuXG4gICAgICAgICAgICAgICAgLy8gT25seSB1cGRhdGUgbGFiZWwncyBtaW4gc2NhbGUgaWYgdGhlIGdseXBoIHdhcyByZXN0cmljdGVkIGJ5IGEgY29sbGlzaW9uXG4gICAgICAgICAgICAgICAgaWYgKGNvbGxpc2lvbkZyZWVTY2FsZSA+IG1pblBsYWNlbWVudFNjYWxlICYmXG4gICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbkZyZWVTY2FsZSA+IG1pblNjYWxlICYmXG4gICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbkZyZWVTY2FsZSA8IG1heFNjYWxlICYmXG4gICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbkZyZWVTY2FsZSA8IGJsb2NraW5nW2xdLm1heFNjYWxlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1pblBsYWNlbWVudFNjYWxlID0gY29sbGlzaW9uRnJlZVNjYWxlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChtaW5QbGFjZW1lbnRTY2FsZSA+IHRoaXMubWF4UGxhY2VtZW50U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWluUGxhY2VtZW50U2NhbGU7XG59O1xuXG5Db2xsaXNpb24ucHJvdG90eXBlLmdldFBsYWNlbWVudFJhbmdlID0gZnVuY3Rpb24oZ2x5cGhzLCBwbGFjZW1lbnRTY2FsZSwgaG9yaXpvbnRhbCkge1xuXG4gICAgdmFyIHBsYWNlbWVudFJhbmdlID0gWzIqTWF0aC5QSSwgMF07XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGdseXBocy5sZW5ndGg7IGsrKykge1xuICAgICAgICB2YXIgZ2x5cGggPSBnbHlwaHNba107XG4gICAgICAgIHZhciBiYm94ID0gZ2x5cGguaEJveCB8fCBnbHlwaC5ib3g7XG4gICAgICAgIHZhciBhbmNob3IgPSBnbHlwaC5hbmNob3I7XG5cbiAgICAgICAgdmFyIG1pblBsYWNlZFggPSBhbmNob3IueCArIGJib3gueDEgLyBwbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgdmFyIG1pblBsYWNlZFkgPSBhbmNob3IueSArIGJib3gueTEgLyBwbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgdmFyIG1heFBsYWNlZFggPSBhbmNob3IueCArIGJib3gueDIgLyBwbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgdmFyIG1heFBsYWNlZFkgPSBhbmNob3IueSArIGJib3gueTIgLyBwbGFjZW1lbnRTY2FsZTtcblxuICAgICAgICB2YXIgc2VhcmNoQm94ID0gW21pblBsYWNlZFgsIG1pblBsYWNlZFksIG1heFBsYWNlZFgsIG1heFBsYWNlZFldO1xuXG4gICAgICAgIHZhciBibG9ja2luZyA9IHRoaXMuaFRyZWUuc2VhcmNoKHNlYXJjaEJveCk7XG5cbiAgICAgICAgaWYgKGhvcml6b250YWwpIHtcbiAgICAgICAgICAgIGJsb2NraW5nID0gYmxvY2tpbmcuY29uY2F0KHRoaXMuY1RyZWUuc2VhcmNoKHNlYXJjaEJveCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCBibG9ja2luZy5sZW5ndGg7IGwrKykge1xuICAgICAgICAgICAgdmFyIGIgPSBibG9ja2luZ1tsXTtcbiAgICAgICAgICAgIHZhciBiYm94MiA9IGIuaEJveCB8fCBiLmJveDtcblxuICAgICAgICAgICAgdmFyIHgxLCB4MiwgeTEsIHkyLCBpbnRlcnNlY3RYLCBpbnRlcnNlY3RZO1xuXG4gICAgICAgICAgICAvLyBBZGp1c3QgYW5kIGNvbXBhcmUgYmJveGVzIHRvIHNlZSBpZiB0aGUgZ2x5cGhzIG1pZ2h0IGludGVyc2VjdFxuICAgICAgICAgICAgaWYgKHBsYWNlbWVudFNjYWxlID4gYi5wbGFjZW1lbnRTY2FsZSkge1xuICAgICAgICAgICAgICAgIHgxID0gYi5hbmNob3IueCArIGJib3gyLngxIC8gcGxhY2VtZW50U2NhbGU7XG4gICAgICAgICAgICAgICAgeTEgPSBiLmFuY2hvci55ICsgYmJveDIueTEgLyBwbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgICAgICAgICB4MiA9IGIuYW5jaG9yLnggKyBiYm94Mi54MiAvIHBsYWNlbWVudFNjYWxlO1xuICAgICAgICAgICAgICAgIHkyID0gYi5hbmNob3IueSArIGJib3gyLnkyIC8gcGxhY2VtZW50U2NhbGU7XG4gICAgICAgICAgICAgICAgaW50ZXJzZWN0WCA9IHgxIDwgbWF4UGxhY2VkWCAmJiB4MiA+IG1pblBsYWNlZFg7XG4gICAgICAgICAgICAgICAgaW50ZXJzZWN0WSA9IHkxIDwgbWF4UGxhY2VkWSAmJiB5MiA+IG1pblBsYWNlZFk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHgxID0gYW5jaG9yLnggKyBiYm94LngxIC8gYi5wbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgICAgICAgICB5MSA9IGFuY2hvci55ICsgYmJveC55MSAvIGIucGxhY2VtZW50U2NhbGU7XG4gICAgICAgICAgICAgICAgeDIgPSBhbmNob3IueCArIGJib3gueDIgLyBiLnBsYWNlbWVudFNjYWxlO1xuICAgICAgICAgICAgICAgIHkyID0gYW5jaG9yLnkgKyBiYm94LnkyIC8gYi5wbGFjZW1lbnRTY2FsZTtcbiAgICAgICAgICAgICAgICBpbnRlcnNlY3RYID0geDEgPCBiWzJdICYmIHgyID4gYlswXTtcbiAgICAgICAgICAgICAgICBpbnRlcnNlY3RZID0geTEgPCBiWzNdICYmIHkyID4gYlsxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgdGhleSBjYW4ndCBpbnRlcnNlY3QsIHNraXAgbW9yZSBleHBlbnNpdmUgcm90YXRpb24gY2FsY3VsYXRpb25cbiAgICAgICAgICAgIGlmICghKGludGVyc2VjdFggJiYgaW50ZXJzZWN0WSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgc2NhbGUgPSBNYXRoLm1heChwbGFjZW1lbnRTY2FsZSwgYi5wbGFjZW1lbnRTY2FsZSk7XG4gICAgICAgICAgICB2YXIgcmFuZ2UgPSByb3RhdGlvblJhbmdlLnJvdGF0aW9uUmFuZ2UoZ2x5cGgsIGIsIHNjYWxlKTtcblxuICAgICAgICAgICAgcGxhY2VtZW50UmFuZ2VbMF0gPSBNYXRoLm1pbihwbGFjZW1lbnRSYW5nZVswXSwgcmFuZ2VbMF0pO1xuICAgICAgICAgICAgcGxhY2VtZW50UmFuZ2VbMV0gPSBNYXRoLm1heChwbGFjZW1lbnRSYW5nZVsxXSwgcmFuZ2VbMV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBsYWNlbWVudFJhbmdlO1xuXG59O1xuXG4vLyBJbnNlcnQgZ2x5cGggcGxhY2VtZW50cyBpbnRvIHJ0cmVlLlxuQ29sbGlzaW9uLnByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbihnbHlwaHMsIGFuY2hvciwgcGxhY2VtZW50U2NhbGUsIHBsYWNlbWVudFJhbmdlLCBob3Jpem9udGFsKSB7XG5cbiAgICB2YXIgYWxsQm91bmRzID0gW107XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGdseXBocy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBnbHlwaCA9IGdseXBoc1trXTtcbiAgICAgICAgdmFyIGJib3ggPSBnbHlwaC5oQm94IHx8IGdseXBoLmJveDtcblxuICAgICAgICB2YXIgbWluU2NhbGUgPSBNYXRoLm1heChwbGFjZW1lbnRTY2FsZSwgZ2x5cGgubWluU2NhbGUpO1xuICAgICAgICB2YXIgbWF4U2NhbGUgPSBnbHlwaC5tYXhTY2FsZSB8fCBJbmZpbml0eTtcblxuICAgICAgICB2YXIgYm91bmRzID0gdGhpcy5nZXRCb3goYW5jaG9yLCBiYm94LCBtaW5TY2FsZSwgbWF4U2NhbGUpO1xuXG4gICAgICAgIGJvdW5kcy5hbmNob3IgPSBhbmNob3I7XG4gICAgICAgIGJvdW5kcy5ib3ggPSBnbHlwaC5ib3g7XG4gICAgICAgIGlmIChnbHlwaC5oQm94KSBib3VuZHMuaEJveCA9IGJib3g7XG4gICAgICAgIGJvdW5kcy5wbGFjZW1lbnRSYW5nZSA9IHBsYWNlbWVudFJhbmdlO1xuICAgICAgICBib3VuZHMucGxhY2VtZW50U2NhbGUgPSBtaW5TY2FsZTtcbiAgICAgICAgYm91bmRzLm1heFNjYWxlID0gbWF4U2NhbGU7XG4gICAgICAgIGJvdW5kcy5wYWRkaW5nID0gZ2x5cGgucGFkZGluZztcblxuICAgICAgICBhbGxCb3VuZHMucHVzaChib3VuZHMpO1xuICAgIH1cblxuICAgIChob3Jpem9udGFsID8gdGhpcy5oVHJlZSA6IHRoaXMuY1RyZWUpLmxvYWQoYWxsQm91bmRzKTtcbn07XG5cbkNvbGxpc2lvbi5wcm90b3R5cGUuZ2V0Qm94ID0gZnVuY3Rpb24oYW5jaG9yLCBiYm94LCBtaW5TY2FsZSwgbWF4U2NhbGUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBhbmNob3IueCArIE1hdGgubWluKGJib3gueDEgLyBtaW5TY2FsZSwgYmJveC54MSAvIG1heFNjYWxlKSxcbiAgICAgICAgYW5jaG9yLnkgKyBNYXRoLm1pbihiYm94LnkxIC8gbWluU2NhbGUsIGJib3gueTEgLyBtYXhTY2FsZSksXG4gICAgICAgIGFuY2hvci54ICsgTWF0aC5tYXgoYmJveC54MiAvIG1pblNjYWxlLCBiYm94LngyIC8gbWF4U2NhbGUpLFxuICAgICAgICBhbmNob3IueSArIE1hdGgubWF4KGJib3gueTIgLyBtaW5TY2FsZSwgYmJveC55MiAvIG1heFNjYWxlKV07XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmluUGFjayA9IHJlcXVpcmUoJy4vYmlucGFjay5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoQXRsYXM7XG5mdW5jdGlvbiBHbHlwaEF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW5kZXggPSB7fTtcbiAgICB0aGlzLmlkcyA9IHt9O1xuICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbn1cblxuR2x5cGhBdGxhcy5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGRlYnVnKCkge1xuICAgICAgICByZXR1cm4gJ2NhbnZhcycgaW4gdGhpcztcbiAgICB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgJiYgIXRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuZ2V0R2x5cGhzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdseXBocyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghZ2x5cGhzW25hbWVdKSBnbHlwaHNbbmFtZV0gPSBbXTtcbiAgICAgICAgZ2x5cGhzW25hbWVdLnB1c2goaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBnbHlwaHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5nZXRSZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWN0cyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghcmVjdHNbbmFtZV0pIHJlY3RzW25hbWVdID0ge307XG4gICAgICAgIHJlY3RzW25hbWVdW2lkXSA9IHRoaXMuaW5kZXhba2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5yZW1vdmVHbHlwaHMgPSBmdW5jdGlvbihpZCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmlkcykge1xuXG4gICAgICAgIHZhciBpZHMgPSB0aGlzLmlkc1trZXldO1xuXG4gICAgICAgIHZhciBwb3MgPSBpZHMuaW5kZXhPZihpZCk7XG4gICAgICAgIGlmIChwb3MgPj0gMCkgaWRzLnNwbGljZShwb3MsIDEpO1xuICAgICAgICB0aGlzLmlkc1trZXldID0gaWRzO1xuXG4gICAgICAgIGlmICghaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHJlY3QgPSB0aGlzLmluZGV4W2tleV07XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHJlY3QuaDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5KSArIHJlY3QueDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHJlY3QudzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmJpbi5yZWxlYXNlKHJlY3QpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pbmRleFtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWRzW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHRoaXMudXBkYXRlVGV4dHVyZSh0aGlzLmdsKTtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmFkZEdseXBoID0gZnVuY3Rpb24oaWQsIG5hbWUsIGdseXBoLCBidWZmZXIpIHtcbiAgICBpZiAoIWdseXBoKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignbWlzc2luZyBnbHlwaCcsIGNvZGUsIFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIGtleSA9IG5hbWUgKyBcIiNcIiArIGdseXBoLmlkO1xuXG4gICAgLy8gVGhlIGdseXBoIGlzIGFscmVhZHkgaW4gdGhpcyB0ZXh0dXJlLlxuICAgIGlmICh0aGlzLmluZGV4W2tleV0pIHtcbiAgICAgICAgaWYgKHRoaXMuaWRzW2tleV0uaW5kZXhPZihpZCkgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmlkc1trZXldLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZGV4W2tleV07XG4gICAgfVxuXG4gICAgLy8gVGhlIGdseXBoIGJpdG1hcCBoYXMgemVybyB3aWR0aC5cbiAgICBpZiAoIWdseXBoLmJpdG1hcCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYnVmZmVyZWRfd2lkdGggPSBnbHlwaC53aWR0aCArIGJ1ZmZlciAqIDI7XG4gICAgdmFyIGJ1ZmZlcmVkX2hlaWdodCA9IGdseXBoLmhlaWdodCArIGJ1ZmZlciAqIDI7XG5cbiAgICAvLyBBZGQgYSAxcHggYm9yZGVyIGFyb3VuZCBldmVyeSBpbWFnZS5cbiAgICB2YXIgcGFja193aWR0aCA9IGJ1ZmZlcmVkX3dpZHRoO1xuICAgIHZhciBwYWNrX2hlaWdodCA9IGJ1ZmZlcmVkX2hlaWdodDtcblxuICAgIC8vIEluY3JlYXNlIHRvIG5leHQgbnVtYmVyIGRpdmlzaWJsZSBieSA0LCBidXQgYXQgbGVhc3QgMS5cbiAgICAvLyBUaGlzIGlzIHNvIHdlIGNhbiBzY2FsZSBkb3duIHRoZSB0ZXh0dXJlIGNvb3JkaW5hdGVzIGFuZCBwYWNrIHRoZW1cbiAgICAvLyBpbnRvIDIgYnl0ZXMgcmF0aGVyIHRoYW4gNCBieXRlcy5cbiAgICBwYWNrX3dpZHRoICs9ICg0IC0gcGFja193aWR0aCAlIDQpO1xuICAgIHBhY2tfaGVpZ2h0ICs9ICg0IC0gcGFja19oZWlnaHQgJSA0KTtcblxuICAgIHZhciByZWN0ID0gdGhpcy5iaW4uYWxsb2NhdGUocGFja193aWR0aCwgcGFja19oZWlnaHQpO1xuICAgIGlmIChyZWN0LnggPCAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignZ2x5cGggYml0bWFwIG92ZXJmbG93Jyk7XG4gICAgICAgIHJldHVybiB7IGdseXBoOiBnbHlwaCwgcmVjdDogbnVsbCB9O1xuICAgIH1cblxuICAgIC8vIEFkZCBsZWZ0IGFuZCB0b3AgZ2x5cGggb2Zmc2V0cyB0byByZWN0LlxuICAgIHJlY3QubCA9IGdseXBoLmxlZnQ7XG4gICAgcmVjdC50ID0gZ2x5cGgudG9wO1xuXG4gICAgdGhpcy5pbmRleFtrZXldID0gcmVjdDtcbiAgICB0aGlzLmlkc1trZXldID0gW2lkXTtcblxuICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgdmFyIHNvdXJjZSA9IGdseXBoLmJpdG1hcDtcbiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGJ1ZmZlcmVkX2hlaWdodDsgeSsrKSB7XG4gICAgICAgIHZhciB5MSA9IHRoaXMud2lkdGggKiAocmVjdC55ICsgeSkgKyByZWN0Lng7XG4gICAgICAgIHZhciB5MiA9IGJ1ZmZlcmVkX3dpZHRoICogeTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBidWZmZXJlZF93aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICB0YXJnZXRbeTEgKyB4XSA9IHNvdXJjZVt5MiArIHhdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5kaXJ0eSA9IHRydWU7XG5cbiAgICByZXR1cm4gcmVjdDtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihnbCkge1xuICAgIHRoaXMuZ2wgPSBnbDtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1QsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLkFMUEhBLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCwgMCwgZ2wuQUxQSEEsIGdsLlVOU0lHTkVEX0JZVEUsIG51bGwpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICB9XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS51cGRhdGVUZXh0dXJlID0gZnVuY3Rpb24oZ2wpIHtcbiAgICB0aGlzLmJpbmQoZ2wpO1xuICAgIGlmICh0aGlzLmRpcnR5KSB7XG5cbiAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCAwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCwgZ2wuQUxQSEEsIGdsLlVOU0lHTkVEX0JZVEUsIHRoaXMuZGF0YSk7XG5cbiAgICAgICAgLy8gREVCVUdcbiAgICAgICAgaWYgKHRoaXMuY3R4KSB7XG4gICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuY3R4LmdldEltYWdlRGF0YSgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyssIGogKz0gNCkge1xuICAgICAgICAgICAgICAgIGRhdGEuZGF0YVtqXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaisxXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaisyXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaiszXSA9IDI1NTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY3R4LnB1dEltYWdlRGF0YShkYXRhLCAwLCAwKTtcblxuICAgICAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSAncmVkJztcbiAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGhpcy5iaW4uZnJlZS5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gdGhpcy5iaW4uZnJlZVtrXTtcbiAgICAgICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VSZWN0KGZyZWUueCwgZnJlZS55LCBmcmVlLncsIGZyZWUuaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRU5EIERFQlVHXG5cbiAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnZXRBcnJheUJ1ZmZlciA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheC5qcycpLmdldEFycmF5QnVmZmVyO1xudmFyIEdseXBocyA9IHJlcXVpcmUoJy4uL3V0aWwvZ2x5cGhzLmpzJyk7XG52YXIgUHJvdG9idWYgPSByZXF1aXJlKCdwYmYnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFNvdXJjZTtcblxuZnVuY3Rpb24gR2x5cGhTb3VyY2UodXJsLCBnbHlwaEF0bGFzKSB7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gICAgdGhpcy5nbHlwaEF0bGFzID0gZ2x5cGhBdGxhcztcbiAgICB0aGlzLnN0YWNrcyA9IHt9O1xuICAgIHRoaXMubG9hZGluZyA9IHt9O1xufVxuXG5HbHlwaFNvdXJjZS5wcm90b3R5cGUuZ2V0UmVjdHMgPSBmdW5jdGlvbihmb250c3RhY2ssIGdseXBoSURzLCB0aWxlSUQsIGNhbGxiYWNrKSB7XG5cbiAgICBpZiAodGhpcy5zdGFja3NbZm9udHN0YWNrXSA9PT0gdW5kZWZpbmVkKSB0aGlzLnN0YWNrc1tmb250c3RhY2tdID0ge307XG5cbiAgICB2YXIgcmVjdHMgPSB7fTtcbiAgICB2YXIgZ2x5cGhzID0ge307XG4gICAgdmFyIHJlc3VsdCA9IHsgcmVjdHM6IHJlY3RzLCBnbHlwaHM6IGdseXBocyB9O1xuXG4gICAgdmFyIHN0YWNrID0gdGhpcy5zdGFja3NbZm9udHN0YWNrXTtcbiAgICB2YXIgZ2x5cGhBdGxhcyA9IHRoaXMuZ2x5cGhBdGxhcztcblxuICAgIHZhciBtaXNzaW5nID0ge307XG4gICAgdmFyIHJlbWFpbmluZyA9IDA7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdseXBoSURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnbHlwaElEID0gZ2x5cGhJRHNbaV07XG4gICAgICAgIHZhciByYW5nZSA9IE1hdGguZmxvb3IoZ2x5cGhJRCAvIDI1Nik7XG5cbiAgICAgICAgaWYgKHN0YWNrW3JhbmdlXSkge1xuICAgICAgICAgICAgdmFyIGdseXBoID0gc3RhY2tbcmFuZ2VdLmdseXBoc1tnbHlwaElEXTtcbiAgICAgICAgICAgIHZhciBidWZmZXIgPSAzO1xuICAgICAgICAgICAgcmVjdHNbZ2x5cGhJRF0gPSBnbHlwaEF0bGFzLmFkZEdseXBoKHRpbGVJRCwgZm9udHN0YWNrLCBnbHlwaCwgYnVmZmVyKTtcbiAgICAgICAgICAgIGlmIChnbHlwaCkgZ2x5cGhzW2dseXBoSURdID0gc2ltcGxlR2x5cGgoZ2x5cGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKG1pc3NpbmdbcmFuZ2VdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nW3JhbmdlXSA9IFtdO1xuICAgICAgICAgICAgICAgIHJlbWFpbmluZysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWlzc2luZ1tyYW5nZV0ucHVzaChnbHlwaElEKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIHJlc3VsdCk7XG5cbiAgICB2YXIgZ2x5cGhTb3VyY2UgPSB0aGlzO1xuICAgIGZvciAodmFyIHIgaW4gbWlzc2luZykge1xuICAgICAgICB0aGlzLmxvYWRSYW5nZShmb250c3RhY2ssIHIsIG9uUmFuZ2VMb2FkZWQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uUmFuZ2VMb2FkZWQoZXJyLCByYW5nZSwgZGF0YSkge1xuICAgICAgICAvLyBUT0RPIG5vdCBiZSBzaWxlbnQgYWJvdXQgZXJyb3JzXG4gICAgICAgIGlmICghZXJyKSB7XG4gICAgICAgICAgICB2YXIgc3RhY2sgPSBnbHlwaFNvdXJjZS5zdGFja3NbZm9udHN0YWNrXVtyYW5nZV0gPSBkYXRhLnN0YWNrc1tmb250c3RhY2tdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtaXNzaW5nW3JhbmdlXS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBnbHlwaElEID0gbWlzc2luZ1tyYW5nZV1baV07XG4gICAgICAgICAgICAgICAgdmFyIGdseXBoID0gc3RhY2suZ2x5cGhzW2dseXBoSURdO1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSAzO1xuICAgICAgICAgICAgICAgIHJlY3RzW2dseXBoSURdID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh0aWxlSUQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKGdseXBoKSBnbHlwaHNbZ2x5cGhJRF0gPSBzaW1wbGVHbHlwaChnbHlwaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIHJlc3VsdCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gc2ltcGxlR2x5cGgoZ2x5cGgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBhZHZhbmNlOiBnbHlwaC5hZHZhbmNlLFxuICAgICAgICBsZWZ0OiBnbHlwaC5sZWZ0LFxuICAgICAgICB0b3A6IGdseXBoLnRvcFxuICAgIH07XG59XG5cbkdseXBoU291cmNlLnByb3RvdHlwZS5sb2FkUmFuZ2UgPSBmdW5jdGlvbihmb250c3RhY2ssIHJhbmdlLCBjYWxsYmFjaykge1xuXG4gICAgaWYgKHJhbmdlICogMjU2ID49IDY1MjgwKSByZXR1cm4gY2FsbGJhY2soJ2d5cGhzID4gNjUyODAgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgaWYgKHRoaXMubG9hZGluZ1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMubG9hZGluZ1tmb250c3RhY2tdID0ge307XG4gICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbZm9udHN0YWNrXTtcblxuICAgIGlmIChsb2FkaW5nW3JhbmdlXSkge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXSA9IFtjYWxsYmFja107XG5cbiAgICAgICAgdmFyIHJhbmdlTmFtZSA9IChyYW5nZSAqIDI1NikgKyAnLScgKyAocmFuZ2UgKiAyNTYgKyAyNTUpO1xuICAgICAgICB2YXIgdXJsID0gZ2x5cGhVcmwoZm9udHN0YWNrLCByYW5nZU5hbWUsIHRoaXMudXJsKTtcblxuICAgICAgICBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgdmFyIGdseXBocyA9ICFlcnIgJiYgbmV3IEdseXBocyhuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1tyYW5nZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2FkaW5nW3JhbmdlXVtpXShlcnIsIHJhbmdlLCBnbHlwaHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGxvYWRpbmdbcmFuZ2VdO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnbHlwaFVybChmb250c3RhY2ssIHJhbmdlLCB1cmwsIHN1YmRvbWFpbnMpIHtcbiAgICBzdWJkb21haW5zID0gc3ViZG9tYWlucyB8fCAnYWJjJztcblxuICAgIHJldHVybiB1cmxcbiAgICAgICAgLnJlcGxhY2UoJ3tzfScsIHN1YmRvbWFpbnNbZm9udHN0YWNrLmxlbmd0aCAlIHN1YmRvbWFpbnMubGVuZ3RoXSlcbiAgICAgICAgLnJlcGxhY2UoJ3tmb250c3RhY2t9JywgZm9udHN0YWNrKVxuICAgICAgICAucmVwbGFjZSgne3JhbmdlfScsIHJhbmdlKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwuanMnKSxcbiAgICBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGU7XG5cbnZhciBtaW5TY2FsZSA9IDAuNTtcbnZhciBtaW5TY2FsZUFycmF5cyA9IHtcbiAgICAxOiBbbWluU2NhbGVdLFxuICAgIDI6IFttaW5TY2FsZSwgMl0sXG4gICAgNDogW21pblNjYWxlLCA0LCAyLCA0XSxcbiAgICA4OiBbbWluU2NhbGUsIDgsIDQsIDgsIDIsIDgsIDQsIDhdXG59O1xuXG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKHZlcnRpY2VzLCBzcGFjaW5nLCBtaW5TY2FsZSwgbWF4U2NhbGUsIHRpbGVQaXhlbFJhdGlvLCBzdGFydCkge1xuXG4gICAgaWYgKG1pblNjYWxlID09PSB1bmRlZmluZWQpIG1pblNjYWxlID0gMDtcblxuICAgIG1heFNjYWxlID0gTWF0aC5yb3VuZChNYXRoLm1heChNYXRoLm1pbig4LCBtYXhTY2FsZSAvIDIpLCAxKSk7XG4gICAgc3BhY2luZyAqPSB0aWxlUGl4ZWxSYXRpbyAvIG1heFNjYWxlO1xuICAgIHZhciBtaW5TY2FsZXMgPSBtaW5TY2FsZUFycmF5c1ttYXhTY2FsZV07XG4gICAgdmFyIGxlbiA9IG1pblNjYWxlcy5sZW5ndGg7XG5cbiAgICB2YXIgZGlzdGFuY2UgPSAwLFxuICAgICAgICBtYXJrZWREaXN0YW5jZSA9IDAsXG4gICAgICAgIGFkZGVkID0gc3RhcnQgfHwgMDtcblxuICAgIHZhciBwb2ludHMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoIC0gMTsgaSsrKSB7XG5cbiAgICAgICAgdmFyIGEgPSB2ZXJ0aWNlc1tpXSxcbiAgICAgICAgICAgIGIgPSB2ZXJ0aWNlc1tpICsgMV07XG5cbiAgICAgICAgdmFyIHNlZ21lbnREaXN0ID0gYS5kaXN0KGIpLFxuICAgICAgICAgICAgYW5nbGUgPSBiLmFuZ2xlVG8oYSk7XG5cbiAgICAgICAgd2hpbGUgKG1hcmtlZERpc3RhbmNlICsgc3BhY2luZyA8IGRpc3RhbmNlICsgc2VnbWVudERpc3QpIHtcbiAgICAgICAgICAgIG1hcmtlZERpc3RhbmNlICs9IHNwYWNpbmc7XG5cbiAgICAgICAgICAgIHZhciB0ID0gKG1hcmtlZERpc3RhbmNlIC0gZGlzdGFuY2UpIC8gc2VnbWVudERpc3QsXG4gICAgICAgICAgICAgICAgeCA9IHV0aWwuaW50ZXJwKGEueCwgYi54LCB0KSxcbiAgICAgICAgICAgICAgICB5ID0gdXRpbC5pbnRlcnAoYS55LCBiLnksIHQpLFxuICAgICAgICAgICAgICAgIHMgPSBtaW5TY2FsZXNbYWRkZWQgJSBsZW5dO1xuXG4gICAgICAgICAgICBpZiAoeCA+PSAwICYmIHggPCA0MDk2ICYmIHkgPj0gMCAmJiB5IDwgNDA5Nikge1xuICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKG5ldyBBbmNob3IoeCwgeSwgYW5nbGUsIHMsIGkpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYWRkZWQrKztcbiAgICAgICAgfVxuXG4gICAgICAgIGRpc3RhbmNlICs9IHNlZ21lbnREaXN0O1xuICAgIH1cblxuICAgIHJldHVybiBwb2ludHM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEljb246IGdldEljb24sXG4gICAgZ2V0R2x5cGhzOiBnZXRHbHlwaHNcbn07XG5cbnZhciBtaW5TY2FsZSA9IDAuNTsgLy8gdW5kZXJzY2FsZSBieSAxIHpvb20gbGV2ZWxcblxuZnVuY3Rpb24gZ2V0SWNvbihhbmNob3IsIGltYWdlLCBib3hTY2FsZSwgbGluZSwgcHJvcHMpIHtcblxuICAgIHZhciB4ID0gaW1hZ2Uud2lkdGggLyAyIC8gaW1hZ2UucGl4ZWxSYXRpbztcbiAgICB2YXIgeSA9IGltYWdlLmhlaWdodCAvIDIgLyBpbWFnZS5waXhlbFJhdGlvO1xuXG4gICAgdmFyIGR4ID0gcHJvcHNbJ2ljb24tb2Zmc2V0J11bMF07XG4gICAgdmFyIGR5ID0gcHJvcHNbJ2ljb24tb2Zmc2V0J11bMV07XG4gICAgdmFyIHgxID0gKGR4IC0geCk7XG4gICAgdmFyIHgyID0gKGR4ICsgeCk7XG4gICAgdmFyIHkxID0gKGR5IC0geSk7XG4gICAgdmFyIHkyID0gKGR5ICsgeSk7XG5cbiAgICB2YXIgdGwgPSBuZXcgUG9pbnQoeDEsIHkxKTtcbiAgICB2YXIgdHIgPSBuZXcgUG9pbnQoeDIsIHkxKTtcbiAgICB2YXIgYnIgPSBuZXcgUG9pbnQoeDIsIHkyKTtcbiAgICB2YXIgYmwgPSBuZXcgUG9pbnQoeDEsIHkyKTtcblxuICAgIHZhciBhbmdsZSA9IHByb3BzWydpY29uLXJvdGF0ZSddICogTWF0aC5QSSAvIDE4MDtcbiAgICBpZiAoYW5jaG9yLnNlZ21lbnQgIT09IHVuZGVmaW5lZCAmJiBwcm9wc1snaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSAhPT0gJ3ZpZXdwb3J0Jykge1xuICAgICAgICB2YXIgbmV4dCA9IGxpbmVbYW5jaG9yLnNlZ21lbnRdO1xuICAgICAgICBhbmdsZSArPSAtTWF0aC5hdGFuMihuZXh0LnggLSBhbmNob3IueCwgbmV4dC55IC0gYW5jaG9yLnkpICsgTWF0aC5QSSAvIDI7XG4gICAgfVxuXG4gICAgaWYgKGFuZ2xlKSB7XG4gICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICBjb3MgPSBNYXRoLmNvcyhhbmdsZSksXG4gICAgICAgICAgICBtYXRyaXggPSBbY29zLCAtc2luLCBzaW4sIGNvc107XG5cbiAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgIHRyID0gdHIubWF0TXVsdChtYXRyaXgpO1xuICAgICAgICBibCA9IGJsLm1hdE11bHQobWF0cml4KTtcbiAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG5cbiAgICAgICAgeDEgPSBNYXRoLm1pbih0bC54LCB0ci54LCBibC54LCBici54KTtcbiAgICAgICAgeDIgPSBNYXRoLm1heCh0bC54LCB0ci54LCBibC54LCBici54KTtcbiAgICAgICAgeTEgPSBNYXRoLm1pbih0bC55LCB0ci55LCBibC55LCBici55KTtcbiAgICAgICAgeTIgPSBNYXRoLm1heCh0bC55LCB0ci55LCBibC55LCBici55KTtcbiAgICB9XG4gICAgdmFyIGJveCA9IHtcbiAgICAgICAgeDE6IHgxICogYm94U2NhbGUsXG4gICAgICAgIHgyOiB4MiAqIGJveFNjYWxlLFxuICAgICAgICB5MTogeTEgKiBib3hTY2FsZSxcbiAgICAgICAgeTI6IHkyICogYm94U2NhbGVcbiAgICB9O1xuXG4gICAgdmFyIGljb25Cb3ggPSB7XG4gICAgICAgIGJveDogYm94LFxuICAgICAgICBhbmNob3I6IGFuY2hvcixcbiAgICAgICAgbWluU2NhbGU6IG1pblNjYWxlLFxuICAgICAgICBtYXhTY2FsZTogSW5maW5pdHksXG4gICAgICAgIHBhZGRpbmc6IHByb3BzWydpY29uLXBhZGRpbmcnXVxuICAgIH07XG5cbiAgICB2YXIgaWNvbiA9IHtcbiAgICAgICAgdGw6IHRsLFxuICAgICAgICB0cjogdHIsXG4gICAgICAgIGJyOiBicixcbiAgICAgICAgYmw6IGJsLFxuICAgICAgICB0ZXg6IGltYWdlLFxuICAgICAgICBhbmdsZTogMCxcbiAgICAgICAgYW5jaG9yOiBhbmNob3IsXG4gICAgICAgIG1pblNjYWxlOiBtaW5TY2FsZSxcbiAgICAgICAgbWF4U2NhbGU6IEluZmluaXR5XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNoYXBlczogW2ljb25dLFxuICAgICAgICBib3hlczogW2ljb25Cb3hdLFxuICAgICAgICBtaW5TY2FsZTogYW5jaG9yLnNjYWxlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0R2x5cGhzKGFuY2hvciwgb3JpZ2luLCBzaGFwaW5nLCBmYWNlcywgYm94U2NhbGUsIGhvcml6b250YWwsIGxpbmUsIHByb3BzKSB7XG5cbiAgICB2YXIgbWF4QW5nbGVEZWx0YSA9IHByb3BzWyd0ZXh0LW1heC1hbmdsZSddICogTWF0aC5QSSAvIDE4MDtcbiAgICB2YXIgcm90YXRlID0gcHJvcHNbJ3RleHQtcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBwYWRkaW5nID0gcHJvcHNbJ3RleHQtcGFkZGluZyddO1xuICAgIHZhciBhbG9uZ0xpbmUgPSBwcm9wc1sndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSAhPT0gJ3ZpZXdwb3J0JztcbiAgICB2YXIga2VlcFVwcmlnaHQgPSBwcm9wc1sndGV4dC1rZWVwLXVwcmlnaHQnXTtcblxuICAgIHZhciBnbHlwaHMgPSBbXSxcbiAgICAgICAgYm94ZXMgPSBbXTtcblxuICAgIHZhciBidWZmZXIgPSAzO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBzaGFwaW5nLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBzaGFwZSA9IHNoYXBpbmdba107XG4gICAgICAgIHZhciBmb250c3RhY2sgPSBmYWNlc1tzaGFwZS5mb250c3RhY2tdO1xuICAgICAgICB2YXIgZ2x5cGggPSBmb250c3RhY2suZ2x5cGhzW3NoYXBlLmdseXBoXTtcbiAgICAgICAgdmFyIHJlY3QgPSBmb250c3RhY2sucmVjdHNbc2hhcGUuZ2x5cGhdO1xuXG4gICAgICAgIGlmICghZ2x5cGgpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmICghKHJlY3QgJiYgcmVjdC53ID4gMCAmJiByZWN0LmggPiAwKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIHggPSAob3JpZ2luLnggKyBzaGFwZS54ICsgZ2x5cGgubGVmdCAtIGJ1ZmZlciArIHJlY3QudyAvIDIpICogYm94U2NhbGU7XG5cbiAgICAgICAgdmFyIGdseXBoSW5zdGFuY2VzO1xuICAgICAgICBpZiAoYW5jaG9yLnNlZ21lbnQgIT09IHVuZGVmaW5lZCAmJiBhbG9uZ0xpbmUpIHtcbiAgICAgICAgICAgIGdseXBoSW5zdGFuY2VzID0gW107XG4gICAgICAgICAgICBnZXRTZWdtZW50R2x5cGhzKGdseXBoSW5zdGFuY2VzLCBhbmNob3IsIHgsIGxpbmUsIGFuY2hvci5zZWdtZW50LCAxLCBtYXhBbmdsZURlbHRhKTtcbiAgICAgICAgICAgIGlmIChrZWVwVXByaWdodCkgZ2V0U2VnbWVudEdseXBocyhnbHlwaEluc3RhbmNlcywgYW5jaG9yLCB4LCBsaW5lLCBhbmNob3Iuc2VnbWVudCwgLTEsIG1heEFuZ2xlRGVsdGEpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbHlwaEluc3RhbmNlcyA9IFt7XG4gICAgICAgICAgICAgICAgYW5jaG9yOiBhbmNob3IsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICAgICAgICAgIGFuZ2xlOiAwLFxuICAgICAgICAgICAgICAgIG1heFNjYWxlOiBJbmZpbml0eSxcbiAgICAgICAgICAgICAgICBtaW5TY2FsZTogbWluU2NhbGVcbiAgICAgICAgICAgIH1dO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHgxID0gb3JpZ2luLnggKyBzaGFwZS54ICsgZ2x5cGgubGVmdCAtIGJ1ZmZlcixcbiAgICAgICAgICAgIHkxID0gb3JpZ2luLnkgKyBzaGFwZS55IC0gZ2x5cGgudG9wIC0gYnVmZmVyLFxuICAgICAgICAgICAgeDIgPSB4MSArIHJlY3QudyxcbiAgICAgICAgICAgIHkyID0geTEgKyByZWN0LmgsXG5cbiAgICAgICAgICAgIG90bCA9IG5ldyBQb2ludCh4MSwgeTEpLFxuICAgICAgICAgICAgb3RyID0gbmV3IFBvaW50KHgyLCB5MSksXG4gICAgICAgICAgICBvYmwgPSBuZXcgUG9pbnQoeDEsIHkyKSxcbiAgICAgICAgICAgIG9iciA9IG5ldyBQb2ludCh4MiwgeTIpO1xuXG4gICAgICAgIHZhciBvYm94ID0ge1xuICAgICAgICAgICAgICAgIHgxOiBib3hTY2FsZSAqIHgxLFxuICAgICAgICAgICAgICAgIHkxOiBib3hTY2FsZSAqIHkxLFxuICAgICAgICAgICAgICAgIHgyOiBib3hTY2FsZSAqIHgyLFxuICAgICAgICAgICAgICAgIHkyOiBib3hTY2FsZSAqIHkyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2x5cGhJbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gZ2x5cGhJbnN0YW5jZXNbaV0sXG5cbiAgICAgICAgICAgICAgICB0bCA9IG90bCxcbiAgICAgICAgICAgICAgICB0ciA9IG90cixcbiAgICAgICAgICAgICAgICBibCA9IG9ibCxcbiAgICAgICAgICAgICAgICBiciA9IG9icixcbiAgICAgICAgICAgICAgICBib3ggPSBvYm94LFxuXG4gICAgICAgICAgICAgICAgLy8gQ2xhbXAgdG8gLTkwLys5MCBkZWdyZWVzXG4gICAgICAgICAgICAgICAgYW5nbGUgPSBpbnN0YW5jZS5hbmdsZSArIHJvdGF0ZTtcblxuICAgICAgICAgICAgaWYgKGFuZ2xlKSB7XG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgdHJhbnNmb3JtYXRpb24gbWF0cml4LlxuICAgICAgICAgICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgICAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgdHIgPSB0ci5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgbGFiZWwgZnJvbSBleHRlbmRpbmcgcGFzdCB0aGUgZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICB2YXIgZ2x5cGhNaW5TY2FsZSA9IE1hdGgubWF4KGluc3RhbmNlLm1pblNjYWxlLCBhbmNob3Iuc2NhbGUpO1xuXG4gICAgICAgICAgICAvLyBSZW1lbWJlciB0aGUgZ2x5cGggZm9yIGxhdGVyIGluc2VydGlvbi5cbiAgICAgICAgICAgIGdseXBocy5wdXNoKHtcbiAgICAgICAgICAgICAgICB0bDogdGwsXG4gICAgICAgICAgICAgICAgdHI6IHRyLFxuICAgICAgICAgICAgICAgIGJsOiBibCxcbiAgICAgICAgICAgICAgICBicjogYnIsXG4gICAgICAgICAgICAgICAgdGV4OiByZWN0LFxuICAgICAgICAgICAgICAgIGFuZ2xlOiAoYW5jaG9yLmFuZ2xlICsgcm90YXRlICsgaW5zdGFuY2Uub2Zmc2V0ICsgMiAqIE1hdGguUEkpICUgKDIgKiBNYXRoLlBJKSxcbiAgICAgICAgICAgICAgICBhbmNob3I6IGluc3RhbmNlLmFuY2hvcixcbiAgICAgICAgICAgICAgICBtaW5TY2FsZTogZ2x5cGhNaW5TY2FsZSxcbiAgICAgICAgICAgICAgICBtYXhTY2FsZTogaW5zdGFuY2UubWF4U2NhbGVcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIWluc3RhbmNlLm9mZnNldCkgeyAvLyBub3QgYSBmbGlwcGVkIGdseXBoXG4gICAgICAgICAgICAgICAgaWYgKGFuZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgcm90YXRlZCBnbHlwaCdzIGJvdW5kaW5nIGJveCBvZmZzZXRzIGZyb20gdGhlIGFuY2hvciBwb2ludC5cbiAgICAgICAgICAgICAgICAgICAgYm94ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgeDE6IGJveFNjYWxlICogTWF0aC5taW4odGwueCwgdHIueCwgYmwueCwgYnIueCksXG4gICAgICAgICAgICAgICAgICAgICAgICB5MTogYm94U2NhbGUgKiBNYXRoLm1pbih0bC55LCB0ci55LCBibC55LCBici55KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHgyOiBib3hTY2FsZSAqIE1hdGgubWF4KHRsLngsIHRyLngsIGJsLngsIGJyLngpLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTI6IGJveFNjYWxlICogTWF0aC5tYXgodGwueSwgdHIueSwgYmwueSwgYnIueSlcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYm94ZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGJveDogYm94LFxuICAgICAgICAgICAgICAgICAgICBhbmNob3I6IGluc3RhbmNlLmFuY2hvcixcbiAgICAgICAgICAgICAgICAgICAgbWluU2NhbGU6IGdseXBoTWluU2NhbGUsXG4gICAgICAgICAgICAgICAgICAgIG1heFNjYWxlOiBpbnN0YW5jZS5tYXhTY2FsZSxcbiAgICAgICAgICAgICAgICAgICAgcGFkZGluZzogcGFkZGluZ1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBhdm9pZCBjcmVhdGluZyB0aGUgYm94ZXMgaW4gdGhlIGZpcnN0IHBsYWNlP1xuICAgIGlmIChob3Jpem9udGFsKSBib3hlcyA9IFtnZXRNZXJnZWRCb3hlcyhib3hlcywgYW5jaG9yKV07XG5cbiAgICB2YXIgbWluUGxhY2VtZW50U2NhbGUgPSBhbmNob3Iuc2NhbGU7XG4gICAgdmFyIG1pbkdseXBoU2NhbGUgPSBJbmZpbml0eTtcbiAgICBmb3IgKHZhciBtID0gMDsgbSA8IGJveGVzLmxlbmd0aDsgbSsrKSB7XG4gICAgICAgIG1pbkdseXBoU2NhbGUgPSBNYXRoLm1pbihtaW5HbHlwaFNjYWxlLCBib3hlc1ttXS5taW5TY2FsZSk7XG4gICAgfVxuICAgIG1pbkdseXBoU2NhbGUgPSBNYXRoLm1heChtaW5QbGFjZW1lbnRTY2FsZSwgbWluU2NhbGUpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYm94ZXM6IGJveGVzLFxuICAgICAgICBzaGFwZXM6IGdseXBocyxcbiAgICAgICAgbWluU2NhbGU6IG1pbkdseXBoU2NhbGVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRTZWdtZW50R2x5cGhzKGdseXBocywgYW5jaG9yLCBvZmZzZXQsIGxpbmUsIHNlZ21lbnQsIGRpcmVjdGlvbiwgbWF4QW5nbGVEZWx0YSkge1xuICAgIHZhciB1cHNpZGVEb3duID0gZGlyZWN0aW9uIDwgMDtcblxuICAgIGlmIChvZmZzZXQgPCAwKSAgZGlyZWN0aW9uICo9IC0xO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHNlZ21lbnQrKztcblxuICAgIHZhciBuZXdBbmNob3IgPSBhbmNob3I7XG4gICAgdmFyIGVuZCA9IGxpbmVbc2VnbWVudF07XG4gICAgdmFyIHByZXZzY2FsZSA9IEluZmluaXR5O1xuICAgIHZhciBwcmV2QW5nbGU7XG5cbiAgICBvZmZzZXQgPSBNYXRoLmFicyhvZmZzZXQpO1xuXG4gICAgdmFyIHBsYWNlbWVudFNjYWxlID0gYW5jaG9yLnNjYWxlO1xuXG4gICAgc2VnbWVudF9sb29wOlxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIHZhciBkaXN0ID0gbmV3QW5jaG9yLmRpc3QoZW5kKTtcbiAgICAgICAgdmFyIHNjYWxlID0gb2Zmc2V0L2Rpc3Q7XG4gICAgICAgIHZhciBhbmdsZSA9IC1NYXRoLmF0YW4yKGVuZC54IC0gbmV3QW5jaG9yLngsIGVuZC55IC0gbmV3QW5jaG9yLnkpICsgZGlyZWN0aW9uICogTWF0aC5QSSAvIDI7XG4gICAgICAgIGlmICh1cHNpZGVEb3duKSBhbmdsZSArPSBNYXRoLlBJO1xuXG4gICAgICAgIC8vIERvbid0IHBsYWNlIGFyb3VuZCBzaGFycCBjb3JuZXJzXG4gICAgICAgIHZhciBhbmdsZURpZmYgPSAoYW5nbGUgLSBwcmV2QW5nbGUpICUgKDIgKiBNYXRoLlBJKTtcbiAgICAgICAgaWYgKHByZXZBbmdsZSAmJiBNYXRoLmFicyhhbmdsZURpZmYpID4gbWF4QW5nbGVEZWx0YSkge1xuICAgICAgICAgICAgYW5jaG9yLnNjYWxlID0gcHJldnNjYWxlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBnbHlwaHMucHVzaCh7XG4gICAgICAgICAgICBhbmNob3I6IG5ld0FuY2hvcixcbiAgICAgICAgICAgIG9mZnNldDogdXBzaWRlRG93biA/IE1hdGguUEkgOiAwLFxuICAgICAgICAgICAgbWluU2NhbGU6IHNjYWxlLFxuICAgICAgICAgICAgbWF4U2NhbGU6IHByZXZzY2FsZSxcbiAgICAgICAgICAgIGFuZ2xlOiAoYW5nbGUgKyAyICogTWF0aC5QSSkgJSAoMiAqIE1hdGguUEkpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzY2FsZSA8PSBwbGFjZW1lbnRTY2FsZSkgYnJlYWs7XG5cbiAgICAgICAgbmV3QW5jaG9yID0gZW5kO1xuXG4gICAgICAgIC8vIHNraXAgZHVwbGljYXRlIG5vZGVzXG4gICAgICAgIHdoaWxlIChuZXdBbmNob3IuZXF1YWxzKGVuZCkpIHtcbiAgICAgICAgICAgIHNlZ21lbnQgKz0gZGlyZWN0aW9uO1xuICAgICAgICAgICAgZW5kID0gbGluZVtzZWdtZW50XTtcblxuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICBhbmNob3Iuc2NhbGUgPSBzY2FsZTtcbiAgICAgICAgICAgICAgICBicmVhayBzZWdtZW50X2xvb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdW5pdCA9IGVuZC5zdWIobmV3QW5jaG9yKS5fdW5pdCgpO1xuICAgICAgICBuZXdBbmNob3IgPSBuZXdBbmNob3Iuc3ViKHVuaXQuX211bHQoZGlzdCkpO1xuXG4gICAgICAgIHByZXZzY2FsZSA9IHNjYWxlO1xuICAgICAgICBwcmV2QW5nbGUgPSBhbmdsZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldE1lcmdlZEJveGVzKGdseXBocywgYW5jaG9yKSB7XG4gICAgICAvLyBDb2xsaXNpb24gY2hlY2tzIGJldHdlZW4gcm90YXRpbmcgYW5kIGZpeGVkIGxhYmVscyBhcmUgcmVsYXRpdmVseSBleHBlbnNpdmUsXG4gICAgICAvLyBzbyB3ZSB1c2Ugb25lIGJveCBwZXIgbGFiZWwsIG5vdCBwZXIgZ2x5cGggZm9yIGhvcml6b250YWwgbGFiZWxzLlxuXG4gICAgdmFyIG1lcmdlZGdseXBocyA9IHtcbiAgICAgICAgYm94OiB7IHgxOiBJbmZpbml0eSwgeTE6IEluZmluaXR5LCB4MjogLUluZmluaXR5LCB5MjogLUluZmluaXR5IH0sXG4gICAgICAgIGFuY2hvcjogYW5jaG9yLFxuICAgICAgICBtaW5TY2FsZTogMCxcbiAgICAgICAgcGFkZGluZzogLUluZmluaXR5XG4gICAgfTtcblxuICAgIHZhciBib3ggPSBtZXJnZWRnbHlwaHMuYm94O1xuXG4gICAgZm9yICh2YXIgbSA9IDA7IG0gPCBnbHlwaHMubGVuZ3RoOyBtKyspIHtcbiAgICAgICAgdmFyIGdib3ggPSBnbHlwaHNbbV0uYm94O1xuICAgICAgICBib3gueDEgPSBNYXRoLm1pbihib3gueDEsIGdib3gueDEpO1xuICAgICAgICBib3gueTEgPSBNYXRoLm1pbihib3gueTEsIGdib3gueTEpO1xuICAgICAgICBib3gueDIgPSBNYXRoLm1heChib3gueDIsIGdib3gueDIpO1xuICAgICAgICBib3gueTIgPSBNYXRoLm1heChib3gueTIsIGdib3gueTIpO1xuICAgICAgICBtZXJnZWRnbHlwaHMubWluU2NhbGUgPSBNYXRoLm1heChtZXJnZWRnbHlwaHMubWluU2NhbGUsIGdseXBoc1ttXS5taW5TY2FsZSk7XG4gICAgICAgIG1lcmdlZGdseXBocy5wYWRkaW5nID0gTWF0aC5tYXgobWVyZ2VkZ2x5cGhzLnBhZGRpbmcsIGdseXBoc1ttXS5wYWRkaW5nKTtcbiAgICB9XG4gICAgLy8gZm9yIGFsbCBob3Jpem9udGFsIGxhYmVscywgY2FsY3VsYXRlIGJib3ggY292ZXJpbmcgYWxsIHJvdGF0ZWQgcG9zaXRpb25zXG4gICAgdmFyIHgxMiA9IGJveC54MSAqIGJveC54MSxcbiAgICAgICAgeTEyID0gYm94LnkxICogYm94LnkxLFxuICAgICAgICB4MjIgPSBib3gueDIgKiBib3gueDIsXG4gICAgICAgIHkyMiA9IGJveC55MiAqIGJveC55MixcbiAgICAgICAgZGlhZyA9IE1hdGguc3FydChNYXRoLm1heCh4MTIgKyB5MTIsIHgxMiArIHkyMiwgeDIyICsgeTEyLCB4MjIgKyB5MjIpKTtcblxuICAgIG1lcmdlZGdseXBocy5oQm94ID0ge1xuICAgICAgICB4MTogLWRpYWcsXG4gICAgICAgIHkxOiAtZGlhZyxcbiAgICAgICAgeDI6IGRpYWcsXG4gICAgICAgIHkyOiBkaWFnXG4gICAgfTtcblxuICAgIHJldHVybiBtZXJnZWRnbHlwaHM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbi5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUZXh0O1xuXG4vLyBGb3IgYW4gYXJyYXkgb2YgZmVhdHVyZXMgZGV0ZXJtaW5lIHdoYXQgZ2x5cGggcmFuZ2VzIG5lZWQgdG8gYmUgbG9hZGVkXG4vLyBhbmQgYXBwbHkgYW55IHRleHQgcHJlcHJvY2Vzc2luZy4gVGhlIHJlbWFpbmluZyB1c2VycyBvZiB0ZXh0IHNob3VsZFxuLy8gdXNlIHRoZSBgdGV4dEZlYXR1cmVzYCBrZXkgcmV0dXJuZWQgYnkgdGhpcyBmdW5jdGlvbiByYXRoZXIgdGhhbiBhY2Nlc3Npbmdcbi8vIGZlYXR1cmUgdGV4dCBkaXJlY3RseS5cbmZ1bmN0aW9uIHJlc29sdmVUZXh0KGZlYXR1cmVzLCBpbmZvLCBnbHlwaHMpIHtcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gW107XG4gICAgdmFyIGNvZGVwb2ludHMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBmbCA9IGZlYXR1cmVzLmxlbmd0aDsgaSA8IGZsOyBpKyspIHtcbiAgICAgICAgdmFyIHRleHQgPSByZXNvbHZlVG9rZW5zKGZlYXR1cmVzW2ldLnByb3BlcnRpZXMsIGluZm9bJ3RleHQtZmllbGQnXSk7XG4gICAgICAgIHZhciBoYXN0ZXh0ID0gZmFsc2U7XG4gICAgICAgIGlmICghdGV4dCkgY29udGludWU7XG4gICAgICAgIHRleHQgPSB0ZXh0LnRvU3RyaW5nKCk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IGluZm9bJ3RleHQtdHJhbnNmb3JtJ107XG4gICAgICAgIGlmICh0cmFuc2Zvcm0gPT09ICd1cHBlcmNhc2UnKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC50b0xvY2FsZVVwcGVyQ2FzZSgpO1xuICAgICAgICB9IGVsc2UgaWYgKHRyYW5zZm9ybSA9PT0gJ2xvd2VyY2FzZScpIHtcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0LnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBqID0gMCwgamwgPSB0ZXh0Lmxlbmd0aDsgaiA8IGpsOyBqKyspIHtcbiAgICAgICAgICAgIGlmICh0ZXh0LmNoYXJDb2RlQXQoaikgPD0gNjU1MzMpIHtcbiAgICAgICAgICAgICAgICBjb2RlcG9pbnRzLnB1c2godGV4dC5jaGFyQ29kZUF0KGopKTtcbiAgICAgICAgICAgICAgICBoYXN0ZXh0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBUcmFjayBpbmRleGVzIG9mIGZlYXR1cmVzIHdpdGggdGV4dC5cbiAgICAgICAgaWYgKGhhc3RleHQpIHtcbiAgICAgICAgICAgIHRleHRGZWF0dXJlc1tpXSA9IHRleHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBnZXQgYSBsaXN0IG9mIHVuaXF1ZSBjb2RlcG9pbnRzIHdlIGFyZSBtaXNzaW5nXG4gICAgY29kZXBvaW50cyA9IHVuaXEoY29kZXBvaW50cywgZ2x5cGhzKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHRleHRGZWF0dXJlczogdGV4dEZlYXR1cmVzLFxuICAgICAgICBjb2RlcG9pbnRzOiBjb2RlcG9pbnRzXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gdW5pcShpZHMsIGFscmVhZHlIYXZlKSB7XG4gICAgdmFyIHUgPSBbXTtcbiAgICB2YXIgbGFzdDtcbiAgICBpZHMuc29ydChzb3J0TnVtYmVycyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGlkc1tpXSAhPT0gbGFzdCkge1xuICAgICAgICAgICAgbGFzdCA9IGlkc1tpXTtcbiAgICAgICAgICAgIGlmICghYWxyZWFkeUhhdmVbbGFzdF0pIHUucHVzaChpZHNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1O1xufVxuXG5mdW5jdGlvbiBzb3J0TnVtYmVycyhhLCBiKSB7XG4gICAgcmV0dXJuIGEgLSBiO1xufVxuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsLmpzJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICByb3RhdGlvblJhbmdlOiByb3RhdGlvblJhbmdlLFxuICAgIG1lcmdlQ29sbGlzaW9uczogbWVyZ2VDb2xsaXNpb25zLFxuXG4gICAgcm90YXRpbmdGaXhlZENvbGxpc2lvbnM6IHJvdGF0aW5nRml4ZWRDb2xsaXNpb25zLFxuICAgIHJvdGF0aW5nUm90YXRpbmdDb2xsaXNpb25zOiByb3RhdGluZ1JvdGF0aW5nQ29sbGlzaW9ucyxcblxuICAgIGNvcm5lckJveENvbGxpc2lvbnM6IGNvcm5lckJveENvbGxpc2lvbnMsXG4gICAgY2lyY2xlRWRnZUNvbGxpc2lvbnM6IGNpcmNsZUVkZ2VDb2xsaXNpb25zLFxuXG4gICAgZ2V0Q29ybmVyczogZ2V0Q29ybmVycyxcbn07XG5cbi8qXG4gKiBDYWxjdWxhdGUgdGhlIHJhbmdlIGEgYm94IGNvbmZsaWN0cyB3aXRoIGEgc2Vjb25kIGJveFxuICovXG5mdW5jdGlvbiByb3RhdGlvblJhbmdlKGluc2VydGluZywgYmxvY2tlciwgc2NhbGUpIHtcblxuICAgIHZhciBjb2xsaXNpb25zLCBib3g7XG5cbiAgICB2YXIgYSA9IGluc2VydGluZztcbiAgICB2YXIgYiA9IGJsb2NrZXI7XG5cbiAgICAvLyBJbnN0ZWFkIG9mIHNjYWxpbmcgdGhlIGJveGVzLCB3ZSBtb3ZlIHRoZSBhbmNob3JzXG4gICAgdmFyIHJlbGF0aXZlQW5jaG9yID0gbmV3IFBvaW50KFxuICAgICAgICAoYi5hbmNob3IueCAtIGEuYW5jaG9yLngpICogc2NhbGUsXG4gICAgICAgIChiLmFuY2hvci55IC0gYS5hbmNob3IueSkgKiBzY2FsZSk7XG5cbiAgICAvLyBHZW5lcmF0ZSBhIGxpc3Qgb2YgY29sbGlzaW9uIGludGVydmFsXG4gICAgaWYgKGEuaEJveCAmJiBiLmhCb3gpIHtcbiAgICAgICAgY29sbGlzaW9ucyA9IHJvdGF0aW5nUm90YXRpbmdDb2xsaXNpb25zKGEuYm94LCBiLmJveCwgcmVsYXRpdmVBbmNob3IpO1xuXG4gICAgfSBlbHNlIGlmIChhLmhCb3gpIHtcbiAgICAgICAgYm94ID0ge1xuICAgICAgICAgICAgeDE6IGIuYm94LngxICsgcmVsYXRpdmVBbmNob3IueCxcbiAgICAgICAgICAgIHkxOiBiLmJveC55MSArIHJlbGF0aXZlQW5jaG9yLnksXG4gICAgICAgICAgICB4MjogYi5ib3gueDIgKyByZWxhdGl2ZUFuY2hvci54LFxuICAgICAgICAgICAgeTI6IGIuYm94LnkyICsgcmVsYXRpdmVBbmNob3IueVxuICAgICAgICB9O1xuICAgICAgICBjb2xsaXNpb25zID0gcm90YXRpbmdGaXhlZENvbGxpc2lvbnMoYS5ib3gsIGJveCk7XG5cblxuICAgIH0gZWxzZSBpZiAoYi5oQm94KSB7XG4gICAgICAgIGJveCA9IHtcbiAgICAgICAgICAgIHgxOiBhLmJveC54MSAtIHJlbGF0aXZlQW5jaG9yLngsXG4gICAgICAgICAgICB5MTogYS5ib3gueTEgLSByZWxhdGl2ZUFuY2hvci55LFxuICAgICAgICAgICAgeDI6IGEuYm94LngyIC0gcmVsYXRpdmVBbmNob3IueCxcbiAgICAgICAgICAgIHkyOiBhLmJveC55MiAtIHJlbGF0aXZlQW5jaG9yLnlcbiAgICAgICAgfTtcbiAgICAgICAgY29sbGlzaW9ucyA9IHJvdGF0aW5nRml4ZWRDb2xsaXNpb25zKGIuYm94LCBib3gpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29sbGlzaW9ucyA9IFtdO1xuICAgIH1cblxuICAgIC8vIEZpbmQgYW5kIHJldHVybiB0aGUgY29udGlub3VzIGFyZSBhcm91bmQgMCB3aGVyZSB0aGVyZSBhcmUgbm8gY29sbGlzaW9uc1xuICAgIHJldHVybiBtZXJnZUNvbGxpc2lvbnMoY29sbGlzaW9ucywgYmxvY2tlci5wbGFjZW1lbnRSYW5nZSk7XG59XG5cbi8qXG4gKiBDb21iaW5lIGFuIGFycmF5IG9mIGNvbGxpc2lvbiByYW5nZXMgdG8gZm9ybSBhIGNvbnRpbnVvdXNcbiAqIHJhbmdlIHRoYXQgaW5jbHVkZXMgMC4gQ29sbGlzaW9ucyB3aXRoaW4gdGhlIGlnbm9yZVJhbmdlIGFyZSBpZ25vcmVkXG4gKi9cbmZ1bmN0aW9uIG1lcmdlQ29sbGlzaW9ucyhjb2xsaXNpb25zLCBpZ25vcmVSYW5nZSkge1xuXG4gICAgLy8gZmluZCBjb250aW51b3VzIGludGVydmFsIGluY2x1ZGluZyAwIHRoYXQgZG9lc24ndCBoYXZlIGFueSBjb2xsaXNpb25zXG4gICAgdmFyIG1pbiA9IDIgKiBNYXRoLlBJO1xuICAgIHZhciBtYXggPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2xsaXNpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjb2xsaXNpb24gPSBjb2xsaXNpb25zW2ldO1xuXG4gICAgICAgIHZhciBlbnRyeU91dHNpZGUgPSBpZ25vcmVSYW5nZVswXSA8PSBjb2xsaXNpb25bMF0gJiYgY29sbGlzaW9uWzBdIDw9IGlnbm9yZVJhbmdlWzFdO1xuICAgICAgICB2YXIgZXhpdE91dHNpZGUgPSBpZ25vcmVSYW5nZVswXSA8PSBjb2xsaXNpb25bMV0gJiYgY29sbGlzaW9uWzFdIDw9IGlnbm9yZVJhbmdlWzFdO1xuXG4gICAgICAgIGlmIChlbnRyeU91dHNpZGUgJiYgZXhpdE91dHNpZGUpIHtcbiAgICAgICAgICAgIC8vIG5vIGNvbGxpc2lvbiwgc2luY2UgYmxvY2tlciBpcyBvdXQgb2YgcmFuZ2VcbiAgICAgICAgfSBlbHNlIGlmIChlbnRyeU91dHNpZGUpIHtcbiAgICAgICAgICAgIG1pbiA9IE1hdGgubWluKG1pbiwgaWdub3JlUmFuZ2VbMV0pO1xuICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBjb2xsaXNpb25bMV0pO1xuICAgICAgICB9IGVsc2UgaWYgKGV4aXRPdXRzaWRlKSB7XG4gICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIGNvbGxpc2lvblswXSk7XG4gICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIGlnbm9yZVJhbmdlWzBdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1pbiA9IE1hdGgubWluKG1pbiwgY29sbGlzaW9uWzBdKTtcbiAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgY29sbGlzaW9uWzFdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbbWluLCBtYXhdO1xufVxuXG4vKlxuICogIENhbGN1bGF0ZSBjb2xsaXNpb24gcmFuZ2VzIGZvciB0d28gcm90YXRpbmcgYm94ZXMuXG4gKi9cblxudmFyIGhvcml6b250YWwgPSBuZXcgUG9pbnQoMSwgMCk7XG5cbmZ1bmN0aW9uIHJvdGF0aW5nUm90YXRpbmdDb2xsaXNpb25zKGEsIGIsIGFuY2hvclRvQW5jaG9yKSB7XG4gICAgdmFyIGQgPSBhbmNob3JUb0FuY2hvci5tYWcoKTtcblxuICAgIHZhciBhbmdsZUJldHdlZW5BbmNob3JzID0gYW5jaG9yVG9BbmNob3IuYW5nbGVXaXRoKGhvcml6b250YWwpO1xuXG4gICAgdmFyIGMgPSBbXSxcbiAgICAgICAgY29sbGlzaW9ucyA9IFtdLFxuICAgICAgICBrO1xuXG4gICAgLy8gQ2FsY3VsYXRlIGFuZ2xlcyBhdCB3aGljaCBjb2xsaXNpb25zIG1heSBvY2N1clxuICAgIC8vIHRvcC9ib3R0b21cbiAgICBjWzBdID0gTWF0aC5hc2luKChhLnkyIC0gYi55MSkgLyBkKTtcbiAgICBjWzFdID0gTWF0aC5hc2luKChhLnkyIC0gYi55MSkgLyBkKSArIE1hdGguUEk7XG4gICAgY1syXSA9IDIgKiBNYXRoLlBJIC0gTWF0aC5hc2luKCgtYS55MSArIGIueTIpIC8gZCk7XG4gICAgY1szXSA9IE1hdGguUEkgLSBNYXRoLmFzaW4oKC1hLnkxICsgYi55MikgLyBkKTtcblxuICAgIC8vIGxlZnQvcmlnaHRcbiAgICBjWzRdID0gMiAqIE1hdGguUEkgLSBNYXRoLmFjb3MoKGEueDIgLSBiLngxKSAvIGQpO1xuICAgIGNbNV0gPSBNYXRoLmFjb3MoKGEueDIgLSBiLngxKSAvIGQpO1xuICAgIGNbNl0gPSBNYXRoLlBJIC0gTWF0aC5hY29zKCgtYS54MSArIGIueDIpIC8gZCk7XG4gICAgY1s3XSA9IE1hdGguUEkgKyBNYXRoLmFjb3MoKC1hLngxICsgYi54MikgLyBkKTtcblxuICAgIHZhciBybCA9IGEueDIgLSBiLngxO1xuICAgIHZhciBsciA9IC1hLngxICsgYi54MjtcbiAgICB2YXIgdGIgPSBhLnkyIC0gYi55MTtcbiAgICB2YXIgYnQgPSAtYS55MSArIGIueTI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRpc3RhbmNlIHNxdWFyZWQgb2YgdGhlIGRpYWdvbmFsIHdoaWNoIHdpbGwgYmUgdXNlZFxuICAgIC8vIHRvIGNoZWNrIGlmIHRoZSBib3hlcyBhcmUgY2xvc2UgZW5vdWdoIGZvciBjb2xsaXNpb25zIHRvIG9jY3VyIGF0IGVhY2ggYW5nbGVcbiAgICAvLyB0b2RvLCB0cmlwbGUgY2hlY2sgdGhlc2VcbiAgICB2YXIgZSA9IFtdO1xuICAgIC8vIHRvcC9ib3R0b21cbiAgICBlWzBdID0gcmwgKiBybCArIHRiICogdGI7XG4gICAgZVsxXSA9IGxyICogbHIgKyB0YiAqIHRiO1xuICAgIGVbMl0gPSBybCAqIHJsICsgYnQgKiBidDtcbiAgICBlWzNdID0gbHIgKiBsciArIGJ0ICogYnQ7XG4gICAgLy8gbGVmdC9yaWdodFxuICAgIGVbNF0gPSBybCAqIHJsICsgdGIgKiB0YjtcbiAgICBlWzVdID0gcmwgKiBybCArIGJ0ICogYnQ7XG4gICAgZVs2XSA9IGxyICogbHIgKyBidCAqIGJ0O1xuICAgIGVbN10gPSBsciAqIGxyICsgdGIgKiB0YjtcblxuXG4gICAgYyA9IGMuZmlsdGVyKGZ1bmN0aW9uKHgsIGkpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhleSBhcmUgY2xvc2UgZW5vdWdoIHRvIGNvbGxpZGVcbiAgICAgICAgcmV0dXJuICFpc05hTih4KSAmJiBkICogZCA8PSBlW2ldO1xuICAgIH0pLm1hcChmdW5jdGlvbih4KSB7XG4gICAgICAgIC8vIFNvIGZhciwgYW5nbGVzIGhhdmUgYmVlbiBjYWx1bGF0ZWQgYXMgcmVsYXRpdmUgdG8gdGhlIHZlY3RvciBiZXR3ZWVuIGFuY2hvcnMuXG4gICAgICAgIC8vIENvbnZlcnQgdGhlIGFuZ2xlcyB0byBhbmdsZXMgZnJvbSBub3J0aC5cbiAgICAgICAgcmV0dXJuICh4ICsgYW5nbGVCZXR3ZWVuQW5jaG9ycyArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG4gICAgfSk7XG5cbiAgICAvLyBHcm91cCB0aGUgY29sbGlzaW9uIGFuZ2xlcyBieSB0d29cbiAgICAvLyBlYWNoIGdyb3VwIHJlcHJlc2VudHMgYSByYW5nZSB3aGVyZSB0aGUgdHdvIGJveGVzIGNvbGxpZGVcbiAgICBjLnNvcnQoKTtcbiAgICBmb3IgKGsgPSAwOyBrIDwgYy5sZW5ndGg7IGsrPTIpIHtcbiAgICAgICAgY29sbGlzaW9ucy5wdXNoKFtjW2tdLCBjW2srMV1dKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGlzaW9ucztcblxufVxuXG4vKlxuICogIENhbGN1bGF0ZSBjb2xsaXNpb24gcmFuZ2VzIGZvciBhIHJvdGF0aW5nIGJveCBhbmQgYSBmaXhlZCBib3g7XG4gKi9cbmZ1bmN0aW9uIHJvdGF0aW5nRml4ZWRDb2xsaXNpb25zKHJvdGF0aW5nLCBmaXhlZCkge1xuXG4gICAgdmFyIGNvcm5lcnNSID0gZ2V0Q29ybmVycyhyb3RhdGluZyk7XG4gICAgdmFyIGNvcm5lcnNGID0gZ2V0Q29ybmVycyhmaXhlZCk7XG5cbiAgICAvLyBBIGNvbGxpc2lvbiBvY2N1cnMgd2hlbiwgYW5kIG9ubHkgYXQgbGVhc3Qgb25lIGNvcm5lciBmcm9tIG9uZSBvZiB0aGUgYm94ZXNcbiAgICAvLyBpcyB3aXRoaW4gdGhlIG90aGVyIGJveC4gQ2FsY3VsYXRlIHRoZXNlIHJhbmdlcyBmb3IgZWFjaCBjb3JuZXIuXG5cbiAgICB2YXIgY29sbGlzaW9ucyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKysgKSB7XG4gICAgICAgIGNvcm5lckJveENvbGxpc2lvbnMoY29sbGlzaW9ucywgY29ybmVyc1JbaV0sIGNvcm5lcnNGKTtcbiAgICAgICAgY29ybmVyQm94Q29sbGlzaW9ucyhjb2xsaXNpb25zLCBjb3JuZXJzRltpXSwgY29ybmVyc1IsIHRydWUpO1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsaXNpb25zO1xufVxuXG5cbi8qXG4gKiAgQ2FsY3VsYXRlIHRoZSByYW5nZXMgZm9yIHdoaWNoIHRoZSBjb3JuZXIsXG4gKiAgcm90YXRhdGVkIGFyb3VuZCB0aGUgYW5jaG9yLCBpcyB3aXRoaW4gdGhlIGJveDtcbiAqL1xuZnVuY3Rpb24gY29ybmVyQm94Q29sbGlzaW9ucyhjb2xsaXNpb25zLCBjb3JuZXIsIGJveENvcm5lcnMsIGZsaXApIHtcbiAgICB2YXIgcmFkaXVzID0gY29ybmVyLm1hZygpLFxuICAgICAgICBhbmdsZXMgPSBbXTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgcG9pbnRzIGF0IHdoaWNoIHRoZSBjb3JuZXJzIGludGVyc2VjdCB3aXRoIHRoZSBlZGdlc1xuICAgIGZvciAodmFyIGkgPSAwLCBqID0gMzsgaSA8IDQ7IGogPSBpKyspIHtcbiAgICAgICAgY2lyY2xlRWRnZUNvbGxpc2lvbnMoYW5nbGVzLCBjb3JuZXIsIHJhZGl1cywgYm94Q29ybmVyc1tqXSwgYm94Q29ybmVyc1tpXSk7XG4gICAgfVxuXG4gICAgaWYgKGFuZ2xlcy5sZW5ndGggJSAyICE9PSAwKSB7XG4gICAgICAgIC8vIFRPRE8gZml4XG4gICAgICAgIC8vIFRoaXMgY291bGQgZ2V0IGhpdCB3aGVuIGEgcG9pbnQgaW50ZXJzZWN0cyB2ZXJ5IGNsb3NlIHRvIGEgY29ybmVyXG4gICAgICAgIC8vIGFuZCBmbG9hdGluZyBwb2ludCBpc3N1ZXMgY2F1c2Ugb25seSBvbmUgb2YgdGhlIGVudHJ5IG9yIGV4aXQgdG8gYmUgY291bnRlZFxuICAgICAgICB0aHJvdygnZXhwZWN0aW5nIGFuIGV2ZW4gbnVtYmVyIG9mIGludGVyc2VjdGlvbnMnKTtcbiAgICB9XG5cbiAgICBhbmdsZXMuc29ydCgpO1xuXG4gICAgLy8gR3JvdXAgYnkgcGFpcnMsIHdoZXJlIGVhY2ggcmVwcmVzZW50cyBhIHJhbmdlIHdoZXJlIGEgY29sbGlzaW9uIG9jY3Vyc1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYW5nbGVzLmxlbmd0aDsgays9Mikge1xuICAgICAgICBjb2xsaXNpb25zW2svMl0gPSBmbGlwID9cbiAgICAgICAgICAgIFsyICogTWF0aC5QSSAtIGFuZ2xlc1trKzFdLCAyICogTWF0aC5QSSAtIGFuZ2xlc1trXV0gOiAvLyByZWZsZWN0IGFuIGFuZ2xlIGFyb3VuZCAwIGRlZ3JlZXNcbiAgICAgICAgICAgIFthbmdsZXNba10sIGFuZ2xlc1trKzFdXTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGlzaW9ucztcbn1cblxuLypcbiAqIFJldHVybiB0aGUgaW50ZXJzZWN0aW9uIHBvaW50cyBvZiBhIGNpcmNsZSBhbmQgYSBsaW5lIHNlZ21lbnQ7XG4gKi9cbmZ1bmN0aW9uIGNpcmNsZUVkZ2VDb2xsaXNpb25zKGFuZ2xlcywgY29ybmVyLCByYWRpdXMsIHAxLCBwMikge1xuXG4gICAgdmFyIGVkZ2VYID0gcDIueCAtIHAxLng7XG4gICAgdmFyIGVkZ2VZID0gcDIueSAtIHAxLnk7XG5cbiAgICB2YXIgYSA9IGVkZ2VYICogZWRnZVggKyBlZGdlWSAqIGVkZ2VZO1xuICAgIHZhciBiID0gKGVkZ2VYICogcDEueCArIGVkZ2VZICogcDEueSkgKiAyO1xuICAgIHZhciBjID0gcDEueCAqIHAxLnggKyBwMS55ICogcDEueSAtIHJhZGl1cyAqIHJhZGl1cztcblxuICAgIHZhciBkaXNjcmltaW5hbnQgPSBiKmIgLSA0KmEqYztcblxuICAgIC8vIGEgY29sbGlzaW9uIGV4aXN0cyBvbmx5IGlmIGxpbmUgaW50ZXJzZWN0cyBjaXJjbGUgYXQgdHdvIHBvaW50c1xuICAgIGlmIChkaXNjcmltaW5hbnQgPiAwKSB7XG4gICAgICAgIHZhciB4MSA9ICgtYiAtIE1hdGguc3FydChkaXNjcmltaW5hbnQpKSAvICgyICogYSk7XG4gICAgICAgIHZhciB4MiA9ICgtYiArIE1hdGguc3FydChkaXNjcmltaW5hbnQpKSAvICgyICogYSk7XG5cbiAgICAgICAgLy8gb25seSBhZGQgcG9pbnRzIGlmIHdpdGhpbiBsaW5lIHNlZ21lbnRcbiAgICAgICAgLy8gaGFjayB0byBoYW5kbGUgZmxvYXRpbmcgcG9pbnQgcmVwcmVzZW50YXRpb25zIG9mIDAgYW5kIDFcbiAgICAgICAgaWYgKDAgPCB4MSAmJiB4MSA8IDEpIHtcbiAgICAgICAgICAgIGFuZ2xlcy5wdXNoKGdldEFuZ2xlKHAxLCBwMiwgeDEsIGNvcm5lcikpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKDAgPCB4MiAmJiB4MiA8IDEpIHtcbiAgICAgICAgICAgIGFuZ2xlcy5wdXNoKGdldEFuZ2xlKHAxLCBwMiwgeDIsIGNvcm5lcikpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuZ2xlcztcbn1cblxuZnVuY3Rpb24gZ2V0QW5nbGUocDEsIHAyLCBkLCBjb3JuZXIpIHtcbiAgICByZXR1cm4gKC1jb3JuZXIuYW5nbGVXaXRoU2VwKFxuICAgICAgICB1dGlsLmludGVycChwMS54LCBwMi54LCBkKSxcbiAgICAgICAgdXRpbC5pbnRlcnAocDEueSwgcDIueSwgZCkpICsgMiAqIE1hdGguUEkpICUgKDIgKiBNYXRoLlBJKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q29ybmVycyhhKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IFBvaW50KGEueDEsIGEueTEpLFxuICAgICAgICBuZXcgUG9pbnQoYS54MSwgYS55MiksXG4gICAgICAgIG5ldyBQb2ludChhLngyLCBhLnkyKSxcbiAgICAgICAgbmV3IFBvaW50KGEueDIsIGEueTEpXG4gICAgXTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc2hhcGU6IHNoYXBlXG59O1xuXG5mdW5jdGlvbiBzaGFwZSh0ZXh0LCBuYW1lLCBzdGFja3MsIG1heFdpZHRoLCBsaW5lSGVpZ2h0LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIGp1c3RpZnksIHNwYWNpbmcsIHRyYW5zbGF0ZSkge1xuICAgIHZhciBnbHlwaHMgPSBzdGFja3NbbmFtZV0uZ2x5cGhzO1xuICAgIHZhciBnbHlwaDtcblxuICAgIHZhciBzaGFwaW5nID0gW107XG5cbiAgICB2YXIgeCA9IHRyYW5zbGF0ZVswXTtcbiAgICB2YXIgeSA9IHRyYW5zbGF0ZVsxXTtcbiAgICB2YXIgaWQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWQgPSB0ZXh0LmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIGdseXBoID0gZ2x5cGhzW2lkXTtcblxuICAgICAgICBpZiAoaWQgPT09IDAgfHwgIWdseXBoKSBjb250aW51ZTtcblxuICAgICAgICBzaGFwaW5nLnB1c2goe1xuICAgICAgICAgICAgZm9udHN0YWNrOiBuYW1lLFxuICAgICAgICAgICAgZ2x5cGg6IGlkLFxuICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgIHk6IHlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgeCArPSBnbHlwaC5hZHZhbmNlICsgc3BhY2luZztcbiAgICB9XG5cbiAgICBpZiAoIXNoYXBpbmcubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgICBzaGFwaW5nID0gbGluZXdyYXAoc2hhcGluZywgZ2x5cGhzLCBsaW5lSGVpZ2h0LCBtYXhXaWR0aCwgaG9yaXpvbnRhbEFsaWduLCB2ZXJ0aWNhbEFsaWduLCBqdXN0aWZ5KTtcblxuICAgIHJldHVybiBzaGFwaW5nO1xufVxuXG52YXIgYnJlYWthYmxlID0geyAzMjogdHJ1ZSB9OyAvLyBDdXJyZW50bHkgb25seSBicmVha3MgYXQgcmVndWxhciBzcGFjZXNcblxuZnVuY3Rpb24gbGluZXdyYXAoc2hhcGluZywgZ2x5cGhzLCBsaW5lSGVpZ2h0LCBtYXhXaWR0aCwgaG9yaXpvbnRhbEFsaWduLCB2ZXJ0aWNhbEFsaWduLCBqdXN0aWZ5KSB7XG4gICAgdmFyIGxhc3RTYWZlQnJlYWsgPSBudWxsO1xuXG4gICAgdmFyIGxlbmd0aEJlZm9yZUN1cnJlbnRMaW5lID0gMDtcbiAgICB2YXIgbGluZVN0YXJ0SW5kZXggPSAwO1xuICAgIHZhciBsaW5lID0gMDtcblxuICAgIHZhciBtYXhMaW5lTGVuZ3RoID0gMDtcblxuICAgIGlmIChtYXhXaWR0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNoYXBpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzaGFwZSA9IHNoYXBpbmdbaV07XG5cbiAgICAgICAgICAgIHNoYXBlLnggLT0gbGVuZ3RoQmVmb3JlQ3VycmVudExpbmU7XG4gICAgICAgICAgICBzaGFwZS55ICs9IGxpbmVIZWlnaHQgKiBsaW5lO1xuXG4gICAgICAgICAgICBpZiAoc2hhcGUueCA+IG1heFdpZHRoICYmIGxhc3RTYWZlQnJlYWsgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgIHZhciBsaW5lTGVuZ3RoID0gc2hhcGluZ1tsYXN0U2FmZUJyZWFrICsgMV0ueDtcbiAgICAgICAgICAgICAgICBtYXhMaW5lTGVuZ3RoID0gTWF0aC5tYXgobGluZUxlbmd0aCwgbWF4TGluZUxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gbGFzdFNhZmVCcmVhayArIDE7IGsgPD0gaTsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNoYXBpbmdba10ueSArPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBzaGFwaW5nW2tdLnggLT0gbGluZUxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoanVzdGlmeSkge1xuICAgICAgICAgICAgICAgICAgICBqdXN0aWZ5TGluZShzaGFwaW5nLCBnbHlwaHMsIGxpbmVTdGFydEluZGV4LCBsYXN0U2FmZUJyZWFrIC0gMSwganVzdGlmeSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGluZVN0YXJ0SW5kZXggPSBsYXN0U2FmZUJyZWFrICsgMTtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gbnVsbDtcbiAgICAgICAgICAgICAgICBsZW5ndGhCZWZvcmVDdXJyZW50TGluZSArPSBsaW5lTGVuZ3RoO1xuICAgICAgICAgICAgICAgIGxpbmUrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGJyZWFrYWJsZVtzaGFwZS5nbHlwaF0pIHtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIG1heExpbmVMZW5ndGggPSBtYXhMaW5lTGVuZ3RoIHx8IHNoYXBpbmdbc2hhcGluZy5sZW5ndGggLSAxXS54O1xuXG4gICAganVzdGlmeUxpbmUoc2hhcGluZywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgc2hhcGluZy5sZW5ndGggLSAxLCBqdXN0aWZ5KTtcbiAgICBhbGlnbihzaGFwaW5nLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpO1xuICAgIHJldHVybiBzaGFwaW5nO1xufVxuXG5mdW5jdGlvbiBqdXN0aWZ5TGluZShzaGFwaW5nLCBnbHlwaHMsIHN0YXJ0LCBlbmQsIGp1c3RpZnkpIHtcbiAgICB2YXIgbGFzdEFkdmFuY2UgPSBnbHlwaHNbc2hhcGluZ1tlbmRdLmdseXBoXS5hZHZhbmNlO1xuICAgIHZhciBsaW5lSW5kZW50ID0gKHNoYXBpbmdbZW5kXS54ICsgbGFzdEFkdmFuY2UpICoganVzdGlmeTtcblxuICAgIGZvciAodmFyIGogPSBzdGFydDsgaiA8PSBlbmQ7IGorKykge1xuICAgICAgICBzaGFwaW5nW2pdLnggLT0gbGluZUluZGVudDtcbiAgICB9XG5cbn1cblxuZnVuY3Rpb24gYWxpZ24oc2hhcGluZywganVzdGlmeSwgaG9yaXpvbnRhbEFsaWduLCB2ZXJ0aWNhbEFsaWduLCBtYXhMaW5lTGVuZ3RoLCBsaW5lSGVpZ2h0LCBsaW5lKSB7XG4gICAgdmFyIHNoaWZ0WCA9IChqdXN0aWZ5IC0gaG9yaXpvbnRhbEFsaWduKSAqIG1heExpbmVMZW5ndGg7XG4gICAgdmFyIHNoaWZ0WSA9ICgtdmVydGljYWxBbGlnbiAqIChsaW5lICsgMSkgKyAwLjUpICogbGluZUhlaWdodDtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgc2hhcGluZy5sZW5ndGg7IGorKykge1xuICAgICAgICBzaGFwaW5nW2pdLnggKz0gc2hpZnRYO1xuICAgICAgICBzaGFwaW5nW2pdLnkgKz0gc2hpZnRZO1xuICAgIH1cbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wuanMnKSxcbiAgICBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbS5qcycpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBdHRyaWJ1dGlvbjtcblxuZnVuY3Rpb24gQXR0cmlidXRpb24oKSB7fVxuXG5BdHRyaWJ1dGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsLWF0dHJpYicsXG4gICAgICAgICAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBET00uY3JlYXRlKCdkaXYnLCBjbGFzc05hbWUsIG1hcC5jb250YWluZXIpO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICBtYXAub24oJ3NvdXJjZS5hZGQnLCB0aGlzLl91cGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICAgIG1hcC5vbignbW92ZWVuZCcsIHRoaXMuX3VwZGF0ZUVkaXRMaW5rLmJpbmQodGhpcykpO1xuXG4gICAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfSxcblxuICAgIF91cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXR0cmlidXRpb25zID0gW107XG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX21hcC5zb3VyY2VzKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gdGhpcy5fbWFwLnNvdXJjZXNbaWRdO1xuICAgICAgICAgICAgaWYgKHNvdXJjZS50aWxlSlNPTiAmJiBzb3VyY2UudGlsZUpTT04uYXR0cmlidXRpb24pIHtcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGlvbnMucHVzaChzb3VyY2UudGlsZUpTT04uYXR0cmlidXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NvbnRhaW5lci5pbm5lckhUTUwgPSBhdHRyaWJ1dGlvbnMuam9pbignIHwgJyk7XG4gICAgICAgIHRoaXMuX2VkaXRMaW5rID0gdGhpcy5fY29udGFpbmVyLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ21hcGJveC1pbXByb3ZlLW1hcCcpWzBdO1xuICAgICAgICB0aGlzLl91cGRhdGVFZGl0TGluaygpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlRWRpdExpbms6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fZWRpdExpbmspIHtcbiAgICAgICAgICAgIHZhciBjZW50ZXIgPSB0aGlzLl9tYXAuZ2V0Q2VudGVyKCk7XG4gICAgICAgICAgICB0aGlzLl9lZGl0TGluay5ocmVmID0gJ2h0dHBzOi8vd3d3Lm1hcGJveC5jb20vbWFwLWZlZWRiYWNrLyMvJyArXG4gICAgICAgICAgICAgICAgICAgIGNlbnRlci5sbmcgKyAnLycgKyBjZW50ZXIubGF0ICsgJy8nICsgTWF0aC5yb3VuZCh0aGlzLl9tYXAuZ2V0Wm9vbSgpICsgMSk7XG4gICAgICAgIH1cbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBDb250cm9sO1xuXG5mdW5jdGlvbiBDb250cm9sKCkge31cblxuQ29udHJvbC5wcm90b3R5cGUgPSB7XG5cdGFkZFRvOiBmdW5jdGlvbihtYXApIHtcblx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cdFx0dGhpcy5fY29udGFpbmVyID0gdGhpcy5vbkFkZChtYXApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdHJlbW92ZTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2NvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0aWYgKHRoaXMub25SZW1vdmUpIHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcblx0XHR0aGlzLl9tYXAgPSBudWxsO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbC5qcycpLFxuICAgIERPTSA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvZG9tLmpzJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE5hdmlnYXRpb247XG5cbmZ1bmN0aW9uIE5hdmlnYXRpb24oKSB7fVxuXG5OYXZpZ2F0aW9uLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChDb250cm9sLCB7XG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB2YXIgY2xhc3NOYW1lID0gJ21hcGJveGdsLWN0cmwtbmF2JztcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgY2xhc3NOYW1lLCBtYXAuY29udGFpbmVyKTtcblxuICAgICAgICB0aGlzLl96b29tSW5CdXR0b24gPSB0aGlzLl9jcmVhdGVCdXR0b24oY2xhc3NOYW1lICsgJy16b29tLWluJywgbWFwLnpvb21Jbi5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctem9vbS1vdXQnLCBtYXAuem9vbU91dC5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl9jb21wYXNzID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctY29tcGFzcycsIG1hcC5yZXNldE5vcnRoLmJpbmQobWFwKSk7XG5cbiAgICAgICAgdmFyIGNvbXBhc3NDYW52YXMgPSB0aGlzLl9jb21wYXNzQ2FudmFzID0gRE9NLmNyZWF0ZSgnY2FudmFzJywgY2xhc3NOYW1lICsgJy1jb21wYXNzLWNhbnZhcycsIHRoaXMuX2NvbXBhc3MpO1xuICAgICAgICBjb21wYXNzQ2FudmFzLnN0eWxlLmNzc1RleHQgPSAnd2lkdGg6MjZweDsgaGVpZ2h0OjI2cHg7JztcbiAgICAgICAgY29tcGFzc0NhbnZhcy53aWR0aCA9IDI2ICogMjtcbiAgICAgICAgY29tcGFzc0NhbnZhcy5oZWlnaHQgPSAyNiAqIDI7XG5cbiAgICAgICAgdGhpcy5fY29tcGFzcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vbkNvbXBhc3NEb3duLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLl9vbkNvbXBhc3NNb3ZlID0gdGhpcy5fb25Db21wYXNzTW92ZS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLl9vbkNvbXBhc3NVcCA9IHRoaXMuX29uQ29tcGFzc1VwLmJpbmQodGhpcyk7XG5cbiAgICAgICAgdGhpcy5fY29tcGFzc0N0eCA9IGNvbXBhc3NDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgICBtYXAub24oJ3JvdGF0ZScsIHRoaXMuX2RyYXdOb3J0aC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5fZHJhd05vcnRoKCk7XG5cbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc0Rvd246IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgRE9NLmRpc2FibGVEcmFnKCk7XG5cbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Db21wYXNzTW92ZSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkNvbXBhc3NVcCk7XG4gICAgICAgIHRoaXMuX3ByZXZYID0gZS5zY3JlZW5YO1xuXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSxcblxuICAgIF9vbkNvbXBhc3NNb3ZlOiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHZhciB4ID0gZS5zY3JlZW5YLFxuICAgICAgICAgICAgZCA9IHggPCAyID8gLTUgOiAvLyBsZWZ0IGVkZ2Ugb2YgdGhlIHNjcmVlbiwgY29udGludWUgcm90YXRpbmdcbiAgICAgICAgICAgICAgICB4ID4gd2luZG93LnNjcmVlbi53aWR0aCAtIDIgPyA1IDogLy8gcmlnaHQgZWRnZVxuICAgICAgICAgICAgICAgICh4IC0gdGhpcy5fcHJldlgpIC8gNDtcblxuICAgICAgICB0aGlzLl9tYXAuc2V0QmVhcmluZyh0aGlzLl9tYXAuZ2V0QmVhcmluZygpIC0gZCk7XG4gICAgICAgIHRoaXMuX3ByZXZYID0gZS5zY3JlZW5YO1xuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc1VwOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Db21wYXNzTW92ZSk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkNvbXBhc3NVcCk7XG4gICAgICAgIERPTS5lbmFibGVEcmFnKCk7XG4gICAgfSxcblxuICAgIF9jcmVhdGVCdXR0b246IGZ1bmN0aW9uKGNsYXNzTmFtZSwgZm4pIHtcbiAgICAgICAgdmFyIGEgPSBET00uY3JlYXRlKCdhJywgY2xhc3NOYW1lLCB0aGlzLl9jb250YWluZXIpO1xuICAgICAgICBhLmhyZWYgPSAnIyc7XG4gICAgICAgIGEuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9LFxuXG4gICAgX2RyYXdOb3J0aDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciByYWQgPSAyMCxcbiAgICAgICAgICAgIHdpZHRoID0gOCxcbiAgICAgICAgICAgIGNlbnRlciA9IDI2LFxuICAgICAgICAgICAgYW5nbGUgPSB0aGlzLl9tYXAudHJhbnNmb3JtLmFuZ2xlICsgKE1hdGguUEkgLyAyKSxcbiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2NvbXBhc3NDdHg7XG5cbiAgICAgICAgdGhpcy5fY29tcGFzc0NhbnZhcy53aWR0aCA9IHRoaXMuX2NvbXBhc3NDYW52YXMud2lkdGg7XG5cbiAgICAgICAgY3R4LnRyYW5zbGF0ZShjZW50ZXIsIGNlbnRlcik7XG4gICAgICAgIGN0eC5yb3RhdGUoYW5nbGUpO1xuXG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9ICcjMDAwJztcbiAgICAgICAgY3R4LmxpbmVUbygwLCAtd2lkdGgpO1xuICAgICAgICBjdHgubGluZVRvKC1yYWQsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIHdpZHRoKTtcbiAgICAgICAgY3R4LmZpbGwoKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnI2JiYic7XG4gICAgICAgIGN0eC5tb3ZlVG8oMCwgMCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgd2lkdGgpO1xuICAgICAgICBjdHgubGluZVRvKHJhZCwgMCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmZpbGwoKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9ICcjZmZmJztcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IDQ7XG4gICAgICAgIGN0eC5tb3ZlVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbygwLCB3aWR0aCk7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwuanMnKSxcbiAgICBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyLmpzJyksXG4gICAgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdGxuZy5qcycpLFxuICAgIExhdExuZ0JvdW5kcyA9IHJlcXVpcmUoJy4uL2dlby9sYXRsbmdib3VuZHMuanMnKSxcbiAgICBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbnV0aWwuZXh0ZW5kKGV4cG9ydHMsIHtcbiAgICBpc0Vhc2luZzogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9zdG9wRm47XG4gICAgfSxcblxuICAgIHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3N0b3BGbikge1xuICAgICAgICAgICAgdGhpcy5fc3RvcEZuKCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fc3RvcEZuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBwYW5CeTogZnVuY3Rpb24ob2Zmc2V0LCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMucGFuVG8odGhpcy50cmFuc2Zvcm0uY2VudGVyLCB1dGlsLmV4dGVuZCh7b2Zmc2V0OiBQb2ludC5jb252ZXJ0KG9mZnNldCkubXVsdCgtMSl9LCBvcHRpb25zKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBwYW5UbzogZnVuY3Rpb24obGF0bG5nLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIGxhdGxuZyA9IExhdExuZy5jb252ZXJ0KGxhdGxuZyk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBlYXNpbmc6IHV0aWwuZWFzZSxcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkucm90YXRlKC10ci5hbmdsZSksXG4gICAgICAgICAgICBmcm9tID0gdHIucG9pbnQsXG4gICAgICAgICAgICB0byA9IHRyLnByb2plY3QobGF0bG5nKS5zdWIob2Zmc2V0KTtcblxuICAgICAgICBpZiAoIW9wdGlvbnMubm9Nb3ZlU3RhcnQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zdG9wRm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdChvcHRpb25zLmVhc2luZyh0KSkpKTtcbiAgICAgICAgICAgIHRoaXMuX21vdmUoKTtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcblxuICAgICAgICB9LCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlID8gMCA6IG9wdGlvbnMuZHVyYXRpb24sIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvLyBab29tcyB0byBhIGNlcnRhaW4gem9vbSBsZXZlbCB3aXRoIGVhc2luZy5cbiAgICB6b29tVG86IGZ1bmN0aW9uKHpvb20sIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDBcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICBhcm91bmQgPSB0ci5jZW50ZXIsXG4gICAgICAgICAgICBlYXNpbmcgPSB0aGlzLl91cGRhdGVFYXNpbmcob3B0aW9ucy5kdXJhdGlvbiwgem9vbSwgb3B0aW9ucy5lYXNpbmcpLFxuICAgICAgICAgICAgc3RhcnRab29tID0gdHIuem9vbTtcblxuICAgICAgICBpZiAob3B0aW9ucy5hcm91bmQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IExhdExuZy5jb252ZXJ0KG9wdGlvbnMuYXJvdW5kKTtcbiAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLm9mZnNldCkge1xuICAgICAgICAgICAgYXJvdW5kID0gdHIucG9pbnRMb2NhdGlvbih0ci5jZW50ZXJQb2ludC5hZGQoUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlKSBvcHRpb25zLmR1cmF0aW9uID0gMDtcblxuICAgICAgICBpZiAoIXRoaXMuem9vbWluZykge1xuICAgICAgICAgICAgdGhpcy56b29taW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zdG9wRm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgIHRyLnNldFpvb21Bcm91bmQodXRpbC5pbnRlcnAoc3RhcnRab29tLCB6b29tLCBlYXNpbmcodCkpLCBhcm91bmQpO1xuXG4gICAgICAgICAgICB0aGlzLnN0eWxlLmFuaW1hdGlvbkxvb3Auc2V0KDMwMCk7IC8vIHRleHQgZmFkaW5nXG4gICAgICAgICAgICB0aGlzLl9tb3ZlKHRydWUpO1xuXG4gICAgICAgICAgICBpZiAodCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWFzZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZHVyYXRpb24gPj0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnpvb21pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSwgb3B0aW9ucy5kdXJhdGlvbiwgdGhpcyk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuZHVyYXRpb24gPCAyMDApIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9vblpvb21FbmQpO1xuICAgICAgICAgICAgdGhpcy5fb25ab29tRW5kID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnpvb21pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCAyMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHpvb21JbjogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSArIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICB6b29tT3V0OiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuem9vbVRvKHRoaXMuZ2V0Wm9vbSgpIC0gMSwgb3B0aW9ucyk7XG4gICAgfSxcblxuICAgIHJvdGF0ZVRvOiBmdW5jdGlvbihiZWFyaW5nLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2VcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICBzdGFydCA9IHRoaXMuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgYXJvdW5kID0gdHIuY2VudGVyO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmFyb3VuZCkge1xuICAgICAgICAgICAgYXJvdW5kID0gTGF0TG5nLmNvbnZlcnQob3B0aW9ucy5hcm91bmQpO1xuICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMub2Zmc2V0KSB7XG4gICAgICAgICAgICBhcm91bmQgPSB0ci5wb2ludExvY2F0aW9uKHRyLmNlbnRlclBvaW50LmFkZChQb2ludC5jb252ZXJ0KG9wdGlvbnMub2Zmc2V0KSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yb3RhdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fc3RvcEZuID0gYnJvd3Nlci50aW1lZChmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICBpZiAodCA9PT0gMSkgeyB0aGlzLnJvdGF0aW5nID0gZmFsc2U7IH1cbiAgICAgICAgICAgIHRyLnNldEJlYXJpbmdBcm91bmQodXRpbC5pbnRlcnAoc3RhcnQsIGJlYXJpbmcsIG9wdGlvbnMuZWFzaW5nKHQpKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIHRoaXMuX21vdmUoZmFsc2UsIHRydWUpLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgfSwgb3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSA/IDAgOiBvcHRpb25zLmR1cmF0aW9uLCB0aGlzKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgcmVzZXROb3J0aDogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3RhdGVUbygwLCB1dGlsLmV4dGVuZCh7ZHVyYXRpb246IDEwMDB9LCBvcHRpb25zKSk7XG4gICAgfSxcblxuICAgIGZpdEJvdW5kczogZnVuY3Rpb24oYm91bmRzLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIG1heFpvb206IEluZmluaXR5XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIGJvdW5kcyA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KGJvdW5kcyk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLFxuICAgICAgICAgICAgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG53ID0gdHIucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxuICAgICAgICAgICAgc2UgPSB0ci5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSksXG4gICAgICAgICAgICBzaXplID0gc2Uuc3ViKG53KSxcbiAgICAgICAgICAgIGNlbnRlciA9IHRyLnVucHJvamVjdChudy5hZGQoc2UpLmRpdigyKSksXG5cbiAgICAgICAgICAgIHNjYWxlWCA9ICh0ci53aWR0aCAtIG9wdGlvbnMucGFkZGluZyAqIDIgLSBNYXRoLmFicyhvZmZzZXQueCkgKiAyKSAvIHNpemUueCxcbiAgICAgICAgICAgIHNjYWxlWSA9ICh0ci5oZWlnaHQgLSBvcHRpb25zLnBhZGRpbmcgKiAyIC0gTWF0aC5hYnMob2Zmc2V0LnkpICogMikgLyBzaXplLnksXG5cbiAgICAgICAgICAgIHpvb20gPSBNYXRoLm1pbih0ci5zY2FsZVpvb20odHIuc2NhbGUgKiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSkpLCBvcHRpb25zLm1heFpvb20pO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zLmxpbmVhciA/XG4gICAgICAgICAgICB0aGlzLmVhc2VUbyhjZW50ZXIsIHpvb20sIDAsIG9wdGlvbnMpIDpcbiAgICAgICAgICAgIHRoaXMuZmx5VG8oY2VudGVyLCB6b29tLCAwLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgZWFzZVRvOiBmdW5jdGlvbihsYXRsbmcsIHpvb20sIGJlYXJpbmcsIG9wdGlvbnMpIHtcblxuICAgICAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe1xuICAgICAgICAgICAgb2Zmc2V0OiBbMCwgMF0sXG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2VcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgbGF0bG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcblxuICAgICAgICB2YXIgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgc3RhcnRab29tID0gdGhpcy5nZXRab29tKCksXG4gICAgICAgICAgICBzdGFydEJlYXJpbmcgPSB0aGlzLmdldEJlYXJpbmcoKTtcblxuICAgICAgICB6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gc3RhcnRab29tIDogem9vbTtcbiAgICAgICAgYmVhcmluZyA9IGJlYXJpbmcgPT09IHVuZGVmaW5lZCA/IHN0YXJ0QmVhcmluZyA6IGJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldC5kaXYoc2NhbGUpKSxcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKHRvLnN1Yihmcm9tKS5kaXYoMSAtIDEgLyBzY2FsZSkpKTtcblxuICAgICAgICBpZiAoem9vbSAhPT0gc3RhcnRab29tKSB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuXG4gICAgICAgIHRoaXMuX3N0b3BGbiA9IGJyb3dzZXIudGltZWQoZnVuY3Rpb24gKHQpIHtcbiAgICAgICAgICAgIHZhciBrID0gb3B0aW9ucy5lYXNpbmcodCk7XG5cbiAgICAgICAgICAgIGlmICh6b29tICE9PSBzdGFydFpvb20pIHtcbiAgICAgICAgICAgICAgICB0ci5zZXRab29tQXJvdW5kKHN0YXJ0Wm9vbSArIGsgKiAoem9vbSAtIHN0YXJ0Wm9vbSksIGFyb3VuZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYmVhcmluZyAhPT0gc3RhcnRCZWFyaW5nKSB7XG4gICAgICAgICAgICAgICAgdHIuYmVhcmluZyA9IHV0aWwuaW50ZXJwKHN0YXJ0QmVhcmluZywgYmVhcmluZywgayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoMzAwKTsgLy8gdGV4dCBmYWRpbmdcbiAgICAgICAgICAgIHRoaXMuX21vdmUoem9vbSAhPT0gc3RhcnRab29tLCBiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpO1xuXG4gICAgICAgICAgICBpZiAodCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9LCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlID8gMCA6IG9wdGlvbnMuZHVyYXRpb24sIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBmbHlUbzogZnVuY3Rpb24obGF0bG5nLCB6b29tLCBiZWFyaW5nLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdLFxuICAgICAgICAgICAgc3BlZWQ6IDEuMixcbiAgICAgICAgICAgIGN1cnZlOiAxLjQyLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2VcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgbGF0bG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcblxuICAgICAgICB2YXIgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgc3RhcnRab29tID0gdGhpcy5nZXRab29tKCksXG4gICAgICAgICAgICBzdGFydEJlYXJpbmcgPSB0aGlzLmdldEJlYXJpbmcoKTtcblxuICAgICAgICB6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gc3RhcnRab29tIDogem9vbTtcbiAgICAgICAgYmVhcmluZyA9IGJlYXJpbmcgPT09IHVuZGVmaW5lZCA/IHN0YXJ0QmVhcmluZyA6IGJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldC5kaXYoc2NhbGUpKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0VmlldyhsYXRsbmcsIHpvb20sIGJlYXJpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YXJ0V29ybGRTaXplID0gdHIud29ybGRTaXplLFxuICAgICAgICAgICAgcmhvID0gb3B0aW9ucy5jdXJ2ZSxcbiAgICAgICAgICAgIFYgPSBvcHRpb25zLnNwZWVkLFxuXG4gICAgICAgICAgICB3MCA9IE1hdGgubWF4KHRyLndpZHRoLCB0ci5oZWlnaHQpLFxuICAgICAgICAgICAgdzEgPSB3MCAvIHNjYWxlLFxuICAgICAgICAgICAgdTEgPSB0by5zdWIoZnJvbSkubWFnKCksXG4gICAgICAgICAgICByaG8yID0gcmhvICogcmhvO1xuXG4gICAgICAgIGZ1bmN0aW9uIHIoaSkge1xuICAgICAgICAgICAgdmFyIGIgPSAodzEgKiB3MSAtIHcwICogdzAgKyAoaSA/IC0xIDogMSkgKiByaG8yICogcmhvMiAqIHUxICogdTEpIC8gKDIgKiAoaSA/IHcxIDogdzApICogcmhvMiAqIHUxKTtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmxvZyhNYXRoLnNxcnQoYiAqIGIgKyAxKSAtIGIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gc2luaChuKSB7IHJldHVybiAoTWF0aC5leHAobikgLSBNYXRoLmV4cCgtbikpIC8gMjsgfVxuICAgICAgICBmdW5jdGlvbiBjb3NoKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSArIE1hdGguZXhwKC1uKSkgLyAyOyB9XG4gICAgICAgIGZ1bmN0aW9uIHRhbmgobikgeyByZXR1cm4gc2luaChuKSAvIGNvc2gobik7IH1cblxuICAgICAgICB2YXIgcjAgPSByKDApLFxuICAgICAgICAgICAgdyA9IGZ1bmN0aW9uIChzKSB7IHJldHVybiAoY29zaChyMCkgLyBjb3NoKHIwICsgcmhvICogcykpOyB9LFxuICAgICAgICAgICAgdSA9IGZ1bmN0aW9uIChzKSB7IHJldHVybiB3MCAqICgoY29zaChyMCkgKiB0YW5oKHIwICsgcmhvICogcykgLSBzaW5oKHIwKSkgLyByaG8yKSAvIHUxOyB9LFxuICAgICAgICAgICAgUyA9IChyKDEpIC0gcjApIC8gcmhvO1xuXG4gICAgICAgIGlmIChNYXRoLmFicyh1MSkgPCAwLjAwMDAwMSkge1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKHcwIC0gdzEpIDwgMC4wMDAwMDEpIHJldHVybiB0aGlzO1xuXG4gICAgICAgICAgICB2YXIgayA9IHcxIDwgdzAgPyAtMSA6IDE7XG4gICAgICAgICAgICBTID0gTWF0aC5hYnMoTWF0aC5sb2codzEgLyB3MCkpIC8gcmhvO1xuXG4gICAgICAgICAgICB1ID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuICAgICAgICAgICAgdyA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIE1hdGguZXhwKGsgKiByaG8gKiBzKTsgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkdXJhdGlvbiA9IDEwMDAgKiBTIC8gVjtcblxuICAgICAgICB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9IGJlYXJpbmcpIHRoaXMucm90YXRpbmcgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fc3RvcEZuID0gYnJvd3Nlci50aW1lZChmdW5jdGlvbiAodCkge1xuICAgICAgICAgICAgdmFyIGsgPSBvcHRpb25zLmVhc2luZyh0KSxcbiAgICAgICAgICAgICAgICBzID0gayAqIFMsXG4gICAgICAgICAgICAgICAgdXMgPSB1KHMpO1xuXG4gICAgICAgICAgICB0ci56b29tID0gc3RhcnRab29tICsgdHIuc2NhbGVab29tKDEgLyB3KHMpKTtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdCh1cykpLCBzdGFydFdvcmxkU2l6ZSk7XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gdXRpbC5pbnRlcnAoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdHlsZS5hbmltYXRpb25Mb29wLnNldCgzMDApOyAvLyB0ZXh0IGZhZGluZ1xuXG4gICAgICAgICAgICB0aGlzLl9tb3ZlKHRydWUsIGJlYXJpbmcgIT09IHN0YXJ0QmVhcmluZyk7XG5cbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhpcy56b29taW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBkdXJhdGlvbiwgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF91cGRhdGVFYXNpbmc6IGZ1bmN0aW9uKGR1cmF0aW9uLCB6b29tLCBiZXppZXIpIHtcbiAgICAgICAgdmFyIGVhc2luZztcblxuICAgICAgICBpZiAodGhpcy5lYXNlKSB7XG4gICAgICAgICAgICB2YXIgZWFzZSA9IHRoaXMuZWFzZSxcbiAgICAgICAgICAgICAgICB0ID0gKERhdGUubm93KCkgLSBlYXNlLnN0YXJ0KSAvIGVhc2UuZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgc3BlZWQgPSBlYXNlLmVhc2luZyh0ICsgMC4wMSkgLSBlYXNlLmVhc2luZyh0KSxcblxuICAgICAgICAgICAgICAgIC8vIFF1aWNrIGhhY2sgdG8gbWFrZSBuZXcgYmV6aWVyIHRoYXQgaXMgY29udGludW91cyB3aXRoIGxhc3RcbiAgICAgICAgICAgICAgICB4ID0gMC4yNyAvIE1hdGguc3FydChzcGVlZCAqIHNwZWVkICsgMC4wMDAxKSAqIDAuMDEsXG4gICAgICAgICAgICAgICAgeSA9IE1hdGguc3FydCgwLjI3ICogMC4yNyAtIHggKiB4KTtcblxuICAgICAgICAgICAgZWFzaW5nID0gdXRpbC5iZXppZXIoeCwgeSwgMC4yNSwgMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlYXNpbmcgPSBiZXppZXIgPyB1dGlsLmJlemllci5hcHBseSh1dGlsLCBiZXppZXIpIDogdXRpbC5lYXNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3RvcmUgaW5mb3JtYXRpb24gb24gY3VycmVudCBlYXNpbmdcbiAgICAgICAgdGhpcy5lYXNlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCksXG4gICAgICAgICAgICB0bzogTWF0aC5wb3coMiwgem9vbSksXG4gICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24sXG4gICAgICAgICAgICBlYXNpbmc6IGVhc2luZ1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBlYXNpbmc7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBJbnRlcmFjdGlvbiA9IHJlcXVpcmUoJy4vaW50ZXJhY3Rpb24uanMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbC5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEhhbmRsZXJzO1xuXG5mdW5jdGlvbiBIYW5kbGVycyhtYXApIHtcblxuICAgIHZhciByb3RhdGVFbmQ7XG5cbiAgICB2YXIgaW5lcnRpYUxpbmVhcml0eSA9IDAuMixcbiAgICAgICAgaW5lcnRpYUVhc2luZyA9IHV0aWwuYmV6aWVyKDAsIDAsIGluZXJ0aWFMaW5lYXJpdHksIDEpO1xuXG4gICAgdGhpcy5pbnRlcmFjdGlvbiA9IG5ldyBJbnRlcmFjdGlvbihtYXAuY29udGFpbmVyKVxuICAgICAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ2NsaWNrJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignaG92ZXInLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBtYXAuZmlyZSgnaG92ZXInLCBlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdkb3duJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLnN0b3AoKTtcbiAgICAgICAgICAgIG1hcC5yZXNpemUoKTtcbiAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdwYW4nLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBtYXAuc3RvcCgpO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5wYW5CeShlLm9mZnNldCk7XG4gICAgICAgICAgICBtYXAuX21vdmUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdwYW5lbmQnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBpZiAoIWUuaW5lcnRpYSkgbWFwLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGNvbnZlcnQgdmVsb2NpdHkgdG8gcHgvcyAmIGFkanVzdCBmb3IgaW5jcmVhc2VkIGluaXRpYWwgYW5pbWF0aW9uIHNwZWVkIHdoZW4gZWFzaW5nIG91dFxuICAgICAgICAgICAgICAgIHZhciB2ZWxvY2l0eSA9IGUuaW5lcnRpYS5tdWx0KDEwMDAgKiBpbmVydGlhTGluZWFyaXR5KSxcbiAgICAgICAgICAgICAgICAgICAgc3BlZWQgPSB2ZWxvY2l0eS5tYWcoKTtcblxuICAgICAgICAgICAgICAgIHZhciBtYXhTcGVlZCA9IDQwMDA7IC8vIHB4L3NcblxuICAgICAgICAgICAgICAgIGlmIChzcGVlZCA+PSBtYXhTcGVlZCkge1xuICAgICAgICAgICAgICAgICAgICBzcGVlZCA9IG1heFNwZWVkO1xuICAgICAgICAgICAgICAgICAgICB2ZWxvY2l0eS5fdW5pdCgpLl9tdWx0KG1heFNwZWVkKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgZGVjZWxlcmF0aW9uID0gODAwMCwgLy8gcHgvc14yXG4gICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gc3BlZWQgLyAoZGVjZWxlcmF0aW9uICogaW5lcnRpYUxpbmVhcml0eSksXG4gICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IHZlbG9jaXR5Lm11bHQoLWR1cmF0aW9uIC8gMikucm91bmQoKTtcblxuICAgICAgICAgICAgICAgIG1hcC5wYW5CeShvZmZzZXQsIHtcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uICogMTAwMCxcbiAgICAgICAgICAgICAgICAgICAgZWFzaW5nOiBpbmVydGlhRWFzaW5nLFxuICAgICAgICAgICAgICAgICAgICBub01vdmVTdGFydDogdHJ1ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ3pvb20nLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBTY2FsZSBieSBzaWdtb2lkIG9mIHNjcm9sbCB3aGVlbCBkZWx0YS5cbiAgICAgICAgICAgIHZhciBzY2FsZSA9IDIgLyAoMSArIE1hdGguZXhwKC1NYXRoLmFicyhlLmRlbHRhIC8gMTAwKSkpO1xuICAgICAgICAgICAgaWYgKGUuZGVsdGEgPCAwICYmIHNjYWxlICE9PSAwKSBzY2FsZSA9IDEgLyBzY2FsZTtcblxuICAgICAgICAgICAgdmFyIGZyb21TY2FsZSA9IG1hcC5lYXNlICYmIGlzRmluaXRlKGUuZGVsdGEpID8gbWFwLmVhc2UudG8gOiBtYXAudHJhbnNmb3JtLnNjYWxlLFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gIWlzRmluaXRlKGUuZGVsdGEpID8gODAwIDogZS5zb3VyY2UgPT0gJ3RyYWNrcGFkJyA/IDAgOiAzMDA7XG5cbiAgICAgICAgICAgIG1hcC56b29tVG8obWFwLnRyYW5zZm9ybS5zY2FsZVpvb20oZnJvbVNjYWxlICogc2NhbGUpLCB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICAgICAgICAgIGFyb3VuZDogbWFwLnVucHJvamVjdChlLnBvaW50KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbigncm90YXRlJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgdmFyIGNlbnRlciA9IG1hcC50cmFuc2Zvcm0uY2VudGVyUG9pbnQsIC8vIENlbnRlciBvZiByb3RhdGlvblxuICAgICAgICAgICAgICAgIHN0YXJ0VG9DZW50ZXIgPSBlLnN0YXJ0LnN1YihjZW50ZXIpLFxuICAgICAgICAgICAgICAgIHN0YXJ0VG9DZW50ZXJEaXN0ID0gc3RhcnRUb0NlbnRlci5tYWcoKTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlIGZpcnN0IGNsaWNrIHdhcyB0b28gY2xvc2UgdG8gdGhlIGNlbnRlciwgbW92ZSB0aGUgY2VudGVyIG9mIHJvdGF0aW9uIGJ5IDIwMCBwaXhlbHNcbiAgICAgICAgICAgIC8vIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGNsaWNrLlxuICAgICAgICAgICAgaWYgKHN0YXJ0VG9DZW50ZXJEaXN0IDwgMjAwKSB7XG4gICAgICAgICAgICAgICAgY2VudGVyID0gZS5zdGFydC5hZGQobmV3IFBvaW50KC0yMDAsIDApLl9yb3RhdGUoc3RhcnRUb0NlbnRlci5hbmdsZSgpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBiZWFyaW5nRGlmZiA9IGUucHJldi5zdWIoY2VudGVyKS5hbmdsZVdpdGgoZS5jdXJyZW50LnN1YihjZW50ZXIpKSAvIE1hdGguUEkgKiAxODA7XG4gICAgICAgICAgICBtYXAudHJhbnNmb3JtLmJlYXJpbmcgPSBtYXAuZ2V0QmVhcmluZygpIC0gYmVhcmluZ0RpZmY7XG5cbiAgICAgICAgICAgIG1hcC5fbW92ZShmYWxzZSwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQocm90YXRlRW5kKTtcbiAgICAgICAgICAgIHJvdGF0ZUVuZCA9IHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIG1hcC5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIG1hcC5fcmVyZW5kZXIoKTtcbiAgICAgICAgICAgIH0sIDIwMCk7XG4gICAgICAgIH0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEhhc2g7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsLmpzJyk7XG5cbmZ1bmN0aW9uIEhhc2gobWFwKSB7XG4gICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2hhc2hjaGFuZ2UnLCB0aGlzLm9uaGFzaC5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgbWFwLm9uKCdtb3ZlJywgdXRpbC5kZWJvdW5jZSh0aGlzLnVwZGF0ZUhhc2guYmluZCh0aGlzKSwgMTAwKSk7XG59XG5cbkhhc2gucHJvdG90eXBlID0ge1xuICAgIG9uaGFzaDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBsb2MgPSBsb2NhdGlvbi5oYXNoLnJlcGxhY2UoJyMnLCAnJykuc3BsaXQoJy8nKTtcbiAgICAgICAgaWYgKGxvYy5sZW5ndGggPj0gMykge1xuICAgICAgICAgICAgdGhpcy5tYXAuc2V0VmlldyhbK2xvY1sxXSwgK2xvY1syXV0sICtsb2NbMF0sICsobG9jWzNdIHx8IDApKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgdXBkYXRlSGFzaDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0aGlzLm1hcC5nZXRDZW50ZXIoKSxcbiAgICAgICAgICAgIHpvb20gPSB0aGlzLm1hcC5nZXRab29tKCksXG4gICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5tYXAuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgcHJlY2lzaW9uID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKE1hdGgubG9nKHpvb20pIC8gTWF0aC5MTjIpKSxcblxuICAgICAgICAgICAgaGFzaCA9ICcjJyArIChNYXRoLnJvdW5kKHpvb20gKiAxMDApIC8gMTAwKSArXG4gICAgICAgICAgICAgICAgJy8nICsgY2VudGVyLmxhdC50b0ZpeGVkKHByZWNpc2lvbikgK1xuICAgICAgICAgICAgICAgICcvJyArIGNlbnRlci5sbmcudG9GaXhlZChwcmVjaXNpb24pICtcbiAgICAgICAgICAgICAgICAoYmVhcmluZyA/ICcvJyArIChNYXRoLnJvdW5kKGJlYXJpbmcgKiAxMCkgLyAxMCkgOiAnJyk7XG5cbiAgICAgICAgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKCcnLCAnJywgaGFzaCk7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQuanMnKSxcbiAgICBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyLmpzJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyYWN0aW9uO1xuXG5mdW5jdGlvbiBJbnRlcmFjdGlvbihlbCkge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHRoaXM7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuXG4gICAgdmFyIHJvdGF0aW5nID0gZmFsc2UsXG4gICAgICAgIHBhbm5lZCA9IGZhbHNlLFxuICAgICAgICBmaXJzdFBvcyA9IG51bGwsXG4gICAgICAgIHBvcyA9IG51bGwsXG4gICAgICAgIGluZXJ0aWEgPSBudWxsLFxuICAgICAgICBub3c7XG5cbiAgICBmdW5jdGlvbiBtb3VzZVBvcyhlKSB7XG4gICAgICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICBlLmNsaWVudFggLSByZWN0LmxlZnQgLSBlbC5jbGllbnRMZWZ0LFxuICAgICAgICAgICAgZS5jbGllbnRZIC0gcmVjdC50b3AgLSBlbC5jbGllbnRUb3ApO1xuICAgIH1cblxuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgcm90YXRpbmcgPSB0cnVlO1xuICAgICAgICBmaXJzdFBvcyA9IHBvcyA9IG1vdXNlUG9zKGV2KTtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9LCBmYWxzZSk7XG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25tb3VzZWRvd24sIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25tb3VzZXVwLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25tb3VzZW1vdmUsIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIG9uY2xpY2ssIGZhbHNlKTtcbiAgICBzY3JvbGx3aGVlbCh6b29tKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIG9uZG91YmxlY2xpY2ssIGZhbHNlKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplLCBmYWxzZSk7XG5cbiAgICBmdW5jdGlvbiB6b29tKHR5cGUsIGRlbHRhLCBwb2ludCkge1xuICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCd6b29tJywge1xuICAgICAgICAgICAgc291cmNlOiB0eXBlLFxuICAgICAgICAgICAgZGVsdGE6IGRlbHRhLFxuICAgICAgICAgICAgcG9pbnQ6IHBvaW50XG4gICAgICAgIH0pO1xuICAgICAgICBpbmVydGlhID0gbnVsbDtcbiAgICAgICAgbm93ID0gbnVsbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGljayhwb2ludCkge1xuICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdjbGljaycsIHtwb2ludDogcG9pbnR9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBob3Zlcihwb2ludCkge1xuICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdob3ZlcicsIHtwb2ludDogcG9pbnR9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYW4ocG9pbnQpIHtcbiAgICAgICAgaWYgKHBvcykge1xuICAgICAgICAgICAgdmFyIG9mZnNldCA9IHBvcy5zdWIocG9pbnQpO1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgncGFuJywge29mZnNldDogb2Zmc2V0fSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCBhbiBhdmVyYWdlZCB2ZXJzaW9uIG9mIHRoaXMgbW92ZW1lbnQgdG8gdGhlIGluZXJ0aWEgdmVjdG9yXG4gICAgICAgICAgICBpZiAoaW5lcnRpYSkge1xuICAgICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBub3c7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRpbWVzIGl0J3MgMCBhZnRlciBzb21lIGVycmF0aWMgcGFuaW5nXG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lID0gZHVyYXRpb24gKyBub3c7XG4gICAgICAgICAgICAgICAgICAgIGluZXJ0aWEucHVzaChbdGltZSwgcG9pbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGluZXJ0aWEubGVuZ3RoID4gMiAmJiB0aW1lIC0gaW5lcnRpYVswXVswXSA+IDEwMCkgaW5lcnRpYS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmVydGlhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgcG9zID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUoKSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3Jlc2l6ZScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJvdGF0ZShwb2ludCkge1xuICAgICAgICBpZiAocG9zKSB7XG4gICAgICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdyb3RhdGUnLCB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGZpcnN0UG9zLFxuICAgICAgICAgICAgICAgIHByZXY6IHBvcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50OiBwb2ludFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwb3MgPSBwb2ludDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubW91c2Vkb3duKGV2KSB7XG4gICAgICAgIGZpcnN0UG9zID0gcG9zID0gbW91c2VQb3MoZXYpO1xuICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdkb3duJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZXVwKCkge1xuICAgICAgICBwYW5uZWQgPSBwb3MgJiYgZmlyc3RQb3MgJiYgKHBvcy54ICE9IGZpcnN0UG9zLnggfHwgcG9zLnkgIT0gZmlyc3RQb3MueSk7XG5cbiAgICAgICAgcm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgcG9zID0gbnVsbDtcblxuICAgICAgICBpZiAoaW5lcnRpYSAmJiBpbmVydGlhLmxlbmd0aCA+PSAyICYmIG5vdyA+IERhdGUubm93KCkgLSAxMDApIHtcbiAgICAgICAgICAgIHZhciBsYXN0ID0gaW5lcnRpYVtpbmVydGlhLmxlbmd0aCAtIDFdLFxuICAgICAgICAgICAgICAgIGZpcnN0ID0gaW5lcnRpYVswXSxcbiAgICAgICAgICAgICAgICB2ZWxvY2l0eSA9IGxhc3RbMV0uc3ViKGZpcnN0WzFdKS5kaXYobGFzdFswXSAtIGZpcnN0WzBdKTtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3BhbmVuZCcsICB7aW5lcnRpYTogdmVsb2NpdHl9KTtcblxuICAgICAgICB9IGVsc2UgaW50ZXJhY3Rpb24uZmlyZSgncGFuZW5kJyk7XG5cbiAgICAgICAgaW5lcnRpYSA9IG51bGw7XG4gICAgICAgIG5vdyA9IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZW1vdmUoZXYpIHtcbiAgICAgICAgdmFyIHBvaW50ID0gbW91c2VQb3MoZXYpO1xuXG4gICAgICAgIGlmIChyb3RhdGluZykgeyByb3RhdGUocG9pbnQpOyB9XG4gICAgICAgIGVsc2UgaWYgKHBvcykgcGFuKHBvaW50KTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZXYudG9FbGVtZW50O1xuICAgICAgICAgICAgd2hpbGUgKHRhcmdldCAmJiB0YXJnZXQgIT0gZWwgJiYgdGFyZ2V0LnBhcmVudE5vZGUpIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PSBlbCkge1xuICAgICAgICAgICAgICAgIGhvdmVyKHBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uY2xpY2soZXYpIHtcbiAgICAgICAgaWYgKCFwYW5uZWQpIGNsaWNrKG1vdXNlUG9zKGV2KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25kb3VibGVjbGljayhldikge1xuICAgICAgICB6b29tKCd3aGVlbCcsIEluZmluaXR5ICogKGV2LnNoaWZ0S2V5ID8gLTEgOiAxKSwgbW91c2VQb3MoZXYpKTtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzY3JvbGx3aGVlbChjYWxsYmFjaykge1xuICAgICAgICB2YXIgZmlyZWZveCA9IC9GaXJlZm94L2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICAgICAgdmFyIHNhZmFyaSA9IC9TYWZhcmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmICEvQ2hyb20oaXVtfGUpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICAgICAgdmFyIHRpbWUgPSB3aW5kb3cucGVyZm9ybWFuY2UgfHwgRGF0ZTtcblxuICAgICAgICBlbC5hZGRFdmVudExpc3RlbmVyKCd3aGVlbCcsIHdoZWVsLCBmYWxzZSk7XG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNld2hlZWwnLCBtb3VzZXdoZWVsLCBmYWxzZSk7XG5cbiAgICAgICAgdmFyIGxhc3RFdmVudCA9IDA7XG5cbiAgICAgICAgdmFyIHR5cGUgPSBudWxsO1xuICAgICAgICB2YXIgdHlwZVRpbWVvdXQgPSBudWxsO1xuICAgICAgICB2YXIgaW5pdGlhbFZhbHVlID0gbnVsbDtcblxuICAgICAgICBmdW5jdGlvbiBzY3JvbGwodmFsdWUsIGV2KSB7XG4gICAgICAgICAgICB2YXIgc3RhbXAgPSB0aW1lLm5vdygpO1xuICAgICAgICAgICAgdmFyIHRpbWVEZWx0YSA9IHN0YW1wIC0gbGFzdEV2ZW50O1xuICAgICAgICAgICAgbGFzdEV2ZW50ID0gc3RhbXA7XG5cbiAgICAgICAgICAgIHZhciBwb2ludCA9IG1vdXNlUG9zKGV2KTtcblxuICAgICAgICAgICAgaWYgKHZhbHVlICE9PSAwICYmICh2YWx1ZSAlIDQuMDAwMjQ0MTQwNjI1KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgb25lIGlzIGRlZmluaXRlbHkgYSBtb3VzZSB3aGVlbCBldmVudC5cbiAgICAgICAgICAgICAgICB0eXBlID0gJ3doZWVsJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUgIT09IDAgJiYgTWF0aC5hYnModmFsdWUpIDwgNCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgb25lIGlzIGRlZmluaXRlbHkgYSB0cmFja3BhZCBldmVudCBiZWNhdXNlIGl0IGlzIHNvIHNtYWxsLlxuICAgICAgICAgICAgICAgIHR5cGUgPSAndHJhY2twYWQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aW1lRGVsdGEgPiA0MDApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGxpa2VseSBhIG5ldyBzY3JvbGwgYWN0aW9uLlxuICAgICAgICAgICAgICAgIHR5cGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIC8vIFN0YXJ0IGEgdGltZW91dCBpbiBjYXNlIHRoaXMgd2FzIGEgc2luZ3VsYXIgZXZlbnQsIGFuZCBkZWx5IGl0XG4gICAgICAgICAgICAgICAgLy8gYnkgdXAgdG8gNDBtcy5cbiAgICAgICAgICAgICAgICB0eXBlVGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnd2hlZWwnO1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayh0eXBlLCAtaW5pdGlhbFZhbHVlLCBwb2ludCk7XG4gICAgICAgICAgICAgICAgfSwgNDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIHJlcGVhdGluZyBldmVudCwgYnV0IHdlIGRvbid0IGtub3cgdGhlIHR5cGUgb2YgZXZlbnRcbiAgICAgICAgICAgICAgICAvLyBqdXN0IHlldC4gSWYgdGhlIGRlbHRhIHBlciB0aW1lIGlzIHNtYWxsLCB3ZSBhc3N1bWUgaXQncyBhXG4gICAgICAgICAgICAgICAgLy8gZmFzdCB0cmFja3BhZDsgb3RoZXJ3aXNlIHdlIHN3aXRjaCBpbnRvIHdoZWVsIG1vZGUuXG4gICAgICAgICAgICAgICAgdHlwZSA9IChNYXRoLmFicyh0aW1lRGVsdGEgKiB2YWx1ZSkgPCAyMDApID8gJ3RyYWNrcGFkJyA6ICd3aGVlbCc7XG5cbiAgICAgICAgICAgICAgICAvLyBNYWtlIHN1cmUgb3VyIGRlbGF5ZWQgZXZlbnQgaXNuJ3QgZmlyZWQgYWdhaW4sIGJlY2F1c2Ugd2VcbiAgICAgICAgICAgICAgICAvLyBhY2N1bXVsYXRlIHRoZSBwcmV2aW91cyBldmVudCAod2hpY2ggd2FzIGxlc3MgdGhhbiA0MG1zIGFnbykgaW50b1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0eXBlVGltZW91dCk7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgKz0gaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gT25seSBmaXJlIHRoZSBjYWxsYmFjayBpZiB3ZSBhY3R1YWxseSBrbm93IHdoYXQgdHlwZSBvZiBzY3JvbGxpbmdcbiAgICAgICAgICAgIC8vIGRldmljZSB0aGUgdXNlciB1c2VzLlxuICAgICAgICAgICAgaWYgKHR5cGUgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh0eXBlLCAtdmFsdWUsIHBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHdoZWVsKGUpIHtcbiAgICAgICAgICAgIHZhciBkZWx0YVkgPSBlLmRlbHRhWTtcbiAgICAgICAgICAgIC8vIEZpcmVmb3ggZG91YmxlcyB0aGUgdmFsdWVzIG9uIHJldGluYSBzY3JlZW5zLi4uXG4gICAgICAgICAgICBpZiAoZmlyZWZveCAmJiBlLmRlbHRhTW9kZSA9PSB3aW5kb3cuV2hlZWxFdmVudC5ET01fREVMVEFfUElYRUwpIGRlbHRhWSAvPSBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG4gICAgICAgICAgICBpZiAoZS5kZWx0YU1vZGUgPT0gd2luZG93LldoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIGRlbHRhWSAqPSA0MDtcbiAgICAgICAgICAgIHNjcm9sbChkZWx0YVksIGUpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2V3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gLWUud2hlZWxEZWx0YVk7XG4gICAgICAgICAgICBpZiAoc2FmYXJpKSBkZWx0YVkgPSBkZWx0YVkgLyAzO1xuICAgICAgICAgICAgc2Nyb2xsKGRlbHRhWSwgZSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbkludGVyYWN0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRlZCk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBEaXNwYXRjaGVyID0gcmVxdWlyZSgnLi4vdXRpbC9kaXNwYXRjaGVyLmpzJyksXG4gICAgQ2FudmFzID0gcmVxdWlyZSgnLi4vdXRpbC9jYW52YXMuanMnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsLmpzJyksXG4gICAgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3Nlci5qcycpLFxuICAgIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXguanMnKSxcbiAgICBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkLmpzJyksXG5cbiAgICBTdHlsZSA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlLmpzJyksXG4gICAgQW5pbWF0aW9uTG9vcCA9IHJlcXVpcmUoJy4uL3N0eWxlL2FuaW1hdGlvbmxvb3AuanMnKSxcbiAgICBHTFBhaW50ZXIgPSByZXF1aXJlKCcuLi9yZW5kZXIvcGFpbnRlci5qcycpLFxuXG4gICAgVHJhbnNmb3JtID0gcmVxdWlyZSgnLi4vZ2VvL3RyYW5zZm9ybS5qcycpLFxuICAgIEhhc2ggPSByZXF1aXJlKCcuL2hhc2guanMnKSxcbiAgICBIYW5kbGVycyA9IHJlcXVpcmUoJy4vaGFuZGxlcnMuanMnKSxcbiAgICBTb3VyY2UgPSByZXF1aXJlKCcuLi9zb3VyY2Uvc291cmNlLmpzJyksXG4gICAgRWFzaW5ncyA9IHJlcXVpcmUoJy4vZWFzaW5ncy5qcycpLFxuICAgIExhdExuZyA9IHJlcXVpcmUoJy4uL2dlby9sYXRsbmcuanMnKSxcbiAgICBMYXRMbmdCb3VuZHMgPSByZXF1aXJlKCcuLi9nZW8vbGF0bG5nYm91bmRzLmpzJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpLFxuICAgIEdseXBoU291cmNlID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoc291cmNlLmpzJyksXG4gICAgQXR0cmlidXRpb24gPSByZXF1aXJlKCcuL2NvbnRyb2wvYXR0cmlidXRpb24uanMnKTtcblxuLy8gYWxsb3cgcmVkZWZpbmluZyBNYXAgaGVyZSAoanNoaW50IHRoaW5rcyBpdCdzIGdsb2JhbClcbi8vIGpzaGludCAtVzA3OVxuXG52YXIgTWFwID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRpb25zKSB7XG5cbiAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zID0gdXRpbC5pbmhlcml0KHRoaXMub3B0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLmFuaW1hdGlvbkxvb3AgPSBuZXcgQW5pbWF0aW9uTG9vcCgpO1xuICAgIHRoaXMudHJhbnNmb3JtID0gbmV3IFRyYW5zZm9ybShvcHRpb25zLm1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgdGhpcy5oYXNoID0gb3B0aW9ucy5oYXNoICYmIG5ldyBIYXNoKHRoaXMpO1xuXG4gICAgaWYgKG9wdGlvbnMubWF4Qm91bmRzKSB7XG4gICAgICAgIHZhciBiID0gTGF0TG5nQm91bmRzLmNvbnZlcnQob3B0aW9ucy5tYXhCb3VuZHMpO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5sYXRSYW5nZSA9IFtiLmdldFNvdXRoKCksIGIuZ2V0Tm9ydGgoKV07XG4gICAgICAgIHRoaXMudHJhbnNmb3JtLmxuZ1JhbmdlID0gW2IuZ2V0V2VzdCgpLCBiLmdldEVhc3QoKV07XG4gICAgfVxuXG4gICAgdGhpcy5fb25TdHlsZUNoYW5nZSA9IHRoaXMuX29uU3R5bGVDaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl91cGRhdGVCdWNrZXRzID0gdGhpcy5fdXBkYXRlQnVja2V0cy5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVuZGVyID0gdGhpcy5yZW5kZXIuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3NldHVwQ29udGFpbmVyKCk7XG4gICAgdGhpcy5fc2V0dXBQYWludGVyKCk7XG5cbiAgICB0aGlzLmhhbmRsZXJzID0gb3B0aW9ucy5pbnRlcmFjdGl2ZSAmJiBuZXcgSGFuZGxlcnModGhpcyk7XG4gICAgdGhpcy5kaXNwYXRjaGVyID0gbmV3IERpc3BhdGNoZXIoTWF0aC5tYXgob3B0aW9ucy5udW1Xb3JrZXJzLCAxKSwgdGhpcyk7XG5cbiAgICAgLy8gZG9uJ3Qgc2V0IHBvc2l0aW9uIGZyb20gb3B0aW9ucyBpZiBzZXQgdGhyb3VnaCBoYXNoXG4gICAgaWYgKCF0aGlzLmhhc2ggfHwgIXRoaXMuaGFzaC5vbmhhc2goKSkge1xuICAgICAgICB0aGlzLnNldFZpZXcob3B0aW9ucy5jZW50ZXIsIG9wdGlvbnMuem9vbSwgb3B0aW9ucy5iZWFyaW5nKTtcbiAgICB9XG5cbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcbiAgICB0aGlzLnN0YWNrcyA9IHt9O1xuXG4gICAgdGhpcy5yZXNpemUoKTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zdHlsZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdGhpcy5zZXRTdHlsZShvcHRpb25zLnN0eWxlKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMuc3R5bGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTihvcHRpb25zLnN0eWxlLCBmdW5jdGlvbiAoZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB0aHJvdyBlcnI7XG4gICAgICAgICAgICB0aGlzLnNldFN0eWxlKGRhdGEpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF0dHJpYnV0aW9uQ29udHJvbCkgdGhpcy5hZGRDb250cm9sKG5ldyBBdHRyaWJ1dGlvbigpKTtcbn07XG5cbnV0aWwuZXh0ZW5kKE1hcC5wcm90b3R5cGUsIEV2ZW50ZWQpO1xudXRpbC5leHRlbmQoTWFwLnByb3RvdHlwZSwgRWFzaW5ncyk7XG51dGlsLmV4dGVuZChNYXAucHJvdG90eXBlLCB7XG5cbiAgICBvcHRpb25zOiB7XG4gICAgICAgIGNlbnRlcjogWzAsIDBdLFxuICAgICAgICB6b29tOiAwLFxuICAgICAgICBiZWFyaW5nOiAwLFxuXG4gICAgICAgIG1pblpvb206IDAsXG4gICAgICAgIG1heFpvb206IDIwLFxuICAgICAgICBudW1Xb3JrZXJzOiBicm93c2VyLmhhcmR3YXJlQ29uY3VycmVuY3kgLSAxLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICBoYXNoOiBmYWxzZSxcblxuICAgICAgICBhdHRyaWJ1dGlvbkNvbnRyb2w6IHRydWVcbiAgICB9LFxuXG4gICAgYWRkU291cmNlOiBmdW5jdGlvbihpZCwgc291cmNlKSB7XG4gICAgICAgIHRoaXMuc291cmNlc1tpZF0gPSBzb3VyY2U7XG4gICAgICAgIHNvdXJjZS5pZCA9IGlkO1xuICAgICAgICBpZiAoc291cmNlLm9uQWRkKSB7XG4gICAgICAgICAgICBzb3VyY2Uub25BZGQodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNvdXJjZS5lbmFibGVkKSBzb3VyY2UuZmlyZSgnc291cmNlLmFkZCcsIHtzb3VyY2U6IHNvdXJjZX0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgcmVtb3ZlU291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICAgICAgaWYgKHNvdXJjZS5vblJlbW92ZSkge1xuICAgICAgICAgICAgc291cmNlLm9uUmVtb3ZlKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLnNvdXJjZXNbaWRdO1xuICAgICAgICByZXR1cm4gdGhpcy5maXJlKCdzb3VyY2UucmVtb3ZlJywge3NvdXJjZTogc291cmNlfSk7XG4gICAgfSxcblxuICAgIGFkZENvbnRyb2w6IGZ1bmN0aW9uKGNvbnRyb2wpIHtcbiAgICAgICAgY29udHJvbC5hZGRUbyh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8vIFNldCB0aGUgbWFwJ3MgY2VudGVyLCB6b29tLCBhbmQgYmVhcmluZ1xuICAgIHNldFZpZXc6IGZ1bmN0aW9uKGNlbnRlciwgem9vbSwgYmVhcmluZykge1xuICAgICAgICB0aGlzLnN0b3AoKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIHpvb21DaGFuZ2VkID0gdHIuem9vbSAhPT0gK3pvb20sXG4gICAgICAgICAgICBiZWFyaW5nQ2hhbmdlZCA9IHRyLmJlYXJpbmcgIT09ICtiZWFyaW5nO1xuXG4gICAgICAgIHRyLmNlbnRlciA9IExhdExuZy5jb252ZXJ0KGNlbnRlcik7XG4gICAgICAgIHRyLnpvb20gPSArem9vbTtcbiAgICAgICAgdHIuYmVhcmluZyA9ICtiZWFyaW5nO1xuXG4gICAgICAgIHJldHVybiB0aGlzXG4gICAgICAgICAgICAuZmlyZSgnbW92ZXN0YXJ0JylcbiAgICAgICAgICAgIC5fbW92ZSh6b29tQ2hhbmdlZCwgYmVhcmluZ0NoYW5nZWQpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICBzZXRDZW50ZXI6IGZ1bmN0aW9uKGNlbnRlcikge1xuICAgICAgICB0aGlzLnNldFZpZXcoY2VudGVyLCB0aGlzLmdldFpvb20oKSwgdGhpcy5nZXRCZWFyaW5nKCkpO1xuICAgIH0sXG5cbiAgICBzZXRab29tOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHRoaXMuc2V0Vmlldyh0aGlzLmdldENlbnRlcigpLCB6b29tLCB0aGlzLmdldEJlYXJpbmcoKSk7XG4gICAgfSxcblxuICAgIHNldEJlYXJpbmc6IGZ1bmN0aW9uKGJlYXJpbmcpIHtcbiAgICAgICAgdGhpcy5zZXRWaWV3KHRoaXMuZ2V0Q2VudGVyKCksIHRoaXMuZ2V0Wm9vbSgpLCBiZWFyaW5nKTtcbiAgICB9LFxuXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmNlbnRlcjsgfSxcbiAgICBnZXRab29tOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLnpvb207IH0sXG4gICAgZ2V0QmVhcmluZzogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnRyYW5zZm9ybS5iZWFyaW5nOyB9LFxuXG4gICAgLy8gRGV0ZWN0IHRoZSBtYXAncyBuZXcgd2lkdGggYW5kIGhlaWdodCBhbmQgcmVzaXplIGl0LlxuICAgIHJlc2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDAsIGhlaWdodCA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuY29udGFpbmVyKSB7XG4gICAgICAgICAgICB3aWR0aCA9IHRoaXMuY29udGFpbmVyLm9mZnNldFdpZHRoIHx8IDQwMDtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAzMDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNhbnZhcy5yZXNpemUod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgdGhpcy50cmFuc2Zvcm0ud2lkdGggPSB3aWR0aDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0uaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5fY29uc3RyYWluKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuc3R5bGUgJiYgdGhpcy5zdHlsZS5zcHJpdGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUuc3ByaXRlLnJlc2l6ZSh0aGlzLnBhaW50ZXIuZ2wpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wYWludGVyLnJlc2l6ZSh3aWR0aCwgaGVpZ2h0KTtcblxuICAgICAgICByZXR1cm4gdGhpc1xuICAgICAgICAgICAgLmZpcmUoJ21vdmVzdGFydCcpXG4gICAgICAgICAgICAuX21vdmUoKVxuICAgICAgICAgICAgLmZpcmUoJ3Jlc2l6ZScpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICBnZXRCb3VuZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcbiAgICAgICAgICAgIHRoaXMudHJhbnNmb3JtLnBvaW50TG9jYXRpb24obmV3IFBvaW50KDAsIDApKSxcbiAgICAgICAgICAgIHRoaXMudHJhbnNmb3JtLnBvaW50TG9jYXRpb24odGhpcy50cmFuc2Zvcm0uc2l6ZSkpO1xuICAgIH0sXG5cbiAgICBwcm9qZWN0OiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmxvY2F0aW9uUG9pbnQoTGF0TG5nLmNvbnZlcnQobGF0bG5nKSk7XG4gICAgfSxcbiAgICB1bnByb2plY3Q6IGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKFBvaW50LmNvbnZlcnQocG9pbnQpKTtcbiAgICB9LFxuXG4gICAgZmVhdHVyZXNBdDogZnVuY3Rpb24ocG9pbnQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGZlYXR1cmVzID0gW107XG4gICAgICAgIHZhciBlcnJvciA9IG51bGw7XG4gICAgICAgIHZhciBtYXAgPSB0aGlzO1xuXG4gICAgICAgIHBvaW50ID0gUG9pbnQuY29udmVydChwb2ludCk7XG5cbiAgICAgICAgdXRpbC5hc3luY0VhY2goT2JqZWN0LmtleXModGhpcy5zb3VyY2VzKSwgZnVuY3Rpb24oaWQsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gbWFwLnNvdXJjZXNbaWRdO1xuICAgICAgICAgICAgc291cmNlLmZlYXR1cmVzQXQocG9pbnQsIHBhcmFtcywgZnVuY3Rpb24oZXJyLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSBmZWF0dXJlcyA9IGZlYXR1cmVzLmNvbmNhdChyZXN1bHQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIGVycm9yID0gZXJyO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgZmVhdHVyZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHNldFN0eWxlOiBmdW5jdGlvbihzdHlsZSkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkge1xuICAgICAgICAgICAgdGhpcy5zdHlsZS5vZmYoJ2NoYW5nZScsIHRoaXMuX29uU3R5bGVDaGFuZ2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0eWxlIGluc3RhbmNlb2YgU3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBuZXcgU3R5bGUoc3R5bGUsIHRoaXMuYW5pbWF0aW9uTG9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc291cmNlcyA9IHRoaXMuc3R5bGUuc3R5bGVzaGVldC5zb3VyY2VzO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBzb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFNvdXJjZShpZCwgU291cmNlLmNyZWF0ZShzb3VyY2VzW2lkXSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZSA9IG5ldyBHbHlwaFNvdXJjZSh0aGlzLnN0eWxlLnN0eWxlc2hlZXQuZ2x5cGhzLCB0aGlzLnBhaW50ZXIuZ2x5cGhBdGxhcyk7XG5cbiAgICAgICAgdGhpcy5zdHlsZS5vbignY2hhbmdlJywgdGhpcy5fb25TdHlsZUNoYW5nZSk7XG5cbiAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRydWU7XG4gICAgICAgIHRoaXMuX3RpbGVzRGlydHkgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUJ1Y2tldHMoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlR2x5cGhzKCk7XG5cbiAgICAgICAgdGhpcy5maXJlKCdzdHlsZS5jaGFuZ2UnKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX21vdmU6IGZ1bmN0aW9uICh6b29tLCByb3RhdGUpIHtcblxuICAgICAgICB0aGlzLnVwZGF0ZSh6b29tKS5maXJlKCdtb3ZlJyk7XG5cbiAgICAgICAgaWYgKHpvb20pIHRoaXMuZmlyZSgnem9vbScpO1xuICAgICAgICBpZiAocm90YXRlKSB0aGlzLmZpcmUoJ3JvdGF0ZScpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvLyBtYXAgc2V0dXAgY29kZVxuXG4gICAgX3NldHVwQ29udGFpbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGlkID0gdGhpcy5vcHRpb25zLmNvbnRhaW5lcjtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyID0gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xuICAgICAgICBpZiAoY29udGFpbmVyKSBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtbWFwJyk7XG4gICAgICAgIHRoaXMuY2FudmFzID0gbmV3IENhbnZhcyh0aGlzLCBjb250YWluZXIpO1xuICAgIH0sXG5cbiAgICBfc2V0dXBQYWludGVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdsID0gdGhpcy5jYW52YXMuZ2V0V2ViR0xDb250ZXh0KCk7XG5cbiAgICAgICAgaWYgKCFnbCkge1xuICAgICAgICAgICAgYWxlcnQoJ0ZhaWxlZCB0byBpbml0aWFsaXplIFdlYkdMJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhaW50ZXIgPSBuZXcgR0xQYWludGVyKGdsLCB0aGlzLnRyYW5zZm9ybSk7XG4gICAgfSxcblxuICAgIF9jb250ZXh0TG9zdDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIGJyb3dzZXIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRleHRSZXN0b3JlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvLyBDYWxsYmFja3MgZnJvbSB3ZWIgd29ya2Vyc1xuXG4gICAgJ2RlYnVnIG1lc3NhZ2UnOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIGRhdGEpO1xuICAgIH0sXG5cbiAgICAnYWxlcnQgbWVzc2FnZSc6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgYWxlcnQuYXBwbHkod2luZG93LCBkYXRhKTtcbiAgICB9LFxuXG4gICAgJ2dldCBzcHJpdGUganNvbic6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNwcml0ZSA9IHRoaXMuc3R5bGUuc3ByaXRlO1xuICAgICAgICBpZiAoc3ByaXRlLmxvYWRlZCgpKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7IHNwcml0ZTogc3ByaXRlLmRhdGEsIHJldGluYTogc3ByaXRlLnJldGluYSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwcml0ZS5vbignbG9hZGVkJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgeyBzcHJpdGU6IHNwcml0ZS5kYXRhLCByZXRpbmE6IHNwcml0ZS5yZXRpbmEgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAnZ2V0IGdseXBocyc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZS5nZXRSZWN0cyhwYXJhbXMuZm9udHN0YWNrLCBwYXJhbXMuY29kZXBvaW50cywgcGFyYW1zLmlkLCBjYWxsYmFjayk7XG4gICAgfSxcblxuICAgIC8vIFJlbmRlcmluZ1xuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih1cGRhdGVTdHlsZSkge1xuXG4gICAgICAgIGlmICghdGhpcy5zdHlsZSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRoaXMuX3N0eWxlRGlydHkgfHwgdXBkYXRlU3R5bGU7XG4gICAgICAgIHRoaXMuX3RpbGVzRGlydHkgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8vIENhbGwgd2hlbiBhIChyZS0pcmVuZGVyIG9mIHRoZSBtYXAgaXMgcmVxdWlyZWQsIGUuZy4gd2hlbiB0aGUgdXNlciBwYW5uZWQgb3Igem9vbWVkLGYgb3IgbmV3IGRhdGEgaXMgYXZhaWxhYmxlLlxuICAgIHJlbmRlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHlsZURpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVTdHlsZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX3RpbGVzRGlydHkpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuc291cmNlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlc1tpZF0udXBkYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl90aWxlc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9yZW5kZXJHcm91cHModGhpcy5zdHlsZS5sYXllckdyb3Vwcyk7XG4gICAgICAgIHRoaXMuZmlyZSgncmVuZGVyJyk7XG5cbiAgICAgICAgdGhpcy5fZnJhbWVJZCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCF0aGlzLmFuaW1hdGlvbkxvb3Auc3RvcHBlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9yZXBhaW50IHx8ICF0aGlzLmFuaW1hdGlvbkxvb3Auc3RvcHBlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9yZW5kZXJHcm91cHM6IGZ1bmN0aW9uKGdyb3VwcywgbmFtZSkge1xuXG4gICAgICAgIHZhciBpLCBsZW4sIGdyb3VwLCBzb3VyY2UsIGs7XG5cbiAgICAgICAgLy8gUmVuZGVyIGFsbCBkZXBlbmRlbmNpZXMgKGNvbXBvc2l0ZWQgbGF5ZXJzKSB0byB0ZXh0dXJlc1xuICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBncm91cHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGdyb3VwID0gZ3JvdXBzW2ldO1xuXG4gICAgICAgICAgICBmb3IgKGsgaW4gZ3JvdXAuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyR3JvdXBzKGdyb3VwLmRlcGVuZGVuY2llc1trXSwgayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhdHRhY2ggcmVuZGVyIGRlc3RpbmF0aW9uLiBpZiBubyBuYW1lLCBtYWluIGNhbnZhcy5cbiAgICAgICAgdGhpcy5wYWludGVyLmJpbmRSZW5kZXJUZXh0dXJlKG5hbWUpO1xuXG4gICAgICAgIC8vIFJlbmRlciB0aGUgZ3JvdXBzXG4gICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGdyb3Vwcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgZ3JvdXAgPSBncm91cHNbaV07XG4gICAgICAgICAgICBzb3VyY2UgPSB0aGlzLnNvdXJjZXNbZ3JvdXAuc291cmNlXTtcblxuICAgICAgICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGFpbnRlci5jbGVhclN0ZW5jaWwoKTtcbiAgICAgICAgICAgICAgICBzb3VyY2UucmVuZGVyKGdyb3VwKTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChncm91cC5jb21wb3NpdGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYWludGVyLmRyYXcodW5kZWZpbmVkLCB0aGlzLnN0eWxlLCBncm91cCwge30pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChncm91cC5zb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGFpbnRlci5kcmF3KHVuZGVmaW5lZCwgdGhpcy5zdHlsZSwgZ3JvdXAsIHsgYmFja2dyb3VuZDogdHJ1ZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfcmVyZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2ZyYW1lSWQgPSBicm93c2VyLmZyYW1lKHRoaXMucmVuZGVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfb25TdHlsZUNoYW5nZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVwZGF0ZSh0cnVlKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVN0eWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0eWxlKSByZXR1cm47XG4gICAgICAgIHRoaXMuc3R5bGUucmVjYWxjdWxhdGUodGhpcy50cmFuc2Zvcm0uem9vbSk7XG4gICAgfSxcblxuICAgIF91cGRhdGVHbHlwaHM6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXIuYnJvYWRjYXN0KCdzZXQgZ2x5cGhzJywgdGhpcy5zdHlsZS5zdHlsZXNoZWV0LmdseXBocyk7XG4gICAgfSxcblxuICAgIF91cGRhdGVCdWNrZXRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gVHJhbnNmZXIgYSBzdHJpcHBlZCBkb3duIHZlcnNpb24gb2YgdGhlIHN0eWxlIHRvIHRoZSB3b3JrZXJzLiBUaGV5IG9ubHlcbiAgICAgICAgLy8gbmVlZCB0aGUgYnVja2V0IGluZm9ybWF0aW9uIHRvIGtub3cgd2hhdCBmZWF0dXJlcyB0byBleHRyYWN0IGZyb20gdGhlIHRpbGUuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoJ3NldCBidWNrZXRzJywgdGhpcy5zdHlsZS5vcmRlcmVkQnVja2V0cyk7XG5cbiAgICAgICAgLy8gY2xlYXJzIGFsbCB0aWxlcyB0byByZWNhbGN1bGF0ZSBnZW9tZXRyaWVzIChmb3IgY2hhbmdlcyB0byBsaW5lY2FwcywgbGluZWpvaW5zLCAuLi4pXG4gICAgICAgIGZvciAodmFyIHMgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZXNbc10ubG9hZCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICB9XG59KTtcblxudXRpbC5leHRlbmRBbGwoTWFwLnByb3RvdHlwZSwge1xuXG4gICAgLy8gZGVidWcgY29kZVxuICAgIF9kZWJ1ZzogZmFsc2UsXG4gICAgZ2V0IGRlYnVnKCkgeyByZXR1cm4gdGhpcy5fZGVidWc7IH0sXG4gICAgc2V0IGRlYnVnKHZhbHVlKSB7IHRoaXMuX2RlYnVnID0gdmFsdWU7IHRoaXMuX3JlcmVuZGVyKCk7IH0sXG5cbiAgICAvLyBjb250aW51b3VzIHJlcGFpbnRcbiAgICBfcmVwYWludDogZmFsc2UsXG4gICAgZ2V0IHJlcGFpbnQoKSB7IHJldHVybiB0aGlzLl9yZXBhaW50OyB9LFxuICAgIHNldCByZXBhaW50KHZhbHVlKSB7IHRoaXMuX3JlcGFpbnQgPSB2YWx1ZTsgdGhpcy5fcmVyZW5kZXIoKTsgfSxcblxuICAgIC8vIHBvbHlnb24gYW50aWFsaWFzaW5nXG4gICAgX2FudGlhbGlhc2luZzogdHJ1ZSxcbiAgICBnZXQgYW50aWFsaWFzaW5nKCkgeyByZXR1cm4gdGhpcy5fYW50aWFsaWFzaW5nOyB9LFxuICAgIHNldCBhbnRpYWxpYXNpbmcodmFsdWUpIHsgdGhpcy5fYW50aWFsaWFzaW5nID0gdmFsdWU7IHRoaXMuX3JlcmVuZGVyKCk7IH0sXG5cbiAgICAvLyBzaG93IHZlcnRpY2VzXG4gICAgX3ZlcnRpY2VzOiBmYWxzZSxcbiAgICBnZXQgdmVydGljZXMoKSB7IHJldHVybiB0aGlzLl92ZXJ0aWNlczsgfSxcbiAgICBzZXQgdmVydGljZXModmFsdWUpIHsgdGhpcy5fdmVydGljZXMgPSB2YWx1ZTsgdGhpcy5fcmVyZW5kZXIoKTsgfSxcblxuICAgIC8vIHNob3cgdmVydGljZXNcbiAgICBfbG9hZE5ld1RpbGVzOiB0cnVlLFxuICAgIGdldCBsb2FkTmV3VGlsZXMoKSB7IHJldHVybiB0aGlzLl9sb2FkTmV3VGlsZXM7IH0sXG4gICAgc2V0IGxvYWROZXdUaWxlcyh2YWx1ZSkgeyB0aGlzLl9sb2FkTmV3VGlsZXMgPSB2YWx1ZTsgdGhpcy51cGRhdGUoKTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQWN0b3I7XG5cbmZ1bmN0aW9uIEFjdG9yKHRhcmdldCwgcGFyZW50KSB7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5jYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLmNhbGxiYWNrSUQgPSAwO1xuICAgIHRoaXMucmVjZWl2ZSA9IHRoaXMucmVjZWl2ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0aGlzLnJlY2VpdmUsIGZhbHNlKTtcbn1cblxuQWN0b3IucHJvdG90eXBlLnJlY2VpdmUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG4gICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGEsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PSAnPHJlc3BvbnNlPicpIHtcbiAgICAgICAgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrc1tkYXRhLmlkXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2RhdGEuaWRdO1xuICAgICAgICBjYWxsYmFjayhkYXRhLmVycm9yIHx8IG51bGwsIGRhdGEuZGF0YSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZGF0YS5pZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdmFyIGlkID0gZGF0YS5pZDtcbiAgICAgICAgdGhpcy5wYXJlbnRbZGF0YS50eXBlXShkYXRhLmRhdGEsIGZ1bmN0aW9uIHJlc3BvbnNlKGVyciwgZGF0YSwgYnVmZmVycykge1xuICAgICAgICAgICAgLy8gY29uc29sZS53YXJuKCd0cnlpbmcgdG8gY2xvbmUnLCBkYXRhLCBidWZmZXJzLCBtZXNzYWdlLnRhcmdldCk7XG4gICAgICAgICAgICBtZXNzYWdlLnRhcmdldC5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICAgICAgdHlwZTogJzxyZXNwb25zZT4nLFxuICAgICAgICAgICAgICAgIGlkOiBTdHJpbmcoaWQpLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgPyBTdHJpbmcoZXJyKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgZGF0YTogZGF0YVxuICAgICAgICAgICAgfSwgYnVmZmVycyk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhKTtcbiAgICB9XG59O1xuXG5BY3Rvci5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCBidWZmZXJzKSB7XG4gICAgdmFyIGlkID0gbnVsbDtcbiAgICBpZiAoY2FsbGJhY2spIHRoaXMuY2FsbGJhY2tzW2lkID0gdGhpcy5jYWxsYmFja0lEKytdID0gY2FsbGJhY2s7XG4gICAgdGhpcy50YXJnZXQucG9zdE1lc3NhZ2UoeyB0eXBlOiB0eXBlLCBpZDogU3RyaW5nKGlkKSwgZGF0YTogZGF0YSB9LCBidWZmZXJzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuZ2V0SlNPTiA9IGZ1bmN0aW9uKHVybCwgY2FsbGJhY2spIHtcbiAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgeGhyLm9wZW4oJ0dFVCcsIHVybCwgdHJ1ZSk7XG4gICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7XG4gICAgICAgIGNhbGxiYWNrKGUpO1xuICAgIH07XG4gICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCAmJiB4aHIucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHZhciBkYXRhO1xuICAgICAgICAgICAgdHJ5IHsgZGF0YSA9IEpTT04ucGFyc2UoeGhyLnJlc3BvbnNlKTsgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikgeyByZXR1cm4gY2FsbGJhY2soZXJyKTsgfVxuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjayhuZXcgRXJyb3IoeGhyLnN0YXR1c1RleHQpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgeGhyLnNlbmQoKTtcbiAgICByZXR1cm4geGhyO1xufTtcblxuZXhwb3J0cy5nZXRBcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKHVybCwgY2FsbGJhY2spIHtcbiAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgeGhyLm9wZW4oJ0dFVCcsIHVybCwgdHJ1ZSk7XG4gICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG4gICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7XG4gICAgICAgIGNhbGxiYWNrKGUpO1xuICAgIH07XG4gICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCAmJiB4aHIucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHhoci5yZXNwb25zZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjayhuZXcgRXJyb3IoeGhyLnN0YXR1c1RleHQpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgeGhyLnNlbmQoKTtcbiAgICByZXR1cm4geGhyO1xufTtcblxuZXhwb3J0cy5nZXRJbWFnZSA9IGZ1bmN0aW9uKHVybCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgaW1nLmNyb3NzT3JpZ2luID0gJ0Fub255bW91cyc7XG4gICAgaW1nLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCBpbWcpO1xuICAgIH07XG4gICAgaW1nLnNyYyA9IHVybDtcbiAgICBpbWcuZ2V0RGF0YSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZ2V0SW1hZ2VEYXRhKHRoaXMpOyB9O1xuICAgIHJldHVybiBpbWc7XG59O1xuXG5mdW5jdGlvbiBnZXRJbWFnZURhdGEoaW1nKSB7XG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIHZhciBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgY2FudmFzLndpZHRoID0gaW1nLndpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBpbWcuaGVpZ2h0O1xuICAgIGNvbnRleHQuZHJhd0ltYWdlKGltZywgMCwgMCk7XG4gICAgcmV0dXJuIGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGltZy53aWR0aCwgaW1nLmhlaWdodCkuZGF0YTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGZyYW1lTmFtZSA9IChmdW5jdGlvbigpIHtcbiAgICBpZiAod2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSkgcmV0dXJuICdyZXF1ZXN0QW5pbWF0aW9uRnJhbWUnO1xuICAgIGlmICh3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lKSByZXR1cm4gJ21velJlcXVlc3RBbmltYXRpb25GcmFtZSc7XG4gICAgaWYgKHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHJldHVybiAnd2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lJztcbiAgICBpZiAod2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lKSByZXR1cm4gJ21zUmVxdWVzdEFuaW1hdGlvbkZyYW1lJztcbn0pKCk7XG5cbmV4cG9ydHMuZnJhbWUgPSBmdW5jdGlvbihmbikge1xuICAgIHJldHVybiB3aW5kb3dbZnJhbWVOYW1lXShmbik7XG59O1xuXG5leHBvcnRzLmNhbmNlbEZyYW1lID0gZnVuY3Rpb24oaWQpIHtcbiAgICAod2luZG93LmNhbmNlbFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgICAgICB3aW5kb3cubW96Q2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgICAgIHdpbmRvdy53ZWJraXRDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICAgICAgd2luZG93Lm1zQ2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lKShpZCk7XG59O1xuXG5leHBvcnRzLnRpbWVkID0gZnVuY3Rpb24gKGZuLCBkdXIsIGN0eCkge1xuICAgIGlmICghZHVyKSB7IHJldHVybiBmbi5jYWxsKGN0eCwgMSk7IH1cblxuICAgIHZhciBhYm9ydCA9IGZhbHNlLFxuICAgICAgICBzdGFydCA9IHdpbmRvdy5wZXJmb3JtYW5jZSA/IHdpbmRvdy5wZXJmb3JtYW5jZS5ub3coKSA6IERhdGUubm93KCk7XG5cbiAgICBmdW5jdGlvbiB0aWNrKG5vdykge1xuICAgICAgICBpZiAoYWJvcnQpIHJldHVybjtcbiAgICAgICAgaWYgKCF3aW5kb3cucGVyZm9ybWFuY2UpIG5vdyA9IERhdGUubm93KCk7XG5cbiAgICAgICAgaWYgKG5vdyA+IHN0YXJ0ICsgZHVyKSB7XG4gICAgICAgICAgICBmbi5jYWxsKGN0eCwgMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmbi5jYWxsKGN0eCwgKG5vdyAtIHN0YXJ0KSAvIGR1cik7XG4gICAgICAgICAgICBleHBvcnRzLmZyYW1lKHRpY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXhwb3J0cy5mcmFtZSh0aWNrKTtcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHsgYWJvcnQgPSB0cnVlOyB9O1xufTtcblxuZXhwb3J0cy5zdXBwb3J0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc3VwcG9ydHMgPSBbXG5cbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJzsgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCc7IH0sXG5cbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICEhKEFycmF5LnByb3RvdHlwZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5ldmVyeSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5maWx0ZXIgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZm9yRWFjaCAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5pbmRleE9mICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmxhc3RJbmRleE9mICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLm1hcCAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5zb21lICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnJlZHVjZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2VSaWdodCAmJlxuICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuICEhKEZ1bmN0aW9uLnByb3RvdHlwZSAmJiBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCksXG4gICAgICAgICAgICAgICAgISEoT2JqZWN0LmtleXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmNyZWF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmlzU2VhbGVkICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5pc0Zyb3plbiAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuaXNFeHRlbnNpYmxlICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5zZWFsICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAnSlNPTicgaW4gd2luZG93ICYmICdwYXJzZScgaW4gSlNPTiAmJiAnc3RyaW5naWZ5JyBpbiBKU09OO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgaWYgKCdzdXBwb3J0c0NvbnRleHQnIGluIGNhbnZhcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYW52YXMuc3VwcG9ydHNDb250ZXh0KCd3ZWJnbCcpIHx8IGNhbnZhcy5zdXBwb3J0c0NvbnRleHQoJ2V4cGVyaW1lbnRhbC13ZWJnbCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICEhd2luZG93LldlYkdMUmVuZGVyaW5nQ29udGV4dCAmJlxuICAgICAgICAgICAgICAgICghIWNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcpIHx8ICEhY2FudmFzLmdldENvbnRleHQoJ2V4cGVyaW1lbnRhbC13ZWJnbCcpKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuICdXb3JrZXInIGluIHdpbmRvdzsgfVxuICAgIF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1cHBvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghc3VwcG9ydHNbaV0oKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydHMuaGFyZHdhcmVDb25jdXJyZW5jeSA9IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5IHx8IDg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGV2aWNlUGl4ZWxSYXRpbycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENhbnZhcztcblxuZnVuY3Rpb24gQ2FudmFzKHBhcmVudCwgY29udGFpbmVyKSB7XG4gICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICB0aGlzLmNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgdGhpcy5jYW52YXMuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtY2FudmFzJyk7XG4gICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0bG9zdCcsIHBhcmVudC5fY29udGV4dExvc3QuYmluZChwYXJlbnQpLCBmYWxzZSk7XG4gICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0cmVzdG9yZWQnLCBwYXJlbnQuX2NvbnRleHRSZXN0b3JlZC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpO1xufVxuXG5DYW52YXMucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB2YXIgcGl4ZWxSYXRpbyA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIHx8IDE7XG5cbiAgICAvLyBSZXF1ZXN0IHRoZSByZXF1aXJlZCBjYW52YXMgc2l6ZSB0YWtpbmcgdGhlIHBpeGVscmF0aW8gaW50byBhY2NvdW50LlxuICAgIHRoaXMuY2FudmFzLndpZHRoID0gcGl4ZWxSYXRpbyAqIHdpZHRoO1xuICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHBpeGVsUmF0aW8gKiBoZWlnaHQ7XG5cbiAgICAvLyBNYWludGFpbiB0aGUgc2FtZSBjYW52YXMgc2l6ZSwgcG90ZW50aWFsbHkgZG93bnNjYWxpbmcgaXQgZm9yIEhpRFBJIGRpc3BsYXlzXG4gICAgdGhpcy5jYW52YXMuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgdGhpcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICsgJ3B4Jztcbn07XG5cbkNhbnZhcy5wcm90b3R5cGUuZ2V0V2ViR0xDb250ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldENvbnRleHQoXCJleHBlcmltZW50YWwtd2ViZ2xcIiwge1xuICAgICAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgICAgICBhbHBoYTogdHJ1ZSxcbiAgICAgICAgc3RlbmNpbDogdHJ1ZSxcbiAgICAgICAgZGVwdGg6IGZhbHNlXG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQWN0b3IgPSByZXF1aXJlKCcuLi9hY3Rvci5qcycpO1xuXG52YXIgc2NyaXB0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwic2NyaXB0XCIpO1xudmFyIHdvcmtlckZpbGUgPSBzY3JpcHRzW3NjcmlwdHMubGVuZ3RoIC0gMV0uZ2V0QXR0cmlidXRlKCdzcmMnKTtcbnZhciBhYnNvbHV0ZSA9IHdvcmtlckZpbGUuaW5kZXhPZignaHR0cCcpICE9PSAtMTtcblxuXG4vLyBNYW5hZ2VzIHRoZSBXZWJXb3JrZXJzXG5tb2R1bGUuZXhwb3J0cyA9IERpc3BhdGNoZXI7XG5mdW5jdGlvbiBEaXNwYXRjaGVyKGxlbmd0aCwgcGFyZW50KSB7XG4gICAgdGhpcy5hY3RvcnMgPSBbXTtcbiAgICB0aGlzLmN1cnJlbnRBY3RvciA9IDA7XG5cbiAgICB2YXIgdXJsLCBibG9iLCBpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIC8vIGR1ZSB0byBjcm9zcyBkb21haW4gaXNzdWVzIHdlIGNhbid0IGxvYWQgaXQgZGlyZWN0bHkgd2l0aCB0aGUgdXJsLFxuICAgICAgICAvLyBzbyBjcmVhdGUgYSBibG9iIGFuZCBvYmplY3QgdXJsIGFuZCBsb2FkIHRoYXRcbiAgICAgICAgaWYgKGFic29sdXRlKSB7XG4gICAgICAgICAgICBibG9iID0gbmV3IEJsb2IoWydpbXBvcnRTY3JpcHRzKFwiJyArIHdvcmtlckZpbGUgKyAnXCIpOyddLCB7dHlwZSA6ICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0J30pO1xuICAgICAgICAgICAgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cmwgPSB3b3JrZXJGaWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHdvcmtlciA9IG5ldyBXb3JrZXIodXJsKTtcbiAgICAgICAgdmFyIGFjdG9yID0gbmV3IEFjdG9yKHdvcmtlciwgcGFyZW50KTtcbiAgICAgICAgYWN0b3IubmFtZSA9IFwiV29ya2VyIFwiICsgaTtcbiAgICAgICAgdGhpcy5hY3RvcnMucHVzaChhY3Rvcik7XG4gICAgfVxufVxuXG5EaXNwYXRjaGVyLnByb3RvdHlwZS5icm9hZGNhc3QgPSBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmFjdG9ycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmFjdG9yc1tpXS5zZW5kKHR5cGUsIGRhdGEpO1xuICAgIH1cbn07XG5cbkRpc3BhdGNoZXIucHJvdG90eXBlLnNlbmQgPSBmdW5jdGlvbih0eXBlLCBkYXRhLCBjYWxsYmFjaywgdGFyZ2V0SUQsIGJ1ZmZlcnMpIHtcbiAgICBpZiAodHlwZW9mIHRhcmdldElEICE9PSAnbnVtYmVyJyB8fCBpc05hTih0YXJnZXRJRCkpIHtcbiAgICAgICAgLy8gVXNlIHJvdW5kIHJvYmluIHRvIHNlbmQgcmVxdWVzdHMgdG8gd2ViIHdvcmtlcnMuXG4gICAgICAgIHRhcmdldElEID0gdGhpcy5jdXJyZW50QWN0b3IgPSAodGhpcy5jdXJyZW50QWN0b3IgKyAxKSAlIHRoaXMuYWN0b3JzLmxlbmd0aDtcbiAgICB9XG5cbiAgICB0aGlzLmFjdG9yc1t0YXJnZXRJRF0uc2VuZCh0eXBlLCBkYXRhLCBjYWxsYmFjaywgYnVmZmVycyk7XG4gICAgcmV0dXJuIHRhcmdldElEO1xufTtcblxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIVFRQX1VSTDogJ2h0dHA6Ly9hLnRpbGVzLm1hcGJveC5jb20vdjQnLFxuICAgIEhUVFBTX1VSTDogJ2h0dHBzOi8vYS50aWxlcy5tYXBib3guY29tL3Y0JyxcbiAgICBGT1JDRV9IVFRQUzogZmFsc2UsXG4gICAgUkVRVUlSRV9BQ0NFU1NfVE9LRU46IHRydWVcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24gKHRhZ05hbWUsIGNsYXNzTmFtZSwgY29udGFpbmVyKSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlbC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgaWYgKGNvbnRhaW5lcikgY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcbiAgICByZXR1cm4gZWw7XG59O1xuXG5mdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xufVxuXG52YXIgZG9jRWwgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IDoge30sXG4gICAgc2VsZWN0UHJvcCA9XG4gICAgICAgICd1c2VyU2VsZWN0JyBpbiBkb2NFbCA/ICd1c2VyU2VsZWN0JyA6XG4gICAgICAgICdNb3pVc2VyU2VsZWN0JyBpbiBkb2NFbCA/ICdNb3pVc2VyU2VsZWN0JyA6XG4gICAgICAgICdXZWJraXRVc2VyU2VsZWN0JyBpbiBkb2NFbCA/ICdXZWJraXRVc2VyU2VsZWN0JyA6IG51bGwsXG4gICAgdXNlclNlbGVjdDtcblxuZXhwb3J0cy5kaXNhYmxlRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgcHJldmVudERlZmF1bHQpO1xuXG4gICAgaWYgKCdvbnNlbGVjdHN0YXJ0JyBpbiBkb2N1bWVudCkgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xuICAgIGVsc2UgaWYgKHNlbGVjdFByb3ApIHtcbiAgICAgICAgdXNlclNlbGVjdCA9IGRvY0VsLnN0eWxlW3NlbGVjdFByb3BdO1xuICAgICAgICBkb2NFbC5zdHlsZVtzZWxlY3RQcm9wXSA9ICdub25lJztcbiAgICB9XG59O1xuZXhwb3J0cy5lbmFibGVEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XG5cbiAgICBpZiAoJ29uc2VsZWN0c3RhcnQnIGluIGRvY3VtZW50KSB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XG4gICAgZWxzZSBpZiAoc2VsZWN0UHJvcCkgZG9jRWwuc3R5bGVbc2VsZWN0UHJvcF0gPSB1c2VyU2VsZWN0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgb246IGZ1bmN0aW9uKHR5cGUsIGZuKSB7XG4gICAgICAgIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gdGhpcy5fZXZlbnRzW3R5cGVdIHx8IFtdO1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChmbik7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIG9mZjogZnVuY3Rpb24odHlwZSwgZm4pIHtcbiAgICAgICAgaWYgKCF0eXBlKSB7XG4gICAgICAgICAgICAvLyBjbGVhciBhbGwgbGlzdGVuZXJzIGlmIG5vIGFyZ3VtZW50cyBzcGVjaWZpZWRcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAoZm4pIHtcbiAgICAgICAgICAgIHZhciBpZHggPSB0aGlzLl9ldmVudHNbdHlwZV0uaW5kZXhPZihmbik7XG4gICAgICAgICAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBmaXJlOiBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBkYXRhID0gdXRpbC5leHRlbmQoe30sIGRhdGEpO1xuICAgICAgICB1dGlsLmV4dGVuZChkYXRhLCB7dHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzfSk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmNhbGwodGhpcywgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgbGlzdGVuczogZnVuY3Rpb24odHlwZSkge1xuICAgICAgICByZXR1cm4gISEodGhpcy5fZXZlbnRzICYmIHRoaXMuX2V2ZW50c1t0eXBlXSk7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaHM7XG5mdW5jdGlvbiBHbHlwaHMoYnVmZmVyLCBlbmQpIHtcbiAgICAvLyBQdWJsaWNcbiAgICB0aGlzLnN0YWNrcyA9IHt9O1xuICAgIC8vIFByaXZhdGVcbiAgICB0aGlzLl9idWZmZXIgPSBidWZmZXI7XG5cbiAgICB2YXIgdmFsLCB0YWc7XG4gICAgaWYgKHR5cGVvZiBlbmQgPT09ICd1bmRlZmluZWQnKSBlbmQgPSBidWZmZXIubGVuZ3RoO1xuICAgIHdoaWxlIChidWZmZXIucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhbCA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgICAgIHRhZyA9IHZhbCA+PiAzO1xuICAgICAgICBpZiAodGFnID09IDEpIHtcbiAgICAgICAgICAgIHZhciBmb250c3RhY2sgPSB0aGlzLnJlYWRGb250c3RhY2soKTtcbiAgICAgICAgICAgIHRoaXMuc3RhY2tzW2ZvbnRzdGFjay5uYW1lXSA9IGZvbnRzdGFjaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUud2Fybignc2tpcHBpbmcgdGlsZSB0YWcgJyArIHRhZyk7XG4gICAgICAgICAgICBidWZmZXIuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5HbHlwaHMucHJvdG90eXBlLnJlYWRGb250c3RhY2sgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnVmZmVyID0gdGhpcy5fYnVmZmVyO1xuICAgIHZhciBmb250c3RhY2sgPSB7IGdseXBoczoge30gfTtcblxuICAgIHZhciBieXRlcyA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgdmFyIHZhbCwgdGFnO1xuICAgIHZhciBlbmQgPSBidWZmZXIucG9zICsgYnl0ZXM7XG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgdmFsID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgdGFnID0gdmFsID4+IDM7XG5cbiAgICAgICAgaWYgKHRhZyA9PSAxKSB7XG4gICAgICAgICAgICBmb250c3RhY2submFtZSA9IGJ1ZmZlci5yZWFkU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDIpIHtcbiAgICAgICAgICAgIHZhciByYW5nZSA9IGJ1ZmZlci5yZWFkU3RyaW5nKCk7XG4gICAgICAgICAgICBmb250c3RhY2sucmFuZ2UgPSByYW5nZTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gMykge1xuICAgICAgICAgICAgdmFyIGdseXBoID0gdGhpcy5yZWFkR2x5cGgoKTtcbiAgICAgICAgICAgIGZvbnRzdGFjay5nbHlwaHNbZ2x5cGguaWRdID0gZ2x5cGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBidWZmZXIuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvbnRzdGFjaztcbn07XG5cbkdseXBocy5wcm90b3R5cGUucmVhZEdseXBoID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuX2J1ZmZlcjtcbiAgICB2YXIgZ2x5cGggPSB7fTtcblxuICAgIHZhciBieXRlcyA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgdmFyIHZhbCwgdGFnO1xuICAgIHZhciBlbmQgPSBidWZmZXIucG9zICsgYnl0ZXM7XG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgdmFsID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgdGFnID0gdmFsID4+IDM7XG5cbiAgICAgICAgaWYgKHRhZyA9PSAxKSB7XG4gICAgICAgICAgICBnbHlwaC5pZCA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDIpIHtcbiAgICAgICAgICAgIGdseXBoLmJpdG1hcCA9IGJ1ZmZlci5yZWFkQnVmZmVyKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDMpIHtcbiAgICAgICAgICAgIGdseXBoLndpZHRoID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNCkge1xuICAgICAgICAgICAgZ2x5cGguaGVpZ2h0ID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNSkge1xuICAgICAgICAgICAgZ2x5cGgubGVmdCA9IGJ1ZmZlci5yZWFkU1ZhcmludCgpO1xuICAgICAgICB9IGVsc2UgaWYgKHRhZyA9PSA2KSB7XG4gICAgICAgICAgICBnbHlwaC50b3AgPSBidWZmZXIucmVhZFNWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNykge1xuICAgICAgICAgICAgZ2x5cGguYWR2YW5jZSA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBidWZmZXIuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGdseXBoO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLypcbiAqIEEgW21vc3QtcmVjZW50bHktdXNlZCBjYWNoZV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DYWNoZV9hbGdvcml0aG1zKVxuICogd2l0aCBoYXNoIGxvb2t1cCBtYWRlIHBvc3NpYmxlIGJ5IGtlZXBpbmcgYSBsaXN0IG9mIGtleXMgaW4gcGFyYWxsZWwgdG9cbiAqIGFuIGFycmF5IG9mIGRpY3Rpb25hcnkgb2YgdmFsdWVzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gTVJVQ2FjaGU7XG5mdW5jdGlvbiBNUlVDYWNoZShsZW5ndGgsIG9uUmVtb3ZlKSB7XG4gICAgdGhpcy5tYXggPSBsZW5ndGg7XG4gICAgdGhpcy5vblJlbW92ZSA9IG9uUmVtb3ZlO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cblxuLypcbiAqIENsZWFycyB0aGUgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5saXN0ID0ge307XG4gICAgdGhpcy5vcmRlciA9IFtdO1xuXG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKlxuICogQWRkIGEga2V5LCB2YWx1ZSBjb21iaW5hdGlvbiB0byB0aGUgY2FjaGUsIHRyaW1taW5nIGl0cyBzaXplIGlmIHRoaXMgcHVzaGVzXG4gKiBpdCBvdmVyIG1heCBsZW5ndGguXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB0aGlzLmxpc3Rba2V5XSA9IGRhdGE7XG4gICAgdGhpcy5vcmRlci5wdXNoKGtleSk7XG5cbiAgICBpZiAodGhpcy5vcmRlci5sZW5ndGggPiB0aGlzLm1heCkge1xuICAgICAgICB2YXIgcmVtb3ZlZERhdGEgPSB0aGlzLmdldCh0aGlzLm9yZGVyWzBdKTtcbiAgICAgICAgaWYgKHJlbW92ZWREYXRhKSB0aGlzLm9uUmVtb3ZlKHJlbW92ZWREYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYGtleWAgaXMgcHJlc2VudFxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmxpc3Q7XG59O1xuXG4vKlxuICogTGlzdCBhbGwga2V5cyBpbiB0aGUgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLmtleXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5vcmRlcjtcbn07XG5cbi8qXG4gKiBHZXQgdGhlIHZhbHVlIGF0dGFjaGVkIHRvIGEgc3BlY2lmaWMga2V5LiBJZiB0aGUga2V5IGlzIG5vdCBmb3VuZCxcbiAqIHJldHVybnMgYG51bGxgXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsgcmV0dXJuIG51bGw7IH1cblxuICAgIHZhciBkYXRhID0gdGhpcy5saXN0W2tleV07XG5cbiAgICBkZWxldGUgdGhpcy5saXN0W2tleV07XG4gICAgdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGtleSksIDEpO1xuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUb2tlbnM7XG5cbnZhciB0b2tlblBhdHRlcm4gPSAveyhbXFx3LV0rKX0vO1xuXG5mdW5jdGlvbiByZXNvbHZlVG9rZW5zKHByb3BlcnRpZXMsIGV4cHJlc3Npb24pIHtcbiAgICB2YXIgbWF0Y2g7XG4gICAgdmFyIHZhbHVlO1xuICAgIHZhciB0ZXh0ID0gZXhwcmVzc2lvbjtcbiAgICB3aGlsZSAoKG1hdGNoID0gdGV4dC5tYXRjaCh0b2tlblBhdHRlcm4pKSkge1xuICAgICAgICB2YWx1ZSA9IHR5cGVvZiBwcm9wZXJ0aWVzW21hdGNoWzFdXSA9PT0gJ3VuZGVmaW5lZCcgPyAnJyA6IHByb3BlcnRpZXNbbWF0Y2hbMV1dO1xuICAgICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKG1hdGNoWzBdLCB2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihwYXRoLCBhY2Nlc3NUb2tlbikge1xuICAgIGFjY2Vzc1Rva2VuID0gYWNjZXNzVG9rZW4gfHwgY29uZmlnLkFDQ0VTU19UT0tFTjtcblxuICAgIGlmICghYWNjZXNzVG9rZW4gJiYgY29uZmlnLlJFUVVJUkVfQUNDRVNTX1RPS0VOKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQW4gQVBJIGFjY2VzcyB0b2tlbiBpcyByZXF1aXJlZCB0byB1c2UgTWFwYm94IEdMLiAnICtcbiAgICAgICAgICAgICdTZWUgaHR0cHM6Ly93d3cubWFwYm94LmNvbS9kZXZlbG9wZXJzL2FwaS8jYWNjZXNzLXRva2VucycpO1xuICAgIH1cblxuICAgIHZhciB1cmwgPSAoKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgJ2h0dHBzOicgPT09IGRvY3VtZW50LmxvY2F0aW9uLnByb3RvY29sKSB8fFxuICAgICAgICBjb25maWcuRk9SQ0VfSFRUUFMpID8gY29uZmlnLkhUVFBTX1VSTCA6IGNvbmZpZy5IVFRQX1VSTDtcbiAgICB1cmwgKz0gcGF0aDtcbiAgICB1cmwgKz0gdXJsLmluZGV4T2YoJz8nKSAhPT0gLTEgPyAnJmFjY2Vzc190b2tlbj0nIDogJz9hY2Nlc3NfdG9rZW49JztcblxuICAgIGlmIChjb25maWcuUkVRVUlSRV9BQ0NFU1NfVE9LRU4pIHtcbiAgICAgICAgaWYgKGFjY2Vzc1Rva2VuWzBdID09PSAncycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVXNlIGEgcHVibGljIGFjY2VzcyB0b2tlbiAocGsuKikgd2l0aCBNYXBib3ggR0wgSlMsIG5vdCBhIHNlY3JldCBhY2Nlc3MgdG9rZW4gKHNrLiopLiAnICtcbiAgICAgICAgICAgICAgICAnU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZGV2ZWxvcGVycy9hcGkvI2FjY2Vzcy10b2tlbnMnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVybCArPSBhY2Nlc3NUb2tlbjtcbiAgICB9XG5cbiAgICByZXR1cm4gdXJsO1xufTtcblxubW9kdWxlLmV4cG9ydHMudGlsZUpTT04gPSBmdW5jdGlvbihtYXBJRCwgYWNjZXNzVG9rZW4pIHtcbiAgICB2YXIgdXJsID0gbW9kdWxlLmV4cG9ydHMoJy8nICsgbWFwSUQgKyAnLmpzb24nLCBhY2Nlc3NUb2tlbik7XG5cbiAgICAvLyBUaWxlSlNPTiByZXF1ZXN0cyBuZWVkIGEgc2VjdXJlIGZsYWcgYXBwZW5kZWQgdG8gdGhlaXIgVVJMcyBzb1xuICAgIC8vIHRoYXQgdGhlIHNlcnZlciBrbm93cyB0byBzZW5kIFNTTC1pZmllZCByZXNvdXJjZSByZWZlcmVuY2VzLlxuICAgIGlmICh1cmwuaW5kZXhPZignaHR0cHMnKSA9PT0gMClcbiAgICAgICAgdXJsICs9ICcmc2VjdXJlJztcblxuICAgIHJldHVybiB1cmw7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVW5pdEJlemllciA9IHJlcXVpcmUoJ3VuaXRiZXppZXInKTtcblxuZXhwb3J0cy5lYXNlQ3ViaWNJbk91dCA9IGZ1bmN0aW9uICh0KSB7XG4gICAgaWYgKHQgPD0gMCkgcmV0dXJuIDA7XG4gICAgaWYgKHQgPj0gMSkgcmV0dXJuIDE7XG4gICAgdmFyIHQyID0gdCAqIHQsXG4gICAgICAgIHQzID0gdDIgKiB0O1xuICAgIHJldHVybiA0ICogKHQgPCAwLjUgPyB0MyA6IDMgKiAodCAtIHQyKSArIHQzIC0gMC43NSk7XG59O1xuXG5leHBvcnRzLmJlemllciA9IGZ1bmN0aW9uKHAxeCwgcDF5LCBwMngsIHAyeSkge1xuICAgIHZhciBiZXppZXIgPSBuZXcgVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiBiZXppZXIuc29sdmUodCk7XG4gICAgfTtcbn07XG5cbmV4cG9ydHMuZWFzZSA9IGV4cG9ydHMuYmV6aWVyKDAuMjUsIDAuMSwgMC4yNSwgMSk7XG5cbmV4cG9ydHMuaW50ZXJwID0gZnVuY3Rpb24gKGEsIGIsIHQpIHtcbiAgICByZXR1cm4gKGEgKiAoMSAtIHQpKSArIChiICogdCk7XG59O1xuXG5leHBvcnRzLnByZW11bHRpcGx5ID0gZnVuY3Rpb24gKGMpIHtcbiAgICBjWzBdICo9IGNbM107XG4gICAgY1sxXSAqPSBjWzNdO1xuICAgIGNbMl0gKj0gY1szXTtcbiAgICByZXR1cm4gYztcbn07XG5cbmV4cG9ydHMuYXN5bmNFYWNoID0gZnVuY3Rpb24gKGFycmF5LCBmbiwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVtYWluaW5nID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChyZW1haW5pbmcgPT09IDApIHJldHVybiBjYWxsYmFjaygpO1xuICAgIGZ1bmN0aW9uIGNoZWNrKCkgeyBpZiAoLS1yZW1haW5pbmcgPT09IDApIGNhbGxiYWNrKCk7IH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBmbihhcnJheVtpXSwgY2hlY2spO1xufTtcblxuZXhwb3J0cy5rZXlzRGlmZmVyZW5jZSA9IGZ1bmN0aW9uIChvYmosIG90aGVyKSB7XG4gICAgdmFyIGRpZmZlcmVuY2UgPSBbXTtcbiAgICBmb3IgKHZhciBpIGluIG9iaikge1xuICAgICAgICBpZiAoIShpIGluIG90aGVyKSkge1xuICAgICAgICAgICAgZGlmZmVyZW5jZS5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkaWZmZXJlbmNlO1xufTtcblxuZXhwb3J0cy5leHRlbmQgPSBmdW5jdGlvbiAoZGVzdCwgc3JjKSB7XG4gICAgZm9yICh2YXIgaSBpbiBzcmMpIHtcbiAgICAgICAgZGVzdFtpXSA9IHNyY1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG59O1xuXG5leHBvcnRzLmV4dGVuZEFsbCA9IGZ1bmN0aW9uIChkZXN0LCBzcmMpIHtcbiAgICBmb3IgKHZhciBpIGluIHNyYykge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGVzdCwgaSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzcmMsIGkpKTtcbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG59O1xuXG5leHBvcnRzLmluaGVyaXQgPSBmdW5jdGlvbiAocGFyZW50LCBwcm9wcykge1xuICAgIHZhciBwYXJlbnRQcm90byA9IHR5cGVvZiBwYXJlbnQgPT09ICdmdW5jdGlvbicgPyBwYXJlbnQucHJvdG90eXBlIDogcGFyZW50LFxuICAgICAgICBwcm90byA9IE9iamVjdC5jcmVhdGUocGFyZW50UHJvdG8pO1xuICAgIGV4cG9ydHMuZXh0ZW5kQWxsKHByb3RvLCBwcm9wcyk7XG4gICAgcmV0dXJuIHByb3RvO1xufTtcblxudmFyIGlkID0gMTtcblxuZXhwb3J0cy51bmlxdWVJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gaWQrKztcbn07XG5cbmV4cG9ydHMudGhyb3R0bGUgPSBmdW5jdGlvbiAoZm4sIHRpbWUsIGNvbnRleHQpIHtcbiAgICB2YXIgbG9jaywgYXJncywgd3JhcHBlckZuLCBsYXRlcjtcblxuICAgIGxhdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyByZXNldCBsb2NrIGFuZCBjYWxsIGlmIHF1ZXVlZFxuICAgICAgICBsb2NrID0gZmFsc2U7XG4gICAgICAgIGlmIChhcmdzKSB7XG4gICAgICAgICAgICB3cmFwcGVyRm4uYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICBhcmdzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgd3JhcHBlckZuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobG9jaykge1xuICAgICAgICAgICAgLy8gY2FsbGVkIHRvbyBzb29uLCBxdWV1ZSB0byBjYWxsIGxhdGVyXG4gICAgICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjYWxsIGFuZCBsb2NrIHVudGlsIGxhdGVyXG4gICAgICAgICAgICBmbi5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgc2V0VGltZW91dChsYXRlciwgdGltZSk7XG4gICAgICAgICAgICBsb2NrID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gd3JhcHBlckZuO1xufTtcblxuZXhwb3J0cy5kZWJvdW5jZSA9IGZ1bmN0aW9uKGZuLCB0aW1lKSB7XG4gICAgdmFyIHRpbWVyLCBhcmdzO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuXG4gICAgICAgIHRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZuLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICB9LCB0aW1lKTtcbiAgICB9O1xufTtcbiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJ2Jhc2U2NC1qcycpXG52YXIgaWVlZTc1NCA9IHJlcXVpcmUoJ2llZWU3NTQnKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcbkJ1ZmZlci5wb29sU2l6ZSA9IDgxOTJcblxuLyoqXG4gKiBJZiBgVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqIC0gSW1wbGVtZW50YXRpb24gbXVzdCBzdXBwb3J0IGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLlxuICogICBGaXJlZm94IDQtMjkgbGFja2VkIHN1cHBvcnQsIGZpeGVkIGluIEZpcmVmb3ggMzArLlxuICogICBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOC5cbiAqXG4gKiAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgIGluY29ycmVjdCBsZW5ndGggaW4gc29tZSBzaXR1YXRpb25zLlxuICpcbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBUWVBFRF9BUlJBWV9TVVBQT1JUYCB0byBgZmFsc2VgIHNvIHRoZXkgd2lsbFxuICogZ2V0IHRoZSBPYmplY3QgaW1wbGVtZW50YXRpb24sIHdoaWNoIGlzIHNsb3dlciBidXQgd2lsbCB3b3JrIGNvcnJlY3RseS5cbiAqL1xudmFyIFRZUEVEX0FSUkFZX1NVUFBPUlQgPSAoZnVuY3Rpb24gKCkge1xuICB0cnkge1xuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoMClcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoYnVmKVxuICAgIGFyci5mb28gPSBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9XG4gICAgcmV0dXJuIDQyID09PSBhcnIuZm9vKCkgJiYgLy8gdHlwZWQgYXJyYXkgaW5zdGFuY2VzIGNhbiBiZSBhdWdtZW50ZWRcbiAgICAgICAgdHlwZW9mIGFyci5zdWJhcnJheSA9PT0gJ2Z1bmN0aW9uJyAmJiAvLyBjaHJvbWUgOS0xMCBsYWNrIGBzdWJhcnJheWBcbiAgICAgICAgbmV3IFVpbnQ4QXJyYXkoMSkuc3ViYXJyYXkoMSwgMSkuYnl0ZUxlbmd0aCA9PT0gMCAvLyBpZTEwIGhhcyBicm9rZW4gYHN1YmFycmF5YFxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn0pKClcblxuLyoqXG4gKiBDbGFzczogQnVmZmVyXG4gKiA9PT09PT09PT09PT09XG4gKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBhcmUgYXVnbWVudGVkXG4gKiB3aXRoIGZ1bmN0aW9uIHByb3BlcnRpZXMgZm9yIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBBUEkgZnVuY3Rpb25zLiBXZSB1c2VcbiAqIGBVaW50OEFycmF5YCBzbyB0aGF0IHNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0IHJldHVybnNcbiAqIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIEJ5IGF1Z21lbnRpbmcgdGhlIGluc3RhbmNlcywgd2UgY2FuIGF2b2lkIG1vZGlmeWluZyB0aGUgYFVpbnQ4QXJyYXlgXG4gKiBwcm90b3R5cGUuXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlciAoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSlcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcihzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKVxuXG4gIHZhciB0eXBlID0gdHlwZW9mIHN1YmplY3RcblxuICAvLyBGaW5kIHRoZSBsZW5ndGhcbiAgdmFyIGxlbmd0aFxuICBpZiAodHlwZSA9PT0gJ251bWJlcicpXG4gICAgbGVuZ3RoID0gc3ViamVjdCA+IDAgPyBzdWJqZWN0ID4+PiAwIDogMFxuICBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIGlmIChlbmNvZGluZyA9PT0gJ2Jhc2U2NCcpXG4gICAgICBzdWJqZWN0ID0gYmFzZTY0Y2xlYW4oc3ViamVjdClcbiAgICBsZW5ndGggPSBCdWZmZXIuYnl0ZUxlbmd0aChzdWJqZWN0LCBlbmNvZGluZylcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0JyAmJiBzdWJqZWN0ICE9PSBudWxsKSB7IC8vIGFzc3VtZSBvYmplY3QgaXMgYXJyYXktbGlrZVxuICAgIGlmIChzdWJqZWN0LnR5cGUgPT09ICdCdWZmZXInICYmIGlzQXJyYXkoc3ViamVjdC5kYXRhKSlcbiAgICAgIHN1YmplY3QgPSBzdWJqZWN0LmRhdGFcbiAgICBsZW5ndGggPSArc3ViamVjdC5sZW5ndGggPiAwID8gTWF0aC5mbG9vcigrc3ViamVjdC5sZW5ndGgpIDogMFxuICB9IGVsc2VcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG5lZWRzIHRvIGJlIGEgbnVtYmVyLCBhcnJheSBvciBzdHJpbmcuJylcblxuICB2YXIgYnVmXG4gIGlmIChUWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUHJlZmVycmVkOiBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIGJ1ZiA9IEJ1ZmZlci5fYXVnbWVudChuZXcgVWludDhBcnJheShsZW5ndGgpKVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gVEhJUyBpbnN0YW5jZSBvZiBCdWZmZXIgKGNyZWF0ZWQgYnkgYG5ld2ApXG4gICAgYnVmID0gdGhpc1xuICAgIGJ1Zi5sZW5ndGggPSBsZW5ndGhcbiAgICBidWYuX2lzQnVmZmVyID0gdHJ1ZVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKFRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgdHlwZW9mIHN1YmplY3QuYnl0ZUxlbmd0aCA9PT0gJ251bWJlcicpIHtcbiAgICAvLyBTcGVlZCBvcHRpbWl6YXRpb24gLS0gdXNlIHNldCBpZiB3ZSdyZSBjb3B5aW5nIGZyb20gYSB0eXBlZCBhcnJheVxuICAgIGJ1Zi5fc2V0KHN1YmplY3QpXG4gIH0gZWxzZSBpZiAoaXNBcnJheWlzaChzdWJqZWN0KSkge1xuICAgIC8vIFRyZWF0IGFycmF5LWlzaCBvYmplY3RzIGFzIGEgYnl0ZSBhcnJheVxuICAgIGlmIChCdWZmZXIuaXNCdWZmZXIoc3ViamVjdCkpIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKylcbiAgICAgICAgYnVmW2ldID0gc3ViamVjdC5yZWFkVUludDgoaSlcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKVxuICAgICAgICBidWZbaV0gPSAoKHN1YmplY3RbaV0gJSAyNTYpICsgMjU2KSAlIDI1NlxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIGJ1Zi53cml0ZShzdWJqZWN0LCAwLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiAhVFlQRURfQVJSQVlfU1VQUE9SVCAmJiAhbm9aZXJvKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBidWZbaV0gPSAwXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG4vLyBTVEFUSUMgTUVUSE9EU1xuLy8gPT09PT09PT09PT09PT1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24gKHN0ciwgZW5jb2RpbmcpIHtcbiAgdmFyIHJldFxuICBzdHIgPSBzdHIudG9TdHJpbmcoKVxuICBzd2l0Y2ggKGVuY29kaW5nIHx8ICd1dGY4Jykge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoIC8gMlxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgICByZXQgPSB1dGY4VG9CeXRlcyhzdHIpLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdyYXcnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gYmFzZTY0VG9CeXRlcyhzdHIpLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aCAqIDJcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBlbmNvZGluZycpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIHRvdGFsTGVuZ3RoKSB7XG4gIGFzc2VydChpc0FycmF5KGxpc3QpLCAnVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdFssIGxlbmd0aF0pJylcblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcigwKVxuICB9IGVsc2UgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGxpc3RbMF1cbiAgfVxuXG4gIHZhciBpXG4gIGlmICh0b3RhbExlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdG90YWxMZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRvdGFsTGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIodG90YWxMZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldXG4gICAgaXRlbS5jb3B5KGJ1ZiwgcG9zKVxuICAgIHBvcyArPSBpdGVtLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiAoYSwgYikge1xuICBhc3NlcnQoQnVmZmVyLmlzQnVmZmVyKGEpICYmIEJ1ZmZlci5pc0J1ZmZlcihiKSwgJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKVxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IE1hdGgubWluKHgsIHkpOyBpIDwgbGVuICYmIGFbaV0gPT09IGJbaV07IGkrKykge31cbiAgaWYgKGkgIT09IGxlbikge1xuICAgIHggPSBhW2ldXG4gICAgeSA9IGJbaV1cbiAgfVxuICBpZiAoeCA8IHkpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZiAoeSA8IHgpIHtcbiAgICByZXR1cm4gMVxuICB9XG4gIHJldHVybiAwXG59XG5cbi8vIEJVRkZFUiBJTlNUQU5DRSBNRVRIT0RTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIC8vIG11c3QgYmUgYW4gZXZlbiBudW1iZXIgb2YgZGlnaXRzXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGFzc2VydChzdHJMZW4gJSAyID09PSAwLCAnSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGJ5dGUgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgYXNzZXJ0KCFpc05hTihieXRlKSwgJ0ludmFsaWQgaGV4IHN0cmluZycpXG4gICAgYnVmW29mZnNldCArIGldID0gYnl0ZVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIGJpbmFyeVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGFzY2lpV3JpdGUoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiB1dGYxNmxlV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gU3VwcG9ydCBib3RoIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZylcbiAgLy8gYW5kIHRoZSBsZWdhY3kgKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIGlmICghaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgfSBlbHNlIHsgIC8vIGxlZ2FjeVxuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aFxuICAgIGxlbmd0aCA9IHN3YXBcbiAgfVxuXG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG5cbiAgdmFyIHJldFxuICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgICByZXQgPSBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICByZXQgPSBiaW5hcnlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IHV0ZjE2bGVXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGVuY29kaW5nJylcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG4gIHN0YXJ0ID0gTnVtYmVyKHN0YXJ0KSB8fCAwXG4gIGVuZCA9IChlbmQgPT09IHVuZGVmaW5lZCkgPyBzZWxmLmxlbmd0aCA6IE51bWJlcihlbmQpXG5cbiAgLy8gRmFzdHBhdGggZW1wdHkgc3RyaW5nc1xuICBpZiAoZW5kID09PSBzdGFydClcbiAgICByZXR1cm4gJydcblxuICB2YXIgcmV0XG4gIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgICAgcmV0ID0gaGV4U2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgICAgcmV0ID0gdXRmOFNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIHJldCA9IGFzY2lpU2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgIHJldCA9IGJpbmFyeVNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXQgPSBiYXNlNjRTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gdXRmMTZsZVNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2RpbmcnKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiAoYikge1xuICBhc3NlcnQoQnVmZmVyLmlzQnVmZmVyKGIpLCAnQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiAoYikge1xuICBhc3NlcnQoQnVmZmVyLmlzQnVmZmVyKGIpLCAnQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiAodGFyZ2V0LCB0YXJnZXRfc3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHNvdXJjZSA9IHRoaXNcblxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAoIXRhcmdldF9zdGFydCkgdGFyZ2V0X3N0YXJ0ID0gMFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHNvdXJjZS5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgYXNzZXJ0KGVuZCA+PSBzdGFydCwgJ3NvdXJjZUVuZCA8IHNvdXJjZVN0YXJ0JylcbiAgYXNzZXJ0KHRhcmdldF9zdGFydCA+PSAwICYmIHRhcmdldF9zdGFydCA8IHRhcmdldC5sZW5ndGgsXG4gICAgICAndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGFzc2VydChzdGFydCA+PSAwICYmIHN0YXJ0IDwgc291cmNlLmxlbmd0aCwgJ3NvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBhc3NlcnQoZW5kID49IDAgJiYgZW5kIDw9IHNvdXJjZS5sZW5ndGgsICdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKVxuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0X3N0YXJ0IDwgZW5kIC0gc3RhcnQpXG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldF9zdGFydCArIHN0YXJ0XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG5cbiAgaWYgKGxlbiA8IDEwMCB8fCAhVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0X3N0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0YXJnZXQuX3NldCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksIHRhcmdldF9zdGFydClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJlcyA9ICcnXG4gIHZhciB0bXAgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICBpZiAoYnVmW2ldIDw9IDB4N0YpIHtcbiAgICAgIHJlcyArPSBkZWNvZGVVdGY4Q2hhcih0bXApICsgU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gICAgICB0bXAgPSAnJ1xuICAgIH0gZWxzZSB7XG4gICAgICB0bXAgKz0gJyUnICsgYnVmW2ldLnRvU3RyaW5nKDE2KVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXMgKyBkZWNvZGVVdGY4Q2hhcih0bXApXG59XG5cbmZ1bmN0aW9uIGFzY2lpU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gYmluYXJ5U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICByZXR1cm4gYXNjaWlTbGljZShidWYsIHN0YXJ0LCBlbmQpXG59XG5cbmZ1bmN0aW9uIGhleFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICB2YXIgb3V0ID0gJydcbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICBvdXQgKz0gdG9IZXgoYnVmW2ldKVxuICB9XG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGJ5dGVzID0gYnVmLnNsaWNlKHN0YXJ0LCBlbmQpXG4gIHZhciByZXMgPSAnJ1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0gKyBieXRlc1tpICsgMV0gKiAyNTYpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIHN0YXJ0ID0gfn5zdGFydFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbiA6IH5+ZW5kXG5cbiAgaWYgKHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ICs9IGxlbjtcbiAgICBpZiAoc3RhcnQgPCAwKVxuICAgICAgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApXG4gICAgICBlbmQgPSAwXG4gIH0gZWxzZSBpZiAoZW5kID4gbGVuKSB7XG4gICAgZW5kID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgc3RhcnQpXG4gICAgZW5kID0gc3RhcnRcblxuICBpZiAoVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHJldHVybiBCdWZmZXIuX2F1Z21lbnQodGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSlcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIHZhciBuZXdCdWYgPSBuZXcgQnVmZmVyKHNsaWNlTGVuLCB1bmRlZmluZWQsIHRydWUpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGljZUxlbjsgaSsrKSB7XG4gICAgICBuZXdCdWZbaV0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gICAgcmV0dXJuIG5ld0J1ZlxuICB9XG59XG5cbi8vIGBnZXRgIHdpbGwgYmUgcmVtb3ZlZCBpbiBOb2RlIDAuMTMrXG5CdWZmZXIucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5nZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLnJlYWRVSW50OChvZmZzZXQpXG59XG5cbi8vIGBzZXRgIHdpbGwgYmUgcmVtb3ZlZCBpbiBOb2RlIDAuMTMrXG5CdWZmZXIucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uICh2LCBvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5zZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLndyaXRlVUludDgodiwgb2Zmc2V0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpXG4gICAgcmV0dXJuXG5cbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5mdW5jdGlvbiByZWFkVUludDE2IChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDEgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgdmFyIHZhbFxuICBpZiAobGl0dGxlRW5kaWFuKSB7XG4gICAgdmFsID0gYnVmW29mZnNldF1cbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMV0gPDwgOFxuICB9IGVsc2Uge1xuICAgIHZhbCA9IGJ1ZltvZmZzZXRdIDw8IDhcbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMV1cbiAgfVxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHJlYWRVSW50MTYodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gcmVhZFVJbnQxNih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gcmVhZFVJbnQzMiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWxcbiAgaWYgKGxpdHRsZUVuZGlhbikge1xuICAgIGlmIChvZmZzZXQgKyAyIDwgbGVuKVxuICAgICAgdmFsID0gYnVmW29mZnNldCArIDJdIDw8IDE2XG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDFdIDw8IDhcbiAgICB2YWwgfD0gYnVmW29mZnNldF1cbiAgICBpZiAob2Zmc2V0ICsgMyA8IGxlbilcbiAgICAgIHZhbCA9IHZhbCArIChidWZbb2Zmc2V0ICsgM10gPDwgMjQgPj4+IDApXG4gIH0gZWxzZSB7XG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgPSBidWZbb2Zmc2V0ICsgMV0gPDwgMTZcbiAgICBpZiAob2Zmc2V0ICsgMiA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMl0gPDwgOFxuICAgIGlmIChvZmZzZXQgKyAzIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAzXVxuICAgIHZhbCA9IHZhbCArIChidWZbb2Zmc2V0XSA8PCAyNCA+Pj4gMClcbiAgfVxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHJlYWRVSW50MzIodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gcmVhZFVJbnQzMih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLFxuICAgICAgICAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpXG4gICAgcmV0dXJuXG5cbiAgdmFyIG5lZyA9IHRoaXNbb2Zmc2V0XSAmIDB4ODBcbiAgaWYgKG5lZylcbiAgICByZXR1cm4gKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xXG4gIGVsc2VcbiAgICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbmZ1bmN0aW9uIHJlYWRJbnQxNiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWwgPSByZWFkVUludDE2KGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIHRydWUpXG4gIHZhciBuZWcgPSB2YWwgJiAweDgwMDBcbiAgaWYgKG5lZylcbiAgICByZXR1cm4gKDB4ZmZmZiAtIHZhbCArIDEpICogLTFcbiAgZWxzZVxuICAgIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiByZWFkSW50MTYodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiByZWFkSW50MTYodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHJlYWRJbnQzMiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWwgPSByZWFkVUludDMyKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIHRydWUpXG4gIHZhciBuZWcgPSB2YWwgJiAweDgwMDAwMDAwXG4gIGlmIChuZWcpXG4gICAgcmV0dXJuICgweGZmZmZmZmZmIC0gdmFsICsgMSkgKiAtMVxuICBlbHNlXG4gICAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHJlYWRJbnQzMih0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHJlYWRJbnQzMih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gcmVhZEZsb2F0IChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHJldHVybiBpZWVlNzU0LnJlYWQoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gcmVhZEZsb2F0KHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gcmVhZEZsb2F0KHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiByZWFkRG91YmxlIChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgKyA3IDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHJldHVybiBpZWVlNzU0LnJlYWQoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHJlYWREb3VibGUodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gcmVhZERvdWJsZSh0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAndHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnVpbnQodmFsdWUsIDB4ZmYpXG4gIH1cblxuICBpZiAob2Zmc2V0ID49IHRoaXMubGVuZ3RoKSByZXR1cm5cblxuICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5mdW5jdGlvbiB3cml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ3RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZ1aW50KHZhbHVlLCAweGZmZmYpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGxlbiAtIG9mZnNldCwgMik7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPVxuICAgICAgICAodmFsdWUgJiAoMHhmZiA8PCAoOCAqIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpKSkpID4+PlxuICAgICAgICAgICAgKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkgKiA4XG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHdyaXRlVUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAndHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnVpbnQodmFsdWUsIDB4ZmZmZmZmZmYpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGxlbiAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPVxuICAgICAgICAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnNpbnQodmFsdWUsIDB4N2YsIC0weDgwKVxuICB9XG5cbiAgaWYgKG9mZnNldCA+PSB0aGlzLmxlbmd0aClcbiAgICByZXR1cm5cblxuICBpZiAodmFsdWUgPj0gMClcbiAgICB0aGlzLndyaXRlVUludDgodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpXG4gIGVsc2VcbiAgICB0aGlzLndyaXRlVUludDgoMHhmZiArIHZhbHVlICsgMSwgb2Zmc2V0LCBub0Fzc2VydClcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuZnVuY3Rpb24gd3JpdGVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZzaW50KHZhbHVlLCAweDdmZmYsIC0weDgwMDApXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZiAodmFsdWUgPj0gMClcbiAgICB3cml0ZVVJbnQxNihidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG4gIGVsc2VcbiAgICB3cml0ZVVJbnQxNihidWYsIDB4ZmZmZiArIHZhbHVlICsgMSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnNpbnQodmFsdWUsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgaWYgKHZhbHVlID49IDApXG4gICAgd3JpdGVVSW50MzIoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxuICBlbHNlXG4gICAgd3JpdGVVSW50MzIoYnVmLCAweGZmZmZmZmZmICsgdmFsdWUgKyAxLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmSUVFRTc1NCh2YWx1ZSwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgNyA8IGJ1Zi5sZW5ndGgsXG4gICAgICAgICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmSUVFRTc1NCh2YWx1ZSwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gZmlsbCh2YWx1ZSwgc3RhcnQ9MCwgZW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiAodmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCF2YWx1ZSkgdmFsdWUgPSAwXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCkgZW5kID0gdGhpcy5sZW5ndGhcblxuICBhc3NlcnQoZW5kID49IHN0YXJ0LCAnZW5kIDwgc3RhcnQnKVxuXG4gIC8vIEZpbGwgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgYXNzZXJ0KHN0YXJ0ID49IDAgJiYgc3RhcnQgPCB0aGlzLmxlbmd0aCwgJ3N0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBhc3NlcnQoZW5kID49IDAgJiYgZW5kIDw9IHRoaXMubGVuZ3RoLCAnZW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIHZhciBpXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IHZhbHVlXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBieXRlcyA9IHV0ZjhUb0J5dGVzKHZhbHVlLnRvU3RyaW5nKCkpXG4gICAgdmFyIGxlbiA9IGJ5dGVzLmxlbmd0aFxuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIHRoaXNbaV0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIG91dCA9IFtdXG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgb3V0W2ldID0gdG9IZXgodGhpc1tpXSlcbiAgICBpZiAoaSA9PT0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUykge1xuICAgICAgb3V0W2kgKyAxXSA9ICcuLi4nXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIG91dC5qb2luKCcgJykgKyAnPidcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gKCkge1xuICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKFRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCdWZmZXIudG9BcnJheUJ1ZmZlciBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlcicpXG4gIH1cbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG52YXIgQlAgPSBCdWZmZXIucHJvdG90eXBlXG5cbi8qKlxuICogQXVnbWVudCBhIFVpbnQ4QXJyYXkgKmluc3RhbmNlKiAobm90IHRoZSBVaW50OEFycmF5IGNsYXNzISkgd2l0aCBCdWZmZXIgbWV0aG9kc1xuICovXG5CdWZmZXIuX2F1Z21lbnQgPSBmdW5jdGlvbiAoYXJyKSB7XG4gIGFyci5faXNCdWZmZXIgPSB0cnVlXG5cbiAgLy8gc2F2ZSByZWZlcmVuY2UgdG8gb3JpZ2luYWwgVWludDhBcnJheSBnZXQvc2V0IG1ldGhvZHMgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fZ2V0ID0gYXJyLmdldFxuICBhcnIuX3NldCA9IGFyci5zZXRcblxuICAvLyBkZXByZWNhdGVkLCB3aWxsIGJlIHJlbW92ZWQgaW4gbm9kZSAwLjEzK1xuICBhcnIuZ2V0ID0gQlAuZ2V0XG4gIGFyci5zZXQgPSBCUC5zZXRcblxuICBhcnIud3JpdGUgPSBCUC53cml0ZVxuICBhcnIudG9TdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9Mb2NhbGVTdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9KU09OID0gQlAudG9KU09OXG4gIGFyci5lcXVhbHMgPSBCUC5lcXVhbHNcbiAgYXJyLmNvbXBhcmUgPSBCUC5jb21wYXJlXG4gIGFyci5jb3B5ID0gQlAuY29weVxuICBhcnIuc2xpY2UgPSBCUC5zbGljZVxuICBhcnIucmVhZFVJbnQ4ID0gQlAucmVhZFVJbnQ4XG4gIGFyci5yZWFkVUludDE2TEUgPSBCUC5yZWFkVUludDE2TEVcbiAgYXJyLnJlYWRVSW50MTZCRSA9IEJQLnJlYWRVSW50MTZCRVxuICBhcnIucmVhZFVJbnQzMkxFID0gQlAucmVhZFVJbnQzMkxFXG4gIGFyci5yZWFkVUludDMyQkUgPSBCUC5yZWFkVUludDMyQkVcbiAgYXJyLnJlYWRJbnQ4ID0gQlAucmVhZEludDhcbiAgYXJyLnJlYWRJbnQxNkxFID0gQlAucmVhZEludDE2TEVcbiAgYXJyLnJlYWRJbnQxNkJFID0gQlAucmVhZEludDE2QkVcbiAgYXJyLnJlYWRJbnQzMkxFID0gQlAucmVhZEludDMyTEVcbiAgYXJyLnJlYWRJbnQzMkJFID0gQlAucmVhZEludDMyQkVcbiAgYXJyLnJlYWRGbG9hdExFID0gQlAucmVhZEZsb2F0TEVcbiAgYXJyLnJlYWRGbG9hdEJFID0gQlAucmVhZEZsb2F0QkVcbiAgYXJyLnJlYWREb3VibGVMRSA9IEJQLnJlYWREb3VibGVMRVxuICBhcnIucmVhZERvdWJsZUJFID0gQlAucmVhZERvdWJsZUJFXG4gIGFyci53cml0ZVVJbnQ4ID0gQlAud3JpdGVVSW50OFxuICBhcnIud3JpdGVVSW50MTZMRSA9IEJQLndyaXRlVUludDE2TEVcbiAgYXJyLndyaXRlVUludDE2QkUgPSBCUC53cml0ZVVJbnQxNkJFXG4gIGFyci53cml0ZVVJbnQzMkxFID0gQlAud3JpdGVVSW50MzJMRVxuICBhcnIud3JpdGVVSW50MzJCRSA9IEJQLndyaXRlVUludDMyQkVcbiAgYXJyLndyaXRlSW50OCA9IEJQLndyaXRlSW50OFxuICBhcnIud3JpdGVJbnQxNkxFID0gQlAud3JpdGVJbnQxNkxFXG4gIGFyci53cml0ZUludDE2QkUgPSBCUC53cml0ZUludDE2QkVcbiAgYXJyLndyaXRlSW50MzJMRSA9IEJQLndyaXRlSW50MzJMRVxuICBhcnIud3JpdGVJbnQzMkJFID0gQlAud3JpdGVJbnQzMkJFXG4gIGFyci53cml0ZUZsb2F0TEUgPSBCUC53cml0ZUZsb2F0TEVcbiAgYXJyLndyaXRlRmxvYXRCRSA9IEJQLndyaXRlRmxvYXRCRVxuICBhcnIud3JpdGVEb3VibGVMRSA9IEJQLndyaXRlRG91YmxlTEVcbiAgYXJyLndyaXRlRG91YmxlQkUgPSBCUC53cml0ZURvdWJsZUJFXG4gIGFyci5maWxsID0gQlAuZmlsbFxuICBhcnIuaW5zcGVjdCA9IEJQLmluc3BlY3RcbiAgYXJyLnRvQXJyYXlCdWZmZXIgPSBCUC50b0FycmF5QnVmZmVyXG5cbiAgcmV0dXJuIGFyclxufVxuXG52YXIgSU5WQUxJRF9CQVNFNjRfUkUgPSAvW14rXFwvMC05QS16XS9nXG5cbmZ1bmN0aW9uIGJhc2U2NGNsZWFuIChzdHIpIHtcbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0cmluZ3RyaW0oc3RyKS5yZXBsYWNlKElOVkFMSURfQkFTRTY0X1JFLCAnJylcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gc3RyaW5ndHJpbSAoc3RyKSB7XG4gIGlmIChzdHIudHJpbSkgcmV0dXJuIHN0ci50cmltKClcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJylcbn1cblxuZnVuY3Rpb24gaXNBcnJheSAoc3ViamVjdCkge1xuICByZXR1cm4gKEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKHN1YmplY3QpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHN1YmplY3QpID09PSAnW29iamVjdCBBcnJheV0nXG4gIH0pKHN1YmplY3QpXG59XG5cbmZ1bmN0aW9uIGlzQXJyYXlpc2ggKHN1YmplY3QpIHtcbiAgcmV0dXJuIGlzQXJyYXkoc3ViamVjdCkgfHwgQnVmZmVyLmlzQnVmZmVyKHN1YmplY3QpIHx8XG4gICAgICBzdWJqZWN0ICYmIHR5cGVvZiBzdWJqZWN0ID09PSAnb2JqZWN0JyAmJlxuICAgICAgdHlwZW9mIHN1YmplY3QubGVuZ3RoID09PSAnbnVtYmVyJ1xufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGIgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGlmIChiIDw9IDB4N0YpIHtcbiAgICAgIGJ5dGVBcnJheS5wdXNoKGIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBzdGFydCA9IGlcbiAgICAgIGlmIChiID49IDB4RDgwMCAmJiBiIDw9IDB4REZGRikgaSsrXG4gICAgICB2YXIgaCA9IGVuY29kZVVSSUNvbXBvbmVudChzdHIuc2xpY2Uoc3RhcnQsIGkrMSkpLnN1YnN0cigxKS5zcGxpdCgnJScpXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGgubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgYnl0ZUFycmF5LnB1c2gocGFyc2VJbnQoaFtqXSwgMTYpKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGMsIGhpLCBsb1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShzdHIpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKVxuICAgICAgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiBkZWNvZGVVdGY4Q2hhciAoc3RyKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHIpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4RkZGRCkgLy8gVVRGIDggaW52YWxpZCBjaGFyXG4gIH1cbn1cblxuLypcbiAqIFdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHZhbHVlIGlzIGEgdmFsaWQgaW50ZWdlci4gVGhpcyBtZWFucyB0aGF0IGl0XG4gKiBpcyBub24tbmVnYXRpdmUuIEl0IGhhcyBubyBmcmFjdGlvbmFsIGNvbXBvbmVudCBhbmQgdGhhdCBpdCBkb2VzIG5vdFxuICogZXhjZWVkIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHZlcmlmdWludCAodmFsdWUsIG1heCkge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPj0gMCwgJ3NwZWNpZmllZCBhIG5lZ2F0aXZlIHZhbHVlIGZvciB3cml0aW5nIGFuIHVuc2lnbmVkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlIDw9IG1heCwgJ3ZhbHVlIGlzIGxhcmdlciB0aGFuIG1heGltdW0gdmFsdWUgZm9yIHR5cGUnKVxuICBhc3NlcnQoTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlLCAndmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQnKVxufVxuXG5mdW5jdGlvbiB2ZXJpZnNpbnQgKHZhbHVlLCBtYXgsIG1pbikge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPD0gbWF4LCAndmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlID49IG1pbiwgJ3ZhbHVlIHNtYWxsZXIgdGhhbiBtaW5pbXVtIGFsbG93ZWQgdmFsdWUnKVxuICBhc3NlcnQoTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlLCAndmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQnKVxufVxuXG5mdW5jdGlvbiB2ZXJpZklFRUU3NTQgKHZhbHVlLCBtYXgsIG1pbikge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPD0gbWF4LCAndmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlID49IG1pbiwgJ3ZhbHVlIHNtYWxsZXIgdGhhbiBtaW5pbXVtIGFsbG93ZWQgdmFsdWUnKVxufVxuXG5mdW5jdGlvbiBhc3NlcnQgKHRlc3QsIG1lc3NhZ2UpIHtcbiAgaWYgKCF0ZXN0KSB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSB8fCAnRmFpbGVkIGFzc2VydGlvbicpXG59XG4iLCJ2YXIgbG9va3VwID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nO1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuICB2YXIgQXJyID0gKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJylcbiAgICA/IFVpbnQ4QXJyYXlcbiAgICA6IEFycmF5XG5cblx0dmFyIFBMVVMgICA9ICcrJy5jaGFyQ29kZUF0KDApXG5cdHZhciBTTEFTSCAgPSAnLycuY2hhckNvZGVBdCgwKVxuXHR2YXIgTlVNQkVSID0gJzAnLmNoYXJDb2RlQXQoMClcblx0dmFyIExPV0VSICA9ICdhJy5jaGFyQ29kZUF0KDApXG5cdHZhciBVUFBFUiAgPSAnQScuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTKVxuXHRcdFx0cmV0dXJuIDYyIC8vICcrJ1xuXHRcdGlmIChjb2RlID09PSBTTEFTSClcblx0XHRcdHJldHVybiA2MyAvLyAnLydcblx0XHRpZiAoY29kZSA8IE5VTUJFUilcblx0XHRcdHJldHVybiAtMSAvL25vIG1hdGNoXG5cdFx0aWYgKGNvZGUgPCBOVU1CRVIgKyAxMClcblx0XHRcdHJldHVybiBjb2RlIC0gTlVNQkVSICsgMjYgKyAyNlxuXHRcdGlmIChjb2RlIDwgVVBQRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gVVBQRVJcblx0XHRpZiAoY29kZSA8IExPV0VSICsgMjYpXG5cdFx0XHRyZXR1cm4gY29kZSAtIExPV0VSICsgMjZcblx0fVxuXG5cdGZ1bmN0aW9uIGI2NFRvQnl0ZUFycmF5IChiNjQpIHtcblx0XHR2YXIgaSwgaiwgbCwgdG1wLCBwbGFjZUhvbGRlcnMsIGFyclxuXG5cdFx0aWYgKGI2NC5sZW5ndGggJSA0ID4gMCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0Jylcblx0XHR9XG5cblx0XHQvLyB0aGUgbnVtYmVyIG9mIGVxdWFsIHNpZ25zIChwbGFjZSBob2xkZXJzKVxuXHRcdC8vIGlmIHRoZXJlIGFyZSB0d28gcGxhY2Vob2xkZXJzLCB0aGFuIHRoZSB0d28gY2hhcmFjdGVycyBiZWZvcmUgaXRcblx0XHQvLyByZXByZXNlbnQgb25lIGJ5dGVcblx0XHQvLyBpZiB0aGVyZSBpcyBvbmx5IG9uZSwgdGhlbiB0aGUgdGhyZWUgY2hhcmFjdGVycyBiZWZvcmUgaXQgcmVwcmVzZW50IDIgYnl0ZXNcblx0XHQvLyB0aGlzIGlzIGp1c3QgYSBjaGVhcCBoYWNrIHRvIG5vdCBkbyBpbmRleE9mIHR3aWNlXG5cdFx0dmFyIGxlbiA9IGI2NC5sZW5ndGhcblx0XHRwbGFjZUhvbGRlcnMgPSAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMikgPyAyIDogJz0nID09PSBiNjQuY2hhckF0KGxlbiAtIDEpID8gMSA6IDBcblxuXHRcdC8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuXHRcdGFyciA9IG5ldyBBcnIoYjY0Lmxlbmd0aCAqIDMgLyA0IC0gcGxhY2VIb2xkZXJzKVxuXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuXHRcdGwgPSBwbGFjZUhvbGRlcnMgPiAwID8gYjY0Lmxlbmd0aCAtIDQgOiBiNjQubGVuZ3RoXG5cblx0XHR2YXIgTCA9IDBcblxuXHRcdGZ1bmN0aW9uIHB1c2ggKHYpIHtcblx0XHRcdGFycltMKytdID0gdlxuXHRcdH1cblxuXHRcdGZvciAoaSA9IDAsIGogPSAwOyBpIDwgbDsgaSArPSA0LCBqICs9IDMpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTgpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgMTIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAyKSkgPDwgNikgfCBkZWNvZGUoYjY0LmNoYXJBdChpICsgMykpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDAwMCkgPj4gMTYpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDApID4+IDgpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlSG9sZGVycyA9PT0gMikge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAyKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpID4+IDQpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fSBlbHNlIGlmIChwbGFjZUhvbGRlcnMgPT09IDEpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTApIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgNCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA+PiAyKVxuXHRcdFx0cHVzaCgodG1wID4+IDgpICYgMHhGRilcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRyZXR1cm4gYXJyXG5cdH1cblxuXHRmdW5jdGlvbiB1aW50OFRvQmFzZTY0ICh1aW50OCkge1xuXHRcdHZhciBpLFxuXHRcdFx0ZXh0cmFCeXRlcyA9IHVpbnQ4Lmxlbmd0aCAlIDMsIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG5cdFx0XHRvdXRwdXQgPSBcIlwiLFxuXHRcdFx0dGVtcCwgbGVuZ3RoXG5cblx0XHRmdW5jdGlvbiBlbmNvZGUgKG51bSkge1xuXHRcdFx0cmV0dXJuIGxvb2t1cC5jaGFyQXQobnVtKVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG5cdFx0XHRyZXR1cm4gZW5jb2RlKG51bSA+PiAxOCAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiAxMiAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiA2ICYgMHgzRikgKyBlbmNvZGUobnVtICYgMHgzRilcblx0XHR9XG5cblx0XHQvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG5cdFx0Zm9yIChpID0gMCwgbGVuZ3RoID0gdWludDgubGVuZ3RoIC0gZXh0cmFCeXRlczsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG5cdFx0XHR0ZW1wID0gKHVpbnQ4W2ldIDw8IDE2KSArICh1aW50OFtpICsgMV0gPDwgOCkgKyAodWludDhbaSArIDJdKVxuXHRcdFx0b3V0cHV0ICs9IHRyaXBsZXRUb0Jhc2U2NCh0ZW1wKVxuXHRcdH1cblxuXHRcdC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcblx0XHRzd2l0Y2ggKGV4dHJhQnl0ZXMpIHtcblx0XHRcdGNhc2UgMTpcblx0XHRcdFx0dGVtcCA9IHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUodGVtcCA+PiAyKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9PSdcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0dGVtcCA9ICh1aW50OFt1aW50OC5sZW5ndGggLSAyXSA8PCA4KSArICh1aW50OFt1aW50OC5sZW5ndGggLSAxXSlcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDEwKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wID4+IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA8PCAyKSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSAnPSdcblx0XHRcdFx0YnJlYWtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0cHV0XG5cdH1cblxuXHRleHBvcnRzLnRvQnl0ZUFycmF5ID0gYjY0VG9CeXRlQXJyYXlcblx0ZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gdWludDhUb0Jhc2U2NFxufSh0eXBlb2YgZXhwb3J0cyA9PT0gJ3VuZGVmaW5lZCcgPyAodGhpcy5iYXNlNjRqcyA9IHt9KSA6IGV4cG9ydHMpKVxuIiwiZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24oYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldO1xuXG4gIGkgKz0gZDtcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKTtcbiAgcyA+Pj0gKC1uQml0cyk7XG4gIG5CaXRzICs9IGVMZW47XG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSBlICogMjU2ICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpO1xuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xuICBlID4+PSAoLW5CaXRzKTtcbiAgbkJpdHMgKz0gbUxlbjtcbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCk7XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzO1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSk7XG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKTtcbiAgICBlID0gZSAtIGVCaWFzO1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pO1xufTtcblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMDtcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKTtcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMDtcbiAgICBlID0gZU1heDtcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMik7XG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tO1xuICAgICAgYyAqPSAyO1xuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gYztcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpO1xuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrKztcbiAgICAgIGMgLz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwO1xuICAgICAgZSA9IGVNYXg7XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IGUgKyBlQmlhcztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IDA7XG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCk7XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbTtcbiAgZUxlbiArPSBtTGVuO1xuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpO1xuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyODtcbn07XG4iLCIvLyAoYykgRGVhbiBNY05hbWVlIDxkZWFuQGdtYWlsLmNvbT4sIDIwMTIuXG4vL1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL2RlYW5tL2Nzcy1jb2xvci1wYXJzZXItanNcbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuLy8gRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HU1xuLy8gSU4gVEhFIFNPRlRXQVJFLlxuXG4vLyBodHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLWNvbG9yL1xudmFyIGtDU1NDb2xvclRhYmxlID0ge1xuICBcInRyYW5zcGFyZW50XCI6IFswLDAsMCwwXSwgXCJhbGljZWJsdWVcIjogWzI0MCwyNDgsMjU1LDFdLFxuICBcImFudGlxdWV3aGl0ZVwiOiBbMjUwLDIzNSwyMTUsMV0sIFwiYXF1YVwiOiBbMCwyNTUsMjU1LDFdLFxuICBcImFxdWFtYXJpbmVcIjogWzEyNywyNTUsMjEyLDFdLCBcImF6dXJlXCI6IFsyNDAsMjU1LDI1NSwxXSxcbiAgXCJiZWlnZVwiOiBbMjQ1LDI0NSwyMjAsMV0sIFwiYmlzcXVlXCI6IFsyNTUsMjI4LDE5NiwxXSxcbiAgXCJibGFja1wiOiBbMCwwLDAsMV0sIFwiYmxhbmNoZWRhbG1vbmRcIjogWzI1NSwyMzUsMjA1LDFdLFxuICBcImJsdWVcIjogWzAsMCwyNTUsMV0sIFwiYmx1ZXZpb2xldFwiOiBbMTM4LDQzLDIyNiwxXSxcbiAgXCJicm93blwiOiBbMTY1LDQyLDQyLDFdLCBcImJ1cmx5d29vZFwiOiBbMjIyLDE4NCwxMzUsMV0sXG4gIFwiY2FkZXRibHVlXCI6IFs5NSwxNTgsMTYwLDFdLCBcImNoYXJ0cmV1c2VcIjogWzEyNywyNTUsMCwxXSxcbiAgXCJjaG9jb2xhdGVcIjogWzIxMCwxMDUsMzAsMV0sIFwiY29yYWxcIjogWzI1NSwxMjcsODAsMV0sXG4gIFwiY29ybmZsb3dlcmJsdWVcIjogWzEwMCwxNDksMjM3LDFdLCBcImNvcm5zaWxrXCI6IFsyNTUsMjQ4LDIyMCwxXSxcbiAgXCJjcmltc29uXCI6IFsyMjAsMjAsNjAsMV0sIFwiY3lhblwiOiBbMCwyNTUsMjU1LDFdLFxuICBcImRhcmtibHVlXCI6IFswLDAsMTM5LDFdLCBcImRhcmtjeWFuXCI6IFswLDEzOSwxMzksMV0sXG4gIFwiZGFya2dvbGRlbnJvZFwiOiBbMTg0LDEzNCwxMSwxXSwgXCJkYXJrZ3JheVwiOiBbMTY5LDE2OSwxNjksMV0sXG4gIFwiZGFya2dyZWVuXCI6IFswLDEwMCwwLDFdLCBcImRhcmtncmV5XCI6IFsxNjksMTY5LDE2OSwxXSxcbiAgXCJkYXJra2hha2lcIjogWzE4OSwxODMsMTA3LDFdLCBcImRhcmttYWdlbnRhXCI6IFsxMzksMCwxMzksMV0sXG4gIFwiZGFya29saXZlZ3JlZW5cIjogWzg1LDEwNyw0NywxXSwgXCJkYXJrb3JhbmdlXCI6IFsyNTUsMTQwLDAsMV0sXG4gIFwiZGFya29yY2hpZFwiOiBbMTUzLDUwLDIwNCwxXSwgXCJkYXJrcmVkXCI6IFsxMzksMCwwLDFdLFxuICBcImRhcmtzYWxtb25cIjogWzIzMywxNTAsMTIyLDFdLCBcImRhcmtzZWFncmVlblwiOiBbMTQzLDE4OCwxNDMsMV0sXG4gIFwiZGFya3NsYXRlYmx1ZVwiOiBbNzIsNjEsMTM5LDFdLCBcImRhcmtzbGF0ZWdyYXlcIjogWzQ3LDc5LDc5LDFdLFxuICBcImRhcmtzbGF0ZWdyZXlcIjogWzQ3LDc5LDc5LDFdLCBcImRhcmt0dXJxdW9pc2VcIjogWzAsMjA2LDIwOSwxXSxcbiAgXCJkYXJrdmlvbGV0XCI6IFsxNDgsMCwyMTEsMV0sIFwiZGVlcHBpbmtcIjogWzI1NSwyMCwxNDcsMV0sXG4gIFwiZGVlcHNreWJsdWVcIjogWzAsMTkxLDI1NSwxXSwgXCJkaW1ncmF5XCI6IFsxMDUsMTA1LDEwNSwxXSxcbiAgXCJkaW1ncmV5XCI6IFsxMDUsMTA1LDEwNSwxXSwgXCJkb2RnZXJibHVlXCI6IFszMCwxNDQsMjU1LDFdLFxuICBcImZpcmVicmlja1wiOiBbMTc4LDM0LDM0LDFdLCBcImZsb3JhbHdoaXRlXCI6IFsyNTUsMjUwLDI0MCwxXSxcbiAgXCJmb3Jlc3RncmVlblwiOiBbMzQsMTM5LDM0LDFdLCBcImZ1Y2hzaWFcIjogWzI1NSwwLDI1NSwxXSxcbiAgXCJnYWluc2Jvcm9cIjogWzIyMCwyMjAsMjIwLDFdLCBcImdob3N0d2hpdGVcIjogWzI0OCwyNDgsMjU1LDFdLFxuICBcImdvbGRcIjogWzI1NSwyMTUsMCwxXSwgXCJnb2xkZW5yb2RcIjogWzIxOCwxNjUsMzIsMV0sXG4gIFwiZ3JheVwiOiBbMTI4LDEyOCwxMjgsMV0sIFwiZ3JlZW5cIjogWzAsMTI4LDAsMV0sXG4gIFwiZ3JlZW55ZWxsb3dcIjogWzE3MywyNTUsNDcsMV0sIFwiZ3JleVwiOiBbMTI4LDEyOCwxMjgsMV0sXG4gIFwiaG9uZXlkZXdcIjogWzI0MCwyNTUsMjQwLDFdLCBcImhvdHBpbmtcIjogWzI1NSwxMDUsMTgwLDFdLFxuICBcImluZGlhbnJlZFwiOiBbMjA1LDkyLDkyLDFdLCBcImluZGlnb1wiOiBbNzUsMCwxMzAsMV0sXG4gIFwiaXZvcnlcIjogWzI1NSwyNTUsMjQwLDFdLCBcImtoYWtpXCI6IFsyNDAsMjMwLDE0MCwxXSxcbiAgXCJsYXZlbmRlclwiOiBbMjMwLDIzMCwyNTAsMV0sIFwibGF2ZW5kZXJibHVzaFwiOiBbMjU1LDI0MCwyNDUsMV0sXG4gIFwibGF3bmdyZWVuXCI6IFsxMjQsMjUyLDAsMV0sIFwibGVtb25jaGlmZm9uXCI6IFsyNTUsMjUwLDIwNSwxXSxcbiAgXCJsaWdodGJsdWVcIjogWzE3MywyMTYsMjMwLDFdLCBcImxpZ2h0Y29yYWxcIjogWzI0MCwxMjgsMTI4LDFdLFxuICBcImxpZ2h0Y3lhblwiOiBbMjI0LDI1NSwyNTUsMV0sIFwibGlnaHRnb2xkZW5yb2R5ZWxsb3dcIjogWzI1MCwyNTAsMjEwLDFdLFxuICBcImxpZ2h0Z3JheVwiOiBbMjExLDIxMSwyMTEsMV0sIFwibGlnaHRncmVlblwiOiBbMTQ0LDIzOCwxNDQsMV0sXG4gIFwibGlnaHRncmV5XCI6IFsyMTEsMjExLDIxMSwxXSwgXCJsaWdodHBpbmtcIjogWzI1NSwxODIsMTkzLDFdLFxuICBcImxpZ2h0c2FsbW9uXCI6IFsyNTUsMTYwLDEyMiwxXSwgXCJsaWdodHNlYWdyZWVuXCI6IFszMiwxNzgsMTcwLDFdLFxuICBcImxpZ2h0c2t5Ymx1ZVwiOiBbMTM1LDIwNiwyNTAsMV0sIFwibGlnaHRzbGF0ZWdyYXlcIjogWzExOSwxMzYsMTUzLDFdLFxuICBcImxpZ2h0c2xhdGVncmV5XCI6IFsxMTksMTM2LDE1MywxXSwgXCJsaWdodHN0ZWVsYmx1ZVwiOiBbMTc2LDE5NiwyMjIsMV0sXG4gIFwibGlnaHR5ZWxsb3dcIjogWzI1NSwyNTUsMjI0LDFdLCBcImxpbWVcIjogWzAsMjU1LDAsMV0sXG4gIFwibGltZWdyZWVuXCI6IFs1MCwyMDUsNTAsMV0sIFwibGluZW5cIjogWzI1MCwyNDAsMjMwLDFdLFxuICBcIm1hZ2VudGFcIjogWzI1NSwwLDI1NSwxXSwgXCJtYXJvb25cIjogWzEyOCwwLDAsMV0sXG4gIFwibWVkaXVtYXF1YW1hcmluZVwiOiBbMTAyLDIwNSwxNzAsMV0sIFwibWVkaXVtYmx1ZVwiOiBbMCwwLDIwNSwxXSxcbiAgXCJtZWRpdW1vcmNoaWRcIjogWzE4Niw4NSwyMTEsMV0sIFwibWVkaXVtcHVycGxlXCI6IFsxNDcsMTEyLDIxOSwxXSxcbiAgXCJtZWRpdW1zZWFncmVlblwiOiBbNjAsMTc5LDExMywxXSwgXCJtZWRpdW1zbGF0ZWJsdWVcIjogWzEyMywxMDQsMjM4LDFdLFxuICBcIm1lZGl1bXNwcmluZ2dyZWVuXCI6IFswLDI1MCwxNTQsMV0sIFwibWVkaXVtdHVycXVvaXNlXCI6IFs3MiwyMDksMjA0LDFdLFxuICBcIm1lZGl1bXZpb2xldHJlZFwiOiBbMTk5LDIxLDEzMywxXSwgXCJtaWRuaWdodGJsdWVcIjogWzI1LDI1LDExMiwxXSxcbiAgXCJtaW50Y3JlYW1cIjogWzI0NSwyNTUsMjUwLDFdLCBcIm1pc3R5cm9zZVwiOiBbMjU1LDIyOCwyMjUsMV0sXG4gIFwibW9jY2FzaW5cIjogWzI1NSwyMjgsMTgxLDFdLCBcIm5hdmFqb3doaXRlXCI6IFsyNTUsMjIyLDE3MywxXSxcbiAgXCJuYXZ5XCI6IFswLDAsMTI4LDFdLCBcIm9sZGxhY2VcIjogWzI1MywyNDUsMjMwLDFdLFxuICBcIm9saXZlXCI6IFsxMjgsMTI4LDAsMV0sIFwib2xpdmVkcmFiXCI6IFsxMDcsMTQyLDM1LDFdLFxuICBcIm9yYW5nZVwiOiBbMjU1LDE2NSwwLDFdLCBcIm9yYW5nZXJlZFwiOiBbMjU1LDY5LDAsMV0sXG4gIFwib3JjaGlkXCI6IFsyMTgsMTEyLDIxNCwxXSwgXCJwYWxlZ29sZGVucm9kXCI6IFsyMzgsMjMyLDE3MCwxXSxcbiAgXCJwYWxlZ3JlZW5cIjogWzE1MiwyNTEsMTUyLDFdLCBcInBhbGV0dXJxdW9pc2VcIjogWzE3NSwyMzgsMjM4LDFdLFxuICBcInBhbGV2aW9sZXRyZWRcIjogWzIxOSwxMTIsMTQ3LDFdLCBcInBhcGF5YXdoaXBcIjogWzI1NSwyMzksMjEzLDFdLFxuICBcInBlYWNocHVmZlwiOiBbMjU1LDIxOCwxODUsMV0sIFwicGVydVwiOiBbMjA1LDEzMyw2MywxXSxcbiAgXCJwaW5rXCI6IFsyNTUsMTkyLDIwMywxXSwgXCJwbHVtXCI6IFsyMjEsMTYwLDIyMSwxXSxcbiAgXCJwb3dkZXJibHVlXCI6IFsxNzYsMjI0LDIzMCwxXSwgXCJwdXJwbGVcIjogWzEyOCwwLDEyOCwxXSxcbiAgXCJyZWRcIjogWzI1NSwwLDAsMV0sIFwicm9zeWJyb3duXCI6IFsxODgsMTQzLDE0MywxXSxcbiAgXCJyb3lhbGJsdWVcIjogWzY1LDEwNSwyMjUsMV0sIFwic2FkZGxlYnJvd25cIjogWzEzOSw2OSwxOSwxXSxcbiAgXCJzYWxtb25cIjogWzI1MCwxMjgsMTE0LDFdLCBcInNhbmR5YnJvd25cIjogWzI0NCwxNjQsOTYsMV0sXG4gIFwic2VhZ3JlZW5cIjogWzQ2LDEzOSw4NywxXSwgXCJzZWFzaGVsbFwiOiBbMjU1LDI0NSwyMzgsMV0sXG4gIFwic2llbm5hXCI6IFsxNjAsODIsNDUsMV0sIFwic2lsdmVyXCI6IFsxOTIsMTkyLDE5MiwxXSxcbiAgXCJza3libHVlXCI6IFsxMzUsMjA2LDIzNSwxXSwgXCJzbGF0ZWJsdWVcIjogWzEwNiw5MCwyMDUsMV0sXG4gIFwic2xhdGVncmF5XCI6IFsxMTIsMTI4LDE0NCwxXSwgXCJzbGF0ZWdyZXlcIjogWzExMiwxMjgsMTQ0LDFdLFxuICBcInNub3dcIjogWzI1NSwyNTAsMjUwLDFdLCBcInNwcmluZ2dyZWVuXCI6IFswLDI1NSwxMjcsMV0sXG4gIFwic3RlZWxibHVlXCI6IFs3MCwxMzAsMTgwLDFdLCBcInRhblwiOiBbMjEwLDE4MCwxNDAsMV0sXG4gIFwidGVhbFwiOiBbMCwxMjgsMTI4LDFdLCBcInRoaXN0bGVcIjogWzIxNiwxOTEsMjE2LDFdLFxuICBcInRvbWF0b1wiOiBbMjU1LDk5LDcxLDFdLCBcInR1cnF1b2lzZVwiOiBbNjQsMjI0LDIwOCwxXSxcbiAgXCJ2aW9sZXRcIjogWzIzOCwxMzAsMjM4LDFdLCBcIndoZWF0XCI6IFsyNDUsMjIyLDE3OSwxXSxcbiAgXCJ3aGl0ZVwiOiBbMjU1LDI1NSwyNTUsMV0sIFwid2hpdGVzbW9rZVwiOiBbMjQ1LDI0NSwyNDUsMV0sXG4gIFwieWVsbG93XCI6IFsyNTUsMjU1LDAsMV0sIFwieWVsbG93Z3JlZW5cIjogWzE1NCwyMDUsNTAsMV19XG5cbmZ1bmN0aW9uIGNsYW1wX2Nzc19ieXRlKGkpIHsgIC8vIENsYW1wIHRvIGludGVnZXIgMCAuLiAyNTUuXG4gIGkgPSBNYXRoLnJvdW5kKGkpOyAgLy8gU2VlbXMgdG8gYmUgd2hhdCBDaHJvbWUgZG9lcyAodnMgdHJ1bmNhdGlvbikuXG4gIHJldHVybiBpIDwgMCA/IDAgOiBpID4gMjU1ID8gMjU1IDogaTtcbn1cblxuZnVuY3Rpb24gY2xhbXBfY3NzX2Zsb2F0KGYpIHsgIC8vIENsYW1wIHRvIGZsb2F0IDAuMCAuLiAxLjAuXG4gIHJldHVybiBmIDwgMCA/IDAgOiBmID4gMSA/IDEgOiBmO1xufVxuXG5mdW5jdGlvbiBwYXJzZV9jc3NfaW50KHN0cikgeyAgLy8gaW50IG9yIHBlcmNlbnRhZ2UuXG4gIGlmIChzdHJbc3RyLmxlbmd0aCAtIDFdID09PSAnJScpXG4gICAgcmV0dXJuIGNsYW1wX2Nzc19ieXRlKHBhcnNlRmxvYXQoc3RyKSAvIDEwMCAqIDI1NSk7XG4gIHJldHVybiBjbGFtcF9jc3NfYnl0ZShwYXJzZUludChzdHIpKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VfY3NzX2Zsb2F0KHN0cikgeyAgLy8gZmxvYXQgb3IgcGVyY2VudGFnZS5cbiAgaWYgKHN0cltzdHIubGVuZ3RoIC0gMV0gPT09ICclJylcbiAgICByZXR1cm4gY2xhbXBfY3NzX2Zsb2F0KHBhcnNlRmxvYXQoc3RyKSAvIDEwMCk7XG4gIHJldHVybiBjbGFtcF9jc3NfZmxvYXQocGFyc2VGbG9hdChzdHIpKTtcbn1cblxuZnVuY3Rpb24gY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKSB7XG4gIGlmIChoIDwgMCkgaCArPSAxO1xuICBlbHNlIGlmIChoID4gMSkgaCAtPSAxO1xuXG4gIGlmIChoICogNiA8IDEpIHJldHVybiBtMSArIChtMiAtIG0xKSAqIGggKiA2O1xuICBpZiAoaCAqIDIgPCAxKSByZXR1cm4gbTI7XG4gIGlmIChoICogMyA8IDIpIHJldHVybiBtMSArIChtMiAtIG0xKSAqICgyLzMgLSBoKSAqIDY7XG4gIHJldHVybiBtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VDU1NDb2xvcihjc3Nfc3RyKSB7XG4gIC8vIFJlbW92ZSBhbGwgd2hpdGVzcGFjZSwgbm90IGNvbXBsaWFudCwgYnV0IHNob3VsZCBqdXN0IGJlIG1vcmUgYWNjZXB0aW5nLlxuICB2YXIgc3RyID0gY3NzX3N0ci5yZXBsYWNlKC8gL2csICcnKS50b0xvd2VyQ2FzZSgpO1xuXG4gIC8vIENvbG9yIGtleXdvcmRzIChhbmQgdHJhbnNwYXJlbnQpIGxvb2t1cC5cbiAgaWYgKHN0ciBpbiBrQ1NTQ29sb3JUYWJsZSkgcmV0dXJuIGtDU1NDb2xvclRhYmxlW3N0cl0uc2xpY2UoKTsgIC8vIGR1cC5cblxuICAvLyAjYWJjIGFuZCAjYWJjMTIzIHN5bnRheC5cbiAgaWYgKHN0clswXSA9PT0gJyMnKSB7XG4gICAgaWYgKHN0ci5sZW5ndGggPT09IDQpIHtcbiAgICAgIHZhciBpdiA9IHBhcnNlSW50KHN0ci5zdWJzdHIoMSksIDE2KTsgIC8vIFRPRE8oZGVhbm0pOiBTdHJpY3RlciBwYXJzaW5nLlxuICAgICAgaWYgKCEoaXYgPj0gMCAmJiBpdiA8PSAweGZmZikpIHJldHVybiBudWxsOyAgLy8gQ292ZXJzIE5hTi5cbiAgICAgIHJldHVybiBbKChpdiAmIDB4ZjAwKSA+PiA0KSB8ICgoaXYgJiAweGYwMCkgPj4gOCksXG4gICAgICAgICAgICAgIChpdiAmIDB4ZjApIHwgKChpdiAmIDB4ZjApID4+IDQpLFxuICAgICAgICAgICAgICAoaXYgJiAweGYpIHwgKChpdiAmIDB4ZikgPDwgNCksXG4gICAgICAgICAgICAgIDFdO1xuICAgIH0gZWxzZSBpZiAoc3RyLmxlbmd0aCA9PT0gNykge1xuICAgICAgdmFyIGl2ID0gcGFyc2VJbnQoc3RyLnN1YnN0cigxKSwgMTYpOyAgLy8gVE9ETyhkZWFubSk6IFN0cmljdGVyIHBhcnNpbmcuXG4gICAgICBpZiAoIShpdiA+PSAwICYmIGl2IDw9IDB4ZmZmZmZmKSkgcmV0dXJuIG51bGw7ICAvLyBDb3ZlcnMgTmFOLlxuICAgICAgcmV0dXJuIFsoaXYgJiAweGZmMDAwMCkgPj4gMTYsXG4gICAgICAgICAgICAgIChpdiAmIDB4ZmYwMCkgPj4gOCxcbiAgICAgICAgICAgICAgaXYgJiAweGZmLFxuICAgICAgICAgICAgICAxXTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHZhciBvcCA9IHN0ci5pbmRleE9mKCcoJyksIGVwID0gc3RyLmluZGV4T2YoJyknKTtcbiAgaWYgKG9wICE9PSAtMSAmJiBlcCArIDEgPT09IHN0ci5sZW5ndGgpIHtcbiAgICB2YXIgZm5hbWUgPSBzdHIuc3Vic3RyKDAsIG9wKTtcbiAgICB2YXIgcGFyYW1zID0gc3RyLnN1YnN0cihvcCsxLCBlcC0ob3ArMSkpLnNwbGl0KCcsJyk7XG4gICAgdmFyIGFscGhhID0gMTsgIC8vIFRvIGFsbG93IGNhc2UgZmFsbHRocm91Z2guXG4gICAgc3dpdGNoIChmbmFtZSkge1xuICAgICAgY2FzZSAncmdiYSc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSA0KSByZXR1cm4gbnVsbDtcbiAgICAgICAgYWxwaGEgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zLnBvcCgpKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoLlxuICAgICAgY2FzZSAncmdiJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gW3BhcnNlX2Nzc19pbnQocGFyYW1zWzBdKSxcbiAgICAgICAgICAgICAgICBwYXJzZV9jc3NfaW50KHBhcmFtc1sxXSksXG4gICAgICAgICAgICAgICAgcGFyc2VfY3NzX2ludChwYXJhbXNbMl0pLFxuICAgICAgICAgICAgICAgIGFscGhhXTtcbiAgICAgIGNhc2UgJ2hzbGEnOlxuICAgICAgICBpZiAocGFyYW1zLmxlbmd0aCAhPT0gNCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGFscGhhID0gcGFyc2VfY3NzX2Zsb2F0KHBhcmFtcy5wb3AoKSk7XG4gICAgICAgIC8vIEZhbGwgdGhyb3VnaC5cbiAgICAgIGNhc2UgJ2hzbCc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSAzKSByZXR1cm4gbnVsbDtcbiAgICAgICAgdmFyIGggPSAoKChwYXJzZUZsb2F0KHBhcmFtc1swXSkgJSAzNjApICsgMzYwKSAlIDM2MCkgLyAzNjA7ICAvLyAwIC4uIDFcbiAgICAgICAgLy8gTk9URShkZWFubSk6IEFjY29yZGluZyB0byB0aGUgQ1NTIHNwZWMgcy9sIHNob3VsZCBvbmx5IGJlXG4gICAgICAgIC8vIHBlcmNlbnRhZ2VzLCBidXQgd2UgZG9uJ3QgYm90aGVyIGFuZCBsZXQgZmxvYXQgb3IgcGVyY2VudGFnZS5cbiAgICAgICAgdmFyIHMgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zWzFdKTtcbiAgICAgICAgdmFyIGwgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zWzJdKTtcbiAgICAgICAgdmFyIG0yID0gbCA8PSAwLjUgPyBsICogKHMgKyAxKSA6IGwgKyBzIC0gbCAqIHM7XG4gICAgICAgIHZhciBtMSA9IGwgKiAyIC0gbTI7XG4gICAgICAgIHJldHVybiBbY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKzEvMykgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGNsYW1wX2Nzc19ieXRlKGNzc19odWVfdG9fcmdiKG0xLCBtMiwgaCkgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGNsYW1wX2Nzc19ieXRlKGNzc19odWVfdG9fcmdiKG0xLCBtMiwgaC0xLzMpICogMjU1KSxcbiAgICAgICAgICAgICAgICBhbHBoYV07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxudHJ5IHsgZXhwb3J0cy5wYXJzZUNTU0NvbG9yID0gcGFyc2VDU1NDb2xvciB9IGNhdGNoKGUpIHsgfVxuIiwidmFyIGdlb2pzb25BcmVhID0gcmVxdWlyZSgnZ2VvanNvbi1hcmVhJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmV3aW5kO1xuXG5mdW5jdGlvbiByZXdpbmQoZ2osIG91dGVyKSB7XG4gICAgc3dpdGNoICgoZ2ogJiYgZ2oudHlwZSkgfHwgbnVsbCkge1xuICAgICAgICBjYXNlICdGZWF0dXJlQ29sbGVjdGlvbic6XG4gICAgICAgICAgICBnai5mZWF0dXJlcyA9IGdqLmZlYXR1cmVzLm1hcChjdXJyeU91dGVyKHJld2luZCwgb3V0ZXIpKTtcbiAgICAgICAgICAgIHJldHVybiBnajtcbiAgICAgICAgY2FzZSAnRmVhdHVyZSc6XG4gICAgICAgICAgICBnai5nZW9tZXRyeSA9IHJld2luZChnai5nZW9tZXRyeSwgb3V0ZXIpO1xuICAgICAgICAgICAgcmV0dXJuIGdqO1xuICAgICAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgICAgY2FzZSAnTXVsdGlQb2x5Z29uJzpcbiAgICAgICAgICAgIHJldHVybiBjb3JyZWN0KGdqLCBvdXRlcik7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZ2o7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjdXJyeU91dGVyKGEsIGIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oXykgeyByZXR1cm4gYShfLCBiKTsgfTtcbn1cblxuZnVuY3Rpb24gY29ycmVjdChfLCBvdXRlcikge1xuICAgIGlmIChfLnR5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgICBfLmNvb3JkaW5hdGVzID0gY29ycmVjdFJpbmdzKF8uY29vcmRpbmF0ZXMsIG91dGVyKTtcbiAgICB9IGVsc2UgaWYgKF8udHlwZSA9PT0gJ011bHRpUG9seWdvbicpIHtcbiAgICAgICAgXy5jb29yZGluYXRlcyA9IF8uY29vcmRpbmF0ZXMubWFwKGN1cnJ5T3V0ZXIoY29ycmVjdFJpbmdzLCBvdXRlcikpO1xuICAgIH1cbiAgICByZXR1cm4gXztcbn1cblxuZnVuY3Rpb24gY29ycmVjdFJpbmdzKF8sIG91dGVyKSB7XG4gICAgb3V0ZXIgPSAhIW91dGVyO1xuICAgIF9bMF0gPSB3aW5kKF9bMF0sICFvdXRlcik7XG4gICAgZm9yICh2YXIgaSA9IDE7IGkgPCBfLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIF9baV0gPSB3aW5kKF9baV0sIG91dGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIF87XG59XG5cbmZ1bmN0aW9uIHdpbmQoXywgZGlyKSB7XG4gICAgcmV0dXJuIGN3KF8pID09PSBkaXIgPyBfIDogXy5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIGN3KF8pIHtcbiAgICByZXR1cm4gZ2VvanNvbkFyZWEucmluZyhfKSA+PSAwO1xufVxuIiwidmFyIHdnczg0ID0gcmVxdWlyZSgnd2dzODQnKTtcblxubW9kdWxlLmV4cG9ydHMuZ2VvbWV0cnkgPSBnZW9tZXRyeTtcbm1vZHVsZS5leHBvcnRzLnJpbmcgPSByaW5nQXJlYTtcblxuZnVuY3Rpb24gZ2VvbWV0cnkoXykge1xuICAgIGlmIChfLnR5cGUgPT09ICdQb2x5Z29uJykgcmV0dXJuIHBvbHlnb25BcmVhKF8uY29vcmRpbmF0ZXMpO1xuICAgIGVsc2UgaWYgKF8udHlwZSA9PT0gJ011bHRpUG9seWdvbicpIHtcbiAgICAgICAgdmFyIGFyZWEgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF8uY29vcmRpbmF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZWEgKz0gcG9seWdvbkFyZWEoXy5jb29yZGluYXRlc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwb2x5Z29uQXJlYShjb29yZHMpIHtcbiAgICB2YXIgYXJlYSA9IDA7XG4gICAgaWYgKGNvb3JkcyAmJiBjb29yZHMubGVuZ3RoID4gMCkge1xuICAgICAgICBhcmVhICs9IE1hdGguYWJzKHJpbmdBcmVhKGNvb3Jkc1swXSkpO1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJlYSAtPSBNYXRoLmFicyhyaW5nQXJlYShjb29yZHNbaV0pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJlYTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIGFwcHJveGltYXRlIGFyZWEgb2YgdGhlIHBvbHlnb24gd2VyZSBpdCBwcm9qZWN0ZWQgb250b1xuICogICAgIHRoZSBlYXJ0aC4gIE5vdGUgdGhhdCB0aGlzIGFyZWEgd2lsbCBiZSBwb3NpdGl2ZSBpZiByaW5nIGlzIG9yaWVudGVkXG4gKiAgICAgY2xvY2t3aXNlLCBvdGhlcndpc2UgaXQgd2lsbCBiZSBuZWdhdGl2ZS5cbiAqXG4gKiBSZWZlcmVuY2U6XG4gKiBSb2JlcnQuIEcuIENoYW1iZXJsYWluIGFuZCBXaWxsaWFtIEguIER1cXVldHRlLCBcIlNvbWUgQWxnb3JpdGhtcyBmb3JcbiAqICAgICBQb2x5Z29ucyBvbiBhIFNwaGVyZVwiLCBKUEwgUHVibGljYXRpb24gMDctMDMsIEpldCBQcm9wdWxzaW9uXG4gKiAgICAgTGFib3JhdG9yeSwgUGFzYWRlbmEsIENBLCBKdW5lIDIwMDcgaHR0cDovL3Rycy1uZXcuanBsLm5hc2EuZ292L2RzcGFjZS9oYW5kbGUvMjAxNC80MDQwOVxuICpcbiAqIFJldHVybnM6XG4gKiB7ZmxvYXR9IFRoZSBhcHByb3hpbWF0ZSBzaWduZWQgZ2VvZGVzaWMgYXJlYSBvZiB0aGUgcG9seWdvbiBpbiBzcXVhcmVcbiAqICAgICBtZXRlcnMuXG4gKi9cblxuZnVuY3Rpb24gcmluZ0FyZWEoY29vcmRzKSB7XG4gICAgdmFyIGFyZWEgPSAwO1xuXG4gICAgaWYgKGNvb3Jkcy5sZW5ndGggPiAyKSB7XG4gICAgICAgIHZhciBwMSwgcDI7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgcDEgPSBjb29yZHNbaV07XG4gICAgICAgICAgICBwMiA9IGNvb3Jkc1tpICsgMV07XG4gICAgICAgICAgICBhcmVhICs9IHJhZChwMlswXSAtIHAxWzBdKSAqICgyICsgTWF0aC5zaW4ocmFkKHAxWzFdKSkgKyBNYXRoLnNpbihyYWQocDJbMV0pKSk7XG4gICAgICAgIH1cblxuICAgICAgICBhcmVhID0gYXJlYSAqIHdnczg0LlJBRElVUyAqIHdnczg0LlJBRElVUyAvIDI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFyZWE7XG59XG5cbmZ1bmN0aW9uIHJhZChfKSB7XG4gICAgcmV0dXJuIF8gKiBNYXRoLlBJIC8gMTgwO1xufVxuIiwibW9kdWxlLmV4cG9ydHMuUkFESVVTID0gNjM3ODEzNztcbm1vZHVsZS5leHBvcnRzLkZMQVRURU5JTkcgPSAxLzI5OC4yNTcyMjM1NjM7XG5tb2R1bGUuZXhwb3J0cy5QT0xBUl9SQURJVVMgPSA2MzU2NzUyLjMxNDI7XG4iLCJtb2R1bGUuZXhwb3J0cz17XG4gIFwiJHZlcnNpb25cIjogNCxcbiAgXCIkcm9vdFwiOiB7XG4gICAgXCJ2ZXJzaW9uXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgNFxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiU3R5bGVzaGVldCB2ZXJzaW9uIG51bWJlci4gTXVzdCBiZSA0LlwiXG4gICAgfSxcbiAgICBcImNvbnN0YW50c1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb25zdGFudHNcIixcbiAgICAgIFwiZG9jXCI6IFwiQW4gb2JqZWN0IG9mIGNvbnN0YW50cyB0byBiZSByZWZlcmVuY2VkIGluIGxheWVycy5cIlxuICAgIH0sXG4gICAgXCJzb3VyY2VzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcInNvdXJjZXNcIixcbiAgICAgIFwiZG9jXCI6IFwiRGF0YSBzb3VyY2Ugc3BlY2lmaWNhdGlvbnMgZm9yIGxheWVycyB0byBwdWxsIGZyb20uXCJcbiAgICB9LFxuICAgIFwibGF5ZXJzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibGF5ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQW4gYXJyYXkgb2YgbGF5ZXJzLiBUaGUgb3JkZXIgb2YgbGF5ZXJzIGNvaW5jaWRlcyB3aXRoIHRoZSBvcmRlciB0aGV5IHdpbGwgYmUgZHJhd24uXCJcbiAgICB9LFxuICAgIFwic3ByaXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInNwcml0ZVwiLFxuICAgICAgXCJkb2NcIjogXCJTcHJpdGUgZGVmaW5pdGlvbi5cIlxuICAgIH0sXG4gICAgXCJnbHlwaHNcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgVVJMIHRlbXBsYXRlIGZvciBsb2FkaW5nIHNpZ25lZC1kaXN0YW5jZS1maWVsZCBnbHlwaCBzZXRzIGluIFBCRiBmb3JtYXQuIFZhbGlkIHRva2VucyBhcmUge2ZvbnRzdGFja30gYW5kIHtyYW5nZX0uXCJcbiAgICB9LFxuICAgIFwidHJhbnNpdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJ0cmFuc2l0aW9uXCIsXG4gICAgICBcImRvY1wiOiBcIkEgZ2xvYmFsIHRyYW5zaXRpb24gZGVmaW5pdGlvbiB0byB1c2UgYXMgYSBkZWZhdWx0IGFjcm9zcyBwcm9wZXJ0aWVzLlwiXG4gICAgfVxuICB9LFxuICBcInNwcml0ZVwiOiBbe1xuICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgIFwiZG9jXCI6IFwiQSBiYXNlIFVSTCBmb3IgcmV0cmlldmluZyB0aGUgc3ByaXRlIGltYWdlIGFuZCBtZXRhZGF0YS4gVGhlIGV4dGVuc2lvbnMgYC5wbmdgLCBgLmpzb25gIGFuZCBzY2FsZSBmYWN0b3IgYEAyeC5wbmdgIHdpbGwgYmUgYXV0b21hdGljYWxseSBhcHBlbmRlZC5cIlxuICB9XSxcbiAgXCJjb25zdGFudHNcIjoge1xuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIkEgY29uc3RhbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkIHZlcmJhdGltIGluIHRoZSByZWZlcmVuY2luZyBwbGFjZS4gVGhpcyBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBvYmplY3RzIGFuZCBhcnJheXMuIEFsbCB2YXJpYWJsZSBuYW1lcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggYW4gYEBgIHN5bWJvbC5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VzXCI6IHtcbiAgICBcIipcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic291cmNlXCJcbiAgICB9XG4gIH0sXG4gIFwic291cmNlXCI6IHtcbiAgICBcInR5cGVcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZlY3RvclwiLFxuICAgICAgICBcInJhc3RlclwiLFxuICAgICAgICBcImdlb2pzb25cIixcbiAgICAgICAgXCJ2aWRlb1wiXG4gICAgICBdLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGF0YSB0eXBlIG9mIHRoZSBzb3VyY2UuXCJcbiAgICB9LFxuICAgIFwidXJsXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJBIFVSTCwgb3IgVVJMIHRlbXBsYXRlIHRvIHJldHJpdmUgdGhlIHNvdXJjZSBkYXRhLlwiXG4gICAgfSxcbiAgICBcInRpbGVTaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDUxMixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gdmlzdWFsIHNpemUgKGluIHB4KSB0byBkaXNwbGF5IHRpbGVzIGZvciB0aGlzIGxheWVyLiBPbmx5IGNvbmZpZ3VyYWJsZSBmb3IgcmFzdGVyIGxheWVycy5cIlxuICAgIH0sXG4gICAgXCJtaW5ab29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImRvY1wiOiBcIk1pbmltdW0gem9vbSBsZXZlbCBmb3Igd2hpY2ggdGlsZXMgYXJlIGF2YWlsYWJsZS5cIlxuICAgIH0sXG4gICAgXCJtYXhab29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJNYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHdoaWNoIHRpbGVzIGFyZSBhdmFpbGFibGUuIERhdGEgZnJvbSB0aWxlcyBhdCB0aGUgbWF4Wm9vbSBhcmUgdXNlZCB3aGVuIGRpc3BsYXlpbmcgdGhlIG1hcCBhdCBoaWdoZXIgem9vbSBsZXZlbHMuXCJcbiAgICB9LFxuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIk90aGVyIGtleXMgdG8gY29uZmlndXJlIHRoZSBkYXRhIHNvdXJjZS5cIlxuICAgIH1cbiAgfSxcbiAgXCJsYXllclwiOiB7XG4gICAgXCJpZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiVW5pcXVlIGxheWVyIG5hbWUuXCJcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiZmlsbFwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJzeW1ib2xcIixcbiAgICAgICAgXCJyYXN0ZXJcIixcbiAgICAgICAgXCJiYWNrZ3JvdW5kXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlJlbmRlcmluZyB0eXBlIG9mIHRoaXMgbGF5ZXIuXCJcbiAgICB9LFxuICAgIFwicmVmXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJSZWZlcmVuY2VzIGFub3RoZXIgbGF5ZXIgdG8gY29weSBgc291cmNlYCwgYHNvdXJjZV9sYXllcmAsIGBmaWx0ZXJgLCBhbmQgYHJlbmRlcmAgcHJvcGVydGllcyBmcm9tLiBUaGlzIGFsbG93cyB0aGUgbGF5ZXJzIHRvIHNoYXJlIHByb2Nlc3NpbmcgYW5kIGJlIG1vcmUgZWZmaWNpZW50LlwiXG4gICAgfSxcbiAgICBcInNvdXJjZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTmFtZSBvZiBhIHNvdXJjZSBkZXNjcmlwdGlvbiB0byBiZSB1c2VkIGZvciB0aGlzIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZS1sYXllclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTGF5ZXIgdG8gdXNlIGZyb20gYSB2ZWN0b3IgdGlsZSBzb3VyY2UuIFJlcXVpcmVkIGlmIHRoZSBzb3VyY2Ugc3VwcG9ydHMgbXVsdGlwbGUgbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcIm1pbi16b29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWluaW11bSB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsYXllciBnZXRzIHBhcnNlZCBhbmQgYXBwZWFycyBvbi5cIlxuICAgIH0sXG4gICAgXCJtYXgtem9vbVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbGF5ZXIgZ2V0cyBwYXJzZWQgYW5kIGFwcGVhcnMgb24uXCJcbiAgICB9LFxuICAgIFwiaW50ZXJhY3RpdmVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJkb2NcIjogXCJFbmFibGUgcXVlcnlpbmcgb2YgZmVhdHVyZSBkYXRhIGZyb20gdGhpcyBsYXllciBmb3IgaW50ZXJhY3Rpdml0eS5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICAgIH0sXG4gICAgXCJyZW5kZXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwicmVuZGVyXCIsXG4gICAgICBcImRvY1wiOiBcIlN5bWJvbGl6ZXIgdHlwZSB0aGF0IHNob3VsZCBiZSB1c2VkIHRvIHZpc3VhbGl6ZSB0aGlzIGxheWVyLiBJZiB1bnNwZWNpZmllZCBvciBudWxsLCB0aGlzIGxheWVyIGlzIG5vdCB0cmVhdGVkIGFzIGEgc3ltYm9saXplciBhbmQgb25seSBleGlzdHMgdG8gaGF2ZSBwcm9wZXJ0aWVzIGluaGVyaXRlZCB0byBvdGhlciBsYXllcnMgdXNpbmcgcmVmLlwiXG4gICAgfSxcbiAgICBcImZpbHRlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQXJyYXkgb3Igb2JqZWN0IG9mIGZpbHRlcnMgb3IgZXhwcmVzc2lvbnMuXCJcbiAgICB9LFxuICAgIFwibGF5ZXJzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibGF5ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiSWYgYHR5cGVgIGlzIGByYXN0ZXJgLCB0aGUgY2hpbGQgbGF5ZXJzIGFyZSBjb21wb3NpdGVkIHRvZ2V0aGVyIG9udG8gdGhlIHByZXZpb3VzIGxldmVsIGxheWVyIGxldmVsLlwiXG4gICAgfSxcbiAgICBcInN0eWxlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNsYXNzXCIsXG4gICAgICBcImRvY1wiOiBcIkRlZmF1bHQgc3R5bGUgcHJvcGVydGllcyBmb3IgdGhpcyBsYXllci5cIlxuICAgIH0sXG4gICAgXCJzdHlsZS4qXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNsYXNzXCIsXG4gICAgICBcImRvY1wiOiBcIk92ZXJyaWRlIHN0eWxlIHByb3BlcnRpZXMgZm9yIHRoaXMgbGF5ZXIuIFRoZSBjbGFzcyBuYW1lIGlzIHRoZSBwYXJ0IGFmdGVyIHRoZSBmaXJzdCBkb3QuXCJcbiAgICB9XG4gIH0sXG4gIFwicmVuZGVyXCI6IFtcbiAgICBcInJlbmRlcl9maWxsXCIsXG4gICAgXCJyZW5kZXJfbGluZVwiLFxuICAgIFwicmVuZGVyX3N5bWJvbFwiLFxuICAgIFwicmVuZGVyX3Jhc3RlclwiLFxuICAgIFwicmVuZGVyX2JhY2tncm91bmRcIlxuICBdLFxuICBcInJlbmRlcl9iYWNrZ3JvdW5kXCI6IHtcbiAgfSxcbiAgXCJyZW5kZXJfZmlsbFwiOiB7XG4gIH0sXG4gIFwicmVuZGVyX2xpbmVcIjoge1xuICAgIFwibGluZS1jYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImJ1dHRcIixcbiAgICAgICAgXCJyb3VuZFwiLFxuICAgICAgICBcInNxdWFyZVwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiYnV0dFwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiBsaW5lIGVuZGluZ3MuXCJcbiAgICB9LFxuICAgIFwibGluZS1qb2luXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJiZXZlbFwiLFxuICAgICAgICBcInJvdW5kXCIsXG4gICAgICAgIFwibWl0ZXJcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1pdGVyXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIGxpbmVzIHdoZW4gam9pbmluZy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLW1pdGVyLWxpbWl0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIsXG4gICAgICBcImRvY1wiOiBcIlVzZWQgdG8gYXV0b21hdGljYWxseSBjb252ZXJ0IG1pdGVyIGpvaW5zIHRvIGJldmVsIGpvaW5zIGZvciBzaGFycCBhbmdsZXMuXCJcbiAgICB9LFxuICAgIFwibGluZS1yb3VuZC1saW1pdFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJVc2VkIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCByb3VuZCBqb2lucyB0byBtaXRlciBqb2lucyBmb3Igc2hhbGxvdyBhbmdsZXMuXCJcbiAgICB9XG4gIH0sXG4gIFwicmVuZGVyX3N5bWJvbFwiOiB7XG4gICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgICAgICBcInBvaW50XCIsXG4gICAgICAgICAgICBcImxpbmVcIlxuICAgICAgICBdLFxuICAgICAgICBcImRlZmF1bHRcIjogXCJwb2ludFwiLFxuICAgICAgICBcImRvY1wiOiBcIlBsYWNlbWVudCBvZiBhIGxhYmVsIHJlbGF0aXZlIHRvIGl0cyBnZW9tZXRyeS4gYExpbmVgIGNhbiBvbmx5IGJlIHVzZWQgb24gTGluZVN0cmluZ3MgYW5kIFBvbHlnb25zLlwiXG4gICAgfSxcbiAgICBcInN5bWJvbC1taW4tZGlzdGFuY2VcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMjUwLFxuICAgICAgXCJkb2NcIjogXCJNaW5pbXVtIGRpc3RhbmNlIGJldHdlZW4gdHdvIHN5bWJvbCBhbmNob3JzIChweClcIlxuICAgIH0sXG4gICAgXCJzeW1ib2wtYXZvaWQtZWRnZXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgc3ltYm9scyB3aWxsIG5vdCBjcm9zcyB0aWxlIGVkZ2VzLiBTeW1ib2xzIHRoYXQgY3Jvc3MgdGlsZSBlZGdlcyBtYXkgY2F1c2UgY29sbGlzaW9ucyBpbiBzb21lIGNhc2VzLiBUaGlzIHByb3BlcnR5IHNob3VsZCBiZSBzZXQgdG8gdHJ1ZSBpZiB0aGUgbGF5ZXIgZG9lcyBub3QgaGF2ZSBlbm91Z2ggcGFkZGluZyBpbiB0aGUgdmVjdG9yIHRpbGUgdG8gcHJldmVudCBjb2xsaXNpb25zLCBvciBpZiBpdCBpcyBhIHBvaW50IHN5bWJvbCBsYXllciBwbGFjZWQgYWZ0ZXIgYSBsaW5lIHN5bWJvbCBsYXllci5cIlxuICAgIH0sXG4gICAgXCJpY29uLWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCB0ZXh0LlwiXG4gICAgfSxcbiAgICBcImljb24taWdub3JlLXBsYWNlbWVudFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIHdvbid0IGFmZmVjdCBwbGFjZW1lbnQgb2Ygb3RoZXIgaWNvbnMgYW5kIHRleHQuXCJcbiAgICB9LFxuICAgIFwiaWNvbi1vcHRpb25hbFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRleHQgY2FuIGJlIHNob3duIHdpdGhvdXQgaXRzIGNvcnJlc3BvbmRpbmcgaWNvbi5cIlxuICAgIH0sXG4gICAgXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpZXdwb3J0XCIsXG4gICAgICBcImRvY1wiOiBcIk9yaWVudGF0aW9uIG9mIGljb24gd2hlbiBtYXAgaXMgcm90YXRlZFwiXG4gICAgfSxcbiAgICBcImljb24tbWF4LXNpemVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gYW1vdW50IHRvIHNjYWxlIHRoZSBpY29uIGJ5LlwiXG4gICAgfSxcbiAgICBcImljb24taW1hZ2VcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgc3RyaW5nIHdpdGgge3Rva2Vuc30gcmVwbGFjZWQsIHJlZmVyZW5jaW5nIHRoZSBkYXRhIHByb3BlcnR5IHRvIHB1bGwgZnJvbS5cIlxuICAgIH0sXG4gICAgXCJpY29uLXJvdGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSBpY29uIGNsb2Nrd2lzZSBieSB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBkZWdyZWVzLlwiXG4gICAgfSxcbiAgICBcImljb24tcGFkZGluZ1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCBpY29uIGJvdW5kaW5nIGJveCB0byBhdm9pZCBpY29uIGNvbGxpc2lvbnMgKHB4KS5cIlxuICAgIH0sXG4gICAgXCJpY29uLWtlZXAtdXByaWdodFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIG1heSBiZSBmbGlwcGVkIHRvIHByZXZlbnQgaXQgZnJvbSBiZWluZyByZW5kZXJlZCB1cHNpZGUtZG93blwiXG4gICAgfSxcbiAgICBcImljb24tb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiSWNvbidzIG9mZnNldCwgaW4gcGl4ZWxzLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpZXdwb3J0XCIsXG4gICAgICBcImRvY1wiOiBcIk9yaWVudGF0aW9uIG9mIGljb24gb3IgdGV4dCB3aGVuIG1hcCBpcyByb3RhdGVkXCJcbiAgICB9LFxuICAgIFwidGV4dC1maWVsZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIlwiLFxuICAgICAgXCJkb2NcIjogXCJWYWx1ZSB0byB1c2UgZm9yIGEgdGV4dCBsYWJlbC4gRmVhdHVyZSBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdG9rZW5zIGxpa2Uge2ZpZWxkX25hbWV9LlwiXG4gICAgfSxcbiAgICBcInRleHQtZm9udFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiRm9udCBzdGFjayB0byB1c2UgZm9yIGRpc3BsYXlpbmcgdGV4dC5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWF4aW11bSBzaXplIHRleHQgd2lsbCBiZSBkaXNwbGF5ZWQuXCJcbiAgICB9LFxuICAgIFwidGV4dC1tYXgtd2lkdGhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMTUsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIGxpbmUgd2lkdGggZm9yIHRleHQgd3JhcHBpbmcgKGVtKS5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEuMixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBsZWFkaW5nIHZhbHVlIGZvciBtdWx0aS1saW5lIHRleHQuXCJcbiAgICB9LFxuICAgIFwidGV4dC1sZXR0ZXItc3BhY2luZ1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJkb2NcIjogXCJUZXh0IGtlcm5pbmcgdmFsdWUgKGVtKS5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LWp1c3RpZnlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcImxlZnRcIixcbiAgICAgICAgXCJyaWdodFwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiY2VudGVyXCIsXG4gICAgICBcImRvY1wiOiBcIlRleHQganVzdGlmaWNhdGlvbiBvcHRpb25zLlwiXG4gICAgfSxcbiAgICBcInRleHQtaG9yaXpvbnRhbC1hbGlnblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibGVmdFwiLFxuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcInJpZ2h0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJjZW50ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiSG9yaXpvbnRhbCBhbGlnbm1lbnQgb2YgdGhlIHRleHQgcmVsYXRpdmUgdG8gdGhlIGFuY2hvci5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LXZlcnRpY2FsLWFsaWduXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJ0b3BcIixcbiAgICAgICAgXCJjZW50ZXJcIixcbiAgICAgICAgXCJib3R0b21cIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImNlbnRlclwiLFxuICAgICAgXCJkb2NcIjogXCJWZXJ0aWNhbCBhbGlnbm1lbnQgb2YgdGhlIHRleHQgcmVsYXRpdmUgdG8gdGhlIGFuY2hvci5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1hbmdsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiA0NSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gYW5nbGUgY2hhbmdlLCBpbiBkZWdyZWVzLCBhbGxvd2VkIGJldHdlZW4gYWRqYWNlbnQgY2hhcmFjdGVycy5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LXJvdGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSB0ZXh0IGNsb2Nrd2lzZSBieSB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBkZWdyZWVzLlwiXG4gICAgfSxcbiAgICBcInRleHQtcGFkZGluZ1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCB0ZXh0IGJvdW5kaW5nIGJveCB0byBhdm9pZCBsYWJlbCBjb2xsaXNpb25zIChweCkuXCJcbiAgICB9LFxuICAgIFwidGV4dC1rZWVwLXVwcmlnaHRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiB0cnVlLFxuICAgICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHRleHQgbWF5IGJlIGZsaXBwZWQgdG8gcHJldmVudCBpdCBmcm9tIGJlaW5nIHJlbmRlcmVkIHVwc2lkZS1kb3duXCJcbiAgICB9LFxuICAgIFwidGV4dC10cmFuc2Zvcm1cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm5vbmVcIixcbiAgICAgICAgXCJ1cHBlcmNhc2VcIixcbiAgICAgICAgXCJsb3dlcmNhc2VcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm5vbmVcIixcbiAgICAgIFwiZG9jXCI6IFwiU3BlY2lmaWVzIGhvdyB0byBjYXBpdGFsaXplIHRleHQsIHNpbWlsYXIgdG8gdGhlIENTUyBgdGV4dC10cmFuc2Zvcm1gIHByb3BlcnR5LlwiXG4gICAgfSxcbiAgICBcInRleHQtb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCBsYWJlbHMuXCJcbiAgICB9LFxuICAgIFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgIFwiZG9jXCI6IFwiSWYgdHJ1ZSwgdGhlIHRleHQgd29uJ3QgYWZmZWN0IHBsYWNlbWVudCBvZiBvdGhlciBpY29ucyBhbmQgbGFiZWxzLlwiXG4gICAgfSxcbiAgICBcInRleHQtb3B0aW9uYWxcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCBpY29ucyBjYW4gYmUgc2hvd24gd2l0aG91dCB0aGVpciBjb3JyZXNwb25kaW5nIHRleHQuXCJcbiAgICB9XG4gIH0sXG4gIFwicmVuZGVyX3Jhc3RlclwiOiB7XG4gICAgXCJyYXN0ZXItc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwiZGVmYXVsdFwiOiAyNTYsXG4gICAgICBcImRvY1wiOiBcIlRoZSB0ZXh0dXJlIGltYWdlIHNpemUgKGluIHBpeGVscykgdmVjdG9yIGxheWVycyB3aWxsIGJlIHJhc3Rlcml6ZWQgYXQuIFdpbGwgYXV0b21hdGljYWxseSBieSBzY2FsZWQgdG8gbWF0Y2ggdGhlIHZpc3VhbCB0aWxlIHNpemUuXCJcbiAgICB9LFxuICAgIFwicmFzdGVyLWJsdXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZG9jXCI6IFwiQmx1ciByYWRpdXMgdG8gYXBwbHkgdG8gdGhlIHJhc3RlciB0ZXh0dXJlIGJlZm9yZSBkaXNwbGF5LlwiXG4gICAgfVxuICB9LFxuICBcImZpbHRlclwiOiBbXG4gICAge1xuICAgICAgXCJ0eXBlXCI6IFwiZmlsdGVyX2V4cHJlc3Npb25cIixcbiAgICAgIFwiZG9jXCI6IFwiVmFyaW91cyBmaWx0ZXIgZXhwcmVzc2lvbnMuIFVubGVzcyBvdmVycmlkZGVuIGJ5IHBhcmVudCwgdGhlc2UgYXJlIGludGVycHJldGVkIGFzIGBBTkRgLlwiXG4gICAgfSxcbiAgICB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcImZpbHRlcl9leHByZXNzaW9uXCIsXG4gICAgICBcImRvY1wiOiBcIlZhcmlvdXMgZmlsdGVyIGV4cHJlc3Npb25zLiBVbmxlc3Mgb3ZlcnJpZGRlbiBieSBwYXJlbnQsIHRoZXNlIGFyZSBpbnRlcnByZXRlZCBhcyBgT1JgLlwiXG4gICAgfVxuICBdLFxuICBcImZpbHRlcl9leHByZXNzaW9uXCI6IHtcbiAgICBcIiZcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZmlsdGVyXCIsXG4gICAgICBcImRvY1wiOiBcIkFORCBvcGVyYXRvci5cIlxuICAgIH0sXG4gICAgXCJ8XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImZpbHRlclwiLFxuICAgICAgXCJkb2NcIjogXCJPUiBvcGVyYXRvci5cIlxuICAgIH0sXG4gICAgXCJeXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImZpbHRlclwiLFxuICAgICAgXCJkb2NcIjogXCJYT1Igb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiIVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiTk9SIG9wZXJhdG9yLlwiXG4gICAgfSxcbiAgICBcIiR0eXBlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJQb2ludFwiLFxuICAgICAgICBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgXCJQb2x5Z29uXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkdlb21ldHJ5IHR5cGUgdGhhdCBmZWF0dXJlcyBtdXN0IG1hdGNoLlwiXG4gICAgfSxcbiAgICBcIipcIjogW1xuICAgICAge1xuICAgICAgICBcInR5cGVcIjogXCJmaWx0ZXJfY29tcGFyaXNvblwiLFxuICAgICAgICBcImRvY1wiOiBcIkFyYml0YXJpbHkgbmFtZWQgZmVhdHVyZSBtZW1iZXIuIEEgY29tcGFyaXNvbiBvYmplY3QgZGVmaW5pbmcgYSBmaWx0ZXIgZXhwcmVzc2lvbi5cIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgXCJ0eXBlXCI6IFwiZmlsdGVyX3ZhbHVlXCIsXG4gICAgICAgIFwiZG9jXCI6IFwiQXJiaXRhcmlseSBuYW1lZCBmZWF0dXJlIG1lbWJlci4gQSBmaWx0ZXJfdmFsdWUgaW1wbGllcyB0aGUgZXF1YWxpdHkgKHN0cmluZy9udW1iZXIvYm9vbGVhbikgb3Igc2V0IG1lbWJlcnNoaXAgb3BlcmF0b3IgKGFycmF5KS5cIlxuICAgICAgfVxuICAgIF1cbiAgfSxcbiAgXCJmaWx0ZXJfY29tcGFyaXNvblwiOiB7XG4gICAgXCI9PVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJfdmFsdWVcIixcbiAgICAgIFwiZG9jXCI6IFwiRXF1YWxpdHkgb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiIT1cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZmlsdGVyX3ZhbHVlXCIsXG4gICAgICBcImRvY1wiOiBcIkluZXF1YWxpdHkgb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiPlwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJfdmFsdWVcIixcbiAgICAgIFwiZG9jXCI6IFwiR3JlYXRlciB0aGFuIG9wZXJhdG9yLlwiXG4gICAgfSxcbiAgICBcIj49XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImZpbHRlcl92YWx1ZVwiLFxuICAgICAgXCJkb2NcIjogXCJHcmVhdGVyIG9yIGVxdWFsIHRoYW4gb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiPFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJfdmFsdWVcIixcbiAgICAgIFwiZG9jXCI6IFwiTGVzcyB0aGFuIG9wZXJhdG9yLlwiXG4gICAgfSxcbiAgICBcIjw9XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImZpbHRlcl92YWx1ZVwiLFxuICAgICAgXCJkb2NcIjogXCJMZXNzIHRoYW4gb3IgZXF1YWwgb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiaW5cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJmaWx0ZXJfcHJpbWl0aXZlXCIsXG4gICAgICBcImRvY1wiOiBcIlNldCBtZW1iZXIgb3BlcmF0b3IuXCJcbiAgICB9LFxuICAgIFwiIWluXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwiZmlsdGVyX3ByaW1pdGl2ZVwiLFxuICAgICAgXCJkb2NcIjogXCJOb3QgaW4gc2V0IG9wZXJhdG9yLlwiXG4gICAgfVxuICB9LFxuICBcImZpbHRlcl92YWx1ZVwiOiBbXG4gICAge1xuICAgICAgXCJ0eXBlXCI6IFwiZmlsdGVyX3ByaW1pdGl2ZVwiXG4gICAgfSxcbiAgICB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcImZpbHRlcl9wcmltaXRpdmVcIlxuICAgIH1cbiAgXSxcbiAgXCJmaWx0ZXJfcHJpbWl0aXZlXCI6IFtcbiAgICB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCJcbiAgICB9LFxuICAgIHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIlxuICAgIH1cbiAgXSxcbiAgXCJmdW5jdGlvblwiOiB7XG4gICAgXCJzdG9wc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBhcnJheSBvZiBzdG9wcy5cIixcbiAgICAgIFwidmFsdWVcIjogXCJmdW5jdGlvbl9zdG9wXCJcbiAgICB9LFxuICAgIFwiYmFzZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZXhwb25lbnRpYWwgYmFzZSBvZiB0aGUgaW50ZXJwb2xhdGlvbiBjdXJ2ZS4gSXQgY29udHJvbHMgdGhlIHJhdGUgYXQgd2hpY2ggdGhlIHJlc3VsdCBpbmNyZWFzZXMuIEhpZ2hlciB2YWx1ZXMgbWFrZSB0aGUgcmVzdWx0IGluY3JlYXNlIG1vcmUgdG93YXJkcyB0aGUgaGlnaCBlbmQgb2YgdGhlIHJhbmdlLiBXaXRoIGAxYCB0aGUgc3RvcHMgYXJlIGludGVycG9sYXRlZCBsaW5lYXJseS5cIlxuICAgIH1cbiAgfSxcbiAgXCJmdW5jdGlvbl9zdG9wXCI6IHtcbiAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgIFwidmFsdWVcIjogW1wibnVtYmVyXCIsIFwiY29sb3JcIl0sXG4gICAgXCJsZW5ndGhcIjogMixcbiAgICBcImRvY1wiOiBcIlpvb20gbGV2ZWwgYW5kIHZhbHVlIHBhaXIuXCJcbiAgfSxcbiAgXCJjbGFzc1wiOiBbXG4gICAgXCJjbGFzc19maWxsXCIsXG4gICAgXCJjbGFzc19saW5lXCIsXG4gICAgXCJjbGFzc19zeW1ib2xcIixcbiAgICBcImNsYXNzX3Jhc3RlclwiLFxuICAgIFwiY2xhc3NfYmFja2dyb3VuZFwiXG4gIF0sXG4gIFwiY2xhc3NfZmlsbFwiOiB7XG4gICAgXCJmaWxsLWFudGlhbGlhc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRlZmF1bHRcIjogdHJ1ZSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiV2hldGhlciBvciBub3QgdGhlIGZpbGwgc2hvdWxkIGJlIGFudGlhbGlhc2VkLlwiXG4gICAgfSxcbiAgICBcImZpbGwtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwiZmlsbC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMVxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImZpbGwtb3V0bGluZS1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3V0bGluZSBjb2xvciBvZiB0aGUgZmlsbC4gTWF0Y2hlcyB0aGUgdmFsdWUgb2YgYGZpbGwtY29sb3JgIGlmIHVuc3BlY2lmaWVkLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwiZmlsbC10cmFuc2xhdGVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwXG4gICAgICBdLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIlRoZSBnZW9tZXRyeSdzIG9mZnNldCwgaW4gcGl4ZWxzLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJmaWxsLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIlxuICAgIH0sXG4gICAgXCJmaWxsLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJOYW1lIG9mIGltYWdlIGluIHNwcml0ZSB0byB1c2UgZm9yIGRyYXdpbmcgaW1hZ2UgZmlsbHMuXCJcbiAgICB9XG4gIH0sXG4gIFwiY2xhc3NfbGluZVwiOiB7XG4gICAgXCJsaW5lLW9wYWNpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcImRlZmF1bHRcIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDFcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGdlb21ldHJ5J3Mgb2Zmc2V0LCBpbiBwaXhlbHMuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiXG4gICAgfSxcbiAgICBcImxpbmUtd2lkdGhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJMaW5lIHdpZHRoIChpbiBweClcIlxuICAgIH0sXG4gICAgXCJsaW5lLW9mZnNldFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJkb2NcIjogXCJMaW5lIGNhc2luZyB3aGVyZSBgbGluZS1vZmZzZXRgIGluZGljYXRlcyB0b3RhbCB3aWR0aC4gQFRPRE8gcmVuYW1lP1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwibGluZS1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiTGluZSBibHVyLCBpbiBwaXhlbHMuXCJcbiAgICB9LFxuICAgIFwibGluZS1kYXNoYXJyYXlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAxLFxuICAgICAgICAtMVxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtaW1hZ2VcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBsaW5lcy5cIlxuICAgIH1cbiAgfSxcbiAgXCJjbGFzc19zeW1ib2xcIjoge1xuICAgIFwiaWNvbi1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJpY29uLXNpemVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJUaGUgYW1vdW50IHRvIHNjYWxlIHRoZSBpY29uIGJ5LiAxIGlzIG9yaWdpbmFsIHNpemUsIDMgdHJpcGxlcyB0aGUgc2l6ZS5cIlxuICAgIH0sXG4gICAgXCJpY29uLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwLFxuICAgICAgICAwLFxuICAgICAgICAxXG4gICAgICBdLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIlRoZSBjb2xvciBvZiB0aGUgaWNvbi4gVGhpcyBjYW4gb25seSBiZSB1c2VkIHdpdGggc2RmIGljb25zLlwiXG4gICAgfSxcbiAgICBcImljb24taGFsby1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJUaGUgY29sb3Igb2YgdGhlIGljb24ncyBoYWxvLiBJY29uIGhhbG9zIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBzZGYgaWNvbnMuXCJcbiAgICB9LFxuICAgIFwiaWNvbi1oYWxvLXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiSG93IGZhciBhd2F5IHRoZSBoYWxvIGlzIGZyb20gdGhlIGljb24gb3V0bGluZSwgaW4gcGl4ZWxzLlwiXG4gICAgfSxcbiAgICBcImljb24taGFsby1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiRmFkZSBvdXQgdGhlIGhhbG8gdG93YXJkcyB0aGUgb3V0c2lkZSwgaW4gcGl4ZWxzLlwiXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBpY29uJ3Mgb2Zmc2V0LCBpbiBwaXhlbHMuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiXG4gICAgfSxcbiAgICBcInRleHQtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwidGV4dC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIkZvbnQgc2l6ZSBpbiBwaXhlbHMuIElmIHVuc3BlY2lmaWVkLCB0aGUgdGV4dCB3aWxsIGJlIGFzIGJpZyBhcyBhbGxvd2VkIGJ5IHRoZSBsYXllciBkZWZpbml0aW9uLlwiXG4gICAgfSxcbiAgICBcInRleHQtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDFcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJ0ZXh0LWhhbG8tY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJ0ZXh0LWhhbG8td2lkdGhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJIb3cgZmFyIGF3YXkgdGhlIGhhbG8gaXMgZnJvbSB0aGUgZm9udCBvdXRsaW5lLCBpbiBwaXhlbHMuIE1heCB0ZXh0IGhhbG8gd2lkdGggaXMgMS80IG9mIHRoZSBmb250LXNpemUgKHB4KS5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LWhhbG8tYmx1clwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIkZhZGUgb3V0IHRoZSBoYWxvIHRvd2FyZHMgdGhlIG91dHNpZGUsIGluIHBpeGVscy5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiQSBsYWJlbCdzIG9mZnNldCwgaW4gcGl4ZWxzLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJ0ZXh0LXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIlxuICAgIH1cbiAgfSxcbiAgXCJjbGFzc19yYXN0ZXJcIjoge1xuICAgIFwicmFzdGVyLW9wYWNpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcInJhc3Rlci1odWUtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiUm90YXRlcyBodWVzIGFyb3VuZCB0aGUgY29sb3Igd2hlZWwgYnkgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgZGVncmVlcy5cIlxuICAgIH0sXG4gICAgXCJyYXN0ZXItYnJpZ2h0bmVzc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDFcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItc2F0dXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLWNvbnRyYXN0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IHRydWUsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItZmFkZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIkR1cmF0aW9uIG9mIHRoZSBmYWRlIHdoZW4gYSBuZXcgdGlsZSBpcyBhZGRlZC4gQFRPRE8gcmVuYW1lP1wiXG4gICAgfVxuICB9LFxuICBcImNsYXNzX2JhY2tncm91bmRcIjoge1xuICAgIFwiYmFja2dyb3VuZC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMCxcbiAgICAgICAgMVxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImJhY2tncm91bmQtaW1hZ2VcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICB9XG4gIH0sXG4gIFwidHJhbnNpdGlvblwiOiB7XG4gICAgXCJkdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcImRvY1wiOiBcIlRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgaXQgdGFrZXMgZm9yIHRyYW5zaXRpb25zIHRvIGNvbXBsZXRlLlwiXG4gICAgfSxcbiAgICBcImRlbGF5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcImRvY1wiOiBcIlRpbWUgaW4gbWlsbGlzZWNvbmRzIGJlZm9yZSBhIHRyYW5zaXRpb24gYmVnaW5zLlwiXG4gICAgfVxuICB9XG59XG4iLCIoZnVuY3Rpb24gKEJ1ZmZlcil7XG4ndXNlIHN0cmljdCc7XG5cbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb3RvYnVmO1xuZnVuY3Rpb24gUHJvdG9idWYoYnVmKSB7XG4gICAgdGhpcy5idWYgPSBidWY7XG4gICAgdGhpcy5wb3MgPSAwO1xufVxuXG5Qcm90b2J1Zi5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGxlbmd0aCgpIHsgcmV0dXJuIHRoaXMuYnVmLmxlbmd0aDsgfVxufTtcblxuUHJvdG9idWYuVmFyaW50ID0gMDtcblByb3RvYnVmLkludDY0ID0gMTtcblByb3RvYnVmLk1lc3NhZ2UgPSAyO1xuUHJvdG9idWYuU3RyaW5nID0gMjtcblByb3RvYnVmLlBhY2tlZCA9IDI7XG5Qcm90b2J1Zi5JbnQzMiA9IDU7XG5cblByb3RvYnVmLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5idWYgPSBudWxsO1xufTtcblxuLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuUHJvdG9idWYucHJvdG90eXBlLnJlYWRVSW50MzIgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZFVJbnQzMkxFKHRoaXMucG9zKTtcbiAgICB0aGlzLnBvcyArPSA0O1xuICAgIHJldHVybiB2YWw7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUucmVhZFVJbnQ2NCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkVUludDY0TEUodGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDg7XG4gICAgcmV0dXJuIHZhbDtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS5yZWFkRG91YmxlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbCA9IGllZWU3NTQucmVhZCh0aGlzLmJ1ZiwgdGhpcy5wb3MsIHRydWUsIDUyLCA4KTtcbiAgICB0aGlzLnBvcyArPSA4O1xuICAgIHJldHVybiB2YWw7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUucmVhZFZhcmludCA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIFRPRE86IGJvdW5kcyBjaGVja2luZ1xuICAgIHZhciBwb3MgPSB0aGlzLnBvcztcbiAgICBpZiAodGhpcy5idWZbcG9zXSA8PSAweDdmKSB7XG4gICAgICAgIHRoaXMucG9zKys7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1Zltwb3NdO1xuICAgIH0gZWxzZSBpZiAodGhpcy5idWZbcG9zICsgMV0gPD0gMHg3Zikge1xuICAgICAgICB0aGlzLnBvcyArPSAyO1xuICAgICAgICByZXR1cm4gKHRoaXMuYnVmW3Bvc10gJiAweDdmKSB8ICh0aGlzLmJ1Zltwb3MgKyAxXSA8PCA3KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuYnVmW3BvcyArIDJdIDw9IDB4N2YpIHtcbiAgICAgICAgdGhpcy5wb3MgKz0gMztcbiAgICAgICAgcmV0dXJuICh0aGlzLmJ1Zltwb3NdICYgMHg3ZikgfCAodGhpcy5idWZbcG9zICsgMV0gJiAweDdmKSA8PCA3IHwgKHRoaXMuYnVmW3BvcyArIDJdKSA8PCAxNDtcbiAgICB9IGVsc2UgaWYgKHRoaXMuYnVmW3BvcyArIDNdIDw9IDB4N2YpIHtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuICh0aGlzLmJ1Zltwb3NdICYgMHg3ZikgfCAodGhpcy5idWZbcG9zICsgMV0gJiAweDdmKSA8PCA3IHwgKHRoaXMuYnVmW3BvcyArIDJdICYgMHg3ZikgPDwgMTQgfCAodGhpcy5idWZbcG9zICsgM10pIDw8IDIxO1xuICAgIH0gZWxzZSBpZiAodGhpcy5idWZbcG9zICsgNF0gPD0gMHg3Zikge1xuICAgICAgICB0aGlzLnBvcyArPSA1O1xuICAgICAgICByZXR1cm4gKCh0aGlzLmJ1Zltwb3NdICYgMHg3ZikgfCAodGhpcy5idWZbcG9zICsgMV0gJiAweDdmKSA8PCA3IHwgKHRoaXMuYnVmW3BvcyArIDJdICYgMHg3ZikgPDwgMTQgfCAodGhpcy5idWZbcG9zICsgM10pIDw8IDIxKSArICh0aGlzLmJ1Zltwb3MgKyA0XSAqIDI2ODQzNTQ1Nik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5za2lwKFByb3RvYnVmLlZhcmludCk7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXCJUT0RPOiBIYW5kbGUgNisgYnl0ZSB2YXJpbnRzXCIpO1xuICAgIH1cbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS5yZWFkU1ZhcmludCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBudW0gPSB0aGlzLnJlYWRWYXJpbnQoKTtcbiAgICBpZiAobnVtID4gMjE0NzQ4MzY0NykgdGhyb3cgbmV3IEVycm9yKCdUT0RPOiBIYW5kbGUgbnVtYmVycyA+PSAyXjMwJyk7XG4gICAgLy8gemlnemFnIGVuY29kaW5nXG4gICAgcmV0dXJuICgobnVtID4+IDEpIF4gLShudW0gJiAxKSk7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUucmVhZFN0cmluZyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBieXRlcyA9IHRoaXMucmVhZFZhcmludCgpO1xuICAgIC8vIFRPRE86IGJvdW5kcyBjaGVja2luZ1xuICAgIHZhciBjaHIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlO1xuICAgIHZhciBiID0gdGhpcy5idWY7XG4gICAgdmFyIHAgPSB0aGlzLnBvcztcbiAgICB2YXIgZW5kID0gdGhpcy5wb3MgKyBieXRlcztcbiAgICB2YXIgc3RyID0gJyc7XG4gICAgd2hpbGUgKHAgPCBlbmQpIHtcbiAgICAgICAgaWYgKGJbcF0gPD0gMHg3Rikgc3RyICs9IGNocihiW3ArK10pO1xuICAgICAgICBlbHNlIGlmIChiW3BdIDw9IDB4QkYpIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBVVEYtOCBjb2RlcG9pbnQ6ICcgKyBiW3BdKTtcbiAgICAgICAgZWxzZSBpZiAoYltwXSA8PSAweERGKSBzdHIgKz0gY2hyKChiW3ArK10gJiAweDFGKSA8PCA2IHwgKGJbcCsrXSAmIDB4M0YpKTtcbiAgICAgICAgZWxzZSBpZiAoYltwXSA8PSAweEVGKSBzdHIgKz0gY2hyKChiW3ArK10gJiAweDFGKSA8PCAxMiB8IChiW3ArK10gJiAweDNGKSA8PCA2IHwgKGJbcCsrXSAmIDB4M0YpKTtcbiAgICAgICAgZWxzZSBpZiAoYltwXSA8PSAweEY3KSBwICs9IDQ7IC8vIFdlIGNhbid0IGhhbmRsZSB0aGVzZSBjb2RlcG9pbnRzIGluIEpTLCBzbyBza2lwLlxuICAgICAgICBlbHNlIGlmIChiW3BdIDw9IDB4RkIpIHAgKz0gNTtcbiAgICAgICAgZWxzZSBpZiAoYltwXSA8PSAweEZEKSBwICs9IDY7XG4gICAgICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFVURi04IGNvZGVwb2ludDogJyArIGJbcF0pO1xuICAgIH1cbiAgICB0aGlzLnBvcyArPSBieXRlcztcbiAgICByZXR1cm4gc3RyO1xufTtcblxuUHJvdG9idWYucHJvdG90eXBlLnJlYWRCdWZmZXIgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnl0ZXMgPSB0aGlzLnJlYWRWYXJpbnQoKTtcbiAgICB2YXIgYnVmZmVyID0gdGhpcy5idWYuc3ViYXJyYXkodGhpcy5wb3MsIHRoaXMucG9zICsgYnl0ZXMpO1xuICAgIHRoaXMucG9zICs9IGJ5dGVzO1xuICAgIHJldHVybiBidWZmZXI7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUucmVhZFBhY2tlZCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAvLyBUT0RPOiBib3VuZHMgY2hlY2tpbmdcbiAgICB2YXIgYnl0ZXMgPSB0aGlzLnJlYWRWYXJpbnQoKTtcbiAgICB2YXIgZW5kID0gdGhpcy5wb3MgKyBieXRlcztcbiAgICB2YXIgYXJyYXkgPSBbXTtcbiAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIHtcbiAgICAgICAgYXJyYXkucHVzaCh0aGlzWydyZWFkJyArIHR5cGVdKCkpO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUuc2tpcCA9IGZ1bmN0aW9uKHZhbCkge1xuICAgIC8vIFRPRE86IGJvdW5kcyBjaGVja2luZ1xuICAgIHZhciB0eXBlID0gdmFsICYgMHg3O1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAvKiB2YXJpbnQgKi8gY2FzZSBQcm90b2J1Zi5WYXJpbnQ6IHdoaWxlICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA+IDB4N2YpOyBicmVhaztcbiAgICAgICAgLyogNjQgYml0ICovIGNhc2UgUHJvdG9idWYuSW50NjQ6IHRoaXMucG9zICs9IDg7IGJyZWFrO1xuICAgICAgICAvKiBsZW5ndGggKi8gY2FzZSBQcm90b2J1Zi5NZXNzYWdlOiB2YXIgYnl0ZXMgPSB0aGlzLnJlYWRWYXJpbnQoKTsgdGhpcy5wb3MgKz0gYnl0ZXM7IGJyZWFrO1xuICAgICAgICAvKiAzMiBiaXQgKi8gY2FzZSBQcm90b2J1Zi5JbnQzMjogdGhpcy5wb3MgKz0gNDsgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6IHRocm93IG5ldyBFcnJvcignVW5pbXBsZW1lbnRlZCB0eXBlOiAnICsgdHlwZSk7XG4gICAgfVxufTtcblxuLy8gPT09IFdSSVRJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlVGFnID0gZnVuY3Rpb24odGFnLCB0eXBlKSB7XG4gICAgdGhpcy53cml0ZVZhcmludCgodGFnIDw8IDMpIHwgdHlwZSk7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUucmVhbGxvYyA9IGZ1bmN0aW9uKG1pbikge1xuICAgIHZhciBsZW5ndGggPSB0aGlzLmJ1Zi5sZW5ndGg7XG4gICAgd2hpbGUgKGxlbmd0aCA8IHRoaXMucG9zICsgbWluKSBsZW5ndGggKj0gMjtcbiAgICBpZiAobGVuZ3RoICE9IHRoaXMuYnVmLmxlbmd0aCkge1xuICAgICAgICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihsZW5ndGgpO1xuICAgICAgICB0aGlzLmJ1Zi5jb3B5KGJ1Zik7XG4gICAgICAgIHRoaXMuYnVmID0gYnVmO1xuICAgIH1cbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS5maW5pc2ggPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5idWYuc2xpY2UoMCwgdGhpcy5wb3MpO1xufTtcblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlUGFja2VkID0gZnVuY3Rpb24odHlwZSwgdGFnLCBpdGVtcykge1xuICAgIGlmICghaXRlbXMubGVuZ3RoKSByZXR1cm47XG5cbiAgICB2YXIgbWVzc2FnZSA9IG5ldyBQcm90b2J1ZigpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbWVzc2FnZVsnd3JpdGUnICsgdHlwZV0oaXRlbXNbaV0pO1xuICAgIH1cbiAgICB2YXIgZGF0YSA9IG1lc3NhZ2UuZmluaXNoKCk7XG5cbiAgICB0aGlzLndyaXRlVGFnKHRhZywgUHJvdG9idWYuUGFja2VkKTtcbiAgICB0aGlzLndyaXRlQnVmZmVyKGRhdGEpO1xufTtcblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlVUludDMyID0gZnVuY3Rpb24odmFsKSB7XG4gICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgIHRoaXMuYnVmLndyaXRlVUludDMyTEUodmFsLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gNDtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZVRhZ2dlZFVJbnQzMiA9IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFByb3RvYnVmLkludDMyKTtcbiAgICB0aGlzLndyaXRlVUludDMyKHZhbCk7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVWYXJpbnQgPSBmdW5jdGlvbih2YWwpIHtcbiAgICB2YWwgPSBOdW1iZXIodmFsKTtcbiAgICBpZiAoaXNOYU4odmFsKSkge1xuICAgICAgICB2YWwgPSAwO1xuICAgIH1cblxuICAgIGlmICh2YWwgPD0gMHg3Zikge1xuICAgICAgICB0aGlzLnJlYWxsb2MoMSk7XG4gICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gdmFsO1xuICAgIH0gZWxzZSBpZiAodmFsIDw9IDB4M2ZmZikge1xuICAgICAgICB0aGlzLnJlYWxsb2MoMik7XG4gICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gMHg4MCB8ICgodmFsID4+PiAwKSAmIDB4N2YpO1xuICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9IDB4MDAgfCAoKHZhbCA+Pj4gNykgJiAweDdmKTtcbiAgICB9IGVsc2UgaWYgKHZhbCA8PSAweDFmZmZmZmYpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDMpO1xuICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9IDB4ODAgfCAoKHZhbCA+Pj4gMCkgJiAweDdmKTtcbiAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAweDgwIHwgKCh2YWwgPj4+IDcpICYgMHg3Zik7XG4gICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gMHgwMCB8ICgodmFsID4+PiAxNCkgJiAweDdmKTtcbiAgICB9IGVsc2UgaWYgKHZhbCA8PSAweGZmZmZmZmYpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9IDB4ODAgfCAoKHZhbCA+Pj4gMCkgJiAweDdmKTtcbiAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAweDgwIHwgKCh2YWwgPj4+IDcpICYgMHg3Zik7XG4gICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gMHg4MCB8ICgodmFsID4+PiAxNCkgJiAweDdmKTtcbiAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAweDAwIHwgKCh2YWwgPj4+IDIxKSAmIDB4N2YpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdoaWxlICh2YWwgPiAwKSB7XG4gICAgICAgICAgICB2YXIgYiA9IHZhbCAmIDB4N2Y7XG4gICAgICAgICAgICB2YWwgPSBNYXRoLmZsb29yKHZhbCAvIDEyOCk7XG4gICAgICAgICAgICBpZiAodmFsID4gMCkgYiB8PSAweDgwXG4gICAgICAgICAgICB0aGlzLnJlYWxsb2MoMSk7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9IGI7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVUYWdnZWRWYXJpbnQgPSBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQcm90b2J1Zi5WYXJpbnQpO1xuICAgIHRoaXMud3JpdGVWYXJpbnQodmFsKTtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZVNWYXJpbnQgPSBmdW5jdGlvbih2YWwpIHtcbiAgICBpZiAodmFsID49IDApIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludCh2YWwgKiAyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCAqIC0yIC0gMSk7XG4gICAgfVxufTtcblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlVGFnZ2VkU1ZhcmludCA9IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFByb3RvYnVmLlZhcmludCk7XG4gICAgdGhpcy53cml0ZVNWYXJpbnQodmFsKTtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZUJvb2xlYW4gPSBmdW5jdGlvbih2YWwpIHtcbiAgICB0aGlzLndyaXRlVmFyaW50KEJvb2xlYW4odmFsKSk7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVUYWdnZWRCb29sZWFuID0gZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICB0aGlzLndyaXRlVGFnZ2VkVmFyaW50KHRhZywgQm9vbGVhbih2YWwpKTtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZVN0cmluZyA9IGZ1bmN0aW9uKHN0cikge1xuICAgIHN0ciA9IFN0cmluZyhzdHIpO1xuICAgIHZhciBieXRlcyA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHN0cik7XG4gICAgdGhpcy53cml0ZVZhcmludChieXRlcyk7XG4gICAgdGhpcy5yZWFsbG9jKGJ5dGVzKTtcbiAgICB0aGlzLmJ1Zi53cml0ZShzdHIsIHRoaXMucG9zKTtcbiAgICB0aGlzLnBvcyArPSBieXRlcztcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZVRhZ2dlZFN0cmluZyA9IGZ1bmN0aW9uKHRhZywgc3RyKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFByb3RvYnVmLlN0cmluZyk7XG4gICAgdGhpcy53cml0ZVN0cmluZyhzdHIpO1xufTtcblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlRmxvYXQgPSBmdW5jdGlvbih2YWwpIHtcbiAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgdGhpcy5idWYud3JpdGVGbG9hdExFKHZhbCwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDQ7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVUYWdnZWRGbG9hdCA9IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFByb3RvYnVmLkludDMyKTtcbiAgICB0aGlzLndyaXRlRmxvYXQodmFsKTtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZURvdWJsZSA9IGZ1bmN0aW9uKHZhbCkge1xuICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICB0aGlzLmJ1Zi53cml0ZURvdWJsZUxFKHZhbCwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDg7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVUYWdnZWREb3VibGUgPSBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQcm90b2J1Zi5JbnQ2NCk7XG4gICAgdGhpcy53cml0ZURvdWJsZSh2YWwpO1xufTtcblxuUHJvdG9idWYucHJvdG90eXBlLndyaXRlQnVmZmVyID0gZnVuY3Rpb24oYnVmZmVyKSB7XG4gICAgdmFyIGJ5dGVzID0gYnVmZmVyLmxlbmd0aDtcbiAgICB0aGlzLndyaXRlVmFyaW50KGJ5dGVzKTtcbiAgICB0aGlzLnJlYWxsb2MoYnl0ZXMpO1xuICAgIGJ1ZmZlci5jb3B5KHRoaXMuYnVmLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gYnl0ZXM7XG59O1xuXG5Qcm90b2J1Zi5wcm90b3R5cGUud3JpdGVUYWdnZWRCdWZmZXIgPSBmdW5jdGlvbih0YWcsIGJ1ZmZlcikge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQcm90b2J1Zi5TdHJpbmcpO1xuICAgIHRoaXMud3JpdGVCdWZmZXIoYnVmZmVyKTtcbn07XG5cblByb3RvYnVmLnByb3RvdHlwZS53cml0ZU1lc3NhZ2UgPSBmdW5jdGlvbih0YWcsIHByb3RvYnVmKSB7XG4gICAgdmFyIGJ1ZmZlciA9IHByb3RvYnVmLmZpbmlzaCgpO1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQcm90b2J1Zi5NZXNzYWdlKTtcbiAgICB0aGlzLndyaXRlQnVmZmVyKGJ1ZmZlcik7XG59O1xuXG59KS5jYWxsKHRoaXMscmVxdWlyZShcImJ1ZmZlclwiKS5CdWZmZXIpIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBvaW50O1xuXG5mdW5jdGlvbiBQb2ludCh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xufVxuXG5Qb2ludC5wcm90b3R5cGUgPSB7XG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgdGhpcy55KTsgfSxcblxuICAgIGFkZDogICAgIGZ1bmN0aW9uKHApIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHApOyAgICAgfSxcbiAgICBzdWI6ICAgICBmdW5jdGlvbihwKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3N1YihwKTsgICAgIH0sXG4gICAgbXVsdDogICAgZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0KGspOyAgICB9LFxuICAgIGRpdjogICAgIGZ1bmN0aW9uKGspIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2KGspOyAgICAgfSxcbiAgICByb3RhdGU6ICBmdW5jdGlvbihhKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZShhKTsgIH0sXG4gICAgbWF0TXVsdDogZnVuY3Rpb24obSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tYXRNdWx0KG0pOyB9LFxuICAgIHVuaXQ6ICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCk7IH0sXG4gICAgcGVycDogICAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKTsgfSxcbiAgICByb3VuZDogICBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTsgfSxcblxuICAgIG1hZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQodGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55KTtcbiAgICB9LFxuXG4gICAgZXF1YWxzOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnggPT09IHAueCAmJlxuICAgICAgICAgICAgICAgdGhpcy55ID09PSBwLnk7XG4gICAgfSxcblxuICAgIGRpc3Q6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIocCkpO1xuICAgIH0sXG5cbiAgICBkaXN0U3FyOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHZhciBkeCA9IHAueCAtIHRoaXMueCxcbiAgICAgICAgICAgIGR5ID0gcC55IC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG4gICAgfSxcblxuICAgIGFuZ2xlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpO1xuICAgIH0sXG5cbiAgICBhbmdsZVRvOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMueSAtIGIueSwgdGhpcy54IC0gYi54KTtcbiAgICB9LFxuXG4gICAgYW5nbGVXaXRoOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFuZ2xlV2l0aFNlcChiLngsIGIueSk7XG4gICAgfSxcblxuICAgIC8vIEZpbmQgdGhlIGFuZ2xlIG9mIHRoZSB0d28gdmVjdG9ycywgc29sdmluZyB0aGUgZm9ybXVsYSBmb3IgdGhlIGNyb3NzIHByb2R1Y3QgYSB4IGIgPSB8YXx8YnxzaW4ozrgpIGZvciDOuC5cbiAgICBhbmdsZVdpdGhTZXA6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoXG4gICAgICAgICAgICB0aGlzLnggKiB5IC0gdGhpcy55ICogeCxcbiAgICAgICAgICAgIHRoaXMueCAqIHggKyB0aGlzLnkgKiB5KTtcbiAgICB9LFxuXG4gICAgX21hdE11bHQ6IGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgdmFyIHggPSBtWzBdICogdGhpcy54ICsgbVsxXSAqIHRoaXMueSxcbiAgICAgICAgICAgIHkgPSBtWzJdICogdGhpcy54ICsgbVszXSAqIHRoaXMueTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hZGQ6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54ICs9IHAueDtcbiAgICAgICAgdGhpcy55ICs9IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9zdWI6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54IC09IHAueDtcbiAgICAgICAgdGhpcy55IC09IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9tdWx0OiBmdW5jdGlvbihrKSB7XG4gICAgICAgIHRoaXMueCAqPSBrO1xuICAgICAgICB0aGlzLnkgKj0gaztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kaXY6IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdGhpcy54IC89IGs7XG4gICAgICAgIHRoaXMueSAvPSBrO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3VuaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9kaXYodGhpcy5tYWcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcGVycDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55O1xuICAgICAgICB0aGlzLnkgPSB0aGlzLng7XG4gICAgICAgIHRoaXMueCA9IC15O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdGF0ZTogZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgICAgIHggPSBjb3MgKiB0aGlzLnggLSBzaW4gKiB0aGlzLnksXG4gICAgICAgICAgICB5ID0gc2luICogdGhpcy54ICsgY29zICogdGhpcy55O1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgUG9pbnQgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblBvaW50LmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoYVswXSwgYVsxXSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIHNsaWNlID0gW10uc2xpY2U7XG5cbiAgZnVuY3Rpb24gcXVldWUocGFyYWxsZWxpc20pIHtcbiAgICB2YXIgcSxcbiAgICAgICAgdGFza3MgPSBbXSxcbiAgICAgICAgc3RhcnRlZCA9IDAsIC8vIG51bWJlciBvZiB0YXNrcyB0aGF0IGhhdmUgYmVlbiBzdGFydGVkIChhbmQgcGVyaGFwcyBmaW5pc2hlZClcbiAgICAgICAgYWN0aXZlID0gMCwgLy8gbnVtYmVyIG9mIHRhc2tzIGN1cnJlbnRseSBiZWluZyBleGVjdXRlZCAoc3RhcnRlZCBidXQgbm90IGZpbmlzaGVkKVxuICAgICAgICByZW1haW5pbmcgPSAwLCAvLyBudW1iZXIgb2YgdGFza3Mgbm90IHlldCBmaW5pc2hlZFxuICAgICAgICBwb3BwaW5nLCAvLyBpbnNpZGUgYSBzeW5jaHJvbm91cyB0YXNrIGNhbGxiYWNrP1xuICAgICAgICBlcnJvciA9IG51bGwsXG4gICAgICAgIGF3YWl0ID0gbm9vcCxcbiAgICAgICAgYWxsO1xuXG4gICAgaWYgKCFwYXJhbGxlbGlzbSkgcGFyYWxsZWxpc20gPSBJbmZpbml0eTtcblxuICAgIGZ1bmN0aW9uIHBvcCgpIHtcbiAgICAgIHdoaWxlIChwb3BwaW5nID0gc3RhcnRlZCA8IHRhc2tzLmxlbmd0aCAmJiBhY3RpdmUgPCBwYXJhbGxlbGlzbSkge1xuICAgICAgICB2YXIgaSA9IHN0YXJ0ZWQrKyxcbiAgICAgICAgICAgIHQgPSB0YXNrc1tpXSxcbiAgICAgICAgICAgIGEgPSBzbGljZS5jYWxsKHQsIDEpO1xuICAgICAgICBhLnB1c2goY2FsbGJhY2soaSkpO1xuICAgICAgICArK2FjdGl2ZTtcbiAgICAgICAgdFswXS5hcHBseShudWxsLCBhKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxsYmFjayhpKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oZSwgcikge1xuICAgICAgICAtLWFjdGl2ZTtcbiAgICAgICAgaWYgKGVycm9yICE9IG51bGwpIHJldHVybjtcbiAgICAgICAgaWYgKGUgIT0gbnVsbCkge1xuICAgICAgICAgIGVycm9yID0gZTsgLy8gaWdub3JlIG5ldyB0YXNrcyBhbmQgc3F1ZWxjaCBhY3RpdmUgY2FsbGJhY2tzXG4gICAgICAgICAgc3RhcnRlZCA9IHJlbWFpbmluZyA9IE5hTjsgLy8gc3RvcCBxdWV1ZWQgdGFza3MgZnJvbSBzdGFydGluZ1xuICAgICAgICAgIG5vdGlmeSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRhc2tzW2ldID0gcjtcbiAgICAgICAgICBpZiAoLS1yZW1haW5pbmcpIHBvcHBpbmcgfHwgcG9wKCk7XG4gICAgICAgICAgZWxzZSBub3RpZnkoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3RpZnkoKSB7XG4gICAgICBpZiAoZXJyb3IgIT0gbnVsbCkgYXdhaXQoZXJyb3IpO1xuICAgICAgZWxzZSBpZiAoYWxsKSBhd2FpdChlcnJvciwgdGFza3MpO1xuICAgICAgZWxzZSBhd2FpdC5hcHBseShudWxsLCBbZXJyb3JdLmNvbmNhdCh0YXNrcykpO1xuICAgIH1cblxuICAgIHJldHVybiBxID0ge1xuICAgICAgZGVmZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIWVycm9yKSB7XG4gICAgICAgICAgdGFza3MucHVzaChhcmd1bWVudHMpO1xuICAgICAgICAgICsrcmVtYWluaW5nO1xuICAgICAgICAgIHBvcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBxO1xuICAgICAgfSxcbiAgICAgIGF3YWl0OiBmdW5jdGlvbihmKSB7XG4gICAgICAgIGF3YWl0ID0gZjtcbiAgICAgICAgYWxsID0gZmFsc2U7XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBub3RpZnkoKTtcbiAgICAgICAgcmV0dXJuIHE7XG4gICAgICB9LFxuICAgICAgYXdhaXRBbGw6IGZ1bmN0aW9uKGYpIHtcbiAgICAgICAgYXdhaXQgPSBmO1xuICAgICAgICBhbGwgPSB0cnVlO1xuICAgICAgICBpZiAoIXJlbWFpbmluZykgbm90aWZ5KCk7XG4gICAgICAgIHJldHVybiBxO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBub29wKCkge31cblxuICBxdWV1ZS52ZXJzaW9uID0gXCIxLjAuN1wiO1xuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIGRlZmluZShmdW5jdGlvbigpIHsgcmV0dXJuIHF1ZXVlOyB9KTtcbiAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiBtb2R1bGUuZXhwb3J0cykgbW9kdWxlLmV4cG9ydHMgPSBxdWV1ZTtcbiAgZWxzZSB0aGlzLnF1ZXVlID0gcXVldWU7XG59KSgpO1xuIiwiLypcbiAoYykgMjAxMywgVmxhZGltaXIgQWdhZm9ua2luXG4gUkJ1c2gsIGEgSmF2YVNjcmlwdCBsaWJyYXJ5IGZvciBoaWdoLXBlcmZvcm1hbmNlIDJEIHNwYXRpYWwgaW5kZXhpbmcgb2YgcG9pbnRzIGFuZCByZWN0YW5nbGVzLlxuIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3VybmVyL3JidXNoXG4qL1xuXG4oZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCkge1xuXG4gICAgLy8ganNoaW50IG5ld2NhcDogZmFsc2UsIHZhbGlkdGhpczogdHJ1ZVxuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiByYnVzaCkpIHsgcmV0dXJuIG5ldyByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpOyB9XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgICAgaWYgKCF0aGlzLl9pbnRlcnNlY3RzKGJib3gsIG5vZGUuYmJveCkpIHsgcmV0dXJuIHJlc3VsdDsgfVxuXG4gICAgICAgIHZhciBub2Rlc1RvU2VhcmNoID0gW10sXG4gICAgICAgICAgICBpLCBsZW4sIGNoaWxkLCBjaGlsZEJCb3g7XG5cbiAgICAgICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IG5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgY2hpbGRCQm94ID0gbm9kZS5sZWFmID8gdGhpcy50b0JCb3goY2hpbGQpIDogY2hpbGQuYmJveDtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pbnRlcnNlY3RzKGJib3gsIGNoaWxkQkJveCkpIHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5sZWFmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjaGlsZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9jb250YWlucyhiYm94LCBjaGlsZEJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hbGwoY2hpbGQsIHJlc3VsdCk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzVG9TZWFyY2gucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgbG9hZDogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgaWYgKCEoZGF0YSAmJiBkYXRhLmxlbmd0aCkpIHsgcmV0dXJuIHRoaXM7IH1cblxuICAgICAgICBpZiAoZGF0YS5sZW5ndGggPCB0aGlzLl9taW5FbnRyaWVzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gZGF0YS5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5zZXJ0KGRhdGFbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZWN1cnNpdmVseSBidWlsZCB0aGUgdHJlZSB3aXRoIHRoZSBnaXZlbiBkYXRhIGZyb20gc3RyYXRjaCB1c2luZyBPTVQgYWxnb3JpdGhtXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fYnVpbGQoZGF0YS5zbGljZSgpLCAwKTtcblxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHNhdmUgYXMgaXMgaWYgdHJlZSBpcyBlbXB0eVxuICAgICAgICAgICAgdGhpcy5kYXRhID0gbm9kZTtcblxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPT09IG5vZGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICAvLyBzcGxpdCByb290IGlmIHRyZWVzIGhhdmUgdGhlIHNhbWUgaGVpZ2h0XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLCBub2RlKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPCBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgdHJlZXMgaWYgaW5zZXJ0ZWQgb25lIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgIHZhciB0bXBOb2RlID0gdGhpcy5kYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IHRtcE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGluc2VydCB0aGUgc21hbGwgdHJlZSBpbnRvIHRoZSBsYXJnZSB0cmVlIGF0IGFwcHJvcHJpYXRlIGxldmVsXG4gICAgICAgICAgICB0aGlzLl9pbnNlcnQobm9kZSwgdGhpcy5kYXRhLmhlaWdodCAtIG5vZGUuaGVpZ2h0IC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBpZiAoaXRlbSkge1xuICAgICAgICAgICAgdGhpcy5faW5zZXJ0KGl0ZW0sIHRoaXMuZGF0YS5oZWlnaHQgLSAxKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgY2xlYXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgICAgICAgbGVhZjogdHJ1ZSxcbiAgICAgICAgICAgIGJib3g6IHRoaXMuX2VtcHR5KCksXG4gICAgICAgICAgICBoZWlnaHQ6IDFcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgaWYgKCFpdGVtKSB7IHJldHVybiB0aGlzOyB9XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBub2RlLmNoaWxkcmVuLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiB0aGlzLl9jb250YWlucyhub2RlLmJib3gsIGJib3gpKSB7IC8vIGdvIGRvd25cbiAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bMF07XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50KSB7IC8vIGdvIHJpZ2h0XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBwYXJlbnQuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9IGVsc2UgeyAvLyBub3RoaW5nIGZvdW5kXG4gICAgICAgICAgICAgICAgbm9kZSA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgdG9CQm94OiBmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gaXRlbTsgfSxcblxuICAgIGNvbXBhcmVNaW5YOiBmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYVswXSAtIGJbMF07IH0sXG4gICAgY29tcGFyZU1pblk6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhWzFdIC0gYlsxXTsgfSxcblxuICAgIHRvSlNPTjogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5kYXRhOyB9LFxuXG4gICAgZnJvbUpTT046IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfYWxsOiBmdW5jdGlvbiAobm9kZSwgcmVzdWx0KSB7XG4gICAgICAgIHZhciBub2Rlc1RvU2VhcmNoID0gW107XG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5sZWFmKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2guYXBwbHkocmVzdWx0LCBub2RlLmNoaWxkcmVuKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9kZXNUb1NlYXJjaC5wdXNoLmFwcGx5KG5vZGVzVG9TZWFyY2gsIG5vZGUuY2hpbGRyZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgX2J1aWxkOiBmdW5jdGlvbiAoaXRlbXMsIGxldmVsLCBoZWlnaHQpIHtcblxuICAgICAgICB2YXIgTiA9IGl0ZW1zLmxlbmd0aCxcbiAgICAgICAgICAgIE0gPSB0aGlzLl9tYXhFbnRyaWVzLFxuICAgICAgICAgICAgbm9kZTtcblxuICAgICAgICBpZiAoTiA8PSBNKSB7XG4gICAgICAgICAgICBub2RlID0ge1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBpdGVtcyxcbiAgICAgICAgICAgICAgICBsZWFmOiB0cnVlLFxuICAgICAgICAgICAgICAgIGhlaWdodDogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuX2NhbGNCQm94KG5vZGUpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWxldmVsKSB7XG4gICAgICAgICAgICAvLyB0YXJnZXQgaGVpZ2h0IG9mIHRoZSBidWxrLWxvYWRlZCB0cmVlXG4gICAgICAgICAgICBoZWlnaHQgPSBNYXRoLmNlaWwoTWF0aC5sb2coTikgLyBNYXRoLmxvZyhNKSk7XG5cbiAgICAgICAgICAgIC8vIHRhcmdldCBudW1iZXIgb2Ygcm9vdCBlbnRyaWVzIHRvIG1heGltaXplIHN0b3JhZ2UgdXRpbGl6YXRpb25cbiAgICAgICAgICAgIE0gPSBNYXRoLmNlaWwoTiAvIE1hdGgucG93KE0sIGhlaWdodCAtIDEpKTtcblxuICAgICAgICAgICAgaXRlbXMuc29ydCh0aGlzLmNvbXBhcmVNaW5YKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRPRE8gZWxpbWluYXRlIHJlY3Vyc2lvbj9cblxuICAgICAgICBub2RlID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgTjEgPSBNYXRoLmNlaWwoTiAvIE0pICogTWF0aC5jZWlsKE1hdGguc3FydChNKSksXG4gICAgICAgICAgICBOMiA9IE1hdGguY2VpbChOIC8gTSksXG4gICAgICAgICAgICBjb21wYXJlID0gbGV2ZWwgJSAyID09PSAxID8gdGhpcy5jb21wYXJlTWluWCA6IHRoaXMuY29tcGFyZU1pblksXG4gICAgICAgICAgICBpLCBqLCBzbGljZSwgc2xpY2VMZW4sIGNoaWxkTm9kZTtcblxuICAgICAgICAvLyBzcGxpdCB0aGUgaXRlbXMgaW50byBNIG1vc3RseSBzcXVhcmUgdGlsZXNcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IE47IGkgKz0gTjEpIHtcbiAgICAgICAgICAgIHNsaWNlID0gaXRlbXMuc2xpY2UoaSwgaSArIE4xKS5zb3J0KGNvbXBhcmUpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSAwLCBzbGljZUxlbiA9IHNsaWNlLmxlbmd0aDsgaiA8IHNsaWNlTGVuOyBqICs9IE4yKSB7XG4gICAgICAgICAgICAgICAgLy8gcGFjayBlYWNoIGVudHJ5IHJlY3Vyc2l2ZWx5XG4gICAgICAgICAgICAgICAgY2hpbGROb2RlID0gdGhpcy5fYnVpbGQoc2xpY2Uuc2xpY2UoaiwgaiArIE4yKSwgbGV2ZWwgKyAxLCBoZWlnaHQgLSAxKTtcbiAgICAgICAgICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NhbGNCQm94KG5vZGUpO1xuXG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3VidHJlZTogZnVuY3Rpb24gKGJib3gsIG5vZGUsIGxldmVsLCBwYXRoKSB7XG5cbiAgICAgICAgdmFyIGksIGxlbiwgY2hpbGQsIHRhcmdldE5vZGUsIGFyZWEsIGVubGFyZ2VtZW50LCBtaW5BcmVhLCBtaW5FbmxhcmdlbWVudDtcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuXG4gICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IHBhdGgubGVuZ3RoIC0gMSA9PT0gbGV2ZWwpIHsgYnJlYWs7IH1cblxuICAgICAgICAgICAgbWluQXJlYSA9IG1pbkVubGFyZ2VtZW50ID0gSW5maW5pdHk7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IG5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgYXJlYSA9IHRoaXMuX2FyZWEoY2hpbGQuYmJveCk7XG4gICAgICAgICAgICAgICAgZW5sYXJnZW1lbnQgPSB0aGlzLl9lbmxhcmdlZEFyZWEoYmJveCwgY2hpbGQuYmJveCkgLSBhcmVhO1xuXG4gICAgICAgICAgICAgICAgLy8gY2hvb3NlIGVudHJ5IHdpdGggdGhlIGxlYXN0IGFyZWEgZW5sYXJnZW1lbnRcbiAgICAgICAgICAgICAgICBpZiAoZW5sYXJnZW1lbnQgPCBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBtaW5FbmxhcmdlbWVudCA9IGVubGFyZ2VtZW50O1xuICAgICAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYSA8IG1pbkFyZWEgPyBhcmVhIDogbWluQXJlYTtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Tm9kZSA9IGNoaWxkO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlbmxhcmdlbWVudCA9PT0gbWluRW5sYXJnZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGNob29zZSBvbmUgd2l0aCB0aGUgc21hbGxlc3QgYXJlYVxuICAgICAgICAgICAgICAgICAgICBpZiAoYXJlYSA8IG1pbkFyZWEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Tm9kZSA9IGNoaWxkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBub2RlID0gdGFyZ2V0Tm9kZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH0sXG5cbiAgICBfaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSwgbGV2ZWwsIGlzTm9kZSkge1xuXG4gICAgICAgIHZhciBiYm94ID0gaXNOb2RlID8gaXRlbS5iYm94IDogdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBpbnNlcnRQYXRoID0gW107XG5cbiAgICAgICAgLy8gZmluZCB0aGUgYmVzdCBub2RlIGZvciBhY2NvbW1vZGF0aW5nIHRoZSBpdGVtLCBzYXZpbmcgYWxsIG5vZGVzIGFsb25nIHRoZSBwYXRoIHRvb1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX2Nob29zZVN1YnRyZWUoYmJveCwgdGhpcy5kYXRhLCBsZXZlbCwgaW5zZXJ0UGF0aCk7XG5cbiAgICAgICAgLy8gcHV0IHRoZSBpdGVtIGludG8gdGhlIG5vZGVcbiAgICAgICAgbm9kZS5jaGlsZHJlbi5wdXNoKGl0ZW0pO1xuICAgICAgICB0aGlzLl9leHRlbmQobm9kZS5iYm94LCBiYm94KTtcblxuICAgICAgICAvLyBzcGxpdCBvbiBub2RlIG92ZXJmbG93OyBwcm9wYWdhdGUgdXB3YXJkcyBpZiBuZWNlc3NhcnlcbiAgICAgICAgd2hpbGUgKGxldmVsID49IDApIHtcbiAgICAgICAgICAgIGlmIChpbnNlcnRQYXRoW2xldmVsXS5jaGlsZHJlbi5sZW5ndGggPiB0aGlzLl9tYXhFbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3BsaXQoaW5zZXJ0UGF0aCwgbGV2ZWwpO1xuICAgICAgICAgICAgICAgIGxldmVsLS07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBiYm94ZXMgYWxvbmcgdGhlIGluc2VydGlvbiBwYXRoXG4gICAgICAgIHRoaXMuX2FkanVzdFBhcmVudEJCb3hlcyhiYm94LCBpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgfSxcblxuICAgIC8vIHNwbGl0IG92ZXJmbG93ZWQgbm9kZSBpbnRvIHR3b1xuICAgIF9zcGxpdDogZnVuY3Rpb24gKGluc2VydFBhdGgsIGxldmVsKSB7XG5cbiAgICAgICAgdmFyIG5vZGUgPSBpbnNlcnRQYXRoW2xldmVsXSxcbiAgICAgICAgICAgIE0gPSBub2RlLmNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICAgIG0gPSB0aGlzLl9taW5FbnRyaWVzO1xuXG4gICAgICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhub2RlLCBtLCBNKTtcblxuICAgICAgICB2YXIgbmV3Tm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLnNwbGljZSh0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pKSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobm9kZS5sZWFmKSB7XG4gICAgICAgICAgICBuZXdOb2RlLmxlYWYgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY2FsY0JCb3gobm9kZSk7XG4gICAgICAgIHRoaXMuX2NhbGNCQm94KG5ld05vZGUpO1xuXG4gICAgICAgIGlmIChsZXZlbCkge1xuICAgICAgICAgICAgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3Qobm9kZSwgbmV3Tm9kZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX3NwbGl0Um9vdDogZnVuY3Rpb24gKG5vZGUsIG5ld05vZGUpIHtcbiAgICAgICAgLy8gc3BsaXQgcm9vdCBub2RlXG4gICAgICAgIHRoaXMuZGF0YSA9IHt9O1xuICAgICAgICB0aGlzLmRhdGEuY2hpbGRyZW4gPSBbbm9kZSwgbmV3Tm9kZV07XG4gICAgICAgIHRoaXMuZGF0YS5oZWlnaHQgPSBub2RlLmhlaWdodCArIDE7XG4gICAgICAgIHRoaXMuX2NhbGNCQm94KHRoaXMuZGF0YSk7XG4gICAgfSxcblxuICAgIF9jaG9vc2VTcGxpdEluZGV4OiBmdW5jdGlvbiAobm9kZSwgbSwgTSkge1xuXG4gICAgICAgIHZhciBpLCBiYm94MSwgYmJveDIsIG92ZXJsYXAsIGFyZWEsIG1pbk92ZXJsYXAsIG1pbkFyZWEsIGluZGV4O1xuXG4gICAgICAgIG1pbk92ZXJsYXAgPSBtaW5BcmVhID0gSW5maW5pdHk7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8PSBNIC0gbTsgaSsrKSB7XG4gICAgICAgICAgICBiYm94MSA9IHRoaXMuX2Rpc3RCQm94KG5vZGUsIDAsIGkpO1xuICAgICAgICAgICAgYmJveDIgPSB0aGlzLl9kaXN0QkJveChub2RlLCBpLCBNKTtcblxuICAgICAgICAgICAgb3ZlcmxhcCA9IHRoaXMuX2ludGVyc2VjdGlvbkFyZWEoYmJveDEsIGJib3gyKTtcbiAgICAgICAgICAgIGFyZWEgPSB0aGlzLl9hcmVhKGJib3gxKSArIHRoaXMuX2FyZWEoYmJveDIpO1xuXG4gICAgICAgICAgICAvLyBjaG9vc2UgZGlzdHJpYnV0aW9uIHdpdGggbWluaW11bSBvdmVybGFwXG4gICAgICAgICAgICBpZiAob3ZlcmxhcCA8IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICBtaW5PdmVybGFwID0gb3ZlcmxhcDtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGk7XG5cbiAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYSA8IG1pbkFyZWEgPyBhcmVhIDogbWluQXJlYTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChvdmVybGFwID09PSBtaW5PdmVybGFwKSB7XG4gICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIGFyZWFcbiAgICAgICAgICAgICAgICBpZiAoYXJlYSA8IG1pbkFyZWEpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfSxcblxuICAgIC8vIHNvcnRzIG5vZGUgY2hpbGRyZW4gYnkgdGhlIGJlc3QgYXhpcyBmb3Igc3BsaXRcbiAgICBfY2hvb3NlU3BsaXRBeGlzOiBmdW5jdGlvbiAobm9kZSwgbSwgTSkge1xuXG4gICAgICAgIHZhciBjb21wYXJlTWluWCA9IG5vZGUubGVhZiA/IHRoaXMuY29tcGFyZU1pblggOiB0aGlzLl9jb21wYXJlTm9kZU1pblgsXG4gICAgICAgICAgICBjb21wYXJlTWluWSA9IG5vZGUubGVhZiA/IHRoaXMuY29tcGFyZU1pblkgOiB0aGlzLl9jb21wYXJlTm9kZU1pblksXG4gICAgICAgICAgICB4TWFyZ2luID0gdGhpcy5fYWxsRGlzdE1hcmdpbihub2RlLCBtLCBNLCBjb21wYXJlTWluWCksXG4gICAgICAgICAgICB5TWFyZ2luID0gdGhpcy5fYWxsRGlzdE1hcmdpbihub2RlLCBtLCBNLCBjb21wYXJlTWluWSk7XG5cbiAgICAgICAgLy8gaWYgdG90YWwgZGlzdHJpYnV0aW9ucyBtYXJnaW4gdmFsdWUgaXMgbWluaW1hbCBmb3IgeCwgc29ydCBieSBtaW5YLFxuICAgICAgICAvLyBvdGhlcndpc2UgaXQncyBhbHJlYWR5IHNvcnRlZCBieSBtaW5ZXG5cbiAgICAgICAgaWYgKHhNYXJnaW4gPCB5TWFyZ2luKSB7XG4gICAgICAgICAgICBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZU1pblgpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8vIHRvdGFsIG1hcmdpbiBvZiBhbGwgcG9zc2libGUgc3BsaXQgZGlzdHJpYnV0aW9ucyB3aGVyZSBlYWNoIG5vZGUgaXMgYXQgbGVhc3QgbSBmdWxsXG4gICAgX2FsbERpc3RNYXJnaW46IGZ1bmN0aW9uIChub2RlLCBtLCBNLCBjb21wYXJlKSB7XG5cbiAgICAgICAgbm9kZS5jaGlsZHJlbi5zb3J0KGNvbXBhcmUpO1xuXG4gICAgICAgIHZhciBsZWZ0QkJveCA9IHRoaXMuX2Rpc3RCQm94KG5vZGUsIDAsIG0pLFxuICAgICAgICAgICAgcmlnaHRCQm94ID0gdGhpcy5fZGlzdEJCb3gobm9kZSwgTSAtIG0sIE0pLFxuICAgICAgICAgICAgbWFyZ2luID0gdGhpcy5fbWFyZ2luKGxlZnRCQm94KSArIHRoaXMuX21hcmdpbihyaWdodEJCb3gpLFxuICAgICAgICAgICAgaSwgY2hpbGQ7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIHRoaXMuX2V4dGVuZChsZWZ0QkJveCwgbm9kZS5sZWFmID8gdGhpcy50b0JCb3goY2hpbGQpIDogY2hpbGQuYmJveCk7XG4gICAgICAgICAgICBtYXJnaW4gKz0gdGhpcy5fbWFyZ2luKGxlZnRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IE0gLSBtIC0gMTsgaSA+PSBtOyBpLS0pIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIHRoaXMuX2V4dGVuZChyaWdodEJCb3gsIG5vZGUubGVhZiA/IHRoaXMudG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IHRoaXMuX21hcmdpbihyaWdodEJCb3gpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1hcmdpbjtcbiAgICB9LFxuXG4gICAgLy8gbWluIGJvdW5kaW5nIHJlY3RhbmdsZSBvZiBub2RlIGNoaWxkcmVuIGZyb20gayB0byBwLTFcbiAgICBfZGlzdEJCb3g6IGZ1bmN0aW9uIChub2RlLCBrLCBwKSB7XG4gICAgICAgIHZhciBiYm94ID0gdGhpcy5fZW1wdHkoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIHRoaXMuX2V4dGVuZChiYm94LCBub2RlLmxlYWYgPyB0aGlzLnRvQkJveChjaGlsZCkgOiBjaGlsZC5iYm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBiYm94O1xuICAgIH0sXG5cbiAgICAvLyBjYWxjdWxhdGUgbm9kZSdzIGJib3ggZnJvbSBiYm94ZXMgb2YgaXRzIGNoaWxkcmVuXG4gICAgX2NhbGNCQm94OiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBub2RlLmJib3ggPSB0aGlzLl9kaXN0QkJveChub2RlLCAwLCBub2RlLmNoaWxkcmVuLmxlbmd0aCk7XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgdGhpcy5fZXh0ZW5kKHBhdGhbaV0uYmJveCwgYmJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbmRlbnNlOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIHRoZSBwYXRoLCByZW1vdmluZyBlbXB0eSBub2RlcyBhbmQgdXBkYXRpbmcgYmJveGVzXG4gICAgICAgIGZvciAodmFyIGkgPSBwYXRoLmxlbmd0aCAtIDEsIHBhcmVudDsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGlmIChwYXRoW2ldLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW2kgLSAxXS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50LnNwbGljZShwYXJlbnQuaW5kZXhPZihwYXRoW2ldKSwgMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsY0JCb3gocGF0aFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRhaW5zOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBhWzBdIDw9IGJbMF0gJiZcbiAgICAgICAgICAgICAgIGFbMV0gPD0gYlsxXSAmJlxuICAgICAgICAgICAgICAgYlsyXSA8PSBhWzJdICYmXG4gICAgICAgICAgICAgICBiWzNdIDw9IGFbM107XG4gICAgfSxcblxuICAgIF9pbnRlcnNlY3RzOiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYlswXSA8PSBhWzJdICYmXG4gICAgICAgICAgICAgICBiWzFdIDw9IGFbM10gJiZcbiAgICAgICAgICAgICAgIGJbMl0gPj0gYVswXSAmJlxuICAgICAgICAgICAgICAgYlszXSA+PSBhWzFdO1xuICAgIH0sXG5cbiAgICBfZXh0ZW5kOiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICBhWzBdID0gTWF0aC5taW4oYVswXSwgYlswXSk7XG4gICAgICAgIGFbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICAgICAgYVsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pO1xuICAgICAgICBhWzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH0sXG5cbiAgICBfYXJlYTogICBmdW5jdGlvbiAoYSkgeyByZXR1cm4gKGFbMl0gLSBhWzBdKSAqIChhWzNdIC0gYVsxXSk7IH0sXG4gICAgX21hcmdpbjogZnVuY3Rpb24gKGEpIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKyAoYVszXSAtIGFbMV0pOyB9LFxuXG4gICAgX2VubGFyZ2VkQXJlYTogZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIChNYXRoLm1heChiWzJdLCBhWzJdKSAtIE1hdGgubWluKGJbMF0sIGFbMF0pKSAqXG4gICAgICAgICAgICAgICAoTWF0aC5tYXgoYlszXSwgYVszXSkgLSBNYXRoLm1pbihiWzFdLCBhWzFdKSk7XG4gICAgfSxcblxuICAgIF9pbnRlcnNlY3Rpb25BcmVhOiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICB2YXIgbWluWCA9IE1hdGgubWF4KGFbMF0sIGJbMF0pLFxuICAgICAgICAgICAgbWluWSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pLFxuICAgICAgICAgICAgbWF4WCA9IE1hdGgubWluKGFbMl0sIGJbMl0pLFxuICAgICAgICAgICAgbWF4WSA9IE1hdGgubWluKGFbM10sIGJbM10pO1xuXG4gICAgICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICAgICAgTWF0aC5tYXgoMCwgbWF4WSAtIG1pblkpO1xuICAgIH0sXG5cbiAgICBfZW1wdHk6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsgfSxcblxuICAgIF9jb21wYXJlTm9kZU1pblg6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLmJib3hbMF0gLSBiLmJib3hbMF07IH0sXG4gICAgX2NvbXBhcmVOb2RlTWluWTogZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEuYmJveFsxXSAtIGIuYmJveFsxXTsgfSxcblxuICAgIF9pbml0Rm9ybWF0OiBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgIC8vIGRhdGEgZm9ybWF0IChtaW5YLCBtaW5ZLCBtYXhYLCBtYXhZIGFjY2Vzc29ycylcblxuICAgICAgICAvLyB1c2VzIGV2YWwtdHlwZSBmdW5jdGlvbiBjb21waWxhdGlvbiBpbnN0ZWFkIG9mIGp1c3QgYWNjZXB0aW5nIGEgdG9CQm94IGZ1bmN0aW9uXG4gICAgICAgIC8vIGJlY2F1c2UgdGhlIGFsZ29yaXRobXMgYXJlIHZlcnkgc2Vuc2l0aXZlIHRvIHNvcnRpbmcgZnVuY3Rpb25zIHBlcmZvcm1hbmNlLFxuICAgICAgICAvLyBzbyB0aGV5IHNob3VsZCBiZSBkZWFkIHNpbXBsZSBhbmQgd2l0aG91dCBpbm5lciBjYWxsc1xuXG4gICAgICAgIC8vIGpzaGludCBldmlsOiB0cnVlXG5cbiAgICAgICAgdmFyIGNvbXBhcmVBcnIgPSBbJ3JldHVybiBhJywgJyAtIGInLCAnOyddO1xuXG4gICAgICAgIHRoaXMuY29tcGFyZU1pblggPSBuZXcgRnVuY3Rpb24oJ2EnLCAnYicsIGNvbXBhcmVBcnIuam9pbihmb3JtYXRbMF0pKTtcbiAgICAgICAgdGhpcy5jb21wYXJlTWluWSA9IG5ldyBGdW5jdGlvbignYScsICdiJywgY29tcGFyZUFyci5qb2luKGZvcm1hdFsxXSkpO1xuXG4gICAgICAgIHRoaXMudG9CQm94ID0gbmV3IEZ1bmN0aW9uKCdhJywgJ3JldHVybiBbYScgKyBmb3JtYXQuam9pbignLCBhJykgKyAnXTsnKTtcbiAgICB9XG59O1xuXG5pZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcmJ1c2g7XG4gICAgfSk7XG59IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSByYnVzaDtcbn0gZWxzZSBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgc2VsZi5yYnVzaCA9IHJidXNoO1xufSBlbHNlIHtcbiAgICB3aW5kb3cucmJ1c2ggPSByYnVzaDtcbn1cblxufSkoKTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMDggQXBwbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dFxuICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zXG4gKiBhcmUgbWV0OlxuICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0XG4gKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlXG4gKiAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuICpcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgQVBQTEUgSU5DLiBgYEFTIElTJycgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEVcbiAqIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUlxuICogUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIEFQUExFIElOQy4gT1JcbiAqIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLFxuICogRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLFxuICogUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SXG4gKiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZXG4gKiBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxuICogT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqXG4gKiBQb3J0ZWQgZnJvbSBXZWJraXRcbiAqIGh0dHA6Ly9zdm4ud2Via2l0Lm9yZy9yZXBvc2l0b3J5L3dlYmtpdC90cnVuay9Tb3VyY2UvV2ViQ29yZS9wbGF0Zm9ybS9ncmFwaGljcy9Vbml0QmV6aWVyLmhcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFVuaXRCZXppZXI7XG5cbmZ1bmN0aW9uIFVuaXRCZXppZXIocDF4LCBwMXksIHAyeCwgcDJ5KSB7XG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBwb2x5bm9taWFsIGNvZWZmaWNpZW50cywgaW1wbGljaXQgZmlyc3QgYW5kIGxhc3QgY29udHJvbCBwb2ludHMgYXJlICgwLDApIGFuZCAoMSwxKS5cbiAgICB0aGlzLmN4ID0gMy4wICogcDF4O1xuICAgIHRoaXMuYnggPSAzLjAgKiAocDJ4IC0gcDF4KSAtIHRoaXMuY3g7XG4gICAgdGhpcy5heCA9IDEuMCAtIHRoaXMuY3ggLSB0aGlzLmJ4O1xuXG4gICAgdGhpcy5jeSA9IDMuMCAqIHAxeTtcbiAgICB0aGlzLmJ5ID0gMy4wICogKHAyeSAtIHAxeSkgLSB0aGlzLmN5O1xuICAgIHRoaXMuYXkgPSAxLjAgLSB0aGlzLmN5IC0gdGhpcy5ieTtcblxuICAgIHRoaXMucDF4ID0gcDF4O1xuICAgIHRoaXMucDF5ID0gcDJ5O1xuICAgIHRoaXMucDJ4ID0gcDJ4O1xuICAgIHRoaXMucDJ5ID0gcDJ5O1xufVxuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zYW1wbGVDdXJ2ZVggPSBmdW5jdGlvbih0KSB7XG4gICAgLy8gYGF4IHReMyArIGJ4IHReMiArIGN4IHQnIGV4cGFuZGVkIHVzaW5nIEhvcm5lcidzIHJ1bGUuXG4gICAgcmV0dXJuICgodGhpcy5heCAqIHQgKyB0aGlzLmJ4KSAqIHQgKyB0aGlzLmN4KSAqIHQ7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zYW1wbGVDdXJ2ZVkgPSBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuICgodGhpcy5heSAqIHQgKyB0aGlzLmJ5KSAqIHQgKyB0aGlzLmN5KSAqIHQ7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zYW1wbGVDdXJ2ZURlcml2YXRpdmVYID0gZnVuY3Rpb24odCkge1xuICAgIHJldHVybiAoMy4wICogdGhpcy5heCAqIHQgKyAyLjAgKiB0aGlzLmJ4KSAqIHQgKyB0aGlzLmN4O1xufTtcblxuVW5pdEJlemllci5wcm90b3R5cGUuc29sdmVDdXJ2ZVggPSBmdW5jdGlvbih4LCBlcHNpbG9uKSB7XG4gICAgaWYgKHR5cGVvZiBlcHNpbG9uID09PSAndW5kZWZpbmVkJykgZXBzaWxvbiA9IDFlLTY7XG5cbiAgICB2YXIgdDAsIHQxLCB0MiwgeDIsIGk7XG5cbiAgICAvLyBGaXJzdCB0cnkgYSBmZXcgaXRlcmF0aW9ucyBvZiBOZXd0b24ncyBtZXRob2QgLS0gbm9ybWFsbHkgdmVyeSBmYXN0LlxuICAgIGZvciAodDIgPSB4LCBpID0gMDsgaSA8IDg7IGkrKykge1xuXG4gICAgICAgIHgyID0gdGhpcy5zYW1wbGVDdXJ2ZVgodDIpIC0geDtcbiAgICAgICAgaWYgKE1hdGguYWJzKHgyKSA8IGVwc2lsb24pIHJldHVybiB0MjtcblxuICAgICAgICB2YXIgZDIgPSB0aGlzLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVgodDIpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoZDIpIDwgMWUtNikgYnJlYWs7XG5cbiAgICAgICAgdDIgPSB0MiAtIHgyIC8gZDI7XG4gICAgfVxuXG4gICAgLy8gRmFsbCBiYWNrIHRvIHRoZSBiaXNlY3Rpb24gbWV0aG9kIGZvciByZWxpYWJpbGl0eS5cbiAgICB0MCA9IDAuMDtcbiAgICB0MSA9IDEuMDtcbiAgICB0MiA9IHg7XG5cbiAgICBpZiAodDIgPCB0MCkgcmV0dXJuIHQwO1xuICAgIGlmICh0MiA+IHQxKSByZXR1cm4gdDE7XG5cbiAgICB3aGlsZSAodDAgPCB0MSkge1xuXG4gICAgICAgIHgyID0gdGhpcy5zYW1wbGVDdXJ2ZVgodDIpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoeDIgLSB4KSA8IGVwc2lsb24pIHJldHVybiB0MjtcblxuICAgICAgICBpZiAoeCA+IHgyKSB7XG4gICAgICAgICAgICB0MCA9IHQyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdDEgPSB0MjtcbiAgICAgICAgfVxuXG4gICAgICAgIHQyID0gKHQxIC0gdDApICogMC41ICsgdDA7XG4gICAgfVxuXG4gICAgLy8gRmFpbHVyZS5cbiAgICByZXR1cm4gdDI7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zb2x2ZSA9IGZ1bmN0aW9uKHgsIGVwc2lsb24pIHtcbiAgICByZXR1cm4gdGhpcy5zYW1wbGVDdXJ2ZVkodGhpcy5zb2x2ZUN1cnZlWCh4LCBlcHNpbG9uKSk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZSA9IHJlcXVpcmUoJy4vbGliL3ZlY3RvcnRpbGUuanMnKTtcbm1vZHVsZS5leHBvcnRzLlZlY3RvclRpbGVGZWF0dXJlID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZWZlYXR1cmUuanMnKTtcbm1vZHVsZS5leHBvcnRzLlZlY3RvclRpbGVMYXllciA9IHJlcXVpcmUoJy4vbGliL3ZlY3RvcnRpbGVsYXllci5qcycpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVmVjdG9yVGlsZUxheWVyID0gcmVxdWlyZSgnLi92ZWN0b3J0aWxlbGF5ZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlKGJ1ZmZlciwgZW5kKSB7XG5cbiAgICB0aGlzLmxheWVycyA9IHt9O1xuICAgIHRoaXMuX2J1ZmZlciA9IGJ1ZmZlcjtcblxuICAgIGVuZCA9IGVuZCB8fCBidWZmZXIubGVuZ3RoO1xuXG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgdmFyIHZhbCA9IGJ1ZmZlci5yZWFkVmFyaW50KCksXG4gICAgICAgICAgICB0YWcgPSB2YWwgPj4gMztcblxuICAgICAgICBpZiAodGFnID09IDMpIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IHRoaXMucmVhZExheWVyKCk7XG4gICAgICAgICAgICBpZiAobGF5ZXIubGVuZ3RoKSB0aGlzLmxheWVyc1tsYXllci5uYW1lXSA9IGxheWVyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyLnNraXAodmFsKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuVmVjdG9yVGlsZS5wcm90b3R5cGUucmVhZExheWVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuX2J1ZmZlcixcbiAgICAgICAgYnl0ZXMgPSBidWZmZXIucmVhZFZhcmludCgpLFxuICAgICAgICBlbmQgPSBidWZmZXIucG9zICsgYnl0ZXMsXG4gICAgICAgIGxheWVyID0gbmV3IFZlY3RvclRpbGVMYXllcihidWZmZXIsIGVuZCk7XG5cbiAgICBidWZmZXIucG9zID0gZW5kO1xuXG4gICAgcmV0dXJuIGxheWVyO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlRmVhdHVyZTtcblxuZnVuY3Rpb24gVmVjdG9yVGlsZUZlYXR1cmUoYnVmZmVyLCBlbmQsIGV4dGVudCwga2V5cywgdmFsdWVzKSB7XG5cbiAgICB0aGlzLnByb3BlcnRpZXMgPSB7fTtcblxuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIHRoaXMudHlwZSA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fYnVmZmVyID0gYnVmZmVyO1xuICAgIHRoaXMuX2dlb21ldHJ5ID0gLTE7XG5cbiAgICBlbmQgPSBlbmQgfHwgYnVmZmVyLmxlbmd0aDtcblxuICAgIHdoaWxlIChidWZmZXIucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhciB2YWwgPSBidWZmZXIucmVhZFZhcmludCgpLFxuICAgICAgICAgICAgdGFnID0gdmFsID4+IDM7XG5cbiAgICAgICAgaWYgKHRhZyA9PSAxKSB7XG4gICAgICAgICAgICB0aGlzLl9pZCA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG5cbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gMikge1xuICAgICAgICAgICAgdmFyIHRhZ0VuZCA9IGJ1ZmZlci5wb3MgKyBidWZmZXIucmVhZFZhcmludCgpO1xuXG4gICAgICAgICAgICB3aGlsZSAoYnVmZmVyLnBvcyA8IHRhZ0VuZCkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzW2J1ZmZlci5yZWFkVmFyaW50KCldO1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHZhbHVlc1tidWZmZXIucmVhZFZhcmludCgpXTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDMpIHtcbiAgICAgICAgICAgIHRoaXMudHlwZSA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG5cbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNCkge1xuICAgICAgICAgICAgdGhpcy5fZ2VvbWV0cnkgPSBidWZmZXIucG9zO1xuICAgICAgICAgICAgYnVmZmVyLnNraXAodmFsKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyLnNraXAodmFsKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuVmVjdG9yVGlsZUZlYXR1cmUudHlwZXMgPSBbJ1Vua25vd24nLCAnUG9pbnQnLCAnTGluZVN0cmluZycsICdQb2x5Z29uJ107XG5cblZlY3RvclRpbGVGZWF0dXJlLnByb3RvdHlwZS5sb2FkR2VvbWV0cnkgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnVmZmVyID0gdGhpcy5fYnVmZmVyO1xuICAgIGJ1ZmZlci5wb3MgPSB0aGlzLl9nZW9tZXRyeTtcblxuICAgIHZhciBieXRlcyA9IGJ1ZmZlci5yZWFkVmFyaW50KCksXG4gICAgICAgIGVuZCA9IGJ1ZmZlci5wb3MgKyBieXRlcyxcbiAgICAgICAgY21kID0gMSxcbiAgICAgICAgbGVuZ3RoID0gMCxcbiAgICAgICAgeCA9IDAsXG4gICAgICAgIHkgPSAwLFxuICAgICAgICBsaW5lcyA9IFtdLFxuICAgICAgICBsaW5lO1xuXG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBjbWRfbGVuZ3RoID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZF9sZW5ndGggJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRfbGVuZ3RoID4+IDM7XG4gICAgICAgIH1cblxuICAgICAgICBsZW5ndGgtLTtcblxuICAgICAgICBpZiAoY21kID09PSAxIHx8IGNtZCA9PT0gMikge1xuICAgICAgICAgICAgeCArPSBidWZmZXIucmVhZFNWYXJpbnQoKTtcbiAgICAgICAgICAgIHkgKz0gYnVmZmVyLnJlYWRTVmFyaW50KCk7XG5cbiAgICAgICAgICAgIGlmIChjbWQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBtb3ZlVG9cbiAgICAgICAgICAgICAgICBpZiAobGluZSkge1xuICAgICAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKGxpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUucHVzaChuZXcgUG9pbnQoeCwgeSkpO1xuICAgICAgICB9IGVsc2UgaWYgKGNtZCA9PT0gNykge1xuICAgICAgICAgICAgLy8gY2xvc2VQb2x5Z29uXG4gICAgICAgICAgICBsaW5lLnB1c2gobGluZVswXS5jbG9uZSgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxpbmUpIGxpbmVzLnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gbGluZXM7XG59O1xuXG5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBidWZmZXIgPSB0aGlzLl9idWZmZXI7XG4gICAgYnVmZmVyLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGJ5dGVzID0gYnVmZmVyLnJlYWRWYXJpbnQoKSxcbiAgICAgICAgZW5kID0gYnVmZmVyLnBvcyArIGJ5dGVzLFxuXG4gICAgICAgIGNtZCA9IDEsXG4gICAgICAgIGxlbmd0aCA9IDAsXG4gICAgICAgIHggPSAwLFxuICAgICAgICB5ID0gMCxcbiAgICAgICAgeDEgPSBJbmZpbml0eSxcbiAgICAgICAgeDIgPSAtSW5maW5pdHksXG4gICAgICAgIHkxID0gSW5maW5pdHksXG4gICAgICAgIHkyID0gLUluZmluaXR5O1xuXG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBjbWRfbGVuZ3RoID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZF9sZW5ndGggJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRfbGVuZ3RoID4+IDM7XG4gICAgICAgIH1cblxuICAgICAgICBsZW5ndGgtLTtcblxuICAgICAgICBpZiAoY21kID09PSAxIHx8IGNtZCA9PT0gMikge1xuICAgICAgICAgICAgeCArPSBidWZmZXIucmVhZFNWYXJpbnQoKTtcbiAgICAgICAgICAgIHkgKz0gYnVmZmVyLnJlYWRTVmFyaW50KCk7XG4gICAgICAgICAgICBpZiAoeCA8IHgxKSB4MSA9IHg7XG4gICAgICAgICAgICBpZiAoeCA+IHgyKSB4MiA9IHg7XG4gICAgICAgICAgICBpZiAoeSA8IHkxKSB5MSA9IHk7XG4gICAgICAgICAgICBpZiAoeSA+IHkyKSB5MiA9IHk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChjbWQgIT09IDcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4MSwgeTEsIHgyLCB5Ml07XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGVmZWF0dXJlLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmVjdG9yVGlsZUxheWVyO1xuZnVuY3Rpb24gVmVjdG9yVGlsZUxheWVyKGJ1ZmZlciwgZW5kKSB7XG4gICAgLy8gUHVibGljXG4gICAgdGhpcy52ZXJzaW9uID0gMTtcbiAgICB0aGlzLm5hbWUgPSBudWxsO1xuICAgIHRoaXMuZXh0ZW50ID0gNDA5NjtcbiAgICB0aGlzLmxlbmd0aCA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fYnVmZmVyID0gYnVmZmVyO1xuICAgIHRoaXMuX2tleXMgPSBbXTtcbiAgICB0aGlzLl92YWx1ZXMgPSBbXTtcbiAgICB0aGlzLl9mZWF0dXJlcyA9IFtdO1xuXG4gICAgdmFyIHZhbCwgdGFnO1xuXG4gICAgZW5kID0gZW5kIHx8IGJ1ZmZlci5sZW5ndGg7XG5cbiAgICB3aGlsZSAoYnVmZmVyLnBvcyA8IGVuZCkge1xuICAgICAgICB2YWwgPSBidWZmZXIucmVhZFZhcmludCgpO1xuICAgICAgICB0YWcgPSB2YWwgPj4gMztcblxuICAgICAgICBpZiAodGFnID09PSAxNSkge1xuICAgICAgICAgICAgdGhpcy52ZXJzaW9uID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT09IDEpIHtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IGJ1ZmZlci5yZWFkU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09PSA1KSB7XG4gICAgICAgICAgICB0aGlzLmV4dGVudCA9IGJ1ZmZlci5yZWFkVmFyaW50KCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09PSAyKSB7XG4gICAgICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgICAgICAgdGhpcy5fZmVhdHVyZXMucHVzaChidWZmZXIucG9zKTtcbiAgICAgICAgICAgIGJ1ZmZlci5za2lwKHZhbCk7XG5cbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT09IDMpIHtcbiAgICAgICAgICAgIHRoaXMuX2tleXMucHVzaChidWZmZXIucmVhZFN0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT09IDQpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbHVlcy5wdXNoKHRoaXMucmVhZEZlYXR1cmVWYWx1ZSgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ1ZmZlci5za2lwKHZhbCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cblZlY3RvclRpbGVMYXllci5wcm90b3R5cGUucmVhZEZlYXR1cmVWYWx1ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBidWZmZXIgPSB0aGlzLl9idWZmZXIsXG4gICAgICAgIHZhbHVlID0gbnVsbCxcbiAgICAgICAgYnl0ZXMgPSBidWZmZXIucmVhZFZhcmludCgpLFxuICAgICAgICBlbmQgPSBidWZmZXIucG9zICsgYnl0ZXMsXG4gICAgICAgIHZhbCwgdGFnO1xuXG4gICAgd2hpbGUgKGJ1ZmZlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgdmFsID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgdGFnID0gdmFsID4+IDM7XG5cbiAgICAgICAgaWYgKHRhZyA9PSAxKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGJ1ZmZlci5yZWFkU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncmVhZCBmbG9hdCcpO1xuICAgICAgICB9IGVsc2UgaWYgKHRhZyA9PSAzKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGJ1ZmZlci5yZWFkRG91YmxlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGFnID09IDQpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYnVmZmVyLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWFkIHVpbnQnKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNikge1xuICAgICAgICAgICAgdmFsdWUgPSBidWZmZXIucmVhZFNWYXJpbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YWcgPT0gNykge1xuICAgICAgICAgICAgdmFsdWUgPSBCb29sZWFuKGJ1ZmZlci5yZWFkVmFyaW50KCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZmVyLnNraXAodmFsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbn07XG5cbi8vIHJldHVybiBmZWF0dXJlIGBpYCBmcm9tIHRoaXMgbGF5ZXIgYXMgYSBgVmVjdG9yVGlsZUZlYXR1cmVgXG5WZWN0b3JUaWxlTGF5ZXIucHJvdG90eXBlLmZlYXR1cmUgPSBmdW5jdGlvbihpKSB7XG4gICAgaWYgKGkgPCAwIHx8IGkgPj0gdGhpcy5fZmVhdHVyZXMubGVuZ3RoKSB0aHJvdyBuZXcgRXJyb3IoJ2ZlYXR1cmUgaW5kZXggb3V0IG9mIGJvdW5kcycpO1xuXG4gICAgdGhpcy5fYnVmZmVyLnBvcyA9IHRoaXMuX2ZlYXR1cmVzW2ldO1xuICAgIHZhciBlbmQgPSB0aGlzLl9idWZmZXIucmVhZFZhcmludCgpICsgdGhpcy5fYnVmZmVyLnBvcztcblxuICAgIHJldHVybiBuZXcgVmVjdG9yVGlsZUZlYXR1cmUodGhpcy5fYnVmZmVyLCBlbmQsIHRoaXMuZXh0ZW50LCB0aGlzLl9rZXlzLCB0aGlzLl92YWx1ZXMpO1xufTtcbiJdfQ==