1//#region node_modules/@tmcw/togeojson/dist/togeojson.es.mjs 2function $(element, tagName) { 3 return Array.from(element.getElementsByTagName(tagName)); 4} 5function normalizeId(id) { 6 return id[0] === "#" ? id : `#${id}`; 7} 8function $ns(element, tagName, ns) { 9 return Array.from(element.getElementsByTagNameNS(ns, tagName)); 10} 11/** 12* get the content of a text node, if any 13*/ 14function nodeVal(node) { 15 node?.normalize(); 16 return node?.textContent || ""; 17} 18/** 19* Get one Y child of X, if any, otherwise null 20*/ 21function get1(node, tagName, callback) { 22 const n = node.getElementsByTagName(tagName); 23 const result = n.length ? n[0] : null; 24 if (result && callback) callback(result); 25 return result; 26} 27function get(node, tagName, callback) { 28 const properties = {}; 29 if (!node) return properties; 30 const n = node.getElementsByTagName(tagName); 31 const result = n.length ? n[0] : null; 32 if (result && callback) return callback(result, properties); 33 return properties; 34} 35function val1(node, tagName, callback) { 36 const val = nodeVal(get1(node, tagName)); 37 if (val && callback) return callback(val) || {}; 38 return {}; 39} 40function $num(node, tagName, callback) { 41 const val = Number.parseFloat(nodeVal(get1(node, tagName))); 42 if (Number.isNaN(val)) return void 0; 43 if (val && callback) return callback(val) || {}; 44 return {}; 45} 46function num1(node, tagName, callback) { 47 const val = Number.parseFloat(nodeVal(get1(node, tagName))); 48 if (Number.isNaN(val)) return void 0; 49 if (callback) callback(val); 50 return val; 51} 52function getMulti(node, propertyNames) { 53 const properties = {}; 54 for (const property of propertyNames) val1(node, property, (val) => { 55 properties[property] = val; 56 }); 57 return properties; 58} 59function isElement(node) { 60 return node?.nodeType === 1; 61} 62function getExtensions(node) { 63 let values = []; 64 if (node === null) return values; 65 for (const child of Array.from(node.childNodes)) { 66 if (!isElement(child)) continue; 67 const name = abbreviateName(child.nodeName); 68 if (name === "gpxtpx:TrackPointExtension") values = values.concat(getExtensions(child)); 69 else { 70 const val = nodeVal(child); 71 values.push([name, parseNumeric(val)]); 72 } 73 } 74 return values; 75} 76function abbreviateName(name) { 77 return [ 78 "heart", 79 "gpxtpx:hr", 80 "hr" 81 ].includes(name) ? "heart" : name; 82} 83function parseNumeric(val) { 84 const num = Number.parseFloat(val); 85 return Number.isNaN(num) ? val : num; 86} 87function coordPair$1(node) { 88 const ll = [Number.parseFloat(node.getAttribute("lon") || ""), Number.parseFloat(node.getAttribute("lat") || "")]; 89 if (Number.isNaN(ll[0]) || Number.isNaN(ll[1])) return null; 90 num1(node, "ele", (val) => { 91 ll.push(val); 92 }); 93 const time = get1(node, "time"); 94 return { 95 coordinates: ll, 96 time: time ? nodeVal(time) : null, 97 extendedValues: getExtensions(get1(node, "extensions")) 98 }; 99} 100function getLineStyle(node) { 101 return get(node, "line", (lineStyle) => { 102 return Object.assign({}, val1(lineStyle, "color", (color) => { 103 return { stroke: `#${color}` }; 104 }), $num(lineStyle, "opacity", (opacity) => { 105 return { "stroke-opacity": opacity }; 106 }), $num(lineStyle, "width", (width) => { 107 return { "stroke-width": width * 96 / 25.4 }; 108 })); 109 }); 110} 111function extractProperties(ns, node) { 112 const properties = getMulti(node, [ 113 "name", 114 "cmt", 115 "desc", 116 "type", 117 "time", 118 "keywords" 119 ]); 120 for (const [n, url] of ns) for (const child of Array.from(node.getElementsByTagNameNS(url, "*"))) properties[child.tagName.replace(":", "_")] = nodeVal(child)?.trim(); 121 const links = $(node, "link"); 122 if (links.length) properties.links = links.map((link) => Object.assign({ href: link.getAttribute("href") }, getMulti(link, ["text", "type"]))); 123 return properties; 124} 125/** 126* Extract points from a trkseg or rte element. 127*/ 128function getPoints$1(node, pointname) { 129 const pts = $(node, pointname); 130 const line = []; 131 const times = []; 132 const extendedValues = {}; 133 for (let i = 0; i < pts.length; i++) { 134 const c = coordPair$1(pts[i]); 135 if (!c) continue; 136 line.push(c.coordinates); 137 if (c.time) times.push(c.time); 138 for (const [name, val] of c.extendedValues) { 139 const plural = name === "heart" ? name : `${name.replace("gpxtpx:", "")}s`; 140 if (!extendedValues[plural]) extendedValues[plural] = Array(pts.length).fill(null); 141 extendedValues[plural][i] = val; 142 } 143 } 144 if (line.length < 2) return; 145 return { 146 line, 147 times, 148 extendedValues 149 }; 150} 151/** 152* Extract a LineString geometry from a rte 153* element. 154*/ 155function getRoute(ns, node) { 156 const line = getPoints$1(node, "rtept"); 157 if (!line) return; 158 return { 159 type: "Feature", 160 properties: Object.assign({ _gpxType: "rte" }, extractProperties(ns, node), getLineStyle(get1(node, "extensions"))), 161 geometry: { 162 type: "LineString", 163 coordinates: line.line 164 } 165 }; 166} 167function getTrack(ns, node) { 168 const segments = $(node, "trkseg"); 169 const track = []; 170 const times = []; 171 const extractedLines = []; 172 for (const segment of segments) { 173 const line = getPoints$1(segment, "trkpt"); 174 if (line) { 175 extractedLines.push(line); 176 if (line.times?.length) times.push(line.times); 177 } 178 } 179 if (extractedLines.length === 0) return null; 180 const multi = extractedLines.length > 1; 181 const properties = Object.assign({ _gpxType: "trk" }, extractProperties(ns, node), getLineStyle(get1(node, "extensions")), times.length ? { coordinateProperties: { times: multi ? times : times[0] } } : {}); 182 for (let i = 0; i < extractedLines.length; i++) { 183 const line = extractedLines[i]; 184 track.push(line.line); 185 if (!properties.coordinateProperties) properties.coordinateProperties = {};
186 const props = properties.coordinateProperties; 187 for (const [name, val] of Object.entries(line.extendedValues)) if (multi) { 188 if (!props[name]) props[name] = extractedLines.map((line) => new Array(line.line.length).fill(null)); 189 props[name][i] = val; 190 } else props[name] = val; 191 } 192 return { 193 type: "Feature", 194 properties, 195 geometry: multi ? { 196 type: "MultiLineString", 197 coordinates: track 198 } : { 199 type: "LineString", 200 coordinates: track[0] 201 } 202 }; 203} 204/** 205* Extract a point, if possible, from a given node, 206* which is usually a wpt or trkpt 207*/ 208function getPoint(ns, node) { 209 const properties = Object.assign(extractProperties(ns, node), getMulti(node, ["sym"])); 210 const pair = coordPair$1(node); 211 if (!pair) return null; 212 return { 213 type: "Feature", 214 properties, 215 geometry: { 216 type: "Point", 217 coordinates: pair.coordinates 218 } 219 }; 220} 221/** 222* Convert GPX to GeoJSON incrementally, returning 223* a [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) 224* that yields output feature by feature. 225*/ 226function* gpxGen(node) { 227 const n = node; 228 const GPXX = "gpxx"; 229 const GPXX_URI = "http://www.garmin.com/xmlschemas/GpxExtensions/v3"; 230 const ns = [[GPXX, GPXX_URI]]; 231 const attrs = n.getElementsByTagName("gpx")[0]?.attributes; 232 if (attrs) { 233 for (const attr of Array.from(attrs)) if (attr.name?.startsWith("xmlns:") && attr.value !== GPXX_URI) ns.push([attr.name, attr.value]); 234 } 235 for (const track of $(n, "trk")) { 236 const feature = getTrack(ns, track); 237 if (feature) yield feature; 238 } 239 for (const route of $(n, "rte")) { 240 const feature = getRoute(ns, route); 241 if (feature) yield feature; 242 } 243 for (const waypoint of $(n, "wpt")) { 244 const point = getPoint(ns, waypoint); 245 if (point) yield point; 246 } 247} 248/** 249* 250* Convert a GPX document to GeoJSON. The first argument, `doc`, must be a GPX 251* document as an XML DOM - not as a string. You can get this using jQuery's default 252* `.ajax` function or using a bare XMLHttpRequest with the `.response` property 253* holding an XML DOM. 254* 255* The output is a JavaScript object of GeoJSON data, same as `.kml` outputs, with the 256* addition of a `_gpxType` property on each `LineString` feature that indicates whether 257* the feature was encoded as a route (`rte`) or track (`trk`) in the GPX document. 258*/ 259function gpx(node) { 260 return { 261 type: "FeatureCollection", 262 features: Array.from(gpxGen(node)) 263 }; 264} 265var EXTENSIONS_NS = "http://www.garmin.com/xmlschemas/ActivityExtension/v2"; 266var TRACKPOINT_ATTRIBUTES = [ 267 ["heartRate", "heartRates"], 268 ["Cadence", "cadences"], 269 ["Speed", "speeds"], 270 ["Watts", "watts"] 271]; 272var LAP_ATTRIBUTES = [ 273 ["TotalTimeSeconds", "totalTimeSeconds"], 274 ["DistanceMeters", "distanceMeters"], 275 ["MaximumSpeed", "maxSpeed"], 276 ["AverageHeartRateBpm", "avgHeartRate"], 277 ["MaximumHeartRateBpm", "maxHeartRate"], 278 ["AvgSpeed", "avgSpeed"], 279 ["AvgWatts", "avgWatts"], 280 ["MaxWatts", "maxWatts"] 281]; 282function getProperties(node, attributeNames) { 283 const properties = []; 284 for (const [tag, alias] of attributeNames) { 285 let elem = get1(node, tag); 286 if (!elem) { 287 const elements = node.getElementsByTagNameNS(EXTENSIONS_NS, tag); 288 if (elements.length) elem = elements[0]; 289 } 290 const val = Number.parseFloat(nodeVal(elem)); 291 if (!Number.isNaN(val)) properties.push([alias, val]); 292 } 293 return properties; 294} 295function coordPair(node) { 296 const ll = [num1(node, "LongitudeDegrees"), num1(node, "LatitudeDegrees")]; 297 if (ll[0] === void 0 || Number.isNaN(ll[0]) || ll[1] === void 0 || Number.isNaN(ll[1])) return null; 298 const heartRate = get1(node, "HeartRateBpm"); 299 const time = nodeVal(get1(node, "Time")); 300 get1(node, "AltitudeMeters", (alt) => { 301 const a = Number.parseFloat(nodeVal(alt)); 302 if (!Number.isNaN(a)) ll.push(a); 303 }); 304 return { 305 coordinates: ll, 306 time: time || null, 307 heartRate: heartRate ? Number.parseFloat(nodeVal(heartRate)) : null, 308 extensions: getProperties(node, TRACKPOINT_ATTRIBUTES) 309 }; 310} 311function getPoints(node) { 312 const pts = $(node, "Trackpoint"); 313 const line = []; 314 const times = []; 315 const heartRates = []; 316 if (pts.length < 2) return null; 317 const extendedProperties = {}; 318 const result = { extendedProperties }; 319 for (let i = 0; i < pts.length; i++) { 320 const c = coordPair(pts[i]); 321 if (c === null) continue; 322 line.push(c.coordinates); 323 const { time, heartRate, extensions } = c; 324 if (time) times.push(time); 325 if (heartRate) heartRates.push(heartRate); 326 for (const [alias, value] of extensions) { 327 if (!extendedProperties[alias]) extendedProperties[alias] = Array(pts.length).fill(null); 328 extendedProperties[alias][i] = value; 329 } 330 } 331 if (line.length < 2) return null; 332 return Object.assign(result, { 333 line, 334 times, 335 heartRates 336 }); 337} 338function getLap(node) { 339 const segments = $(node, "Track"); 340 const track = []; 341 const times = []; 342 const heartRates = []; 343 const allExtendedProperties = []; 344 let line; 345 const properties = Object.assign(Object.fromEntries(getProperties(node, LAP_ATTRIBUTES)), get(node, "Name", (nameElement) => { 346 return { name: nodeVal(nameElement) }; 347 })); 348 for (const segment of segments) { 349 line = getPoints(segment); 350 if (line) { 351 track.push(line.line); 352 if (line.times.length) times.push(line.times); 353 if (line.heartRates.length) heartRates.push(line.heartRates); 354 allExtendedProperties.push(line.extendedProperties); 355 } 356 } 357 for (let i = 0; i < allExtendedProperties.length; i++) { 358 const extendedProperties = allExtendedProperties[i]; 359 for (const property in extendedProperties) if (segments.length === 1) { 360 if (line) properties[property] = line.extendedProperties[property]; 361 } else { 362 if (!properties[property]) properties[property] = track.map((track) => Array(track.length).fill(null)); 363 properties[property][i] = extendedProperties[property]; 364 } 365 } 366 if (track.length === 0) return null; 367 if (times.length || heartRates.length) properties.coordinateProperties = Object.assign(times.length ? { times: track.length === 1 ? times[0] : times } : {}, heartRates.length ? { heart: track.length === 1 ? heartRates[0] : heartRates } : {}); 368 return { 369 type: "Feature", 370 properties, 371 geometry: track.length === 1 ? { 372 type: "LineString", 373 coordinates: track[0] 374 } : { 375 type: "MultiLineString", 376 coordinates: track 377 } 378 }; 379} 380/** 381* Incrementally convert a TCX document to GeoJSON. The 382* first argument, `doc`, must be a TCX 383* document as an XML DOM - not as a string. 384*/ 385function* tcxGen(node) { 386 for (const lap of $(node, "Lap")) { 387 const feature = getLap(lap); 388 if (feature) yield feature; 389 } 390 for (const course of $(node, "Courses")) { 391 const feature = getLap(course); 392 if (feature) yield feature; 393 } 394} 395/** 396* Convert a TCX document to GeoJSON. The first argument, `doc`, must be a TCX 397* document as an XML DOM - not as a string. 398*/ 399function tcx(node) { 400 return { 401 type: "FeatureCollection", 402 features: Array.from(tcxGen(node)) 403 }; 404}
405function fixColor(v, prefix) { 406 const properties = {}; 407 const colorProp = prefix === "stroke" || prefix === "fill" ? prefix : `${prefix}-color`; 408 if (v[0] === "#") v = v.substring(1); 409 if (v.length === 6 || v.length === 3) properties[colorProp] = `#${v}`; 410 else if (v.length === 8) { 411 properties[`${prefix}-opacity`] = Number.parseInt(v.substring(0, 2), 16) / 255; 412 properties[colorProp] = `#${v.substring(6, 8)}${v.substring(4, 6)}${v.substring(2, 4)}`; 413 } 414 return properties; 415} 416function numericProperty(node, source, target) { 417 const properties = {}; 418 num1(node, source, (val) => { 419 properties[target] = val; 420 }); 421 return properties; 422} 423function getColor(node, output) { 424 return get(node, "color", (elem) => fixColor(nodeVal(elem), output)); 425} 426function extractIconHref(node) { 427 return get(node, "Icon", (icon, properties) => { 428 val1(icon, "href", (href) => { 429 properties.icon = href; 430 }); 431 return properties; 432 }); 433} 434function extractIcon(node) { 435 return get(node, "IconStyle", (iconStyle) => { 436 return Object.assign(getColor(iconStyle, "icon"), numericProperty(iconStyle, "scale", "icon-scale"), numericProperty(iconStyle, "heading", "icon-heading"), get(iconStyle, "hotSpot", (hotspot) => { 437 const left = Number.parseFloat(hotspot.getAttribute("x") || ""); 438 const top = Number.parseFloat(hotspot.getAttribute("y") || ""); 439 const xunits = hotspot.getAttribute("xunits") || ""; 440 const yunits = hotspot.getAttribute("yunits") || ""; 441 if (!Number.isNaN(left) && !Number.isNaN(top)) return { 442 "icon-offset": [left, top], 443 "icon-offset-units": [xunits, yunits] 444 }; 445 return {}; 446 }), extractIconHref(iconStyle)); 447 }); 448} 449function extractLabel(node) { 450 return get(node, "LabelStyle", (labelStyle) => { 451 return Object.assign(getColor(labelStyle, "label"), numericProperty(labelStyle, "scale", "label-scale")); 452 }); 453} 454function extractLine(node) { 455 return get(node, "LineStyle", (lineStyle) => { 456 return Object.assign(getColor(lineStyle, "stroke"), numericProperty(lineStyle, "width", "stroke-width")); 457 }); 458} 459function extractPoly(node) { 460 return get(node, "PolyStyle", (polyStyle, properties) => { 461 return Object.assign(properties, get(polyStyle, "color", (elem) => fixColor(nodeVal(elem), "fill")), val1(polyStyle, "fill", (fill) => { 462 if (fill === "0") return { "fill-opacity": 0 }; 463 }), val1(polyStyle, "outline", (outline) => { 464 if (outline === "0") return { "stroke-opacity": 0 }; 465 })); 466 }); 467} 468function extractStyle(node) { 469 return Object.assign({}, extractPoly(node), extractLine(node), extractLabel(node), extractIcon(node)); 470} 471var removeSpace = /\s*/g; 472var trimSpace = /^\s*|\s*$/g; 473var splitSpace = /\s+/; 474/** 475* Get one coordinate from a coordinate array, if any 476*/ 477function coord1(value) { 478 return value.replace(removeSpace, "").split(",").map(Number.parseFloat).filter((num) => !Number.isNaN(num)).slice(0, 3); 479} 480/** 481* Get all coordinates from a coordinate array as [[],[]] 482*/ 483function coord(value) { 484 return value.replace(trimSpace, "").split(splitSpace).map(coord1).filter((coord) => { 485 return coord.length >= 2; 486 }); 487} 488function gxCoords(node) { 489 let elems = $(node, "coord"); 490 if (elems.length === 0) elems = $ns(node, "coord", "*"); 491 const coordinates = elems.map((elem) => { 492 return nodeVal(elem).split(" ").map(Number.parseFloat); 493 }); 494 if (coordinates.length === 0) return null; 495 return { 496 geometry: coordinates.length > 2 ? { 497 type: "LineString", 498 coordinates 499 } : { 500 type: "Point", 501 coordinates: coordinates[0] 502 }, 503 times: $(node, "when").map((elem) => nodeVal(elem)) 504 }; 505} 506function fixRing(ring) { 507 if (ring.length === 0) return ring; 508 const first = ring[0]; 509 const last = ring[ring.length - 1]; 510 let equal = true; 511 for (let i = 0; i < Math.max(first.length, last.length); i++) if (first[i] !== last[i]) { 512 equal = false; 513 break; 514 } 515 if (!equal) return ring.concat([ring[0]]); 516 return ring; 517} 518function getCoordinates(node) { 519 return nodeVal(get1(node, "coordinates")); 520} 521function getGeometry(node) { 522 let geometries = []; 523 let coordTimes = []; 524 for (let i = 0; i < node.childNodes.length; i++) { 525 const child = node.childNodes.item(i); 526 if (isElement(child)) switch (child.tagName) { 527 case "MultiGeometry": 528 case "MultiTrack": 529 case "gx:MultiTrack": { 530 const childGeometries = getGeometry(child); 531 geometries = geometries.concat(childGeometries.geometries); 532 coordTimes = coordTimes.concat(childGeometries.coordTimes); 533 break; 534 } 535 case "Point": {
536 const coordinates = coord1(getCoordinates(child)); 537 if (coordinates.length >= 2) geometries.push({ 538 type: "Point", 539 coordinates 540 }); 541 break; 542 } 543 case "LinearRing": 544 case "LineString": { 545 const coordinates = coord(getCoordinates(child)); 546 if (coordinates.length >= 2) geometries.push({ 547 type: "LineString", 548 coordinates 549 }); 550 break; 551 } 552 case "Polygon": { 553 const coords = []; 554 for (const linearRing of $(child, "LinearRing")) { 555 const ring = fixRing(coord(getCoordinates(linearRing))); 556 if (ring.length >= 4) coords.push(ring); 557 } 558 if (coords.length) geometries.push({ 559 type: "Polygon", 560 coordinates: coords 561 }); 562 break; 563 } 564 case "Track": 565 case "gx:Track": { 566 const gx = gxCoords(child); 567 if (!gx) break; 568 const { times, geometry } = gx; 569 geometries.push(geometry); 570 if (times.length) coordTimes.push(times); 571 break; 572 } 573 } 574 } 575 return { 576 geometries, 577 coordTimes 578 }; 579} 580var toNumber = (x) => Number(x); 581var typeConverters = { 582 string: (x) => x, 583 int: toNumber, 584 uint: toNumber, 585 short: toNumber, 586 ushort: toNumber, 587 float: toNumber, 588 double: toNumber, 589 bool: (x) => Boolean(x) 590}; 591function extractExtendedData(node, schema) { 592 return get(node, "ExtendedData", (extendedData, properties) => { 593 for (const data of $(extendedData, "Data")) properties[data.getAttribute("name") || ""] = nodeVal(get1(data, "value")); 594 for (const simpleData of $(extendedData, "SimpleData")) { 595 const name = simpleData.getAttribute("name") || ""; 596 properties[name] = (schema[name] || typeConverters.string)(nodeVal(simpleData)); 597 } 598 return properties; 599 }); 600} 601function getMaybeHTMLDescription(node) { 602 const descriptionNode = get1(node, "description"); 603 for (const c of Array.from(descriptionNode?.childNodes || [])) if (c.nodeType === 4) return { description: { 604 "@type": "html", 605 value: nodeVal(c) 606 } }; 607 return {}; 608} 609function extractTimeSpan(node) { 610 return get(node, "TimeSpan", (timeSpan) => { 611 return { timespan: { 612 begin: nodeVal(get1(timeSpan, "begin")), 613 end: nodeVal(get1(timeSpan, "end")) 614 } }; 615 }); 616} 617function extractTimeStamp(node) { 618 return get(node, "TimeStamp", (timeStamp) => { 619 return { timestamp: nodeVal(get1(timeStamp, "when")) }; 620 }); 621} 622function extractCascadedStyle(node, styleMap) { 623 return val1(node, "styleUrl", (styleUrl) => { 624 styleUrl = normalizeId(styleUrl); 625 if (styleMap[styleUrl]) return Object.assign({ styleUrl }, styleMap[styleUrl]); 626 return { styleUrl }; 627 }); 628} 629var AltitudeMode; 630(function(AltitudeMode) { 631 AltitudeMode["ABSOLUTE"] = "absolute"; 632 AltitudeMode["RELATIVE_TO_GROUND"] = "relativeToGround";
633 AltitudeMode["CLAMP_TO_GROUND"] = "clampToGround"; 634 AltitudeMode["CLAMP_TO_SEAFLOOR"] = "clampToSeaFloor"; 635 AltitudeMode["RELATIVE_TO_SEAFLOOR"] = "relativeToSeaFloor"; 636})(AltitudeMode || (AltitudeMode = {})); 637function processAltitudeMode(mode) { 638 switch (mode?.textContent) { 639 case AltitudeMode.ABSOLUTE: return AltitudeMode.ABSOLUTE; 640 case AltitudeMode.CLAMP_TO_GROUND: return AltitudeMode.CLAMP_TO_GROUND; 641 case AltitudeMode.CLAMP_TO_SEAFLOOR: return AltitudeMode.CLAMP_TO_SEAFLOOR; 642 case AltitudeMode.RELATIVE_TO_GROUND: return AltitudeMode.RELATIVE_TO_GROUND; 643 case AltitudeMode.RELATIVE_TO_SEAFLOOR: return AltitudeMode.RELATIVE_TO_SEAFLOOR; 644 } 645 return null; 646} 647function getGroundOverlayBox(node) { 648 if (get1(node, "gx:LatLonQuad")) return { geometry: { 649 type: "Polygon", 650 coordinates: [fixRing(coord(getCoordinates(node)))] 651 } }; 652 return getLatLonBox(node); 653} 654var DEGREES_TO_RADIANS = Math.PI / 180; 655function rotateBox(bbox, coordinates, rotation) { 656 const center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2]; 657 return [coordinates[0].map((coordinate) => { 658 const dy = coordinate[1] - center[1]; 659 const dx = coordinate[0] - center[0]; 660 const distance = Math.sqrt(dy ** 2 + dx ** 2); 661 const angle = Math.atan2(dy, dx) + rotation * DEGREES_TO_RADIANS; 662 return [center[0] + Math.cos(angle) * distance, center[1] + Math.sin(angle) * distance]; 663 })]; 664} 665function getLatLonBox(node) { 666 const latLonBox = get1(node, "LatLonBox"); 667 if (latLonBox) { 668 const north = num1(latLonBox, "north"); 669 const west = num1(latLonBox, "west"); 670 const east = num1(latLonBox, "east"); 671 const south = num1(latLonBox, "south"); 672 const rotation = num1(latLonBox, "rotation"); 673 if (typeof north === "number" && typeof south === "number" && typeof west === "number" && typeof east === "number") { 674 const bbox = [ 675 west, 676 south, 677 east, 678 north 679 ]; 680 let coordinates = [[ 681 [west, north], 682 [east, north], 683 [east, south], 684 [west, south], 685 [west, north] 686 ]]; 687 if (typeof rotation === "number") coordinates = rotateBox(bbox, coordinates, rotation); 688 return { 689 bbox, 690 geometry: { 691 type: "Polygon", 692 coordinates 693 } 694 }; 695 } 696 } 697 return null; 698} 699function getGroundOverlay(node, styleMap, schema, options) { 700 const box = getGroundOverlayBox(node); 701 const geometry = box?.geometry || null; 702 if (!geometry && options.skipNullGeometry) return null; 703 const feature = { 704 type: "Feature", 705 geometry, 706 properties: Object.assign( 707 /** 708 * Related to 709 * https://gist.github.com/tmcw/037a1cb6660d74a392e9da7446540f46 710 */ 711 { "@geometry-type": "groundoverlay" }, 712 getMulti(node, [ 713 "name", 714 "address", 715 "visibility", 716 "open", 717 "phoneNumber", 718 "description" 719 ]), 720 getMaybeHTMLDescription(node), 721 extractCascadedStyle(node, styleMap), 722 extractStyle(node), 723 extractIconHref(node), 724 extractExtendedData(node, schema), 725 extractTimeSpan(node), 726 extractTimeStamp(node) 727 ) 728 }; 729 if (box?.bbox) feature.bbox = box.bbox; 730 if (feature.properties?.visibility !== void 0) feature.properties.visibility = feature.properties.visibility !== "0"; 731 const id = node.getAttribute("id"); 732 if (id !== null && id !== "") feature.id = id; 733 return feature; 734} 735function getNetworkLinkRegion(node) { 736 const region = get1(node, "Region"); 737 if (region) return { 738 coordinateBox: getLatLonAltBox(region), 739 lod: getLod(node) 740 }; 741 return null; 742} 743function getLod(node) { 744 const lod = get1(node, "Lod"); 745 if (lod) return [ 746 num1(lod, "minLodPixels") ?? -1, 747 num1(lod, "maxLodPixels") ?? -1, 748 num1(lod, "minFadeExtent") ?? null, 749 num1(lod, "maxFadeExtent") ?? null 750 ]; 751 return null; 752} 753function getLatLonAltBox(node) { 754 const latLonAltBox = get1(node, "LatLonAltBox"); 755 if (latLonAltBox) { 756 const north = num1(latLonAltBox, "north"); 757 const west = num1(latLonAltBox, "west"); 758 const east = num1(latLonAltBox, "east"); 759 const south = num1(latLonAltBox, "south"); 760 if (processAltitudeMode(get1(latLonAltBox, "altitudeMode") || get1(latLonAltBox, "gx:altitudeMode"))) console.debug("Encountered an unsupported feature of KML for togeojson: please contact developers for support of altitude mode."); 761 if (typeof north === "number" && typeof south === "number" && typeof west === "number" && typeof east === "number") return { 762 bbox: [ 763 west, 764 south, 765 east, 766 north 767 ], 768 geometry: { 769 type: "Polygon", 770 coordinates: [[ 771 [west, north], 772 [east, north], 773 [east, south], 774 [west, south], 775 [west, north] 776 ]] 777 } 778 }; 779 } 780 return null; 781} 782function getLinkObject(node) { 783 const linkObj = get1(node, "Link");
784 if (linkObj) return getMulti(linkObj, [ 785 "href", 786 "refreshMode", 787 "refreshInterval", 788 "viewRefreshMode", 789 "viewRefreshTime", 790 "viewBoundScale", 791 "viewFormat", 792 "httpQuery" 793 ]); 794 return {}; 795} 796function getNetworkLink(node, styleMap, schema, options) { 797 const box = getNetworkLinkRegion(node); 798 const geometry = box?.coordinateBox?.geometry || null; 799 if (!geometry && options.skipNullGeometry) return null; 800 const feature = { 801 type: "Feature", 802 geometry, 803 properties: Object.assign( 804 /** 805 * Related to 806 * https://gist.github.com/tmcw/037a1cb6660d74a392e9da7446540f46 807 */ 808 { "@geometry-type": "networklink" }, 809 getMulti(node, [ 810 "name", 811 "address", 812 "visibility", 813 "open", 814 "phoneNumber", 815 "styleUrl", 816 "refreshVisibility", 817 "flyToView", 818 "description" 819 ]), 820 getMaybeHTMLDescription(node), 821 extractCascadedStyle(node, styleMap), 822 extractStyle(node), 823 extractIconHref(node), 824 extractExtendedData(node, schema), 825 extractTimeSpan(node), 826 extractTimeStamp(node), 827 getLinkObject(node), 828 box?.lod ? { lod: box.lod } : {} 829 ) 830 }; 831 if (box?.coordinateBox?.bbox) feature.bbox = box.coordinateBox.bbox; 832 if (feature.properties?.visibility !== void 0) feature.properties.visibility = feature.properties.visibility !== "0"; 833 const id = node.getAttribute("id"); 834 if (id !== null && id !== "") feature.id = id; 835 return feature; 836} 837function geometryListToGeometry(geometries) { 838 return geometries.length === 0 ? null : geometries.length === 1 ? geometries[0] : { 839 type: "GeometryCollection", 840 geometries 841 }; 842} 843function getPlacemark(node, styleMap, schema, options) { 844 const { coordTimes, geometries } = getGeometry(node); 845 const geometry = geometryListToGeometry(geometries); 846 if (!geometry && options.skipNullGeometry) return null; 847 const feature = { 848 type: "Feature", 849 geometry, 850 properties: Object.assign(getMulti(node, [ 851 "name", 852 "address", 853 "visibility", 854 "open", 855 "phoneNumber", 856 "description" 857 ]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length ? { coordinateProperties: { times: coordTimes.length === 1 ? coordTimes[0] : coordTimes } } : {}) 858 }; 859 if (feature.properties?.visibility !== void 0) feature.properties.visibility = feature.properties.visibility !== "0"; 860 const id = node.getAttribute("id"); 861 if (id !== null && id !== "") feature.id = id; 862 return feature; 863} 864function getStyleId(style) { 865 let id = style.getAttribute("id"); 866 const parentNode = style.parentNode; 867 if (!id && isElement(parentNode) && parentNode.localName === "CascadingStyle") id = parentNode.getAttribute("kml:id") || parentNode.getAttribute("id"); 868 return normalizeId(id || ""); 869} 870function buildStyleMap(node) { 871 const styleMap = {}; 872 for (const style of $(node, "Style")) styleMap[getStyleId(style)] = extractStyle(style); 873 for (const map of $(node, "StyleMap")) { 874 const id = normalizeId(map.getAttribute("id") || ""); 875 val1(map, "styleUrl", (styleUrl) => { 876 styleUrl = normalizeId(styleUrl); 877 if (styleMap[styleUrl]) styleMap[id] = styleMap[styleUrl]; 878 }); 879 } 880 return styleMap; 881} 882function buildSchema(node) { 883 const schema = {}; 884 for (const field of $(node, "SimpleField")) schema[field.getAttribute("name") || ""] = typeConverters[field.getAttribute("type") || ""] || typeConverters.string; 885 return schema; 886} 887var FOLDER_PROPS = [ 888 "name", 889 "visibility", 890 "open", 891 "address", 892 "description", 893 "phoneNumber", 894 "visibility" 895]; 896function getFolder(node) { 897 const meta = {}; 898 for (const child of Array.from(node.childNodes)) if (isElement(child) && FOLDER_PROPS.includes(child.tagName)) meta[child.tagName] = nodeVal(child); 899 return { 900 type: "folder", 901 meta, 902 children: [] 903 }; 904} 905/** 906* Yield a nested tree with KML folder structure 907* 908* This generates a tree with the given structure: 909* 910* ```js 911* { 912* "type": "root", 913* "children": [ 914* { 915* "type": "folder", 916* "meta": { 917* "name": "Test" 918* }, 919* "children": [ 920* // ...features and folders 921* ] 922* } 923* // ...features 924* ] 925* } 926* ``` 927* 928* ### GroundOverlay 929* 930* GroundOverlay elements are converted into 931* `Feature` objects with `Polygon` geometries, 932* a property like: 933* 934* ```json 935* { 936* "@geometry-type": "groundoverlay" 937* } 938* ``` 939* 940* And the ground overlay's image URL in the `href` 941* property. Ground overlays will need to be displayed 942* with a separate method to other features, depending 943* on which map framework you're using. 944*/ 945function kmlWithFolders(node, options = { skipNullGeometry: false }) { 946 const n = node; 947 const styleMap = buildStyleMap(n); 948 const schema = buildSchema(n); 949 const tree = { 950 type: "root", 951 children: [] 952 }; 953 function traverse(node, pointer, options) { 954 if (isElement(node)) switch (node.tagName) { 955 case "GroundOverlay": { 956 const placemark = getGroundOverlay(node, styleMap, schema, options); 957 if (placemark) pointer.children.push(placemark); 958 break; 959 } 960 case "Placemark": { 961 const placemark = getPlacemark(node, styleMap, schema, options); 962 if (placemark) pointer.children.push(placemark); 963 break; 964 } 965 case "Folder": { 966 const folder = getFolder(node); 967 pointer.children.push(folder); 968 pointer = folder; 969 break; 970 } 971 case "NetworkLink": { 972 const networkLink = getNetworkLink(node, styleMap, schema, options); 973 if (networkLink) pointer.children.push(networkLink); 974 break; 975 } 976 } 977 if (node.childNodes) for (let i = 0; i < node.childNodes.length; i++) traverse(node.childNodes[i], pointer, options); 978 } 979 traverse(n, tree, options); 980 return tree; 981} 982/** 983* Convert KML to GeoJSON incrementally, returning 984* a [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) 985* that yields output feature by feature. 986*/ 987function* kmlGen(node, options = { skipNullGeometry: false }) { 988 const n = node; 989 const styleMap = buildStyleMap(n); 990 const schema = buildSchema(n); 991 for (const placemark of $(n, "Placemark")) { 992 const feature = getPlacemark(placemark, styleMap, schema, options); 993 if (feature) yield feature; 994 } 995 for (const groundOverlay of $(n, "GroundOverlay")) { 996 const feature = getGroundOverlay(groundOverlay, styleMap, schema, options); 997 if (feature) yield feature; 998 } 999 for (const networkLink of $(n, "NetworkLink")) { 1000 const feature = getNetworkLink(networkLink, styleMap, schema, options); 1001 if (feature) yield feature; 1002 } 1003} 1004/** 1005* Convert a KML document to GeoJSON. The first argument, `doc`, must be a KML 1006* document as an XML DOM - not as a string. You can get this using jQuery's default 1007* `.ajax` function or using a bare XMLHttpRequest with the `.response` property 1008* holding an XML DOM. 1009* 1010* The output is a JavaScript object of GeoJSON data. You can convert it to a string 1011* with [JSON.stringify](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) 1012* or use it directly in libraries. 1013*/ 1014function kml(node, options = { skipNullGeometry: false }) { 1015 return { 1016 type: "FeatureCollection", 1017 features: Array.from(kmlGen(node, options)) 1018 }; 1019} 1020//#endregion 1021export { gpx, gpxGen, kml, kmlGen, kmlWithFolders, tcx, tcxGen }; 1022 1023//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQHRtY3dfdG9nZW9qc29uLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL0B0bWN3L3RvZ2VvanNvbi9kaXN0L3RvZ2VvanNvbi5lcy5tanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gJChlbGVtZW50LCB0YWdOYW1lKSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oZWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSh0YWdOYW1lKSk7XG59XG5mdW5jdGlvbiBub3JtYWxpem
1023VJZChpZCkge1xuICAgIHJldHVybiBpZFswXSA9PT0gXCIjXCIgPyBpZCA6IGAjJHtpZH1gO1xufVxuZnVuY3Rpb24gJG5zKGVsZW1lbnQsIHRhZ05hbWUsIG5zKSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oZWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZU5TKG5zLCB0YWdOYW1lKSk7XG59XG4vKipcbiAqIGdldCB0aGUgY29udGVudCBvZiBhIHRleHQgbm9kZSwgaWYgYW55XG4gKi9cbmZ1bmN0aW9uIG5vZGVWYWwobm9kZSkge1xuICAgIG5vZGU/Lm5vcm1hbGl6ZSgpO1xuICAgIHJldHVybiBub2RlPy50ZXh0Q29udGVudCB8fCBcIlwiO1xufVxuLyoqXG4gKiBHZXQgb25lIFkgY2hpbGQgb2YgWCwgaWYgYW55LCBvdGhlcndpc2UgbnVsbFxuICovXG5mdW5jdGlvbiBnZXQxKG5vZGUsIHRhZ05hbWUsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgbiA9IG5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUodGFnTmFtZSk7XG4gICAgY29uc3QgcmVzdWx0ID0gbi5sZW5ndGggPyBuWzBdIDogbnVsbDtcbiAgICBpZiAocmVzdWx0ICYmIGNhbGxiYWNrKVxuICAgICAgICBjYWxsYmFjayhyZXN1bHQpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBnZXQobm9kZSwgdGFnTmFtZSwgY2FsbGJhY2spIHtcbiAgICBjb25zdCBwcm9wZXJ0aWVzID0ge307XG4gICAgaWYgKCFub2RlKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcbiAgICBjb25zdCBuID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZSh0YWdOYW1lKTtcbiAgICBjb25zdCByZXN1bHQgPSBuLmxlbmd0aCA/IG5bMF0gOiBudWxsO1xuICAgIGlmIChyZXN1bHQgJiYgY2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHJlc3VsdCwgcHJvcGVydGllcyk7XG4gICAgfVxuICAgIHJldHVybiBwcm9wZXJ0aWVzO1xufVxuZnVuY3Rpb24gdmFsMShub2RlLCB0YWdOYW1lLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHZhbCA9IG5vZGVWYWwoZ2V0MShub2RlLCB0YWdOYW1lKSk7XG4gICAgaWYgKHZhbCAmJiBjYWxsYmFjaylcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHZhbCkgfHwge307XG4gICAgcmV0dXJuIHt9O1xufVxuZnVuY3Rpb24gJG51bShub2RlLCB0YWdOYW1lLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHZhbCA9IE51bWJlci5wYXJzZUZsb2F0KG5vZGVWYWwoZ2V0MShub2RlLCB0YWdOYW1lKSkpO1xuICAgIGlmIChOdW1iZXIuaXNOYU4odmFsKSlcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAodmFsICYmIGNhbGxiYWNrKVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sodmFsKSB8fCB7fTtcbiAgICByZXR1cm4ge307XG59XG5mdW5jdGlvbiBudW0xKG5vZGUsIHRhZ05hbWUsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdmFsID0gTnVtYmVyLnBhcnNlRmxvYXQobm9kZVZhbChnZXQxKG5vZGUsIHRhZ05hbWUpKSk7XG4gICAgaWYgKE51bWJlci5pc05hTih2YWwpKVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChjYWxsYmFjaylcbiAgICAgICAgY2FsbGJhY2sodmFsKTtcbiAgICByZXR1cm4gdmFsO1xufVxuZnVuY3Rpb24gZ2V0TXVsdGkobm9kZSwgcHJvcGVydHlOYW1lcykge1xuICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IHByb3BlcnR5IG9mIHByb3BlcnR5TmFtZXMpIHtcbiAgICAgICAgdmFsMShub2RlLCBwcm9wZXJ0eSwgKHZhbCkgPT4ge1xuICAgICAgICAgICAgcHJvcGVydGllc1twcm9wZXJ0eV0gPSB2YWw7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcHJvcGVydGllcztcbn1cbmZ1bmN0aW9uIGlzRWxlbWVudChub2RlKSB7XG4gICAgcmV0dXJuIG5vZGU/Lm5vZGVUeXBlID09PSAxO1xufVxuXG5mdW5jdGlvbiBnZXRFeHRlbnNpb25zKG5vZGUpIHtcbiAgICBsZXQgdmFsdWVzID0gW107XG4gICAgaWYgKG5vZGUgPT09IG51bGwpXG4gICAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBBcnJheS5mcm9tKG5vZGUuY2hpbGROb2RlcykpIHtcbiAgICAgICAgaWYgKCFpc0VsZW1lbnQoY2hpbGQpKVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBhYmJyZXZpYXRlTmFtZShjaGlsZC5ub2RlTmFtZSk7XG4gICAgICAgIGlmIChuYW1lID09PSBcImdweHRweDpUcmFja1BvaW50RXh0ZW5zaW9uXCIpIHtcbiAgICAgICAgICAgIC8vIGxvb3AgYWdhaW4gZm9yIG5lc3RlZCBnYXJtaW4gZXh0ZW5zaW9ucyAoZWcuIFwiZ3B4dHB4OmhyXCIpXG4gICAgICAgICAgICB2YWx1ZXMgPSB2YWx1ZXMuY29uY2F0KGdldEV4dGVuc2lvbnMoY2hpbGQpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHB1c2ggY3VzdG9tIGV4dGVuc2lvbiAoZWcuIFwicG93ZXJcIilcbiAgICAgICAgICAgIGNvbnN0IHZhbCA9IG5vZGVWYWwoY2hpbGQpO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goW25hbWUsIHBhcnNlTnVtZXJpYyh2YWwpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcztcbn1cbmZ1bmN0aW9uIGFiYnJldmlhdGVOYW1lKG5hbWUpIHtcbiAgICByZXR1cm4gW1wiaGVhcnRcIiwgXCJncHh0cHg6aHJcIiwgXCJoclwiXS5pbmNsdWRlcyhuYW1lKSA/IFwiaGVhcnRcIiA6IG5hbWU7XG59XG5mdW5jdGlvbiBwYXJzZU51bWVyaWModmFsKSB7XG4gICAgY29uc3QgbnVtID0gTnVtYmVyLnBhcnNlRmxvYXQodmFsKTtcbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKG51bSkgPyB2YWwgOiBudW07XG59XG5cbmZ1bmN0aW9uIGNvb3JkUGFpciQxKG5vZGUpIHtcbiAgICBjb25zdCBsbCA9IFtcbiAgICAgICAgTnVtYmVyLnBhcnNlRmxvYXQobm9kZS5nZXRBdHRyaWJ1dGUoXCJsb25cIikgfHwgXCJcIiksXG4gICAgICAgIE51bWJlci5wYXJzZUZsb2F0KG5vZGUuZ2V0QXR0cmlidXRlKFwibGF0XCIpIHx8IFwiXCIpLFxuICAgIF07XG4gICAgaWYgKE51bWJlci5pc05hTihsbFswXSkgfHwgTnVtYmVyLmlzTmFOKGxsWzFdKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgbnVtMShub2RlLCBcImVsZVwiLCAodmFsKSA9PiB7XG4gICAgICAgIGxsLnB1c2godmFsKTtcbiAgICB9KTtcbiAgICBjb25zdCB0aW1lID0gZ2V0MShub2RlLCBcInRpbWVcIik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29vcmRpbmF0ZXM6IGxsLFxuICAgICAgICB0aW1lOiB0aW1lID8gbm9kZVZhbCh0aW1lKSA6IG51bGwsXG4gICAgICAgIGV4dGVuZGVkVmFsdWVzOiBnZXRFeHRlbnNpb25zKGdldDEobm9kZSwgXCJleHRlbnNpb25zXCIpKSxcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRMaW5lU3R5bGUobm9kZSkge1xuICAgIHJldHVybi
1023BnZXQobm9kZSwgXCJsaW5lXCIsIChsaW5lU3R5bGUpID0+IHtcbiAgICAgICAgY29uc3QgdmFsID0gT2JqZWN0LmFzc2lnbih7fSwgdmFsMShsaW5lU3R5bGUsIFwiY29sb3JcIiwgKGNvbG9yKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4geyBzdHJva2U6IGAjJHtjb2xvcn1gIH07XG4gICAgICAgIH0pLCAkbnVtKGxpbmVTdHlsZSwgXCJvcGFjaXR5XCIsIChvcGFjaXR5KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4geyBcInN0cm9rZS1vcGFjaXR5XCI6IG9wYWNpdHkgfTtcbiAgICAgICAgfSksICRudW0obGluZVN0eWxlLCBcIndpZHRoXCIsICh3aWR0aCkgPT4ge1xuICAgICAgICAgICAgLy8gR1BYIHdpZHRoIGlzIGluIG1tLCBjb252ZXJ0IHRvIHB4IHdpdGggOTYgcHggcGVyIGluY2hcbiAgICAgICAgICAgIHJldHVybiB7IFwic3Ryb2tlLXdpZHRoXCI6ICh3aWR0aCAqIDk2KSAvIDI1LjQgfTtcbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0UHJvcGVydGllcyhucywgbm9kZSkge1xuICAgIGNvbnN0IHByb3BlcnRpZXMgPSBnZXRNdWx0aShub2RlLCBbXG4gICAgICAgIFwibmFtZVwiLFxuICAgICAgICBcImNtdFwiLFxuICAgICAgICBcImRlc2NcIixcbiAgICAgICAgXCJ0eXBlXCIsXG4gICAgICAgIFwidGltZVwiLFxuICAgICAgICBcImtleXdvcmRzXCIsXG4gICAgXSk7XG4gICAgZm9yIChjb25zdCBbbiwgdXJsXSBvZiBucykge1xuICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIEFycmF5LmZyb20obm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZU5TKHVybCwgXCIqXCIpKSkge1xuICAgICAgICAgICAgcHJvcGVydGllc1tjaGlsZC50YWdOYW1lLnJlcGxhY2UoXCI6XCIsIFwiX1wiKV0gPSBub2RlVmFsKGNoaWxkKT8udHJpbSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGxpbmtzID0gJChub2RlLCBcImxpbmtcIik7XG4gICAgaWYgKGxpbmtzLmxlbmd0aCkge1xuICAgICAgICBwcm9wZXJ0aWVzLmxpbmtzID0gbGlua3MubWFwKChsaW5rKSA9PiBPYmplY3QuYXNzaWduKHsgaHJlZjogbGluay5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpIH0sIGdldE11bHRpKGxpbmssIFtcInRleHRcIiwgXCJ0eXBlXCJdKSkpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvcGVydGllcztcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHBvaW50cyBmcm9tIGEgdHJrc2VnIG9yIHJ0ZSBlbGVtZW50LlxuICovXG5mdW5jdGlvbiBnZXRQb2ludHMkMShub2RlLCBwb2ludG5hbWUpIHtcbiAgICBjb25zdCBwdHMgPSAkKG5vZGUsIHBvaW50bmFtZSk7XG4gICAgY29uc3QgbGluZSA9IFtdO1xuICAgIGNvbnN0IHRpbWVzID0gW107XG4gICAgY29uc3QgZXh0ZW5kZWRWYWx1ZXMgPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjID0gY29vcmRQYWlyJDEocHRzW2ldKTtcbiAgICAgICAgaWYgKCFjKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsaW5lLnB1c2goYy5jb29yZGluYXRlcyk7XG4gICAgICAgIGlmIChjLnRpbWUpXG4gICAgICAgICAgICB0aW1lcy5wdXNoKGMudGltZSk7XG4gICAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbF0gb2YgYy5leHRlbmRlZFZhbHVlcykge1xuICAgICAgICAgICAgY29uc3QgcGx1cmFsID0gbmFtZSA9PT0gXCJoZWFydFwiID8gbmFtZSA6IGAke25hbWUucmVwbGFjZShcImdweHRweDpcIiwgXCJcIil9c2A7XG4gICAgICAgICAgICBpZiAoIWV4dGVuZGVkVmFsdWVzW3BsdXJhbF0pIHtcbiAgICAgICAgICAgICAgICBleHRlbmRlZFZhbHVlc1twbHVyYWxdID0gQXJyYXkocHRzLmxlbmd0aCkuZmlsbChudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV4dGVuZGVkVmFsdWVzW3BsdXJhbF1baV0gPSB2YWw7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxpbmUubGVuZ3RoIDwgMilcbiAgICAgICAgcmV0dXJuOyAvLyBJbnZhbGlkIGxpbmUgaW4gR2VvSlNPTlxuICAgIHJldHVybiB7XG4gICAgICAgIGxpbmU6IGxpbmUsXG4gICAgICAgIHRpbWVzOiB0aW1lcyxcbiAgICAgICAgZXh0ZW5kZWRWYWx1ZXM6IGV4dGVuZGVkVmFsdWVzLFxuICAgIH07XG59XG4vKipcbiAqIEV4dHJhY3QgYSBMaW5lU3RyaW5nIGdlb21ldHJ5IGZyb20gYSBydGVcbiAqIGVsZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGdldFJvdXRlKG5zLCBub2RlKSB7XG4gICAgY29uc3QgbGluZSA9IGdldFBvaW50cyQxKG5vZGUsIFwicnRlcHRcIik7XG4gICAgaWYgKCFsaW5lKVxuICAgICAgICByZXR1cm47XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJGZWF0dXJlXCIsXG4gICAgICAgIHByb3BlcnRpZXM6IE9iamVjdC5hc3NpZ24oeyBfZ3B4VHlwZTogXCJydGVcIiB9LCBleHRyYWN0UHJvcGVydGllcyhucywgbm9kZSksIGdldExpbmVTdHlsZShnZXQxKG5vZGUsIFwiZXh0ZW5zaW9uc1wiKSkpLFxuICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgdHlwZTogXCJMaW5lU3RyaW5nXCIsXG4gICAgICAgICAgICBjb29yZGluYXRlczogbGluZS5saW5lLFxuICAgICAgICB9LFxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRUcmFjayhucywgbm9kZSkge1xuICAgIGNvbnN0IHNlZ21lbnRzID0gJChub2RlLCBcInRya3NlZ1wiKTtcbiAgICBjb25zdCB0cmFjayA9IFtdO1xuICAgIGNvbnN0IHRpbWVzID0gW107XG4gICAgY29uc3QgZXh0cmFjdGVkTGluZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpIHtcbiAgICAgICAgY29uc3QgbGluZSA9IGdldFBvaW50cyQxKHNlZ21lbnQsIFwidHJrcHRcIik7XG4gICAgICAgIGlmIChsaW5lKSB7XG4gICAgICAgICAgICBleHRyYWN0ZWRMaW5lcy5wdXNoKGxpbmUpO1xuICAgICAgICAgICAgaWYgKGxpbmUudGltZXM/Lmxlbmd0aClcbiAgICAgICAgICAgICAgICB0aW1lcy5wdXNoKGxpbmUudGltZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChleHRyYWN0
1023ZWRMaW5lcy5sZW5ndGggPT09IDApXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIGNvbnN0IG11bHRpID0gZXh0cmFjdGVkTGluZXMubGVuZ3RoID4gMTtcbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gT2JqZWN0LmFzc2lnbih7IF9ncHhUeXBlOiBcInRya1wiIH0sIGV4dHJhY3RQcm9wZXJ0aWVzKG5zLCBub2RlKSwgZ2V0TGluZVN0eWxlKGdldDEobm9kZSwgXCJleHRlbnNpb25zXCIpKSwgdGltZXMubGVuZ3RoXG4gICAgICAgID8ge1xuICAgICAgICAgICAgY29vcmRpbmF0ZVByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICB0aW1lczogbXVsdGkgPyB0aW1lcyA6IHRpbWVzWzBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgICA6IHt9KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4dHJhY3RlZExpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGxpbmUgPSBleHRyYWN0ZWRMaW5lc1tpXTtcbiAgICAgICAgdHJhY2sucHVzaChsaW5lLmxpbmUpO1xuICAgICAgICBpZiAoIXByb3BlcnRpZXMuY29vcmRpbmF0ZVByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMuY29vcmRpbmF0ZVByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcm9wcyA9IHByb3BlcnRpZXMuY29vcmRpbmF0ZVByb3BlcnRpZXM7XG4gICAgICAgIC8vIEdlbmVyYWxseSBleHRlbmRlZFZhbHVlcyB3aWxsIGJlIHRoaW5ncyBsaWtlIGhlYXJ0XG4gICAgICAgIC8vIHJhdGUsIGFuZCB0aGlzIGlzIGFuIGFycmF5IGxpa2UgeyBoZWFydDogWzEwMCwgMTAxLi4uXSB9XG4gICAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbF0gb2YgT2JqZWN0LmVud
1023HJpZXMobGluZS5leHRlbmRlZFZhbHVlcykpIHtcbiAgICAgICAgICAgIGlmIChtdWx0aSkge1xuICAgICAgICAgICAgICAgIGlmICghcHJvcHNbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHNbbmFtZV0gPSBleHRyYWN0ZWRMaW5lcy5tYXAoKGxpbmUpID0+IG5ldyBBcnJheShsaW5lLmxpbmUubGVuZ3RoKS5maWxsKG51bGwpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvcHNbbmFtZV1baV0gPSB2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcm9wc1tuYW1lXSA9IHZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVcIixcbiAgICAgICAgcHJvcGVydGllczogcHJvcGVydGllcyxcbiAgICAgICAgZ2VvbWV0cnk6IG11bHRpXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcIk11bHRpTGluZVN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiB0cmFjayxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiTGluZVN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiB0cmFja1swXSxcbiAgICAgICAgICAgIH0sXG4gICAgfTtcbn1cbi8qKlxuICogRXh0cmFjdCBhIHBvaW50LCBpZiBwb3NzaWJsZSwgZnJvbSBhIGdpdmVuIG5vZGUsXG4gKiB3aGljaCBpcyB1c3VhbGx5IGEgd3B0IG9yIHRya3B0XG4gKi9cbmZ1bmN0aW9uIGdldFBvaW50KG5zLCBub2RlKSB7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IE9iamVjdC5hc3NpZ24oZXh0cmFjdFByb3BlcnRpZXMobnMsIG5vZGUpLCBnZXRNdWx0aShub2RlLCBbXCJzeW1cIl0pKTtcbiAgICBjb25zdCBwYWlyID0gY29vcmRQYWlyJDEobm9kZSk7XG4gICAgaWYgKCFwYWlyKVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVcIixcbiAgICAgICAgcHJvcGVydGllcyxcbiAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAgIHR5cGU6IFwiUG9pbnRcIixcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBwYWlyLmNvb3JkaW5hdGVzLFxuICAgICAgICB9LFxuICAgIH07XG59XG4vKipcbiAqIENvbnZlcnQgR1BYIHRvIEdlb0pTT04gaW5jcmVtZW50YWxseSwgcmV0dXJuaW5nXG4gKiBhIFtHZW5lcmF0b3JdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvSXRlcmF0b3JzX2FuZF9HZW5lcmF0b3JzKVxuICogdGhhdCB5aWVsZHMgb3V0cHV0IGZlYXR1cmUgYnkgZmVhdHVyZS5cbiAqL1xuZnVuY3Rpb24qIGdweEdlbihub2RlKSB7XG4gICAgY29uc3QgbiA9IG5vZGU7XG4gICAgY29uc3QgR1BYWCA9IFwiZ3B4eFwiO1xuICAgIGNvbnN0IEdQWFhfVVJJID0gXCJodHRwOi8vd3d3Lmdhcm1pbi5jb20veG1sc2NoZW1hcy9HcHhFeHRlbnNpb25zL3YzXCI7XG4gICAgLy8gTmFtZXNwYWNlc1xuICAgIGNvbnN0IG5zID0gW1tHUFhYLCBHUFhYX1VSSV1dO1xuICAgIGNvbnN0IGF0dHJzID0gbi5nZXRFbGVtZW50c0J5VGFnTmFtZShcImdweFwiKVswXT8uYXR0cmlidXRlcztcbiAgICBpZiAoYXR0cnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBhdHRyIG9mIEFycmF5LmZyb20oYXR0cnMpKSB7XG4gICAgICAgICAgICBpZiAoYXR0ci5uYW1lPy5zdGFydHNXaXRoKFwieG1sbnM6XCIpICYmIGF0dHIudmFsdWUgIT09IEdQWFhfVVJJKSB7XG4gICAgICAgICAgICAgICAgbnMucHVzaChbYXR0ci5uYW1lLCBhdHRyLnZhbHVlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCB0cmFjayBvZiAkKG4sIFwidHJrXCIpKSB7XG4gICAgICAgIGNvbnN0IGZlYXR1cmUgPSBnZXRUcmFjayhucywgdHJhY2spO1xuICAgICAgICBpZiAoZmVhdHVyZSlcbiAgICAgICAgICAgIHlpZWxkIGZlYXR1cmU7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgcm91dGUgb2YgJChuLCBcInJ0ZVwiKSkge1xuICAgICAgICBjb25zdCBmZWF0dXJlID0gZ2V0Um91dGUobnMsIHJvdXRlKTtcbiAgICAgICAgaWYgKGZlYXR1cmUpXG4gICAgICAgICAgICB5aWVsZCBmZWF0dXJlO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IHdheXBvaW50IG9mICQobiwgXCJ3cHRcIikpIHtcbiAgICAgICAgY29uc3QgcG9pbnQgPSBnZXRQb2ludChucywgd2F5cG9pbnQpO1xuICAgICAgICBpZiAocG9pbnQpXG4gICAgICAgICAgICB5aWVsZCBwb2ludDtcbiAgICB9XG59XG4vKipcbiAqXG4gKiBDb252ZXJ0IGEgR1BYIGRvY3VtZW50IHRvIEdlb0pTT04uIFRoZSBmaXJzdCBhcmd1bWVudCwgYGRvY2AsIG11c3QgYmUgYSBHUFhcbiAqIGRvY3VtZW50IGFzIGFuIFhNTCBET00gLSBub3QgYXMgYSBzdHJpbmcuIFlvdSBjYW4gZ2V0IHRoaXMgdXNpbmcgalF1ZXJ5J3MgZGVmYXVsdFxuICogYC5hamF4YCBmdW5jdGlvbiBvciB1c2luZyBhIGJhcmUgWE1MSHR0cFJlcXVlc3Qgd2l0aCB0aGUgYC5yZXNwb25zZWAgcHJvcGVydHlcbiAqIGhvbGRpbmcgYW4gWE1MIERPTS5cbiAqXG4gKiBUaGUgb3V0cHV0IGlzIGEgSmF2YVNjcmlwdCBvYmplY3Qgb2YgR2VvSlNPTiBkYXRhLCBzYW1lIGFzIGAua21sYCBvdXRwdXRzLCB3aXRoIHRoZVxuICogYWRkaXRpb24gb2YgYSBgX2dweFR5cGVgIHByb3BlcnR5IG9uIGVhY2ggYExpbmVTdHJpbmdgIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgd2hldGhlclxuICogdGhlIGZlYXR1cmUgd2FzIGVuY29kZWQgYXMgYSByb3V0ZSAoYHJ0ZWApIG9yIHRyYWNrIChgdHJrYCkgaW4gdGhlIEdQWCBkb2N1bWVudC5cbiAqL1xuZnVuY3Rpb24gZ3B4KG5vZGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXG4gICAgICAgIGZlYXR1cmVzOiBBcnJheS5mcm9tKGdweEdlbihub2RlKSksXG4gICAgfTtcbn1cblxuY29uc3QgRVhURU5TSU9OU19OUyA9IFwiaHR0cDovL3d3dy5nYXJtaW4uY29tL3htbHNjaGVtYXMvQWN0aXZpdHlFeHRlbnNpb24vdjJcIjtcbmNvbnN0IFRSQUNLUE9JTlRfQVRUUklCVVRFUyA9IFtcbiAgICBbXCJoZWFydFJhdGVcIiwgXCJo
1023ZWFydFJhdGVzXCJdLFxuICAgIFtcIkNhZGVuY2VcIiwgXCJjYWRlbmNlc1wiXSxcbiAgICAvLyBFeHRlbmRlZCBUcmFja3BvaW50IGF0dHJpYnV0ZXNcbiAgICBbXCJTcGVlZFwiLCBcInNwZWVkc1wiXSxcbiAgICBbXCJXYXR0c1wiLCBcIndhdHRzXCJdLFxuXTtcbmNvbnN0IExBUF9BVFRSSUJVVEVTID0gW1xuICAgIFtcIlRvdGFsVGltZVNlY29uZHNcIiwgXCJ0b3RhbFRpbWVTZWNvbmRzXCJdLFxuICAgIFtcIkRpc3RhbmNlTWV0ZXJzXCIsIFwiZGlzdGFuY2VNZXRlcnNcIl0sXG4gICAgW1wiTWF4aW11bVNwZWVkXCIsIFwibWF4U3BlZWRcIl0sXG4gICAgW1wiQXZlcmFnZUhlYXJ0UmF0ZUJwbVwiLCBcImF2Z0hlYXJ0UmF0ZVwiXSxcbiAgICBbXCJNYXhpbXVtSGVhcnRSYXRlQnBtXCIsIFwibWF4SGVhcnRSYXRlXCJdLFxuICAgIC8vIEV4dGVuZGVkIExhcCBhdHRyaWJ1dGVzXG4gICAgW1wiQXZnU3BlZWRcIiwgXCJhdmdTcGVlZFwiXSxcbiAgICBbXCJBdmdXYXR0c1wiLCBcImF2Z1dhdHRzXCJdLFxuICAgIFtcIk1heFdhdHRzXCIsIFwibWF4V2F0dHNcIl0sXG5dO1xuZnVuY3Rpb24gZ2V0UHJvcGVydGllcyhub2RlLCBhdHRyaWJ1dGVOYW1lcykge1xuICAgIGNvbnN0IHByb3BlcnRpZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IFt0YWcsIGFsaWFzXSBvZiBhdHRyaWJ1dGVOYW1lcykge1xuICAgICAgICBsZXQgZWxlbSA9IGdldDEobm9kZSwgdGFnKTtcbiAgICAgICAgaWYgKCFlbGVtKSB7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50cyA9IG5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWVOUyhFWFRFTlNJT05TX05TLCB0YWcpO1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGVsZW0gPSBlbGVtZW50c1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWwgPSBOdW1iZXIucGFyc2VGbG9hdChub2RlVmFsKGVsZW0pKTtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNOYU4odmFsKSkge1xuICAgICAgICAgICAgcHJvcGVydGllcy5wdXNoKFthbGlhcywgdmFsXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByb3BlcnRpZXM7XG59XG5mdW5jdGlvbiBjb29yZFBhaXIobm9kZSkge1xuICAgIGNvbnN0IGxsID0gW251bTEobm9kZSwgXCJMb25naXR1ZGVEZWdyZWVzXCIpLCBudW0xKG5vZGUsIFwiTGF0aXR1ZGVEZWdyZWVzXCIpXTtcbiAgICBpZiAobGxbMF0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBOdW1iZXIuaXNOYU4obGxbMF0pIHx8XG4gICAgICAgIGxsWzFdID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgTnVtYmVyLmlzTmFOKGxsWzFdKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgaGVhcnRSYXRlID0gZ2V0MShub2RlLCBcIkhlYXJ0UmF0ZUJwbVwiKTtcbiAgICBjb25zdCB0aW1lID0gbm9kZVZhbChnZXQxKG5vZGUsIFwiVGltZVwiKSk7XG4gICAgZ2V0MShub2RlLCBcIkFsdGl0dWRlTWV0ZXJzXCIsIChhbHQpID0+IHtcbiAgICAgICAgY29uc3QgYSA9IE51bWJlci5wYXJzZUZsb2F0KG5vZGVWYWwoYWx0KSk7XG4gICAgICAgIGlmICghTnVtYmVyLmlzTmFOKGEpKSB7XG4gICAgICAgICAgICBsbC5wdXNoKGEpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29vcmRpbmF0ZXM6IGxsLFxuICAgICAgICB0aW1lOiB0aW1lIHx8IG51bGwsXG4gICAgICAgIGhlYXJ0UmF0ZTogaGVhcnRSYXRlID8gTnVtYmVyLnBhcnNlRmxvYXQobm9kZVZhbChoZWFydFJhdGUpKSA6IG51bGwsXG4gICAgICAgIGV4dGVuc2lvbnM6IGdldFByb3BlcnRpZXMobm9kZSwgVFJBQ0tQT0lOVF9BVFRSSUJVVEVTKSxcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0UG9pbnRzKG5vZGUpIHtcbiAgICBjb25zdCBwdHMgPSAkKG5vZGUsIFwiVHJhY2twb2ludFwiKTtcbiAgICBjb25zdCBsaW5lID0gW107XG4gICAgY29uc3QgdGltZXMgPSBbXTtcbiAgICBjb25zdCBoZWFydFJhdGVzID0gW107XG4gICAgaWYgKHB0cy5sZW5ndGggPCAyKVxuICAgICAgICByZXR1cm4gbnVsbDsgLy8gSW52YWxpZCBsaW5lIGluIEdlb0pTT05cbiAgICBjb25zdCBleHRlbmRlZFByb3BlcnRpZXMgPSB7fTtcbiAgICBjb25zdCByZXN1bHQgPSB7IGV4dGVuZGVkUHJvcGVydGllcyB9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGMgPSBjb29yZFBhaXIocHRzW2ldKTtcbiAgICAgICAgaWYgKGMgPT09IG51bGwpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgbGluZS5wdXNoKGMuY29vcmRpbmF0ZXMpO1xuICAgICAgICBjb25zdCB7IHRpbWUsIGhlYXJ0UmF0ZSwgZXh0ZW5zaW9ucyB9ID0gYztcbiAgICAgICAgaWYgKHRpbWUpXG4gICAgICAgICAgICB0aW1lcy5wdXNoKHRpbWUpO1xuICAgICAgICBpZiAoaGVhcnRSYXRlKVxuICAgICAgICAgICAgaGVhcnRSYXRlcy5wdXNoKGhlYXJ0UmF0ZSk7XG4gICAgICAgIGZvciAoY29uc3QgW2FsaWFzLCB2YWx1ZV0gb2YgZXh0ZW5zaW9ucykge1xuICAgICAgICAgICAgaWYgKCFleHRlbmRlZFByb3BlcnRpZXNbYWxpYXNdKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5kZWRQcm9wZXJ0aWVzW2FsaWFzXSA9IEFycmF5KHB0cy5sZW5ndGgpLmZpbGwobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBleHRlbmRlZFByb3BlcnRpZXNbYWxpYXNdW2ldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxpbmUubGVuZ3RoIDwgMilcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB7XG4gICAgICAgIGxpbmU6IGxpbmUsXG4gICAgICAgIHRpbWVzOiB0aW1lcyxcbiAgICAgICAgaGVhcnRSYXRlczogaGVhcnRSYXRlcyxcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGdldExhcChub2RlKSB7XG4gICAgY29uc3Qgc2VnbWVudHMgPSAkKG5vZGUsIFwiVHJhY2tcIik7XG4gICAgY29uc3QgdHJhY2sgPSBbXTtcbiAgICBjb25zdCB0aW1lcyA9IFtdO1xuICAgIGNvbnN0IGhlYXJ0UmF0ZXMgPSBbXTtcbiAgICBjb25zdCBhbGxFeHRlbmRlZFByb3BlcnRpZXMgPSBbXTtcbiAgICBsZXQgbGluZTtcbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuZnJvbUVudHJpZXMoZ2V0UHJvcGVydGllcyhub2RlLCBMQVBfQVRUUklCVVRFUykpLCBnZXQobm9kZSwgXCJOYW1lXCIsIChuYW1lRWxlbWVudCkgPT4ge1xuICAgICAgICByZXR1cm4geyBuYW1lOiBub2RlVmFsKG5hbWVFbGVtZW50KSB9O1xuICAgIH0pKTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpIHtcbiAgICAgICAgbGluZSA9IGdldFBvaW50cyhzZWdtZW50KTtcbiAgICAgICAgaWYgKGxpbmUpIHtcbiAgICAgICAgICAgI
1023HRyYWNrLnB1c2gobGluZS5saW5lKTtcbiAgICAgICAgICAgIGlmIChsaW5lLnRpbWVzLmxlbmd0aClcbiAgICAgICAgICAgICAgICB0aW1lcy5wdXNoKGxpbmUudGltZXMpO1xuICAgICAgICAgICAgaWYgKGxpbmUuaGVhcnRSYXRlcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgaGVhcnRSYXRlcy5wdXNoKGxpbmUuaGVhcnRSYXRlcyk7XG4gICAgICAgICAgICBhbGxFeHRlbmRlZFByb3BlcnRpZXMucHVzaChsaW5lLmV4dGVuZGVkUHJvcGVydGllcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGxFeHRlbmRlZFByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgZXh0ZW5kZWRQcm9wZXJ0aWVzID0gYWxsRXh0ZW5kZWRQcm9wZXJ0aWVzW2ldO1xuICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIGV4dGVuZGVkUHJvcGVydGllcykge1xuICAgICAgICAgICAgaWYgKHNlZ21lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChsaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXNbcHJvcGVydHldID0gbGluZS5leHRlbmRlZFByb3BlcnRpZXNbcHJvcGVydHldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghcHJvcGVydGllc1twcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllc1twcm9wZXJ0eV0gPSB0cmFjay5tYXAoKHRyYWNrKSA9PiBBcnJheSh0cmFjay5sZW5ndGgpLmZpbGwobnVsbCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzW3Byb3BlcnR5XVtpXSA9IGV4dGVuZGVkUHJvcGVydGllc1twcm9wZXJ0eV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRyYWNrLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgaWYgKHRpbWVzLmxlbmd0aCB8fCBoZWFydFJhdGVzLmxlbmd0aCkge1xuICAgICAgICBwcm9wZXJ0aWVzLmNvb3JkaW5hdGVQcm9wZXJ0aWVzID0gT2JqZWN0LmFzc2lnbih0aW1lcy5sZW5ndGhcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIHRpbWVzOiB0cmFjay5sZW5ndGggPT09IDEgPyB0aW1lc1swXSA6IHRpbWVzLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSwgaGVhcnRSYXRlcy5sZW5ndGhcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIGhlYXJ0OiB0cmFjay5sZW5ndGggPT09IDEgPyBoZWFydFJhdGVzWzBdIDogaGVhcnRSYXRlcyxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge30pO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVcIixcbiAgICAgICAgcHJvcGVydGllczogcHJvcGVydGllcyxcbiAgICAgICAgZ2VvbWV0cnk6IHRyYWNrLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJMaW5lU3RyaW5nXCIsXG4gICAgICAgICAgICAgICAgY29vcmRpbmF0ZXM6IHRyYWNrWzBdLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJNdWx0aUxpbmVTdHJpbmdcIixcbiAgICAgICAgICAgICAgICBjb29yZGluYXRlczogdHJhY2ssXG4gICAgICAgICAgICB9LFxuICAgIH07XG59XG4vKipcbiAqIEluY3JlbWVudGFsbHkgY29udmVydCBhIFRDWCBkb2N1bWVudCB0byBHZW9KU09OLiBUaGVcbiAqIGZpcnN0IGFyZ3VtZW50LCBgZG9jYCwgbXVzdCBiZSBhIFRDWFxuICogZG9jdW1lbnQgYXMgYW4gWE1MIERPTSAtIG5vdCBhcyBhIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24qIHRjeEdlbihub2RlKSB7XG4gICAgZm9yIChjb25zdCBsYXAgb2YgJChub2RlLCBcIkxhcFwiKSkge1xuICAgICAgICBjb25zdCBmZWF0dXJlID0gZ2V0TGFwKGxhcCk7XG4gICAgICAgIGlmIChmZWF0dXJlKVxuICAgICAgICAgICAgeWllbGQgZmVhdHVyZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBjb3Vyc2Ugb2YgJChub2RlLCBcIkNvdXJzZXNcIikpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IGdldExhcChjb3Vyc2UpO1xuICAgICAgICBpZiAoZmVhdHVyZSlcbiAgICAgICAgICAgIHlpZWxkIGZlYXR1cmU7XG4gICAgfVxufVxuLyoqXG4gKiBDb252ZXJ0IGEgVENYIGRvY3VtZW50IHRvIEdlb0pTT04uIFRoZSBmaXJzdCBhcmd1bWVudCwgYGRvY2AsIG11c3QgYmUgYSBUQ1hcbiAqIGRvY3VtZW50IGFzIGFuIFhNTCBET00gLSBub3QgYXMgYSBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIHRjeChub2RlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICAgICAgICBmZWF0dXJlczogQXJyYXkuZnJvbSh0Y3hHZW4obm9kZSkpLFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGZpeENvbG9yKHYsIHByZWZpeCkge1xuICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7fTtcbiAgICBjb25zdCBjb2xvclByb3AgPSBwcmVmaXggPT09IFwic3Ryb2tlXCIgfHwgcHJlZml4ID09PSBcImZpbGxcIiA/IHByZWZpeCA6IGAke3ByZWZpeH0tY29sb3JgO1xuICAgIGlmICh2WzBdID09PSBcIiNcIikge1xuICAgICAgICB2ID0gdi5zdWJzdHJpbmcoMSk7XG4gICAgfVxuICAgIGlmICh2Lmxlbmd0aCA9PT0gNiB8fCB2Lmxlbmd0aCA9PT0gMykge1xuICAgICAgICBwcm9wZXJ0aWVzW2NvbG9yUHJvcF0gPSBgIyR7dn1gO1xuICAgIH1cbiAgICBlbHNlIGlmICh2Lmxlbmd0aCA9PT0gOCkge1xuICAgICAgICBwcm9wZXJ0aWVzW2Ake3ByZWZpeH0tb3BhY2l0eWBdID1cbiAgICAgICAgICAgIE51bWJlci5wYXJzZUludCh2LnN1YnN0cmluZygwLCAyKSwgMTYpIC8gMjU1O1xuICAgICAgICBwcm9wZXJ0aWVzW2NvbG9yUHJvcF0gPVxuICAgICAgICAgICAgYCMke3Yuc3Vic3RyaW5nKDYsIDgpfSR7di5zdWJzdHJpbmcoNCwgNil9JHt2LnN1YnN0cmluZygyLCA0KX1gO1xuICAgIH1cbiAgICByZXR1cm4gcHJvcGVydGllcztcbn1cblxuZnVuY3Rpb24gbnVtZXJpY1Byb3BlcnR5KG5vZGUsIHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IHt9O1xuICAgIG51bTEobm9kZSwgc291cmNlLCAodmFsKSA9PiB7XG4gICAgICAgI
1023HByb3BlcnRpZXNbdGFyZ2V0XSA9IHZhbDtcbiAgICB9KTtcbiAgICByZXR1cm4gcHJvcGVydGllcztcbn1cbmZ1bmN0aW9uIGdldENvbG9yKG5vZGUsIG91dHB1dCkge1xuICAgIHJldHVybiBnZXQobm9kZSwgXCJjb2xvclwiLCAoZWxlbSkgPT4gZml4Q29sb3Iobm9kZVZhbChlbGVtKSwgb3V0cHV0KSk7XG59XG5mdW5jdGlvbiBleHRyYWN0SWNvbkhyZWYobm9kZSkge1xuICAgIHJldHVybiBnZXQobm9kZSwgXCJJY29uXCIsIChpY29uLCBwcm9wZXJ0aWVzKSA9PiB7XG4gICAgICAgIHZhbDEoaWNvbiwgXCJocmVmXCIsIChocmVmKSA9PiB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLmljb24gPSBocmVmO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHByb3BlcnRpZXM7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBleHRyYWN0SWNvbihub2RlKSB7XG4gICAgcmV0dXJuIGdldChub2RlLCBcIkljb25TdHlsZVwiLCAoaWNvblN0eWxlKSA9PiB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGdldENvbG9yKGljb25TdHlsZSwgXCJpY29uXCIpLCBudW1lcmljUHJvcGVydHkoaWNvblN0eWxlLCBcInNjYWxlXCIsIFwiaWNvbi1zY2FsZVwiKSwgbnVtZXJpY1Byb3BlcnR5KGljb25TdHlsZSwgXCJoZWFkaW5nXCIsIFwiaWNvbi1oZWFkaW5nXCIpLCBnZXQoaWNvblN0eWxlLCBcImhvdFNwb3RcIiwgKGhvdHNwb3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxlZnQgPSBOdW1iZXIucGFyc2VGbG9hdChob3RzcG90LmdldEF0dHJpYnV0ZShcInhcIikgfHwgXCJcIik7XG4gICAgICAgICAgICBjb25zdCB0b3AgPSBOdW1iZXIucGFyc2VGbG9hdChob3RzcG90LmdldEF0dHJpYnV0ZShcInlcIikgfHwgXCJcIik7XG4gICAgICAgICAgICBjb25zdCB4dW5pdHMgPSBob3RzcG90LmdldEF0dHJpYnV0ZShcInh1bml0c1wiKSB8fCBcIlwiO1xuICAgICAgICAgICAgY29uc3QgeXVuaXRzID0gaG90c3BvdC5nZXRBdHRyaWJ1dGUoXCJ5dW5pdHNcIikgfHwgXCJcIjtcbiAgICAgICAgICAgIGlmICghTnVtYmVyLmlzTmFOKGxlZnQpICYmICFOdW1iZXIuaXNOYU4odG9wKSlcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBcImljb24tb2Zmc2V0XCI6IFtsZWZ0LCB0b3BdLFxuICAgICAgICAgICAgICAgICAgICBcImljb24tb2Zmc2V0LXVuaXRzXCI6IFt4dW5pdHMsIHl1bml0c10sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfSksIGV4dHJhY3RJY29uSHJlZihpY29uU3R5bGUpKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGV4dHJhY3RMYWJlbChub2RlKSB7XG4gICAgcmV0dXJuIGdldChub2RlLCBcIkxhYmVsU3R5bGVcIiwgKGxhYmVsU3R5bGUpID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oZ2V0Q29sb3IobGFiZWxTdHlsZSwgXCJsYWJlbFwiKSwgbnVtZXJpY1Byb3BlcnR5KGxhYmVsU3R5bGUsIFwic2NhbGVcIiwgXCJsYWJlbC1zY2FsZVwiKSk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBleHRyYWN0TGluZShub2RlKSB7XG4gICAgcmV0dXJuIGdldChub2RlLCBcIkxpbmVTdHlsZVwiLCAobGluZVN0eWxlKSA9PiB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGdldENvbG9yKGxpbmVTdHlsZSwgXCJzdHJva2VcIiksIG51bWVyaWNQcm9wZXJ0eShsaW5lU3R5bGUsIFwid2lkdGhcIiwgXCJzdHJva2Utd2lkdGhcIikpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZXh0cmFjdFBvbHkobm9kZSkge1xuICAgIHJldHVybiBnZXQobm9kZSwgXCJQb2x5U3R5bGVcIiwgKHBvbHlTdHlsZSwgcHJvcGVydGllcykgPT4ge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihwcm9wZXJ0aWVzLCBnZXQocG9seVN0eWxlLCBcImNvbG9yXCIsIChlbGVtKSA9PiBmaXhDb2xvcihub2RlVmFsKGVsZW0pLCBcImZpbGxcIikpLCB2YWwxKHBvbHlTdHlsZSwgXCJmaWxsXCIsIChmaWxsKSA9PiB7XG4gICAgICAgICAgICBpZiAoZmlsbCA9PT0gXCIwXCIpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgXCJmaWxsLW9wYWNpdHlcIjogMCB9O1xuICAgICAgICB9KSwgdmFsMShwb2x5U3R5bGUsIFwib3V0bGluZVwiLCAob3V0bGluZSkgPT4ge1xuICAgICAgICAgICAgaWYgKG91dGxpbmUgPT09IFwiMFwiKVxuICAgICAgICAgICAgICAgIHJldHVybiB7IFwic3Ryb2tlLW9wYWNpdHlcIjogMCB9O1xuICAgICAgICB9KSk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBleHRyYWN0U3R5bGUobm9kZSkge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBleHRyYWN0UG9seShub2RlKSwgZXh0cmFjdExpbmUobm9kZSksIGV4dHJhY3RMYWJlbChub2RlKSwgZXh0cmFjdEljb24obm9kZSkpO1xufVxuXG5jb25zdCByZW1vdmVTcGFjZSA9IC9cXHMqL2c7XG5jb25zdCB0cmltU3BhY2UgPSAvXlxccyp8XFxzKiQvZztcbmNvbnN0IHNwbGl0U3BhY2UgPSAvXFxzKy87XG4vKipcbiAqIEdldCBvbmUgY29vcmRpbmF0ZSBmcm9tIGEgY29vcmRpbmF0ZSBhcnJheSwgaWYgYW55XG4gKi9cbmZ1bmN0aW9uIGNvb3JkMSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZVxuICAgICAgICAucmVwbGFjZShyZW1vdmVTcGFjZSwgXCJcIilcbiAgICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgICAubWFwKE51bWJlci5wYXJzZUZsb2F0KVxuICAgICAgICAuZmlsdGVyKChudW0pID0+ICFOdW1iZXIuaXNOYU4obnVtKSlcbiAgICAgICAgLnNsaWNlKDAsIDMpO1xufVxuLyoqXG4gKiBHZXQgYWxsIGNvb3JkaW5hdGVzIGZyb20gYSBjb29yZGluYXRlIGFycmF5IGFzIFtbXSxbXV1cbiAqL1xuZnVuY3Rpb24gY29vcmQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgLnJlcGxhY2UodHJpbVNwYWNlLCBcIlwiKVxuICAgICAgICAuc3BsaXQoc3BsaXRTcGFjZSlcbiAgICAgICAgLm1hcChjb29yZDEpXG4gICAgICAgIC5maWx0ZXIoKGNvb3JkKSA9PiB7XG4gICAgICAgIHJldHVybiBjb29yZC5sZW5ndGggPj0gMjtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGd4Q29vcmRzKG5vZGUpIHtcbiAgICBsZXQgZWxlbXMgPSAkKG5vZGUsIFwiY29vcmRcIik7XG4gICAgaWYgKGVsZW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBlbGVtcyA9ICRucyhub2RlLCBcImNvb3JkXCIsIFwiKlwiKTtcbiAgICB9XG4gICAgY29uc3QgY29vcmRpbmF0ZXMgPSBlbGVtcy5tYXAoKGVsZW0pID0+IHtcbiAgICAgICAgcmV0dXJuIG5vZGVWYWwoZWxlbSkuc3BsaXQoXCIgXCIpLm1hcChOdW1iZXIucGFyc2VGbG9hdCk7XG4gICAgfSk7XG4gICAgaWYgKGNvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2VvbWV0cnk6IGNvb3JkaW5hdGVzLmxlbmd0aCA+IDJcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgI
1023HR5cGU6IFwiTGluZVN0cmluZ1wiLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJQb2ludFwiLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZGluYXRlc1swXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIHRpbWVzOiAkKG5vZGUsIFwid2hlblwiKS5tYXAoKGVsZW0pID0+IG5vZGVWYWwoZWxlbSkpLFxuICAgIH07XG59XG5mdW5jdGlvbiBmaXhSaW5nKHJpbmcpIHtcbiAgICBpZiAocmluZy5sZW5ndGggPT09IDApXG4gICAgICAgIHJldHVybiByaW5nO1xuICAgIGNvbnN0IGZpcnN0ID0gcmluZ1swXTtcbiAgICBjb25zdCBsYXN0ID0gcmluZ1tyaW5nLmxlbmd0aCAtIDFdO1xuICAgIGxldCBlcXVhbCA9IHRydWU7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBNYXRoLm1heChmaXJzdC5sZW5ndGgsIGxhc3QubGVuZ3RoKTsgaSsrKSB7XG4gICAgICAgIGlmIChmaXJzdFtpXSAhPT0gbGFzdFtpXSkge1xuICAgICAgICAgICAgZXF1YWwgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghZXF1YWwpIHtcbiAgICAgICAgcmV0dXJuIHJpbmcuY29uY2F0KFtyaW5nWzBdXSk7XG4gICAgfVxuICAgIHJldHVybiByaW5nO1xufVxuZnVuY3Rpb24gZ2V0Q29vcmRpbmF0ZXMobm9kZSkge1xuICAgIHJldHVybiBub2RlVmFsKGdldDEobm9kZSwgXCJjb29yZGluYXRlc1wiKSk7XG59XG5mdW5jdGlvbiBnZXRHZW9tZXRyeShub2RlKSB7XG4gICAgbGV0IGdlb21ldHJpZXMgPSBbXTtcbiAgICBsZXQgY29vcmRUaW1lcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gbm9kZS5jaGlsZE5vZGVzLml0ZW0oaSk7XG4gICAgICAgIGlmIChpc0VsZW1lbnQoY2hpbGQpKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGNoaWxkLnRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFwiTXVsdGlHZW9tZXRyeVwiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJNdWx0aVRyYWNrXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcImd4Ok11bHRpVHJhY2tcIjoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGlsZEdlb21ldHJpZXMgPSBnZXRHZW9tZXRyeShjaGlsZCk7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJpZXMgPSBnZW9tZXRyaWVzLmNvbmNhdChjaGlsZEdlb21ldHJpZXMuZ2VvbWV0cmllcyk7XG4gICAgICAgICAgICAgICAgICAgIGNvb3JkVGltZXMgPSBjb29yZFRpbWVzLmNvbmNhdChjaGlsZEdlb21ldHJpZXMuY29vcmRUaW1lcyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlIFwiUG9pbnRcIjoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb29yZGluYXRlcyA9IGNvb3JkMShnZXRDb29yZGluYXRlcyhjaGlsZCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29vcmRpbmF0ZXMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdlb21ldHJpZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJQb2ludFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgXCJMaW5lYXJSaW5nXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIkxpbmVTdHJpbmdcIjoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb29yZGluYXRlcyA9IGNvb3JkKGdldENvb3JkaW5hdGVzKGNoaWxkKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb29yZGluYXRlcy5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZGluYXRlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlIFwiUG9seWdvblwiOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvb3JkcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpbmVhclJpbmcgb2YgJChjaGlsZCwgXCJMaW5lYXJSaW5nXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByaW5nID0gZml4UmluZyhjb29yZChnZXRDb29yZGluYXRlcyhsaW5lYXJSaW5nKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpbmcubGVuZ3RoID49IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZHMucHVzaChyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY29vcmRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIlBvbHlnb25cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZGluYXRlczogY29vcmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgXCJUcmFja1wiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJneDpUcmFja1wiOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGd4ID0gZ3hDb29yZHMoY2hpbGQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWd4KVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgdGltZXMsIGdlb21ldHJ5IH0gPSBneDtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGdlb21ldHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRpbWVzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkVGltZXMucHVzaCh0aW1lcyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgI
1023H1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBnZW9tZXRyaWVzLFxuICAgICAgICBjb29yZFRpbWVzLFxuICAgIH07XG59XG5cbmNvbnN0IHRvTnVtYmVyID0gKHgpID0+IE51bWJlcih4KTtcbmNvbnN0IHR5cGVDb252ZXJ0ZXJzID0ge1xuICAgIHN0cmluZzogKHgpID0+IHgsXG4gICAgaW50OiB0b051bWJlcixcbiAgICB1aW50OiB0b051bWJlcixcbiAgICBzaG9ydDogdG9OdW1iZXIsXG4gICAgdXNob3J0OiB0b051bWJlcixcbiAgICBmbG9hdDogdG9OdW1iZXIsXG4gICAgZG91YmxlOiB0b051bWJlcixcbiAgICBib29sOiAoeCkgPT4gQm9vbGVhbih4KSxcbn07XG5mdW5jdGlvbiBleHRyYWN0RXh0ZW5kZWREYXRhKG5vZGUsIHNjaGVtYSkge1xuICAgIHJldHVybiBnZXQobm9kZSwgXCJFeHRlbmRlZERhdGFcIiwgKGV4dGVuZGVkRGF0YSwgcHJvcGVydGllcykgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgJChleHRlbmRlZERhdGEsIFwiRGF0YVwiKSkge1xuICAgICAgICAgICAgcHJvcGVydGllc1tkYXRhLmdldEF0dHJpYnV0ZShcIm5hbWVcIikgfHwgXCJcIl0gPSBub2RlVmFsKGdldDEoZGF0YSwgXCJ2YWx1ZVwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBzaW1wbGVEYXRhIG9mICQoZXh0ZW5kZWREYXRhLCBcIlNpbXBsZURhdGFcIikpIHtcbiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBzaW1wbGVEYXRhLmdldEF0dHJpYnV0ZShcIm5hbWVcIikgfHwgXCJcIjtcbiAgICAgICAgICAgIGNvbnN0IHR5cGVDb252ZXJ0ZXIgPSBzY2hlbWFbbmFtZV0gfHwgdHlwZUNvbnZlcnRlcnMuc3RyaW5nO1xuICAgICAgICAgICAgcHJvcGVydGllc1tuYW1lXSA9IHR5cGVDb252ZXJ0ZXIobm9kZVZhbChzaW1wbGVEYXRhKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHByb3BlcnRpZXM7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBnZXRNYXliZUhUTUxEZXNjcmlwdGlvbihub2RlKSB7XG4gICAgY29uc3QgZGVzY3JpcHRpb25Ob2RlID0gZ2V0MShub2RlLCBcImRlc2NyaXB0aW9uXCIpO1xuICAgIGZvciAoY29uc3QgYyBvZiBBcnJheS5mcm9tKGRlc2NyaXB0aW9uTm9kZT8uY2hpbGROb2RlcyB8fCBbXSkpIHtcbiAgICAgICAgaWYgKGMubm9kZVR5cGUgPT09IDQpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHtcbiAgICAgICAgICAgICAgICAgICAgXCJAdHlwZVwiOiBcImh0bWxcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5vZGVWYWwoYyksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHt9O1xufVxuZnVuY3Rpb24gZXh0cmFjdFRpbWVTcGFuKG5vZGUpIHtcbiAgICByZXR1cm4gZ2V0KG5vZGUsIFwiVGltZVNwYW5cIiwgKHRpbWVTcGFuKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0aW1lc3Bhbjoge1xuICAgICAgICAgICAgICAgIGJlZ2luOiBub2RlVmFsKGdldDEodGltZVNwYW4sIFwiYmVnaW5cIikpLFxuICAgICAgICAgICAgICAgIGVuZDogbm9kZVZhbChnZXQxKHRpbWVTcGFuLCBcImVuZFwiKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZXh0cmFjdFRpbWVTdGFtcChub2RlKSB7XG4gICAgcmV0dXJuIGdldChub2RlLCBcIlRpbWVTdGFtcFwiLCAodGltZVN0YW1wKSA9PiB7XG4gICAgICAgIHJldHVybiB7IHRpbWVzdGFtcDogbm9kZVZhbChnZXQxKHRpbWVTdGFtcCwgXCJ3aGVuXCIpKSB9O1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZXh0cmFjdENhc2NhZGVkU3R5bGUobm9kZSwgc3R5bGVNYXApIHtcbiAgICByZXR1cm4gdmFsMShub2RlLCBcInN0eWxlVXJsXCIsIChzdHlsZVVybCkgPT4ge1xuICAgICAgICBzdHlsZVVybCA9IG5vcm1hbGl6ZUlkKHN0eWxlVXJsKTtcbiAgICAgICAgaWYgKHN0eWxlTWFwW3N0eWxlVXJsXSkge1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oeyBzdHlsZVVybCB9LCBzdHlsZU1hcFtzdHlsZVVybF0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZvciBiYWNrd2FyZC1jb21wYXRpYmlsaXR5LiBTaG91bGQgd2Ugc3RpbGwgaW5jbHVkZVxuICAgICAgICAvLyBzdHlsZVVybCBldmVuIGlmIGl0J3Mgbm90IHJlc29sdmVkP1xuICAgICAgICByZXR1cm4geyBzdHlsZVVybCB9O1xuICAgIH0pO1xufVxudmFyIEFsdGl0dWRlTW9kZTtcbihmdW5jdGlvbiAoQWx0aXR1ZGVNb2RlKSB7XG4gICAgQWx0aXR1ZGVNb2RlW1wiQUJTT0xVVEVcIl0gPSBcImFic29sdXRlXCI7XG4gICAgQWx0aXR1ZGVNb2RlW1wiUkVMQVRJVkVfVE9fR1JPVU5EXCJdID0gXCJyZWxhdGl2ZVRvR3JvdW5kXCI7XG4gICAgQWx0aXR1ZGVNb2RlW1wiQ0xBTVBfVE9fR1JPVU5EXCJdID0gXCJjbGFtcFRvR3JvdW5kXCI7XG4gICAgQWx0aXR1ZGVNb2RlW1wiQ0xBTVBfVE9fU0VBRkxPT1JcIl0gPSBcImNsYW1wVG9TZWFGbG9vclwiO1xuICAgIEFsdGl0dWRlTW9kZVtcIlJFTEFUSVZFX1RPX1NFQUZMT09SXCJdID0gXCJyZWxhdGl2ZVRvU2VhRmxvb3JcIjtcbn0pKEFsdGl0dWRlTW9kZSB8fCAoQWx0aXR1ZGVNb2RlID0ge30pKTtcbmZ1bmN0aW9uIHByb2Nlc3NBbHRpdHVkZU1vZGUobW9kZSkge1xuICAgIHN3aXRjaCAobW9kZT8udGV4dENvbnRlbnQpIHtcbiAgICAgICAgY2FzZSBBbHRpdHVkZU1vZGUuQUJTT0xVVEU6XG4gICAgICAgICAgICByZXR1cm4gQWx0aXR1ZGVNb2RlLkFCU09MVVRFO1xuICAgICAgICBjYXNlIEFsdGl0dWRlTW9kZS5DTEFNUF9UT19HUk9VTkQ6XG4gICAgICAgICAgICByZXR1cm4gQWx0aXR1ZGVNb2RlLkNMQU1QX1RPX0dST1VORDtcbiAgICAgICAgY2FzZSBBbHRpdHVkZU1vZGUuQ0xBTVBfVE9fU0VBRkxPT1I6XG4gICAgICAgICAgICByZXR1cm4gQWx0aXR1ZGVNb2RlLkNMQU1QX1RPX1NFQUZMT09SO1xuICAgICAgICBjYXNlIEFsdGl0dWRlTW9kZS5SRUxBVElWRV9UT19HUk9VTkQ6XG4gICAgICAgICAgICByZXR1cm4gQWx0aXR1ZGVNb2RlLlJFTEFUSVZFX1RPX0dST1VORDtcbiAgICAgICAgY2FzZSBBbHRpdHVkZU1vZGUuUkVMQVRJVkVfVE9fU0VBRkxPT1I6XG4gICAgICAgICAgICByZXR1cm4gQWx0aXR1ZGVNb2RlLlJFTEFUSVZFX1RPX1NFQUZMT09SO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gZ2V0R3JvdW5kT3ZlcmxheUJveChub2RlKSB7XG4gICAgY29uc3QgbGF0TG9uUXVhZCA9IGdldDEobm9kZSwgXCJneDpMYXRMb25RdWFkXCIpO1xuICAgIGlmIChsYXRMb25RdWFkKSB7XG4gICAgICAgIGNvbnN0IHJpbmcgPSBmaXhSaW5nKGNvb3JkKGdldENvb3JkaW5hdGVzKG5vZGUpKSk7XG4gICAgICAgI
1023HJldHVybiB7XG4gICAgICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBbcmluZ10sXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZ2V0TGF0TG9uQm94KG5vZGUpO1xufVxuY29uc3QgREVHUkVFU19UT19SQURJQU5TID0gTWF0aC5QSSAvIDE4MDtcbmZ1bmN0aW9uIHJvdGF0ZUJveChiYm94LCBjb29yZGluYXRlcywgcm90YXRpb24pIHtcbiAgICBjb25zdCBjZW50ZXIgPSBbKGJib3hbMF0gKyBiYm94WzJdKSAvIDIsIChiYm94WzFdICsgYmJveFszXSkgLyAyXTtcbiAgICByZXR1cm4gW1xuICAgICAgICBjb29yZGluYXRlc1swXS5tYXAoKGNvb3JkaW5hdGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGR5ID0gY29vcmRpbmF0ZVsxXSAtIGNlbnRlclsxXTtcbiAgICAgICAgICAgIGNvbnN0IGR4ID0gY29vcmRpbmF0ZVswXSAtIGNlbnRlclswXTtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KGR5ICoqIDIgKyBkeCAqKiAyKTtcbiAgICAgICAgICAgIGNvbnN0IGFuZ2xlID0gTWF0aC5hdGFuMihkeSwgZHgpICsgcm90YXRpb24gKiBERUdSRUVTX1RPX1JBRElBTlM7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIGNlbnRlclswXSArIE1hdGguY29zKGFuZ2xlKSAqIGRpc3RhbmNlLFxuICAgICAgICAgICAgICAgIGNlbnRlclsxXSArIE1hdGguc2luKGFuZ2xlKSAqIGRpc3RhbmNlLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfSksXG4gICAgXTtcbn1cbmZ1bmN0aW9uIGdldExhdExvbkJveChub2RlKSB7XG4gICAgY29uc3QgbGF0TG9uQm94ID0gZ2V0MShub2RlLCBcIkxhdExvbkJveFwiKTtcbiAgICBpZiAobGF0TG9uQm94KSB7XG4gICAgICAgIGNvbnN0IG5vcnRoID0gbnVtMShsYXRMb25Cb3gsIFwibm9ydGhcIik7XG4gICAgICAgIGNvbnN0IHdlc3QgPSBudW0xKGxhdExvbkJveCwgXCJ3ZXN0XCIpO1xuICAgICAgICBjb25zdCBlYXN0ID0gbnVtMShsYXRMb25Cb3gsIFwiZWFzdFwiKTtcbiAgICAgICAgY29uc3Qgc291dGggPSBudW0xKGxhdExvbkJveCwgXCJzb3V0aFwiKTtcbiAgICAgICAgY29uc3Qgcm90YXRpb24gPSBudW0xKGxhdExvbkJveCwgXCJyb3RhdGlvblwiKTtcbiAgICAgICAgaWYgKHR5cGVvZiBub3J0aCA9PT0gXCJudW1iZXJcIiAmJlxuICAgICAgICAgICAgdHlwZW9mIHNvdXRoID09PSBcIm51bWJlclwiICYmXG4gICAgICAgICAgICB0eXBlb2Ygd2VzdCA9PT0gXCJudW1iZXJcIiAmJlxuICAgICAgICAgICAgdHlwZW9mIGVhc3QgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGJib3ggPSBbd2VzdCwgc291dGgsIGVhc3QsIG5vcnRoXTtcbiAgICAgICAgICAgIGxldCBjb29yZGluYXRlcyA9IFtcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIFt3ZXN0LCBub3J0aF0sIC8vIHRvcCBsZWZ0XG4gICAgICAgICAgICAgICAgICAgIFtlYXN0LCBub3J0aF0sIC8vIHRvcCByaWdodFxuICAgICAgICAgICAgICAgICAgICBbZWFzdCwgc291dGhdLCAvLyB0b3AgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgW3dlc3QsIHNvdXRoXSwgLy8gYm90dG9tIGxlZnRcbiAgICAgICAgICAgICAgICAgICAgW3dlc3QsIG5vcnRoXSwgLy8gdG9wIGxlZnQgKGFnYWluKVxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByb3RhdGlvbiA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzID0gcm90YXRlQm94KGJib3gsIGNvb3JkaW5hdGVzLCByb3RhdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGJib3gsXG4gICAgICAgICAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJQb2x5Z29uXCIsXG4gICAgICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZ2V0R3JvdW5kT3ZlcmxheShub2RlLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKSB7XG4gICAgY29uc3QgYm94ID0gZ2V0R3JvdW5kT3ZlcmxheUJveChub2RlKTtcbiAgICBjb25zdCBnZW9tZXRyeSA9IGJveD8uZ2VvbWV0cnkgfHwgbnVsbDtcbiAgICBpZiAoIWdlb21ldHJ5ICYmIG9wdGlvbnMuc2tpcE51bGxHZW9tZXRyeSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgZmVhdHVyZSA9IHtcbiAgICAgICAgdHlwZTogXCJGZWF0dXJlXCIsXG4gICAgICAgIGdlb21ldHJ5LFxuICAgICAgICBwcm9wZXJ0aWVzOiBPYmplY3QuYXNzaWduKFxuICAgICAgICAvKipcbiAgICAgICAgICogUmVsYXRlZCB0b1xuICAgICAgICAgKiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS90bWN3LzAzN2ExY2I2NjYwZDc0YTM5MmU5ZGE3NDQ2NTQwZjQ2XG4gICAgICAgICAqL1xuICAgICAgICB7IFwiQGdlb21ldHJ5LXR5cGVcIjogXCJncm91bmRvdmVybGF5XCIgfSwgZ2V0TXVsdGkobm9kZSwgW1xuICAgICAgICAgICAgXCJuYW1lXCIsXG4gICAgICAgICAgICBcImFkZHJlc3NcIixcbiAgICAgICAgICAgIFwidmlzaWJpbGl0eVwiLFxuICAgICAgICAgICAgXCJvcGVuXCIsXG4gICAgICAgICAgICBcInBob25lTnVtYmVyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCIsXG4gICAgICAgIF0pLCBnZXRNYXliZUhUTUxEZXNjcmlwdGlvbihub2RlKSwgZXh0cmFjdENhc2NhZGVkU3R5bGUobm9kZSwgc3R5bGVNYXApLCBleHRyYWN0U3R5bGUobm9kZSksIGV4dHJhY3RJY29uSHJlZihub2RlKSwgZXh0cmFjdEV4dGVuZGVkRGF0YShub2RlLCBzY2hlbWEpLCBleHRyYWN0VGltZVNwYW4obm9kZSksIGV4dHJhY3RUaW1lU3RhbXAobm9kZSkpLFxuICAgIH07XG4gICAgaWYgKGJveD8uYmJveCkge1xuICAgICAgICBmZWF0dXJlLmJib3ggPSBib3guYmJveDtcbiAgICB9XG4gICAgaWYgKGZlYXR1cmUucHJvcGVydGllcz8udmlzaWJpbGl0eSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGZlYXR1cmUucHJvcGVydGllcy52aXNpYmlsaXR5ID0gZmVhdHVyZS5wcm9wZXJ0aWVzLnZpc2liaWxpdHkgIT09IFwiMFwiO1xuICAgIH1cbiAgICBjb25zdCBpZCA9IG5vZGUuZ2V0QXR0cmlidXRlKFwiaWRcIik7XG4gICAgaWYgKGlkICE9PSBudWxsICYmIGlkICE9PSBcIlwiKVxuICAgICAgICBmZWF0dXJlLmlkID0gaWQ7XG4gICAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGdldE5ldHdvcmtMaW5rUmVnaW9uKG5vZGUpIHtcbiAgICBjb25zdCByZWdpb24gPSBnZXQxKG5vZGUsIFwiUmVnaW9uXCIpO1xuICAgIGlmIChyZWdpb24pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvb3JkaW5hdGVCb3g6IGdldExhdExvbkFsdEJveChyZWdpb24pLFxuICAgICAgICAgICAgbG9kOiBnZXRMb2Qobm9kZSksXG4gICAgICAgI
1023H07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZ2V0TG9kKG5vZGUpIHtcbiAgICBjb25zdCBsb2QgPSBnZXQxKG5vZGUsIFwiTG9kXCIpO1xuICAgIGlmIChsb2QpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIG51bTEobG9kLCBcIm1pbkxvZFBpeGVsc1wiKSA/PyAtMSxcbiAgICAgICAgICAgIG51bTEobG9kLCBcIm1heExvZFBpeGVsc1wiKSA/PyAtMSxcbiAgICAgICAgICAgIG51bTEobG9kLCBcIm1pbkZhZGVFeHRlbnRcIikgPz8gbnVsbCxcbiAgICAgICAgICAgIG51bTEobG9kLCBcIm1heEZhZGVFeHRlbnRcIikgPz8gbnVsbCxcbiAgICAgICAgXTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBnZXRMYXRMb25BbHRCb3gobm9kZSkge1xuICAgIGNvbnN0IGxhdExvbkFsdEJveCA9IGdldDEobm9kZSwgXCJMYXRMb25BbHRCb3hcIik7XG4gICAgaWYgKGxhdExvbkFsdEJveCkge1xuICAgICAgICBjb25zdCBub3J0aCA9IG51bTEobGF0TG9uQWx0Qm94LCBcIm5vcnRoXCIpO1xuICAgICAgICBjb25zdCB3ZXN0ID0gbnVtMShsYXRMb25BbHRCb3gsIFwid2VzdFwiKTtcbiAgICAgICAgY29uc3QgZWFzdCA9IG51bTEobGF0TG9uQWx0Qm94LCBcImVhc3RcIik7XG4gICAgICAgIGNvbnN0IHNvdXRoID0gbnVtMShsYXRMb25BbHRCb3gsIFwic291dGhcIik7XG4gICAgICAgIGNvbnN0IGFsdGl0dWRlTW9kZSA9IHByb2Nlc3NBbHRpdHVkZU1vZGUoZ2V0MShsYXRMb25BbHRCb3gsIFwiYWx0aXR1ZGVNb2RlXCIpIHx8XG4gICAgICAgICAgICBnZXQxKGxhdExvbkFsdEJveCwgXCJneDphbHRpdHVkZU1vZGVcIikpO1xuICAgICAgICBpZiAoYWx0aXR1ZGVNb2RlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiRW5jb3VudGVyZWQgYW4gdW5zdXBwb3J0ZWQgZmVhdHVyZSBvZiBLTUwgZm9yIHRvZ2VvanNvbjogcGxlYXNlIGNvbnRhY3QgZGV2ZWxvcGVycyBmb3Igc3VwcG9ydCBvZiBhbHRpdHVkZSBtb2RlLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIG5vcnRoID09PSBcIm51bWJlclwiICYmXG4gICAgICAgICAgICB0eXBlb2Ygc291dGggPT09IFwibnVtYmVyXCIgJiZcbiAgICAgICAgICAgIHR5cGVvZiB3ZXN0ID09PSBcIm51bWJlclwiICYmXG4gICAgICAgICAgICB0eXBlb2YgZWFzdCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgY29uc3QgYmJveCA9IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdO1xuICAgICAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSBbXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBbd2VzdCwgbm9ydGhdLCAvLyB0b3AgbGVmdFxuICAgICAgICAgICAgICAgICAgICBbZWFzdCwgbm9ydGhdLCAvLyB0b3AgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgW2Vhc3QsIHNvdXRoXSwgLy8gdG9wIHJpZ2h0XG4gICAgICAgICAgICAgICAgICAgIFt3ZXN0LCBzb3V0aF0sIC8vIGJvdHRvbSBsZWZ0XG4gICAgICAgICAgICAgICAgICAgIFt3ZXN0LCBub3J0aF0sIC8vIHRvcCBsZWZ0IChhZ2FpbilcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgYmJveCxcbiAgICAgICAgICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIlBvbHlnb25cIixcbiAgICAgICAgICAgICAgICAgICAgY29vcmRpbmF0ZXMsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBnZXRMaW5rT2JqZWN0KG5vZGUpIHtcbiAgICAvKlxuICAgICAgPExpbmsgaWQ9XCJJRFwiPlxuICAgICAgICA8IS0tIHNwZWNpZmljIHRvIExpbmsgLS0+XG4gICAgICAgIDxocmVmPi4uLjwvaHJlZj4gICAgICAgICAgICAgICAgICAgICAgPCEtLSBzdHJpbmcgLS0+XG4gICAgICAgIDxyZWZyZXNoTW9kZT5vbkNoYW5nZTwvcmVmcmVzaE1vZGU+XG4gICAgICAgICAgPCEtLSByZWZyZXNoTW9kZUVudW06IG9uQ2hhbmdlLCBvbkludGVydmFsLCBvciBvbkV4cGlyZSAtLT5cbiAgICAgICAgPHJlZnJlc2hJbnRlcnZhbD40PC9yZWZyZXNoSW50ZXJ2YWw+ICA8IS0tIGZsb2F0IC0tPlxuICAgICAgICA8dmlld1JlZnJlc2hNb2RlPm5ldmVyPC92aWV3UmVmcmVzaE1vZGU+XG4gICAgICAgICAgPCEtLSB2aWV3UmVmcmVzaE1vZGVFbnVtOiBuZXZlciwgb25TdG9wLCBvblJlcXVlc3QsIG9uUmVnaW9uIC0tPlxuICAgICAgICA8dmlld1JlZnJlc2hUaW1lPjQ8L3ZpZXdSZWZyZXNoVGltZT4gIDwhLS0gZmxvYXQgLS0+XG4gICAgICAgIDx2aWV3Qm91bmRTY2FsZT4xPC92aWV3Qm91bmRTY2FsZT4gICAgPCEtLSBmbG9hdCAtLT5cbiAgICAgICAgPHZpZXdGb3JtYXQ+QkJPWD1bYmJveFdlc3RdLFtiYm94U291dGhdLFtiYm94RWFzdF0sW2Jib3hOb3J0aF08L3ZpZXdGb3JtYXQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBzdHJpbmcgLS0+XG4gICAgICAgIDxodHRwUXVlcnk+Li4uPC9odHRwUXVlcnk+ICAgICAgICAgICAgPCEtLSBzdHJpbmcgLS0+XG4gICAgICA8L0xpbms+XG4gICAgKi9cbiAgICBjb25zdCBsaW5rT2JqID0gZ2V0MShub2RlLCBcIkxpbmtcIik7XG4gICAgaWYgKGxpbmtPYmopIHtcbiAgICAgICAgcmV0dXJuIGdldE11bHRpKGxpbmtPYmosIFtcbiAgICAgICAgICAgIFwiaHJlZlwiLFxuICAgICAgICAgICAgXCJyZWZyZXNoTW9kZVwiLFxuICAgICAgICAgICAgXCJyZWZyZXNoSW50ZXJ2YWxcIixcbiAgICAgICAgICAgIFwidmlld1JlZnJlc2hNb2RlXCIsXG4gICAgICAgICAgICBcInZpZXdSZWZyZXNoVGltZVwiLFxuICAgICAgICAgICAgXCJ2aWV3Qm91bmRTY2FsZVwiLFxuICAgICAgICAgICAgXCJ2aWV3Rm9ybWF0XCIsXG4gICAgICAgICAgICBcImh0dHBRdWVyeVwiLFxuICAgICAgICBdKTtcbiAgICB9XG4gICAgcmV0dXJuIHt9O1xufVxuZnVuY3Rpb24gZ2V0TmV0d29ya0xpbmsobm9kZSwgc3R5bGVNYXAsIHNjaGVtYSwgb3B0aW9ucykge1xuICAgIGNvbnN0IGJveCA9IGdldE5ldHdvcmtMaW5rUmVnaW9uKG5vZGUpO1xuICAgIGNvbnN0IGdlb21ldHJ5ID0gYm94Py5jb29yZGluYX
1023RlQm94Py5nZW9tZXRyeSB8fCBudWxsO1xuICAgIGlmICghZ2VvbWV0cnkgJiYgb3B0aW9ucy5za2lwTnVsbEdlb21ldHJ5KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBmZWF0dXJlID0ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVcIixcbiAgICAgICAgZ2VvbWV0cnksXG4gICAgICAgIHByb3BlcnRpZXM6IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZWxhdGVkIHRvXG4gICAgICAgICAqIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3RtY3cvMDM3YTFjYjY2NjBkNzRhMzkyZTlkYTc0NDY1NDBmNDZcbiAgICAgICAgICovXG4gICAgICAgIHsgXCJAZ2VvbWV0cnktdHlwZVwiOiBcIm5ldHdvcmtsaW5rXCIgfSwgZ2V0TXVsdGkobm9kZSwgW1xuICAgICAgICAgICAgXCJuYW1lXCIsXG4gICAgICAgICAgICBcImFkZHJlc3NcIixcbiAgICAgICAgICAgIFwidmlzaWJpbGl0eVwiLFxuICAgICAgICAgICAgXCJvcGVuXCIsXG4gICAgICAgICAgICBcInBob25lTnVtYmVyXCIsXG4gICAgICAgICAgICBcInN0eWxlVXJsXCIsXG4gICAgICAgICAgICBcInJlZnJlc2hWaXNpYmlsaXR5XCIsXG4gICAgICAgICAgICBcImZseVRvVmlld1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiLFxuICAgICAgICBdKSwgZ2V0TWF5YmVIVE1MRGVzY3JpcHRpb24obm9kZSksIGV4dHJhY3RDYXNjYWRlZFN0eWxlKG5vZGUsIHN0eWxlTWFwKSwgZXh0cmFjdFN0eWxlKG5vZGUpLCBleHRyYWN0SWNvbkhyZWYobm9kZSksIGV4dHJhY3RFeHRlbmRlZERhdGEobm9kZSwgc2NoZW1hKSwgZXh0cmFjdFRpbWVTcGFuKG5vZGUpLCBleHRyYWN0VGltZVN0YW1wKG5vZGUpLCBnZXRMaW5rT2JqZWN0KG5vZGUpLCBib3g/LmxvZCA/IHsgbG9kOiBib3gubG9kIH0gOiB7fSksXG4gICAgfTtcbiAgICBpZiAoYm94Py5jb29yZGluYXRlQm94Py5iYm94KSB7XG4gICAgICAgIGZlYXR1cmUuYmJveCA9IGJveC5jb29yZGluYXRlQm94LmJib3g7XG4gICAgfVxuICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXM/LnZpc2liaWxpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBmZWF0dXJlLnByb3BlcnRpZXMudmlzaWJpbGl0eSA9IGZlYXR1cmUucHJvcGVydGllcy52aXNpYmlsaXR5ICE9PSBcIjBcIjtcbiAgICB9XG4gICAgY29uc3QgaWQgPSBub2RlLmdldEF0dHJpYnV0ZShcImlkXCIpO1xuICAgIGlmIChpZCAhPT0gbnVsbCAmJiBpZCAhPT0gXCJcIilcbiAgICAgICAgZmVhdHVyZS5pZCA9IGlkO1xuICAgIHJldHVybiBmZWF0dXJlO1xufVxuXG5mdW5jdGlvbiBnZW9tZXRyeUxpc3RUb0dlb21ldHJ5KGdlb21ldHJpZXMpIHtcbiAgICByZXR1cm4gZ2VvbWV0cmllcy5sZW5ndGggPT09IDBcbiAgICAgICAgPyBudWxsXG4gICAgICAgIDogZ2VvbWV0cmllcy5sZW5ndGggPT09IDFcbiAgICAgICAgICAgID8gZ2VvbWV0cmllc1swXVxuICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJHZW9tZXRyeUNvbGxlY3Rpb25cIixcbiAgICAgICAgICAgICAgICBnZW9tZXRyaWVzLFxuICAgICAgICAgICAgfTtcbn1cbmZ1bmN0aW9uIGdldFBsYWNlbWFyayhub2RlLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKSB7XG4gICAgY29uc3QgeyBjb29yZFRpbWVzLCBnZW9tZXRyaWVzIH0gPSBnZXRHZW9tZXRyeShub2RlKTtcbiAgICBjb25zdCBnZW9tZXRyeSA9IGdlb21ldHJ5TGlzdFRvR2VvbWV0cnkoZ2VvbWV0cmllcyk7XG4gICAgaWYgKCFnZW9tZXRyeSAmJiBvcHRpb25zLnNraXBOdWxsR2VvbWV0cnkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGZlYXR1cmUgPSB7XG4gICAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgICBnZW9tZXRyeSxcbiAgICAgICAgcHJvcGVydGllczogT2JqZWN0LmFzc2lnbihnZXRNdWx0aShub2RlLCBbXG4gICAgICAgICAgICBcIm5hbWVcIixcbiAgICAgICAgICAgIFwiYWRkcmVzc1wiLFxuICAgICAgICAgICAgXCJ2aXNpYmlsaXR5XCIsXG4gICAgICAgICAgICBcIm9wZW5cIixcbiAgICAgICAgICAgIFwicGhvbmVOdW1iZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIixcbiAgICAgICAgXSksIGdldE1heWJlSFRNTERlc2NyaXB0aW9uKG5vZGUpLCBleHRyYWN0Q2FzY2FkZWRTdHlsZShub2RlLCBzdHlsZU1hcCksIGV4dHJhY3RTdHlsZShub2RlKSwgZXh0cmFjdEV4dGVuZGVkRGF0YShub2RlLCBzY2hlbWEpLCBleHRyYWN0VGltZVNwYW4obm9kZSksIGV4dHJhY3RUaW1lU3RhbXAobm9kZSksIGNvb3JkVGltZXMubGVuZ3RoXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBjb29yZGluYXRlUHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICB0aW1lczogY29vcmRUaW1lcy5sZW5ndGggPT09IDEgPyBjb29yZFRpbWVzWzBdIDogY29vcmRUaW1lcyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgfTtcbiAgICBpZiAoZmVhdHVyZS5wcm9wZXJ0aWVzPy52aXNpYmlsaXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZmVhdHVyZS5wcm9wZXJ0aWVzLnZpc2liaWxpdHkgPSBmZWF0dXJlLnByb3BlcnRpZXMudmlzaWJpbGl0eSAhPT0gXCIwXCI7XG4gICAgfVxuICAgIGNvbnN0IGlkID0gbm9kZS5nZXRBdHRyaWJ1dGUoXCJpZFwiKTtcbiAgICBpZiAoaWQgIT09IG51bGwgJiYgaWQgIT09IFwiXCIpXG4gICAgICAgIGZlYXR1cmUuaWQgPSBpZDtcbiAgICByZXR1cm4gZmVhdHVyZTtcbn1cblxuZnVuY3Rpb24gZ2V0U3R5bGVJZChzdHlsZSkge1xuICAgIGxldCBpZCA9IHN0eWxlLmdldEF0dHJpYnV0ZShcImlkXCIpO1xuICAgIGNvbnN0IHBhcmVudE5vZGUgPSBzdHlsZS5wYXJlbnROb2RlO1xuICAgIGlmICghaWQgJiZcbiAgICAgICAgaXNFbGVtZW50KHBhcmVudE5vZGUpICYmXG4gICAgICAgIHBhcmVudE5vZGUubG9jYWxOYW1lID09PSBcIkNhc2NhZGluZ1N0eWxlXCIpIHtcbiAgICAgICAgaWQgPSBwYXJlbnROb2RlLmdldEF0dHJpYnV0ZShcImttbDppZFwiKSB8fCBwYXJlbnROb2RlLmdldEF0dHJpYnV0ZShcImlkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gbm9ybWFsaXplSWQoaWQgfHwgXCJcIik7XG59XG5mdW5jdGlvbiBidWlsZFN0eWxlTWFwKG5vZGUpIHtcbiAgICBjb25zdCBzdHlsZU1hcCA9IHt9O1xuICAgIGZvciAoY29uc3Qgc3R5bGUgb2YgJChub2RlLCBcIlN0eWxlXCIpKSB7XG4gICAgICAgI
1023HN0eWxlTWFwW2dldFN0eWxlSWQoc3R5bGUpXSA9IGV4dHJhY3RTdHlsZShzdHlsZSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgbWFwIG9mICQobm9kZSwgXCJTdHlsZU1hcFwiKSkge1xuICAgICAgICBjb25zdCBpZCA9IG5vcm1hbGl6ZUlkKG1hcC5nZXRBdHRyaWJ1dGUoXCJpZFwiKSB8fCBcIlwiKTtcbiAgICAgICAgdmFsMShtYXAsIFwic3R5bGVVcmxcIiwgKHN0eWxlVXJsKSA9PiB7XG4gICAgICAgICAgICBzdHlsZVVybCA9IG5vcm1hbGl6ZUlkKHN0eWxlVXJsKTtcbiAgICAgICAgICAgIGlmIChzdHlsZU1hcFtzdHlsZVVybF0pIHtcbiAgICAgICAgICAgICAgICBzdHlsZU1hcFtpZF0gPSBzdHlsZU1hcFtzdHlsZVVybF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc3R5bGVNYXA7XG59XG5mdW5jdGlvbiBidWlsZFNjaGVtYShub2RlKSB7XG4gICAgY29uc3Qgc2NoZW1hID0ge307XG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiAkKG5vZGUsIFwiU2ltcGxlRmllbGRcIikpIHtcbiAgICAgICAgc2NoZW1hW2ZpZWxkLmdldEF0dHJpYnV0ZShcIm5hbWVcIikgfHwgXCJcIl0gPVxuICAgICAgICAgICAgdHlwZUNvbnZlcnRlcnNbZmllbGQuZ2V0QXR0cmlidXRlKFwidHlwZVwiKSB8fCBcIlwiXSB8fCB0eXBlQ29udmVydGVycy5zdHJpbmc7XG4gICAgfVxuICAgIHJldHVybiBzY2hlbWE7XG59XG5jb25zdCBGT0xERVJfUFJPUFMgPSBbXG4gICAgXCJuYW1lXCIsXG4gICAgXCJ2aXNpYmlsaXR5XCIsXG4gICAgXCJvcGVuXCIsXG4gICAgXCJhZGRyZXNzXCIsXG4gICAgXCJkZXNjcmlwdGlvblwiLFxuICAgIFwicGhvbmVOdW1iZXJcIixcbiAgICBcInZpc2liaWxpdHlcIixcbl07XG5mdW5jdGlvbiBnZXRGb2xkZXIobm9kZSkge1xuICAgIGNvbnN0IG1ldGEgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIEFycmF5LmZyb20obm9kZS5jaGlsZE5vZGVzKSkge1xuICAgICAgICBpZiAoaXNFbGVtZW50KGNoaWxkKSAmJiBGT0xERVJfUFJPUFMuaW5jbHVkZXMoY2hpbGQudGFnTmFtZSkpIHtcbiAgICAgICAgICAgIG1ldGFbY2hpbGQudGFnTmFtZV0gPSBub2RlVmFsKGNoaWxkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImZvbGRlclwiLFxuICAgICAgICBtZXRhLFxuICAgICAgICBjaGlsZHJlbjogW10sXG4gICAgfTtcbn1cbi8qKlxuICogWWllbGQgYSBuZXN0ZWQgdHJlZSB3aXRoIEtNTCBmb2xkZXIgc3RydWN0dXJlXG4gKlxuICogVGhpcyBnZW5lcmF0ZXMgYSB0cmVlIHdpdGggdGhlIGdpdmVuIHN0cnVjdHVyZTpcbiAqXG4gKiBgYGBqc1xuICoge1xuICogICBcInR5cGVcIjogXCJyb290XCIsXG4gKiAgIFwiY2hpbGRyZW5cIjogW1xuICogICAgIHtcbiAqICAgICAgIFwidHlwZVwiOiBcImZvbGRlclwiLFxuICogICAgICAgXCJtZXRhXCI6IHtcbiAqICAgICAgICAgXCJuYW1lXCI6IFwiVGVzdFwiXG4gKiAgICAgICB9LFxuICogICAgICAgXCJjaGlsZHJlblwiOiBbXG4gKiAgICAgICAgICAvLyAuLi5mZWF0dXJlcyBhbmQgZm9sZGVyc1xuICogICAgICAgXVxuICogICAgIH1cbiAqICAgICAvLyAuLi5mZWF0dXJlc1xuICogICBdXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAjIyMgR3JvdW5kT3ZlcmxheVxuICpcbiAqIEdyb3VuZE92ZXJsYXkgZWxlbWVudHMgYXJlIGNvbnZlcnRlZCBpbnRvXG4gKiBgRmVhdHVyZWAgb2JqZWN0cyB3aXRoIGBQb2x5Z29uYCBnZW9tZXRyaWVzLFxuICogYSBwcm9wZXJ0eSBsaWtlOlxuICpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICAgXCJAZ2VvbWV0cnktdHlwZVwiOiBcImdyb3VuZG92ZXJsYXlcIlxuICogfVxuICogYGBgXG4gKlxuICogQW5kIHRoZSBncm91bmQgb3ZlcmxheSdzIGltYWdlIFVSTCBpbiB0aGUgYGhyZWZgXG4gKiBwcm9wZXJ0eS4gR3JvdW5kIG92ZXJsYXlzIHdpbGwgbmVlZCB0byBiZSBkaXNwbGF5ZWRcbiAqIHdpdGggYSBzZXBhcmF0ZSBtZXRob2QgdG8gb3RoZXIgZmVhdHVyZXMsIGRlcGVuZGluZ1xuICogb24gd2hpY2ggbWFwIGZyYW1ld29yayB5b3UncmUgdXNpbmcuXG4gKi9cbmZ1bmN0aW9uIGttbFdpdGhGb2xkZXJzKG5vZGUsIG9wdGlvbnMgPSB7XG4gICAgc2tpcE51bGxHZW9tZXRyeTogZmFsc2UsXG59KSB7XG4gICAgY29uc3QgbiA9IG5vZGU7XG4gICAgY29uc3Qgc3R5bGVNYXAgPSBidWlsZFN0eWxlTWFwKG4pO1xuICAgIGNvbnN0IHNjaGVtYSA9IGJ1aWxkU2NoZW1hKG4pO1xuICAgIGNvbnN0IHRyZWUgPSB7IHR5cGU6IFwicm9vdFwiLCBjaGlsZHJlbjogW10gfTtcbiAgICBmdW5jdGlvbiB0cmF2ZXJzZShub2RlLCBwb2ludGVyLCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChpc0VsZW1lbnQobm9kZSkpIHtcbiAgICAgICAgICAgIHN3aXRjaCAobm9kZS50YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcIkdyb3VuZE92ZXJsYXlcIjoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwbGFjZW1hcmsgPSBnZXRHcm91bmRPdmVybGF5KG5vZGUsIHN0eWxlTWFwLCBzY2hlbWEsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGxhY2VtYXJrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyLmNoaWxkcmVuLnB1c2gocGxhY2VtYXJrKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSBcIlBsYWNlbWFya1wiOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBsYWNlbWFyayA9IGdldFBsYWNlbWFyayhub2RlLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYWNlbWFyaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRlci5jaGlsZHJlbi5wdXNoKHBsYWNlbWFyayk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgXCJGb2xkZXJcIjoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmb2xkZXIgPSBnZXRGb2xkZXIobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgI
1023HBvaW50ZXIuY2hpbGRyZW4ucHVzaChmb2xkZXIpO1xuICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gZm9sZGVyO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSBcIk5ldHdvcmtMaW5rXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV0d29ya0xpbmsgPSBnZXROZXR3b3JrTGluayhub2RlLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ldHdvcmtMaW5rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyLmNoaWxkcmVuLnB1c2gobmV0d29ya0xpbmspO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5jaGlsZE5vZGVzKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRyYXZlcnNlKG5vZGUuY2hpbGROb2Rlc1tpXSwgcG9pbnRlciwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdHJhdmVyc2UobiwgdHJlZSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHRyZWU7XG59XG4vKipcbiAqIENvbnZlcnQgS01MIHRvIEdlb0pTT04gaW5jcmVtZW50YWxseSwgcmV0dXJuaW5nXG4gKiBhIFtHZW5lcmF0b3JdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvSXRlcmF0b3JzX2FuZF9HZW5lcmF0b3JzKVxuICogdGhhdCB5aWVsZHMgb3V0cHV0IGZlYXR1cmUgYnkgZmVhdHVyZS5cbiAqL1xuZnVuY3Rpb24qIGttbEdlbihub2RlLCBvcHRpb25zID0ge1xuICAgIHNraXBOdWxsR2VvbWV0cnk6IGZhbHNlLFxufSkge1xuICAgIGNvbnN0IG4gPSBub2RlO1xuICAgIGNvbnN0IHN0eWxlTWFwID0gYnVpbGRTdHlsZU1hcChuKTtcbiAgICBjb25zdCBzY2hlbWEgPSBidWlsZFNjaGVtYShuKTtcbiAgICBmb3IgKGNvbnN0IHBsYWNlbWFyayBvZiAkKG4sIFwiUGxhY2VtYXJrXCIpKSB7XG4gICAgICAgIGNvbnN0IGZlYXR1cmUgPSBnZXRQbGFjZW1hcmsocGxhY2VtYXJrLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKGZlYXR1cmUpXG4gICAgICAgICAgICB5aWVsZCBmZWF0dXJlO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGdyb3VuZE92ZXJsYXkgb2YgJChuLCBcIkdyb3VuZE92ZXJsYXlcIikpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IGdldEdyb3VuZE92ZXJsYXkoZ3JvdW5kT3ZlcmxheSwgc3R5bGVNYXAsIHNjaGVtYSwgb3B0aW9ucyk7XG4gICAgICAgIGlmIChmZWF0dXJlKVxuICAgICAgICAgICAgeWllbGQgZmVhdHVyZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBuZXR3b3JrTGluayBvZiAkKG4sIFwiTmV0d29ya0xpbmtcIikpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IGdldE5ldHdvcmtMaW5rKG5ldHdvcmtMaW5rLCBzdHlsZU1hcCwgc2NoZW1hLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKGZlYXR1cmUpXG4gICAgICAgICAgICB5aWVsZCBmZWF0dXJlO1xuICAgIH1cbn1cbi8qKlxuICogQ29udmVydCBhIEtNTCBkb2N1bWVudCB0byBHZW9KU09OLiBUaGUgZmlyc3QgYXJndW1lbnQsIGBkb2NgLCBtdXN0IGJlIGEgS01MXG4gKiBkb2N1bWVudCBhcyBhbiBYTUwgRE9NIC0gbm90IGFzIGEgc3RyaW5nLiBZb3UgY2FuIGdldCB0aGlzIHVzaW5nIGpRdWVyeSdzIGRlZmF1bHRcbiAqIGAuYWpheGAgZnVuY3Rpb24gb3IgdXNpbmcgYSBiYXJlIFhNTEh0dHBSZXF1
1023ZXN0IHdpdGggdGhlIGAucmVzcG9uc2VgIHByb3BlcnR5XG4gKiBob2xkaW5nIGFuIFhNTCBET00uXG4gKlxuICogVGhlIG91dHB1dCBpcyBhIEphdmFTY3JpcHQgb2JqZWN0IG9mIEdlb0pTT04gZGF0YS4gWW91IGNhbiBjb252ZXJ0IGl0IHRvIGEgc3RyaW5nXG4gKiB3aXRoIFtKU09OLnN0cmluZ2lmeV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvSlNPTi9zdHJpbmdpZnkpXG4gKiBvciB1c2UgaXQgZGlyZWN0bHkgaW4gbGlicmFyaWVzLlxuICovXG5mdW5jdGlvbiBrbWwobm9kZSwgb3B0aW9ucyA9IHtcbiAgICBza2lwTnVsbEdlb21ldHJ5OiBmYWxzZSxcbn0pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXG4gICAgICAgIGZlYXR1cmVzOiBBcnJheS5mcm9tKGttbEdlbihub2RlLCBvcHRpb25zKSksXG4gICAgfTtcbn1cblxuZXhwb3J0IHsgZ3B4LCBncHhHZW4sIGttbCwga21sR2VuLCBrbWxXaXRoRm9sZGVycywgdGN4LCB0Y3hHZW4gfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXRvZ2VvanNvbi5lcy5tanMubWFwXG4iXSwibWFwcGluZ3MiOiI7QUFBQSxTQUFTLEVBQUUsU0FBUyxTQUFTO0NBQ3pCLE9BQU8sTUFBTSxLQUFLLFFBQVEscUJBQXFCLE9BQU8sQ0FBQztBQUMzRDtBQUNBLFNBQVMsWUFBWSxJQUFJO0NBQ3JCLE9BQU8sR0FBRyxPQUFPLE1BQU0sS0FBSyxJQUFJO0FBQ3BDO0FBQ0EsU0FBUyxJQUFJLFNBQVMsU0FBUyxJQUFJO0NBQy9CLE9BQU8sTUFBTSxLQUFLLFFBQVEsdUJBQXVCLElBQUksT0FBTyxDQUFDO0FBQ2pFOzs7O0FBSUEsU0FBUyxRQUFRLE1BQU07Q0FDbkIsTUFBTSxVQUFVO0NBQ2hCLE9BQU8s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BQU07SUFDNUIsVUFBVTtJQUNWO0dBQ0o7R0FDQSxLQUFLLGVBQWU7SUFDaEIsTUFBTSxjQUFjLGVBQWUsTUFBTSxVQUFVLFFBQVEsT0FBTztJQUNsRSxJQUFJLGFBQ0EsUUFBUSxTQUFTLEtBQUssV0FBVztJQUVyQztHQUNKO0VBQ0o7RUFFSixJQUFJLEtBQUssWUFDTCxLQUFLLElBQUksSUFBSSxHQUFHLElBQUksS0FBSyxXQUFXLFFBQVEsS0FDeEMsU0FBUyxLQUFLLFdBQVcsSUFBSSxTQUFTLE9BQU87Q0FHekQ7Q0FDQSxTQUFTLEdBQUcsTUFBTSxPQUFPO0NBQ3pCLE9BQU87QUFDWDs7Ozs7O0FBTUEsVUFBVSxPQUFPLE1BQU0sVUFBVSxFQUM3QixrQkFBa0IsTUFDdEIsR0FBRztDQUNDLE1BQU0sSUFBSTtDQUNWLE1BQU0sV0FBVyxjQUFjLENBQUM7Q0FDaEMsTUFBTSxTQUFTLFlBQVksQ0FBQztDQUM1QixLQUFLLE1BQU0sYUFBYSxFQUFFLEdBQUcsV0FBVyxHQUFHO0VBQ3ZDLE1BQU0sVUFBVSxhQUFhLFdBQVcsVUFBVSxRQUFRLE9BQU87RUFDakUsSUFBSSxTQUNBLE1BQU07Q0FDZDtDQUNBLEtBQUssTUFBTSxpQkFBaUIsRUFBRSxHQU
1023FHLGVBQWUsR0FBRztFQUMvQyxNQUFNLFVBQVUsaUJBQWlCLGVBQWUsVUFBVSxRQUFRLE9BQU87RUFDekUsSUFBSSxTQUNBLE1BQU07Q0FDZDtDQUNBLEtBQUssTUFBTSxlQUFlLEVBQUUsR0FBRyxhQUFhLEdBQUc7RUFDM0MsTUFBTSxVQUFVLGVBQWUsYUFBYSxVQUFVLFFBQVEsT0FBTztFQUNyRSxJQUFJLFNBQ0EsTUFBTTtDQUNkO0FBQ0o7Ozs7Ozs7Ozs7O0FBV0EsU0FBUyxJQUFJLE1BQU0sVUFBVSxFQUN6QixrQkFBa0IsTUFDdEIsR0FBRztDQUNDLE9BQU87RUFDSCxNQUFNO0VBQ04sVUFBVSxNQUFNLEtBQUssT0FBTyxNQUFNLE9BQU8sQ0FBQztDQUM5QztBQUNKIiwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdfQ==
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.