From 19772073ae31476bba25527e0a49ed10344c6342 Mon Sep 17 00:00:00 2001 From: Tobias Hopp Date: Sun, 21 May 2023 18:46:48 +0200 Subject: [PATCH] initial commit --- .dockerignore | 1 + .gitignore | 1 + .idea/.gitignore | 5 + .idea/jsLibraryMappings.xml | 7 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/pm25.iml | 13 + .idea/runConfigurations/bin_www.xml | 11 + Dockerfile | 19 + app.js | 39 + bin/dbHandler.js | 21 + bin/www | 90 + log.txt | 16 + main.js | 14 + models/PMEntry.js | 13 + models/Status.js | 14 + package.json | 23 + public/javascripts/main.js | 200 + public/javascripts/main2.js | 28 + public/javascripts/web.bundle.js | 15218 ++++++++++++++++++++++++++ public/stylesheets/style.css | 28 + routes/index.js | 64 + views/error.pug | 6 + views/index.pug | 7 + views/layout.pug | 10 + webpack.config.js | 27 + yarn.lock | 1773 +++ 27 files changed, 17663 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/jsLibraryMappings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/pm25.iml create mode 100644 .idea/runConfigurations/bin_www.xml create mode 100644 Dockerfile create mode 100644 app.js create mode 100644 bin/dbHandler.js create mode 100755 bin/www create mode 100644 log.txt create mode 100644 main.js create mode 100644 models/PMEntry.js create mode 100644 models/Status.js create mode 100644 package.json create mode 100644 public/javascripts/main.js create mode 100644 public/javascripts/main2.js create mode 100644 public/javascripts/web.bundle.js create mode 100644 public/stylesheets/style.css create mode 100644 routes/index.js create mode 100644 views/error.pug create mode 100644 views/index.pug create mode 100644 views/layout.pug create mode 100644 webpack.config.js create mode 100644 yarn.lock diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..8ce4854 --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ac27c87 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/pm25.iml b/.idea/pm25.iml new file mode 100644 index 0000000..9b5516c --- /dev/null +++ b/.idea/pm25.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/bin_www.xml b/.idea/runConfigurations/bin_www.xml new file mode 100644 index 0000000..14bb4af --- /dev/null +++ b/.idea/runConfigurations/bin_www.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..83f32ea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM node:18 + +# Create app directory +WORKDIR /app/ +VOLUME /app/ + +RUN npm install -g npm@latest + +COPY ./package.json ./ +RUN yarn + +EXPOSE 8081 + +COPY . . + +ENV MONGODB_URL="mongodb://db:27017/pm25" +ENV PORT=8081 +CMD DEBUG=pm25:* node main.js + diff --git a/app.js b/app.js new file mode 100644 index 0000000..835e677 --- /dev/null +++ b/app.js @@ -0,0 +1,39 @@ +const createError = require( "http-errors" ); +const express = require( "express" ); +const path = require( "path" ); +const cookieParser = require( "cookie-parser" ); +const logger = require( "morgan" ); + +const indexRouter = require( "./routes/index" ); + +const app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'pug'); + +app.use(logger('dev')); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', indexRouter); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +module.exports = app; diff --git a/bin/dbHandler.js b/bin/dbHandler.js new file mode 100644 index 0000000..f11be30 --- /dev/null +++ b/bin/dbHandler.js @@ -0,0 +1,21 @@ +const mongoose = require("mongoose"); +function connect( ) +{ + return new Promise( async (resolve, reject) => { + console.log("Connecting to DB...") + let url = process.env.MONGODB_URL || "mongodb://localhost:27017/pm25"; + try { + mongoose.connect(url, { + useNewUrlParser: true, + useUnifiedTopology: true + }) + resolve(); + console.log("Connected!"); + } catch( e ) + { + reject(e); + } + } ) + +} +module.exports = {connect} \ No newline at end of file diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..4bc7164 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +const app = require('../app'); +const debug = require('debug')('pm25:server'); +const http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +const port = normalizePort(process.env.PORT || '8081'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +const server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..3236b5c --- /dev/null +++ b/log.txt @@ -0,0 +1,16 @@ +yarn run v1.22.19 +$ node ./bin/www +GET / 304 454.863 ms - - +GET /stylesheets/style.css 304 4.045 ms - - +GET /javascripts/main.js 304 1.168 ms - - +info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. +yarn run v1.22.19 +$ node main.js +Starting PM2.5 Sensor Server +Connecting to DB... +Connected! +yarn run v1.22.19 +$ node main.js +Starting PM2.5 Sensor Server +Connecting to DB... +Connected! diff --git a/main.js b/main.js new file mode 100644 index 0000000..7153724 --- /dev/null +++ b/main.js @@ -0,0 +1,14 @@ + +const dbHandler = require("./bin/dbHandler"); + +console.log("Starting PM2.5 Sensor Server"); + + +async function main() +{ + await dbHandler.connect(); + + require("./bin/www"); // Starting Webserver +} +main(); + diff --git a/models/PMEntry.js b/models/PMEntry.js new file mode 100644 index 0000000..cb8bbb3 --- /dev/null +++ b/models/PMEntry.js @@ -0,0 +1,13 @@ +const mongoose = require( "mongoose" ); + +// PM2.5 = 2.10, PM10 = 5.30 +const schema = new mongoose.Schema( { + pm25: { type: Number, required: true }, + pm10:{ type: Number, required: true }, + sensor_name: {type: String} +}, { timestamps: true } ); +const Model = mongoose.model( + "PMEntry", + schema, +); +module.exports = Model; \ No newline at end of file diff --git a/models/Status.js b/models/Status.js new file mode 100644 index 0000000..1991922 --- /dev/null +++ b/models/Status.js @@ -0,0 +1,14 @@ +const mongoose = require( "mongoose" ); + +// PM2.5 = 2.10, PM10 = 5.30 +const schema = new mongoose.Schema( { + error: { type: Boolean, required: true }, + sleeping: { type: Boolean, required: true }, + ip: { type: String, required: true }, + +}, { timestamps: true } ); +const Model = mongoose.model( + "Status", + schema, +); +module.exports = Model; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..a220be6 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "pm25", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node main.js" + }, + "dependencies": { + "chart.js": "^4.3.0", + "chartjs-plugin-annotation": "^3.0.0", + "cookie-parser": "~1.4.4", + "debug": "~2.6.9", + "express": "~4.16.1", + "http-errors": "~1.6.3", + "mongoose": "^7.1.1", + "morgan": "~1.9.1", + "pug": "2.0.0-beta11" + }, + "devDependencies": { + "webpack": "^5.82.1", + "webpack-cli": "^5.1.1" + } +} diff --git a/public/javascripts/main.js b/public/javascripts/main.js new file mode 100644 index 0000000..5f6e3b9 --- /dev/null +++ b/public/javascripts/main.js @@ -0,0 +1,200 @@ +const lastStatus = document.getElementById("lastStatus"); + +const pm10 = document.getElementById("pm10"); +const pm25 = document.getElementById("pm25"); + + +// Define color ranges for the different value ranges +const colorRanges = { + good: 'rgba(154, 204, 91, 0.5)', + moderate: 'rgba(255, 235, 59, 0.5)', + unhealthySensitive: 'rgba(255, 152, 0, 0.5)', + unhealthy: 'rgba(255, 59, 59, 0.5)', + veryUnhealthy: 'rgba(143, 63, 151, 0.5)', + hazardous: 'rgba(126, 10, 2, 0.5)', +}; + +// Define the annotations +const annotations = { + annotations: + [ + { + type: 'box', + yMin: 0, + yMax: 12, + backgroundColor: colorRanges.good, + }, + { + type: 'box', + + yMin: 12.1, + yMax: 35.4, + backgroundColor: colorRanges.moderate, + }, + { + type: 'box', + + yMin: 35.5, + yMax: 55.4, + backgroundColor: colorRanges.unhealthySensitive, + }, + { + type: 'box', + + yMin: 55.5, + yMax: 150.4, + backgroundColor: colorRanges.unhealthy, + }, + { + type: 'box', + + yMin: 150.5, + yMax: 250.4, + backgroundColor: colorRanges.veryUnhealthy, + }, + { + type: 'box', + yMin: 250.5, + yMax: 500.4, + backgroundColor: colorRanges.hazardous, + }, + ] +}; + + +// Initialisiere das Chart-Objekt +var ctx = document.getElementById('chart').getContext('2d'); +var chart = new Chart(ctx, { + // Art des Diagramms + type: 'line', + + // Daten + data: { + labels: [], + datasets: [{ + label: 'PM2.5', + data: [], + backgroundColor: 'rgba(255, 99, 132, 0.2)', + borderColor: 'rgba(255,99,132,1)', + borderWidth: 2, + fill: false + }, { + label: 'PM10', + data: [], + backgroundColor: 'rgba(54, 162, 235, 0.2)', + borderColor: 'rgba(54, 162, 235, 1)', + borderWidth: 2, + fill: false + }] + }, + + // Konfigurationsoptionen + options: { + maintainAspectRatio: false, + responsive: true, + title: { + display: true, + text: 'Feinstaubwerte' + }, + scales: { + x: { + /*type: 'time', + time: { + unit: 'hour', + displayFormats: { + hour: 'MMM D, hA' + } + },*/ + display: true, + }, + y: { + display: true, + scaleLabel: { + display: true, + labelString: 'µg/m³' + }, + beginAtZero: true, + suggestedMin: 0, + suggestedMax: 10 + } + }, + plugins: { + annotation: annotations + }, + }, + +}); + +// Funktion zum Hinzufügen neuer Datenpunkte +function addData(time, pm25, pm10) { + // Füge die neuen Datenpunkte hinzu + chart.data.labels.push(time); + chart.data.datasets[0].data.push(pm25); + chart.data.datasets[1].data.push(pm10); + + // Begrenze die Anzahl der Datenpunkte auf 100 oder die letzten 12 Stunden + var maxPoints = 60; + var maxTime = new Date(); + maxTime.setHours(maxTime.getHours() - 12); + + while (chart.data.labels.length > maxPoints || (chart.data.labels.length > 0 && new Date(chart.data.labels[0]) < maxTime)) { + chart.data.labels.shift(); + chart.data.datasets[0].data.shift(); + chart.data.datasets[1].data.shift(); + } + + // Aktualisiere das Chart + chart.update(); +} + + + +setInterval(( ) => { + //addData(new Date().toLocaleTimeString(), 1+Math.floor(Math.random() *2), 3+Math.floor(Math.random() * 2)); + loadValues(); + loadStatus(); +}, 2000); + + +function httpGetAsync(theUrl) +{ + return new Promise( (resolve) => { + const xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState === 4 && xmlHttp.status === 200) + resolve(JSON.parse(xmlHttp.responseText)); + } + xmlHttp.open("GET", theUrl, true); // true for asynchronous + xmlHttp.send(null); + }) +} + + +let last_request = new Date(); +last_request.setDate(last_request.getDate()-1); + +function loadValues() +{ + return new Promise( async () => { + let data = await httpGetAsync("/data/" + last_request.getTime() ); + for( let entry of data ) + { + addData(new Date(entry.createdAt).toLocaleTimeString(), entry.pm25, entry.pm10) + pm25.innerText = "" + (Math.round(entry.pm25*100)/100); + pm10.innerText = "" + (Math.round(entry.pm10*100)/100); + } + last_request = new Date(); + }) +} +function loadStatus() +{ + return new Promise( async () => { + let data = await httpGetAsync("/status" ); + if( data.sleeping ) + lastStatus.innerHTML = "Letzter Status:
Schläft | " + (new Date(data.createdAt).toLocaleTimeString()) + "
Status: " + (data["error"] ? "Fehler!" : "OK"); + else + lastStatus.innerHTML = "Letzter Status:
Misst | " + (new Date(data.createdAt).toLocaleTimeString()) + "
Status: " + (data["error"] ? "Fehler!" : "OK"); + }) +} +loadStatus(); +loadValues(); \ No newline at end of file diff --git a/public/javascripts/main2.js b/public/javascripts/main2.js new file mode 100644 index 0000000..69d0da8 --- /dev/null +++ b/public/javascripts/main2.js @@ -0,0 +1,28 @@ +const options = { + type: 'line', + data: { + labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], + datasets: [{ + label: '# of Votes', + data: [12, 19, 3, 5, 2, 3], + borderWidth: 1 + }] + }, + options: { + plugins: { + annotation: { + annotations: { + box1: { + type: "box", + yMin: 5, + yMax: 10, + backgroundColor: "rgba(255, 99, 132, 0.25)" + } + } + } + } + } +} + +const ctx = document.getElementById('chart').getContext('2d'); +const chart = new Chart(ctx, options); \ No newline at end of file diff --git a/public/javascripts/web.bundle.js b/public/javascripts/web.bundle.js new file mode 100644 index 0000000..d53f41f --- /dev/null +++ b/public/javascripts/web.bundle.js @@ -0,0 +1,15218 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./node_modules/@kurkle/color/dist/color.esm.js": +/*!******************************************************!*\ + !*** ./node_modules/@kurkle/color/dist/color.esm.js ***! + \******************************************************/ +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "Color": () => (/* binding */ Color), +/* harmony export */ "b2n": () => (/* binding */ b2n), +/* harmony export */ "b2p": () => (/* binding */ b2p), +/* harmony export */ "default": () => (/* binding */ index_esm), +/* harmony export */ "hexParse": () => (/* binding */ hexParse), +/* harmony export */ "hexString": () => (/* binding */ hexString), +/* harmony export */ "hsl2rgb": () => (/* binding */ hsl2rgb), +/* harmony export */ "hslString": () => (/* binding */ hslString), +/* harmony export */ "hsv2rgb": () => (/* binding */ hsv2rgb), +/* harmony export */ "hueParse": () => (/* binding */ hueParse), +/* harmony export */ "hwb2rgb": () => (/* binding */ hwb2rgb), +/* harmony export */ "lim": () => (/* binding */ lim), +/* harmony export */ "n2b": () => (/* binding */ n2b), +/* harmony export */ "n2p": () => (/* binding */ n2p), +/* harmony export */ "nameParse": () => (/* binding */ nameParse), +/* harmony export */ "p2b": () => (/* binding */ p2b), +/* harmony export */ "rgb2hsl": () => (/* binding */ rgb2hsl), +/* harmony export */ "rgbParse": () => (/* binding */ rgbParse), +/* harmony export */ "rgbString": () => (/* binding */ rgbString), +/* harmony export */ "rotate": () => (/* binding */ rotate), +/* harmony export */ "round": () => (/* binding */ round) +/* harmony export */ }); +/*! + * @kurkle/color v0.3.2 + * https://github.com/kurkle/color#readme + * (c) 2023 Jukka Kurkela + * Released under the MIT License + */ +function round(v) { + return v + 0.5 | 0; +} +const lim = (v, l, h) => Math.max(Math.min(v, h), l); +function p2b(v) { + return lim(round(v * 2.55), 0, 255); +} +function b2p(v) { + return lim(round(v / 2.55), 0, 100); +} +function n2b(v) { + return lim(round(v * 255), 0, 255); +} +function b2n(v) { + return lim(round(v / 2.55) / 100, 0, 1); +} +function n2p(v) { + return lim(round(v * 100), 0, 100); +} + +const map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15}; +const hex = [...'0123456789ABCDEF']; +const h1 = b => hex[b & 0xF]; +const h2 = b => hex[(b & 0xF0) >> 4] + hex[b & 0xF]; +const eq = b => ((b & 0xF0) >> 4) === (b & 0xF); +const isShort = v => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a); +function hexParse(str) { + var len = str.length; + var ret; + if (str[0] === '#') { + if (len === 4 || len === 5) { + ret = { + r: 255 & map$1[str[1]] * 17, + g: 255 & map$1[str[2]] * 17, + b: 255 & map$1[str[3]] * 17, + a: len === 5 ? map$1[str[4]] * 17 : 255 + }; + } else if (len === 7 || len === 9) { + ret = { + r: map$1[str[1]] << 4 | map$1[str[2]], + g: map$1[str[3]] << 4 | map$1[str[4]], + b: map$1[str[5]] << 4 | map$1[str[6]], + a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255 + }; + } + } + return ret; +} +const alpha = (a, f) => a < 255 ? f(a) : ''; +function hexString(v) { + var f = isShort(v) ? h1 : h2; + return v + ? '#' + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f) + : undefined; +} + +const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/; +function hsl2rgbn(h, s, l) { + const a = s * Math.min(l, 1 - l); + const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); + return [f(0), f(8), f(4)]; +} +function hsv2rgbn(h, s, v) { + const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0); + return [f(5), f(3), f(1)]; +} +function hwb2rgbn(h, w, b) { + const rgb = hsl2rgbn(h, 1, 0.5); + let i; + if (w + b > 1) { + i = 1 / (w + b); + w *= i; + b *= i; + } + for (i = 0; i < 3; i++) { + rgb[i] *= 1 - w - b; + rgb[i] += w; + } + return rgb; +} +function hueValue(r, g, b, d, max) { + if (r === max) { + return ((g - b) / d) + (g < b ? 6 : 0); + } + if (g === max) { + return (b - r) / d + 2; + } + return (r - g) / d + 4; +} +function rgb2hsl(v) { + const range = 255; + const r = v.r / range; + const g = v.g / range; + const b = v.b / range; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const l = (max + min) / 2; + let h, s, d; + if (max !== min) { + d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + h = hueValue(r, g, b, d, max); + h = h * 60 + 0.5; + } + return [h | 0, s || 0, l]; +} +function calln(f, a, b, c) { + return ( + Array.isArray(a) + ? f(a[0], a[1], a[2]) + : f(a, b, c) + ).map(n2b); +} +function hsl2rgb(h, s, l) { + return calln(hsl2rgbn, h, s, l); +} +function hwb2rgb(h, w, b) { + return calln(hwb2rgbn, h, w, b); +} +function hsv2rgb(h, s, v) { + return calln(hsv2rgbn, h, s, v); +} +function hue(h) { + return (h % 360 + 360) % 360; +} +function hueParse(str) { + const m = HUE_RE.exec(str); + let a = 255; + let v; + if (!m) { + return; + } + if (m[5] !== v) { + a = m[6] ? p2b(+m[5]) : n2b(+m[5]); + } + const h = hue(+m[2]); + const p1 = +m[3] / 100; + const p2 = +m[4] / 100; + if (m[1] === 'hwb') { + v = hwb2rgb(h, p1, p2); + } else if (m[1] === 'hsv') { + v = hsv2rgb(h, p1, p2); + } else { + v = hsl2rgb(h, p1, p2); + } + return { + r: v[0], + g: v[1], + b: v[2], + a: a + }; +} +function rotate(v, deg) { + var h = rgb2hsl(v); + h[0] = hue(h[0] + deg); + h = hsl2rgb(h); + v.r = h[0]; + v.g = h[1]; + v.b = h[2]; +} +function hslString(v) { + if (!v) { + return; + } + const a = rgb2hsl(v); + const h = a[0]; + const s = n2p(a[1]); + const l = n2p(a[2]); + return v.a < 255 + ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})` + : `hsl(${h}, ${s}%, ${l}%)`; +} + +const map = { + x: 'dark', + Z: 'light', + Y: 're', + X: 'blu', + W: 'gr', + V: 'medium', + U: 'slate', + A: 'ee', + T: 'ol', + S: 'or', + B: 'ra', + C: 'lateg', + D: 'ights', + R: 'in', + Q: 'turquois', + E: 'hi', + P: 'ro', + O: 'al', + N: 'le', + M: 'de', + L: 'yello', + F: 'en', + K: 'ch', + G: 'arks', + H: 'ea', + I: 'ightg', + J: 'wh' +}; +const names$1 = { + OiceXe: 'f0f8ff', + antiquewEte: 'faebd7', + aqua: 'ffff', + aquamarRe: '7fffd4', + azuY: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '0', + blanKedOmond: 'ffebcd', + Xe: 'ff', + XeviTet: '8a2be2', + bPwn: 'a52a2a', + burlywood: 'deb887', + caMtXe: '5f9ea0', + KartYuse: '7fff00', + KocTate: 'd2691e', + cSO: 'ff7f50', + cSnflowerXe: '6495ed', + cSnsilk: 'fff8dc', + crimson: 'dc143c', + cyan: 'ffff', + xXe: '8b', + xcyan: '8b8b', + xgTMnPd: 'b8860b', + xWay: 'a9a9a9', + xgYF: '6400', + xgYy: 'a9a9a9', + xkhaki: 'bdb76b', + xmagFta: '8b008b', + xTivegYF: '556b2f', + xSange: 'ff8c00', + xScEd: '9932cc', + xYd: '8b0000', + xsOmon: 'e9967a', + xsHgYF: '8fbc8f', + xUXe: '483d8b', + xUWay: '2f4f4f', + xUgYy: '2f4f4f', + xQe: 'ced1', + xviTet: '9400d3', + dAppRk: 'ff1493', + dApskyXe: 'bfff', + dimWay: '696969', + dimgYy: '696969', + dodgerXe: '1e90ff', + fiYbrick: 'b22222', + flSOwEte: 'fffaf0', + foYstWAn: '228b22', + fuKsia: 'ff00ff', + gaRsbSo: 'dcdcdc', + ghostwEte: 'f8f8ff', + gTd: 'ffd700', + gTMnPd: 'daa520', + Way: '808080', + gYF: '8000', + gYFLw: 'adff2f', + gYy: '808080', + honeyMw: 'f0fff0', + hotpRk: 'ff69b4', + RdianYd: 'cd5c5c', + Rdigo: '4b0082', + ivSy: 'fffff0', + khaki: 'f0e68c', + lavFMr: 'e6e6fa', + lavFMrXsh: 'fff0f5', + lawngYF: '7cfc00', + NmoncEffon: 'fffacd', + ZXe: 'add8e6', + ZcSO: 'f08080', + Zcyan: 'e0ffff', + ZgTMnPdLw: 'fafad2', + ZWay: 'd3d3d3', + ZgYF: '90ee90', + ZgYy: 'd3d3d3', + ZpRk: 'ffb6c1', + ZsOmon: 'ffa07a', + ZsHgYF: '20b2aa', + ZskyXe: '87cefa', + ZUWay: '778899', + ZUgYy: '778899', + ZstAlXe: 'b0c4de', + ZLw: 'ffffe0', + lime: 'ff00', + limegYF: '32cd32', + lRF: 'faf0e6', + magFta: 'ff00ff', + maPon: '800000', + VaquamarRe: '66cdaa', + VXe: 'cd', + VScEd: 'ba55d3', + VpurpN: '9370db', + VsHgYF: '3cb371', + VUXe: '7b68ee', + VsprRggYF: 'fa9a', + VQe: '48d1cc', + VviTetYd: 'c71585', + midnightXe: '191970', + mRtcYam: 'f5fffa', + mistyPse: 'ffe4e1', + moccasR: 'ffe4b5', + navajowEte: 'ffdead', + navy: '80', + Tdlace: 'fdf5e6', + Tive: '808000', + TivedBb: '6b8e23', + Sange: 'ffa500', + SangeYd: 'ff4500', + ScEd: 'da70d6', + pOegTMnPd: 'eee8aa', + pOegYF: '98fb98', + pOeQe: 'afeeee', + pOeviTetYd: 'db7093', + papayawEp: 'ffefd5', + pHKpuff: 'ffdab9', + peru: 'cd853f', + pRk: 'ffc0cb', + plum: 'dda0dd', + powMrXe: 'b0e0e6', + purpN: '800080', + YbeccapurpN: '663399', + Yd: 'ff0000', + Psybrown: 'bc8f8f', + PyOXe: '4169e1', + saddNbPwn: '8b4513', + sOmon: 'fa8072', + sandybPwn: 'f4a460', + sHgYF: '2e8b57', + sHshell: 'fff5ee', + siFna: 'a0522d', + silver: 'c0c0c0', + skyXe: '87ceeb', + UXe: '6a5acd', + UWay: '708090', + UgYy: '708090', + snow: 'fffafa', + sprRggYF: 'ff7f', + stAlXe: '4682b4', + tan: 'd2b48c', + teO: '8080', + tEstN: 'd8bfd8', + tomato: 'ff6347', + Qe: '40e0d0', + viTet: 'ee82ee', + JHt: 'f5deb3', + wEte: 'ffffff', + wEtesmoke: 'f5f5f5', + Lw: 'ffff00', + LwgYF: '9acd32' +}; +function unpack() { + const unpacked = {}; + const keys = Object.keys(names$1); + const tkeys = Object.keys(map); + let i, j, k, ok, nk; + for (i = 0; i < keys.length; i++) { + ok = nk = keys[i]; + for (j = 0; j < tkeys.length; j++) { + k = tkeys[j]; + nk = nk.replace(k, map[k]); + } + k = parseInt(names$1[ok], 16); + unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF]; + } + return unpacked; +} + +let names; +function nameParse(str) { + if (!names) { + names = unpack(); + names.transparent = [0, 0, 0, 0]; + } + const a = names[str.toLowerCase()]; + return a && { + r: a[0], + g: a[1], + b: a[2], + a: a.length === 4 ? a[3] : 255 + }; +} + +const RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/; +function rgbParse(str) { + const m = RGB_RE.exec(str); + let a = 255; + let r, g, b; + if (!m) { + return; + } + if (m[7] !== r) { + const v = +m[7]; + a = m[8] ? p2b(v) : lim(v * 255, 0, 255); + } + r = +m[1]; + g = +m[3]; + b = +m[5]; + r = 255 & (m[2] ? p2b(r) : lim(r, 0, 255)); + g = 255 & (m[4] ? p2b(g) : lim(g, 0, 255)); + b = 255 & (m[6] ? p2b(b) : lim(b, 0, 255)); + return { + r: r, + g: g, + b: b, + a: a + }; +} +function rgbString(v) { + return v && ( + v.a < 255 + ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})` + : `rgb(${v.r}, ${v.g}, ${v.b})` + ); +} + +const to = v => v <= 0.0031308 ? v * 12.92 : Math.pow(v, 1.0 / 2.4) * 1.055 - 0.055; +const from = v => v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); +function interpolate(rgb1, rgb2, t) { + const r = from(b2n(rgb1.r)); + const g = from(b2n(rgb1.g)); + const b = from(b2n(rgb1.b)); + return { + r: n2b(to(r + t * (from(b2n(rgb2.r)) - r))), + g: n2b(to(g + t * (from(b2n(rgb2.g)) - g))), + b: n2b(to(b + t * (from(b2n(rgb2.b)) - b))), + a: rgb1.a + t * (rgb2.a - rgb1.a) + }; +} + +function modHSL(v, i, ratio) { + if (v) { + let tmp = rgb2hsl(v); + tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1)); + tmp = hsl2rgb(tmp); + v.r = tmp[0]; + v.g = tmp[1]; + v.b = tmp[2]; + } +} +function clone(v, proto) { + return v ? Object.assign(proto || {}, v) : v; +} +function fromObject(input) { + var v = {r: 0, g: 0, b: 0, a: 255}; + if (Array.isArray(input)) { + if (input.length >= 3) { + v = {r: input[0], g: input[1], b: input[2], a: 255}; + if (input.length > 3) { + v.a = n2b(input[3]); + } + } + } else { + v = clone(input, {r: 0, g: 0, b: 0, a: 1}); + v.a = n2b(v.a); + } + return v; +} +function functionParse(str) { + if (str.charAt(0) === 'r') { + return rgbParse(str); + } + return hueParse(str); +} +class Color { + constructor(input) { + if (input instanceof Color) { + return input; + } + const type = typeof input; + let v; + if (type === 'object') { + v = fromObject(input); + } else if (type === 'string') { + v = hexParse(input) || nameParse(input) || functionParse(input); + } + this._rgb = v; + this._valid = !!v; + } + get valid() { + return this._valid; + } + get rgb() { + var v = clone(this._rgb); + if (v) { + v.a = b2n(v.a); + } + return v; + } + set rgb(obj) { + this._rgb = fromObject(obj); + } + rgbString() { + return this._valid ? rgbString(this._rgb) : undefined; + } + hexString() { + return this._valid ? hexString(this._rgb) : undefined; + } + hslString() { + return this._valid ? hslString(this._rgb) : undefined; + } + mix(color, weight) { + if (color) { + const c1 = this.rgb; + const c2 = color.rgb; + let w2; + const p = weight === w2 ? 0.5 : weight; + const w = 2 * p - 1; + const a = c1.a - c2.a; + const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + w2 = 1 - w1; + c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5; + c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5; + c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5; + c1.a = p * c1.a + (1 - p) * c2.a; + this.rgb = c1; + } + return this; + } + interpolate(color, t) { + if (color) { + this._rgb = interpolate(this._rgb, color._rgb, t); + } + return this; + } + clone() { + return new Color(this.rgb); + } + alpha(a) { + this._rgb.a = n2b(a); + return this; + } + clearer(ratio) { + const rgb = this._rgb; + rgb.a *= 1 - ratio; + return this; + } + greyscale() { + const rgb = this._rgb; + const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11); + rgb.r = rgb.g = rgb.b = val; + return this; + } + opaquer(ratio) { + const rgb = this._rgb; + rgb.a *= 1 + ratio; + return this; + } + negate() { + const v = this._rgb; + v.r = 255 - v.r; + v.g = 255 - v.g; + v.b = 255 - v.b; + return this; + } + lighten(ratio) { + modHSL(this._rgb, 2, ratio); + return this; + } + darken(ratio) { + modHSL(this._rgb, 2, -ratio); + return this; + } + saturate(ratio) { + modHSL(this._rgb, 1, ratio); + return this; + } + desaturate(ratio) { + modHSL(this._rgb, 1, -ratio); + return this; + } + rotate(deg) { + rotate(this._rgb, deg); + return this; + } +} + +function index_esm(input) { + return new Color(input); +} + + + + +/***/ }), + +/***/ "./node_modules/chart.js/dist/chart.js": +/*!*********************************************!*\ + !*** ./node_modules/chart.js/dist/chart.js ***! + \*********************************************/ +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "Animation": () => (/* binding */ Animation), +/* harmony export */ "Animations": () => (/* binding */ Animations), +/* harmony export */ "ArcElement": () => (/* binding */ ArcElement), +/* harmony export */ "BarController": () => (/* binding */ BarController), +/* harmony export */ "BarElement": () => (/* binding */ BarElement), +/* harmony export */ "BasePlatform": () => (/* binding */ BasePlatform), +/* harmony export */ "BasicPlatform": () => (/* binding */ BasicPlatform), +/* harmony export */ "BubbleController": () => (/* binding */ BubbleController), +/* harmony export */ "CategoryScale": () => (/* binding */ CategoryScale), +/* harmony export */ "Chart": () => (/* binding */ Chart), +/* harmony export */ "Colors": () => (/* binding */ plugin_colors), +/* harmony export */ "DatasetController": () => (/* binding */ DatasetController), +/* harmony export */ "Decimation": () => (/* binding */ plugin_decimation), +/* harmony export */ "DomPlatform": () => (/* binding */ DomPlatform), +/* harmony export */ "DoughnutController": () => (/* binding */ DoughnutController), +/* harmony export */ "Element": () => (/* binding */ Element), +/* harmony export */ "Filler": () => (/* binding */ index), +/* harmony export */ "Interaction": () => (/* binding */ Interaction), +/* harmony export */ "Legend": () => (/* binding */ plugin_legend), +/* harmony export */ "LineController": () => (/* binding */ LineController), +/* harmony export */ "LineElement": () => (/* binding */ LineElement), +/* harmony export */ "LinearScale": () => (/* binding */ LinearScale), +/* harmony export */ "LogarithmicScale": () => (/* binding */ LogarithmicScale), +/* harmony export */ "PieController": () => (/* binding */ PieController), +/* harmony export */ "PointElement": () => (/* binding */ PointElement), +/* harmony export */ "PolarAreaController": () => (/* binding */ PolarAreaController), +/* harmony export */ "RadarController": () => (/* binding */ RadarController), +/* harmony export */ "RadialLinearScale": () => (/* binding */ RadialLinearScale), +/* harmony export */ "Scale": () => (/* binding */ Scale), +/* harmony export */ "ScatterController": () => (/* binding */ ScatterController), +/* harmony export */ "SubTitle": () => (/* binding */ plugin_subtitle), +/* harmony export */ "Ticks": () => (/* reexport safe */ _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aL), +/* harmony export */ "TimeScale": () => (/* binding */ TimeScale), +/* harmony export */ "TimeSeriesScale": () => (/* binding */ TimeSeriesScale), +/* harmony export */ "Title": () => (/* binding */ plugin_title), +/* harmony export */ "Tooltip": () => (/* binding */ plugin_tooltip), +/* harmony export */ "_adapters": () => (/* binding */ adapters), +/* harmony export */ "_detectPlatform": () => (/* binding */ _detectPlatform), +/* harmony export */ "animator": () => (/* binding */ animator), +/* harmony export */ "controllers": () => (/* binding */ controllers), +/* harmony export */ "defaults": () => (/* reexport safe */ _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d), +/* harmony export */ "elements": () => (/* binding */ elements), +/* harmony export */ "layouts": () => (/* binding */ layouts), +/* harmony export */ "plugins": () => (/* binding */ plugins), +/* harmony export */ "registerables": () => (/* binding */ registerables), +/* harmony export */ "registry": () => (/* binding */ registry), +/* harmony export */ "scales": () => (/* binding */ scales) +/* harmony export */ }); +/* harmony import */ var _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunks/helpers.segment.js */ "./node_modules/chart.js/dist/chunks/helpers.segment.js"); +/*! + * Chart.js v4.3.0 + * https://www.chartjs.org + * (c) 2023 Chart.js Contributors + * Released under the MIT License + */ + + + +class Animator { + constructor(){ + this._request = null; + this._charts = new Map(); + this._running = false; + this._lastDate = undefined; + } + _notify(chart, anims, date, type) { + const callbacks = anims.listeners[type]; + const numSteps = anims.duration; + callbacks.forEach((fn)=>fn({ + chart, + initial: anims.initial, + numSteps, + currentStep: Math.min(date - anims.start, numSteps) + })); + } + _refresh() { + if (this._request) { + return; + } + this._running = true; + this._request = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.r.call(window, ()=>{ + this._update(); + this._request = null; + if (this._running) { + this._refresh(); + } + }); + } + _update(date = Date.now()) { + let remaining = 0; + this._charts.forEach((anims, chart)=>{ + if (!anims.running || !anims.items.length) { + return; + } + const items = anims.items; + let i = items.length - 1; + let draw = false; + let item; + for(; i >= 0; --i){ + item = items[i]; + if (item._active) { + if (item._total > anims.duration) { + anims.duration = item._total; + } + item.tick(date); + draw = true; + } else { + items[i] = items[items.length - 1]; + items.pop(); + } + } + if (draw) { + chart.draw(); + this._notify(chart, anims, date, 'progress'); + } + if (!items.length) { + anims.running = false; + this._notify(chart, anims, date, 'complete'); + anims.initial = false; + } + remaining += items.length; + }); + this._lastDate = date; + if (remaining === 0) { + this._running = false; + } + } + _getAnims(chart) { + const charts = this._charts; + let anims = charts.get(chart); + if (!anims) { + anims = { + running: false, + initial: true, + items: [], + listeners: { + complete: [], + progress: [] + } + }; + charts.set(chart, anims); + } + return anims; + } + listen(chart, event, cb) { + this._getAnims(chart).listeners[event].push(cb); + } + add(chart, items) { + if (!items || !items.length) { + return; + } + this._getAnims(chart).items.push(...items); + } + has(chart) { + return this._getAnims(chart).items.length > 0; + } + start(chart) { + const anims = this._charts.get(chart); + if (!anims) { + return; + } + anims.running = true; + anims.start = Date.now(); + anims.duration = anims.items.reduce((acc, cur)=>Math.max(acc, cur._duration), 0); + this._refresh(); + } + running(chart) { + if (!this._running) { + return false; + } + const anims = this._charts.get(chart); + if (!anims || !anims.running || !anims.items.length) { + return false; + } + return true; + } + stop(chart) { + const anims = this._charts.get(chart); + if (!anims || !anims.items.length) { + return; + } + const items = anims.items; + let i = items.length - 1; + for(; i >= 0; --i){ + items[i].cancel(); + } + anims.items = []; + this._notify(chart, anims, Date.now(), 'complete'); + } + remove(chart) { + return this._charts.delete(chart); + } +} +var animator = /* #__PURE__ */ new Animator(); + +const transparent = 'transparent'; +const interpolators = { + boolean (from, to, factor) { + return factor > 0.5 ? to : from; + }, + color (from, to, factor) { + const c0 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.c)(from || transparent); + const c1 = c0.valid && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.c)(to || transparent); + return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to; + }, + number (from, to, factor) { + return from + (to - from) * factor; + } +}; +class Animation { + constructor(cfg, target, prop, to){ + const currentValue = target[prop]; + to = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([ + cfg.to, + to, + currentValue, + cfg.from + ]); + const from = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([ + cfg.from, + currentValue, + to + ]); + this._active = true; + this._fn = cfg.fn || interpolators[cfg.type || typeof from]; + this._easing = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.e[cfg.easing] || _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.e.linear; + this._start = Math.floor(Date.now() + (cfg.delay || 0)); + this._duration = this._total = Math.floor(cfg.duration); + this._loop = !!cfg.loop; + this._target = target; + this._prop = prop; + this._from = from; + this._to = to; + this._promises = undefined; + } + active() { + return this._active; + } + update(cfg, to, date) { + if (this._active) { + this._notify(false); + const currentValue = this._target[this._prop]; + const elapsed = date - this._start; + const remain = this._duration - elapsed; + this._start = date; + this._duration = Math.floor(Math.max(remain, cfg.duration)); + this._total += elapsed; + this._loop = !!cfg.loop; + this._to = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([ + cfg.to, + to, + currentValue, + cfg.from + ]); + this._from = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([ + cfg.from, + currentValue, + to + ]); + } + } + cancel() { + if (this._active) { + this.tick(Date.now()); + this._active = false; + this._notify(false); + } + } + tick(date) { + const elapsed = date - this._start; + const duration = this._duration; + const prop = this._prop; + const from = this._from; + const loop = this._loop; + const to = this._to; + let factor; + this._active = from !== to && (loop || elapsed < duration); + if (!this._active) { + this._target[prop] = to; + this._notify(true); + return; + } + if (elapsed < 0) { + this._target[prop] = from; + return; + } + factor = elapsed / duration % 2; + factor = loop && factor > 1 ? 2 - factor : factor; + factor = this._easing(Math.min(1, Math.max(0, factor))); + this._target[prop] = this._fn(from, to, factor); + } + wait() { + const promises = this._promises || (this._promises = []); + return new Promise((res, rej)=>{ + promises.push({ + res, + rej + }); + }); + } + _notify(resolved) { + const method = resolved ? 'res' : 'rej'; + const promises = this._promises || []; + for(let i = 0; i < promises.length; i++){ + promises[i][method](); + } + } +} + +class Animations { + constructor(chart, config){ + this._chart = chart; + this._properties = new Map(); + this.configure(config); + } + configure(config) { + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(config)) { + return; + } + const animationOptions = Object.keys(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.animation); + const animatedProps = this._properties; + Object.getOwnPropertyNames(config).forEach((key)=>{ + const cfg = config[key]; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(cfg)) { + return; + } + const resolved = {}; + for (const option of animationOptions){ + resolved[option] = cfg[option]; + } + ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(cfg.properties) && cfg.properties || [ + key + ]).forEach((prop)=>{ + if (prop === key || !animatedProps.has(prop)) { + animatedProps.set(prop, resolved); + } + }); + }); + } + _animateOptions(target, values) { + const newOptions = values.options; + const options = resolveTargetOptions(target, newOptions); + if (!options) { + return []; + } + const animations = this._createAnimations(options, newOptions); + if (newOptions.$shared) { + awaitAll(target.options.$animations, newOptions).then(()=>{ + target.options = newOptions; + }, ()=>{ + }); + } + return animations; + } + _createAnimations(target, values) { + const animatedProps = this._properties; + const animations = []; + const running = target.$animations || (target.$animations = {}); + const props = Object.keys(values); + const date = Date.now(); + let i; + for(i = props.length - 1; i >= 0; --i){ + const prop = props[i]; + if (prop.charAt(0) === '$') { + continue; + } + if (prop === 'options') { + animations.push(...this._animateOptions(target, values)); + continue; + } + const value = values[prop]; + let animation = running[prop]; + const cfg = animatedProps.get(prop); + if (animation) { + if (cfg && animation.active()) { + animation.update(cfg, value, date); + continue; + } else { + animation.cancel(); + } + } + if (!cfg || !cfg.duration) { + target[prop] = value; + continue; + } + running[prop] = animation = new Animation(cfg, target, prop, value); + animations.push(animation); + } + return animations; + } + update(target, values) { + if (this._properties.size === 0) { + Object.assign(target, values); + return; + } + const animations = this._createAnimations(target, values); + if (animations.length) { + animator.add(this._chart, animations); + return true; + } + } +} +function awaitAll(animations, properties) { + const running = []; + const keys = Object.keys(properties); + for(let i = 0; i < keys.length; i++){ + const anim = animations[keys[i]]; + if (anim && anim.active()) { + running.push(anim.wait()); + } + } + return Promise.all(running); +} +function resolveTargetOptions(target, newOptions) { + if (!newOptions) { + return; + } + let options = target.options; + if (!options) { + target.options = newOptions; + return; + } + if (options.$shared) { + target.options = options = Object.assign({}, options, { + $shared: false, + $animations: {} + }); + } + return options; +} + +function scaleClip(scale, allowedOverflow) { + const opts = scale && scale.options || {}; + const reverse = opts.reverse; + const min = opts.min === undefined ? allowedOverflow : 0; + const max = opts.max === undefined ? allowedOverflow : 0; + return { + start: reverse ? max : min, + end: reverse ? min : max + }; +} +function defaultClip(xScale, yScale, allowedOverflow) { + if (allowedOverflow === false) { + return false; + } + const x = scaleClip(xScale, allowedOverflow); + const y = scaleClip(yScale, allowedOverflow); + return { + top: y.end, + right: x.end, + bottom: y.start, + left: x.start + }; +} +function toClip(value) { + let t, r, b, l; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(value)) { + t = value.top; + r = value.right; + b = value.bottom; + l = value.left; + } else { + t = r = b = l = value; + } + return { + top: t, + right: r, + bottom: b, + left: l, + disabled: value === false + }; +} +function getSortedDatasetIndices(chart, filterVisible) { + const keys = []; + const metasets = chart._getSortedDatasetMetas(filterVisible); + let i, ilen; + for(i = 0, ilen = metasets.length; i < ilen; ++i){ + keys.push(metasets[i].index); + } + return keys; +} +function applyStack(stack, value, dsIndex, options = {}) { + const keys = stack.keys; + const singleMode = options.mode === 'single'; + let i, ilen, datasetIndex, otherValue; + if (value === null) { + return; + } + for(i = 0, ilen = keys.length; i < ilen; ++i){ + datasetIndex = +keys[i]; + if (datasetIndex === dsIndex) { + if (options.all) { + continue; + } + break; + } + otherValue = stack.values[datasetIndex]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(otherValue) && (singleMode || value === 0 || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) === (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(otherValue))) { + value += otherValue; + } + } + return value; +} +function convertObjectDataToArray(data) { + const keys = Object.keys(data); + const adata = new Array(keys.length); + let i, ilen, key; + for(i = 0, ilen = keys.length; i < ilen; ++i){ + key = keys[i]; + adata[i] = { + x: key, + y: data[key] + }; + } + return adata; +} +function isStacked(scale, meta) { + const stacked = scale && scale.options.stacked; + return stacked || stacked === undefined && meta.stack !== undefined; +} +function getStackKey(indexScale, valueScale, meta) { + return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`; +} +function getUserBounds(scale) { + const { min , max , minDefined , maxDefined } = scale.getUserBounds(); + return { + min: minDefined ? min : Number.NEGATIVE_INFINITY, + max: maxDefined ? max : Number.POSITIVE_INFINITY + }; +} +function getOrCreateStack(stacks, stackKey, indexValue) { + const subStack = stacks[stackKey] || (stacks[stackKey] = {}); + return subStack[indexValue] || (subStack[indexValue] = {}); +} +function getLastIndexInStack(stack, vScale, positive, type) { + for (const meta of vScale.getMatchingVisibleMetas(type).reverse()){ + const value = stack[meta.index]; + if (positive && value > 0 || !positive && value < 0) { + return meta.index; + } + } + return null; +} +function updateStacks(controller, parsed) { + const { chart , _cachedMeta: meta } = controller; + const stacks = chart._stacks || (chart._stacks = {}); + const { iScale , vScale , index: datasetIndex } = meta; + const iAxis = iScale.axis; + const vAxis = vScale.axis; + const key = getStackKey(iScale, vScale, meta); + const ilen = parsed.length; + let stack; + for(let i = 0; i < ilen; ++i){ + const item = parsed[i]; + const { [iAxis]: index , [vAxis]: value } = item; + const itemStacks = item._stacks || (item._stacks = {}); + stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index); + stack[datasetIndex] = value; + stack._top = getLastIndexInStack(stack, vScale, true, meta.type); + stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type); + const visualValues = stack._visualValues || (stack._visualValues = {}); + visualValues[datasetIndex] = value; + } +} +function getFirstScaleId(chart, axis) { + const scales = chart.scales; + return Object.keys(scales).filter((key)=>scales[key].axis === axis).shift(); +} +function createDatasetContext(parent, index) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + active: false, + dataset: undefined, + datasetIndex: index, + index, + mode: 'default', + type: 'dataset' + }); +} +function createDataContext(parent, index, element) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + active: false, + dataIndex: index, + parsed: undefined, + raw: undefined, + element, + index, + mode: 'default', + type: 'data' + }); +} +function clearStacks(meta, items) { + const datasetIndex = meta.controller.index; + const axis = meta.vScale && meta.vScale.axis; + if (!axis) { + return; + } + items = items || meta._parsed; + for (const parsed of items){ + const stacks = parsed._stacks; + if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) { + return; + } + delete stacks[axis][datasetIndex]; + if (stacks[axis]._visualValues !== undefined && stacks[axis]._visualValues[datasetIndex] !== undefined) { + delete stacks[axis]._visualValues[datasetIndex]; + } + } +} +const isDirectUpdateMode = (mode)=>mode === 'reset' || mode === 'none'; +const cloneIfNotShared = (cached, shared)=>shared ? cached : Object.assign({}, cached); +const createStack = (canStack, meta, chart)=>canStack && !meta.hidden && meta._stacked && { + keys: getSortedDatasetIndices(chart, true), + values: null + }; +class DatasetController { + static defaults = {}; + static datasetElementType = null; + static dataElementType = null; + constructor(chart, datasetIndex){ + this.chart = chart; + this._ctx = chart.ctx; + this.index = datasetIndex; + this._cachedDataOpts = {}; + this._cachedMeta = this.getMeta(); + this._type = this._cachedMeta.type; + this.options = undefined; + this._parsing = false; + this._data = undefined; + this._objectData = undefined; + this._sharedOptions = undefined; + this._drawStart = undefined; + this._drawCount = undefined; + this.enableOptionSharing = false; + this.supportsDecimation = false; + this.$context = undefined; + this._syncList = []; + this.datasetElementType = new.target.datasetElementType; + this.dataElementType = new.target.dataElementType; + this.initialize(); + } + initialize() { + const meta = this._cachedMeta; + this.configure(); + this.linkScales(); + meta._stacked = isStacked(meta.vScale, meta); + this.addElements(); + if (this.options.fill && !this.chart.isPluginEnabled('filler')) { + console.warn("Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options"); + } + } + updateIndex(datasetIndex) { + if (this.index !== datasetIndex) { + clearStacks(this._cachedMeta); + } + this.index = datasetIndex; + } + linkScales() { + const chart = this.chart; + const meta = this._cachedMeta; + const dataset = this.getDataset(); + const chooseId = (axis, x, y, r)=>axis === 'x' ? x : axis === 'r' ? r : y; + const xid = meta.xAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.xAxisID, getFirstScaleId(chart, 'x')); + const yid = meta.yAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.yAxisID, getFirstScaleId(chart, 'y')); + const rid = meta.rAxisID = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(dataset.rAxisID, getFirstScaleId(chart, 'r')); + const indexAxis = meta.indexAxis; + const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid); + const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid); + meta.xScale = this.getScaleForId(xid); + meta.yScale = this.getScaleForId(yid); + meta.rScale = this.getScaleForId(rid); + meta.iScale = this.getScaleForId(iid); + meta.vScale = this.getScaleForId(vid); + } + getDataset() { + return this.chart.data.datasets[this.index]; + } + getMeta() { + return this.chart.getDatasetMeta(this.index); + } + getScaleForId(scaleID) { + return this.chart.scales[scaleID]; + } + _getOtherScale(scale) { + const meta = this._cachedMeta; + return scale === meta.iScale ? meta.vScale : meta.iScale; + } + reset() { + this._update('reset'); + } + _destroy() { + const meta = this._cachedMeta; + if (this._data) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.u)(this._data, this); + } + if (meta._stacked) { + clearStacks(meta); + } + } + _dataCheck() { + const dataset = this.getDataset(); + const data = dataset.data || (dataset.data = []); + const _data = this._data; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(data)) { + this._data = convertObjectDataToArray(data); + } else if (_data !== data) { + if (_data) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.u)(_data, this); + const meta = this._cachedMeta; + clearStacks(meta); + meta._parsed = []; + } + if (data && Object.isExtensible(data)) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.l)(data, this); + } + this._syncList = []; + this._data = data; + } + } + addElements() { + const meta = this._cachedMeta; + this._dataCheck(); + if (this.datasetElementType) { + meta.dataset = new this.datasetElementType(); + } + } + buildOrUpdateElements(resetNewElements) { + const meta = this._cachedMeta; + const dataset = this.getDataset(); + let stackChanged = false; + this._dataCheck(); + const oldStacked = meta._stacked; + meta._stacked = isStacked(meta.vScale, meta); + if (meta.stack !== dataset.stack) { + stackChanged = true; + clearStacks(meta); + meta.stack = dataset.stack; + } + this._resyncElements(resetNewElements); + if (stackChanged || oldStacked !== meta._stacked) { + updateStacks(this, meta._parsed); + } + } + configure() { + const config = this.chart.config; + const scopeKeys = config.datasetScopeKeys(this._type); + const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true); + this.options = config.createResolver(scopes, this.getContext()); + this._parsing = this.options.parsing; + this._cachedDataOpts = {}; + } + parse(start, count) { + const { _cachedMeta: meta , _data: data } = this; + const { iScale , _stacked } = meta; + const iAxis = iScale.axis; + let sorted = start === 0 && count === data.length ? true : meta._sorted; + let prev = start > 0 && meta._parsed[start - 1]; + let i, cur, parsed; + if (this._parsing === false) { + meta._parsed = data; + meta._sorted = true; + parsed = data; + } else { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(data[start])) { + parsed = this.parseArrayData(meta, data, start, count); + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) { + parsed = this.parseObjectData(meta, data, start, count); + } else { + parsed = this.parsePrimitiveData(meta, data, start, count); + } + const isNotInOrderComparedToPrev = ()=>cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis]; + for(i = 0; i < count; ++i){ + meta._parsed[i + start] = cur = parsed[i]; + if (sorted) { + if (isNotInOrderComparedToPrev()) { + sorted = false; + } + prev = cur; + } + } + meta._sorted = sorted; + } + if (_stacked) { + updateStacks(this, parsed); + } + } + parsePrimitiveData(meta, data, start, count) { + const { iScale , vScale } = meta; + const iAxis = iScale.axis; + const vAxis = vScale.axis; + const labels = iScale.getLabels(); + const singleScale = iScale === vScale; + const parsed = new Array(count); + let i, ilen, index; + for(i = 0, ilen = count; i < ilen; ++i){ + index = i + start; + parsed[i] = { + [iAxis]: singleScale || iScale.parse(labels[index], index), + [vAxis]: vScale.parse(data[index], index) + }; + } + return parsed; + } + parseArrayData(meta, data, start, count) { + const { xScale , yScale } = meta; + const parsed = new Array(count); + let i, ilen, index, item; + for(i = 0, ilen = count; i < ilen; ++i){ + index = i + start; + item = data[index]; + parsed[i] = { + x: xScale.parse(item[0], index), + y: yScale.parse(item[1], index) + }; + } + return parsed; + } + parseObjectData(meta, data, start, count) { + const { xScale , yScale } = meta; + const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing; + const parsed = new Array(count); + let i, ilen, index, item; + for(i = 0, ilen = count; i < ilen; ++i){ + index = i + start; + item = data[index]; + parsed[i] = { + x: xScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, xAxisKey), index), + y: yScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(item, yAxisKey), index) + }; + } + return parsed; + } + getParsed(index) { + return this._cachedMeta._parsed[index]; + } + getDataElement(index) { + return this._cachedMeta.data[index]; + } + applyStack(scale, parsed, mode) { + const chart = this.chart; + const meta = this._cachedMeta; + const value = parsed[scale.axis]; + const stack = { + keys: getSortedDatasetIndices(chart, true), + values: parsed._stacks[scale.axis]._visualValues + }; + return applyStack(stack, value, meta.index, { + mode + }); + } + updateRangeFromParsed(range, scale, parsed, stack) { + const parsedValue = parsed[scale.axis]; + let value = parsedValue === null ? NaN : parsedValue; + const values = stack && parsed._stacks[scale.axis]; + if (stack && values) { + stack.values = values; + value = applyStack(stack, parsedValue, this._cachedMeta.index); + } + range.min = Math.min(range.min, value); + range.max = Math.max(range.max, value); + } + getMinMax(scale, canStack) { + const meta = this._cachedMeta; + const _parsed = meta._parsed; + const sorted = meta._sorted && scale === meta.iScale; + const ilen = _parsed.length; + const otherScale = this._getOtherScale(scale); + const stack = createStack(canStack, meta, this.chart); + const range = { + min: Number.POSITIVE_INFINITY, + max: Number.NEGATIVE_INFINITY + }; + const { min: otherMin , max: otherMax } = getUserBounds(otherScale); + let i, parsed; + function _skip() { + parsed = _parsed[i]; + const otherValue = parsed[otherScale.axis]; + return !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue; + } + for(i = 0; i < ilen; ++i){ + if (_skip()) { + continue; + } + this.updateRangeFromParsed(range, scale, parsed, stack); + if (sorted) { + break; + } + } + if (sorted) { + for(i = ilen - 1; i >= 0; --i){ + if (_skip()) { + continue; + } + this.updateRangeFromParsed(range, scale, parsed, stack); + break; + } + } + return range; + } + getAllParsedValues(scale) { + const parsed = this._cachedMeta._parsed; + const values = []; + let i, ilen, value; + for(i = 0, ilen = parsed.length; i < ilen; ++i){ + value = parsed[i][scale.axis]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) { + values.push(value); + } + } + return values; + } + getMaxOverflow() { + return false; + } + getLabelAndValue(index) { + const meta = this._cachedMeta; + const iScale = meta.iScale; + const vScale = meta.vScale; + const parsed = this.getParsed(index); + return { + label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '', + value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : '' + }; + } + _update(mode) { + const meta = this._cachedMeta; + this.update(mode || 'default'); + meta._clip = toClip((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow()))); + } + update(mode) {} + draw() { + const ctx = this._ctx; + const chart = this.chart; + const meta = this._cachedMeta; + const elements = meta.data || []; + const area = chart.chartArea; + const active = []; + const start = this._drawStart || 0; + const count = this._drawCount || elements.length - start; + const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop; + let i; + if (meta.dataset) { + meta.dataset.draw(ctx, area, start, count); + } + for(i = start; i < start + count; ++i){ + const element = elements[i]; + if (element.hidden) { + continue; + } + if (element.active && drawActiveElementsOnTop) { + active.push(element); + } else { + element.draw(ctx, area); + } + } + for(i = 0; i < active.length; ++i){ + active[i].draw(ctx, area); + } + } + getStyle(index, active) { + const mode = active ? 'active' : 'default'; + return index === undefined && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode); + } + getContext(index, active, mode) { + const dataset = this.getDataset(); + let context; + if (index >= 0 && index < this._cachedMeta.data.length) { + const element = this._cachedMeta.data[index]; + context = element.$context || (element.$context = createDataContext(this.getContext(), index, element)); + context.parsed = this.getParsed(index); + context.raw = dataset.data[index]; + context.index = context.dataIndex = index; + } else { + context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index)); + context.dataset = dataset; + context.index = context.datasetIndex = this.index; + } + context.active = !!active; + context.mode = mode; + return context; + } + resolveDatasetElementOptions(mode) { + return this._resolveElementOptions(this.datasetElementType.id, mode); + } + resolveDataElementOptions(index, mode) { + return this._resolveElementOptions(this.dataElementType.id, mode, index); + } + _resolveElementOptions(elementType, mode = 'default', index) { + const active = mode === 'active'; + const cache = this._cachedDataOpts; + const cacheKey = elementType + '-' + mode; + const cached = cache[cacheKey]; + const sharing = this.enableOptionSharing && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(index); + if (cached) { + return cloneIfNotShared(cached, sharing); + } + const config = this.chart.config; + const scopeKeys = config.datasetElementScopeKeys(this._type, elementType); + const prefixes = active ? [ + `${elementType}Hover`, + 'hover', + elementType, + '' + ] : [ + elementType, + '' + ]; + const scopes = config.getOptionScopes(this.getDataset(), scopeKeys); + const names = Object.keys(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.elements[elementType]); + const context = ()=>this.getContext(index, active, mode); + const values = config.resolveNamedOptions(scopes, names, context, prefixes); + if (values.$shared) { + values.$shared = sharing; + cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing)); + } + return values; + } + _resolveAnimations(index, transition, active) { + const chart = this.chart; + const cache = this._cachedDataOpts; + const cacheKey = `animation-${transition}`; + const cached = cache[cacheKey]; + if (cached) { + return cached; + } + let options; + if (chart.options.animation !== false) { + const config = this.chart.config; + const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition); + const scopes = config.getOptionScopes(this.getDataset(), scopeKeys); + options = config.createResolver(scopes, this.getContext(index, active, transition)); + } + const animations = new Animations(chart, options && options.animations); + if (options && options._cacheable) { + cache[cacheKey] = Object.freeze(animations); + } + return animations; + } + getSharedOptions(options) { + if (!options.$shared) { + return; + } + return this._sharedOptions || (this._sharedOptions = Object.assign({}, options)); + } + includeOptions(mode, sharedOptions) { + return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled; + } + _getSharedOptions(start, mode) { + const firstOpts = this.resolveDataElementOptions(start, mode); + const previouslySharedOptions = this._sharedOptions; + const sharedOptions = this.getSharedOptions(firstOpts); + const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions; + this.updateSharedOptions(sharedOptions, mode, firstOpts); + return { + sharedOptions, + includeOptions + }; + } + updateElement(element, index, properties, mode) { + if (isDirectUpdateMode(mode)) { + Object.assign(element, properties); + } else { + this._resolveAnimations(index, mode).update(element, properties); + } + } + updateSharedOptions(sharedOptions, mode, newOptions) { + if (sharedOptions && !isDirectUpdateMode(mode)) { + this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions); + } + } + _setStyle(element, index, mode, active) { + element.active = active; + const options = this.getStyle(index, active); + this._resolveAnimations(index, mode, active).update(element, { + options: !active && this.getSharedOptions(options) || options + }); + } + removeHoverStyle(element, datasetIndex, index) { + this._setStyle(element, index, 'active', false); + } + setHoverStyle(element, datasetIndex, index) { + this._setStyle(element, index, 'active', true); + } + _removeDatasetHoverStyle() { + const element = this._cachedMeta.dataset; + if (element) { + this._setStyle(element, undefined, 'active', false); + } + } + _setDatasetHoverStyle() { + const element = this._cachedMeta.dataset; + if (element) { + this._setStyle(element, undefined, 'active', true); + } + } + _resyncElements(resetNewElements) { + const data = this._data; + const elements = this._cachedMeta.data; + for (const [method, arg1, arg2] of this._syncList){ + this[method](arg1, arg2); + } + this._syncList = []; + const numMeta = elements.length; + const numData = data.length; + const count = Math.min(numData, numMeta); + if (count) { + this.parse(0, count); + } + if (numData > numMeta) { + this._insertElements(numMeta, numData - numMeta, resetNewElements); + } else if (numData < numMeta) { + this._removeElements(numData, numMeta - numData); + } + } + _insertElements(start, count, resetNewElements = true) { + const meta = this._cachedMeta; + const data = meta.data; + const end = start + count; + let i; + const move = (arr)=>{ + arr.length += count; + for(i = arr.length - 1; i >= end; i--){ + arr[i] = arr[i - count]; + } + }; + move(data); + for(i = start; i < end; ++i){ + data[i] = new this.dataElementType(); + } + if (this._parsing) { + move(meta._parsed); + } + this.parse(start, count); + if (resetNewElements) { + this.updateElements(data, start, count, 'reset'); + } + } + updateElements(element, start, count, mode) {} + _removeElements(start, count) { + const meta = this._cachedMeta; + if (this._parsing) { + const removed = meta._parsed.splice(start, count); + if (meta._stacked) { + clearStacks(meta, removed); + } + } + meta.data.splice(start, count); + } + _sync(args) { + if (this._parsing) { + this._syncList.push(args); + } else { + const [method, arg1, arg2] = args; + this[method](arg1, arg2); + } + this.chart._dataChanges.push([ + this.index, + ...args + ]); + } + _onDataPush() { + const count = arguments.length; + this._sync([ + '_insertElements', + this.getDataset().data.length - count, + count + ]); + } + _onDataPop() { + this._sync([ + '_removeElements', + this._cachedMeta.data.length - 1, + 1 + ]); + } + _onDataShift() { + this._sync([ + '_removeElements', + 0, + 1 + ]); + } + _onDataSplice(start, count) { + if (count) { + this._sync([ + '_removeElements', + start, + count + ]); + } + const newCount = arguments.length - 2; + if (newCount) { + this._sync([ + '_insertElements', + start, + newCount + ]); + } + } + _onDataUnshift() { + this._sync([ + '_insertElements', + 0, + arguments.length + ]); + } +} + +function getAllScaleValues(scale, type) { + if (!scale._cache.$bar) { + const visibleMetas = scale.getMatchingVisibleMetas(type); + let values = []; + for(let i = 0, ilen = visibleMetas.length; i < ilen; i++){ + values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale)); + } + scale._cache.$bar = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort((a, b)=>a - b)); + } + return scale._cache.$bar; +} + function computeMinSampleSize(meta) { + const scale = meta.iScale; + const values = getAllScaleValues(scale, meta.type); + let min = scale._length; + let i, ilen, curr, prev; + const updateMinAndPrev = ()=>{ + if (curr === 32767 || curr === -32768) { + return; + } + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(prev)) { + min = Math.min(min, Math.abs(curr - prev) || min); + } + prev = curr; + }; + for(i = 0, ilen = values.length; i < ilen; ++i){ + curr = scale.getPixelForValue(values[i]); + updateMinAndPrev(); + } + prev = undefined; + for(i = 0, ilen = scale.ticks.length; i < ilen; ++i){ + curr = scale.getPixelForTick(i); + updateMinAndPrev(); + } + return min; +} + function computeFitCategoryTraits(index, ruler, options, stackCount) { + const thickness = options.barThickness; + let size, ratio; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(thickness)) { + size = ruler.min * options.categoryPercentage; + ratio = options.barPercentage; + } else { + size = thickness * stackCount; + ratio = 1; + } + return { + chunk: size / stackCount, + ratio, + start: ruler.pixels[index] - size / 2 + }; +} + function computeFlexCategoryTraits(index, ruler, options, stackCount) { + const pixels = ruler.pixels; + const curr = pixels[index]; + let prev = index > 0 ? pixels[index - 1] : null; + let next = index < pixels.length - 1 ? pixels[index + 1] : null; + const percent = options.categoryPercentage; + if (prev === null) { + prev = curr - (next === null ? ruler.end - ruler.start : next - curr); + } + if (next === null) { + next = curr + curr - prev; + } + const start = curr - (curr - Math.min(prev, next)) / 2 * percent; + const size = Math.abs(next - prev) / 2 * percent; + return { + chunk: size / stackCount, + ratio: options.barPercentage, + start + }; +} +function parseFloatBar(entry, item, vScale, i) { + const startValue = vScale.parse(entry[0], i); + const endValue = vScale.parse(entry[1], i); + const min = Math.min(startValue, endValue); + const max = Math.max(startValue, endValue); + let barStart = min; + let barEnd = max; + if (Math.abs(min) > Math.abs(max)) { + barStart = max; + barEnd = min; + } + item[vScale.axis] = barEnd; + item._custom = { + barStart, + barEnd, + start: startValue, + end: endValue, + min, + max + }; +} +function parseValue(entry, item, vScale, i) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(entry)) { + parseFloatBar(entry, item, vScale, i); + } else { + item[vScale.axis] = vScale.parse(entry, i); + } + return item; +} +function parseArrayOrPrimitive(meta, data, start, count) { + const iScale = meta.iScale; + const vScale = meta.vScale; + const labels = iScale.getLabels(); + const singleScale = iScale === vScale; + const parsed = []; + let i, ilen, item, entry; + for(i = start, ilen = start + count; i < ilen; ++i){ + entry = data[i]; + item = {}; + item[iScale.axis] = singleScale || iScale.parse(labels[i], i); + parsed.push(parseValue(entry, item, vScale, i)); + } + return parsed; +} +function isFloatBar(custom) { + return custom && custom.barStart !== undefined && custom.barEnd !== undefined; +} +function barSign(size, vScale, actualBase) { + if (size !== 0) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(size); + } + return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1); +} +function borderProps(properties) { + let reverse, start, end, top, bottom; + if (properties.horizontal) { + reverse = properties.base > properties.x; + start = 'left'; + end = 'right'; + } else { + reverse = properties.base < properties.y; + start = 'bottom'; + end = 'top'; + } + if (reverse) { + top = 'end'; + bottom = 'start'; + } else { + top = 'start'; + bottom = 'end'; + } + return { + start, + end, + reverse, + top, + bottom + }; +} +function setBorderSkipped(properties, options, stack, index) { + let edge = options.borderSkipped; + const res = {}; + if (!edge) { + properties.borderSkipped = res; + return; + } + if (edge === true) { + properties.borderSkipped = { + top: true, + right: true, + bottom: true, + left: true + }; + return; + } + const { start , end , reverse , top , bottom } = borderProps(properties); + if (edge === 'middle' && stack) { + properties.enableBorderRadius = true; + if ((stack._top || 0) === index) { + edge = top; + } else if ((stack._bottom || 0) === index) { + edge = bottom; + } else { + res[parseEdge(bottom, start, end, reverse)] = true; + edge = top; + } + } + res[parseEdge(edge, start, end, reverse)] = true; + properties.borderSkipped = res; +} +function parseEdge(edge, a, b, reverse) { + if (reverse) { + edge = swap(edge, a, b); + edge = startEnd(edge, b, a); + } else { + edge = startEnd(edge, a, b); + } + return edge; +} +function swap(orig, v1, v2) { + return orig === v1 ? v2 : orig === v2 ? v1 : orig; +} +function startEnd(v, start, end) { + return v === 'start' ? start : v === 'end' ? end : v; +} +function setInflateAmount(properties, { inflateAmount }, ratio) { + properties.inflateAmount = inflateAmount === 'auto' ? ratio === 1 ? 0.33 : 0 : inflateAmount; +} +class BarController extends DatasetController { + static id = 'bar'; + static defaults = { + datasetElementType: false, + dataElementType: 'bar', + categoryPercentage: 0.8, + barPercentage: 0.9, + grouped: true, + animations: { + numbers: { + type: 'number', + properties: [ + 'x', + 'y', + 'base', + 'width', + 'height' + ] + } + } + }; + static overrides = { + scales: { + _index_: { + type: 'category', + offset: true, + grid: { + offset: true + } + }, + _value_: { + type: 'linear', + beginAtZero: true + } + } + }; + parsePrimitiveData(meta, data, start, count) { + return parseArrayOrPrimitive(meta, data, start, count); + } + parseArrayData(meta, data, start, count) { + return parseArrayOrPrimitive(meta, data, start, count); + } + parseObjectData(meta, data, start, count) { + const { iScale , vScale } = meta; + const { xAxisKey ='x' , yAxisKey ='y' } = this._parsing; + const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey; + const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey; + const parsed = []; + let i, ilen, item, obj; + for(i = start, ilen = start + count; i < ilen; ++i){ + obj = data[i]; + item = {}; + item[iScale.axis] = iScale.parse((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, iAxisKey), i); + parsed.push(parseValue((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, vAxisKey), item, vScale, i)); + } + return parsed; + } + updateRangeFromParsed(range, scale, parsed, stack) { + super.updateRangeFromParsed(range, scale, parsed, stack); + const custom = parsed._custom; + if (custom && scale === this._cachedMeta.vScale) { + range.min = Math.min(range.min, custom.min); + range.max = Math.max(range.max, custom.max); + } + } + getMaxOverflow() { + return 0; + } + getLabelAndValue(index) { + const meta = this._cachedMeta; + const { iScale , vScale } = meta; + const parsed = this.getParsed(index); + const custom = parsed._custom; + const value = isFloatBar(custom) ? '[' + custom.start + ', ' + custom.end + ']' : '' + vScale.getLabelForValue(parsed[vScale.axis]); + return { + label: '' + iScale.getLabelForValue(parsed[iScale.axis]), + value + }; + } + initialize() { + this.enableOptionSharing = true; + super.initialize(); + const meta = this._cachedMeta; + meta.stack = this.getDataset().stack; + } + update(mode) { + const meta = this._cachedMeta; + this.updateElements(meta.data, 0, meta.data.length, mode); + } + updateElements(bars, start, count, mode) { + const reset = mode === 'reset'; + const { index , _cachedMeta: { vScale } } = this; + const base = vScale.getBasePixel(); + const horizontal = vScale.isHorizontal(); + const ruler = this._getRuler(); + const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode); + for(let i = start; i < start + count; i++){ + const parsed = this.getParsed(i); + const vpixels = reset || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vScale.axis]) ? { + base, + head: base + } : this._calculateBarValuePixels(i); + const ipixels = this._calculateBarIndexPixels(i, ruler); + const stack = (parsed._stacks || {})[vScale.axis]; + const properties = { + horizontal, + base: vpixels.base, + enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom, + x: horizontal ? vpixels.head : ipixels.center, + y: horizontal ? ipixels.center : vpixels.head, + height: horizontal ? ipixels.size : Math.abs(vpixels.size), + width: horizontal ? Math.abs(vpixels.size) : ipixels.size + }; + if (includeOptions) { + properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode); + } + const options = properties.options || bars[i].options; + setBorderSkipped(properties, options, stack, index); + setInflateAmount(properties, options, ruler.ratio); + this.updateElement(bars[i], i, properties, mode); + } + } + _getStacks(last, dataIndex) { + const { iScale } = this._cachedMeta; + const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta)=>meta.controller.options.grouped); + const stacked = iScale.options.stacked; + const stacks = []; + const skipNull = (meta)=>{ + const parsed = meta.controller.getParsed(dataIndex); + const val = parsed && parsed[meta.vScale.axis]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(val) || isNaN(val)) { + return true; + } + }; + for (const meta of metasets){ + if (dataIndex !== undefined && skipNull(meta)) { + continue; + } + if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === undefined && meta.stack === undefined) { + stacks.push(meta.stack); + } + if (meta.index === last) { + break; + } + } + if (!stacks.length) { + stacks.push(undefined); + } + return stacks; + } + _getStackCount(index) { + return this._getStacks(undefined, index).length; + } + _getStackIndex(datasetIndex, name, dataIndex) { + const stacks = this._getStacks(datasetIndex, dataIndex); + const index = name !== undefined ? stacks.indexOf(name) : -1; + return index === -1 ? stacks.length - 1 : index; + } + _getRuler() { + const opts = this.options; + const meta = this._cachedMeta; + const iScale = meta.iScale; + const pixels = []; + let i, ilen; + for(i = 0, ilen = meta.data.length; i < ilen; ++i){ + pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i)); + } + const barThickness = opts.barThickness; + const min = barThickness || computeMinSampleSize(meta); + return { + min, + pixels, + start: iScale._startPixel, + end: iScale._endPixel, + stackCount: this._getStackCount(), + scale: iScale, + grouped: opts.grouped, + ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage + }; + } + _calculateBarValuePixels(index) { + const { _cachedMeta: { vScale , _stacked , index: datasetIndex } , options: { base: baseValue , minBarLength } } = this; + const actualBase = baseValue || 0; + const parsed = this.getParsed(index); + const custom = parsed._custom; + const floating = isFloatBar(custom); + let value = parsed[vScale.axis]; + let start = 0; + let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value; + let head, size; + if (length !== value) { + start = length - value; + length = value; + } + if (floating) { + value = custom.barStart; + length = custom.barEnd - custom.barStart; + if (value !== 0 && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(value) !== (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(custom.barEnd)) { + start = 0; + } + start += value; + } + const startValue = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(baseValue) && !floating ? baseValue : start; + let base = vScale.getPixelForValue(startValue); + if (this.chart.getDataVisibility(index)) { + head = vScale.getPixelForValue(start + length); + } else { + head = base; + } + size = head - base; + if (Math.abs(size) < minBarLength) { + size = barSign(size, vScale, actualBase) * minBarLength; + if (value === actualBase) { + base -= size / 2; + } + const startPixel = vScale.getPixelForDecimal(0); + const endPixel = vScale.getPixelForDecimal(1); + const min = Math.min(startPixel, endPixel); + const max = Math.max(startPixel, endPixel); + base = Math.max(Math.min(base, max), min); + head = base + size; + if (_stacked && !floating) { + parsed._stacks[vScale.axis]._visualValues[datasetIndex] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base); + } + } + if (base === vScale.getPixelForValue(actualBase)) { + const halfGrid = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(size) * vScale.getLineWidthForValue(actualBase) / 2; + base += halfGrid; + size -= halfGrid; + } + return { + size, + base, + head, + center: head + size / 2 + }; + } + _calculateBarIndexPixels(index, ruler) { + const scale = ruler.scale; + const options = this.options; + const skipNull = options.skipNull; + const maxBarThickness = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.maxBarThickness, Infinity); + let center, size; + if (ruler.grouped) { + const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount; + const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options, stackCount) : computeFitCategoryTraits(index, ruler, options, stackCount); + const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined); + center = range.start + range.chunk * stackIndex + range.chunk / 2; + size = Math.min(maxBarThickness, range.chunk * range.ratio); + } else { + center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index); + size = Math.min(maxBarThickness, ruler.min * ruler.ratio); + } + return { + base: center - size / 2, + head: center + size / 2, + center, + size + }; + } + draw() { + const meta = this._cachedMeta; + const vScale = meta.vScale; + const rects = meta.data; + const ilen = rects.length; + let i = 0; + for(; i < ilen; ++i){ + if (this.getParsed(i)[vScale.axis] !== null) { + rects[i].draw(this._ctx); + } + } + } +} + +class BubbleController extends DatasetController { + static id = 'bubble'; + static defaults = { + datasetElementType: false, + dataElementType: 'point', + animations: { + numbers: { + type: 'number', + properties: [ + 'x', + 'y', + 'borderWidth', + 'radius' + ] + } + } + }; + static overrides = { + scales: { + x: { + type: 'linear' + }, + y: { + type: 'linear' + } + } + }; + initialize() { + this.enableOptionSharing = true; + super.initialize(); + } + parsePrimitiveData(meta, data, start, count) { + const parsed = super.parsePrimitiveData(meta, data, start, count); + for(let i = 0; i < parsed.length; i++){ + parsed[i]._custom = this.resolveDataElementOptions(i + start).radius; + } + return parsed; + } + parseArrayData(meta, data, start, count) { + const parsed = super.parseArrayData(meta, data, start, count); + for(let i = 0; i < parsed.length; i++){ + const item = data[start + i]; + parsed[i]._custom = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(item[2], this.resolveDataElementOptions(i + start).radius); + } + return parsed; + } + parseObjectData(meta, data, start, count) { + const parsed = super.parseObjectData(meta, data, start, count); + for(let i = 0; i < parsed.length; i++){ + const item = data[start + i]; + parsed[i]._custom = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(item && item.r && +item.r, this.resolveDataElementOptions(i + start).radius); + } + return parsed; + } + getMaxOverflow() { + const data = this._cachedMeta.data; + let max = 0; + for(let i = data.length - 1; i >= 0; --i){ + max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2); + } + return max > 0 && max; + } + getLabelAndValue(index) { + const meta = this._cachedMeta; + const labels = this.chart.data.labels || []; + const { xScale , yScale } = meta; + const parsed = this.getParsed(index); + const x = xScale.getLabelForValue(parsed.x); + const y = yScale.getLabelForValue(parsed.y); + const r = parsed._custom; + return { + label: labels[index] || '', + value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')' + }; + } + update(mode) { + const points = this._cachedMeta.data; + this.updateElements(points, 0, points.length, mode); + } + updateElements(points, start, count, mode) { + const reset = mode === 'reset'; + const { iScale , vScale } = this._cachedMeta; + const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode); + const iAxis = iScale.axis; + const vAxis = vScale.axis; + for(let i = start; i < start + count; i++){ + const point = points[i]; + const parsed = !reset && this.getParsed(i); + const properties = {}; + const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]); + const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]); + properties.skip = isNaN(iPixel) || isNaN(vPixel); + if (includeOptions) { + properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode); + if (reset) { + properties.options.radius = 0; + } + } + this.updateElement(point, i, properties, mode); + } + } + resolveDataElementOptions(index, mode) { + const parsed = this.getParsed(index); + let values = super.resolveDataElementOptions(index, mode); + if (values.$shared) { + values = Object.assign({}, values, { + $shared: false + }); + } + const radius = values.radius; + if (mode !== 'active') { + values.radius = 0; + } + values.radius += (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(parsed && parsed._custom, radius); + return values; + } +} + +function getRatioAndOffset(rotation, circumference, cutout) { + let ratioX = 1; + let ratioY = 1; + let offsetX = 0; + let offsetY = 0; + if (circumference < _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T) { + const startAngle = rotation; + const endAngle = startAngle + circumference; + const startX = Math.cos(startAngle); + const startY = Math.sin(startAngle); + const endX = Math.cos(endAngle); + const endY = Math.sin(endAngle); + const calcMax = (angle, a, b)=>(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout); + const calcMin = (angle, a, b)=>(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout); + const maxX = calcMax(0, startX, endX); + const maxY = calcMax(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY); + const minX = calcMin(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P, startX, endX); + const minY = calcMin(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startY, endY); + ratioX = (maxX - minX) / 2; + ratioY = (maxY - minY) / 2; + offsetX = -(maxX + minX) / 2; + offsetY = -(maxY + minY) / 2; + } + return { + ratioX, + ratioY, + offsetX, + offsetY + }; +} +class DoughnutController extends DatasetController { + static id = 'doughnut'; + static defaults = { + datasetElementType: false, + dataElementType: 'arc', + animation: { + animateRotate: true, + animateScale: false + }, + animations: { + numbers: { + type: 'number', + properties: [ + 'circumference', + 'endAngle', + 'innerRadius', + 'outerRadius', + 'startAngle', + 'x', + 'y', + 'offset', + 'borderWidth', + 'spacing' + ] + } + }, + cutout: '50%', + rotation: 0, + circumference: 360, + radius: '100%', + spacing: 0, + indexAxis: 'r' + }; + static descriptors = { + _scriptable: (name)=>name !== 'spacing', + _indexable: (name)=>name !== 'spacing' && !name.startsWith('borderDash') && !name.startsWith('hoverBorderDash') + }; + static overrides = { + aspectRatio: 1, + plugins: { + legend: { + labels: { + generateLabels (chart) { + const data = chart.data; + if (data.labels.length && data.datasets.length) { + const { labels: { pointStyle , color } } = chart.legend.options; + return data.labels.map((label, i)=>{ + const meta = chart.getDatasetMeta(0); + const style = meta.controller.getStyle(i); + return { + text: label, + fillStyle: style.backgroundColor, + strokeStyle: style.borderColor, + fontColor: color, + lineWidth: style.borderWidth, + pointStyle: pointStyle, + hidden: !chart.getDataVisibility(i), + index: i + }; + }); + } + return []; + } + }, + onClick (e, legendItem, legend) { + legend.chart.toggleDataVisibility(legendItem.index); + legend.chart.update(); + } + } + } + }; + constructor(chart, datasetIndex){ + super(chart, datasetIndex); + this.enableOptionSharing = true; + this.innerRadius = undefined; + this.outerRadius = undefined; + this.offsetX = undefined; + this.offsetY = undefined; + } + linkScales() {} + parse(start, count) { + const data = this.getDataset().data; + const meta = this._cachedMeta; + if (this._parsing === false) { + meta._parsed = data; + } else { + let getter = (i)=>+data[i]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(data[start])) { + const { key ='value' } = this._parsing; + getter = (i)=>+(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(data[i], key); + } + let i, ilen; + for(i = start, ilen = start + count; i < ilen; ++i){ + meta._parsed[i] = getter(i); + } + } + } + _getRotation() { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.rotation - 90); + } + _getCircumference() { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.circumference); + } + _getRotationExtents() { + let min = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; + let max = -_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T; + for(let i = 0; i < this.chart.data.datasets.length; ++i){ + if (this.chart.isDatasetVisible(i) && this.chart.getDatasetMeta(i).type === this._type) { + const controller = this.chart.getDatasetMeta(i).controller; + const rotation = controller._getRotation(); + const circumference = controller._getCircumference(); + min = Math.min(min, rotation); + max = Math.max(max, rotation + circumference); + } + } + return { + rotation: min, + circumference: max - min + }; + } + update(mode) { + const chart = this.chart; + const { chartArea } = chart; + const meta = this._cachedMeta; + const arcs = meta.data; + const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing; + const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0); + const cutout = Math.min((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.m)(this.options.cutout, maxSize), 1); + const chartWeight = this._getRingWeight(this.index); + const { circumference , rotation } = this._getRotationExtents(); + const { ratioX , ratioY , offsetX , offsetY } = getRatioAndOffset(rotation, circumference, cutout); + const maxWidth = (chartArea.width - spacing) / ratioX; + const maxHeight = (chartArea.height - spacing) / ratioY; + const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0); + const outerRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.n)(this.options.radius, maxRadius); + const innerRadius = Math.max(outerRadius * cutout, 0); + const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal(); + this.offsetX = offsetX * outerRadius; + this.offsetY = offsetY * outerRadius; + meta.total = this.calculateTotal(); + this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index); + this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0); + this.updateElements(arcs, 0, arcs.length, mode); + } + _circumference(i, reset) { + const opts = this.options; + const meta = this._cachedMeta; + const circumference = this._getCircumference(); + if (reset && opts.animation.animateRotate || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) { + return 0; + } + return this.calculateCircumference(meta._parsed[i] * circumference / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); + } + updateElements(arcs, start, count, mode) { + const reset = mode === 'reset'; + const chart = this.chart; + const chartArea = chart.chartArea; + const opts = chart.options; + const animationOpts = opts.animation; + const centerX = (chartArea.left + chartArea.right) / 2; + const centerY = (chartArea.top + chartArea.bottom) / 2; + const animateScale = reset && animationOpts.animateScale; + const innerRadius = animateScale ? 0 : this.innerRadius; + const outerRadius = animateScale ? 0 : this.outerRadius; + const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode); + let startAngle = this._getRotation(); + let i; + for(i = 0; i < start; ++i){ + startAngle += this._circumference(i, reset); + } + for(i = start; i < start + count; ++i){ + const circumference = this._circumference(i, reset); + const arc = arcs[i]; + const properties = { + x: centerX + this.offsetX, + y: centerY + this.offsetY, + startAngle, + endAngle: startAngle + circumference, + circumference, + outerRadius, + innerRadius + }; + if (includeOptions) { + properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode); + } + startAngle += circumference; + this.updateElement(arc, i, properties, mode); + } + } + calculateTotal() { + const meta = this._cachedMeta; + const metaData = meta.data; + let total = 0; + let i; + for(i = 0; i < metaData.length; i++){ + const value = meta._parsed[i]; + if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) { + total += Math.abs(value); + } + } + return total; + } + calculateCircumference(value) { + const total = this._cachedMeta.total; + if (total > 0 && !isNaN(value)) { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T * (Math.abs(value) / total); + } + return 0; + } + getLabelAndValue(index) { + const meta = this._cachedMeta; + const chart = this.chart; + const labels = chart.data.labels || []; + const value = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index], chart.options.locale); + return { + label: labels[index] || '', + value + }; + } + getMaxBorderWidth(arcs) { + let max = 0; + const chart = this.chart; + let i, ilen, meta, controller, options; + if (!arcs) { + for(i = 0, ilen = chart.data.datasets.length; i < ilen; ++i){ + if (chart.isDatasetVisible(i)) { + meta = chart.getDatasetMeta(i); + arcs = meta.data; + controller = meta.controller; + break; + } + } + } + if (!arcs) { + return 0; + } + for(i = 0, ilen = arcs.length; i < ilen; ++i){ + options = controller.resolveDataElementOptions(i); + if (options.borderAlign !== 'inner') { + max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0); + } + } + return max; + } + getMaxOffset(arcs) { + let max = 0; + for(let i = 0, ilen = arcs.length; i < ilen; ++i){ + const options = this.resolveDataElementOptions(i); + max = Math.max(max, options.offset || 0, options.hoverOffset || 0); + } + return max; + } + _getRingWeightOffset(datasetIndex) { + let ringWeightOffset = 0; + for(let i = 0; i < datasetIndex; ++i){ + if (this.chart.isDatasetVisible(i)) { + ringWeightOffset += this._getRingWeight(i); + } + } + return ringWeightOffset; + } + _getRingWeight(datasetIndex) { + return Math.max((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(this.chart.data.datasets[datasetIndex].weight, 1), 0); + } + _getVisibleDatasetWeightTotal() { + return this._getRingWeightOffset(this.chart.data.datasets.length) || 1; + } +} + +class LineController extends DatasetController { + static id = 'line'; + static defaults = { + datasetElementType: 'line', + dataElementType: 'point', + showLine: true, + spanGaps: false + }; + static overrides = { + scales: { + _index_: { + type: 'category' + }, + _value_: { + type: 'linear' + } + } + }; + initialize() { + this.enableOptionSharing = true; + this.supportsDecimation = true; + super.initialize(); + } + update(mode) { + const meta = this._cachedMeta; + const { dataset: line , data: points = [] , _dataset } = meta; + const animationsDisabled = this.chart._animationsDisabled; + let { start , count } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled); + this._drawStart = start; + this._drawCount = count; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) { + start = 0; + count = points.length; + } + line._chart = this.chart; + line._datasetIndex = this.index; + line._decimated = !!_dataset._decimated; + line.points = points; + const options = this.resolveDatasetElementOptions(mode); + if (!this.options.showLine) { + options.borderWidth = 0; + } + options.segment = this.options.segment; + this.updateElement(line, undefined, { + animated: !animationsDisabled, + options + }, mode); + this.updateElements(points, start, count, mode); + } + updateElements(points, start, count, mode) { + const reset = mode === 'reset'; + const { iScale , vScale , _stacked , _dataset } = this._cachedMeta; + const { sharedOptions , includeOptions } = this._getSharedOptions(start, mode); + const iAxis = iScale.axis; + const vAxis = vScale.axis; + const { spanGaps , segment } = this.options; + const maxGapLength = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY; + const directUpdate = this.chart._animationsDisabled || reset || mode === 'none'; + const end = start + count; + const pointsCount = points.length; + let prevParsed = start > 0 && this.getParsed(start - 1); + for(let i = 0; i < pointsCount; ++i){ + const point = points[i]; + const properties = directUpdate ? point : {}; + if (i < start || i >= end) { + properties.skip = true; + continue; + } + const parsed = this.getParsed(i); + const nullData = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]); + const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i); + const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i); + properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData; + properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength; + if (segment) { + properties.parsed = parsed; + properties.raw = _dataset.data[i]; + } + if (includeOptions) { + properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode); + } + if (!directUpdate) { + this.updateElement(point, i, properties, mode); + } + prevParsed = parsed; + } + } + getMaxOverflow() { + const meta = this._cachedMeta; + const dataset = meta.dataset; + const border = dataset.options && dataset.options.borderWidth || 0; + const data = meta.data || []; + if (!data.length) { + return border; + } + const firstPoint = data[0].size(this.resolveDataElementOptions(0)); + const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1)); + return Math.max(border, firstPoint, lastPoint) / 2; + } + draw() { + const meta = this._cachedMeta; + meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis); + super.draw(); + } +} + +class PolarAreaController extends DatasetController { + static id = 'polarArea'; + static defaults = { + dataElementType: 'arc', + animation: { + animateRotate: true, + animateScale: true + }, + animations: { + numbers: { + type: 'number', + properties: [ + 'x', + 'y', + 'startAngle', + 'endAngle', + 'innerRadius', + 'outerRadius' + ] + } + }, + indexAxis: 'r', + startAngle: 0 + }; + static overrides = { + aspectRatio: 1, + plugins: { + legend: { + labels: { + generateLabels (chart) { + const data = chart.data; + if (data.labels.length && data.datasets.length) { + const { labels: { pointStyle , color } } = chart.legend.options; + return data.labels.map((label, i)=>{ + const meta = chart.getDatasetMeta(0); + const style = meta.controller.getStyle(i); + return { + text: label, + fillStyle: style.backgroundColor, + strokeStyle: style.borderColor, + fontColor: color, + lineWidth: style.borderWidth, + pointStyle: pointStyle, + hidden: !chart.getDataVisibility(i), + index: i + }; + }); + } + return []; + } + }, + onClick (e, legendItem, legend) { + legend.chart.toggleDataVisibility(legendItem.index); + legend.chart.update(); + } + } + }, + scales: { + r: { + type: 'radialLinear', + angleLines: { + display: false + }, + beginAtZero: true, + grid: { + circular: true + }, + pointLabels: { + display: false + }, + startAngle: 0 + } + } + }; + constructor(chart, datasetIndex){ + super(chart, datasetIndex); + this.innerRadius = undefined; + this.outerRadius = undefined; + } + getLabelAndValue(index) { + const meta = this._cachedMeta; + const chart = this.chart; + const labels = chart.data.labels || []; + const value = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(meta._parsed[index].r, chart.options.locale); + return { + label: labels[index] || '', + value + }; + } + parseObjectData(meta, data, start, count) { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count); + } + update(mode) { + const arcs = this._cachedMeta.data; + this._updateRadius(); + this.updateElements(arcs, 0, arcs.length, mode); + } + getMinMax() { + const meta = this._cachedMeta; + const range = { + min: Number.POSITIVE_INFINITY, + max: Number.NEGATIVE_INFINITY + }; + meta.data.forEach((element, index)=>{ + const parsed = this.getParsed(index).r; + if (!isNaN(parsed) && this.chart.getDataVisibility(index)) { + if (parsed < range.min) { + range.min = parsed; + } + if (parsed > range.max) { + range.max = parsed; + } + } + }); + return range; + } + _updateRadius() { + const chart = this.chart; + const chartArea = chart.chartArea; + const opts = chart.options; + const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); + const outerRadius = Math.max(minSize / 2, 0); + const innerRadius = Math.max(opts.cutoutPercentage ? outerRadius / 100 * opts.cutoutPercentage : 1, 0); + const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount(); + this.outerRadius = outerRadius - radiusLength * this.index; + this.innerRadius = this.outerRadius - radiusLength; + } + updateElements(arcs, start, count, mode) { + const reset = mode === 'reset'; + const chart = this.chart; + const opts = chart.options; + const animationOpts = opts.animation; + const scale = this._cachedMeta.rScale; + const centerX = scale.xCenter; + const centerY = scale.yCenter; + const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P; + let angle = datasetStartAngle; + let i; + const defaultAngle = 360 / this.countVisibleElements(); + for(i = 0; i < start; ++i){ + angle += this._computeAngle(i, mode, defaultAngle); + } + for(i = start; i < start + count; i++){ + const arc = arcs[i]; + let startAngle = angle; + let endAngle = angle + this._computeAngle(i, mode, defaultAngle); + let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(this.getParsed(i).r) : 0; + angle = endAngle; + if (reset) { + if (animationOpts.animateScale) { + outerRadius = 0; + } + if (animationOpts.animateRotate) { + startAngle = endAngle = datasetStartAngle; + } + } + const properties = { + x: centerX, + y: centerY, + innerRadius: 0, + outerRadius, + startAngle, + endAngle, + options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode) + }; + this.updateElement(arc, i, properties, mode); + } + } + countVisibleElements() { + const meta = this._cachedMeta; + let count = 0; + meta.data.forEach((element, index)=>{ + if (!isNaN(this.getParsed(index).r) && this.chart.getDataVisibility(index)) { + count++; + } + }); + return count; + } + _computeAngle(index, mode, defaultAngle) { + return this.chart.getDataVisibility(index) ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0; + } +} + +class PieController extends DoughnutController { + static id = 'pie'; + static defaults = { + cutout: 0, + rotation: 0, + circumference: 360, + radius: '100%' + }; +} + +class RadarController extends DatasetController { + static id = 'radar'; + static defaults = { + datasetElementType: 'line', + dataElementType: 'point', + indexAxis: 'r', + showLine: true, + elements: { + line: { + fill: 'start' + } + } + }; + static overrides = { + aspectRatio: 1, + scales: { + r: { + type: 'radialLinear' + } + } + }; + getLabelAndValue(index) { + const vScale = this._cachedMeta.vScale; + const parsed = this.getParsed(index); + return { + label: vScale.getLabels()[index], + value: '' + vScale.getLabelForValue(parsed[vScale.axis]) + }; + } + parseObjectData(meta, data, start, count) { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.y.bind(this)(meta, data, start, count); + } + update(mode) { + const meta = this._cachedMeta; + const line = meta.dataset; + const points = meta.data || []; + const labels = meta.iScale.getLabels(); + line.points = points; + if (mode !== 'resize') { + const options = this.resolveDatasetElementOptions(mode); + if (!this.options.showLine) { + options.borderWidth = 0; + } + const properties = { + _loop: true, + _fullLoop: labels.length === points.length, + options + }; + this.updateElement(line, undefined, properties, mode); + } + this.updateElements(points, 0, points.length, mode); + } + updateElements(points, start, count, mode) { + const scale = this._cachedMeta.rScale; + const reset = mode === 'reset'; + for(let i = start; i < start + count; i++){ + const point = points[i]; + const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode); + const pointPosition = scale.getPointPositionForValue(i, this.getParsed(i).r); + const x = reset ? scale.xCenter : pointPosition.x; + const y = reset ? scale.yCenter : pointPosition.y; + const properties = { + x, + y, + angle: pointPosition.angle, + skip: isNaN(x) || isNaN(y), + options + }; + this.updateElement(point, i, properties, mode); + } + } +} + +class ScatterController extends DatasetController { + static id = 'scatter'; + static defaults = { + datasetElementType: false, + dataElementType: 'point', + showLine: false, + fill: false + }; + static overrides = { + interaction: { + mode: 'point' + }, + scales: { + x: { + type: 'linear' + }, + y: { + type: 'linear' + } + } + }; + getLabelAndValue(index) { + const meta = this._cachedMeta; + const labels = this.chart.data.labels || []; + const { xScale , yScale } = meta; + const parsed = this.getParsed(index); + const x = xScale.getLabelForValue(parsed.x); + const y = yScale.getLabelForValue(parsed.y); + return { + label: labels[index] || '', + value: '(' + x + ', ' + y + ')' + }; + } + update(mode) { + const meta = this._cachedMeta; + const { data: points = [] } = meta; + const animationsDisabled = this.chart._animationsDisabled; + let { start , count } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.q)(meta, points, animationsDisabled); + this._drawStart = start; + this._drawCount = count; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.w)(meta)) { + start = 0; + count = points.length; + } + if (this.options.showLine) { + const { dataset: line , _dataset } = meta; + line._chart = this.chart; + line._datasetIndex = this.index; + line._decimated = !!_dataset._decimated; + line.points = points; + const options = this.resolveDatasetElementOptions(mode); + options.segment = this.options.segment; + this.updateElement(line, undefined, { + animated: !animationsDisabled, + options + }, mode); + } + this.updateElements(points, start, count, mode); + } + addElements() { + const { showLine } = this.options; + if (!this.datasetElementType && showLine) { + this.datasetElementType = this.chart.registry.getElement('line'); + } + super.addElements(); + } + updateElements(points, start, count, mode) { + const reset = mode === 'reset'; + const { iScale , vScale , _stacked , _dataset } = this._cachedMeta; + const firstOpts = this.resolveDataElementOptions(start, mode); + const sharedOptions = this.getSharedOptions(firstOpts); + const includeOptions = this.includeOptions(mode, sharedOptions); + const iAxis = iScale.axis; + const vAxis = vScale.axis; + const { spanGaps , segment } = this.options; + const maxGapLength = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY; + const directUpdate = this.chart._animationsDisabled || reset || mode === 'none'; + let prevParsed = start > 0 && this.getParsed(start - 1); + for(let i = start; i < start + count; ++i){ + const point = points[i]; + const parsed = this.getParsed(i); + const properties = directUpdate ? point : {}; + const nullData = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(parsed[vAxis]); + const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i); + const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i); + properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData; + properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength; + if (segment) { + properties.parsed = parsed; + properties.raw = _dataset.data[i]; + } + if (includeOptions) { + properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode); + } + if (!directUpdate) { + this.updateElement(point, i, properties, mode); + } + prevParsed = parsed; + } + this.updateSharedOptions(sharedOptions, mode, firstOpts); + } + getMaxOverflow() { + const meta = this._cachedMeta; + const data = meta.data || []; + if (!this.options.showLine) { + let max = 0; + for(let i = data.length - 1; i >= 0; --i){ + max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2); + } + return max > 0 && max; + } + const dataset = meta.dataset; + const border = dataset.options && dataset.options.borderWidth || 0; + if (!data.length) { + return border; + } + const firstPoint = data[0].size(this.resolveDataElementOptions(0)); + const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1)); + return Math.max(border, firstPoint, lastPoint) / 2; + } +} + +var controllers = /*#__PURE__*/Object.freeze({ +__proto__: null, +BarController: BarController, +BubbleController: BubbleController, +DoughnutController: DoughnutController, +LineController: LineController, +PieController: PieController, +PolarAreaController: PolarAreaController, +RadarController: RadarController, +ScatterController: ScatterController +}); + +/** + * @namespace Chart._adapters + * @since 2.8.0 + * @private + */ function abstract() { + throw new Error('This method is not implemented: Check that a complete date adapter is provided.'); +} +/** + * Date adapter (current used by the time scale) + * @namespace Chart._adapters._date + * @memberof Chart._adapters + * @private + */ class DateAdapterBase { + /** + * Override default date adapter methods. + * Accepts type parameter to define options type. + * @example + * Chart._adapters._date.override<{myAdapterOption: string}>({ + * init() { + * console.log(this.options.myAdapterOption); + * } + * }) + */ static override(members) { + Object.assign(DateAdapterBase.prototype, members); + } + options; + constructor(options){ + this.options = options || {}; + } + // eslint-disable-next-line @typescript-eslint/no-empty-function + init() {} + formats() { + return abstract(); + } + parse() { + return abstract(); + } + format() { + return abstract(); + } + add() { + return abstract(); + } + diff() { + return abstract(); + } + startOf() { + return abstract(); + } + endOf() { + return abstract(); + } +} +var adapters = { + _date: DateAdapterBase +}; + +function binarySearch(metaset, axis, value, intersect) { + const { controller , data , _sorted } = metaset; + const iScale = controller._cachedMeta.iScale; + if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) { + const lookupMethod = iScale._reversePixels ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.A : _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B; + if (!intersect) { + return lookupMethod(data, axis, value); + } else if (controller._sharedOptions) { + const el = data[0]; + const range = typeof el.getRange === 'function' && el.getRange(axis); + if (range) { + const start = lookupMethod(data, axis, value - range); + const end = lookupMethod(data, axis, value + range); + return { + lo: start.lo, + hi: end.hi + }; + } + } + } + return { + lo: 0, + hi: data.length - 1 + }; +} + function evaluateInteractionItems(chart, axis, position, handler, intersect) { + const metasets = chart.getSortedVisibleDatasetMetas(); + const value = position[axis]; + for(let i = 0, ilen = metasets.length; i < ilen; ++i){ + const { index , data } = metasets[i]; + const { lo , hi } = binarySearch(metasets[i], axis, value, intersect); + for(let j = lo; j <= hi; ++j){ + const element = data[j]; + if (!element.skip) { + handler(element, index, j); + } + } + } +} + function getDistanceMetricForAxis(axis) { + const useX = axis.indexOf('x') !== -1; + const useY = axis.indexOf('y') !== -1; + return function(pt1, pt2) { + const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; + const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; + return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + }; +} + function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) { + const items = []; + if (!includeInvisible && !chart.isPointInArea(position)) { + return items; + } + const evaluationFunc = function(element, datasetIndex, index) { + if (!includeInvisible && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)(element, chart.chartArea, 0)) { + return; + } + if (element.inRange(position.x, position.y, useFinalPosition)) { + items.push({ + element, + datasetIndex, + index + }); + } + }; + evaluateInteractionItems(chart, axis, position, evaluationFunc, true); + return items; +} + function getNearestRadialItems(chart, position, axis, useFinalPosition) { + let items = []; + function evaluationFunc(element, datasetIndex, index) { + const { startAngle , endAngle } = element.getProps([ + 'startAngle', + 'endAngle' + ], useFinalPosition); + const { angle } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(element, { + x: position.x, + y: position.y + }); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle)) { + items.push({ + element, + datasetIndex, + index + }); + } + } + evaluateInteractionItems(chart, axis, position, evaluationFunc); + return items; +} + function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) { + let items = []; + const distanceMetric = getDistanceMetricForAxis(axis); + let minDistance = Number.POSITIVE_INFINITY; + function evaluationFunc(element, datasetIndex, index) { + const inRange = element.inRange(position.x, position.y, useFinalPosition); + if (intersect && !inRange) { + return; + } + const center = element.getCenterPoint(useFinalPosition); + const pointInArea = !!includeInvisible || chart.isPointInArea(center); + if (!pointInArea && !inRange) { + return; + } + const distance = distanceMetric(position, center); + if (distance < minDistance) { + items = [ + { + element, + datasetIndex, + index + } + ]; + minDistance = distance; + } else if (distance === minDistance) { + items.push({ + element, + datasetIndex, + index + }); + } + } + evaluateInteractionItems(chart, axis, position, evaluationFunc); + return items; +} + function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) { + if (!includeInvisible && !chart.isPointInArea(position)) { + return []; + } + return axis === 'r' && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible); +} + function getAxisItems(chart, position, axis, intersect, useFinalPosition) { + const items = []; + const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange'; + let intersectsItem = false; + evaluateInteractionItems(chart, axis, position, (element, datasetIndex, index)=>{ + if (element[rangeMethod](position[axis], useFinalPosition)) { + items.push({ + element, + datasetIndex, + index + }); + intersectsItem = intersectsItem || element.inRange(position.x, position.y, useFinalPosition); + } + }); + if (intersect && !intersectsItem) { + return []; + } + return items; +} + var Interaction = { + evaluateInteractionItems, + modes: { + index (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + const axis = options.axis || 'x'; + const includeInvisible = options.includeInvisible || false; + const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible); + const elements = []; + if (!items.length) { + return []; + } + chart.getSortedVisibleDatasetMetas().forEach((meta)=>{ + const index = items[0].index; + const element = meta.data[index]; + if (element && !element.skip) { + elements.push({ + element, + datasetIndex: meta.index, + index + }); + } + }); + return elements; + }, + dataset (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + const axis = options.axis || 'xy'; + const includeInvisible = options.includeInvisible || false; + let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible); + if (items.length > 0) { + const datasetIndex = items[0].datasetIndex; + const data = chart.getDatasetMeta(datasetIndex).data; + items = []; + for(let i = 0; i < data.length; ++i){ + items.push({ + element: data[i], + datasetIndex, + index: i + }); + } + } + return items; + }, + point (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + const axis = options.axis || 'xy'; + const includeInvisible = options.includeInvisible || false; + return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible); + }, + nearest (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + const axis = options.axis || 'xy'; + const includeInvisible = options.includeInvisible || false; + return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible); + }, + x (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + return getAxisItems(chart, position, 'x', options.intersect, useFinalPosition); + }, + y (chart, e, options, useFinalPosition) { + const position = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(e, chart); + return getAxisItems(chart, position, 'y', options.intersect, useFinalPosition); + } + } +}; + +const STATIC_POSITIONS = [ + 'left', + 'top', + 'right', + 'bottom' +]; +function filterByPosition(array, position) { + return array.filter((v)=>v.pos === position); +} +function filterDynamicPositionByAxis(array, axis) { + return array.filter((v)=>STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis); +} +function sortByWeight(array, reverse) { + return array.sort((a, b)=>{ + const v0 = reverse ? b : a; + const v1 = reverse ? a : b; + return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight; + }); +} +function wrapBoxes(boxes) { + const layoutBoxes = []; + let i, ilen, box, pos, stack, stackWeight; + for(i = 0, ilen = (boxes || []).length; i < ilen; ++i){ + box = boxes[i]; + ({ position: pos , options: { stack , stackWeight =1 } } = box); + layoutBoxes.push({ + index: i, + box, + pos, + horizontal: box.isHorizontal(), + weight: box.weight, + stack: stack && pos + stack, + stackWeight + }); + } + return layoutBoxes; +} +function buildStacks(layouts) { + const stacks = {}; + for (const wrap of layouts){ + const { stack , pos , stackWeight } = wrap; + if (!stack || !STATIC_POSITIONS.includes(pos)) { + continue; + } + const _stack = stacks[stack] || (stacks[stack] = { + count: 0, + placed: 0, + weight: 0, + size: 0 + }); + _stack.count++; + _stack.weight += stackWeight; + } + return stacks; +} + function setLayoutDims(layouts, params) { + const stacks = buildStacks(layouts); + const { vBoxMaxWidth , hBoxMaxHeight } = params; + let i, ilen, layout; + for(i = 0, ilen = layouts.length; i < ilen; ++i){ + layout = layouts[i]; + const { fullSize } = layout.box; + const stack = stacks[layout.stack]; + const factor = stack && layout.stackWeight / stack.weight; + if (layout.horizontal) { + layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth; + layout.height = hBoxMaxHeight; + } else { + layout.width = vBoxMaxWidth; + layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight; + } + } + return stacks; +} +function buildLayoutBoxes(boxes) { + const layoutBoxes = wrapBoxes(boxes); + const fullSize = sortByWeight(layoutBoxes.filter((wrap)=>wrap.box.fullSize), true); + const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true); + const right = sortByWeight(filterByPosition(layoutBoxes, 'right')); + const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true); + const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom')); + const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x'); + const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y'); + return { + fullSize, + leftAndTop: left.concat(top), + rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal), + chartArea: filterByPosition(layoutBoxes, 'chartArea'), + vertical: left.concat(right).concat(centerVertical), + horizontal: top.concat(bottom).concat(centerHorizontal) + }; +} +function getCombinedMax(maxPadding, chartArea, a, b) { + return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]); +} +function updateMaxPadding(maxPadding, boxPadding) { + maxPadding.top = Math.max(maxPadding.top, boxPadding.top); + maxPadding.left = Math.max(maxPadding.left, boxPadding.left); + maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom); + maxPadding.right = Math.max(maxPadding.right, boxPadding.right); +} +function updateDims(chartArea, params, layout, stacks) { + const { pos , box } = layout; + const maxPadding = chartArea.maxPadding; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(pos)) { + if (layout.size) { + chartArea[pos] -= layout.size; + } + const stack = stacks[layout.stack] || { + size: 0, + count: 1 + }; + stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width); + layout.size = stack.size / stack.count; + chartArea[pos] += layout.size; + } + if (box.getPadding) { + updateMaxPadding(maxPadding, box.getPadding()); + } + const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right')); + const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom')); + const widthChanged = newWidth !== chartArea.w; + const heightChanged = newHeight !== chartArea.h; + chartArea.w = newWidth; + chartArea.h = newHeight; + return layout.horizontal ? { + same: widthChanged, + other: heightChanged + } : { + same: heightChanged, + other: widthChanged + }; +} +function handleMaxPadding(chartArea) { + const maxPadding = chartArea.maxPadding; + function updatePos(pos) { + const change = Math.max(maxPadding[pos] - chartArea[pos], 0); + chartArea[pos] += change; + return change; + } + chartArea.y += updatePos('top'); + chartArea.x += updatePos('left'); + updatePos('right'); + updatePos('bottom'); +} +function getMargins(horizontal, chartArea) { + const maxPadding = chartArea.maxPadding; + function marginForPositions(positions) { + const margin = { + left: 0, + top: 0, + right: 0, + bottom: 0 + }; + positions.forEach((pos)=>{ + margin[pos] = Math.max(chartArea[pos], maxPadding[pos]); + }); + return margin; + } + return horizontal ? marginForPositions([ + 'left', + 'right' + ]) : marginForPositions([ + 'top', + 'bottom' + ]); +} +function fitBoxes(boxes, chartArea, params, stacks) { + const refitBoxes = []; + let i, ilen, layout, box, refit, changed; + for(i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i){ + layout = boxes[i]; + box = layout.box; + box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea)); + const { same , other } = updateDims(chartArea, params, layout, stacks); + refit |= same && refitBoxes.length; + changed = changed || other; + if (!box.fullSize) { + refitBoxes.push(layout); + } + } + return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed; +} +function setBoxDims(box, left, top, width, height) { + box.top = top; + box.left = left; + box.right = left + width; + box.bottom = top + height; + box.width = width; + box.height = height; +} +function placeBoxes(boxes, chartArea, params, stacks) { + const userPadding = params.padding; + let { x , y } = chartArea; + for (const layout of boxes){ + const box = layout.box; + const stack = stacks[layout.stack] || { + count: 1, + placed: 0, + weight: 1 + }; + const weight = layout.stackWeight / stack.weight || 1; + if (layout.horizontal) { + const width = chartArea.w * weight; + const height = stack.size || box.height; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) { + y = stack.start; + } + if (box.fullSize) { + setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height); + } else { + setBoxDims(box, chartArea.left + stack.placed, y, width, height); + } + stack.start = y; + stack.placed += width; + y = box.bottom; + } else { + const height = chartArea.h * weight; + const width = stack.size || box.width; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(stack.start)) { + x = stack.start; + } + if (box.fullSize) { + setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top); + } else { + setBoxDims(box, x, chartArea.top + stack.placed, width, height); + } + stack.start = x; + stack.placed += height; + x = box.right; + } + } + chartArea.x = x; + chartArea.y = y; +} +var layouts = { + addBox (chart, item) { + if (!chart.boxes) { + chart.boxes = []; + } + item.fullSize = item.fullSize || false; + item.position = item.position || 'top'; + item.weight = item.weight || 0; + item._layers = item._layers || function() { + return [ + { + z: 0, + draw (chartArea) { + item.draw(chartArea); + } + } + ]; + }; + chart.boxes.push(item); + }, + removeBox (chart, layoutItem) { + const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; + if (index !== -1) { + chart.boxes.splice(index, 1); + } + }, + configure (chart, item, options) { + item.fullSize = options.fullSize; + item.position = options.position; + item.weight = options.weight; + }, + update (chart, width, height, minPadding) { + if (!chart) { + return; + } + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(chart.options.layout.padding); + const availableWidth = Math.max(width - padding.width, 0); + const availableHeight = Math.max(height - padding.height, 0); + const boxes = buildLayoutBoxes(chart.boxes); + const verticalBoxes = boxes.vertical; + const horizontalBoxes = boxes.horizontal; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(chart.boxes, (box)=>{ + if (typeof box.beforeLayout === 'function') { + box.beforeLayout(); + } + }); + const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap)=>wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1; + const params = Object.freeze({ + outerWidth: width, + outerHeight: height, + padding, + availableWidth, + availableHeight, + vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount, + hBoxMaxHeight: availableHeight / 2 + }); + const maxPadding = Object.assign({}, padding); + updateMaxPadding(maxPadding, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(minPadding)); + const chartArea = Object.assign({ + maxPadding, + w: availableWidth, + h: availableHeight, + x: padding.left, + y: padding.top + }, padding); + const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params); + fitBoxes(boxes.fullSize, chartArea, params, stacks); + fitBoxes(verticalBoxes, chartArea, params, stacks); + if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) { + fitBoxes(verticalBoxes, chartArea, params, stacks); + } + handleMaxPadding(chartArea); + placeBoxes(boxes.leftAndTop, chartArea, params, stacks); + chartArea.x += chartArea.w; + chartArea.y += chartArea.h; + placeBoxes(boxes.rightAndBottom, chartArea, params, stacks); + chart.chartArea = { + left: chartArea.left, + top: chartArea.top, + right: chartArea.left + chartArea.w, + bottom: chartArea.top + chartArea.h, + height: chartArea.h, + width: chartArea.w + }; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(boxes.chartArea, (layout)=>{ + const box = layout.box; + Object.assign(box, chart.chartArea); + box.update(chartArea.w, chartArea.h, { + left: 0, + top: 0, + right: 0, + bottom: 0 + }); + }); + } +}; + +class BasePlatform { + acquireContext(canvas, aspectRatio) {} + releaseContext(context) { + return false; + } + addEventListener(chart, type, listener) {} + removeEventListener(chart, type, listener) {} + getDevicePixelRatio() { + return 1; + } + getMaximumSize(element, width, height, aspectRatio) { + width = Math.max(0, width || element.width); + height = height || element.height; + return { + width, + height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height) + }; + } + isAttached(canvas) { + return true; + } + updateConfig(config) { + } +} + +class BasicPlatform extends BasePlatform { + acquireContext(item) { + return item && item.getContext && item.getContext('2d') || null; + } + updateConfig(config) { + config.options.animation = false; + } +} + +const EXPANDO_KEY = '$chartjs'; + const EVENT_TYPES = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup', + pointerenter: 'mouseenter', + pointerdown: 'mousedown', + pointermove: 'mousemove', + pointerup: 'mouseup', + pointerleave: 'mouseout', + pointerout: 'mouseout' +}; +const isNullOrEmpty = (value)=>value === null || value === ''; + function initCanvas(canvas, aspectRatio) { + const style = canvas.style; + const renderHeight = canvas.getAttribute('height'); + const renderWidth = canvas.getAttribute('width'); + canvas[EXPANDO_KEY] = { + initial: { + height: renderHeight, + width: renderWidth, + style: { + display: style.display, + height: style.height, + width: style.width + } + } + }; + style.display = style.display || 'block'; + style.boxSizing = style.boxSizing || 'border-box'; + if (isNullOrEmpty(renderWidth)) { + const displayWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'width'); + if (displayWidth !== undefined) { + canvas.width = displayWidth; + } + } + if (isNullOrEmpty(renderHeight)) { + if (canvas.style.height === '') { + canvas.height = canvas.width / (aspectRatio || 2); + } else { + const displayHeight = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.J)(canvas, 'height'); + if (displayHeight !== undefined) { + canvas.height = displayHeight; + } + } + } + return canvas; +} +const eventListenerOptions = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.K ? { + passive: true +} : false; +function addListener(node, type, listener) { + node.addEventListener(type, listener, eventListenerOptions); +} +function removeListener(chart, type, listener) { + chart.canvas.removeEventListener(type, listener, eventListenerOptions); +} +function fromNativeEvent(event, chart) { + const type = EVENT_TYPES[event.type] || event.type; + const { x , y } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.z)(event, chart); + return { + type, + chart, + native: event, + x: x !== undefined ? x : null, + y: y !== undefined ? y : null + }; +} +function nodeListContains(nodeList, canvas) { + for (const node of nodeList){ + if (node === canvas || node.contains(canvas)) { + return true; + } + } +} +function createAttachObserver(chart, type, listener) { + const canvas = chart.canvas; + const observer = new MutationObserver((entries)=>{ + let trigger = false; + for (const entry of entries){ + trigger = trigger || nodeListContains(entry.addedNodes, canvas); + trigger = trigger && !nodeListContains(entry.removedNodes, canvas); + } + if (trigger) { + listener(); + } + }); + observer.observe(document, { + childList: true, + subtree: true + }); + return observer; +} +function createDetachObserver(chart, type, listener) { + const canvas = chart.canvas; + const observer = new MutationObserver((entries)=>{ + let trigger = false; + for (const entry of entries){ + trigger = trigger || nodeListContains(entry.removedNodes, canvas); + trigger = trigger && !nodeListContains(entry.addedNodes, canvas); + } + if (trigger) { + listener(); + } + }); + observer.observe(document, { + childList: true, + subtree: true + }); + return observer; +} +const drpListeningCharts = new Map(); +let oldDevicePixelRatio = 0; +function onWindowResize() { + const dpr = window.devicePixelRatio; + if (dpr === oldDevicePixelRatio) { + return; + } + oldDevicePixelRatio = dpr; + drpListeningCharts.forEach((resize, chart)=>{ + if (chart.currentDevicePixelRatio !== dpr) { + resize(); + } + }); +} +function listenDevicePixelRatioChanges(chart, resize) { + if (!drpListeningCharts.size) { + window.addEventListener('resize', onWindowResize); + } + drpListeningCharts.set(chart, resize); +} +function unlistenDevicePixelRatioChanges(chart) { + drpListeningCharts.delete(chart); + if (!drpListeningCharts.size) { + window.removeEventListener('resize', onWindowResize); + } +} +function createResizeObserver(chart, type, listener) { + const canvas = chart.canvas; + const container = canvas && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas); + if (!container) { + return; + } + const resize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)((width, height)=>{ + const w = container.clientWidth; + listener(width, height); + if (w < container.clientWidth) { + listener(); + } + }, window); + const observer = new ResizeObserver((entries)=>{ + const entry = entries[0]; + const width = entry.contentRect.width; + const height = entry.contentRect.height; + if (width === 0 && height === 0) { + return; + } + resize(width, height); + }); + observer.observe(container); + listenDevicePixelRatioChanges(chart, resize); + return observer; +} +function releaseObserver(chart, type, observer) { + if (observer) { + observer.disconnect(); + } + if (type === 'resize') { + unlistenDevicePixelRatioChanges(chart); + } +} +function createProxyAndListen(chart, type, listener) { + const canvas = chart.canvas; + const proxy = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.L)((event)=>{ + if (chart.ctx !== null) { + listener(fromNativeEvent(event, chart)); + } + }, chart); + addListener(canvas, type, proxy); + return proxy; +} + class DomPlatform extends BasePlatform { + acquireContext(canvas, aspectRatio) { + const context = canvas && canvas.getContext && canvas.getContext('2d'); + if (context && context.canvas === canvas) { + initCanvas(canvas, aspectRatio); + return context; + } + return null; + } + releaseContext(context) { + const canvas = context.canvas; + if (!canvas[EXPANDO_KEY]) { + return false; + } + const initial = canvas[EXPANDO_KEY].initial; + [ + 'height', + 'width' + ].forEach((prop)=>{ + const value = initial[prop]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) { + canvas.removeAttribute(prop); + } else { + canvas.setAttribute(prop, value); + } + }); + const style = initial.style || {}; + Object.keys(style).forEach((key)=>{ + canvas.style[key] = style[key]; + }); + canvas.width = canvas.width; + delete canvas[EXPANDO_KEY]; + return true; + } + addEventListener(chart, type, listener) { + this.removeEventListener(chart, type); + const proxies = chart.$proxies || (chart.$proxies = {}); + const handlers = { + attach: createAttachObserver, + detach: createDetachObserver, + resize: createResizeObserver + }; + const handler = handlers[type] || createProxyAndListen; + proxies[type] = handler(chart, type, listener); + } + removeEventListener(chart, type) { + const proxies = chart.$proxies || (chart.$proxies = {}); + const proxy = proxies[type]; + if (!proxy) { + return; + } + const handlers = { + attach: releaseObserver, + detach: releaseObserver, + resize: releaseObserver + }; + const handler = handlers[type] || removeListener; + handler(chart, type, proxy); + proxies[type] = undefined; + } + getDevicePixelRatio() { + return window.devicePixelRatio; + } + getMaximumSize(canvas, width, height, aspectRatio) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.G)(canvas, width, height, aspectRatio); + } + isAttached(canvas) { + const container = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.I)(canvas); + return !!(container && container.isConnected); + } +} + +function _detectPlatform(canvas) { + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)() || typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) { + return BasicPlatform; + } + return DomPlatform; +} + +class Element { + static defaults = {}; + static defaultRoutes = undefined; + x; + y; + active = false; + options; + $animations; + tooltipPosition(useFinalPosition) { + const { x , y } = this.getProps([ + 'x', + 'y' + ], useFinalPosition); + return { + x, + y + }; + } + hasValue() { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.x) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(this.y); + } + getProps(props, final) { + const anims = this.$animations; + if (!final || !anims) { + // let's not create an object, if not needed + return this; + } + const ret = {}; + props.forEach((prop)=>{ + ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop]; + }); + return ret; + } +} + +function autoSkip(scale, ticks) { + const tickOpts = scale.options.ticks; + const determinedMaxTicks = determineMaxTicks(scale); + const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks); + const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : []; + const numMajorIndices = majorIndices.length; + const first = majorIndices[0]; + const last = majorIndices[numMajorIndices - 1]; + const newTicks = []; + if (numMajorIndices > ticksLimit) { + skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit); + return newTicks; + } + const spacing = calculateSpacing(majorIndices, ticks, ticksLimit); + if (numMajorIndices > 0) { + let i, ilen; + const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null; + skip(ticks, newTicks, spacing, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first); + for(i = 0, ilen = numMajorIndices - 1; i < ilen; i++){ + skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]); + } + skip(ticks, newTicks, spacing, last, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing); + return newTicks; + } + skip(ticks, newTicks, spacing); + return newTicks; +} +function determineMaxTicks(scale) { + const offset = scale.options.offset; + const tickLength = scale._tickSize(); + const maxScale = scale._length / tickLength + (offset ? 0 : 1); + const maxChart = scale._maxLength / tickLength; + return Math.floor(Math.min(maxScale, maxChart)); +} + function calculateSpacing(majorIndices, ticks, ticksLimit) { + const evenMajorSpacing = getEvenSpacing(majorIndices); + const spacing = ticks.length / ticksLimit; + if (!evenMajorSpacing) { + return Math.max(spacing, 1); + } + const factors = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.N)(evenMajorSpacing); + for(let i = 0, ilen = factors.length - 1; i < ilen; i++){ + const factor = factors[i]; + if (factor > spacing) { + return factor; + } + } + return Math.max(spacing, 1); +} + function getMajorIndices(ticks) { + const result = []; + let i, ilen; + for(i = 0, ilen = ticks.length; i < ilen; i++){ + if (ticks[i].major) { + result.push(i); + } + } + return result; +} + function skipMajors(ticks, newTicks, majorIndices, spacing) { + let count = 0; + let next = majorIndices[0]; + let i; + spacing = Math.ceil(spacing); + for(i = 0; i < ticks.length; i++){ + if (i === next) { + newTicks.push(ticks[i]); + count++; + next = majorIndices[count * spacing]; + } + } +} + function skip(ticks, newTicks, spacing, majorStart, majorEnd) { + const start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorStart, 0); + const end = Math.min((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(majorEnd, ticks.length), ticks.length); + let count = 0; + let length, i, next; + spacing = Math.ceil(spacing); + if (majorEnd) { + length = majorEnd - majorStart; + spacing = length / Math.floor(length / spacing); + } + next = start; + while(next < 0){ + count++; + next = Math.round(start + count * spacing); + } + for(i = Math.max(start, 0); i < end; i++){ + if (i === next) { + newTicks.push(ticks[i]); + count++; + next = Math.round(start + count * spacing); + } + } +} + function getEvenSpacing(arr) { + const len = arr.length; + let i, diff; + if (len < 2) { + return false; + } + for(diff = arr[0], i = 1; i < len; ++i){ + if (arr[i] - arr[i - 1] !== diff) { + return false; + } + } + return diff; +} + +const reverseAlign = (align)=>align === 'left' ? 'right' : align === 'right' ? 'left' : align; +const offsetFromEdge = (scale, edge, offset)=>edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset; +const getTicksLimit = (ticksLength, maxTicksLimit)=>Math.min(maxTicksLimit || ticksLength, ticksLength); + function sample(arr, numItems) { + const result = []; + const increment = arr.length / numItems; + const len = arr.length; + let i = 0; + for(; i < len; i += increment){ + result.push(arr[Math.floor(i)]); + } + return result; +} + function getPixelForGridLine(scale, index, offsetGridLines) { + const length = scale.ticks.length; + const validIndex = Math.min(index, length - 1); + const start = scale._startPixel; + const end = scale._endPixel; + const epsilon = 1e-6; + let lineValue = scale.getPixelForTick(validIndex); + let offset; + if (offsetGridLines) { + if (length === 1) { + offset = Math.max(lineValue - start, end - lineValue); + } else if (index === 0) { + offset = (scale.getPixelForTick(1) - lineValue) / 2; + } else { + offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2; + } + lineValue += validIndex < index ? offset : -offset; + if (lineValue < start - epsilon || lineValue > end + epsilon) { + return; + } + } + return lineValue; +} + function garbageCollect(caches, length) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(caches, (cache)=>{ + const gc = cache.gc; + const gcLen = gc.length / 2; + let i; + if (gcLen > length) { + for(i = 0; i < gcLen; ++i){ + delete cache.data[gc[i]]; + } + gc.splice(0, gcLen); + } + }); +} + function getTickMarkLength(options) { + return options.drawTicks ? options.tickLength : 0; +} + function getTitleHeight(options, fallback) { + if (!options.display) { + return 0; + } + const font = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.font, fallback); + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding); + const lines = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(options.text) ? options.text.length : 1; + return lines * font.lineHeight + padding.height; +} +function createScaleContext(parent, scale) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + scale, + type: 'scale' + }); +} +function createTickContext(parent, index, tick) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + tick, + index, + type: 'tick' + }); +} +function titleAlign(align, position, reverse) { + let ret = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a1)(align); + if (reverse && position !== 'right' || !reverse && position === 'right') { + ret = reverseAlign(ret); + } + return ret; +} +function titleArgs(scale, offset, position, align) { + const { top , left , bottom , right , chart } = scale; + const { chartArea , scales } = chart; + let rotation = 0; + let maxWidth, titleX, titleY; + const height = bottom - top; + const width = right - left; + if (scale.isHorizontal()) { + titleX = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + titleY = scales[positionAxisID].getPixelForValue(value) + height - offset; + } else if (position === 'center') { + titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset; + } else { + titleY = offsetFromEdge(scale, position, offset); + } + maxWidth = right - left; + } else { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + titleX = scales[positionAxisID].getPixelForValue(value) - width + offset; + } else if (position === 'center') { + titleX = (chartArea.left + chartArea.right) / 2 - width + offset; + } else { + titleX = offsetFromEdge(scale, position, offset); + } + titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top); + rotation = position === 'left' ? -_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H : _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H; + } + return { + titleX, + titleY, + maxWidth, + rotation + }; +} +class Scale extends Element { + constructor(cfg){ + super(); + this.id = cfg.id; + this.type = cfg.type; + this.options = undefined; + this.ctx = cfg.ctx; + this.chart = cfg.chart; + this.top = undefined; + this.bottom = undefined; + this.left = undefined; + this.right = undefined; + this.width = undefined; + this.height = undefined; + this._margins = { + left: 0, + right: 0, + top: 0, + bottom: 0 + }; + this.maxWidth = undefined; + this.maxHeight = undefined; + this.paddingTop = undefined; + this.paddingBottom = undefined; + this.paddingLeft = undefined; + this.paddingRight = undefined; + this.axis = undefined; + this.labelRotation = undefined; + this.min = undefined; + this.max = undefined; + this._range = undefined; + this.ticks = []; + this._gridLineItems = null; + this._labelItems = null; + this._labelSizes = null; + this._length = 0; + this._maxLength = 0; + this._longestTextCache = {}; + this._startPixel = undefined; + this._endPixel = undefined; + this._reversePixels = false; + this._userMax = undefined; + this._userMin = undefined; + this._suggestedMax = undefined; + this._suggestedMin = undefined; + this._ticksLength = 0; + this._borderValue = 0; + this._cache = {}; + this._dataLimitsCached = false; + this.$context = undefined; + } + init(options) { + this.options = options.setContext(this.getContext()); + this.axis = options.axis; + this._userMin = this.parse(options.min); + this._userMax = this.parse(options.max); + this._suggestedMin = this.parse(options.suggestedMin); + this._suggestedMax = this.parse(options.suggestedMax); + } + parse(raw, index) { + return raw; + } + getUserBounds() { + let { _userMin , _userMax , _suggestedMin , _suggestedMax } = this; + _userMin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, Number.POSITIVE_INFINITY); + _userMax = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, Number.NEGATIVE_INFINITY); + _suggestedMin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMin, Number.POSITIVE_INFINITY); + _suggestedMax = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_suggestedMax, Number.NEGATIVE_INFINITY); + return { + min: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMin, _suggestedMin), + max: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(_userMax, _suggestedMax), + minDefined: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMin), + maxDefined: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(_userMax) + }; + } + getMinMax(canStack) { + let { min , max , minDefined , maxDefined } = this.getUserBounds(); + let range; + if (minDefined && maxDefined) { + return { + min, + max + }; + } + const metas = this.getMatchingVisibleMetas(); + for(let i = 0, ilen = metas.length; i < ilen; ++i){ + range = metas[i].controller.getMinMax(this, canStack); + if (!minDefined) { + min = Math.min(min, range.min); + } + if (!maxDefined) { + max = Math.max(max, range.max); + } + } + min = maxDefined && min > max ? max : min; + max = minDefined && min > max ? min : max; + return { + min: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, min)), + max: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(max, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(min, max)) + }; + } + getPadding() { + return { + left: this.paddingLeft || 0, + top: this.paddingTop || 0, + right: this.paddingRight || 0, + bottom: this.paddingBottom || 0 + }; + } + getTicks() { + return this.ticks; + } + getLabels() { + const data = this.chart.data; + return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || []; + } + getLabelItems(chartArea = this.chart.chartArea) { + const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea)); + return items; + } + beforeLayout() { + this._cache = {}; + this._dataLimitsCached = false; + } + beforeUpdate() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeUpdate, [ + this + ]); + } + update(maxWidth, maxHeight, margins) { + const { beginAtZero , grace , ticks: tickOpts } = this.options; + const sampleSize = tickOpts.sampleSize; + this.beforeUpdate(); + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this._margins = margins = Object.assign({ + left: 0, + right: 0, + top: 0, + bottom: 0 + }, margins); + this.ticks = null; + this._labelSizes = null; + this._gridLineItems = null; + this._labelItems = null; + this.beforeSetDimensions(); + this.setDimensions(); + this.afterSetDimensions(); + this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom; + if (!this._dataLimitsCached) { + this.beforeDataLimits(); + this.determineDataLimits(); + this.afterDataLimits(); + this._range = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.R)(this, grace, beginAtZero); + this._dataLimitsCached = true; + } + this.beforeBuildTicks(); + this.ticks = this.buildTicks() || []; + this.afterBuildTicks(); + const samplingEnabled = sampleSize < this.ticks.length; + this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks); + this.configure(); + this.beforeCalculateLabelRotation(); + this.calculateLabelRotation(); + this.afterCalculateLabelRotation(); + if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) { + this.ticks = autoSkip(this, this.ticks); + this._labelSizes = null; + this.afterAutoSkip(); + } + if (samplingEnabled) { + this._convertTicksToLabels(this.ticks); + } + this.beforeFit(); + this.fit(); + this.afterFit(); + this.afterUpdate(); + } + configure() { + let reversePixels = this.options.reverse; + let startPixel, endPixel; + if (this.isHorizontal()) { + startPixel = this.left; + endPixel = this.right; + } else { + startPixel = this.top; + endPixel = this.bottom; + reversePixels = !reversePixels; + } + this._startPixel = startPixel; + this._endPixel = endPixel; + this._reversePixels = reversePixels; + this._length = endPixel - startPixel; + this._alignToPixels = this.options.alignToPixels; + } + afterUpdate() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterUpdate, [ + this + ]); + } + beforeSetDimensions() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeSetDimensions, [ + this + ]); + } + setDimensions() { + if (this.isHorizontal()) { + this.width = this.maxWidth; + this.left = 0; + this.right = this.width; + } else { + this.height = this.maxHeight; + this.top = 0; + this.bottom = this.height; + } + this.paddingLeft = 0; + this.paddingTop = 0; + this.paddingRight = 0; + this.paddingBottom = 0; + } + afterSetDimensions() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterSetDimensions, [ + this + ]); + } + _callHooks(name) { + this.chart.notifyPlugins(name, this.getContext()); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options[name], [ + this + ]); + } + beforeDataLimits() { + this._callHooks('beforeDataLimits'); + } + determineDataLimits() {} + afterDataLimits() { + this._callHooks('afterDataLimits'); + } + beforeBuildTicks() { + this._callHooks('beforeBuildTicks'); + } + buildTicks() { + return []; + } + afterBuildTicks() { + this._callHooks('afterBuildTicks'); + } + beforeTickToLabelConversion() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeTickToLabelConversion, [ + this + ]); + } + generateTickLabels(ticks) { + const tickOpts = this.options.ticks; + let i, ilen, tick; + for(i = 0, ilen = ticks.length; i < ilen; i++){ + tick = ticks[i]; + tick.label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(tickOpts.callback, [ + tick.value, + i, + ticks + ], this); + } + } + afterTickToLabelConversion() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterTickToLabelConversion, [ + this + ]); + } + beforeCalculateLabelRotation() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeCalculateLabelRotation, [ + this + ]); + } + calculateLabelRotation() { + const options = this.options; + const tickOpts = options.ticks; + const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit); + const minRotation = tickOpts.minRotation || 0; + const maxRotation = tickOpts.maxRotation; + let labelRotation = minRotation; + let tickWidth, maxHeight, maxLabelDiagonal; + if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) { + this.labelRotation = minRotation; + return; + } + const labelSizes = this._getLabelSizes(); + const maxLabelWidth = labelSizes.widest.width; + const maxLabelHeight = labelSizes.highest.height; + const maxWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(this.chart.width - maxLabelWidth, 0, this.maxWidth); + tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1); + if (maxLabelWidth + 6 > tickWidth) { + tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1)); + maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font); + maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight); + labelRotation = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(Math.min(Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(maxLabelHeight / maxLabelDiagonal, -1, 1)))); + labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation)); + } + this.labelRotation = labelRotation; + } + afterCalculateLabelRotation() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterCalculateLabelRotation, [ + this + ]); + } + afterAutoSkip() {} + beforeFit() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.beforeFit, [ + this + ]); + } + fit() { + const minSize = { + width: 0, + height: 0 + }; + const { chart , options: { ticks: tickOpts , title: titleOpts , grid: gridOpts } } = this; + const display = this._isVisible(); + const isHorizontal = this.isHorizontal(); + if (display) { + const titleHeight = getTitleHeight(titleOpts, chart.options.font); + if (isHorizontal) { + minSize.width = this.maxWidth; + minSize.height = getTickMarkLength(gridOpts) + titleHeight; + } else { + minSize.height = this.maxHeight; + minSize.width = getTickMarkLength(gridOpts) + titleHeight; + } + if (tickOpts.display && this.ticks.length) { + const { first , last , widest , highest } = this._getLabelSizes(); + const tickPadding = tickOpts.padding * 2; + const angleRadians = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation); + const cos = Math.cos(angleRadians); + const sin = Math.sin(angleRadians); + if (isHorizontal) { + const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height; + minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding); + } else { + const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height; + minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding); + } + this._calculatePadding(first, last, sin, cos); + } + } + this._handleMargins(); + if (isHorizontal) { + this.width = this._length = chart.width - this._margins.left - this._margins.right; + this.height = minSize.height; + } else { + this.width = minSize.width; + this.height = this._length = chart.height - this._margins.top - this._margins.bottom; + } + } + _calculatePadding(first, last, sin, cos) { + const { ticks: { align , padding } , position } = this.options; + const isRotated = this.labelRotation !== 0; + const labelsBelowTicks = position !== 'top' && this.axis === 'x'; + if (this.isHorizontal()) { + const offsetLeft = this.getPixelForTick(0) - this.left; + const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1); + let paddingLeft = 0; + let paddingRight = 0; + if (isRotated) { + if (labelsBelowTicks) { + paddingLeft = cos * first.width; + paddingRight = sin * last.height; + } else { + paddingLeft = sin * first.height; + paddingRight = cos * last.width; + } + } else if (align === 'start') { + paddingRight = last.width; + } else if (align === 'end') { + paddingLeft = first.width; + } else if (align !== 'inner') { + paddingLeft = first.width / 2; + paddingRight = last.width / 2; + } + this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0); + this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0); + } else { + let paddingTop = last.height / 2; + let paddingBottom = first.height / 2; + if (align === 'start') { + paddingTop = 0; + paddingBottom = first.height; + } else if (align === 'end') { + paddingTop = last.height; + paddingBottom = 0; + } + this.paddingTop = paddingTop + padding; + this.paddingBottom = paddingBottom + padding; + } + } + _handleMargins() { + if (this._margins) { + this._margins.left = Math.max(this.paddingLeft, this._margins.left); + this._margins.top = Math.max(this.paddingTop, this._margins.top); + this._margins.right = Math.max(this.paddingRight, this._margins.right); + this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom); + } + } + afterFit() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.afterFit, [ + this + ]); + } + isHorizontal() { + const { axis , position } = this.options; + return position === 'top' || position === 'bottom' || axis === 'x'; + } + isFullSize() { + return this.options.fullSize; + } + _convertTicksToLabels(ticks) { + this.beforeTickToLabelConversion(); + this.generateTickLabels(ticks); + let i, ilen; + for(i = 0, ilen = ticks.length; i < ilen; i++){ + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(ticks[i].label)) { + ticks.splice(i, 1); + ilen--; + i--; + } + } + this.afterTickToLabelConversion(); + } + _getLabelSizes() { + let labelSizes = this._labelSizes; + if (!labelSizes) { + const sampleSize = this.options.ticks.sampleSize; + let ticks = this.ticks; + if (sampleSize < ticks.length) { + ticks = sample(ticks, sampleSize); + } + this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit); + } + return labelSizes; + } + _computeLabelSizes(ticks, length, maxTicksLimit) { + const { ctx , _longestTextCache: caches } = this; + const widths = []; + const heights = []; + const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit)); + let widestLabelSize = 0; + let highestLabelSize = 0; + let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel; + for(i = 0; i < length; i += increment){ + label = ticks[i].label; + tickFont = this._resolveTickFontOptions(i); + ctx.font = fontString = tickFont.string; + cache = caches[fontString] = caches[fontString] || { + data: {}, + gc: [] + }; + lineHeight = tickFont.lineHeight; + width = height = 0; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(label) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) { + width = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, label); + height = lineHeight; + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label)) { + for(j = 0, jlen = label.length; j < jlen; ++j){ + nestedLabel = label[j]; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(nestedLabel) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(nestedLabel)) { + width = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.V)(ctx, cache.data, cache.gc, width, nestedLabel); + height += lineHeight; + } + } + } + widths.push(width); + heights.push(height); + widestLabelSize = Math.max(width, widestLabelSize); + highestLabelSize = Math.max(height, highestLabelSize); + } + garbageCollect(caches, length); + const widest = widths.indexOf(widestLabelSize); + const highest = heights.indexOf(highestLabelSize); + const valueAt = (idx)=>({ + width: widths[idx] || 0, + height: heights[idx] || 0 + }); + return { + first: valueAt(0), + last: valueAt(length - 1), + widest: valueAt(widest), + highest: valueAt(highest), + widths, + heights + }; + } + getLabelForValue(value) { + return value; + } + getPixelForValue(value, index) { + return NaN; + } + getValueForPixel(pixel) {} + getPixelForTick(index) { + const ticks = this.ticks; + if (index < 0 || index > ticks.length - 1) { + return null; + } + return this.getPixelForValue(ticks[index].value); + } + getPixelForDecimal(decimal) { + if (this._reversePixels) { + decimal = 1 - decimal; + } + const pixel = this._startPixel + decimal * this._length; + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.W)(this._alignToPixels ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(this.chart, pixel, 0) : pixel); + } + getDecimalForPixel(pixel) { + const decimal = (pixel - this._startPixel) / this._length; + return this._reversePixels ? 1 - decimal : decimal; + } + getBasePixel() { + return this.getPixelForValue(this.getBaseValue()); + } + getBaseValue() { + const { min , max } = this; + return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0; + } + getContext(index) { + const ticks = this.ticks || []; + if (index >= 0 && index < ticks.length) { + const tick = ticks[index]; + return tick.$context || (tick.$context = createTickContext(this.getContext(), index, tick)); + } + return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this)); + } + _tickSize() { + const optionTicks = this.options.ticks; + const rot = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation); + const cos = Math.abs(Math.cos(rot)); + const sin = Math.abs(Math.sin(rot)); + const labelSizes = this._getLabelSizes(); + const padding = optionTicks.autoSkipPadding || 0; + const w = labelSizes ? labelSizes.widest.width + padding : 0; + const h = labelSizes ? labelSizes.highest.height + padding : 0; + return this.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin; + } + _isVisible() { + const display = this.options.display; + if (display !== 'auto') { + return !!display; + } + return this.getMatchingVisibleMetas().length > 0; + } + _computeGridLineItems(chartArea) { + const axis = this.axis; + const chart = this.chart; + const options = this.options; + const { grid , position , border } = options; + const offset = grid.offset; + const isHorizontal = this.isHorizontal(); + const ticks = this.ticks; + const ticksLength = ticks.length + (offset ? 1 : 0); + const tl = getTickMarkLength(grid); + const items = []; + const borderOpts = border.setContext(this.getContext()); + const axisWidth = borderOpts.display ? borderOpts.width : 0; + const axisHalfWidth = axisWidth / 2; + const alignBorderValue = function(pixel) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, pixel, axisWidth); + }; + let borderValue, i, lineValue, alignedLineValue; + let tx1, ty1, tx2, ty2, x1, y1, x2, y2; + if (position === 'top') { + borderValue = alignBorderValue(this.bottom); + ty1 = this.bottom - tl; + ty2 = borderValue - axisHalfWidth; + y1 = alignBorderValue(chartArea.top) + axisHalfWidth; + y2 = chartArea.bottom; + } else if (position === 'bottom') { + borderValue = alignBorderValue(this.top); + y1 = chartArea.top; + y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth; + ty1 = borderValue + axisHalfWidth; + ty2 = this.top + tl; + } else if (position === 'left') { + borderValue = alignBorderValue(this.right); + tx1 = this.right - tl; + tx2 = borderValue - axisHalfWidth; + x1 = alignBorderValue(chartArea.left) + axisHalfWidth; + x2 = chartArea.right; + } else if (position === 'right') { + borderValue = alignBorderValue(this.left); + x1 = chartArea.left; + x2 = alignBorderValue(chartArea.right) - axisHalfWidth; + tx1 = borderValue + axisHalfWidth; + tx2 = this.left + tl; + } else if (axis === 'x') { + if (position === 'center') { + borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5); + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value)); + } + y1 = chartArea.top; + y2 = chartArea.bottom; + ty1 = borderValue + axisHalfWidth; + ty2 = ty1 + tl; + } else if (axis === 'y') { + if (position === 'center') { + borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2); + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value)); + } + tx1 = borderValue - axisHalfWidth; + tx2 = tx1 - tl; + x1 = chartArea.left; + x2 = chartArea.right; + } + const limit = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.maxTicksLimit, ticksLength); + const step = Math.max(1, Math.ceil(ticksLength / limit)); + for(i = 0; i < ticksLength; i += step){ + const context = this.getContext(i); + const optsAtIndex = grid.setContext(context); + const optsAtIndexBorder = border.setContext(context); + const lineWidth = optsAtIndex.lineWidth; + const lineColor = optsAtIndex.color; + const borderDash = optsAtIndexBorder.dash || []; + const borderDashOffset = optsAtIndexBorder.dashOffset; + const tickWidth = optsAtIndex.tickWidth; + const tickColor = optsAtIndex.tickColor; + const tickBorderDash = optsAtIndex.tickBorderDash || []; + const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset; + lineValue = getPixelForGridLine(this, i, offset); + if (lineValue === undefined) { + continue; + } + alignedLineValue = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, lineValue, lineWidth); + if (isHorizontal) { + tx1 = tx2 = x1 = x2 = alignedLineValue; + } else { + ty1 = ty2 = y1 = y2 = alignedLineValue; + } + items.push({ + tx1, + ty1, + tx2, + ty2, + x1, + y1, + x2, + y2, + width: lineWidth, + color: lineColor, + borderDash, + borderDashOffset, + tickWidth, + tickColor, + tickBorderDash, + tickBorderDashOffset + }); + } + this._ticksLength = ticksLength; + this._borderValue = borderValue; + return items; + } + _computeLabelItems(chartArea) { + const axis = this.axis; + const options = this.options; + const { position , ticks: optionTicks } = options; + const isHorizontal = this.isHorizontal(); + const ticks = this.ticks; + const { align , crossAlign , padding , mirror } = optionTicks; + const tl = getTickMarkLength(options.grid); + const tickAndPadding = tl + padding; + const hTickAndPadding = mirror ? -padding : tickAndPadding; + const rotation = -(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation); + const items = []; + let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset; + let textBaseline = 'middle'; + if (position === 'top') { + y = this.bottom - hTickAndPadding; + textAlign = this._getXAxisLabelAlignment(); + } else if (position === 'bottom') { + y = this.top + hTickAndPadding; + textAlign = this._getXAxisLabelAlignment(); + } else if (position === 'left') { + const ret = this._getYAxisLabelAlignment(tl); + textAlign = ret.textAlign; + x = ret.x; + } else if (position === 'right') { + const ret = this._getYAxisLabelAlignment(tl); + textAlign = ret.textAlign; + x = ret.x; + } else if (axis === 'x') { + if (position === 'center') { + y = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding; + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding; + } + textAlign = this._getXAxisLabelAlignment(); + } else if (axis === 'y') { + if (position === 'center') { + x = (chartArea.left + chartArea.right) / 2 - tickAndPadding; + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + const positionAxisID = Object.keys(position)[0]; + const value = position[positionAxisID]; + x = this.chart.scales[positionAxisID].getPixelForValue(value); + } + textAlign = this._getYAxisLabelAlignment(tl).textAlign; + } + if (axis === 'y') { + if (align === 'start') { + textBaseline = 'top'; + } else if (align === 'end') { + textBaseline = 'bottom'; + } + } + const labelSizes = this._getLabelSizes(); + for(i = 0, ilen = ticks.length; i < ilen; ++i){ + tick = ticks[i]; + label = tick.label; + const optsAtIndex = optionTicks.setContext(this.getContext(i)); + pixel = this.getPixelForTick(i) + optionTicks.labelOffset; + font = this._resolveTickFontOptions(i); + lineHeight = font.lineHeight; + lineCount = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label.length : 1; + const halfCount = lineCount / 2; + const color = optsAtIndex.color; + const strokeColor = optsAtIndex.textStrokeColor; + const strokeWidth = optsAtIndex.textStrokeWidth; + let tickTextAlign = textAlign; + if (isHorizontal) { + x = pixel; + if (textAlign === 'inner') { + if (i === ilen - 1) { + tickTextAlign = !this.options.reverse ? 'right' : 'left'; + } else if (i === 0) { + tickTextAlign = !this.options.reverse ? 'left' : 'right'; + } else { + tickTextAlign = 'center'; + } + } + if (position === 'top') { + if (crossAlign === 'near' || rotation !== 0) { + textOffset = -lineCount * lineHeight + lineHeight / 2; + } else if (crossAlign === 'center') { + textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight; + } else { + textOffset = -labelSizes.highest.height + lineHeight / 2; + } + } else { + if (crossAlign === 'near' || rotation !== 0) { + textOffset = lineHeight / 2; + } else if (crossAlign === 'center') { + textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight; + } else { + textOffset = labelSizes.highest.height - lineCount * lineHeight; + } + } + if (mirror) { + textOffset *= -1; + } + if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) { + x += lineHeight / 2 * Math.sin(rotation); + } + } else { + y = pixel; + textOffset = (1 - lineCount) * lineHeight / 2; + } + let backdrop; + if (optsAtIndex.showLabelBackdrop) { + const labelPadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding); + const height = labelSizes.heights[i]; + const width = labelSizes.widths[i]; + let top = textOffset - labelPadding.top; + let left = 0 - labelPadding.left; + switch(textBaseline){ + case 'middle': + top -= height / 2; + break; + case 'bottom': + top -= height; + break; + } + switch(textAlign){ + case 'center': + left -= width / 2; + break; + case 'right': + left -= width; + break; + } + backdrop = { + left, + top, + width: width + labelPadding.width, + height: height + labelPadding.height, + color: optsAtIndex.backdropColor + }; + } + items.push({ + label, + font, + textOffset, + options: { + rotation, + color, + strokeColor, + strokeWidth, + textAlign: tickTextAlign, + textBaseline, + translation: [ + x, + y + ], + backdrop + } + }); + } + return items; + } + _getXAxisLabelAlignment() { + const { position , ticks } = this.options; + const rotation = -(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.labelRotation); + if (rotation) { + return position === 'top' ? 'left' : 'right'; + } + let align = 'center'; + if (ticks.align === 'start') { + align = 'left'; + } else if (ticks.align === 'end') { + align = 'right'; + } else if (ticks.align === 'inner') { + align = 'inner'; + } + return align; + } + _getYAxisLabelAlignment(tl) { + const { position , ticks: { crossAlign , mirror , padding } } = this.options; + const labelSizes = this._getLabelSizes(); + const tickAndPadding = tl + padding; + const widest = labelSizes.widest.width; + let textAlign; + let x; + if (position === 'left') { + if (mirror) { + x = this.right + padding; + if (crossAlign === 'near') { + textAlign = 'left'; + } else if (crossAlign === 'center') { + textAlign = 'center'; + x += widest / 2; + } else { + textAlign = 'right'; + x += widest; + } + } else { + x = this.right - tickAndPadding; + if (crossAlign === 'near') { + textAlign = 'right'; + } else if (crossAlign === 'center') { + textAlign = 'center'; + x -= widest / 2; + } else { + textAlign = 'left'; + x = this.left; + } + } + } else if (position === 'right') { + if (mirror) { + x = this.left + padding; + if (crossAlign === 'near') { + textAlign = 'right'; + } else if (crossAlign === 'center') { + textAlign = 'center'; + x -= widest / 2; + } else { + textAlign = 'left'; + x -= widest; + } + } else { + x = this.left + tickAndPadding; + if (crossAlign === 'near') { + textAlign = 'left'; + } else if (crossAlign === 'center') { + textAlign = 'center'; + x += widest / 2; + } else { + textAlign = 'right'; + x = this.right; + } + } + } else { + textAlign = 'right'; + } + return { + textAlign, + x + }; + } + _computeLabelArea() { + if (this.options.ticks.mirror) { + return; + } + const chart = this.chart; + const position = this.options.position; + if (position === 'left' || position === 'right') { + return { + top: 0, + left: this.left, + bottom: chart.height, + right: this.right + }; + } + if (position === 'top' || position === 'bottom') { + return { + top: this.top, + left: 0, + bottom: this.bottom, + right: chart.width + }; + } + } + drawBackground() { + const { ctx , options: { backgroundColor } , left , top , width , height } = this; + if (backgroundColor) { + ctx.save(); + ctx.fillStyle = backgroundColor; + ctx.fillRect(left, top, width, height); + ctx.restore(); + } + } + getLineWidthForValue(value) { + const grid = this.options.grid; + if (!this._isVisible() || !grid.display) { + return 0; + } + const ticks = this.ticks; + const index = ticks.findIndex((t)=>t.value === value); + if (index >= 0) { + const opts = grid.setContext(this.getContext(index)); + return opts.lineWidth; + } + return 0; + } + drawGrid(chartArea) { + const grid = this.options.grid; + const ctx = this.ctx; + const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea)); + let i, ilen; + const drawLine = (p1, p2, style)=>{ + if (!style.width || !style.color) { + return; + } + ctx.save(); + ctx.lineWidth = style.width; + ctx.strokeStyle = style.color; + ctx.setLineDash(style.borderDash || []); + ctx.lineDashOffset = style.borderDashOffset; + ctx.beginPath(); + ctx.moveTo(p1.x, p1.y); + ctx.lineTo(p2.x, p2.y); + ctx.stroke(); + ctx.restore(); + }; + if (grid.display) { + for(i = 0, ilen = items.length; i < ilen; ++i){ + const item = items[i]; + if (grid.drawOnChartArea) { + drawLine({ + x: item.x1, + y: item.y1 + }, { + x: item.x2, + y: item.y2 + }, item); + } + if (grid.drawTicks) { + drawLine({ + x: item.tx1, + y: item.ty1 + }, { + x: item.tx2, + y: item.ty2 + }, { + color: item.tickColor, + width: item.tickWidth, + borderDash: item.tickBorderDash, + borderDashOffset: item.tickBorderDashOffset + }); + } + } + } + } + drawBorder() { + const { chart , ctx , options: { border , grid } } = this; + const borderOpts = border.setContext(this.getContext()); + const axisWidth = border.display ? borderOpts.width : 0; + if (!axisWidth) { + return; + } + const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth; + const borderValue = this._borderValue; + let x1, x2, y1, y2; + if (this.isHorizontal()) { + x1 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.left, axisWidth) - axisWidth / 2; + x2 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.right, lastLineWidth) + lastLineWidth / 2; + y1 = y2 = borderValue; + } else { + y1 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.top, axisWidth) - axisWidth / 2; + y2 = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.X)(chart, this.bottom, lastLineWidth) + lastLineWidth / 2; + x1 = x2 = borderValue; + } + ctx.save(); + ctx.lineWidth = borderOpts.width; + ctx.strokeStyle = borderOpts.color; + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); + ctx.restore(); + } + drawLabels(chartArea) { + const optionTicks = this.options.ticks; + if (!optionTicks.display) { + return; + } + const ctx = this.ctx; + const area = this._computeLabelArea(); + if (area) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area); + } + const items = this.getLabelItems(chartArea); + for (const item of items){ + const renderTextOptions = item.options; + const tickFont = item.font; + const label = item.label; + const y = item.textOffset; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, label, 0, y, tickFont, renderTextOptions); + } + if (area) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx); + } + } + drawTitle() { + const { ctx , options: { position , title , reverse } } = this; + if (!title.display) { + return; + } + const font = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(title.font); + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(title.padding); + const align = title.align; + let offset = font.lineHeight / 2; + if (position === 'bottom' || position === 'center' || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(position)) { + offset += padding.bottom; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(title.text)) { + offset += font.lineHeight * (title.text.length - 1); + } + } else { + offset += padding.top; + } + const { titleX , titleY , maxWidth , rotation } = titleArgs(this, offset, position, align); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, title.text, 0, 0, font, { + color: title.color, + maxWidth, + rotation, + textAlign: titleAlign(align, position, reverse), + textBaseline: 'middle', + translation: [ + titleX, + titleY + ] + }); + } + draw(chartArea) { + if (!this._isVisible()) { + return; + } + this.drawBackground(); + this.drawGrid(chartArea); + this.drawBorder(); + this.drawTitle(); + this.drawLabels(chartArea); + } + _layers() { + const opts = this.options; + const tz = opts.ticks && opts.ticks.z || 0; + const gz = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.grid && opts.grid.z, -1); + const bz = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(opts.border && opts.border.z, 0); + if (!this._isVisible() || this.draw !== Scale.prototype.draw) { + return [ + { + z: tz, + draw: (chartArea)=>{ + this.draw(chartArea); + } + } + ]; + } + return [ + { + z: gz, + draw: (chartArea)=>{ + this.drawBackground(); + this.drawGrid(chartArea); + this.drawTitle(); + } + }, + { + z: bz, + draw: ()=>{ + this.drawBorder(); + } + }, + { + z: tz, + draw: (chartArea)=>{ + this.drawLabels(chartArea); + } + } + ]; + } + getMatchingVisibleMetas(type) { + const metas = this.chart.getSortedVisibleDatasetMetas(); + const axisID = this.axis + 'AxisID'; + const result = []; + let i, ilen; + for(i = 0, ilen = metas.length; i < ilen; ++i){ + const meta = metas[i]; + if (meta[axisID] === this.id && (!type || meta.type === type)) { + result.push(meta); + } + } + return result; + } + _resolveTickFontOptions(index) { + const opts = this.options.ticks.setContext(this.getContext(index)); + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font); + } + _maxDigits() { + const fontSize = this._resolveTickFontOptions(0).lineHeight; + return (this.isHorizontal() ? this.width : this.height) / fontSize; + } +} + +class TypedRegistry { + constructor(type, scope, override){ + this.type = type; + this.scope = scope; + this.override = override; + this.items = Object.create(null); + } + isForType(type) { + return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype); + } + register(item) { + const proto = Object.getPrototypeOf(item); + let parentScope; + if (isIChartComponent(proto)) { + parentScope = this.register(proto); + } + const items = this.items; + const id = item.id; + const scope = this.scope + '.' + id; + if (!id) { + throw new Error('class does not have id: ' + item); + } + if (id in items) { + return scope; + } + items[id] = item; + registerDefaults(item, scope, parentScope); + if (this.override) { + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.override(item.id, item.overrides); + } + return scope; + } + get(id) { + return this.items[id]; + } + unregister(item) { + const items = this.items; + const id = item.id; + const scope = this.scope; + if (id in items) { + delete items[id]; + } + if (scope && id in _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d[scope]) { + delete _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d[scope][id]; + if (this.override) { + delete _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3[id]; + } + } + } +} +function registerDefaults(item, scope, parentScope) { + const itemDefaults = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a4)(Object.create(null), [ + parentScope ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.get(parentScope) : {}, + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.get(scope), + item.defaults + ]); + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.set(scope, itemDefaults); + if (item.defaultRoutes) { + routeDefaults(scope, item.defaultRoutes); + } + if (item.descriptors) { + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.describe(scope, item.descriptors); + } +} +function routeDefaults(scope, routes) { + Object.keys(routes).forEach((property)=>{ + const propertyParts = property.split('.'); + const sourceName = propertyParts.pop(); + const sourceScope = [ + scope + ].concat(propertyParts).join('.'); + const parts = routes[property].split('.'); + const targetName = parts.pop(); + const targetScope = parts.join('.'); + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.route(sourceScope, sourceName, targetScope, targetName); + }); +} +function isIChartComponent(proto) { + return 'id' in proto && 'defaults' in proto; +} + +class Registry { + constructor(){ + this.controllers = new TypedRegistry(DatasetController, 'datasets', true); + this.elements = new TypedRegistry(Element, 'elements'); + this.plugins = new TypedRegistry(Object, 'plugins'); + this.scales = new TypedRegistry(Scale, 'scales'); + this._typedRegistries = [ + this.controllers, + this.scales, + this.elements + ]; + } + add(...args) { + this._each('register', args); + } + remove(...args) { + this._each('unregister', args); + } + addControllers(...args) { + this._each('register', args, this.controllers); + } + addElements(...args) { + this._each('register', args, this.elements); + } + addPlugins(...args) { + this._each('register', args, this.plugins); + } + addScales(...args) { + this._each('register', args, this.scales); + } + getController(id) { + return this._get(id, this.controllers, 'controller'); + } + getElement(id) { + return this._get(id, this.elements, 'element'); + } + getPlugin(id) { + return this._get(id, this.plugins, 'plugin'); + } + getScale(id) { + return this._get(id, this.scales, 'scale'); + } + removeControllers(...args) { + this._each('unregister', args, this.controllers); + } + removeElements(...args) { + this._each('unregister', args, this.elements); + } + removePlugins(...args) { + this._each('unregister', args, this.plugins); + } + removeScales(...args) { + this._each('unregister', args, this.scales); + } + _each(method, args, typedRegistry) { + [ + ...args + ].forEach((arg)=>{ + const reg = typedRegistry || this._getRegistryForType(arg); + if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) { + this._exec(method, reg, arg); + } else { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(arg, (item)=>{ + const itemReg = typedRegistry || this._getRegistryForType(item); + this._exec(method, itemReg, item); + }); + } + }); + } + _exec(method, registry, component) { + const camelMethod = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a5)(method); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['before' + camelMethod], [], component); + registry[method](component); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(component['after' + camelMethod], [], component); + } + _getRegistryForType(type) { + for(let i = 0; i < this._typedRegistries.length; i++){ + const reg = this._typedRegistries[i]; + if (reg.isForType(type)) { + return reg; + } + } + return this.plugins; + } + _get(id, typedRegistry, type) { + const item = typedRegistry.get(id); + if (item === undefined) { + throw new Error('"' + id + '" is not a registered ' + type + '.'); + } + return item; + } +} +var registry = /* #__PURE__ */ new Registry(); + +class PluginService { + constructor(){ + this._init = []; + } + notify(chart, hook, args, filter) { + if (hook === 'beforeInit') { + this._init = this._createDescriptors(chart, true); + this._notify(this._init, chart, 'install'); + } + const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart); + const result = this._notify(descriptors, chart, hook, args); + if (hook === 'afterDestroy') { + this._notify(descriptors, chart, 'stop'); + this._notify(this._init, chart, 'uninstall'); + } + return result; + } + _notify(descriptors, chart, hook, args) { + args = args || {}; + for (const descriptor of descriptors){ + const plugin = descriptor.plugin; + const method = plugin[hook]; + const params = [ + chart, + args, + descriptor.options + ]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(method, params, plugin) === false && args.cancelable) { + return false; + } + } + return true; + } + invalidate() { + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(this._cache)) { + this._oldCache = this._cache; + this._cache = undefined; + } + } + _descriptors(chart) { + if (this._cache) { + return this._cache; + } + const descriptors = this._cache = this._createDescriptors(chart); + this._notifyStateChanges(chart); + return descriptors; + } + _createDescriptors(chart, all) { + const config = chart && chart.config; + const options = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(config.options && config.options.plugins, {}); + const plugins = allPlugins(config); + return options === false && !all ? [] : createDescriptors(chart, plugins, options, all); + } + _notifyStateChanges(chart) { + const previousDescriptors = this._oldCache || []; + const descriptors = this._cache; + const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.plugin.id === y.plugin.id)); + this._notify(diff(previousDescriptors, descriptors), chart, 'stop'); + this._notify(diff(descriptors, previousDescriptors), chart, 'start'); + } +} + function allPlugins(config) { + const localIds = {}; + const plugins = []; + const keys = Object.keys(registry.plugins.items); + for(let i = 0; i < keys.length; i++){ + plugins.push(registry.getPlugin(keys[i])); + } + const local = config.plugins || []; + for(let i = 0; i < local.length; i++){ + const plugin = local[i]; + if (plugins.indexOf(plugin) === -1) { + plugins.push(plugin); + localIds[plugin.id] = true; + } + } + return { + plugins, + localIds + }; +} +function getOpts(options, all) { + if (!all && options === false) { + return null; + } + if (options === true) { + return {}; + } + return options; +} +function createDescriptors(chart, { plugins , localIds }, options, all) { + const result = []; + const context = chart.getContext(); + for (const plugin of plugins){ + const id = plugin.id; + const opts = getOpts(options[id], all); + if (opts === null) { + continue; + } + result.push({ + plugin, + options: pluginOpts(chart.config, { + plugin, + local: localIds[id] + }, opts, context) + }); + } + return result; +} +function pluginOpts(config, { plugin , local }, opts, context) { + const keys = config.pluginScopeKeys(plugin); + const scopes = config.getOptionScopes(opts, keys); + if (local && plugin.defaults) { + scopes.push(plugin.defaults); + } + return config.createResolver(scopes, context, [ + '' + ], { + scriptable: false, + indexable: false, + allKeys: true + }); +} + +function getIndexAxis(type, options) { + const datasetDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {}; + const datasetOptions = (options.datasets || {})[type] || {}; + return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x'; +} +function getAxisFromDefaultScaleID(id, indexAxis) { + let axis = id; + if (id === '_index_') { + axis = indexAxis; + } else if (id === '_value_') { + axis = indexAxis === 'x' ? 'y' : 'x'; + } + return axis; +} +function getDefaultScaleIDFromAxis(axis, indexAxis) { + return axis === indexAxis ? '_index_' : '_value_'; +} +function idMatchesAxis(id) { + if (id === 'x' || id === 'y' || id === 'r') { + return id; + } +} +function axisFromPosition(position) { + if (position === 'top' || position === 'bottom') { + return 'x'; + } + if (position === 'left' || position === 'right') { + return 'y'; + } +} +function determineAxis(id, ...scaleOptions) { + if (idMatchesAxis(id)) { + return id; + } + for (const opts of scaleOptions){ + const axis = opts.axis || axisFromPosition(opts.position) || id.length > 1 && idMatchesAxis(id[0].toLowerCase()); + if (axis) { + return axis; + } + } + throw new Error(`Cannot determine type of '${id}' axis. Please provide 'axis' or 'position' option.`); +} +function getAxisFromDataset(id, axis, dataset) { + if (dataset[axis + 'AxisID'] === id) { + return { + axis + }; + } +} +function retrieveAxisFromDatasets(id, config) { + if (config.data && config.data.datasets) { + const boundDs = config.data.datasets.filter((d)=>d.xAxisID === id || d.yAxisID === id); + if (boundDs.length) { + return getAxisFromDataset(id, 'x', boundDs[0]) || getAxisFromDataset(id, 'y', boundDs[0]); + } + } + return {}; +} +function mergeScaleConfig(config, options) { + const chartDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3[config.type] || { + scales: {} + }; + const configScales = options.scales || {}; + const chartIndexAxis = getIndexAxis(config.type, options); + const scales = Object.create(null); + Object.keys(configScales).forEach((id)=>{ + const scaleConf = configScales[id]; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(scaleConf)) { + return console.error(`Invalid scale configuration for scale: ${id}`); + } + if (scaleConf._proxy) { + return console.warn(`Ignoring resolver passed as options for scale: ${id}`); + } + const axis = determineAxis(id, scaleConf, retrieveAxisFromDatasets(id, config), _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scaleConf.type]); + const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis); + const defaultScaleOptions = chartDefaults.scales || {}; + scales[id] = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(Object.create(null), [ + { + axis + }, + scaleConf, + defaultScaleOptions[axis], + defaultScaleOptions[defaultId] + ]); + }); + config.data.datasets.forEach((dataset)=>{ + const type = dataset.type || config.type; + const indexAxis = dataset.indexAxis || getIndexAxis(type, options); + const datasetDefaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {}; + const defaultScaleOptions = datasetDefaults.scales || {}; + Object.keys(defaultScaleOptions).forEach((defaultID)=>{ + const axis = getAxisFromDefaultScaleID(defaultID, indexAxis); + const id = dataset[axis + 'AxisID'] || axis; + scales[id] = scales[id] || Object.create(null); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scales[id], [ + { + axis + }, + configScales[id], + defaultScaleOptions[defaultID] + ]); + }); + }); + Object.keys(scales).forEach((key)=>{ + const scale = scales[key]; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(scale, [ + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.scales[scale.type], + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.scale + ]); + }); + return scales; +} +function initOptions(config) { + const options = config.options || (config.options = {}); + options.plugins = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.plugins, {}); + options.scales = mergeScaleConfig(config, options); +} +function initData(data) { + data = data || {}; + data.datasets = data.datasets || []; + data.labels = data.labels || []; + return data; +} +function initConfig(config) { + config = config || {}; + config.data = initData(config.data); + initOptions(config); + return config; +} +const keyCache = new Map(); +const keysCached = new Set(); +function cachedKeys(cacheKey, generate) { + let keys = keyCache.get(cacheKey); + if (!keys) { + keys = generate(); + keyCache.set(cacheKey, keys); + keysCached.add(keys); + } + return keys; +} +const addIfFound = (set, obj, key)=>{ + const opts = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.f)(obj, key); + if (opts !== undefined) { + set.add(opts); + } +}; +class Config { + constructor(config){ + this._config = initConfig(config); + this._scopeCache = new Map(); + this._resolverCache = new Map(); + } + get platform() { + return this._config.platform; + } + get type() { + return this._config.type; + } + set type(type) { + this._config.type = type; + } + get data() { + return this._config.data; + } + set data(data) { + this._config.data = initData(data); + } + get options() { + return this._config.options; + } + set options(options) { + this._config.options = options; + } + get plugins() { + return this._config.plugins; + } + update() { + const config = this._config; + this.clearCache(); + initOptions(config); + } + clearCache() { + this._scopeCache.clear(); + this._resolverCache.clear(); + } + datasetScopeKeys(datasetType) { + return cachedKeys(datasetType, ()=>[ + [ + `datasets.${datasetType}`, + '' + ] + ]); + } + datasetAnimationScopeKeys(datasetType, transition) { + return cachedKeys(`${datasetType}.transition.${transition}`, ()=>[ + [ + `datasets.${datasetType}.transitions.${transition}`, + `transitions.${transition}` + ], + [ + `datasets.${datasetType}`, + '' + ] + ]); + } + datasetElementScopeKeys(datasetType, elementType) { + return cachedKeys(`${datasetType}-${elementType}`, ()=>[ + [ + `datasets.${datasetType}.elements.${elementType}`, + `datasets.${datasetType}`, + `elements.${elementType}`, + '' + ] + ]); + } + pluginScopeKeys(plugin) { + const id = plugin.id; + const type = this.type; + return cachedKeys(`${type}-plugin-${id}`, ()=>[ + [ + `plugins.${id}`, + ...plugin.additionalOptionScopes || [] + ] + ]); + } + _cachedScopes(mainScope, resetCache) { + const _scopeCache = this._scopeCache; + let cache = _scopeCache.get(mainScope); + if (!cache || resetCache) { + cache = new Map(); + _scopeCache.set(mainScope, cache); + } + return cache; + } + getOptionScopes(mainScope, keyLists, resetCache) { + const { options , type } = this; + const cache = this._cachedScopes(mainScope, resetCache); + const cached = cache.get(keyLists); + if (cached) { + return cached; + } + const scopes = new Set(); + keyLists.forEach((keys)=>{ + if (mainScope) { + scopes.add(mainScope); + keys.forEach((key)=>addIfFound(scopes, mainScope, key)); + } + keys.forEach((key)=>addIfFound(scopes, options, key)); + keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {}, key)); + keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d, key)); + keys.forEach((key)=>addIfFound(scopes, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a6, key)); + }); + const array = Array.from(scopes); + if (array.length === 0) { + array.push(Object.create(null)); + } + if (keysCached.has(keyLists)) { + cache.set(keyLists, array); + } + return array; + } + chartOptionScopes() { + const { options , type } = this; + return [ + options, + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3[type] || {}, + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type] || {}, + { + type + }, + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d, + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a6 + ]; + } + resolveNamedOptions(scopes, names, context, prefixes = [ + '' + ]) { + const result = { + $shared: true + }; + const { resolver , subPrefixes } = getResolver(this._resolverCache, scopes, prefixes); + let options = resolver; + if (needContext(resolver, names)) { + result.$shared = false; + context = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(context) ? context() : context; + const subResolver = this.createResolver(scopes, context, subPrefixes); + options = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, subResolver); + } + for (const prop of names){ + result[prop] = options[prop]; + } + return result; + } + createResolver(scopes, context, prefixes = [ + '' + ], descriptorDefaults) { + const { resolver } = getResolver(this._resolverCache, scopes, prefixes); + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(context) ? (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a8)(resolver, context, undefined, descriptorDefaults) : resolver; + } +} +function getResolver(resolverCache, scopes, prefixes) { + let cache = resolverCache.get(scopes); + if (!cache) { + cache = new Map(); + resolverCache.set(scopes, cache); + } + const cacheKey = prefixes.join(); + let cached = cache.get(cacheKey); + if (!cached) { + const resolver = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a9)(scopes, prefixes); + cached = { + resolver, + subPrefixes: prefixes.filter((p)=>!p.toLowerCase().includes('hover')) + }; + cache.set(cacheKey, cached); + } + return cached; +} +const hasFunction = (value)=>(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(value) && Object.getOwnPropertyNames(value).reduce((acc, key)=>acc || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value[key]), false); +function needContext(proxy, names) { + const { isScriptable , isIndexable } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aa)(proxy); + for (const prop of names){ + const scriptable = isScriptable(prop); + const indexable = isIndexable(prop); + const value = (indexable || scriptable) && proxy[prop]; + if (scriptable && ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(value) || hasFunction(value)) || indexable && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(value)) { + return true; + } + } + return false; +} + +var version = "4.3.0"; + +const KNOWN_POSITIONS = [ + 'top', + 'bottom', + 'left', + 'right', + 'chartArea' +]; +function positionIsHorizontal(position, axis) { + return position === 'top' || position === 'bottom' || KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x'; +} +function compare2Level(l1, l2) { + return function(a, b) { + return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1]; + }; +} +function onAnimationsComplete(context) { + const chart = context.chart; + const animationOptions = chart.options.animation; + chart.notifyPlugins('afterRender'); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onComplete, [ + context + ], chart); +} +function onAnimationProgress(context) { + const chart = context.chart; + const animationOptions = chart.options.animation; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(animationOptions && animationOptions.onProgress, [ + context + ], chart); +} + function getCanvas(item) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.M)() && typeof item === 'string') { + item = document.getElementById(item); + } else if (item && item.length) { + item = item[0]; + } + if (item && item.canvas) { + item = item.canvas; + } + return item; +} +const instances = {}; +const getChart = (key)=>{ + const canvas = getCanvas(key); + return Object.values(instances).filter((c)=>c.canvas === canvas).pop(); +}; +function moveNumericKeys(obj, start, move) { + const keys = Object.keys(obj); + for (const key of keys){ + const intKey = +key; + if (intKey >= start) { + const value = obj[key]; + delete obj[key]; + if (move > 0 || intKey > start) { + obj[intKey + move] = value; + } + } + } +} + function determineLastEvent(e, lastEvent, inChartArea, isClick) { + if (!inChartArea || e.type === 'mouseout') { + return null; + } + if (isClick) { + return lastEvent; + } + return e; +} +function getDatasetArea(meta) { + const { xScale , yScale } = meta; + if (xScale && yScale) { + return { + left: xScale.left, + right: xScale.right, + top: yScale.top, + bottom: yScale.bottom + }; + } +} +class Chart { + static defaults = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d; + static instances = instances; + static overrides = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a3; + static registry = registry; + static version = version; + static getChart = getChart; + static register(...items) { + registry.add(...items); + invalidatePlugins(); + } + static unregister(...items) { + registry.remove(...items); + invalidatePlugins(); + } + constructor(item, userConfig){ + const config = this.config = new Config(userConfig); + const initialCanvas = getCanvas(item); + const existingChart = getChart(initialCanvas); + if (existingChart) { + throw new Error('Canvas is already in use. Chart with ID \'' + existingChart.id + '\'' + ' must be destroyed before the canvas with ID \'' + existingChart.canvas.id + '\' can be reused.'); + } + const options = config.createResolver(config.chartOptionScopes(), this.getContext()); + this.platform = new (config.platform || _detectPlatform(initialCanvas))(); + this.platform.updateConfig(config); + const context = this.platform.acquireContext(initialCanvas, options.aspectRatio); + const canvas = context && context.canvas; + const height = canvas && canvas.height; + const width = canvas && canvas.width; + this.id = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ac)(); + this.ctx = context; + this.canvas = canvas; + this.width = width; + this.height = height; + this._options = options; + this._aspectRatio = this.aspectRatio; + this._layers = []; + this._metasets = []; + this._stacks = undefined; + this.boxes = []; + this.currentDevicePixelRatio = undefined; + this.chartArea = undefined; + this._active = []; + this._lastEvent = undefined; + this._listeners = {}; + this._responsiveListeners = undefined; + this._sortedMetasets = []; + this.scales = {}; + this._plugins = new PluginService(); + this.$proxies = {}; + this._hiddenIndices = {}; + this.attached = false; + this._animationsDisabled = undefined; + this.$context = undefined; + this._doResize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ad)((mode)=>this.update(mode), options.resizeDelay || 0); + this._dataChanges = []; + instances[this.id] = this; + if (!context || !canvas) { + console.error("Failed to create chart: can't acquire context from the given item"); + return; + } + animator.listen(this, 'complete', onAnimationsComplete); + animator.listen(this, 'progress', onAnimationProgress); + this._initialize(); + if (this.attached) { + this.update(); + } + } + get aspectRatio() { + const { options: { aspectRatio , maintainAspectRatio } , width , height , _aspectRatio } = this; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(aspectRatio)) { + return aspectRatio; + } + if (maintainAspectRatio && _aspectRatio) { + return _aspectRatio; + } + return height ? width / height : null; + } + get data() { + return this.config.data; + } + set data(data) { + this.config.data = data; + } + get options() { + return this._options; + } + set options(options) { + this.config.options = options; + } + get registry() { + return registry; + } + _initialize() { + this.notifyPlugins('beforeInit'); + if (this.options.responsive) { + this.resize(); + } else { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, this.options.devicePixelRatio); + } + this.bindEvents(); + this.notifyPlugins('afterInit'); + return this; + } + clear() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.af)(this.canvas, this.ctx); + return this; + } + stop() { + animator.stop(this); + return this; + } + resize(width, height) { + if (!animator.running(this)) { + this._resize(width, height); + } else { + this._resizeBeforeDraw = { + width, + height + }; + } + } + _resize(width, height) { + const options = this.options; + const canvas = this.canvas; + const aspectRatio = options.maintainAspectRatio && this.aspectRatio; + const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio); + const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio(); + const mode = this.width ? 'resize' : 'attach'; + this.width = newSize.width; + this.height = newSize.height; + this._aspectRatio = this.aspectRatio; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ae)(this, newRatio, true)) { + return; + } + this.notifyPlugins('resize', { + size: newSize + }); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onResize, [ + this, + newSize + ], this); + if (this.attached) { + if (this._doResize(mode)) { + this.render(); + } + } + } + ensureScalesHaveIDs() { + const options = this.options; + const scalesOptions = options.scales || {}; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(scalesOptions, (axisOptions, axisID)=>{ + axisOptions.id = axisID; + }); + } + buildOrUpdateScales() { + const options = this.options; + const scaleOpts = options.scales; + const scales = this.scales; + const updated = Object.keys(scales).reduce((obj, id)=>{ + obj[id] = false; + return obj; + }, {}); + let items = []; + if (scaleOpts) { + items = items.concat(Object.keys(scaleOpts).map((id)=>{ + const scaleOptions = scaleOpts[id]; + const axis = determineAxis(id, scaleOptions); + const isRadial = axis === 'r'; + const isHorizontal = axis === 'x'; + return { + options: scaleOptions, + dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left', + dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear' + }; + })); + } + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(items, (item)=>{ + const scaleOptions = item.options; + const id = scaleOptions.id; + const axis = determineAxis(id, scaleOptions); + const scaleType = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(scaleOptions.type, item.dtype); + if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) { + scaleOptions.position = item.dposition; + } + updated[id] = true; + let scale = null; + if (id in scales && scales[id].type === scaleType) { + scale = scales[id]; + } else { + const scaleClass = registry.getScale(scaleType); + scale = new scaleClass({ + id, + type: scaleType, + ctx: this.ctx, + chart: this + }); + scales[scale.id] = scale; + } + scale.init(scaleOptions, options); + }); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(updated, (hasUpdated, id)=>{ + if (!hasUpdated) { + delete scales[id]; + } + }); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(scales, (scale)=>{ + layouts.configure(this, scale, scale.options); + layouts.addBox(this, scale); + }); + } + _updateMetasets() { + const metasets = this._metasets; + const numData = this.data.datasets.length; + const numMeta = metasets.length; + metasets.sort((a, b)=>a.index - b.index); + if (numMeta > numData) { + for(let i = numData; i < numMeta; ++i){ + this._destroyDatasetMeta(i); + } + metasets.splice(numData, numMeta - numData); + } + this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index')); + } + _removeUnreferencedMetasets() { + const { _metasets: metasets , data: { datasets } } = this; + if (metasets.length > datasets.length) { + delete this._stacks; + } + metasets.forEach((meta, index)=>{ + if (datasets.filter((x)=>x === meta._dataset).length === 0) { + this._destroyDatasetMeta(index); + } + }); + } + buildOrUpdateControllers() { + const newControllers = []; + const datasets = this.data.datasets; + let i, ilen; + this._removeUnreferencedMetasets(); + for(i = 0, ilen = datasets.length; i < ilen; i++){ + const dataset = datasets[i]; + let meta = this.getDatasetMeta(i); + const type = dataset.type || this.config.type; + if (meta.type && meta.type !== type) { + this._destroyDatasetMeta(i); + meta = this.getDatasetMeta(i); + } + meta.type = type; + meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options); + meta.order = dataset.order || 0; + meta.index = i; + meta.label = '' + dataset.label; + meta.visible = this.isDatasetVisible(i); + if (meta.controller) { + meta.controller.updateIndex(i); + meta.controller.linkScales(); + } else { + const ControllerClass = registry.getController(type); + const { datasetElementType , dataElementType } = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.datasets[type]; + Object.assign(ControllerClass, { + dataElementType: registry.getElement(dataElementType), + datasetElementType: datasetElementType && registry.getElement(datasetElementType) + }); + meta.controller = new ControllerClass(this, i); + newControllers.push(meta.controller); + } + } + this._updateMetasets(); + return newControllers; + } + _resetElements() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.data.datasets, (dataset, datasetIndex)=>{ + this.getDatasetMeta(datasetIndex).controller.reset(); + }, this); + } + reset() { + this._resetElements(); + this.notifyPlugins('reset'); + } + update(mode) { + const config = this.config; + config.update(); + const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext()); + const animsDisabled = this._animationsDisabled = !options.animation; + this._updateScales(); + this._checkEventBindings(); + this._updateHiddenIndices(); + this._plugins.invalidate(); + if (this.notifyPlugins('beforeUpdate', { + mode, + cancelable: true + }) === false) { + return; + } + const newControllers = this.buildOrUpdateControllers(); + this.notifyPlugins('beforeElementsUpdate'); + let minPadding = 0; + for(let i = 0, ilen = this.data.datasets.length; i < ilen; i++){ + const { controller } = this.getDatasetMeta(i); + const reset = !animsDisabled && newControllers.indexOf(controller) === -1; + controller.buildOrUpdateElements(reset); + minPadding = Math.max(+controller.getMaxOverflow(), minPadding); + } + minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0; + this._updateLayout(minPadding); + if (!animsDisabled) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(newControllers, (controller)=>{ + controller.reset(); + }); + } + this._updateDatasets(mode); + this.notifyPlugins('afterUpdate', { + mode + }); + this._layers.sort(compare2Level('z', '_idx')); + const { _active , _lastEvent } = this; + if (_lastEvent) { + this._eventHandler(_lastEvent, true); + } else if (_active.length) { + this._updateHoverStyles(_active, _active, true); + } + this.render(); + } + _updateScales() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.scales, (scale)=>{ + layouts.removeBox(this, scale); + }); + this.ensureScalesHaveIDs(); + this.buildOrUpdateScales(); + } + _checkEventBindings() { + const options = this.options; + const existingEvents = new Set(Object.keys(this._listeners)); + const newEvents = new Set(options.events); + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ag)(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) { + this.unbindEvents(); + this.bindEvents(); + } + } + _updateHiddenIndices() { + const { _hiddenIndices } = this; + const changes = this._getUniformDataChanges() || []; + for (const { method , start , count } of changes){ + const move = method === '_removeElements' ? -count : count; + moveNumericKeys(_hiddenIndices, start, move); + } + } + _getUniformDataChanges() { + const _dataChanges = this._dataChanges; + if (!_dataChanges || !_dataChanges.length) { + return; + } + this._dataChanges = []; + const datasetCount = this.data.datasets.length; + const makeSet = (idx)=>new Set(_dataChanges.filter((c)=>c[0] === idx).map((c, i)=>i + ',' + c.splice(1).join(','))); + const changeSet = makeSet(0); + for(let i = 1; i < datasetCount; i++){ + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ag)(changeSet, makeSet(i))) { + return; + } + } + return Array.from(changeSet).map((c)=>c.split(',')).map((a)=>({ + method: a[1], + start: +a[2], + count: +a[3] + })); + } + _updateLayout(minPadding) { + if (this.notifyPlugins('beforeLayout', { + cancelable: true + }) === false) { + return; + } + layouts.update(this, this.width, this.height, minPadding); + const area = this.chartArea; + const noArea = area.width <= 0 || area.height <= 0; + this._layers = []; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.boxes, (box)=>{ + if (noArea && box.position === 'chartArea') { + return; + } + if (box.configure) { + box.configure(); + } + this._layers.push(...box._layers()); + }, this); + this._layers.forEach((item, index)=>{ + item._idx = index; + }); + this.notifyPlugins('afterLayout'); + } + _updateDatasets(mode) { + if (this.notifyPlugins('beforeDatasetsUpdate', { + mode, + cancelable: true + }) === false) { + return; + } + for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){ + this.getDatasetMeta(i).controller.configure(); + } + for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){ + this._updateDataset(i, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a7)(mode) ? mode({ + datasetIndex: i + }) : mode); + } + this.notifyPlugins('afterDatasetsUpdate', { + mode + }); + } + _updateDataset(index, mode) { + const meta = this.getDatasetMeta(index); + const args = { + meta, + index, + mode, + cancelable: true + }; + if (this.notifyPlugins('beforeDatasetUpdate', args) === false) { + return; + } + meta.controller._update(mode); + args.cancelable = false; + this.notifyPlugins('afterDatasetUpdate', args); + } + render() { + if (this.notifyPlugins('beforeRender', { + cancelable: true + }) === false) { + return; + } + if (animator.has(this)) { + if (this.attached && !animator.running(this)) { + animator.start(this); + } + } else { + this.draw(); + onAnimationsComplete({ + chart: this + }); + } + } + draw() { + let i; + if (this._resizeBeforeDraw) { + const { width , height } = this._resizeBeforeDraw; + this._resize(width, height); + this._resizeBeforeDraw = null; + } + this.clear(); + if (this.width <= 0 || this.height <= 0) { + return; + } + if (this.notifyPlugins('beforeDraw', { + cancelable: true + }) === false) { + return; + } + const layers = this._layers; + for(i = 0; i < layers.length && layers[i].z <= 0; ++i){ + layers[i].draw(this.chartArea); + } + this._drawDatasets(); + for(; i < layers.length; ++i){ + layers[i].draw(this.chartArea); + } + this.notifyPlugins('afterDraw'); + } + _getSortedDatasetMetas(filterVisible) { + const metasets = this._sortedMetasets; + const result = []; + let i, ilen; + for(i = 0, ilen = metasets.length; i < ilen; ++i){ + const meta = metasets[i]; + if (!filterVisible || meta.visible) { + result.push(meta); + } + } + return result; + } + getSortedVisibleDatasetMetas() { + return this._getSortedDatasetMetas(true); + } + _drawDatasets() { + if (this.notifyPlugins('beforeDatasetsDraw', { + cancelable: true + }) === false) { + return; + } + const metasets = this.getSortedVisibleDatasetMetas(); + for(let i = metasets.length - 1; i >= 0; --i){ + this._drawDataset(metasets[i]); + } + this.notifyPlugins('afterDatasetsDraw'); + } + _drawDataset(meta) { + const ctx = this.ctx; + const clip = meta._clip; + const useClip = !clip.disabled; + const area = getDatasetArea(meta) || this.chartArea; + const args = { + meta, + index: meta.index, + cancelable: true + }; + if (this.notifyPlugins('beforeDatasetDraw', args) === false) { + return; + } + if (useClip) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, { + left: clip.left === false ? 0 : area.left - clip.left, + right: clip.right === false ? this.width : area.right + clip.right, + top: clip.top === false ? 0 : area.top - clip.top, + bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom + }); + } + meta.controller.draw(); + if (useClip) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx); + } + args.cancelable = false; + this.notifyPlugins('afterDatasetDraw', args); + } + isPointInArea(point) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)(point, this.chartArea, this._minPadding); + } + getElementsAtEventForMode(e, mode, options, useFinalPosition) { + const method = Interaction.modes[mode]; + if (typeof method === 'function') { + return method(this, e, options, useFinalPosition); + } + return []; + } + getDatasetMeta(datasetIndex) { + const dataset = this.data.datasets[datasetIndex]; + const metasets = this._metasets; + let meta = metasets.filter((x)=>x && x._dataset === dataset).pop(); + if (!meta) { + meta = { + type: null, + data: [], + dataset: null, + controller: null, + hidden: null, + xAxisID: null, + yAxisID: null, + order: dataset && dataset.order || 0, + index: datasetIndex, + _dataset: dataset, + _parsed: [], + _sorted: false + }; + metasets.push(meta); + } + return meta; + } + getContext() { + return this.$context || (this.$context = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(null, { + chart: this, + type: 'chart' + })); + } + getVisibleDatasetCount() { + return this.getSortedVisibleDatasetMetas().length; + } + isDatasetVisible(datasetIndex) { + const dataset = this.data.datasets[datasetIndex]; + if (!dataset) { + return false; + } + const meta = this.getDatasetMeta(datasetIndex); + return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden; + } + setDatasetVisibility(datasetIndex, visible) { + const meta = this.getDatasetMeta(datasetIndex); + meta.hidden = !visible; + } + toggleDataVisibility(index) { + this._hiddenIndices[index] = !this._hiddenIndices[index]; + } + getDataVisibility(index) { + return !this._hiddenIndices[index]; + } + _updateVisibility(datasetIndex, dataIndex, visible) { + const mode = visible ? 'show' : 'hide'; + const meta = this.getDatasetMeta(datasetIndex); + const anims = meta.controller._resolveAnimations(undefined, mode); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.h)(dataIndex)) { + meta.data[dataIndex].hidden = !visible; + this.update(); + } else { + this.setDatasetVisibility(datasetIndex, visible); + anims.update(meta, { + visible + }); + this.update((ctx)=>ctx.datasetIndex === datasetIndex ? mode : undefined); + } + } + hide(datasetIndex, dataIndex) { + this._updateVisibility(datasetIndex, dataIndex, false); + } + show(datasetIndex, dataIndex) { + this._updateVisibility(datasetIndex, dataIndex, true); + } + _destroyDatasetMeta(datasetIndex) { + const meta = this._metasets[datasetIndex]; + if (meta && meta.controller) { + meta.controller._destroy(); + } + delete this._metasets[datasetIndex]; + } + _stop() { + let i, ilen; + this.stop(); + animator.remove(this); + for(i = 0, ilen = this.data.datasets.length; i < ilen; ++i){ + this._destroyDatasetMeta(i); + } + } + destroy() { + this.notifyPlugins('beforeDestroy'); + const { canvas , ctx } = this; + this._stop(); + this.config.clearCache(); + if (canvas) { + this.unbindEvents(); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.af)(canvas, ctx); + this.platform.releaseContext(ctx); + this.canvas = null; + this.ctx = null; + } + delete instances[this.id]; + this.notifyPlugins('afterDestroy'); + } + toBase64Image(...args) { + return this.canvas.toDataURL(...args); + } + bindEvents() { + this.bindUserEvents(); + if (this.options.responsive) { + this.bindResponsiveEvents(); + } else { + this.attached = true; + } + } + bindUserEvents() { + const listeners = this._listeners; + const platform = this.platform; + const _add = (type, listener)=>{ + platform.addEventListener(this, type, listener); + listeners[type] = listener; + }; + const listener = (e, x, y)=>{ + e.offsetX = x; + e.offsetY = y; + this._eventHandler(e); + }; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.options.events, (type)=>_add(type, listener)); + } + bindResponsiveEvents() { + if (!this._responsiveListeners) { + this._responsiveListeners = {}; + } + const listeners = this._responsiveListeners; + const platform = this.platform; + const _add = (type, listener)=>{ + platform.addEventListener(this, type, listener); + listeners[type] = listener; + }; + const _remove = (type, listener)=>{ + if (listeners[type]) { + platform.removeEventListener(this, type, listener); + delete listeners[type]; + } + }; + const listener = (width, height)=>{ + if (this.canvas) { + this.resize(width, height); + } + }; + let detached; + const attached = ()=>{ + _remove('attach', attached); + this.attached = true; + this.resize(); + _add('resize', listener); + _add('detach', detached); + }; + detached = ()=>{ + this.attached = false; + _remove('resize', listener); + this._stop(); + this._resize(0, 0); + _add('attach', attached); + }; + if (platform.isAttached(this.canvas)) { + attached(); + } else { + detached(); + } + } + unbindEvents() { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._listeners, (listener, type)=>{ + this.platform.removeEventListener(this, type, listener); + }); + this._listeners = {}; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this._responsiveListeners, (listener, type)=>{ + this.platform.removeEventListener(this, type, listener); + }); + this._responsiveListeners = undefined; + } + updateHoverStyle(items, mode, enabled) { + const prefix = enabled ? 'set' : 'remove'; + let meta, item, i, ilen; + if (mode === 'dataset') { + meta = this.getDatasetMeta(items[0].datasetIndex); + meta.controller['_' + prefix + 'DatasetHoverStyle'](); + } + for(i = 0, ilen = items.length; i < ilen; ++i){ + item = items[i]; + const controller = item && this.getDatasetMeta(item.datasetIndex).controller; + if (controller) { + controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index); + } + } + } + getActiveElements() { + return this._active || []; + } + setActiveElements(activeElements) { + const lastActive = this._active || []; + const active = activeElements.map(({ datasetIndex , index })=>{ + const meta = this.getDatasetMeta(datasetIndex); + if (!meta) { + throw new Error('No dataset found at index ' + datasetIndex); + } + return { + datasetIndex, + element: meta.data[index], + index + }; + }); + const changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ah)(active, lastActive); + if (changed) { + this._active = active; + this._lastEvent = null; + this._updateHoverStyles(active, lastActive); + } + } + notifyPlugins(hook, args, filter) { + return this._plugins.notify(this, hook, args, filter); + } + isPluginEnabled(pluginId) { + return this._plugins._cache.filter((p)=>p.plugin.id === pluginId).length === 1; + } + _updateHoverStyles(active, lastActive, replay) { + const hoverOptions = this.options.hover; + const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.datasetIndex === y.datasetIndex && x.index === y.index)); + const deactivated = diff(lastActive, active); + const activated = replay ? active : diff(active, lastActive); + if (deactivated.length) { + this.updateHoverStyle(deactivated, hoverOptions.mode, false); + } + if (activated.length && hoverOptions.mode) { + this.updateHoverStyle(activated, hoverOptions.mode, true); + } + } + _eventHandler(e, replay) { + const args = { + event: e, + replay, + cancelable: true, + inChartArea: this.isPointInArea(e) + }; + const eventFilter = (plugin)=>(plugin.options.events || this.options.events).includes(e.native.type); + if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) { + return; + } + const changed = this._handleEvent(e, replay, args.inChartArea); + args.cancelable = false; + this.notifyPlugins('afterEvent', args, eventFilter); + if (changed || args.changed) { + this.render(); + } + return this; + } + _handleEvent(e, replay, inChartArea) { + const { _active: lastActive = [] , options } = this; + const useFinalPosition = replay; + const active = this._getActiveElements(e, lastActive, inChartArea, useFinalPosition); + const isClick = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ai)(e); + const lastEvent = determineLastEvent(e, this._lastEvent, inChartArea, isClick); + if (inChartArea) { + this._lastEvent = null; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onHover, [ + e, + active, + this + ], this); + if (isClick) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(options.onClick, [ + e, + active, + this + ], this); + } + } + const changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ah)(active, lastActive); + if (changed || replay) { + this._active = active; + this._updateHoverStyles(active, lastActive, replay); + } + this._lastEvent = lastEvent; + return changed; + } + _getActiveElements(e, lastActive, inChartArea, useFinalPosition) { + if (e.type === 'mouseout') { + return []; + } + if (!inChartArea) { + return lastActive; + } + const hoverOptions = this.options.hover; + return this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition); + } +} +function invalidatePlugins() { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(Chart.instances, (chart)=>chart._plugins.invalidate()); +} + +function clipArc(ctx, element, endAngle) { + const { startAngle , pixelMargin , x , y , outerRadius , innerRadius } = element; + let angleMargin = pixelMargin / outerRadius; + // Draw an inner border by clipping the arc and drawing a double-width border + // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders + ctx.beginPath(); + ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin); + if (innerRadius > pixelMargin) { + angleMargin = pixelMargin / innerRadius; + ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true); + } else { + ctx.arc(x, y, pixelMargin, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); + } + ctx.closePath(); + ctx.clip(); +} +function toRadiusCorners(value) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ak)(value, [ + 'outerStart', + 'outerEnd', + 'innerStart', + 'innerEnd' + ]); +} +/** + * Parse border radius from the provided options + */ function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) { + const o = toRadiusCorners(arc.options.borderRadius); + const halfThickness = (outerRadius - innerRadius) / 2; + const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2); + // Outer limits are complicated. We want to compute the available angular distance at + // a radius of outerRadius - borderRadius because for small angular distances, this term limits. + // We compute at r = outerRadius - borderRadius because this circle defines the center of the border corners. + // + // If the borderRadius is large, that value can become negative. + // This causes the outer borders to lose their radius entirely, which is rather unexpected. To solve that, if borderRadius > outerRadius + // we know that the thickness term will dominate and compute the limits at that point + const computeOuterLimit = (val)=>{ + const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2; + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(val, 0, Math.min(halfThickness, outerArcLimit)); + }; + return { + outerStart: computeOuterLimit(o.outerStart), + outerEnd: computeOuterLimit(o.outerEnd), + innerStart: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerStart, 0, innerLimit), + innerEnd: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(o.innerEnd, 0, innerLimit) + }; +} +/** + * Convert (r, 𝜃) to (x, y) + */ function rThetaToXY(r, theta, x, y) { + return { + x: x + r * Math.cos(theta), + y: y + r * Math.sin(theta) + }; +} +/** + * Path the arc, respecting border radius by separating into left and right halves. + * + * Start End + * + * 1--->a--->2 Outer + * / \ + * 8 3 + * | | + * | | + * 7 4 + * \ / + * 6<---b<---5 Inner + */ function pathArc(ctx, element, offset, spacing, end, circular) { + const { x , y , startAngle: start , pixelMargin , innerRadius: innerR } = element; + const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0); + const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0; + let spacingOffset = 0; + const alpha = end - start; + if (spacing) { + // When spacing is present, it is the same for all items + // So we adjust the start and end angle of the arc such that + // the distance is the same as it would be without the spacing + const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0; + const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0; + const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2; + const adjustedAngle = avNogSpacingRadius !== 0 ? alpha * avNogSpacingRadius / (avNogSpacingRadius + spacing) : alpha; + spacingOffset = (alpha - adjustedAngle) / 2; + } + const beta = Math.max(0.001, alpha * outerRadius - offset / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P) / outerRadius; + const angleOffset = (alpha - beta) / 2; + const startAngle = start + angleOffset + spacingOffset; + const endAngle = end - angleOffset - spacingOffset; + const { outerStart , outerEnd , innerStart , innerEnd } = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle); + const outerStartAdjustedRadius = outerRadius - outerStart; + const outerEndAdjustedRadius = outerRadius - outerEnd; + const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius; + const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius; + const innerStartAdjustedRadius = innerRadius + innerStart; + const innerEndAdjustedRadius = innerRadius + innerEnd; + const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius; + const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius; + ctx.beginPath(); + if (circular) { + // The first arc segments from point 1 to point a to point 2 + const outerMidAdjustedAngle = (outerStartAdjustedAngle + outerEndAdjustedAngle) / 2; + ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerMidAdjustedAngle); + ctx.arc(x, y, outerRadius, outerMidAdjustedAngle, outerEndAdjustedAngle); + // The corner segment from point 2 to point 3 + if (outerEnd > 0) { + const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y); + ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); + } + // The line from point 3 to point 4 + const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y); + ctx.lineTo(p4.x, p4.y); + // The corner segment from point 4 to point 5 + if (innerEnd > 0) { + const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y); + ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, innerEndAdjustedAngle + Math.PI); + } + // The inner arc from point 5 to point b to point 6 + const innerMidAdjustedAngle = (endAngle - innerEnd / innerRadius + (startAngle + innerStart / innerRadius)) / 2; + ctx.arc(x, y, innerRadius, endAngle - innerEnd / innerRadius, innerMidAdjustedAngle, true); + ctx.arc(x, y, innerRadius, innerMidAdjustedAngle, startAngle + innerStart / innerRadius, true); + // The corner segment from point 6 to point 7 + if (innerStart > 0) { + const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y); + ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H); + } + // The line from point 7 to point 8 + const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y); + ctx.lineTo(p8.x, p8.y); + // The corner segment from point 8 to point 1 + if (outerStart > 0) { + const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y); + ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H, outerStartAdjustedAngle); + } + } else { + ctx.moveTo(x, y); + const outerStartX = Math.cos(outerStartAdjustedAngle) * outerRadius + x; + const outerStartY = Math.sin(outerStartAdjustedAngle) * outerRadius + y; + ctx.lineTo(outerStartX, outerStartY); + const outerEndX = Math.cos(outerEndAdjustedAngle) * outerRadius + x; + const outerEndY = Math.sin(outerEndAdjustedAngle) * outerRadius + y; + ctx.lineTo(outerEndX, outerEndY); + } + ctx.closePath(); +} +function drawArc(ctx, element, offset, spacing, circular) { + const { fullCircles , startAngle , circumference } = element; + let endAngle = element.endAngle; + if (fullCircles) { + pathArc(ctx, element, offset, spacing, endAngle, circular); + for(let i = 0; i < fullCircles; ++i){ + ctx.fill(); + } + if (!isNaN(circumference)) { + endAngle = startAngle + (circumference % _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); + } + } + pathArc(ctx, element, offset, spacing, endAngle, circular); + ctx.fill(); + return endAngle; +} +function drawBorder(ctx, element, offset, spacing, circular) { + const { fullCircles , startAngle , circumference , options } = element; + const { borderWidth , borderJoinStyle , borderDash , borderDashOffset } = options; + const inner = options.borderAlign === 'inner'; + if (!borderWidth) { + return; + } + ctx.setLineDash(borderDash || []); + ctx.lineDashOffset = borderDashOffset; + if (inner) { + ctx.lineWidth = borderWidth * 2; + ctx.lineJoin = borderJoinStyle || 'round'; + } else { + ctx.lineWidth = borderWidth; + ctx.lineJoin = borderJoinStyle || 'bevel'; + } + let endAngle = element.endAngle; + if (fullCircles) { + pathArc(ctx, element, offset, spacing, endAngle, circular); + for(let i = 0; i < fullCircles; ++i){ + ctx.stroke(); + } + if (!isNaN(circumference)) { + endAngle = startAngle + (circumference % _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T || _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); + } + } + if (inner) { + clipArc(ctx, element, endAngle); + } + if (!fullCircles) { + pathArc(ctx, element, offset, spacing, endAngle, circular); + ctx.stroke(); + } +} +class ArcElement extends Element { + static id = 'arc'; + static defaults = { + borderAlign: 'center', + borderColor: '#fff', + borderDash: [], + borderDashOffset: 0, + borderJoinStyle: undefined, + borderRadius: 0, + borderWidth: 2, + offset: 0, + spacing: 0, + angle: undefined, + circular: true + }; + static defaultRoutes = { + backgroundColor: 'backgroundColor' + }; + static descriptors = { + _scriptable: true, + _indexable: (name)=>name !== 'borderDash' + }; + circumference; + endAngle; + fullCircles; + innerRadius; + outerRadius; + pixelMargin; + startAngle; + constructor(cfg){ + super(); + this.options = undefined; + this.circumference = undefined; + this.startAngle = undefined; + this.endAngle = undefined; + this.innerRadius = undefined; + this.outerRadius = undefined; + this.pixelMargin = 0; + this.fullCircles = 0; + if (cfg) { + Object.assign(this, cfg); + } + } + inRange(chartX, chartY, useFinalPosition) { + const point = this.getProps([ + 'x', + 'y' + ], useFinalPosition); + const { angle , distance } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.D)(point, { + x: chartX, + y: chartY + }); + const { startAngle , endAngle , innerRadius , outerRadius , circumference } = this.getProps([ + 'startAngle', + 'endAngle', + 'innerRadius', + 'outerRadius', + 'circumference' + ], useFinalPosition); + const rAdjust = (this.options.spacing + this.options.borderWidth) / 2; + const _circumference = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(circumference, endAngle - startAngle); + const betweenAngles = _circumference >= _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.p)(angle, startAngle, endAngle); + const withinRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(distance, innerRadius + rAdjust, outerRadius + rAdjust); + return betweenAngles && withinRadius; + } + getCenterPoint(useFinalPosition) { + const { x , y , startAngle , endAngle , innerRadius , outerRadius } = this.getProps([ + 'x', + 'y', + 'startAngle', + 'endAngle', + 'innerRadius', + 'outerRadius' + ], useFinalPosition); + const { offset , spacing } = this.options; + const halfAngle = (startAngle + endAngle) / 2; + const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2; + return { + x: x + Math.cos(halfAngle) * halfRadius, + y: y + Math.sin(halfAngle) * halfRadius + }; + } + tooltipPosition(useFinalPosition) { + return this.getCenterPoint(useFinalPosition); + } + draw(ctx) { + const { options , circumference } = this; + const offset = (options.offset || 0) / 4; + const spacing = (options.spacing || 0) / 2; + const circular = options.circular; + this.pixelMargin = options.borderAlign === 'inner' ? 0.33 : 0; + this.fullCircles = circumference > _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T ? Math.floor(circumference / _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T) : 0; + if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) { + return; + } + ctx.save(); + const halfAngle = (this.startAngle + this.endAngle) / 2; + ctx.translate(Math.cos(halfAngle) * offset, Math.sin(halfAngle) * offset); + const fix = 1 - Math.sin(Math.min(_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P, circumference || 0)); + const radiusOffset = offset * fix; + ctx.fillStyle = options.backgroundColor; + ctx.strokeStyle = options.borderColor; + drawArc(ctx, this, radiusOffset, spacing, circular); + drawBorder(ctx, this, radiusOffset, spacing, circular); + ctx.restore(); + } +} + +function setStyle(ctx, options, style = options) { + ctx.lineCap = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderCapStyle, options.borderCapStyle); + ctx.setLineDash((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDash, options.borderDash)); + ctx.lineDashOffset = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderDashOffset, options.borderDashOffset); + ctx.lineJoin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderJoinStyle, options.borderJoinStyle); + ctx.lineWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderWidth, options.borderWidth); + ctx.strokeStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(style.borderColor, options.borderColor); +} +function lineTo(ctx, previous, target) { + ctx.lineTo(target.x, target.y); +} + function getLineMethod(options) { + if (options.stepped) { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ar; + } + if (options.tension || options.cubicInterpolationMode === 'monotone') { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.as; + } + return lineTo; +} +function pathVars(points, segment, params = {}) { + const count = points.length; + const { start: paramsStart = 0 , end: paramsEnd = count - 1 } = params; + const { start: segmentStart , end: segmentEnd } = segment; + const start = Math.max(paramsStart, segmentStart); + const end = Math.min(paramsEnd, segmentEnd); + const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd; + return { + count, + start, + loop: segment.loop, + ilen: end < start && !outside ? count + end - start : end - start + }; +} + function pathSegment(ctx, line, segment, params) { + const { points , options } = line; + const { count , start , loop , ilen } = pathVars(points, segment, params); + const lineMethod = getLineMethod(options); + let { move =true , reverse } = params || {}; + let i, point, prev; + for(i = 0; i <= ilen; ++i){ + point = points[(start + (reverse ? ilen - i : i)) % count]; + if (point.skip) { + continue; + } else if (move) { + ctx.moveTo(point.x, point.y); + move = false; + } else { + lineMethod(ctx, prev, point, reverse, options.stepped); + } + prev = point; + } + if (loop) { + point = points[(start + (reverse ? ilen : 0)) % count]; + lineMethod(ctx, prev, point, reverse, options.stepped); + } + return !!loop; +} + function fastPathSegment(ctx, line, segment, params) { + const points = line.points; + const { count , start , ilen } = pathVars(points, segment, params); + const { move =true , reverse } = params || {}; + let avgX = 0; + let countX = 0; + let i, point, prevX, minY, maxY, lastY; + const pointIndex = (index)=>(start + (reverse ? ilen - index : index)) % count; + const drawX = ()=>{ + if (minY !== maxY) { + ctx.lineTo(avgX, maxY); + ctx.lineTo(avgX, minY); + ctx.lineTo(avgX, lastY); + } + }; + if (move) { + point = points[pointIndex(0)]; + ctx.moveTo(point.x, point.y); + } + for(i = 0; i <= ilen; ++i){ + point = points[pointIndex(i)]; + if (point.skip) { + continue; + } + const x = point.x; + const y = point.y; + const truncX = x | 0; + if (truncX === prevX) { + if (y < minY) { + minY = y; + } else if (y > maxY) { + maxY = y; + } + avgX = (countX * avgX + x) / ++countX; + } else { + drawX(); + ctx.lineTo(x, y); + prevX = truncX; + countX = 0; + minY = maxY = y; + } + lastY = y; + } + drawX(); +} + function _getSegmentMethod(line) { + const opts = line.options; + const borderDash = opts.borderDash && opts.borderDash.length; + const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash; + return useFastPath ? fastPathSegment : pathSegment; +} + function _getInterpolationMethod(options) { + if (options.stepped) { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ao; + } + if (options.tension || options.cubicInterpolationMode === 'monotone') { + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ap; + } + return _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aq; +} +function strokePathWithCache(ctx, line, start, count) { + let path = line._path; + if (!path) { + path = line._path = new Path2D(); + if (line.path(path, start, count)) { + path.closePath(); + } + } + setStyle(ctx, line.options); + ctx.stroke(path); +} +function strokePathDirect(ctx, line, start, count) { + const { segments , options } = line; + const segmentMethod = _getSegmentMethod(line); + for (const segment of segments){ + setStyle(ctx, options, segment.style); + ctx.beginPath(); + if (segmentMethod(ctx, line, segment, { + start, + end: start + count - 1 + })) { + ctx.closePath(); + } + ctx.stroke(); + } +} +const usePath2D = typeof Path2D === 'function'; +function draw(ctx, line, start, count) { + if (usePath2D && !line.options.segment) { + strokePathWithCache(ctx, line, start, count); + } else { + strokePathDirect(ctx, line, start, count); + } +} +class LineElement extends Element { + static id = 'line'; + static defaults = { + borderCapStyle: 'butt', + borderDash: [], + borderDashOffset: 0, + borderJoinStyle: 'miter', + borderWidth: 3, + capBezierPoints: true, + cubicInterpolationMode: 'default', + fill: false, + spanGaps: false, + stepped: false, + tension: 0 + }; + static defaultRoutes = { + backgroundColor: 'backgroundColor', + borderColor: 'borderColor' + }; + static descriptors = { + _scriptable: true, + _indexable: (name)=>name !== 'borderDash' && name !== 'fill' + }; + constructor(cfg){ + super(); + this.animated = true; + this.options = undefined; + this._chart = undefined; + this._loop = undefined; + this._fullLoop = undefined; + this._path = undefined; + this._points = undefined; + this._segments = undefined; + this._decimated = false; + this._pointsUpdated = false; + this._datasetIndex = undefined; + if (cfg) { + Object.assign(this, cfg); + } + } + updateControlPoints(chartArea, indexAxis) { + const options = this.options; + if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) { + const loop = options.spanGaps ? this._loop : this._fullLoop; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.al)(this._points, options, chartArea, loop, indexAxis); + this._pointsUpdated = true; + } + } + set points(points) { + this._points = points; + delete this._segments; + delete this._path; + this._pointsUpdated = false; + } + get points() { + return this._points; + } + get segments() { + return this._segments || (this._segments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.am)(this, this.options.segment)); + } + first() { + const segments = this.segments; + const points = this.points; + return segments.length && points[segments[0].start]; + } + last() { + const segments = this.segments; + const points = this.points; + const count = segments.length; + return count && points[segments[count - 1].end]; + } + interpolate(point, property) { + const options = this.options; + const value = point[property]; + const points = this.points; + const segments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.an)(this, { + property, + start: value, + end: value + }); + if (!segments.length) { + return; + } + const result = []; + const _interpolate = _getInterpolationMethod(options); + let i, ilen; + for(i = 0, ilen = segments.length; i < ilen; ++i){ + const { start , end } = segments[i]; + const p1 = points[start]; + const p2 = points[end]; + if (p1 === p2) { + result.push(p1); + continue; + } + const t = Math.abs((value - p1[property]) / (p2[property] - p1[property])); + const interpolated = _interpolate(p1, p2, t, options.stepped); + interpolated[property] = point[property]; + result.push(interpolated); + } + return result.length === 1 ? result[0] : result; + } + pathSegment(ctx, segment, params) { + const segmentMethod = _getSegmentMethod(this); + return segmentMethod(ctx, this, segment, params); + } + path(ctx, start, count) { + const segments = this.segments; + const segmentMethod = _getSegmentMethod(this); + let loop = this._loop; + start = start || 0; + count = count || this.points.length - start; + for (const segment of segments){ + loop &= segmentMethod(ctx, this, segment, { + start, + end: start + count - 1 + }); + } + return !!loop; + } + draw(ctx, chartArea, start, count) { + const options = this.options || {}; + const points = this.points || []; + if (points.length && options.borderWidth) { + ctx.save(); + draw(ctx, this, start, count); + ctx.restore(); + } + if (this.animated) { + this._pointsUpdated = false; + this._path = undefined; + } + } +} + +function inRange$1(el, pos, axis, useFinalPosition) { + const options = el.options; + const { [axis]: value } = el.getProps([ + axis + ], useFinalPosition); + return Math.abs(pos - value) < options.radius + options.hitRadius; +} +class PointElement extends Element { + static id = 'point'; + parsed; + skip; + stop; + /** + * @type {any} + */ static defaults = { + borderWidth: 1, + hitRadius: 1, + hoverBorderWidth: 1, + hoverRadius: 4, + pointStyle: 'circle', + radius: 3, + rotation: 0 + }; + /** + * @type {any} + */ static defaultRoutes = { + backgroundColor: 'backgroundColor', + borderColor: 'borderColor' + }; + constructor(cfg){ + super(); + this.options = undefined; + this.parsed = undefined; + this.skip = undefined; + this.stop = undefined; + if (cfg) { + Object.assign(this, cfg); + } + } + inRange(mouseX, mouseY, useFinalPosition) { + const options = this.options; + const { x , y } = this.getProps([ + 'x', + 'y' + ], useFinalPosition); + return Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2) < Math.pow(options.hitRadius + options.radius, 2); + } + inXRange(mouseX, useFinalPosition) { + return inRange$1(this, mouseX, 'x', useFinalPosition); + } + inYRange(mouseY, useFinalPosition) { + return inRange$1(this, mouseY, 'y', useFinalPosition); + } + getCenterPoint(useFinalPosition) { + const { x , y } = this.getProps([ + 'x', + 'y' + ], useFinalPosition); + return { + x, + y + }; + } + size(options) { + options = options || this.options || {}; + let radius = options.radius || 0; + radius = Math.max(radius, radius && options.hoverRadius || 0); + const borderWidth = radius && options.borderWidth || 0; + return (radius + borderWidth) * 2; + } + draw(ctx, area) { + const options = this.options; + if (this.skip || options.radius < 0.1 || !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)(this, area, this.size(options) / 2)) { + return; + } + ctx.strokeStyle = options.borderColor; + ctx.lineWidth = options.borderWidth; + ctx.fillStyle = options.backgroundColor; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(ctx, options, this.x, this.y); + } + getRange() { + const options = this.options || {}; + // @ts-expect-error Fallbacks should never be hit in practice + return options.radius + options.hitRadius; + } +} + +function getBarBounds(bar, useFinalPosition) { + const { x , y , base , width , height } = bar.getProps([ + 'x', + 'y', + 'base', + 'width', + 'height' + ], useFinalPosition); + let left, right, top, bottom, half; + if (bar.horizontal) { + half = height / 2; + left = Math.min(x, base); + right = Math.max(x, base); + top = y - half; + bottom = y + half; + } else { + half = width / 2; + left = x - half; + right = x + half; + top = Math.min(y, base); + bottom = Math.max(y, base); + } + return { + left, + top, + right, + bottom + }; +} +function skipOrLimit(skip, value, min, max) { + return skip ? 0 : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(value, min, max); +} +function parseBorderWidth(bar, maxW, maxH) { + const value = bar.options.borderWidth; + const skip = bar.borderSkipped; + const o = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.av)(value); + return { + t: skipOrLimit(skip.top, o.top, 0, maxH), + r: skipOrLimit(skip.right, o.right, 0, maxW), + b: skipOrLimit(skip.bottom, o.bottom, 0, maxH), + l: skipOrLimit(skip.left, o.left, 0, maxW) + }; +} +function parseBorderRadius(bar, maxW, maxH) { + const { enableBorderRadius } = bar.getProps([ + 'enableBorderRadius' + ]); + const value = bar.options.borderRadius; + const o = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(value); + const maxR = Math.min(maxW, maxH); + const skip = bar.borderSkipped; + const enableBorder = enableBorderRadius || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(value); + return { + topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR), + topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR), + bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR), + bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR) + }; +} +function boundingRects(bar) { + const bounds = getBarBounds(bar); + const width = bounds.right - bounds.left; + const height = bounds.bottom - bounds.top; + const border = parseBorderWidth(bar, width / 2, height / 2); + const radius = parseBorderRadius(bar, width / 2, height / 2); + return { + outer: { + x: bounds.left, + y: bounds.top, + w: width, + h: height, + radius + }, + inner: { + x: bounds.left + border.l, + y: bounds.top + border.t, + w: width - border.l - border.r, + h: height - border.t - border.b, + radius: { + topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)), + topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)), + bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)), + bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)) + } + } + }; +} +function inRange(bar, x, y, useFinalPosition) { + const skipX = x === null; + const skipY = y === null; + const skipBoth = skipX && skipY; + const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition); + return bounds && (skipX || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(x, bounds.left, bounds.right)) && (skipY || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(y, bounds.top, bounds.bottom)); +} +function hasRadius(radius) { + return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight; +} + function addNormalRectPath(ctx, rect) { + ctx.rect(rect.x, rect.y, rect.w, rect.h); +} +function inflateRect(rect, amount, refRect = {}) { + const x = rect.x !== refRect.x ? -amount : 0; + const y = rect.y !== refRect.y ? -amount : 0; + const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x; + const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y; + return { + x: rect.x + x, + y: rect.y + y, + w: rect.w + w, + h: rect.h + h, + radius: rect.radius + }; +} +class BarElement extends Element { + static id = 'bar'; + static defaults = { + borderSkipped: 'start', + borderWidth: 0, + borderRadius: 0, + inflateAmount: 'auto', + pointStyle: undefined + }; + static defaultRoutes = { + backgroundColor: 'backgroundColor', + borderColor: 'borderColor' + }; + constructor(cfg){ + super(); + this.options = undefined; + this.horizontal = undefined; + this.base = undefined; + this.width = undefined; + this.height = undefined; + this.inflateAmount = undefined; + if (cfg) { + Object.assign(this, cfg); + } + } + draw(ctx) { + const { inflateAmount , options: { borderColor , backgroundColor } } = this; + const { inner , outer } = boundingRects(this); + const addRectPath = hasRadius(outer.radius) ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au : addNormalRectPath; + ctx.save(); + if (outer.w !== inner.w || outer.h !== inner.h) { + ctx.beginPath(); + addRectPath(ctx, inflateRect(outer, inflateAmount, inner)); + ctx.clip(); + addRectPath(ctx, inflateRect(inner, -inflateAmount, outer)); + ctx.fillStyle = borderColor; + ctx.fill('evenodd'); + } + ctx.beginPath(); + addRectPath(ctx, inflateRect(inner, inflateAmount)); + ctx.fillStyle = backgroundColor; + ctx.fill(); + ctx.restore(); + } + inRange(mouseX, mouseY, useFinalPosition) { + return inRange(this, mouseX, mouseY, useFinalPosition); + } + inXRange(mouseX, useFinalPosition) { + return inRange(this, mouseX, null, useFinalPosition); + } + inYRange(mouseY, useFinalPosition) { + return inRange(this, null, mouseY, useFinalPosition); + } + getCenterPoint(useFinalPosition) { + const { x , y , base , horizontal } = this.getProps([ + 'x', + 'y', + 'base', + 'horizontal' + ], useFinalPosition); + return { + x: horizontal ? (x + base) / 2 : x, + y: horizontal ? y : (y + base) / 2 + }; + } + getRange(axis) { + return axis === 'x' ? this.width / 2 : this.height / 2; + } +} + +var elements = /*#__PURE__*/Object.freeze({ +__proto__: null, +ArcElement: ArcElement, +BarElement: BarElement, +LineElement: LineElement, +PointElement: PointElement +}); + +const BORDER_COLORS = [ + 'rgb(54, 162, 235)', + 'rgb(255, 99, 132)', + 'rgb(255, 159, 64)', + 'rgb(255, 205, 86)', + 'rgb(75, 192, 192)', + 'rgb(153, 102, 255)', + 'rgb(201, 203, 207)' // grey +]; +// Border colors with 50% transparency +const BACKGROUND_COLORS = /* #__PURE__ */ BORDER_COLORS.map((color)=>color.replace('rgb(', 'rgba(').replace(')', ', 0.5)')); +function getBorderColor(i) { + return BORDER_COLORS[i % BORDER_COLORS.length]; +} +function getBackgroundColor(i) { + return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length]; +} +function colorizeDefaultDataset(dataset, i) { + dataset.borderColor = getBorderColor(i); + dataset.backgroundColor = getBackgroundColor(i); + return ++i; +} +function colorizeDoughnutDataset(dataset, i) { + dataset.backgroundColor = dataset.data.map(()=>getBorderColor(i++)); + return i; +} +function colorizePolarAreaDataset(dataset, i) { + dataset.backgroundColor = dataset.data.map(()=>getBackgroundColor(i++)); + return i; +} +function getColorizer(chart) { + let i = 0; + return (dataset, datasetIndex)=>{ + const controller = chart.getDatasetMeta(datasetIndex).controller; + if (controller instanceof DoughnutController) { + i = colorizeDoughnutDataset(dataset, i); + } else if (controller instanceof PolarAreaController) { + i = colorizePolarAreaDataset(dataset, i); + } else if (controller) { + i = colorizeDefaultDataset(dataset, i); + } + }; +} +function containsColorsDefinitions(descriptors) { + let k; + for(k in descriptors){ + if (descriptors[k].borderColor || descriptors[k].backgroundColor) { + return true; + } + } + return false; +} +function containsColorsDefinition(descriptor) { + return descriptor && (descriptor.borderColor || descriptor.backgroundColor); +} +var plugin_colors = { + id: 'colors', + defaults: { + enabled: true, + forceOverride: false + }, + beforeLayout (chart, _args, options) { + if (!options.enabled) { + return; + } + const { data: { datasets } , options: chartOptions } = chart.config; + const { elements } = chartOptions; + if (!options.forceOverride && (containsColorsDefinitions(datasets) || containsColorsDefinition(chartOptions) || elements && containsColorsDefinitions(elements))) { + return; + } + const colorizer = getColorizer(chart); + datasets.forEach(colorizer); + } +}; + +function lttbDecimation(data, start, count, availableWidth, options) { + const samples = options.samples || availableWidth; + if (samples >= count) { + return data.slice(start, start + count); + } + const decimated = []; + const bucketWidth = (count - 2) / (samples - 2); + let sampledIndex = 0; + const endIndex = start + count - 1; + let a = start; + let i, maxAreaPoint, maxArea, area, nextA; + decimated[sampledIndex++] = data[a]; + for(i = 0; i < samples - 2; i++){ + let avgX = 0; + let avgY = 0; + let j; + const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start; + const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start; + const avgRangeLength = avgRangeEnd - avgRangeStart; + for(j = avgRangeStart; j < avgRangeEnd; j++){ + avgX += data[j].x; + avgY += data[j].y; + } + avgX /= avgRangeLength; + avgY /= avgRangeLength; + const rangeOffs = Math.floor(i * bucketWidth) + 1 + start; + const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start; + const { x: pointAx , y: pointAy } = data[a]; + maxArea = area = -1; + for(j = rangeOffs; j < rangeTo; j++){ + area = 0.5 * Math.abs((pointAx - avgX) * (data[j].y - pointAy) - (pointAx - data[j].x) * (avgY - pointAy)); + if (area > maxArea) { + maxArea = area; + maxAreaPoint = data[j]; + nextA = j; + } + } + decimated[sampledIndex++] = maxAreaPoint; + a = nextA; + } + decimated[sampledIndex++] = data[endIndex]; + return decimated; +} +function minMaxDecimation(data, start, count, availableWidth) { + let avgX = 0; + let countX = 0; + let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY; + const decimated = []; + const endIndex = start + count - 1; + const xMin = data[start].x; + const xMax = data[endIndex].x; + const dx = xMax - xMin; + for(i = start; i < start + count; ++i){ + point = data[i]; + x = (point.x - xMin) / dx * availableWidth; + y = point.y; + const truncX = x | 0; + if (truncX === prevX) { + if (y < minY) { + minY = y; + minIndex = i; + } else if (y > maxY) { + maxY = y; + maxIndex = i; + } + avgX = (countX * avgX + point.x) / ++countX; + } else { + const lastIndex = i - 1; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(minIndex) && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(maxIndex)) { + const intermediateIndex1 = Math.min(minIndex, maxIndex); + const intermediateIndex2 = Math.max(minIndex, maxIndex); + if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) { + decimated.push({ + ...data[intermediateIndex1], + x: avgX + }); + } + if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) { + decimated.push({ + ...data[intermediateIndex2], + x: avgX + }); + } + } + if (i > 0 && lastIndex !== startIndex) { + decimated.push(data[lastIndex]); + } + decimated.push(point); + prevX = truncX; + countX = 0; + minY = maxY = y; + minIndex = maxIndex = startIndex = i; + } + } + return decimated; +} +function cleanDecimatedDataset(dataset) { + if (dataset._decimated) { + const data = dataset._data; + delete dataset._decimated; + delete dataset._data; + Object.defineProperty(dataset, 'data', { + configurable: true, + enumerable: true, + writable: true, + value: data + }); + } +} +function cleanDecimatedData(chart) { + chart.data.datasets.forEach((dataset)=>{ + cleanDecimatedDataset(dataset); + }); +} +function getStartAndCountOfVisiblePointsSimplified(meta, points) { + const pointCount = points.length; + let start = 0; + let count; + const { iScale } = meta; + const { min , max , minDefined , maxDefined } = iScale.getUserBounds(); + if (minDefined) { + start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, min).lo, 0, pointCount - 1); + } + if (maxDefined) { + count = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(points, iScale.axis, max).hi + 1, start, pointCount) - start; + } else { + count = pointCount - start; + } + return { + start, + count + }; +} +var plugin_decimation = { + id: 'decimation', + defaults: { + algorithm: 'min-max', + enabled: false + }, + beforeElementsUpdate: (chart, args, options)=>{ + if (!options.enabled) { + cleanDecimatedData(chart); + return; + } + const availableWidth = chart.width; + chart.data.datasets.forEach((dataset, datasetIndex)=>{ + const { _data , indexAxis } = dataset; + const meta = chart.getDatasetMeta(datasetIndex); + const data = _data || dataset.data; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a)([ + indexAxis, + chart.options.indexAxis + ]) === 'y') { + return; + } + if (!meta.controller.supportsDecimation) { + return; + } + const xAxis = chart.scales[meta.xAxisID]; + if (xAxis.type !== 'linear' && xAxis.type !== 'time') { + return; + } + if (chart.options.parsing) { + return; + } + let { start , count } = getStartAndCountOfVisiblePointsSimplified(meta, data); + const threshold = options.threshold || 4 * availableWidth; + if (count <= threshold) { + cleanDecimatedDataset(dataset); + return; + } + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(_data)) { + dataset._data = data; + delete dataset.data; + Object.defineProperty(dataset, 'data', { + configurable: true, + enumerable: true, + get: function() { + return this._decimated; + }, + set: function(d) { + this._data = d; + } + }); + } + let decimated; + switch(options.algorithm){ + case 'lttb': + decimated = lttbDecimation(data, start, count, availableWidth, options); + break; + case 'min-max': + decimated = minMaxDecimation(data, start, count, availableWidth); + break; + default: + throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`); + } + dataset._decimated = decimated; + }); + }, + destroy (chart) { + cleanDecimatedData(chart); + } +}; + +function _segments(line, target, property) { + const segments = line.segments; + const points = line.points; + const tpoints = target.points; + const parts = []; + for (const segment of segments){ + let { start , end } = segment; + end = _findSegmentEnd(start, end, points); + const bounds = _getBounds(property, points[start], points[end], segment.loop); + if (!target.segments) { + parts.push({ + source: segment, + target: bounds, + start: points[start], + end: points[end] + }); + continue; + } + const targetSegments = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.an)(target, bounds); + for (const tgt of targetSegments){ + const subBounds = _getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop); + const fillSources = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ax)(segment, points, subBounds); + for (const fillSource of fillSources){ + parts.push({ + source: fillSource, + target: tgt, + start: { + [property]: _getEdge(bounds, subBounds, 'start', Math.max) + }, + end: { + [property]: _getEdge(bounds, subBounds, 'end', Math.min) + } + }); + } + } + } + return parts; +} +function _getBounds(property, first, last, loop) { + if (loop) { + return; + } + let start = first[property]; + let end = last[property]; + if (property === 'angle') { + start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay)(start); + end = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay)(end); + } + return { + property, + start, + end + }; +} +function _pointsFromSegments(boundary, line) { + const { x =null , y =null } = boundary || {}; + const linePoints = line.points; + const points = []; + line.segments.forEach(({ start , end })=>{ + end = _findSegmentEnd(start, end, linePoints); + const first = linePoints[start]; + const last = linePoints[end]; + if (y !== null) { + points.push({ + x: first.x, + y + }); + points.push({ + x: last.x, + y + }); + } else if (x !== null) { + points.push({ + x, + y: first.y + }); + points.push({ + x, + y: last.y + }); + } + }); + return points; +} +function _findSegmentEnd(start, end, points) { + for(; end > start; end--){ + const point = points[end]; + if (!isNaN(point.x) && !isNaN(point.y)) { + break; + } + } + return end; +} +function _getEdge(a, b, prop, fn) { + if (a && b) { + return fn(a[prop], b[prop]); + } + return a ? a[prop] : b ? b[prop] : 0; +} + +function _createBoundaryLine(boundary, line) { + let points = []; + let _loop = false; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(boundary)) { + _loop = true; + points = boundary; + } else { + points = _pointsFromSegments(boundary, line); + } + return points.length ? new LineElement({ + points, + options: { + tension: 0 + }, + _loop, + _fullLoop: _loop + }) : null; +} +function _shouldApplyFill(source) { + return source && source.fill !== false; +} + +function _resolveTarget(sources, index, propagate) { + const source = sources[index]; + let fill = source.fill; + const visited = [ + index + ]; + let target; + if (!propagate) { + return fill; + } + while(fill !== false && visited.indexOf(fill) === -1){ + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) { + return fill; + } + target = sources[fill]; + if (!target) { + return false; + } + if (target.visible) { + return fill; + } + visited.push(fill); + fill = target.fill; + } + return false; +} + function _decodeFill(line, index, count) { + const fill = parseFillOption(line); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { + return isNaN(fill.value) ? false : fill; + } + let target = parseFloat(fill); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(target) && Math.floor(target) === target) { + return decodeTargetIndex(fill[0], index, target, count); + } + return [ + 'origin', + 'start', + 'end', + 'stack', + 'shape' + ].indexOf(fill) >= 0 && fill; +} +function decodeTargetIndex(firstCh, index, target, count) { + if (firstCh === '-' || firstCh === '+') { + target = index + target; + } + if (target === index || target < 0 || target >= count) { + return false; + } + return target; +} + function _getTargetPixel(fill, scale) { + let pixel = null; + if (fill === 'start') { + pixel = scale.bottom; + } else if (fill === 'end') { + pixel = scale.top; + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { + pixel = scale.getPixelForValue(fill.value); + } else if (scale.getBasePixel) { + pixel = scale.getBasePixel(); + } + return pixel; +} + function _getTargetValue(fill, scale, startValue) { + let value; + if (fill === 'start') { + value = startValue; + } else if (fill === 'end') { + value = scale.options.reverse ? scale.min : scale.max; + } else if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(fill)) { + value = fill.value; + } else { + value = scale.getBaseValue(); + } + return value; +} + function parseFillOption(line) { + const options = line.options; + const fillOption = options.fill; + let fill = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(fillOption && fillOption.target, fillOption); + if (fill === undefined) { + fill = !!options.backgroundColor; + } + if (fill === false || fill === null) { + return false; + } + if (fill === true) { + return 'origin'; + } + return fill; +} + +function _buildStackLine(source) { + const { scale , index , line } = source; + const points = []; + const segments = line.segments; + const sourcePoints = line.points; + const linesBelow = getLinesBelow(scale, index); + linesBelow.push(_createBoundaryLine({ + x: null, + y: scale.bottom + }, line)); + for(let i = 0; i < segments.length; i++){ + const segment = segments[i]; + for(let j = segment.start; j <= segment.end; j++){ + addPointsBelow(points, sourcePoints[j], linesBelow); + } + } + return new LineElement({ + points, + options: {} + }); +} + function getLinesBelow(scale, index) { + const below = []; + const metas = scale.getMatchingVisibleMetas('line'); + for(let i = 0; i < metas.length; i++){ + const meta = metas[i]; + if (meta.index === index) { + break; + } + if (!meta.hidden) { + below.unshift(meta.dataset); + } + } + return below; +} + function addPointsBelow(points, sourcePoint, linesBelow) { + const postponed = []; + for(let j = 0; j < linesBelow.length; j++){ + const line = linesBelow[j]; + const { first , last , point } = findPoint(line, sourcePoint, 'x'); + if (!point || first && last) { + continue; + } + if (first) { + postponed.unshift(point); + } else { + points.push(point); + if (!last) { + break; + } + } + } + points.push(...postponed); +} + function findPoint(line, sourcePoint, property) { + const point = line.interpolate(sourcePoint, property); + if (!point) { + return {}; + } + const pointValue = point[property]; + const segments = line.segments; + const linePoints = line.points; + let first = false; + let last = false; + for(let i = 0; i < segments.length; i++){ + const segment = segments[i]; + const firstValue = linePoints[segment.start][property]; + const lastValue = linePoints[segment.end][property]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(pointValue, firstValue, lastValue)) { + first = pointValue === firstValue; + last = pointValue === lastValue; + break; + } + } + return { + first, + last, + point + }; +} + +class simpleArc { + constructor(opts){ + this.x = opts.x; + this.y = opts.y; + this.radius = opts.radius; + } + pathSegment(ctx, bounds, opts) { + const { x , y , radius } = this; + bounds = bounds || { + start: 0, + end: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T + }; + ctx.arc(x, y, radius, bounds.end, bounds.start, true); + return !opts.bounds; + } + interpolate(point) { + const { x , y , radius } = this; + const angle = point.angle; + return { + x: x + Math.cos(angle) * radius, + y: y + Math.sin(angle) * radius, + angle + }; + } +} + +function _getTarget(source) { + const { chart , fill , line } = source; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(fill)) { + return getLineByIndex(chart, fill); + } + if (fill === 'stack') { + return _buildStackLine(source); + } + if (fill === 'shape') { + return true; + } + const boundary = computeBoundary(source); + if (boundary instanceof simpleArc) { + return boundary; + } + return _createBoundaryLine(boundary, line); +} + function getLineByIndex(chart, index) { + const meta = chart.getDatasetMeta(index); + const visible = meta && chart.isDatasetVisible(index); + return visible ? meta.dataset : null; +} +function computeBoundary(source) { + const scale = source.scale || {}; + if (scale.getPointPositionForValue) { + return computeCircularBoundary(source); + } + return computeLinearBoundary(source); +} +function computeLinearBoundary(source) { + const { scale ={} , fill } = source; + const pixel = _getTargetPixel(fill, scale); + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(pixel)) { + const horizontal = scale.isHorizontal(); + return { + x: horizontal ? pixel : null, + y: horizontal ? null : pixel + }; + } + return null; +} +function computeCircularBoundary(source) { + const { scale , fill } = source; + const options = scale.options; + const length = scale.getLabels().length; + const start = options.reverse ? scale.max : scale.min; + const value = _getTargetValue(fill, scale, start); + const target = []; + if (options.grid.circular) { + const center = scale.getPointPositionForValue(0, start); + return new simpleArc({ + x: center.x, + y: center.y, + radius: scale.getDistanceFromCenterForValue(value) + }); + } + for(let i = 0; i < length; ++i){ + target.push(scale.getPointPositionForValue(i, value)); + } + return target; +} + +function _drawfill(ctx, source, area) { + const target = _getTarget(source); + const { line , scale , axis } = source; + const lineOpts = line.options; + const fillOption = lineOpts.fill; + const color = lineOpts.backgroundColor; + const { above =color , below =color } = fillOption || {}; + if (target && line.points.length) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, area); + doFill(ctx, { + line, + target, + above, + below, + area, + scale, + axis + }); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx); + } +} +function doFill(ctx, cfg) { + const { line , target , above , below , area , scale } = cfg; + const property = line._loop ? 'angle' : cfg.axis; + ctx.save(); + if (property === 'x' && below !== above) { + clipVertical(ctx, target, area.top); + fill(ctx, { + line, + target, + color: above, + scale, + property + }); + ctx.restore(); + ctx.save(); + clipVertical(ctx, target, area.bottom); + } + fill(ctx, { + line, + target, + color: below, + scale, + property + }); + ctx.restore(); +} +function clipVertical(ctx, target, clipY) { + const { segments , points } = target; + let first = true; + let lineLoop = false; + ctx.beginPath(); + for (const segment of segments){ + const { start , end } = segment; + const firstPoint = points[start]; + const lastPoint = points[_findSegmentEnd(start, end, points)]; + if (first) { + ctx.moveTo(firstPoint.x, firstPoint.y); + first = false; + } else { + ctx.lineTo(firstPoint.x, clipY); + ctx.lineTo(firstPoint.x, firstPoint.y); + } + lineLoop = !!target.pathSegment(ctx, segment, { + move: lineLoop + }); + if (lineLoop) { + ctx.closePath(); + } else { + ctx.lineTo(lastPoint.x, clipY); + } + } + ctx.lineTo(target.first().x, clipY); + ctx.closePath(); + ctx.clip(); +} +function fill(ctx, cfg) { + const { line , target , property , color , scale } = cfg; + const segments = _segments(line, target, property); + for (const { source: src , target: tgt , start , end } of segments){ + const { style: { backgroundColor =color } = {} } = src; + const notShape = target !== true; + ctx.save(); + ctx.fillStyle = backgroundColor; + clipBounds(ctx, scale, notShape && _getBounds(property, start, end)); + ctx.beginPath(); + const lineLoop = !!line.pathSegment(ctx, src); + let loop; + if (notShape) { + if (lineLoop) { + ctx.closePath(); + } else { + interpolatedLineTo(ctx, target, end, property); + } + const targetLoop = !!target.pathSegment(ctx, tgt, { + move: lineLoop, + reverse: true + }); + loop = lineLoop && targetLoop; + if (!loop) { + interpolatedLineTo(ctx, target, start, property); + } + } + ctx.closePath(); + ctx.fill(loop ? 'evenodd' : 'nonzero'); + ctx.restore(); + } +} +function clipBounds(ctx, scale, bounds) { + const { top , bottom } = scale.chart.chartArea; + const { property , start , end } = bounds || {}; + if (property === 'x') { + ctx.beginPath(); + ctx.rect(start, top, end - start, bottom - top); + ctx.clip(); + } +} +function interpolatedLineTo(ctx, target, point, property) { + const interpolatedPoint = target.interpolate(point, property); + if (interpolatedPoint) { + ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y); + } +} + +var index = { + id: 'filler', + afterDatasetsUpdate (chart, _args, options) { + const count = (chart.data.datasets || []).length; + const sources = []; + let meta, i, line, source; + for(i = 0; i < count; ++i){ + meta = chart.getDatasetMeta(i); + line = meta.dataset; + source = null; + if (line && line.options && line instanceof LineElement) { + source = { + visible: chart.isDatasetVisible(i), + index: i, + fill: _decodeFill(line, i, count), + chart, + axis: meta.controller.options.indexAxis, + scale: meta.vScale, + line + }; + } + meta.$filler = source; + sources.push(source); + } + for(i = 0; i < count; ++i){ + source = sources[i]; + if (!source || source.fill === false) { + continue; + } + source.fill = _resolveTarget(sources, i, options.propagate); + } + }, + beforeDraw (chart, _args, options) { + const draw = options.drawTime === 'beforeDraw'; + const metasets = chart.getSortedVisibleDatasetMetas(); + const area = chart.chartArea; + for(let i = metasets.length - 1; i >= 0; --i){ + const source = metasets[i].$filler; + if (!source) { + continue; + } + source.line.updateControlPoints(area, source.axis); + if (draw && source.fill) { + _drawfill(chart.ctx, source, area); + } + } + }, + beforeDatasetsDraw (chart, _args, options) { + if (options.drawTime !== 'beforeDatasetsDraw') { + return; + } + const metasets = chart.getSortedVisibleDatasetMetas(); + for(let i = metasets.length - 1; i >= 0; --i){ + const source = metasets[i].$filler; + if (_shouldApplyFill(source)) { + _drawfill(chart.ctx, source, chart.chartArea); + } + } + }, + beforeDatasetDraw (chart, args, options) { + const source = args.meta.$filler; + if (!_shouldApplyFill(source) || options.drawTime !== 'beforeDatasetDraw') { + return; + } + _drawfill(chart.ctx, source, chart.chartArea); + }, + defaults: { + propagate: true, + drawTime: 'beforeDatasetDraw' + } +}; + +const getBoxSize = (labelOpts, fontSize)=>{ + let { boxHeight =fontSize , boxWidth =fontSize } = labelOpts; + if (labelOpts.usePointStyle) { + boxHeight = Math.min(boxHeight, fontSize); + boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize); + } + return { + boxWidth, + boxHeight, + itemHeight: Math.max(fontSize, boxHeight) + }; +}; +const itemsEqual = (a, b)=>a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index; +class Legend extends Element { + constructor(config){ + super(); + this._added = false; + this.legendHitBoxes = []; + this._hoveredItem = null; + this.doughnutMode = false; + this.chart = config.chart; + this.options = config.options; + this.ctx = config.ctx; + this.legendItems = undefined; + this.columnSizes = undefined; + this.lineWidths = undefined; + this.maxHeight = undefined; + this.maxWidth = undefined; + this.top = undefined; + this.bottom = undefined; + this.left = undefined; + this.right = undefined; + this.height = undefined; + this.width = undefined; + this._margins = undefined; + this.position = undefined; + this.weight = undefined; + this.fullSize = undefined; + } + update(maxWidth, maxHeight, margins) { + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this._margins = margins; + this.setDimensions(); + this.buildLabels(); + this.fit(); + } + setDimensions() { + if (this.isHorizontal()) { + this.width = this.maxWidth; + this.left = this._margins.left; + this.right = this.width; + } else { + this.height = this.maxHeight; + this.top = this._margins.top; + this.bottom = this.height; + } + } + buildLabels() { + const labelOpts = this.options.labels || {}; + let legendItems = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(labelOpts.generateLabels, [ + this.chart + ], this) || []; + if (labelOpts.filter) { + legendItems = legendItems.filter((item)=>labelOpts.filter(item, this.chart.data)); + } + if (labelOpts.sort) { + legendItems = legendItems.sort((a, b)=>labelOpts.sort(a, b, this.chart.data)); + } + if (this.options.reverse) { + legendItems.reverse(); + } + this.legendItems = legendItems; + } + fit() { + const { options , ctx } = this; + if (!options.display) { + this.width = this.height = 0; + return; + } + const labelOpts = options.labels; + const labelFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font); + const fontSize = labelFont.size; + const titleHeight = this._computeTitleHeight(); + const { boxWidth , itemHeight } = getBoxSize(labelOpts, fontSize); + let width, height; + ctx.font = labelFont.string; + if (this.isHorizontal()) { + width = this.maxWidth; + height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10; + } else { + height = this.maxHeight; + width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10; + } + this.width = Math.min(width, options.maxWidth || this.maxWidth); + this.height = Math.min(height, options.maxHeight || this.maxHeight); + } + _fitRows(titleHeight, fontSize, boxWidth, itemHeight) { + const { ctx , maxWidth , options: { labels: { padding } } } = this; + const hitboxes = this.legendHitBoxes = []; + const lineWidths = this.lineWidths = [ + 0 + ]; + const lineHeight = itemHeight + padding; + let totalHeight = titleHeight; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + let row = -1; + let top = -lineHeight; + this.legendItems.forEach((legendItem, i)=>{ + const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width; + if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) { + totalHeight += lineHeight; + lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0; + top += lineHeight; + row++; + } + hitboxes[i] = { + left: 0, + top, + row, + width: itemWidth, + height: itemHeight + }; + lineWidths[lineWidths.length - 1] += itemWidth + padding; + }); + return totalHeight; + } + _fitCols(titleHeight, labelFont, boxWidth, _itemHeight) { + const { ctx , maxHeight , options: { labels: { padding } } } = this; + const hitboxes = this.legendHitBoxes = []; + const columnSizes = this.columnSizes = []; + const heightLimit = maxHeight - titleHeight; + let totalWidth = padding; + let currentColWidth = 0; + let currentColHeight = 0; + let left = 0; + let col = 0; + this.legendItems.forEach((legendItem, i)=>{ + const { itemWidth , itemHeight } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight); + if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) { + totalWidth += currentColWidth + padding; + columnSizes.push({ + width: currentColWidth, + height: currentColHeight + }); + left += currentColWidth + padding; + col++; + currentColWidth = currentColHeight = 0; + } + hitboxes[i] = { + left, + top: currentColHeight, + col, + width: itemWidth, + height: itemHeight + }; + currentColWidth = Math.max(currentColWidth, itemWidth); + currentColHeight += itemHeight + padding; + }); + totalWidth += currentColWidth; + columnSizes.push({ + width: currentColWidth, + height: currentColHeight + }); + return totalWidth; + } + adjustHitBoxes() { + if (!this.options.display) { + return; + } + const titleHeight = this._computeTitleHeight(); + const { legendHitBoxes: hitboxes , options: { align , labels: { padding } , rtl } } = this; + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(rtl, this.left, this.width); + if (this.isHorizontal()) { + let row = 0; + let left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]); + for (const hitbox of hitboxes){ + if (row !== hitbox.row) { + row = hitbox.row; + left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - this.lineWidths[row]); + } + hitbox.top += this.top + titleHeight + padding; + hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width); + left += hitbox.width + padding; + } + } else { + let col = 0; + let top = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height); + for (const hitbox of hitboxes){ + if (hitbox.col !== col) { + col = hitbox.col; + top = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height); + } + hitbox.top = top; + hitbox.left += this.left + padding; + hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width); + top += hitbox.height + padding; + } + } + } + isHorizontal() { + return this.options.position === 'top' || this.options.position === 'bottom'; + } + draw() { + if (this.options.display) { + const ctx = this.ctx; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Y)(ctx, this); + this._draw(); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.$)(ctx); + } + } + _draw() { + const { options: opts , columnSizes , lineWidths , ctx } = this; + const { align , labels: labelOpts } = opts; + const defaultColor = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.color; + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(opts.rtl, this.left, this.width); + const labelFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(labelOpts.font); + const { padding } = labelOpts; + const fontSize = labelFont.size; + const halfFontSize = fontSize / 2; + let cursor; + this.drawTitle(); + ctx.textAlign = rtlHelper.textAlign('left'); + ctx.textBaseline = 'middle'; + ctx.lineWidth = 0.5; + ctx.font = labelFont.string; + const { boxWidth , boxHeight , itemHeight } = getBoxSize(labelOpts, fontSize); + const drawLegendBox = function(x, y, legendItem) { + if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) { + return; + } + ctx.save(); + const lineWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineWidth, 1); + ctx.fillStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.fillStyle, defaultColor); + ctx.lineCap = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineCap, 'butt'); + ctx.lineDashOffset = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDashOffset, 0); + ctx.lineJoin = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineJoin, 'miter'); + ctx.lineWidth = lineWidth; + ctx.strokeStyle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.strokeStyle, defaultColor); + ctx.setLineDash((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(legendItem.lineDash, [])); + if (labelOpts.usePointStyle) { + const drawOptions = { + radius: boxHeight * Math.SQRT2 / 2, + pointStyle: legendItem.pointStyle, + rotation: legendItem.rotation, + borderWidth: lineWidth + }; + const centerX = rtlHelper.xPlus(x, boxWidth / 2); + const centerY = y + halfFontSize; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aD)(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth); + } else { + const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0); + const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth); + const borderRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(legendItem.borderRadius); + ctx.beginPath(); + if (Object.values(borderRadius).some((v)=>v !== 0)) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(ctx, { + x: xBoxLeft, + y: yBoxTop, + w: boxWidth, + h: boxHeight, + radius: borderRadius + }); + } else { + ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight); + } + ctx.fill(); + if (lineWidth !== 0) { + ctx.stroke(); + } + } + ctx.restore(); + }; + const fillText = function(x, y, legendItem) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, legendItem.text, x, y + itemHeight / 2, labelFont, { + strikethrough: legendItem.hidden, + textAlign: rtlHelper.textAlign(legendItem.textAlign) + }); + }; + const isHorizontal = this.isHorizontal(); + const titleHeight = this._computeTitleHeight(); + if (isHorizontal) { + cursor = { + x: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[0]), + y: this.top + padding + titleHeight, + line: 0 + }; + } else { + cursor = { + x: this.left + padding, + y: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height), + line: 0 + }; + } + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aA)(this.ctx, opts.textDirection); + const lineHeight = itemHeight + padding; + this.legendItems.forEach((legendItem, i)=>{ + ctx.strokeStyle = legendItem.fontColor; + ctx.fillStyle = legendItem.fontColor; + const textWidth = ctx.measureText(legendItem.text).width; + const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign)); + const width = boxWidth + halfFontSize + textWidth; + let x = cursor.x; + let y = cursor.y; + rtlHelper.setWidth(this.width); + if (isHorizontal) { + if (i > 0 && x + width + padding > this.right) { + y = cursor.y += lineHeight; + cursor.line++; + x = cursor.x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.left + padding, this.right - lineWidths[cursor.line]); + } + } else if (i > 0 && y + lineHeight > this.bottom) { + x = cursor.x = x + columnSizes[cursor.line].width + padding; + cursor.line++; + y = cursor.y = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height); + } + const realX = rtlHelper.x(x); + drawLegendBox(realX, y, legendItem); + x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aB)(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl); + fillText(rtlHelper.x(x), y, legendItem); + if (isHorizontal) { + cursor.x += width + padding; + } else if (typeof legendItem.text !== 'string') { + const fontLineHeight = labelFont.lineHeight; + cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight); + } else { + cursor.y += lineHeight; + } + }); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aC)(this.ctx, opts.textDirection); + } + drawTitle() { + const opts = this.options; + const titleOpts = opts.title; + const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font); + const titlePadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding); + if (!titleOpts.display) { + return; + } + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(opts.rtl, this.left, this.width); + const ctx = this.ctx; + const position = titleOpts.position; + const halfFontSize = titleFont.size / 2; + const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize; + let y; + let left = this.left; + let maxWidth = this.width; + if (this.isHorizontal()) { + maxWidth = Math.max(...this.lineWidths); + y = this.top + topPaddingPlusHalfFontSize; + left = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, left, this.right - maxWidth); + } else { + const maxHeight = this.columnSizes.reduce((acc, size)=>Math.max(acc, size.height), 0); + y = topPaddingPlusHalfFontSize + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight()); + } + const x = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(position, left, left + maxWidth); + ctx.textAlign = rtlHelper.textAlign((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a1)(position)); + ctx.textBaseline = 'middle'; + ctx.strokeStyle = titleOpts.color; + ctx.fillStyle = titleOpts.color; + ctx.font = titleFont.string; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, titleOpts.text, x, y, titleFont); + } + _computeTitleHeight() { + const titleOpts = this.options.title; + const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(titleOpts.font); + const titlePadding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(titleOpts.padding); + return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0; + } + _getLegendItemAt(x, y) { + let i, hitBox, lh; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(x, this.left, this.right) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(y, this.top, this.bottom)) { + lh = this.legendHitBoxes; + for(i = 0; i < lh.length; ++i){ + hitBox = lh[i]; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(x, hitBox.left, hitBox.left + hitBox.width) && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aj)(y, hitBox.top, hitBox.top + hitBox.height)) { + return this.legendItems[i]; + } + } + } + return null; + } + handleEvent(e) { + const opts = this.options; + if (!isListened(e.type, opts)) { + return; + } + const hoveredItem = this._getLegendItemAt(e.x, e.y); + if (e.type === 'mousemove' || e.type === 'mouseout') { + const previous = this._hoveredItem; + const sameItem = itemsEqual(previous, hoveredItem); + if (previous && !sameItem) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onLeave, [ + e, + previous, + this + ], this); + } + this._hoveredItem = hoveredItem; + if (hoveredItem && !sameItem) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onHover, [ + e, + hoveredItem, + this + ], this); + } + } else if (hoveredItem) { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(opts.onClick, [ + e, + hoveredItem, + this + ], this); + } + } +} +function calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) { + const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx); + const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight); + return { + itemWidth, + itemHeight + }; +} +function calculateItemWidth(legendItem, boxWidth, labelFont, ctx) { + let legendItemText = legendItem.text; + if (legendItemText && typeof legendItemText !== 'string') { + legendItemText = legendItemText.reduce((a, b)=>a.length > b.length ? a : b); + } + return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width; +} +function calculateItemHeight(_itemHeight, legendItem, fontLineHeight) { + let itemHeight = _itemHeight; + if (typeof legendItem.text !== 'string') { + itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight); + } + return itemHeight; +} +function calculateLegendItemHeight(legendItem, fontLineHeight) { + const labelHeight = legendItem.text ? legendItem.text.length + 0.5 : 0; + return fontLineHeight * labelHeight; +} +function isListened(type, opts) { + if ((type === 'mousemove' || type === 'mouseout') && (opts.onHover || opts.onLeave)) { + return true; + } + if (opts.onClick && (type === 'click' || type === 'mouseup')) { + return true; + } + return false; +} +var plugin_legend = { + id: 'legend', + _element: Legend, + start (chart, _args, options) { + const legend = chart.legend = new Legend({ + ctx: chart.ctx, + options, + chart + }); + layouts.configure(chart, legend, options); + layouts.addBox(chart, legend); + }, + stop (chart) { + layouts.removeBox(chart, chart.legend); + delete chart.legend; + }, + beforeUpdate (chart, _args, options) { + const legend = chart.legend; + layouts.configure(chart, legend, options); + legend.options = options; + }, + afterUpdate (chart) { + const legend = chart.legend; + legend.buildLabels(); + legend.adjustHitBoxes(); + }, + afterEvent (chart, args) { + if (!args.replay) { + chart.legend.handleEvent(args.event); + } + }, + defaults: { + display: true, + position: 'top', + align: 'center', + fullSize: true, + reverse: false, + weight: 1000, + onClick (e, legendItem, legend) { + const index = legendItem.datasetIndex; + const ci = legend.chart; + if (ci.isDatasetVisible(index)) { + ci.hide(index); + legendItem.hidden = true; + } else { + ci.show(index); + legendItem.hidden = false; + } + }, + onHover: null, + onLeave: null, + labels: { + color: (ctx)=>ctx.chart.options.color, + boxWidth: 40, + padding: 10, + generateLabels (chart) { + const datasets = chart.data.datasets; + const { labels: { usePointStyle , pointStyle , textAlign , color , useBorderRadius , borderRadius } } = chart.legend.options; + return chart._getSortedDatasetMetas().map((meta)=>{ + const style = meta.controller.getStyle(usePointStyle ? 0 : undefined); + const borderWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(style.borderWidth); + return { + text: datasets[meta.index].label, + fillStyle: style.backgroundColor, + fontColor: color, + hidden: !meta.visible, + lineCap: style.borderCapStyle, + lineDash: style.borderDash, + lineDashOffset: style.borderDashOffset, + lineJoin: style.borderJoinStyle, + lineWidth: (borderWidth.width + borderWidth.height) / 4, + strokeStyle: style.borderColor, + pointStyle: pointStyle || style.pointStyle, + rotation: style.rotation, + textAlign: textAlign || style.textAlign, + borderRadius: useBorderRadius && (borderRadius || style.borderRadius), + datasetIndex: meta.index + }; + }, this); + } + }, + title: { + color: (ctx)=>ctx.chart.options.color, + display: false, + position: 'center', + text: '' + } + }, + descriptors: { + _scriptable: (name)=>!name.startsWith('on'), + labels: { + _scriptable: (name)=>![ + 'generateLabels', + 'filter', + 'sort' + ].includes(name) + } + } +}; + +class Title extends Element { + constructor(config){ + super(); + this.chart = config.chart; + this.options = config.options; + this.ctx = config.ctx; + this._padding = undefined; + this.top = undefined; + this.bottom = undefined; + this.left = undefined; + this.right = undefined; + this.width = undefined; + this.height = undefined; + this.position = undefined; + this.weight = undefined; + this.fullSize = undefined; + } + update(maxWidth, maxHeight) { + const opts = this.options; + this.left = 0; + this.top = 0; + if (!opts.display) { + this.width = this.height = this.right = this.bottom = 0; + return; + } + this.width = this.right = maxWidth; + this.height = this.bottom = maxHeight; + const lineCount = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(opts.text) ? opts.text.length : 1; + this._padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.padding); + const textSize = lineCount * (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font).lineHeight + this._padding.height; + if (this.isHorizontal()) { + this.height = textSize; + } else { + this.width = textSize; + } + } + isHorizontal() { + const pos = this.options.position; + return pos === 'top' || pos === 'bottom'; + } + _drawArgs(offset) { + const { top , left , bottom , right , options } = this; + const align = options.align; + let rotation = 0; + let maxWidth, titleX, titleY; + if (this.isHorizontal()) { + titleX = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, left, right); + titleY = top + offset; + maxWidth = right - left; + } else { + if (options.position === 'left') { + titleX = left + offset; + titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, bottom, top); + rotation = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P * -0.5; + } else { + titleX = right - offset; + titleY = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a2)(align, top, bottom); + rotation = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P * 0.5; + } + maxWidth = bottom - top; + } + return { + titleX, + titleY, + maxWidth, + rotation + }; + } + draw() { + const ctx = this.ctx; + const opts = this.options; + if (!opts.display) { + return; + } + const fontOpts = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font); + const lineHeight = fontOpts.lineHeight; + const offset = lineHeight / 2 + this._padding.top; + const { titleX , titleY , maxWidth , rotation } = this._drawArgs(offset); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, opts.text, 0, 0, fontOpts, { + color: opts.color, + maxWidth, + rotation, + textAlign: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a1)(opts.align), + textBaseline: 'middle', + translation: [ + titleX, + titleY + ] + }); + } +} +function createTitle(chart, titleOpts) { + const title = new Title({ + ctx: chart.ctx, + options: titleOpts, + chart + }); + layouts.configure(chart, title, titleOpts); + layouts.addBox(chart, title); + chart.titleBlock = title; +} +var plugin_title = { + id: 'title', + _element: Title, + start (chart, _args, options) { + createTitle(chart, options); + }, + stop (chart) { + const titleBlock = chart.titleBlock; + layouts.removeBox(chart, titleBlock); + delete chart.titleBlock; + }, + beforeUpdate (chart, _args, options) { + const title = chart.titleBlock; + layouts.configure(chart, title, options); + title.options = options; + }, + defaults: { + align: 'center', + display: false, + font: { + weight: 'bold' + }, + fullSize: true, + padding: 10, + position: 'top', + text: '', + weight: 2000 + }, + defaultRoutes: { + color: 'color' + }, + descriptors: { + _scriptable: true, + _indexable: false + } +}; + +const map = new WeakMap(); +var plugin_subtitle = { + id: 'subtitle', + start (chart, _args, options) { + const title = new Title({ + ctx: chart.ctx, + options, + chart + }); + layouts.configure(chart, title, options); + layouts.addBox(chart, title); + map.set(chart, title); + }, + stop (chart) { + layouts.removeBox(chart, map.get(chart)); + map.delete(chart); + }, + beforeUpdate (chart, _args, options) { + const title = map.get(chart); + layouts.configure(chart, title, options); + title.options = options; + }, + defaults: { + align: 'center', + display: false, + font: { + weight: 'normal' + }, + fullSize: true, + padding: 0, + position: 'top', + text: '', + weight: 1500 + }, + defaultRoutes: { + color: 'color' + }, + descriptors: { + _scriptable: true, + _indexable: false + } +}; + +const positioners = { + average (items) { + if (!items.length) { + return false; + } + let i, len; + let x = 0; + let y = 0; + let count = 0; + for(i = 0, len = items.length; i < len; ++i){ + const el = items[i].element; + if (el && el.hasValue()) { + const pos = el.tooltipPosition(); + x += pos.x; + y += pos.y; + ++count; + } + } + return { + x: x / count, + y: y / count + }; + }, + nearest (items, eventPosition) { + if (!items.length) { + return false; + } + let x = eventPosition.x; + let y = eventPosition.y; + let minDistance = Number.POSITIVE_INFINITY; + let i, len, nearestElement; + for(i = 0, len = items.length; i < len; ++i){ + const el = items[i].element; + if (el && el.hasValue()) { + const center = el.getCenterPoint(); + const d = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aE)(eventPosition, center); + if (d < minDistance) { + minDistance = d; + nearestElement = el; + } + } + } + if (nearestElement) { + const tp = nearestElement.tooltipPosition(); + x = tp.x; + y = tp.y; + } + return { + x, + y + }; + } +}; +function pushOrConcat(base, toPush) { + if (toPush) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(toPush)) { + Array.prototype.push.apply(base, toPush); + } else { + base.push(toPush); + } + } + return base; +} + function splitNewlines(str) { + if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) { + return str.split('\n'); + } + return str; +} + function createTooltipItem(chart, item) { + const { element , datasetIndex , index } = item; + const controller = chart.getDatasetMeta(datasetIndex).controller; + const { label , value } = controller.getLabelAndValue(index); + return { + chart, + label, + parsed: controller.getParsed(index), + raw: chart.data.datasets[datasetIndex].data[index], + formattedValue: value, + dataset: controller.getDataset(), + dataIndex: index, + datasetIndex, + element + }; +} + function getTooltipSize(tooltip, options) { + const ctx = tooltip.chart.ctx; + const { body , footer , title } = tooltip; + const { boxWidth , boxHeight } = options; + const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont); + const titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont); + const footerFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont); + const titleLineCount = title.length; + const footerLineCount = footer.length; + const bodyLineItemCount = body.length; + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding); + let height = padding.height; + let width = 0; + let combinedBodyLength = body.reduce((count, bodyItem)=>count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0); + combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length; + if (titleLineCount) { + height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom; + } + if (combinedBodyLength) { + const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight; + height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing; + } + if (footerLineCount) { + height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing; + } + let widthPadding = 0; + const maxLineWidth = function(line) { + width = Math.max(width, ctx.measureText(line).width + widthPadding); + }; + ctx.save(); + ctx.font = titleFont.string; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.title, maxLineWidth); + ctx.font = bodyFont.string; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth); + widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(body, (bodyItem)=>{ + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, maxLineWidth); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.lines, maxLineWidth); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, maxLineWidth); + }); + widthPadding = 0; + ctx.font = footerFont.string; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltip.footer, maxLineWidth); + ctx.restore(); + width += padding.width; + return { + width, + height + }; +} +function determineYAlign(chart, size) { + const { y , height } = size; + if (y < height / 2) { + return 'top'; + } else if (y > chart.height - height / 2) { + return 'bottom'; + } + return 'center'; +} +function doesNotFitWithAlign(xAlign, chart, options, size) { + const { x , width } = size; + const caret = options.caretSize + options.caretPadding; + if (xAlign === 'left' && x + width + caret > chart.width) { + return true; + } + if (xAlign === 'right' && x - width - caret < 0) { + return true; + } +} +function determineXAlign(chart, options, size, yAlign) { + const { x , width } = size; + const { width: chartWidth , chartArea: { left , right } } = chart; + let xAlign = 'center'; + if (yAlign === 'center') { + xAlign = x <= (left + right) / 2 ? 'left' : 'right'; + } else if (x <= width / 2) { + xAlign = 'left'; + } else if (x >= chartWidth - width / 2) { + xAlign = 'right'; + } + if (doesNotFitWithAlign(xAlign, chart, options, size)) { + xAlign = 'center'; + } + return xAlign; +} + function determineAlignment(chart, options, size) { + const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size); + return { + xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign), + yAlign + }; +} +function alignX(size, xAlign) { + let { x , width } = size; + if (xAlign === 'right') { + x -= width; + } else if (xAlign === 'center') { + x -= width / 2; + } + return x; +} +function alignY(size, yAlign, paddingAndSize) { + let { y , height } = size; + if (yAlign === 'top') { + y += paddingAndSize; + } else if (yAlign === 'bottom') { + y -= height + paddingAndSize; + } else { + y -= height / 2; + } + return y; +} + function getBackgroundPoint(options, size, alignment, chart) { + const { caretSize , caretPadding , cornerRadius } = options; + const { xAlign , yAlign } = alignment; + const paddingAndSize = caretSize + caretPadding; + const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(cornerRadius); + let x = alignX(size, xAlign); + const y = alignY(size, yAlign, paddingAndSize); + if (yAlign === 'center') { + if (xAlign === 'left') { + x += paddingAndSize; + } else if (xAlign === 'right') { + x -= paddingAndSize; + } + } else if (xAlign === 'left') { + x -= Math.max(topLeft, bottomLeft) + caretSize; + } else if (xAlign === 'right') { + x += Math.max(topRight, bottomRight) + caretSize; + } + return { + x: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(x, 0, chart.width - size.width), + y: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(y, 0, chart.height - size.height) + }; +} +function getAlignedX(tooltip, align, options) { + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding); + return align === 'center' ? tooltip.x + tooltip.width / 2 : align === 'right' ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left; +} + function getBeforeAfterBodyLines(callback) { + return pushOrConcat([], splitNewlines(callback)); +} +function createTooltipContext(parent, tooltip, tooltipItems) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + tooltip, + tooltipItems, + type: 'tooltip' + }); +} +function overrideCallbacks(callbacks, context) { + const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks; + return override ? callbacks.override(override) : callbacks; +} +const defaultCallbacks = { + beforeTitle: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + title (tooltipItems) { + if (tooltipItems.length > 0) { + const item = tooltipItems[0]; + const labels = item.chart.data.labels; + const labelCount = labels ? labels.length : 0; + if (this && this.options && this.options.mode === 'dataset') { + return item.dataset.label || ''; + } else if (item.label) { + return item.label; + } else if (labelCount > 0 && item.dataIndex < labelCount) { + return labels[item.dataIndex]; + } + } + return ''; + }, + afterTitle: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + beforeBody: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + beforeLabel: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + label (tooltipItem) { + if (this && this.options && this.options.mode === 'dataset') { + return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue; + } + let label = tooltipItem.dataset.label || ''; + if (label) { + label += ': '; + } + const value = tooltipItem.formattedValue; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) { + label += value; + } + return label; + }, + labelColor (tooltipItem) { + const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); + const options = meta.controller.getStyle(tooltipItem.dataIndex); + return { + borderColor: options.borderColor, + backgroundColor: options.backgroundColor, + borderWidth: options.borderWidth, + borderDash: options.borderDash, + borderDashOffset: options.borderDashOffset, + borderRadius: 0 + }; + }, + labelTextColor () { + return this.options.bodyColor; + }, + labelPointStyle (tooltipItem) { + const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); + const options = meta.controller.getStyle(tooltipItem.dataIndex); + return { + pointStyle: options.pointStyle, + rotation: options.rotation + }; + }, + afterLabel: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + afterBody: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + beforeFooter: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + footer: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF, + afterFooter: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aF +}; + function invokeCallbackWithFallback(callbacks, name, ctx, arg) { + const result = callbacks[name].call(ctx, arg); + if (typeof result === 'undefined') { + return defaultCallbacks[name].call(ctx, arg); + } + return result; +} +class Tooltip extends Element { + static positioners = positioners; + constructor(config){ + super(); + this.opacity = 0; + this._active = []; + this._eventPosition = undefined; + this._size = undefined; + this._cachedAnimations = undefined; + this._tooltipItems = []; + this.$animations = undefined; + this.$context = undefined; + this.chart = config.chart; + this.options = config.options; + this.dataPoints = undefined; + this.title = undefined; + this.beforeBody = undefined; + this.body = undefined; + this.afterBody = undefined; + this.footer = undefined; + this.xAlign = undefined; + this.yAlign = undefined; + this.x = undefined; + this.y = undefined; + this.height = undefined; + this.width = undefined; + this.caretX = undefined; + this.caretY = undefined; + this.labelColors = undefined; + this.labelPointStyles = undefined; + this.labelTextColors = undefined; + } + initialize(options) { + this.options = options; + this._cachedAnimations = undefined; + this.$context = undefined; + } + _resolveAnimations() { + const cached = this._cachedAnimations; + if (cached) { + return cached; + } + const chart = this.chart; + const options = this.options.setContext(this.getContext()); + const opts = options.enabled && chart.options.animation && options.animations; + const animations = new Animations(this.chart, opts); + if (opts._cacheable) { + this._cachedAnimations = Object.freeze(animations); + } + return animations; + } + getContext() { + return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems)); + } + getTitle(context, options) { + const { callbacks } = options; + const beforeTitle = invokeCallbackWithFallback(callbacks, 'beforeTitle', this, context); + const title = invokeCallbackWithFallback(callbacks, 'title', this, context); + const afterTitle = invokeCallbackWithFallback(callbacks, 'afterTitle', this, context); + let lines = []; + lines = pushOrConcat(lines, splitNewlines(beforeTitle)); + lines = pushOrConcat(lines, splitNewlines(title)); + lines = pushOrConcat(lines, splitNewlines(afterTitle)); + return lines; + } + getBeforeBody(tooltipItems, options) { + return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'beforeBody', this, tooltipItems)); + } + getBody(tooltipItems, options) { + const { callbacks } = options; + const bodyItems = []; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{ + const bodyItem = { + before: [], + lines: [], + after: [] + }; + const scoped = overrideCallbacks(callbacks, context); + pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, 'beforeLabel', this, context))); + pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, 'label', this, context)); + pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, 'afterLabel', this, context))); + bodyItems.push(bodyItem); + }); + return bodyItems; + } + getAfterBody(tooltipItems, options) { + return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'afterBody', this, tooltipItems)); + } + getFooter(tooltipItems, options) { + const { callbacks } = options; + const beforeFooter = invokeCallbackWithFallback(callbacks, 'beforeFooter', this, tooltipItems); + const footer = invokeCallbackWithFallback(callbacks, 'footer', this, tooltipItems); + const afterFooter = invokeCallbackWithFallback(callbacks, 'afterFooter', this, tooltipItems); + let lines = []; + lines = pushOrConcat(lines, splitNewlines(beforeFooter)); + lines = pushOrConcat(lines, splitNewlines(footer)); + lines = pushOrConcat(lines, splitNewlines(afterFooter)); + return lines; + } + _createItems(options) { + const active = this._active; + const data = this.chart.data; + const labelColors = []; + const labelPointStyles = []; + const labelTextColors = []; + let tooltipItems = []; + let i, len; + for(i = 0, len = active.length; i < len; ++i){ + tooltipItems.push(createTooltipItem(this.chart, active[i])); + } + if (options.filter) { + tooltipItems = tooltipItems.filter((element, index, array)=>options.filter(element, index, array, data)); + } + if (options.itemSort) { + tooltipItems = tooltipItems.sort((a, b)=>options.itemSort(a, b, data)); + } + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(tooltipItems, (context)=>{ + const scoped = overrideCallbacks(options.callbacks, context); + labelColors.push(invokeCallbackWithFallback(scoped, 'labelColor', this, context)); + labelPointStyles.push(invokeCallbackWithFallback(scoped, 'labelPointStyle', this, context)); + labelTextColors.push(invokeCallbackWithFallback(scoped, 'labelTextColor', this, context)); + }); + this.labelColors = labelColors; + this.labelPointStyles = labelPointStyles; + this.labelTextColors = labelTextColors; + this.dataPoints = tooltipItems; + return tooltipItems; + } + update(changed, replay) { + const options = this.options.setContext(this.getContext()); + const active = this._active; + let properties; + let tooltipItems = []; + if (!active.length) { + if (this.opacity !== 0) { + properties = { + opacity: 0 + }; + } + } else { + const position = positioners[options.position].call(this, active, this._eventPosition); + tooltipItems = this._createItems(options); + this.title = this.getTitle(tooltipItems, options); + this.beforeBody = this.getBeforeBody(tooltipItems, options); + this.body = this.getBody(tooltipItems, options); + this.afterBody = this.getAfterBody(tooltipItems, options); + this.footer = this.getFooter(tooltipItems, options); + const size = this._size = getTooltipSize(this, options); + const positionAndSize = Object.assign({}, position, size); + const alignment = determineAlignment(this.chart, options, positionAndSize); + const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart); + this.xAlign = alignment.xAlign; + this.yAlign = alignment.yAlign; + properties = { + opacity: 1, + x: backgroundPoint.x, + y: backgroundPoint.y, + width: size.width, + height: size.height, + caretX: position.x, + caretY: position.y + }; + } + this._tooltipItems = tooltipItems; + this.$context = undefined; + if (properties) { + this._resolveAnimations().update(this, properties); + } + if (changed && options.external) { + options.external.call(this, { + chart: this.chart, + tooltip: this, + replay + }); + } + } + drawCaret(tooltipPoint, ctx, size, options) { + const caretPosition = this.getCaretPosition(tooltipPoint, size, options); + ctx.lineTo(caretPosition.x1, caretPosition.y1); + ctx.lineTo(caretPosition.x2, caretPosition.y2); + ctx.lineTo(caretPosition.x3, caretPosition.y3); + } + getCaretPosition(tooltipPoint, size, options) { + const { xAlign , yAlign } = this; + const { caretSize , cornerRadius } = options; + const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(cornerRadius); + const { x: ptX , y: ptY } = tooltipPoint; + const { width , height } = size; + let x1, x2, x3, y1, y2, y3; + if (yAlign === 'center') { + y2 = ptY + height / 2; + if (xAlign === 'left') { + x1 = ptX; + x2 = x1 - caretSize; + y1 = y2 + caretSize; + y3 = y2 - caretSize; + } else { + x1 = ptX + width; + x2 = x1 + caretSize; + y1 = y2 - caretSize; + y3 = y2 + caretSize; + } + x3 = x1; + } else { + if (xAlign === 'left') { + x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize; + } else if (xAlign === 'right') { + x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize; + } else { + x2 = this.caretX; + } + if (yAlign === 'top') { + y1 = ptY; + y2 = y1 - caretSize; + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } else { + y1 = ptY + height; + y2 = y1 + caretSize; + x1 = x2 + caretSize; + x3 = x2 - caretSize; + } + y3 = y1; + } + return { + x1, + x2, + x3, + y1, + y2, + y3 + }; + } + drawTitle(pt, ctx, options) { + const title = this.title; + const length = title.length; + let titleFont, titleSpacing, i; + if (length) { + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(options.rtl, this.x, this.width); + pt.x = getAlignedX(this, options.titleAlign, options); + ctx.textAlign = rtlHelper.textAlign(options.titleAlign); + ctx.textBaseline = 'middle'; + titleFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.titleFont); + titleSpacing = options.titleSpacing; + ctx.fillStyle = options.titleColor; + ctx.font = titleFont.string; + for(i = 0; i < length; ++i){ + ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2); + pt.y += titleFont.lineHeight + titleSpacing; + if (i + 1 === length) { + pt.y += options.titleMarginBottom - titleSpacing; + } + } + } + } + _drawColorBox(ctx, pt, i, rtlHelper, options) { + const labelColor = this.labelColors[i]; + const labelPointStyle = this.labelPointStyles[i]; + const { boxHeight , boxWidth } = options; + const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont); + const colorX = getAlignedX(this, 'left', options); + const rtlColorX = rtlHelper.x(colorX); + const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0; + const colorY = pt.y + yOffSet; + if (options.usePointStyle) { + const drawOptions = { + radius: Math.min(boxWidth, boxHeight) / 2, + pointStyle: labelPointStyle.pointStyle, + rotation: labelPointStyle.rotation, + borderWidth: 1 + }; + const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2; + const centerY = colorY + boxHeight / 2; + ctx.strokeStyle = options.multiKeyBackground; + ctx.fillStyle = options.multiKeyBackground; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(ctx, drawOptions, centerX, centerY); + ctx.strokeStyle = labelColor.borderColor; + ctx.fillStyle = labelColor.backgroundColor; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.at)(ctx, drawOptions, centerX, centerY); + } else { + ctx.lineWidth = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.i)(labelColor.borderWidth) ? Math.max(...Object.values(labelColor.borderWidth)) : labelColor.borderWidth || 1; + ctx.strokeStyle = labelColor.borderColor; + ctx.setLineDash(labelColor.borderDash || []); + ctx.lineDashOffset = labelColor.borderDashOffset || 0; + const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth); + const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2); + const borderRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(labelColor.borderRadius); + if (Object.values(borderRadius).some((v)=>v !== 0)) { + ctx.beginPath(); + ctx.fillStyle = options.multiKeyBackground; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(ctx, { + x: outerX, + y: colorY, + w: boxWidth, + h: boxHeight, + radius: borderRadius + }); + ctx.fill(); + ctx.stroke(); + ctx.fillStyle = labelColor.backgroundColor; + ctx.beginPath(); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(ctx, { + x: innerX, + y: colorY + 1, + w: boxWidth - 2, + h: boxHeight - 2, + radius: borderRadius + }); + ctx.fill(); + } else { + ctx.fillStyle = options.multiKeyBackground; + ctx.fillRect(outerX, colorY, boxWidth, boxHeight); + ctx.strokeRect(outerX, colorY, boxWidth, boxHeight); + ctx.fillStyle = labelColor.backgroundColor; + ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2); + } + } + ctx.fillStyle = this.labelTextColors[i]; + } + drawBody(pt, ctx, options) { + const { body } = this; + const { bodySpacing , bodyAlign , displayColors , boxHeight , boxWidth , boxPadding } = options; + const bodyFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.bodyFont); + let bodyLineHeight = bodyFont.lineHeight; + let xLinePadding = 0; + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(options.rtl, this.x, this.width); + const fillLineOfText = function(line) { + ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2); + pt.y += bodyLineHeight + bodySpacing; + }; + const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign); + let bodyItem, textColor, lines, i, j, ilen, jlen; + ctx.textAlign = bodyAlign; + ctx.textBaseline = 'middle'; + ctx.font = bodyFont.string; + pt.x = getAlignedX(this, bodyAlignForCalculation, options); + ctx.fillStyle = options.bodyColor; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.beforeBody, fillLineOfText); + xLinePadding = displayColors && bodyAlignForCalculation !== 'right' ? bodyAlign === 'center' ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0; + for(i = 0, ilen = body.length; i < ilen; ++i){ + bodyItem = body[i]; + textColor = this.labelTextColors[i]; + ctx.fillStyle = textColor; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.before, fillLineOfText); + lines = bodyItem.lines; + if (displayColors && lines.length) { + this._drawColorBox(ctx, pt, i, rtlHelper, options); + bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight); + } + for(j = 0, jlen = lines.length; j < jlen; ++j){ + fillLineOfText(lines[j]); + bodyLineHeight = bodyFont.lineHeight; + } + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(bodyItem.after, fillLineOfText); + } + xLinePadding = 0; + bodyLineHeight = bodyFont.lineHeight; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.F)(this.afterBody, fillLineOfText); + pt.y -= bodySpacing; + } + drawFooter(pt, ctx, options) { + const footer = this.footer; + const length = footer.length; + let footerFont, i; + if (length) { + const rtlHelper = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.az)(options.rtl, this.x, this.width); + pt.x = getAlignedX(this, options.footerAlign, options); + pt.y += options.footerMarginTop; + ctx.textAlign = rtlHelper.textAlign(options.footerAlign); + ctx.textBaseline = 'middle'; + footerFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(options.footerFont); + ctx.fillStyle = options.footerColor; + ctx.font = footerFont.string; + for(i = 0; i < length; ++i){ + ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2); + pt.y += footerFont.lineHeight + options.footerSpacing; + } + } + } + drawBackground(pt, ctx, tooltipSize, options) { + const { xAlign , yAlign } = this; + const { x , y } = pt; + const { width , height } = tooltipSize; + const { topLeft , topRight , bottomLeft , bottomRight } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(options.cornerRadius); + ctx.fillStyle = options.backgroundColor; + ctx.strokeStyle = options.borderColor; + ctx.lineWidth = options.borderWidth; + ctx.beginPath(); + ctx.moveTo(x + topLeft, y); + if (yAlign === 'top') { + this.drawCaret(pt, ctx, tooltipSize, options); + } + ctx.lineTo(x + width - topRight, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + topRight); + if (yAlign === 'center' && xAlign === 'right') { + this.drawCaret(pt, ctx, tooltipSize, options); + } + ctx.lineTo(x + width, y + height - bottomRight); + ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height); + if (yAlign === 'bottom') { + this.drawCaret(pt, ctx, tooltipSize, options); + } + ctx.lineTo(x + bottomLeft, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft); + if (yAlign === 'center' && xAlign === 'left') { + this.drawCaret(pt, ctx, tooltipSize, options); + } + ctx.lineTo(x, y + topLeft); + ctx.quadraticCurveTo(x, y, x + topLeft, y); + ctx.closePath(); + ctx.fill(); + if (options.borderWidth > 0) { + ctx.stroke(); + } + } + _updateAnimationTarget(options) { + const chart = this.chart; + const anims = this.$animations; + const animX = anims && anims.x; + const animY = anims && anims.y; + if (animX || animY) { + const position = positioners[options.position].call(this, this._active, this._eventPosition); + if (!position) { + return; + } + const size = this._size = getTooltipSize(this, options); + const positionAndSize = Object.assign({}, position, this._size); + const alignment = determineAlignment(chart, options, positionAndSize); + const point = getBackgroundPoint(options, positionAndSize, alignment, chart); + if (animX._to !== point.x || animY._to !== point.y) { + this.xAlign = alignment.xAlign; + this.yAlign = alignment.yAlign; + this.width = size.width; + this.height = size.height; + this.caretX = position.x; + this.caretY = position.y; + this._resolveAnimations().update(this, point); + } + } + } + _willRender() { + return !!this.opacity; + } + draw(ctx) { + const options = this.options.setContext(this.getContext()); + let opacity = this.opacity; + if (!opacity) { + return; + } + this._updateAnimationTarget(options); + const tooltipSize = { + width: this.width, + height: this.height + }; + const pt = { + x: this.x, + y: this.y + }; + opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity; + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(options.padding); + const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length; + if (options.enabled && hasTooltipContent) { + ctx.save(); + ctx.globalAlpha = opacity; + this.drawBackground(pt, ctx, tooltipSize, options); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aA)(ctx, options.textDirection); + pt.y += padding.top; + this.drawTitle(pt, ctx, options); + this.drawBody(pt, ctx, options); + this.drawFooter(pt, ctx, options); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aC)(ctx, options.textDirection); + ctx.restore(); + } + } + getActiveElements() { + return this._active || []; + } + setActiveElements(activeElements, eventPosition) { + const lastActive = this._active; + const active = activeElements.map(({ datasetIndex , index })=>{ + const meta = this.chart.getDatasetMeta(datasetIndex); + if (!meta) { + throw new Error('Cannot find a dataset at index ' + datasetIndex); + } + return { + datasetIndex, + element: meta.data[index], + index + }; + }); + const changed = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ah)(lastActive, active); + const positionChanged = this._positionChanged(active, eventPosition); + if (changed || positionChanged) { + this._active = active; + this._eventPosition = eventPosition; + this._ignoreReplayEvents = true; + this.update(true); + } + } + handleEvent(e, replay, inChartArea = true) { + if (replay && this._ignoreReplayEvents) { + return false; + } + this._ignoreReplayEvents = false; + const options = this.options; + const lastActive = this._active || []; + const active = this._getActiveElements(e, lastActive, replay, inChartArea); + const positionChanged = this._positionChanged(active, e); + const changed = replay || !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ah)(active, lastActive) || positionChanged; + if (changed) { + this._active = active; + if (options.enabled || options.external) { + this._eventPosition = { + x: e.x, + y: e.y + }; + this.update(true, replay); + } + } + return changed; + } + _getActiveElements(e, lastActive, replay, inChartArea) { + const options = this.options; + if (e.type === 'mouseout') { + return []; + } + if (!inChartArea) { + return lastActive; + } + const active = this.chart.getElementsAtEventForMode(e, options.mode, options, replay); + if (options.reverse) { + active.reverse(); + } + return active; + } + _positionChanged(active, e) { + const { caretX , caretY , options } = this; + const position = positioners[options.position].call(this, active, e); + return position !== false && (caretX !== position.x || caretY !== position.y); + } +} +var plugin_tooltip = { + id: 'tooltip', + _element: Tooltip, + positioners, + afterInit (chart, _args, options) { + if (options) { + chart.tooltip = new Tooltip({ + chart, + options + }); + } + }, + beforeUpdate (chart, _args, options) { + if (chart.tooltip) { + chart.tooltip.initialize(options); + } + }, + reset (chart, _args, options) { + if (chart.tooltip) { + chart.tooltip.initialize(options); + } + }, + afterDraw (chart) { + const tooltip = chart.tooltip; + if (tooltip && tooltip._willRender()) { + const args = { + tooltip + }; + if (chart.notifyPlugins('beforeTooltipDraw', { + ...args, + cancelable: true + }) === false) { + return; + } + tooltip.draw(chart.ctx); + chart.notifyPlugins('afterTooltipDraw', args); + } + }, + afterEvent (chart, args) { + if (chart.tooltip) { + const useFinalPosition = args.replay; + if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) { + args.changed = true; + } + } + }, + defaults: { + enabled: true, + external: null, + position: 'average', + backgroundColor: 'rgba(0,0,0,0.8)', + titleColor: '#fff', + titleFont: { + weight: 'bold' + }, + titleSpacing: 2, + titleMarginBottom: 6, + titleAlign: 'left', + bodyColor: '#fff', + bodySpacing: 2, + bodyFont: {}, + bodyAlign: 'left', + footerColor: '#fff', + footerSpacing: 2, + footerMarginTop: 6, + footerFont: { + weight: 'bold' + }, + footerAlign: 'left', + padding: 6, + caretPadding: 2, + caretSize: 5, + cornerRadius: 6, + boxHeight: (ctx, opts)=>opts.bodyFont.size, + boxWidth: (ctx, opts)=>opts.bodyFont.size, + multiKeyBackground: '#fff', + displayColors: true, + boxPadding: 0, + borderColor: 'rgba(0,0,0,0)', + borderWidth: 0, + animation: { + duration: 400, + easing: 'easeOutQuart' + }, + animations: { + numbers: { + type: 'number', + properties: [ + 'x', + 'y', + 'width', + 'height', + 'caretX', + 'caretY' + ] + }, + opacity: { + easing: 'linear', + duration: 200 + } + }, + callbacks: defaultCallbacks + }, + defaultRoutes: { + bodyFont: 'font', + footerFont: 'font', + titleFont: 'font' + }, + descriptors: { + _scriptable: (name)=>name !== 'filter' && name !== 'itemSort' && name !== 'external', + _indexable: false, + callbacks: { + _scriptable: false, + _indexable: false + }, + animation: { + _fallback: false + }, + animations: { + _fallback: 'animation' + } + }, + additionalOptionScopes: [ + 'interaction' + ] +}; + +var plugins = /*#__PURE__*/Object.freeze({ +__proto__: null, +Colors: plugin_colors, +Decimation: plugin_decimation, +Filler: index, +Legend: plugin_legend, +SubTitle: plugin_subtitle, +Title: plugin_title, +Tooltip: plugin_tooltip +}); + +const addIfString = (labels, raw, index, addedLabels)=>{ + if (typeof raw === 'string') { + index = labels.push(raw) - 1; + addedLabels.unshift({ + index, + label: raw + }); + } else if (isNaN(raw)) { + index = null; + } + return index; +}; +function findOrAddLabel(labels, raw, index, addedLabels) { + const first = labels.indexOf(raw); + if (first === -1) { + return addIfString(labels, raw, index, addedLabels); + } + const last = labels.lastIndexOf(raw); + return first !== last ? index : first; +} +const validIndex = (index, max)=>index === null ? null : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(Math.round(index), 0, max); +function _getLabelForValue(value) { + const labels = this.getLabels(); + if (value >= 0 && value < labels.length) { + return labels[value]; + } + return value; +} +class CategoryScale extends Scale { + static id = 'category'; + static defaults = { + ticks: { + callback: _getLabelForValue + } + }; + constructor(cfg){ + super(cfg); + this._startValue = undefined; + this._valueRange = 0; + this._addedLabels = []; + } + init(scaleOptions) { + const added = this._addedLabels; + if (added.length) { + const labels = this.getLabels(); + for (const { index , label } of added){ + if (labels[index] === label) { + labels.splice(index, 1); + } + } + this._addedLabels = []; + } + super.init(scaleOptions); + } + parse(raw, index) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) { + return null; + } + const labels = this.getLabels(); + index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(index, raw), this._addedLabels); + return validIndex(index, labels.length - 1); + } + determineDataLimits() { + const { minDefined , maxDefined } = this.getUserBounds(); + let { min , max } = this.getMinMax(true); + if (this.options.bounds === 'ticks') { + if (!minDefined) { + min = 0; + } + if (!maxDefined) { + max = this.getLabels().length - 1; + } + } + this.min = min; + this.max = max; + } + buildTicks() { + const min = this.min; + const max = this.max; + const offset = this.options.offset; + const ticks = []; + let labels = this.getLabels(); + labels = min === 0 && max === labels.length - 1 ? labels : labels.slice(min, max + 1); + this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1); + this._startValue = this.min - (offset ? 0.5 : 0); + for(let value = min; value <= max; value++){ + ticks.push({ + value + }); + } + return ticks; + } + getLabelForValue(value) { + return _getLabelForValue.call(this, value); + } + configure() { + super.configure(); + if (!this.isHorizontal()) { + this._reversePixels = !this._reversePixels; + } + } + getPixelForValue(value) { + if (typeof value !== 'number') { + value = this.parse(value); + } + return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange); + } + getPixelForTick(index) { + const ticks = this.ticks; + if (index < 0 || index > ticks.length - 1) { + return null; + } + return this.getPixelForValue(ticks[index].value); + } + getValueForPixel(pixel) { + return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange); + } + getBasePixel() { + return this.bottom; + } +} + +function generateTicks$1(generationOptions, dataRange) { + const ticks = []; + const MIN_SPACING = 1e-14; + const { bounds , step , min , max , precision , count , maxTicks , maxDigits , includeBounds } = generationOptions; + const unit = step || 1; + const maxSpaces = maxTicks - 1; + const { min: rmin , max: rmax } = dataRange; + const minDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(min); + const maxDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(max); + const countDefined = !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(count); + const minSpacing = (rmax - rmin) / (maxDigits + 1); + let spacing = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aH)((rmax - rmin) / maxSpaces / unit) * unit; + let factor, niceMin, niceMax, numSpaces; + if (spacing < MIN_SPACING && !minDefined && !maxDefined) { + return [ + { + value: rmin + }, + { + value: rmax + } + ]; + } + numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); + if (numSpaces > maxSpaces) { + spacing = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aH)(numSpaces * spacing / maxSpaces / unit) * unit; + } + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision)) { + factor = Math.pow(10, precision); + spacing = Math.ceil(spacing * factor) / factor; + } + if (bounds === 'ticks') { + niceMin = Math.floor(rmin / spacing) * spacing; + niceMax = Math.ceil(rmax / spacing) * spacing; + } else { + niceMin = rmin; + niceMax = rmax; + } + if (minDefined && maxDefined && step && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aI)((max - min) / step, spacing / 1000)) { + numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks)); + spacing = (max - min) / numSpaces; + niceMin = min; + niceMax = max; + } else if (countDefined) { + niceMin = minDefined ? min : niceMin; + niceMax = maxDefined ? max : niceMax; + numSpaces = count - 1; + spacing = (niceMax - niceMin) / numSpaces; + } else { + numSpaces = (niceMax - niceMin) / spacing; + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aJ)(numSpaces, Math.round(numSpaces), spacing / 1000)) { + numSpaces = Math.round(numSpaces); + } else { + numSpaces = Math.ceil(numSpaces); + } + } + const decimalPlaces = Math.max((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aK)(spacing), (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aK)(niceMin)); + factor = Math.pow(10, (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(precision) ? decimalPlaces : precision); + niceMin = Math.round(niceMin * factor) / factor; + niceMax = Math.round(niceMax * factor) / factor; + let j = 0; + if (minDefined) { + if (includeBounds && niceMin !== min) { + ticks.push({ + value: min + }); + if (niceMin < min) { + j++; + } + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aJ)(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) { + j++; + } + } else if (niceMin < min) { + j++; + } + } + for(; j < numSpaces; ++j){ + const tickValue = Math.round((niceMin + j * spacing) * factor) / factor; + if (maxDefined && tickValue > max) { + break; + } + ticks.push({ + value: tickValue + }); + } + if (maxDefined && includeBounds && niceMax !== max) { + if (ticks.length && (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aJ)(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) { + ticks[ticks.length - 1].value = max; + } else { + ticks.push({ + value: max + }); + } + } else if (!maxDefined || niceMax === max) { + ticks.push({ + value: niceMax + }); + } + return ticks; +} +function relativeLabelSize(value, minSpacing, { horizontal , minRotation }) { + const rad = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(minRotation); + const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001; + const length = 0.75 * minSpacing * ('' + value).length; + return Math.min(minSpacing / ratio, length); +} +class LinearScaleBase extends Scale { + constructor(cfg){ + super(cfg); + this.start = undefined; + this.end = undefined; + this._startValue = undefined; + this._endValue = undefined; + this._valueRange = 0; + } + parse(raw, index) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(raw)) { + return null; + } + if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) { + return null; + } + return +raw; + } + handleTickRangeOptions() { + const { beginAtZero } = this.options; + const { minDefined , maxDefined } = this.getUserBounds(); + let { min , max } = this; + const setMin = (v)=>min = minDefined ? min : v; + const setMax = (v)=>max = maxDefined ? max : v; + if (beginAtZero) { + const minSign = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(min); + const maxSign = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.s)(max); + if (minSign < 0 && maxSign < 0) { + setMax(0); + } else if (minSign > 0 && maxSign > 0) { + setMin(0); + } + } + if (min === max) { + let offset = max === 0 ? 1 : Math.abs(max * 0.05); + setMax(max + offset); + if (!beginAtZero) { + setMin(min - offset); + } + } + this.min = min; + this.max = max; + } + getTickLimit() { + const tickOpts = this.options.ticks; + let { maxTicksLimit , stepSize } = tickOpts; + let maxTicks; + if (stepSize) { + maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1; + if (maxTicks > 1000) { + console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`); + maxTicks = 1000; + } + } else { + maxTicks = this.computeTickLimit(); + maxTicksLimit = maxTicksLimit || 11; + } + if (maxTicksLimit) { + maxTicks = Math.min(maxTicksLimit, maxTicks); + } + return maxTicks; + } + computeTickLimit() { + return Number.POSITIVE_INFINITY; + } + buildTicks() { + const opts = this.options; + const tickOpts = opts.ticks; + let maxTicks = this.getTickLimit(); + maxTicks = Math.max(2, maxTicks); + const numericGeneratorOptions = { + maxTicks, + bounds: opts.bounds, + min: opts.min, + max: opts.max, + precision: tickOpts.precision, + step: tickOpts.stepSize, + count: tickOpts.count, + maxDigits: this._maxDigits(), + horizontal: this.isHorizontal(), + minRotation: tickOpts.minRotation || 0, + includeBounds: tickOpts.includeBounds !== false + }; + const dataRange = this._range || this; + const ticks = generateTicks$1(numericGeneratorOptions, dataRange); + if (opts.bounds === 'ticks') { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aG)(ticks, this, 'value'); + } + if (opts.reverse) { + ticks.reverse(); + this.start = this.max; + this.end = this.min; + } else { + this.start = this.min; + this.end = this.max; + } + return ticks; + } + configure() { + const ticks = this.ticks; + let start = this.min; + let end = this.max; + super.configure(); + if (this.options.offset && ticks.length) { + const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2; + start -= offset; + end += offset; + } + this._startValue = start; + this._endValue = end; + this._valueRange = end - start; + } + getLabelForValue(value) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format); + } +} + +class LinearScale extends LinearScaleBase { + static id = 'linear'; + static defaults = { + ticks: { + callback: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aL.formatters.numeric + } + }; + determineDataLimits() { + const { min , max } = this.getMinMax(true); + this.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? min : 0; + this.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? max : 1; + this.handleTickRangeOptions(); + } + computeTickLimit() { + const horizontal = this.isHorizontal(); + const length = horizontal ? this.width : this.height; + const minRotation = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.options.ticks.minRotation); + const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001; + const tickFont = this._resolveTickFontOptions(0); + return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio)); + } + getPixelForValue(value) { + return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange); + } + getValueForPixel(pixel) { + return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange; + } +} + +const log10Floor = (v)=>Math.floor((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aM)(v)); +const changeExponent = (v, m)=>Math.pow(10, log10Floor(v) + m); +function isMajor(tickVal) { + const remain = tickVal / Math.pow(10, log10Floor(tickVal)); + return remain === 1; +} +function steps(min, max, rangeExp) { + const rangeStep = Math.pow(10, rangeExp); + const start = Math.floor(min / rangeStep); + const end = Math.ceil(max / rangeStep); + return end - start; +} +function startExp(min, max) { + const range = max - min; + let rangeExp = log10Floor(range); + while(steps(min, max, rangeExp) > 10){ + rangeExp++; + } + while(steps(min, max, rangeExp) < 10){ + rangeExp--; + } + return Math.min(rangeExp, log10Floor(min)); +} + function generateTicks(generationOptions, { min , max }) { + min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, min); + const ticks = []; + const minExp = log10Floor(min); + let exp = startExp(min, max); + let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1; + const stepSize = Math.pow(10, exp); + const base = minExp > exp ? Math.pow(10, minExp) : 0; + const start = Math.round((min - base) * precision) / precision; + const offset = Math.floor((min - base) / stepSize / 10) * stepSize * 10; + let significand = Math.floor((start - offset) / Math.pow(10, exp)); + let value = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.min, Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision); + while(value < max){ + ticks.push({ + value, + major: isMajor(value), + significand + }); + if (significand >= 10) { + significand = significand < 15 ? 15 : 20; + } else { + significand++; + } + if (significand >= 20) { + exp++; + significand = 2; + precision = exp >= 0 ? 1 : precision; + } + value = Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision; + } + const lastTick = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.O)(generationOptions.max, value); + ticks.push({ + value: lastTick, + major: isMajor(lastTick), + significand + }); + return ticks; +} +class LogarithmicScale extends Scale { + static id = 'logarithmic'; + static defaults = { + ticks: { + callback: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aL.formatters.logarithmic, + major: { + enabled: true + } + } + }; + constructor(cfg){ + super(cfg); + this.start = undefined; + this.end = undefined; + this._startValue = undefined; + this._valueRange = 0; + } + parse(raw, index) { + const value = LinearScaleBase.prototype.parse.apply(this, [ + raw, + index + ]); + if (value === 0) { + this._zero = true; + return undefined; + } + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value) && value > 0 ? value : null; + } + determineDataLimits() { + const { min , max } = this.getMinMax(true); + this.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) ? Math.max(0, min) : null; + this.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) ? Math.max(0, max) : null; + if (this.options.beginAtZero) { + this._zero = true; + } + if (this._zero && this.min !== this._suggestedMin && !(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(this._userMin)) { + this.min = min === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0); + } + this.handleTickRangeOptions(); + } + handleTickRangeOptions() { + const { minDefined , maxDefined } = this.getUserBounds(); + let min = this.min; + let max = this.max; + const setMin = (v)=>min = minDefined ? min : v; + const setMax = (v)=>max = maxDefined ? max : v; + if (min === max) { + if (min <= 0) { + setMin(1); + setMax(10); + } else { + setMin(changeExponent(min, -1)); + setMax(changeExponent(max, +1)); + } + } + if (min <= 0) { + setMin(changeExponent(max, -1)); + } + if (max <= 0) { + setMax(changeExponent(min, +1)); + } + this.min = min; + this.max = max; + } + buildTicks() { + const opts = this.options; + const generationOptions = { + min: this._userMin, + max: this._userMax + }; + const ticks = generateTicks(generationOptions, this); + if (opts.bounds === 'ticks') { + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aG)(ticks, this, 'value'); + } + if (opts.reverse) { + ticks.reverse(); + this.start = this.max; + this.end = this.min; + } else { + this.start = this.min; + this.end = this.max; + } + return ticks; + } + getLabelForValue(value) { + return value === undefined ? '0' : (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.o)(value, this.chart.options.locale, this.options.ticks.format); + } + configure() { + const start = this.min; + super.configure(); + this._startValue = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aM)(start); + this._valueRange = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aM)(this.max) - (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aM)(start); + } + getPixelForValue(value) { + if (value === undefined || value === 0) { + value = this.min; + } + if (value === null || isNaN(value)) { + return NaN; + } + return this.getPixelForDecimal(value === this.min ? 0 : ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aM)(value) - this._startValue) / this._valueRange); + } + getValueForPixel(pixel) { + const decimal = this.getDecimalForPixel(pixel); + return Math.pow(10, this._startValue + decimal * this._valueRange); + } +} + +function getTickBackdropHeight(opts) { + const tickOpts = opts.ticks; + if (tickOpts.display && opts.display) { + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(tickOpts.backdropPadding); + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(tickOpts.font && tickOpts.font.size, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.d.font.size) + padding.height; + } + return 0; +} +function measureLabelSize(ctx, font, label) { + label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.b)(label) ? label : [ + label + ]; + return { + w: (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aN)(ctx, font.string, label), + h: label.length * font.lineHeight + }; +} +function determineLimits(angle, pos, size, min, max) { + if (angle === min || angle === max) { + return { + start: pos - size / 2, + end: pos + size / 2 + }; + } else if (angle < min || angle > max) { + return { + start: pos - size, + end: pos + }; + } + return { + start: pos, + end: pos + size + }; +} + function fitWithPointLabels(scale) { + const orig = { + l: scale.left + scale._padding.left, + r: scale.right - scale._padding.right, + t: scale.top + scale._padding.top, + b: scale.bottom - scale._padding.bottom + }; + const limits = Object.assign({}, orig); + const labelSizes = []; + const padding = []; + const valueCount = scale._pointLabels.length; + const pointLabelOpts = scale.options.pointLabels; + const additionalAngle = pointLabelOpts.centerPointLabels ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0; + for(let i = 0; i < valueCount; i++){ + const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i)); + padding[i] = opts.padding; + const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i], additionalAngle); + const plFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(opts.font); + const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]); + labelSizes[i] = textSize; + const angleRadians = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay)(scale.getIndexAngle(i) + additionalAngle); + const angle = Math.round((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)(angleRadians)); + const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); + const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); + updateLimits(limits, orig, angleRadians, hLimits, vLimits); + } + scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b); + scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding); +} +function updateLimits(limits, orig, angle, hLimits, vLimits) { + const sin = Math.abs(Math.sin(angle)); + const cos = Math.abs(Math.cos(angle)); + let x = 0; + let y = 0; + if (hLimits.start < orig.l) { + x = (orig.l - hLimits.start) / sin; + limits.l = Math.min(limits.l, orig.l - x); + } else if (hLimits.end > orig.r) { + x = (hLimits.end - orig.r) / sin; + limits.r = Math.max(limits.r, orig.r + x); + } + if (vLimits.start < orig.t) { + y = (orig.t - vLimits.start) / cos; + limits.t = Math.min(limits.t, orig.t - y); + } else if (vLimits.end > orig.b) { + y = (vLimits.end - orig.b) / cos; + limits.b = Math.max(limits.b, orig.b + y); + } +} +function createPointLabelItem(scale, index, itemOpts) { + const outerDistance = scale.drawingArea; + const { extra , additionalAngle , padding , size } = itemOpts; + const pointLabelPosition = scale.getPointPosition(index, outerDistance + extra + padding, additionalAngle); + const angle = Math.round((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.U)((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay)(pointLabelPosition.angle + _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H))); + const y = yForAngle(pointLabelPosition.y, size.h, angle); + const textAlign = getTextAlignForAngle(angle); + const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign); + return { + visible: true, + x: pointLabelPosition.x, + y, + textAlign, + left, + top: y, + right: left + size.w, + bottom: y + size.h + }; +} +function isNotOverlapped(item, area) { + if (!area) { + return true; + } + const { left , top , right , bottom } = item; + const apexesInArea = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)({ + x: left, + y: top + }, area) || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)({ + x: left, + y: bottom + }, area) || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)({ + x: right, + y: top + }, area) || (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.C)({ + x: right, + y: bottom + }, area); + return !apexesInArea; +} +function buildPointLabelItems(scale, labelSizes, padding) { + const items = []; + const valueCount = scale._pointLabels.length; + const opts = scale.options; + const { centerPointLabels , display } = opts.pointLabels; + const itemOpts = { + extra: getTickBackdropHeight(opts) / 2, + additionalAngle: centerPointLabels ? _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.P / valueCount : 0 + }; + let area; + for(let i = 0; i < valueCount; i++){ + itemOpts.padding = padding[i]; + itemOpts.size = labelSizes[i]; + const item = createPointLabelItem(scale, i, itemOpts); + items.push(item); + if (display === 'auto') { + item.visible = isNotOverlapped(item, area); + if (item.visible) { + area = item; + } + } + } + return items; +} +function getTextAlignForAngle(angle) { + if (angle === 0 || angle === 180) { + return 'center'; + } else if (angle < 180) { + return 'left'; + } + return 'right'; +} +function leftForTextAlign(x, w, align) { + if (align === 'right') { + x -= w; + } else if (align === 'center') { + x -= w / 2; + } + return x; +} +function yForAngle(y, h, angle) { + if (angle === 90 || angle === 270) { + y -= h / 2; + } else if (angle > 270 || angle < 90) { + y -= h; + } + return y; +} +function drawPointLabelBox(ctx, opts, item) { + const { left , top , right , bottom } = item; + const { backdropColor } = opts; + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(backdropColor)) { + const borderRadius = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aw)(opts.borderRadius); + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(opts.backdropPadding); + ctx.fillStyle = backdropColor; + const backdropLeft = left - padding.left; + const backdropTop = top - padding.top; + const backdropWidth = right - left + padding.width; + const backdropHeight = bottom - top + padding.height; + if (Object.values(borderRadius).some((v)=>v !== 0)) { + ctx.beginPath(); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.au)(ctx, { + x: backdropLeft, + y: backdropTop, + w: backdropWidth, + h: backdropHeight, + radius: borderRadius + }); + ctx.fill(); + } else { + ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight); + } + } +} +function drawPointLabels(scale, labelCount) { + const { ctx , options: { pointLabels } } = scale; + for(let i = labelCount - 1; i >= 0; i--){ + const item = scale._pointLabelItems[i]; + if (!item.visible) { + continue; + } + const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i)); + drawPointLabelBox(ctx, optsAtIndex, item); + const plFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font); + const { x , y , textAlign } = item; + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, scale._pointLabels[i], x, y + plFont.lineHeight / 2, plFont, { + color: optsAtIndex.color, + textAlign: textAlign, + textBaseline: 'middle' + }); + } +} +function pathRadiusLine(scale, radius, circular, labelCount) { + const { ctx } = scale; + if (circular) { + ctx.arc(scale.xCenter, scale.yCenter, radius, 0, _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T); + } else { + let pointPosition = scale.getPointPosition(0, radius); + ctx.moveTo(pointPosition.x, pointPosition.y); + for(let i = 1; i < labelCount; i++){ + pointPosition = scale.getPointPosition(i, radius); + ctx.lineTo(pointPosition.x, pointPosition.y); + } + } +} +function drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) { + const ctx = scale.ctx; + const circular = gridLineOpts.circular; + const { color , lineWidth } = gridLineOpts; + if (!circular && !labelCount || !color || !lineWidth || radius < 0) { + return; + } + ctx.save(); + ctx.strokeStyle = color; + ctx.lineWidth = lineWidth; + ctx.setLineDash(borderOpts.dash); + ctx.lineDashOffset = borderOpts.dashOffset; + ctx.beginPath(); + pathRadiusLine(scale, radius, circular, labelCount); + ctx.closePath(); + ctx.stroke(); + ctx.restore(); +} +function createPointLabelContext(parent, index, label) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.j)(parent, { + label, + index, + type: 'pointLabel' + }); +} +class RadialLinearScale extends LinearScaleBase { + static id = 'radialLinear'; + static defaults = { + display: true, + animate: true, + position: 'chartArea', + angleLines: { + display: true, + lineWidth: 1, + borderDash: [], + borderDashOffset: 0.0 + }, + grid: { + circular: false + }, + startAngle: 0, + ticks: { + showLabelBackdrop: true, + callback: _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aL.formatters.numeric + }, + pointLabels: { + backdropColor: undefined, + backdropPadding: 2, + display: true, + font: { + size: 10 + }, + callback (label) { + return label; + }, + padding: 5, + centerPointLabels: false + } + }; + static defaultRoutes = { + 'angleLines.color': 'borderColor', + 'pointLabels.color': 'color', + 'ticks.color': 'color' + }; + static descriptors = { + angleLines: { + _fallback: 'grid' + } + }; + constructor(cfg){ + super(cfg); + this.xCenter = undefined; + this.yCenter = undefined; + this.drawingArea = undefined; + this._pointLabels = []; + this._pointLabelItems = []; + } + setDimensions() { + const padding = this._padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(getTickBackdropHeight(this.options) / 2); + const w = this.width = this.maxWidth - padding.width; + const h = this.height = this.maxHeight - padding.height; + this.xCenter = Math.floor(this.left + w / 2 + padding.left); + this.yCenter = Math.floor(this.top + h / 2 + padding.top); + this.drawingArea = Math.floor(Math.min(w, h) / 2); + } + determineDataLimits() { + const { min , max } = this.getMinMax(false); + this.min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : 0; + this.max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : 0; + this.handleTickRangeOptions(); + } + computeTickLimit() { + return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); + } + generateTickLabels(ticks) { + LinearScaleBase.prototype.generateTickLabels.call(this, ticks); + this._pointLabels = this.getLabels().map((value, index)=>{ + const label = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(this.options.pointLabels.callback, [ + value, + index + ], this); + return label || label === 0 ? label : ''; + }).filter((v, i)=>this.chart.getDataVisibility(i)); + } + fit() { + const opts = this.options; + if (opts.display && opts.pointLabels.display) { + fitWithPointLabels(this); + } else { + this.setCenterPoint(0, 0, 0, 0); + } + } + setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) { + this.xCenter += Math.floor((leftMovement - rightMovement) / 2); + this.yCenter += Math.floor((topMovement - bottomMovement) / 2); + this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement)); + } + getIndexAngle(index) { + const angleMultiplier = _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.T / (this._pointLabels.length || 1); + const startAngle = this.options.startAngle || 0; + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ay)(index * angleMultiplier + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(startAngle)); + } + getDistanceFromCenterForValue(value) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(value)) { + return NaN; + } + const scalingFactor = this.drawingArea / (this.max - this.min); + if (this.options.reverse) { + return (this.max - value) * scalingFactor; + } + return (value - this.min) * scalingFactor; + } + getValueForDistanceFromCenter(distance) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(distance)) { + return NaN; + } + const scaledDistance = distance / (this.drawingArea / (this.max - this.min)); + return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance; + } + getPointLabelContext(index) { + const pointLabels = this._pointLabels || []; + if (index >= 0 && index < pointLabels.length) { + const pointLabel = pointLabels[index]; + return createPointLabelContext(this.getContext(), index, pointLabel); + } + } + getPointPosition(index, distanceFromCenter, additionalAngle = 0) { + const angle = this.getIndexAngle(index) - _chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.H + additionalAngle; + return { + x: Math.cos(angle) * distanceFromCenter + this.xCenter, + y: Math.sin(angle) * distanceFromCenter + this.yCenter, + angle + }; + } + getPointPositionForValue(index, value) { + return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); + } + getBasePosition(index) { + return this.getPointPositionForValue(index || 0, this.getBaseValue()); + } + getPointLabelPosition(index) { + const { left , top , right , bottom } = this._pointLabelItems[index]; + return { + left, + top, + right, + bottom + }; + } + drawBackground() { + const { backgroundColor , grid: { circular } } = this.options; + if (backgroundColor) { + const ctx = this.ctx; + ctx.save(); + ctx.beginPath(); + pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length); + ctx.closePath(); + ctx.fillStyle = backgroundColor; + ctx.fill(); + ctx.restore(); + } + } + drawGrid() { + const ctx = this.ctx; + const opts = this.options; + const { angleLines , grid , border } = opts; + const labelCount = this._pointLabels.length; + let i, offset, position; + if (opts.pointLabels.display) { + drawPointLabels(this, labelCount); + } + if (grid.display) { + this.ticks.forEach((tick, index)=>{ + if (index !== 0) { + offset = this.getDistanceFromCenterForValue(tick.value); + const context = this.getContext(index); + const optsAtIndex = grid.setContext(context); + const optsAtIndexBorder = border.setContext(context); + drawRadiusLine(this, optsAtIndex, offset, labelCount, optsAtIndexBorder); + } + }); + } + if (angleLines.display) { + ctx.save(); + for(i = labelCount - 1; i >= 0; i--){ + const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i)); + const { color , lineWidth } = optsAtIndex; + if (!lineWidth || !color) { + continue; + } + ctx.lineWidth = lineWidth; + ctx.strokeStyle = color; + ctx.setLineDash(optsAtIndex.borderDash); + ctx.lineDashOffset = optsAtIndex.borderDashOffset; + offset = this.getDistanceFromCenterForValue(opts.ticks.reverse ? this.min : this.max); + position = this.getPointPosition(i, offset); + ctx.beginPath(); + ctx.moveTo(this.xCenter, this.yCenter); + ctx.lineTo(position.x, position.y); + ctx.stroke(); + } + ctx.restore(); + } + } + drawBorder() {} + drawLabels() { + const ctx = this.ctx; + const opts = this.options; + const tickOpts = opts.ticks; + if (!tickOpts.display) { + return; + } + const startAngle = this.getIndexAngle(0); + let offset, width; + ctx.save(); + ctx.translate(this.xCenter, this.yCenter); + ctx.rotate(startAngle); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + this.ticks.forEach((tick, index)=>{ + if (index === 0 && !opts.reverse) { + return; + } + const optsAtIndex = tickOpts.setContext(this.getContext(index)); + const tickFont = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.a0)(optsAtIndex.font); + offset = this.getDistanceFromCenterForValue(this.ticks[index].value); + if (optsAtIndex.showLabelBackdrop) { + ctx.font = tickFont.string; + width = ctx.measureText(tick.label).width; + ctx.fillStyle = optsAtIndex.backdropColor; + const padding = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.E)(optsAtIndex.backdropPadding); + ctx.fillRect(-width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height); + } + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ctx, tick.label, 0, -offset, tickFont, { + color: optsAtIndex.color + }); + }); + ctx.restore(); + } + drawTitle() {} +} + +const INTERVALS = { + millisecond: { + common: true, + size: 1, + steps: 1000 + }, + second: { + common: true, + size: 1000, + steps: 60 + }, + minute: { + common: true, + size: 60000, + steps: 60 + }, + hour: { + common: true, + size: 3600000, + steps: 24 + }, + day: { + common: true, + size: 86400000, + steps: 30 + }, + week: { + common: false, + size: 604800000, + steps: 4 + }, + month: { + common: true, + size: 2.628e9, + steps: 12 + }, + quarter: { + common: false, + size: 7.884e9, + steps: 4 + }, + year: { + common: true, + size: 3.154e10 + } +}; + const UNITS = /* #__PURE__ */ Object.keys(INTERVALS); + function sorter(a, b) { + return a - b; +} + function parse(scale, input) { + if ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.k)(input)) { + return null; + } + const adapter = scale._adapter; + const { parser , round , isoWeekday } = scale._parseOpts; + let value = input; + if (typeof parser === 'function') { + value = parser(value); + } + if (!(0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(value)) { + value = typeof parser === 'string' ? adapter.parse(value, parser) : adapter.parse(value); + } + if (value === null) { + return null; + } + if (round) { + value = round === 'week' && ((0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, 'isoWeek', isoWeekday) : adapter.startOf(value, round); + } + return +value; +} + function determineUnitForAutoTicks(minUnit, min, max, capacity) { + const ilen = UNITS.length; + for(let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i){ + const interval = INTERVALS[UNITS[i]]; + const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER; + if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) { + return UNITS[i]; + } + } + return UNITS[ilen - 1]; +} + function determineUnitForFormatting(scale, numTicks, minUnit, min, max) { + for(let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--){ + const unit = UNITS[i]; + if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) { + return unit; + } + } + return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0]; +} + function determineMajorUnit(unit) { + for(let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i){ + if (INTERVALS[UNITS[i]].common) { + return UNITS[i]; + } + } +} + function addTick(ticks, time, timestamps) { + if (!timestamps) { + ticks[time] = true; + } else if (timestamps.length) { + const { lo , hi } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aP)(timestamps, time); + const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi]; + ticks[timestamp] = true; + } +} + function setMajorTicks(scale, ticks, map, majorUnit) { + const adapter = scale._adapter; + const first = +adapter.startOf(ticks[0].value, majorUnit); + const last = ticks[ticks.length - 1].value; + let major, index; + for(major = first; major <= last; major = +adapter.add(major, 1, majorUnit)){ + index = map[major]; + if (index >= 0) { + ticks[index].major = true; + } + } + return ticks; +} + function ticksFromTimestamps(scale, values, majorUnit) { + const ticks = []; + const map = {}; + const ilen = values.length; + let i, value; + for(i = 0; i < ilen; ++i){ + value = values[i]; + map[value] = i; + ticks.push({ + value, + major: false + }); + } + return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map, majorUnit); +} +class TimeScale extends Scale { + static id = 'time'; + static defaults = { + bounds: 'data', + adapters: {}, + time: { + parser: false, + unit: false, + round: false, + isoWeekday: false, + minUnit: 'millisecond', + displayFormats: {} + }, + ticks: { + source: 'auto', + callback: false, + major: { + enabled: false + } + } + }; + constructor(props){ + super(props); + this._cache = { + data: [], + labels: [], + all: [] + }; + this._unit = 'day'; + this._majorUnit = undefined; + this._offsets = {}; + this._normalized = false; + this._parseOpts = undefined; + } + init(scaleOpts, opts = {}) { + const time = scaleOpts.time || (scaleOpts.time = {}); + const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date); + adapter.init(opts); + (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.ab)(time.displayFormats, adapter.formats()); + this._parseOpts = { + parser: time.parser, + round: time.round, + isoWeekday: time.isoWeekday + }; + super.init(scaleOpts); + this._normalized = opts.normalized; + } + parse(raw, index) { + if (raw === undefined) { + return null; + } + return parse(this, raw); + } + beforeLayout() { + super.beforeLayout(); + this._cache = { + data: [], + labels: [], + all: [] + }; + } + determineDataLimits() { + const options = this.options; + const adapter = this._adapter; + const unit = options.time.unit || 'day'; + let { min , max , minDefined , maxDefined } = this.getUserBounds(); + function _applyBounds(bounds) { + if (!minDefined && !isNaN(bounds.min)) { + min = Math.min(min, bounds.min); + } + if (!maxDefined && !isNaN(bounds.max)) { + max = Math.max(max, bounds.max); + } + } + if (!minDefined || !maxDefined) { + _applyBounds(this._getLabelBounds()); + if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') { + _applyBounds(this.getMinMax(false)); + } + } + min = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit); + max = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.g)(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1; + this.min = Math.min(min, max - 1); + this.max = Math.max(min + 1, max); + } + _getLabelBounds() { + const arr = this.getLabelTimestamps(); + let min = Number.POSITIVE_INFINITY; + let max = Number.NEGATIVE_INFINITY; + if (arr.length) { + min = arr[0]; + max = arr[arr.length - 1]; + } + return { + min, + max + }; + } + buildTicks() { + const options = this.options; + const timeOpts = options.time; + const tickOpts = options.ticks; + const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate(); + if (options.bounds === 'ticks' && timestamps.length) { + this.min = this._userMin || timestamps[0]; + this.max = this._userMax || timestamps[timestamps.length - 1]; + } + const min = this.min; + const max = this.max; + const ticks = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.aO)(timestamps, min, max); + this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max)); + this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined : determineMajorUnit(this._unit); + this.initOffsets(timestamps); + if (options.reverse) { + ticks.reverse(); + } + return ticksFromTimestamps(this, ticks, this._majorUnit); + } + afterAutoSkip() { + if (this.options.offsetAfterAutoskip) { + this.initOffsets(this.ticks.map((tick)=>+tick.value)); + } + } + initOffsets(timestamps = []) { + let start = 0; + let end = 0; + let first, last; + if (this.options.offset && timestamps.length) { + first = this.getDecimalForValue(timestamps[0]); + if (timestamps.length === 1) { + start = 1 - first; + } else { + start = (this.getDecimalForValue(timestamps[1]) - first) / 2; + } + last = this.getDecimalForValue(timestamps[timestamps.length - 1]); + if (timestamps.length === 1) { + end = last; + } else { + end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2; + } + } + const limit = timestamps.length < 3 ? 0.5 : 0.25; + start = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(start, 0, limit); + end = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.S)(end, 0, limit); + this._offsets = { + start, + end, + factor: 1 / (start + 1 + end) + }; + } + _generate() { + const adapter = this._adapter; + const min = this.min; + const max = this.max; + const options = this.options; + const timeOpts = options.time; + const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min)); + const stepSize = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.v)(options.ticks.stepSize, 1); + const weekday = minor === 'week' ? timeOpts.isoWeekday : false; + const hasWeekday = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.x)(weekday) || weekday === true; + const ticks = {}; + let first = min; + let time, count; + if (hasWeekday) { + first = +adapter.startOf(first, 'isoWeek', weekday); + } + first = +adapter.startOf(first, hasWeekday ? 'day' : minor); + if (adapter.diff(max, min, minor) > 100000 * stepSize) { + throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor); + } + const timestamps = options.ticks.source === 'data' && this.getDataTimestamps(); + for(time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++){ + addTick(ticks, time, timestamps); + } + if (time === max || options.bounds === 'ticks' || count === 1) { + addTick(ticks, time, timestamps); + } + return Object.keys(ticks).sort((a, b)=>a - b).map((x)=>+x); + } + getLabelForValue(value) { + const adapter = this._adapter; + const timeOpts = this.options.time; + if (timeOpts.tooltipFormat) { + return adapter.format(value, timeOpts.tooltipFormat); + } + return adapter.format(value, timeOpts.displayFormats.datetime); + } + format(value, format) { + const options = this.options; + const formats = options.time.displayFormats; + const unit = this._unit; + const fmt = format || formats[unit]; + return this._adapter.format(value, fmt); + } + _tickFormatFunction(time, index, ticks, format) { + const options = this.options; + const formatter = options.ticks.callback; + if (formatter) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.Q)(formatter, [ + time, + index, + ticks + ], this); + } + const formats = options.time.displayFormats; + const unit = this._unit; + const majorUnit = this._majorUnit; + const minorFormat = unit && formats[unit]; + const majorFormat = majorUnit && formats[majorUnit]; + const tick = ticks[index]; + const major = majorUnit && majorFormat && tick && tick.major; + return this._adapter.format(time, format || (major ? majorFormat : minorFormat)); + } + generateTickLabels(ticks) { + let i, ilen, tick; + for(i = 0, ilen = ticks.length; i < ilen; ++i){ + tick = ticks[i]; + tick.label = this._tickFormatFunction(tick.value, i, ticks); + } + } + getDecimalForValue(value) { + return value === null ? NaN : (value - this.min) / (this.max - this.min); + } + getPixelForValue(value) { + const offsets = this._offsets; + const pos = this.getDecimalForValue(value); + return this.getPixelForDecimal((offsets.start + pos) * offsets.factor); + } + getValueForPixel(pixel) { + const offsets = this._offsets; + const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end; + return this.min + pos * (this.max - this.min); + } + _getLabelSize(label) { + const ticksOpts = this.options.ticks; + const tickLabelWidth = this.ctx.measureText(label).width; + const angle = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.t)(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation); + const cosRotation = Math.cos(angle); + const sinRotation = Math.sin(angle); + const tickFontSize = this._resolveTickFontOptions(0).size; + return { + w: tickLabelWidth * cosRotation + tickFontSize * sinRotation, + h: tickLabelWidth * sinRotation + tickFontSize * cosRotation + }; + } + _getLabelCapacity(exampleTime) { + const timeOpts = this.options.time; + const displayFormats = timeOpts.displayFormats; + const format = displayFormats[timeOpts.unit] || displayFormats.millisecond; + const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [ + exampleTime + ], this._majorUnit), format); + const size = this._getLabelSize(exampleLabel); + const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1; + return capacity > 0 ? capacity : 1; + } + getDataTimestamps() { + let timestamps = this._cache.data || []; + let i, ilen; + if (timestamps.length) { + return timestamps; + } + const metas = this.getMatchingVisibleMetas(); + if (this._normalized && metas.length) { + return this._cache.data = metas[0].controller.getAllParsedValues(this); + } + for(i = 0, ilen = metas.length; i < ilen; ++i){ + timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this)); + } + return this._cache.data = this.normalize(timestamps); + } + getLabelTimestamps() { + const timestamps = this._cache.labels || []; + let i, ilen; + if (timestamps.length) { + return timestamps; + } + const labels = this.getLabels(); + for(i = 0, ilen = labels.length; i < ilen; ++i){ + timestamps.push(parse(this, labels[i])); + } + return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps); + } + normalize(values) { + return (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__._)(values.sort(sorter)); + } +} + +function interpolate(table, val, reverse) { + let lo = 0; + let hi = table.length - 1; + let prevSource, nextSource, prevTarget, nextTarget; + if (reverse) { + if (val >= table[lo].pos && val <= table[hi].pos) { + ({ lo , hi } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'pos', val)); + } + ({ pos: prevSource , time: prevTarget } = table[lo]); + ({ pos: nextSource , time: nextTarget } = table[hi]); + } else { + if (val >= table[lo].time && val <= table[hi].time) { + ({ lo , hi } = (0,_chunks_helpers_segment_js__WEBPACK_IMPORTED_MODULE_0__.B)(table, 'time', val)); + } + ({ time: prevSource , pos: prevTarget } = table[lo]); + ({ time: nextSource , pos: nextTarget } = table[hi]); + } + const span = nextSource - prevSource; + return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget; +} +class TimeSeriesScale extends TimeScale { + static id = 'timeseries'; + static defaults = TimeScale.defaults; + constructor(props){ + super(props); + this._table = []; + this._minPos = undefined; + this._tableRange = undefined; + } + initOffsets() { + const timestamps = this._getTimestampsForTable(); + const table = this._table = this.buildLookupTable(timestamps); + this._minPos = interpolate(table, this.min); + this._tableRange = interpolate(table, this.max) - this._minPos; + super.initOffsets(timestamps); + } + buildLookupTable(timestamps) { + const { min , max } = this; + const items = []; + const table = []; + let i, ilen, prev, curr, next; + for(i = 0, ilen = timestamps.length; i < ilen; ++i){ + curr = timestamps[i]; + if (curr >= min && curr <= max) { + items.push(curr); + } + } + if (items.length < 2) { + return [ + { + time: min, + pos: 0 + }, + { + time: max, + pos: 1 + } + ]; + } + for(i = 0, ilen = items.length; i < ilen; ++i){ + next = items[i + 1]; + prev = items[i - 1]; + curr = items[i]; + if (Math.round((next + prev) / 2) !== curr) { + table.push({ + time: curr, + pos: i / (ilen - 1) + }); + } + } + return table; + } + _getTimestampsForTable() { + let timestamps = this._cache.all || []; + if (timestamps.length) { + return timestamps; + } + const data = this.getDataTimestamps(); + const label = this.getLabelTimestamps(); + if (data.length && label.length) { + timestamps = this.normalize(data.concat(label)); + } else { + timestamps = data.length ? data : label; + } + timestamps = this._cache.all = timestamps; + return timestamps; + } + getDecimalForValue(value) { + return (interpolate(this._table, value) - this._minPos) / this._tableRange; + } + getValueForPixel(pixel) { + const offsets = this._offsets; + const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end; + return interpolate(this._table, decimal * this._tableRange + this._minPos, true); + } +} + +var scales = /*#__PURE__*/Object.freeze({ +__proto__: null, +CategoryScale: CategoryScale, +LinearScale: LinearScale, +LogarithmicScale: LogarithmicScale, +RadialLinearScale: RadialLinearScale, +TimeScale: TimeScale, +TimeSeriesScale: TimeSeriesScale +}); + +const registerables = [ + controllers, + elements, + plugins, + scales +]; + + +//# sourceMappingURL=chart.js.map + + +/***/ }), + +/***/ "./node_modules/chart.js/dist/chunks/helpers.segment.js": +/*!**************************************************************!*\ + !*** ./node_modules/chart.js/dist/chunks/helpers.segment.js ***! + \**************************************************************/ +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "$": () => (/* binding */ unclipArea), +/* harmony export */ "A": () => (/* binding */ _rlookupByKey), +/* harmony export */ "B": () => (/* binding */ _lookupByKey), +/* harmony export */ "C": () => (/* binding */ _isPointInArea), +/* harmony export */ "D": () => (/* binding */ getAngleFromPoint), +/* harmony export */ "E": () => (/* binding */ toPadding), +/* harmony export */ "F": () => (/* binding */ each), +/* harmony export */ "G": () => (/* binding */ getMaximumSize), +/* harmony export */ "H": () => (/* binding */ HALF_PI), +/* harmony export */ "I": () => (/* binding */ _getParentNode), +/* harmony export */ "J": () => (/* binding */ readUsedSize), +/* harmony export */ "K": () => (/* binding */ supportsEventListenerOptions), +/* harmony export */ "L": () => (/* binding */ throttled), +/* harmony export */ "M": () => (/* binding */ _isDomSupported), +/* harmony export */ "N": () => (/* binding */ _factorize), +/* harmony export */ "O": () => (/* binding */ finiteOrDefault), +/* harmony export */ "P": () => (/* binding */ PI), +/* harmony export */ "Q": () => (/* binding */ callback), +/* harmony export */ "R": () => (/* binding */ _addGrace), +/* harmony export */ "S": () => (/* binding */ _limitValue), +/* harmony export */ "T": () => (/* binding */ TAU), +/* harmony export */ "U": () => (/* binding */ toDegrees), +/* harmony export */ "V": () => (/* binding */ _measureText), +/* harmony export */ "W": () => (/* binding */ _int16Range), +/* harmony export */ "X": () => (/* binding */ _alignPixel), +/* harmony export */ "Y": () => (/* binding */ clipArea), +/* harmony export */ "Z": () => (/* binding */ renderText), +/* harmony export */ "_": () => (/* binding */ _arrayUnique), +/* harmony export */ "a": () => (/* binding */ resolve), +/* harmony export */ "a$": () => (/* binding */ fontString), +/* harmony export */ "a0": () => (/* binding */ toFont), +/* harmony export */ "a1": () => (/* binding */ _toLeftRightCenter), +/* harmony export */ "a2": () => (/* binding */ _alignStartEnd), +/* harmony export */ "a3": () => (/* binding */ overrides), +/* harmony export */ "a4": () => (/* binding */ merge), +/* harmony export */ "a5": () => (/* binding */ _capitalize), +/* harmony export */ "a6": () => (/* binding */ descriptors), +/* harmony export */ "a7": () => (/* binding */ isFunction), +/* harmony export */ "a8": () => (/* binding */ _attachContext), +/* harmony export */ "a9": () => (/* binding */ _createResolver), +/* harmony export */ "aA": () => (/* binding */ overrideTextDirection), +/* harmony export */ "aB": () => (/* binding */ _textX), +/* harmony export */ "aC": () => (/* binding */ restoreTextDirection), +/* harmony export */ "aD": () => (/* binding */ drawPointLegend), +/* harmony export */ "aE": () => (/* binding */ distanceBetweenPoints), +/* harmony export */ "aF": () => (/* binding */ noop), +/* harmony export */ "aG": () => (/* binding */ _setMinAndMaxByKey), +/* harmony export */ "aH": () => (/* binding */ niceNum), +/* harmony export */ "aI": () => (/* binding */ almostWhole), +/* harmony export */ "aJ": () => (/* binding */ almostEquals), +/* harmony export */ "aK": () => (/* binding */ _decimalPlaces), +/* harmony export */ "aL": () => (/* binding */ Ticks), +/* harmony export */ "aM": () => (/* binding */ log10), +/* harmony export */ "aN": () => (/* binding */ _longestText), +/* harmony export */ "aO": () => (/* binding */ _filterBetween), +/* harmony export */ "aP": () => (/* binding */ _lookup), +/* harmony export */ "aQ": () => (/* binding */ isPatternOrGradient), +/* harmony export */ "aR": () => (/* binding */ getHoverColor), +/* harmony export */ "aS": () => (/* binding */ clone), +/* harmony export */ "aT": () => (/* binding */ _merger), +/* harmony export */ "aU": () => (/* binding */ _mergerIf), +/* harmony export */ "aV": () => (/* binding */ _deprecated), +/* harmony export */ "aW": () => (/* binding */ _splitKey), +/* harmony export */ "aX": () => (/* binding */ toFontString), +/* harmony export */ "aY": () => (/* binding */ splineCurve), +/* harmony export */ "aZ": () => (/* binding */ splineCurveMonotone), +/* harmony export */ "a_": () => (/* binding */ getStyle), +/* harmony export */ "aa": () => (/* binding */ _descriptors), +/* harmony export */ "ab": () => (/* binding */ mergeIf), +/* harmony export */ "ac": () => (/* binding */ uid), +/* harmony export */ "ad": () => (/* binding */ debounce), +/* harmony export */ "ae": () => (/* binding */ retinaScale), +/* harmony export */ "af": () => (/* binding */ clearCanvas), +/* harmony export */ "ag": () => (/* binding */ setsEqual), +/* harmony export */ "ah": () => (/* binding */ _elementsEqual), +/* harmony export */ "ai": () => (/* binding */ _isClickEvent), +/* harmony export */ "aj": () => (/* binding */ _isBetween), +/* harmony export */ "ak": () => (/* binding */ _readValueToProps), +/* harmony export */ "al": () => (/* binding */ _updateBezierControlPoints), +/* harmony export */ "am": () => (/* binding */ _computeSegments), +/* harmony export */ "an": () => (/* binding */ _boundSegments), +/* harmony export */ "ao": () => (/* binding */ _steppedInterpolation), +/* harmony export */ "ap": () => (/* binding */ _bezierInterpolation), +/* harmony export */ "aq": () => (/* binding */ _pointInLine), +/* harmony export */ "ar": () => (/* binding */ _steppedLineTo), +/* harmony export */ "as": () => (/* binding */ _bezierCurveTo), +/* harmony export */ "at": () => (/* binding */ drawPoint), +/* harmony export */ "au": () => (/* binding */ addRoundedRectPath), +/* harmony export */ "av": () => (/* binding */ toTRBL), +/* harmony export */ "aw": () => (/* binding */ toTRBLCorners), +/* harmony export */ "ax": () => (/* binding */ _boundSegment), +/* harmony export */ "ay": () => (/* binding */ _normalizeAngle), +/* harmony export */ "az": () => (/* binding */ getRtlAdapter), +/* harmony export */ "b": () => (/* binding */ isArray), +/* harmony export */ "b0": () => (/* binding */ toLineHeight), +/* harmony export */ "b1": () => (/* binding */ PITAU), +/* harmony export */ "b2": () => (/* binding */ INFINITY), +/* harmony export */ "b3": () => (/* binding */ RAD_PER_DEG), +/* harmony export */ "b4": () => (/* binding */ QUARTER_PI), +/* harmony export */ "b5": () => (/* binding */ TWO_THIRDS_PI), +/* harmony export */ "b6": () => (/* binding */ _angleDiff), +/* harmony export */ "c": () => (/* binding */ color), +/* harmony export */ "d": () => (/* binding */ defaults), +/* harmony export */ "e": () => (/* binding */ effects), +/* harmony export */ "f": () => (/* binding */ resolveObjectKey), +/* harmony export */ "g": () => (/* binding */ isNumberFinite), +/* harmony export */ "h": () => (/* binding */ defined), +/* harmony export */ "i": () => (/* binding */ isObject), +/* harmony export */ "j": () => (/* binding */ createContext), +/* harmony export */ "k": () => (/* binding */ isNullOrUndef), +/* harmony export */ "l": () => (/* binding */ listenArrayEvents), +/* harmony export */ "m": () => (/* binding */ toPercentage), +/* harmony export */ "n": () => (/* binding */ toDimension), +/* harmony export */ "o": () => (/* binding */ formatNumber), +/* harmony export */ "p": () => (/* binding */ _angleBetween), +/* harmony export */ "q": () => (/* binding */ _getStartAndCountOfVisiblePoints), +/* harmony export */ "r": () => (/* binding */ requestAnimFrame), +/* harmony export */ "s": () => (/* binding */ sign), +/* harmony export */ "t": () => (/* binding */ toRadians), +/* harmony export */ "u": () => (/* binding */ unlistenArrayEvents), +/* harmony export */ "v": () => (/* binding */ valueOrDefault), +/* harmony export */ "w": () => (/* binding */ _scaleRangesChanged), +/* harmony export */ "x": () => (/* binding */ isNumber), +/* harmony export */ "y": () => (/* binding */ _parseObjectDataRadialScale), +/* harmony export */ "z": () => (/* binding */ getRelativePosition) +/* harmony export */ }); +/* harmony import */ var _kurkle_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kurkle/color */ "./node_modules/@kurkle/color/dist/color.esm.js"); +/*! + * Chart.js v4.3.0 + * https://www.chartjs.org + * (c) 2023 Chart.js Contributors + * Released under the MIT License + */ + + +/** + * @namespace Chart.helpers + */ /** + * An empty function that can be used, for example, for optional callback. + */ function noop() { +/* noop */ } +/** + * Returns a unique id, sequentially generated from a global variable. + */ const uid = (()=>{ + let id = 0; + return ()=>id++; +})(); +/** + * Returns true if `value` is neither null nor undefined, else returns false. + * @param value - The value to test. + * @since 2.7.0 + */ function isNullOrUndef(value) { + return value === null || typeof value === 'undefined'; +} +/** + * Returns true if `value` is an array (including typed arrays), else returns false. + * @param value - The value to test. + * @function + */ function isArray(value) { + if (Array.isArray && Array.isArray(value)) { + return true; + } + const type = Object.prototype.toString.call(value); + if (type.slice(0, 7) === '[object' && type.slice(-6) === 'Array]') { + return true; + } + return false; +} +/** + * Returns true if `value` is an object (excluding null), else returns false. + * @param value - The value to test. + * @since 2.7.0 + */ function isObject(value) { + return value !== null && Object.prototype.toString.call(value) === '[object Object]'; +} +/** + * Returns true if `value` is a finite number, else returns false + * @param value - The value to test. + */ function isNumberFinite(value) { + return (typeof value === 'number' || value instanceof Number) && isFinite(+value); +} +/** + * Returns `value` if finite, else returns `defaultValue`. + * @param value - The value to return if defined. + * @param defaultValue - The value to return if `value` is not finite. + */ function finiteOrDefault(value, defaultValue) { + return isNumberFinite(value) ? value : defaultValue; +} +/** + * Returns `value` if defined, else returns `defaultValue`. + * @param value - The value to return if defined. + * @param defaultValue - The value to return if `value` is undefined. + */ function valueOrDefault(value, defaultValue) { + return typeof value === 'undefined' ? defaultValue : value; +} +const toPercentage = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 : +value / dimension; +const toDimension = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 * dimension : +value; +/** + * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the + * value returned by `fn`. If `fn` is not a function, this method returns undefined. + * @param fn - The function to call. + * @param args - The arguments with which `fn` should be called. + * @param [thisArg] - The value of `this` provided for the call to `fn`. + */ function callback(fn, args, thisArg) { + if (fn && typeof fn.call === 'function') { + return fn.apply(thisArg, args); + } +} +function each(loopable, fn, thisArg, reverse) { + let i, len, keys; + if (isArray(loopable)) { + len = loopable.length; + if (reverse) { + for(i = len - 1; i >= 0; i--){ + fn.call(thisArg, loopable[i], i); + } + } else { + for(i = 0; i < len; i++){ + fn.call(thisArg, loopable[i], i); + } + } + } else if (isObject(loopable)) { + keys = Object.keys(loopable); + len = keys.length; + for(i = 0; i < len; i++){ + fn.call(thisArg, loopable[keys[i]], keys[i]); + } + } +} +/** + * Returns true if the `a0` and `a1` arrays have the same content, else returns false. + * @param a0 - The array to compare + * @param a1 - The array to compare + * @private + */ function _elementsEqual(a0, a1) { + let i, ilen, v0, v1; + if (!a0 || !a1 || a0.length !== a1.length) { + return false; + } + for(i = 0, ilen = a0.length; i < ilen; ++i){ + v0 = a0[i]; + v1 = a1[i]; + if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) { + return false; + } + } + return true; +} +/** + * Returns a deep copy of `source` without keeping references on objects and arrays. + * @param source - The value to clone. + */ function clone(source) { + if (isArray(source)) { + return source.map(clone); + } + if (isObject(source)) { + const target = Object.create(null); + const keys = Object.keys(source); + const klen = keys.length; + let k = 0; + for(; k < klen; ++k){ + target[keys[k]] = clone(source[keys[k]]); + } + return target; + } + return source; +} +function isValidKey(key) { + return [ + '__proto__', + 'prototype', + 'constructor' + ].indexOf(key) === -1; +} +/** + * The default merger when Chart.helpers.merge is called without merger option. + * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback. + * @private + */ function _merger(key, target, source, options) { + if (!isValidKey(key)) { + return; + } + const tval = target[key]; + const sval = source[key]; + if (isObject(tval) && isObject(sval)) { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + merge(tval, sval, options); + } else { + target[key] = clone(sval); + } +} +function merge(target, source, options) { + const sources = isArray(source) ? source : [ + source + ]; + const ilen = sources.length; + if (!isObject(target)) { + return target; + } + options = options || {}; + const merger = options.merger || _merger; + let current; + for(let i = 0; i < ilen; ++i){ + current = sources[i]; + if (!isObject(current)) { + continue; + } + const keys = Object.keys(current); + for(let k = 0, klen = keys.length; k < klen; ++k){ + merger(keys[k], target, current, options); + } + } + return target; +} +function mergeIf(target, source) { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + return merge(target, source, { + merger: _mergerIf + }); +} +/** + * Merges source[key] in target[key] only if target[key] is undefined. + * @private + */ function _mergerIf(key, target, source) { + if (!isValidKey(key)) { + return; + } + const tval = target[key]; + const sval = source[key]; + if (isObject(tval) && isObject(sval)) { + mergeIf(tval, sval); + } else if (!Object.prototype.hasOwnProperty.call(target, key)) { + target[key] = clone(sval); + } +} +/** + * @private + */ function _deprecated(scope, value, previous, current) { + if (value !== undefined) { + console.warn(scope + ': "' + previous + '" is deprecated. Please use "' + current + '" instead'); + } +} +// resolveObjectKey resolver cache +const keyResolvers = { + // Chart.helpers.core resolveObjectKey should resolve empty key to root object + '': (v)=>v, + // default resolvers + x: (o)=>o.x, + y: (o)=>o.y +}; +/** + * @private + */ function _splitKey(key) { + const parts = key.split('.'); + const keys = []; + let tmp = ''; + for (const part of parts){ + tmp += part; + if (tmp.endsWith('\\')) { + tmp = tmp.slice(0, -1) + '.'; + } else { + keys.push(tmp); + tmp = ''; + } + } + return keys; +} +function _getKeyResolver(key) { + const keys = _splitKey(key); + return (obj)=>{ + for (const k of keys){ + if (k === '') { + break; + } + obj = obj && obj[k]; + } + return obj; + }; +} +function resolveObjectKey(obj, key) { + const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key)); + return resolver(obj); +} +/** + * @private + */ function _capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} +const defined = (value)=>typeof value !== 'undefined'; +const isFunction = (value)=>typeof value === 'function'; +// Adapted from https://stackoverflow.com/questions/31128855/comparing-ecma6-sets-for-equality#31129384 +const setsEqual = (a, b)=>{ + if (a.size !== b.size) { + return false; + } + for (const item of a){ + if (!b.has(item)) { + return false; + } + } + return true; +}; +/** + * @param e - The event + * @private + */ function _isClickEvent(e) { + return e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu'; +} + +/** + * @alias Chart.helpers.math + * @namespace + */ const PI = Math.PI; +const TAU = 2 * PI; +const PITAU = TAU + PI; +const INFINITY = Number.POSITIVE_INFINITY; +const RAD_PER_DEG = PI / 180; +const HALF_PI = PI / 2; +const QUARTER_PI = PI / 4; +const TWO_THIRDS_PI = PI * 2 / 3; +const log10 = Math.log10; +const sign = Math.sign; +function almostEquals(x, y, epsilon) { + return Math.abs(x - y) < epsilon; +} +/** + * Implementation of the nice number algorithm used in determining where axis labels will go + */ function niceNum(range) { + const roundedRange = Math.round(range); + range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range; + const niceRange = Math.pow(10, Math.floor(log10(range))); + const fraction = range / niceRange; + const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10; + return niceFraction * niceRange; +} +/** + * Returns an array of factors sorted from 1 to sqrt(value) + * @private + */ function _factorize(value) { + const result = []; + const sqrt = Math.sqrt(value); + let i; + for(i = 1; i < sqrt; i++){ + if (value % i === 0) { + result.push(i); + result.push(value / i); + } + } + if (sqrt === (sqrt | 0)) { + result.push(sqrt); + } + result.sort((a, b)=>a - b).pop(); + return result; +} +function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} +function almostWhole(x, epsilon) { + const rounded = Math.round(x); + return rounded - epsilon <= x && rounded + epsilon >= x; +} +/** + * @private + */ function _setMinAndMaxByKey(array, target, property) { + let i, ilen, value; + for(i = 0, ilen = array.length; i < ilen; i++){ + value = array[i][property]; + if (!isNaN(value)) { + target.min = Math.min(target.min, value); + target.max = Math.max(target.max, value); + } + } +} +function toRadians(degrees) { + return degrees * (PI / 180); +} +function toDegrees(radians) { + return radians * (180 / PI); +} +/** + * Returns the number of decimal places + * i.e. the number of digits after the decimal point, of the value of this Number. + * @param x - A number. + * @returns The number of decimal places. + * @private + */ function _decimalPlaces(x) { + if (!isNumberFinite(x)) { + return; + } + let e = 1; + let p = 0; + while(Math.round(x * e) / e !== x){ + e *= 10; + p++; + } + return p; +} +// Gets the angle from vertical upright to the point about a centre. +function getAngleFromPoint(centrePoint, anglePoint) { + const distanceFromXCenter = anglePoint.x - centrePoint.x; + const distanceFromYCenter = anglePoint.y - centrePoint.y; + const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); + let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); + if (angle < -0.5 * PI) { + angle += TAU; // make sure the returned angle is in the range of (-PI/2, 3PI/2] + } + return { + angle, + distance: radialDistanceFromCenter + }; +} +function distanceBetweenPoints(pt1, pt2) { + return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); +} +/** + * Shortest distance between angles, in either direction. + * @private + */ function _angleDiff(a, b) { + return (a - b + PITAU) % TAU - PI; +} +/** + * Normalize angle to be between 0 and 2*PI + * @private + */ function _normalizeAngle(a) { + return (a % TAU + TAU) % TAU; +} +/** + * @private + */ function _angleBetween(angle, start, end, sameAngleIsFullCircle) { + const a = _normalizeAngle(angle); + const s = _normalizeAngle(start); + const e = _normalizeAngle(end); + const angleToStart = _normalizeAngle(s - a); + const angleToEnd = _normalizeAngle(e - a); + const startToAngle = _normalizeAngle(a - s); + const endToAngle = _normalizeAngle(a - e); + return a === s || a === e || sameAngleIsFullCircle && s === e || angleToStart > angleToEnd && startToAngle < endToAngle; +} +/** + * Limit `value` between `min` and `max` + * @param value + * @param min + * @param max + * @private + */ function _limitValue(value, min, max) { + return Math.max(min, Math.min(max, value)); +} +/** + * @param {number} value + * @private + */ function _int16Range(value) { + return _limitValue(value, -32768, 32767); +} +/** + * @param value + * @param start + * @param end + * @param [epsilon] + * @private + */ function _isBetween(value, start, end, epsilon = 1e-6) { + return value >= Math.min(start, end) - epsilon && value <= Math.max(start, end) + epsilon; +} + +function _lookup(table, value, cmp) { + cmp = cmp || ((index)=>table[index] < value); + let hi = table.length - 1; + let lo = 0; + let mid; + while(hi - lo > 1){ + mid = lo + hi >> 1; + if (cmp(mid)) { + lo = mid; + } else { + hi = mid; + } + } + return { + lo, + hi + }; +} +/** + * Binary search + * @param table - the table search. must be sorted! + * @param key - property name for the value in each entry + * @param value - value to find + * @param last - lookup last index + * @private + */ const _lookupByKey = (table, key, value, last)=>_lookup(table, value, last ? (index)=>{ + const ti = table[index][key]; + return ti < value || ti === value && table[index + 1][key] === value; + } : (index)=>table[index][key] < value); +/** + * Reverse binary search + * @param table - the table search. must be sorted! + * @param key - property name for the value in each entry + * @param value - value to find + * @private + */ const _rlookupByKey = (table, key, value)=>_lookup(table, value, (index)=>table[index][key] >= value); +/** + * Return subset of `values` between `min` and `max` inclusive. + * Values are assumed to be in sorted order. + * @param values - sorted array of values + * @param min - min value + * @param max - max value + */ function _filterBetween(values, min, max) { + let start = 0; + let end = values.length; + while(start < end && values[start] < min){ + start++; + } + while(end > start && values[end - 1] > max){ + end--; + } + return start > 0 || end < values.length ? values.slice(start, end) : values; +} +const arrayEvents = [ + 'push', + 'pop', + 'shift', + 'splice', + 'unshift' +]; +function listenArrayEvents(array, listener) { + if (array._chartjs) { + array._chartjs.listeners.push(listener); + return; + } + Object.defineProperty(array, '_chartjs', { + configurable: true, + enumerable: false, + value: { + listeners: [ + listener + ] + } + }); + arrayEvents.forEach((key)=>{ + const method = '_onData' + _capitalize(key); + const base = array[key]; + Object.defineProperty(array, key, { + configurable: true, + enumerable: false, + value (...args) { + const res = base.apply(this, args); + array._chartjs.listeners.forEach((object)=>{ + if (typeof object[method] === 'function') { + object[method](...args); + } + }); + return res; + } + }); + }); +} +function unlistenArrayEvents(array, listener) { + const stub = array._chartjs; + if (!stub) { + return; + } + const listeners = stub.listeners; + const index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + if (listeners.length > 0) { + return; + } + arrayEvents.forEach((key)=>{ + delete array[key]; + }); + delete array._chartjs; +} +/** + * @param items + */ function _arrayUnique(items) { + const set = new Set(items); + if (set.size === items.length) { + return items; + } + return Array.from(set); +} + +function fontString(pixelSize, fontStyle, fontFamily) { + return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; +} +/** +* Request animation polyfill +*/ const requestAnimFrame = function() { + if (typeof window === 'undefined') { + return function(callback) { + return callback(); + }; + } + return window.requestAnimationFrame; +}(); +/** + * Throttles calling `fn` once per animation frame + * Latest arguments are used on the actual call + */ function throttled(fn, thisArg) { + let argsToUse = []; + let ticking = false; + return function(...args) { + // Save the args for use later + argsToUse = args; + if (!ticking) { + ticking = true; + requestAnimFrame.call(window, ()=>{ + ticking = false; + fn.apply(thisArg, argsToUse); + }); + } + }; +} +/** + * Debounces calling `fn` for `delay` ms + */ function debounce(fn, delay) { + let timeout; + return function(...args) { + if (delay) { + clearTimeout(timeout); + timeout = setTimeout(fn, delay, args); + } else { + fn.apply(this, args); + } + return delay; + }; +} +/** + * Converts 'start' to 'left', 'end' to 'right' and others to 'center' + * @private + */ const _toLeftRightCenter = (align)=>align === 'start' ? 'left' : align === 'end' ? 'right' : 'center'; +/** + * Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center` + * @private + */ const _alignStartEnd = (align, start, end)=>align === 'start' ? start : align === 'end' ? end : (start + end) / 2; +/** + * Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left` + * @private + */ const _textX = (align, left, right, rtl)=>{ + const check = rtl ? 'left' : 'right'; + return align === check ? right : align === 'center' ? (left + right) / 2 : left; +}; +/** + * Return start and count of visible points. + * @private + */ function _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) { + const pointCount = points.length; + let start = 0; + let count = pointCount; + if (meta._sorted) { + const { iScale , _parsed } = meta; + const axis = iScale.axis; + const { min , max , minDefined , maxDefined } = iScale.getUserBounds(); + if (minDefined) { + start = _limitValue(Math.min(// @ts-expect-error Need to type _parsed + _lookupByKey(_parsed, iScale.axis, min).lo, // @ts-expect-error Need to fix types on _lookupByKey + animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo), 0, pointCount - 1); + } + if (maxDefined) { + count = _limitValue(Math.max(// @ts-expect-error Need to type _parsed + _lookupByKey(_parsed, iScale.axis, max, true).hi + 1, // @ts-expect-error Need to fix types on _lookupByKey + animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1), start, pointCount) - start; + } else { + count = pointCount - start; + } + } + return { + start, + count + }; +} +/** + * Checks if the scale ranges have changed. + * @param {object} meta - dataset meta. + * @returns {boolean} + * @private + */ function _scaleRangesChanged(meta) { + const { xScale , yScale , _scaleRanges } = meta; + const newRanges = { + xmin: xScale.min, + xmax: xScale.max, + ymin: yScale.min, + ymax: yScale.max + }; + if (!_scaleRanges) { + meta._scaleRanges = newRanges; + return true; + } + const changed = _scaleRanges.xmin !== xScale.min || _scaleRanges.xmax !== xScale.max || _scaleRanges.ymin !== yScale.min || _scaleRanges.ymax !== yScale.max; + Object.assign(_scaleRanges, newRanges); + return changed; +} + +const atEdge = (t)=>t === 0 || t === 1; +const elasticIn = (t, s, p)=>-(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p)); +const elasticOut = (t, s, p)=>Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1; +/** + * Easing functions adapted from Robert Penner's easing equations. + * @namespace Chart.helpers.easing.effects + * @see http://www.robertpenner.com/easing/ + */ const effects = { + linear: (t)=>t, + easeInQuad: (t)=>t * t, + easeOutQuad: (t)=>-t * (t - 2), + easeInOutQuad: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1), + easeInCubic: (t)=>t * t * t, + easeOutCubic: (t)=>(t -= 1) * t * t + 1, + easeInOutCubic: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2), + easeInQuart: (t)=>t * t * t * t, + easeOutQuart: (t)=>-((t -= 1) * t * t * t - 1), + easeInOutQuart: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2), + easeInQuint: (t)=>t * t * t * t * t, + easeOutQuint: (t)=>(t -= 1) * t * t * t * t + 1, + easeInOutQuint: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2), + easeInSine: (t)=>-Math.cos(t * HALF_PI) + 1, + easeOutSine: (t)=>Math.sin(t * HALF_PI), + easeInOutSine: (t)=>-0.5 * (Math.cos(PI * t) - 1), + easeInExpo: (t)=>t === 0 ? 0 : Math.pow(2, 10 * (t - 1)), + easeOutExpo: (t)=>t === 1 ? 1 : -Math.pow(2, -10 * t) + 1, + easeInOutExpo: (t)=>atEdge(t) ? t : t < 0.5 ? 0.5 * Math.pow(2, 10 * (t * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2), + easeInCirc: (t)=>t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1), + easeOutCirc: (t)=>Math.sqrt(1 - (t -= 1) * t), + easeInOutCirc: (t)=>(t /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1), + easeInElastic: (t)=>atEdge(t) ? t : elasticIn(t, 0.075, 0.3), + easeOutElastic: (t)=>atEdge(t) ? t : elasticOut(t, 0.075, 0.3), + easeInOutElastic (t) { + const s = 0.1125; + const p = 0.45; + return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p); + }, + easeInBack (t) { + const s = 1.70158; + return t * t * ((s + 1) * t - s); + }, + easeOutBack (t) { + const s = 1.70158; + return (t -= 1) * t * ((s + 1) * t + s) + 1; + }, + easeInOutBack (t) { + let s = 1.70158; + if ((t /= 0.5) < 1) { + return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s)); + } + return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2); + }, + easeInBounce: (t)=>1 - effects.easeOutBounce(1 - t), + easeOutBounce (t) { + const m = 7.5625; + const d = 2.75; + if (t < 1 / d) { + return m * t * t; + } + if (t < 2 / d) { + return m * (t -= 1.5 / d) * t + 0.75; + } + if (t < 2.5 / d) { + return m * (t -= 2.25 / d) * t + 0.9375; + } + return m * (t -= 2.625 / d) * t + 0.984375; + }, + easeInOutBounce: (t)=>t < 0.5 ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5 +}; + +function isPatternOrGradient(value) { + if (value && typeof value === 'object') { + const type = value.toString(); + return type === '[object CanvasPattern]' || type === '[object CanvasGradient]'; + } + return false; +} +function color(value) { + return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value); +} +function getHoverColor(value) { + return isPatternOrGradient(value) ? value : new _kurkle_color__WEBPACK_IMPORTED_MODULE_0__.Color(value).saturate(0.5).darken(0.1).hexString(); +} + +const numbers = [ + 'x', + 'y', + 'borderWidth', + 'radius', + 'tension' +]; +const colors = [ + 'color', + 'borderColor', + 'backgroundColor' +]; +function applyAnimationsDefaults(defaults) { + defaults.set('animation', { + delay: undefined, + duration: 1000, + easing: 'easeOutQuart', + fn: undefined, + from: undefined, + loop: undefined, + to: undefined, + type: undefined + }); + defaults.describe('animation', { + _fallback: false, + _indexable: false, + _scriptable: (name)=>name !== 'onProgress' && name !== 'onComplete' && name !== 'fn' + }); + defaults.set('animations', { + colors: { + type: 'color', + properties: colors + }, + numbers: { + type: 'number', + properties: numbers + } + }); + defaults.describe('animations', { + _fallback: 'animation' + }); + defaults.set('transitions', { + active: { + animation: { + duration: 400 + } + }, + resize: { + animation: { + duration: 0 + } + }, + show: { + animations: { + colors: { + from: 'transparent' + }, + visible: { + type: 'boolean', + duration: 0 + } + } + }, + hide: { + animations: { + colors: { + to: 'transparent' + }, + visible: { + type: 'boolean', + easing: 'linear', + fn: (v)=>v | 0 + } + } + } + }); +} + +function applyLayoutsDefaults(defaults) { + defaults.set('layout', { + autoPadding: true, + padding: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }); +} + +const intlCache = new Map(); +function getNumberFormat(locale, options) { + options = options || {}; + const cacheKey = locale + JSON.stringify(options); + let formatter = intlCache.get(cacheKey); + if (!formatter) { + formatter = new Intl.NumberFormat(locale, options); + intlCache.set(cacheKey, formatter); + } + return formatter; +} +function formatNumber(num, locale, options) { + return getNumberFormat(locale, options).format(num); +} + +const formatters = { + values (value) { + return isArray(value) ? value : '' + value; + }, + numeric (tickValue, index, ticks) { + if (tickValue === 0) { + return '0'; + } + const locale = this.chart.options.locale; + let notation; + let delta = tickValue; + if (ticks.length > 1) { + const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value)); + if (maxTick < 1e-4 || maxTick > 1e+15) { + notation = 'scientific'; + } + delta = calculateDelta(tickValue, ticks); + } + const logDelta = log10(Math.abs(delta)); + const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0); + const options = { + notation, + minimumFractionDigits: numDecimal, + maximumFractionDigits: numDecimal + }; + Object.assign(options, this.options.ticks.format); + return formatNumber(tickValue, locale, options); + }, + logarithmic (tickValue, index, ticks) { + if (tickValue === 0) { + return '0'; + } + const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue))); + if ([ + 1, + 2, + 3, + 5, + 10, + 15 + ].includes(remain) || index > 0.8 * ticks.length) { + return formatters.numeric.call(this, tickValue, index, ticks); + } + return ''; + } +}; +function calculateDelta(tickValue, ticks) { + let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value; + if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) { + delta = tickValue - Math.floor(tickValue); + } + return delta; +} + var Ticks = { + formatters +}; + +function applyScaleDefaults(defaults) { + defaults.set('scale', { + display: true, + offset: false, + reverse: false, + beginAtZero: false, + bounds: 'ticks', + grace: 0, + grid: { + display: true, + lineWidth: 1, + drawOnChartArea: true, + drawTicks: true, + tickLength: 8, + tickWidth: (_ctx, options)=>options.lineWidth, + tickColor: (_ctx, options)=>options.color, + offset: false + }, + border: { + display: true, + dash: [], + dashOffset: 0.0, + width: 1 + }, + title: { + display: false, + text: '', + padding: { + top: 4, + bottom: 4 + } + }, + ticks: { + minRotation: 0, + maxRotation: 50, + mirror: false, + textStrokeWidth: 0, + textStrokeColor: '', + padding: 3, + display: true, + autoSkip: true, + autoSkipPadding: 3, + labelOffset: 0, + callback: Ticks.formatters.values, + minor: {}, + major: {}, + align: 'center', + crossAlign: 'near', + showLabelBackdrop: false, + backdropColor: 'rgba(255, 255, 255, 0.75)', + backdropPadding: 2 + } + }); + defaults.route('scale.ticks', 'color', '', 'color'); + defaults.route('scale.grid', 'color', '', 'borderColor'); + defaults.route('scale.border', 'color', '', 'borderColor'); + defaults.route('scale.title', 'color', '', 'color'); + defaults.describe('scale', { + _fallback: false, + _scriptable: (name)=>!name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser', + _indexable: (name)=>name !== 'borderDash' && name !== 'tickBorderDash' && name !== 'dash' + }); + defaults.describe('scales', { + _fallback: 'scale' + }); + defaults.describe('scale.ticks', { + _scriptable: (name)=>name !== 'backdropPadding' && name !== 'callback', + _indexable: (name)=>name !== 'backdropPadding' + }); +} + +const overrides = Object.create(null); +const descriptors = Object.create(null); + function getScope$1(node, key) { + if (!key) { + return node; + } + const keys = key.split('.'); + for(let i = 0, n = keys.length; i < n; ++i){ + const k = keys[i]; + node = node[k] || (node[k] = Object.create(null)); + } + return node; +} +function set(root, scope, values) { + if (typeof scope === 'string') { + return merge(getScope$1(root, scope), values); + } + return merge(getScope$1(root, ''), scope); +} + class Defaults { + constructor(_descriptors, _appliers){ + this.animation = undefined; + this.backgroundColor = 'rgba(0,0,0,0.1)'; + this.borderColor = 'rgba(0,0,0,0.1)'; + this.color = '#666'; + this.datasets = {}; + this.devicePixelRatio = (context)=>context.chart.platform.getDevicePixelRatio(); + this.elements = {}; + this.events = [ + 'mousemove', + 'mouseout', + 'click', + 'touchstart', + 'touchmove' + ]; + this.font = { + family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + size: 12, + style: 'normal', + lineHeight: 1.2, + weight: null + }; + this.hover = {}; + this.hoverBackgroundColor = (ctx, options)=>getHoverColor(options.backgroundColor); + this.hoverBorderColor = (ctx, options)=>getHoverColor(options.borderColor); + this.hoverColor = (ctx, options)=>getHoverColor(options.color); + this.indexAxis = 'x'; + this.interaction = { + mode: 'nearest', + intersect: true, + includeInvisible: false + }; + this.maintainAspectRatio = true; + this.onHover = null; + this.onClick = null; + this.parsing = true; + this.plugins = {}; + this.responsive = true; + this.scale = undefined; + this.scales = {}; + this.showLine = true; + this.drawActiveElementsOnTop = true; + this.describe(_descriptors); + this.apply(_appliers); + } + set(scope, values) { + return set(this, scope, values); + } + get(scope) { + return getScope$1(this, scope); + } + describe(scope, values) { + return set(descriptors, scope, values); + } + override(scope, values) { + return set(overrides, scope, values); + } + route(scope, name, targetScope, targetName) { + const scopeObject = getScope$1(this, scope); + const targetScopeObject = getScope$1(this, targetScope); + const privateName = '_' + name; + Object.defineProperties(scopeObject, { + [privateName]: { + value: scopeObject[name], + writable: true + }, + [name]: { + enumerable: true, + get () { + const local = this[privateName]; + const target = targetScopeObject[targetName]; + if (isObject(local)) { + return Object.assign({}, target, local); + } + return valueOrDefault(local, target); + }, + set (value) { + this[privateName] = value; + } + } + }); + } + apply(appliers) { + appliers.forEach((apply)=>apply(this)); + } +} +var defaults = /* #__PURE__ */ new Defaults({ + _scriptable: (name)=>!name.startsWith('on'), + _indexable: (name)=>name !== 'events', + hover: { + _fallback: 'interaction' + }, + interaction: { + _scriptable: false, + _indexable: false + } +}, [ + applyAnimationsDefaults, + applyLayoutsDefaults, + applyScaleDefaults +]); + +/** + * Converts the given font object into a CSS font string. + * @param font - A font object. + * @return The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font + * @private + */ function toFontString(font) { + if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) { + return null; + } + return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family; +} +/** + * @private + */ function _measureText(ctx, data, gc, longest, string) { + let textWidth = data[string]; + if (!textWidth) { + textWidth = data[string] = ctx.measureText(string).width; + gc.push(string); + } + if (textWidth > longest) { + longest = textWidth; + } + return longest; +} +/** + * @private + */ // eslint-disable-next-line complexity +function _longestText(ctx, font, arrayOfThings, cache) { + cache = cache || {}; + let data = cache.data = cache.data || {}; + let gc = cache.garbageCollect = cache.garbageCollect || []; + if (cache.font !== font) { + data = cache.data = {}; + gc = cache.garbageCollect = []; + cache.font = font; + } + ctx.save(); + ctx.font = font; + let longest = 0; + const ilen = arrayOfThings.length; + let i, j, jlen, thing, nestedThing; + for(i = 0; i < ilen; i++){ + thing = arrayOfThings[i]; + // Undefined strings and arrays should not be measured + if (thing !== undefined && thing !== null && !isArray(thing)) { + longest = _measureText(ctx, data, gc, longest, thing); + } else if (isArray(thing)) { + // if it is an array lets measure each element + // to do maybe simplify this function a bit so we can do this more recursively? + for(j = 0, jlen = thing.length; j < jlen; j++){ + nestedThing = thing[j]; + // Undefined strings and arrays should not be measured + if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) { + longest = _measureText(ctx, data, gc, longest, nestedThing); + } + } + } + } + ctx.restore(); + const gcLen = gc.length / 2; + if (gcLen > arrayOfThings.length) { + for(i = 0; i < gcLen; i++){ + delete data[gc[i]]; + } + gc.splice(0, gcLen); + } + return longest; +} +/** + * Returns the aligned pixel value to avoid anti-aliasing blur + * @param chart - The chart instance. + * @param pixel - A pixel value. + * @param width - The width of the element. + * @returns The aligned pixel value. + * @private + */ function _alignPixel(chart, pixel, width) { + const devicePixelRatio = chart.currentDevicePixelRatio; + const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0; + return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth; +} +/** + * Clears the entire canvas. + */ function clearCanvas(canvas, ctx) { + ctx = ctx || canvas.getContext('2d'); + ctx.save(); + // canvas.width and canvas.height do not consider the canvas transform, + // while clearRect does + ctx.resetTransform(); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.restore(); +} +function drawPoint(ctx, options, x, y) { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + drawPointLegend(ctx, options, x, y, null); +} +// eslint-disable-next-line complexity +function drawPointLegend(ctx, options, x, y, w) { + let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW; + const style = options.pointStyle; + const rotation = options.rotation; + const radius = options.radius; + let rad = (rotation || 0) * RAD_PER_DEG; + if (style && typeof style === 'object') { + type = style.toString(); + if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { + ctx.save(); + ctx.translate(x, y); + ctx.rotate(rad); + ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height); + ctx.restore(); + return; + } + } + if (isNaN(radius) || radius <= 0) { + return; + } + ctx.beginPath(); + switch(style){ + // Default includes circle + default: + if (w) { + ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU); + } else { + ctx.arc(x, y, radius, 0, TAU); + } + ctx.closePath(); + break; + case 'triangle': + width = w ? w / 2 : radius; + ctx.moveTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius); + ctx.closePath(); + break; + case 'rectRounded': + // NOTE: the rounded rect implementation changed to use `arc` instead of + // `quadraticCurveTo` since it generates better results when rect is + // almost a circle. 0.516 (instead of 0.5) produces results with visually + // closer proportion to the previous impl and it is inscribed in the + // circle with `radius`. For more details, see the following PRs: + // https://github.com/chartjs/Chart.js/issues/5597 + // https://github.com/chartjs/Chart.js/issues/5858 + cornerRadius = radius * 0.516; + size = radius - cornerRadius; + xOffset = Math.cos(rad + QUARTER_PI) * size; + xOffsetW = Math.cos(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size); + yOffset = Math.sin(rad + QUARTER_PI) * size; + yOffsetW = Math.sin(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size); + ctx.arc(x - xOffsetW, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI); + ctx.arc(x + yOffsetW, y - xOffset, cornerRadius, rad - HALF_PI, rad); + ctx.arc(x + xOffsetW, y + yOffset, cornerRadius, rad, rad + HALF_PI); + ctx.arc(x - yOffsetW, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI); + ctx.closePath(); + break; + case 'rect': + if (!rotation) { + size = Math.SQRT1_2 * radius; + width = w ? w / 2 : size; + ctx.rect(x - width, y - size, 2 * width, 2 * size); + break; + } + rad += QUARTER_PI; + /* falls through */ case 'rectRot': + xOffsetW = Math.cos(rad) * (w ? w / 2 : radius); + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + yOffsetW = Math.sin(rad) * (w ? w / 2 : radius); + ctx.moveTo(x - xOffsetW, y - yOffset); + ctx.lineTo(x + yOffsetW, y - xOffset); + ctx.lineTo(x + xOffsetW, y + yOffset); + ctx.lineTo(x - yOffsetW, y + xOffset); + ctx.closePath(); + break; + case 'crossRot': + rad += QUARTER_PI; + /* falls through */ case 'cross': + xOffsetW = Math.cos(rad) * (w ? w / 2 : radius); + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + yOffsetW = Math.sin(rad) * (w ? w / 2 : radius); + ctx.moveTo(x - xOffsetW, y - yOffset); + ctx.lineTo(x + xOffsetW, y + yOffset); + ctx.moveTo(x + yOffsetW, y - xOffset); + ctx.lineTo(x - yOffsetW, y + xOffset); + break; + case 'star': + xOffsetW = Math.cos(rad) * (w ? w / 2 : radius); + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + yOffsetW = Math.sin(rad) * (w ? w / 2 : radius); + ctx.moveTo(x - xOffsetW, y - yOffset); + ctx.lineTo(x + xOffsetW, y + yOffset); + ctx.moveTo(x + yOffsetW, y - xOffset); + ctx.lineTo(x - yOffsetW, y + xOffset); + rad += QUARTER_PI; + xOffsetW = Math.cos(rad) * (w ? w / 2 : radius); + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + yOffsetW = Math.sin(rad) * (w ? w / 2 : radius); + ctx.moveTo(x - xOffsetW, y - yOffset); + ctx.lineTo(x + xOffsetW, y + yOffset); + ctx.moveTo(x + yOffsetW, y - xOffset); + ctx.lineTo(x - yOffsetW, y + xOffset); + break; + case 'line': + xOffset = w ? w / 2 : Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + break; + case 'dash': + ctx.moveTo(x, y); + ctx.lineTo(x + Math.cos(rad) * (w ? w / 2 : radius), y + Math.sin(rad) * radius); + break; + case false: + ctx.closePath(); + break; + } + ctx.fill(); + if (options.borderWidth > 0) { + ctx.stroke(); + } +} +/** + * Returns true if the point is inside the rectangle + * @param point - The point to test + * @param area - The rectangle + * @param margin - allowed margin + * @private + */ function _isPointInArea(point, area, margin) { + margin = margin || 0.5; // margin - default is to match rounded decimals + return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin; +} +function clipArea(ctx, area) { + ctx.save(); + ctx.beginPath(); + ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); + ctx.clip(); +} +function unclipArea(ctx) { + ctx.restore(); +} +/** + * @private + */ function _steppedLineTo(ctx, previous, target, flip, mode) { + if (!previous) { + return ctx.lineTo(target.x, target.y); + } + if (mode === 'middle') { + const midpoint = (previous.x + target.x) / 2.0; + ctx.lineTo(midpoint, previous.y); + ctx.lineTo(midpoint, target.y); + } else if (mode === 'after' !== !!flip) { + ctx.lineTo(previous.x, target.y); + } else { + ctx.lineTo(target.x, previous.y); + } + ctx.lineTo(target.x, target.y); +} +/** + * @private + */ function _bezierCurveTo(ctx, previous, target, flip) { + if (!previous) { + return ctx.lineTo(target.x, target.y); + } + ctx.bezierCurveTo(flip ? previous.cp1x : previous.cp2x, flip ? previous.cp1y : previous.cp2y, flip ? target.cp2x : target.cp1x, flip ? target.cp2y : target.cp1y, target.x, target.y); +} +function setRenderOpts(ctx, opts) { + if (opts.translation) { + ctx.translate(opts.translation[0], opts.translation[1]); + } + if (!isNullOrUndef(opts.rotation)) { + ctx.rotate(opts.rotation); + } + if (opts.color) { + ctx.fillStyle = opts.color; + } + if (opts.textAlign) { + ctx.textAlign = opts.textAlign; + } + if (opts.textBaseline) { + ctx.textBaseline = opts.textBaseline; + } +} +function decorateText(ctx, x, y, line, opts) { + if (opts.strikethrough || opts.underline) { + /** + * Now that IE11 support has been dropped, we can use more + * of the TextMetrics object. The actual bounding boxes + * are unflagged in Chrome, Firefox, Edge, and Safari so they + * can be safely used. + * See https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics#Browser_compatibility + */ const metrics = ctx.measureText(line); + const left = x - metrics.actualBoundingBoxLeft; + const right = x + metrics.actualBoundingBoxRight; + const top = y - metrics.actualBoundingBoxAscent; + const bottom = y + metrics.actualBoundingBoxDescent; + const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom; + ctx.strokeStyle = ctx.fillStyle; + ctx.beginPath(); + ctx.lineWidth = opts.decorationWidth || 2; + ctx.moveTo(left, yDecoration); + ctx.lineTo(right, yDecoration); + ctx.stroke(); + } +} +function drawBackdrop(ctx, opts) { + const oldColor = ctx.fillStyle; + ctx.fillStyle = opts.color; + ctx.fillRect(opts.left, opts.top, opts.width, opts.height); + ctx.fillStyle = oldColor; +} +/** + * Render text onto the canvas + */ function renderText(ctx, text, x, y, font, opts = {}) { + const lines = isArray(text) ? text : [ + text + ]; + const stroke = opts.strokeWidth > 0 && opts.strokeColor !== ''; + let i, line; + ctx.save(); + ctx.font = font.string; + setRenderOpts(ctx, opts); + for(i = 0; i < lines.length; ++i){ + line = lines[i]; + if (opts.backdrop) { + drawBackdrop(ctx, opts.backdrop); + } + if (stroke) { + if (opts.strokeColor) { + ctx.strokeStyle = opts.strokeColor; + } + if (!isNullOrUndef(opts.strokeWidth)) { + ctx.lineWidth = opts.strokeWidth; + } + ctx.strokeText(line, x, y, opts.maxWidth); + } + ctx.fillText(line, x, y, opts.maxWidth); + decorateText(ctx, x, y, line, opts); + y += Number(font.lineHeight); + } + ctx.restore(); +} +/** + * Add a path of a rectangle with rounded corners to the current sub-path + * @param ctx - Context + * @param rect - Bounding rect + */ function addRoundedRectPath(ctx, rect) { + const { x , y , w , h , radius } = rect; + // top left arc + ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true); + // line from top left to bottom left + ctx.lineTo(x, y + h - radius.bottomLeft); + // bottom left arc + ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true); + // line from bottom left to bottom right + ctx.lineTo(x + w - radius.bottomRight, y + h); + // bottom right arc + ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true); + // line from bottom right to top right + ctx.lineTo(x + w, y + radius.topRight); + // top right arc + ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true); + // line from top right to top left + ctx.lineTo(x + radius.topLeft, y); +} + +const LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/; +const FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/; +/** + * @alias Chart.helpers.options + * @namespace + */ /** + * Converts the given line height `value` in pixels for a specific font `size`. + * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). + * @param size - The font size (in pixels) used to resolve relative `value`. + * @returns The effective line height in pixels (size * 1.2 if value is invalid). + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height + * @since 2.7.0 + */ function toLineHeight(value, size) { + const matches = ('' + value).match(LINE_HEIGHT); + if (!matches || matches[1] === 'normal') { + return size * 1.2; + } + value = +matches[2]; + switch(matches[3]){ + case 'px': + return value; + case '%': + value /= 100; + break; + } + return size * value; +} +const numberOrZero = (v)=>+v || 0; +function _readValueToProps(value, props) { + const ret = {}; + const objProps = isObject(props); + const keys = objProps ? Object.keys(props) : props; + const read = isObject(value) ? objProps ? (prop)=>valueOrDefault(value[prop], value[props[prop]]) : (prop)=>value[prop] : ()=>value; + for (const prop of keys){ + ret[prop] = numberOrZero(read(prop)); + } + return ret; +} +/** + * Converts the given value into a TRBL object. + * @param value - If a number, set the value to all TRBL component, + * else, if an object, use defined properties and sets undefined ones to 0. + * x / y are shorthands for same value for left/right and top/bottom. + * @returns The padding values (top, right, bottom, left) + * @since 3.0.0 + */ function toTRBL(value) { + return _readValueToProps(value, { + top: 'y', + right: 'x', + bottom: 'y', + left: 'x' + }); +} +/** + * Converts the given value into a TRBL corners object (similar with css border-radius). + * @param value - If a number, set the value to all TRBL corner components, + * else, if an object, use defined properties and sets undefined ones to 0. + * @returns The TRBL corner values (topLeft, topRight, bottomLeft, bottomRight) + * @since 3.0.0 + */ function toTRBLCorners(value) { + return _readValueToProps(value, [ + 'topLeft', + 'topRight', + 'bottomLeft', + 'bottomRight' + ]); +} +/** + * Converts the given value into a padding object with pre-computed width/height. + * @param value - If a number, set the value to all TRBL component, + * else, if an object, use defined properties and sets undefined ones to 0. + * x / y are shorthands for same value for left/right and top/bottom. + * @returns The padding values (top, right, bottom, left, width, height) + * @since 2.7.0 + */ function toPadding(value) { + const obj = toTRBL(value); + obj.width = obj.left + obj.right; + obj.height = obj.top + obj.bottom; + return obj; +} +/** + * Parses font options and returns the font object. + * @param options - A object that contains font options to be parsed. + * @param fallback - A object that contains fallback font options. + * @return The font object. + * @private + */ function toFont(options, fallback) { + options = options || {}; + fallback = fallback || defaults.font; + let size = valueOrDefault(options.size, fallback.size); + if (typeof size === 'string') { + size = parseInt(size, 10); + } + let style = valueOrDefault(options.style, fallback.style); + if (style && !('' + style).match(FONT_STYLE)) { + console.warn('Invalid font style specified: "' + style + '"'); + style = undefined; + } + const font = { + family: valueOrDefault(options.family, fallback.family), + lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size), + size, + style, + weight: valueOrDefault(options.weight, fallback.weight), + string: '' + }; + font.string = toFontString(font); + return font; +} +/** + * Evaluates the given `inputs` sequentially and returns the first defined value. + * @param inputs - An array of values, falling back to the last value. + * @param context - If defined and the current value is a function, the value + * is called with `context` as first argument and the result becomes the new input. + * @param index - If defined and the current value is an array, the value + * at `index` become the new input. + * @param info - object to return information about resolution in + * @param info.cacheable - Will be set to `false` if option is not cacheable. + * @since 2.7.0 + */ function resolve(inputs, context, index, info) { + let cacheable = true; + let i, ilen, value; + for(i = 0, ilen = inputs.length; i < ilen; ++i){ + value = inputs[i]; + if (value === undefined) { + continue; + } + if (context !== undefined && typeof value === 'function') { + value = value(context); + cacheable = false; + } + if (index !== undefined && isArray(value)) { + value = value[index % value.length]; + cacheable = false; + } + if (value !== undefined) { + if (info && !cacheable) { + info.cacheable = false; + } + return value; + } + } +} +/** + * @param minmax + * @param grace + * @param beginAtZero + * @private + */ function _addGrace(minmax, grace, beginAtZero) { + const { min , max } = minmax; + const change = toDimension(grace, (max - min) / 2); + const keepZero = (value, add)=>beginAtZero && value === 0 ? 0 : value + add; + return { + min: keepZero(min, -Math.abs(change)), + max: keepZero(max, change) + }; +} +function createContext(parentContext, context) { + return Object.assign(Object.create(parentContext), context); +} + +/** + * Creates a Proxy for resolving raw values for options. + * @param scopes - The option scopes to look for values, in resolution order + * @param prefixes - The prefixes for values, in resolution order. + * @param rootScopes - The root option scopes + * @param fallback - Parent scopes fallback + * @param getTarget - callback for getting the target for changed values + * @returns Proxy + * @private + */ function _createResolver(scopes, prefixes = [ + '' +], rootScopes, fallback, getTarget = ()=>scopes[0]) { + const finalRootScopes = rootScopes || scopes; + if (typeof fallback === 'undefined') { + fallback = _resolve('_fallback', scopes); + } + const cache = { + [Symbol.toStringTag]: 'Object', + _cacheable: true, + _scopes: scopes, + _rootScopes: finalRootScopes, + _fallback: fallback, + _getTarget: getTarget, + override: (scope)=>_createResolver([ + scope, + ...scopes + ], prefixes, finalRootScopes, fallback) + }; + return new Proxy(cache, { + /** + * A trap for the delete operator. + */ deleteProperty (target, prop) { + delete target[prop]; // remove from cache + delete target._keys; // remove cached keys + delete scopes[0][prop]; // remove from top level scope + return true; + }, + /** + * A trap for getting property values. + */ get (target, prop) { + return _cached(target, prop, ()=>_resolveWithPrefixes(prop, prefixes, scopes, target)); + }, + /** + * A trap for Object.getOwnPropertyDescriptor. + * Also used by Object.hasOwnProperty. + */ getOwnPropertyDescriptor (target, prop) { + return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop); + }, + /** + * A trap for Object.getPrototypeOf. + */ getPrototypeOf () { + return Reflect.getPrototypeOf(scopes[0]); + }, + /** + * A trap for the in operator. + */ has (target, prop) { + return getKeysFromAllScopes(target).includes(prop); + }, + /** + * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols. + */ ownKeys (target) { + return getKeysFromAllScopes(target); + }, + /** + * A trap for setting property values. + */ set (target, prop, value) { + const storage = target._storage || (target._storage = getTarget()); + target[prop] = storage[prop] = value; // set to top level scope + cache + delete target._keys; // remove cached keys + return true; + } + }); +} +/** + * Returns an Proxy for resolving option values with context. + * @param proxy - The Proxy returned by `_createResolver` + * @param context - Context object for scriptable/indexable options + * @param subProxy - The proxy provided for scriptable options + * @param descriptorDefaults - Defaults for descriptors + * @private + */ function _attachContext(proxy, context, subProxy, descriptorDefaults) { + const cache = { + _cacheable: false, + _proxy: proxy, + _context: context, + _subProxy: subProxy, + _stack: new Set(), + _descriptors: _descriptors(proxy, descriptorDefaults), + setContext: (ctx)=>_attachContext(proxy, ctx, subProxy, descriptorDefaults), + override: (scope)=>_attachContext(proxy.override(scope), context, subProxy, descriptorDefaults) + }; + return new Proxy(cache, { + /** + * A trap for the delete operator. + */ deleteProperty (target, prop) { + delete target[prop]; // remove from cache + delete proxy[prop]; // remove from proxy + return true; + }, + /** + * A trap for getting property values. + */ get (target, prop, receiver) { + return _cached(target, prop, ()=>_resolveWithContext(target, prop, receiver)); + }, + /** + * A trap for Object.getOwnPropertyDescriptor. + * Also used by Object.hasOwnProperty. + */ getOwnPropertyDescriptor (target, prop) { + return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? { + enumerable: true, + configurable: true + } : undefined : Reflect.getOwnPropertyDescriptor(proxy, prop); + }, + /** + * A trap for Object.getPrototypeOf. + */ getPrototypeOf () { + return Reflect.getPrototypeOf(proxy); + }, + /** + * A trap for the in operator. + */ has (target, prop) { + return Reflect.has(proxy, prop); + }, + /** + * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols. + */ ownKeys () { + return Reflect.ownKeys(proxy); + }, + /** + * A trap for setting property values. + */ set (target, prop, value) { + proxy[prop] = value; // set to proxy + delete target[prop]; // remove from cache + return true; + } + }); +} +/** + * @private + */ function _descriptors(proxy, defaults = { + scriptable: true, + indexable: true +}) { + const { _scriptable =defaults.scriptable , _indexable =defaults.indexable , _allKeys =defaults.allKeys } = proxy; + return { + allKeys: _allKeys, + scriptable: _scriptable, + indexable: _indexable, + isScriptable: isFunction(_scriptable) ? _scriptable : ()=>_scriptable, + isIndexable: isFunction(_indexable) ? _indexable : ()=>_indexable + }; +} +const readKey = (prefix, name)=>prefix ? prefix + _capitalize(name) : name; +const needsSubResolver = (prop, value)=>isObject(value) && prop !== 'adapters' && (Object.getPrototypeOf(value) === null || value.constructor === Object); +function _cached(target, prop, resolve) { + if (Object.prototype.hasOwnProperty.call(target, prop)) { + return target[prop]; + } + const value = resolve(); + // cache the resolved value + target[prop] = value; + return value; +} +function _resolveWithContext(target, prop, receiver) { + const { _proxy , _context , _subProxy , _descriptors: descriptors } = target; + let value = _proxy[prop]; // resolve from proxy + // resolve with context + if (isFunction(value) && descriptors.isScriptable(prop)) { + value = _resolveScriptable(prop, value, target, receiver); + } + if (isArray(value) && value.length) { + value = _resolveArray(prop, value, target, descriptors.isIndexable); + } + if (needsSubResolver(prop, value)) { + // if the resolved value is an object, create a sub resolver for it + value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors); + } + return value; +} +function _resolveScriptable(prop, getValue, target, receiver) { + const { _proxy , _context , _subProxy , _stack } = target; + if (_stack.has(prop)) { + throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop); + } + _stack.add(prop); + let value = getValue(_context, _subProxy || receiver); + _stack.delete(prop); + if (needsSubResolver(prop, value)) { + // When scriptable option returns an object, create a resolver on that. + value = createSubResolver(_proxy._scopes, _proxy, prop, value); + } + return value; +} +function _resolveArray(prop, value, target, isIndexable) { + const { _proxy , _context , _subProxy , _descriptors: descriptors } = target; + if (typeof _context.index !== 'undefined' && isIndexable(prop)) { + return value[_context.index % value.length]; + } else if (isObject(value[0])) { + // Array of objects, return array or resolvers + const arr = value; + const scopes = _proxy._scopes.filter((s)=>s !== arr); + value = []; + for (const item of arr){ + const resolver = createSubResolver(scopes, _proxy, prop, item); + value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors)); + } + } + return value; +} +function resolveFallback(fallback, prop, value) { + return isFunction(fallback) ? fallback(prop, value) : fallback; +} +const getScope = (key, parent)=>key === true ? parent : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined; +function addScopes(set, parentScopes, key, parentFallback, value) { + for (const parent of parentScopes){ + const scope = getScope(key, parent); + if (scope) { + set.add(scope); + const fallback = resolveFallback(scope._fallback, key, value); + if (typeof fallback !== 'undefined' && fallback !== key && fallback !== parentFallback) { + // When we reach the descriptor that defines a new _fallback, return that. + // The fallback will resume to that new scope. + return fallback; + } + } else if (scope === false && typeof parentFallback !== 'undefined' && key !== parentFallback) { + // Fallback to `false` results to `false`, when falling back to different key. + // For example `interaction` from `hover` or `plugins.tooltip` and `animation` from `animations` + return null; + } + } + return false; +} +function createSubResolver(parentScopes, resolver, prop, value) { + const rootScopes = resolver._rootScopes; + const fallback = resolveFallback(resolver._fallback, prop, value); + const allScopes = [ + ...parentScopes, + ...rootScopes + ]; + const set = new Set(); + set.add(value); + let key = addScopesFromKey(set, allScopes, prop, fallback || prop, value); + if (key === null) { + return false; + } + if (typeof fallback !== 'undefined' && fallback !== prop) { + key = addScopesFromKey(set, allScopes, fallback, key, value); + if (key === null) { + return false; + } + } + return _createResolver(Array.from(set), [ + '' + ], rootScopes, fallback, ()=>subGetTarget(resolver, prop, value)); +} +function addScopesFromKey(set, allScopes, key, fallback, item) { + while(key){ + key = addScopes(set, allScopes, key, fallback, item); + } + return key; +} +function subGetTarget(resolver, prop, value) { + const parent = resolver._getTarget(); + if (!(prop in parent)) { + parent[prop] = {}; + } + const target = parent[prop]; + if (isArray(target) && isObject(value)) { + // For array of objects, the object is used to store updated values + return value; + } + return target || {}; +} +function _resolveWithPrefixes(prop, prefixes, scopes, proxy) { + let value; + for (const prefix of prefixes){ + value = _resolve(readKey(prefix, prop), scopes); + if (typeof value !== 'undefined') { + return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value; + } + } +} +function _resolve(key, scopes) { + for (const scope of scopes){ + if (!scope) { + continue; + } + const value = scope[key]; + if (typeof value !== 'undefined') { + return value; + } + } +} +function getKeysFromAllScopes(target) { + let keys = target._keys; + if (!keys) { + keys = target._keys = resolveKeysFromAllScopes(target._scopes); + } + return keys; +} +function resolveKeysFromAllScopes(scopes) { + const set = new Set(); + for (const scope of scopes){ + for (const key of Object.keys(scope).filter((k)=>!k.startsWith('_'))){ + set.add(key); + } + } + return Array.from(set); +} +function _parseObjectDataRadialScale(meta, data, start, count) { + const { iScale } = meta; + const { key ='r' } = this._parsing; + const parsed = new Array(count); + let i, ilen, index, item; + for(i = 0, ilen = count; i < ilen; ++i){ + index = i + start; + item = data[index]; + parsed[i] = { + r: iScale.parse(resolveObjectKey(item, key), index) + }; + } + return parsed; +} + +const EPSILON = Number.EPSILON || 1e-14; +const getPoint = (points, i)=>i < points.length && !points[i].skip && points[i]; +const getValueAxis = (indexAxis)=>indexAxis === 'x' ? 'y' : 'x'; +function splineCurve(firstPoint, middlePoint, afterPoint, t) { + // Props to Rob Spencer at scaled innovation for his post on splining between points + // http://scaledinnovation.com/analytics/splines/aboutSplines.html + // This function must also respect "skipped" points + const previous = firstPoint.skip ? middlePoint : firstPoint; + const current = middlePoint; + const next = afterPoint.skip ? middlePoint : afterPoint; + const d01 = distanceBetweenPoints(current, previous); + const d12 = distanceBetweenPoints(next, current); + let s01 = d01 / (d01 + d12); + let s12 = d12 / (d01 + d12); + // If all points are the same, s01 & s02 will be inf + s01 = isNaN(s01) ? 0 : s01; + s12 = isNaN(s12) ? 0 : s12; + const fa = t * s01; // scaling factor for triangle Ta + const fb = t * s12; + return { + previous: { + x: current.x - fa * (next.x - previous.x), + y: current.y - fa * (next.y - previous.y) + }, + next: { + x: current.x + fb * (next.x - previous.x), + y: current.y + fb * (next.y - previous.y) + } + }; +} +/** + * Adjust tangents to ensure monotonic properties + */ function monotoneAdjust(points, deltaK, mK) { + const pointsLen = points.length; + let alphaK, betaK, tauK, squaredMagnitude, pointCurrent; + let pointAfter = getPoint(points, 0); + for(let i = 0; i < pointsLen - 1; ++i){ + pointCurrent = pointAfter; + pointAfter = getPoint(points, i + 1); + if (!pointCurrent || !pointAfter) { + continue; + } + if (almostEquals(deltaK[i], 0, EPSILON)) { + mK[i] = mK[i + 1] = 0; + continue; + } + alphaK = mK[i] / deltaK[i]; + betaK = mK[i + 1] / deltaK[i]; + squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); + if (squaredMagnitude <= 9) { + continue; + } + tauK = 3 / Math.sqrt(squaredMagnitude); + mK[i] = alphaK * tauK * deltaK[i]; + mK[i + 1] = betaK * tauK * deltaK[i]; + } +} +function monotoneCompute(points, mK, indexAxis = 'x') { + const valueAxis = getValueAxis(indexAxis); + const pointsLen = points.length; + let delta, pointBefore, pointCurrent; + let pointAfter = getPoint(points, 0); + for(let i = 0; i < pointsLen; ++i){ + pointBefore = pointCurrent; + pointCurrent = pointAfter; + pointAfter = getPoint(points, i + 1); + if (!pointCurrent) { + continue; + } + const iPixel = pointCurrent[indexAxis]; + const vPixel = pointCurrent[valueAxis]; + if (pointBefore) { + delta = (iPixel - pointBefore[indexAxis]) / 3; + pointCurrent[`cp1${indexAxis}`] = iPixel - delta; + pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i]; + } + if (pointAfter) { + delta = (pointAfter[indexAxis] - iPixel) / 3; + pointCurrent[`cp2${indexAxis}`] = iPixel + delta; + pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i]; + } + } +} +/** + * This function calculates Bézier control points in a similar way than |splineCurve|, + * but preserves monotonicity of the provided data and ensures no local extremums are added + * between the dataset discrete points due to the interpolation. + * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation + */ function splineCurveMonotone(points, indexAxis = 'x') { + const valueAxis = getValueAxis(indexAxis); + const pointsLen = points.length; + const deltaK = Array(pointsLen).fill(0); + const mK = Array(pointsLen); + // Calculate slopes (deltaK) and initialize tangents (mK) + let i, pointBefore, pointCurrent; + let pointAfter = getPoint(points, 0); + for(i = 0; i < pointsLen; ++i){ + pointBefore = pointCurrent; + pointCurrent = pointAfter; + pointAfter = getPoint(points, i + 1); + if (!pointCurrent) { + continue; + } + if (pointAfter) { + const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis]; + // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 + deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0; + } + mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : sign(deltaK[i - 1]) !== sign(deltaK[i]) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2; + } + monotoneAdjust(points, deltaK, mK); + monotoneCompute(points, mK, indexAxis); +} +function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); +} +function capBezierPoints(points, area) { + let i, ilen, point, inArea, inAreaPrev; + let inAreaNext = _isPointInArea(points[0], area); + for(i = 0, ilen = points.length; i < ilen; ++i){ + inAreaPrev = inArea; + inArea = inAreaNext; + inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area); + if (!inArea) { + continue; + } + point = points[i]; + if (inAreaPrev) { + point.cp1x = capControlPoint(point.cp1x, area.left, area.right); + point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom); + } + if (inAreaNext) { + point.cp2x = capControlPoint(point.cp2x, area.left, area.right); + point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom); + } + } +} +/** + * @private + */ function _updateBezierControlPoints(points, options, area, loop, indexAxis) { + let i, ilen, point, controlPoints; + // Only consider points that are drawn in case the spanGaps option is used + if (options.spanGaps) { + points = points.filter((pt)=>!pt.skip); + } + if (options.cubicInterpolationMode === 'monotone') { + splineCurveMonotone(points, indexAxis); + } else { + let prev = loop ? points[points.length - 1] : points[0]; + for(i = 0, ilen = points.length; i < ilen; ++i){ + point = points[i]; + controlPoints = splineCurve(prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension); + point.cp1x = controlPoints.previous.x; + point.cp1y = controlPoints.previous.y; + point.cp2x = controlPoints.next.x; + point.cp2y = controlPoints.next.y; + prev = point; + } + } + if (options.capBezierPoints) { + capBezierPoints(points, area); + } +} + +/** + * Note: typedefs are auto-exported, so use a made-up `dom` namespace where + * necessary to avoid duplicates with `export * from './helpers`; see + * https://github.com/microsoft/TypeScript/issues/46011 + * @typedef { import('../core/core.controller.js').default } dom.Chart + * @typedef { import('../../types').ChartEvent } ChartEvent + */ /** + * @private + */ function _isDomSupported() { + return typeof window !== 'undefined' && typeof document !== 'undefined'; +} +/** + * @private + */ function _getParentNode(domNode) { + let parent = domNode.parentNode; + if (parent && parent.toString() === '[object ShadowRoot]') { + parent = parent.host; + } + return parent; +} +/** + * convert max-width/max-height values that may be percentages into a number + * @private + */ function parseMaxStyle(styleValue, node, parentProperty) { + let valueInPixels; + if (typeof styleValue === 'string') { + valueInPixels = parseInt(styleValue, 10); + if (styleValue.indexOf('%') !== -1) { + // percentage * size in dimension + valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; + } + } else { + valueInPixels = styleValue; + } + return valueInPixels; +} +const getComputedStyle = (element)=>element.ownerDocument.defaultView.getComputedStyle(element, null); +function getStyle(el, property) { + return getComputedStyle(el).getPropertyValue(property); +} +const positions = [ + 'top', + 'right', + 'bottom', + 'left' +]; +function getPositionedStyle(styles, style, suffix) { + const result = {}; + suffix = suffix ? '-' + suffix : ''; + for(let i = 0; i < 4; i++){ + const pos = positions[i]; + result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0; + } + result.width = result.left + result.right; + result.height = result.top + result.bottom; + return result; +} +const useOffsetPos = (x, y, target)=>(x > 0 || y > 0) && (!target || !target.shadowRoot); +/** + * @param e + * @param canvas + * @returns Canvas position + */ function getCanvasPosition(e, canvas) { + const touches = e.touches; + const source = touches && touches.length ? touches[0] : e; + const { offsetX , offsetY } = source; + let box = false; + let x, y; + if (useOffsetPos(offsetX, offsetY, e.target)) { + x = offsetX; + y = offsetY; + } else { + const rect = canvas.getBoundingClientRect(); + x = source.clientX - rect.left; + y = source.clientY - rect.top; + box = true; + } + return { + x, + y, + box + }; +} +/** + * Gets an event's x, y coordinates, relative to the chart area + * @param event + * @param chart + * @returns x and y coordinates of the event + */ function getRelativePosition(event, chart) { + if ('native' in event) { + return event; + } + const { canvas , currentDevicePixelRatio } = chart; + const style = getComputedStyle(canvas); + const borderBox = style.boxSizing === 'border-box'; + const paddings = getPositionedStyle(style, 'padding'); + const borders = getPositionedStyle(style, 'border', 'width'); + const { x , y , box } = getCanvasPosition(event, canvas); + const xOffset = paddings.left + (box && borders.left); + const yOffset = paddings.top + (box && borders.top); + let { width , height } = chart; + if (borderBox) { + width -= paddings.width + borders.width; + height -= paddings.height + borders.height; + } + return { + x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio), + y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio) + }; +} +function getContainerSize(canvas, width, height) { + let maxWidth, maxHeight; + if (width === undefined || height === undefined) { + const container = _getParentNode(canvas); + if (!container) { + width = canvas.clientWidth; + height = canvas.clientHeight; + } else { + const rect = container.getBoundingClientRect(); // this is the border box of the container + const containerStyle = getComputedStyle(container); + const containerBorder = getPositionedStyle(containerStyle, 'border', 'width'); + const containerPadding = getPositionedStyle(containerStyle, 'padding'); + width = rect.width - containerPadding.width - containerBorder.width; + height = rect.height - containerPadding.height - containerBorder.height; + maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth'); + maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight'); + } + } + return { + width, + height, + maxWidth: maxWidth || INFINITY, + maxHeight: maxHeight || INFINITY + }; +} +const round1 = (v)=>Math.round(v * 10) / 10; +// eslint-disable-next-line complexity +function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) { + const style = getComputedStyle(canvas); + const margins = getPositionedStyle(style, 'margin'); + const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY; + const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY; + const containerSize = getContainerSize(canvas, bbWidth, bbHeight); + let { width , height } = containerSize; + if (style.boxSizing === 'content-box') { + const borders = getPositionedStyle(style, 'border', 'width'); + const paddings = getPositionedStyle(style, 'padding'); + width -= paddings.width + borders.width; + height -= paddings.height + borders.height; + } + width = Math.max(0, width - margins.width); + height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height); + width = round1(Math.min(width, maxWidth, containerSize.maxWidth)); + height = round1(Math.min(height, maxHeight, containerSize.maxHeight)); + if (width && !height) { + // https://github.com/chartjs/Chart.js/issues/4659 + // If the canvas has width, but no height, default to aspectRatio of 2 (canvas default) + height = round1(width / 2); + } + const maintainHeight = bbWidth !== undefined || bbHeight !== undefined; + if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) { + height = containerSize.height; + width = round1(Math.floor(height * aspectRatio)); + } + return { + width, + height + }; +} +/** + * @param chart + * @param forceRatio + * @param forceStyle + * @returns True if the canvas context size or transformation has changed. + */ function retinaScale(chart, forceRatio, forceStyle) { + const pixelRatio = forceRatio || 1; + const deviceHeight = Math.floor(chart.height * pixelRatio); + const deviceWidth = Math.floor(chart.width * pixelRatio); + chart.height = Math.floor(chart.height); + chart.width = Math.floor(chart.width); + const canvas = chart.canvas; + // If no style has been set on the canvas, the render size is used as display size, + // making the chart visually bigger, so let's enforce it to the "correct" values. + // See https://github.com/chartjs/Chart.js/issues/3575 + if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) { + canvas.style.height = `${chart.height}px`; + canvas.style.width = `${chart.width}px`; + } + if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) { + chart.currentDevicePixelRatio = pixelRatio; + canvas.height = deviceHeight; + canvas.width = deviceWidth; + chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + return true; + } + return false; +} +/** + * Detects support for options object argument in addEventListener. + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support + * @private + */ const supportsEventListenerOptions = function() { + let passiveSupported = false; + try { + const options = { + get passive () { + passiveSupported = true; + return false; + } + }; + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) { + // continue regardless of error + } + return passiveSupported; +}(); +/** + * The "used" size is the final value of a dimension property after all calculations have + * been performed. This method uses the computed style of `element` but returns undefined + * if the computed style is not expressed in pixels. That can happen in some cases where + * `element` has a size relative to its parent and this last one is not yet displayed, + * for example because of `display: none` on a parent node. + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value + * @returns Size in pixels or undefined if unknown. + */ function readUsedSize(element, property) { + const value = getStyle(element, property); + const matches = value && value.match(/^(\d+)(\.\d+)?px$/); + return matches ? +matches[1] : undefined; +} + +/** + * @private + */ function _pointInLine(p1, p2, t, mode) { + return { + x: p1.x + t * (p2.x - p1.x), + y: p1.y + t * (p2.y - p1.y) + }; +} +/** + * @private + */ function _steppedInterpolation(p1, p2, t, mode) { + return { + x: p1.x + t * (p2.x - p1.x), + y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y : mode === 'after' ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y + }; +} +/** + * @private + */ function _bezierInterpolation(p1, p2, t, mode) { + const cp1 = { + x: p1.cp2x, + y: p1.cp2y + }; + const cp2 = { + x: p2.cp1x, + y: p2.cp1y + }; + const a = _pointInLine(p1, cp1, t); + const b = _pointInLine(cp1, cp2, t); + const c = _pointInLine(cp2, p2, t); + const d = _pointInLine(a, b, t); + const e = _pointInLine(b, c, t); + return _pointInLine(d, e, t); +} + +const getRightToLeftAdapter = function(rectX, width) { + return { + x (x) { + return rectX + rectX + width - x; + }, + setWidth (w) { + width = w; + }, + textAlign (align) { + if (align === 'center') { + return align; + } + return align === 'right' ? 'left' : 'right'; + }, + xPlus (x, value) { + return x - value; + }, + leftForLtr (x, itemWidth) { + return x - itemWidth; + } + }; +}; +const getLeftToRightAdapter = function() { + return { + x (x) { + return x; + }, + setWidth (w) {}, + textAlign (align) { + return align; + }, + xPlus (x, value) { + return x + value; + }, + leftForLtr (x, _itemWidth) { + return x; + } + }; +}; +function getRtlAdapter(rtl, rectX, width) { + return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter(); +} +function overrideTextDirection(ctx, direction) { + let style, original; + if (direction === 'ltr' || direction === 'rtl') { + style = ctx.canvas.style; + original = [ + style.getPropertyValue('direction'), + style.getPropertyPriority('direction') + ]; + style.setProperty('direction', direction, 'important'); + ctx.prevTextDirection = original; + } +} +function restoreTextDirection(ctx, original) { + if (original !== undefined) { + delete ctx.prevTextDirection; + ctx.canvas.style.setProperty('direction', original[0], original[1]); + } +} + +function propertyFn(property) { + if (property === 'angle') { + return { + between: _angleBetween, + compare: _angleDiff, + normalize: _normalizeAngle + }; + } + return { + between: _isBetween, + compare: (a, b)=>a - b, + normalize: (x)=>x + }; +} +function normalizeSegment({ start , end , count , loop , style }) { + return { + start: start % count, + end: end % count, + loop: loop && (end - start + 1) % count === 0, + style + }; +} +function getSegment(segment, points, bounds) { + const { property , start: startBound , end: endBound } = bounds; + const { between , normalize } = propertyFn(property); + const count = points.length; + let { start , end , loop } = segment; + let i, ilen; + if (loop) { + start += count; + end += count; + for(i = 0, ilen = count; i < ilen; ++i){ + if (!between(normalize(points[start % count][property]), startBound, endBound)) { + break; + } + start--; + end--; + } + start %= count; + end %= count; + } + if (end < start) { + end += count; + } + return { + start, + end, + loop, + style: segment.style + }; +} + function _boundSegment(segment, points, bounds) { + if (!bounds) { + return [ + segment + ]; + } + const { property , start: startBound , end: endBound } = bounds; + const count = points.length; + const { compare , between , normalize } = propertyFn(property); + const { start , end , loop , style } = getSegment(segment, points, bounds); + const result = []; + let inside = false; + let subStart = null; + let value, point, prevValue; + const startIsBefore = ()=>between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0; + const endIsBefore = ()=>compare(endBound, value) === 0 || between(endBound, prevValue, value); + const shouldStart = ()=>inside || startIsBefore(); + const shouldStop = ()=>!inside || endIsBefore(); + for(let i = start, prev = start; i <= end; ++i){ + point = points[i % count]; + if (point.skip) { + continue; + } + value = normalize(point[property]); + if (value === prevValue) { + continue; + } + inside = between(value, startBound, endBound); + if (subStart === null && shouldStart()) { + subStart = compare(value, startBound) === 0 ? i : prev; + } + if (subStart !== null && shouldStop()) { + result.push(normalizeSegment({ + start: subStart, + end: i, + loop, + count, + style + })); + subStart = null; + } + prev = i; + prevValue = value; + } + if (subStart !== null) { + result.push(normalizeSegment({ + start: subStart, + end, + loop, + count, + style + })); + } + return result; +} + function _boundSegments(line, bounds) { + const result = []; + const segments = line.segments; + for(let i = 0; i < segments.length; i++){ + const sub = _boundSegment(segments[i], line.points, bounds); + if (sub.length) { + result.push(...sub); + } + } + return result; +} + function findStartAndEnd(points, count, loop, spanGaps) { + let start = 0; + let end = count - 1; + if (loop && !spanGaps) { + while(start < count && !points[start].skip){ + start++; + } + } + while(start < count && points[start].skip){ + start++; + } + start %= count; + if (loop) { + end += start; + } + while(end > start && points[end % count].skip){ + end--; + } + end %= count; + return { + start, + end + }; +} + function solidSegments(points, start, max, loop) { + const count = points.length; + const result = []; + let last = start; + let prev = points[start]; + let end; + for(end = start + 1; end <= max; ++end){ + const cur = points[end % count]; + if (cur.skip || cur.stop) { + if (!prev.skip) { + loop = false; + result.push({ + start: start % count, + end: (end - 1) % count, + loop + }); + start = last = cur.stop ? end : null; + } + } else { + last = end; + if (prev.skip) { + start = end; + } + } + prev = cur; + } + if (last !== null) { + result.push({ + start: start % count, + end: last % count, + loop + }); + } + return result; +} + function _computeSegments(line, segmentOptions) { + const points = line.points; + const spanGaps = line.options.spanGaps; + const count = points.length; + if (!count) { + return []; + } + const loop = !!line._loop; + const { start , end } = findStartAndEnd(points, count, loop, spanGaps); + if (spanGaps === true) { + return splitByStyles(line, [ + { + start, + end, + loop + } + ], points, segmentOptions); + } + const max = end < start ? end + count : end; + const completeLoop = !!line._fullLoop && start === 0 && end === count - 1; + return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions); +} + function splitByStyles(line, segments, points, segmentOptions) { + if (!segmentOptions || !segmentOptions.setContext || !points) { + return segments; + } + return doSplitByStyles(line, segments, points, segmentOptions); +} + function doSplitByStyles(line, segments, points, segmentOptions) { + const chartContext = line._chart.getContext(); + const baseStyle = readStyle(line.options); + const { _datasetIndex: datasetIndex , options: { spanGaps } } = line; + const count = points.length; + const result = []; + let prevStyle = baseStyle; + let start = segments[0].start; + let i = start; + function addStyle(s, e, l, st) { + const dir = spanGaps ? -1 : 1; + if (s === e) { + return; + } + s += count; + while(points[s % count].skip){ + s -= dir; + } + while(points[e % count].skip){ + e += dir; + } + if (s % count !== e % count) { + result.push({ + start: s % count, + end: e % count, + loop: l, + style: st + }); + prevStyle = st; + start = e % count; + } + } + for (const segment of segments){ + start = spanGaps ? start : segment.start; + let prev = points[start % count]; + let style; + for(i = start + 1; i <= segment.end; i++){ + const pt = points[i % count]; + style = readStyle(segmentOptions.setContext(createContext(chartContext, { + type: 'segment', + p0: prev, + p1: pt, + p0DataIndex: (i - 1) % count, + p1DataIndex: i % count, + datasetIndex + }))); + if (styleChanged(style, prevStyle)) { + addStyle(start, i - 1, segment.loop, prevStyle); + } + prev = pt; + prevStyle = style; + } + if (start < i - 1) { + addStyle(start, i - 1, segment.loop, prevStyle); + } + } + return result; +} +function readStyle(options) { + return { + backgroundColor: options.backgroundColor, + borderCapStyle: options.borderCapStyle, + borderDash: options.borderDash, + borderDashOffset: options.borderDashOffset, + borderJoinStyle: options.borderJoinStyle, + borderWidth: options.borderWidth, + borderColor: options.borderColor + }; +} +function styleChanged(style, prevStyle) { + if (!prevStyle) { + return false; + } + const cache = []; + const replacer = function(key, value) { + if (!isPatternOrGradient(value)) { + return value; + } + if (!cache.includes(value)) { + cache.push(value); + } + return cache.indexOf(value); + }; + return JSON.stringify(style, replacer) !== JSON.stringify(prevStyle, replacer); +} + + +//# sourceMappingURL=helpers.segment.js.map + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!************************************!*\ + !*** ./public/javascripts/main.js ***! + \************************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var chart_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! chart.js */ "./node_modules/chart.js/dist/chart.js"); + + + + +// Define color ranges for the different value ranges +const colorRanges = { + good: 'rgba(154, 204, 91, 0.2)', + moderate: 'rgba(255, 235, 59, 0.2)', + unhealthySensitive: 'rgba(255, 152, 0, 0.2)', + unhealthy: 'rgba(255, 59, 59, 0.2)', + veryUnhealthy: 'rgba(143, 63, 151, 0.2)', + hazardous: 'rgba(126, 10, 2, 0.2)', +}; + +// Define the annotations +const annotations = { + drawTime: 'beforeDatasetsDraw', + annotations: [ + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 0, + yMax: 12, + backgroundColor: colorRanges.good, + }, + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 12.1, + yMax: 35.4, + backgroundColor: colorRanges.moderate, + }, + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 35.5, + yMax: 55.4, + backgroundColor: colorRanges.unhealthySensitive, + }, + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 55.5, + yMax: 150.4, + backgroundColor: colorRanges.unhealthy, + }, + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 150.5, + yMax: 250.4, + backgroundColor: colorRanges.veryUnhealthy, + }, + { + type: 'box', + yScaleID: 'y-axis-0', + yMin: 250.5, + yMax: 500.4, + backgroundColor: colorRanges.hazardous, + }, + ], +}; + + +// Initialisiere das Chart-Objekt +var ctx = document.getElementById('chart').getContext('2d'); +var chart = new chart_js__WEBPACK_IMPORTED_MODULE_0__.Chart(ctx, { + // Art des Diagramms + type: 'line', + + // Daten + data: { + labels: [], + datasets: [{ + label: 'PM2.5', + data: [], + backgroundColor: 'rgba(255, 99, 132, 0.2)', + borderColor: 'rgba(255,99,132,1)', + borderWidth: 1, + pointRadius: 0, + fill: false + }, { + label: 'PM10', + data: [], + backgroundColor: 'rgba(54, 162, 235, 0.2)', + borderColor: 'rgba(54, 162, 235, 1)', + borderWidth: 1, + pointRadius: 0, + fill: false + }] + }, + + // Konfigurationsoptionen + options: { + maintainAspectRatio: false, + responsive: true, + title: { + display: true, + text: 'Feinstaubwerte' + }, + scales: { + x: { + /*type: 'time', + time: { + unit: 'hour', + displayFormats: { + hour: 'MMM D, hA' + } + },*/ + display: true + }, + y: { + display: true, + scaleLabel: { + display: true, + labelString: 'µg/m³' + }, + beginAtZero: true, + suggestedMin: 0, + suggestedMax: 10 + } + } + }, + plugins: { + annotation: annotations + }, +}); + +// Funktion zum Hinzufügen neuer Datenpunkte +function addData(time, pm25, pm10) { + // Füge die neuen Datenpunkte hinzu + chart.data.labels.push(time); + chart.data.datasets[0].data.push(pm25); + chart.data.datasets[1].data.push(pm10); + + // Begrenze die Anzahl der Datenpunkte auf 100 oder die letzten 12 Stunden + var maxPoints = 100; + var maxTime = new Date(); + maxTime.setHours(maxTime.getHours() - 12); + + while (chart.data.labels.length > maxPoints || (chart.data.labels.length > 0 && new Date(chart.data.labels[0]) < maxTime)) { + chart.data.labels.shift(); + chart.data.datasets[0].data.shift(); + chart.data.datasets[1].data.shift(); + } + + // Aktualisiere das Chart + chart.update(); +} + + + +setInterval(( ) => { + addData(new Date().toLocaleTimeString(), 1+Math.floor(Math.random() *2), 3+Math.floor(Math.random() * 2)); +}, 1000) +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssU0FBUztBQUMzQyxhQUFhLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRTtBQUM1Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsaUJBQWlCO0FBQy9CO0FBQ0EsZ0JBQWdCLGtCQUFrQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsSUFBSSxJQUFJLElBQUksSUFBSSxJQUFJLElBQUksU0FBUztBQUNqRCxlQUFlLElBQUksSUFBSSxJQUFJLElBQUksSUFBSTtBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLHNCQUFzQix1QkFBdUI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFa007Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDNWtCbE07QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ2lsRTtBQUMxakU7O0FBRXZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsOERBQXFCO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixRQUFRO0FBQzFCO0FB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCxVQUFVO0FBQzdEO0FBQ0E7QUFDQSw0QkFBNEIsNkRBQVk7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSw2REFBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxVQUFVO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLFVBQVU7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsNkRBQWE7QUFDckI7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0MsNkRBQWM7QUFDOUM7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLDZEQUFTO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDZEQUFTO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLDZEQUFhO0FBQzdCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDtBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsNkRBQWM7QUFDN0I7QUFDQTtBQUNBLDBCQUEwQiw2REFBYztBQUN4QztB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O0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSx3QkFBd0I7QUFDcEMsWUFBWSx3QkFBd0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLDBEQUFxQjtBQUNwQztBQUNBO0FBQ0EsZUFBZSwwREFBb0I7QUFDbkM7QUFDQSxXQUFXLDBEQUFZO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxzQkFBc0I7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLDhEQUEwQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQiw2QkFBNkI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7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QSw2Q0FBNkMsVUFBVTtBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsVUFBVTtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFK3RCO0FBQy90Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUMvcFdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNzQzs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsUUFBUTtBQUNyQztBQUNBO0FBQ0EsVUFBVTtBQUNWLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxVQUFVO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFVBQVU7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFVBQVU7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyxVQUFVO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLFVBQVU7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsVUFBVTtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLG9CQUFvQjtBQUNwQztBQUNBLGdCQUFnQix1Q0FBdUM7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0EsWUFBWSxrQ0FBa0M7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0QsZ0RBQUs7QUFDekQ7QUFDQTtBQUNBLG9EQUFvRCxnREFBSztBQUN6RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxPQUFPO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsVUFBVTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0EsNENBQTRDLFVBQVU7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixXQUFXO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxrQkFBa0I7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwwQkFBMEI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsVUFBVTtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxhQUFhO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakMsaUNBQWlDO0FBQ2pDLG9DQUFvQztBQUNwQztBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0RBQWtEO0FBQ2xELGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakMsZ0NBQWdDO0FBQ2hDO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakMsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFlBQVksa0dBQWtHO0FBQzlHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLDZEQUE2RDtBQUN6RSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksMENBQTBDO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSw2REFBNkQ7QUFDekU7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxVQUFVO0FBQ3RCLFlBQVksWUFBWTtBQUN4QjtBQUNBO0FBQ0EsNkJBQTZCLFVBQVU7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixlQUFlO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFVBQVU7QUFDekMsK0JBQStCLFVBQVU7QUFDekM7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFVBQVU7QUFDekMsK0JBQStCLFVBQVU7QUFDekM7QUFDQTtBQUNB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QSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxnQkFBZ0IsMkNBQUs7QUFDckI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQSxDQUFDLE8iLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9wbTI1Ly4vbm9kZV9tb2R1bGVzL0BrdXJrbGUvY29sb3IvZGlzdC9jb2xvci5lc20uanMiLCJ3ZWJwYWNrOi8vcG0yNS8uL25vZGVfbW9kdWxlcy9jaGFydC5qcy9kaXN0L2NoYXJ0LmpzIiwid2VicGFjazovL3BtMjUvLi9ub2RlX21vZHVsZXMvY2hhcnQuanMvZGlzdC9jaHVua3MvaGVscGVycy5zZWdtZW50LmpzIiwid2VicGFjazovL3BtMjUvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vcG0yNS93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vcG0yNS93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL3BtMjUvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9wbTI1Ly4vcHVibGljL2phdmFzY3JpcHRzL21haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAa3Vya2xlL2NvbG9yIHYwLjMuMlxuICogaHR0cHM6Ly9naXRodWIuY29tL2t1cmtsZS9jb2xvciNyZWFkbWVcbiAqIChjKSAyMDIzIEp1a2thIEt1cmtlbGFcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICovXG5mdW5jdGlvbiByb3VuZCh2KSB7XG4gIHJldHVybiB2ICsgMC41IHwgMDtcbn1cbmNvbnN0IGxpbSA9ICh2LCBsLCBoKSA9PiBNYXRoLm1heChNYXRoLm1pbih2LCBoKSwgbCk7XG5mdW5jdGlvbiBwMmIodikge1xuICByZXR1cm4gbGltKHJvdW5kKHYgKiAyLjU1KSwgMCwgMjU1KTtcbn1cbmZ1bmN0aW9uIGIycCh2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAvIDIuNTUpLCAwLCAxMDApO1xufVxuZnVuY3Rpb24gbjJiKHYpIHtcbiAgcmV0dXJuIGxpbShyb3VuZCh2ICogMjU1KSwgMCwgMjU1KTtcbn1cbmZ1bmN0aW9uIGIybih2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAvIDIuNTUpIC8gMTAwLCAwLCAxKTtcbn1cbmZ1bmN0aW9uIG4ycCh2KSB7XG4gIHJldHVybiBsaW0ocm91bmQodiAqIDEwMCksIDAsIDEwMCk7XG59XG5cbmNvbnN0IG1hcCQxID0gezA6IDAsIDE6IDEsIDI6IDIsIDM6IDMsIDQ6IDQsIDU6IDUsIDY6IDYsIDc6IDcsIDg6IDgsIDk6IDksIEE6IDEwLCBCOiAxMSwgQzogMTIsIEQ6IDEzLCBFOiAxNCwgRjogMTUsIGE6IDEwLCBiOiAxMSwgYzogMTIsIGQ6IDEzLCBlOiAxNCwgZjogMTV9O1xuY29uc3QgaGV4ID0gWy4uLicwMTIzNDU2Nzg5QUJDREVGJ107XG5jb25zdCBoMSA9IGIgPT4gaGV4W2IgJiAweEZdO1xuY29uc3QgaDIgPSBiID0+IGhleFsoYiAmIDB4RjApID4+IDRdICsgaGV4W2IgJiAweEZdO1xuY29uc3QgZXEgPSBiID0+ICgoYiAmIDB4RjApID4+IDQpID09PSAoYiAmIDB4Rik7XG5jb25zdCBpc1Nob3J0ID0gdiA9PiBlcSh2LnIpICYmIGVxKHYuZykgJiYgZXEodi5iKSAmJiBlcSh2LmEpO1xuZnVuY3Rpb24gaGV4UGFyc2Uoc3RyKSB7XG4gIHZhciBsZW4gPSBzdHIubGVuZ3RoO1xuICB2YXIgcmV0O1xuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAobGVuID09PSA0IHx8IGxlbiA9PT0gNSkge1xuICAgICAgcmV0ID0ge1xuICAgICAgICByOiAyNTUgJiBtYXAkMVtzdHJbMV1dICogMTcsXG4gICAgICAgIGc6IDI1NSAmIG1hcCQxW3N0clsyXV0gKiAxNyxcbiAgICAgICAgYjogMjU1ICYgbWFwJDFbc3RyWzNdXSAqIDE3LFxuICAgICAgICBhOiBsZW4gPT09IDUgPyBtYXAkMVtzdHJbNF1dICogMTcgOiAyNTVcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChsZW4gPT09IDcgfHwgbGVuID09PSA5KSB7XG4gICAgICByZXQgPSB7XG4gICAgICAgIHI6IG1hcCQxW3N0clsxXV0gPDwgNCB8IG1hcCQxW3N0clsyXV0sXG4gICAgICAgIGc6IG1hcCQxW3N0clszXV0gPDwgNCB8IG1hcCQxW3N0cls0XV0sXG4gICAgICAgIGI6IG1hcCQxW3N0cls1XV0gPDwgNCB8IG1hcCQxW3N0cls2XV0sXG4gICAgICAgIGE6IGxlbiA9PT0gOSA/IChtYXAkMVtzdHJbN11dIDw8IDQgfCBtYXAkMVtzdHJbOF1dKSA6IDI1NVxuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cbmNvbnN0IGFscGhhID0gKGEsIGYpID0+IGEgPCAyNTUgPyBmKGEpIDogJyc7XG5mdW5jdGlvbiBoZXhTdHJpbmcodikge1xuICB2YXIgZiA9IGlzU2hvcnQodikgPyBoMSA6IGgyO1xuICByZXR1cm4gdlxuICAgID8gJyMnICsgZih2LnIpICsgZih2LmcpICsgZih2LmIpICsgYWxwaGEodi5hLCBmKVxuICAgIDogdW5kZWZpbmVkO1xufVxuXG5jb25zdCBIVUVfUkUgPSAvXihoc2xhP3xod2J8aHN2KVxcKFxccyooWy0rLmVcXGRdKykoPzpkZWcpP1tcXHMsXSsoWy0rLmVcXGRdKyklW1xccyxdKyhbLSsuZVxcZF0rKSUoPzpbXFxzLF0rKFstKy5lXFxkXSspKCUpPyk/XFxzKlxcKSQvO1xuZnVuY3Rpb24gaHNsMnJnYm4oaCwgcywgbCkge1xuICBjb25zdCBhID0gcyAqIE1hdGgubWluKGwsIDEgLSBsKTtcbiAgY29uc3QgZiA9IChuLCBrID0gKG4gKyBoIC8gMzApICUgMTIpID0+IGwgLSBhICogTWF0aC5tYXgoTWF0aC5taW4oayAtIDMsIDkgLSBrLCAxKSwgLTEpO1xuICByZXR1cm4gW2YoMCksIGYoOCksIGYoNCldO1xufVxuZnVuY3Rpb24gaHN2MnJnYm4oaCwgcywgdikge1xuICBjb25zdCBmID0gKG4sIGsgPSAobiArIGggLyA2MCkgJSA2KSA9PiB2IC0gdiAqIHMgKiBNYXRoLm1heChNYXRoLm1pbihrLCA0IC0gaywgMSksIDApO1xuICByZXR1cm4gW2YoNSksIGYoMyksIGYoMSldO1xufVxuZnVuY3Rpb24gaHdiMnJnYm4oaCwgdywgYikge1xuICBjb25zdCByZ2IgPSBoc2wycmdibihoLCAxLCAwLjUpO1xuICBsZXQgaTtcbiAgaWYgKHcgKyBiID4gMSkge1xuICAgIGkgPSAxIC8gKHcgKyBiKTtcbiAgICB3ICo9IGk7XG4gICAgYiAqPSBpO1xuICB9XG4gIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICByZ2JbaV0gKj0gMSAtIHcgLSBiO1xuICAgIHJnYltpXSArPSB3O1xuICB9XG4gIHJldHVybiByZ2I7XG59XG5mdW5jdGlvbiBodWVWYWx1ZShyLCBnLCBiLCBkLCBtYXgpIHtcbiAgaWYgKHIgPT09IG1heCkge1xuICAgIHJldHVybiAoKGcgLSBiKSAvIGQpICsgKGcgPCBiID8gNiA6IDApO1xuICB9XG4gIGlmIChnID09PSBtYXgpIHtcbiAgICByZXR1cm4gKGIgLSByKSAvIGQgKyAyO1xuICB9XG4gIHJldHVybiAociAtIGcpIC8gZCArIDQ7XG59XG5mdW5jdGlvbiByZ2IyaHNsKHYpIHtcbiAgY29uc3QgcmFuZ2UgPSAyNTU7XG4gIGNvbnN0IHIgPSB2LnIgLyByYW5nZTtcbiAgY29uc3QgZyA9IHYuZyAvIHJhbmdlO1xuICBjb25zdCBiID0gdi5iIC8gcmFuZ2U7XG4gIGNvbnN0IG1heCA9IE1hdGgubWF4KHIsIGcsIGIpO1xuICBjb25zdCBtaW4gPSBNYXRoLm1pbihyLCBnLCBiKTtcbiAgY29uc3QgbCA9IChtYXggKyBtaW4pIC8gMjtcbiAgbGV0IGgsIHMsIGQ7XG4gIGlmIChtYXggIT09IG1pbikge1xuICAgIGQgPSBtYXggLSBtaW47XG4gICAgcyA9IGwgPiAwLjUgPyBkIC8gKDIgLSBtYXggLSBtaW4pIDogZCAvIChtYXggKyBtaW4pO1xuICAgIGggPSBodWVWYWx1ZShyLCBnLCBiLCBkLCBtYXgpO1xuICAgIGggPSBoICogNjAgKyAwLjU7XG4gIH1cbiAgcmV0dXJuIFtoIHwgMCwgcyB8fCAwLCBsXTtcbn1cbmZ1bmN0aW9uIGNhbGxuKGYsIGEsIGIsIGMpIHtcbiAgcmV0dXJuIChcbiAgICBBcnJheS5pc0FycmF5KGEpXG4gICAgICA/IGYoYVswXSwgYVsxXSwgYVsyXSlcbiAgICAgIDogZihhLCBiLCBjKVxuICApLm1hcChuMmIpO1xufVxuZnVuY3Rpb24gaHNsMnJnYihoLCBzLCBsKSB7XG4gIHJldHVybiBjYWxsbihoc2wycmdibiwgaCwgcywgbCk7XG59XG5mdW5jdGlvbiBod2IycmdiKGgsIHcsIGIpIHtcbiAgcmV0dXJuIGNhbGxuKGh3YjJyZ2JuLCBoLCB3LCBiKTtcbn1cbmZ1bmN0aW9uIGhzdjJyZ2IoaCwgcywgdikge1xuICByZXR1cm4gY2FsbG4oaHN2MnJnYm4sIGgsIHMsIHYpO1xufVxuZnVuY3Rpb24gaHVlKGgpIHtcbiAgcmV0dXJuIChoICUgMzYwICsgMzYwKSAlIDM2MDtcbn1cbmZ1bmN0aW9uIGh1ZVBhcnNlKHN0cikge1xuICBjb25zdCBtID0gSFVFX1JFLmV4ZWMoc3RyKTtcbiAgbGV0IGEgPSAyNTU7XG4gIGxldCB2O1xuICBpZiAoIW0pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKG1bNV0gIT09IHYpIHtcbiAgICBhID0gbVs2XSA/IHAyYigrbVs1XSkgOiBuMmIoK21bNV0pO1xuICB9XG4gIGNvbnN0IGggPSBodWUoK21bMl0pO1xuICBjb25zdCBwMSA9ICttWzNdIC8gMTAwO1xuICBjb25zdCBwMiA9ICttWzRdIC8gMTAwO1xuICBpZiAobVsxXSA9PT0gJ2h3YicpIHtcbiAgICB2ID0gaHdiMnJnYihoLCBwMSwgcDIpO1xuICB9IGVsc2UgaWYgKG1bMV0gPT09ICdoc3YnKSB7XG4gICAgdiA9IGhzdjJyZ2IoaCwgcDEsIHAyKTtcbiAgfSBlbHNlIHtcbiAgICB2ID0gaHNsMnJnYihoLCBwMSwgcDIpO1xuICB9XG4gIHJldHVybiB7XG4gICAgcjogdlswXSxcbiAgICBnOiB2WzFdLFxuICAgIGI6IHZbMl0sXG4gICAgYTogYVxuICB9O1xufVxuZnVuY3Rpb24gcm90YXRlKHYsIGRlZykge1xuICB2YXIgaCA9IHJnYjJoc2wodik7XG4gIGhbMF0gPSBodWUoaFswXSArIGRlZyk7XG4gIGggPSBoc2wycmdiKGgpO1xuICB2LnIgPSBoWzBdO1xuICB2LmcgPSBoWzFdO1xuICB2LmIgPSBoWzJdO1xufVxuZnVuY3Rpb24gaHNsU3RyaW5nKHYpIHtcbiAgaWYgKCF2KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IGEgPSByZ2IyaHNsKHYpO1xuICBjb25zdCBoID0gYVswXTtcbiAgY29uc3QgcyA9IG4ycChhWzFdKTtcbiAgY29uc3QgbCA9IG4ycChhWzJdKTtcbiAgcmV0dXJuIHYuYSA8IDI1NVxuICAgID8gYGhzbGEoJHtofSwgJHtzfSUsICR7bH0lLCAke2Iybih2LmEpfSlgXG4gICAgOiBgaHNsKCR7aH0sICR7c30lLCAke2x9JSlgO1xufVxuXG5jb25zdCBtYXAgPSB7XG4gIHg6ICdkYXJrJyxcbiAgWjogJ2xpZ2h0JyxcbiAgWTogJ3JlJyxcbiAgWDogJ2JsdScsXG4gIFc6ICdncicsXG4gIFY6ICdtZWRpdW0nLFxuICBVOiAnc2xhdGUnLFxuICBBOiAnZWUnLFxuICBUOiAnb2wnLFxuICBTOiAnb3InLFxuICBCOiAncmEnLFxuICBDOiAnbGF0ZWcnLFxuICBEOiAnaWdodHMnLFxuICBSOiAnaW4nLFxuICBROiAndHVycXVvaXMnLFxuICBFOiAnaGknLFxuICBQOiAncm8nLFxuICBPOiAnYWwnLFxuICBOOiAnbGUnLFxuICBNOiAnZGUnLFxuICBMOiAneWVsbG8nLFxuICBGOiAnZW4nLFxuICBLOiAnY2gnLFxuICBHOiAnYXJrcycsXG4gIEg6ICdlYScsXG4gIEk6ICdpZ2h0ZycsXG4gIEo6ICd3aCdcbn07XG5jb25zdCBuYW1lcyQxID0ge1xuICBPaWNlWGU6ICdmMGY4ZmYnLFxuICBhbnRpcXVld0V0ZTogJ2ZhZWJkNycsXG4gIGFxdWE6ICdmZmZmJyxcbiAgYXF1YW1hclJlOiAnN2ZmZmQ0JyxcbiAgYXp1WTogJ2YwZmZmZicsXG4gIGJlaWdlOiAnZjVmNWRjJyxcbiAgYmlzcXVlOiAnZmZlNGM0JyxcbiAgYmxhY2s6ICcwJyxcbiAgYmxhbktlZE9tb25kOiAnZmZlYmNkJyxcbiAgWGU6ICdmZicsXG4gIFhldmlUZXQ6ICc4YTJiZTInLFxuICBiUHduOiAnYTUyYTJhJyxcbiAgYnVybHl3b29kOiAnZGViODg3JyxcbiAgY2FNdFhlOiAnNWY5ZWEwJyxcbiAgS2FydFl1c2U6ICc3ZmZmMDAnLFxuICBLb2NUYXRlOiAnZDI2OTFlJyxcbiAgY1NPOiAnZmY3ZjUwJyxcbiAgY1NuZmxvd2VyWGU6ICc2NDk1ZWQnLFxuICBjU25zaWxrOiAnZmZmOGRjJyxcbiAgY3JpbXNvbjogJ2RjMTQzYycsXG4gIGN5YW46ICdmZmZmJyxcbiAgeFhlOiAnOGInLFxuICB4Y3lhbjogJzhiOGInLFxuICB4Z1RNblBkOiAnYjg4NjBiJyxcbiAgeFdheTogJ2E5YTlhOScsXG4gIHhnWUY6ICc2NDAwJyxcbiAgeGdZeTogJ2E5YTlhOScsXG4gIHhraGFraTogJ2JkYjc2YicsXG4gIHhtYWdGdGE6ICc4YjAwOGInLFxuICB4VGl2ZWdZRjogJzU1NmIyZicsXG4gIHhTYW5nZTogJ2ZmOGMwMCcsXG4gIHhTY0VkOiAnOTkzMmNjJyxcbiAgeFlkOiAnOGIwMDAwJyxcbiAgeHNPbW9uOiAnZTk5NjdhJyxcbiAgeHNIZ1lGOiAnOGZiYzhmJyxcbiAgeFVYZTogJzQ4M2Q4YicsXG4gIHhVV2F5OiAnMmY0ZjRmJyxcbiAgeFVnWXk6ICcyZjRmNGYnLFxuICB4UWU6ICdjZWQxJyxcbiAgeHZpVGV0OiAnOTQwMGQzJyxcbiAgZEFwcFJrOiAnZmYxNDkzJyxcbiAgZEFwc2t5WGU6ICdiZmZmJyxcbiAgZGltV2F5OiAnNjk2OTY5JyxcbiAgZGltZ1l5OiAnNjk2OTY5JyxcbiAgZG9kZ2VyWGU6ICcxZTkwZmYnLFxuICBmaVlicmljazogJ2IyMjIyMicsXG4gIGZsU093RXRlOiAnZmZmYWYwJyxcbiAgZm9Zc3RXQW46ICcyMjhiMjInLFxuICBmdUtzaWE6ICdmZjAwZmYnLFxuICBnYVJzYlNvOiAnZGNkY2RjJyxcbiAgZ2hvc3R3RXRlOiAnZjhmOGZmJyxcbiAgZ1RkOiAnZmZkNzAwJyxcbiAgZ1RNblBkOiAnZGFhNTIwJyxcbiAgV2F5OiAnODA4MDgwJyxcbiAgZ1lGOiAnODAwMCcsXG4gIGdZRkx3OiAnYWRmZjJmJyxcbiAgZ1l5OiAnODA4MDgwJyxcbiAgaG9uZXlNdzogJ2YwZmZmMCcsXG4gIGhvdHBSazogJ2ZmNjliNCcsXG4gIFJkaWFuWWQ6ICdjZDVjNWMnLFxuICBSZGlnbzogJzRiMDA4MicsXG4gIGl2U3k6ICdmZmZmZjAnLFxuICBraGFraTogJ2YwZTY4YycsXG4gIGxhdkZNcjogJ2U2ZTZmYScsXG4gIGxhdkZNclhzaDogJ2ZmZjBmNScsXG4gIGxhd25nWUY6ICc3Y2ZjMDAnLFxuICBObW9uY0VmZm9uOiAnZmZmYWNkJyxcbiAgWlhlOiAnYWRkOGU2JyxcbiAgWmNTTzogJ2YwODA4MCcsXG4gIFpjeWFuOiAnZTBmZmZmJyxcbiAgWmdUTW5QZEx3OiAnZmFmYWQyJyxcbiAgWldheTogJ2QzZDNkMycsXG4gIFpnWUY6ICc5MGVlOTAnLFxuICBaZ1l5OiAnZDNkM2QzJyxcbiAgWnBSazogJ2ZmYjZjMScsXG4gIFpzT21vbjogJ2ZmYTA3YScsXG4gIFpzSGdZRjogJzIwYjJhYScsXG4gIFpza3lYZTogJzg3Y2VmYScsXG4gIFpVV2F5OiAnNzc4ODk5JyxcbiAgWlVnWXk6ICc3Nzg4OTknLFxuICBac3RBbFhlOiAnYjBjNGRlJyxcbiAgWkx3OiAnZmZmZmUwJyxcbiAgbGltZTogJ2ZmMDAnLFxuICBsaW1lZ1lGOiAnMzJjZDMyJyxcbiAgbFJGOiAnZmFmMGU2JyxcbiAgbWFnRnRhOiAnZmYwMGZmJyxcbiAgbWFQb246ICc4MDAwMDAnLFxuICBWYXF1YW1hclJlOiAnNjZjZGFhJyxcbiAgVlhlOiAnY2QnLFxuICBWU2NFZDogJ2JhNTVkMycsXG4gIFZwdXJwTjogJzkzNzBkYicsXG4gIFZzSGdZRjogJzNjYjM3MScsXG4gIFZVWGU6ICc3YjY4ZWUnLFxuICBWc3ByUmdnWUY6ICdmYTlhJyxcbiAgVlFlOiAnNDhkMWNjJyxcbiAgVnZpVGV0WWQ6ICdjNzE1ODUnLFxuICBtaWRuaWdodFhlOiAnMTkxOTcwJyxcbiAgbVJ0Y1lhbTogJ2Y1ZmZmYScsXG4gIG1pc3R5UHNlOiAnZmZlNGUxJyxcbiAgbW9jY2FzUjogJ2ZmZTRiNScsXG4gIG5hdmFqb3dFdGU6ICdmZmRlYWQnLFxuICBuYXZ5OiAnODAnLFxuICBUZGxhY2U6ICdmZGY1ZTYnLFxuICBUaXZlOiAnODA4MDAwJyxcbiAgVGl2ZWRCYjogJzZiOGUyMycsXG4gIFNhbmdlOiAnZmZhNTAwJyxcbiAgU2FuZ2VZZDogJ2ZmNDUwMCcsXG4gIFNjRWQ6ICdkYTcwZDYnLFxuICBwT2VnVE1uUGQ6ICdlZWU4YWEnLFxuICBwT2VnWUY6ICc5OGZiOTgnLFxuICBwT2VRZTogJ2FmZWVlZScsXG4gIHBPZXZpVGV0WWQ6ICdkYjcwOTMnLFxuICBwYXBheWF3RXA6ICdmZmVmZDUnLFxuICBwSEtwdWZmOiAnZmZkYWI5JyxcbiAgcGVydTogJ2NkODUzZicsXG4gIHBSazogJ2ZmYzBjYicsXG4gIHBsdW06ICdkZGEwZGQnLFxuICBwb3dNclhlOiAnYjBlMGU2JyxcbiAgcHVycE46ICc4MDAwODAnLFxuICBZYmVjY2FwdXJwTjogJzY2MzM5OScsXG4gIFlkOiAnZmYwMDAwJyxcbiAgUHN5YnJvd246ICdiYzhmOGYnLFxuICBQeU9YZTogJzQxNjllMScsXG4gIHNhZGROYlB3bjogJzhiNDUxMycsXG4gIHNPbW9uOiAnZmE4MDcyJyxcbiAgc2FuZHliUHduOiAnZjRhNDYwJyxcbiAgc0hnWUY6ICcyZThiNTcnLFxuICBzSHNoZWxsOiAnZmZmNWVlJyxcbiAgc2lGbmE6ICdhMDUyMmQnLFxuICBzaWx2ZXI6ICdjMGMwYzAnLFxuICBza3lYZTogJzg3Y2VlYicsXG4gIFVYZTogJzZhNWFjZCcsXG4gIFVXYXk6ICc3MDgwOTAnLFxuICBVZ1l5OiAnNzA4MDkwJyxcbiAgc25vdzogJ2ZmZmFmYScsXG4gIHNwclJnZ1lGOiAnZmY3ZicsXG4gIHN0QWxYZTogJzQ2ODJiNCcsXG4gIHRhbjogJ2QyYjQ4YycsXG4gIHRlTzogJzgwODAnLFxuICB0RXN0TjogJ2Q4YmZkOCcsXG4gIHRvbWF0bzogJ2ZmNjM0NycsXG4gIFFlOiAnNDBlMGQwJyxcbiAgdmlUZXQ6ICdlZTgyZWUnLFxuICBKSHQ6ICdmNWRlYjMnLFxuICB3RXRlOiAnZmZmZmZmJyxcbiAgd0V0ZXNtb2tlOiAnZjVmNWY1JyxcbiAgTHc6ICdmZmZmMDAnLFxuICBMd2dZRjogJzlhY2QzMidcbn07XG5mdW5jdGlvbiB1bnBhY2soKSB7XG4gIGNvbnN0IHVucGFja2VkID0ge307XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhuYW1lcyQxKTtcbiAgY29uc3QgdGtleXMgPSBPYmplY3Qua2V5cyhtYXApO1xuICBsZXQgaSwgaiwgaywgb2ssIG5rO1xuICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgIG9rID0gbmsgPSBrZXlzW2ldO1xuICAgIGZvciAoaiA9IDA7IGogPCB0a2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgayA9IHRrZXlzW2pdO1xuICAgICAgbmsgPSBuay5yZXBsYWNlKGssIG1hcFtrXSk7XG4gICAgfVxuICAgIGsgPSBwYXJzZUludChuYW1lcyQxW29rXSwgMTYpO1xuICAgIHVucGFja2VkW25rXSA9IFtrID4+IDE2ICYgMHhGRiwgayA+PiA4ICYgMHhGRiwgayAmIDB4RkZdO1xuICB9XG4gIHJldHVybiB1bnBhY2tlZDtcbn1cblxubGV0IG5hbWVzO1xuZnVuY3Rpb24gbmFtZVBhcnNlKHN0cikge1xuICBpZiAoIW5hbWVzKSB7XG4gICAgbmFtZXMgPSB1bnBhY2soKTtcbiAgICBuYW1lcy50cmFuc3BhcmVudCA9IFswLCAwLCAwLCAwXTtcbiAgfVxuICBjb25zdCBhID0gbmFtZXNbc3RyLnRvTG93ZXJDYXNlKCldO1xuICByZXR1cm4gYSAmJiB7XG4gICAgcjogYVswXSxcbiAgICBnOiBhWzFdLFxuICAgIGI6IGFbMl0sXG4gICAgYTogYS5sZW5ndGggPT09IDQgPyBhWzNdIDogMjU1XG4gIH07XG59XG5cbmNvbnN0IFJHQl9SRSA9IC9ecmdiYT9cXChcXHMqKFstKy5cXGRdKykoJSk/W1xccyxdKyhbLSsuZVxcZF0rKSglKT9bXFxzLF0rKFstKy5lXFxkXSspKCUpPyg/OltcXHMsL10rKFstKy5lXFxkXSspKCUpPyk/XFxzKlxcKSQvO1xuZnVuY3Rpb24gcmdiUGFyc2Uoc3RyKSB7XG4gIGNvbnN0IG0gPSBSR0JfUkUuZXhlYyhzdHIpO1xuICBsZXQgYSA9IDI1NTtcbiAgbGV0IHIsIGcsIGI7XG4gIGlmICghbSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAobVs3XSAhPT0gcikge1xuICAgIGNvbnN0IHYgPSArbVs3XTtcbiAgICBhID0gbVs4XSA/IHAyYih2KSA6IGxpbSh2ICogMjU1LCAwLCAyNTUpO1xuICB9XG4gIHIgPSArbVsxXTtcbiAgZyA9ICttWzNdO1xuICBiID0gK21bNV07XG4gIHIgPSAyNTUgJiAobVsyXSA/IHAyYihyKSA6IGxpbShyLCAwLCAyNTUpKTtcbiAgZyA9IDI1NSAmIChtWzRdID8gcDJiKGcpIDogbGltKGcsIDAsIDI1NSkpO1xuICBiID0gMjU1ICYgKG1bNl0gPyBwMmIoYikgOiBsaW0oYiwgMCwgMjU1KSk7XG4gIHJldHVybiB7XG4gICAgcjogcixcbiAgICBnOiBnLFxuICAgIGI6IGIsXG4gICAgYTogYVxuICB9O1xufVxuZnVuY3Rpb24gcmdiU3RyaW5nKHYpIHtcbiAgcmV0dXJuIHYgJiYgKFxuICAgIHYuYSA8IDI1NVxuICAgICAgPyBgcmdiYSgke3Yucn0sICR7di5nfSwgJHt2LmJ9LCAke2Iybih2LmEpfSlgXG4gICAgICA6IGByZ2IoJHt2LnJ9LCAke3YuZ30sICR7di5ifSlgXG4gICk7XG59XG5cbmNvbnN0IHRvID0gdiA9PiB2IDw9IDAuMDAzMTMwOCA/IHYgKiAxMi45MiA6IE1hdGgucG93KHYsIDEuMCAvIDIuNCkgKiAxLjA1NSAtIDAuMDU1O1xuY29uc3QgZnJvbSA9IHYgPT4gdiA8PSAwLjA0MDQ1ID8gdiAvIDEyLjkyIDogTWF0aC5wb3coKHYgKyAwLjA1NSkgLyAxLjA1NSwgMi40KTtcbmZ1bmN0aW9uIGludGVycG9sYXRlKHJnYjEsIHJnYjIsIHQpIHtcbiAgY29uc3QgciA9IGZyb20oYjJuKHJnYjEucikpO1xuICBjb25zdCBnID0gZnJvbShiMm4ocmdiMS5nKSk7XG4gIGNvbnN0IGIgPSBmcm9tKGIybihyZ2IxLmIpKTtcbiAgcmV0dXJuIHtcbiAgICByOiBuMmIodG8ociArIHQgKiAoZnJvbShiMm4ocmdiMi5yKSkgLSByKSkpLFxuICAgIGc6IG4yYih0byhnICsgdCAqIChmcm9tKGIybihyZ2IyLmcpKSAtIGcpKSksXG4gICAgYjogbjJiKHRvKGIgKyB0ICogKGZyb20oYjJuKHJnYjIuYikpIC0gYikpKSxcbiAgICBhOiByZ2IxLmEgKyB0ICogKHJnYjIuYSAtIHJnYjEuYSlcbiAgfTtcbn1cblxuZnVuY3Rpb24gbW9kSFNMKHYsIGksIHJhdGlvKSB7XG4gIGlmICh2KSB7XG4gICAgbGV0IHRtcCA9IHJnYjJoc2wodik7XG4gICAgdG1wW2ldID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odG1wW2ldICsgdG1wW2ldICogcmF0aW8sIGkgPT09IDAgPyAzNjAgOiAxKSk7XG4gICAgdG1wID0gaHNsMnJnYih0bXApO1xuICAgIHYuciA9IHRtcFswXTtcbiAgICB2LmcgPSB0bXBbMV07XG4gICAgdi5iID0gdG1wWzJdO1xuICB9XG59XG5mdW5jdGlvbiBjbG9uZSh2LCBwcm90bykge1xuICByZXR1cm4gdiA/IE9iamVjdC5hc3NpZ24ocHJvdG8gfHwge30sIHYpIDogdjtcbn1cbmZ1bmN0aW9uIGZyb21PYmplY3QoaW5wdXQpIHtcbiAgdmFyIHYgPSB7cjogMCwgZzogMCwgYjogMCwgYTogMjU1fTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgaWYgKGlucHV0Lmxlbmd0aCA+PSAzKSB7XG4gICAgICB2ID0ge3I6IGlucHV0WzBdLCBnOiBpbnB1dFsxXSwgYjogaW5wdXRbMl0sIGE6IDI1NX07XG4gICAgICBpZiAoaW5wdXQubGVuZ3RoID4gMykge1xuICAgICAgICB2LmEgPSBuMmIoaW5wdXRbM10pO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2ID0gY2xvbmUoaW5wdXQsIHtyOiAwLCBnOiAwLCBiOiAwLCBhOiAxfSk7XG4gICAgdi5hID0gbjJiKHYuYSk7XG4gIH1cbiAgcmV0dXJuIHY7XG59XG5mdW5jdGlvbiBmdW5jdGlvblBhcnNlKHN0cikge1xuICBpZiAoc3RyLmNoYXJBdCgwKSA9PT0gJ3InKSB7XG4gICAgcmV0dXJuIHJnYlBhcnNlKHN0cik7XG4gIH1cbiAgcmV0dXJuIGh1ZVBhcnNlKHN0cik7XG59XG5jbGFzcyBDb2xvciB7XG4gIGNvbnN0cnVjdG9yKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgQ29sb3IpIHtcbiAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgY29uc3QgdHlwZSA9IHR5cGVvZiBpbnB1dDtcbiAgICBsZXQgdjtcbiAgICBpZiAodHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHYgPSBmcm9tT2JqZWN0KGlucHV0KTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB2ID0gaGV4UGFyc2UoaW5wdXQpIHx8IG5hbWVQYXJzZShpbnB1dCkgfHwgZnVuY3Rpb25QYXJzZShpbnB1dCk7XG4gICAgfVxuICAgIHRoaXMuX3JnYiA9IHY7XG4gICAgdGhpcy5fdmFsaWQgPSAhIXY7XG4gIH1cbiAgZ2V0IHZhbGlkKCkge1xuICAgIHJldHVybiB0aGlzLl92YWxpZDtcbiAgfVxuICBnZXQgcmdiKCkge1xuICAgIHZhciB2ID0gY2xvbmUodGhpcy5fcmdiKTtcbiAgICBpZiAodikge1xuICAgICAgdi5hID0gYjJuKHYuYSk7XG4gICAgfVxuICAgIHJldHVybiB2O1xuICB9XG4gIHNldCByZ2Iob2JqKSB7XG4gICAgdGhpcy5fcmdiID0gZnJvbU9iamVjdChvYmopO1xuICB9XG4gIHJnYlN0cmluZygpIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsaWQgPyByZ2JTdHJpbmcodGhpcy5fcmdiKSA6IHVuZGVmaW5lZDtcbiAgfVxuICBoZXhTdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkID8gaGV4U3RyaW5nKHRoaXMuX3JnYikgOiB1bmRlZmluZWQ7XG4gIH1cbiAgaHNsU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLl92YWxpZCA/IGhzbFN0cmluZyh0aGlzLl9yZ2IpIDogdW5kZWZpbmVkO1xuICB9XG4gIG1peChjb2xvciwgd2VpZ2h0KSB7XG4gICAgaWYgKGNvbG9yKSB7XG4gICAgICBjb25zdCBjMSA9IHRoaXMucmdiO1xuICAgICAgY29uc3QgYzIgPSBjb2xvci5yZ2I7XG4gICAgICBsZXQgdzI7XG4gICAgICBjb25zdCBwID0gd2VpZ2h0ID09PSB3MiA/IDAuNSA6IHdlaWdodDtcbiAgICAgIGNvbnN0IHcgPSAyICogcCAtIDE7XG4gICAgICBjb25zdCBhID0gYzEuYSAtIGMyLmE7XG4gICAgICBjb25zdCB3MSA9ICgodyAqIGEgPT09IC0xID8gdyA6ICh3ICsgYSkgLyAoMSArIHcgKiBhKSkgKyAxKSAvIDIuMDtcbiAgICAgIHcyID0gMSAtIHcxO1xuICAgICAgYzEuciA9IDB4RkYgJiB3MSAqIGMxLnIgKyB3MiAqIGMyLnIgKyAwLjU7XG4gICAgICBjMS5nID0gMHhGRiAmIHcxICogYzEuZyArIHcyICogYzIuZyArIDAuNTtcbiAgICAgIGMxLmIgPSAweEZGICYgdzEgKiBjMS5iICsgdzIgKiBjMi5iICsgMC41O1xuICAgICAgYzEuYSA9IHAgKiBjMS5hICsgKDEgLSBwKSAqIGMyLmE7XG4gICAgICB0aGlzLnJnYiA9IGMxO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBpbnRlcnBvbGF0ZShjb2xvciwgdCkge1xuICAgIGlmIChjb2xvcikge1xuICAgICAgdGhpcy5fcmdiID0gaW50ZXJwb2xhdGUodGhpcy5fcmdiLCBjb2xvci5fcmdiLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgY2xvbmUoKSB7XG4gICAgcmV0dXJuIG5ldyBDb2xvcih0aGlzLnJnYik7XG4gIH1cbiAgYWxwaGEoYSkge1xuICAgIHRoaXMuX3JnYi5hID0gbjJiKGEpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGNsZWFyZXIocmF0aW8pIHtcbiAgICBjb25zdCByZ2IgPSB0aGlzLl9yZ2I7XG4gICAgcmdiLmEgKj0gMSAtIHJhdGlvO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGdyZXlzY2FsZSgpIHtcbiAgICBjb25zdCByZ2IgPSB0aGlzLl9yZ2I7XG4gICAgY29uc3QgdmFsID0gcm91bmQocmdiLnIgKiAwLjMgKyByZ2IuZyAqIDAuNTkgKyByZ2IuYiAqIDAuMTEpO1xuICAgIHJnYi5yID0gcmdiLmcgPSByZ2IuYiA9IHZhbDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBvcGFxdWVyKHJhdGlvKSB7XG4gICAgY29uc3QgcmdiID0gdGhpcy5fcmdiO1xuICAgIHJnYi5hICo9IDEgKyByYXRpbztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBuZWdhdGUoKSB7XG4gICAgY29uc3QgdiA9IHRoaXMuX3JnYjtcbiAgICB2LnIgPSAyNTUgLSB2LnI7XG4gICAgdi5nID0gMjU1IC0gdi5nO1xuICAgIHYuYiA9IDI1NSAtIHYuYjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICBsaWdodGVuKHJhdGlvKSB7XG4gICAgbW9kSFNMKHRoaXMuX3JnYiwgMiwgcmF0aW8pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIGRhcmtlbihyYXRpbykge1xuICAgIG1vZEhTTCh0aGlzLl9yZ2IsIDIsIC1yYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgc2F0dXJhdGUocmF0aW8pIHtcbiAgICBtb2RIU0wodGhpcy5fcmdiLCAxLCByYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgZGVzYXR1cmF0ZShyYXRpbykge1xuICAgIG1vZEhTTCh0aGlzLl9yZ2IsIDEsIC1yYXRpbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgcm90YXRlKGRlZykge1xuICAgIHJvdGF0ZSh0aGlzLl9yZ2IsIGRlZyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5kZXhfZXNtKGlucHV0KSB7XG4gIHJldHVybiBuZXcgQ29sb3IoaW5wdXQpO1xufVxuXG5leHBvcnQgeyBDb2xvciwgYjJuLCBiMnAsIGluZGV4X2VzbSBhcyBkZWZhdWx0LCBoZXhQYXJzZSwgaGV4U3RyaW5nLCBoc2wycmdiLCBoc2xTdHJpbmcsIGhzdjJyZ2IsIGh1ZVBhcnNlLCBod2IycmdiLCBsaW0sIG4yYiwgbjJwLCBuYW1lUGFyc2UsIHAyYiwgcmdiMmhzbCwgcmdiUGFyc2UsIHJnYlN0cmluZywgcm90YXRlLCByb3VuZCB9O1xuIiwiLyohXG4gKiBDaGFydC5qcyB2NC4zLjBcbiAqIGh0dHBzOi8vd3d3LmNoYXJ0anMub3JnXG4gKiAoYykgMjAyMyBDaGFydC5qcyBDb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICovXG5pbXBvcnQgeyByIGFzIHJlcXVlc3RBbmltRnJhbWUsIGEgYXMgcmVzb2x2ZSwgZSBhcyBlZmZlY3RzLCBjIGFzIGNvbG9yLCBpIGFzIGlzT2JqZWN0LCBkIGFzIGRlZmF1bHRzLCBiIGFzIGlzQXJyYXksIHYgYXMgdmFsdWVPckRlZmF1bHQsIHUgYXMgdW5saXN0ZW5BcnJheUV2ZW50cywgbCBhcyBsaXN0ZW5BcnJheUV2ZW50cywgZiBhcyByZXNvbHZlT2JqZWN0S2V5LCBnIGFzIGlzTnVtYmVyRmluaXRlLCBoIGFzIGRlZmluZWQsIHMgYXMgc2lnbiwgaiBhcyBjcmVhdGVDb250ZXh0LCBrIGFzIGlzTnVsbE9yVW5kZWYsIF8gYXMgX2FycmF5VW5pcXVlLCB0IGFzIHRvUmFkaWFucywgbSBhcyB0b1BlcmNlbnRhZ2UsIG4gYXMgdG9EaW1lbnNpb24sIFQgYXMgVEFVLCBvIGFzIGZvcm1hdE51bWJlciwgcCBhcyBfYW5nbGVCZXR3ZWVuLCBIIGFzIEhBTEZfUEksIFAgYXMgUEksIHEgYXMgX2dldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMsIHcgYXMgX3NjYWxlUmFuZ2VzQ2hhbmdlZCwgeCBhcyBpc051bWJlciwgeSBhcyBfcGFyc2VPYmplY3REYXRhUmFkaWFsU2NhbGUsIHogYXMgZ2V0UmVsYXRpdmVQb3NpdGlvbiwgQSBhcyBfcmxvb2t1cEJ5S2V5LCBCIGFzIF9sb29rdXBCeUtleSwgQyBhcyBfaXNQb2ludEluQXJlYSwgRCBhcyBnZXRBbmdsZUZyb21Qb2ludCwgRSBhcyB0b1BhZGRpbmcsIEYgYXMgZWFjaCwgRyBhcyBnZXRNYXhpbXVtU2l6ZSwgSSBhcyBfZ2V0UGFyZW50Tm9kZSwgSiBhcyByZWFkVXNlZFNpemUsIEsgYXMgc3VwcG9ydHNFdmVudExpc3RlbmVyT3B0aW9ucywgTCBhcyB0aHJvdHRsZWQsIE0gYXMgX2lzRG9tU3VwcG9ydGVkLCBOIGFzIF9mYWN0b3JpemUsIE8gYXMgZmluaXRlT3JEZWZhdWx0LCBRIGFzIGNhbGxiYWNrLCBSIGFzIF9hZGRHcmFjZSwgUyBhcyBfbGltaXRWYWx1ZSwgVSBhcyB0b0RlZ3JlZXMsIFYgYXMgX21lYXN1cmVUZXh0LCBXIGFzIF9pbnQxNlJhbmdlLCBYIGFzIF9hbGlnblBpeGVsLCBZIGFzIGNsaXBBcmVhLCBaIGFzIHJlbmRlclRleHQsICQgYXMgdW5jbGlwQXJlYSwgYTAgYXMgdG9Gb250LCBhMSBhcyBfdG9MZWZ0UmlnaHRDZW50ZXIsIGEyIGFzIF9hbGlnblN0YXJ0RW5kLCBhMyBhcyBvdmVycmlkZXMsIGE0IGFzIG1lcmdlLCBhNSBhcyBfY2FwaXRhbGl6ZSwgYTYgYXMgZGVzY3JpcHRvcnMsIGE3IGFzIGlzRnVuY3Rpb24sIGE4IGFzIF9hdHRhY2hDb250ZXh0LCBhOSBhcyBfY3JlYXRlUmVzb2x2ZXIsIGFhIGFzIF9kZXNjcmlwdG9ycywgYWIgYXMgbWVyZ2VJZiwgYWMgYXMgdWlkLCBhZCBhcyBkZWJvdW5jZSwgYWUgYXMgcmV0aW5hU2NhbGUsIGFmIGFzIGNsZWFyQ2FudmFzLCBhZyBhcyBzZXRzRXF1YWwsIGFoIGFzIF9lbGVtZW50c0VxdWFsLCBhaSBhcyBfaXNDbGlja0V2ZW50LCBhaiBhcyBfaXNCZXR3ZWVuLCBhayBhcyBfcmVhZFZhbHVlVG9Qcm9wcywgYWwgYXMgX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHMsIGFtIGFzIF9jb21wdXRlU2VnbWVudHMsIGFuIGFzIF9ib3VuZFNlZ21lbnRzLCBhbyBhcyBfc3RlcHBlZEludGVycG9sYXRpb24sIGFwIGFzIF9iZXppZXJJbnRlcnBvbGF0aW9uLCBhcSBhcyBfcG9pbnRJbkxpbmUsIGFyIGFzIF9zdGVwcGVkTGluZVRvLCBhcyBhcyBfYmV6aWVyQ3VydmVUbywgYXQgYXMgZHJhd1BvaW50LCBhdSBhcyBhZGRSb3VuZGVkUmVjdFBhdGgsIGF2IGFzIHRvVFJCTCwgYXcgYXMgdG9UUkJMQ29ybmVycywgYXggYXMgX2JvdW5kU2VnbWVudCwgYXkgYXMgX25vcm1hbGl6ZUFuZ2xlLCBheiBhcyBnZXRSdGxBZGFwdGVyLCBhQSBhcyBvdmVycmlkZVRleHREaXJlY3Rpb24sIGFCIGFzIF90ZXh0WCwgYUMgYXMgcmVzdG9yZVRleHREaXJlY3Rpb24sIGFEIGFzIGRyYXdQb2ludExlZ2VuZCwgYUUgYXMgZGlzdGFuY2VCZXR3ZWVuUG9pbnRzLCBhRiBhcyBub29wLCBhRyBhcyBfc2V0TWluQW5kTWF4QnlLZXksIGFIIGFzIG5pY2VOdW0sIGFJIGFzIGFsbW9zdFdob2xlLCBhSiBhcyBhbG1vc3RFcXVhbHMsIGFLIGFzIF9kZWNpbWFsUGxhY2VzLCBhTCBhcyBUaWNrcywgYU0gYXMgbG9nMTAsIGFOIGFzIF9sb25nZXN0VGV4dCwgYU8gYXMgX2ZpbHRlckJldHdlZW4sIGFQIGFzIF9sb29rdXAgfSBmcm9tICcuL2NodW5rcy9oZWxwZXJzLnNlZ21lbnQuanMnO1xuaW1wb3J0ICdAa3Vya2xlL2NvbG9yJztcblxuY2xhc3MgQW5pbWF0b3Ige1xuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuX3JlcXVlc3QgPSBudWxsO1xuICAgICAgICB0aGlzLl9jaGFydHMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fbGFzdERhdGUgPSB1bmRlZmluZWQ7XG4gICAgfVxuIF9ub3RpZnkoY2hhcnQsIGFuaW1zLCBkYXRlLCB0eXBlKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrcyA9IGFuaW1zLmxpc3RlbmVyc1t0eXBlXTtcbiAgICAgICAgY29uc3QgbnVtU3RlcHMgPSBhbmltcy5kdXJhdGlvbjtcbiAgICAgICAgY2FsbGJhY2tzLmZvckVhY2goKGZuKT0+Zm4oe1xuICAgICAgICAgICAgICAgIGNoYXJ0LFxuICAgICAgICAgICAgICAgIGluaXRpYWw6IGFuaW1zLmluaXRpYWwsXG4gICAgICAgICAgICAgICAgbnVtU3RlcHMsXG4gICAgICAgICAgICAgICAgY3VycmVudFN0ZXA6IE1hdGgubWluKGRhdGUgLSBhbmltcy5zdGFydCwgbnVtU3RlcHMpXG4gICAgICAgICAgICB9KSk7XG4gICAgfVxuIF9yZWZyZXNoKCkge1xuICAgICAgICBpZiAodGhpcy5fcmVxdWVzdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3J1bm5pbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLl9yZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZS5jYWxsKHdpbmRvdywgKCk9PntcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fcmVxdWVzdCA9IG51bGw7XG4gICAgICAgICAgICBpZiAodGhpcy5fcnVubmluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZnJlc2goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuIF91cGRhdGUoZGF0ZSA9IERhdGUubm93KCkpIHtcbiAgICAgICAgbGV0IHJlbWFpbmluZyA9IDA7XG4gICAgICAgIHRoaXMuX2NoYXJ0cy5mb3JFYWNoKChhbmltcywgY2hhcnQpPT57XG4gICAgICAgICAgICBpZiAoIWFuaW1zLnJ1bm5pbmcgfHwgIWFuaW1zLml0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGl0ZW1zID0gYW5pbXMuaXRlbXM7XG4gICAgICAgICAgICBsZXQgaSA9IGl0ZW1zLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICBsZXQgZHJhdyA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGl0ZW07XG4gICAgICAgICAgICBmb3IoOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICAgICAgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgIGlmIChpdGVtLl9hY3RpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0uX3RvdGFsID4gYW5pbXMuZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1zLmR1cmF0aW9uID0gaXRlbS5fdG90YWw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaXRlbS50aWNrKGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICBkcmF3ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpdGVtc1tpXSA9IGl0ZW1zW2l0ZW1zLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBpdGVtcy5wb3AoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHJhdykge1xuICAgICAgICAgICAgICAgIGNoYXJ0LmRyYXcoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnkoY2hhcnQsIGFuaW1zLCBkYXRlLCAncHJvZ3Jlc3MnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYW5pbXMucnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeShjaGFydCwgYW5pbXMsIGRhdGUsICdjb21wbGV0ZScpO1xuICAgICAgICAgICAgICAgIGFuaW1zLmluaXRpYWwgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlbWFpbmluZyArPSBpdGVtcy5sZW5ndGg7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9sYXN0RGF0ZSA9IGRhdGU7XG4gICAgICAgIGlmIChyZW1haW5pbmcgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiBfZ2V0QW5pbXMoY2hhcnQpIHtcbiAgICAgICAgY29uc3QgY2hhcnRzID0gdGhpcy5fY2hhcnRzO1xuICAgICAgICBsZXQgYW5pbXMgPSBjaGFydHMuZ2V0KGNoYXJ0KTtcbiAgICAgICAgaWYgKCFhbmltcykge1xuICAgICAgICAgICAgYW5pbXMgPSB7XG4gICAgICAgICAgICAgICAgcnVubmluZzogZmFsc2UsXG4gICAgICAgICAgICAgICAgaW5pdGlhbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpdGVtczogW10sXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M6IFtdXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNoYXJ0cy5zZXQoY2hhcnQsIGFuaW1zKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYW5pbXM7XG4gICAgfVxuIGxpc3RlbihjaGFydCwgZXZlbnQsIGNiKSB7XG4gICAgICAgIHRoaXMuX2dldEFuaW1zKGNoYXJ0KS5saXN0ZW5lcnNbZXZlbnRdLnB1c2goY2IpO1xuICAgIH1cbiBhZGQoY2hhcnQsIGl0ZW1zKSB7XG4gICAgICAgIGlmICghaXRlbXMgfHwgIWl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2dldEFuaW1zKGNoYXJ0KS5pdGVtcy5wdXNoKC4uLml0ZW1zKTtcbiAgICB9XG4gaGFzKGNoYXJ0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRBbmltcyhjaGFydCkuaXRlbXMubGVuZ3RoID4gMDtcbiAgICB9XG4gc3RhcnQoY2hhcnQpIHtcbiAgICAgICAgY29uc3QgYW5pbXMgPSB0aGlzLl9jaGFydHMuZ2V0KGNoYXJ0KTtcbiAgICAgICAgaWYgKCFhbmltcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGFuaW1zLnJ1bm5pbmcgPSB0cnVlO1xuICAgICAgICBhbmltcy5zdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgIGFuaW1zLmR1cmF0aW9uID0gYW5pbXMuaXRlbXMucmVkdWNlKChhY2MsIGN1cik9Pk1hdGgubWF4KGFjYywgY3VyLl9kdXJhdGlvbiksIDApO1xuICAgICAgICB0aGlzLl9yZWZyZXNoKCk7XG4gICAgfVxuICAgIHJ1bm5pbmcoY2hhcnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9ydW5uaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYW5pbXMgPSB0aGlzLl9jaGFydHMuZ2V0KGNoYXJ0KTtcbiAgICAgICAgaWYgKCFhbmltcyB8fCAhYW5pbXMucnVubmluZyB8fCAhYW5pbXMuaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuIHN0b3AoY2hhcnQpIHtcbiAgICAgICAgY29uc3QgYW5pbXMgPSB0aGlzLl9jaGFydHMuZ2V0KGNoYXJ0KTtcbiAgICAgICAgaWYgKCFhbmltcyB8fCAhYW5pbXMuaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSBhbmltcy5pdGVtcztcbiAgICAgICAgbGV0IGkgPSBpdGVtcy5sZW5ndGggLSAxO1xuICAgICAgICBmb3IoOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICBpdGVtc1tpXS5jYW5jZWwoKTtcbiAgICAgICAgfVxuICAgICAgICBhbmltcy5pdGVtcyA9IFtdO1xuICAgICAgICB0aGlzLl9ub3RpZnkoY2hhcnQsIGFuaW1zLCBEYXRlLm5vdygpLCAnY29tcGxldGUnKTtcbiAgICB9XG4gcmVtb3ZlKGNoYXJ0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaGFydHMuZGVsZXRlKGNoYXJ0KTtcbiAgICB9XG59XG52YXIgYW5pbWF0b3IgPSAvKiAjX19QVVJFX18gKi8gbmV3IEFuaW1hdG9yKCk7XG5cbmNvbnN0IHRyYW5zcGFyZW50ID0gJ3RyYW5zcGFyZW50JztcbmNvbnN0IGludGVycG9sYXRvcnMgPSB7XG4gICAgYm9vbGVhbiAoZnJvbSwgdG8sIGZhY3Rvcikge1xuICAgICAgICByZXR1cm4gZmFjdG9yID4gMC41ID8gdG8gOiBmcm9tO1xuICAgIH0sXG4gY29sb3IgKGZyb20sIHRvLCBmYWN0b3IpIHtcbiAgICAgICAgY29uc3QgYzAgPSBjb2xvcihmcm9tIHx8IHRyYW5zcGFyZW50KTtcbiAgICAgICAgY29uc3QgYzEgPSBjMC52YWxpZCAmJiBjb2xvcih0byB8fCB0cmFuc3BhcmVudCk7XG4gICAgICAgIHJldHVybiBjMSAmJiBjMS52YWxpZCA/IGMxLm1peChjMCwgZmFjdG9yKS5oZXhTdHJpbmcoKSA6IHRvO1xuICAgIH0sXG4gICAgbnVtYmVyIChmcm9tLCB0bywgZmFjdG9yKSB7XG4gICAgICAgIHJldHVybiBmcm9tICsgKHRvIC0gZnJvbSkgKiBmYWN0b3I7XG4gICAgfVxufTtcbmNsYXNzIEFuaW1hdGlvbiB7XG4gICAgY29uc3RydWN0b3IoY2ZnLCB0YXJnZXQsIHByb3AsIHRvKXtcbiAgICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gdGFyZ2V0W3Byb3BdO1xuICAgICAgICB0byA9IHJlc29sdmUoW1xuICAgICAgICAgICAgY2ZnLnRvLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICBjdXJyZW50VmFsdWUsXG4gICAgICAgICAgICBjZmcuZnJvbVxuICAgICAgICBdKTtcbiAgICAgICAgY29uc3QgZnJvbSA9IHJlc29sdmUoW1xuICAgICAgICAgICAgY2ZnLmZyb20sXG4gICAgICAgICAgICBjdXJyZW50VmFsdWUsXG4gICAgICAgICAgICB0b1xuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5fYWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fZm4gPSBjZmcuZm4gfHwgaW50ZXJwb2xhdG9yc1tjZmcudHlwZSB8fCB0eXBlb2YgZnJvbV07XG4gICAgICAgIHRoaXMuX2Vhc2luZyA9IGVmZmVjdHNbY2ZnLmVhc2luZ10gfHwgZWZmZWN0cy5saW5lYXI7XG4gICAgICAgIHRoaXMuX3N0YXJ0ID0gTWF0aC5mbG9vcihEYXRlLm5vdygpICsgKGNmZy5kZWxheSB8fCAwKSk7XG4gICAgICAgIHRoaXMuX2R1cmF0aW9uID0gdGhpcy5fdG90YWwgPSBNYXRoLmZsb29yKGNmZy5kdXJhdGlvbik7XG4gICAgICAgIHRoaXMuX2xvb3AgPSAhIWNmZy5sb29wO1xuICAgICAgICB0aGlzLl90YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHRoaXMuX3Byb3AgPSBwcm9wO1xuICAgICAgICB0aGlzLl9mcm9tID0gZnJvbTtcbiAgICAgICAgdGhpcy5fdG8gPSB0bztcbiAgICAgICAgdGhpcy5fcHJvbWlzZXMgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGFjdGl2ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FjdGl2ZTtcbiAgICB9XG4gICAgdXBkYXRlKGNmZywgdG8sIGRhdGUpIHtcbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5KGZhbHNlKTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IHRoaXMuX3RhcmdldFt0aGlzLl9wcm9wXTtcbiAgICAgICAgICAgIGNvbnN0IGVsYXBzZWQgPSBkYXRlIC0gdGhpcy5fc3RhcnQ7XG4gICAgICAgICAgICBjb25zdCByZW1haW4gPSB0aGlzLl9kdXJhdGlvbiAtIGVsYXBzZWQ7XG4gICAgICAgICAgICB0aGlzLl9zdGFydCA9IGRhdGU7XG4gICAgICAgICAgICB0aGlzLl9kdXJhdGlvbiA9IE1hdGguZmxvb3IoTWF0aC5tYXgocmVtYWluLCBjZmcuZHVyYXRpb24pKTtcbiAgICAgICAgICAgIHRoaXMuX3RvdGFsICs9IGVsYXBzZWQ7XG4gICAgICAgICAgICB0aGlzLl9sb29wID0gISFjZmcubG9vcDtcbiAgICAgICAgICAgIHRoaXMuX3RvID0gcmVzb2x2ZShbXG4gICAgICAgICAgICAgICAgY2ZnLnRvLFxuICAgICAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSxcbiAgICAgICAgICAgICAgICBjZmcuZnJvbVxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB0aGlzLl9mcm9tID0gcmVzb2x2ZShbXG4gICAgICAgICAgICAgICAgY2ZnLmZyb20sXG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlLFxuICAgICAgICAgICAgICAgIHRvXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjYW5jZWwoKSB7XG4gICAgICAgIGlmICh0aGlzLl9hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMudGljayhEYXRlLm5vdygpKTtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5KGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aWNrKGRhdGUpIHtcbiAgICAgICAgY29uc3QgZWxhcHNlZCA9IGRhdGUgLSB0aGlzLl9zdGFydDtcbiAgICAgICAgY29uc3QgZHVyYXRpb24gPSB0aGlzLl9kdXJhdGlvbjtcbiAgICAgICAgY29uc3QgcHJvcCA9IHRoaXMuX3Byb3A7XG4gICAgICAgIGNvbnN0IGZyb20gPSB0aGlzLl9mcm9tO1xuICAgICAgICBjb25zdCBsb29wID0gdGhpcy5fbG9vcDtcbiAgICAgICAgY29uc3QgdG8gPSB0aGlzLl90bztcbiAgICAgICAgbGV0IGZhY3RvcjtcbiAgICAgICAgdGhpcy5fYWN0aXZlID0gZnJvbSAhPT0gdG8gJiYgKGxvb3AgfHwgZWxhcHNlZCA8IGR1cmF0aW9uKTtcbiAgICAgICAgaWYgKCF0aGlzLl9hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3RhcmdldFtwcm9wXSA9IHRvO1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5KHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbGFwc2VkIDwgMCkge1xuICAgICAgICAgICAgdGhpcy5fdGFyZ2V0W3Byb3BdID0gZnJvbTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmYWN0b3IgPSBlbGFwc2VkIC8gZHVyYXRpb24gJSAyO1xuICAgICAgICBmYWN0b3IgPSBsb29wICYmIGZhY3RvciA+IDEgPyAyIC0gZmFjdG9yIDogZmFjdG9yO1xuICAgICAgICBmYWN0b3IgPSB0aGlzLl9lYXNpbmcoTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgZmFjdG9yKSkpO1xuICAgICAgICB0aGlzLl90YXJnZXRbcHJvcF0gPSB0aGlzLl9mbihmcm9tLCB0bywgZmFjdG9yKTtcbiAgICB9XG4gICAgd2FpdCgpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSB0aGlzLl9wcm9taXNlcyB8fCAodGhpcy5fcHJvbWlzZXMgPSBbXSk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzLCByZWopPT57XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICByZXMsXG4gICAgICAgICAgICAgICAgcmVqXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIF9ub3RpZnkocmVzb2x2ZWQpIHtcbiAgICAgICAgY29uc3QgbWV0aG9kID0gcmVzb2x2ZWQgPyAncmVzJyA6ICdyZWonO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IHRoaXMuX3Byb21pc2VzIHx8IFtdO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcHJvbWlzZXMubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgcHJvbWlzZXNbaV1bbWV0aG9kXSgpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5jbGFzcyBBbmltYXRpb25zIHtcbiAgICBjb25zdHJ1Y3RvcihjaGFydCwgY29uZmlnKXtcbiAgICAgICAgdGhpcy5fY2hhcnQgPSBjaGFydDtcbiAgICAgICAgdGhpcy5fcHJvcGVydGllcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmUoY29uZmlnKTtcbiAgICB9XG4gICAgY29uZmlndXJlKGNvbmZpZykge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGNvbmZpZykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhbmltYXRpb25PcHRpb25zID0gT2JqZWN0LmtleXMoZGVmYXVsdHMuYW5pbWF0aW9uKTtcbiAgICAgICAgY29uc3QgYW5pbWF0ZWRQcm9wcyA9IHRoaXMuX3Byb3BlcnRpZXM7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGNvbmZpZykuZm9yRWFjaCgoa2V5KT0+e1xuICAgICAgICAgICAgY29uc3QgY2ZnID0gY29uZmlnW2tleV07XG4gICAgICAgICAgICBpZiAoIWlzT2JqZWN0KGNmZykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBvcHRpb24gb2YgYW5pbWF0aW9uT3B0aW9ucyl7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZWRbb3B0aW9uXSA9IGNmZ1tvcHRpb25dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgKGlzQXJyYXkoY2ZnLnByb3BlcnRpZXMpICYmIGNmZy5wcm9wZXJ0aWVzIHx8IFtcbiAgICAgICAgICAgICAgICBrZXlcbiAgICAgICAgICAgIF0pLmZvckVhY2goKHByb3ApPT57XG4gICAgICAgICAgICAgICAgaWYgKHByb3AgPT09IGtleSB8fCAhYW5pbWF0ZWRQcm9wcy5oYXMocHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5pbWF0ZWRQcm9wcy5zZXQocHJvcCwgcmVzb2x2ZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gX2FuaW1hdGVPcHRpb25zKHRhcmdldCwgdmFsdWVzKSB7XG4gICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSB2YWx1ZXMub3B0aW9ucztcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHJlc29sdmVUYXJnZXRPcHRpb25zKHRhcmdldCwgbmV3T3B0aW9ucyk7XG4gICAgICAgIGlmICghb3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSB0aGlzLl9jcmVhdGVBbmltYXRpb25zKG9wdGlvbnMsIG5ld09wdGlvbnMpO1xuICAgICAgICBpZiAobmV3T3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgICAgICAgICBhd2FpdEFsbCh0YXJnZXQub3B0aW9ucy4kYW5pbWF0aW9ucywgbmV3T3B0aW9ucykudGhlbigoKT0+e1xuICAgICAgICAgICAgICAgIHRhcmdldC5vcHRpb25zID0gbmV3T3B0aW9ucztcbiAgICAgICAgICAgIH0sICgpPT57XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgICB9XG4gX2NyZWF0ZUFuaW1hdGlvbnModGFyZ2V0LCB2YWx1ZXMpIHtcbiAgICAgICAgY29uc3QgYW5pbWF0ZWRQcm9wcyA9IHRoaXMuX3Byb3BlcnRpZXM7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXTtcbiAgICAgICAgY29uc3QgcnVubmluZyA9IHRhcmdldC4kYW5pbWF0aW9ucyB8fCAodGFyZ2V0LiRhbmltYXRpb25zID0ge30pO1xuICAgICAgICBjb25zdCBwcm9wcyA9IE9iamVjdC5rZXlzKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IGRhdGUgPSBEYXRlLm5vdygpO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgZm9yKGkgPSBwcm9wcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICBjb25zdCBwcm9wID0gcHJvcHNbaV07XG4gICAgICAgICAgICBpZiAocHJvcC5jaGFyQXQoMCkgPT09ICckJykge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHByb3AgPT09ICdvcHRpb25zJykge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCguLi50aGlzLl9hbmltYXRlT3B0aW9ucyh0YXJnZXQsIHZhbHVlcykpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbcHJvcF07XG4gICAgICAgICAgICBsZXQgYW5pbWF0aW9uID0gcnVubmluZ1twcm9wXTtcbiAgICAgICAgICAgIGNvbnN0IGNmZyA9IGFuaW1hdGVkUHJvcHMuZ2V0KHByb3ApO1xuICAgICAgICAgICAgaWYgKGFuaW1hdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChjZmcgJiYgYW5pbWF0aW9uLmFjdGl2ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbi51cGRhdGUoY2ZnLCB2YWx1ZSwgZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNmZyB8fCAhY2ZnLmR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W3Byb3BdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBydW5uaW5nW3Byb3BdID0gYW5pbWF0aW9uID0gbmV3IEFuaW1hdGlvbihjZmcsIHRhcmdldCwgcHJvcCwgdmFsdWUpO1xuICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKGFuaW1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gICAgfVxuIHVwZGF0ZSh0YXJnZXQsIHZhbHVlcykge1xuICAgICAgICBpZiAodGhpcy5fcHJvcGVydGllcy5zaXplID09PSAwKSB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHRhcmdldCwgdmFsdWVzKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gdGhpcy5fY3JlYXRlQW5pbWF0aW9ucyh0YXJnZXQsIHZhbHVlcyk7XG4gICAgICAgIGlmIChhbmltYXRpb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgYW5pbWF0b3IuYWRkKHRoaXMuX2NoYXJ0LCBhbmltYXRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gYXdhaXRBbGwoYW5pbWF0aW9ucywgcHJvcGVydGllcykge1xuICAgIGNvbnN0IHJ1bm5pbmcgPSBbXTtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspe1xuICAgICAgICBjb25zdCBhbmltID0gYW5pbWF0aW9uc1trZXlzW2ldXTtcbiAgICAgICAgaWYgKGFuaW0gJiYgYW5pbS5hY3RpdmUoKSkge1xuICAgICAgICAgICAgcnVubmluZy5wdXNoKGFuaW0ud2FpdCgpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwocnVubmluZyk7XG59XG5mdW5jdGlvbiByZXNvbHZlVGFyZ2V0T3B0aW9ucyh0YXJnZXQsIG5ld09wdGlvbnMpIHtcbiAgICBpZiAoIW5ld09wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgb3B0aW9ucyA9IHRhcmdldC5vcHRpb25zO1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgICB0YXJnZXQub3B0aW9ucyA9IG5ld09wdGlvbnM7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuJHNoYXJlZCkge1xuICAgICAgICB0YXJnZXQub3B0aW9ucyA9IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zLCB7XG4gICAgICAgICAgICAkc2hhcmVkOiBmYWxzZSxcbiAgICAgICAgICAgICRhbmltYXRpb25zOiB7fVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG59XG5cbmZ1bmN0aW9uIHNjYWxlQ2xpcChzY2FsZSwgYWxsb3dlZE92ZXJmbG93KSB7XG4gICAgY29uc3Qgb3B0cyA9IHNjYWxlICYmIHNjYWxlLm9wdGlvbnMgfHwge307XG4gICAgY29uc3QgcmV2ZXJzZSA9IG9wdHMucmV2ZXJzZTtcbiAgICBjb25zdCBtaW4gPSBvcHRzLm1pbiA9PT0gdW5kZWZpbmVkID8gYWxsb3dlZE92ZXJmbG93IDogMDtcbiAgICBjb25zdCBtYXggPSBvcHRzLm1heCA9PT0gdW5kZWZpbmVkID8gYWxsb3dlZE92ZXJmbG93IDogMDtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogcmV2ZXJzZSA/IG1heCA6IG1pbixcbiAgICAgICAgZW5kOiByZXZlcnNlID8gbWluIDogbWF4XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGlwKHhTY2FsZSwgeVNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpIHtcbiAgICBpZiAoYWxsb3dlZE92ZXJmbG93ID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IHggPSBzY2FsZUNsaXAoeFNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpO1xuICAgIGNvbnN0IHkgPSBzY2FsZUNsaXAoeVNjYWxlLCBhbGxvd2VkT3ZlcmZsb3cpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogeS5lbmQsXG4gICAgICAgIHJpZ2h0OiB4LmVuZCxcbiAgICAgICAgYm90dG9tOiB5LnN0YXJ0LFxuICAgICAgICBsZWZ0OiB4LnN0YXJ0XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHRvQ2xpcCh2YWx1ZSkge1xuICAgIGxldCB0LCByLCBiLCBsO1xuICAgIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgdCA9IHZhbHVlLnRvcDtcbiAgICAgICAgciA9IHZhbHVlLnJpZ2h0O1xuICAgICAgICBiID0gdmFsdWUuYm90dG9tO1xuICAgICAgICBsID0gdmFsdWUubGVmdDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0ID0gciA9IGIgPSBsID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogdCxcbiAgICAgICAgcmlnaHQ6IHIsXG4gICAgICAgIGJvdHRvbTogYixcbiAgICAgICAgbGVmdDogbCxcbiAgICAgICAgZGlzYWJsZWQ6IHZhbHVlID09PSBmYWxzZVxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRTb3J0ZWREYXRhc2V0SW5kaWNlcyhjaGFydCwgZmlsdGVyVmlzaWJsZSkge1xuICAgIGNvbnN0IGtleXMgPSBbXTtcbiAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0Ll9nZXRTb3J0ZWREYXRhc2V0TWV0YXMoZmlsdGVyVmlzaWJsZSk7XG4gICAgbGV0IGksIGlsZW47XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gbWV0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAga2V5cy5wdXNoKG1ldGFzZXRzW2ldLmluZGV4KTtcbiAgICB9XG4gICAgcmV0dXJuIGtleXM7XG59XG5mdW5jdGlvbiBhcHBseVN0YWNrKHN0YWNrLCB2YWx1ZSwgZHNJbmRleCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3Qga2V5cyA9IHN0YWNrLmtleXM7XG4gICAgY29uc3Qgc2luZ2xlTW9kZSA9IG9wdGlvbnMubW9kZSA9PT0gJ3NpbmdsZSc7XG4gICAgbGV0IGksIGlsZW4sIGRhdGFzZXRJbmRleCwgb3RoZXJWYWx1ZTtcbiAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGRhdGFzZXRJbmRleCA9ICtrZXlzW2ldO1xuICAgICAgICBpZiAoZGF0YXNldEluZGV4ID09PSBkc0luZGV4KSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hbGwpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG90aGVyVmFsdWUgPSBzdGFjay52YWx1ZXNbZGF0YXNldEluZGV4XTtcbiAgICAgICAgaWYgKGlzTnVtYmVyRmluaXRlKG90aGVyVmFsdWUpICYmIChzaW5nbGVNb2RlIHx8IHZhbHVlID09PSAwIHx8IHNpZ24odmFsdWUpID09PSBzaWduKG90aGVyVmFsdWUpKSkge1xuICAgICAgICAgICAgdmFsdWUgKz0gb3RoZXJWYWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiBjb252ZXJ0T2JqZWN0RGF0YVRvQXJyYXkoZGF0YSkge1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhkYXRhKTtcbiAgICBjb25zdCBhZGF0YSA9IG5ldyBBcnJheShrZXlzLmxlbmd0aCk7XG4gICAgbGV0IGksIGlsZW4sIGtleTtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgIGFkYXRhW2ldID0ge1xuICAgICAgICAgICAgeDoga2V5LFxuICAgICAgICAgICAgeTogZGF0YVtrZXldXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBhZGF0YTtcbn1cbmZ1bmN0aW9uIGlzU3RhY2tlZChzY2FsZSwgbWV0YSkge1xuICAgIGNvbnN0IHN0YWNrZWQgPSBzY2FsZSAmJiBzY2FsZS5vcHRpb25zLnN0YWNrZWQ7XG4gICAgcmV0dXJuIHN0YWNrZWQgfHwgc3RhY2tlZCA9PT0gdW5kZWZpbmVkICYmIG1ldGEuc3RhY2sgIT09IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGdldFN0YWNrS2V5KGluZGV4U2NhbGUsIHZhbHVlU2NhbGUsIG1ldGEpIHtcbiAgICByZXR1cm4gYCR7aW5kZXhTY2FsZS5pZH0uJHt2YWx1ZVNjYWxlLmlkfS4ke21ldGEuc3RhY2sgfHwgbWV0YS50eXBlfWA7XG59XG5mdW5jdGlvbiBnZXRVc2VyQm91bmRzKHNjYWxlKSB7XG4gICAgY29uc3QgeyBtaW4gLCBtYXggLCBtaW5EZWZpbmVkICwgbWF4RGVmaW5lZCAgfSA9IHNjYWxlLmdldFVzZXJCb3VuZHMoKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBtaW46IG1pbkRlZmluZWQgPyBtaW4gOiBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksXG4gICAgICAgIG1heDogbWF4RGVmaW5lZCA/IG1heCA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWVxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRPckNyZWF0ZVN0YWNrKHN0YWNrcywgc3RhY2tLZXksIGluZGV4VmFsdWUpIHtcbiAgICBjb25zdCBzdWJTdGFjayA9IHN0YWNrc1tzdGFja0tleV0gfHwgKHN0YWNrc1tzdGFja0tleV0gPSB7fSk7XG4gICAgcmV0dXJuIHN1YlN0YWNrW2luZGV4VmFsdWVdIHx8IChzdWJTdGFja1tpbmRleFZhbHVlXSA9IHt9KTtcbn1cbmZ1bmN0aW9uIGdldExhc3RJbmRleEluU3RhY2soc3RhY2ssIHZTY2FsZSwgcG9zaXRpdmUsIHR5cGUpIHtcbiAgICBmb3IgKGNvbnN0IG1ldGEgb2YgdlNjYWxlLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHR5cGUpLnJldmVyc2UoKSl7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gc3RhY2tbbWV0YS5pbmRleF07XG4gICAgICAgIGlmIChwb3NpdGl2ZSAmJiB2YWx1ZSA+IDAgfHwgIXBvc2l0aXZlICYmIHZhbHVlIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGEuaW5kZXg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiB1cGRhdGVTdGFja3MoY29udHJvbGxlciwgcGFyc2VkKSB7XG4gICAgY29uc3QgeyBjaGFydCAsIF9jYWNoZWRNZXRhOiBtZXRhICB9ID0gY29udHJvbGxlcjtcbiAgICBjb25zdCBzdGFja3MgPSBjaGFydC5fc3RhY2tzIHx8IChjaGFydC5fc3RhY2tzID0ge30pO1xuICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICwgaW5kZXg6IGRhdGFzZXRJbmRleCAgfSA9IG1ldGE7XG4gICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICBjb25zdCB2QXhpcyA9IHZTY2FsZS5heGlzO1xuICAgIGNvbnN0IGtleSA9IGdldFN0YWNrS2V5KGlTY2FsZSwgdlNjYWxlLCBtZXRhKTtcbiAgICBjb25zdCBpbGVuID0gcGFyc2VkLmxlbmd0aDtcbiAgICBsZXQgc3RhY2s7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBwYXJzZWRbaV07XG4gICAgICAgIGNvbnN0IHsgW2lBeGlzXTogaW5kZXggLCBbdkF4aXNdOiB2YWx1ZSAgfSA9IGl0ZW07XG4gICAgICAgIGNvbnN0IGl0ZW1TdGFja3MgPSBpdGVtLl9zdGFja3MgfHwgKGl0ZW0uX3N0YWNrcyA9IHt9KTtcbiAgICAgICAgc3RhY2sgPSBpdGVtU3RhY2tzW3ZBeGlzXSA9IGdldE9yQ3JlYXRlU3RhY2soc3RhY2tzLCBrZXksIGluZGV4KTtcbiAgICAgICAgc3RhY2tbZGF0YXNldEluZGV4XSA9IHZhbHVlO1xuICAgICAgICBzdGFjay5fdG9wID0gZ2V0TGFzdEluZGV4SW5TdGFjayhzdGFjaywgdlNjYWxlLCB0cnVlLCBtZXRhLnR5cGUpO1xuICAgICAgICBzdGFjay5fYm90dG9tID0gZ2V0TGFzdEluZGV4SW5TdGFjayhzdGFjaywgdlNjYWxlLCBmYWxzZSwgbWV0YS50eXBlKTtcbiAgICAgICAgY29uc3QgdmlzdWFsVmFsdWVzID0gc3RhY2suX3Zpc3VhbFZhbHVlcyB8fCAoc3RhY2suX3Zpc3VhbFZhbHVlcyA9IHt9KTtcbiAgICAgICAgdmlzdWFsVmFsdWVzW2RhdGFzZXRJbmRleF0gPSB2YWx1ZTtcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsIGF4aXMpIHtcbiAgICBjb25zdCBzY2FsZXMgPSBjaGFydC5zY2FsZXM7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHNjYWxlcykuZmlsdGVyKChrZXkpPT5zY2FsZXNba2V5XS5heGlzID09PSBheGlzKS5zaGlmdCgpO1xufVxuZnVuY3Rpb24gY3JlYXRlRGF0YXNldENvbnRleHQocGFyZW50LCBpbmRleCkge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICBhY3RpdmU6IGZhbHNlLFxuICAgICAgICBkYXRhc2V0OiB1bmRlZmluZWQsXG4gICAgICAgIGRhdGFzZXRJbmRleDogaW5kZXgsXG4gICAgICAgIGluZGV4LFxuICAgICAgICBtb2RlOiAnZGVmYXVsdCcsXG4gICAgICAgIHR5cGU6ICdkYXRhc2V0J1xuICAgIH0pO1xufVxuZnVuY3Rpb24gY3JlYXRlRGF0YUNvbnRleHQocGFyZW50LCBpbmRleCwgZWxlbWVudCkge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICBhY3RpdmU6IGZhbHNlLFxuICAgICAgICBkYXRhSW5kZXg6IGluZGV4LFxuICAgICAgICBwYXJzZWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgcmF3OiB1bmRlZmluZWQsXG4gICAgICAgIGVsZW1lbnQsXG4gICAgICAgIGluZGV4LFxuICAgICAgICBtb2RlOiAnZGVmYXVsdCcsXG4gICAgICAgIHR5cGU6ICdkYXRhJ1xuICAgIH0pO1xufVxuZnVuY3Rpb24gY2xlYXJTdGFja3MobWV0YSwgaXRlbXMpIHtcbiAgICBjb25zdCBkYXRhc2V0SW5kZXggPSBtZXRhLmNvbnRyb2xsZXIuaW5kZXg7XG4gICAgY29uc3QgYXhpcyA9IG1ldGEudlNjYWxlICYmIG1ldGEudlNjYWxlLmF4aXM7XG4gICAgaWYgKCFheGlzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaXRlbXMgPSBpdGVtcyB8fCBtZXRhLl9wYXJzZWQ7XG4gICAgZm9yIChjb25zdCBwYXJzZWQgb2YgaXRlbXMpe1xuICAgICAgICBjb25zdCBzdGFja3MgPSBwYXJzZWQuX3N0YWNrcztcbiAgICAgICAgaWYgKCFzdGFja3MgfHwgc3RhY2tzW2F4aXNdID09PSB1bmRlZmluZWQgfHwgc3RhY2tzW2F4aXNdW2RhdGFzZXRJbmRleF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSBzdGFja3NbYXhpc11bZGF0YXNldEluZGV4XTtcbiAgICAgICAgaWYgKHN0YWNrc1theGlzXS5fdmlzdWFsVmFsdWVzICE9PSB1bmRlZmluZWQgJiYgc3RhY2tzW2F4aXNdLl92aXN1YWxWYWx1ZXNbZGF0YXNldEluZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkZWxldGUgc3RhY2tzW2F4aXNdLl92aXN1YWxWYWx1ZXNbZGF0YXNldEluZGV4XTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmNvbnN0IGlzRGlyZWN0VXBkYXRlTW9kZSA9IChtb2RlKT0+bW9kZSA9PT0gJ3Jlc2V0JyB8fCBtb2RlID09PSAnbm9uZSc7XG5jb25zdCBjbG9uZUlmTm90U2hhcmVkID0gKGNhY2hlZCwgc2hhcmVkKT0+c2hhcmVkID8gY2FjaGVkIDogT2JqZWN0LmFzc2lnbih7fSwgY2FjaGVkKTtcbmNvbnN0IGNyZWF0ZVN0YWNrID0gKGNhblN0YWNrLCBtZXRhLCBjaGFydCk9PmNhblN0YWNrICYmICFtZXRhLmhpZGRlbiAmJiBtZXRhLl9zdGFja2VkICYmIHtcbiAgICAgICAga2V5czogZ2V0U29ydGVkRGF0YXNldEluZGljZXMoY2hhcnQsIHRydWUpLFxuICAgICAgICB2YWx1ZXM6IG51bGxcbiAgICB9O1xuY2xhc3MgRGF0YXNldENvbnRyb2xsZXIge1xuIHN0YXRpYyBkZWZhdWx0cyA9IHt9O1xuIHN0YXRpYyBkYXRhc2V0RWxlbWVudFR5cGUgPSBudWxsO1xuIHN0YXRpYyBkYXRhRWxlbWVudFR5cGUgPSBudWxsO1xuIGNvbnN0cnVjdG9yKGNoYXJ0LCBkYXRhc2V0SW5kZXgpe1xuICAgICAgICB0aGlzLmNoYXJ0ID0gY2hhcnQ7XG4gICAgICAgIHRoaXMuX2N0eCA9IGNoYXJ0LmN0eDtcbiAgICAgICAgdGhpcy5pbmRleCA9IGRhdGFzZXRJbmRleDtcbiAgICAgICAgdGhpcy5fY2FjaGVkRGF0YU9wdHMgPSB7fTtcbiAgICAgICAgdGhpcy5fY2FjaGVkTWV0YSA9IHRoaXMuZ2V0TWV0YSgpO1xuICAgICAgICB0aGlzLl90eXBlID0gdGhpcy5fY2FjaGVkTWV0YS50eXBlO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLl9wYXJzaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX29iamVjdERhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3NoYXJlZE9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2RyYXdTdGFydCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fZHJhd0NvdW50ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zdXBwb3J0c0RlY2ltYXRpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fc3luY0xpc3QgPSBbXTtcbiAgICAgICAgdGhpcy5kYXRhc2V0RWxlbWVudFR5cGUgPSBuZXcudGFyZ2V0LmRhdGFzZXRFbGVtZW50VHlwZTtcbiAgICAgICAgdGhpcy5kYXRhRWxlbWVudFR5cGUgPSBuZXcudGFyZ2V0LmRhdGFFbGVtZW50VHlwZTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XG4gICAgfVxuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyZSgpO1xuICAgICAgICB0aGlzLmxpbmtTY2FsZXMoKTtcbiAgICAgICAgbWV0YS5fc3RhY2tlZCA9IGlzU3RhY2tlZChtZXRhLnZTY2FsZSwgbWV0YSk7XG4gICAgICAgIHRoaXMuYWRkRWxlbWVudHMoKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5maWxsICYmICF0aGlzLmNoYXJ0LmlzUGx1Z2luRW5hYmxlZCgnZmlsbGVyJykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlRyaWVkIHRvIHVzZSB0aGUgJ2ZpbGwnIG9wdGlvbiB3aXRob3V0IHRoZSAnRmlsbGVyJyBwbHVnaW4gZW5hYmxlZC4gUGxlYXNlIGltcG9ydCBhbmQgcmVnaXN0ZXIgdGhlICdGaWxsZXInIHBsdWdpbiBhbmQgbWFrZSBzdXJlIGl0IGlzIG5vdCBkaXNhYmxlZCBpbiB0aGUgb3B0aW9uc1wiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGVJbmRleChkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5kZXggIT09IGRhdGFzZXRJbmRleCkge1xuICAgICAgICAgICAgY2xlYXJTdGFja3ModGhpcy5fY2FjaGVkTWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmRleCA9IGRhdGFzZXRJbmRleDtcbiAgICB9XG4gICAgbGlua1NjYWxlcygpIHtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZ2V0RGF0YXNldCgpO1xuICAgICAgICBjb25zdCBjaG9vc2VJZCA9IChheGlzLCB4LCB5LCByKT0+YXhpcyA9PT0gJ3gnID8geCA6IGF4aXMgPT09ICdyJyA/IHIgOiB5O1xuICAgICAgICBjb25zdCB4aWQgPSBtZXRhLnhBeGlzSUQgPSB2YWx1ZU9yRGVmYXVsdChkYXRhc2V0LnhBeGlzSUQsIGdldEZpcnN0U2NhbGVJZChjaGFydCwgJ3gnKSk7XG4gICAgICAgIGNvbnN0IHlpZCA9IG1ldGEueUF4aXNJRCA9IHZhbHVlT3JEZWZhdWx0KGRhdGFzZXQueUF4aXNJRCwgZ2V0Rmlyc3RTY2FsZUlkKGNoYXJ0LCAneScpKTtcbiAgICAgICAgY29uc3QgcmlkID0gbWV0YS5yQXhpc0lEID0gdmFsdWVPckRlZmF1bHQoZGF0YXNldC5yQXhpc0lELCBnZXRGaXJzdFNjYWxlSWQoY2hhcnQsICdyJykpO1xuICAgICAgICBjb25zdCBpbmRleEF4aXMgPSBtZXRhLmluZGV4QXhpcztcbiAgICAgICAgY29uc3QgaWlkID0gbWV0YS5pQXhpc0lEID0gY2hvb3NlSWQoaW5kZXhBeGlzLCB4aWQsIHlpZCwgcmlkKTtcbiAgICAgICAgY29uc3QgdmlkID0gbWV0YS52QXhpc0lEID0gY2hvb3NlSWQoaW5kZXhBeGlzLCB5aWQsIHhpZCwgcmlkKTtcbiAgICAgICAgbWV0YS54U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoeGlkKTtcbiAgICAgICAgbWV0YS55U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoeWlkKTtcbiAgICAgICAgbWV0YS5yU2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQocmlkKTtcbiAgICAgICAgbWV0YS5pU2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQoaWlkKTtcbiAgICAgICAgbWV0YS52U2NhbGUgPSB0aGlzLmdldFNjYWxlRm9ySWQodmlkKTtcbiAgICB9XG4gICAgZ2V0RGF0YXNldCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0c1t0aGlzLmluZGV4XTtcbiAgICB9XG4gICAgZ2V0TWV0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEodGhpcy5pbmRleCk7XG4gICAgfVxuIGdldFNjYWxlRm9ySWQoc2NhbGVJRCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jaGFydC5zY2FsZXNbc2NhbGVJRF07XG4gICAgfVxuIF9nZXRPdGhlclNjYWxlKHNjYWxlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICByZXR1cm4gc2NhbGUgPT09IG1ldGEuaVNjYWxlID8gbWV0YS52U2NhbGUgOiBtZXRhLmlTY2FsZTtcbiAgICB9XG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZSgncmVzZXQnKTtcbiAgICB9XG4gX2Rlc3Ryb3koKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBpZiAodGhpcy5fZGF0YSkge1xuICAgICAgICAgICAgdW5saXN0ZW5BcnJheUV2ZW50cyh0aGlzLl9kYXRhLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YS5fc3RhY2tlZCkge1xuICAgICAgICAgICAgY2xlYXJTdGFja3MobWV0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gX2RhdGFDaGVjaygpIHtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZ2V0RGF0YXNldCgpO1xuICAgICAgICBjb25zdCBkYXRhID0gZGF0YXNldC5kYXRhIHx8IChkYXRhc2V0LmRhdGEgPSBbXSk7XG4gICAgICAgIGNvbnN0IF9kYXRhID0gdGhpcy5fZGF0YTtcbiAgICAgICAgaWYgKGlzT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgICAgICB0aGlzLl9kYXRhID0gY29udmVydE9iamVjdERhdGFUb0FycmF5KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKF9kYXRhICE9PSBkYXRhKSB7XG4gICAgICAgICAgICBpZiAoX2RhdGEpIHtcbiAgICAgICAgICAgICAgICB1bmxpc3RlbkFycmF5RXZlbnRzKF9kYXRhLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgICAgICAgICBjbGVhclN0YWNrcyhtZXRhKTtcbiAgICAgICAgICAgICAgICBtZXRhLl9wYXJzZWQgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkYXRhICYmIE9iamVjdC5pc0V4dGVuc2libGUoZGF0YSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5BcnJheUV2ZW50cyhkYXRhLCB0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3N5bmNMaXN0ID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRhID0gZGF0YTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhZGRFbGVtZW50cygpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIHRoaXMuX2RhdGFDaGVjaygpO1xuICAgICAgICBpZiAodGhpcy5kYXRhc2V0RWxlbWVudFR5cGUpIHtcbiAgICAgICAgICAgIG1ldGEuZGF0YXNldCA9IG5ldyB0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGJ1aWxkT3JVcGRhdGVFbGVtZW50cyhyZXNldE5ld0VsZW1lbnRzKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5nZXREYXRhc2V0KCk7XG4gICAgICAgIGxldCBzdGFja0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fZGF0YUNoZWNrKCk7XG4gICAgICAgIGNvbnN0IG9sZFN0YWNrZWQgPSBtZXRhLl9zdGFja2VkO1xuICAgICAgICBtZXRhLl9zdGFja2VkID0gaXNTdGFja2VkKG1ldGEudlNjYWxlLCBtZXRhKTtcbiAgICAgICAgaWYgKG1ldGEuc3RhY2sgIT09IGRhdGFzZXQuc3RhY2spIHtcbiAgICAgICAgICAgIHN0YWNrQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgICBjbGVhclN0YWNrcyhtZXRhKTtcbiAgICAgICAgICAgIG1ldGEuc3RhY2sgPSBkYXRhc2V0LnN0YWNrO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Jlc3luY0VsZW1lbnRzKHJlc2V0TmV3RWxlbWVudHMpO1xuICAgICAgICBpZiAoc3RhY2tDaGFuZ2VkIHx8IG9sZFN0YWNrZWQgIT09IG1ldGEuX3N0YWNrZWQpIHtcbiAgICAgICAgICAgIHVwZGF0ZVN0YWNrcyh0aGlzLCBtZXRhLl9wYXJzZWQpO1xuICAgICAgICB9XG4gICAgfVxuIGNvbmZpZ3VyZSgpIHtcbiAgICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5jaGFydC5jb25maWc7XG4gICAgICAgIGNvbnN0IHNjb3BlS2V5cyA9IGNvbmZpZy5kYXRhc2V0U2NvcGVLZXlzKHRoaXMuX3R5cGUpO1xuICAgICAgICBjb25zdCBzY29wZXMgPSBjb25maWcuZ2V0T3B0aW9uU2NvcGVzKHRoaXMuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMsIHRydWUpO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBjb25maWcuY3JlYXRlUmVzb2x2ZXIoc2NvcGVzLCB0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIHRoaXMuX3BhcnNpbmcgPSB0aGlzLm9wdGlvbnMucGFyc2luZztcbiAgICAgICAgdGhpcy5fY2FjaGVkRGF0YU9wdHMgPSB7fTtcbiAgICB9XG4gcGFyc2Uoc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHsgX2NhY2hlZE1ldGE6IG1ldGEgLCBfZGF0YTogZGF0YSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICwgX3N0YWNrZWQgIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCBpQXhpcyA9IGlTY2FsZS5heGlzO1xuICAgICAgICBsZXQgc29ydGVkID0gc3RhcnQgPT09IDAgJiYgY291bnQgPT09IGRhdGEubGVuZ3RoID8gdHJ1ZSA6IG1ldGEuX3NvcnRlZDtcbiAgICAgICAgbGV0IHByZXYgPSBzdGFydCA+IDAgJiYgbWV0YS5fcGFyc2VkW3N0YXJ0IC0gMV07XG4gICAgICAgIGxldCBpLCBjdXIsIHBhcnNlZDtcbiAgICAgICAgaWYgKHRoaXMuX3BhcnNpbmcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBtZXRhLl9wYXJzZWQgPSBkYXRhO1xuICAgICAgICAgICAgbWV0YS5fc29ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlZCA9IGRhdGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoaXNBcnJheShkYXRhW3N0YXJ0XSkpIHtcbiAgICAgICAgICAgICAgICBwYXJzZWQgPSB0aGlzLnBhcnNlQXJyYXlEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGRhdGFbc3RhcnRdKSkge1xuICAgICAgICAgICAgICAgIHBhcnNlZCA9IHRoaXMucGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcnNlZCA9IHRoaXMucGFyc2VQcmltaXRpdmVEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpc05vdEluT3JkZXJDb21wYXJlZFRvUHJldiA9ICgpPT5jdXJbaUF4aXNdID09PSBudWxsIHx8IHByZXYgJiYgY3VyW2lBeGlzXSA8IHByZXZbaUF4aXNdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7ICsraSl7XG4gICAgICAgICAgICAgICAgbWV0YS5fcGFyc2VkW2kgKyBzdGFydF0gPSBjdXIgPSBwYXJzZWRbaV07XG4gICAgICAgICAgICAgICAgaWYgKHNvcnRlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOb3RJbk9yZGVyQ29tcGFyZWRUb1ByZXYoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc29ydGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHJldiA9IGN1cjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZXRhLl9zb3J0ZWQgPSBzb3J0ZWQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF9zdGFja2VkKSB7XG4gICAgICAgICAgICB1cGRhdGVTdGFja3ModGhpcywgcGFyc2VkKTtcbiAgICAgICAgfVxuICAgIH1cbiBwYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICAgICAgY29uc3QgdkF4aXMgPSB2U2NhbGUuYXhpcztcbiAgICAgICAgY29uc3QgbGFiZWxzID0gaVNjYWxlLmdldExhYmVscygpO1xuICAgICAgICBjb25zdCBzaW5nbGVTY2FsZSA9IGlTY2FsZSA9PT0gdlNjYWxlO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBsZXQgaSwgaWxlbiwgaW5kZXg7XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGNvdW50OyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGluZGV4ID0gaSArIHN0YXJ0O1xuICAgICAgICAgICAgcGFyc2VkW2ldID0ge1xuICAgICAgICAgICAgICAgIFtpQXhpc106IHNpbmdsZVNjYWxlIHx8IGlTY2FsZS5wYXJzZShsYWJlbHNbaW5kZXhdLCBpbmRleCksXG4gICAgICAgICAgICAgICAgW3ZBeGlzXTogdlNjYWxlLnBhcnNlKGRhdGFbaW5kZXhdLCBpbmRleClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcnNlZDtcbiAgICB9XG4gcGFyc2VBcnJheURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHsgeFNjYWxlICwgeVNjYWxlICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgbGV0IGksIGlsZW4sIGluZGV4LCBpdGVtO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBpbmRleCA9IGkgKyBzdGFydDtcbiAgICAgICAgICAgIGl0ZW0gPSBkYXRhW2luZGV4XTtcbiAgICAgICAgICAgIHBhcnNlZFtpXSA9IHtcbiAgICAgICAgICAgICAgICB4OiB4U2NhbGUucGFyc2UoaXRlbVswXSwgaW5kZXgpLFxuICAgICAgICAgICAgICAgIHk6IHlTY2FsZS5wYXJzZShpdGVtWzFdLCBpbmRleClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcnNlZDtcbiAgICB9XG4gcGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCB7IHhTY2FsZSAsIHlTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHsgeEF4aXNLZXkgPSd4JyAsIHlBeGlzS2V5ID0neScgIH0gPSB0aGlzLl9wYXJzaW5nO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBsZXQgaSwgaWxlbiwgaW5kZXgsIGl0ZW07XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGNvdW50OyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGluZGV4ID0gaSArIHN0YXJ0O1xuICAgICAgICAgICAgaXRlbSA9IGRhdGFbaW5kZXhdO1xuICAgICAgICAgICAgcGFyc2VkW2ldID0ge1xuICAgICAgICAgICAgICAgIHg6IHhTY2FsZS5wYXJzZShyZXNvbHZlT2JqZWN0S2V5KGl0ZW0sIHhBeGlzS2V5KSwgaW5kZXgpLFxuICAgICAgICAgICAgICAgIHk6IHlTY2FsZS5wYXJzZShyZXNvbHZlT2JqZWN0S2V5KGl0ZW0sIHlBeGlzS2V5KSwgaW5kZXgpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIGdldFBhcnNlZChpbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FjaGVkTWV0YS5fcGFyc2VkW2luZGV4XTtcbiAgICB9XG4gZ2V0RGF0YUVsZW1lbnQoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZE1ldGEuZGF0YVtpbmRleF07XG4gICAgfVxuIGFwcGx5U3RhY2soc2NhbGUsIHBhcnNlZCwgbW9kZSkge1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBhcnNlZFtzY2FsZS5heGlzXTtcbiAgICAgICAgY29uc3Qgc3RhY2sgPSB7XG4gICAgICAgICAgICBrZXlzOiBnZXRTb3J0ZWREYXRhc2V0SW5kaWNlcyhjaGFydCwgdHJ1ZSksXG4gICAgICAgICAgICB2YWx1ZXM6IHBhcnNlZC5fc3RhY2tzW3NjYWxlLmF4aXNdLl92aXN1YWxWYWx1ZXNcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGFwcGx5U3RhY2soc3RhY2ssIHZhbHVlLCBtZXRhLmluZGV4LCB7XG4gICAgICAgICAgICBtb2RlXG4gICAgICAgIH0pO1xuICAgIH1cbiB1cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFZhbHVlID0gcGFyc2VkW3NjYWxlLmF4aXNdO1xuICAgICAgICBsZXQgdmFsdWUgPSBwYXJzZWRWYWx1ZSA9PT0gbnVsbCA/IE5hTiA6IHBhcnNlZFZhbHVlO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBzdGFjayAmJiBwYXJzZWQuX3N0YWNrc1tzY2FsZS5heGlzXTtcbiAgICAgICAgaWYgKHN0YWNrICYmIHZhbHVlcykge1xuICAgICAgICAgICAgc3RhY2sudmFsdWVzID0gdmFsdWVzO1xuICAgICAgICAgICAgdmFsdWUgPSBhcHBseVN0YWNrKHN0YWNrLCBwYXJzZWRWYWx1ZSwgdGhpcy5fY2FjaGVkTWV0YS5pbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgcmFuZ2UubWluID0gTWF0aC5taW4ocmFuZ2UubWluLCB2YWx1ZSk7XG4gICAgICAgIHJhbmdlLm1heCA9IE1hdGgubWF4KHJhbmdlLm1heCwgdmFsdWUpO1xuICAgIH1cbiBnZXRNaW5NYXgoc2NhbGUsIGNhblN0YWNrKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBfcGFyc2VkID0gbWV0YS5fcGFyc2VkO1xuICAgICAgICBjb25zdCBzb3J0ZWQgPSBtZXRhLl9zb3J0ZWQgJiYgc2NhbGUgPT09IG1ldGEuaVNjYWxlO1xuICAgICAgICBjb25zdCBpbGVuID0gX3BhcnNlZC5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG90aGVyU2NhbGUgPSB0aGlzLl9nZXRPdGhlclNjYWxlKHNjYWxlKTtcbiAgICAgICAgY29uc3Qgc3RhY2sgPSBjcmVhdGVTdGFjayhjYW5TdGFjaywgbWV0YSwgdGhpcy5jaGFydCk7XG4gICAgICAgIGNvbnN0IHJhbmdlID0ge1xuICAgICAgICAgICAgbWluOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXG4gICAgICAgICAgICBtYXg6IE51bWJlci5ORUdBVElWRV9JTkZJTklUWVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IG1pbjogb3RoZXJNaW4gLCBtYXg6IG90aGVyTWF4ICB9ID0gZ2V0VXNlckJvdW5kcyhvdGhlclNjYWxlKTtcbiAgICAgICAgbGV0IGksIHBhcnNlZDtcbiAgICAgICAgZnVuY3Rpb24gX3NraXAoKSB7XG4gICAgICAgICAgICBwYXJzZWQgPSBfcGFyc2VkW2ldO1xuICAgICAgICAgICAgY29uc3Qgb3RoZXJWYWx1ZSA9IHBhcnNlZFtvdGhlclNjYWxlLmF4aXNdO1xuICAgICAgICAgICAgcmV0dXJuICFpc051bWJlckZpbml0ZShwYXJzZWRbc2NhbGUuYXhpc10pIHx8IG90aGVyTWluID4gb3RoZXJWYWx1ZSB8fCBvdGhlck1heCA8IG90aGVyVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGlmIChfc2tpcCgpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVJhbmdlRnJvbVBhcnNlZChyYW5nZSwgc2NhbGUsIHBhcnNlZCwgc3RhY2spO1xuICAgICAgICAgICAgaWYgKHNvcnRlZCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzb3J0ZWQpIHtcbiAgICAgICAgICAgIGZvcihpID0gaWxlbiAtIDE7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgICAgICBpZiAoX3NraXAoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVSYW5nZUZyb21QYXJzZWQocmFuZ2UsIHNjYWxlLCBwYXJzZWQsIHN0YWNrKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuICAgIGdldEFsbFBhcnNlZFZhbHVlcyhzY2FsZSkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLl9jYWNoZWRNZXRhLl9wYXJzZWQ7XG4gICAgICAgIGNvbnN0IHZhbHVlcyA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbiwgdmFsdWU7XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IHBhcnNlZC5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdmFsdWUgPSBwYXJzZWRbaV1bc2NhbGUuYXhpc107XG4gICAgICAgICAgICBpZiAoaXNOdW1iZXJGaW5pdGUodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgfVxuIGdldE1heE92ZXJmbG93KCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuIGdldExhYmVsQW5kVmFsdWUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGlTY2FsZSA9IG1ldGEuaVNjYWxlO1xuICAgICAgICBjb25zdCB2U2NhbGUgPSBtZXRhLnZTY2FsZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gdGhpcy5nZXRQYXJzZWQoaW5kZXgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IGlTY2FsZSA/ICcnICsgaVNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW2lTY2FsZS5heGlzXSkgOiAnJyxcbiAgICAgICAgICAgIHZhbHVlOiB2U2NhbGUgPyAnJyArIHZTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZFt2U2NhbGUuYXhpc10pIDogJydcbiAgICAgICAgfTtcbiAgICB9XG4gX3VwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICB0aGlzLnVwZGF0ZShtb2RlIHx8ICdkZWZhdWx0Jyk7XG4gICAgICAgIG1ldGEuX2NsaXAgPSB0b0NsaXAodmFsdWVPckRlZmF1bHQodGhpcy5vcHRpb25zLmNsaXAsIGRlZmF1bHRDbGlwKG1ldGEueFNjYWxlLCBtZXRhLnlTY2FsZSwgdGhpcy5nZXRNYXhPdmVyZmxvdygpKSkpO1xuICAgIH1cbiB1cGRhdGUobW9kZSkge31cbiAgICBkcmF3KCkge1xuICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9jdHg7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gbWV0YS5kYXRhIHx8IFtdO1xuICAgICAgICBjb25zdCBhcmVhID0gY2hhcnQuY2hhcnRBcmVhO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSBbXTtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLl9kcmF3U3RhcnQgfHwgMDtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLl9kcmF3Q291bnQgfHwgZWxlbWVudHMubGVuZ3RoIC0gc3RhcnQ7XG4gICAgICAgIGNvbnN0IGRyYXdBY3RpdmVFbGVtZW50c09uVG9wID0gdGhpcy5vcHRpb25zLmRyYXdBY3RpdmVFbGVtZW50c09uVG9wO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgaWYgKG1ldGEuZGF0YXNldCkge1xuICAgICAgICAgICAgbWV0YS5kYXRhc2V0LmRyYXcoY3R4LCBhcmVhLCBzdGFydCwgY291bnQpO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gc3RhcnQ7IGkgPCBzdGFydCArIGNvdW50OyArK2kpe1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKGVsZW1lbnQuaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZWxlbWVudC5hY3RpdmUgJiYgZHJhd0FjdGl2ZUVsZW1lbnRzT25Ub3ApIHtcbiAgICAgICAgICAgICAgICBhY3RpdmUucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5kcmF3KGN0eCwgYXJlYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWN0aXZlLmxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgIGFjdGl2ZVtpXS5kcmF3KGN0eCwgYXJlYSk7XG4gICAgICAgIH1cbiAgICB9XG4gZ2V0U3R5bGUoaW5kZXgsIGFjdGl2ZSkge1xuICAgICAgICBjb25zdCBtb2RlID0gYWN0aXZlID8gJ2FjdGl2ZScgOiAnZGVmYXVsdCc7XG4gICAgICAgIHJldHVybiBpbmRleCA9PT0gdW5kZWZpbmVkICYmIHRoaXMuX2NhY2hlZE1ldGEuZGF0YXNldCA/IHRoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhtb2RlKSA6IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpbmRleCB8fCAwLCBtb2RlKTtcbiAgICB9XG4gZ2V0Q29udGV4dChpbmRleCwgYWN0aXZlLCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IGRhdGFzZXQgPSB0aGlzLmdldERhdGFzZXQoKTtcbiAgICAgICAgbGV0IGNvbnRleHQ7XG4gICAgICAgIGlmIChpbmRleCA+PSAwICYmIGluZGV4IDwgdGhpcy5fY2FjaGVkTWV0YS5kYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2NhY2hlZE1ldGEuZGF0YVtpbmRleF07XG4gICAgICAgICAgICBjb250ZXh0ID0gZWxlbWVudC4kY29udGV4dCB8fCAoZWxlbWVudC4kY29udGV4dCA9IGNyZWF0ZURhdGFDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpLCBpbmRleCwgZWxlbWVudCkpO1xuICAgICAgICAgICAgY29udGV4dC5wYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgICAgICBjb250ZXh0LnJhdyA9IGRhdGFzZXQuZGF0YVtpbmRleF07XG4gICAgICAgICAgICBjb250ZXh0LmluZGV4ID0gY29udGV4dC5kYXRhSW5kZXggPSBpbmRleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRleHQgPSB0aGlzLiRjb250ZXh0IHx8ICh0aGlzLiRjb250ZXh0ID0gY3JlYXRlRGF0YXNldENvbnRleHQodGhpcy5jaGFydC5nZXRDb250ZXh0KCksIHRoaXMuaW5kZXgpKTtcbiAgICAgICAgICAgIGNvbnRleHQuZGF0YXNldCA9IGRhdGFzZXQ7XG4gICAgICAgICAgICBjb250ZXh0LmluZGV4ID0gY29udGV4dC5kYXRhc2V0SW5kZXggPSB0aGlzLmluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGNvbnRleHQuYWN0aXZlID0gISFhY3RpdmU7XG4gICAgICAgIGNvbnRleHQubW9kZSA9IG1vZGU7XG4gICAgICAgIHJldHVybiBjb250ZXh0O1xuICAgIH1cbiByZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKG1vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVFbGVtZW50T3B0aW9ucyh0aGlzLmRhdGFzZXRFbGVtZW50VHlwZS5pZCwgbW9kZSk7XG4gICAgfVxuIHJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaW5kZXgsIG1vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVFbGVtZW50T3B0aW9ucyh0aGlzLmRhdGFFbGVtZW50VHlwZS5pZCwgbW9kZSwgaW5kZXgpO1xuICAgIH1cbiBfcmVzb2x2ZUVsZW1lbnRPcHRpb25zKGVsZW1lbnRUeXBlLCBtb2RlID0gJ2RlZmF1bHQnLCBpbmRleCkge1xuICAgICAgICBjb25zdCBhY3RpdmUgPSBtb2RlID09PSAnYWN0aXZlJztcbiAgICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLl9jYWNoZWREYXRhT3B0cztcbiAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBlbGVtZW50VHlwZSArICctJyArIG1vZGU7XG4gICAgICAgIGNvbnN0IGNhY2hlZCA9IGNhY2hlW2NhY2hlS2V5XTtcbiAgICAgICAgY29uc3Qgc2hhcmluZyA9IHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyAmJiBkZWZpbmVkKGluZGV4KTtcbiAgICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNsb25lSWZOb3RTaGFyZWQoY2FjaGVkLCBzaGFyaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNoYXJ0LmNvbmZpZztcbiAgICAgICAgY29uc3Qgc2NvcGVLZXlzID0gY29uZmlnLmRhdGFzZXRFbGVtZW50U2NvcGVLZXlzKHRoaXMuX3R5cGUsIGVsZW1lbnRUeXBlKTtcbiAgICAgICAgY29uc3QgcHJlZml4ZXMgPSBhY3RpdmUgPyBbXG4gICAgICAgICAgICBgJHtlbGVtZW50VHlwZX1Ib3ZlcmAsXG4gICAgICAgICAgICAnaG92ZXInLFxuICAgICAgICAgICAgZWxlbWVudFR5cGUsXG4gICAgICAgICAgICAnJ1xuICAgICAgICBdIDogW1xuICAgICAgICAgICAgZWxlbWVudFR5cGUsXG4gICAgICAgICAgICAnJ1xuICAgICAgICBdO1xuICAgICAgICBjb25zdCBzY29wZXMgPSBjb25maWcuZ2V0T3B0aW9uU2NvcGVzKHRoaXMuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMpO1xuICAgICAgICBjb25zdCBuYW1lcyA9IE9iamVjdC5rZXlzKGRlZmF1bHRzLmVsZW1lbnRzW2VsZW1lbnRUeXBlXSk7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSAoKT0+dGhpcy5nZXRDb250ZXh0KGluZGV4LCBhY3RpdmUsIG1vZGUpO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBjb25maWcucmVzb2x2ZU5hbWVkT3B0aW9ucyhzY29wZXMsIG5hbWVzLCBjb250ZXh0LCBwcmVmaXhlcyk7XG4gICAgICAgIGlmICh2YWx1ZXMuJHNoYXJlZCkge1xuICAgICAgICAgICAgdmFsdWVzLiRzaGFyZWQgPSBzaGFyaW5nO1xuICAgICAgICAgICAgY2FjaGVbY2FjaGVLZXldID0gT2JqZWN0LmZyZWV6ZShjbG9uZUlmTm90U2hhcmVkKHZhbHVlcywgc2hhcmluZykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgfVxuIF9yZXNvbHZlQW5pbWF0aW9ucyhpbmRleCwgdHJhbnNpdGlvbiwgYWN0aXZlKSB7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLl9jYWNoZWREYXRhT3B0cztcbiAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBgYW5pbWF0aW9uLSR7dHJhbnNpdGlvbn1gO1xuICAgICAgICBjb25zdCBjYWNoZWQgPSBjYWNoZVtjYWNoZUtleV07XG4gICAgICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgIGlmIChjaGFydC5vcHRpb25zLmFuaW1hdGlvbiAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY2hhcnQuY29uZmlnO1xuICAgICAgICAgICAgY29uc3Qgc2NvcGVLZXlzID0gY29uZmlnLmRhdGFzZXRBbmltYXRpb25TY29wZUtleXModGhpcy5fdHlwZSwgdHJhbnNpdGlvbik7XG4gICAgICAgICAgICBjb25zdCBzY29wZXMgPSBjb25maWcuZ2V0T3B0aW9uU2NvcGVzKHRoaXMuZ2V0RGF0YXNldCgpLCBzY29wZUtleXMpO1xuICAgICAgICAgICAgb3B0aW9ucyA9IGNvbmZpZy5jcmVhdGVSZXNvbHZlcihzY29wZXMsIHRoaXMuZ2V0Q29udGV4dChpbmRleCwgYWN0aXZlLCB0cmFuc2l0aW9uKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IG5ldyBBbmltYXRpb25zKGNoYXJ0LCBvcHRpb25zICYmIG9wdGlvbnMuYW5pbWF0aW9ucyk7XG4gICAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuX2NhY2hlYWJsZSkge1xuICAgICAgICAgICAgY2FjaGVbY2FjaGVLZXldID0gT2JqZWN0LmZyZWV6ZShhbmltYXRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgICB9XG4gZ2V0U2hhcmVkT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgIGlmICghb3B0aW9ucy4kc2hhcmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3NoYXJlZE9wdGlvbnMgfHwgKHRoaXMuX3NoYXJlZE9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zKSk7XG4gICAgfVxuIGluY2x1ZGVPcHRpb25zKG1vZGUsIHNoYXJlZE9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuICFzaGFyZWRPcHRpb25zIHx8IGlzRGlyZWN0VXBkYXRlTW9kZShtb2RlKSB8fCB0aGlzLmNoYXJ0Ll9hbmltYXRpb25zRGlzYWJsZWQ7XG4gICAgfVxuIF9nZXRTaGFyZWRPcHRpb25zKHN0YXJ0LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IGZpcnN0T3B0cyA9IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzbHlTaGFyZWRPcHRpb25zID0gdGhpcy5fc2hhcmVkT3B0aW9ucztcbiAgICAgICAgY29uc3Qgc2hhcmVkT3B0aW9ucyA9IHRoaXMuZ2V0U2hhcmVkT3B0aW9ucyhmaXJzdE9wdHMpO1xuICAgICAgICBjb25zdCBpbmNsdWRlT3B0aW9ucyA9IHRoaXMuaW5jbHVkZU9wdGlvbnMobW9kZSwgc2hhcmVkT3B0aW9ucykgfHwgc2hhcmVkT3B0aW9ucyAhPT0gcHJldmlvdXNseVNoYXJlZE9wdGlvbnM7XG4gICAgICAgIHRoaXMudXBkYXRlU2hhcmVkT3B0aW9ucyhzaGFyZWRPcHRpb25zLCBtb2RlLCBmaXJzdE9wdHMpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2hhcmVkT3B0aW9ucyxcbiAgICAgICAgICAgIGluY2x1ZGVPcHRpb25zXG4gICAgICAgIH07XG4gICAgfVxuIHVwZGF0ZUVsZW1lbnQoZWxlbWVudCwgaW5kZXgsIHByb3BlcnRpZXMsIG1vZGUpIHtcbiAgICAgICAgaWYgKGlzRGlyZWN0VXBkYXRlTW9kZShtb2RlKSkge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihlbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKGluZGV4LCBtb2RlKS51cGRhdGUoZWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIH1cbiAgICB9XG4gdXBkYXRlU2hhcmVkT3B0aW9ucyhzaGFyZWRPcHRpb25zLCBtb2RlLCBuZXdPcHRpb25zKSB7XG4gICAgICAgIGlmIChzaGFyZWRPcHRpb25zICYmICFpc0RpcmVjdFVwZGF0ZU1vZGUobW9kZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKHVuZGVmaW5lZCwgbW9kZSkudXBkYXRlKHNoYXJlZE9wdGlvbnMsIG5ld09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuIF9zZXRTdHlsZShlbGVtZW50LCBpbmRleCwgbW9kZSwgYWN0aXZlKSB7XG4gICAgICAgIGVsZW1lbnQuYWN0aXZlID0gYWN0aXZlO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5nZXRTdHlsZShpbmRleCwgYWN0aXZlKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoaW5kZXgsIG1vZGUsIGFjdGl2ZSkudXBkYXRlKGVsZW1lbnQsIHtcbiAgICAgICAgICAgIG9wdGlvbnM6ICFhY3RpdmUgJiYgdGhpcy5nZXRTaGFyZWRPcHRpb25zKG9wdGlvbnMpIHx8IG9wdGlvbnNcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJlbW92ZUhvdmVyU3R5bGUoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCkge1xuICAgICAgICB0aGlzLl9zZXRTdHlsZShlbGVtZW50LCBpbmRleCwgJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICB9XG4gICAgc2V0SG92ZXJTdHlsZShlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIGluZGV4LCAnYWN0aXZlJywgdHJ1ZSk7XG4gICAgfVxuIF9yZW1vdmVEYXRhc2V0SG92ZXJTdHlsZSgpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2NhY2hlZE1ldGEuZGF0YXNldDtcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldFN0eWxlKGVsZW1lbnQsIHVuZGVmaW5lZCwgJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbiBfc2V0RGF0YXNldEhvdmVyU3R5bGUoKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQ7XG4gICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTdHlsZShlbGVtZW50LCB1bmRlZmluZWQsICdhY3RpdmUnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbiBfcmVzeW5jRWxlbWVudHMocmVzZXROZXdFbGVtZW50cykge1xuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTtcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGE7XG4gICAgICAgIGZvciAoY29uc3QgW21ldGhvZCwgYXJnMSwgYXJnMl0gb2YgdGhpcy5fc3luY0xpc3Qpe1xuICAgICAgICAgICAgdGhpc1ttZXRob2RdKGFyZzEsIGFyZzIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3N5bmNMaXN0ID0gW107XG4gICAgICAgIGNvbnN0IG51bU1ldGEgPSBlbGVtZW50cy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG51bURhdGEgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY291bnQgPSBNYXRoLm1pbihudW1EYXRhLCBudW1NZXRhKTtcbiAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgICB0aGlzLnBhcnNlKDAsIGNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobnVtRGF0YSA+IG51bU1ldGEpIHtcbiAgICAgICAgICAgIHRoaXMuX2luc2VydEVsZW1lbnRzKG51bU1ldGEsIG51bURhdGEgLSBudW1NZXRhLCByZXNldE5ld0VsZW1lbnRzKTtcbiAgICAgICAgfSBlbHNlIGlmIChudW1EYXRhIDwgbnVtTWV0YSkge1xuICAgICAgICAgICAgdGhpcy5fcmVtb3ZlRWxlbWVudHMobnVtRGF0YSwgbnVtTWV0YSAtIG51bURhdGEpO1xuICAgICAgICB9XG4gICAgfVxuIF9pbnNlcnRFbGVtZW50cyhzdGFydCwgY291bnQsIHJlc2V0TmV3RWxlbWVudHMgPSB0cnVlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBkYXRhID0gbWV0YS5kYXRhO1xuICAgICAgICBjb25zdCBlbmQgPSBzdGFydCArIGNvdW50O1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgY29uc3QgbW92ZSA9IChhcnIpPT57XG4gICAgICAgICAgICBhcnIubGVuZ3RoICs9IGNvdW50O1xuICAgICAgICAgICAgZm9yKGkgPSBhcnIubGVuZ3RoIC0gMTsgaSA+PSBlbmQ7IGktLSl7XG4gICAgICAgICAgICAgICAgYXJyW2ldID0gYXJyW2kgLSBjb3VudF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIG1vdmUoZGF0YSk7XG4gICAgICAgIGZvcihpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSl7XG4gICAgICAgICAgICBkYXRhW2ldID0gbmV3IHRoaXMuZGF0YUVsZW1lbnRUeXBlKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3BhcnNpbmcpIHtcbiAgICAgICAgICAgIG1vdmUobWV0YS5fcGFyc2VkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhcnNlKHN0YXJ0LCBjb3VudCk7XG4gICAgICAgIGlmIChyZXNldE5ld0VsZW1lbnRzKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKGRhdGEsIHN0YXJ0LCBjb3VudCwgJ3Jlc2V0Jyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdXBkYXRlRWxlbWVudHMoZWxlbWVudCwgc3RhcnQsIGNvdW50LCBtb2RlKSB7fVxuIF9yZW1vdmVFbGVtZW50cyhzdGFydCwgY291bnQpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGlmICh0aGlzLl9wYXJzaW5nKSB7XG4gICAgICAgICAgICBjb25zdCByZW1vdmVkID0gbWV0YS5fcGFyc2VkLnNwbGljZShzdGFydCwgY291bnQpO1xuICAgICAgICAgICAgaWYgKG1ldGEuX3N0YWNrZWQpIHtcbiAgICAgICAgICAgICAgICBjbGVhclN0YWNrcyhtZXRhLCByZW1vdmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtZXRhLmRhdGEuc3BsaWNlKHN0YXJ0LCBjb3VudCk7XG4gICAgfVxuIF9zeW5jKGFyZ3MpIHtcbiAgICAgICAgaWYgKHRoaXMuX3BhcnNpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuX3N5bmNMaXN0LnB1c2goYXJncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBbbWV0aG9kLCBhcmcxLCBhcmcyXSA9IGFyZ3M7XG4gICAgICAgICAgICB0aGlzW21ldGhvZF0oYXJnMSwgYXJnMik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jaGFydC5fZGF0YUNoYW5nZXMucHVzaChbXG4gICAgICAgICAgICB0aGlzLmluZGV4LFxuICAgICAgICAgICAgLi4uYXJnc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgX29uRGF0YVB1c2goKSB7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAnX2luc2VydEVsZW1lbnRzJyxcbiAgICAgICAgICAgIHRoaXMuZ2V0RGF0YXNldCgpLmRhdGEubGVuZ3RoIC0gY291bnQsXG4gICAgICAgICAgICBjb3VudFxuICAgICAgICBdKTtcbiAgICB9XG4gICAgX29uRGF0YVBvcCgpIHtcbiAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAnX3JlbW92ZUVsZW1lbnRzJyxcbiAgICAgICAgICAgIHRoaXMuX2NhY2hlZE1ldGEuZGF0YS5sZW5ndGggLSAxLFxuICAgICAgICAgICAgMVxuICAgICAgICBdKTtcbiAgICB9XG4gICAgX29uRGF0YVNoaWZ0KCkge1xuICAgICAgICB0aGlzLl9zeW5jKFtcbiAgICAgICAgICAgICdfcmVtb3ZlRWxlbWVudHMnLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIDFcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIF9vbkRhdGFTcGxpY2Uoc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGlmIChjb3VudCkge1xuICAgICAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAgICAgJ19yZW1vdmVFbGVtZW50cycsXG4gICAgICAgICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgICAgICAgY291bnRcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5ld0NvdW50ID0gYXJndW1lbnRzLmxlbmd0aCAtIDI7XG4gICAgICAgIGlmIChuZXdDb3VudCkge1xuICAgICAgICAgICAgdGhpcy5fc3luYyhbXG4gICAgICAgICAgICAgICAgJ19pbnNlcnRFbGVtZW50cycsXG4gICAgICAgICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgICAgICAgbmV3Q291bnRcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIF9vbkRhdGFVbnNoaWZ0KCkge1xuICAgICAgICB0aGlzLl9zeW5jKFtcbiAgICAgICAgICAgICdfaW5zZXJ0RWxlbWVudHMnLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIGFyZ3VtZW50cy5sZW5ndGhcbiAgICAgICAgXSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRBbGxTY2FsZVZhbHVlcyhzY2FsZSwgdHlwZSkge1xuICAgIGlmICghc2NhbGUuX2NhY2hlLiRiYXIpIHtcbiAgICAgICAgY29uc3QgdmlzaWJsZU1ldGFzID0gc2NhbGUuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXModHlwZSk7XG4gICAgICAgIGxldCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgZm9yKGxldCBpID0gMCwgaWxlbiA9IHZpc2libGVNZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICAgICAgdmFsdWVzID0gdmFsdWVzLmNvbmNhdCh2aXNpYmxlTWV0YXNbaV0uY29udHJvbGxlci5nZXRBbGxQYXJzZWRWYWx1ZXMoc2NhbGUpKTtcbiAgICAgICAgfVxuICAgICAgICBzY2FsZS5fY2FjaGUuJGJhciA9IF9hcnJheVVuaXF1ZSh2YWx1ZXMuc29ydCgoYSwgYik9PmEgLSBiKSk7XG4gICAgfVxuICAgIHJldHVybiBzY2FsZS5fY2FjaGUuJGJhcjtcbn1cbiBmdW5jdGlvbiBjb21wdXRlTWluU2FtcGxlU2l6ZShtZXRhKSB7XG4gICAgY29uc3Qgc2NhbGUgPSBtZXRhLmlTY2FsZTtcbiAgICBjb25zdCB2YWx1ZXMgPSBnZXRBbGxTY2FsZVZhbHVlcyhzY2FsZSwgbWV0YS50eXBlKTtcbiAgICBsZXQgbWluID0gc2NhbGUuX2xlbmd0aDtcbiAgICBsZXQgaSwgaWxlbiwgY3VyciwgcHJldjtcbiAgICBjb25zdCB1cGRhdGVNaW5BbmRQcmV2ID0gKCk9PntcbiAgICAgICAgaWYgKGN1cnIgPT09IDMyNzY3IHx8IGN1cnIgPT09IC0zMjc2OCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZWZpbmVkKHByZXYpKSB7XG4gICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIE1hdGguYWJzKGN1cnIgLSBwcmV2KSB8fCBtaW4pO1xuICAgICAgICB9XG4gICAgICAgIHByZXYgPSBjdXJyO1xuICAgIH07XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gdmFsdWVzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGN1cnIgPSBzY2FsZS5nZXRQaXhlbEZvclZhbHVlKHZhbHVlc1tpXSk7XG4gICAgICAgIHVwZGF0ZU1pbkFuZFByZXYoKTtcbiAgICB9XG4gICAgcHJldiA9IHVuZGVmaW5lZDtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBzY2FsZS50aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBjdXJyID0gc2NhbGUuZ2V0UGl4ZWxGb3JUaWNrKGkpO1xuICAgICAgICB1cGRhdGVNaW5BbmRQcmV2KCk7XG4gICAgfVxuICAgIHJldHVybiBtaW47XG59XG4gZnVuY3Rpb24gY29tcHV0ZUZpdENhdGVnb3J5VHJhaXRzKGluZGV4LCBydWxlciwgb3B0aW9ucywgc3RhY2tDb3VudCkge1xuICAgIGNvbnN0IHRoaWNrbmVzcyA9IG9wdGlvbnMuYmFyVGhpY2tuZXNzO1xuICAgIGxldCBzaXplLCByYXRpbztcbiAgICBpZiAoaXNOdWxsT3JVbmRlZih0aGlja25lc3MpKSB7XG4gICAgICAgIHNpemUgPSBydWxlci5taW4gKiBvcHRpb25zLmNhdGVnb3J5UGVyY2VudGFnZTtcbiAgICAgICAgcmF0aW8gPSBvcHRpb25zLmJhclBlcmNlbnRhZ2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2l6ZSA9IHRoaWNrbmVzcyAqIHN0YWNrQ291bnQ7XG4gICAgICAgIHJhdGlvID0gMTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY2h1bms6IHNpemUgLyBzdGFja0NvdW50LFxuICAgICAgICByYXRpbyxcbiAgICAgICAgc3RhcnQ6IHJ1bGVyLnBpeGVsc1tpbmRleF0gLSBzaXplIC8gMlxuICAgIH07XG59XG4gZnVuY3Rpb24gY29tcHV0ZUZsZXhDYXRlZ29yeVRyYWl0cyhpbmRleCwgcnVsZXIsIG9wdGlvbnMsIHN0YWNrQ291bnQpIHtcbiAgICBjb25zdCBwaXhlbHMgPSBydWxlci5waXhlbHM7XG4gICAgY29uc3QgY3VyciA9IHBpeGVsc1tpbmRleF07XG4gICAgbGV0IHByZXYgPSBpbmRleCA+IDAgPyBwaXhlbHNbaW5kZXggLSAxXSA6IG51bGw7XG4gICAgbGV0IG5leHQgPSBpbmRleCA8IHBpeGVscy5sZW5ndGggLSAxID8gcGl4ZWxzW2luZGV4ICsgMV0gOiBudWxsO1xuICAgIGNvbnN0IHBlcmNlbnQgPSBvcHRpb25zLmNhdGVnb3J5UGVyY2VudGFnZTtcbiAgICBpZiAocHJldiA9PT0gbnVsbCkge1xuICAgICAgICBwcmV2ID0gY3VyciAtIChuZXh0ID09PSBudWxsID8gcnVsZXIuZW5kIC0gcnVsZXIuc3RhcnQgOiBuZXh0IC0gY3Vycik7XG4gICAgfVxuICAgIGlmIChuZXh0ID09PSBudWxsKSB7XG4gICAgICAgIG5leHQgPSBjdXJyICsgY3VyciAtIHByZXY7XG4gICAgfVxuICAgIGNvbnN0IHN0YXJ0ID0gY3VyciAtIChjdXJyIC0gTWF0aC5taW4ocHJldiwgbmV4dCkpIC8gMiAqIHBlcmNlbnQ7XG4gICAgY29uc3Qgc2l6ZSA9IE1hdGguYWJzKG5leHQgLSBwcmV2KSAvIDIgKiBwZXJjZW50O1xuICAgIHJldHVybiB7XG4gICAgICAgIGNodW5rOiBzaXplIC8gc3RhY2tDb3VudCxcbiAgICAgICAgcmF0aW86IG9wdGlvbnMuYmFyUGVyY2VudGFnZSxcbiAgICAgICAgc3RhcnRcbiAgICB9O1xufVxuZnVuY3Rpb24gcGFyc2VGbG9hdEJhcihlbnRyeSwgaXRlbSwgdlNjYWxlLCBpKSB7XG4gICAgY29uc3Qgc3RhcnRWYWx1ZSA9IHZTY2FsZS5wYXJzZShlbnRyeVswXSwgaSk7XG4gICAgY29uc3QgZW5kVmFsdWUgPSB2U2NhbGUucGFyc2UoZW50cnlbMV0sIGkpO1xuICAgIGNvbnN0IG1pbiA9IE1hdGgubWluKHN0YXJ0VmFsdWUsIGVuZFZhbHVlKTtcbiAgICBjb25zdCBtYXggPSBNYXRoLm1heChzdGFydFZhbHVlLCBlbmRWYWx1ZSk7XG4gICAgbGV0IGJhclN0YXJ0ID0gbWluO1xuICAgIGxldCBiYXJFbmQgPSBtYXg7XG4gICAgaWYgKE1hdGguYWJzKG1pbikgPiBNYXRoLmFicyhtYXgpKSB7XG4gICAgICAgIGJhclN0YXJ0ID0gbWF4O1xuICAgICAgICBiYXJFbmQgPSBtaW47XG4gICAgfVxuICAgIGl0ZW1bdlNjYWxlLmF4aXNdID0gYmFyRW5kO1xuICAgIGl0ZW0uX2N1c3RvbSA9IHtcbiAgICAgICAgYmFyU3RhcnQsXG4gICAgICAgIGJhckVuZCxcbiAgICAgICAgc3RhcnQ6IHN0YXJ0VmFsdWUsXG4gICAgICAgIGVuZDogZW5kVmFsdWUsXG4gICAgICAgIG1pbixcbiAgICAgICAgbWF4XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlVmFsdWUoZW50cnksIGl0ZW0sIHZTY2FsZSwgaSkge1xuICAgIGlmIChpc0FycmF5KGVudHJ5KSkge1xuICAgICAgICBwYXJzZUZsb2F0QmFyKGVudHJ5LCBpdGVtLCB2U2NhbGUsIGkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZW1bdlNjYWxlLmF4aXNdID0gdlNjYWxlLnBhcnNlKGVudHJ5LCBpKTtcbiAgICB9XG4gICAgcmV0dXJuIGl0ZW07XG59XG5mdW5jdGlvbiBwYXJzZUFycmF5T3JQcmltaXRpdmUobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgY29uc3QgaVNjYWxlID0gbWV0YS5pU2NhbGU7XG4gICAgY29uc3QgdlNjYWxlID0gbWV0YS52U2NhbGU7XG4gICAgY29uc3QgbGFiZWxzID0gaVNjYWxlLmdldExhYmVscygpO1xuICAgIGNvbnN0IHNpbmdsZVNjYWxlID0gaVNjYWxlID09PSB2U2NhbGU7XG4gICAgY29uc3QgcGFyc2VkID0gW107XG4gICAgbGV0IGksIGlsZW4sIGl0ZW0sIGVudHJ5O1xuICAgIGZvcihpID0gc3RhcnQsIGlsZW4gPSBzdGFydCArIGNvdW50OyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgZW50cnkgPSBkYXRhW2ldO1xuICAgICAgICBpdGVtID0ge307XG4gICAgICAgIGl0ZW1baVNjYWxlLmF4aXNdID0gc2luZ2xlU2NhbGUgfHwgaVNjYWxlLnBhcnNlKGxhYmVsc1tpXSwgaSk7XG4gICAgICAgIHBhcnNlZC5wdXNoKHBhcnNlVmFsdWUoZW50cnksIGl0ZW0sIHZTY2FsZSwgaSkpO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xufVxuZnVuY3Rpb24gaXNGbG9hdEJhcihjdXN0b20pIHtcbiAgICByZXR1cm4gY3VzdG9tICYmIGN1c3RvbS5iYXJTdGFydCAhPT0gdW5kZWZpbmVkICYmIGN1c3RvbS5iYXJFbmQgIT09IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGJhclNpZ24oc2l6ZSwgdlNjYWxlLCBhY3R1YWxCYXNlKSB7XG4gICAgaWYgKHNpemUgIT09IDApIHtcbiAgICAgICAgcmV0dXJuIHNpZ24oc2l6ZSk7XG4gICAgfVxuICAgIHJldHVybiAodlNjYWxlLmlzSG9yaXpvbnRhbCgpID8gMSA6IC0xKSAqICh2U2NhbGUubWluID49IGFjdHVhbEJhc2UgPyAxIDogLTEpO1xufVxuZnVuY3Rpb24gYm9yZGVyUHJvcHMocHJvcGVydGllcykge1xuICAgIGxldCByZXZlcnNlLCBzdGFydCwgZW5kLCB0b3AsIGJvdHRvbTtcbiAgICBpZiAocHJvcGVydGllcy5ob3Jpem9udGFsKSB7XG4gICAgICAgIHJldmVyc2UgPSBwcm9wZXJ0aWVzLmJhc2UgPiBwcm9wZXJ0aWVzLng7XG4gICAgICAgIHN0YXJ0ID0gJ2xlZnQnO1xuICAgICAgICBlbmQgPSAncmlnaHQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldmVyc2UgPSBwcm9wZXJ0aWVzLmJhc2UgPCBwcm9wZXJ0aWVzLnk7XG4gICAgICAgIHN0YXJ0ID0gJ2JvdHRvbSc7XG4gICAgICAgIGVuZCA9ICd0b3AnO1xuICAgIH1cbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICB0b3AgPSAnZW5kJztcbiAgICAgICAgYm90dG9tID0gJ3N0YXJ0JztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0b3AgPSAnc3RhcnQnO1xuICAgICAgICBib3R0b20gPSAnZW5kJztcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQsXG4gICAgICAgIGVuZCxcbiAgICAgICAgcmV2ZXJzZSxcbiAgICAgICAgdG9wLFxuICAgICAgICBib3R0b21cbiAgICB9O1xufVxuZnVuY3Rpb24gc2V0Qm9yZGVyU2tpcHBlZChwcm9wZXJ0aWVzLCBvcHRpb25zLCBzdGFjaywgaW5kZXgpIHtcbiAgICBsZXQgZWRnZSA9IG9wdGlvbnMuYm9yZGVyU2tpcHBlZDtcbiAgICBjb25zdCByZXMgPSB7fTtcbiAgICBpZiAoIWVkZ2UpIHtcbiAgICAgICAgcHJvcGVydGllcy5ib3JkZXJTa2lwcGVkID0gcmVzO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChlZGdlID09PSB0cnVlKSB7XG4gICAgICAgIHByb3BlcnRpZXMuYm9yZGVyU2tpcHBlZCA9IHtcbiAgICAgICAgICAgIHRvcDogdHJ1ZSxcbiAgICAgICAgICAgIHJpZ2h0OiB0cnVlLFxuICAgICAgICAgICAgYm90dG9tOiB0cnVlLFxuICAgICAgICAgICAgbGVmdDogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgc3RhcnQgLCBlbmQgLCByZXZlcnNlICwgdG9wICwgYm90dG9tICB9ID0gYm9yZGVyUHJvcHMocHJvcGVydGllcyk7XG4gICAgaWYgKGVkZ2UgPT09ICdtaWRkbGUnICYmIHN0YWNrKSB7XG4gICAgICAgIHByb3BlcnRpZXMuZW5hYmxlQm9yZGVyUmFkaXVzID0gdHJ1ZTtcbiAgICAgICAgaWYgKChzdGFjay5fdG9wIHx8IDApID09PSBpbmRleCkge1xuICAgICAgICAgICAgZWRnZSA9IHRvcDtcbiAgICAgICAgfSBlbHNlIGlmICgoc3RhY2suX2JvdHRvbSB8fCAwKSA9PT0gaW5kZXgpIHtcbiAgICAgICAgICAgIGVkZ2UgPSBib3R0b207XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNbcGFyc2VFZGdlKGJvdHRvbSwgc3RhcnQsIGVuZCwgcmV2ZXJzZSldID0gdHJ1ZTtcbiAgICAgICAgICAgIGVkZ2UgPSB0b3A7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVzW3BhcnNlRWRnZShlZGdlLCBzdGFydCwgZW5kLCByZXZlcnNlKV0gPSB0cnVlO1xuICAgIHByb3BlcnRpZXMuYm9yZGVyU2tpcHBlZCA9IHJlcztcbn1cbmZ1bmN0aW9uIHBhcnNlRWRnZShlZGdlLCBhLCBiLCByZXZlcnNlKSB7XG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgZWRnZSA9IHN3YXAoZWRnZSwgYSwgYik7XG4gICAgICAgIGVkZ2UgPSBzdGFydEVuZChlZGdlLCBiLCBhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBlZGdlID0gc3RhcnRFbmQoZWRnZSwgYSwgYik7XG4gICAgfVxuICAgIHJldHVybiBlZGdlO1xufVxuZnVuY3Rpb24gc3dhcChvcmlnLCB2MSwgdjIpIHtcbiAgICByZXR1cm4gb3JpZyA9PT0gdjEgPyB2MiA6IG9yaWcgPT09IHYyID8gdjEgOiBvcmlnO1xufVxuZnVuY3Rpb24gc3RhcnRFbmQodiwgc3RhcnQsIGVuZCkge1xuICAgIHJldHVybiB2ID09PSAnc3RhcnQnID8gc3RhcnQgOiB2ID09PSAnZW5kJyA/IGVuZCA6IHY7XG59XG5mdW5jdGlvbiBzZXRJbmZsYXRlQW1vdW50KHByb3BlcnRpZXMsIHsgaW5mbGF0ZUFtb3VudCAgfSwgcmF0aW8pIHtcbiAgICBwcm9wZXJ0aWVzLmluZmxhdGVBbW91bnQgPSBpbmZsYXRlQW1vdW50ID09PSAnYXV0bycgPyByYXRpbyA9PT0gMSA/IDAuMzMgOiAwIDogaW5mbGF0ZUFtb3VudDtcbn1cbmNsYXNzIEJhckNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gICAgc3RhdGljIGlkID0gJ2Jhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhc2V0RWxlbWVudFR5cGU6IGZhbHNlLFxuICAgICAgICBkYXRhRWxlbWVudFR5cGU6ICdiYXInLFxuICAgICAgICBjYXRlZ29yeVBlcmNlbnRhZ2U6IDAuOCxcbiAgICAgICAgYmFyUGVyY2VudGFnZTogMC45LFxuICAgICAgICBncm91cGVkOiB0cnVlLFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgcHJvcGVydGllczogW1xuICAgICAgICAgICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICAgICAgICAgJ2Jhc2UnLFxuICAgICAgICAgICAgICAgICAgICAnd2lkdGgnLFxuICAgICAgICAgICAgICAgICAgICAnaGVpZ2h0J1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gc3RhdGljIG92ZXJyaWRlcyA9IHtcbiAgICAgICAgc2NhbGVzOiB7XG4gICAgICAgICAgICBfaW5kZXhfOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2NhdGVnb3J5JyxcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IHRydWUsXG4gICAgICAgICAgICAgICAgZ3JpZDoge1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IHRydWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX3ZhbHVlXzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICAgICAgICAgIGJlZ2luQXRaZXJvOiB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuIHBhcnNlUHJpbWl0aXZlRGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQXJyYXlPclByaW1pdGl2ZShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgIH1cbiBwYXJzZUFycmF5RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQXJyYXlPclByaW1pdGl2ZShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgIH1cbiBwYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHsgaVNjYWxlICwgdlNjYWxlICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgeyB4QXhpc0tleSA9J3gnICwgeUF4aXNLZXkgPSd5JyAgfSA9IHRoaXMuX3BhcnNpbmc7XG4gICAgICAgIGNvbnN0IGlBeGlzS2V5ID0gaVNjYWxlLmF4aXMgPT09ICd4JyA/IHhBeGlzS2V5IDogeUF4aXNLZXk7XG4gICAgICAgIGNvbnN0IHZBeGlzS2V5ID0gdlNjYWxlLmF4aXMgPT09ICd4JyA/IHhBeGlzS2V5IDogeUF4aXNLZXk7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbiwgaXRlbSwgb2JqO1xuICAgICAgICBmb3IoaSA9IHN0YXJ0LCBpbGVuID0gc3RhcnQgKyBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBvYmogPSBkYXRhW2ldO1xuICAgICAgICAgICAgaXRlbSA9IHt9O1xuICAgICAgICAgICAgaXRlbVtpU2NhbGUuYXhpc10gPSBpU2NhbGUucGFyc2UocmVzb2x2ZU9iamVjdEtleShvYmosIGlBeGlzS2V5KSwgaSk7XG4gICAgICAgICAgICBwYXJzZWQucHVzaChwYXJzZVZhbHVlKHJlc29sdmVPYmplY3RLZXkob2JqLCB2QXhpc0tleSksIGl0ZW0sIHZTY2FsZSwgaSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIHVwZGF0ZVJhbmdlRnJvbVBhcnNlZChyYW5nZSwgc2NhbGUsIHBhcnNlZCwgc3RhY2spIHtcbiAgICAgICAgc3VwZXIudXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHJhbmdlLCBzY2FsZSwgcGFyc2VkLCBzdGFjayk7XG4gICAgICAgIGNvbnN0IGN1c3RvbSA9IHBhcnNlZC5fY3VzdG9tO1xuICAgICAgICBpZiAoY3VzdG9tICYmIHNjYWxlID09PSB0aGlzLl9jYWNoZWRNZXRhLnZTY2FsZSkge1xuICAgICAgICAgICAgcmFuZ2UubWluID0gTWF0aC5taW4ocmFuZ2UubWluLCBjdXN0b20ubWluKTtcbiAgICAgICAgICAgIHJhbmdlLm1heCA9IE1hdGgubWF4KHJhbmdlLm1heCwgY3VzdG9tLm1heCk7XG4gICAgICAgIH1cbiAgICB9XG4gZ2V0TWF4T3ZlcmZsb3coKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiBnZXRMYWJlbEFuZFZhbHVlKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCB7IGlTY2FsZSAsIHZTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgY29uc3QgY3VzdG9tID0gcGFyc2VkLl9jdXN0b207XG4gICAgICAgIGNvbnN0IHZhbHVlID0gaXNGbG9hdEJhcihjdXN0b20pID8gJ1snICsgY3VzdG9tLnN0YXJ0ICsgJywgJyArIGN1c3RvbS5lbmQgKyAnXScgOiAnJyArIHZTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZFt2U2NhbGUuYXhpc10pO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6ICcnICsgaVNjYWxlLmdldExhYmVsRm9yVmFsdWUocGFyc2VkW2lTY2FsZS5heGlzXSksXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICB9O1xuICAgIH1cbiAgICBpbml0aWFsaXplKCkge1xuICAgICAgICB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgPSB0cnVlO1xuICAgICAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBtZXRhLnN0YWNrID0gdGhpcy5nZXREYXRhc2V0KCkuc3RhY2s7XG4gICAgfVxuICAgIHVwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKG1ldGEuZGF0YSwgMCwgbWV0YS5kYXRhLmxlbmd0aCwgbW9kZSk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKGJhcnMsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgICAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgICAgIGNvbnN0IHsgaW5kZXggLCBfY2FjaGVkTWV0YTogeyB2U2NhbGUgIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBiYXNlID0gdlNjYWxlLmdldEJhc2VQaXhlbCgpO1xuICAgICAgICBjb25zdCBob3Jpem9udGFsID0gdlNjYWxlLmlzSG9yaXpvbnRhbCgpO1xuICAgICAgICBjb25zdCBydWxlciA9IHRoaXMuX2dldFJ1bGVyKCk7XG4gICAgICAgIGNvbnN0IHsgc2hhcmVkT3B0aW9ucyAsIGluY2x1ZGVPcHRpb25zICB9ID0gdGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgICAgIGZvcihsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGkpO1xuICAgICAgICAgICAgY29uc3QgdnBpeGVscyA9IHJlc2V0IHx8IGlzTnVsbE9yVW5kZWYocGFyc2VkW3ZTY2FsZS5heGlzXSkgPyB7XG4gICAgICAgICAgICAgICAgYmFzZSxcbiAgICAgICAgICAgICAgICBoZWFkOiBiYXNlXG4gICAgICAgICAgICB9IDogdGhpcy5fY2FsY3VsYXRlQmFyVmFsdWVQaXhlbHMoaSk7XG4gICAgICAgICAgICBjb25zdCBpcGl4ZWxzID0gdGhpcy5fY2FsY3VsYXRlQmFySW5kZXhQaXhlbHMoaSwgcnVsZXIpO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2sgPSAocGFyc2VkLl9zdGFja3MgfHwge30pW3ZTY2FsZS5heGlzXTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaG9yaXpvbnRhbCxcbiAgICAgICAgICAgICAgICBiYXNlOiB2cGl4ZWxzLmJhc2UsXG4gICAgICAgICAgICAgICAgZW5hYmxlQm9yZGVyUmFkaXVzOiAhc3RhY2sgfHwgaXNGbG9hdEJhcihwYXJzZWQuX2N1c3RvbSkgfHwgaW5kZXggPT09IHN0YWNrLl90b3AgfHwgaW5kZXggPT09IHN0YWNrLl9ib3R0b20sXG4gICAgICAgICAgICAgICAgeDogaG9yaXpvbnRhbCA/IHZwaXhlbHMuaGVhZCA6IGlwaXhlbHMuY2VudGVyLFxuICAgICAgICAgICAgICAgIHk6IGhvcml6b250YWwgPyBpcGl4ZWxzLmNlbnRlciA6IHZwaXhlbHMuaGVhZCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGhvcml6b250YWwgPyBpcGl4ZWxzLnNpemUgOiBNYXRoLmFicyh2cGl4ZWxzLnNpemUpLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBob3Jpem9udGFsID8gTWF0aC5hYnModnBpeGVscy5zaXplKSA6IGlwaXhlbHMuc2l6ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChpbmNsdWRlT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMub3B0aW9ucyA9IHNoYXJlZE9wdGlvbnMgfHwgdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGksIGJhcnNbaV0uYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSBwcm9wZXJ0aWVzLm9wdGlvbnMgfHwgYmFyc1tpXS5vcHRpb25zO1xuICAgICAgICAgICAgc2V0Qm9yZGVyU2tpcHBlZChwcm9wZXJ0aWVzLCBvcHRpb25zLCBzdGFjaywgaW5kZXgpO1xuICAgICAgICAgICAgc2V0SW5mbGF0ZUFtb3VudChwcm9wZXJ0aWVzLCBvcHRpb25zLCBydWxlci5yYXRpbyk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQoYmFyc1tpXSwgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gX2dldFN0YWNrcyhsYXN0LCBkYXRhSW5kZXgpIHtcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgIH0gPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBtZXRhc2V0cyA9IGlTY2FsZS5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcyh0aGlzLl90eXBlKS5maWx0ZXIoKG1ldGEpPT5tZXRhLmNvbnRyb2xsZXIub3B0aW9ucy5ncm91cGVkKTtcbiAgICAgICAgY29uc3Qgc3RhY2tlZCA9IGlTY2FsZS5vcHRpb25zLnN0YWNrZWQ7XG4gICAgICAgIGNvbnN0IHN0YWNrcyA9IFtdO1xuICAgICAgICBjb25zdCBza2lwTnVsbCA9IChtZXRhKT0+e1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gbWV0YS5jb250cm9sbGVyLmdldFBhcnNlZChkYXRhSW5kZXgpO1xuICAgICAgICAgICAgY29uc3QgdmFsID0gcGFyc2VkICYmIHBhcnNlZFttZXRhLnZTY2FsZS5heGlzXTtcbiAgICAgICAgICAgIGlmIChpc051bGxPclVuZGVmKHZhbCkgfHwgaXNOYU4odmFsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IG1ldGEgb2YgbWV0YXNldHMpe1xuICAgICAgICAgICAgaWYgKGRhdGFJbmRleCAhPT0gdW5kZWZpbmVkICYmIHNraXBOdWxsKG1ldGEpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhY2tlZCA9PT0gZmFsc2UgfHwgc3RhY2tzLmluZGV4T2YobWV0YS5zdGFjaykgPT09IC0xIHx8IHN0YWNrZWQgPT09IHVuZGVmaW5lZCAmJiBtZXRhLnN0YWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzdGFja3MucHVzaChtZXRhLnN0YWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXRhLmluZGV4ID09PSBsYXN0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzdGFja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBzdGFja3MucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdGFja3M7XG4gICAgfVxuIF9nZXRTdGFja0NvdW50KGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRTdGFja3ModW5kZWZpbmVkLCBpbmRleCkubGVuZ3RoO1xuICAgIH1cbiBfZ2V0U3RhY2tJbmRleChkYXRhc2V0SW5kZXgsIG5hbWUsIGRhdGFJbmRleCkge1xuICAgICAgICBjb25zdCBzdGFja3MgPSB0aGlzLl9nZXRTdGFja3MoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgpO1xuICAgICAgICBjb25zdCBpbmRleCA9IG5hbWUgIT09IHVuZGVmaW5lZCA/IHN0YWNrcy5pbmRleE9mKG5hbWUpIDogLTE7XG4gICAgICAgIHJldHVybiBpbmRleCA9PT0gLTEgPyBzdGFja3MubGVuZ3RoIC0gMSA6IGluZGV4O1xuICAgIH1cbiBfZ2V0UnVsZXIoKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBpU2NhbGUgPSBtZXRhLmlTY2FsZTtcbiAgICAgICAgY29uc3QgcGl4ZWxzID0gW107XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBtZXRhLmRhdGEubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHBpeGVscy5wdXNoKGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHRoaXMuZ2V0UGFyc2VkKGkpW2lTY2FsZS5heGlzXSwgaSkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJhclRoaWNrbmVzcyA9IG9wdHMuYmFyVGhpY2tuZXNzO1xuICAgICAgICBjb25zdCBtaW4gPSBiYXJUaGlja25lc3MgfHwgY29tcHV0ZU1pblNhbXBsZVNpemUobWV0YSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBtaW4sXG4gICAgICAgICAgICBwaXhlbHMsXG4gICAgICAgICAgICBzdGFydDogaVNjYWxlLl9zdGFydFBpeGVsLFxuICAgICAgICAgICAgZW5kOiBpU2NhbGUuX2VuZFBpeGVsLFxuICAgICAgICAgICAgc3RhY2tDb3VudDogdGhpcy5fZ2V0U3RhY2tDb3VudCgpLFxuICAgICAgICAgICAgc2NhbGU6IGlTY2FsZSxcbiAgICAgICAgICAgIGdyb3VwZWQ6IG9wdHMuZ3JvdXBlZCxcbiAgICAgICAgICAgIHJhdGlvOiBiYXJUaGlja25lc3MgPyAxIDogb3B0cy5jYXRlZ29yeVBlcmNlbnRhZ2UgKiBvcHRzLmJhclBlcmNlbnRhZ2VcbiAgICAgICAgfTtcbiAgICB9XG4gX2NhbGN1bGF0ZUJhclZhbHVlUGl4ZWxzKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHsgX2NhY2hlZE1ldGE6IHsgdlNjYWxlICwgX3N0YWNrZWQgLCBpbmRleDogZGF0YXNldEluZGV4ICB9ICwgb3B0aW9uczogeyBiYXNlOiBiYXNlVmFsdWUgLCBtaW5CYXJMZW5ndGggIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBhY3R1YWxCYXNlID0gYmFzZVZhbHVlIHx8IDA7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgY29uc3QgY3VzdG9tID0gcGFyc2VkLl9jdXN0b207XG4gICAgICAgIGNvbnN0IGZsb2F0aW5nID0gaXNGbG9hdEJhcihjdXN0b20pO1xuICAgICAgICBsZXQgdmFsdWUgPSBwYXJzZWRbdlNjYWxlLmF4aXNdO1xuICAgICAgICBsZXQgc3RhcnQgPSAwO1xuICAgICAgICBsZXQgbGVuZ3RoID0gX3N0YWNrZWQgPyB0aGlzLmFwcGx5U3RhY2sodlNjYWxlLCBwYXJzZWQsIF9zdGFja2VkKSA6IHZhbHVlO1xuICAgICAgICBsZXQgaGVhZCwgc2l6ZTtcbiAgICAgICAgaWYgKGxlbmd0aCAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gbGVuZ3RoIC0gdmFsdWU7XG4gICAgICAgICAgICBsZW5ndGggPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmxvYXRpbmcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gY3VzdG9tLmJhclN0YXJ0O1xuICAgICAgICAgICAgbGVuZ3RoID0gY3VzdG9tLmJhckVuZCAtIGN1c3RvbS5iYXJTdGFydDtcbiAgICAgICAgICAgIGlmICh2YWx1ZSAhPT0gMCAmJiBzaWduKHZhbHVlKSAhPT0gc2lnbihjdXN0b20uYmFyRW5kKSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YXJ0ICs9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YXJ0VmFsdWUgPSAhaXNOdWxsT3JVbmRlZihiYXNlVmFsdWUpICYmICFmbG9hdGluZyA/IGJhc2VWYWx1ZSA6IHN0YXJ0O1xuICAgICAgICBsZXQgYmFzZSA9IHZTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHN0YXJ0VmFsdWUpO1xuICAgICAgICBpZiAodGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eShpbmRleCkpIHtcbiAgICAgICAgICAgIGhlYWQgPSB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShzdGFydCArIGxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoZWFkID0gYmFzZTtcbiAgICAgICAgfVxuICAgICAgICBzaXplID0gaGVhZCAtIGJhc2U7XG4gICAgICAgIGlmIChNYXRoLmFicyhzaXplKSA8IG1pbkJhckxlbmd0aCkge1xuICAgICAgICAgICAgc2l6ZSA9IGJhclNpZ24oc2l6ZSwgdlNjYWxlLCBhY3R1YWxCYXNlKSAqIG1pbkJhckxlbmd0aDtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gYWN0dWFsQmFzZSkge1xuICAgICAgICAgICAgICAgIGJhc2UgLT0gc2l6ZSAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzdGFydFBpeGVsID0gdlNjYWxlLmdldFBpeGVsRm9yRGVjaW1hbCgwKTtcbiAgICAgICAgICAgIGNvbnN0IGVuZFBpeGVsID0gdlNjYWxlLmdldFBpeGVsRm9yRGVjaW1hbCgxKTtcbiAgICAgICAgICAgIGNvbnN0IG1pbiA9IE1hdGgubWluKHN0YXJ0UGl4ZWwsIGVuZFBpeGVsKTtcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IE1hdGgubWF4KHN0YXJ0UGl4ZWwsIGVuZFBpeGVsKTtcbiAgICAgICAgICAgIGJhc2UgPSBNYXRoLm1heChNYXRoLm1pbihiYXNlLCBtYXgpLCBtaW4pO1xuICAgICAgICAgICAgaGVhZCA9IGJhc2UgKyBzaXplO1xuICAgICAgICAgICAgaWYgKF9zdGFja2VkICYmICFmbG9hdGluZykge1xuICAgICAgICAgICAgICAgIHBhcnNlZC5fc3RhY2tzW3ZTY2FsZS5heGlzXS5fdmlzdWFsVmFsdWVzW2RhdGFzZXRJbmRleF0gPSB2U2NhbGUuZ2V0VmFsdWVGb3JQaXhlbChoZWFkKSAtIHZTY2FsZS5nZXRWYWx1ZUZvclBpeGVsKGJhc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChiYXNlID09PSB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShhY3R1YWxCYXNlKSkge1xuICAgICAgICAgICAgY29uc3QgaGFsZkdyaWQgPSBzaWduKHNpemUpICogdlNjYWxlLmdldExpbmVXaWR0aEZvclZhbHVlKGFjdHVhbEJhc2UpIC8gMjtcbiAgICAgICAgICAgIGJhc2UgKz0gaGFsZkdyaWQ7XG4gICAgICAgICAgICBzaXplIC09IGhhbGZHcmlkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzaXplLFxuICAgICAgICAgICAgYmFzZSxcbiAgICAgICAgICAgIGhlYWQsXG4gICAgICAgICAgICBjZW50ZXI6IGhlYWQgKyBzaXplIC8gMlxuICAgICAgICB9O1xuICAgIH1cbiBfY2FsY3VsYXRlQmFySW5kZXhQaXhlbHMoaW5kZXgsIHJ1bGVyKSB7XG4gICAgICAgIGNvbnN0IHNjYWxlID0gcnVsZXIuc2NhbGU7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHNraXBOdWxsID0gb3B0aW9ucy5za2lwTnVsbDtcbiAgICAgICAgY29uc3QgbWF4QmFyVGhpY2tuZXNzID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy5tYXhCYXJUaGlja25lc3MsIEluZmluaXR5KTtcbiAgICAgICAgbGV0IGNlbnRlciwgc2l6ZTtcbiAgICAgICAgaWYgKHJ1bGVyLmdyb3VwZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YWNrQ291bnQgPSBza2lwTnVsbCA/IHRoaXMuX2dldFN0YWNrQ291bnQoaW5kZXgpIDogcnVsZXIuc3RhY2tDb3VudDtcbiAgICAgICAgICAgIGNvbnN0IHJhbmdlID0gb3B0aW9ucy5iYXJUaGlja25lc3MgPT09ICdmbGV4JyA/IGNvbXB1dGVGbGV4Q2F0ZWdvcnlUcmFpdHMoaW5kZXgsIHJ1bGVyLCBvcHRpb25zLCBzdGFja0NvdW50KSA6IGNvbXB1dGVGaXRDYXRlZ29yeVRyYWl0cyhpbmRleCwgcnVsZXIsIG9wdGlvbnMsIHN0YWNrQ291bnQpO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2tJbmRleCA9IHRoaXMuX2dldFN0YWNrSW5kZXgodGhpcy5pbmRleCwgdGhpcy5fY2FjaGVkTWV0YS5zdGFjaywgc2tpcE51bGwgPyBpbmRleCA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICBjZW50ZXIgPSByYW5nZS5zdGFydCArIHJhbmdlLmNodW5rICogc3RhY2tJbmRleCArIHJhbmdlLmNodW5rIC8gMjtcbiAgICAgICAgICAgIHNpemUgPSBNYXRoLm1pbihtYXhCYXJUaGlja25lc3MsIHJhbmdlLmNodW5rICogcmFuZ2UucmF0aW8pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2VudGVyID0gc2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZSh0aGlzLmdldFBhcnNlZChpbmRleClbc2NhbGUuYXhpc10sIGluZGV4KTtcbiAgICAgICAgICAgIHNpemUgPSBNYXRoLm1pbihtYXhCYXJUaGlja25lc3MsIHJ1bGVyLm1pbiAqIHJ1bGVyLnJhdGlvKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYmFzZTogY2VudGVyIC0gc2l6ZSAvIDIsXG4gICAgICAgICAgICBoZWFkOiBjZW50ZXIgKyBzaXplIC8gMixcbiAgICAgICAgICAgIGNlbnRlcixcbiAgICAgICAgICAgIHNpemVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZHJhdygpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IHZTY2FsZSA9IG1ldGEudlNjYWxlO1xuICAgICAgICBjb25zdCByZWN0cyA9IG1ldGEuZGF0YTtcbiAgICAgICAgY29uc3QgaWxlbiA9IHJlY3RzLmxlbmd0aDtcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBmb3IoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldFBhcnNlZChpKVt2U2NhbGUuYXhpc10gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZWN0c1tpXS5kcmF3KHRoaXMuX2N0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmNsYXNzIEJ1YmJsZUNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gICAgc3RhdGljIGlkID0gJ2J1YmJsZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhc2V0RWxlbWVudFR5cGU6IGZhbHNlLFxuICAgICAgICBkYXRhRWxlbWVudFR5cGU6ICdwb2ludCcsXG4gICAgICAgIGFuaW1hdGlvbnM6IHtcbiAgICAgICAgICAgIG51bWJlcnM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBbXG4gICAgICAgICAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICAgICAgICAgJ3knLFxuICAgICAgICAgICAgICAgICAgICAnYm9yZGVyV2lkdGgnLFxuICAgICAgICAgICAgICAgICAgICAncmFkaXVzJ1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gc3RhdGljIG92ZXJyaWRlcyA9IHtcbiAgICAgICAgc2NhbGVzOiB7XG4gICAgICAgICAgICB4OiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB5OiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgaW5pdGlhbGl6ZSgpIHtcbiAgICAgICAgdGhpcy5lbmFibGVPcHRpb25TaGFyaW5nID0gdHJ1ZTtcbiAgICAgICAgc3VwZXIuaW5pdGlhbGl6ZSgpO1xuICAgIH1cbiBwYXJzZVByaW1pdGl2ZURhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHN1cGVyLnBhcnNlUHJpbWl0aXZlRGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcGFyc2VkLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIHBhcnNlZFtpXS5fY3VzdG9tID0gdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkgKyBzdGFydCkucmFkaXVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIHBhcnNlQXJyYXlEYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBzdXBlci5wYXJzZUFycmF5RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcGFyc2VkLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBkYXRhW3N0YXJ0ICsgaV07XG4gICAgICAgICAgICBwYXJzZWRbaV0uX2N1c3RvbSA9IHZhbHVlT3JEZWZhdWx0KGl0ZW1bMl0sIHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpICsgc3RhcnQpLnJhZGl1cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcnNlZDtcbiAgICB9XG4gcGFyc2VPYmplY3REYXRhKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBzdXBlci5wYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHBhcnNlZC5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBjb25zdCBpdGVtID0gZGF0YVtzdGFydCArIGldO1xuICAgICAgICAgICAgcGFyc2VkW2ldLl9jdXN0b20gPSB2YWx1ZU9yRGVmYXVsdChpdGVtICYmIGl0ZW0uciAmJiAraXRlbS5yLCB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSArIHN0YXJ0KS5yYWRpdXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJzZWQ7XG4gICAgfVxuIGdldE1heE92ZXJmbG93KCkge1xuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5fY2FjaGVkTWV0YS5kYXRhO1xuICAgICAgICBsZXQgbWF4ID0gMDtcbiAgICAgICAgZm9yKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIGRhdGFbaV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSkpIC8gMik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1heCA+IDAgJiYgbWF4O1xuICAgIH1cbiBnZXRMYWJlbEFuZFZhbHVlKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmNoYXJ0LmRhdGEubGFiZWxzIHx8IFtdO1xuICAgICAgICBjb25zdCB7IHhTY2FsZSAsIHlTY2FsZSAgfSA9IG1ldGE7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgY29uc3QgeCA9IHhTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZC54KTtcbiAgICAgICAgY29uc3QgeSA9IHlTY2FsZS5nZXRMYWJlbEZvclZhbHVlKHBhcnNlZC55KTtcbiAgICAgICAgY29uc3QgciA9IHBhcnNlZC5fY3VzdG9tO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IGxhYmVsc1tpbmRleF0gfHwgJycsXG4gICAgICAgICAgICB2YWx1ZTogJygnICsgeCArICcsICcgKyB5ICsgKHIgPyAnLCAnICsgciA6ICcnKSArICcpJ1xuICAgICAgICB9O1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBwb2ludHMgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGE7XG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudHMocG9pbnRzLCAwLCBwb2ludHMubGVuZ3RoLCBtb2RlKTtcbiAgICB9XG4gICAgdXBkYXRlRWxlbWVudHMocG9pbnRzLCBzdGFydCwgY291bnQsIG1vZGUpIHtcbiAgICAgICAgY29uc3QgcmVzZXQgPSBtb2RlID09PSAncmVzZXQnO1xuICAgICAgICBjb25zdCB7IGlTY2FsZSAsIHZTY2FsZSAgfSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IHsgc2hhcmVkT3B0aW9ucyAsIGluY2x1ZGVPcHRpb25zICB9ID0gdGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gICAgICAgIGZvcihsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gIXJlc2V0ICYmIHRoaXMuZ2V0UGFyc2VkKGkpO1xuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSByZXNldCA/IGlTY2FsZS5nZXRQaXhlbEZvckRlY2ltYWwoMC41KSA6IGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHBhcnNlZFtpQXhpc10pO1xuICAgICAgICAgICAgY29uc3QgdlBpeGVsID0gcHJvcGVydGllc1t2QXhpc10gPSByZXNldCA/IHZTY2FsZS5nZXRCYXNlUGl4ZWwoKSA6IHZTY2FsZS5nZXRQaXhlbEZvclZhbHVlKHBhcnNlZFt2QXhpc10pO1xuICAgICAgICAgICAgcHJvcGVydGllcy5za2lwID0gaXNOYU4oaVBpeGVsKSB8fCBpc05hTih2UGl4ZWwpO1xuICAgICAgICAgICAgaWYgKGluY2x1ZGVPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5vcHRpb25zID0gc2hhcmVkT3B0aW9ucyB8fCB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgcG9pbnQuYWN0aXZlID8gJ2FjdGl2ZScgOiBtb2RlKTtcbiAgICAgICAgICAgICAgICBpZiAocmVzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllcy5vcHRpb25zLnJhZGl1cyA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KHBvaW50LCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICAgICAgfVxuICAgIH1cbiByZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGluZGV4LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KTtcbiAgICAgICAgbGV0IHZhbHVlcyA9IHN1cGVyLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaW5kZXgsIG1vZGUpO1xuICAgICAgICBpZiAodmFsdWVzLiRzaGFyZWQpIHtcbiAgICAgICAgICAgIHZhbHVlcyA9IE9iamVjdC5hc3NpZ24oe30sIHZhbHVlcywge1xuICAgICAgICAgICAgICAgICRzaGFyZWQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByYWRpdXMgPSB2YWx1ZXMucmFkaXVzO1xuICAgICAgICBpZiAobW9kZSAhPT0gJ2FjdGl2ZScpIHtcbiAgICAgICAgICAgIHZhbHVlcy5yYWRpdXMgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlcy5yYWRpdXMgKz0gdmFsdWVPckRlZmF1bHQocGFyc2VkICYmIHBhcnNlZC5fY3VzdG9tLCByYWRpdXMpO1xuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0UmF0aW9BbmRPZmZzZXQocm90YXRpb24sIGNpcmN1bWZlcmVuY2UsIGN1dG91dCkge1xuICAgIGxldCByYXRpb1ggPSAxO1xuICAgIGxldCByYXRpb1kgPSAxO1xuICAgIGxldCBvZmZzZXRYID0gMDtcbiAgICBsZXQgb2Zmc2V0WSA9IDA7XG4gICAgaWYgKGNpcmN1bWZlcmVuY2UgPCBUQVUpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRBbmdsZSA9IHJvdGF0aW9uO1xuICAgICAgICBjb25zdCBlbmRBbmdsZSA9IHN0YXJ0QW5nbGUgKyBjaXJjdW1mZXJlbmNlO1xuICAgICAgICBjb25zdCBzdGFydFggPSBNYXRoLmNvcyhzdGFydEFuZ2xlKTtcbiAgICAgICAgY29uc3Qgc3RhcnRZID0gTWF0aC5zaW4oc3RhcnRBbmdsZSk7XG4gICAgICAgIGNvbnN0IGVuZFggPSBNYXRoLmNvcyhlbmRBbmdsZSk7XG4gICAgICAgIGNvbnN0IGVuZFkgPSBNYXRoLnNpbihlbmRBbmdsZSk7XG4gICAgICAgIGNvbnN0IGNhbGNNYXggPSAoYW5nbGUsIGEsIGIpPT5fYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSwgdHJ1ZSkgPyAxIDogTWF0aC5tYXgoYSwgYSAqIGN1dG91dCwgYiwgYiAqIGN1dG91dCk7XG4gICAgICAgIGNvbnN0IGNhbGNNaW4gPSAoYW5nbGUsIGEsIGIpPT5fYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSwgdHJ1ZSkgPyAtMSA6IE1hdGgubWluKGEsIGEgKiBjdXRvdXQsIGIsIGIgKiBjdXRvdXQpO1xuICAgICAgICBjb25zdCBtYXhYID0gY2FsY01heCgwLCBzdGFydFgsIGVuZFgpO1xuICAgICAgICBjb25zdCBtYXhZID0gY2FsY01heChIQUxGX1BJLCBzdGFydFksIGVuZFkpO1xuICAgICAgICBjb25zdCBtaW5YID0gY2FsY01pbihQSSwgc3RhcnRYLCBlbmRYKTtcbiAgICAgICAgY29uc3QgbWluWSA9IGNhbGNNaW4oUEkgKyBIQUxGX1BJLCBzdGFydFksIGVuZFkpO1xuICAgICAgICByYXRpb1ggPSAobWF4WCAtIG1pblgpIC8gMjtcbiAgICAgICAgcmF0aW9ZID0gKG1heFkgLSBtaW5ZKSAvIDI7XG4gICAgICAgIG9mZnNldFggPSAtKG1heFggKyBtaW5YKSAvIDI7XG4gICAgICAgIG9mZnNldFkgPSAtKG1heFkgKyBtaW5ZKSAvIDI7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHJhdGlvWCxcbiAgICAgICAgcmF0aW9ZLFxuICAgICAgICBvZmZzZXRYLFxuICAgICAgICBvZmZzZXRZXG4gICAgfTtcbn1cbmNsYXNzIERvdWdobnV0Q29udHJvbGxlciBleHRlbmRzIERhdGFzZXRDb250cm9sbGVyIHtcbiAgICBzdGF0aWMgaWQgPSAnZG91Z2hudXQnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiBmYWxzZSxcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAnYXJjJyxcbiAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICBhbmltYXRlUm90YXRlOiB0cnVlLFxuICAgICAgICAgICAgYW5pbWF0ZVNjYWxlOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgcHJvcGVydGllczogW1xuICAgICAgICAgICAgICAgICAgICAnY2lyY3VtZmVyZW5jZScsXG4gICAgICAgICAgICAgICAgICAgICdlbmRBbmdsZScsXG4gICAgICAgICAgICAgICAgICAgICdpbm5lclJhZGl1cycsXG4gICAgICAgICAgICAgICAgICAgICdvdXRlclJhZGl1cycsXG4gICAgICAgICAgICAgICAgICAgICdzdGFydEFuZ2xlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgICAgICAgICAneScsXG4gICAgICAgICAgICAgICAgICAgICdvZmZzZXQnLFxuICAgICAgICAgICAgICAgICAgICAnYm9yZGVyV2lkdGgnLFxuICAgICAgICAgICAgICAgICAgICAnc3BhY2luZydcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGN1dG91dDogJzUwJScsXG4gICAgICAgIHJvdGF0aW9uOiAwLFxuICAgICAgICBjaXJjdW1mZXJlbmNlOiAzNjAsXG4gICAgICAgIHJhZGl1czogJzEwMCUnLFxuICAgICAgICBzcGFjaW5nOiAwLFxuICAgICAgICBpbmRleEF4aXM6ICdyJ1xuICAgIH07XG4gICAgc3RhdGljIGRlc2NyaXB0b3JzID0ge1xuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnc3BhY2luZycsXG4gICAgICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ3NwYWNpbmcnICYmICFuYW1lLnN0YXJ0c1dpdGgoJ2JvcmRlckRhc2gnKSAmJiAhbmFtZS5zdGFydHNXaXRoKCdob3ZlckJvcmRlckRhc2gnKVxuICAgIH07XG4gc3RhdGljIG92ZXJyaWRlcyA9IHtcbiAgICAgICAgYXNwZWN0UmF0aW86IDEsXG4gICAgICAgIHBsdWdpbnM6IHtcbiAgICAgICAgICAgIGxlZ2VuZDoge1xuICAgICAgICAgICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgICAgICAgICBnZW5lcmF0ZUxhYmVscyAoY2hhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBjaGFydC5kYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEubGFiZWxzLmxlbmd0aCAmJiBkYXRhLmRhdGFzZXRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgbGFiZWxzOiB7IHBvaW50U3R5bGUgLCBjb2xvciAgfSAgfSA9IGNoYXJ0LmxlZ2VuZC5vcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhLmxhYmVscy5tYXAoKGxhYmVsLCBpKT0+e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0eWxlID0gbWV0YS5jb250cm9sbGVyLmdldFN0eWxlKGkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogbGFiZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsU3R5bGU6IHN0eWxlLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZVN0eWxlOiBzdHlsZS5ib3JkZXJDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogY29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lV2lkdGg6IHN0eWxlLmJvcmRlcldpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogcG9pbnRTdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGRlbjogIWNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25DbGljayAoZSwgbGVnZW5kSXRlbSwgbGVnZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5jaGFydC50b2dnbGVEYXRhVmlzaWJpbGl0eShsZWdlbmRJdGVtLmluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmNoYXJ0LnVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2hhcnQsIGRhdGFzZXRJbmRleCl7XG4gICAgICAgIHN1cGVyKGNoYXJ0LCBkYXRhc2V0SW5kZXgpO1xuICAgICAgICB0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLmlubmVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm91dGVyUmFkaXVzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm9mZnNldFggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMub2Zmc2V0WSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgbGlua1NjYWxlcygpIHt9XG4gcGFyc2Uoc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmdldERhdGFzZXQoKS5kYXRhO1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgaWYgKHRoaXMuX3BhcnNpbmcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBtZXRhLl9wYXJzZWQgPSBkYXRhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGdldHRlciA9IChpKT0+K2RhdGFbaV07XG4gICAgICAgICAgICBpZiAoaXNPYmplY3QoZGF0YVtzdGFydF0pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBrZXkgPSd2YWx1ZScgIH0gPSB0aGlzLl9wYXJzaW5nO1xuICAgICAgICAgICAgICAgIGdldHRlciA9IChpKT0+K3Jlc29sdmVPYmplY3RLZXkoZGF0YVtpXSwga2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICAgICAgZm9yKGkgPSBzdGFydCwgaWxlbiA9IHN0YXJ0ICsgY291bnQ7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgICAgIG1ldGEuX3BhcnNlZFtpXSA9IGdldHRlcihpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiBfZ2V0Um90YXRpb24oKSB7XG4gICAgICAgIHJldHVybiB0b1JhZGlhbnModGhpcy5vcHRpb25zLnJvdGF0aW9uIC0gOTApO1xuICAgIH1cbiBfZ2V0Q2lyY3VtZmVyZW5jZSgpIHtcbiAgICAgICAgcmV0dXJuIHRvUmFkaWFucyh0aGlzLm9wdGlvbnMuY2lyY3VtZmVyZW5jZSk7XG4gICAgfVxuIF9nZXRSb3RhdGlvbkV4dGVudHMoKSB7XG4gICAgICAgIGxldCBtaW4gPSBUQVU7XG4gICAgICAgIGxldCBtYXggPSAtVEFVO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzLmxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgIGlmICh0aGlzLmNoYXJ0LmlzRGF0YXNldFZpc2libGUoaSkgJiYgdGhpcy5jaGFydC5nZXREYXRhc2V0TWV0YShpKS50eXBlID09PSB0aGlzLl90eXBlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IHRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEoaSkuY29udHJvbGxlcjtcbiAgICAgICAgICAgICAgICBjb25zdCByb3RhdGlvbiA9IGNvbnRyb2xsZXIuX2dldFJvdGF0aW9uKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY2lyY3VtZmVyZW5jZSA9IGNvbnRyb2xsZXIuX2dldENpcmN1bWZlcmVuY2UoKTtcbiAgICAgICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIHJvdGF0aW9uKTtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIHJvdGF0aW9uICsgY2lyY3VtZmVyZW5jZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvdGF0aW9uOiBtaW4sXG4gICAgICAgICAgICBjaXJjdW1mZXJlbmNlOiBtYXggLSBtaW5cbiAgICAgICAgfTtcbiAgICB9XG4gdXBkYXRlKG1vZGUpIHtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCB7IGNoYXJ0QXJlYSAgfSA9IGNoYXJ0O1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgYXJjcyA9IG1ldGEuZGF0YTtcbiAgICAgICAgY29uc3Qgc3BhY2luZyA9IHRoaXMuZ2V0TWF4Qm9yZGVyV2lkdGgoKSArIHRoaXMuZ2V0TWF4T2Zmc2V0KGFyY3MpICsgdGhpcy5vcHRpb25zLnNwYWNpbmc7XG4gICAgICAgIGNvbnN0IG1heFNpemUgPSBNYXRoLm1heCgoTWF0aC5taW4oY2hhcnRBcmVhLndpZHRoLCBjaGFydEFyZWEuaGVpZ2h0KSAtIHNwYWNpbmcpIC8gMiwgMCk7XG4gICAgICAgIGNvbnN0IGN1dG91dCA9IE1hdGgubWluKHRvUGVyY2VudGFnZSh0aGlzLm9wdGlvbnMuY3V0b3V0LCBtYXhTaXplKSwgMSk7XG4gICAgICAgIGNvbnN0IGNoYXJ0V2VpZ2h0ID0gdGhpcy5fZ2V0UmluZ1dlaWdodCh0aGlzLmluZGV4KTtcbiAgICAgICAgY29uc3QgeyBjaXJjdW1mZXJlbmNlICwgcm90YXRpb24gIH0gPSB0aGlzLl9nZXRSb3RhdGlvbkV4dGVudHMoKTtcbiAgICAgICAgY29uc3QgeyByYXRpb1ggLCByYXRpb1kgLCBvZmZzZXRYICwgb2Zmc2V0WSAgfSA9IGdldFJhdGlvQW5kT2Zmc2V0KHJvdGF0aW9uLCBjaXJjdW1mZXJlbmNlLCBjdXRvdXQpO1xuICAgICAgICBjb25zdCBtYXhXaWR0aCA9IChjaGFydEFyZWEud2lkdGggLSBzcGFjaW5nKSAvIHJhdGlvWDtcbiAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gKGNoYXJ0QXJlYS5oZWlnaHQgLSBzcGFjaW5nKSAvIHJhdGlvWTtcbiAgICAgICAgY29uc3QgbWF4UmFkaXVzID0gTWF0aC5tYXgoTWF0aC5taW4obWF4V2lkdGgsIG1heEhlaWdodCkgLyAyLCAwKTtcbiAgICAgICAgY29uc3Qgb3V0ZXJSYWRpdXMgPSB0b0RpbWVuc2lvbih0aGlzLm9wdGlvbnMucmFkaXVzLCBtYXhSYWRpdXMpO1xuICAgICAgICBjb25zdCBpbm5lclJhZGl1cyA9IE1hdGgubWF4KG91dGVyUmFkaXVzICogY3V0b3V0LCAwKTtcbiAgICAgICAgY29uc3QgcmFkaXVzTGVuZ3RoID0gKG91dGVyUmFkaXVzIC0gaW5uZXJSYWRpdXMpIC8gdGhpcy5fZ2V0VmlzaWJsZURhdGFzZXRXZWlnaHRUb3RhbCgpO1xuICAgICAgICB0aGlzLm9mZnNldFggPSBvZmZzZXRYICogb3V0ZXJSYWRpdXM7XG4gICAgICAgIHRoaXMub2Zmc2V0WSA9IG9mZnNldFkgKiBvdXRlclJhZGl1cztcbiAgICAgICAgbWV0YS50b3RhbCA9IHRoaXMuY2FsY3VsYXRlVG90YWwoKTtcbiAgICAgICAgdGhpcy5vdXRlclJhZGl1cyA9IG91dGVyUmFkaXVzIC0gcmFkaXVzTGVuZ3RoICogdGhpcy5fZ2V0UmluZ1dlaWdodE9mZnNldCh0aGlzLmluZGV4KTtcbiAgICAgICAgdGhpcy5pbm5lclJhZGl1cyA9IE1hdGgubWF4KHRoaXMub3V0ZXJSYWRpdXMgLSByYWRpdXNMZW5ndGggKiBjaGFydFdlaWdodCwgMCk7XG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudHMoYXJjcywgMCwgYXJjcy5sZW5ndGgsIG1vZGUpO1xuICAgIH1cbiBfY2lyY3VtZmVyZW5jZShpLCByZXNldCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgY2lyY3VtZmVyZW5jZSA9IHRoaXMuX2dldENpcmN1bWZlcmVuY2UoKTtcbiAgICAgICAgaWYgKHJlc2V0ICYmIG9wdHMuYW5pbWF0aW9uLmFuaW1hdGVSb3RhdGUgfHwgIXRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaSkgfHwgbWV0YS5fcGFyc2VkW2ldID09PSBudWxsIHx8IG1ldGEuZGF0YVtpXS5oaWRkZW4pIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZUNpcmN1bWZlcmVuY2UobWV0YS5fcGFyc2VkW2ldICogY2lyY3VtZmVyZW5jZSAvIFRBVSk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKGFyY3MsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgICAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgY2hhcnRBcmVhID0gY2hhcnQuY2hhcnRBcmVhO1xuICAgICAgICBjb25zdCBvcHRzID0gY2hhcnQub3B0aW9ucztcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uT3B0cyA9IG9wdHMuYW5pbWF0aW9uO1xuICAgICAgICBjb25zdCBjZW50ZXJYID0gKGNoYXJ0QXJlYS5sZWZ0ICsgY2hhcnRBcmVhLnJpZ2h0KSAvIDI7XG4gICAgICAgIGNvbnN0IGNlbnRlclkgPSAoY2hhcnRBcmVhLnRvcCArIGNoYXJ0QXJlYS5ib3R0b20pIC8gMjtcbiAgICAgICAgY29uc3QgYW5pbWF0ZVNjYWxlID0gcmVzZXQgJiYgYW5pbWF0aW9uT3B0cy5hbmltYXRlU2NhbGU7XG4gICAgICAgIGNvbnN0IGlubmVyUmFkaXVzID0gYW5pbWF0ZVNjYWxlID8gMCA6IHRoaXMuaW5uZXJSYWRpdXM7XG4gICAgICAgIGNvbnN0IG91dGVyUmFkaXVzID0gYW5pbWF0ZVNjYWxlID8gMCA6IHRoaXMub3V0ZXJSYWRpdXM7XG4gICAgICAgIGNvbnN0IHsgc2hhcmVkT3B0aW9ucyAsIGluY2x1ZGVPcHRpb25zICB9ID0gdGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhzdGFydCwgbW9kZSk7XG4gICAgICAgIGxldCBzdGFydEFuZ2xlID0gdGhpcy5fZ2V0Um90YXRpb24oKTtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHN0YXJ0OyArK2kpe1xuICAgICAgICAgICAgc3RhcnRBbmdsZSArPSB0aGlzLl9jaXJjdW1mZXJlbmNlKGksIHJlc2V0KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IGNpcmN1bWZlcmVuY2UgPSB0aGlzLl9jaXJjdW1mZXJlbmNlKGksIHJlc2V0KTtcbiAgICAgICAgICAgIGNvbnN0IGFyYyA9IGFyY3NbaV07XG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIHg6IGNlbnRlclggKyB0aGlzLm9mZnNldFgsXG4gICAgICAgICAgICAgICAgeTogY2VudGVyWSArIHRoaXMub2Zmc2V0WSxcbiAgICAgICAgICAgICAgICBzdGFydEFuZ2xlLFxuICAgICAgICAgICAgICAgIGVuZEFuZ2xlOiBzdGFydEFuZ2xlICsgY2lyY3VtZmVyZW5jZSxcbiAgICAgICAgICAgICAgICBjaXJjdW1mZXJlbmNlLFxuICAgICAgICAgICAgICAgIG91dGVyUmFkaXVzLFxuICAgICAgICAgICAgICAgIGlubmVyUmFkaXVzXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGluY2x1ZGVPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5vcHRpb25zID0gc2hhcmVkT3B0aW9ucyB8fCB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgYXJjLmFjdGl2ZSA/ICdhY3RpdmUnIDogbW9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGFydEFuZ2xlICs9IGNpcmN1bWZlcmVuY2U7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQoYXJjLCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjYWxjdWxhdGVUb3RhbCgpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IG1ldGFEYXRhID0gbWV0YS5kYXRhO1xuICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbWV0YURhdGEubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBtZXRhLl9wYXJzZWRbaV07XG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgIWlzTmFOKHZhbHVlKSAmJiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpICYmICFtZXRhRGF0YVtpXS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICB0b3RhbCArPSBNYXRoLmFicyh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFsO1xuICAgIH1cbiAgICBjYWxjdWxhdGVDaXJjdW1mZXJlbmNlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IHRvdGFsID0gdGhpcy5fY2FjaGVkTWV0YS50b3RhbDtcbiAgICAgICAgaWYgKHRvdGFsID4gMCAmJiAhaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gVEFVICogKE1hdGguYWJzKHZhbHVlKSAvIHRvdGFsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBsYWJlbHMgPSBjaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBmb3JtYXROdW1iZXIobWV0YS5fcGFyc2VkW2luZGV4XSwgY2hhcnQub3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IGxhYmVsc1tpbmRleF0gfHwgJycsXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRNYXhCb3JkZXJXaWR0aChhcmNzKSB7XG4gICAgICAgIGxldCBtYXggPSAwO1xuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGxldCBpLCBpbGVuLCBtZXRhLCBjb250cm9sbGVyLCBvcHRpb25zO1xuICAgICAgICBpZiAoIWFyY3MpIHtcbiAgICAgICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGNoYXJ0LmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgICAgICBpZiAoY2hhcnQuaXNEYXRhc2V0VmlzaWJsZShpKSkge1xuICAgICAgICAgICAgICAgICAgICBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoaSk7XG4gICAgICAgICAgICAgICAgICAgIGFyY3MgPSBtZXRhLmRhdGE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXIgPSBtZXRhLmNvbnRyb2xsZXI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWFyY3MpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGFyY3MubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBjb250cm9sbGVyLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSk7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5ib3JkZXJBbGlnbiAhPT0gJ2lubmVyJykge1xuICAgICAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgb3B0aW9ucy5ib3JkZXJXaWR0aCB8fCAwLCBvcHRpb25zLmhvdmVyQm9yZGVyV2lkdGggfHwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1heDtcbiAgICB9XG4gICAgZ2V0TWF4T2Zmc2V0KGFyY3MpIHtcbiAgICAgICAgbGV0IG1heCA9IDA7XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSBhcmNzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkpO1xuICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBvcHRpb25zLm9mZnNldCB8fCAwLCBvcHRpb25zLmhvdmVyT2Zmc2V0IHx8IDApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgfVxuIF9nZXRSaW5nV2VpZ2h0T2Zmc2V0KGRhdGFzZXRJbmRleCkge1xuICAgICAgICBsZXQgcmluZ1dlaWdodE9mZnNldCA9IDA7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBkYXRhc2V0SW5kZXg7ICsraSl7XG4gICAgICAgICAgICBpZiAodGhpcy5jaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpKSB7XG4gICAgICAgICAgICAgICAgcmluZ1dlaWdodE9mZnNldCArPSB0aGlzLl9nZXRSaW5nV2VpZ2h0KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByaW5nV2VpZ2h0T2Zmc2V0O1xuICAgIH1cbiBfZ2V0UmluZ1dlaWdodChkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHZhbHVlT3JEZWZhdWx0KHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0c1tkYXRhc2V0SW5kZXhdLndlaWdodCwgMSksIDApO1xuICAgIH1cbiBfZ2V0VmlzaWJsZURhdGFzZXRXZWlnaHRUb3RhbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldFJpbmdXZWlnaHRPZmZzZXQodGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzLmxlbmd0aCkgfHwgMTtcbiAgICB9XG59XG5cbmNsYXNzIExpbmVDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdsaW5lJztcbiBzdGF0aWMgZGVmYXVsdHMgPSB7XG4gICAgICAgIGRhdGFzZXRFbGVtZW50VHlwZTogJ2xpbmUnLFxuICAgICAgICBkYXRhRWxlbWVudFR5cGU6ICdwb2ludCcsXG4gICAgICAgIHNob3dMaW5lOiB0cnVlLFxuICAgICAgICBzcGFuR2FwczogZmFsc2VcbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgX2luZGV4Xzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdjYXRlZ29yeSdcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfdmFsdWVfOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgaW5pdGlhbGl6ZSgpIHtcbiAgICAgICAgdGhpcy5lbmFibGVPcHRpb25TaGFyaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdXBwb3J0c0RlY2ltYXRpb24gPSB0cnVlO1xuICAgICAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgfVxuICAgIHVwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCB7IGRhdGFzZXQ6IGxpbmUgLCBkYXRhOiBwb2ludHMgPSBbXSAsIF9kYXRhc2V0ICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uc0Rpc2FibGVkID0gdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkO1xuICAgICAgICBsZXQgeyBzdGFydCAsIGNvdW50ICB9ID0gX2dldFN0YXJ0QW5kQ291bnRPZlZpc2libGVQb2ludHMobWV0YSwgcG9pbnRzLCBhbmltYXRpb25zRGlzYWJsZWQpO1xuICAgICAgICB0aGlzLl9kcmF3U3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy5fZHJhd0NvdW50ID0gY291bnQ7XG4gICAgICAgIGlmIChfc2NhbGVSYW5nZXNDaGFuZ2VkKG1ldGEpKSB7XG4gICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgbGluZS5fY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBsaW5lLl9kYXRhc2V0SW5kZXggPSB0aGlzLmluZGV4O1xuICAgICAgICBsaW5lLl9kZWNpbWF0ZWQgPSAhIV9kYXRhc2V0Ll9kZWNpbWF0ZWQ7XG4gICAgICAgIGxpbmUucG9pbnRzID0gcG9pbnRzO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5yZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKG1vZGUpO1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93TGluZSkge1xuICAgICAgICAgICAgb3B0aW9ucy5ib3JkZXJXaWR0aCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucy5zZWdtZW50ID0gdGhpcy5vcHRpb25zLnNlZ21lbnQ7XG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudChsaW5lLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICAgIGFuaW1hdGVkOiAhYW5pbWF0aW9uc0Rpc2FibGVkLFxuICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICB9LCBtb2RlKTtcbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKHBvaW50cywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCB2U2NhbGUgLCBfc3RhY2tlZCAsIF9kYXRhc2V0ICB9ID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgeyBzaGFyZWRPcHRpb25zICwgaW5jbHVkZU9wdGlvbnMgIH0gPSB0aGlzLl9nZXRTaGFyZWRPcHRpb25zKHN0YXJ0LCBtb2RlKTtcbiAgICAgICAgY29uc3QgaUF4aXMgPSBpU2NhbGUuYXhpcztcbiAgICAgICAgY29uc3QgdkF4aXMgPSB2U2NhbGUuYXhpcztcbiAgICAgICAgY29uc3QgeyBzcGFuR2FwcyAsIHNlZ21lbnQgIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IG1heEdhcExlbmd0aCA9IGlzTnVtYmVyKHNwYW5HYXBzKSA/IHNwYW5HYXBzIDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgICBjb25zdCBkaXJlY3RVcGRhdGUgPSB0aGlzLmNoYXJ0Ll9hbmltYXRpb25zRGlzYWJsZWQgfHwgcmVzZXQgfHwgbW9kZSA9PT0gJ25vbmUnO1xuICAgICAgICBjb25zdCBlbmQgPSBzdGFydCArIGNvdW50O1xuICAgICAgICBjb25zdCBwb2ludHNDb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgICAgIGxldCBwcmV2UGFyc2VkID0gc3RhcnQgPiAwICYmIHRoaXMuZ2V0UGFyc2VkKHN0YXJ0IC0gMSk7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwb2ludHNDb3VudDsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IGRpcmVjdFVwZGF0ZSA/IHBvaW50IDoge307XG4gICAgICAgICAgICBpZiAoaSA8IHN0YXJ0IHx8IGkgPj0gZW5kKSB7XG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5za2lwID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGkpO1xuICAgICAgICAgICAgY29uc3QgbnVsbERhdGEgPSBpc051bGxPclVuZGVmKHBhcnNlZFt2QXhpc10pO1xuICAgICAgICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbaUF4aXNdLCBpKTtcbiAgICAgICAgICAgIGNvbnN0IHZQaXhlbCA9IHByb3BlcnRpZXNbdkF4aXNdID0gcmVzZXQgfHwgbnVsbERhdGEgPyB2U2NhbGUuZ2V0QmFzZVBpeGVsKCkgOiB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShfc3RhY2tlZCA/IHRoaXMuYXBwbHlTdGFjayh2U2NhbGUsIHBhcnNlZCwgX3N0YWNrZWQpIDogcGFyc2VkW3ZBeGlzXSwgaSk7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnNraXAgPSBpc05hTihpUGl4ZWwpIHx8IGlzTmFOKHZQaXhlbCkgfHwgbnVsbERhdGE7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnN0b3AgPSBpID4gMCAmJiBNYXRoLmFicyhwYXJzZWRbaUF4aXNdIC0gcHJldlBhcnNlZFtpQXhpc10pID4gbWF4R2FwTGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHNlZ21lbnQpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnJhdyA9IF9kYXRhc2V0LmRhdGFbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jbHVkZU9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBwb2ludC5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkaXJlY3RVcGRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldlBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgfVxuICAgIH1cbiBnZXRNYXhPdmVyZmxvdygpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IGRhdGFzZXQgPSBtZXRhLmRhdGFzZXQ7XG4gICAgICAgIGNvbnN0IGJvcmRlciA9IGRhdGFzZXQub3B0aW9ucyAmJiBkYXRhc2V0Lm9wdGlvbnMuYm9yZGVyV2lkdGggfHwgMDtcbiAgICAgICAgY29uc3QgZGF0YSA9IG1ldGEuZGF0YSB8fCBbXTtcbiAgICAgICAgaWYgKCFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGJvcmRlcjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaXJzdFBvaW50ID0gZGF0YVswXS5zaXplKHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucygwKSk7XG4gICAgICAgIGNvbnN0IGxhc3RQb2ludCA9IGRhdGFbZGF0YS5sZW5ndGggLSAxXS5zaXplKHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhkYXRhLmxlbmd0aCAtIDEpKTtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGJvcmRlciwgZmlyc3RQb2ludCwgbGFzdFBvaW50KSAvIDI7XG4gICAgfVxuICAgIGRyYXcoKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBtZXRhLmRhdGFzZXQudXBkYXRlQ29udHJvbFBvaW50cyh0aGlzLmNoYXJ0LmNoYXJ0QXJlYSwgbWV0YS5pU2NhbGUuYXhpcyk7XG4gICAgICAgIHN1cGVyLmRyYXcoKTtcbiAgICB9XG59XG5cbmNsYXNzIFBvbGFyQXJlYUNvbnRyb2xsZXIgZXh0ZW5kcyBEYXRhc2V0Q29udHJvbGxlciB7XG4gICAgc3RhdGljIGlkID0gJ3BvbGFyQXJlYSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhRWxlbWVudFR5cGU6ICdhcmMnLFxuICAgICAgICBhbmltYXRpb246IHtcbiAgICAgICAgICAgIGFuaW1hdGVSb3RhdGU6IHRydWUsXG4gICAgICAgICAgICBhbmltYXRlU2NhbGU6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgYW5pbWF0aW9uczoge1xuICAgICAgICAgICAgbnVtYmVyczoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgICAgICAgICAneScsXG4gICAgICAgICAgICAgICAgICAgICdzdGFydEFuZ2xlJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VuZEFuZ2xlJyxcbiAgICAgICAgICAgICAgICAgICAgJ2lubmVyUmFkaXVzJyxcbiAgICAgICAgICAgICAgICAgICAgJ291dGVyUmFkaXVzJ1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgaW5kZXhBeGlzOiAncicsXG4gICAgICAgIHN0YXJ0QW5nbGU6IDBcbiAgICB9O1xuIHN0YXRpYyBvdmVycmlkZXMgPSB7XG4gICAgICAgIGFzcGVjdFJhdGlvOiAxLFxuICAgICAgICBwbHVnaW5zOiB7XG4gICAgICAgICAgICBsZWdlbmQ6IHtcbiAgICAgICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVMYWJlbHMgKGNoYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gY2hhcnQuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmxhYmVscy5sZW5ndGggJiYgZGF0YS5kYXRhc2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGxhYmVsczogeyBwb2ludFN0eWxlICwgY29sb3IgIH0gIH0gPSBjaGFydC5sZWdlbmQub3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5sYWJlbHMubWFwKChsYWJlbCwgaSk9PntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHlsZSA9IG1ldGEuY29udHJvbGxlci5nZXRTdHlsZShpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGxhYmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbFN0eWxlOiBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VTdHlsZTogc3R5bGUuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250Q29sb3I6IGNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZVdpZHRoOiBzdHlsZS5ib3JkZXJXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50U3R5bGU6IHBvaW50U3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW46ICFjaGFydC5nZXREYXRhVmlzaWJpbGl0eShpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiBpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uQ2xpY2sgKGUsIGxlZ2VuZEl0ZW0sIGxlZ2VuZCkge1xuICAgICAgICAgICAgICAgICAgICBsZWdlbmQuY2hhcnQudG9nZ2xlRGF0YVZpc2liaWxpdHkobGVnZW5kSXRlbS5pbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5jaGFydC51cGRhdGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNjYWxlczoge1xuICAgICAgICAgICAgcjoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdyYWRpYWxMaW5lYXInLFxuICAgICAgICAgICAgICAgIGFuZ2xlTGluZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZmFsc2VcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGJlZ2luQXRaZXJvOiB0cnVlLFxuICAgICAgICAgICAgICAgIGdyaWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgY2lyY3VsYXI6IHRydWVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBvaW50TGFiZWxzOiB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzdGFydEFuZ2xlOiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGNoYXJ0LCBkYXRhc2V0SW5kZXgpe1xuICAgICAgICBzdXBlcihjaGFydCwgZGF0YXNldEluZGV4KTtcbiAgICAgICAgdGhpcy5pbm5lclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5vdXRlclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBsYWJlbHMgPSBjaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBmb3JtYXROdW1iZXIobWV0YS5fcGFyc2VkW2luZGV4XS5yLCBjaGFydC5vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsYWJlbDogbGFiZWxzW2luZGV4XSB8fCAnJyxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgIH07XG4gICAgfVxuICAgIHBhcnNlT2JqZWN0RGF0YShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpIHtcbiAgICAgICAgcmV0dXJuIF9wYXJzZU9iamVjdERhdGFSYWRpYWxTY2FsZS5iaW5kKHRoaXMpKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCk7XG4gICAgfVxuICAgIHVwZGF0ZShtb2RlKSB7XG4gICAgICAgIGNvbnN0IGFyY3MgPSB0aGlzLl9jYWNoZWRNZXRhLmRhdGE7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJhZGl1cygpO1xuICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnRzKGFyY3MsIDAsIGFyY3MubGVuZ3RoLCBtb2RlKTtcbiAgICB9XG4gZ2V0TWluTWF4KCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgcmFuZ2UgPSB7XG4gICAgICAgICAgICBtaW46IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSxcbiAgICAgICAgICAgIG1heDogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZXG4gICAgICAgIH07XG4gICAgICAgIG1ldGEuZGF0YS5mb3JFYWNoKChlbGVtZW50LCBpbmRleCk9PntcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZ2V0UGFyc2VkKGluZGV4KS5yO1xuICAgICAgICAgICAgaWYgKCFpc05hTihwYXJzZWQpICYmIHRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcnNlZCA8IHJhbmdlLm1pbikge1xuICAgICAgICAgICAgICAgICAgICByYW5nZS5taW4gPSBwYXJzZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwYXJzZWQgPiByYW5nZS5tYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UubWF4ID0gcGFyc2VkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9XG4gX3VwZGF0ZVJhZGl1cygpIHtcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBjaGFydEFyZWEgPSBjaGFydC5jaGFydEFyZWE7XG4gICAgICAgIGNvbnN0IG9wdHMgPSBjaGFydC5vcHRpb25zO1xuICAgICAgICBjb25zdCBtaW5TaXplID0gTWF0aC5taW4oY2hhcnRBcmVhLnJpZ2h0IC0gY2hhcnRBcmVhLmxlZnQsIGNoYXJ0QXJlYS5ib3R0b20gLSBjaGFydEFyZWEudG9wKTtcbiAgICAgICAgY29uc3Qgb3V0ZXJSYWRpdXMgPSBNYXRoLm1heChtaW5TaXplIC8gMiwgMCk7XG4gICAgICAgIGNvbnN0IGlubmVyUmFkaXVzID0gTWF0aC5tYXgob3B0cy5jdXRvdXRQZXJjZW50YWdlID8gb3V0ZXJSYWRpdXMgLyAxMDAgKiBvcHRzLmN1dG91dFBlcmNlbnRhZ2UgOiAxLCAwKTtcbiAgICAgICAgY29uc3QgcmFkaXVzTGVuZ3RoID0gKG91dGVyUmFkaXVzIC0gaW5uZXJSYWRpdXMpIC8gY2hhcnQuZ2V0VmlzaWJsZURhdGFzZXRDb3VudCgpO1xuICAgICAgICB0aGlzLm91dGVyUmFkaXVzID0gb3V0ZXJSYWRpdXMgLSByYWRpdXNMZW5ndGggKiB0aGlzLmluZGV4O1xuICAgICAgICB0aGlzLmlubmVyUmFkaXVzID0gdGhpcy5vdXRlclJhZGl1cyAtIHJhZGl1c0xlbmd0aDtcbiAgICB9XG4gICAgdXBkYXRlRWxlbWVudHMoYXJjcywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICAgICAgY29uc3QgY2hhcnQgPSB0aGlzLmNoYXJ0O1xuICAgICAgICBjb25zdCBvcHRzID0gY2hhcnQub3B0aW9ucztcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uT3B0cyA9IG9wdHMuYW5pbWF0aW9uO1xuICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX2NhY2hlZE1ldGEuclNjYWxlO1xuICAgICAgICBjb25zdCBjZW50ZXJYID0gc2NhbGUueENlbnRlcjtcbiAgICAgICAgY29uc3QgY2VudGVyWSA9IHNjYWxlLnlDZW50ZXI7XG4gICAgICAgIGNvbnN0IGRhdGFzZXRTdGFydEFuZ2xlID0gc2NhbGUuZ2V0SW5kZXhBbmdsZSgwKSAtIDAuNSAqIFBJO1xuICAgICAgICBsZXQgYW5nbGUgPSBkYXRhc2V0U3RhcnRBbmdsZTtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRBbmdsZSA9IDM2MCAvIHRoaXMuY291bnRWaXNpYmxlRWxlbWVudHMoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3RhcnQ7ICsraSl7XG4gICAgICAgICAgICBhbmdsZSArPSB0aGlzLl9jb21wdXRlQW5nbGUoaSwgbW9kZSwgZGVmYXVsdEFuZ2xlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IGFyYyA9IGFyY3NbaV07XG4gICAgICAgICAgICBsZXQgc3RhcnRBbmdsZSA9IGFuZ2xlO1xuICAgICAgICAgICAgbGV0IGVuZEFuZ2xlID0gYW5nbGUgKyB0aGlzLl9jb21wdXRlQW5nbGUoaSwgbW9kZSwgZGVmYXVsdEFuZ2xlKTtcbiAgICAgICAgICAgIGxldCBvdXRlclJhZGl1cyA9IGNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpID8gc2NhbGUuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy5nZXRQYXJzZWQoaSkucikgOiAwO1xuICAgICAgICAgICAgYW5nbGUgPSBlbmRBbmdsZTtcbiAgICAgICAgICAgIGlmIChyZXNldCkge1xuICAgICAgICAgICAgICAgIGlmIChhbmltYXRpb25PcHRzLmFuaW1hdGVTY2FsZSkge1xuICAgICAgICAgICAgICAgICAgICBvdXRlclJhZGl1cyA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhbmltYXRpb25PcHRzLmFuaW1hdGVSb3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRBbmdsZSA9IGVuZEFuZ2xlID0gZGF0YXNldFN0YXJ0QW5nbGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICB4OiBjZW50ZXJYLFxuICAgICAgICAgICAgICAgIHk6IGNlbnRlclksXG4gICAgICAgICAgICAgICAgaW5uZXJSYWRpdXM6IDAsXG4gICAgICAgICAgICAgICAgb3V0ZXJSYWRpdXMsXG4gICAgICAgICAgICAgICAgc3RhcnRBbmdsZSxcbiAgICAgICAgICAgICAgICBlbmRBbmdsZSxcbiAgICAgICAgICAgICAgICBvcHRpb25zOiB0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSwgYXJjLmFjdGl2ZSA/ICdhY3RpdmUnIDogbW9kZSlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQoYXJjLCBpLCBwcm9wZXJ0aWVzLCBtb2RlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb3VudFZpc2libGVFbGVtZW50cygpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgIG1ldGEuZGF0YS5mb3JFYWNoKChlbGVtZW50LCBpbmRleCk9PntcbiAgICAgICAgICAgIGlmICghaXNOYU4odGhpcy5nZXRQYXJzZWQoaW5kZXgpLnIpICYmIHRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb3VudDtcbiAgICB9XG4gX2NvbXB1dGVBbmdsZShpbmRleCwgbW9kZSwgZGVmYXVsdEFuZ2xlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGluZGV4KSA/IHRvUmFkaWFucyh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaW5kZXgsIG1vZGUpLmFuZ2xlIHx8IGRlZmF1bHRBbmdsZSkgOiAwO1xuICAgIH1cbn1cblxuY2xhc3MgUGllQ29udHJvbGxlciBleHRlbmRzIERvdWdobnV0Q29udHJvbGxlciB7XG4gICAgc3RhdGljIGlkID0gJ3BpZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBjdXRvdXQ6IDAsXG4gICAgICAgIHJvdGF0aW9uOiAwLFxuICAgICAgICBjaXJjdW1mZXJlbmNlOiAzNjAsXG4gICAgICAgIHJhZGl1czogJzEwMCUnXG4gICAgfTtcbn1cblxuY2xhc3MgUmFkYXJDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdyYWRhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkYXRhc2V0RWxlbWVudFR5cGU6ICdsaW5lJyxcbiAgICAgICAgZGF0YUVsZW1lbnRUeXBlOiAncG9pbnQnLFxuICAgICAgICBpbmRleEF4aXM6ICdyJyxcbiAgICAgICAgc2hvd0xpbmU6IHRydWUsXG4gICAgICAgIGVsZW1lbnRzOiB7XG4gICAgICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICAgICAgZmlsbDogJ3N0YXJ0J1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiBzdGF0aWMgb3ZlcnJpZGVzID0ge1xuICAgICAgICBhc3BlY3RSYXRpbzogMSxcbiAgICAgICAgc2NhbGVzOiB7XG4gICAgICAgICAgICByOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3JhZGlhbExpbmVhcidcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCB2U2NhbGUgPSB0aGlzLl9jYWNoZWRNZXRhLnZTY2FsZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gdGhpcy5nZXRQYXJzZWQoaW5kZXgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGFiZWw6IHZTY2FsZS5nZXRMYWJlbHMoKVtpbmRleF0sXG4gICAgICAgICAgICB2YWx1ZTogJycgKyB2U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWRbdlNjYWxlLmF4aXNdKVxuICAgICAgICB9O1xuICAgIH1cbiAgICBwYXJzZU9iamVjdERhdGEobWV0YSwgZGF0YSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIHJldHVybiBfcGFyc2VPYmplY3REYXRhUmFkaWFsU2NhbGUuYmluZCh0aGlzKShtZXRhLCBkYXRhLCBzdGFydCwgY291bnQpO1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgbGluZSA9IG1ldGEuZGF0YXNldDtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gbWV0YS5kYXRhIHx8IFtdO1xuICAgICAgICBjb25zdCBsYWJlbHMgPSBtZXRhLmlTY2FsZS5nZXRMYWJlbHMoKTtcbiAgICAgICAgbGluZS5wb2ludHMgPSBwb2ludHM7XG4gICAgICAgIGlmIChtb2RlICE9PSAncmVzaXplJykge1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhtb2RlKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5vcHRpb25zLnNob3dMaW5lKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5ib3JkZXJXaWR0aCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIF9sb29wOiB0cnVlLFxuICAgICAgICAgICAgICAgIF9mdWxsTG9vcDogbGFiZWxzLmxlbmd0aCA9PT0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50KGxpbmUsIHVuZGVmaW5lZCwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhwb2ludHMsIDAsIHBvaW50cy5sZW5ndGgsIG1vZGUpO1xuICAgIH1cbiAgICB1cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSkge1xuICAgICAgICBjb25zdCBzY2FsZSA9IHRoaXMuX2NhY2hlZE1ldGEuclNjYWxlO1xuICAgICAgICBjb25zdCByZXNldCA9IG1vZGUgPT09ICdyZXNldCc7XG4gICAgICAgIGZvcihsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyBjb3VudDsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBwb2ludC5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgICAgICAgY29uc3QgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZShpLCB0aGlzLmdldFBhcnNlZChpKS5yKTtcbiAgICAgICAgICAgIGNvbnN0IHggPSByZXNldCA/IHNjYWxlLnhDZW50ZXIgOiBwb2ludFBvc2l0aW9uLng7XG4gICAgICAgICAgICBjb25zdCB5ID0gcmVzZXQgPyBzY2FsZS55Q2VudGVyIDogcG9pbnRQb3NpdGlvbi55O1xuICAgICAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgIHksXG4gICAgICAgICAgICAgICAgYW5nbGU6IHBvaW50UG9zaXRpb24uYW5nbGUsXG4gICAgICAgICAgICAgICAgc2tpcDogaXNOYU4oeCkgfHwgaXNOYU4oeSksXG4gICAgICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudChwb2ludCwgaSwgcHJvcGVydGllcywgbW9kZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmNsYXNzIFNjYXR0ZXJDb250cm9sbGVyIGV4dGVuZHMgRGF0YXNldENvbnRyb2xsZXIge1xuICAgIHN0YXRpYyBpZCA9ICdzY2F0dGVyJztcbiBzdGF0aWMgZGVmYXVsdHMgPSB7XG4gICAgICAgIGRhdGFzZXRFbGVtZW50VHlwZTogZmFsc2UsXG4gICAgICAgIGRhdGFFbGVtZW50VHlwZTogJ3BvaW50JyxcbiAgICAgICAgc2hvd0xpbmU6IGZhbHNlLFxuICAgICAgICBmaWxsOiBmYWxzZVxuICAgIH07XG4gc3RhdGljIG92ZXJyaWRlcyA9IHtcbiAgICAgICAgaW50ZXJhY3Rpb246IHtcbiAgICAgICAgICAgIG1vZGU6ICdwb2ludCdcbiAgICAgICAgfSxcbiAgICAgICAgc2NhbGVzOiB7XG4gICAgICAgICAgICB4OiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB5OiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcidcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgbGFiZWxzID0gdGhpcy5jaGFydC5kYXRhLmxhYmVscyB8fCBbXTtcbiAgICAgICAgY29uc3QgeyB4U2NhbGUgLCB5U2NhbGUgIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpbmRleCk7XG4gICAgICAgIGNvbnN0IHggPSB4U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWQueCk7XG4gICAgICAgIGNvbnN0IHkgPSB5U2NhbGUuZ2V0TGFiZWxGb3JWYWx1ZShwYXJzZWQueSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsYWJlbDogbGFiZWxzW2luZGV4XSB8fCAnJyxcbiAgICAgICAgICAgIHZhbHVlOiAnKCcgKyB4ICsgJywgJyArIHkgKyAnKSdcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlKG1vZGUpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuX2NhY2hlZE1ldGE7XG4gICAgICAgIGNvbnN0IHsgZGF0YTogcG9pbnRzID0gW10gIH0gPSBtZXRhO1xuICAgICAgICBjb25zdCBhbmltYXRpb25zRGlzYWJsZWQgPSB0aGlzLmNoYXJ0Ll9hbmltYXRpb25zRGlzYWJsZWQ7XG4gICAgICAgIGxldCB7IHN0YXJ0ICwgY291bnQgIH0gPSBfZ2V0U3RhcnRBbmRDb3VudE9mVmlzaWJsZVBvaW50cyhtZXRhLCBwb2ludHMsIGFuaW1hdGlvbnNEaXNhYmxlZCk7XG4gICAgICAgIHRoaXMuX2RyYXdTdGFydCA9IHN0YXJ0O1xuICAgICAgICB0aGlzLl9kcmF3Q291bnQgPSBjb3VudDtcbiAgICAgICAgaWYgKF9zY2FsZVJhbmdlc0NoYW5nZWQobWV0YSkpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgICAgIGNvdW50ID0gcG9pbnRzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNob3dMaW5lKSB7XG4gICAgICAgICAgICBjb25zdCB7IGRhdGFzZXQ6IGxpbmUgLCBfZGF0YXNldCAgfSA9IG1ldGE7XG4gICAgICAgICAgICBsaW5lLl9jaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgICAgICBsaW5lLl9kYXRhc2V0SW5kZXggPSB0aGlzLmluZGV4O1xuICAgICAgICAgICAgbGluZS5fZGVjaW1hdGVkID0gISFfZGF0YXNldC5fZGVjaW1hdGVkO1xuICAgICAgICAgICAgbGluZS5wb2ludHMgPSBwb2ludHM7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5yZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKG1vZGUpO1xuICAgICAgICAgICAgb3B0aW9ucy5zZWdtZW50ID0gdGhpcy5vcHRpb25zLnNlZ21lbnQ7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQobGluZSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICAgICAgYW5pbWF0ZWQ6ICFhbmltYXRpb25zRGlzYWJsZWQsXG4gICAgICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICAgICAgfSwgbW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVFbGVtZW50cyhwb2ludHMsIHN0YXJ0LCBjb3VudCwgbW9kZSk7XG4gICAgfVxuICAgIGFkZEVsZW1lbnRzKCkge1xuICAgICAgICBjb25zdCB7IHNob3dMaW5lICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoIXRoaXMuZGF0YXNldEVsZW1lbnRUeXBlICYmIHNob3dMaW5lKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSA9IHRoaXMuY2hhcnQucmVnaXN0cnkuZ2V0RWxlbWVudCgnbGluZScpO1xuICAgICAgICB9XG4gICAgICAgIHN1cGVyLmFkZEVsZW1lbnRzKCk7XG4gICAgfVxuICAgIHVwZGF0ZUVsZW1lbnRzKHBvaW50cywgc3RhcnQsIGNvdW50LCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJlc2V0ID0gbW9kZSA9PT0gJ3Jlc2V0JztcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCB2U2NhbGUgLCBfc3RhY2tlZCAsIF9kYXRhc2V0ICB9ID0gdGhpcy5fY2FjaGVkTWV0YTtcbiAgICAgICAgY29uc3QgZmlyc3RPcHRzID0gdGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHN0YXJ0LCBtb2RlKTtcbiAgICAgICAgY29uc3Qgc2hhcmVkT3B0aW9ucyA9IHRoaXMuZ2V0U2hhcmVkT3B0aW9ucyhmaXJzdE9wdHMpO1xuICAgICAgICBjb25zdCBpbmNsdWRlT3B0aW9ucyA9IHRoaXMuaW5jbHVkZU9wdGlvbnMobW9kZSwgc2hhcmVkT3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGlBeGlzID0gaVNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHZBeGlzID0gdlNjYWxlLmF4aXM7XG4gICAgICAgIGNvbnN0IHsgc3BhbkdhcHMgLCBzZWdtZW50ICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBtYXhHYXBMZW5ndGggPSBpc051bWJlcihzcGFuR2FwcykgPyBzcGFuR2FwcyA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgY29uc3QgZGlyZWN0VXBkYXRlID0gdGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkIHx8IHJlc2V0IHx8IG1vZGUgPT09ICdub25lJztcbiAgICAgICAgbGV0IHByZXZQYXJzZWQgPSBzdGFydCA+IDAgJiYgdGhpcy5nZXRQYXJzZWQoc3RhcnQgLSAxKTtcbiAgICAgICAgZm9yKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFydCArIGNvdW50OyArK2kpe1xuICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmdldFBhcnNlZChpKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBkaXJlY3RVcGRhdGUgPyBwb2ludCA6IHt9O1xuICAgICAgICAgICAgY29uc3QgbnVsbERhdGEgPSBpc051bGxPclVuZGVmKHBhcnNlZFt2QXhpc10pO1xuICAgICAgICAgICAgY29uc3QgaVBpeGVsID0gcHJvcGVydGllc1tpQXhpc10gPSBpU2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShwYXJzZWRbaUF4aXNdLCBpKTtcbiAgICAgICAgICAgIGNvbnN0IHZQaXhlbCA9IHByb3BlcnRpZXNbdkF4aXNdID0gcmVzZXQgfHwgbnVsbERhdGEgPyB2U2NhbGUuZ2V0QmFzZVBpeGVsKCkgOiB2U2NhbGUuZ2V0UGl4ZWxGb3JWYWx1ZShfc3RhY2tlZCA/IHRoaXMuYXBwbHlTdGFjayh2U2NhbGUsIHBhcnNlZCwgX3N0YWNrZWQpIDogcGFyc2VkW3ZBeGlzXSwgaSk7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnNraXAgPSBpc05hTihpUGl4ZWwpIHx8IGlzTmFOKHZQaXhlbCkgfHwgbnVsbERhdGE7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLnN0b3AgPSBpID4gMCAmJiBNYXRoLmFicyhwYXJzZWRbaUF4aXNdIC0gcHJldlBhcnNlZFtpQXhpc10pID4gbWF4R2FwTGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHNlZ21lbnQpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnJhdyA9IF9kYXRhc2V0LmRhdGFbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jbHVkZU9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLm9wdGlvbnMgPSBzaGFyZWRPcHRpb25zIHx8IHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLCBwb2ludC5hY3RpdmUgPyAnYWN0aXZlJyA6IG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkaXJlY3RVcGRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVsZW1lbnQocG9pbnQsIGksIHByb3BlcnRpZXMsIG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldlBhcnNlZCA9IHBhcnNlZDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZVNoYXJlZE9wdGlvbnMoc2hhcmVkT3B0aW9ucywgbW9kZSwgZmlyc3RPcHRzKTtcbiAgICB9XG4gZ2V0TWF4T3ZlcmZsb3coKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLl9jYWNoZWRNZXRhO1xuICAgICAgICBjb25zdCBkYXRhID0gbWV0YS5kYXRhIHx8IFtdO1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93TGluZSkge1xuICAgICAgICAgICAgbGV0IG1heCA9IDA7XG4gICAgICAgICAgICBmb3IobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIGRhdGFbaV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSkpIC8gMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF4ID4gMCAmJiBtYXg7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YXNldCA9IG1ldGEuZGF0YXNldDtcbiAgICAgICAgY29uc3QgYm9yZGVyID0gZGF0YXNldC5vcHRpb25zICYmIGRhdGFzZXQub3B0aW9ucy5ib3JkZXJXaWR0aCB8fCAwO1xuICAgICAgICBpZiAoIWRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gYm9yZGVyO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpcnN0UG9pbnQgPSBkYXRhWzBdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKDApKTtcbiAgICAgICAgY29uc3QgbGFzdFBvaW50ID0gZGF0YVtkYXRhLmxlbmd0aCAtIDFdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGRhdGEubGVuZ3RoIC0gMSkpO1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoYm9yZGVyLCBmaXJzdFBvaW50LCBsYXN0UG9pbnQpIC8gMjtcbiAgICB9XG59XG5cbnZhciBjb250cm9sbGVycyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbl9fcHJvdG9fXzogbnVsbCxcbkJhckNvbnRyb2xsZXI6IEJhckNvbnRyb2xsZXIsXG5CdWJibGVDb250cm9sbGVyOiBCdWJibGVDb250cm9sbGVyLFxuRG91Z2hudXRDb250cm9sbGVyOiBEb3VnaG51dENvbnRyb2xsZXIsXG5MaW5lQ29udHJvbGxlcjogTGluZUNvbnRyb2xsZXIsXG5QaWVDb250cm9sbGVyOiBQaWVDb250cm9sbGVyLFxuUG9sYXJBcmVhQ29udHJvbGxlcjogUG9sYXJBcmVhQ29udHJvbGxlcixcblJhZGFyQ29udHJvbGxlcjogUmFkYXJDb250cm9sbGVyLFxuU2NhdHRlckNvbnRyb2xsZXI6IFNjYXR0ZXJDb250cm9sbGVyXG59KTtcblxuLyoqXG4gKiBAbmFtZXNwYWNlIENoYXJ0Ll9hZGFwdGVyc1xuICogQHNpbmNlIDIuOC4wXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIGFic3RyYWN0KCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBtZXRob2QgaXMgbm90IGltcGxlbWVudGVkOiBDaGVjayB0aGF0IGEgY29tcGxldGUgZGF0ZSBhZGFwdGVyIGlzIHByb3ZpZGVkLicpO1xufVxuLyoqXG4gKiBEYXRlIGFkYXB0ZXIgKGN1cnJlbnQgdXNlZCBieSB0aGUgdGltZSBzY2FsZSlcbiAqIEBuYW1lc3BhY2UgQ2hhcnQuX2FkYXB0ZXJzLl9kYXRlXG4gKiBAbWVtYmVyb2YgQ2hhcnQuX2FkYXB0ZXJzXG4gKiBAcHJpdmF0ZVxuICovIGNsYXNzIERhdGVBZGFwdGVyQmFzZSB7XG4gICAgLyoqXG4gICAqIE92ZXJyaWRlIGRlZmF1bHQgZGF0ZSBhZGFwdGVyIG1ldGhvZHMuXG4gICAqIEFjY2VwdHMgdHlwZSBwYXJhbWV0ZXIgdG8gZGVmaW5lIG9wdGlvbnMgdHlwZS5cbiAgICogQGV4YW1wbGVcbiAgICogQ2hhcnQuX2FkYXB0ZXJzLl9kYXRlLm92ZXJyaWRlPHtteUFkYXB0ZXJPcHRpb246IHN0cmluZ30+KHtcbiAgICogICBpbml0KCkge1xuICAgKiAgICAgY29uc29sZS5sb2codGhpcy5vcHRpb25zLm15QWRhcHRlck9wdGlvbik7XG4gICAqICAgfVxuICAgKiB9KVxuICAgKi8gc3RhdGljIG92ZXJyaWRlKG1lbWJlcnMpIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihEYXRlQWRhcHRlckJhc2UucHJvdG90eXBlLCBtZW1iZXJzKTtcbiAgICB9XG4gICAgb3B0aW9ucztcbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zKXtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgIGluaXQoKSB7fVxuICAgIGZvcm1hdHMoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbiAgICBwYXJzZSgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGZvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGFkZCgpIHtcbiAgICAgICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gICAgfVxuICAgIGRpZmYoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbiAgICBzdGFydE9mKCkge1xuICAgICAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgICB9XG4gICAgZW5kT2YoKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICAgIH1cbn1cbnZhciBhZGFwdGVycyA9IHtcbiAgICBfZGF0ZTogRGF0ZUFkYXB0ZXJCYXNlXG59O1xuXG5mdW5jdGlvbiBiaW5hcnlTZWFyY2gobWV0YXNldCwgYXhpcywgdmFsdWUsIGludGVyc2VjdCkge1xuICAgIGNvbnN0IHsgY29udHJvbGxlciAsIGRhdGEgLCBfc29ydGVkICB9ID0gbWV0YXNldDtcbiAgICBjb25zdCBpU2NhbGUgPSBjb250cm9sbGVyLl9jYWNoZWRNZXRhLmlTY2FsZTtcbiAgICBpZiAoaVNjYWxlICYmIGF4aXMgPT09IGlTY2FsZS5heGlzICYmIGF4aXMgIT09ICdyJyAmJiBfc29ydGVkICYmIGRhdGEubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGxvb2t1cE1ldGhvZCA9IGlTY2FsZS5fcmV2ZXJzZVBpeGVscyA/IF9ybG9va3VwQnlLZXkgOiBfbG9va3VwQnlLZXk7XG4gICAgICAgIGlmICghaW50ZXJzZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gbG9va3VwTWV0aG9kKGRhdGEsIGF4aXMsIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sbGVyLl9zaGFyZWRPcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBlbCA9IGRhdGFbMF07XG4gICAgICAgICAgICBjb25zdCByYW5nZSA9IHR5cGVvZiBlbC5nZXRSYW5nZSA9PT0gJ2Z1bmN0aW9uJyAmJiBlbC5nZXRSYW5nZShheGlzKTtcbiAgICAgICAgICAgIGlmIChyYW5nZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gbG9va3VwTWV0aG9kKGRhdGEsIGF4aXMsIHZhbHVlIC0gcmFuZ2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVuZCA9IGxvb2t1cE1ldGhvZChkYXRhLCBheGlzLCB2YWx1ZSArIHJhbmdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBsbzogc3RhcnQubG8sXG4gICAgICAgICAgICAgICAgICAgIGhpOiBlbmQuaGlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGxvOiAwLFxuICAgICAgICBoaTogZGF0YS5sZW5ndGggLSAxXG4gICAgfTtcbn1cbiBmdW5jdGlvbiBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBoYW5kbGVyLCBpbnRlcnNlY3QpIHtcbiAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0LmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW2F4aXNdO1xuICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSBtZXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBjb25zdCB7IGluZGV4ICwgZGF0YSAgfSA9IG1ldGFzZXRzW2ldO1xuICAgICAgICBjb25zdCB7IGxvICwgaGkgIH0gPSBiaW5hcnlTZWFyY2gobWV0YXNldHNbaV0sIGF4aXMsIHZhbHVlLCBpbnRlcnNlY3QpO1xuICAgICAgICBmb3IobGV0IGogPSBsbzsgaiA8PSBoaTsgKytqKXtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkYXRhW2pdO1xuICAgICAgICAgICAgaWYgKCFlbGVtZW50LnNraXApIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVyKGVsZW1lbnQsIGluZGV4LCBqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbiBmdW5jdGlvbiBnZXREaXN0YW5jZU1ldHJpY0ZvckF4aXMoYXhpcykge1xuICAgIGNvbnN0IHVzZVggPSBheGlzLmluZGV4T2YoJ3gnKSAhPT0gLTE7XG4gICAgY29uc3QgdXNlWSA9IGF4aXMuaW5kZXhPZigneScpICE9PSAtMTtcbiAgICByZXR1cm4gZnVuY3Rpb24ocHQxLCBwdDIpIHtcbiAgICAgICAgY29uc3QgZGVsdGFYID0gdXNlWCA/IE1hdGguYWJzKHB0MS54IC0gcHQyLngpIDogMDtcbiAgICAgICAgY29uc3QgZGVsdGFZID0gdXNlWSA/IE1hdGguYWJzKHB0MS55IC0gcHQyLnkpIDogMDtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyhkZWx0YVgsIDIpICsgTWF0aC5wb3coZGVsdGFZLCAyKSk7XG4gICAgfTtcbn1cbiBmdW5jdGlvbiBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIHtcbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGlmICghaW5jbHVkZUludmlzaWJsZSAmJiAhY2hhcnQuaXNQb2ludEluQXJlYShwb3NpdGlvbikpIHtcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH1cbiAgICBjb25zdCBldmFsdWF0aW9uRnVuYyA9IGZ1bmN0aW9uKGVsZW1lbnQsIGRhdGFzZXRJbmRleCwgaW5kZXgpIHtcbiAgICAgICAgaWYgKCFpbmNsdWRlSW52aXNpYmxlICYmICFfaXNQb2ludEluQXJlYShlbGVtZW50LCBjaGFydC5jaGFydEFyZWEsIDApKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsZW1lbnQuaW5SYW5nZShwb3NpdGlvbi54LCBwb3NpdGlvbi55LCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBldmFsdWF0aW9uRnVuYywgdHJ1ZSk7XG4gICAgcmV0dXJuIGl0ZW1zO1xufVxuIGZ1bmN0aW9uIGdldE5lYXJlc3RSYWRpYWxJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBsZXQgaXRlbXMgPSBbXTtcbiAgICBmdW5jdGlvbiBldmFsdWF0aW9uRnVuYyhlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHsgc3RhcnRBbmdsZSAsIGVuZEFuZ2xlICB9ID0gZWxlbWVudC5nZXRQcm9wcyhbXG4gICAgICAgICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAgICAgICAnZW5kQW5nbGUnXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCB7IGFuZ2xlICB9ID0gZ2V0QW5nbGVGcm9tUG9pbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgeDogcG9zaXRpb24ueCxcbiAgICAgICAgICAgIHk6IHBvc2l0aW9uLnlcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChfYW5nbGVCZXR3ZWVuKGFuZ2xlLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSkpIHtcbiAgICAgICAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgZGF0YXNldEluZGV4LFxuICAgICAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCBldmFsdWF0aW9uRnVuYyk7XG4gICAgcmV0dXJuIGl0ZW1zO1xufVxuIGZ1bmN0aW9uIGdldE5lYXJlc3RDYXJ0ZXNpYW5JdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIGludGVyc2VjdCwgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSkge1xuICAgIGxldCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IGRpc3RhbmNlTWV0cmljID0gZ2V0RGlzdGFuY2VNZXRyaWNGb3JBeGlzKGF4aXMpO1xuICAgIGxldCBtaW5EaXN0YW5jZSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICBmdW5jdGlvbiBldmFsdWF0aW9uRnVuYyhlbGVtZW50LCBkYXRhc2V0SW5kZXgsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IGluUmFuZ2UgPSBlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGlmIChpbnRlcnNlY3QgJiYgIWluUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjZW50ZXIgPSBlbGVtZW50LmdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBwb2ludEluQXJlYSA9ICEhaW5jbHVkZUludmlzaWJsZSB8fCBjaGFydC5pc1BvaW50SW5BcmVhKGNlbnRlcik7XG4gICAgICAgIGlmICghcG9pbnRJbkFyZWEgJiYgIWluUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGRpc3RhbmNlTWV0cmljKHBvc2l0aW9uLCBjZW50ZXIpO1xuICAgICAgICBpZiAoZGlzdGFuY2UgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgaXRlbXMgPSBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gZGlzdGFuY2U7XG4gICAgICAgIH0gZWxzZSBpZiAoZGlzdGFuY2UgPT09IG1pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgICBpdGVtcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleCxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXZhbHVhdGVJbnRlcmFjdGlvbkl0ZW1zKGNoYXJ0LCBheGlzLCBwb3NpdGlvbiwgZXZhbHVhdGlvbkZ1bmMpO1xuICAgIHJldHVybiBpdGVtcztcbn1cbiBmdW5jdGlvbiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBpbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIHtcbiAgICBpZiAoIWluY2x1ZGVJbnZpc2libGUgJiYgIWNoYXJ0LmlzUG9pbnRJbkFyZWEocG9zaXRpb24pKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIGF4aXMgPT09ICdyJyAmJiAhaW50ZXJzZWN0ID8gZ2V0TmVhcmVzdFJhZGlhbEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgdXNlRmluYWxQb3NpdGlvbikgOiBnZXROZWFyZXN0Q2FydGVzaWFuSXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBpbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xufVxuIGZ1bmN0aW9uIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIGludGVyc2VjdCwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgY29uc3QgcmFuZ2VNZXRob2QgPSBheGlzID09PSAneCcgPyAnaW5YUmFuZ2UnIDogJ2luWVJhbmdlJztcbiAgICBsZXQgaW50ZXJzZWN0c0l0ZW0gPSBmYWxzZTtcbiAgICBldmFsdWF0ZUludGVyYWN0aW9uSXRlbXMoY2hhcnQsIGF4aXMsIHBvc2l0aW9uLCAoZWxlbWVudCwgZGF0YXNldEluZGV4LCBpbmRleCk9PntcbiAgICAgICAgaWYgKGVsZW1lbnRbcmFuZ2VNZXRob2RdKHBvc2l0aW9uW2F4aXNdLCB1c2VGaW5hbFBvc2l0aW9uKSkge1xuICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaW50ZXJzZWN0c0l0ZW0gPSBpbnRlcnNlY3RzSXRlbSB8fCBlbGVtZW50LmluUmFuZ2UocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoaW50ZXJzZWN0ICYmICFpbnRlcnNlY3RzSXRlbSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbn1cbiB2YXIgSW50ZXJhY3Rpb24gPSB7XG4gICAgZXZhbHVhdGVJbnRlcmFjdGlvbkl0ZW1zLFxuICAgIG1vZGVzOiB7XG4gaW5kZXggKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgY29uc3QgYXhpcyA9IG9wdGlvbnMuYXhpcyB8fCAneCc7XG4gICAgICAgICAgICBjb25zdCBpbmNsdWRlSW52aXNpYmxlID0gb3B0aW9ucy5pbmNsdWRlSW52aXNpYmxlIHx8IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgaXRlbXMgPSBvcHRpb25zLmludGVyc2VjdCA/IGdldEludGVyc2VjdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSkgOiBnZXROZWFyZXN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCBmYWxzZSwgdXNlRmluYWxQb3NpdGlvbiwgaW5jbHVkZUludmlzaWJsZSk7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50cyA9IFtdO1xuICAgICAgICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkuZm9yRWFjaCgobWV0YSk9PntcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IGl0ZW1zWzBdLmluZGV4O1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBtZXRhLmRhdGFbaW5kZXhdO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICYmICFlbGVtZW50LnNraXApIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldEluZGV4OiBtZXRhLmluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgICAgIH0sXG4gZGF0YXNldCAoY2hhcnQsIGUsIG9wdGlvbnMsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gZ2V0UmVsYXRpdmVQb3NpdGlvbihlLCBjaGFydCk7XG4gICAgICAgICAgICBjb25zdCBheGlzID0gb3B0aW9ucy5heGlzIHx8ICd4eSc7XG4gICAgICAgICAgICBjb25zdCBpbmNsdWRlSW52aXNpYmxlID0gb3B0aW9ucy5pbmNsdWRlSW52aXNpYmxlIHx8IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGl0ZW1zID0gb3B0aW9ucy5pbnRlcnNlY3QgPyBnZXRJbnRlcnNlY3RJdGVtcyhjaGFydCwgcG9zaXRpb24sIGF4aXMsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpIDogZ2V0TmVhcmVzdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgZmFsc2UsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xuICAgICAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhc2V0SW5kZXggPSBpdGVtc1swXS5kYXRhc2V0SW5kZXg7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuZGF0YTtcbiAgICAgICAgICAgICAgICBpdGVtcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgICAgICAgICAgaXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBkYXRhW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGlcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgICAgICB9LFxuIHBvaW50IChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVJbnZpc2libGUgPSBvcHRpb25zLmluY2x1ZGVJbnZpc2libGUgfHwgZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZ2V0SW50ZXJzZWN0SXRlbXMoY2hhcnQsIHBvc2l0aW9uLCBheGlzLCB1c2VGaW5hbFBvc2l0aW9uLCBpbmNsdWRlSW52aXNpYmxlKTtcbiAgICAgICAgfSxcbiBuZWFyZXN0IChjaGFydCwgZSwgb3B0aW9ucywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBnZXRSZWxhdGl2ZVBvc2l0aW9uKGUsIGNoYXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IGF4aXMgPSBvcHRpb25zLmF4aXMgfHwgJ3h5JztcbiAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVJbnZpc2libGUgPSBvcHRpb25zLmluY2x1ZGVJbnZpc2libGUgfHwgZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZ2V0TmVhcmVzdEl0ZW1zKGNoYXJ0LCBwb3NpdGlvbiwgYXhpcywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24sIGluY2x1ZGVJbnZpc2libGUpO1xuICAgICAgICB9LFxuIHggKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgcmV0dXJuIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sICd4Jywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICB9LFxuIHkgKGNoYXJ0LCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGdldFJlbGF0aXZlUG9zaXRpb24oZSwgY2hhcnQpO1xuICAgICAgICAgICAgcmV0dXJuIGdldEF4aXNJdGVtcyhjaGFydCwgcG9zaXRpb24sICd5Jywgb3B0aW9ucy5pbnRlcnNlY3QsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuY29uc3QgU1RBVElDX1BPU0lUSU9OUyA9IFtcbiAgICAnbGVmdCcsXG4gICAgJ3RvcCcsXG4gICAgJ3JpZ2h0JyxcbiAgICAnYm90dG9tJ1xuXTtcbmZ1bmN0aW9uIGZpbHRlckJ5UG9zaXRpb24oYXJyYXksIHBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGFycmF5LmZpbHRlcigodik9PnYucG9zID09PSBwb3NpdGlvbik7XG59XG5mdW5jdGlvbiBmaWx0ZXJEeW5hbWljUG9zaXRpb25CeUF4aXMoYXJyYXksIGF4aXMpIHtcbiAgICByZXR1cm4gYXJyYXkuZmlsdGVyKCh2KT0+U1RBVElDX1BPU0lUSU9OUy5pbmRleE9mKHYucG9zKSA9PT0gLTEgJiYgdi5ib3guYXhpcyA9PT0gYXhpcyk7XG59XG5mdW5jdGlvbiBzb3J0QnlXZWlnaHQoYXJyYXksIHJldmVyc2UpIHtcbiAgICByZXR1cm4gYXJyYXkuc29ydCgoYSwgYik9PntcbiAgICAgICAgY29uc3QgdjAgPSByZXZlcnNlID8gYiA6IGE7XG4gICAgICAgIGNvbnN0IHYxID0gcmV2ZXJzZSA/IGEgOiBiO1xuICAgICAgICByZXR1cm4gdjAud2VpZ2h0ID09PSB2MS53ZWlnaHQgPyB2MC5pbmRleCAtIHYxLmluZGV4IDogdjAud2VpZ2h0IC0gdjEud2VpZ2h0O1xuICAgIH0pO1xufVxuZnVuY3Rpb24gd3JhcEJveGVzKGJveGVzKSB7XG4gICAgY29uc3QgbGF5b3V0Qm94ZXMgPSBbXTtcbiAgICBsZXQgaSwgaWxlbiwgYm94LCBwb3MsIHN0YWNrLCBzdGFja1dlaWdodDtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSAoYm94ZXMgfHwgW10pLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGJveCA9IGJveGVzW2ldO1xuICAgICAgICAoeyBwb3NpdGlvbjogcG9zICwgb3B0aW9uczogeyBzdGFjayAsIHN0YWNrV2VpZ2h0ID0xICB9ICB9ID0gYm94KTtcbiAgICAgICAgbGF5b3V0Qm94ZXMucHVzaCh7XG4gICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgIGJveCxcbiAgICAgICAgICAgIHBvcyxcbiAgICAgICAgICAgIGhvcml6b250YWw6IGJveC5pc0hvcml6b250YWwoKSxcbiAgICAgICAgICAgIHdlaWdodDogYm94LndlaWdodCxcbiAgICAgICAgICAgIHN0YWNrOiBzdGFjayAmJiBwb3MgKyBzdGFjayxcbiAgICAgICAgICAgIHN0YWNrV2VpZ2h0XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gbGF5b3V0Qm94ZXM7XG59XG5mdW5jdGlvbiBidWlsZFN0YWNrcyhsYXlvdXRzKSB7XG4gICAgY29uc3Qgc3RhY2tzID0ge307XG4gICAgZm9yIChjb25zdCB3cmFwIG9mIGxheW91dHMpe1xuICAgICAgICBjb25zdCB7IHN0YWNrICwgcG9zICwgc3RhY2tXZWlnaHQgIH0gPSB3cmFwO1xuICAgICAgICBpZiAoIXN0YWNrIHx8ICFTVEFUSUNfUE9TSVRJT05TLmluY2x1ZGVzKHBvcykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IF9zdGFjayA9IHN0YWNrc1tzdGFja10gfHwgKHN0YWNrc1tzdGFja10gPSB7XG4gICAgICAgICAgICBjb3VudDogMCxcbiAgICAgICAgICAgIHBsYWNlZDogMCxcbiAgICAgICAgICAgIHdlaWdodDogMCxcbiAgICAgICAgICAgIHNpemU6IDBcbiAgICAgICAgfSk7XG4gICAgICAgIF9zdGFjay5jb3VudCsrO1xuICAgICAgICBfc3RhY2sud2VpZ2h0ICs9IHN0YWNrV2VpZ2h0O1xuICAgIH1cbiAgICByZXR1cm4gc3RhY2tzO1xufVxuIGZ1bmN0aW9uIHNldExheW91dERpbXMobGF5b3V0cywgcGFyYW1zKSB7XG4gICAgY29uc3Qgc3RhY2tzID0gYnVpbGRTdGFja3MobGF5b3V0cyk7XG4gICAgY29uc3QgeyB2Qm94TWF4V2lkdGggLCBoQm94TWF4SGVpZ2h0ICB9ID0gcGFyYW1zO1xuICAgIGxldCBpLCBpbGVuLCBsYXlvdXQ7XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gbGF5b3V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBsYXlvdXQgPSBsYXlvdXRzW2ldO1xuICAgICAgICBjb25zdCB7IGZ1bGxTaXplICB9ID0gbGF5b3V0LmJveDtcbiAgICAgICAgY29uc3Qgc3RhY2sgPSBzdGFja3NbbGF5b3V0LnN0YWNrXTtcbiAgICAgICAgY29uc3QgZmFjdG9yID0gc3RhY2sgJiYgbGF5b3V0LnN0YWNrV2VpZ2h0IC8gc3RhY2sud2VpZ2h0O1xuICAgICAgICBpZiAobGF5b3V0Lmhvcml6b250YWwpIHtcbiAgICAgICAgICAgIGxheW91dC53aWR0aCA9IGZhY3RvciA/IGZhY3RvciAqIHZCb3hNYXhXaWR0aCA6IGZ1bGxTaXplICYmIHBhcmFtcy5hdmFpbGFibGVXaWR0aDtcbiAgICAgICAgICAgIGxheW91dC5oZWlnaHQgPSBoQm94TWF4SGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGF5b3V0LndpZHRoID0gdkJveE1heFdpZHRoO1xuICAgICAgICAgICAgbGF5b3V0LmhlaWdodCA9IGZhY3RvciA/IGZhY3RvciAqIGhCb3hNYXhIZWlnaHQgOiBmdWxsU2l6ZSAmJiBwYXJhbXMuYXZhaWxhYmxlSGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzdGFja3M7XG59XG5mdW5jdGlvbiBidWlsZExheW91dEJveGVzKGJveGVzKSB7XG4gICAgY29uc3QgbGF5b3V0Qm94ZXMgPSB3cmFwQm94ZXMoYm94ZXMpO1xuICAgIGNvbnN0IGZ1bGxTaXplID0gc29ydEJ5V2VpZ2h0KGxheW91dEJveGVzLmZpbHRlcigod3JhcCk9PndyYXAuYm94LmZ1bGxTaXplKSwgdHJ1ZSk7XG4gICAgY29uc3QgbGVmdCA9IHNvcnRCeVdlaWdodChmaWx0ZXJCeVBvc2l0aW9uKGxheW91dEJveGVzLCAnbGVmdCcpLCB0cnVlKTtcbiAgICBjb25zdCByaWdodCA9IHNvcnRCeVdlaWdodChmaWx0ZXJCeVBvc2l0aW9uKGxheW91dEJveGVzLCAncmlnaHQnKSk7XG4gICAgY29uc3QgdG9wID0gc29ydEJ5V2VpZ2h0KGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICd0b3AnKSwgdHJ1ZSk7XG4gICAgY29uc3QgYm90dG9tID0gc29ydEJ5V2VpZ2h0KGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICdib3R0b20nKSk7XG4gICAgY29uc3QgY2VudGVySG9yaXpvbnRhbCA9IGZpbHRlckR5bmFtaWNQb3NpdGlvbkJ5QXhpcyhsYXlvdXRCb3hlcywgJ3gnKTtcbiAgICBjb25zdCBjZW50ZXJWZXJ0aWNhbCA9IGZpbHRlckR5bmFtaWNQb3NpdGlvbkJ5QXhpcyhsYXlvdXRCb3hlcywgJ3knKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBmdWxsU2l6ZSxcbiAgICAgICAgbGVmdEFuZFRvcDogbGVmdC5jb25jYXQodG9wKSxcbiAgICAgICAgcmlnaHRBbmRCb3R0b206IHJpZ2h0LmNvbmNhdChjZW50ZXJWZXJ0aWNhbCkuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpLFxuICAgICAgICBjaGFydEFyZWE6IGZpbHRlckJ5UG9zaXRpb24obGF5b3V0Qm94ZXMsICdjaGFydEFyZWEnKSxcbiAgICAgICAgdmVydGljYWw6IGxlZnQuY29uY2F0KHJpZ2h0KS5jb25jYXQoY2VudGVyVmVydGljYWwpLFxuICAgICAgICBob3Jpem9udGFsOiB0b3AuY29uY2F0KGJvdHRvbSkuY29uY2F0KGNlbnRlckhvcml6b250YWwpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldENvbWJpbmVkTWF4KG1heFBhZGRpbmcsIGNoYXJ0QXJlYSwgYSwgYikge1xuICAgIHJldHVybiBNYXRoLm1heChtYXhQYWRkaW5nW2FdLCBjaGFydEFyZWFbYV0pICsgTWF0aC5tYXgobWF4UGFkZGluZ1tiXSwgY2hhcnRBcmVhW2JdKTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZU1heFBhZGRpbmcobWF4UGFkZGluZywgYm94UGFkZGluZykge1xuICAgIG1heFBhZGRpbmcudG9wID0gTWF0aC5tYXgobWF4UGFkZGluZy50b3AsIGJveFBhZGRpbmcudG9wKTtcbiAgICBtYXhQYWRkaW5nLmxlZnQgPSBNYXRoLm1heChtYXhQYWRkaW5nLmxlZnQsIGJveFBhZGRpbmcubGVmdCk7XG4gICAgbWF4UGFkZGluZy5ib3R0b20gPSBNYXRoLm1heChtYXhQYWRkaW5nLmJvdHRvbSwgYm94UGFkZGluZy5ib3R0b20pO1xuICAgIG1heFBhZGRpbmcucmlnaHQgPSBNYXRoLm1heChtYXhQYWRkaW5nLnJpZ2h0LCBib3hQYWRkaW5nLnJpZ2h0KTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZURpbXMoY2hhcnRBcmVhLCBwYXJhbXMsIGxheW91dCwgc3RhY2tzKSB7XG4gICAgY29uc3QgeyBwb3MgLCBib3ggIH0gPSBsYXlvdXQ7XG4gICAgY29uc3QgbWF4UGFkZGluZyA9IGNoYXJ0QXJlYS5tYXhQYWRkaW5nO1xuICAgIGlmICghaXNPYmplY3QocG9zKSkge1xuICAgICAgICBpZiAobGF5b3V0LnNpemUpIHtcbiAgICAgICAgICAgIGNoYXJ0QXJlYVtwb3NdIC09IGxheW91dC5zaXplO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YWNrID0gc3RhY2tzW2xheW91dC5zdGFja10gfHwge1xuICAgICAgICAgICAgc2l6ZTogMCxcbiAgICAgICAgICAgIGNvdW50OiAxXG4gICAgICAgIH07XG4gICAgICAgIHN0YWNrLnNpemUgPSBNYXRoLm1heChzdGFjay5zaXplLCBsYXlvdXQuaG9yaXpvbnRhbCA/IGJveC5oZWlnaHQgOiBib3gud2lkdGgpO1xuICAgICAgICBsYXlvdXQuc2l6ZSA9IHN0YWNrLnNpemUgLyBzdGFjay5jb3VudDtcbiAgICAgICAgY2hhcnRBcmVhW3Bvc10gKz0gbGF5b3V0LnNpemU7XG4gICAgfVxuICAgIGlmIChib3guZ2V0UGFkZGluZykge1xuICAgICAgICB1cGRhdGVNYXhQYWRkaW5nKG1heFBhZGRpbmcsIGJveC5nZXRQYWRkaW5nKCkpO1xuICAgIH1cbiAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGgubWF4KDAsIHBhcmFtcy5vdXRlcldpZHRoIC0gZ2V0Q29tYmluZWRNYXgobWF4UGFkZGluZywgY2hhcnRBcmVhLCAnbGVmdCcsICdyaWdodCcpKTtcbiAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLm1heCgwLCBwYXJhbXMub3V0ZXJIZWlnaHQgLSBnZXRDb21iaW5lZE1heChtYXhQYWRkaW5nLCBjaGFydEFyZWEsICd0b3AnLCAnYm90dG9tJykpO1xuICAgIGNvbnN0IHdpZHRoQ2hhbmdlZCA9IG5ld1dpZHRoICE9PSBjaGFydEFyZWEudztcbiAgICBjb25zdCBoZWlnaHRDaGFuZ2VkID0gbmV3SGVpZ2h0ICE9PSBjaGFydEFyZWEuaDtcbiAgICBjaGFydEFyZWEudyA9IG5ld1dpZHRoO1xuICAgIGNoYXJ0QXJlYS5oID0gbmV3SGVpZ2h0O1xuICAgIHJldHVybiBsYXlvdXQuaG9yaXpvbnRhbCA/IHtcbiAgICAgICAgc2FtZTogd2lkdGhDaGFuZ2VkLFxuICAgICAgICBvdGhlcjogaGVpZ2h0Q2hhbmdlZFxuICAgIH0gOiB7XG4gICAgICAgIHNhbWU6IGhlaWdodENoYW5nZWQsXG4gICAgICAgIG90aGVyOiB3aWR0aENoYW5nZWRcbiAgICB9O1xufVxuZnVuY3Rpb24gaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpIHtcbiAgICBjb25zdCBtYXhQYWRkaW5nID0gY2hhcnRBcmVhLm1heFBhZGRpbmc7XG4gICAgZnVuY3Rpb24gdXBkYXRlUG9zKHBvcykge1xuICAgICAgICBjb25zdCBjaGFuZ2UgPSBNYXRoLm1heChtYXhQYWRkaW5nW3Bvc10gLSBjaGFydEFyZWFbcG9zXSwgMCk7XG4gICAgICAgIGNoYXJ0QXJlYVtwb3NdICs9IGNoYW5nZTtcbiAgICAgICAgcmV0dXJuIGNoYW5nZTtcbiAgICB9XG4gICAgY2hhcnRBcmVhLnkgKz0gdXBkYXRlUG9zKCd0b3AnKTtcbiAgICBjaGFydEFyZWEueCArPSB1cGRhdGVQb3MoJ2xlZnQnKTtcbiAgICB1cGRhdGVQb3MoJ3JpZ2h0Jyk7XG4gICAgdXBkYXRlUG9zKCdib3R0b20nKTtcbn1cbmZ1bmN0aW9uIGdldE1hcmdpbnMoaG9yaXpvbnRhbCwgY2hhcnRBcmVhKSB7XG4gICAgY29uc3QgbWF4UGFkZGluZyA9IGNoYXJ0QXJlYS5tYXhQYWRkaW5nO1xuICAgIGZ1bmN0aW9uIG1hcmdpbkZvclBvc2l0aW9ucyhwb3NpdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWFyZ2luID0ge1xuICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICAgICAgYm90dG9tOiAwXG4gICAgICAgIH07XG4gICAgICAgIHBvc2l0aW9ucy5mb3JFYWNoKChwb3MpPT57XG4gICAgICAgICAgICBtYXJnaW5bcG9zXSA9IE1hdGgubWF4KGNoYXJ0QXJlYVtwb3NdLCBtYXhQYWRkaW5nW3Bvc10pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1hcmdpbjtcbiAgICB9XG4gICAgcmV0dXJuIGhvcml6b250YWwgPyBtYXJnaW5Gb3JQb3NpdGlvbnMoW1xuICAgICAgICAnbGVmdCcsXG4gICAgICAgICdyaWdodCdcbiAgICBdKSA6IG1hcmdpbkZvclBvc2l0aW9ucyhbXG4gICAgICAgICd0b3AnLFxuICAgICAgICAnYm90dG9tJ1xuICAgIF0pO1xufVxuZnVuY3Rpb24gZml0Qm94ZXMoYm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpIHtcbiAgICBjb25zdCByZWZpdEJveGVzID0gW107XG4gICAgbGV0IGksIGlsZW4sIGxheW91dCwgYm94LCByZWZpdCwgY2hhbmdlZDtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBib3hlcy5sZW5ndGgsIHJlZml0ID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGxheW91dCA9IGJveGVzW2ldO1xuICAgICAgICBib3ggPSBsYXlvdXQuYm94O1xuICAgICAgICBib3gudXBkYXRlKGxheW91dC53aWR0aCB8fCBjaGFydEFyZWEudywgbGF5b3V0LmhlaWdodCB8fCBjaGFydEFyZWEuaCwgZ2V0TWFyZ2lucyhsYXlvdXQuaG9yaXpvbnRhbCwgY2hhcnRBcmVhKSk7XG4gICAgICAgIGNvbnN0IHsgc2FtZSAsIG90aGVyICB9ID0gdXBkYXRlRGltcyhjaGFydEFyZWEsIHBhcmFtcywgbGF5b3V0LCBzdGFja3MpO1xuICAgICAgICByZWZpdCB8PSBzYW1lICYmIHJlZml0Qm94ZXMubGVuZ3RoO1xuICAgICAgICBjaGFuZ2VkID0gY2hhbmdlZCB8fCBvdGhlcjtcbiAgICAgICAgaWYgKCFib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgIHJlZml0Qm94ZXMucHVzaChsYXlvdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWZpdCAmJiBmaXRCb3hlcyhyZWZpdEJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSB8fCBjaGFuZ2VkO1xufVxuZnVuY3Rpb24gc2V0Qm94RGltcyhib3gsIGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCkge1xuICAgIGJveC50b3AgPSB0b3A7XG4gICAgYm94LmxlZnQgPSBsZWZ0O1xuICAgIGJveC5yaWdodCA9IGxlZnQgKyB3aWR0aDtcbiAgICBib3guYm90dG9tID0gdG9wICsgaGVpZ2h0O1xuICAgIGJveC53aWR0aCA9IHdpZHRoO1xuICAgIGJveC5oZWlnaHQgPSBoZWlnaHQ7XG59XG5mdW5jdGlvbiBwbGFjZUJveGVzKGJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSB7XG4gICAgY29uc3QgdXNlclBhZGRpbmcgPSBwYXJhbXMucGFkZGluZztcbiAgICBsZXQgeyB4ICwgeSAgfSA9IGNoYXJ0QXJlYTtcbiAgICBmb3IgKGNvbnN0IGxheW91dCBvZiBib3hlcyl7XG4gICAgICAgIGNvbnN0IGJveCA9IGxheW91dC5ib3g7XG4gICAgICAgIGNvbnN0IHN0YWNrID0gc3RhY2tzW2xheW91dC5zdGFja10gfHwge1xuICAgICAgICAgICAgY291bnQ6IDEsXG4gICAgICAgICAgICBwbGFjZWQ6IDAsXG4gICAgICAgICAgICB3ZWlnaHQ6IDFcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd2VpZ2h0ID0gbGF5b3V0LnN0YWNrV2VpZ2h0IC8gc3RhY2sud2VpZ2h0IHx8IDE7XG4gICAgICAgIGlmIChsYXlvdXQuaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBjaGFydEFyZWEudyAqIHdlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHN0YWNrLnNpemUgfHwgYm94LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChkZWZpbmVkKHN0YWNrLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHkgPSBzdGFjay5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgICAgICBzZXRCb3hEaW1zKGJveCwgdXNlclBhZGRpbmcubGVmdCwgeSwgcGFyYW1zLm91dGVyV2lkdGggLSB1c2VyUGFkZGluZy5yaWdodCAtIHVzZXJQYWRkaW5nLmxlZnQsIGhlaWdodCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldEJveERpbXMoYm94LCBjaGFydEFyZWEubGVmdCArIHN0YWNrLnBsYWNlZCwgeSwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGFjay5zdGFydCA9IHk7XG4gICAgICAgICAgICBzdGFjay5wbGFjZWQgKz0gd2lkdGg7XG4gICAgICAgICAgICB5ID0gYm94LmJvdHRvbTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGNoYXJ0QXJlYS5oICogd2VpZ2h0O1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBzdGFjay5zaXplIHx8IGJveC53aWR0aDtcbiAgICAgICAgICAgIGlmIChkZWZpbmVkKHN0YWNrLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHggPSBzdGFjay5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChib3guZnVsbFNpemUpIHtcbiAgICAgICAgICAgICAgICBzZXRCb3hEaW1zKGJveCwgeCwgdXNlclBhZGRpbmcudG9wLCB3aWR0aCwgcGFyYW1zLm91dGVySGVpZ2h0IC0gdXNlclBhZGRpbmcuYm90dG9tIC0gdXNlclBhZGRpbmcudG9wKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0Qm94RGltcyhib3gsIHgsIGNoYXJ0QXJlYS50b3AgKyBzdGFjay5wbGFjZWQsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RhY2suc3RhcnQgPSB4O1xuICAgICAgICAgICAgc3RhY2sucGxhY2VkICs9IGhlaWdodDtcbiAgICAgICAgICAgIHggPSBib3gucmlnaHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2hhcnRBcmVhLnggPSB4O1xuICAgIGNoYXJ0QXJlYS55ID0geTtcbn1cbnZhciBsYXlvdXRzID0ge1xuIGFkZEJveCAoY2hhcnQsIGl0ZW0pIHtcbiAgICAgICAgaWYgKCFjaGFydC5ib3hlcykge1xuICAgICAgICAgICAgY2hhcnQuYm94ZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpdGVtLmZ1bGxTaXplID0gaXRlbS5mdWxsU2l6ZSB8fCBmYWxzZTtcbiAgICAgICAgaXRlbS5wb3NpdGlvbiA9IGl0ZW0ucG9zaXRpb24gfHwgJ3RvcCc7XG4gICAgICAgIGl0ZW0ud2VpZ2h0ID0gaXRlbS53ZWlnaHQgfHwgMDtcbiAgICAgICAgaXRlbS5fbGF5ZXJzID0gaXRlbS5fbGF5ZXJzIHx8IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHo6IDAsXG4gICAgICAgICAgICAgICAgICAgIGRyYXcgKGNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5kcmF3KGNoYXJ0QXJlYSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdO1xuICAgICAgICB9O1xuICAgICAgICBjaGFydC5ib3hlcy5wdXNoKGl0ZW0pO1xuICAgIH0sXG4gcmVtb3ZlQm94IChjaGFydCwgbGF5b3V0SXRlbSkge1xuICAgICAgICBjb25zdCBpbmRleCA9IGNoYXJ0LmJveGVzID8gY2hhcnQuYm94ZXMuaW5kZXhPZihsYXlvdXRJdGVtKSA6IC0xO1xuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBjaGFydC5ib3hlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgfSxcbiBjb25maWd1cmUgKGNoYXJ0LCBpdGVtLCBvcHRpb25zKSB7XG4gICAgICAgIGl0ZW0uZnVsbFNpemUgPSBvcHRpb25zLmZ1bGxTaXplO1xuICAgICAgICBpdGVtLnBvc2l0aW9uID0gb3B0aW9ucy5wb3NpdGlvbjtcbiAgICAgICAgaXRlbS53ZWlnaHQgPSBvcHRpb25zLndlaWdodDtcbiAgICB9LFxuIHVwZGF0ZSAoY2hhcnQsIHdpZHRoLCBoZWlnaHQsIG1pblBhZGRpbmcpIHtcbiAgICAgICAgaWYgKCFjaGFydCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSB0b1BhZGRpbmcoY2hhcnQub3B0aW9ucy5sYXlvdXQucGFkZGluZyk7XG4gICAgICAgIGNvbnN0IGF2YWlsYWJsZVdpZHRoID0gTWF0aC5tYXgod2lkdGggLSBwYWRkaW5nLndpZHRoLCAwKTtcbiAgICAgICAgY29uc3QgYXZhaWxhYmxlSGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0IC0gcGFkZGluZy5oZWlnaHQsIDApO1xuICAgICAgICBjb25zdCBib3hlcyA9IGJ1aWxkTGF5b3V0Qm94ZXMoY2hhcnQuYm94ZXMpO1xuICAgICAgICBjb25zdCB2ZXJ0aWNhbEJveGVzID0gYm94ZXMudmVydGljYWw7XG4gICAgICAgIGNvbnN0IGhvcml6b250YWxCb3hlcyA9IGJveGVzLmhvcml6b250YWw7XG4gICAgICAgIGVhY2goY2hhcnQuYm94ZXMsIChib3gpPT57XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJveC5iZWZvcmVMYXlvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBib3guYmVmb3JlTGF5b3V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB2aXNpYmxlVmVydGljYWxCb3hDb3VudCA9IHZlcnRpY2FsQm94ZXMucmVkdWNlKCh0b3RhbCwgd3JhcCk9PndyYXAuYm94Lm9wdGlvbnMgJiYgd3JhcC5ib3gub3B0aW9ucy5kaXNwbGF5ID09PSBmYWxzZSA/IHRvdGFsIDogdG90YWwgKyAxLCAwKSB8fCAxO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgICAgIG91dGVyV2lkdGg6IHdpZHRoLFxuICAgICAgICAgICAgb3V0ZXJIZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHBhZGRpbmcsXG4gICAgICAgICAgICBhdmFpbGFibGVXaWR0aCxcbiAgICAgICAgICAgIGF2YWlsYWJsZUhlaWdodCxcbiAgICAgICAgICAgIHZCb3hNYXhXaWR0aDogYXZhaWxhYmxlV2lkdGggLyAyIC8gdmlzaWJsZVZlcnRpY2FsQm94Q291bnQsXG4gICAgICAgICAgICBoQm94TWF4SGVpZ2h0OiBhdmFpbGFibGVIZWlnaHQgLyAyXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBtYXhQYWRkaW5nID0gT2JqZWN0LmFzc2lnbih7fSwgcGFkZGluZyk7XG4gICAgICAgIHVwZGF0ZU1heFBhZGRpbmcobWF4UGFkZGluZywgdG9QYWRkaW5nKG1pblBhZGRpbmcpKTtcbiAgICAgICAgY29uc3QgY2hhcnRBcmVhID0gT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICBtYXhQYWRkaW5nLFxuICAgICAgICAgICAgdzogYXZhaWxhYmxlV2lkdGgsXG4gICAgICAgICAgICBoOiBhdmFpbGFibGVIZWlnaHQsXG4gICAgICAgICAgICB4OiBwYWRkaW5nLmxlZnQsXG4gICAgICAgICAgICB5OiBwYWRkaW5nLnRvcFxuICAgICAgICB9LCBwYWRkaW5nKTtcbiAgICAgICAgY29uc3Qgc3RhY2tzID0gc2V0TGF5b3V0RGltcyh2ZXJ0aWNhbEJveGVzLmNvbmNhdChob3Jpem9udGFsQm94ZXMpLCBwYXJhbXMpO1xuICAgICAgICBmaXRCb3hlcyhib3hlcy5mdWxsU2l6ZSwgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgICAgIGZpdEJveGVzKHZlcnRpY2FsQm94ZXMsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBpZiAoZml0Qm94ZXMoaG9yaXpvbnRhbEJveGVzLCBjaGFydEFyZWEsIHBhcmFtcywgc3RhY2tzKSkge1xuICAgICAgICAgICAgZml0Qm94ZXModmVydGljYWxCb3hlcywgY2hhcnRBcmVhLCBwYXJhbXMsIHN0YWNrcyk7XG4gICAgICAgIH1cbiAgICAgICAgaGFuZGxlTWF4UGFkZGluZyhjaGFydEFyZWEpO1xuICAgICAgICBwbGFjZUJveGVzKGJveGVzLmxlZnRBbmRUb3AsIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBjaGFydEFyZWEueCArPSBjaGFydEFyZWEudztcbiAgICAgICAgY2hhcnRBcmVhLnkgKz0gY2hhcnRBcmVhLmg7XG4gICAgICAgIHBsYWNlQm94ZXMoYm94ZXMucmlnaHRBbmRCb3R0b20sIGNoYXJ0QXJlYSwgcGFyYW1zLCBzdGFja3MpO1xuICAgICAgICBjaGFydC5jaGFydEFyZWEgPSB7XG4gICAgICAgICAgICBsZWZ0OiBjaGFydEFyZWEubGVmdCxcbiAgICAgICAgICAgIHRvcDogY2hhcnRBcmVhLnRvcCxcbiAgICAgICAgICAgIHJpZ2h0OiBjaGFydEFyZWEubGVmdCArIGNoYXJ0QXJlYS53LFxuICAgICAgICAgICAgYm90dG9tOiBjaGFydEFyZWEudG9wICsgY2hhcnRBcmVhLmgsXG4gICAgICAgICAgICBoZWlnaHQ6IGNoYXJ0QXJlYS5oLFxuICAgICAgICAgICAgd2lkdGg6IGNoYXJ0QXJlYS53XG4gICAgICAgIH07XG4gICAgICAgIGVhY2goYm94ZXMuY2hhcnRBcmVhLCAobGF5b3V0KT0+e1xuICAgICAgICAgICAgY29uc3QgYm94ID0gbGF5b3V0LmJveDtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oYm94LCBjaGFydC5jaGFydEFyZWEpO1xuICAgICAgICAgICAgYm94LnVwZGF0ZShjaGFydEFyZWEudywgY2hhcnRBcmVhLmgsIHtcbiAgICAgICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgICAgICBib3R0b206IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5jbGFzcyBCYXNlUGxhdGZvcm0ge1xuIGFjcXVpcmVDb250ZXh0KGNhbnZhcywgYXNwZWN0UmF0aW8pIHt9XG4gcmVsZWFzZUNvbnRleHQoY29udGV4dCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuIGFkZEV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7fVxuIHJlbW92ZUV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7fVxuIGdldERldmljZVBpeGVsUmF0aW8oKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiBnZXRNYXhpbXVtU2l6ZShlbGVtZW50LCB3aWR0aCwgaGVpZ2h0LCBhc3BlY3RSYXRpbykge1xuICAgICAgICB3aWR0aCA9IE1hdGgubWF4KDAsIHdpZHRoIHx8IGVsZW1lbnQud2lkdGgpO1xuICAgICAgICBoZWlnaHQgPSBoZWlnaHQgfHwgZWxlbWVudC5oZWlnaHQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoMCwgYXNwZWN0UmF0aW8gPyBNYXRoLmZsb29yKHdpZHRoIC8gYXNwZWN0UmF0aW8pIDogaGVpZ2h0KVxuICAgICAgICB9O1xuICAgIH1cbiBpc0F0dGFjaGVkKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gdXBkYXRlQ29uZmlnKGNvbmZpZykge1xuICAgIH1cbn1cblxuY2xhc3MgQmFzaWNQbGF0Zm9ybSBleHRlbmRzIEJhc2VQbGF0Zm9ybSB7XG4gICAgYWNxdWlyZUNvbnRleHQoaXRlbSkge1xuICAgICAgICByZXR1cm4gaXRlbSAmJiBpdGVtLmdldENvbnRleHQgJiYgaXRlbS5nZXRDb250ZXh0KCcyZCcpIHx8IG51bGw7XG4gICAgfVxuICAgIHVwZGF0ZUNvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnLm9wdGlvbnMuYW5pbWF0aW9uID0gZmFsc2U7XG4gICAgfVxufVxuXG5jb25zdCBFWFBBTkRPX0tFWSA9ICckY2hhcnRqcyc7XG4gY29uc3QgRVZFTlRfVFlQRVMgPSB7XG4gICAgdG91Y2hzdGFydDogJ21vdXNlZG93bicsXG4gICAgdG91Y2htb3ZlOiAnbW91c2Vtb3ZlJyxcbiAgICB0b3VjaGVuZDogJ21vdXNldXAnLFxuICAgIHBvaW50ZXJlbnRlcjogJ21vdXNlZW50ZXInLFxuICAgIHBvaW50ZXJkb3duOiAnbW91c2Vkb3duJyxcbiAgICBwb2ludGVybW92ZTogJ21vdXNlbW92ZScsXG4gICAgcG9pbnRlcnVwOiAnbW91c2V1cCcsXG4gICAgcG9pbnRlcmxlYXZlOiAnbW91c2VvdXQnLFxuICAgIHBvaW50ZXJvdXQ6ICdtb3VzZW91dCdcbn07XG5jb25zdCBpc051bGxPckVtcHR5ID0gKHZhbHVlKT0+dmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnO1xuIGZ1bmN0aW9uIGluaXRDYW52YXMoY2FudmFzLCBhc3BlY3RSYXRpbykge1xuICAgIGNvbnN0IHN0eWxlID0gY2FudmFzLnN0eWxlO1xuICAgIGNvbnN0IHJlbmRlckhlaWdodCA9IGNhbnZhcy5nZXRBdHRyaWJ1dGUoJ2hlaWdodCcpO1xuICAgIGNvbnN0IHJlbmRlcldpZHRoID0gY2FudmFzLmdldEF0dHJpYnV0ZSgnd2lkdGgnKTtcbiAgICBjYW52YXNbRVhQQU5ET19LRVldID0ge1xuICAgICAgICBpbml0aWFsOiB7XG4gICAgICAgICAgICBoZWlnaHQ6IHJlbmRlckhlaWdodCxcbiAgICAgICAgICAgIHdpZHRoOiByZW5kZXJXaWR0aCxcbiAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgZGlzcGxheTogc3R5bGUuZGlzcGxheSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHN0eWxlLmhlaWdodCxcbiAgICAgICAgICAgICAgICB3aWR0aDogc3R5bGUud2lkdGhcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgc3R5bGUuZGlzcGxheSA9IHN0eWxlLmRpc3BsYXkgfHwgJ2Jsb2NrJztcbiAgICBzdHlsZS5ib3hTaXppbmcgPSBzdHlsZS5ib3hTaXppbmcgfHwgJ2JvcmRlci1ib3gnO1xuICAgIGlmIChpc051bGxPckVtcHR5KHJlbmRlcldpZHRoKSkge1xuICAgICAgICBjb25zdCBkaXNwbGF5V2lkdGggPSByZWFkVXNlZFNpemUoY2FudmFzLCAnd2lkdGgnKTtcbiAgICAgICAgaWYgKGRpc3BsYXlXaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjYW52YXMud2lkdGggPSBkaXNwbGF5V2lkdGg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzTnVsbE9yRW1wdHkocmVuZGVySGVpZ2h0KSkge1xuICAgICAgICBpZiAoY2FudmFzLnN0eWxlLmhlaWdodCA9PT0gJycpIHtcbiAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBjYW52YXMud2lkdGggLyAoYXNwZWN0UmF0aW8gfHwgMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBkaXNwbGF5SGVpZ2h0ID0gcmVhZFVzZWRTaXplKGNhbnZhcywgJ2hlaWdodCcpO1xuICAgICAgICAgICAgaWYgKGRpc3BsYXlIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBkaXNwbGF5SGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjYW52YXM7XG59XG5jb25zdCBldmVudExpc3RlbmVyT3B0aW9ucyA9IHN1cHBvcnRzRXZlbnRMaXN0ZW5lck9wdGlvbnMgPyB7XG4gICAgcGFzc2l2ZTogdHJ1ZVxufSA6IGZhbHNlO1xuZnVuY3Rpb24gYWRkTGlzdGVuZXIobm9kZSwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBub2RlLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIGV2ZW50TGlzdGVuZXJPcHRpb25zKTtcbn1cbmZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICAgIGNoYXJ0LmNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBldmVudExpc3RlbmVyT3B0aW9ucyk7XG59XG5mdW5jdGlvbiBmcm9tTmF0aXZlRXZlbnQoZXZlbnQsIGNoYXJ0KSB7XG4gICAgY29uc3QgdHlwZSA9IEVWRU5UX1RZUEVTW2V2ZW50LnR5cGVdIHx8IGV2ZW50LnR5cGU7XG4gICAgY29uc3QgeyB4ICwgeSAgfSA9IGdldFJlbGF0aXZlUG9zaXRpb24oZXZlbnQsIGNoYXJ0KTtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlLFxuICAgICAgICBjaGFydCxcbiAgICAgICAgbmF0aXZlOiBldmVudCxcbiAgICAgICAgeDogeCAhPT0gdW5kZWZpbmVkID8geCA6IG51bGwsXG4gICAgICAgIHk6IHkgIT09IHVuZGVmaW5lZCA/IHkgOiBudWxsXG4gICAgfTtcbn1cbmZ1bmN0aW9uIG5vZGVMaXN0Q29udGFpbnMobm9kZUxpc3QsIGNhbnZhcykge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2RlTGlzdCl7XG4gICAgICAgIGlmIChub2RlID09PSBjYW52YXMgfHwgbm9kZS5jb250YWlucyhjYW52YXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIGNyZWF0ZUF0dGFjaE9ic2VydmVyKGNoYXJ0LCB0eXBlLCBsaXN0ZW5lcikge1xuICAgIGNvbnN0IGNhbnZhcyA9IGNoYXJ0LmNhbnZhcztcbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKChlbnRyaWVzKT0+e1xuICAgICAgICBsZXQgdHJpZ2dlciA9IGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpe1xuICAgICAgICAgICAgdHJpZ2dlciA9IHRyaWdnZXIgfHwgbm9kZUxpc3RDb250YWlucyhlbnRyeS5hZGRlZE5vZGVzLCBjYW52YXMpO1xuICAgICAgICAgICAgdHJpZ2dlciA9IHRyaWdnZXIgJiYgIW5vZGVMaXN0Q29udGFpbnMoZW50cnkucmVtb3ZlZE5vZGVzLCBjYW52YXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0cmlnZ2VyKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcigpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgb2JzZXJ2ZXIub2JzZXJ2ZShkb2N1bWVudCwge1xuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWVcbiAgICB9KTtcbiAgICByZXR1cm4gb2JzZXJ2ZXI7XG59XG5mdW5jdGlvbiBjcmVhdGVEZXRhY2hPYnNlcnZlcihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBjb25zdCBjYW52YXMgPSBjaGFydC5jYW52YXM7XG4gICAgY29uc3Qgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigoZW50cmllcyk9PntcbiAgICAgICAgbGV0IHRyaWdnZXIgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKXtcbiAgICAgICAgICAgIHRyaWdnZXIgPSB0cmlnZ2VyIHx8IG5vZGVMaXN0Q29udGFpbnMoZW50cnkucmVtb3ZlZE5vZGVzLCBjYW52YXMpO1xuICAgICAgICAgICAgdHJpZ2dlciA9IHRyaWdnZXIgJiYgIW5vZGVMaXN0Q29udGFpbnMoZW50cnkuYWRkZWROb2RlcywgY2FudmFzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHJpZ2dlcikge1xuICAgICAgICAgICAgbGlzdGVuZXIoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIG9ic2VydmVyLm9ic2VydmUoZG9jdW1lbnQsIHtcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIG9ic2VydmVyO1xufVxuY29uc3QgZHJwTGlzdGVuaW5nQ2hhcnRzID0gbmV3IE1hcCgpO1xubGV0IG9sZERldmljZVBpeGVsUmF0aW8gPSAwO1xuZnVuY3Rpb24gb25XaW5kb3dSZXNpemUoKSB7XG4gICAgY29uc3QgZHByID0gd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gICAgaWYgKGRwciA9PT0gb2xkRGV2aWNlUGl4ZWxSYXRpbykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9sZERldmljZVBpeGVsUmF0aW8gPSBkcHI7XG4gICAgZHJwTGlzdGVuaW5nQ2hhcnRzLmZvckVhY2goKHJlc2l6ZSwgY2hhcnQpPT57XG4gICAgICAgIGlmIChjaGFydC5jdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyAhPT0gZHByKSB7XG4gICAgICAgICAgICByZXNpemUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gbGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQsIHJlc2l6ZSkge1xuICAgIGlmICghZHJwTGlzdGVuaW5nQ2hhcnRzLnNpemUpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIG9uV2luZG93UmVzaXplKTtcbiAgICB9XG4gICAgZHJwTGlzdGVuaW5nQ2hhcnRzLnNldChjaGFydCwgcmVzaXplKTtcbn1cbmZ1bmN0aW9uIHVubGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQpIHtcbiAgICBkcnBMaXN0ZW5pbmdDaGFydHMuZGVsZXRlKGNoYXJ0KTtcbiAgICBpZiAoIWRycExpc3RlbmluZ0NoYXJ0cy5zaXplKSB7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCBvbldpbmRvd1Jlc2l6ZSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY3JlYXRlUmVzaXplT2JzZXJ2ZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgY29uc3QgY2FudmFzID0gY2hhcnQuY2FudmFzO1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IGNhbnZhcyAmJiBfZ2V0UGFyZW50Tm9kZShjYW52YXMpO1xuICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVzaXplID0gdGhyb3R0bGVkKCh3aWR0aCwgaGVpZ2h0KT0+e1xuICAgICAgICBjb25zdCB3ID0gY29udGFpbmVyLmNsaWVudFdpZHRoO1xuICAgICAgICBsaXN0ZW5lcih3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgaWYgKHcgPCBjb250YWluZXIuY2xpZW50V2lkdGgpIHtcbiAgICAgICAgICAgIGxpc3RlbmVyKCk7XG4gICAgICAgIH1cbiAgICB9LCB3aW5kb3cpO1xuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKChlbnRyaWVzKT0+e1xuICAgICAgICBjb25zdCBlbnRyeSA9IGVudHJpZXNbMF07XG4gICAgICAgIGNvbnN0IHdpZHRoID0gZW50cnkuY29udGVudFJlY3Qud2lkdGg7XG4gICAgICAgIGNvbnN0IGhlaWdodCA9IGVudHJ5LmNvbnRlbnRSZWN0LmhlaWdodDtcbiAgICAgICAgaWYgKHdpZHRoID09PSAwICYmIGhlaWdodCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJlc2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbiAgICB9KTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lcik7XG4gICAgbGlzdGVuRGV2aWNlUGl4ZWxSYXRpb0NoYW5nZXMoY2hhcnQsIHJlc2l6ZSk7XG4gICAgcmV0dXJuIG9ic2VydmVyO1xufVxuZnVuY3Rpb24gcmVsZWFzZU9ic2VydmVyKGNoYXJ0LCB0eXBlLCBvYnNlcnZlcikge1xuICAgIGlmIChvYnNlcnZlcikge1xuICAgICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgfVxuICAgIGlmICh0eXBlID09PSAncmVzaXplJykge1xuICAgICAgICB1bmxpc3RlbkRldmljZVBpeGVsUmF0aW9DaGFuZ2VzKGNoYXJ0KTtcbiAgICB9XG59XG5mdW5jdGlvbiBjcmVhdGVQcm94eUFuZExpc3RlbihjaGFydCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICBjb25zdCBjYW52YXMgPSBjaGFydC5jYW52YXM7XG4gICAgY29uc3QgcHJveHkgPSB0aHJvdHRsZWQoKGV2ZW50KT0+e1xuICAgICAgICBpZiAoY2hhcnQuY3R4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcihmcm9tTmF0aXZlRXZlbnQoZXZlbnQsIGNoYXJ0KSk7XG4gICAgICAgIH1cbiAgICB9LCBjaGFydCk7XG4gICAgYWRkTGlzdGVuZXIoY2FudmFzLCB0eXBlLCBwcm94eSk7XG4gICAgcmV0dXJuIHByb3h5O1xufVxuIGNsYXNzIERvbVBsYXRmb3JtIGV4dGVuZHMgQmFzZVBsYXRmb3JtIHtcbiBhY3F1aXJlQ29udGV4dChjYW52YXMsIGFzcGVjdFJhdGlvKSB7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBjYW52YXMgJiYgY2FudmFzLmdldENvbnRleHQgJiYgY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIGlmIChjb250ZXh0ICYmIGNvbnRleHQuY2FudmFzID09PSBjYW52YXMpIHtcbiAgICAgICAgICAgIGluaXRDYW52YXMoY2FudmFzLCBhc3BlY3RSYXRpbyk7XG4gICAgICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gcmVsZWFzZUNvbnRleHQoY29udGV4dCkge1xuICAgICAgICBjb25zdCBjYW52YXMgPSBjb250ZXh0LmNhbnZhcztcbiAgICAgICAgaWYgKCFjYW52YXNbRVhQQU5ET19LRVldKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaW5pdGlhbCA9IGNhbnZhc1tFWFBBTkRPX0tFWV0uaW5pdGlhbDtcbiAgICAgICAgW1xuICAgICAgICAgICAgJ2hlaWdodCcsXG4gICAgICAgICAgICAnd2lkdGgnXG4gICAgICAgIF0uZm9yRWFjaCgocHJvcCk9PntcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gaW5pdGlhbFtwcm9wXTtcbiAgICAgICAgICAgIGlmIChpc051bGxPclVuZGVmKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGNhbnZhcy5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbnZhcy5zZXRBdHRyaWJ1dGUocHJvcCwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBpbml0aWFsLnN0eWxlIHx8IHt9O1xuICAgICAgICBPYmplY3Qua2V5cyhzdHlsZSkuZm9yRWFjaCgoa2V5KT0+e1xuICAgICAgICAgICAgY2FudmFzLnN0eWxlW2tleV0gPSBzdHlsZVtrZXldO1xuICAgICAgICB9KTtcbiAgICAgICAgY2FudmFzLndpZHRoID0gY2FudmFzLndpZHRoO1xuICAgICAgICBkZWxldGUgY2FudmFzW0VYUEFORE9fS0VZXTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuIGFkZEV2ZW50TGlzdGVuZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihjaGFydCwgdHlwZSk7XG4gICAgICAgIGNvbnN0IHByb3hpZXMgPSBjaGFydC4kcHJveGllcyB8fCAoY2hhcnQuJHByb3hpZXMgPSB7fSk7XG4gICAgICAgIGNvbnN0IGhhbmRsZXJzID0ge1xuICAgICAgICAgICAgYXR0YWNoOiBjcmVhdGVBdHRhY2hPYnNlcnZlcixcbiAgICAgICAgICAgIGRldGFjaDogY3JlYXRlRGV0YWNoT2JzZXJ2ZXIsXG4gICAgICAgICAgICByZXNpemU6IGNyZWF0ZVJlc2l6ZU9ic2VydmVyXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSBoYW5kbGVyc1t0eXBlXSB8fCBjcmVhdGVQcm94eUFuZExpc3RlbjtcbiAgICAgICAgcHJveGllc1t0eXBlXSA9IGhhbmRsZXIoY2hhcnQsIHR5cGUsIGxpc3RlbmVyKTtcbiAgICB9XG4gcmVtb3ZlRXZlbnRMaXN0ZW5lcihjaGFydCwgdHlwZSkge1xuICAgICAgICBjb25zdCBwcm94aWVzID0gY2hhcnQuJHByb3hpZXMgfHwgKGNoYXJ0LiRwcm94aWVzID0ge30pO1xuICAgICAgICBjb25zdCBwcm94eSA9IHByb3hpZXNbdHlwZV07XG4gICAgICAgIGlmICghcHJveHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBoYW5kbGVycyA9IHtcbiAgICAgICAgICAgIGF0dGFjaDogcmVsZWFzZU9ic2VydmVyLFxuICAgICAgICAgICAgZGV0YWNoOiByZWxlYXNlT2JzZXJ2ZXIsXG4gICAgICAgICAgICByZXNpemU6IHJlbGVhc2VPYnNlcnZlclxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnNbdHlwZV0gfHwgcmVtb3ZlTGlzdGVuZXI7XG4gICAgICAgIGhhbmRsZXIoY2hhcnQsIHR5cGUsIHByb3h5KTtcbiAgICAgICAgcHJveGllc1t0eXBlXSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgZ2V0RGV2aWNlUGl4ZWxSYXRpbygpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvO1xuICAgIH1cbiBnZXRNYXhpbXVtU2l6ZShjYW52YXMsIHdpZHRoLCBoZWlnaHQsIGFzcGVjdFJhdGlvKSB7XG4gICAgICAgIHJldHVybiBnZXRNYXhpbXVtU2l6ZShjYW52YXMsIHdpZHRoLCBoZWlnaHQsIGFzcGVjdFJhdGlvKTtcbiAgICB9XG4gaXNBdHRhY2hlZChjYW52YXMpIHtcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gX2dldFBhcmVudE5vZGUoY2FudmFzKTtcbiAgICAgICAgcmV0dXJuICEhKGNvbnRhaW5lciAmJiBjb250YWluZXIuaXNDb25uZWN0ZWQpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gX2RldGVjdFBsYXRmb3JtKGNhbnZhcykge1xuICAgIGlmICghX2lzRG9tU3VwcG9ydGVkKCkgfHwgdHlwZW9mIE9mZnNjcmVlbkNhbnZhcyAhPT0gJ3VuZGVmaW5lZCcgJiYgY2FudmFzIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzKSB7XG4gICAgICAgIHJldHVybiBCYXNpY1BsYXRmb3JtO1xuICAgIH1cbiAgICByZXR1cm4gRG9tUGxhdGZvcm07XG59XG5cbmNsYXNzIEVsZW1lbnQge1xuICAgIHN0YXRpYyBkZWZhdWx0cyA9IHt9O1xuICAgIHN0YXRpYyBkZWZhdWx0Um91dGVzID0gdW5kZWZpbmVkO1xuICAgIHg7XG4gICAgeTtcbiAgICBhY3RpdmUgPSBmYWxzZTtcbiAgICBvcHRpb25zO1xuICAgICRhbmltYXRpb25zO1xuICAgIHRvb2x0aXBQb3NpdGlvbih1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHsgeCAsIHkgIH0gPSB0aGlzLmdldFByb3BzKFtcbiAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICd5J1xuICAgICAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5XG4gICAgICAgIH07XG4gICAgfVxuICAgIGhhc1ZhbHVlKCkge1xuICAgICAgICByZXR1cm4gaXNOdW1iZXIodGhpcy54KSAmJiBpc051bWJlcih0aGlzLnkpO1xuICAgIH1cbiAgICBnZXRQcm9wcyhwcm9wcywgZmluYWwpIHtcbiAgICAgICAgY29uc3QgYW5pbXMgPSB0aGlzLiRhbmltYXRpb25zO1xuICAgICAgICBpZiAoIWZpbmFsIHx8ICFhbmltcykge1xuICAgICAgICAgICAgLy8gbGV0J3Mgbm90IGNyZWF0ZSBhbiBvYmplY3QsIGlmIG5vdCBuZWVkZWRcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJldCA9IHt9O1xuICAgICAgICBwcm9wcy5mb3JFYWNoKChwcm9wKT0+e1xuICAgICAgICAgICAgcmV0W3Byb3BdID0gYW5pbXNbcHJvcF0gJiYgYW5pbXNbcHJvcF0uYWN0aXZlKCkgPyBhbmltc1twcm9wXS5fdG8gOiB0aGlzW3Byb3BdO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGF1dG9Ta2lwKHNjYWxlLCB0aWNrcykge1xuICAgIGNvbnN0IHRpY2tPcHRzID0gc2NhbGUub3B0aW9ucy50aWNrcztcbiAgICBjb25zdCBkZXRlcm1pbmVkTWF4VGlja3MgPSBkZXRlcm1pbmVNYXhUaWNrcyhzY2FsZSk7XG4gICAgY29uc3QgdGlja3NMaW1pdCA9IE1hdGgubWluKHRpY2tPcHRzLm1heFRpY2tzTGltaXQgfHwgZGV0ZXJtaW5lZE1heFRpY2tzLCBkZXRlcm1pbmVkTWF4VGlja3MpO1xuICAgIGNvbnN0IG1ham9ySW5kaWNlcyA9IHRpY2tPcHRzLm1ham9yLmVuYWJsZWQgPyBnZXRNYWpvckluZGljZXModGlja3MpIDogW107XG4gICAgY29uc3QgbnVtTWFqb3JJbmRpY2VzID0gbWFqb3JJbmRpY2VzLmxlbmd0aDtcbiAgICBjb25zdCBmaXJzdCA9IG1ham9ySW5kaWNlc1swXTtcbiAgICBjb25zdCBsYXN0ID0gbWFqb3JJbmRpY2VzW251bU1ham9ySW5kaWNlcyAtIDFdO1xuICAgIGNvbnN0IG5ld1RpY2tzID0gW107XG4gICAgaWYgKG51bU1ham9ySW5kaWNlcyA+IHRpY2tzTGltaXQpIHtcbiAgICAgICAgc2tpcE1ham9ycyh0aWNrcywgbmV3VGlja3MsIG1ham9ySW5kaWNlcywgbnVtTWFqb3JJbmRpY2VzIC8gdGlja3NMaW1pdCk7XG4gICAgICAgIHJldHVybiBuZXdUaWNrcztcbiAgICB9XG4gICAgY29uc3Qgc3BhY2luZyA9IGNhbGN1bGF0ZVNwYWNpbmcobWFqb3JJbmRpY2VzLCB0aWNrcywgdGlja3NMaW1pdCk7XG4gICAgaWYgKG51bU1ham9ySW5kaWNlcyA+IDApIHtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGNvbnN0IGF2Z01ham9yU3BhY2luZyA9IG51bU1ham9ySW5kaWNlcyA+IDEgPyBNYXRoLnJvdW5kKChsYXN0IC0gZmlyc3QpIC8gKG51bU1ham9ySW5kaWNlcyAtIDEpKSA6IG51bGw7XG4gICAgICAgIHNraXAodGlja3MsIG5ld1RpY2tzLCBzcGFjaW5nLCBpc051bGxPclVuZGVmKGF2Z01ham9yU3BhY2luZykgPyAwIDogZmlyc3QgLSBhdmdNYWpvclNwYWNpbmcsIGZpcnN0KTtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gbnVtTWFqb3JJbmRpY2VzIC0gMTsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgICAgICBza2lwKHRpY2tzLCBuZXdUaWNrcywgc3BhY2luZywgbWFqb3JJbmRpY2VzW2ldLCBtYWpvckluZGljZXNbaSArIDFdKTtcbiAgICAgICAgfVxuICAgICAgICBza2lwKHRpY2tzLCBuZXdUaWNrcywgc3BhY2luZywgbGFzdCwgaXNOdWxsT3JVbmRlZihhdmdNYWpvclNwYWNpbmcpID8gdGlja3MubGVuZ3RoIDogbGFzdCArIGF2Z01ham9yU3BhY2luZyk7XG4gICAgICAgIHJldHVybiBuZXdUaWNrcztcbiAgICB9XG4gICAgc2tpcCh0aWNrcywgbmV3VGlja3MsIHNwYWNpbmcpO1xuICAgIHJldHVybiBuZXdUaWNrcztcbn1cbmZ1bmN0aW9uIGRldGVybWluZU1heFRpY2tzKHNjYWxlKSB7XG4gICAgY29uc3Qgb2Zmc2V0ID0gc2NhbGUub3B0aW9ucy5vZmZzZXQ7XG4gICAgY29uc3QgdGlja0xlbmd0aCA9IHNjYWxlLl90aWNrU2l6ZSgpO1xuICAgIGNvbnN0IG1heFNjYWxlID0gc2NhbGUuX2xlbmd0aCAvIHRpY2tMZW5ndGggKyAob2Zmc2V0ID8gMCA6IDEpO1xuICAgIGNvbnN0IG1heENoYXJ0ID0gc2NhbGUuX21heExlbmd0aCAvIHRpY2tMZW5ndGg7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5taW4obWF4U2NhbGUsIG1heENoYXJ0KSk7XG59XG4gZnVuY3Rpb24gY2FsY3VsYXRlU3BhY2luZyhtYWpvckluZGljZXMsIHRpY2tzLCB0aWNrc0xpbWl0KSB7XG4gICAgY29uc3QgZXZlbk1ham9yU3BhY2luZyA9IGdldEV2ZW5TcGFjaW5nKG1ham9ySW5kaWNlcyk7XG4gICAgY29uc3Qgc3BhY2luZyA9IHRpY2tzLmxlbmd0aCAvIHRpY2tzTGltaXQ7XG4gICAgaWYgKCFldmVuTWFqb3JTcGFjaW5nKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChzcGFjaW5nLCAxKTtcbiAgICB9XG4gICAgY29uc3QgZmFjdG9ycyA9IF9mYWN0b3JpemUoZXZlbk1ham9yU3BhY2luZyk7XG4gICAgZm9yKGxldCBpID0gMCwgaWxlbiA9IGZhY3RvcnMubGVuZ3RoIC0gMTsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgIGNvbnN0IGZhY3RvciA9IGZhY3RvcnNbaV07XG4gICAgICAgIGlmIChmYWN0b3IgPiBzcGFjaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFjdG9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBNYXRoLm1heChzcGFjaW5nLCAxKTtcbn1cbiBmdW5jdGlvbiBnZXRNYWpvckluZGljZXModGlja3MpIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aWNrcy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICBpZiAodGlja3NbaV0ubWFqb3IpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG4gZnVuY3Rpb24gc2tpcE1ham9ycyh0aWNrcywgbmV3VGlja3MsIG1ham9ySW5kaWNlcywgc3BhY2luZykge1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgbGV0IG5leHQgPSBtYWpvckluZGljZXNbMF07XG4gICAgbGV0IGk7XG4gICAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nKTtcbiAgICBmb3IoaSA9IDA7IGkgPCB0aWNrcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGlmIChpID09PSBuZXh0KSB7XG4gICAgICAgICAgICBuZXdUaWNrcy5wdXNoKHRpY2tzW2ldKTtcbiAgICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgICAgICBuZXh0ID0gbWFqb3JJbmRpY2VzW2NvdW50ICogc3BhY2luZ107XG4gICAgICAgIH1cbiAgICB9XG59XG4gZnVuY3Rpb24gc2tpcCh0aWNrcywgbmV3VGlja3MsIHNwYWNpbmcsIG1ham9yU3RhcnQsIG1ham9yRW5kKSB7XG4gICAgY29uc3Qgc3RhcnQgPSB2YWx1ZU9yRGVmYXVsdChtYWpvclN0YXJ0LCAwKTtcbiAgICBjb25zdCBlbmQgPSBNYXRoLm1pbih2YWx1ZU9yRGVmYXVsdChtYWpvckVuZCwgdGlja3MubGVuZ3RoKSwgdGlja3MubGVuZ3RoKTtcbiAgICBsZXQgY291bnQgPSAwO1xuICAgIGxldCBsZW5ndGgsIGksIG5leHQ7XG4gICAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nKTtcbiAgICBpZiAobWFqb3JFbmQpIHtcbiAgICAgICAgbGVuZ3RoID0gbWFqb3JFbmQgLSBtYWpvclN0YXJ0O1xuICAgICAgICBzcGFjaW5nID0gbGVuZ3RoIC8gTWF0aC5mbG9vcihsZW5ndGggLyBzcGFjaW5nKTtcbiAgICB9XG4gICAgbmV4dCA9IHN0YXJ0O1xuICAgIHdoaWxlKG5leHQgPCAwKXtcbiAgICAgICAgY291bnQrKztcbiAgICAgICAgbmV4dCA9IE1hdGgucm91bmQoc3RhcnQgKyBjb3VudCAqIHNwYWNpbmcpO1xuICAgIH1cbiAgICBmb3IoaSA9IE1hdGgubWF4KHN0YXJ0LCAwKTsgaSA8IGVuZDsgaSsrKXtcbiAgICAgICAgaWYgKGkgPT09IG5leHQpIHtcbiAgICAgICAgICAgIG5ld1RpY2tzLnB1c2godGlja3NbaV0pO1xuICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgIG5leHQgPSBNYXRoLnJvdW5kKHN0YXJ0ICsgY291bnQgKiBzcGFjaW5nKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiBmdW5jdGlvbiBnZXRFdmVuU3BhY2luZyhhcnIpIHtcbiAgICBjb25zdCBsZW4gPSBhcnIubGVuZ3RoO1xuICAgIGxldCBpLCBkaWZmO1xuICAgIGlmIChsZW4gPCAyKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yKGRpZmYgPSBhcnJbMF0sIGkgPSAxOyBpIDwgbGVuOyArK2kpe1xuICAgICAgICBpZiAoYXJyW2ldIC0gYXJyW2kgLSAxXSAhPT0gZGlmZikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkaWZmO1xufVxuXG5jb25zdCByZXZlcnNlQWxpZ24gPSAoYWxpZ24pPT5hbGlnbiA9PT0gJ2xlZnQnID8gJ3JpZ2h0JyA6IGFsaWduID09PSAncmlnaHQnID8gJ2xlZnQnIDogYWxpZ247XG5jb25zdCBvZmZzZXRGcm9tRWRnZSA9IChzY2FsZSwgZWRnZSwgb2Zmc2V0KT0+ZWRnZSA9PT0gJ3RvcCcgfHwgZWRnZSA9PT0gJ2xlZnQnID8gc2NhbGVbZWRnZV0gKyBvZmZzZXQgOiBzY2FsZVtlZGdlXSAtIG9mZnNldDtcbmNvbnN0IGdldFRpY2tzTGltaXQgPSAodGlja3NMZW5ndGgsIG1heFRpY2tzTGltaXQpPT5NYXRoLm1pbihtYXhUaWNrc0xpbWl0IHx8IHRpY2tzTGVuZ3RoLCB0aWNrc0xlbmd0aCk7XG4gZnVuY3Rpb24gc2FtcGxlKGFyciwgbnVtSXRlbXMpIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBjb25zdCBpbmNyZW1lbnQgPSBhcnIubGVuZ3RoIC8gbnVtSXRlbXM7XG4gICAgY29uc3QgbGVuID0gYXJyLmxlbmd0aDtcbiAgICBsZXQgaSA9IDA7XG4gICAgZm9yKDsgaSA8IGxlbjsgaSArPSBpbmNyZW1lbnQpe1xuICAgICAgICByZXN1bHQucHVzaChhcnJbTWF0aC5mbG9vcihpKV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIGZ1bmN0aW9uIGdldFBpeGVsRm9yR3JpZExpbmUoc2NhbGUsIGluZGV4LCBvZmZzZXRHcmlkTGluZXMpIHtcbiAgICBjb25zdCBsZW5ndGggPSBzY2FsZS50aWNrcy5sZW5ndGg7XG4gICAgY29uc3QgdmFsaWRJbmRleCA9IE1hdGgubWluKGluZGV4LCBsZW5ndGggLSAxKTtcbiAgICBjb25zdCBzdGFydCA9IHNjYWxlLl9zdGFydFBpeGVsO1xuICAgIGNvbnN0IGVuZCA9IHNjYWxlLl9lbmRQaXhlbDtcbiAgICBjb25zdCBlcHNpbG9uID0gMWUtNjtcbiAgICBsZXQgbGluZVZhbHVlID0gc2NhbGUuZ2V0UGl4ZWxGb3JUaWNrKHZhbGlkSW5kZXgpO1xuICAgIGxldCBvZmZzZXQ7XG4gICAgaWYgKG9mZnNldEdyaWRMaW5lcykge1xuICAgICAgICBpZiAobGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBNYXRoLm1heChsaW5lVmFsdWUgLSBzdGFydCwgZW5kIC0gbGluZVZhbHVlKTtcbiAgICAgICAgfSBlbHNlIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gKHNjYWxlLmdldFBpeGVsRm9yVGljaygxKSAtIGxpbmVWYWx1ZSkgLyAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2Zmc2V0ID0gKGxpbmVWYWx1ZSAtIHNjYWxlLmdldFBpeGVsRm9yVGljayh2YWxpZEluZGV4IC0gMSkpIC8gMjtcbiAgICAgICAgfVxuICAgICAgICBsaW5lVmFsdWUgKz0gdmFsaWRJbmRleCA8IGluZGV4ID8gb2Zmc2V0IDogLW9mZnNldDtcbiAgICAgICAgaWYgKGxpbmVWYWx1ZSA8IHN0YXJ0IC0gZXBzaWxvbiB8fCBsaW5lVmFsdWUgPiBlbmQgKyBlcHNpbG9uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxpbmVWYWx1ZTtcbn1cbiBmdW5jdGlvbiBnYXJiYWdlQ29sbGVjdChjYWNoZXMsIGxlbmd0aCkge1xuICAgIGVhY2goY2FjaGVzLCAoY2FjaGUpPT57XG4gICAgICAgIGNvbnN0IGdjID0gY2FjaGUuZ2M7XG4gICAgICAgIGNvbnN0IGdjTGVuID0gZ2MubGVuZ3RoIC8gMjtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGlmIChnY0xlbiA+IGxlbmd0aCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZ2NMZW47ICsraSl7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNhY2hlLmRhdGFbZ2NbaV1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2Muc3BsaWNlKDAsIGdjTGVuKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuIGZ1bmN0aW9uIGdldFRpY2tNYXJrTGVuZ3RoKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gb3B0aW9ucy5kcmF3VGlja3MgPyBvcHRpb25zLnRpY2tMZW5ndGggOiAwO1xufVxuIGZ1bmN0aW9uIGdldFRpdGxlSGVpZ2h0KG9wdGlvbnMsIGZhbGxiYWNrKSB7XG4gICAgaWYgKCFvcHRpb25zLmRpc3BsYXkpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IGZvbnQgPSB0b0ZvbnQob3B0aW9ucy5mb250LCBmYWxsYmFjayk7XG4gICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICAgIGNvbnN0IGxpbmVzID0gaXNBcnJheShvcHRpb25zLnRleHQpID8gb3B0aW9ucy50ZXh0Lmxlbmd0aCA6IDE7XG4gICAgcmV0dXJuIGxpbmVzICogZm9udC5saW5lSGVpZ2h0ICsgcGFkZGluZy5oZWlnaHQ7XG59XG5mdW5jdGlvbiBjcmVhdGVTY2FsZUNvbnRleHQocGFyZW50LCBzY2FsZSkge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICBzY2FsZSxcbiAgICAgICAgdHlwZTogJ3NjYWxlJ1xuICAgIH0pO1xufVxuZnVuY3Rpb24gY3JlYXRlVGlja0NvbnRleHQocGFyZW50LCBpbmRleCwgdGljaykge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICB0aWNrLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgdHlwZTogJ3RpY2snXG4gICAgfSk7XG59XG5mdW5jdGlvbiB0aXRsZUFsaWduKGFsaWduLCBwb3NpdGlvbiwgcmV2ZXJzZSkge1xuICAgICBsZXQgcmV0ID0gX3RvTGVmdFJpZ2h0Q2VudGVyKGFsaWduKTtcbiAgICBpZiAocmV2ZXJzZSAmJiBwb3NpdGlvbiAhPT0gJ3JpZ2h0JyB8fCAhcmV2ZXJzZSAmJiBwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICByZXQgPSByZXZlcnNlQWxpZ24ocmV0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbn1cbmZ1bmN0aW9uIHRpdGxlQXJncyhzY2FsZSwgb2Zmc2V0LCBwb3NpdGlvbiwgYWxpZ24pIHtcbiAgICBjb25zdCB7IHRvcCAsIGxlZnQgLCBib3R0b20gLCByaWdodCAsIGNoYXJ0ICB9ID0gc2NhbGU7XG4gICAgY29uc3QgeyBjaGFydEFyZWEgLCBzY2FsZXMgIH0gPSBjaGFydDtcbiAgICBsZXQgcm90YXRpb24gPSAwO1xuICAgIGxldCBtYXhXaWR0aCwgdGl0bGVYLCB0aXRsZVk7XG4gICAgY29uc3QgaGVpZ2h0ID0gYm90dG9tIC0gdG9wO1xuICAgIGNvbnN0IHdpZHRoID0gcmlnaHQgLSBsZWZ0O1xuICAgIGlmIChzY2FsZS5pc0hvcml6b250YWwoKSkge1xuICAgICAgICB0aXRsZVggPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgbGVmdCwgcmlnaHQpO1xuICAgICAgICBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbkF4aXNJRCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uKVswXTtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcG9zaXRpb25bcG9zaXRpb25BeGlzSURdO1xuICAgICAgICAgICAgdGl0bGVZID0gc2NhbGVzW3Bvc2l0aW9uQXhpc0lEXS5nZXRQaXhlbEZvclZhbHVlKHZhbHVlKSArIGhlaWdodCAtIG9mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgIHRpdGxlWSA9IChjaGFydEFyZWEuYm90dG9tICsgY2hhcnRBcmVhLnRvcCkgLyAyICsgaGVpZ2h0IC0gb2Zmc2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGl0bGVZID0gb2Zmc2V0RnJvbUVkZ2Uoc2NhbGUsIHBvc2l0aW9uLCBvZmZzZXQpO1xuICAgICAgICB9XG4gICAgICAgIG1heFdpZHRoID0gcmlnaHQgLSBsZWZ0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgICAgICB0aXRsZVggPSBzY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpIC0gd2lkdGggKyBvZmZzZXQ7XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICB0aXRsZVggPSAoY2hhcnRBcmVhLmxlZnQgKyBjaGFydEFyZWEucmlnaHQpIC8gMiAtIHdpZHRoICsgb2Zmc2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGl0bGVYID0gb2Zmc2V0RnJvbUVkZ2Uoc2NhbGUsIHBvc2l0aW9uLCBvZmZzZXQpO1xuICAgICAgICB9XG4gICAgICAgIHRpdGxlWSA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBib3R0b20sIHRvcCk7XG4gICAgICAgIHJvdGF0aW9uID0gcG9zaXRpb24gPT09ICdsZWZ0JyA/IC1IQUxGX1BJIDogSEFMRl9QSTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGl0bGVYLFxuICAgICAgICB0aXRsZVksXG4gICAgICAgIG1heFdpZHRoLFxuICAgICAgICByb3RhdGlvblxuICAgIH07XG59XG5jbGFzcyBTY2FsZSBleHRlbmRzIEVsZW1lbnQge1xuICAgIGNvbnN0cnVjdG9yKGNmZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgICB0aGlzLmlkID0gY2ZnLmlkO1xuICAgICAgICAgdGhpcy50eXBlID0gY2ZnLnR5cGU7XG4gICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLmN0eCA9IGNmZy5jdHg7XG4gICAgICAgICB0aGlzLmNoYXJ0ID0gY2ZnLmNoYXJ0O1xuICAgICAgICAgdGhpcy50b3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLmJvdHRvbSA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMubGVmdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMucmlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5oZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX21hcmdpbnMgPSB7XG4gICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgcmlnaHQ6IDAsXG4gICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICBib3R0b206IDBcbiAgICAgICAgfTtcbiAgICAgICAgIHRoaXMubWF4V2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLm1heEhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMucGFkZGluZ1RvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMucGFkZGluZ0JvdHRvbSA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMucGFkZGluZ0xlZnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLnBhZGRpbmdSaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuYXhpcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMubGFiZWxSb3RhdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5taW4gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMubWF4ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9yYW5nZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMudGlja3MgPSBbXTtcbiAgICAgICAgIHRoaXMuX2dyaWRMaW5lSXRlbXMgPSBudWxsO1xuICAgICAgICAgdGhpcy5fbGFiZWxJdGVtcyA9IG51bGw7XG4gICAgICAgICB0aGlzLl9sYWJlbFNpemVzID0gbnVsbDtcbiAgICAgICAgdGhpcy5fbGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5fbWF4TGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5fbG9uZ2VzdFRleHRDYWNoZSA9IHt9O1xuICAgICAgICAgdGhpcy5fc3RhcnRQaXhlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuX2VuZFBpeGVsID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9yZXZlcnNlUGl4ZWxzID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX3VzZXJNYXggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3VzZXJNaW4gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3N1Z2dlc3RlZE1heCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fc3VnZ2VzdGVkTWluID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl90aWNrc0xlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMuX2JvcmRlclZhbHVlID0gMDtcbiAgICAgICAgdGhpcy5fY2FjaGUgPSB7fTtcbiAgICAgICAgdGhpcy5fZGF0YUxpbWl0c0NhY2hlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLiRjb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgIH1cbiBpbml0KG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgdGhpcy5heGlzID0gb3B0aW9ucy5heGlzO1xuICAgICAgICB0aGlzLl91c2VyTWluID0gdGhpcy5wYXJzZShvcHRpb25zLm1pbik7XG4gICAgICAgIHRoaXMuX3VzZXJNYXggPSB0aGlzLnBhcnNlKG9wdGlvbnMubWF4KTtcbiAgICAgICAgdGhpcy5fc3VnZ2VzdGVkTWluID0gdGhpcy5wYXJzZShvcHRpb25zLnN1Z2dlc3RlZE1pbik7XG4gICAgICAgIHRoaXMuX3N1Z2dlc3RlZE1heCA9IHRoaXMucGFyc2Uob3B0aW9ucy5zdWdnZXN0ZWRNYXgpO1xuICAgIH1cbiBwYXJzZShyYXcsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiByYXc7XG4gICAgfVxuIGdldFVzZXJCb3VuZHMoKSB7XG4gICAgICAgIGxldCB7IF91c2VyTWluICwgX3VzZXJNYXggLCBfc3VnZ2VzdGVkTWluICwgX3N1Z2dlc3RlZE1heCAgfSA9IHRoaXM7XG4gICAgICAgIF91c2VyTWluID0gZmluaXRlT3JEZWZhdWx0KF91c2VyTWluLCBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpO1xuICAgICAgICBfdXNlck1heCA9IGZpbml0ZU9yRGVmYXVsdChfdXNlck1heCwgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKTtcbiAgICAgICAgX3N1Z2dlc3RlZE1pbiA9IGZpbml0ZU9yRGVmYXVsdChfc3VnZ2VzdGVkTWluLCBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpO1xuICAgICAgICBfc3VnZ2VzdGVkTWF4ID0gZmluaXRlT3JEZWZhdWx0KF9zdWdnZXN0ZWRNYXgsIE51bWJlci5ORUdBVElWRV9JTkZJTklUWSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBtaW46IGZpbml0ZU9yRGVmYXVsdChfdXNlck1pbiwgX3N1Z2dlc3RlZE1pbiksXG4gICAgICAgICAgICBtYXg6IGZpbml0ZU9yRGVmYXVsdChfdXNlck1heCwgX3N1Z2dlc3RlZE1heCksXG4gICAgICAgICAgICBtaW5EZWZpbmVkOiBpc051bWJlckZpbml0ZShfdXNlck1pbiksXG4gICAgICAgICAgICBtYXhEZWZpbmVkOiBpc051bWJlckZpbml0ZShfdXNlck1heClcbiAgICAgICAgfTtcbiAgICB9XG4gZ2V0TWluTWF4KGNhblN0YWNrKSB7XG4gICAgICAgIGxldCB7IG1pbiAsIG1heCAsIG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gdGhpcy5nZXRVc2VyQm91bmRzKCk7XG4gICAgICAgIGxldCByYW5nZTtcbiAgICAgICAgaWYgKG1pbkRlZmluZWQgJiYgbWF4RGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBtaW4sXG4gICAgICAgICAgICAgICAgbWF4XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1ldGFzID0gdGhpcy5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygpO1xuICAgICAgICBmb3IobGV0IGkgPSAwLCBpbGVuID0gbWV0YXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHJhbmdlID0gbWV0YXNbaV0uY29udHJvbGxlci5nZXRNaW5NYXgodGhpcywgY2FuU3RhY2spO1xuICAgICAgICAgICAgaWYgKCFtaW5EZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWluID0gTWF0aC5taW4obWluLCByYW5nZS5taW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtYXhEZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCByYW5nZS5tYXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG1pbiA9IG1heERlZmluZWQgJiYgbWluID4gbWF4ID8gbWF4IDogbWluO1xuICAgICAgICBtYXggPSBtaW5EZWZpbmVkICYmIG1pbiA+IG1heCA/IG1pbiA6IG1heDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbjogZmluaXRlT3JEZWZhdWx0KG1pbiwgZmluaXRlT3JEZWZhdWx0KG1heCwgbWluKSksXG4gICAgICAgICAgICBtYXg6IGZpbml0ZU9yRGVmYXVsdChtYXgsIGZpbml0ZU9yRGVmYXVsdChtaW4sIG1heCkpXG4gICAgICAgIH07XG4gICAgfVxuIGdldFBhZGRpbmcoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsZWZ0OiB0aGlzLnBhZGRpbmdMZWZ0IHx8IDAsXG4gICAgICAgICAgICB0b3A6IHRoaXMucGFkZGluZ1RvcCB8fCAwLFxuICAgICAgICAgICAgcmlnaHQ6IHRoaXMucGFkZGluZ1JpZ2h0IHx8IDAsXG4gICAgICAgICAgICBib3R0b206IHRoaXMucGFkZGluZ0JvdHRvbSB8fCAwXG4gICAgICAgIH07XG4gICAgfVxuIGdldFRpY2tzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50aWNrcztcbiAgICB9XG4gZ2V0TGFiZWxzKCkge1xuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5jaGFydC5kYXRhO1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmxhYmVscyB8fCAodGhpcy5pc0hvcml6b250YWwoKSA/IGRhdGEueExhYmVscyA6IGRhdGEueUxhYmVscykgfHwgZGF0YS5sYWJlbHMgfHwgW107XG4gICAgfVxuIGdldExhYmVsSXRlbXMoY2hhcnRBcmVhID0gdGhpcy5jaGFydC5jaGFydEFyZWEpIHtcbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLl9sYWJlbEl0ZW1zIHx8ICh0aGlzLl9sYWJlbEl0ZW1zID0gdGhpcy5fY29tcHV0ZUxhYmVsSXRlbXMoY2hhcnRBcmVhKSk7XG4gICAgICAgIHJldHVybiBpdGVtcztcbiAgICB9XG4gICAgYmVmb3JlTGF5b3V0KCkge1xuICAgICAgICB0aGlzLl9jYWNoZSA9IHt9O1xuICAgICAgICB0aGlzLl9kYXRhTGltaXRzQ2FjaGVkID0gZmFsc2U7XG4gICAgfVxuICAgIGJlZm9yZVVwZGF0ZSgpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmJlZm9yZVVwZGF0ZSwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gdXBkYXRlKG1heFdpZHRoLCBtYXhIZWlnaHQsIG1hcmdpbnMpIHtcbiAgICAgICAgY29uc3QgeyBiZWdpbkF0WmVybyAsIGdyYWNlICwgdGlja3M6IHRpY2tPcHRzICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBzYW1wbGVTaXplID0gdGlja09wdHMuc2FtcGxlU2l6ZTtcbiAgICAgICAgdGhpcy5iZWZvcmVVcGRhdGUoKTtcbiAgICAgICAgdGhpcy5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgICAgICB0aGlzLm1heEhlaWdodCA9IG1heEhlaWdodDtcbiAgICAgICAgdGhpcy5fbWFyZ2lucyA9IG1hcmdpbnMgPSBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIGJvdHRvbTogMFxuICAgICAgICB9LCBtYXJnaW5zKTtcbiAgICAgICAgdGhpcy50aWNrcyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2xhYmVsU2l6ZXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9ncmlkTGluZUl0ZW1zID0gbnVsbDtcbiAgICAgICAgdGhpcy5fbGFiZWxJdGVtcyA9IG51bGw7XG4gICAgICAgIHRoaXMuYmVmb3JlU2V0RGltZW5zaW9ucygpO1xuICAgICAgICB0aGlzLnNldERpbWVuc2lvbnMoKTtcbiAgICAgICAgdGhpcy5hZnRlclNldERpbWVuc2lvbnMoKTtcbiAgICAgICAgdGhpcy5fbWF4TGVuZ3RoID0gdGhpcy5pc0hvcml6b250YWwoKSA/IHRoaXMud2lkdGggKyBtYXJnaW5zLmxlZnQgKyBtYXJnaW5zLnJpZ2h0IDogdGhpcy5oZWlnaHQgKyBtYXJnaW5zLnRvcCArIG1hcmdpbnMuYm90dG9tO1xuICAgICAgICBpZiAoIXRoaXMuX2RhdGFMaW1pdHNDYWNoZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYmVmb3JlRGF0YUxpbWl0cygpO1xuICAgICAgICAgICAgdGhpcy5kZXRlcm1pbmVEYXRhTGltaXRzKCk7XG4gICAgICAgICAgICB0aGlzLmFmdGVyRGF0YUxpbWl0cygpO1xuICAgICAgICAgICAgdGhpcy5fcmFuZ2UgPSBfYWRkR3JhY2UodGhpcywgZ3JhY2UsIGJlZ2luQXRaZXJvKTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFMaW1pdHNDYWNoZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmVmb3JlQnVpbGRUaWNrcygpO1xuICAgICAgICB0aGlzLnRpY2tzID0gdGhpcy5idWlsZFRpY2tzKCkgfHwgW107XG4gICAgICAgIHRoaXMuYWZ0ZXJCdWlsZFRpY2tzKCk7XG4gICAgICAgIGNvbnN0IHNhbXBsaW5nRW5hYmxlZCA9IHNhbXBsZVNpemUgPCB0aGlzLnRpY2tzLmxlbmd0aDtcbiAgICAgICAgdGhpcy5fY29udmVydFRpY2tzVG9MYWJlbHMoc2FtcGxpbmdFbmFibGVkID8gc2FtcGxlKHRoaXMudGlja3MsIHNhbXBsZVNpemUpIDogdGhpcy50aWNrcyk7XG4gICAgICAgIHRoaXMuY29uZmlndXJlKCk7XG4gICAgICAgIHRoaXMuYmVmb3JlQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpO1xuICAgICAgICB0aGlzLmNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKTtcbiAgICAgICAgdGhpcy5hZnRlckNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKTtcbiAgICAgICAgaWYgKHRpY2tPcHRzLmRpc3BsYXkgJiYgKHRpY2tPcHRzLmF1dG9Ta2lwIHx8IHRpY2tPcHRzLnNvdXJjZSA9PT0gJ2F1dG8nKSkge1xuICAgICAgICAgICAgdGhpcy50aWNrcyA9IGF1dG9Ta2lwKHRoaXMsIHRoaXMudGlja3MpO1xuICAgICAgICAgICAgdGhpcy5fbGFiZWxTaXplcyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmFmdGVyQXV0b1NraXAoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2FtcGxpbmdFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9jb252ZXJ0VGlja3NUb0xhYmVscyh0aGlzLnRpY2tzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJlZm9yZUZpdCgpO1xuICAgICAgICB0aGlzLmZpdCgpO1xuICAgICAgICB0aGlzLmFmdGVyRml0KCk7XG4gICAgICAgIHRoaXMuYWZ0ZXJVcGRhdGUoKTtcbiAgICB9XG4gY29uZmlndXJlKCkge1xuICAgICAgICBsZXQgcmV2ZXJzZVBpeGVscyA9IHRoaXMub3B0aW9ucy5yZXZlcnNlO1xuICAgICAgICBsZXQgc3RhcnRQaXhlbCwgZW5kUGl4ZWw7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICBzdGFydFBpeGVsID0gdGhpcy5sZWZ0O1xuICAgICAgICAgICAgZW5kUGl4ZWwgPSB0aGlzLnJpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RhcnRQaXhlbCA9IHRoaXMudG9wO1xuICAgICAgICAgICAgZW5kUGl4ZWwgPSB0aGlzLmJvdHRvbTtcbiAgICAgICAgICAgIHJldmVyc2VQaXhlbHMgPSAhcmV2ZXJzZVBpeGVscztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdGFydFBpeGVsID0gc3RhcnRQaXhlbDtcbiAgICAgICAgdGhpcy5fZW5kUGl4ZWwgPSBlbmRQaXhlbDtcbiAgICAgICAgdGhpcy5fcmV2ZXJzZVBpeGVscyA9IHJldmVyc2VQaXhlbHM7XG4gICAgICAgIHRoaXMuX2xlbmd0aCA9IGVuZFBpeGVsIC0gc3RhcnRQaXhlbDtcbiAgICAgICAgdGhpcy5fYWxpZ25Ub1BpeGVscyA9IHRoaXMub3B0aW9ucy5hbGlnblRvUGl4ZWxzO1xuICAgIH1cbiAgICBhZnRlclVwZGF0ZSgpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmFmdGVyVXBkYXRlLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBiZWZvcmVTZXREaW1lbnNpb25zKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYmVmb3JlU2V0RGltZW5zaW9ucywgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgc2V0RGltZW5zaW9ucygpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB0aGlzLm1heFdpZHRoO1xuICAgICAgICAgICAgdGhpcy5sZWZ0ID0gMDtcbiAgICAgICAgICAgIHRoaXMucmlnaHQgPSB0aGlzLndpZHRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLm1heEhlaWdodDtcbiAgICAgICAgICAgIHRoaXMudG9wID0gMDtcbiAgICAgICAgICAgIHRoaXMuYm90dG9tID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYWRkaW5nTGVmdCA9IDA7XG4gICAgICAgIHRoaXMucGFkZGluZ1RvcCA9IDA7XG4gICAgICAgIHRoaXMucGFkZGluZ1JpZ2h0ID0gMDtcbiAgICAgICAgdGhpcy5wYWRkaW5nQm90dG9tID0gMDtcbiAgICB9XG4gICAgYWZ0ZXJTZXREaW1lbnNpb25zKCkge1xuICAgICAgICBjYWxsYmFjayh0aGlzLm9wdGlvbnMuYWZ0ZXJTZXREaW1lbnNpb25zLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBfY2FsbEhvb2tzKG5hbWUpIHtcbiAgICAgICAgdGhpcy5jaGFydC5ub3RpZnlQbHVnaW5zKG5hbWUsIHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zW25hbWVdLCBbXG4gICAgICAgICAgICB0aGlzXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBiZWZvcmVEYXRhTGltaXRzKCkge1xuICAgICAgICB0aGlzLl9jYWxsSG9va3MoJ2JlZm9yZURhdGFMaW1pdHMnKTtcbiAgICB9XG4gICAgZGV0ZXJtaW5lRGF0YUxpbWl0cygpIHt9XG4gICAgYWZ0ZXJEYXRhTGltaXRzKCkge1xuICAgICAgICB0aGlzLl9jYWxsSG9va3MoJ2FmdGVyRGF0YUxpbWl0cycpO1xuICAgIH1cbiAgICBiZWZvcmVCdWlsZFRpY2tzKCkge1xuICAgICAgICB0aGlzLl9jYWxsSG9va3MoJ2JlZm9yZUJ1aWxkVGlja3MnKTtcbiAgICB9XG4gYnVpbGRUaWNrcygpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBhZnRlckJ1aWxkVGlja3MoKSB7XG4gICAgICAgIHRoaXMuX2NhbGxIb29rcygnYWZ0ZXJCdWlsZFRpY2tzJyk7XG4gICAgfVxuICAgIGJlZm9yZVRpY2tUb0xhYmVsQ29udmVyc2lvbigpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmJlZm9yZVRpY2tUb0xhYmVsQ29udmVyc2lvbiwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gZ2VuZXJhdGVUaWNrTGFiZWxzKHRpY2tzKSB7XG4gICAgICAgIGNvbnN0IHRpY2tPcHRzID0gdGhpcy5vcHRpb25zLnRpY2tzO1xuICAgICAgICBsZXQgaSwgaWxlbiwgdGljaztcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gdGlja3MubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIHRpY2sgPSB0aWNrc1tpXTtcbiAgICAgICAgICAgIHRpY2subGFiZWwgPSBjYWxsYmFjayh0aWNrT3B0cy5jYWxsYmFjaywgW1xuICAgICAgICAgICAgICAgIHRpY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgaSxcbiAgICAgICAgICAgICAgICB0aWNrc1xuICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYWZ0ZXJUaWNrVG9MYWJlbENvbnZlcnNpb24oKSB7XG4gICAgICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbiwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgYmVmb3JlQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmJlZm9yZUNhbGN1bGF0ZUxhYmVsUm90YXRpb24sIFtcbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIGNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHRpY2tPcHRzID0gb3B0aW9ucy50aWNrcztcbiAgICAgICAgY29uc3QgbnVtVGlja3MgPSBnZXRUaWNrc0xpbWl0KHRoaXMudGlja3MubGVuZ3RoLCBvcHRpb25zLnRpY2tzLm1heFRpY2tzTGltaXQpO1xuICAgICAgICBjb25zdCBtaW5Sb3RhdGlvbiA9IHRpY2tPcHRzLm1pblJvdGF0aW9uIHx8IDA7XG4gICAgICAgIGNvbnN0IG1heFJvdGF0aW9uID0gdGlja09wdHMubWF4Um90YXRpb247XG4gICAgICAgIGxldCBsYWJlbFJvdGF0aW9uID0gbWluUm90YXRpb247XG4gICAgICAgIGxldCB0aWNrV2lkdGgsIG1heEhlaWdodCwgbWF4TGFiZWxEaWFnb25hbDtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1Zpc2libGUoKSB8fCAhdGlja09wdHMuZGlzcGxheSB8fCBtaW5Sb3RhdGlvbiA+PSBtYXhSb3RhdGlvbiB8fCBudW1UaWNrcyA8PSAxIHx8ICF0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0aGlzLmxhYmVsUm90YXRpb24gPSBtaW5Sb3RhdGlvbjtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsYWJlbFNpemVzID0gdGhpcy5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICBjb25zdCBtYXhMYWJlbFdpZHRoID0gbGFiZWxTaXplcy53aWRlc3Qud2lkdGg7XG4gICAgICAgIGNvbnN0IG1heExhYmVsSGVpZ2h0ID0gbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodDtcbiAgICAgICAgY29uc3QgbWF4V2lkdGggPSBfbGltaXRWYWx1ZSh0aGlzLmNoYXJ0LndpZHRoIC0gbWF4TGFiZWxXaWR0aCwgMCwgdGhpcy5tYXhXaWR0aCk7XG4gICAgICAgIHRpY2tXaWR0aCA9IG9wdGlvbnMub2Zmc2V0ID8gdGhpcy5tYXhXaWR0aCAvIG51bVRpY2tzIDogbWF4V2lkdGggLyAobnVtVGlja3MgLSAxKTtcbiAgICAgICAgaWYgKG1heExhYmVsV2lkdGggKyA2ID4gdGlja1dpZHRoKSB7XG4gICAgICAgICAgICB0aWNrV2lkdGggPSBtYXhXaWR0aCAvIChudW1UaWNrcyAtIChvcHRpb25zLm9mZnNldCA/IDAuNSA6IDEpKTtcbiAgICAgICAgICAgIG1heEhlaWdodCA9IHRoaXMubWF4SGVpZ2h0IC0gZ2V0VGlja01hcmtMZW5ndGgob3B0aW9ucy5ncmlkKSAtIHRpY2tPcHRzLnBhZGRpbmcgLSBnZXRUaXRsZUhlaWdodChvcHRpb25zLnRpdGxlLCB0aGlzLmNoYXJ0Lm9wdGlvbnMuZm9udCk7XG4gICAgICAgICAgICBtYXhMYWJlbERpYWdvbmFsID0gTWF0aC5zcXJ0KG1heExhYmVsV2lkdGggKiBtYXhMYWJlbFdpZHRoICsgbWF4TGFiZWxIZWlnaHQgKiBtYXhMYWJlbEhlaWdodCk7XG4gICAgICAgICAgICBsYWJlbFJvdGF0aW9uID0gdG9EZWdyZWVzKE1hdGgubWluKE1hdGguYXNpbihfbGltaXRWYWx1ZSgobGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCArIDYpIC8gdGlja1dpZHRoLCAtMSwgMSkpLCBNYXRoLmFzaW4oX2xpbWl0VmFsdWUobWF4SGVpZ2h0IC8gbWF4TGFiZWxEaWFnb25hbCwgLTEsIDEpKSAtIE1hdGguYXNpbihfbGltaXRWYWx1ZShtYXhMYWJlbEhlaWdodCAvIG1heExhYmVsRGlhZ29uYWwsIC0xLCAxKSkpKTtcbiAgICAgICAgICAgIGxhYmVsUm90YXRpb24gPSBNYXRoLm1heChtaW5Sb3RhdGlvbiwgTWF0aC5taW4obWF4Um90YXRpb24sIGxhYmVsUm90YXRpb24pKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhYmVsUm90YXRpb24gPSBsYWJlbFJvdGF0aW9uO1xuICAgIH1cbiAgICBhZnRlckNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKSB7XG4gICAgICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlckNhbGN1bGF0ZUxhYmVsUm90YXRpb24sIFtcbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIGFmdGVyQXV0b1NraXAoKSB7fVxuICAgIGJlZm9yZUZpdCgpIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5vcHRpb25zLmJlZm9yZUZpdCwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gICAgZml0KCkge1xuICAgICAgICBjb25zdCBtaW5TaXplID0ge1xuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgeyBjaGFydCAsIG9wdGlvbnM6IHsgdGlja3M6IHRpY2tPcHRzICwgdGl0bGU6IHRpdGxlT3B0cyAsIGdyaWQ6IGdyaWRPcHRzICB9ICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgZGlzcGxheSA9IHRoaXMuX2lzVmlzaWJsZSgpO1xuICAgICAgICBjb25zdCBpc0hvcml6b250YWwgPSB0aGlzLmlzSG9yaXpvbnRhbCgpO1xuICAgICAgICBpZiAoZGlzcGxheSkge1xuICAgICAgICAgICAgY29uc3QgdGl0bGVIZWlnaHQgPSBnZXRUaXRsZUhlaWdodCh0aXRsZU9wdHMsIGNoYXJ0Lm9wdGlvbnMuZm9udCk7XG4gICAgICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgbWluU2l6ZS53aWR0aCA9IHRoaXMubWF4V2lkdGg7XG4gICAgICAgICAgICAgICAgbWluU2l6ZS5oZWlnaHQgPSBnZXRUaWNrTWFya0xlbmd0aChncmlkT3B0cykgKyB0aXRsZUhlaWdodDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbWluU2l6ZS5oZWlnaHQgPSB0aGlzLm1heEhlaWdodDtcbiAgICAgICAgICAgICAgICBtaW5TaXplLndpZHRoID0gZ2V0VGlja01hcmtMZW5ndGgoZ3JpZE9wdHMpICsgdGl0bGVIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGlja09wdHMuZGlzcGxheSAmJiB0aGlzLnRpY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgZmlyc3QgLCBsYXN0ICwgd2lkZXN0ICwgaGlnaGVzdCAgfSA9IHRoaXMuX2dldExhYmVsU2l6ZXMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB0aWNrUGFkZGluZyA9IHRpY2tPcHRzLnBhZGRpbmcgKiAyO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFuZ2xlUmFkaWFucyA9IHRvUmFkaWFucyh0aGlzLmxhYmVsUm90YXRpb24pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvcyA9IE1hdGguY29zKGFuZ2xlUmFkaWFucyk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2luID0gTWF0aC5zaW4oYW5nbGVSYWRpYW5zKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsSGVpZ2h0ID0gdGlja09wdHMubWlycm9yID8gMCA6IHNpbiAqIHdpZGVzdC53aWR0aCArIGNvcyAqIGhpZ2hlc3QuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBtaW5TaXplLmhlaWdodCA9IE1hdGgubWluKHRoaXMubWF4SGVpZ2h0LCBtaW5TaXplLmhlaWdodCArIGxhYmVsSGVpZ2h0ICsgdGlja1BhZGRpbmcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsV2lkdGggPSB0aWNrT3B0cy5taXJyb3IgPyAwIDogY29zICogd2lkZXN0LndpZHRoICsgc2luICogaGlnaGVzdC5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIG1pblNpemUud2lkdGggPSBNYXRoLm1pbih0aGlzLm1heFdpZHRoLCBtaW5TaXplLndpZHRoICsgbGFiZWxXaWR0aCArIHRpY2tQYWRkaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsY3VsYXRlUGFkZGluZyhmaXJzdCwgbGFzdCwgc2luLCBjb3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hhbmRsZU1hcmdpbnMoKTtcbiAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMuX2xlbmd0aCA9IGNoYXJ0LndpZHRoIC0gdGhpcy5fbWFyZ2lucy5sZWZ0IC0gdGhpcy5fbWFyZ2lucy5yaWdodDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gbWluU2l6ZS5oZWlnaHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gbWluU2l6ZS53aWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gdGhpcy5fbGVuZ3RoID0gY2hhcnQuaGVpZ2h0IC0gdGhpcy5fbWFyZ2lucy50b3AgLSB0aGlzLl9tYXJnaW5zLmJvdHRvbTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBfY2FsY3VsYXRlUGFkZGluZyhmaXJzdCwgbGFzdCwgc2luLCBjb3MpIHtcbiAgICAgICAgY29uc3QgeyB0aWNrczogeyBhbGlnbiAsIHBhZGRpbmcgIH0gLCBwb3NpdGlvbiAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgaXNSb3RhdGVkID0gdGhpcy5sYWJlbFJvdGF0aW9uICE9PSAwO1xuICAgICAgICBjb25zdCBsYWJlbHNCZWxvd1RpY2tzID0gcG9zaXRpb24gIT09ICd0b3AnICYmIHRoaXMuYXhpcyA9PT0gJ3gnO1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0TGVmdCA9IHRoaXMuZ2V0UGl4ZWxGb3JUaWNrKDApIC0gdGhpcy5sZWZ0O1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0UmlnaHQgPSB0aGlzLnJpZ2h0IC0gdGhpcy5nZXRQaXhlbEZvclRpY2sodGhpcy50aWNrcy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGxldCBwYWRkaW5nTGVmdCA9IDA7XG4gICAgICAgICAgICBsZXQgcGFkZGluZ1JpZ2h0ID0gMDtcbiAgICAgICAgICAgIGlmIChpc1JvdGF0ZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAobGFiZWxzQmVsb3dUaWNrcykge1xuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nTGVmdCA9IGNvcyAqIGZpcnN0LndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBzaW4gKiBsYXN0LmhlaWdodDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nTGVmdCA9IHNpbiAqIGZpcnN0LmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgcGFkZGluZ1JpZ2h0ID0gY29zICogbGFzdC53aWR0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnc3RhcnQnKSB7XG4gICAgICAgICAgICAgICAgcGFkZGluZ1JpZ2h0ID0gbGFzdC53aWR0aDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICAgICAgICAgICAgcGFkZGluZ0xlZnQgPSBmaXJzdC53aWR0aDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxpZ24gIT09ICdpbm5lcicpIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nTGVmdCA9IGZpcnN0LndpZHRoIC8gMjtcbiAgICAgICAgICAgICAgICBwYWRkaW5nUmlnaHQgPSBsYXN0LndpZHRoIC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGFkZGluZ0xlZnQgPSBNYXRoLm1heCgocGFkZGluZ0xlZnQgLSBvZmZzZXRMZWZ0ICsgcGFkZGluZykgKiB0aGlzLndpZHRoIC8gKHRoaXMud2lkdGggLSBvZmZzZXRMZWZ0KSwgMCk7XG4gICAgICAgICAgICB0aGlzLnBhZGRpbmdSaWdodCA9IE1hdGgubWF4KChwYWRkaW5nUmlnaHQgLSBvZmZzZXRSaWdodCArIHBhZGRpbmcpICogdGhpcy53aWR0aCAvICh0aGlzLndpZHRoIC0gb2Zmc2V0UmlnaHQpLCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBwYWRkaW5nVG9wID0gbGFzdC5oZWlnaHQgLyAyO1xuICAgICAgICAgICAgbGV0IHBhZGRpbmdCb3R0b20gPSBmaXJzdC5oZWlnaHQgLyAyO1xuICAgICAgICAgICAgaWYgKGFsaWduID09PSAnc3RhcnQnKSB7XG4gICAgICAgICAgICAgICAgcGFkZGluZ1RvcCA9IDA7XG4gICAgICAgICAgICAgICAgcGFkZGluZ0JvdHRvbSA9IGZpcnN0LmhlaWdodDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICAgICAgICAgICAgcGFkZGluZ1RvcCA9IGxhc3QuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIHBhZGRpbmdCb3R0b20gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wYWRkaW5nVG9wID0gcGFkZGluZ1RvcCArIHBhZGRpbmc7XG4gICAgICAgICAgICB0aGlzLnBhZGRpbmdCb3R0b20gPSBwYWRkaW5nQm90dG9tICsgcGFkZGluZztcbiAgICAgICAgfVxuICAgIH1cbiBfaGFuZGxlTWFyZ2lucygpIHtcbiAgICAgICAgaWYgKHRoaXMuX21hcmdpbnMpIHtcbiAgICAgICAgICAgIHRoaXMuX21hcmdpbnMubGVmdCA9IE1hdGgubWF4KHRoaXMucGFkZGluZ0xlZnQsIHRoaXMuX21hcmdpbnMubGVmdCk7XG4gICAgICAgICAgICB0aGlzLl9tYXJnaW5zLnRvcCA9IE1hdGgubWF4KHRoaXMucGFkZGluZ1RvcCwgdGhpcy5fbWFyZ2lucy50b3ApO1xuICAgICAgICAgICAgdGhpcy5fbWFyZ2lucy5yaWdodCA9IE1hdGgubWF4KHRoaXMucGFkZGluZ1JpZ2h0LCB0aGlzLl9tYXJnaW5zLnJpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuX21hcmdpbnMuYm90dG9tID0gTWF0aC5tYXgodGhpcy5wYWRkaW5nQm90dG9tLCB0aGlzLl9tYXJnaW5zLmJvdHRvbSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYWZ0ZXJGaXQoKSB7XG4gICAgICAgIGNhbGxiYWNrKHRoaXMub3B0aW9ucy5hZnRlckZpdCwgW1xuICAgICAgICAgICAgdGhpc1xuICAgICAgICBdKTtcbiAgICB9XG4gaXNIb3Jpem9udGFsKCkge1xuICAgICAgICBjb25zdCB7IGF4aXMgLCBwb3NpdGlvbiAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgcmV0dXJuIHBvc2l0aW9uID09PSAndG9wJyB8fCBwb3NpdGlvbiA9PT0gJ2JvdHRvbScgfHwgYXhpcyA9PT0gJ3gnO1xuICAgIH1cbiBpc0Z1bGxTaXplKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmZ1bGxTaXplO1xuICAgIH1cbiBfY29udmVydFRpY2tzVG9MYWJlbHModGlja3MpIHtcbiAgICAgICAgdGhpcy5iZWZvcmVUaWNrVG9MYWJlbENvbnZlcnNpb24oKTtcbiAgICAgICAgdGhpcy5nZW5lcmF0ZVRpY2tMYWJlbHModGlja3MpO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gdGlja3MubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIGlmIChpc051bGxPclVuZGVmKHRpY2tzW2ldLmxhYmVsKSkge1xuICAgICAgICAgICAgICAgIHRpY2tzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBpbGVuLS07XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWZ0ZXJUaWNrVG9MYWJlbENvbnZlcnNpb24oKTtcbiAgICB9XG4gX2dldExhYmVsU2l6ZXMoKSB7XG4gICAgICAgIGxldCBsYWJlbFNpemVzID0gdGhpcy5fbGFiZWxTaXplcztcbiAgICAgICAgaWYgKCFsYWJlbFNpemVzKSB7XG4gICAgICAgICAgICBjb25zdCBzYW1wbGVTaXplID0gdGhpcy5vcHRpb25zLnRpY2tzLnNhbXBsZVNpemU7XG4gICAgICAgICAgICBsZXQgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICAgICAgaWYgKHNhbXBsZVNpemUgPCB0aWNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aWNrcyA9IHNhbXBsZSh0aWNrcywgc2FtcGxlU2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sYWJlbFNpemVzID0gbGFiZWxTaXplcyA9IHRoaXMuX2NvbXB1dGVMYWJlbFNpemVzKHRpY2tzLCB0aWNrcy5sZW5ndGgsIHRoaXMub3B0aW9ucy50aWNrcy5tYXhUaWNrc0xpbWl0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGFiZWxTaXplcztcbiAgICB9XG4gX2NvbXB1dGVMYWJlbFNpemVzKHRpY2tzLCBsZW5ndGgsIG1heFRpY2tzTGltaXQpIHtcbiAgICAgICAgY29uc3QgeyBjdHggLCBfbG9uZ2VzdFRleHRDYWNoZTogY2FjaGVzICB9ID0gdGhpcztcbiAgICAgICAgY29uc3Qgd2lkdGhzID0gW107XG4gICAgICAgIGNvbnN0IGhlaWdodHMgPSBbXTtcbiAgICAgICAgY29uc3QgaW5jcmVtZW50ID0gTWF0aC5mbG9vcihsZW5ndGggLyBnZXRUaWNrc0xpbWl0KGxlbmd0aCwgbWF4VGlja3NMaW1pdCkpO1xuICAgICAgICBsZXQgd2lkZXN0TGFiZWxTaXplID0gMDtcbiAgICAgICAgbGV0IGhpZ2hlc3RMYWJlbFNpemUgPSAwO1xuICAgICAgICBsZXQgaSwgaiwgamxlbiwgbGFiZWwsIHRpY2tGb250LCBmb250U3RyaW5nLCBjYWNoZSwgbGluZUhlaWdodCwgd2lkdGgsIGhlaWdodCwgbmVzdGVkTGFiZWw7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbmd0aDsgaSArPSBpbmNyZW1lbnQpe1xuICAgICAgICAgICAgbGFiZWwgPSB0aWNrc1tpXS5sYWJlbDtcbiAgICAgICAgICAgIHRpY2tGb250ID0gdGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucyhpKTtcbiAgICAgICAgICAgIGN0eC5mb250ID0gZm9udFN0cmluZyA9IHRpY2tGb250LnN0cmluZztcbiAgICAgICAgICAgIGNhY2hlID0gY2FjaGVzW2ZvbnRTdHJpbmddID0gY2FjaGVzW2ZvbnRTdHJpbmddIHx8IHtcbiAgICAgICAgICAgICAgICBkYXRhOiB7fSxcbiAgICAgICAgICAgICAgICBnYzogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsaW5lSGVpZ2h0ID0gdGlja0ZvbnQubGluZUhlaWdodDtcbiAgICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIGlmICghaXNOdWxsT3JVbmRlZihsYWJlbCkgJiYgIWlzQXJyYXkobGFiZWwpKSB7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBfbWVhc3VyZVRleHQoY3R4LCBjYWNoZS5kYXRhLCBjYWNoZS5nYywgd2lkdGgsIGxhYmVsKTtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGxhYmVsKSkge1xuICAgICAgICAgICAgICAgIGZvcihqID0gMCwgamxlbiA9IGxhYmVsLmxlbmd0aDsgaiA8IGpsZW47ICsrail7XG4gICAgICAgICAgICAgICAgICAgIG5lc3RlZExhYmVsID0gIGxhYmVsW2pdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWYobmVzdGVkTGFiZWwpICYmICFpc0FycmF5KG5lc3RlZExhYmVsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSBfbWVhc3VyZVRleHQoY3R4LCBjYWNoZS5kYXRhLCBjYWNoZS5nYywgd2lkdGgsIG5lc3RlZExhYmVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCArPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2lkdGhzLnB1c2god2lkdGgpO1xuICAgICAgICAgICAgaGVpZ2h0cy5wdXNoKGhlaWdodCk7XG4gICAgICAgICAgICB3aWRlc3RMYWJlbFNpemUgPSBNYXRoLm1heCh3aWR0aCwgd2lkZXN0TGFiZWxTaXplKTtcbiAgICAgICAgICAgIGhpZ2hlc3RMYWJlbFNpemUgPSBNYXRoLm1heChoZWlnaHQsIGhpZ2hlc3RMYWJlbFNpemUpO1xuICAgICAgICB9XG4gICAgICAgIGdhcmJhZ2VDb2xsZWN0KGNhY2hlcywgbGVuZ3RoKTtcbiAgICAgICAgY29uc3Qgd2lkZXN0ID0gd2lkdGhzLmluZGV4T2Yod2lkZXN0TGFiZWxTaXplKTtcbiAgICAgICAgY29uc3QgaGlnaGVzdCA9IGhlaWdodHMuaW5kZXhPZihoaWdoZXN0TGFiZWxTaXplKTtcbiAgICAgICAgY29uc3QgdmFsdWVBdCA9IChpZHgpPT4oe1xuICAgICAgICAgICAgICAgIHdpZHRoOiB3aWR0aHNbaWR4XSB8fCAwLFxuICAgICAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0c1tpZHhdIHx8IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZmlyc3Q6IHZhbHVlQXQoMCksXG4gICAgICAgICAgICBsYXN0OiB2YWx1ZUF0KGxlbmd0aCAtIDEpLFxuICAgICAgICAgICAgd2lkZXN0OiB2YWx1ZUF0KHdpZGVzdCksXG4gICAgICAgICAgICBoaWdoZXN0OiB2YWx1ZUF0KGhpZ2hlc3QpLFxuICAgICAgICAgICAgd2lkdGhzLFxuICAgICAgICAgICAgaGVpZ2h0c1xuICAgICAgICB9O1xuICAgIH1cbiBnZXRMYWJlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIE5hTjtcbiAgICB9XG4gZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge31cbiBnZXRQaXhlbEZvclRpY2soaW5kZXgpIHtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBpZiAoaW5kZXggPCAwIHx8IGluZGV4ID4gdGlja3MubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGl4ZWxGb3JWYWx1ZSh0aWNrc1tpbmRleF0udmFsdWUpO1xuICAgIH1cbiBnZXRQaXhlbEZvckRlY2ltYWwoZGVjaW1hbCkge1xuICAgICAgICBpZiAodGhpcy5fcmV2ZXJzZVBpeGVscykge1xuICAgICAgICAgICAgZGVjaW1hbCA9IDEgLSBkZWNpbWFsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBpeGVsID0gdGhpcy5fc3RhcnRQaXhlbCArIGRlY2ltYWwgKiB0aGlzLl9sZW5ndGg7XG4gICAgICAgIHJldHVybiBfaW50MTZSYW5nZSh0aGlzLl9hbGlnblRvUGl4ZWxzID8gX2FsaWduUGl4ZWwodGhpcy5jaGFydCwgcGl4ZWwsIDApIDogcGl4ZWwpO1xuICAgIH1cbiBnZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpIHtcbiAgICAgICAgY29uc3QgZGVjaW1hbCA9IChwaXhlbCAtIHRoaXMuX3N0YXJ0UGl4ZWwpIC8gdGhpcy5fbGVuZ3RoO1xuICAgICAgICByZXR1cm4gdGhpcy5fcmV2ZXJzZVBpeGVscyA/IDEgLSBkZWNpbWFsIDogZGVjaW1hbDtcbiAgICB9XG4gZ2V0QmFzZVBpeGVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaXhlbEZvclZhbHVlKHRoaXMuZ2V0QmFzZVZhbHVlKCkpO1xuICAgIH1cbiBnZXRCYXNlVmFsdWUoKSB7XG4gICAgICAgIGNvbnN0IHsgbWluICwgbWF4ICB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG1pbiA8IDAgJiYgbWF4IDwgMCA/IG1heCA6IG1pbiA+IDAgJiYgbWF4ID4gMCA/IG1pbiA6IDA7XG4gICAgfVxuIGdldENvbnRleHQoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzIHx8IFtdO1xuICAgICAgICBpZiAoaW5kZXggPj0gMCAmJiBpbmRleCA8IHRpY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgdGljayA9IHRpY2tzW2luZGV4XTtcbiAgICAgICAgICAgIHJldHVybiB0aWNrLiRjb250ZXh0IHx8ICh0aWNrLiRjb250ZXh0ID0gY3JlYXRlVGlja0NvbnRleHQodGhpcy5nZXRDb250ZXh0KCksIGluZGV4LCB0aWNrKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuJGNvbnRleHQgfHwgKHRoaXMuJGNvbnRleHQgPSBjcmVhdGVTY2FsZUNvbnRleHQodGhpcy5jaGFydC5nZXRDb250ZXh0KCksIHRoaXMpKTtcbiAgICB9XG4gX3RpY2tTaXplKCkge1xuICAgICAgICBjb25zdCBvcHRpb25UaWNrcyA9IHRoaXMub3B0aW9ucy50aWNrcztcbiAgICAgICAgY29uc3Qgcm90ID0gdG9SYWRpYW5zKHRoaXMubGFiZWxSb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IGNvcyA9IE1hdGguYWJzKE1hdGguY29zKHJvdCkpO1xuICAgICAgICBjb25zdCBzaW4gPSBNYXRoLmFicyhNYXRoLnNpbihyb3QpKTtcbiAgICAgICAgY29uc3QgbGFiZWxTaXplcyA9IHRoaXMuX2dldExhYmVsU2l6ZXMoKTtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IG9wdGlvblRpY2tzLmF1dG9Ta2lwUGFkZGluZyB8fCAwO1xuICAgICAgICBjb25zdCB3ID0gbGFiZWxTaXplcyA/IGxhYmVsU2l6ZXMud2lkZXN0LndpZHRoICsgcGFkZGluZyA6IDA7XG4gICAgICAgIGNvbnN0IGggPSBsYWJlbFNpemVzID8gbGFiZWxTaXplcy5oaWdoZXN0LmhlaWdodCArIHBhZGRpbmcgOiAwO1xuICAgICAgICByZXR1cm4gdGhpcy5pc0hvcml6b250YWwoKSA/IGggKiBjb3MgPiB3ICogc2luID8gdyAvIGNvcyA6IGggLyBzaW4gOiBoICogc2luIDwgdyAqIGNvcyA/IGggLyBjb3MgOiB3IC8gc2luO1xuICAgIH1cbiBfaXNWaXNpYmxlKCkge1xuICAgICAgICBjb25zdCBkaXNwbGF5ID0gdGhpcy5vcHRpb25zLmRpc3BsYXk7XG4gICAgICAgIGlmIChkaXNwbGF5ICE9PSAnYXV0bycpIHtcbiAgICAgICAgICAgIHJldHVybiAhIWRpc3BsYXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoKS5sZW5ndGggPiAwO1xuICAgIH1cbiBfY29tcHV0ZUdyaWRMaW5lSXRlbXMoY2hhcnRBcmVhKSB7XG4gICAgICAgIGNvbnN0IGF4aXMgPSB0aGlzLmF4aXM7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgeyBncmlkICwgcG9zaXRpb24gLCBib3JkZXIgIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBncmlkLm9mZnNldDtcbiAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gdGhpcy5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBjb25zdCB0aWNrc0xlbmd0aCA9IHRpY2tzLmxlbmd0aCArIChvZmZzZXQgPyAxIDogMCk7XG4gICAgICAgIGNvbnN0IHRsID0gZ2V0VGlja01hcmtMZW5ndGgoZ3JpZCk7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgICAgIGNvbnN0IGJvcmRlck9wdHMgPSBib3JkZXIuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIGNvbnN0IGF4aXNXaWR0aCA9IGJvcmRlck9wdHMuZGlzcGxheSA/IGJvcmRlck9wdHMud2lkdGggOiAwO1xuICAgICAgICBjb25zdCBheGlzSGFsZldpZHRoID0gYXhpc1dpZHRoIC8gMjtcbiAgICAgICAgY29uc3QgYWxpZ25Cb3JkZXJWYWx1ZSA9IGZ1bmN0aW9uKHBpeGVsKSB7XG4gICAgICAgICAgICByZXR1cm4gX2FsaWduUGl4ZWwoY2hhcnQsIHBpeGVsLCBheGlzV2lkdGgpO1xuICAgICAgICB9O1xuICAgICAgICBsZXQgYm9yZGVyVmFsdWUsIGksIGxpbmVWYWx1ZSwgYWxpZ25lZExpbmVWYWx1ZTtcbiAgICAgICAgbGV0IHR4MSwgdHkxLCB0eDIsIHR5MiwgeDEsIHkxLCB4MiwgeTI7XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLmJvdHRvbSk7XG4gICAgICAgICAgICB0eTEgPSB0aGlzLmJvdHRvbSAtIHRsO1xuICAgICAgICAgICAgdHkyID0gYm9yZGVyVmFsdWUgLSBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgeTEgPSBhbGlnbkJvcmRlclZhbHVlKGNoYXJ0QXJlYS50b3ApICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHkyID0gY2hhcnRBcmVhLmJvdHRvbTtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLnRvcCk7XG4gICAgICAgICAgICB5MSA9IGNoYXJ0QXJlYS50b3A7XG4gICAgICAgICAgICB5MiA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLmJvdHRvbSkgLSBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgdHkxID0gYm9yZGVyVmFsdWUgKyBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgdHkyID0gdGhpcy50b3AgKyB0bDtcbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICBib3JkZXJWYWx1ZSA9IGFsaWduQm9yZGVyVmFsdWUodGhpcy5yaWdodCk7XG4gICAgICAgICAgICB0eDEgPSB0aGlzLnJpZ2h0IC0gdGw7XG4gICAgICAgICAgICB0eDIgPSBib3JkZXJWYWx1ZSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB4MSA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLmxlZnQpICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHgyID0gY2hhcnRBcmVhLnJpZ2h0O1xuICAgICAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICBib3JkZXJWYWx1ZSA9IGFsaWduQm9yZGVyVmFsdWUodGhpcy5sZWZ0KTtcbiAgICAgICAgICAgIHgxID0gY2hhcnRBcmVhLmxlZnQ7XG4gICAgICAgICAgICB4MiA9IGFsaWduQm9yZGVyVmFsdWUoY2hhcnRBcmVhLnJpZ2h0KSAtIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB0eDEgPSBib3JkZXJWYWx1ZSArIGF4aXNIYWxmV2lkdGg7XG4gICAgICAgICAgICB0eDIgPSB0aGlzLmxlZnQgKyB0bDtcbiAgICAgICAgfSBlbHNlIGlmIChheGlzID09PSAneCcpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgICAgICBib3JkZXJWYWx1ZSA9IGFsaWduQm9yZGVyVmFsdWUoKGNoYXJ0QXJlYS50b3AgKyBjaGFydEFyZWEuYm90dG9tKSAvIDIgKyAwLjUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChwb3NpdGlvbikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbkF4aXNJRCA9IE9iamVjdC5rZXlzKHBvc2l0aW9uKVswXTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBvc2l0aW9uW3Bvc2l0aW9uQXhpc0lEXTtcbiAgICAgICAgICAgICAgICBib3JkZXJWYWx1ZSA9IGFsaWduQm9yZGVyVmFsdWUodGhpcy5jaGFydC5zY2FsZXNbcG9zaXRpb25BeGlzSURdLmdldFBpeGVsRm9yVmFsdWUodmFsdWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkxID0gY2hhcnRBcmVhLnRvcDtcbiAgICAgICAgICAgIHkyID0gY2hhcnRBcmVhLmJvdHRvbTtcbiAgICAgICAgICAgIHR5MSA9IGJvcmRlclZhbHVlICsgYXhpc0hhbGZXaWR0aDtcbiAgICAgICAgICAgIHR5MiA9IHR5MSArIHRsO1xuICAgICAgICB9IGVsc2UgaWYgKGF4aXMgPT09ICd5Jykge1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSgoY2hhcnRBcmVhLmxlZnQgKyBjaGFydEFyZWEucmlnaHQpIC8gMik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcG9zaXRpb25bcG9zaXRpb25BeGlzSURdO1xuICAgICAgICAgICAgICAgIGJvcmRlclZhbHVlID0gYWxpZ25Cb3JkZXJWYWx1ZSh0aGlzLmNoYXJ0LnNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHgxID0gYm9yZGVyVmFsdWUgLSBheGlzSGFsZldpZHRoO1xuICAgICAgICAgICAgdHgyID0gdHgxIC0gdGw7XG4gICAgICAgICAgICB4MSA9IGNoYXJ0QXJlYS5sZWZ0O1xuICAgICAgICAgICAgeDIgPSBjaGFydEFyZWEucmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGltaXQgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLnRpY2tzLm1heFRpY2tzTGltaXQsIHRpY2tzTGVuZ3RoKTtcbiAgICAgICAgY29uc3Qgc3RlcCA9IE1hdGgubWF4KDEsIE1hdGguY2VpbCh0aWNrc0xlbmd0aCAvIGxpbWl0KSk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHRpY2tzTGVuZ3RoOyBpICs9IHN0ZXApe1xuICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuZ2V0Q29udGV4dChpKTtcbiAgICAgICAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gZ3JpZC5zZXRDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXhCb3JkZXIgPSBib3JkZXIuc2V0Q29udGV4dChjb250ZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IG9wdHNBdEluZGV4LmxpbmVXaWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVDb2xvciA9IG9wdHNBdEluZGV4LmNvbG9yO1xuICAgICAgICAgICAgY29uc3QgYm9yZGVyRGFzaCA9IG9wdHNBdEluZGV4Qm9yZGVyLmRhc2ggfHwgW107XG4gICAgICAgICAgICBjb25zdCBib3JkZXJEYXNoT2Zmc2V0ID0gb3B0c0F0SW5kZXhCb3JkZXIuZGFzaE9mZnNldDtcbiAgICAgICAgICAgIGNvbnN0IHRpY2tXaWR0aCA9IG9wdHNBdEluZGV4LnRpY2tXaWR0aDtcbiAgICAgICAgICAgIGNvbnN0IHRpY2tDb2xvciA9IG9wdHNBdEluZGV4LnRpY2tDb2xvcjtcbiAgICAgICAgICAgIGNvbnN0IHRpY2tCb3JkZXJEYXNoID0gb3B0c0F0SW5kZXgudGlja0JvcmRlckRhc2ggfHwgW107XG4gICAgICAgICAgICBjb25zdCB0aWNrQm9yZGVyRGFzaE9mZnNldCA9IG9wdHNBdEluZGV4LnRpY2tCb3JkZXJEYXNoT2Zmc2V0O1xuICAgICAgICAgICAgbGluZVZhbHVlID0gZ2V0UGl4ZWxGb3JHcmlkTGluZSh0aGlzLCBpLCBvZmZzZXQpO1xuICAgICAgICAgICAgaWYgKGxpbmVWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbGlnbmVkTGluZVZhbHVlID0gX2FsaWduUGl4ZWwoY2hhcnQsIGxpbmVWYWx1ZSwgbGluZVdpZHRoKTtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICB0eDEgPSB0eDIgPSB4MSA9IHgyID0gYWxpZ25lZExpbmVWYWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHkxID0gdHkyID0geTEgPSB5MiA9IGFsaWduZWRMaW5lVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpdGVtcy5wdXNoKHtcbiAgICAgICAgICAgICAgICB0eDEsXG4gICAgICAgICAgICAgICAgdHkxLFxuICAgICAgICAgICAgICAgIHR4MixcbiAgICAgICAgICAgICAgICB0eTIsXG4gICAgICAgICAgICAgICAgeDEsXG4gICAgICAgICAgICAgICAgeTEsXG4gICAgICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICAgICAgeTIsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGxpbmVXaWR0aCxcbiAgICAgICAgICAgICAgICBjb2xvcjogbGluZUNvbG9yLFxuICAgICAgICAgICAgICAgIGJvcmRlckRhc2gsXG4gICAgICAgICAgICAgICAgYm9yZGVyRGFzaE9mZnNldCxcbiAgICAgICAgICAgICAgICB0aWNrV2lkdGgsXG4gICAgICAgICAgICAgICAgdGlja0NvbG9yLFxuICAgICAgICAgICAgICAgIHRpY2tCb3JkZXJEYXNoLFxuICAgICAgICAgICAgICAgIHRpY2tCb3JkZXJEYXNoT2Zmc2V0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl90aWNrc0xlbmd0aCA9IHRpY2tzTGVuZ3RoO1xuICAgICAgICB0aGlzLl9ib3JkZXJWYWx1ZSA9IGJvcmRlclZhbHVlO1xuICAgICAgICByZXR1cm4gaXRlbXM7XG4gICAgfVxuIF9jb21wdXRlTGFiZWxJdGVtcyhjaGFydEFyZWEpIHtcbiAgICAgICAgY29uc3QgYXhpcyA9IHRoaXMuYXhpcztcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgeyBwb3NpdGlvbiAsIHRpY2tzOiBvcHRpb25UaWNrcyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IHRoaXMuaXNIb3Jpem9udGFsKCk7XG4gICAgICAgIGNvbnN0IHRpY2tzID0gdGhpcy50aWNrcztcbiAgICAgICAgY29uc3QgeyBhbGlnbiAsIGNyb3NzQWxpZ24gLCBwYWRkaW5nICwgbWlycm9yICB9ID0gb3B0aW9uVGlja3M7XG4gICAgICAgIGNvbnN0IHRsID0gZ2V0VGlja01hcmtMZW5ndGgob3B0aW9ucy5ncmlkKTtcbiAgICAgICAgY29uc3QgdGlja0FuZFBhZGRpbmcgPSB0bCArIHBhZGRpbmc7XG4gICAgICAgIGNvbnN0IGhUaWNrQW5kUGFkZGluZyA9IG1pcnJvciA/IC1wYWRkaW5nIDogdGlja0FuZFBhZGRpbmc7XG4gICAgICAgIGNvbnN0IHJvdGF0aW9uID0gLXRvUmFkaWFucyh0aGlzLmxhYmVsUm90YXRpb24pO1xuICAgICAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbiwgdGljaywgbGFiZWwsIHgsIHksIHRleHRBbGlnbiwgcGl4ZWwsIGZvbnQsIGxpbmVIZWlnaHQsIGxpbmVDb3VudCwgdGV4dE9mZnNldDtcbiAgICAgICAgbGV0IHRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICBpZiAocG9zaXRpb24gPT09ICd0b3AnKSB7XG4gICAgICAgICAgICB5ID0gdGhpcy5ib3R0b20gLSBoVGlja0FuZFBhZGRpbmc7XG4gICAgICAgICAgICB0ZXh0QWxpZ24gPSB0aGlzLl9nZXRYQXhpc0xhYmVsQWxpZ25tZW50KCk7XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICB5ID0gdGhpcy50b3AgKyBoVGlja0FuZFBhZGRpbmc7XG4gICAgICAgICAgICB0ZXh0QWxpZ24gPSB0aGlzLl9nZXRYQXhpc0xhYmVsQWxpZ25tZW50KCk7XG4gICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gdGhpcy5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudCh0bCk7XG4gICAgICAgICAgICB0ZXh0QWxpZ24gPSByZXQudGV4dEFsaWduO1xuICAgICAgICAgICAgeCA9IHJldC54O1xuICAgICAgICB9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSB0aGlzLl9nZXRZQXhpc0xhYmVsQWxpZ25tZW50KHRsKTtcbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHJldC50ZXh0QWxpZ247XG4gICAgICAgICAgICB4ID0gcmV0Lng7XG4gICAgICAgIH0gZWxzZSBpZiAoYXhpcyA9PT0gJ3gnKSB7XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgeSA9IChjaGFydEFyZWEudG9wICsgY2hhcnRBcmVhLmJvdHRvbSkgLyAyICsgdGlja0FuZFBhZGRpbmc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQXhpc0lEID0gT2JqZWN0LmtleXMocG9zaXRpb24pWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcG9zaXRpb25bcG9zaXRpb25BeGlzSURdO1xuICAgICAgICAgICAgICAgIHkgPSB0aGlzLmNoYXJ0LnNjYWxlc1twb3NpdGlvbkF4aXNJRF0uZ2V0UGl4ZWxGb3JWYWx1ZSh2YWx1ZSkgKyB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHRoaXMuX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChheGlzID09PSAneScpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICAgICAgICB4ID0gKGNoYXJ0QXJlYS5sZWZ0ICsgY2hhcnRBcmVhLnJpZ2h0KSAvIDIgLSB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25BeGlzSUQgPSBPYmplY3Qua2V5cyhwb3NpdGlvbilbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwb3NpdGlvbltwb3NpdGlvbkF4aXNJRF07XG4gICAgICAgICAgICAgICAgeCA9IHRoaXMuY2hhcnQuc2NhbGVzW3Bvc2l0aW9uQXhpc0lEXS5nZXRQaXhlbEZvclZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRleHRBbGlnbiA9IHRoaXMuX2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodGwpLnRleHRBbGlnbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXhpcyA9PT0gJ3knKSB7XG4gICAgICAgICAgICBpZiAoYWxpZ24gPT09ICdzdGFydCcpIHtcbiAgICAgICAgICAgICAgICB0ZXh0QmFzZWxpbmUgPSAndG9wJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxpZ24gPT09ICdlbmQnKSB7XG4gICAgICAgICAgICAgICAgdGV4dEJhc2VsaW5lID0gJ2JvdHRvbSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGFiZWxTaXplcyA9IHRoaXMuX2dldExhYmVsU2l6ZXMoKTtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gdGlja3MubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRpY2sgPSB0aWNrc1tpXTtcbiAgICAgICAgICAgIGxhYmVsID0gdGljay5sYWJlbDtcbiAgICAgICAgICAgIGNvbnN0IG9wdHNBdEluZGV4ID0gb3B0aW9uVGlja3Muc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoaSkpO1xuICAgICAgICAgICAgcGl4ZWwgPSB0aGlzLmdldFBpeGVsRm9yVGljayhpKSArIG9wdGlvblRpY2tzLmxhYmVsT2Zmc2V0O1xuICAgICAgICAgICAgZm9udCA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoaSk7XG4gICAgICAgICAgICBsaW5lSGVpZ2h0ID0gZm9udC5saW5lSGVpZ2h0O1xuICAgICAgICAgICAgbGluZUNvdW50ID0gaXNBcnJheShsYWJlbCkgPyBsYWJlbC5sZW5ndGggOiAxO1xuICAgICAgICAgICAgY29uc3QgaGFsZkNvdW50ID0gbGluZUNvdW50IC8gMjtcbiAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gb3B0c0F0SW5kZXguY29sb3I7XG4gICAgICAgICAgICBjb25zdCBzdHJva2VDb2xvciA9IG9wdHNBdEluZGV4LnRleHRTdHJva2VDb2xvcjtcbiAgICAgICAgICAgIGNvbnN0IHN0cm9rZVdpZHRoID0gb3B0c0F0SW5kZXgudGV4dFN0cm9rZVdpZHRoO1xuICAgICAgICAgICAgbGV0IHRpY2tUZXh0QWxpZ24gPSB0ZXh0QWxpZ247XG4gICAgICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgeCA9IHBpeGVsO1xuICAgICAgICAgICAgICAgIGlmICh0ZXh0QWxpZ24gPT09ICdpbm5lcicpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT09IGlsZW4gLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aWNrVGV4dEFsaWduID0gIXRoaXMub3B0aW9ucy5yZXZlcnNlID8gJ3JpZ2h0JyA6ICdsZWZ0JztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aWNrVGV4dEFsaWduID0gIXRoaXMub3B0aW9ucy5yZXZlcnNlID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tUZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjcm9zc0FsaWduID09PSAnbmVhcicgfHwgcm90YXRpb24gIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSAtbGluZUNvdW50ICogbGluZUhlaWdodCArIGxpbmVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gLWxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLyAyIC0gaGFsZkNvdW50ICogbGluZUhlaWdodCArIGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gLWxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgKyBsaW5lSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjcm9zc0FsaWduID09PSAnbmVhcicgfHwgcm90YXRpb24gIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSBsaW5lSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcm9zc0FsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dE9mZnNldCA9IGxhYmVsU2l6ZXMuaGlnaGVzdC5oZWlnaHQgLyAyIC0gaGFsZkNvdW50ICogbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgPSBsYWJlbFNpemVzLmhpZ2hlc3QuaGVpZ2h0IC0gbGluZUNvdW50ICogbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWlycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRPZmZzZXQgKj0gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyb3RhdGlvbiAhPT0gMCAmJiAhb3B0c0F0SW5kZXguc2hvd0xhYmVsQmFja2Ryb3ApIHtcbiAgICAgICAgICAgICAgICAgICAgeCArPSBsaW5lSGVpZ2h0IC8gMiAqIE1hdGguc2luKHJvdGF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHkgPSBwaXhlbDtcbiAgICAgICAgICAgICAgICB0ZXh0T2Zmc2V0ID0gKDEgLSBsaW5lQ291bnQpICogbGluZUhlaWdodCAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYmFja2Ryb3A7XG4gICAgICAgICAgICBpZiAob3B0c0F0SW5kZXguc2hvd0xhYmVsQmFja2Ryb3ApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsYWJlbFBhZGRpbmcgPSB0b1BhZGRpbmcob3B0c0F0SW5kZXguYmFja2Ryb3BQYWRkaW5nKTtcbiAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBsYWJlbFNpemVzLmhlaWdodHNbaV07XG4gICAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBsYWJlbFNpemVzLndpZHRoc1tpXTtcbiAgICAgICAgICAgICAgICBsZXQgdG9wID0gdGV4dE9mZnNldCAtIGxhYmVsUGFkZGluZy50b3A7XG4gICAgICAgICAgICAgICAgbGV0IGxlZnQgPSAwIC0gbGFiZWxQYWRkaW5nLmxlZnQ7XG4gICAgICAgICAgICAgICAgc3dpdGNoKHRleHRCYXNlbGluZSl7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pZGRsZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3AgLT0gaGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wIC09IGhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzd2l0Y2godGV4dEFsaWduKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnY2VudGVyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgLT0gd2lkdGggLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgLT0gd2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYmFja2Ryb3AgPSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQsXG4gICAgICAgICAgICAgICAgICAgIHRvcCxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHdpZHRoICsgbGFiZWxQYWRkaW5nLndpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCArIGxhYmVsUGFkZGluZy5oZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBvcHRzQXRJbmRleC5iYWNrZHJvcENvbG9yXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICAgICAgICAgIGxhYmVsLFxuICAgICAgICAgICAgICAgIGZvbnQsXG4gICAgICAgICAgICAgICAgdGV4dE9mZnNldCxcbiAgICAgICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uLFxuICAgICAgICAgICAgICAgICAgICBjb2xvcixcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZVdpZHRoLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ246IHRpY2tUZXh0QWxpZ24sXG4gICAgICAgICAgICAgICAgICAgIHRleHRCYXNlbGluZSxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRpb246IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgICAgICAgICB5XG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgIGJhY2tkcm9wXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH1cbiAgICBfZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpIHtcbiAgICAgICAgY29uc3QgeyBwb3NpdGlvbiAsIHRpY2tzICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCByb3RhdGlvbiA9IC10b1JhZGlhbnModGhpcy5sYWJlbFJvdGF0aW9uKTtcbiAgICAgICAgaWYgKHJvdGF0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gcG9zaXRpb24gPT09ICd0b3AnID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgICAgICAgfVxuICAgICAgICBsZXQgYWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgaWYgKHRpY2tzLmFsaWduID09PSAnc3RhcnQnKSB7XG4gICAgICAgICAgICBhbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgfSBlbHNlIGlmICh0aWNrcy5hbGlnbiA9PT0gJ2VuZCcpIHtcbiAgICAgICAgICAgIGFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgfSBlbHNlIGlmICh0aWNrcy5hbGlnbiA9PT0gJ2lubmVyJykge1xuICAgICAgICAgICAgYWxpZ24gPSAnaW5uZXInO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhbGlnbjtcbiAgICB9XG4gICAgX2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodGwpIHtcbiAgICAgICAgY29uc3QgeyBwb3NpdGlvbiAsIHRpY2tzOiB7IGNyb3NzQWxpZ24gLCBtaXJyb3IgLCBwYWRkaW5nICB9ICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBsYWJlbFNpemVzID0gdGhpcy5fZ2V0TGFiZWxTaXplcygpO1xuICAgICAgICBjb25zdCB0aWNrQW5kUGFkZGluZyA9IHRsICsgcGFkZGluZztcbiAgICAgICAgY29uc3Qgd2lkZXN0ID0gbGFiZWxTaXplcy53aWRlc3Qud2lkdGg7XG4gICAgICAgIGxldCB0ZXh0QWxpZ247XG4gICAgICAgIGxldCB4O1xuICAgICAgICBpZiAocG9zaXRpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgaWYgKG1pcnJvcikge1xuICAgICAgICAgICAgICAgIHggPSB0aGlzLnJpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgICAgICAgICAgICB4ICs9IHdpZGVzdCAvIDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICAgICAgeCArPSB3aWRlc3Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB4ID0gdGhpcy5yaWdodCAtIHRpY2tBbmRQYWRkaW5nO1xuICAgICAgICAgICAgICAgIGlmIChjcm9zc0FsaWduID09PSAnbmVhcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgICAgICAgICAgICB4IC09IHdpZGVzdCAvIDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICAgICAgICAgICAgICB4ID0gdGhpcy5sZWZ0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgaWYgKG1pcnJvcikge1xuICAgICAgICAgICAgICAgIHggPSB0aGlzLmxlZnQgKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGlmIChjcm9zc0FsaWduID09PSAnbmVhcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgICAgICAgICAgICB4IC09IHdpZGVzdCAvIDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICAgICAgICAgICAgICB4IC09IHdpZGVzdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHggPSB0aGlzLmxlZnQgKyB0aWNrQW5kUGFkZGluZztcbiAgICAgICAgICAgICAgICBpZiAoY3Jvc3NBbGlnbiA9PT0gJ25lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdsZWZ0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyb3NzQWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAgICAgICAgICAgICB4ICs9IHdpZGVzdCAvIDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgICAgICAgICAgICAgeCA9IHRoaXMucmlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdGV4dEFsaWduLFxuICAgICAgICAgICAgeFxuICAgICAgICB9O1xuICAgIH1cbiBfY29tcHV0ZUxhYmVsQXJlYSgpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy50aWNrcy5taXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFydCA9IHRoaXMuY2hhcnQ7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5vcHRpb25zLnBvc2l0aW9uO1xuICAgICAgICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICAgICAgbGVmdDogdGhpcy5sZWZ0LFxuICAgICAgICAgICAgICAgIGJvdHRvbTogY2hhcnQuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHJpZ2h0OiB0aGlzLnJpZ2h0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHRvcDogdGhpcy50b3AsXG4gICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICBib3R0b206IHRoaXMuYm90dG9tLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBjaGFydC53aWR0aFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiBkcmF3QmFja2dyb3VuZCgpIHtcbiAgICAgICAgY29uc3QgeyBjdHggLCBvcHRpb25zOiB7IGJhY2tncm91bmRDb2xvciAgfSAsIGxlZnQgLCB0b3AgLCB3aWR0aCAsIGhlaWdodCAgfSA9IHRoaXM7XG4gICAgICAgIGlmIChiYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gYmFja2dyb3VuZENvbG9yO1xuICAgICAgICAgICAgY3R4LmZpbGxSZWN0KGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldExpbmVXaWR0aEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGdyaWQgPSB0aGlzLm9wdGlvbnMuZ3JpZDtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1Zpc2libGUoKSB8fCAhZ3JpZC5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0aWNrcyA9IHRoaXMudGlja3M7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGlja3MuZmluZEluZGV4KCh0KT0+dC52YWx1ZSA9PT0gdmFsdWUpO1xuICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgICAgICAgY29uc3Qgb3B0cyA9IGdyaWQuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoaW5kZXgpKTtcbiAgICAgICAgICAgIHJldHVybiBvcHRzLmxpbmVXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gZHJhd0dyaWQoY2hhcnRBcmVhKSB7XG4gICAgICAgIGNvbnN0IGdyaWQgPSB0aGlzLm9wdGlvbnMuZ3JpZDtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5fZ3JpZExpbmVJdGVtcyB8fCAodGhpcy5fZ3JpZExpbmVJdGVtcyA9IHRoaXMuX2NvbXB1dGVHcmlkTGluZUl0ZW1zKGNoYXJ0QXJlYSkpO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgY29uc3QgZHJhd0xpbmUgPSAocDEsIHAyLCBzdHlsZSk9PntcbiAgICAgICAgICAgIGlmICghc3R5bGUud2lkdGggfHwgIXN0eWxlLmNvbG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBzdHlsZS53aWR0aDtcbiAgICAgICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IHN0eWxlLmNvbG9yO1xuICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKHN0eWxlLmJvcmRlckRhc2ggfHwgW10pO1xuICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gc3R5bGUuYm9yZGVyRGFzaE9mZnNldDtcbiAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8ocDEueCwgcDEueSk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHAyLngsIHAyLnkpO1xuICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGdyaWQuZGlzcGxheSkge1xuICAgICAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gaXRlbXMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgICAgICBjb25zdCBpdGVtID0gaXRlbXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGdyaWQuZHJhd09uQ2hhcnRBcmVhKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYXdMaW5lKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGl0ZW0ueDEsXG4gICAgICAgICAgICAgICAgICAgICAgICB5OiBpdGVtLnkxXG4gICAgICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGl0ZW0ueDIsXG4gICAgICAgICAgICAgICAgICAgICAgICB5OiBpdGVtLnkyXG4gICAgICAgICAgICAgICAgICAgIH0sIGl0ZW0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZ3JpZC5kcmF3VGlja3MpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJhd0xpbmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgeDogaXRlbS50eDEsXG4gICAgICAgICAgICAgICAgICAgICAgICB5OiBpdGVtLnR5MVxuICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4OiBpdGVtLnR4MixcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IGl0ZW0udHkyXG4gICAgICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBpdGVtLnRpY2tDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBpdGVtLnRpY2tXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlckRhc2g6IGl0ZW0udGlja0JvcmRlckRhc2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJEYXNoT2Zmc2V0OiBpdGVtLnRpY2tCb3JkZXJEYXNoT2Zmc2V0XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiBkcmF3Qm9yZGVyKCkge1xuICAgICAgICBjb25zdCB7IGNoYXJ0ICwgY3R4ICwgb3B0aW9uczogeyBib3JkZXIgLCBncmlkICB9ICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgYm9yZGVyT3B0cyA9IGJvcmRlci5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY29uc3QgYXhpc1dpZHRoID0gYm9yZGVyLmRpc3BsYXkgPyBib3JkZXJPcHRzLndpZHRoIDogMDtcbiAgICAgICAgaWYgKCFheGlzV2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsYXN0TGluZVdpZHRoID0gZ3JpZC5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgwKSkubGluZVdpZHRoO1xuICAgICAgICBjb25zdCBib3JkZXJWYWx1ZSA9IHRoaXMuX2JvcmRlclZhbHVlO1xuICAgICAgICBsZXQgeDEsIHgyLCB5MSwgeTI7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB4MSA9IF9hbGlnblBpeGVsKGNoYXJ0LCB0aGlzLmxlZnQsIGF4aXNXaWR0aCkgLSBheGlzV2lkdGggLyAyO1xuICAgICAgICAgICAgeDIgPSBfYWxpZ25QaXhlbChjaGFydCwgdGhpcy5yaWdodCwgbGFzdExpbmVXaWR0aCkgKyBsYXN0TGluZVdpZHRoIC8gMjtcbiAgICAgICAgICAgIHkxID0geTIgPSBib3JkZXJWYWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHkxID0gX2FsaWduUGl4ZWwoY2hhcnQsIHRoaXMudG9wLCBheGlzV2lkdGgpIC0gYXhpc1dpZHRoIC8gMjtcbiAgICAgICAgICAgIHkyID0gX2FsaWduUGl4ZWwoY2hhcnQsIHRoaXMuYm90dG9tLCBsYXN0TGluZVdpZHRoKSArIGxhc3RMaW5lV2lkdGggLyAyO1xuICAgICAgICAgICAgeDEgPSB4MiA9IGJvcmRlclZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSBib3JkZXJPcHRzLndpZHRoO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBib3JkZXJPcHRzLmNvbG9yO1xuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5tb3ZlVG8oeDEsIHkxKTtcbiAgICAgICAgY3R4LmxpbmVUbyh4MiwgeTIpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgfVxuIGRyYXdMYWJlbHMoY2hhcnRBcmVhKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvblRpY2tzID0gdGhpcy5vcHRpb25zLnRpY2tzO1xuICAgICAgICBpZiAoIW9wdGlvblRpY2tzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICAgICAgY29uc3QgYXJlYSA9IHRoaXMuX2NvbXB1dGVMYWJlbEFyZWEoKTtcbiAgICAgICAgaWYgKGFyZWEpIHtcbiAgICAgICAgICAgIGNsaXBBcmVhKGN0eCwgYXJlYSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLmdldExhYmVsSXRlbXMoY2hhcnRBcmVhKTtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKXtcbiAgICAgICAgICAgIGNvbnN0IHJlbmRlclRleHRPcHRpb25zID0gaXRlbS5vcHRpb25zO1xuICAgICAgICAgICAgY29uc3QgdGlja0ZvbnQgPSBpdGVtLmZvbnQ7XG4gICAgICAgICAgICBjb25zdCBsYWJlbCA9IGl0ZW0ubGFiZWw7XG4gICAgICAgICAgICBjb25zdCB5ID0gaXRlbS50ZXh0T2Zmc2V0O1xuICAgICAgICAgICAgcmVuZGVyVGV4dChjdHgsIGxhYmVsLCAwLCB5LCB0aWNrRm9udCwgcmVuZGVyVGV4dE9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhcmVhKSB7XG4gICAgICAgICAgICB1bmNsaXBBcmVhKGN0eCk7XG4gICAgICAgIH1cbiAgICB9XG4gZHJhd1RpdGxlKCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIG9wdGlvbnM6IHsgcG9zaXRpb24gLCB0aXRsZSAsIHJldmVyc2UgIH0gIH0gPSB0aGlzO1xuICAgICAgICBpZiAoIXRpdGxlLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmb250ID0gdG9Gb250KHRpdGxlLmZvbnQpO1xuICAgICAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKHRpdGxlLnBhZGRpbmcpO1xuICAgICAgICBjb25zdCBhbGlnbiA9IHRpdGxlLmFsaWduO1xuICAgICAgICBsZXQgb2Zmc2V0ID0gZm9udC5saW5lSGVpZ2h0IC8gMjtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAnYm90dG9tJyB8fCBwb3NpdGlvbiA9PT0gJ2NlbnRlcicgfHwgaXNPYmplY3QocG9zaXRpb24pKSB7XG4gICAgICAgICAgICBvZmZzZXQgKz0gcGFkZGluZy5ib3R0b207XG4gICAgICAgICAgICBpZiAoaXNBcnJheSh0aXRsZS50ZXh0KSkge1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSBmb250LmxpbmVIZWlnaHQgKiAodGl0bGUudGV4dC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9mZnNldCArPSBwYWRkaW5nLnRvcDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHRpdGxlWCAsIHRpdGxlWSAsIG1heFdpZHRoICwgcm90YXRpb24gIH0gPSB0aXRsZUFyZ3ModGhpcywgb2Zmc2V0LCBwb3NpdGlvbiwgYWxpZ24pO1xuICAgICAgICByZW5kZXJUZXh0KGN0eCwgdGl0bGUudGV4dCwgMCwgMCwgZm9udCwge1xuICAgICAgICAgICAgY29sb3I6IHRpdGxlLmNvbG9yLFxuICAgICAgICAgICAgbWF4V2lkdGgsXG4gICAgICAgICAgICByb3RhdGlvbixcbiAgICAgICAgICAgIHRleHRBbGlnbjogdGl0bGVBbGlnbihhbGlnbiwgcG9zaXRpb24sIHJldmVyc2UpLFxuICAgICAgICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJyxcbiAgICAgICAgICAgIHRyYW5zbGF0aW9uOiBbXG4gICAgICAgICAgICAgICAgdGl0bGVYLFxuICAgICAgICAgICAgICAgIHRpdGxlWVxuICAgICAgICAgICAgXVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZHJhdyhjaGFydEFyZWEpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1Zpc2libGUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZHJhd0JhY2tncm91bmQoKTtcbiAgICAgICAgdGhpcy5kcmF3R3JpZChjaGFydEFyZWEpO1xuICAgICAgICB0aGlzLmRyYXdCb3JkZXIoKTtcbiAgICAgICAgdGhpcy5kcmF3VGl0bGUoKTtcbiAgICAgICAgdGhpcy5kcmF3TGFiZWxzKGNoYXJ0QXJlYSk7XG4gICAgfVxuIF9sYXllcnMoKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHR6ID0gb3B0cy50aWNrcyAmJiBvcHRzLnRpY2tzLnogfHwgMDtcbiAgICAgICAgY29uc3QgZ3ogPSB2YWx1ZU9yRGVmYXVsdChvcHRzLmdyaWQgJiYgb3B0cy5ncmlkLnosIC0xKTtcbiAgICAgICAgY29uc3QgYnogPSB2YWx1ZU9yRGVmYXVsdChvcHRzLmJvcmRlciAmJiBvcHRzLmJvcmRlci56LCAwKTtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1Zpc2libGUoKSB8fCB0aGlzLmRyYXcgIT09IFNjYWxlLnByb3RvdHlwZS5kcmF3KSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgejogdHosXG4gICAgICAgICAgICAgICAgICAgIGRyYXc6IChjaGFydEFyZWEpPT57XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXcoY2hhcnRBcmVhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB6OiBneixcbiAgICAgICAgICAgICAgICBkcmF3OiAoY2hhcnRBcmVhKT0+e1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXdCYWNrZ3JvdW5kKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd0dyaWQoY2hhcnRBcmVhKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3VGl0bGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHo6IGJ6LFxuICAgICAgICAgICAgICAgIGRyYXc6ICgpPT57XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd0JvcmRlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgejogdHosXG4gICAgICAgICAgICAgICAgZHJhdzogKGNoYXJ0QXJlYSk9PntcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmF3TGFiZWxzKGNoYXJ0QXJlYSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICBdO1xuICAgIH1cbiBnZXRNYXRjaGluZ1Zpc2libGVNZXRhcyh0eXBlKSB7XG4gICAgICAgIGNvbnN0IG1ldGFzID0gdGhpcy5jaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCk7XG4gICAgICAgIGNvbnN0IGF4aXNJRCA9IHRoaXMuYXhpcyArICdBeGlzSUQnO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IG1ldGFzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gbWV0YXNbaV07XG4gICAgICAgICAgICBpZiAobWV0YVtheGlzSURdID09PSB0aGlzLmlkICYmICghdHlwZSB8fCBtZXRhLnR5cGUgPT09IHR5cGUpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobWV0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoaW5kZXgpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucy50aWNrcy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dChpbmRleCkpO1xuICAgICAgICByZXR1cm4gdG9Gb250KG9wdHMuZm9udCk7XG4gICAgfVxuIF9tYXhEaWdpdHMoKSB7XG4gICAgICAgIGNvbnN0IGZvbnRTaXplID0gdGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucygwKS5saW5lSGVpZ2h0O1xuICAgICAgICByZXR1cm4gKHRoaXMuaXNIb3Jpem9udGFsKCkgPyB0aGlzLndpZHRoIDogdGhpcy5oZWlnaHQpIC8gZm9udFNpemU7XG4gICAgfVxufVxuXG5jbGFzcyBUeXBlZFJlZ2lzdHJ5IHtcbiAgICBjb25zdHJ1Y3Rvcih0eXBlLCBzY29wZSwgb3ZlcnJpZGUpe1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7XG4gICAgICAgIHRoaXMub3ZlcnJpZGUgPSBvdmVycmlkZTtcbiAgICAgICAgdGhpcy5pdGVtcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgfVxuICAgIGlzRm9yVHlwZSh0eXBlKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmlzUHJvdG90eXBlT2YuY2FsbCh0aGlzLnR5cGUucHJvdG90eXBlLCB0eXBlLnByb3RvdHlwZSk7XG4gICAgfVxuIHJlZ2lzdGVyKGl0ZW0pIHtcbiAgICAgICAgY29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoaXRlbSk7XG4gICAgICAgIGxldCBwYXJlbnRTY29wZTtcbiAgICAgICAgaWYgKGlzSUNoYXJ0Q29tcG9uZW50KHByb3RvKSkge1xuICAgICAgICAgICAgcGFyZW50U2NvcGUgPSB0aGlzLnJlZ2lzdGVyKHByb3RvKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgIGNvbnN0IGlkID0gaXRlbS5pZDtcbiAgICAgICAgY29uc3Qgc2NvcGUgPSB0aGlzLnNjb3BlICsgJy4nICsgaWQ7XG4gICAgICAgIGlmICghaWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2xhc3MgZG9lcyBub3QgaGF2ZSBpZDogJyArIGl0ZW0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpZCBpbiBpdGVtcykge1xuICAgICAgICAgICAgcmV0dXJuIHNjb3BlO1xuICAgICAgICB9XG4gICAgICAgIGl0ZW1zW2lkXSA9IGl0ZW07XG4gICAgICAgIHJlZ2lzdGVyRGVmYXVsdHMoaXRlbSwgc2NvcGUsIHBhcmVudFNjb3BlKTtcbiAgICAgICAgaWYgKHRoaXMub3ZlcnJpZGUpIHtcbiAgICAgICAgICAgIGRlZmF1bHRzLm92ZXJyaWRlKGl0ZW0uaWQsIGl0ZW0ub3ZlcnJpZGVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2NvcGU7XG4gICAgfVxuIGdldChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pdGVtc1tpZF07XG4gICAgfVxuIHVucmVnaXN0ZXIoaXRlbSkge1xuICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgIGNvbnN0IGlkID0gaXRlbS5pZDtcbiAgICAgICAgY29uc3Qgc2NvcGUgPSB0aGlzLnNjb3BlO1xuICAgICAgICBpZiAoaWQgaW4gaXRlbXMpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBpdGVtc1tpZF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjb3BlICYmIGlkIGluIGRlZmF1bHRzW3Njb3BlXSkge1xuICAgICAgICAgICAgZGVsZXRlIGRlZmF1bHRzW3Njb3BlXVtpZF07XG4gICAgICAgICAgICBpZiAodGhpcy5vdmVycmlkZSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvdmVycmlkZXNbaWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0cyhpdGVtLCBzY29wZSwgcGFyZW50U2NvcGUpIHtcbiAgICBjb25zdCBpdGVtRGVmYXVsdHMgPSBtZXJnZShPYmplY3QuY3JlYXRlKG51bGwpLCBbXG4gICAgICAgIHBhcmVudFNjb3BlID8gZGVmYXVsdHMuZ2V0KHBhcmVudFNjb3BlKSA6IHt9LFxuICAgICAgICBkZWZhdWx0cy5nZXQoc2NvcGUpLFxuICAgICAgICBpdGVtLmRlZmF1bHRzXG4gICAgXSk7XG4gICAgZGVmYXVsdHMuc2V0KHNjb3BlLCBpdGVtRGVmYXVsdHMpO1xuICAgIGlmIChpdGVtLmRlZmF1bHRSb3V0ZXMpIHtcbiAgICAgICAgcm91dGVEZWZhdWx0cyhzY29wZSwgaXRlbS5kZWZhdWx0Um91dGVzKTtcbiAgICB9XG4gICAgaWYgKGl0ZW0uZGVzY3JpcHRvcnMpIHtcbiAgICAgICAgZGVmYXVsdHMuZGVzY3JpYmUoc2NvcGUsIGl0ZW0uZGVzY3JpcHRvcnMpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJvdXRlRGVmYXVsdHMoc2NvcGUsIHJvdXRlcykge1xuICAgIE9iamVjdC5rZXlzKHJvdXRlcykuZm9yRWFjaCgocHJvcGVydHkpPT57XG4gICAgICAgIGNvbnN0IHByb3BlcnR5UGFydHMgPSBwcm9wZXJ0eS5zcGxpdCgnLicpO1xuICAgICAgICBjb25zdCBzb3VyY2VOYW1lID0gcHJvcGVydHlQYXJ0cy5wb3AoKTtcbiAgICAgICAgY29uc3Qgc291cmNlU2NvcGUgPSBbXG4gICAgICAgICAgICBzY29wZVxuICAgICAgICBdLmNvbmNhdChwcm9wZXJ0eVBhcnRzKS5qb2luKCcuJyk7XG4gICAgICAgIGNvbnN0IHBhcnRzID0gcm91dGVzW3Byb3BlcnR5XS5zcGxpdCgnLicpO1xuICAgICAgICBjb25zdCB0YXJnZXROYW1lID0gcGFydHMucG9wKCk7XG4gICAgICAgIGNvbnN0IHRhcmdldFNjb3BlID0gcGFydHMuam9pbignLicpO1xuICAgICAgICBkZWZhdWx0cy5yb3V0ZShzb3VyY2VTY29wZSwgc291cmNlTmFtZSwgdGFyZ2V0U2NvcGUsIHRhcmdldE5hbWUpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gaXNJQ2hhcnRDb21wb25lbnQocHJvdG8pIHtcbiAgICByZXR1cm4gJ2lkJyBpbiBwcm90byAmJiAnZGVmYXVsdHMnIGluIHByb3RvO1xufVxuXG5jbGFzcyBSZWdpc3RyeSB7XG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5jb250cm9sbGVycyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KERhdGFzZXRDb250cm9sbGVyLCAnZGF0YXNldHMnLCB0cnVlKTtcbiAgICAgICAgdGhpcy5lbGVtZW50cyA9IG5ldyBUeXBlZFJlZ2lzdHJ5KEVsZW1lbnQsICdlbGVtZW50cycpO1xuICAgICAgICB0aGlzLnBsdWdpbnMgPSBuZXcgVHlwZWRSZWdpc3RyeShPYmplY3QsICdwbHVnaW5zJyk7XG4gICAgICAgIHRoaXMuc2NhbGVzID0gbmV3IFR5cGVkUmVnaXN0cnkoU2NhbGUsICdzY2FsZXMnKTtcbiAgICAgICAgdGhpcy5fdHlwZWRSZWdpc3RyaWVzID0gW1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVycyxcbiAgICAgICAgICAgIHRoaXMuc2NhbGVzLFxuICAgICAgICAgICAgdGhpcy5lbGVtZW50c1xuICAgICAgICBdO1xuICAgIH1cbiBhZGQoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCdyZWdpc3RlcicsIGFyZ3MpO1xuICAgIH1cbiAgICByZW1vdmUoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCd1bnJlZ2lzdGVyJywgYXJncyk7XG4gICAgfVxuIGFkZENvbnRyb2xsZXJzKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLmNvbnRyb2xsZXJzKTtcbiAgICB9XG4gYWRkRWxlbWVudHMoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCdyZWdpc3RlcicsIGFyZ3MsIHRoaXMuZWxlbWVudHMpO1xuICAgIH1cbiBhZGRQbHVnaW5zKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgncmVnaXN0ZXInLCBhcmdzLCB0aGlzLnBsdWdpbnMpO1xuICAgIH1cbiBhZGRTY2FsZXMoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCdyZWdpc3RlcicsIGFyZ3MsIHRoaXMuc2NhbGVzKTtcbiAgICB9XG4gZ2V0Q29udHJvbGxlcihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGlkLCB0aGlzLmNvbnRyb2xsZXJzLCAnY29udHJvbGxlcicpO1xuICAgIH1cbiBnZXRFbGVtZW50KGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXQoaWQsIHRoaXMuZWxlbWVudHMsICdlbGVtZW50Jyk7XG4gICAgfVxuIGdldFBsdWdpbihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0KGlkLCB0aGlzLnBsdWdpbnMsICdwbHVnaW4nKTtcbiAgICB9XG4gZ2V0U2NhbGUoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldChpZCwgdGhpcy5zY2FsZXMsICdzY2FsZScpO1xuICAgIH1cbiByZW1vdmVDb250cm9sbGVycyguLi5hcmdzKSB7XG4gICAgICAgIHRoaXMuX2VhY2goJ3VucmVnaXN0ZXInLCBhcmdzLCB0aGlzLmNvbnRyb2xsZXJzKTtcbiAgICB9XG4gcmVtb3ZlRWxlbWVudHMoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCd1bnJlZ2lzdGVyJywgYXJncywgdGhpcy5lbGVtZW50cyk7XG4gICAgfVxuIHJlbW92ZVBsdWdpbnMoLi4uYXJncykge1xuICAgICAgICB0aGlzLl9lYWNoKCd1bnJlZ2lzdGVyJywgYXJncywgdGhpcy5wbHVnaW5zKTtcbiAgICB9XG4gcmVtb3ZlU2NhbGVzKC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5fZWFjaCgndW5yZWdpc3RlcicsIGFyZ3MsIHRoaXMuc2NhbGVzKTtcbiAgICB9XG4gX2VhY2gobWV0aG9kLCBhcmdzLCB0eXBlZFJlZ2lzdHJ5KSB7XG4gICAgICAgIFtcbiAgICAgICAgICAgIC4uLmFyZ3NcbiAgICAgICAgXS5mb3JFYWNoKChhcmcpPT57XG4gICAgICAgICAgICBjb25zdCByZWcgPSB0eXBlZFJlZ2lzdHJ5IHx8IHRoaXMuX2dldFJlZ2lzdHJ5Rm9yVHlwZShhcmcpO1xuICAgICAgICAgICAgaWYgKHR5cGVkUmVnaXN0cnkgfHwgcmVnLmlzRm9yVHlwZShhcmcpIHx8IHJlZyA9PT0gdGhpcy5wbHVnaW5zICYmIGFyZy5pZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWMobWV0aG9kLCByZWcsIGFyZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVhY2goYXJnLCAoaXRlbSk9PntcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbVJlZyA9IHR5cGVkUmVnaXN0cnkgfHwgdGhpcy5fZ2V0UmVnaXN0cnlGb3JUeXBlKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9leGVjKG1ldGhvZCwgaXRlbVJlZywgaXRlbSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiBfZXhlYyhtZXRob2QsIHJlZ2lzdHJ5LCBjb21wb25lbnQpIHtcbiAgICAgICAgY29uc3QgY2FtZWxNZXRob2QgPSBfY2FwaXRhbGl6ZShtZXRob2QpO1xuICAgICAgICBjYWxsYmFjayhjb21wb25lbnRbJ2JlZm9yZScgKyBjYW1lbE1ldGhvZF0sIFtdLCBjb21wb25lbnQpO1xuICAgICAgICByZWdpc3RyeVttZXRob2RdKGNvbXBvbmVudCk7XG4gICAgICAgIGNhbGxiYWNrKGNvbXBvbmVudFsnYWZ0ZXInICsgY2FtZWxNZXRob2RdLCBbXSwgY29tcG9uZW50KTtcbiAgICB9XG4gX2dldFJlZ2lzdHJ5Rm9yVHlwZSh0eXBlKSB7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLl90eXBlZFJlZ2lzdHJpZXMubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgY29uc3QgcmVnID0gdGhpcy5fdHlwZWRSZWdpc3RyaWVzW2ldO1xuICAgICAgICAgICAgaWYgKHJlZy5pc0ZvclR5cGUodHlwZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnBsdWdpbnM7XG4gICAgfVxuIF9nZXQoaWQsIHR5cGVkUmVnaXN0cnksIHR5cGUpIHtcbiAgICAgICAgY29uc3QgaXRlbSA9IHR5cGVkUmVnaXN0cnkuZ2V0KGlkKTtcbiAgICAgICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIicgKyBpZCArICdcIiBpcyBub3QgYSByZWdpc3RlcmVkICcgKyB0eXBlICsgJy4nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXRlbTtcbiAgICB9XG59XG52YXIgcmVnaXN0cnkgPSAvKiAjX19QVVJFX18gKi8gbmV3IFJlZ2lzdHJ5KCk7XG5cbmNsYXNzIFBsdWdpblNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuX2luaXQgPSBbXTtcbiAgICB9XG4gbm90aWZ5KGNoYXJ0LCBob29rLCBhcmdzLCBmaWx0ZXIpIHtcbiAgICAgICAgaWYgKGhvb2sgPT09ICdiZWZvcmVJbml0Jykge1xuICAgICAgICAgICAgdGhpcy5faW5pdCA9IHRoaXMuX2NyZWF0ZURlc2NyaXB0b3JzKGNoYXJ0LCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuX25vdGlmeSh0aGlzLl9pbml0LCBjaGFydCwgJ2luc3RhbGwnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZXNjcmlwdG9ycyA9IGZpbHRlciA/IHRoaXMuX2Rlc2NyaXB0b3JzKGNoYXJ0KS5maWx0ZXIoZmlsdGVyKSA6IHRoaXMuX2Rlc2NyaXB0b3JzKGNoYXJ0KTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fbm90aWZ5KGRlc2NyaXB0b3JzLCBjaGFydCwgaG9vaywgYXJncyk7XG4gICAgICAgIGlmIChob29rID09PSAnYWZ0ZXJEZXN0cm95Jykge1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5KGRlc2NyaXB0b3JzLCBjaGFydCwgJ3N0b3AnKTtcbiAgICAgICAgICAgIHRoaXMuX25vdGlmeSh0aGlzLl9pbml0LCBjaGFydCwgJ3VuaW5zdGFsbCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuIF9ub3RpZnkoZGVzY3JpcHRvcnMsIGNoYXJ0LCBob29rLCBhcmdzKSB7XG4gICAgICAgIGFyZ3MgPSBhcmdzIHx8IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGRlc2NyaXB0b3Igb2YgZGVzY3JpcHRvcnMpe1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gZGVzY3JpcHRvci5wbHVnaW47XG4gICAgICAgICAgICBjb25zdCBtZXRob2QgPSBwbHVnaW5baG9va107XG4gICAgICAgICAgICBjb25zdCBwYXJhbXMgPSBbXG4gICAgICAgICAgICAgICAgY2hhcnQsXG4gICAgICAgICAgICAgICAgYXJncyxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdG9yLm9wdGlvbnNcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2sobWV0aG9kLCBwYXJhbXMsIHBsdWdpbikgPT09IGZhbHNlICYmIGFyZ3MuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaW52YWxpZGF0ZSgpIHtcbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKHRoaXMuX2NhY2hlKSkge1xuICAgICAgICAgICAgdGhpcy5fb2xkQ2FjaGUgPSB0aGlzLl9jYWNoZTtcbiAgICAgICAgICAgIHRoaXMuX2NhY2hlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxuIF9kZXNjcmlwdG9ycyhjaGFydCkge1xuICAgICAgICBpZiAodGhpcy5fY2FjaGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jYWNoZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZXNjcmlwdG9ycyA9IHRoaXMuX2NhY2hlID0gdGhpcy5fY3JlYXRlRGVzY3JpcHRvcnMoY2hhcnQpO1xuICAgICAgICB0aGlzLl9ub3RpZnlTdGF0ZUNoYW5nZXMoY2hhcnQpO1xuICAgICAgICByZXR1cm4gZGVzY3JpcHRvcnM7XG4gICAgfVxuICAgIF9jcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgYWxsKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IGNoYXJ0ICYmIGNoYXJ0LmNvbmZpZztcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHZhbHVlT3JEZWZhdWx0KGNvbmZpZy5vcHRpb25zICYmIGNvbmZpZy5vcHRpb25zLnBsdWdpbnMsIHt9KTtcbiAgICAgICAgY29uc3QgcGx1Z2lucyA9IGFsbFBsdWdpbnMoY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIG9wdGlvbnMgPT09IGZhbHNlICYmICFhbGwgPyBbXSA6IGNyZWF0ZURlc2NyaXB0b3JzKGNoYXJ0LCBwbHVnaW5zLCBvcHRpb25zLCBhbGwpO1xuICAgIH1cbiBfbm90aWZ5U3RhdGVDaGFuZ2VzKGNoYXJ0KSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzRGVzY3JpcHRvcnMgPSB0aGlzLl9vbGRDYWNoZSB8fCBbXTtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvcnMgPSB0aGlzLl9jYWNoZTtcbiAgICAgICAgY29uc3QgZGlmZiA9IChhLCBiKT0+YS5maWx0ZXIoKHgpPT4hYi5zb21lKCh5KT0+eC5wbHVnaW4uaWQgPT09IHkucGx1Z2luLmlkKSk7XG4gICAgICAgIHRoaXMuX25vdGlmeShkaWZmKHByZXZpb3VzRGVzY3JpcHRvcnMsIGRlc2NyaXB0b3JzKSwgY2hhcnQsICdzdG9wJyk7XG4gICAgICAgIHRoaXMuX25vdGlmeShkaWZmKGRlc2NyaXB0b3JzLCBwcmV2aW91c0Rlc2NyaXB0b3JzKSwgY2hhcnQsICdzdGFydCcpO1xuICAgIH1cbn1cbiBmdW5jdGlvbiBhbGxQbHVnaW5zKGNvbmZpZykge1xuICAgIGNvbnN0IGxvY2FsSWRzID0ge307XG4gICAgY29uc3QgcGx1Z2lucyA9IFtdO1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhyZWdpc3RyeS5wbHVnaW5zLml0ZW1zKTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIHBsdWdpbnMucHVzaChyZWdpc3RyeS5nZXRQbHVnaW4oa2V5c1tpXSkpO1xuICAgIH1cbiAgICBjb25zdCBsb2NhbCA9IGNvbmZpZy5wbHVnaW5zIHx8IFtdO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsb2NhbC5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IHBsdWdpbiA9IGxvY2FsW2ldO1xuICAgICAgICBpZiAocGx1Z2lucy5pbmRleE9mKHBsdWdpbikgPT09IC0xKSB7XG4gICAgICAgICAgICBwbHVnaW5zLnB1c2gocGx1Z2luKTtcbiAgICAgICAgICAgIGxvY2FsSWRzW3BsdWdpbi5pZF0gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHBsdWdpbnMsXG4gICAgICAgIGxvY2FsSWRzXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldE9wdHMob3B0aW9ucywgYWxsKSB7XG4gICAgaWYgKCFhbGwgJiYgb3B0aW9ucyA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChvcHRpb25zID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG59XG5mdW5jdGlvbiBjcmVhdGVEZXNjcmlwdG9ycyhjaGFydCwgeyBwbHVnaW5zICwgbG9jYWxJZHMgIH0sIG9wdGlvbnMsIGFsbCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IGNvbnRleHQgPSBjaGFydC5nZXRDb250ZXh0KCk7XG4gICAgZm9yIChjb25zdCBwbHVnaW4gb2YgcGx1Z2lucyl7XG4gICAgICAgIGNvbnN0IGlkID0gcGx1Z2luLmlkO1xuICAgICAgICBjb25zdCBvcHRzID0gZ2V0T3B0cyhvcHRpb25zW2lkXSwgYWxsKTtcbiAgICAgICAgaWYgKG9wdHMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICAgIHBsdWdpbixcbiAgICAgICAgICAgIG9wdGlvbnM6IHBsdWdpbk9wdHMoY2hhcnQuY29uZmlnLCB7XG4gICAgICAgICAgICAgICAgcGx1Z2luLFxuICAgICAgICAgICAgICAgIGxvY2FsOiBsb2NhbElkc1tpZF1cbiAgICAgICAgICAgIH0sIG9wdHMsIGNvbnRleHQpXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gcGx1Z2luT3B0cyhjb25maWcsIHsgcGx1Z2luICwgbG9jYWwgIH0sIG9wdHMsIGNvbnRleHQpIHtcbiAgICBjb25zdCBrZXlzID0gY29uZmlnLnBsdWdpblNjb3BlS2V5cyhwbHVnaW4pO1xuICAgIGNvbnN0IHNjb3BlcyA9IGNvbmZpZy5nZXRPcHRpb25TY29wZXMob3B0cywga2V5cyk7XG4gICAgaWYgKGxvY2FsICYmIHBsdWdpbi5kZWZhdWx0cykge1xuICAgICAgICBzY29wZXMucHVzaChwbHVnaW4uZGVmYXVsdHMpO1xuICAgIH1cbiAgICByZXR1cm4gY29uZmlnLmNyZWF0ZVJlc29sdmVyKHNjb3BlcywgY29udGV4dCwgW1xuICAgICAgICAnJ1xuICAgIF0sIHtcbiAgICAgICAgc2NyaXB0YWJsZTogZmFsc2UsXG4gICAgICAgIGluZGV4YWJsZTogZmFsc2UsXG4gICAgICAgIGFsbEtleXM6IHRydWVcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0SW5kZXhBeGlzKHR5cGUsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBkYXRhc2V0RGVmYXVsdHMgPSBkZWZhdWx0cy5kYXRhc2V0c1t0eXBlXSB8fCB7fTtcbiAgICBjb25zdCBkYXRhc2V0T3B0aW9ucyA9IChvcHRpb25zLmRhdGFzZXRzIHx8IHt9KVt0eXBlXSB8fCB7fTtcbiAgICByZXR1cm4gZGF0YXNldE9wdGlvbnMuaW5kZXhBeGlzIHx8IG9wdGlvbnMuaW5kZXhBeGlzIHx8IGRhdGFzZXREZWZhdWx0cy5pbmRleEF4aXMgfHwgJ3gnO1xufVxuZnVuY3Rpb24gZ2V0QXhpc0Zyb21EZWZhdWx0U2NhbGVJRChpZCwgaW5kZXhBeGlzKSB7XG4gICAgbGV0IGF4aXMgPSBpZDtcbiAgICBpZiAoaWQgPT09ICdfaW5kZXhfJykge1xuICAgICAgICBheGlzID0gaW5kZXhBeGlzO1xuICAgIH0gZWxzZSBpZiAoaWQgPT09ICdfdmFsdWVfJykge1xuICAgICAgICBheGlzID0gaW5kZXhBeGlzID09PSAneCcgPyAneScgOiAneCc7XG4gICAgfVxuICAgIHJldHVybiBheGlzO1xufVxuZnVuY3Rpb24gZ2V0RGVmYXVsdFNjYWxlSURGcm9tQXhpcyhheGlzLCBpbmRleEF4aXMpIHtcbiAgICByZXR1cm4gYXhpcyA9PT0gaW5kZXhBeGlzID8gJ19pbmRleF8nIDogJ192YWx1ZV8nO1xufVxuZnVuY3Rpb24gaWRNYXRjaGVzQXhpcyhpZCkge1xuICAgIGlmIChpZCA9PT0gJ3gnIHx8IGlkID09PSAneScgfHwgaWQgPT09ICdyJykge1xuICAgICAgICByZXR1cm4gaWQ7XG4gICAgfVxufVxuZnVuY3Rpb24gYXhpc0Zyb21Qb3NpdGlvbihwb3NpdGlvbikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nKSB7XG4gICAgICAgIHJldHVybiAneCc7XG4gICAgfVxuICAgIGlmIChwb3NpdGlvbiA9PT0gJ2xlZnQnIHx8IHBvc2l0aW9uID09PSAncmlnaHQnKSB7XG4gICAgICAgIHJldHVybiAneSc7XG4gICAgfVxufVxuZnVuY3Rpb24gZGV0ZXJtaW5lQXhpcyhpZCwgLi4uc2NhbGVPcHRpb25zKSB7XG4gICAgaWYgKGlkTWF0Y2hlc0F4aXMoaWQpKSB7XG4gICAgICAgIHJldHVybiBpZDtcbiAgICB9XG4gICAgZm9yIChjb25zdCBvcHRzIG9mIHNjYWxlT3B0aW9ucyl7XG4gICAgICAgIGNvbnN0IGF4aXMgPSBvcHRzLmF4aXMgfHwgYXhpc0Zyb21Qb3NpdGlvbihvcHRzLnBvc2l0aW9uKSB8fCBpZC5sZW5ndGggPiAxICYmIGlkTWF0Y2hlc0F4aXMoaWRbMF0udG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGlmIChheGlzKSB7XG4gICAgICAgICAgICByZXR1cm4gYXhpcztcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBkZXRlcm1pbmUgdHlwZSBvZiAnJHtpZH0nIGF4aXMuIFBsZWFzZSBwcm92aWRlICdheGlzJyBvciAncG9zaXRpb24nIG9wdGlvbi5gKTtcbn1cbmZ1bmN0aW9uIGdldEF4aXNGcm9tRGF0YXNldChpZCwgYXhpcywgZGF0YXNldCkge1xuICAgIGlmIChkYXRhc2V0W2F4aXMgKyAnQXhpc0lEJ10gPT09IGlkKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBheGlzXG4gICAgICAgIH07XG4gICAgfVxufVxuZnVuY3Rpb24gcmV0cmlldmVBeGlzRnJvbURhdGFzZXRzKGlkLCBjb25maWcpIHtcbiAgICBpZiAoY29uZmlnLmRhdGEgJiYgY29uZmlnLmRhdGEuZGF0YXNldHMpIHtcbiAgICAgICAgY29uc3QgYm91bmREcyA9IGNvbmZpZy5kYXRhLmRhdGFzZXRzLmZpbHRlcigoZCk9PmQueEF4aXNJRCA9PT0gaWQgfHwgZC55QXhpc0lEID09PSBpZCk7XG4gICAgICAgIGlmIChib3VuZERzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGdldEF4aXNGcm9tRGF0YXNldChpZCwgJ3gnLCBib3VuZERzWzBdKSB8fCBnZXRBeGlzRnJvbURhdGFzZXQoaWQsICd5JywgYm91bmREc1swXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHt9O1xufVxuZnVuY3Rpb24gbWVyZ2VTY2FsZUNvbmZpZyhjb25maWcsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBjaGFydERlZmF1bHRzID0gb3ZlcnJpZGVzW2NvbmZpZy50eXBlXSB8fCB7XG4gICAgICAgIHNjYWxlczoge31cbiAgICB9O1xuICAgIGNvbnN0IGNvbmZpZ1NjYWxlcyA9IG9wdGlvbnMuc2NhbGVzIHx8IHt9O1xuICAgIGNvbnN0IGNoYXJ0SW5kZXhBeGlzID0gZ2V0SW5kZXhBeGlzKGNvbmZpZy50eXBlLCBvcHRpb25zKTtcbiAgICBjb25zdCBzY2FsZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIE9iamVjdC5rZXlzKGNvbmZpZ1NjYWxlcykuZm9yRWFjaCgoaWQpPT57XG4gICAgICAgIGNvbnN0IHNjYWxlQ29uZiA9IGNvbmZpZ1NjYWxlc1tpZF07XG4gICAgICAgIGlmICghaXNPYmplY3Qoc2NhbGVDb25mKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUuZXJyb3IoYEludmFsaWQgc2NhbGUgY29uZmlndXJhdGlvbiBmb3Igc2NhbGU6ICR7aWR9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjYWxlQ29uZi5fcHJveHkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLndhcm4oYElnbm9yaW5nIHJlc29sdmVyIHBhc3NlZCBhcyBvcHRpb25zIGZvciBzY2FsZTogJHtpZH1gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBheGlzID0gZGV0ZXJtaW5lQXhpcyhpZCwgc2NhbGVDb25mLCByZXRyaWV2ZUF4aXNGcm9tRGF0YXNldHMoaWQsIGNvbmZpZyksIGRlZmF1bHRzLnNjYWxlc1tzY2FsZUNvbmYudHlwZV0pO1xuICAgICAgICBjb25zdCBkZWZhdWx0SWQgPSBnZXREZWZhdWx0U2NhbGVJREZyb21BeGlzKGF4aXMsIGNoYXJ0SW5kZXhBeGlzKTtcbiAgICAgICAgY29uc3QgZGVmYXVsdFNjYWxlT3B0aW9ucyA9IGNoYXJ0RGVmYXVsdHMuc2NhbGVzIHx8IHt9O1xuICAgICAgICBzY2FsZXNbaWRdID0gbWVyZ2VJZihPYmplY3QuY3JlYXRlKG51bGwpLCBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYXhpc1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNjYWxlQ29uZixcbiAgICAgICAgICAgIGRlZmF1bHRTY2FsZU9wdGlvbnNbYXhpc10sXG4gICAgICAgICAgICBkZWZhdWx0U2NhbGVPcHRpb25zW2RlZmF1bHRJZF1cbiAgICAgICAgXSk7XG4gICAgfSk7XG4gICAgY29uZmlnLmRhdGEuZGF0YXNldHMuZm9yRWFjaCgoZGF0YXNldCk9PntcbiAgICAgICAgY29uc3QgdHlwZSA9IGRhdGFzZXQudHlwZSB8fCBjb25maWcudHlwZTtcbiAgICAgICAgY29uc3QgaW5kZXhBeGlzID0gZGF0YXNldC5pbmRleEF4aXMgfHwgZ2V0SW5kZXhBeGlzKHR5cGUsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkYXRhc2V0RGVmYXVsdHMgPSBvdmVycmlkZXNbdHlwZV0gfHwge307XG4gICAgICAgIGNvbnN0IGRlZmF1bHRTY2FsZU9wdGlvbnMgPSBkYXRhc2V0RGVmYXVsdHMuc2NhbGVzIHx8IHt9O1xuICAgICAgICBPYmplY3Qua2V5cyhkZWZhdWx0U2NhbGVPcHRpb25zKS5mb3JFYWNoKChkZWZhdWx0SUQpPT57XG4gICAgICAgICAgICBjb25zdCBheGlzID0gZ2V0QXhpc0Zyb21EZWZhdWx0U2NhbGVJRChkZWZhdWx0SUQsIGluZGV4QXhpcyk7XG4gICAgICAgICAgICBjb25zdCBpZCA9IGRhdGFzZXRbYXhpcyArICdBeGlzSUQnXSB8fCBheGlzO1xuICAgICAgICAgICAgc2NhbGVzW2lkXSA9IHNjYWxlc1tpZF0gfHwgT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgICAgIG1lcmdlSWYoc2NhbGVzW2lkXSwgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgYXhpc1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY29uZmlnU2NhbGVzW2lkXSxcbiAgICAgICAgICAgICAgICBkZWZhdWx0U2NhbGVPcHRpb25zW2RlZmF1bHRJRF1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICBPYmplY3Qua2V5cyhzY2FsZXMpLmZvckVhY2goKGtleSk9PntcbiAgICAgICAgY29uc3Qgc2NhbGUgPSBzY2FsZXNba2V5XTtcbiAgICAgICAgbWVyZ2VJZihzY2FsZSwgW1xuICAgICAgICAgICAgZGVmYXVsdHMuc2NhbGVzW3NjYWxlLnR5cGVdLFxuICAgICAgICAgICAgZGVmYXVsdHMuc2NhbGVcbiAgICAgICAgXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNjYWxlcztcbn1cbmZ1bmN0aW9uIGluaXRPcHRpb25zKGNvbmZpZykge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBjb25maWcub3B0aW9ucyB8fCAoY29uZmlnLm9wdGlvbnMgPSB7fSk7XG4gICAgb3B0aW9ucy5wbHVnaW5zID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy5wbHVnaW5zLCB7fSk7XG4gICAgb3B0aW9ucy5zY2FsZXMgPSBtZXJnZVNjYWxlQ29uZmlnKGNvbmZpZywgb3B0aW9ucyk7XG59XG5mdW5jdGlvbiBpbml0RGF0YShkYXRhKSB7XG4gICAgZGF0YSA9IGRhdGEgfHwge307XG4gICAgZGF0YS5kYXRhc2V0cyA9IGRhdGEuZGF0YXNldHMgfHwgW107XG4gICAgZGF0YS5sYWJlbHMgPSBkYXRhLmxhYmVscyB8fCBbXTtcbiAgICByZXR1cm4gZGF0YTtcbn1cbmZ1bmN0aW9uIGluaXRDb25maWcoY29uZmlnKSB7XG4gICAgY29uZmlnID0gY29uZmlnIHx8IHt9O1xuICAgIGNvbmZpZy5kYXRhID0gaW5pdERhdGEoY29uZmlnLmRhdGEpO1xuICAgIGluaXRPcHRpb25zKGNvbmZpZyk7XG4gICAgcmV0dXJuIGNvbmZpZztcbn1cbmNvbnN0IGtleUNhY2hlID0gbmV3IE1hcCgpO1xuY29uc3Qga2V5c0NhY2hlZCA9IG5ldyBTZXQoKTtcbmZ1bmN0aW9uIGNhY2hlZEtleXMoY2FjaGVLZXksIGdlbmVyYXRlKSB7XG4gICAgbGV0IGtleXMgPSBrZXlDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmICgha2V5cykge1xuICAgICAgICBrZXlzID0gZ2VuZXJhdGUoKTtcbiAgICAgICAga2V5Q2FjaGUuc2V0KGNhY2hlS2V5LCBrZXlzKTtcbiAgICAgICAga2V5c0NhY2hlZC5hZGQoa2V5cyk7XG4gICAgfVxuICAgIHJldHVybiBrZXlzO1xufVxuY29uc3QgYWRkSWZGb3VuZCA9IChzZXQsIG9iaiwga2V5KT0+e1xuICAgIGNvbnN0IG9wdHMgPSByZXNvbHZlT2JqZWN0S2V5KG9iaiwga2V5KTtcbiAgICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNldC5hZGQob3B0cyk7XG4gICAgfVxufTtcbmNsYXNzIENvbmZpZyB7XG4gICAgY29uc3RydWN0b3IoY29uZmlnKXtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gaW5pdENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLl9zY29wZUNhY2hlID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLl9yZXNvbHZlckNhY2hlID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICBnZXQgcGxhdGZvcm0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb25maWcucGxhdGZvcm07XG4gICAgfVxuICAgIGdldCB0eXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29uZmlnLnR5cGU7XG4gICAgfVxuICAgIHNldCB0eXBlKHR5cGUpIHtcbiAgICAgICAgdGhpcy5fY29uZmlnLnR5cGUgPSB0eXBlO1xuICAgIH1cbiAgICBnZXQgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhO1xuICAgIH1cbiAgICBzZXQgZGF0YShkYXRhKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZy5kYXRhID0gaW5pdERhdGEoZGF0YSk7XG4gICAgfVxuICAgIGdldCBvcHRpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29uZmlnLm9wdGlvbnM7XG4gICAgfVxuICAgIHNldCBvcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fY29uZmlnLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cbiAgICBnZXQgcGx1Z2lucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5wbHVnaW5zO1xuICAgIH1cbiAgICB1cGRhdGUoKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuX2NvbmZpZztcbiAgICAgICAgdGhpcy5jbGVhckNhY2hlKCk7XG4gICAgICAgIGluaXRPcHRpb25zKGNvbmZpZyk7XG4gICAgfVxuICAgIGNsZWFyQ2FjaGUoKSB7XG4gICAgICAgIHRoaXMuX3Njb3BlQ2FjaGUuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZXJDYWNoZS5jbGVhcigpO1xuICAgIH1cbiBkYXRhc2V0U2NvcGVLZXlzKGRhdGFzZXRUeXBlKSB7XG4gICAgICAgIHJldHVybiBjYWNoZWRLZXlzKGRhdGFzZXRUeXBlLCAoKT0+W1xuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgYGRhdGFzZXRzLiR7ZGF0YXNldFR5cGV9YCxcbiAgICAgICAgICAgICAgICAgICAgJydcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdKTtcbiAgICB9XG4gZGF0YXNldEFuaW1hdGlvblNjb3BlS2V5cyhkYXRhc2V0VHlwZSwgdHJhbnNpdGlvbikge1xuICAgICAgICByZXR1cm4gY2FjaGVkS2V5cyhgJHtkYXRhc2V0VHlwZX0udHJhbnNpdGlvbi4ke3RyYW5zaXRpb259YCwgKCk9PltcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfS50cmFuc2l0aW9ucy4ke3RyYW5zaXRpb259YCxcbiAgICAgICAgICAgICAgICAgICAgYHRyYW5zaXRpb25zLiR7dHJhbnNpdGlvbn1gXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGBkYXRhc2V0cy4ke2RhdGFzZXRUeXBlfWAsXG4gICAgICAgICAgICAgICAgICAgICcnXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXSk7XG4gICAgfVxuIGRhdGFzZXRFbGVtZW50U2NvcGVLZXlzKGRhdGFzZXRUeXBlLCBlbGVtZW50VHlwZSkge1xuICAgICAgICByZXR1cm4gY2FjaGVkS2V5cyhgJHtkYXRhc2V0VHlwZX0tJHtlbGVtZW50VHlwZX1gLCAoKT0+W1xuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgYGRhdGFzZXRzLiR7ZGF0YXNldFR5cGV9LmVsZW1lbnRzLiR7ZWxlbWVudFR5cGV9YCxcbiAgICAgICAgICAgICAgICAgICAgYGRhdGFzZXRzLiR7ZGF0YXNldFR5cGV9YCxcbiAgICAgICAgICAgICAgICAgICAgYGVsZW1lbnRzLiR7ZWxlbWVudFR5cGV9YCxcbiAgICAgICAgICAgICAgICAgICAgJydcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdKTtcbiAgICB9XG4gcGx1Z2luU2NvcGVLZXlzKHBsdWdpbikge1xuICAgICAgICBjb25zdCBpZCA9IHBsdWdpbi5pZDtcbiAgICAgICAgY29uc3QgdHlwZSA9IHRoaXMudHlwZTtcbiAgICAgICAgcmV0dXJuIGNhY2hlZEtleXMoYCR7dHlwZX0tcGx1Z2luLSR7aWR9YCwgKCk9PltcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGBwbHVnaW5zLiR7aWR9YCxcbiAgICAgICAgICAgICAgICAgICAgLi4ucGx1Z2luLmFkZGl0aW9uYWxPcHRpb25TY29wZXMgfHwgW11cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdKTtcbiAgICB9XG4gX2NhY2hlZFNjb3BlcyhtYWluU2NvcGUsIHJlc2V0Q2FjaGUpIHtcbiAgICAgICAgY29uc3QgX3Njb3BlQ2FjaGUgPSB0aGlzLl9zY29wZUNhY2hlO1xuICAgICAgICBsZXQgY2FjaGUgPSBfc2NvcGVDYWNoZS5nZXQobWFpblNjb3BlKTtcbiAgICAgICAgaWYgKCFjYWNoZSB8fCByZXNldENhY2hlKSB7XG4gICAgICAgICAgICBjYWNoZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIF9zY29wZUNhY2hlLnNldChtYWluU2NvcGUsIGNhY2hlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FjaGU7XG4gICAgfVxuIGdldE9wdGlvblNjb3BlcyhtYWluU2NvcGUsIGtleUxpc3RzLCByZXNldENhY2hlKSB7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9ucyAsIHR5cGUgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBjYWNoZSA9IHRoaXMuX2NhY2hlZFNjb3BlcyhtYWluU2NvcGUsIHJlc2V0Q2FjaGUpO1xuICAgICAgICBjb25zdCBjYWNoZWQgPSBjYWNoZS5nZXQoa2V5TGlzdHMpO1xuICAgICAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNjb3BlcyA9IG5ldyBTZXQoKTtcbiAgICAgICAga2V5TGlzdHMuZm9yRWFjaCgoa2V5cyk9PntcbiAgICAgICAgICAgIGlmIChtYWluU2NvcGUpIHtcbiAgICAgICAgICAgICAgICBzY29wZXMuYWRkKG1haW5TY29wZSk7XG4gICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKChrZXkpPT5hZGRJZkZvdW5kKHNjb3BlcywgbWFpblNjb3BlLCBrZXkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KT0+YWRkSWZGb3VuZChzY29wZXMsIG9wdGlvbnMsIGtleSkpO1xuICAgICAgICAgICAga2V5cy5mb3JFYWNoKChrZXkpPT5hZGRJZkZvdW5kKHNjb3Blcywgb3ZlcnJpZGVzW3R5cGVdIHx8IHt9LCBrZXkpKTtcbiAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KT0+YWRkSWZGb3VuZChzY29wZXMsIGRlZmF1bHRzLCBrZXkpKTtcbiAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KT0+YWRkSWZGb3VuZChzY29wZXMsIGRlc2NyaXB0b3JzLCBrZXkpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gQXJyYXkuZnJvbShzY29wZXMpO1xuICAgICAgICBpZiAoYXJyYXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBhcnJheS5wdXNoKE9iamVjdC5jcmVhdGUobnVsbCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXlzQ2FjaGVkLmhhcyhrZXlMaXN0cykpIHtcbiAgICAgICAgICAgIGNhY2hlLnNldChrZXlMaXN0cywgYXJyYXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG4gY2hhcnRPcHRpb25TY29wZXMoKSB7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9ucyAsIHR5cGUgIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgIG92ZXJyaWRlc1t0eXBlXSB8fCB7fSxcbiAgICAgICAgICAgIGRlZmF1bHRzLmRhdGFzZXRzW3R5cGVdIHx8IHt9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZhdWx0cyxcbiAgICAgICAgICAgIGRlc2NyaXB0b3JzXG4gICAgICAgIF07XG4gICAgfVxuIHJlc29sdmVOYW1lZE9wdGlvbnMoc2NvcGVzLCBuYW1lcywgY29udGV4dCwgcHJlZml4ZXMgPSBbXG4gICAgICAgICcnXG4gICAgXSkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgICAgICAkc2hhcmVkOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHsgcmVzb2x2ZXIgLCBzdWJQcmVmaXhlcyAgfSA9IGdldFJlc29sdmVyKHRoaXMuX3Jlc29sdmVyQ2FjaGUsIHNjb3BlcywgcHJlZml4ZXMpO1xuICAgICAgICBsZXQgb3B0aW9ucyA9IHJlc29sdmVyO1xuICAgICAgICBpZiAobmVlZENvbnRleHQocmVzb2x2ZXIsIG5hbWVzKSkge1xuICAgICAgICAgICAgcmVzdWx0LiRzaGFyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnRleHQgPSBpc0Z1bmN0aW9uKGNvbnRleHQpID8gY29udGV4dCgpIDogY29udGV4dDtcbiAgICAgICAgICAgIGNvbnN0IHN1YlJlc29sdmVyID0gdGhpcy5jcmVhdGVSZXNvbHZlcihzY29wZXMsIGNvbnRleHQsIHN1YlByZWZpeGVzKTtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBfYXR0YWNoQ29udGV4dChyZXNvbHZlciwgY29udGV4dCwgc3ViUmVzb2x2ZXIpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBuYW1lcyl7XG4gICAgICAgICAgICByZXN1bHRbcHJvcF0gPSBvcHRpb25zW3Byb3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuIGNyZWF0ZVJlc29sdmVyKHNjb3BlcywgY29udGV4dCwgcHJlZml4ZXMgPSBbXG4gICAgICAgICcnXG4gICAgXSwgZGVzY3JpcHRvckRlZmF1bHRzKSB7XG4gICAgICAgIGNvbnN0IHsgcmVzb2x2ZXIgIH0gPSBnZXRSZXNvbHZlcih0aGlzLl9yZXNvbHZlckNhY2hlLCBzY29wZXMsIHByZWZpeGVzKTtcbiAgICAgICAgcmV0dXJuIGlzT2JqZWN0KGNvbnRleHQpID8gX2F0dGFjaENvbnRleHQocmVzb2x2ZXIsIGNvbnRleHQsIHVuZGVmaW5lZCwgZGVzY3JpcHRvckRlZmF1bHRzKSA6IHJlc29sdmVyO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldFJlc29sdmVyKHJlc29sdmVyQ2FjaGUsIHNjb3BlcywgcHJlZml4ZXMpIHtcbiAgICBsZXQgY2FjaGUgPSByZXNvbHZlckNhY2hlLmdldChzY29wZXMpO1xuICAgIGlmICghY2FjaGUpIHtcbiAgICAgICAgY2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgICAgIHJlc29sdmVyQ2FjaGUuc2V0KHNjb3BlcywgY2FjaGUpO1xuICAgIH1cbiAgICBjb25zdCBjYWNoZUtleSA9IHByZWZpeGVzLmpvaW4oKTtcbiAgICBsZXQgY2FjaGVkID0gY2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICBpZiAoIWNhY2hlZCkge1xuICAgICAgICBjb25zdCByZXNvbHZlciA9IF9jcmVhdGVSZXNvbHZlcihzY29wZXMsIHByZWZpeGVzKTtcbiAgICAgICAgY2FjaGVkID0ge1xuICAgICAgICAgICAgcmVzb2x2ZXIsXG4gICAgICAgICAgICBzdWJQcmVmaXhlczogcHJlZml4ZXMuZmlsdGVyKChwKT0+IXAudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnaG92ZXInKSlcbiAgICAgICAgfTtcbiAgICAgICAgY2FjaGUuc2V0KGNhY2hlS2V5LCBjYWNoZWQpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkO1xufVxuY29uc3QgaGFzRnVuY3Rpb24gPSAodmFsdWUpPT5pc09iamVjdCh2YWx1ZSkgJiYgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModmFsdWUpLnJlZHVjZSgoYWNjLCBrZXkpPT5hY2MgfHwgaXNGdW5jdGlvbih2YWx1ZVtrZXldKSwgZmFsc2UpO1xuZnVuY3Rpb24gbmVlZENvbnRleHQocHJveHksIG5hbWVzKSB7XG4gICAgY29uc3QgeyBpc1NjcmlwdGFibGUgLCBpc0luZGV4YWJsZSAgfSA9IF9kZXNjcmlwdG9ycyhwcm94eSk7XG4gICAgZm9yIChjb25zdCBwcm9wIG9mIG5hbWVzKXtcbiAgICAgICAgY29uc3Qgc2NyaXB0YWJsZSA9IGlzU2NyaXB0YWJsZShwcm9wKTtcbiAgICAgICAgY29uc3QgaW5kZXhhYmxlID0gaXNJbmRleGFibGUocHJvcCk7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gKGluZGV4YWJsZSB8fCBzY3JpcHRhYmxlKSAmJiBwcm94eVtwcm9wXTtcbiAgICAgICAgaWYgKHNjcmlwdGFibGUgJiYgKGlzRnVuY3Rpb24odmFsdWUpIHx8IGhhc0Z1bmN0aW9uKHZhbHVlKSkgfHwgaW5kZXhhYmxlICYmIGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbnZhciB2ZXJzaW9uID0gXCI0LjMuMFwiO1xuXG5jb25zdCBLTk9XTl9QT1NJVElPTlMgPSBbXG4gICAgJ3RvcCcsXG4gICAgJ2JvdHRvbScsXG4gICAgJ2xlZnQnLFxuICAgICdyaWdodCcsXG4gICAgJ2NoYXJ0QXJlYSdcbl07XG5mdW5jdGlvbiBwb3NpdGlvbklzSG9yaXpvbnRhbChwb3NpdGlvbiwgYXhpcykge1xuICAgIHJldHVybiBwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nIHx8IEtOT1dOX1BPU0lUSU9OUy5pbmRleE9mKHBvc2l0aW9uKSA9PT0gLTEgJiYgYXhpcyA9PT0gJ3gnO1xufVxuZnVuY3Rpb24gY29tcGFyZTJMZXZlbChsMSwgbDIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYVtsMV0gPT09IGJbbDFdID8gYVtsMl0gLSBiW2wyXSA6IGFbbDFdIC0gYltsMV07XG4gICAgfTtcbn1cbmZ1bmN0aW9uIG9uQW5pbWF0aW9uc0NvbXBsZXRlKGNvbnRleHQpIHtcbiAgICBjb25zdCBjaGFydCA9IGNvbnRleHQuY2hhcnQ7XG4gICAgY29uc3QgYW5pbWF0aW9uT3B0aW9ucyA9IGNoYXJ0Lm9wdGlvbnMuYW5pbWF0aW9uO1xuICAgIGNoYXJ0Lm5vdGlmeVBsdWdpbnMoJ2FmdGVyUmVuZGVyJyk7XG4gICAgY2FsbGJhY2soYW5pbWF0aW9uT3B0aW9ucyAmJiBhbmltYXRpb25PcHRpb25zLm9uQ29tcGxldGUsIFtcbiAgICAgICAgY29udGV4dFxuICAgIF0sIGNoYXJ0KTtcbn1cbmZ1bmN0aW9uIG9uQW5pbWF0aW9uUHJvZ3Jlc3MoY29udGV4dCkge1xuICAgIGNvbnN0IGNoYXJ0ID0gY29udGV4dC5jaGFydDtcbiAgICBjb25zdCBhbmltYXRpb25PcHRpb25zID0gY2hhcnQub3B0aW9ucy5hbmltYXRpb247XG4gICAgY2FsbGJhY2soYW5pbWF0aW9uT3B0aW9ucyAmJiBhbmltYXRpb25PcHRpb25zLm9uUHJvZ3Jlc3MsIFtcbiAgICAgICAgY29udGV4dFxuICAgIF0sIGNoYXJ0KTtcbn1cbiBmdW5jdGlvbiBnZXRDYW52YXMoaXRlbSkge1xuICAgIGlmIChfaXNEb21TdXBwb3J0ZWQoKSAmJiB0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaXRlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGl0ZW0pO1xuICAgIH0gZWxzZSBpZiAoaXRlbSAmJiBpdGVtLmxlbmd0aCkge1xuICAgICAgICBpdGVtID0gaXRlbVswXTtcbiAgICB9XG4gICAgaWYgKGl0ZW0gJiYgaXRlbS5jYW52YXMpIHtcbiAgICAgICAgaXRlbSA9IGl0ZW0uY2FudmFzO1xuICAgIH1cbiAgICByZXR1cm4gaXRlbTtcbn1cbmNvbnN0IGluc3RhbmNlcyA9IHt9O1xuY29uc3QgZ2V0Q2hhcnQgPSAoa2V5KT0+e1xuICAgIGNvbnN0IGNhbnZhcyA9IGdldENhbnZhcyhrZXkpO1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKGluc3RhbmNlcykuZmlsdGVyKChjKT0+Yy5jYW52YXMgPT09IGNhbnZhcykucG9wKCk7XG59O1xuZnVuY3Rpb24gbW92ZU51bWVyaWNLZXlzKG9iaiwgc3RhcnQsIG1vdmUpIHtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKXtcbiAgICAgICAgY29uc3QgaW50S2V5ID0gK2tleTtcbiAgICAgICAgaWYgKGludEtleSA+PSBzdGFydCkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvYmpba2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSBvYmpba2V5XTtcbiAgICAgICAgICAgIGlmIChtb3ZlID4gMCB8fCBpbnRLZXkgPiBzdGFydCkge1xuICAgICAgICAgICAgICAgIG9ialtpbnRLZXkgKyBtb3ZlXSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIGZ1bmN0aW9uIGRldGVybWluZUxhc3RFdmVudChlLCBsYXN0RXZlbnQsIGluQ2hhcnRBcmVhLCBpc0NsaWNrKSB7XG4gICAgaWYgKCFpbkNoYXJ0QXJlYSB8fCBlLnR5cGUgPT09ICdtb3VzZW91dCcpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChpc0NsaWNrKSB7XG4gICAgICAgIHJldHVybiBsYXN0RXZlbnQ7XG4gICAgfVxuICAgIHJldHVybiBlO1xufVxuZnVuY3Rpb24gZ2V0RGF0YXNldEFyZWEobWV0YSkge1xuICAgIGNvbnN0IHsgeFNjYWxlICwgeVNjYWxlICB9ID0gbWV0YTtcbiAgICBpZiAoeFNjYWxlICYmIHlTY2FsZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVmdDogeFNjYWxlLmxlZnQsXG4gICAgICAgICAgICByaWdodDogeFNjYWxlLnJpZ2h0LFxuICAgICAgICAgICAgdG9wOiB5U2NhbGUudG9wLFxuICAgICAgICAgICAgYm90dG9tOiB5U2NhbGUuYm90dG9tXG4gICAgICAgIH07XG4gICAgfVxufVxuY2xhc3MgQ2hhcnQge1xuICAgIHN0YXRpYyBkZWZhdWx0cyA9IGRlZmF1bHRzO1xuICAgIHN0YXRpYyBpbnN0YW5jZXMgPSBpbnN0YW5jZXM7XG4gICAgc3RhdGljIG92ZXJyaWRlcyA9IG92ZXJyaWRlcztcbiAgICBzdGF0aWMgcmVnaXN0cnkgPSByZWdpc3RyeTtcbiAgICBzdGF0aWMgdmVyc2lvbiA9IHZlcnNpb247XG4gICAgc3RhdGljIGdldENoYXJ0ID0gZ2V0Q2hhcnQ7XG4gICAgc3RhdGljIHJlZ2lzdGVyKC4uLml0ZW1zKSB7XG4gICAgICAgIHJlZ2lzdHJ5LmFkZCguLi5pdGVtcyk7XG4gICAgICAgIGludmFsaWRhdGVQbHVnaW5zKCk7XG4gICAgfVxuICAgIHN0YXRpYyB1bnJlZ2lzdGVyKC4uLml0ZW1zKSB7XG4gICAgICAgIHJlZ2lzdHJ5LnJlbW92ZSguLi5pdGVtcyk7XG4gICAgICAgIGludmFsaWRhdGVQbHVnaW5zKCk7XG4gICAgfVxuICAgIGNvbnN0cnVjdG9yKGl0ZW0sIHVzZXJDb25maWcpe1xuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZyA9IG5ldyBDb25maWcodXNlckNvbmZpZyk7XG4gICAgICAgIGNvbnN0IGluaXRpYWxDYW52YXMgPSBnZXRDYW52YXMoaXRlbSk7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nQ2hhcnQgPSBnZXRDaGFydChpbml0aWFsQ2FudmFzKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nQ2hhcnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FudmFzIGlzIGFscmVhZHkgaW4gdXNlLiBDaGFydCB3aXRoIElEIFxcJycgKyBleGlzdGluZ0NoYXJ0LmlkICsgJ1xcJycgKyAnIG11c3QgYmUgZGVzdHJveWVkIGJlZm9yZSB0aGUgY2FudmFzIHdpdGggSUQgXFwnJyArIGV4aXN0aW5nQ2hhcnQuY2FudmFzLmlkICsgJ1xcJyBjYW4gYmUgcmV1c2VkLicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBjb25maWcuY3JlYXRlUmVzb2x2ZXIoY29uZmlnLmNoYXJ0T3B0aW9uU2NvcGVzKCksIHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybSA9IG5ldyAoY29uZmlnLnBsYXRmb3JtIHx8IF9kZXRlY3RQbGF0Zm9ybShpbml0aWFsQ2FudmFzKSkoKTtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybS51cGRhdGVDb25maWcoY29uZmlnKTtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMucGxhdGZvcm0uYWNxdWlyZUNvbnRleHQoaW5pdGlhbENhbnZhcywgb3B0aW9ucy5hc3BlY3RSYXRpbyk7XG4gICAgICAgIGNvbnN0IGNhbnZhcyA9IGNvbnRleHQgJiYgY29udGV4dC5jYW52YXM7XG4gICAgICAgIGNvbnN0IGhlaWdodCA9IGNhbnZhcyAmJiBjYW52YXMuaGVpZ2h0O1xuICAgICAgICBjb25zdCB3aWR0aCA9IGNhbnZhcyAmJiBjYW52YXMud2lkdGg7XG4gICAgICAgIHRoaXMuaWQgPSB1aWQoKTtcbiAgICAgICAgdGhpcy5jdHggPSBjb250ZXh0O1xuICAgICAgICB0aGlzLmNhbnZhcyA9IGNhbnZhcztcbiAgICAgICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMuX2FzcGVjdFJhdGlvID0gdGhpcy5hc3BlY3RSYXRpbztcbiAgICAgICAgdGhpcy5fbGF5ZXJzID0gW107XG4gICAgICAgIHRoaXMuX21ldGFzZXRzID0gW107XG4gICAgICAgIHRoaXMuX3N0YWNrcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5ib3hlcyA9IFtdO1xuICAgICAgICB0aGlzLmN1cnJlbnREZXZpY2VQaXhlbFJhdGlvID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNoYXJ0QXJlYSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fYWN0aXZlID0gW107XG4gICAgICAgIHRoaXMuX2xhc3RFdmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fbGlzdGVuZXJzID0ge307XG4gICAgICAgICB0aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9zb3J0ZWRNZXRhc2V0cyA9IFtdO1xuICAgICAgICB0aGlzLnNjYWxlcyA9IHt9O1xuICAgICAgICB0aGlzLl9wbHVnaW5zID0gbmV3IFBsdWdpblNlcnZpY2UoKTtcbiAgICAgICAgdGhpcy4kcHJveGllcyA9IHt9O1xuICAgICAgICB0aGlzLl9oaWRkZW5JbmRpY2VzID0ge307XG4gICAgICAgIHRoaXMuYXR0YWNoZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fYW5pbWF0aW9uc0Rpc2FibGVkID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLiRjb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9kb1Jlc2l6ZSA9IGRlYm91bmNlKChtb2RlKT0+dGhpcy51cGRhdGUobW9kZSksIG9wdGlvbnMucmVzaXplRGVsYXkgfHwgMCk7XG4gICAgICAgIHRoaXMuX2RhdGFDaGFuZ2VzID0gW107XG4gICAgICAgIGluc3RhbmNlc1t0aGlzLmlkXSA9IHRoaXM7XG4gICAgICAgIGlmICghY29udGV4dCB8fCAhY2FudmFzKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIGNyZWF0ZSBjaGFydDogY2FuJ3QgYWNxdWlyZSBjb250ZXh0IGZyb20gdGhlIGdpdmVuIGl0ZW1cIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgYW5pbWF0b3IubGlzdGVuKHRoaXMsICdjb21wbGV0ZScsIG9uQW5pbWF0aW9uc0NvbXBsZXRlKTtcbiAgICAgICAgYW5pbWF0b3IubGlzdGVuKHRoaXMsICdwcm9ncmVzcycsIG9uQW5pbWF0aW9uUHJvZ3Jlc3MpO1xuICAgICAgICB0aGlzLl9pbml0aWFsaXplKCk7XG4gICAgICAgIGlmICh0aGlzLmF0dGFjaGVkKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBhc3BlY3RSYXRpbygpIHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zOiB7IGFzcGVjdFJhdGlvICwgbWFpbnRhaW5Bc3BlY3RSYXRpbyAgfSAsIHdpZHRoICwgaGVpZ2h0ICwgX2FzcGVjdFJhdGlvICB9ID0gdGhpcztcbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKGFzcGVjdFJhdGlvKSkge1xuICAgICAgICAgICAgcmV0dXJuIGFzcGVjdFJhdGlvO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYWludGFpbkFzcGVjdFJhdGlvICYmIF9hc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgcmV0dXJuIF9hc3BlY3RSYXRpbztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGVpZ2h0ID8gd2lkdGggLyBoZWlnaHQgOiBudWxsO1xuICAgIH1cbiAgICBnZXQgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGE7XG4gICAgfVxuICAgIHNldCBkYXRhKGRhdGEpIHtcbiAgICAgICAgdGhpcy5jb25maWcuZGF0YSA9IGRhdGE7XG4gICAgfVxuICAgIGdldCBvcHRpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucztcbiAgICB9XG4gICAgc2V0IG9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICB0aGlzLmNvbmZpZy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgZ2V0IHJlZ2lzdHJ5KCkge1xuICAgICAgICByZXR1cm4gcmVnaXN0cnk7XG4gICAgfVxuIF9pbml0aWFsaXplKCkge1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZUluaXQnKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5yZXNwb25zaXZlKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0aW5hU2NhbGUodGhpcywgdGhpcy5vcHRpb25zLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmluZEV2ZW50cygpO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVySW5pdCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgY2xlYXIoKSB7XG4gICAgICAgIGNsZWFyQ2FudmFzKHRoaXMuY2FudmFzLCB0aGlzLmN0eCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzdG9wKCkge1xuICAgICAgICBhbmltYXRvci5zdG9wKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gcmVzaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgaWYgKCFhbmltYXRvci5ydW5uaW5nKHRoaXMpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNpemUod2lkdGgsIGhlaWdodCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVCZWZvcmVEcmF3ID0ge1xuICAgICAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBfcmVzaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgY2FudmFzID0gdGhpcy5jYW52YXM7XG4gICAgICAgIGNvbnN0IGFzcGVjdFJhdGlvID0gb3B0aW9ucy5tYWludGFpbkFzcGVjdFJhdGlvICYmIHRoaXMuYXNwZWN0UmF0aW87XG4gICAgICAgIGNvbnN0IG5ld1NpemUgPSB0aGlzLnBsYXRmb3JtLmdldE1heGltdW1TaXplKGNhbnZhcywgd2lkdGgsIGhlaWdodCwgYXNwZWN0UmF0aW8pO1xuICAgICAgICBjb25zdCBuZXdSYXRpbyA9IG9wdGlvbnMuZGV2aWNlUGl4ZWxSYXRpbyB8fCB0aGlzLnBsYXRmb3JtLmdldERldmljZVBpeGVsUmF0aW8oKTtcbiAgICAgICAgY29uc3QgbW9kZSA9IHRoaXMud2lkdGggPyAncmVzaXplJyA6ICdhdHRhY2gnO1xuICAgICAgICB0aGlzLndpZHRoID0gbmV3U2l6ZS53aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBuZXdTaXplLmhlaWdodDtcbiAgICAgICAgdGhpcy5fYXNwZWN0UmF0aW8gPSB0aGlzLmFzcGVjdFJhdGlvO1xuICAgICAgICBpZiAoIXJldGluYVNjYWxlKHRoaXMsIG5ld1JhdGlvLCB0cnVlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygncmVzaXplJywge1xuICAgICAgICAgICAgc2l6ZTogbmV3U2l6ZVxuICAgICAgICB9KTtcbiAgICAgICAgY2FsbGJhY2sob3B0aW9ucy5vblJlc2l6ZSwgW1xuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgIG5ld1NpemVcbiAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmF0dGFjaGVkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fZG9SZXNpemUobW9kZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGVuc3VyZVNjYWxlc0hhdmVJRHMoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHNjYWxlc09wdGlvbnMgPSBvcHRpb25zLnNjYWxlcyB8fCB7fTtcbiAgICAgICAgZWFjaChzY2FsZXNPcHRpb25zLCAoYXhpc09wdGlvbnMsIGF4aXNJRCk9PntcbiAgICAgICAgICAgIGF4aXNPcHRpb25zLmlkID0gYXhpc0lEO1xuICAgICAgICB9KTtcbiAgICB9XG4gYnVpbGRPclVwZGF0ZVNjYWxlcygpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3Qgc2NhbGVPcHRzID0gb3B0aW9ucy5zY2FsZXM7XG4gICAgICAgIGNvbnN0IHNjYWxlcyA9IHRoaXMuc2NhbGVzO1xuICAgICAgICBjb25zdCB1cGRhdGVkID0gT2JqZWN0LmtleXMoc2NhbGVzKS5yZWR1Y2UoKG9iaiwgaWQpPT57XG4gICAgICAgICAgICBvYmpbaWRdID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9LCB7fSk7XG4gICAgICAgIGxldCBpdGVtcyA9IFtdO1xuICAgICAgICBpZiAoc2NhbGVPcHRzKSB7XG4gICAgICAgICAgICBpdGVtcyA9IGl0ZW1zLmNvbmNhdChPYmplY3Qua2V5cyhzY2FsZU9wdHMpLm1hcCgoaWQpPT57XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVPcHRpb25zID0gc2NhbGVPcHRzW2lkXTtcbiAgICAgICAgICAgICAgICBjb25zdCBheGlzID0gZGV0ZXJtaW5lQXhpcyhpZCwgc2NhbGVPcHRpb25zKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1JhZGlhbCA9IGF4aXMgPT09ICdyJztcbiAgICAgICAgICAgICAgICBjb25zdCBpc0hvcml6b250YWwgPSBheGlzID09PSAneCc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uczogc2NhbGVPcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICBkcG9zaXRpb246IGlzUmFkaWFsID8gJ2NoYXJ0QXJlYScgOiBpc0hvcml6b250YWwgPyAnYm90dG9tJyA6ICdsZWZ0JyxcbiAgICAgICAgICAgICAgICAgICAgZHR5cGU6IGlzUmFkaWFsID8gJ3JhZGlhbExpbmVhcicgOiBpc0hvcml6b250YWwgPyAnY2F0ZWdvcnknIDogJ2xpbmVhcidcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIGVhY2goaXRlbXMsIChpdGVtKT0+e1xuICAgICAgICAgICAgY29uc3Qgc2NhbGVPcHRpb25zID0gaXRlbS5vcHRpb25zO1xuICAgICAgICAgICAgY29uc3QgaWQgPSBzY2FsZU9wdGlvbnMuaWQ7XG4gICAgICAgICAgICBjb25zdCBheGlzID0gZGV0ZXJtaW5lQXhpcyhpZCwgc2NhbGVPcHRpb25zKTtcbiAgICAgICAgICAgIGNvbnN0IHNjYWxlVHlwZSA9IHZhbHVlT3JEZWZhdWx0KHNjYWxlT3B0aW9ucy50eXBlLCBpdGVtLmR0eXBlKTtcbiAgICAgICAgICAgIGlmIChzY2FsZU9wdGlvbnMucG9zaXRpb24gPT09IHVuZGVmaW5lZCB8fCBwb3NpdGlvbklzSG9yaXpvbnRhbChzY2FsZU9wdGlvbnMucG9zaXRpb24sIGF4aXMpICE9PSBwb3NpdGlvbklzSG9yaXpvbnRhbChpdGVtLmRwb3NpdGlvbikpIHtcbiAgICAgICAgICAgICAgICBzY2FsZU9wdGlvbnMucG9zaXRpb24gPSBpdGVtLmRwb3NpdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHVwZGF0ZWRbaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBzY2FsZSA9IG51bGw7XG4gICAgICAgICAgICBpZiAoaWQgaW4gc2NhbGVzICYmIHNjYWxlc1tpZF0udHlwZSA9PT0gc2NhbGVUeXBlKSB7XG4gICAgICAgICAgICAgICAgc2NhbGUgPSBzY2FsZXNbaWRdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzY2FsZUNsYXNzID0gcmVnaXN0cnkuZ2V0U2NhbGUoc2NhbGVUeXBlKTtcbiAgICAgICAgICAgICAgICBzY2FsZSA9IG5ldyBzY2FsZUNsYXNzKHtcbiAgICAgICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IHNjYWxlVHlwZSxcbiAgICAgICAgICAgICAgICAgICAgY3R4OiB0aGlzLmN0eCxcbiAgICAgICAgICAgICAgICAgICAgY2hhcnQ6IHRoaXNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzY2FsZXNbc2NhbGUuaWRdID0gc2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzY2FsZS5pbml0KHNjYWxlT3B0aW9ucywgb3B0aW9ucyk7XG4gICAgICAgIH0pO1xuICAgICAgICBlYWNoKHVwZGF0ZWQsIChoYXNVcGRhdGVkLCBpZCk9PntcbiAgICAgICAgICAgIGlmICghaGFzVXBkYXRlZCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBzY2FsZXNbaWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZWFjaChzY2FsZXMsIChzY2FsZSk9PntcbiAgICAgICAgICAgIGxheW91dHMuY29uZmlndXJlKHRoaXMsIHNjYWxlLCBzY2FsZS5vcHRpb25zKTtcbiAgICAgICAgICAgIGxheW91dHMuYWRkQm94KHRoaXMsIHNjYWxlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuIF91cGRhdGVNZXRhc2V0cygpIHtcbiAgICAgICAgY29uc3QgbWV0YXNldHMgPSB0aGlzLl9tZXRhc2V0cztcbiAgICAgICAgY29uc3QgbnVtRGF0YSA9IHRoaXMuZGF0YS5kYXRhc2V0cy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG51bU1ldGEgPSBtZXRhc2V0cy5sZW5ndGg7XG4gICAgICAgIG1ldGFzZXRzLnNvcnQoKGEsIGIpPT5hLmluZGV4IC0gYi5pbmRleCk7XG4gICAgICAgIGlmIChudW1NZXRhID4gbnVtRGF0YSkge1xuICAgICAgICAgICAgZm9yKGxldCBpID0gbnVtRGF0YTsgaSA8IG51bU1ldGE7ICsraSl7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGVzdHJveURhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWV0YXNldHMuc3BsaWNlKG51bURhdGEsIG51bU1ldGEgLSBudW1EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zb3J0ZWRNZXRhc2V0cyA9IG1ldGFzZXRzLnNsaWNlKDApLnNvcnQoY29tcGFyZTJMZXZlbCgnb3JkZXInLCAnaW5kZXgnKSk7XG4gICAgfVxuIF9yZW1vdmVVbnJlZmVyZW5jZWRNZXRhc2V0cygpIHtcbiAgICAgICAgY29uc3QgeyBfbWV0YXNldHM6IG1ldGFzZXRzICwgZGF0YTogeyBkYXRhc2V0cyAgfSAgfSA9IHRoaXM7XG4gICAgICAgIGlmIChtZXRhc2V0cy5sZW5ndGggPiBkYXRhc2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9zdGFja3M7XG4gICAgICAgIH1cbiAgICAgICAgbWV0YXNldHMuZm9yRWFjaCgobWV0YSwgaW5kZXgpPT57XG4gICAgICAgICAgICBpZiAoZGF0YXNldHMuZmlsdGVyKCh4KT0+eCA9PT0gbWV0YS5fZGF0YXNldCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGVzdHJveURhdGFzZXRNZXRhKGluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGJ1aWxkT3JVcGRhdGVDb250cm9sbGVycygpIHtcbiAgICAgICAgY29uc3QgbmV3Q29udHJvbGxlcnMgPSBbXTtcbiAgICAgICAgY29uc3QgZGF0YXNldHMgPSB0aGlzLmRhdGEuZGF0YXNldHM7XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICB0aGlzLl9yZW1vdmVVbnJlZmVyZW5jZWRNZXRhc2V0cygpO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBkYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyBpKyspe1xuICAgICAgICAgICAgY29uc3QgZGF0YXNldCA9IGRhdGFzZXRzW2ldO1xuICAgICAgICAgICAgbGV0IG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgY29uc3QgdHlwZSA9IGRhdGFzZXQudHlwZSB8fCB0aGlzLmNvbmZpZy50eXBlO1xuICAgICAgICAgICAgaWYgKG1ldGEudHlwZSAmJiBtZXRhLnR5cGUgIT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kZXN0cm95RGF0YXNldE1ldGEoaSk7XG4gICAgICAgICAgICAgICAgbWV0YSA9IHRoaXMuZ2V0RGF0YXNldE1ldGEoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZXRhLnR5cGUgPSB0eXBlO1xuICAgICAgICAgICAgbWV0YS5pbmRleEF4aXMgPSBkYXRhc2V0LmluZGV4QXhpcyB8fCBnZXRJbmRleEF4aXModHlwZSwgdGhpcy5vcHRpb25zKTtcbiAgICAgICAgICAgIG1ldGEub3JkZXIgPSBkYXRhc2V0Lm9yZGVyIHx8IDA7XG4gICAgICAgICAgICBtZXRhLmluZGV4ID0gaTtcbiAgICAgICAgICAgIG1ldGEubGFiZWwgPSAnJyArIGRhdGFzZXQubGFiZWw7XG4gICAgICAgICAgICBtZXRhLnZpc2libGUgPSB0aGlzLmlzRGF0YXNldFZpc2libGUoaSk7XG4gICAgICAgICAgICBpZiAobWV0YS5jb250cm9sbGVyKSB7XG4gICAgICAgICAgICAgICAgbWV0YS5jb250cm9sbGVyLnVwZGF0ZUluZGV4KGkpO1xuICAgICAgICAgICAgICAgIG1ldGEuY29udHJvbGxlci5saW5rU2NhbGVzKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IENvbnRyb2xsZXJDbGFzcyA9IHJlZ2lzdHJ5LmdldENvbnRyb2xsZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBkYXRhc2V0RWxlbWVudFR5cGUgLCBkYXRhRWxlbWVudFR5cGUgIH0gPSBkZWZhdWx0cy5kYXRhc2V0c1t0eXBlXTtcbiAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKENvbnRyb2xsZXJDbGFzcywge1xuICAgICAgICAgICAgICAgICAgICBkYXRhRWxlbWVudFR5cGU6IHJlZ2lzdHJ5LmdldEVsZW1lbnQoZGF0YUVsZW1lbnRUeXBlKSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YXNldEVsZW1lbnRUeXBlOiBkYXRhc2V0RWxlbWVudFR5cGUgJiYgcmVnaXN0cnkuZ2V0RWxlbWVudChkYXRhc2V0RWxlbWVudFR5cGUpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbWV0YS5jb250cm9sbGVyID0gbmV3IENvbnRyb2xsZXJDbGFzcyh0aGlzLCBpKTtcbiAgICAgICAgICAgICAgICBuZXdDb250cm9sbGVycy5wdXNoKG1ldGEuY29udHJvbGxlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdXBkYXRlTWV0YXNldHMoKTtcbiAgICAgICAgcmV0dXJuIG5ld0NvbnRyb2xsZXJzO1xuICAgIH1cbiBfcmVzZXRFbGVtZW50cygpIHtcbiAgICAgICAgZWFjaCh0aGlzLmRhdGEuZGF0YXNldHMsIChkYXRhc2V0LCBkYXRhc2V0SW5kZXgpPT57XG4gICAgICAgICAgICB0aGlzLmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuY29udHJvbGxlci5yZXNldCgpO1xuICAgICAgICB9LCB0aGlzKTtcbiAgICB9XG4gcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuX3Jlc2V0RWxlbWVudHMoKTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdyZXNldCcpO1xuICAgIH1cbiAgICB1cGRhdGUobW9kZSkge1xuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZztcbiAgICAgICAgY29uZmlnLnVwZGF0ZSgpO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5fb3B0aW9ucyA9IGNvbmZpZy5jcmVhdGVSZXNvbHZlcihjb25maWcuY2hhcnRPcHRpb25TY29wZXMoKSwgdGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICBjb25zdCBhbmltc0Rpc2FibGVkID0gdGhpcy5fYW5pbWF0aW9uc0Rpc2FibGVkID0gIW9wdGlvbnMuYW5pbWF0aW9uO1xuICAgICAgICB0aGlzLl91cGRhdGVTY2FsZXMoKTtcbiAgICAgICAgdGhpcy5fY2hlY2tFdmVudEJpbmRpbmdzKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUhpZGRlbkluZGljZXMoKTtcbiAgICAgICAgdGhpcy5fcGx1Z2lucy5pbnZhbGlkYXRlKCk7XG4gICAgICAgIGlmICh0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZVVwZGF0ZScsIHtcbiAgICAgICAgICAgIG1vZGUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5ld0NvbnRyb2xsZXJzID0gdGhpcy5idWlsZE9yVXBkYXRlQ29udHJvbGxlcnMoKTtcbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVFbGVtZW50c1VwZGF0ZScpO1xuICAgICAgICBsZXQgbWluUGFkZGluZyA9IDA7XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgICAgIGNvbnN0IHsgY29udHJvbGxlciAgfSA9IHRoaXMuZ2V0RGF0YXNldE1ldGEoaSk7XG4gICAgICAgICAgICBjb25zdCByZXNldCA9ICFhbmltc0Rpc2FibGVkICYmIG5ld0NvbnRyb2xsZXJzLmluZGV4T2YoY29udHJvbGxlcikgPT09IC0xO1xuICAgICAgICAgICAgY29udHJvbGxlci5idWlsZE9yVXBkYXRlRWxlbWVudHMocmVzZXQpO1xuICAgICAgICAgICAgbWluUGFkZGluZyA9IE1hdGgubWF4KCtjb250cm9sbGVyLmdldE1heE92ZXJmbG93KCksIG1pblBhZGRpbmcpO1xuICAgICAgICB9XG4gICAgICAgIG1pblBhZGRpbmcgPSB0aGlzLl9taW5QYWRkaW5nID0gb3B0aW9ucy5sYXlvdXQuYXV0b1BhZGRpbmcgPyBtaW5QYWRkaW5nIDogMDtcbiAgICAgICAgdGhpcy5fdXBkYXRlTGF5b3V0KG1pblBhZGRpbmcpO1xuICAgICAgICBpZiAoIWFuaW1zRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGVhY2gobmV3Q29udHJvbGxlcnMsIChjb250cm9sbGVyKT0+e1xuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXIucmVzZXQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3VwZGF0ZURhdGFzZXRzKG1vZGUpO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyVXBkYXRlJywge1xuICAgICAgICAgICAgbW9kZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fbGF5ZXJzLnNvcnQoY29tcGFyZTJMZXZlbCgneicsICdfaWR4JykpO1xuICAgICAgICBjb25zdCB7IF9hY3RpdmUgLCBfbGFzdEV2ZW50ICB9ID0gdGhpcztcbiAgICAgICAgaWYgKF9sYXN0RXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlcihfbGFzdEV2ZW50LCB0cnVlKTtcbiAgICAgICAgfSBlbHNlIGlmIChfYWN0aXZlLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlSG92ZXJTdHlsZXMoX2FjdGl2ZSwgX2FjdGl2ZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICB9XG4gX3VwZGF0ZVNjYWxlcygpIHtcbiAgICAgICAgZWFjaCh0aGlzLnNjYWxlcywgKHNjYWxlKT0+e1xuICAgICAgICAgICAgbGF5b3V0cy5yZW1vdmVCb3godGhpcywgc2NhbGUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5lbnN1cmVTY2FsZXNIYXZlSURzKCk7XG4gICAgICAgIHRoaXMuYnVpbGRPclVwZGF0ZVNjYWxlcygpO1xuICAgIH1cbiBfY2hlY2tFdmVudEJpbmRpbmdzKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBleGlzdGluZ0V2ZW50cyA9IG5ldyBTZXQoT2JqZWN0LmtleXModGhpcy5fbGlzdGVuZXJzKSk7XG4gICAgICAgIGNvbnN0IG5ld0V2ZW50cyA9IG5ldyBTZXQob3B0aW9ucy5ldmVudHMpO1xuICAgICAgICBpZiAoIXNldHNFcXVhbChleGlzdGluZ0V2ZW50cywgbmV3RXZlbnRzKSB8fCAhIXRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnMgIT09IG9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgICAgICAgdGhpcy51bmJpbmRFdmVudHMoKTtcbiAgICAgICAgICAgIHRoaXMuYmluZEV2ZW50cygpO1xuICAgICAgICB9XG4gICAgfVxuIF91cGRhdGVIaWRkZW5JbmRpY2VzKCkge1xuICAgICAgICBjb25zdCB7IF9oaWRkZW5JbmRpY2VzICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgY2hhbmdlcyA9IHRoaXMuX2dldFVuaWZvcm1EYXRhQ2hhbmdlcygpIHx8IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHsgbWV0aG9kICwgc3RhcnQgLCBjb3VudCAgfSBvZiBjaGFuZ2VzKXtcbiAgICAgICAgICAgIGNvbnN0IG1vdmUgPSBtZXRob2QgPT09ICdfcmVtb3ZlRWxlbWVudHMnID8gLWNvdW50IDogY291bnQ7XG4gICAgICAgICAgICBtb3ZlTnVtZXJpY0tleXMoX2hpZGRlbkluZGljZXMsIHN0YXJ0LCBtb3ZlKTtcbiAgICAgICAgfVxuICAgIH1cbiBfZ2V0VW5pZm9ybURhdGFDaGFuZ2VzKCkge1xuICAgICAgICBjb25zdCBfZGF0YUNoYW5nZXMgPSB0aGlzLl9kYXRhQ2hhbmdlcztcbiAgICAgICAgaWYgKCFfZGF0YUNoYW5nZXMgfHwgIV9kYXRhQ2hhbmdlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9kYXRhQ2hhbmdlcyA9IFtdO1xuICAgICAgICBjb25zdCBkYXRhc2V0Q291bnQgPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoO1xuICAgICAgICBjb25zdCBtYWtlU2V0ID0gKGlkeCk9Pm5ldyBTZXQoX2RhdGFDaGFuZ2VzLmZpbHRlcigoYyk9PmNbMF0gPT09IGlkeCkubWFwKChjLCBpKT0+aSArICcsJyArIGMuc3BsaWNlKDEpLmpvaW4oJywnKSkpO1xuICAgICAgICBjb25zdCBjaGFuZ2VTZXQgPSBtYWtlU2V0KDApO1xuICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgZGF0YXNldENvdW50OyBpKyspe1xuICAgICAgICAgICAgaWYgKCFzZXRzRXF1YWwoY2hhbmdlU2V0LCBtYWtlU2V0KGkpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbShjaGFuZ2VTZXQpLm1hcCgoYyk9PmMuc3BsaXQoJywnKSkubWFwKChhKT0+KHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6IGFbMV0sXG4gICAgICAgICAgICAgICAgc3RhcnQ6ICthWzJdLFxuICAgICAgICAgICAgICAgIGNvdW50OiArYVszXVxuICAgICAgICAgICAgfSkpO1xuICAgIH1cbiBfdXBkYXRlTGF5b3V0KG1pblBhZGRpbmcpIHtcbiAgICAgICAgaWYgKHRoaXMubm90aWZ5UGx1Z2lucygnYmVmb3JlTGF5b3V0Jywge1xuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsYXlvdXRzLnVwZGF0ZSh0aGlzLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCwgbWluUGFkZGluZyk7XG4gICAgICAgIGNvbnN0IGFyZWEgPSB0aGlzLmNoYXJ0QXJlYTtcbiAgICAgICAgY29uc3Qgbm9BcmVhID0gYXJlYS53aWR0aCA8PSAwIHx8IGFyZWEuaGVpZ2h0IDw9IDA7XG4gICAgICAgIHRoaXMuX2xheWVycyA9IFtdO1xuICAgICAgICBlYWNoKHRoaXMuYm94ZXMsIChib3gpPT57XG4gICAgICAgICAgICBpZiAobm9BcmVhICYmIGJveC5wb3NpdGlvbiA9PT0gJ2NoYXJ0QXJlYScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYm94LmNvbmZpZ3VyZSkge1xuICAgICAgICAgICAgICAgIGJveC5jb25maWd1cmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2xheWVycy5wdXNoKC4uLmJveC5fbGF5ZXJzKCkpO1xuICAgICAgICB9LCB0aGlzKTtcbiAgICAgICAgdGhpcy5fbGF5ZXJzLmZvckVhY2goKGl0ZW0sIGluZGV4KT0+e1xuICAgICAgICAgICAgaXRlbS5faWR4ID0gaW5kZXg7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyTGF5b3V0Jyk7XG4gICAgfVxuIF91cGRhdGVEYXRhc2V0cyhtb2RlKSB7XG4gICAgICAgIGlmICh0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURhdGFzZXRzVXBkYXRlJywge1xuICAgICAgICAgICAgbW9kZSxcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGxldCBpID0gMCwgaWxlbiA9IHRoaXMuZGF0YS5kYXRhc2V0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdGhpcy5nZXREYXRhc2V0TWV0YShpKS5jb250cm9sbGVyLmNvbmZpZ3VyZSgpO1xuICAgICAgICB9XG4gICAgICAgIGZvcihsZXQgaSA9IDAsIGlsZW4gPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZURhdGFzZXQoaSwgaXNGdW5jdGlvbihtb2RlKSA/IG1vZGUoe1xuICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleDogaVxuICAgICAgICAgICAgfSkgOiBtb2RlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldHNVcGRhdGUnLCB7XG4gICAgICAgICAgICBtb2RlXG4gICAgICAgIH0pO1xuICAgIH1cbiBfdXBkYXRlRGF0YXNldChpbmRleCwgbW9kZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShpbmRleCk7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICAgICAgICBtZXRhLFxuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBtb2RlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEYXRhc2V0VXBkYXRlJywgYXJncykgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbWV0YS5jb250cm9sbGVyLl91cGRhdGUobW9kZSk7XG4gICAgICAgIGFyZ3MuY2FuY2VsYWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldFVwZGF0ZScsIGFyZ3MpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZVJlbmRlcicsIHtcbiAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgfSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFuaW1hdG9yLmhhcyh0aGlzKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuYXR0YWNoZWQgJiYgIWFuaW1hdG9yLnJ1bm5pbmcodGhpcykpIHtcbiAgICAgICAgICAgICAgICBhbmltYXRvci5zdGFydCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZHJhdygpO1xuICAgICAgICAgICAgb25BbmltYXRpb25zQ29tcGxldGUoe1xuICAgICAgICAgICAgICAgIGNoYXJ0OiB0aGlzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkcmF3KCkge1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgaWYgKHRoaXMuX3Jlc2l6ZUJlZm9yZURyYXcpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgd2lkdGggLCBoZWlnaHQgIH0gPSB0aGlzLl9yZXNpemVCZWZvcmVEcmF3O1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplQmVmb3JlRHJhdyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgICBpZiAodGhpcy53aWR0aCA8PSAwIHx8IHRoaXMuaGVpZ2h0IDw9IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEcmF3Jywge1xuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsYXllcnMgPSB0aGlzLl9sYXllcnM7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxheWVycy5sZW5ndGggJiYgbGF5ZXJzW2ldLnogPD0gMDsgKytpKXtcbiAgICAgICAgICAgIGxheWVyc1tpXS5kcmF3KHRoaXMuY2hhcnRBcmVhKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9kcmF3RGF0YXNldHMoKTtcbiAgICAgICAgZm9yKDsgaSA8IGxheWVycy5sZW5ndGg7ICsraSl7XG4gICAgICAgICAgICBsYXllcnNbaV0uZHJhdyh0aGlzLmNoYXJ0QXJlYSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub3RpZnlQbHVnaW5zKCdhZnRlckRyYXcnKTtcbiAgICB9XG4gX2dldFNvcnRlZERhdGFzZXRNZXRhcyhmaWx0ZXJWaXNpYmxlKSB7XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gdGhpcy5fc29ydGVkTWV0YXNldHM7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbjtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gbWV0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IG1ldGEgPSBtZXRhc2V0c1tpXTtcbiAgICAgICAgICAgIGlmICghZmlsdGVyVmlzaWJsZSB8fCBtZXRhLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChtZXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiBnZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0U29ydGVkRGF0YXNldE1ldGFzKHRydWUpO1xuICAgIH1cbiBfZHJhd0RhdGFzZXRzKCkge1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVEYXRhc2V0c0RyYXcnLCB7XG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gdGhpcy5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCk7XG4gICAgICAgIGZvcihsZXQgaSA9IG1ldGFzZXRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKXtcbiAgICAgICAgICAgIHRoaXMuX2RyYXdEYXRhc2V0KG1ldGFzZXRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldHNEcmF3Jyk7XG4gICAgfVxuIF9kcmF3RGF0YXNldChtZXRhKSB7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICBjb25zdCBjbGlwID0gbWV0YS5fY2xpcDtcbiAgICAgICAgY29uc3QgdXNlQ2xpcCA9ICFjbGlwLmRpc2FibGVkO1xuICAgICAgICBjb25zdCBhcmVhID0gZ2V0RGF0YXNldEFyZWEobWV0YSkgfHwgdGhpcy5jaGFydEFyZWE7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICAgICAgICBtZXRhLFxuICAgICAgICAgICAgaW5kZXg6IG1ldGEuaW5kZXgsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURhdGFzZXREcmF3JywgYXJncykgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVzZUNsaXApIHtcbiAgICAgICAgICAgIGNsaXBBcmVhKGN0eCwge1xuICAgICAgICAgICAgICAgIGxlZnQ6IGNsaXAubGVmdCA9PT0gZmFsc2UgPyAwIDogYXJlYS5sZWZ0IC0gY2xpcC5sZWZ0LFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBjbGlwLnJpZ2h0ID09PSBmYWxzZSA/IHRoaXMud2lkdGggOiBhcmVhLnJpZ2h0ICsgY2xpcC5yaWdodCxcbiAgICAgICAgICAgICAgICB0b3A6IGNsaXAudG9wID09PSBmYWxzZSA/IDAgOiBhcmVhLnRvcCAtIGNsaXAudG9wLFxuICAgICAgICAgICAgICAgIGJvdHRvbTogY2xpcC5ib3R0b20gPT09IGZhbHNlID8gdGhpcy5oZWlnaHQgOiBhcmVhLmJvdHRvbSArIGNsaXAuYm90dG9tXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBtZXRhLmNvbnRyb2xsZXIuZHJhdygpO1xuICAgICAgICBpZiAodXNlQ2xpcCkge1xuICAgICAgICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgICAgICB9XG4gICAgICAgIGFyZ3MuY2FuY2VsYWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGF0YXNldERyYXcnLCBhcmdzKTtcbiAgICB9XG4gaXNQb2ludEluQXJlYShwb2ludCkge1xuICAgICAgICByZXR1cm4gX2lzUG9pbnRJbkFyZWEocG9pbnQsIHRoaXMuY2hhcnRBcmVhLCB0aGlzLl9taW5QYWRkaW5nKTtcbiAgICB9XG4gICAgZ2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZShlLCBtb2RlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IG1ldGhvZCA9IEludGVyYWN0aW9uLm1vZGVzW21vZGVdO1xuICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGhvZCh0aGlzLCBlLCBvcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkge1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5kYXRhLmRhdGFzZXRzW2RhdGFzZXRJbmRleF07XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gdGhpcy5fbWV0YXNldHM7XG4gICAgICAgIGxldCBtZXRhID0gbWV0YXNldHMuZmlsdGVyKCh4KT0+eCAmJiB4Ll9kYXRhc2V0ID09PSBkYXRhc2V0KS5wb3AoKTtcbiAgICAgICAgaWYgKCFtZXRhKSB7XG4gICAgICAgICAgICBtZXRhID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IG51bGwsXG4gICAgICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICAgICAgZGF0YXNldDogbnVsbCxcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBudWxsLFxuICAgICAgICAgICAgICAgIGhpZGRlbjogbnVsbCxcbiAgICAgICAgICAgICAgICB4QXhpc0lEOiBudWxsLFxuICAgICAgICAgICAgICAgIHlBeGlzSUQ6IG51bGwsXG4gICAgICAgICAgICAgICAgb3JkZXI6IGRhdGFzZXQgJiYgZGF0YXNldC5vcmRlciB8fCAwLFxuICAgICAgICAgICAgICAgIGluZGV4OiBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgX2RhdGFzZXQ6IGRhdGFzZXQsXG4gICAgICAgICAgICAgICAgX3BhcnNlZDogW10sXG4gICAgICAgICAgICAgICAgX3NvcnRlZDogZmFsc2VcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBtZXRhc2V0cy5wdXNoKG1ldGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhO1xuICAgIH1cbiAgICBnZXRDb250ZXh0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kY29udGV4dCB8fCAodGhpcy4kY29udGV4dCA9IGNyZWF0ZUNvbnRleHQobnVsbCwge1xuICAgICAgICAgICAgY2hhcnQ6IHRoaXMsXG4gICAgICAgICAgICB0eXBlOiAnY2hhcnQnXG4gICAgICAgIH0pKTtcbiAgICB9XG4gICAgZ2V0VmlzaWJsZURhdGFzZXRDb3VudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpLmxlbmd0aDtcbiAgICB9XG4gICAgaXNEYXRhc2V0VmlzaWJsZShkYXRhc2V0SW5kZXgpIHtcbiAgICAgICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZGF0YS5kYXRhc2V0c1tkYXRhc2V0SW5kZXhdO1xuICAgICAgICBpZiAoIWRhdGFzZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICByZXR1cm4gdHlwZW9mIG1ldGEuaGlkZGVuID09PSAnYm9vbGVhbicgPyAhbWV0YS5oaWRkZW4gOiAhZGF0YXNldC5oaWRkZW47XG4gICAgfVxuICAgIHNldERhdGFzZXRWaXNpYmlsaXR5KGRhdGFzZXRJbmRleCwgdmlzaWJsZSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICBtZXRhLmhpZGRlbiA9ICF2aXNpYmxlO1xuICAgIH1cbiAgICB0b2dnbGVEYXRhVmlzaWJpbGl0eShpbmRleCkge1xuICAgICAgICB0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XSA9ICF0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XTtcbiAgICB9XG4gICAgZ2V0RGF0YVZpc2liaWxpdHkoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLl9oaWRkZW5JbmRpY2VzW2luZGV4XTtcbiAgICB9XG4gX3VwZGF0ZVZpc2liaWxpdHkoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgsIHZpc2libGUpIHtcbiAgICAgICAgY29uc3QgbW9kZSA9IHZpc2libGUgPyAnc2hvdycgOiAnaGlkZSc7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IGFuaW1zID0gbWV0YS5jb250cm9sbGVyLl9yZXNvbHZlQW5pbWF0aW9ucyh1bmRlZmluZWQsIG1vZGUpO1xuICAgICAgICBpZiAoZGVmaW5lZChkYXRhSW5kZXgpKSB7XG4gICAgICAgICAgICBtZXRhLmRhdGFbZGF0YUluZGV4XS5oaWRkZW4gPSAhdmlzaWJsZTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldERhdGFzZXRWaXNpYmlsaXR5KGRhdGFzZXRJbmRleCwgdmlzaWJsZSk7XG4gICAgICAgICAgICBhbmltcy51cGRhdGUobWV0YSwge1xuICAgICAgICAgICAgICAgIHZpc2libGVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUoKGN0eCk9PmN0eC5kYXRhc2V0SW5kZXggPT09IGRhdGFzZXRJbmRleCA/IG1vZGUgOiB1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhpZGUoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlVmlzaWJpbGl0eShkYXRhc2V0SW5kZXgsIGRhdGFJbmRleCwgZmFsc2UpO1xuICAgIH1cbiAgICBzaG93KGRhdGFzZXRJbmRleCwgZGF0YUluZGV4KSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVZpc2liaWxpdHkoZGF0YXNldEluZGV4LCBkYXRhSW5kZXgsIHRydWUpO1xuICAgIH1cbiBfZGVzdHJveURhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5fbWV0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICAgICAgaWYgKG1ldGEgJiYgbWV0YS5jb250cm9sbGVyKSB7XG4gICAgICAgICAgICBtZXRhLmNvbnRyb2xsZXIuX2Rlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgdGhpcy5fbWV0YXNldHNbZGF0YXNldEluZGV4XTtcbiAgICB9XG4gICAgX3N0b3AoKSB7XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgYW5pbWF0b3IucmVtb3ZlKHRoaXMpO1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSB0aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2JlZm9yZURlc3Ryb3knKTtcbiAgICAgICAgY29uc3QgeyBjYW52YXMgLCBjdHggIH0gPSB0aGlzO1xuICAgICAgICB0aGlzLl9zdG9wKCk7XG4gICAgICAgIHRoaXMuY29uZmlnLmNsZWFyQ2FjaGUoKTtcbiAgICAgICAgaWYgKGNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy51bmJpbmRFdmVudHMoKTtcbiAgICAgICAgICAgIGNsZWFyQ2FudmFzKGNhbnZhcywgY3R4KTtcbiAgICAgICAgICAgIHRoaXMucGxhdGZvcm0ucmVsZWFzZUNvbnRleHQoY3R4KTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgaW5zdGFuY2VzW3RoaXMuaWRdO1xuICAgICAgICB0aGlzLm5vdGlmeVBsdWdpbnMoJ2FmdGVyRGVzdHJveScpO1xuICAgIH1cbiAgICB0b0Jhc2U2NEltYWdlKC4uLmFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzLnRvRGF0YVVSTCguLi5hcmdzKTtcbiAgICB9XG4gYmluZEV2ZW50cygpIHtcbiAgICAgICAgdGhpcy5iaW5kVXNlckV2ZW50cygpO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJlc3BvbnNpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuYmluZFJlc3BvbnNpdmVFdmVudHMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuIGJpbmRVc2VyRXZlbnRzKCkge1xuICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICAgIGNvbnN0IHBsYXRmb3JtID0gdGhpcy5wbGF0Zm9ybTtcbiAgICAgICAgY29uc3QgX2FkZCA9ICh0eXBlLCBsaXN0ZW5lcik9PntcbiAgICAgICAgICAgIHBsYXRmb3JtLmFkZEV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXJzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGxpc3RlbmVyID0gKGUsIHgsIHkpPT57XG4gICAgICAgICAgICBlLm9mZnNldFggPSB4O1xuICAgICAgICAgICAgZS5vZmZzZXRZID0geTtcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlcihlKTtcbiAgICAgICAgfTtcbiAgICAgICAgZWFjaCh0aGlzLm9wdGlvbnMuZXZlbnRzLCAodHlwZSk9Pl9hZGQodHlwZSwgbGlzdGVuZXIpKTtcbiAgICB9XG4gYmluZFJlc3BvbnNpdmVFdmVudHMoKSB7XG4gICAgICAgIGlmICghdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycykge1xuICAgICAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnM7XG4gICAgICAgIGNvbnN0IHBsYXRmb3JtID0gdGhpcy5wbGF0Zm9ybTtcbiAgICAgICAgY29uc3QgX2FkZCA9ICh0eXBlLCBsaXN0ZW5lcik9PntcbiAgICAgICAgICAgIHBsYXRmb3JtLmFkZEV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXJzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IF9yZW1vdmUgPSAodHlwZSwgbGlzdGVuZXIpPT57XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgcGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGxpc3RlbmVyc1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAod2lkdGgsIGhlaWdodCk9PntcbiAgICAgICAgICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBsZXQgZGV0YWNoZWQ7XG4gICAgICAgIGNvbnN0IGF0dGFjaGVkID0gKCk9PntcbiAgICAgICAgICAgIF9yZW1vdmUoJ2F0dGFjaCcsIGF0dGFjaGVkKTtcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICAgICAgICAgIF9hZGQoJ3Jlc2l6ZScsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIF9hZGQoJ2RldGFjaCcsIGRldGFjaGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgZGV0YWNoZWQgPSAoKT0+e1xuICAgICAgICAgICAgdGhpcy5hdHRhY2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgX3JlbW92ZSgncmVzaXplJywgbGlzdGVuZXIpO1xuICAgICAgICAgICAgdGhpcy5fc3RvcCgpO1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplKDAsIDApO1xuICAgICAgICAgICAgX2FkZCgnYXR0YWNoJywgYXR0YWNoZWQpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAocGxhdGZvcm0uaXNBdHRhY2hlZCh0aGlzLmNhbnZhcykpIHtcbiAgICAgICAgICAgIGF0dGFjaGVkKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZXRhY2hlZCgpO1xuICAgICAgICB9XG4gICAgfVxuIHVuYmluZEV2ZW50cygpIHtcbiAgICAgICAgZWFjaCh0aGlzLl9saXN0ZW5lcnMsIChsaXN0ZW5lciwgdHlwZSk9PntcbiAgICAgICAgICAgIHRoaXMucGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9saXN0ZW5lcnMgPSB7fTtcbiAgICAgICAgZWFjaCh0aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzLCAobGlzdGVuZXIsIHR5cGUpPT57XG4gICAgICAgICAgICB0aGlzLnBsYXRmb3JtLnJlbW92ZUV2ZW50TGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdXBkYXRlSG92ZXJTdHlsZShpdGVtcywgbW9kZSwgZW5hYmxlZCkge1xuICAgICAgICBjb25zdCBwcmVmaXggPSBlbmFibGVkID8gJ3NldCcgOiAncmVtb3ZlJztcbiAgICAgICAgbGV0IG1ldGEsIGl0ZW0sIGksIGlsZW47XG4gICAgICAgIGlmIChtb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICAgIG1ldGEgPSB0aGlzLmdldERhdGFzZXRNZXRhKGl0ZW1zWzBdLmRhdGFzZXRJbmRleCk7XG4gICAgICAgICAgICBtZXRhLmNvbnRyb2xsZXJbJ18nICsgcHJlZml4ICsgJ0RhdGFzZXRIb3ZlclN0eWxlJ10oKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IGl0ZW0gJiYgdGhpcy5nZXREYXRhc2V0TWV0YShpdGVtLmRhdGFzZXRJbmRleCkuY29udHJvbGxlcjtcbiAgICAgICAgICAgIGlmIChjb250cm9sbGVyKSB7XG4gICAgICAgICAgICAgICAgY29udHJvbGxlcltwcmVmaXggKyAnSG92ZXJTdHlsZSddKGl0ZW0uZWxlbWVudCwgaXRlbS5kYXRhc2V0SW5kZXgsIGl0ZW0uaW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuIGdldEFjdGl2ZUVsZW1lbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgIH1cbiBzZXRBY3RpdmVFbGVtZW50cyhhY3RpdmVFbGVtZW50cykge1xuICAgICAgICBjb25zdCBsYXN0QWN0aXZlID0gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSBhY3RpdmVFbGVtZW50cy5tYXAoKHsgZGF0YXNldEluZGV4ICwgaW5kZXggIH0pPT57XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgaWYgKCFtZXRhKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBkYXRhc2V0IGZvdW5kIGF0IGluZGV4ICcgKyBkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXgsXG4gICAgICAgICAgICAgICAgZWxlbWVudDogbWV0YS5kYXRhW2luZGV4XSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNoYW5nZWQgPSAhX2VsZW1lbnRzRXF1YWwoYWN0aXZlLCBsYXN0QWN0aXZlKTtcbiAgICAgICAgaWYgKGNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuX2xhc3RFdmVudCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVIb3ZlclN0eWxlcyhhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICB9XG4gICAgfVxuIG5vdGlmeVBsdWdpbnMoaG9vaywgYXJncywgZmlsdGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wbHVnaW5zLm5vdGlmeSh0aGlzLCBob29rLCBhcmdzLCBmaWx0ZXIpO1xuICAgIH1cbiBpc1BsdWdpbkVuYWJsZWQocGx1Z2luSWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BsdWdpbnMuX2NhY2hlLmZpbHRlcigocCk9PnAucGx1Z2luLmlkID09PSBwbHVnaW5JZCkubGVuZ3RoID09PSAxO1xuICAgIH1cbiBfdXBkYXRlSG92ZXJTdHlsZXMoYWN0aXZlLCBsYXN0QWN0aXZlLCByZXBsYXkpIHtcbiAgICAgICAgY29uc3QgaG92ZXJPcHRpb25zID0gdGhpcy5vcHRpb25zLmhvdmVyO1xuICAgICAgICBjb25zdCBkaWZmID0gKGEsIGIpPT5hLmZpbHRlcigoeCk9PiFiLnNvbWUoKHkpPT54LmRhdGFzZXRJbmRleCA9PT0geS5kYXRhc2V0SW5kZXggJiYgeC5pbmRleCA9PT0geS5pbmRleCkpO1xuICAgICAgICBjb25zdCBkZWFjdGl2YXRlZCA9IGRpZmYobGFzdEFjdGl2ZSwgYWN0aXZlKTtcbiAgICAgICAgY29uc3QgYWN0aXZhdGVkID0gcmVwbGF5ID8gYWN0aXZlIDogZGlmZihhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICBpZiAoZGVhY3RpdmF0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUhvdmVyU3R5bGUoZGVhY3RpdmF0ZWQsIGhvdmVyT3B0aW9ucy5tb2RlLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGl2YXRlZC5sZW5ndGggJiYgaG92ZXJPcHRpb25zLm1vZGUpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSG92ZXJTdHlsZShhY3RpdmF0ZWQsIGhvdmVyT3B0aW9ucy5tb2RlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbiBfZXZlbnRIYW5kbGVyKGUsIHJlcGxheSkge1xuICAgICAgICBjb25zdCBhcmdzID0ge1xuICAgICAgICAgICAgZXZlbnQ6IGUsXG4gICAgICAgICAgICByZXBsYXksXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgaW5DaGFydEFyZWE6IHRoaXMuaXNQb2ludEluQXJlYShlKVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBldmVudEZpbHRlciA9IChwbHVnaW4pPT4ocGx1Z2luLm9wdGlvbnMuZXZlbnRzIHx8IHRoaXMub3B0aW9ucy5ldmVudHMpLmluY2x1ZGVzKGUubmF0aXZlLnR5cGUpO1xuICAgICAgICBpZiAodGhpcy5ub3RpZnlQbHVnaW5zKCdiZWZvcmVFdmVudCcsIGFyZ3MsIGV2ZW50RmlsdGVyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFuZ2VkID0gdGhpcy5faGFuZGxlRXZlbnQoZSwgcmVwbGF5LCBhcmdzLmluQ2hhcnRBcmVhKTtcbiAgICAgICAgYXJncy5jYW5jZWxhYmxlID0gZmFsc2U7XG4gICAgICAgIHRoaXMubm90aWZ5UGx1Z2lucygnYWZ0ZXJFdmVudCcsIGFyZ3MsIGV2ZW50RmlsdGVyKTtcbiAgICAgICAgaWYgKGNoYW5nZWQgfHwgYXJncy5jaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiBfaGFuZGxlRXZlbnQoZSwgcmVwbGF5LCBpbkNoYXJ0QXJlYSkge1xuICAgICAgICBjb25zdCB7IF9hY3RpdmU6IGxhc3RBY3RpdmUgPSBbXSAsIG9wdGlvbnMgIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB1c2VGaW5hbFBvc2l0aW9uID0gcmVwbGF5O1xuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLl9nZXRBY3RpdmVFbGVtZW50cyhlLCBsYXN0QWN0aXZlLCBpbkNoYXJ0QXJlYSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGNvbnN0IGlzQ2xpY2sgPSBfaXNDbGlja0V2ZW50KGUpO1xuICAgICAgICBjb25zdCBsYXN0RXZlbnQgPSBkZXRlcm1pbmVMYXN0RXZlbnQoZSwgdGhpcy5fbGFzdEV2ZW50LCBpbkNoYXJ0QXJlYSwgaXNDbGljayk7XG4gICAgICAgIGlmIChpbkNoYXJ0QXJlYSkge1xuICAgICAgICAgICAgdGhpcy5fbGFzdEV2ZW50ID0gbnVsbDtcbiAgICAgICAgICAgIGNhbGxiYWNrKG9wdGlvbnMub25Ib3ZlciwgW1xuICAgICAgICAgICAgICAgIGUsXG4gICAgICAgICAgICAgICAgYWN0aXZlLFxuICAgICAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgIF0sIHRoaXMpO1xuICAgICAgICAgICAgaWYgKGlzQ2xpY2spIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhvcHRpb25zLm9uQ2xpY2ssIFtcbiAgICAgICAgICAgICAgICAgICAgZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hhbmdlZCA9ICFfZWxlbWVudHNFcXVhbChhY3RpdmUsIGxhc3RBY3RpdmUpO1xuICAgICAgICBpZiAoY2hhbmdlZCB8fCByZXBsYXkpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUhvdmVyU3R5bGVzKGFjdGl2ZSwgbGFzdEFjdGl2ZSwgcmVwbGF5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sYXN0RXZlbnQgPSBsYXN0RXZlbnQ7XG4gICAgICAgIHJldHVybiBjaGFuZ2VkO1xuICAgIH1cbiBfZ2V0QWN0aXZlRWxlbWVudHMoZSwgbGFzdEFjdGl2ZSwgaW5DaGFydEFyZWEsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgaWYgKGUudHlwZSA9PT0gJ21vdXNlb3V0Jykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaW5DaGFydEFyZWEpIHtcbiAgICAgICAgICAgIHJldHVybiBsYXN0QWN0aXZlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhvdmVyT3B0aW9ucyA9IHRoaXMub3B0aW9ucy5ob3ZlcjtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZShlLCBob3Zlck9wdGlvbnMubW9kZSwgaG92ZXJPcHRpb25zLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnZhbGlkYXRlUGx1Z2lucygpIHtcbiAgICByZXR1cm4gZWFjaChDaGFydC5pbnN0YW5jZXMsIChjaGFydCk9PmNoYXJ0Ll9wbHVnaW5zLmludmFsaWRhdGUoKSk7XG59XG5cbmZ1bmN0aW9uIGNsaXBBcmMoY3R4LCBlbGVtZW50LCBlbmRBbmdsZSkge1xuICAgIGNvbnN0IHsgc3RhcnRBbmdsZSAsIHBpeGVsTWFyZ2luICwgeCAsIHkgLCBvdXRlclJhZGl1cyAsIGlubmVyUmFkaXVzICB9ID0gZWxlbWVudDtcbiAgICBsZXQgYW5nbGVNYXJnaW4gPSBwaXhlbE1hcmdpbiAvIG91dGVyUmFkaXVzO1xuICAgIC8vIERyYXcgYW4gaW5uZXIgYm9yZGVyIGJ5IGNsaXBwaW5nIHRoZSBhcmMgYW5kIGRyYXdpbmcgYSBkb3VibGUtd2lkdGggYm9yZGVyXG4gICAgLy8gRW5sYXJnZSB0aGUgY2xpcHBpbmcgYXJjIGJ5IDAuMzMgcGl4ZWxzIHRvIGVsaW1pbmF0ZSBnbGl0Y2hlcyBiZXR3ZWVuIGJvcmRlcnNcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LmFyYyh4LCB5LCBvdXRlclJhZGl1cywgc3RhcnRBbmdsZSAtIGFuZ2xlTWFyZ2luLCBlbmRBbmdsZSArIGFuZ2xlTWFyZ2luKTtcbiAgICBpZiAoaW5uZXJSYWRpdXMgPiBwaXhlbE1hcmdpbikge1xuICAgICAgICBhbmdsZU1hcmdpbiA9IHBpeGVsTWFyZ2luIC8gaW5uZXJSYWRpdXM7XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgaW5uZXJSYWRpdXMsIGVuZEFuZ2xlICsgYW5nbGVNYXJnaW4sIHN0YXJ0QW5nbGUgLSBhbmdsZU1hcmdpbiwgdHJ1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmFyYyh4LCB5LCBwaXhlbE1hcmdpbiwgZW5kQW5nbGUgKyBIQUxGX1BJLCBzdGFydEFuZ2xlIC0gSEFMRl9QSSk7XG4gICAgfVxuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHguY2xpcCgpO1xufVxuZnVuY3Rpb24gdG9SYWRpdXNDb3JuZXJzKHZhbHVlKSB7XG4gICAgcmV0dXJuIF9yZWFkVmFsdWVUb1Byb3BzKHZhbHVlLCBbXG4gICAgICAgICdvdXRlclN0YXJ0JyxcbiAgICAgICAgJ291dGVyRW5kJyxcbiAgICAgICAgJ2lubmVyU3RhcnQnLFxuICAgICAgICAnaW5uZXJFbmQnXG4gICAgXSk7XG59XG4vKipcbiAqIFBhcnNlIGJvcmRlciByYWRpdXMgZnJvbSB0aGUgcHJvdmlkZWQgb3B0aW9uc1xuICovIGZ1bmN0aW9uIHBhcnNlQm9yZGVyUmFkaXVzJDEoYXJjLCBpbm5lclJhZGl1cywgb3V0ZXJSYWRpdXMsIGFuZ2xlRGVsdGEpIHtcbiAgICBjb25zdCBvID0gdG9SYWRpdXNDb3JuZXJzKGFyYy5vcHRpb25zLmJvcmRlclJhZGl1cyk7XG4gICAgY29uc3QgaGFsZlRoaWNrbmVzcyA9IChvdXRlclJhZGl1cyAtIGlubmVyUmFkaXVzKSAvIDI7XG4gICAgY29uc3QgaW5uZXJMaW1pdCA9IE1hdGgubWluKGhhbGZUaGlja25lc3MsIGFuZ2xlRGVsdGEgKiBpbm5lclJhZGl1cyAvIDIpO1xuICAgIC8vIE91dGVyIGxpbWl0cyBhcmUgY29tcGxpY2F0ZWQuIFdlIHdhbnQgdG8gY29tcHV0ZSB0aGUgYXZhaWxhYmxlIGFuZ3VsYXIgZGlzdGFuY2UgYXRcbiAgICAvLyBhIHJhZGl1cyBvZiBvdXRlclJhZGl1cyAtIGJvcmRlclJhZGl1cyBiZWNhdXNlIGZvciBzbWFsbCBhbmd1bGFyIGRpc3RhbmNlcywgdGhpcyB0ZXJtIGxpbWl0cy5cbiAgICAvLyBXZSBjb21wdXRlIGF0IHIgPSBvdXRlclJhZGl1cyAtIGJvcmRlclJhZGl1cyBiZWNhdXNlIHRoaXMgY2lyY2xlIGRlZmluZXMgdGhlIGNlbnRlciBvZiB0aGUgYm9yZGVyIGNvcm5lcnMuXG4gICAgLy9cbiAgICAvLyBJZiB0aGUgYm9yZGVyUmFkaXVzIGlzIGxhcmdlLCB0aGF0IHZhbHVlIGNhbiBiZWNvbWUgbmVnYXRpdmUuXG4gICAgLy8gVGhpcyBjYXVzZXMgdGhlIG91dGVyIGJvcmRlcnMgdG8gbG9zZSB0aGVpciByYWRpdXMgZW50aXJlbHksIHdoaWNoIGlzIHJhdGhlciB1bmV4cGVjdGVkLiBUbyBzb2x2ZSB0aGF0LCBpZiBib3JkZXJSYWRpdXMgPiBvdXRlclJhZGl1c1xuICAgIC8vIHdlIGtub3cgdGhhdCB0aGUgdGhpY2tuZXNzIHRlcm0gd2lsbCBkb21pbmF0ZSBhbmQgY29tcHV0ZSB0aGUgbGltaXRzIGF0IHRoYXQgcG9pbnRcbiAgICBjb25zdCBjb21wdXRlT3V0ZXJMaW1pdCA9ICh2YWwpPT57XG4gICAgICAgIGNvbnN0IG91dGVyQXJjTGltaXQgPSAob3V0ZXJSYWRpdXMgLSBNYXRoLm1pbihoYWxmVGhpY2tuZXNzLCB2YWwpKSAqIGFuZ2xlRGVsdGEgLyAyO1xuICAgICAgICByZXR1cm4gX2xpbWl0VmFsdWUodmFsLCAwLCBNYXRoLm1pbihoYWxmVGhpY2tuZXNzLCBvdXRlckFyY0xpbWl0KSk7XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBvdXRlclN0YXJ0OiBjb21wdXRlT3V0ZXJMaW1pdChvLm91dGVyU3RhcnQpLFxuICAgICAgICBvdXRlckVuZDogY29tcHV0ZU91dGVyTGltaXQoby5vdXRlckVuZCksXG4gICAgICAgIGlubmVyU3RhcnQ6IF9saW1pdFZhbHVlKG8uaW5uZXJTdGFydCwgMCwgaW5uZXJMaW1pdCksXG4gICAgICAgIGlubmVyRW5kOiBfbGltaXRWYWx1ZShvLmlubmVyRW5kLCAwLCBpbm5lckxpbWl0KVxuICAgIH07XG59XG4vKipcbiAqIENvbnZlcnQgKHIsIPCdnIMpIHRvICh4LCB5KVxuICovIGZ1bmN0aW9uIHJUaGV0YVRvWFkociwgdGhldGEsIHgsIHkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiB4ICsgciAqIE1hdGguY29zKHRoZXRhKSxcbiAgICAgICAgeTogeSArIHIgKiBNYXRoLnNpbih0aGV0YSlcbiAgICB9O1xufVxuLyoqXG4gKiBQYXRoIHRoZSBhcmMsIHJlc3BlY3RpbmcgYm9yZGVyIHJhZGl1cyBieSBzZXBhcmF0aW5nIGludG8gbGVmdCBhbmQgcmlnaHQgaGFsdmVzLlxuICpcbiAqICAgU3RhcnQgICAgICBFbmRcbiAqXG4gKiAgICAxLS0tPmEtLS0+MiAgICBPdXRlclxuICogICAvICAgICAgICAgICBcXFxuICogICA4ICAgICAgICAgICAzXG4gKiAgIHwgICAgICAgICAgIHxcbiAqICAgfCAgICAgICAgICAgfFxuICogICA3ICAgICAgICAgICA0XG4gKiAgIFxcICAgICAgICAgICAvXG4gKiAgICA2PC0tLWI8LS0tNSAgICBJbm5lclxuICovIGZ1bmN0aW9uIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZCwgY2lyY3VsYXIpIHtcbiAgICBjb25zdCB7IHggLCB5ICwgc3RhcnRBbmdsZTogc3RhcnQgLCBwaXhlbE1hcmdpbiAsIGlubmVyUmFkaXVzOiBpbm5lclIgIH0gPSBlbGVtZW50O1xuICAgIGNvbnN0IG91dGVyUmFkaXVzID0gTWF0aC5tYXgoZWxlbWVudC5vdXRlclJhZGl1cyArIHNwYWNpbmcgKyBvZmZzZXQgLSBwaXhlbE1hcmdpbiwgMCk7XG4gICAgY29uc3QgaW5uZXJSYWRpdXMgPSBpbm5lclIgPiAwID8gaW5uZXJSICsgc3BhY2luZyArIG9mZnNldCArIHBpeGVsTWFyZ2luIDogMDtcbiAgICBsZXQgc3BhY2luZ09mZnNldCA9IDA7XG4gICAgY29uc3QgYWxwaGEgPSBlbmQgLSBzdGFydDtcbiAgICBpZiAoc3BhY2luZykge1xuICAgICAgICAvLyBXaGVuIHNwYWNpbmcgaXMgcHJlc2VudCwgaXQgaXMgdGhlIHNhbWUgZm9yIGFsbCBpdGVtc1xuICAgICAgICAvLyBTbyB3ZSBhZGp1c3QgdGhlIHN0YXJ0IGFuZCBlbmQgYW5nbGUgb2YgdGhlIGFyYyBzdWNoIHRoYXRcbiAgICAgICAgLy8gdGhlIGRpc3RhbmNlIGlzIHRoZSBzYW1lIGFzIGl0IHdvdWxkIGJlIHdpdGhvdXQgdGhlIHNwYWNpbmdcbiAgICAgICAgY29uc3Qgbm9TcGFjaW5nSW5uZXJSYWRpdXMgPSBpbm5lclIgPiAwID8gaW5uZXJSIC0gc3BhY2luZyA6IDA7XG4gICAgICAgIGNvbnN0IG5vU3BhY2luZ091dGVyUmFkaXVzID0gb3V0ZXJSYWRpdXMgPiAwID8gb3V0ZXJSYWRpdXMgLSBzcGFjaW5nIDogMDtcbiAgICAgICAgY29uc3QgYXZOb2dTcGFjaW5nUmFkaXVzID0gKG5vU3BhY2luZ0lubmVyUmFkaXVzICsgbm9TcGFjaW5nT3V0ZXJSYWRpdXMpIC8gMjtcbiAgICAgICAgY29uc3QgYWRqdXN0ZWRBbmdsZSA9IGF2Tm9nU3BhY2luZ1JhZGl1cyAhPT0gMCA/IGFscGhhICogYXZOb2dTcGFjaW5nUmFkaXVzIC8gKGF2Tm9nU3BhY2luZ1JhZGl1cyArIHNwYWNpbmcpIDogYWxwaGE7XG4gICAgICAgIHNwYWNpbmdPZmZzZXQgPSAoYWxwaGEgLSBhZGp1c3RlZEFuZ2xlKSAvIDI7XG4gICAgfVxuICAgIGNvbnN0IGJldGEgPSBNYXRoLm1heCgwLjAwMSwgYWxwaGEgKiBvdXRlclJhZGl1cyAtIG9mZnNldCAvIFBJKSAvIG91dGVyUmFkaXVzO1xuICAgIGNvbnN0IGFuZ2xlT2Zmc2V0ID0gKGFscGhhIC0gYmV0YSkgLyAyO1xuICAgIGNvbnN0IHN0YXJ0QW5nbGUgPSBzdGFydCArIGFuZ2xlT2Zmc2V0ICsgc3BhY2luZ09mZnNldDtcbiAgICBjb25zdCBlbmRBbmdsZSA9IGVuZCAtIGFuZ2xlT2Zmc2V0IC0gc3BhY2luZ09mZnNldDtcbiAgICBjb25zdCB7IG91dGVyU3RhcnQgLCBvdXRlckVuZCAsIGlubmVyU3RhcnQgLCBpbm5lckVuZCAgfSA9IHBhcnNlQm9yZGVyUmFkaXVzJDEoZWxlbWVudCwgaW5uZXJSYWRpdXMsIG91dGVyUmFkaXVzLCBlbmRBbmdsZSAtIHN0YXJ0QW5nbGUpO1xuICAgIGNvbnN0IG91dGVyU3RhcnRBZGp1c3RlZFJhZGl1cyA9IG91dGVyUmFkaXVzIC0gb3V0ZXJTdGFydDtcbiAgICBjb25zdCBvdXRlckVuZEFkanVzdGVkUmFkaXVzID0gb3V0ZXJSYWRpdXMgLSBvdXRlckVuZDtcbiAgICBjb25zdCBvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSA9IHN0YXJ0QW5nbGUgKyBvdXRlclN0YXJ0IC8gb3V0ZXJTdGFydEFkanVzdGVkUmFkaXVzO1xuICAgIGNvbnN0IG91dGVyRW5kQWRqdXN0ZWRBbmdsZSA9IGVuZEFuZ2xlIC0gb3V0ZXJFbmQgLyBvdXRlckVuZEFkanVzdGVkUmFkaXVzO1xuICAgIGNvbnN0IGlubmVyU3RhcnRBZGp1c3RlZFJhZGl1cyA9IGlubmVyUmFkaXVzICsgaW5uZXJTdGFydDtcbiAgICBjb25zdCBpbm5lckVuZEFkanVzdGVkUmFkaXVzID0gaW5uZXJSYWRpdXMgKyBpbm5lckVuZDtcbiAgICBjb25zdCBpbm5lclN0YXJ0QWRqdXN0ZWRBbmdsZSA9IHN0YXJ0QW5nbGUgKyBpbm5lclN0YXJ0IC8gaW5uZXJTdGFydEFkanVzdGVkUmFkaXVzO1xuICAgIGNvbnN0IGlubmVyRW5kQWRqdXN0ZWRBbmdsZSA9IGVuZEFuZ2xlIC0gaW5uZXJFbmQgLyBpbm5lckVuZEFkanVzdGVkUmFkaXVzO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBpZiAoY2lyY3VsYXIpIHtcbiAgICAgICAgLy8gVGhlIGZpcnN0IGFyYyBzZWdtZW50cyBmcm9tIHBvaW50IDEgdG8gcG9pbnQgYSB0byBwb2ludCAyXG4gICAgICAgIGNvbnN0IG91dGVyTWlkQWRqdXN0ZWRBbmdsZSA9IChvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSArIG91dGVyRW5kQWRqdXN0ZWRBbmdsZSkgLyAyO1xuICAgICAgICBjdHguYXJjKHgsIHksIG91dGVyUmFkaXVzLCBvdXRlclN0YXJ0QWRqdXN0ZWRBbmdsZSwgb3V0ZXJNaWRBZGp1c3RlZEFuZ2xlKTtcbiAgICAgICAgY3R4LmFyYyh4LCB5LCBvdXRlclJhZGl1cywgb3V0ZXJNaWRBZGp1c3RlZEFuZ2xlLCBvdXRlckVuZEFkanVzdGVkQW5nbGUpO1xuICAgICAgICAvLyBUaGUgY29ybmVyIHNlZ21lbnQgZnJvbSBwb2ludCAyIHRvIHBvaW50IDNcbiAgICAgICAgaWYgKG91dGVyRW5kID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcENlbnRlciA9IHJUaGV0YVRvWFkob3V0ZXJFbmRBZGp1c3RlZFJhZGl1cywgb3V0ZXJFbmRBZGp1c3RlZEFuZ2xlLCB4LCB5KTtcbiAgICAgICAgICAgIGN0eC5hcmMocENlbnRlci54LCBwQ2VudGVyLnksIG91dGVyRW5kLCBvdXRlckVuZEFkanVzdGVkQW5nbGUsIGVuZEFuZ2xlICsgSEFMRl9QSSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIGxpbmUgZnJvbSBwb2ludCAzIHRvIHBvaW50IDRcbiAgICAgICAgY29uc3QgcDQgPSByVGhldGFUb1hZKGlubmVyRW5kQWRqdXN0ZWRSYWRpdXMsIGVuZEFuZ2xlLCB4LCB5KTtcbiAgICAgICAgY3R4LmxpbmVUbyhwNC54LCBwNC55KTtcbiAgICAgICAgLy8gVGhlIGNvcm5lciBzZWdtZW50IGZyb20gcG9pbnQgNCB0byBwb2ludCA1XG4gICAgICAgIGlmIChpbm5lckVuZCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHBDZW50ZXIgPSByVGhldGFUb1hZKGlubmVyRW5kQWRqdXN0ZWRSYWRpdXMsIGlubmVyRW5kQWRqdXN0ZWRBbmdsZSwgeCwgeSk7XG4gICAgICAgICAgICBjdHguYXJjKHBDZW50ZXIueCwgcENlbnRlci55LCBpbm5lckVuZCwgZW5kQW5nbGUgKyBIQUxGX1BJLCBpbm5lckVuZEFkanVzdGVkQW5nbGUgKyBNYXRoLlBJKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgaW5uZXIgYXJjIGZyb20gcG9pbnQgNSB0byBwb2ludCBiIHRvIHBvaW50IDZcbiAgICAgICAgY29uc3QgaW5uZXJNaWRBZGp1c3RlZEFuZ2xlID0gKGVuZEFuZ2xlIC0gaW5uZXJFbmQgLyBpbm5lclJhZGl1cyArIChzdGFydEFuZ2xlICsgaW5uZXJTdGFydCAvIGlubmVyUmFkaXVzKSkgLyAyO1xuICAgICAgICBjdHguYXJjKHgsIHksIGlubmVyUmFkaXVzLCBlbmRBbmdsZSAtIGlubmVyRW5kIC8gaW5uZXJSYWRpdXMsIGlubmVyTWlkQWRqdXN0ZWRBbmdsZSwgdHJ1ZSk7XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgaW5uZXJSYWRpdXMsIGlubmVyTWlkQWRqdXN0ZWRBbmdsZSwgc3RhcnRBbmdsZSArIGlubmVyU3RhcnQgLyBpbm5lclJhZGl1cywgdHJ1ZSk7XG4gICAgICAgIC8vIFRoZSBjb3JuZXIgc2VnbWVudCBmcm9tIHBvaW50IDYgdG8gcG9pbnQgN1xuICAgICAgICBpZiAoaW5uZXJTdGFydCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHBDZW50ZXIgPSByVGhldGFUb1hZKGlubmVyU3RhcnRBZGp1c3RlZFJhZGl1cywgaW5uZXJTdGFydEFkanVzdGVkQW5nbGUsIHgsIHkpO1xuICAgICAgICAgICAgY3R4LmFyYyhwQ2VudGVyLngsIHBDZW50ZXIueSwgaW5uZXJTdGFydCwgaW5uZXJTdGFydEFkanVzdGVkQW5nbGUgKyBNYXRoLlBJLCBzdGFydEFuZ2xlIC0gSEFMRl9QSSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIGxpbmUgZnJvbSBwb2ludCA3IHRvIHBvaW50IDhcbiAgICAgICAgY29uc3QgcDggPSByVGhldGFUb1hZKG91dGVyU3RhcnRBZGp1c3RlZFJhZGl1cywgc3RhcnRBbmdsZSwgeCwgeSk7XG4gICAgICAgIGN0eC5saW5lVG8ocDgueCwgcDgueSk7XG4gICAgICAgIC8vIFRoZSBjb3JuZXIgc2VnbWVudCBmcm9tIHBvaW50IDggdG8gcG9pbnQgMVxuICAgICAgICBpZiAob3V0ZXJTdGFydCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHBDZW50ZXIgPSByVGhldGFUb1hZKG91dGVyU3RhcnRBZGp1c3RlZFJhZGl1cywgb3V0ZXJTdGFydEFkanVzdGVkQW5nbGUsIHgsIHkpO1xuICAgICAgICAgICAgY3R4LmFyYyhwQ2VudGVyLngsIHBDZW50ZXIueSwgb3V0ZXJTdGFydCwgc3RhcnRBbmdsZSAtIEhBTEZfUEksIG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGN0eC5tb3ZlVG8oeCwgeSk7XG4gICAgICAgIGNvbnN0IG91dGVyU3RhcnRYID0gTWF0aC5jb3Mob3V0ZXJTdGFydEFkanVzdGVkQW5nbGUpICogb3V0ZXJSYWRpdXMgKyB4O1xuICAgICAgICBjb25zdCBvdXRlclN0YXJ0WSA9IE1hdGguc2luKG91dGVyU3RhcnRBZGp1c3RlZEFuZ2xlKSAqIG91dGVyUmFkaXVzICsgeTtcbiAgICAgICAgY3R4LmxpbmVUbyhvdXRlclN0YXJ0WCwgb3V0ZXJTdGFydFkpO1xuICAgICAgICBjb25zdCBvdXRlckVuZFggPSBNYXRoLmNvcyhvdXRlckVuZEFkanVzdGVkQW5nbGUpICogb3V0ZXJSYWRpdXMgKyB4O1xuICAgICAgICBjb25zdCBvdXRlckVuZFkgPSBNYXRoLnNpbihvdXRlckVuZEFkanVzdGVkQW5nbGUpICogb3V0ZXJSYWRpdXMgKyB5O1xuICAgICAgICBjdHgubGluZVRvKG91dGVyRW5kWCwgb3V0ZXJFbmRZKTtcbiAgICB9XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xufVxuZnVuY3Rpb24gZHJhd0FyYyhjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgY2lyY3VsYXIpIHtcbiAgICBjb25zdCB7IGZ1bGxDaXJjbGVzICwgc3RhcnRBbmdsZSAsIGNpcmN1bWZlcmVuY2UgIH0gPSBlbGVtZW50O1xuICAgIGxldCBlbmRBbmdsZSA9IGVsZW1lbnQuZW5kQW5nbGU7XG4gICAgaWYgKGZ1bGxDaXJjbGVzKSB7XG4gICAgICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlLCBjaXJjdWxhcik7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBmdWxsQ2lyY2xlczsgKytpKXtcbiAgICAgICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc05hTihjaXJjdW1mZXJlbmNlKSkge1xuICAgICAgICAgICAgZW5kQW5nbGUgPSBzdGFydEFuZ2xlICsgKGNpcmN1bWZlcmVuY2UgJSBUQVUgfHwgVEFVKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwYXRoQXJjKGN0eCwgZWxlbWVudCwgb2Zmc2V0LCBzcGFjaW5nLCBlbmRBbmdsZSwgY2lyY3VsYXIpO1xuICAgIGN0eC5maWxsKCk7XG4gICAgcmV0dXJuIGVuZEFuZ2xlO1xufVxuZnVuY3Rpb24gZHJhd0JvcmRlcihjdHgsIGVsZW1lbnQsIG9mZnNldCwgc3BhY2luZywgY2lyY3VsYXIpIHtcbiAgICBjb25zdCB7IGZ1bGxDaXJjbGVzICwgc3RhcnRBbmdsZSAsIGNpcmN1bWZlcmVuY2UgLCBvcHRpb25zICB9ID0gZWxlbWVudDtcbiAgICBjb25zdCB7IGJvcmRlcldpZHRoICwgYm9yZGVySm9pblN0eWxlICwgYm9yZGVyRGFzaCAsIGJvcmRlckRhc2hPZmZzZXQgIH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IGlubmVyID0gb3B0aW9ucy5ib3JkZXJBbGlnbiA9PT0gJ2lubmVyJztcbiAgICBpZiAoIWJvcmRlcldpZHRoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY3R4LnNldExpbmVEYXNoKGJvcmRlckRhc2ggfHwgW10pO1xuICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IGJvcmRlckRhc2hPZmZzZXQ7XG4gICAgaWYgKGlubmVyKSB7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSBib3JkZXJXaWR0aCAqIDI7XG4gICAgICAgIGN0eC5saW5lSm9pbiA9IGJvcmRlckpvaW5TdHlsZSB8fCAncm91bmQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSBib3JkZXJXaWR0aDtcbiAgICAgICAgY3R4LmxpbmVKb2luID0gYm9yZGVySm9pblN0eWxlIHx8ICdiZXZlbCc7XG4gICAgfVxuICAgIGxldCBlbmRBbmdsZSA9IGVsZW1lbnQuZW5kQW5nbGU7XG4gICAgaWYgKGZ1bGxDaXJjbGVzKSB7XG4gICAgICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlLCBjaXJjdWxhcik7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBmdWxsQ2lyY2xlczsgKytpKXtcbiAgICAgICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzTmFOKGNpcmN1bWZlcmVuY2UpKSB7XG4gICAgICAgICAgICBlbmRBbmdsZSA9IHN0YXJ0QW5nbGUgKyAoY2lyY3VtZmVyZW5jZSAlIFRBVSB8fCBUQVUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChpbm5lcikge1xuICAgICAgICBjbGlwQXJjKGN0eCwgZWxlbWVudCwgZW5kQW5nbGUpO1xuICAgIH1cbiAgICBpZiAoIWZ1bGxDaXJjbGVzKSB7XG4gICAgICAgIHBhdGhBcmMoY3R4LCBlbGVtZW50LCBvZmZzZXQsIHNwYWNpbmcsIGVuZEFuZ2xlLCBjaXJjdWxhcik7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG59XG5jbGFzcyBBcmNFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7XG4gICAgc3RhdGljIGlkID0gJ2FyYyc7XG4gICAgc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBib3JkZXJBbGlnbjogJ2NlbnRlcicsXG4gICAgICAgIGJvcmRlckNvbG9yOiAnI2ZmZicsXG4gICAgICAgIGJvcmRlckRhc2g6IFtdLFxuICAgICAgICBib3JkZXJEYXNoT2Zmc2V0OiAwLFxuICAgICAgICBib3JkZXJKb2luU3R5bGU6IHVuZGVmaW5lZCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAwLFxuICAgICAgICBib3JkZXJXaWR0aDogMixcbiAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICBzcGFjaW5nOiAwLFxuICAgICAgICBhbmdsZTogdW5kZWZpbmVkLFxuICAgICAgICBjaXJjdWxhcjogdHJ1ZVxuICAgIH07XG4gICAgc3RhdGljIGRlZmF1bHRSb3V0ZXMgPSB7XG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogJ2JhY2tncm91bmRDb2xvcidcbiAgICB9O1xuICAgIHN0YXRpYyBkZXNjcmlwdG9ycyA9IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IHRydWUsXG4gICAgICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ2JvcmRlckRhc2gnXG4gICAgfTtcbiAgICBjaXJjdW1mZXJlbmNlO1xuICAgIGVuZEFuZ2xlO1xuICAgIGZ1bGxDaXJjbGVzO1xuICAgIGlubmVyUmFkaXVzO1xuICAgIG91dGVyUmFkaXVzO1xuICAgIHBpeGVsTWFyZ2luO1xuICAgIHN0YXJ0QW5nbGU7XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNpcmN1bWZlcmVuY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuc3RhcnRBbmdsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5lbmRBbmdsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5pbm5lclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5vdXRlclJhZGl1cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5waXhlbE1hcmdpbiA9IDA7XG4gICAgICAgIHRoaXMuZnVsbENpcmNsZXMgPSAwO1xuICAgICAgICBpZiAoY2ZnKSB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaW5SYW5nZShjaGFydFgsIGNoYXJ0WSwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICBjb25zdCBwb2ludCA9IHRoaXMuZ2V0UHJvcHMoW1xuICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgJ3knXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCB7IGFuZ2xlICwgZGlzdGFuY2UgIH0gPSBnZXRBbmdsZUZyb21Qb2ludChwb2ludCwge1xuICAgICAgICAgICAgeDogY2hhcnRYLFxuICAgICAgICAgICAgeTogY2hhcnRZXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB7IHN0YXJ0QW5nbGUgLCBlbmRBbmdsZSAsIGlubmVyUmFkaXVzICwgb3V0ZXJSYWRpdXMgLCBjaXJjdW1mZXJlbmNlICB9ID0gdGhpcy5nZXRQcm9wcyhbXG4gICAgICAgICAgICAnc3RhcnRBbmdsZScsXG4gICAgICAgICAgICAnZW5kQW5nbGUnLFxuICAgICAgICAgICAgJ2lubmVyUmFkaXVzJyxcbiAgICAgICAgICAgICdvdXRlclJhZGl1cycsXG4gICAgICAgICAgICAnY2lyY3VtZmVyZW5jZSdcbiAgICAgICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIGNvbnN0IHJBZGp1c3QgPSAodGhpcy5vcHRpb25zLnNwYWNpbmcgKyB0aGlzLm9wdGlvbnMuYm9yZGVyV2lkdGgpIC8gMjtcbiAgICAgICAgY29uc3QgX2NpcmN1bWZlcmVuY2UgPSB2YWx1ZU9yRGVmYXVsdChjaXJjdW1mZXJlbmNlLCBlbmRBbmdsZSAtIHN0YXJ0QW5nbGUpO1xuICAgICAgICBjb25zdCBiZXR3ZWVuQW5nbGVzID0gX2NpcmN1bWZlcmVuY2UgPj0gVEFVIHx8IF9hbmdsZUJldHdlZW4oYW5nbGUsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlKTtcbiAgICAgICAgY29uc3Qgd2l0aGluUmFkaXVzID0gX2lzQmV0d2VlbihkaXN0YW5jZSwgaW5uZXJSYWRpdXMgKyByQWRqdXN0LCBvdXRlclJhZGl1cyArIHJBZGp1c3QpO1xuICAgICAgICByZXR1cm4gYmV0d2VlbkFuZ2xlcyAmJiB3aXRoaW5SYWRpdXM7XG4gICAgfVxuICAgIGdldENlbnRlclBvaW50KHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgeyB4ICwgeSAsIHN0YXJ0QW5nbGUgLCBlbmRBbmdsZSAsIGlubmVyUmFkaXVzICwgb3V0ZXJSYWRpdXMgIH0gPSB0aGlzLmdldFByb3BzKFtcbiAgICAgICAgICAgICd4JyxcbiAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICdzdGFydEFuZ2xlJyxcbiAgICAgICAgICAgICdlbmRBbmdsZScsXG4gICAgICAgICAgICAnaW5uZXJSYWRpdXMnLFxuICAgICAgICAgICAgJ291dGVyUmFkaXVzJ1xuICAgICAgICBdLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgeyBvZmZzZXQgLCBzcGFjaW5nICB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBoYWxmQW5nbGUgPSAoc3RhcnRBbmdsZSArIGVuZEFuZ2xlKSAvIDI7XG4gICAgICAgIGNvbnN0IGhhbGZSYWRpdXMgPSAoaW5uZXJSYWRpdXMgKyBvdXRlclJhZGl1cyArIHNwYWNpbmcgKyBvZmZzZXQpIC8gMjtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IHggKyBNYXRoLmNvcyhoYWxmQW5nbGUpICogaGFsZlJhZGl1cyxcbiAgICAgICAgICAgIHk6IHkgKyBNYXRoLnNpbihoYWxmQW5nbGUpICogaGFsZlJhZGl1c1xuICAgICAgICB9O1xuICAgIH1cbiAgICB0b29sdGlwUG9zaXRpb24odXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDZW50ZXJQb2ludCh1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG4gICAgZHJhdyhjdHgpIHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zICwgY2lyY3VtZmVyZW5jZSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IChvcHRpb25zLm9mZnNldCB8fCAwKSAvIDQ7XG4gICAgICAgIGNvbnN0IHNwYWNpbmcgPSAob3B0aW9ucy5zcGFjaW5nIHx8IDApIC8gMjtcbiAgICAgICAgY29uc3QgY2lyY3VsYXIgPSBvcHRpb25zLmNpcmN1bGFyO1xuICAgICAgICB0aGlzLnBpeGVsTWFyZ2luID0gb3B0aW9ucy5ib3JkZXJBbGlnbiA9PT0gJ2lubmVyJyA/IDAuMzMgOiAwO1xuICAgICAgICB0aGlzLmZ1bGxDaXJjbGVzID0gY2lyY3VtZmVyZW5jZSA+IFRBVSA/IE1hdGguZmxvb3IoY2lyY3VtZmVyZW5jZSAvIFRBVSkgOiAwO1xuICAgICAgICBpZiAoY2lyY3VtZmVyZW5jZSA9PT0gMCB8fCB0aGlzLmlubmVyUmFkaXVzIDwgMCB8fCB0aGlzLm91dGVyUmFkaXVzIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgIGNvbnN0IGhhbGZBbmdsZSA9ICh0aGlzLnN0YXJ0QW5nbGUgKyB0aGlzLmVuZEFuZ2xlKSAvIDI7XG4gICAgICAgIGN0eC50cmFuc2xhdGUoTWF0aC5jb3MoaGFsZkFuZ2xlKSAqIG9mZnNldCwgTWF0aC5zaW4oaGFsZkFuZ2xlKSAqIG9mZnNldCk7XG4gICAgICAgIGNvbnN0IGZpeCA9IDEgLSBNYXRoLnNpbihNYXRoLm1pbihQSSwgY2lyY3VtZmVyZW5jZSB8fCAwKSk7XG4gICAgICAgIGNvbnN0IHJhZGl1c09mZnNldCA9IG9mZnNldCAqIGZpeDtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBvcHRpb25zLmJvcmRlckNvbG9yO1xuICAgICAgICBkcmF3QXJjKGN0eCwgdGhpcywgcmFkaXVzT2Zmc2V0LCBzcGFjaW5nLCBjaXJjdWxhcik7XG4gICAgICAgIGRyYXdCb3JkZXIoY3R4LCB0aGlzLCByYWRpdXNPZmZzZXQsIHNwYWNpbmcsIGNpcmN1bGFyKTtcbiAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFN0eWxlKGN0eCwgb3B0aW9ucywgc3R5bGUgPSBvcHRpb25zKSB7XG4gICAgY3R4LmxpbmVDYXAgPSB2YWx1ZU9yRGVmYXVsdChzdHlsZS5ib3JkZXJDYXBTdHlsZSwgb3B0aW9ucy5ib3JkZXJDYXBTdHlsZSk7XG4gICAgY3R4LnNldExpbmVEYXNoKHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckRhc2gsIG9wdGlvbnMuYm9yZGVyRGFzaCkpO1xuICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlckRhc2hPZmZzZXQsIG9wdGlvbnMuYm9yZGVyRGFzaE9mZnNldCk7XG4gICAgY3R4LmxpbmVKb2luID0gdmFsdWVPckRlZmF1bHQoc3R5bGUuYm9yZGVySm9pblN0eWxlLCBvcHRpb25zLmJvcmRlckpvaW5TdHlsZSk7XG4gICAgY3R4LmxpbmVXaWR0aCA9IHZhbHVlT3JEZWZhdWx0KHN0eWxlLmJvcmRlcldpZHRoLCBvcHRpb25zLmJvcmRlcldpZHRoKTtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChzdHlsZS5ib3JkZXJDb2xvciwgb3B0aW9ucy5ib3JkZXJDb2xvcik7XG59XG5mdW5jdGlvbiBsaW5lVG8oY3R4LCBwcmV2aW91cywgdGFyZ2V0KSB7XG4gICAgY3R4LmxpbmVUbyh0YXJnZXQueCwgdGFyZ2V0LnkpO1xufVxuIGZ1bmN0aW9uIGdldExpbmVNZXRob2Qob3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLnN0ZXBwZWQpIHtcbiAgICAgICAgcmV0dXJuIF9zdGVwcGVkTGluZVRvO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy50ZW5zaW9uIHx8IG9wdGlvbnMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSA9PT0gJ21vbm90b25lJykge1xuICAgICAgICByZXR1cm4gX2JlemllckN1cnZlVG87XG4gICAgfVxuICAgIHJldHVybiBsaW5lVG87XG59XG5mdW5jdGlvbiBwYXRoVmFycyhwb2ludHMsIHNlZ21lbnQsIHBhcmFtcyA9IHt9KSB7XG4gICAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIGNvbnN0IHsgc3RhcnQ6IHBhcmFtc1N0YXJ0ID0gMCAsIGVuZDogcGFyYW1zRW5kID0gY291bnQgLSAxICB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHsgc3RhcnQ6IHNlZ21lbnRTdGFydCAsIGVuZDogc2VnbWVudEVuZCAgfSA9IHNlZ21lbnQ7XG4gICAgY29uc3Qgc3RhcnQgPSBNYXRoLm1heChwYXJhbXNTdGFydCwgc2VnbWVudFN0YXJ0KTtcbiAgICBjb25zdCBlbmQgPSBNYXRoLm1pbihwYXJhbXNFbmQsIHNlZ21lbnRFbmQpO1xuICAgIGNvbnN0IG91dHNpZGUgPSBwYXJhbXNTdGFydCA8IHNlZ21lbnRTdGFydCAmJiBwYXJhbXNFbmQgPCBzZWdtZW50U3RhcnQgfHwgcGFyYW1zU3RhcnQgPiBzZWdtZW50RW5kICYmIHBhcmFtc0VuZCA+IHNlZ21lbnRFbmQ7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY291bnQsXG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBsb29wOiBzZWdtZW50Lmxvb3AsXG4gICAgICAgIGlsZW46IGVuZCA8IHN0YXJ0ICYmICFvdXRzaWRlID8gY291bnQgKyBlbmQgLSBzdGFydCA6IGVuZCAtIHN0YXJ0XG4gICAgfTtcbn1cbiBmdW5jdGlvbiBwYXRoU2VnbWVudChjdHgsIGxpbmUsIHNlZ21lbnQsIHBhcmFtcykge1xuICAgIGNvbnN0IHsgcG9pbnRzICwgb3B0aW9ucyAgfSA9IGxpbmU7XG4gICAgY29uc3QgeyBjb3VudCAsIHN0YXJ0ICwgbG9vcCAsIGlsZW4gIH0gPSBwYXRoVmFycyhwb2ludHMsIHNlZ21lbnQsIHBhcmFtcyk7XG4gICAgY29uc3QgbGluZU1ldGhvZCA9IGdldExpbmVNZXRob2Qob3B0aW9ucyk7XG4gICAgbGV0IHsgbW92ZSA9dHJ1ZSAsIHJldmVyc2UgIH0gPSBwYXJhbXMgfHwge307XG4gICAgbGV0IGksIHBvaW50LCBwcmV2O1xuICAgIGZvcihpID0gMDsgaSA8PSBpbGVuOyArK2kpe1xuICAgICAgICBwb2ludCA9IHBvaW50c1soc3RhcnQgKyAocmV2ZXJzZSA/IGlsZW4gLSBpIDogaSkpICUgY291bnRdO1xuICAgICAgICBpZiAocG9pbnQuc2tpcCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSBpZiAobW92ZSkge1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyhwb2ludC54LCBwb2ludC55KTtcbiAgICAgICAgICAgIG1vdmUgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxpbmVNZXRob2QoY3R4LCBwcmV2LCBwb2ludCwgcmV2ZXJzZSwgb3B0aW9ucy5zdGVwcGVkKTtcbiAgICAgICAgfVxuICAgICAgICBwcmV2ID0gcG9pbnQ7XG4gICAgfVxuICAgIGlmIChsb29wKSB7XG4gICAgICAgIHBvaW50ID0gcG9pbnRzWyhzdGFydCArIChyZXZlcnNlID8gaWxlbiA6IDApKSAlIGNvdW50XTtcbiAgICAgICAgbGluZU1ldGhvZChjdHgsIHByZXYsIHBvaW50LCByZXZlcnNlLCBvcHRpb25zLnN0ZXBwZWQpO1xuICAgIH1cbiAgICByZXR1cm4gISFsb29wO1xufVxuIGZ1bmN0aW9uIGZhc3RQYXRoU2VnbWVudChjdHgsIGxpbmUsIHNlZ21lbnQsIHBhcmFtcykge1xuICAgIGNvbnN0IHBvaW50cyA9IGxpbmUucG9pbnRzO1xuICAgIGNvbnN0IHsgY291bnQgLCBzdGFydCAsIGlsZW4gIH0gPSBwYXRoVmFycyhwb2ludHMsIHNlZ21lbnQsIHBhcmFtcyk7XG4gICAgY29uc3QgeyBtb3ZlID10cnVlICwgcmV2ZXJzZSAgfSA9IHBhcmFtcyB8fCB7fTtcbiAgICBsZXQgYXZnWCA9IDA7XG4gICAgbGV0IGNvdW50WCA9IDA7XG4gICAgbGV0IGksIHBvaW50LCBwcmV2WCwgbWluWSwgbWF4WSwgbGFzdFk7XG4gICAgY29uc3QgcG9pbnRJbmRleCA9IChpbmRleCk9PihzdGFydCArIChyZXZlcnNlID8gaWxlbiAtIGluZGV4IDogaW5kZXgpKSAlIGNvdW50O1xuICAgIGNvbnN0IGRyYXdYID0gKCk9PntcbiAgICAgICAgaWYgKG1pblkgIT09IG1heFkpIHtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oYXZnWCwgbWF4WSk7XG4gICAgICAgICAgICBjdHgubGluZVRvKGF2Z1gsIG1pblkpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhhdmdYLCBsYXN0WSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGlmIChtb3ZlKSB7XG4gICAgICAgIHBvaW50ID0gcG9pbnRzW3BvaW50SW5kZXgoMCldO1xuICAgICAgICBjdHgubW92ZVRvKHBvaW50LngsIHBvaW50LnkpO1xuICAgIH1cbiAgICBmb3IoaSA9IDA7IGkgPD0gaWxlbjsgKytpKXtcbiAgICAgICAgcG9pbnQgPSBwb2ludHNbcG9pbnRJbmRleChpKV07XG4gICAgICAgIGlmIChwb2ludC5za2lwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB4ID0gcG9pbnQueDtcbiAgICAgICAgY29uc3QgeSA9IHBvaW50Lnk7XG4gICAgICAgIGNvbnN0IHRydW5jWCA9IHggfCAwO1xuICAgICAgICBpZiAodHJ1bmNYID09PSBwcmV2WCkge1xuICAgICAgICAgICAgaWYgKHkgPCBtaW5ZKSB7XG4gICAgICAgICAgICAgICAgbWluWSA9IHk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHkgPiBtYXhZKSB7XG4gICAgICAgICAgICAgICAgbWF4WSA9IHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhdmdYID0gKGNvdW50WCAqIGF2Z1ggKyB4KSAvICsrY291bnRYO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZHJhd1goKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCwgeSk7XG4gICAgICAgICAgICBwcmV2WCA9IHRydW5jWDtcbiAgICAgICAgICAgIGNvdW50WCA9IDA7XG4gICAgICAgICAgICBtaW5ZID0gbWF4WSA9IHk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdFkgPSB5O1xuICAgIH1cbiAgICBkcmF3WCgpO1xufVxuIGZ1bmN0aW9uIF9nZXRTZWdtZW50TWV0aG9kKGxpbmUpIHtcbiAgICBjb25zdCBvcHRzID0gbGluZS5vcHRpb25zO1xuICAgIGNvbnN0IGJvcmRlckRhc2ggPSBvcHRzLmJvcmRlckRhc2ggJiYgb3B0cy5ib3JkZXJEYXNoLmxlbmd0aDtcbiAgICBjb25zdCB1c2VGYXN0UGF0aCA9ICFsaW5lLl9kZWNpbWF0ZWQgJiYgIWxpbmUuX2xvb3AgJiYgIW9wdHMudGVuc2lvbiAmJiBvcHRzLmN1YmljSW50ZXJwb2xhdGlvbk1vZGUgIT09ICdtb25vdG9uZScgJiYgIW9wdHMuc3RlcHBlZCAmJiAhYm9yZGVyRGFzaDtcbiAgICByZXR1cm4gdXNlRmFzdFBhdGggPyBmYXN0UGF0aFNlZ21lbnQgOiBwYXRoU2VnbWVudDtcbn1cbiBmdW5jdGlvbiBfZ2V0SW50ZXJwb2xhdGlvbk1ldGhvZChvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMuc3RlcHBlZCkge1xuICAgICAgICByZXR1cm4gX3N0ZXBwZWRJbnRlcnBvbGF0aW9uO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy50ZW5zaW9uIHx8IG9wdGlvbnMuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSA9PT0gJ21vbm90b25lJykge1xuICAgICAgICByZXR1cm4gX2JlemllckludGVycG9sYXRpb247XG4gICAgfVxuICAgIHJldHVybiBfcG9pbnRJbkxpbmU7XG59XG5mdW5jdGlvbiBzdHJva2VQYXRoV2l0aENhY2hlKGN0eCwgbGluZSwgc3RhcnQsIGNvdW50KSB7XG4gICAgbGV0IHBhdGggPSBsaW5lLl9wYXRoO1xuICAgIGlmICghcGF0aCkge1xuICAgICAgICBwYXRoID0gbGluZS5fcGF0aCA9IG5ldyBQYXRoMkQoKTtcbiAgICAgICAgaWYgKGxpbmUucGF0aChwYXRoLCBzdGFydCwgY291bnQpKSB7XG4gICAgICAgICAgICBwYXRoLmNsb3NlUGF0aCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHNldFN0eWxlKGN0eCwgbGluZS5vcHRpb25zKTtcbiAgICBjdHguc3Ryb2tlKHBhdGgpO1xufVxuZnVuY3Rpb24gc3Ryb2tlUGF0aERpcmVjdChjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IHsgc2VnbWVudHMgLCBvcHRpb25zICB9ID0gbGluZTtcbiAgICBjb25zdCBzZWdtZW50TWV0aG9kID0gX2dldFNlZ21lbnRNZXRob2QobGluZSk7XG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKXtcbiAgICAgICAgc2V0U3R5bGUoY3R4LCBvcHRpb25zLCBzZWdtZW50LnN0eWxlKTtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBpZiAoc2VnbWVudE1ldGhvZChjdHgsIGxpbmUsIHNlZ21lbnQsIHtcbiAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBzdGFydCArIGNvdW50IC0gMVxuICAgICAgICB9KSkge1xuICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG59XG5jb25zdCB1c2VQYXRoMkQgPSB0eXBlb2YgUGF0aDJEID09PSAnZnVuY3Rpb24nO1xuZnVuY3Rpb24gZHJhdyhjdHgsIGxpbmUsIHN0YXJ0LCBjb3VudCkge1xuICAgIGlmICh1c2VQYXRoMkQgJiYgIWxpbmUub3B0aW9ucy5zZWdtZW50KSB7XG4gICAgICAgIHN0cm9rZVBhdGhXaXRoQ2FjaGUoY3R4LCBsaW5lLCBzdGFydCwgY291bnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cm9rZVBhdGhEaXJlY3QoY3R4LCBsaW5lLCBzdGFydCwgY291bnQpO1xuICAgIH1cbn1cbmNsYXNzIExpbmVFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7XG4gICAgc3RhdGljIGlkID0gJ2xpbmUnO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgYm9yZGVyQ2FwU3R5bGU6ICdidXR0JyxcbiAgICAgICAgYm9yZGVyRGFzaDogW10sXG4gICAgICAgIGJvcmRlckRhc2hPZmZzZXQ6IDAsXG4gICAgICAgIGJvcmRlckpvaW5TdHlsZTogJ21pdGVyJyxcbiAgICAgICAgYm9yZGVyV2lkdGg6IDMsXG4gICAgICAgIGNhcEJlemllclBvaW50czogdHJ1ZSxcbiAgICAgICAgY3ViaWNJbnRlcnBvbGF0aW9uTW9kZTogJ2RlZmF1bHQnLFxuICAgICAgICBmaWxsOiBmYWxzZSxcbiAgICAgICAgc3BhbkdhcHM6IGZhbHNlLFxuICAgICAgICBzdGVwcGVkOiBmYWxzZSxcbiAgICAgICAgdGVuc2lvbjogMFxuICAgIH07XG4gc3RhdGljIGRlZmF1bHRSb3V0ZXMgPSB7XG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogJ2JhY2tncm91bmRDb2xvcicsXG4gICAgICAgIGJvcmRlckNvbG9yOiAnYm9yZGVyQ29sb3InXG4gICAgfTtcbiAgICBzdGF0aWMgZGVzY3JpcHRvcnMgPSB7XG4gICAgICAgIF9zY3JpcHRhYmxlOiB0cnVlLFxuICAgICAgICBfaW5kZXhhYmxlOiAobmFtZSk9Pm5hbWUgIT09ICdib3JkZXJEYXNoJyAmJiBuYW1lICE9PSAnZmlsbCdcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGNmZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuYW5pbWF0ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2NoYXJ0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9sb29wID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9mdWxsTG9vcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fcGF0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fcG9pbnRzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9zZWdtZW50cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fZGVjaW1hdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX3BvaW50c1VwZGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fZGF0YXNldEluZGV4ID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY2ZnKSB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNmZyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdXBkYXRlQ29udHJvbFBvaW50cyhjaGFydEFyZWEsIGluZGV4QXhpcykge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoKG9wdGlvbnMudGVuc2lvbiB8fCBvcHRpb25zLmN1YmljSW50ZXJwb2xhdGlvbk1vZGUgPT09ICdtb25vdG9uZScpICYmICFvcHRpb25zLnN0ZXBwZWQgJiYgIXRoaXMuX3BvaW50c1VwZGF0ZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvb3AgPSBvcHRpb25zLnNwYW5HYXBzID8gdGhpcy5fbG9vcCA6IHRoaXMuX2Z1bGxMb29wO1xuICAgICAgICAgICAgX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHModGhpcy5fcG9pbnRzLCBvcHRpb25zLCBjaGFydEFyZWEsIGxvb3AsIGluZGV4QXhpcyk7XG4gICAgICAgICAgICB0aGlzLl9wb2ludHNVcGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXQgcG9pbnRzKHBvaW50cykge1xuICAgICAgICB0aGlzLl9wb2ludHMgPSBwb2ludHM7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9zZWdtZW50cztcbiAgICAgICAgZGVsZXRlIHRoaXMuX3BhdGg7XG4gICAgICAgIHRoaXMuX3BvaW50c1VwZGF0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgZ2V0IHBvaW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BvaW50cztcbiAgICB9XG4gICAgZ2V0IHNlZ21lbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2VnbWVudHMgfHwgKHRoaXMuX3NlZ21lbnRzID0gX2NvbXB1dGVTZWdtZW50cyh0aGlzLCB0aGlzLm9wdGlvbnMuc2VnbWVudCkpO1xuICAgIH1cbiBmaXJzdCgpIHtcbiAgICAgICAgY29uc3Qgc2VnbWVudHMgPSB0aGlzLnNlZ21lbnRzO1xuICAgICAgICBjb25zdCBwb2ludHMgPSB0aGlzLnBvaW50cztcbiAgICAgICAgcmV0dXJuIHNlZ21lbnRzLmxlbmd0aCAmJiBwb2ludHNbc2VnbWVudHNbMF0uc3RhcnRdO1xuICAgIH1cbiBsYXN0KCkge1xuICAgICAgICBjb25zdCBzZWdtZW50cyA9IHRoaXMuc2VnbWVudHM7XG4gICAgICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzO1xuICAgICAgICBjb25zdCBjb3VudCA9IHNlZ21lbnRzLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIGNvdW50ICYmIHBvaW50c1tzZWdtZW50c1tjb3VudCAtIDFdLmVuZF07XG4gICAgfVxuIGludGVycG9sYXRlKHBvaW50LCBwcm9wZXJ0eSkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBvaW50W3Byb3BlcnR5XTtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gdGhpcy5wb2ludHM7XG4gICAgICAgIGNvbnN0IHNlZ21lbnRzID0gX2JvdW5kU2VnbWVudHModGhpcywge1xuICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICBzdGFydDogdmFsdWUsXG4gICAgICAgICAgICBlbmQ6IHZhbHVlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIXNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICBjb25zdCBfaW50ZXJwb2xhdGUgPSBfZ2V0SW50ZXJwb2xhdGlvbk1ldGhvZChvcHRpb25zKTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IHNlZ21lbnRzLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICB9ID0gc2VnbWVudHNbaV07XG4gICAgICAgICAgICBjb25zdCBwMSA9IHBvaW50c1tzdGFydF07XG4gICAgICAgICAgICBjb25zdCBwMiA9IHBvaW50c1tlbmRdO1xuICAgICAgICAgICAgaWYgKHAxID09PSBwMikge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHAxKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHQgPSBNYXRoLmFicygodmFsdWUgLSBwMVtwcm9wZXJ0eV0pIC8gKHAyW3Byb3BlcnR5XSAtIHAxW3Byb3BlcnR5XSkpO1xuICAgICAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkID0gX2ludGVycG9sYXRlKHAxLCBwMiwgdCwgb3B0aW9ucy5zdGVwcGVkKTtcbiAgICAgICAgICAgIGludGVycG9sYXRlZFtwcm9wZXJ0eV0gPSBwb2ludFtwcm9wZXJ0eV07XG4gICAgICAgICAgICByZXN1bHQucHVzaChpbnRlcnBvbGF0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQubGVuZ3RoID09PSAxID8gcmVzdWx0WzBdIDogcmVzdWx0O1xuICAgIH1cbiBwYXRoU2VnbWVudChjdHgsIHNlZ21lbnQsIHBhcmFtcykge1xuICAgICAgICBjb25zdCBzZWdtZW50TWV0aG9kID0gX2dldFNlZ21lbnRNZXRob2QodGhpcyk7XG4gICAgICAgIHJldHVybiBzZWdtZW50TWV0aG9kKGN0eCwgdGhpcywgc2VnbWVudCwgcGFyYW1zKTtcbiAgICB9XG4gcGF0aChjdHgsIHN0YXJ0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBzZWdtZW50cyA9IHRoaXMuc2VnbWVudHM7XG4gICAgICAgIGNvbnN0IHNlZ21lbnRNZXRob2QgPSBfZ2V0U2VnbWVudE1ldGhvZCh0aGlzKTtcbiAgICAgICAgbGV0IGxvb3AgPSB0aGlzLl9sb29wO1xuICAgICAgICBzdGFydCA9IHN0YXJ0IHx8IDA7XG4gICAgICAgIGNvdW50ID0gY291bnQgfHwgdGhpcy5wb2ludHMubGVuZ3RoIC0gc3RhcnQ7XG4gICAgICAgIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cyl7XG4gICAgICAgICAgICBsb29wICY9IHNlZ21lbnRNZXRob2QoY3R4LCB0aGlzLCBzZWdtZW50LCB7XG4gICAgICAgICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgICAgICAgZW5kOiBzdGFydCArIGNvdW50IC0gMVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICEhbG9vcDtcbiAgICB9XG4gZHJhdyhjdHgsIGNoYXJ0QXJlYSwgc3RhcnQsIGNvdW50KSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgfHwge307XG4gICAgICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzIHx8IFtdO1xuICAgICAgICBpZiAocG9pbnRzLmxlbmd0aCAmJiBvcHRpb25zLmJvcmRlcldpZHRoKSB7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgZHJhdyhjdHgsIHRoaXMsIHN0YXJ0LCBjb3VudCk7XG4gICAgICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmFuaW1hdGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9wb2ludHNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9wYXRoID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpblJhbmdlJDEoZWwsIHBvcywgYXhpcywgdXNlRmluYWxQb3NpdGlvbikge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBlbC5vcHRpb25zO1xuICAgIGNvbnN0IHsgW2F4aXNdOiB2YWx1ZSAgfSA9IGVsLmdldFByb3BzKFtcbiAgICAgICAgYXhpc1xuICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIHJldHVybiBNYXRoLmFicyhwb3MgLSB2YWx1ZSkgPCBvcHRpb25zLnJhZGl1cyArIG9wdGlvbnMuaGl0UmFkaXVzO1xufVxuY2xhc3MgUG9pbnRFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7XG4gICAgc3RhdGljIGlkID0gJ3BvaW50JztcbiAgICBwYXJzZWQ7XG4gICAgc2tpcDtcbiAgICBzdG9wO1xuICAgIC8qKlxuICAgKiBAdHlwZSB7YW55fVxuICAgKi8gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBib3JkZXJXaWR0aDogMSxcbiAgICAgICAgaGl0UmFkaXVzOiAxLFxuICAgICAgICBob3ZlckJvcmRlcldpZHRoOiAxLFxuICAgICAgICBob3ZlclJhZGl1czogNCxcbiAgICAgICAgcG9pbnRTdHlsZTogJ2NpcmNsZScsXG4gICAgICAgIHJhZGl1czogMyxcbiAgICAgICAgcm90YXRpb246IDBcbiAgICB9O1xuICAgIC8qKlxuICAgKiBAdHlwZSB7YW55fVxuICAgKi8gc3RhdGljIGRlZmF1bHRSb3V0ZXMgPSB7XG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogJ2JhY2tncm91bmRDb2xvcicsXG4gICAgICAgIGJvcmRlckNvbG9yOiAnYm9yZGVyQ29sb3InXG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucGFyc2VkID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnNraXAgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuc3RvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGNmZykge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBjZmcpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGluUmFuZ2UobW91c2VYLCBtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgeyB4ICwgeSAgfSA9IHRoaXMuZ2V0UHJvcHMoW1xuICAgICAgICAgICAgJ3gnLFxuICAgICAgICAgICAgJ3knXG4gICAgICAgIF0sIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgICAgICByZXR1cm4gTWF0aC5wb3cobW91c2VYIC0geCwgMikgKyBNYXRoLnBvdyhtb3VzZVkgLSB5LCAyKSA8IE1hdGgucG93KG9wdGlvbnMuaGl0UmFkaXVzICsgb3B0aW9ucy5yYWRpdXMsIDIpO1xuICAgIH1cbiAgICBpblhSYW5nZShtb3VzZVgsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuIGluUmFuZ2UkMSh0aGlzLCBtb3VzZVgsICd4JywgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgfVxuICAgIGluWVJhbmdlKG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gaW5SYW5nZSQxKHRoaXMsIG1vdXNlWSwgJ3knLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG4gICAgZ2V0Q2VudGVyUG9pbnQodXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICBjb25zdCB7IHggLCB5ICB9ID0gdGhpcy5nZXRQcm9wcyhbXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAneSdcbiAgICAgICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4LFxuICAgICAgICAgICAgeVxuICAgICAgICB9O1xuICAgIH1cbiAgICBzaXplKG9wdGlvbnMpIHtcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwgdGhpcy5vcHRpb25zIHx8IHt9O1xuICAgICAgICBsZXQgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXMgfHwgMDtcbiAgICAgICAgcmFkaXVzID0gTWF0aC5tYXgocmFkaXVzLCByYWRpdXMgJiYgb3B0aW9ucy5ob3ZlclJhZGl1cyB8fCAwKTtcbiAgICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSByYWRpdXMgJiYgb3B0aW9ucy5ib3JkZXJXaWR0aCB8fCAwO1xuICAgICAgICByZXR1cm4gKHJhZGl1cyArIGJvcmRlcldpZHRoKSAqIDI7XG4gICAgfVxuICAgIGRyYXcoY3R4LCBhcmVhKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmICh0aGlzLnNraXAgfHwgb3B0aW9ucy5yYWRpdXMgPCAwLjEgfHwgIV9pc1BvaW50SW5BcmVhKHRoaXMsIGFyZWEsIHRoaXMuc2l6ZShvcHRpb25zKSAvIDIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0aW9ucy5ib3JkZXJDb2xvcjtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IG9wdGlvbnMuYm9yZGVyV2lkdGg7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgZHJhd1BvaW50KGN0eCwgb3B0aW9ucywgdGhpcy54LCB0aGlzLnkpO1xuICAgIH1cbiAgICBnZXRSYW5nZSgpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyB8fCB7fTtcbiAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBGYWxsYmFja3Mgc2hvdWxkIG5ldmVyIGJlIGhpdCBpbiBwcmFjdGljZVxuICAgICAgICByZXR1cm4gb3B0aW9ucy5yYWRpdXMgKyBvcHRpb25zLmhpdFJhZGl1cztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEJhckJvdW5kcyhiYXIsIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICBjb25zdCB7IHggLCB5ICwgYmFzZSAsIHdpZHRoICwgaGVpZ2h0ICB9ID0gIGJhci5nZXRQcm9wcyhbXG4gICAgICAgICd4JyxcbiAgICAgICAgJ3knLFxuICAgICAgICAnYmFzZScsXG4gICAgICAgICd3aWR0aCcsXG4gICAgICAgICdoZWlnaHQnXG4gICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgbGV0IGxlZnQsIHJpZ2h0LCB0b3AsIGJvdHRvbSwgaGFsZjtcbiAgICBpZiAoYmFyLmhvcml6b250YWwpIHtcbiAgICAgICAgaGFsZiA9IGhlaWdodCAvIDI7XG4gICAgICAgIGxlZnQgPSBNYXRoLm1pbih4LCBiYXNlKTtcbiAgICAgICAgcmlnaHQgPSBNYXRoLm1heCh4LCBiYXNlKTtcbiAgICAgICAgdG9wID0geSAtIGhhbGY7XG4gICAgICAgIGJvdHRvbSA9IHkgKyBoYWxmO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhhbGYgPSB3aWR0aCAvIDI7XG4gICAgICAgIGxlZnQgPSB4IC0gaGFsZjtcbiAgICAgICAgcmlnaHQgPSB4ICsgaGFsZjtcbiAgICAgICAgdG9wID0gTWF0aC5taW4oeSwgYmFzZSk7XG4gICAgICAgIGJvdHRvbSA9IE1hdGgubWF4KHksIGJhc2UpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0LFxuICAgICAgICB0b3AsXG4gICAgICAgIHJpZ2h0LFxuICAgICAgICBib3R0b21cbiAgICB9O1xufVxuZnVuY3Rpb24gc2tpcE9yTGltaXQoc2tpcCwgdmFsdWUsIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIHNraXAgPyAwIDogX2xpbWl0VmFsdWUodmFsdWUsIG1pbiwgbWF4KTtcbn1cbmZ1bmN0aW9uIHBhcnNlQm9yZGVyV2lkdGgoYmFyLCBtYXhXLCBtYXhIKSB7XG4gICAgY29uc3QgdmFsdWUgPSBiYXIub3B0aW9ucy5ib3JkZXJXaWR0aDtcbiAgICBjb25zdCBza2lwID0gYmFyLmJvcmRlclNraXBwZWQ7XG4gICAgY29uc3QgbyA9IHRvVFJCTCh2YWx1ZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdDogc2tpcE9yTGltaXQoc2tpcC50b3AsIG8udG9wLCAwLCBtYXhIKSxcbiAgICAgICAgcjogc2tpcE9yTGltaXQoc2tpcC5yaWdodCwgby5yaWdodCwgMCwgbWF4VyksXG4gICAgICAgIGI6IHNraXBPckxpbWl0KHNraXAuYm90dG9tLCBvLmJvdHRvbSwgMCwgbWF4SCksXG4gICAgICAgIGw6IHNraXBPckxpbWl0KHNraXAubGVmdCwgby5sZWZ0LCAwLCBtYXhXKVxuICAgIH07XG59XG5mdW5jdGlvbiBwYXJzZUJvcmRlclJhZGl1cyhiYXIsIG1heFcsIG1heEgpIHtcbiAgICBjb25zdCB7IGVuYWJsZUJvcmRlclJhZGl1cyAgfSA9IGJhci5nZXRQcm9wcyhbXG4gICAgICAgICdlbmFibGVCb3JkZXJSYWRpdXMnXG4gICAgXSk7XG4gICAgY29uc3QgdmFsdWUgPSBiYXIub3B0aW9ucy5ib3JkZXJSYWRpdXM7XG4gICAgY29uc3QgbyA9IHRvVFJCTENvcm5lcnModmFsdWUpO1xuICAgIGNvbnN0IG1heFIgPSBNYXRoLm1pbihtYXhXLCBtYXhIKTtcbiAgICBjb25zdCBza2lwID0gYmFyLmJvcmRlclNraXBwZWQ7XG4gICAgY29uc3QgZW5hYmxlQm9yZGVyID0gZW5hYmxlQm9yZGVyUmFkaXVzIHx8IGlzT2JqZWN0KHZhbHVlKTtcbiAgICByZXR1cm4ge1xuICAgICAgICB0b3BMZWZ0OiBza2lwT3JMaW1pdCghZW5hYmxlQm9yZGVyIHx8IHNraXAudG9wIHx8IHNraXAubGVmdCwgby50b3BMZWZ0LCAwLCBtYXhSKSxcbiAgICAgICAgdG9wUmlnaHQ6IHNraXBPckxpbWl0KCFlbmFibGVCb3JkZXIgfHwgc2tpcC50b3AgfHwgc2tpcC5yaWdodCwgby50b3BSaWdodCwgMCwgbWF4UiksXG4gICAgICAgIGJvdHRvbUxlZnQ6IHNraXBPckxpbWl0KCFlbmFibGVCb3JkZXIgfHwgc2tpcC5ib3R0b20gfHwgc2tpcC5sZWZ0LCBvLmJvdHRvbUxlZnQsIDAsIG1heFIpLFxuICAgICAgICBib3R0b21SaWdodDogc2tpcE9yTGltaXQoIWVuYWJsZUJvcmRlciB8fCBza2lwLmJvdHRvbSB8fCBza2lwLnJpZ2h0LCBvLmJvdHRvbVJpZ2h0LCAwLCBtYXhSKVxuICAgIH07XG59XG5mdW5jdGlvbiBib3VuZGluZ1JlY3RzKGJhcikge1xuICAgIGNvbnN0IGJvdW5kcyA9IGdldEJhckJvdW5kcyhiYXIpO1xuICAgIGNvbnN0IHdpZHRoID0gYm91bmRzLnJpZ2h0IC0gYm91bmRzLmxlZnQ7XG4gICAgY29uc3QgaGVpZ2h0ID0gYm91bmRzLmJvdHRvbSAtIGJvdW5kcy50b3A7XG4gICAgY29uc3QgYm9yZGVyID0gcGFyc2VCb3JkZXJXaWR0aChiYXIsIHdpZHRoIC8gMiwgaGVpZ2h0IC8gMik7XG4gICAgY29uc3QgcmFkaXVzID0gcGFyc2VCb3JkZXJSYWRpdXMoYmFyLCB3aWR0aCAvIDIsIGhlaWdodCAvIDIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG91dGVyOiB7XG4gICAgICAgICAgICB4OiBib3VuZHMubGVmdCxcbiAgICAgICAgICAgIHk6IGJvdW5kcy50b3AsXG4gICAgICAgICAgICB3OiB3aWR0aCxcbiAgICAgICAgICAgIGg6IGhlaWdodCxcbiAgICAgICAgICAgIHJhZGl1c1xuICAgICAgICB9LFxuICAgICAgICBpbm5lcjoge1xuICAgICAgICAgICAgeDogYm91bmRzLmxlZnQgKyBib3JkZXIubCxcbiAgICAgICAgICAgIHk6IGJvdW5kcy50b3AgKyBib3JkZXIudCxcbiAgICAgICAgICAgIHc6IHdpZHRoIC0gYm9yZGVyLmwgLSBib3JkZXIucixcbiAgICAgICAgICAgIGg6IGhlaWdodCAtIGJvcmRlci50IC0gYm9yZGVyLmIsXG4gICAgICAgICAgICByYWRpdXM6IHtcbiAgICAgICAgICAgICAgICB0b3BMZWZ0OiBNYXRoLm1heCgwLCByYWRpdXMudG9wTGVmdCAtIE1hdGgubWF4KGJvcmRlci50LCBib3JkZXIubCkpLFxuICAgICAgICAgICAgICAgIHRvcFJpZ2h0OiBNYXRoLm1heCgwLCByYWRpdXMudG9wUmlnaHQgLSBNYXRoLm1heChib3JkZXIudCwgYm9yZGVyLnIpKSxcbiAgICAgICAgICAgICAgICBib3R0b21MZWZ0OiBNYXRoLm1heCgwLCByYWRpdXMuYm90dG9tTGVmdCAtIE1hdGgubWF4KGJvcmRlci5iLCBib3JkZXIubCkpLFxuICAgICAgICAgICAgICAgIGJvdHRvbVJpZ2h0OiBNYXRoLm1heCgwLCByYWRpdXMuYm90dG9tUmlnaHQgLSBNYXRoLm1heChib3JkZXIuYiwgYm9yZGVyLnIpKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGluUmFuZ2UoYmFyLCB4LCB5LCB1c2VGaW5hbFBvc2l0aW9uKSB7XG4gICAgY29uc3Qgc2tpcFggPSB4ID09PSBudWxsO1xuICAgIGNvbnN0IHNraXBZID0geSA9PT0gbnVsbDtcbiAgICBjb25zdCBza2lwQm90aCA9IHNraXBYICYmIHNraXBZO1xuICAgIGNvbnN0IGJvdW5kcyA9IGJhciAmJiAhc2tpcEJvdGggJiYgZ2V0QmFyQm91bmRzKGJhciwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgcmV0dXJuIGJvdW5kcyAmJiAoc2tpcFggfHwgX2lzQmV0d2Vlbih4LCBib3VuZHMubGVmdCwgYm91bmRzLnJpZ2h0KSkgJiYgKHNraXBZIHx8IF9pc0JldHdlZW4oeSwgYm91bmRzLnRvcCwgYm91bmRzLmJvdHRvbSkpO1xufVxuZnVuY3Rpb24gaGFzUmFkaXVzKHJhZGl1cykge1xuICAgIHJldHVybiByYWRpdXMudG9wTGVmdCB8fCByYWRpdXMudG9wUmlnaHQgfHwgcmFkaXVzLmJvdHRvbUxlZnQgfHwgcmFkaXVzLmJvdHRvbVJpZ2h0O1xufVxuIGZ1bmN0aW9uIGFkZE5vcm1hbFJlY3RQYXRoKGN0eCwgcmVjdCkge1xuICAgIGN0eC5yZWN0KHJlY3QueCwgcmVjdC55LCByZWN0LncsIHJlY3QuaCk7XG59XG5mdW5jdGlvbiBpbmZsYXRlUmVjdChyZWN0LCBhbW91bnQsIHJlZlJlY3QgPSB7fSkge1xuICAgIGNvbnN0IHggPSByZWN0LnggIT09IHJlZlJlY3QueCA/IC1hbW91bnQgOiAwO1xuICAgIGNvbnN0IHkgPSByZWN0LnkgIT09IHJlZlJlY3QueSA/IC1hbW91bnQgOiAwO1xuICAgIGNvbnN0IHcgPSAocmVjdC54ICsgcmVjdC53ICE9PSByZWZSZWN0LnggKyByZWZSZWN0LncgPyBhbW91bnQgOiAwKSAtIHg7XG4gICAgY29uc3QgaCA9IChyZWN0LnkgKyByZWN0LmggIT09IHJlZlJlY3QueSArIHJlZlJlY3QuaCA/IGFtb3VudCA6IDApIC0geTtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiByZWN0LnggKyB4LFxuICAgICAgICB5OiByZWN0LnkgKyB5LFxuICAgICAgICB3OiByZWN0LncgKyB3LFxuICAgICAgICBoOiByZWN0LmggKyBoLFxuICAgICAgICByYWRpdXM6IHJlY3QucmFkaXVzXG4gICAgfTtcbn1cbmNsYXNzIEJhckVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgICBzdGF0aWMgaWQgPSAnYmFyJztcbiBzdGF0aWMgZGVmYXVsdHMgPSB7XG4gICAgICAgIGJvcmRlclNraXBwZWQ6ICdzdGFydCcsXG4gICAgICAgIGJvcmRlcldpZHRoOiAwLFxuICAgICAgICBib3JkZXJSYWRpdXM6IDAsXG4gICAgICAgIGluZmxhdGVBbW91bnQ6ICdhdXRvJyxcbiAgICAgICAgcG9pbnRTdHlsZTogdW5kZWZpbmVkXG4gICAgfTtcbiBzdGF0aWMgZGVmYXVsdFJvdXRlcyA9IHtcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZENvbG9yJyxcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcidcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGNmZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5ob3Jpem9udGFsID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmJhc2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMud2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmluZmxhdGVBbW91bnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjZmcpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgY2ZnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkcmF3KGN0eCkge1xuICAgICAgICBjb25zdCB7IGluZmxhdGVBbW91bnQgLCBvcHRpb25zOiB7IGJvcmRlckNvbG9yICwgYmFja2dyb3VuZENvbG9yICB9ICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgeyBpbm5lciAsIG91dGVyICB9ID0gYm91bmRpbmdSZWN0cyh0aGlzKTtcbiAgICAgICAgY29uc3QgYWRkUmVjdFBhdGggPSBoYXNSYWRpdXMob3V0ZXIucmFkaXVzKSA/IGFkZFJvdW5kZWRSZWN0UGF0aCA6IGFkZE5vcm1hbFJlY3RQYXRoO1xuICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICBpZiAob3V0ZXIudyAhPT0gaW5uZXIudyB8fCBvdXRlci5oICE9PSBpbm5lci5oKSB7XG4gICAgICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgICAgICBhZGRSZWN0UGF0aChjdHgsIGluZmxhdGVSZWN0KG91dGVyLCBpbmZsYXRlQW1vdW50LCBpbm5lcikpO1xuICAgICAgICAgICAgY3R4LmNsaXAoKTtcbiAgICAgICAgICAgIGFkZFJlY3RQYXRoKGN0eCwgaW5mbGF0ZVJlY3QoaW5uZXIsIC1pbmZsYXRlQW1vdW50LCBvdXRlcikpO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJvcmRlckNvbG9yO1xuICAgICAgICAgICAgY3R4LmZpbGwoJ2V2ZW5vZGQnKTtcbiAgICAgICAgfVxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGFkZFJlY3RQYXRoKGN0eCwgaW5mbGF0ZVJlY3QoaW5uZXIsIGluZmxhdGVBbW91bnQpKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgY3R4LmZpbGwoKTtcbiAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICB9XG4gICAgaW5SYW5nZShtb3VzZVgsIG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gaW5SYW5nZSh0aGlzLCBtb3VzZVgsIG1vdXNlWSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgfVxuICAgIGluWFJhbmdlKG1vdXNlWCwgdXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICByZXR1cm4gaW5SYW5nZSh0aGlzLCBtb3VzZVgsIG51bGwsIHVzZUZpbmFsUG9zaXRpb24pO1xuICAgIH1cbiAgICBpbllSYW5nZShtb3VzZVksIHVzZUZpbmFsUG9zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuIGluUmFuZ2UodGhpcywgbnVsbCwgbW91c2VZLCB1c2VGaW5hbFBvc2l0aW9uKTtcbiAgICB9XG4gICAgZ2V0Q2VudGVyUG9pbnQodXNlRmluYWxQb3NpdGlvbikge1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgYmFzZSAsIGhvcml6b250YWwgIH0gPSAgdGhpcy5nZXRQcm9wcyhbXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAneScsXG4gICAgICAgICAgICAnYmFzZScsXG4gICAgICAgICAgICAnaG9yaXpvbnRhbCdcbiAgICAgICAgXSwgdXNlRmluYWxQb3NpdGlvbik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiBob3Jpem9udGFsID8gKHggKyBiYXNlKSAvIDIgOiB4LFxuICAgICAgICAgICAgeTogaG9yaXpvbnRhbCA/IHkgOiAoeSArIGJhc2UpIC8gMlxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRSYW5nZShheGlzKSB7XG4gICAgICAgIHJldHVybiBheGlzID09PSAneCcgPyB0aGlzLndpZHRoIC8gMiA6IHRoaXMuaGVpZ2h0IC8gMjtcbiAgICB9XG59XG5cbnZhciBlbGVtZW50cyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbl9fcHJvdG9fXzogbnVsbCxcbkFyY0VsZW1lbnQ6IEFyY0VsZW1lbnQsXG5CYXJFbGVtZW50OiBCYXJFbGVtZW50LFxuTGluZUVsZW1lbnQ6IExpbmVFbGVtZW50LFxuUG9pbnRFbGVtZW50OiBQb2ludEVsZW1lbnRcbn0pO1xuXG5jb25zdCBCT1JERVJfQ09MT1JTID0gW1xuICAgICdyZ2IoNTQsIDE2MiwgMjM1KScsXG4gICAgJ3JnYigyNTUsIDk5LCAxMzIpJyxcbiAgICAncmdiKDI1NSwgMTU5LCA2NCknLFxuICAgICdyZ2IoMjU1LCAyMDUsIDg2KScsXG4gICAgJ3JnYig3NSwgMTkyLCAxOTIpJyxcbiAgICAncmdiKDE1MywgMTAyLCAyNTUpJyxcbiAgICAncmdiKDIwMSwgMjAzLCAyMDcpJyAvLyBncmV5XG5dO1xuLy8gQm9yZGVyIGNvbG9ycyB3aXRoIDUwJSB0cmFuc3BhcmVuY3lcbmNvbnN0IEJBQ0tHUk9VTkRfQ09MT1JTID0gLyogI19fUFVSRV9fICovIEJPUkRFUl9DT0xPUlMubWFwKChjb2xvcik9PmNvbG9yLnJlcGxhY2UoJ3JnYignLCAncmdiYSgnKS5yZXBsYWNlKCcpJywgJywgMC41KScpKTtcbmZ1bmN0aW9uIGdldEJvcmRlckNvbG9yKGkpIHtcbiAgICByZXR1cm4gQk9SREVSX0NPTE9SU1tpICUgQk9SREVSX0NPTE9SUy5sZW5ndGhdO1xufVxuZnVuY3Rpb24gZ2V0QmFja2dyb3VuZENvbG9yKGkpIHtcbiAgICByZXR1cm4gQkFDS0dST1VORF9DT0xPUlNbaSAlIEJBQ0tHUk9VTkRfQ09MT1JTLmxlbmd0aF07XG59XG5mdW5jdGlvbiBjb2xvcml6ZURlZmF1bHREYXRhc2V0KGRhdGFzZXQsIGkpIHtcbiAgICBkYXRhc2V0LmJvcmRlckNvbG9yID0gZ2V0Qm9yZGVyQ29sb3IoaSk7XG4gICAgZGF0YXNldC5iYWNrZ3JvdW5kQ29sb3IgPSBnZXRCYWNrZ3JvdW5kQ29sb3IoaSk7XG4gICAgcmV0dXJuICsraTtcbn1cbmZ1bmN0aW9uIGNvbG9yaXplRG91Z2hudXREYXRhc2V0KGRhdGFzZXQsIGkpIHtcbiAgICBkYXRhc2V0LmJhY2tncm91bmRDb2xvciA9IGRhdGFzZXQuZGF0YS5tYXAoKCk9PmdldEJvcmRlckNvbG9yKGkrKykpO1xuICAgIHJldHVybiBpO1xufVxuZnVuY3Rpb24gY29sb3JpemVQb2xhckFyZWFEYXRhc2V0KGRhdGFzZXQsIGkpIHtcbiAgICBkYXRhc2V0LmJhY2tncm91bmRDb2xvciA9IGRhdGFzZXQuZGF0YS5tYXAoKCk9PmdldEJhY2tncm91bmRDb2xvcihpKyspKTtcbiAgICByZXR1cm4gaTtcbn1cbmZ1bmN0aW9uIGdldENvbG9yaXplcihjaGFydCkge1xuICAgIGxldCBpID0gMDtcbiAgICByZXR1cm4gKGRhdGFzZXQsIGRhdGFzZXRJbmRleCk9PntcbiAgICAgICAgY29uc3QgY29udHJvbGxlciA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCkuY29udHJvbGxlcjtcbiAgICAgICAgaWYgKGNvbnRyb2xsZXIgaW5zdGFuY2VvZiBEb3VnaG51dENvbnRyb2xsZXIpIHtcbiAgICAgICAgICAgIGkgPSBjb2xvcml6ZURvdWdobnV0RGF0YXNldChkYXRhc2V0LCBpKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sbGVyIGluc3RhbmNlb2YgUG9sYXJBcmVhQ29udHJvbGxlcikge1xuICAgICAgICAgICAgaSA9IGNvbG9yaXplUG9sYXJBcmVhRGF0YXNldChkYXRhc2V0LCBpKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sbGVyKSB7XG4gICAgICAgICAgICBpID0gY29sb3JpemVEZWZhdWx0RGF0YXNldChkYXRhc2V0LCBpKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5mdW5jdGlvbiBjb250YWluc0NvbG9yc0RlZmluaXRpb25zKGRlc2NyaXB0b3JzKSB7XG4gICAgbGV0IGs7XG4gICAgZm9yKGsgaW4gZGVzY3JpcHRvcnMpe1xuICAgICAgICBpZiAoZGVzY3JpcHRvcnNba10uYm9yZGVyQ29sb3IgfHwgZGVzY3JpcHRvcnNba10uYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBjb250YWluc0NvbG9yc0RlZmluaXRpb24oZGVzY3JpcHRvcikge1xuICAgIHJldHVybiBkZXNjcmlwdG9yICYmIChkZXNjcmlwdG9yLmJvcmRlckNvbG9yIHx8IGRlc2NyaXB0b3IuYmFja2dyb3VuZENvbG9yKTtcbn1cbnZhciBwbHVnaW5fY29sb3JzID0ge1xuICAgIGlkOiAnY29sb3JzJyxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICBmb3JjZU92ZXJyaWRlOiBmYWxzZVxuICAgIH0sXG4gICAgYmVmb3JlTGF5b3V0IChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKCFvcHRpb25zLmVuYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGRhdGE6IHsgZGF0YXNldHMgIH0gLCBvcHRpb25zOiBjaGFydE9wdGlvbnMgIH0gPSBjaGFydC5jb25maWc7XG4gICAgICAgIGNvbnN0IHsgZWxlbWVudHMgIH0gPSBjaGFydE9wdGlvbnM7XG4gICAgICAgIGlmICghb3B0aW9ucy5mb3JjZU92ZXJyaWRlICYmIChjb250YWluc0NvbG9yc0RlZmluaXRpb25zKGRhdGFzZXRzKSB8fCBjb250YWluc0NvbG9yc0RlZmluaXRpb24oY2hhcnRPcHRpb25zKSB8fCBlbGVtZW50cyAmJiBjb250YWluc0NvbG9yc0RlZmluaXRpb25zKGVsZW1lbnRzKSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb2xvcml6ZXIgPSBnZXRDb2xvcml6ZXIoY2hhcnQpO1xuICAgICAgICBkYXRhc2V0cy5mb3JFYWNoKGNvbG9yaXplcik7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gbHR0YkRlY2ltYXRpb24oZGF0YSwgc3RhcnQsIGNvdW50LCBhdmFpbGFibGVXaWR0aCwgb3B0aW9ucykge1xuIGNvbnN0IHNhbXBsZXMgPSBvcHRpb25zLnNhbXBsZXMgfHwgYXZhaWxhYmxlV2lkdGg7XG4gICAgaWYgKHNhbXBsZXMgPj0gY291bnQpIHtcbiAgICAgICAgcmV0dXJuIGRhdGEuc2xpY2Uoc3RhcnQsIHN0YXJ0ICsgY291bnQpO1xuICAgIH1cbiAgICBjb25zdCBkZWNpbWF0ZWQgPSBbXTtcbiAgICBjb25zdCBidWNrZXRXaWR0aCA9IChjb3VudCAtIDIpIC8gKHNhbXBsZXMgLSAyKTtcbiAgICBsZXQgc2FtcGxlZEluZGV4ID0gMDtcbiAgICBjb25zdCBlbmRJbmRleCA9IHN0YXJ0ICsgY291bnQgLSAxO1xuICAgIGxldCBhID0gc3RhcnQ7XG4gICAgbGV0IGksIG1heEFyZWFQb2ludCwgbWF4QXJlYSwgYXJlYSwgbmV4dEE7XG4gICAgZGVjaW1hdGVkW3NhbXBsZWRJbmRleCsrXSA9IGRhdGFbYV07XG4gICAgZm9yKGkgPSAwOyBpIDwgc2FtcGxlcyAtIDI7IGkrKyl7XG4gICAgICAgIGxldCBhdmdYID0gMDtcbiAgICAgICAgbGV0IGF2Z1kgPSAwO1xuICAgICAgICBsZXQgajtcbiAgICAgICAgY29uc3QgYXZnUmFuZ2VTdGFydCA9IE1hdGguZmxvb3IoKGkgKyAxKSAqIGJ1Y2tldFdpZHRoKSArIDEgKyBzdGFydDtcbiAgICAgICAgY29uc3QgYXZnUmFuZ2VFbmQgPSBNYXRoLm1pbihNYXRoLmZsb29yKChpICsgMikgKiBidWNrZXRXaWR0aCkgKyAxLCBjb3VudCkgKyBzdGFydDtcbiAgICAgICAgY29uc3QgYXZnUmFuZ2VMZW5ndGggPSBhdmdSYW5nZUVuZCAtIGF2Z1JhbmdlU3RhcnQ7XG4gICAgICAgIGZvcihqID0gYXZnUmFuZ2VTdGFydDsgaiA8IGF2Z1JhbmdlRW5kOyBqKyspe1xuICAgICAgICAgICAgYXZnWCArPSBkYXRhW2pdLng7XG4gICAgICAgICAgICBhdmdZICs9IGRhdGFbal0ueTtcbiAgICAgICAgfVxuICAgICAgICBhdmdYIC89IGF2Z1JhbmdlTGVuZ3RoO1xuICAgICAgICBhdmdZIC89IGF2Z1JhbmdlTGVuZ3RoO1xuICAgICAgICBjb25zdCByYW5nZU9mZnMgPSBNYXRoLmZsb29yKGkgKiBidWNrZXRXaWR0aCkgKyAxICsgc3RhcnQ7XG4gICAgICAgIGNvbnN0IHJhbmdlVG8gPSBNYXRoLm1pbihNYXRoLmZsb29yKChpICsgMSkgKiBidWNrZXRXaWR0aCkgKyAxLCBjb3VudCkgKyBzdGFydDtcbiAgICAgICAgY29uc3QgeyB4OiBwb2ludEF4ICwgeTogcG9pbnRBeSAgfSA9IGRhdGFbYV07XG4gICAgICAgIG1heEFyZWEgPSBhcmVhID0gLTE7XG4gICAgICAgIGZvcihqID0gcmFuZ2VPZmZzOyBqIDwgcmFuZ2VUbzsgaisrKXtcbiAgICAgICAgICAgIGFyZWEgPSAwLjUgKiBNYXRoLmFicygocG9pbnRBeCAtIGF2Z1gpICogKGRhdGFbal0ueSAtIHBvaW50QXkpIC0gKHBvaW50QXggLSBkYXRhW2pdLngpICogKGF2Z1kgLSBwb2ludEF5KSk7XG4gICAgICAgICAgICBpZiAoYXJlYSA+IG1heEFyZWEpIHtcbiAgICAgICAgICAgICAgICBtYXhBcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICBtYXhBcmVhUG9pbnQgPSBkYXRhW2pdO1xuICAgICAgICAgICAgICAgIG5leHRBID0gajtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBkZWNpbWF0ZWRbc2FtcGxlZEluZGV4KytdID0gbWF4QXJlYVBvaW50O1xuICAgICAgICBhID0gbmV4dEE7XG4gICAgfVxuICAgIGRlY2ltYXRlZFtzYW1wbGVkSW5kZXgrK10gPSBkYXRhW2VuZEluZGV4XTtcbiAgICByZXR1cm4gZGVjaW1hdGVkO1xufVxuZnVuY3Rpb24gbWluTWF4RGVjaW1hdGlvbihkYXRhLCBzdGFydCwgY291bnQsIGF2YWlsYWJsZVdpZHRoKSB7XG4gICAgbGV0IGF2Z1ggPSAwO1xuICAgIGxldCBjb3VudFggPSAwO1xuICAgIGxldCBpLCBwb2ludCwgeCwgeSwgcHJldlgsIG1pbkluZGV4LCBtYXhJbmRleCwgc3RhcnRJbmRleCwgbWluWSwgbWF4WTtcbiAgICBjb25zdCBkZWNpbWF0ZWQgPSBbXTtcbiAgICBjb25zdCBlbmRJbmRleCA9IHN0YXJ0ICsgY291bnQgLSAxO1xuICAgIGNvbnN0IHhNaW4gPSBkYXRhW3N0YXJ0XS54O1xuICAgIGNvbnN0IHhNYXggPSBkYXRhW2VuZEluZGV4XS54O1xuICAgIGNvbnN0IGR4ID0geE1heCAtIHhNaW47XG4gICAgZm9yKGkgPSBzdGFydDsgaSA8IHN0YXJ0ICsgY291bnQ7ICsraSl7XG4gICAgICAgIHBvaW50ID0gZGF0YVtpXTtcbiAgICAgICAgeCA9IChwb2ludC54IC0geE1pbikgLyBkeCAqIGF2YWlsYWJsZVdpZHRoO1xuICAgICAgICB5ID0gcG9pbnQueTtcbiAgICAgICAgY29uc3QgdHJ1bmNYID0geCB8IDA7XG4gICAgICAgIGlmICh0cnVuY1ggPT09IHByZXZYKSB7XG4gICAgICAgICAgICBpZiAoeSA8IG1pblkpIHtcbiAgICAgICAgICAgICAgICBtaW5ZID0geTtcbiAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHkgPiBtYXhZKSB7XG4gICAgICAgICAgICAgICAgbWF4WSA9IHk7XG4gICAgICAgICAgICAgICAgbWF4SW5kZXggPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXZnWCA9IChjb3VudFggKiBhdmdYICsgcG9pbnQueCkgLyArK2NvdW50WDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RJbmRleCA9IGkgLSAxO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKG1pbkluZGV4KSAmJiAhaXNOdWxsT3JVbmRlZihtYXhJbmRleCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnRlcm1lZGlhdGVJbmRleDEgPSBNYXRoLm1pbihtaW5JbmRleCwgbWF4SW5kZXgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGludGVybWVkaWF0ZUluZGV4MiA9IE1hdGgubWF4KG1pbkluZGV4LCBtYXhJbmRleCk7XG4gICAgICAgICAgICAgICAgaWYgKGludGVybWVkaWF0ZUluZGV4MSAhPT0gc3RhcnRJbmRleCAmJiBpbnRlcm1lZGlhdGVJbmRleDEgIT09IGxhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBkZWNpbWF0ZWQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5kYXRhW2ludGVybWVkaWF0ZUluZGV4MV0sXG4gICAgICAgICAgICAgICAgICAgICAgICB4OiBhdmdYXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJtZWRpYXRlSW5kZXgyICE9PSBzdGFydEluZGV4ICYmIGludGVybWVkaWF0ZUluZGV4MiAhPT0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYXRlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmRhdGFbaW50ZXJtZWRpYXRlSW5kZXgyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGF2Z1hcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPiAwICYmIGxhc3RJbmRleCAhPT0gc3RhcnRJbmRleCkge1xuICAgICAgICAgICAgICAgIGRlY2ltYXRlZC5wdXNoKGRhdGFbbGFzdEluZGV4XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWNpbWF0ZWQucHVzaChwb2ludCk7XG4gICAgICAgICAgICBwcmV2WCA9IHRydW5jWDtcbiAgICAgICAgICAgIGNvdW50WCA9IDA7XG4gICAgICAgICAgICBtaW5ZID0gbWF4WSA9IHk7XG4gICAgICAgICAgICBtaW5JbmRleCA9IG1heEluZGV4ID0gc3RhcnRJbmRleCA9IGk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRlY2ltYXRlZDtcbn1cbmZ1bmN0aW9uIGNsZWFuRGVjaW1hdGVkRGF0YXNldChkYXRhc2V0KSB7XG4gICAgaWYgKGRhdGFzZXQuX2RlY2ltYXRlZCkge1xuICAgICAgICBjb25zdCBkYXRhID0gZGF0YXNldC5fZGF0YTtcbiAgICAgICAgZGVsZXRlIGRhdGFzZXQuX2RlY2ltYXRlZDtcbiAgICAgICAgZGVsZXRlIGRhdGFzZXQuX2RhdGE7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRhc2V0LCAnZGF0YScsIHtcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlOiBkYXRhXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNsZWFuRGVjaW1hdGVkRGF0YShjaGFydCkge1xuICAgIGNoYXJ0LmRhdGEuZGF0YXNldHMuZm9yRWFjaCgoZGF0YXNldCk9PntcbiAgICAgICAgY2xlYW5EZWNpbWF0ZWREYXRhc2V0KGRhdGFzZXQpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZ2V0U3RhcnRBbmRDb3VudE9mVmlzaWJsZVBvaW50c1NpbXBsaWZpZWQobWV0YSwgcG9pbnRzKSB7XG4gICAgY29uc3QgcG9pbnRDb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgbGV0IHN0YXJ0ID0gMDtcbiAgICBsZXQgY291bnQ7XG4gICAgY29uc3QgeyBpU2NhbGUgIH0gPSBtZXRhO1xuICAgIGNvbnN0IHsgbWluICwgbWF4ICwgbWluRGVmaW5lZCAsIG1heERlZmluZWQgIH0gPSBpU2NhbGUuZ2V0VXNlckJvdW5kcygpO1xuICAgIGlmIChtaW5EZWZpbmVkKSB7XG4gICAgICAgIHN0YXJ0ID0gX2xpbWl0VmFsdWUoX2xvb2t1cEJ5S2V5KHBvaW50cywgaVNjYWxlLmF4aXMsIG1pbikubG8sIDAsIHBvaW50Q291bnQgLSAxKTtcbiAgICB9XG4gICAgaWYgKG1heERlZmluZWQpIHtcbiAgICAgICAgY291bnQgPSBfbGltaXRWYWx1ZShfbG9va3VwQnlLZXkocG9pbnRzLCBpU2NhbGUuYXhpcywgbWF4KS5oaSArIDEsIHN0YXJ0LCBwb2ludENvdW50KSAtIHN0YXJ0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvdW50ID0gcG9pbnRDb3VudCAtIHN0YXJ0O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydCxcbiAgICAgICAgY291bnRcbiAgICB9O1xufVxudmFyIHBsdWdpbl9kZWNpbWF0aW9uID0ge1xuICAgIGlkOiAnZGVjaW1hdGlvbicsXG4gICAgZGVmYXVsdHM6IHtcbiAgICAgICAgYWxnb3JpdGhtOiAnbWluLW1heCcsXG4gICAgICAgIGVuYWJsZWQ6IGZhbHNlXG4gICAgfSxcbiAgICBiZWZvcmVFbGVtZW50c1VwZGF0ZTogKGNoYXJ0LCBhcmdzLCBvcHRpb25zKT0+e1xuICAgICAgICBpZiAoIW9wdGlvbnMuZW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYW5EZWNpbWF0ZWREYXRhKGNoYXJ0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhdmFpbGFibGVXaWR0aCA9IGNoYXJ0LndpZHRoO1xuICAgICAgICBjaGFydC5kYXRhLmRhdGFzZXRzLmZvckVhY2goKGRhdGFzZXQsIGRhdGFzZXRJbmRleCk9PntcbiAgICAgICAgICAgIGNvbnN0IHsgX2RhdGEgLCBpbmRleEF4aXMgIH0gPSBkYXRhc2V0O1xuICAgICAgICAgICAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGRhdGFzZXRJbmRleCk7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gX2RhdGEgfHwgZGF0YXNldC5kYXRhO1xuICAgICAgICAgICAgaWYgKHJlc29sdmUoW1xuICAgICAgICAgICAgICAgIGluZGV4QXhpcyxcbiAgICAgICAgICAgICAgICBjaGFydC5vcHRpb25zLmluZGV4QXhpc1xuICAgICAgICAgICAgXSkgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbWV0YS5jb250cm9sbGVyLnN1cHBvcnRzRGVjaW1hdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHhBeGlzID0gY2hhcnQuc2NhbGVzW21ldGEueEF4aXNJRF07XG4gICAgICAgICAgICBpZiAoeEF4aXMudHlwZSAhPT0gJ2xpbmVhcicgJiYgeEF4aXMudHlwZSAhPT0gJ3RpbWUnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNoYXJ0Lm9wdGlvbnMucGFyc2luZykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB7IHN0YXJ0ICwgY291bnQgIH0gPSBnZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzU2ltcGxpZmllZChtZXRhLCBkYXRhKTtcbiAgICAgICAgICAgIGNvbnN0IHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkIHx8IDQgKiBhdmFpbGFibGVXaWR0aDtcbiAgICAgICAgICAgIGlmIChjb3VudCA8PSB0aHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICBjbGVhbkRlY2ltYXRlZERhdGFzZXQoZGF0YXNldCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWYoX2RhdGEpKSB7XG4gICAgICAgICAgICAgICAgZGF0YXNldC5fZGF0YSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFzZXQuZGF0YTtcbiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGF0YXNldCwgJ2RhdGEnLCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWNpbWF0ZWQ7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0YSA9IGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkZWNpbWF0ZWQ7XG4gICAgICAgICAgICBzd2l0Y2gob3B0aW9ucy5hbGdvcml0aG0pe1xuICAgICAgICAgICAgICAgIGNhc2UgJ2x0dGInOlxuICAgICAgICAgICAgICAgICAgICBkZWNpbWF0ZWQgPSBsdHRiRGVjaW1hdGlvbihkYXRhLCBzdGFydCwgY291bnQsIGF2YWlsYWJsZVdpZHRoLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbWluLW1heCc6XG4gICAgICAgICAgICAgICAgICAgIGRlY2ltYXRlZCA9IG1pbk1heERlY2ltYXRpb24oZGF0YSwgc3RhcnQsIGNvdW50LCBhdmFpbGFibGVXaWR0aCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGVjaW1hdGlvbiBhbGdvcml0aG0gJyR7b3B0aW9ucy5hbGdvcml0aG19J2ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0YXNldC5fZGVjaW1hdGVkID0gZGVjaW1hdGVkO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGRlc3Ryb3kgKGNoYXJ0KSB7XG4gICAgICAgIGNsZWFuRGVjaW1hdGVkRGF0YShjaGFydCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gX3NlZ21lbnRzKGxpbmUsIHRhcmdldCwgcHJvcGVydHkpIHtcbiAgICBjb25zdCBzZWdtZW50cyA9IGxpbmUuc2VnbWVudHM7XG4gICAgY29uc3QgcG9pbnRzID0gbGluZS5wb2ludHM7XG4gICAgY29uc3QgdHBvaW50cyA9IHRhcmdldC5wb2ludHM7XG4gICAgY29uc3QgcGFydHMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpe1xuICAgICAgICBsZXQgeyBzdGFydCAsIGVuZCAgfSA9IHNlZ21lbnQ7XG4gICAgICAgIGVuZCA9IF9maW5kU2VnbWVudEVuZChzdGFydCwgZW5kLCBwb2ludHMpO1xuICAgICAgICBjb25zdCBib3VuZHMgPSBfZ2V0Qm91bmRzKHByb3BlcnR5LCBwb2ludHNbc3RhcnRdLCBwb2ludHNbZW5kXSwgc2VnbWVudC5sb29wKTtcbiAgICAgICAgaWYgKCF0YXJnZXQuc2VnbWVudHMpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIHNvdXJjZTogc2VnbWVudCxcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IGJvdW5kcyxcbiAgICAgICAgICAgICAgICBzdGFydDogcG9pbnRzW3N0YXJ0XSxcbiAgICAgICAgICAgICAgICBlbmQ6IHBvaW50c1tlbmRdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRhcmdldFNlZ21lbnRzID0gX2JvdW5kU2VnbWVudHModGFyZ2V0LCBib3VuZHMpO1xuICAgICAgICBmb3IgKGNvbnN0IHRndCBvZiB0YXJnZXRTZWdtZW50cyl7XG4gICAgICAgICAgICBjb25zdCBzdWJCb3VuZHMgPSBfZ2V0Qm91bmRzKHByb3BlcnR5LCB0cG9pbnRzW3RndC5zdGFydF0sIHRwb2ludHNbdGd0LmVuZF0sIHRndC5sb29wKTtcbiAgICAgICAgICAgIGNvbnN0IGZpbGxTb3VyY2VzID0gX2JvdW5kU2VnbWVudChzZWdtZW50LCBwb2ludHMsIHN1YkJvdW5kcyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGxTb3VyY2Ugb2YgZmlsbFNvdXJjZXMpe1xuICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IGZpbGxTb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldDogdGd0LFxuICAgICAgICAgICAgICAgICAgICBzdGFydDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgW3Byb3BlcnR5XTogX2dldEVkZ2UoYm91bmRzLCBzdWJCb3VuZHMsICdzdGFydCcsIE1hdGgubWF4KVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwcm9wZXJ0eV06IF9nZXRFZGdlKGJvdW5kcywgc3ViQm91bmRzLCAnZW5kJywgTWF0aC5taW4pXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFydHM7XG59XG5mdW5jdGlvbiBfZ2V0Qm91bmRzKHByb3BlcnR5LCBmaXJzdCwgbGFzdCwgbG9vcCkge1xuICAgIGlmIChsb29wKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHN0YXJ0ID0gZmlyc3RbcHJvcGVydHldO1xuICAgIGxldCBlbmQgPSBsYXN0W3Byb3BlcnR5XTtcbiAgICBpZiAocHJvcGVydHkgPT09ICdhbmdsZScpIHtcbiAgICAgICAgc3RhcnQgPSBfbm9ybWFsaXplQW5nbGUoc3RhcnQpO1xuICAgICAgICBlbmQgPSBfbm9ybWFsaXplQW5nbGUoZW5kKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcHJvcGVydHksXG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBlbmRcbiAgICB9O1xufVxuZnVuY3Rpb24gX3BvaW50c0Zyb21TZWdtZW50cyhib3VuZGFyeSwgbGluZSkge1xuICAgIGNvbnN0IHsgeCA9bnVsbCAsIHkgPW51bGwgIH0gPSBib3VuZGFyeSB8fCB7fTtcbiAgICBjb25zdCBsaW5lUG9pbnRzID0gbGluZS5wb2ludHM7XG4gICAgY29uc3QgcG9pbnRzID0gW107XG4gICAgbGluZS5zZWdtZW50cy5mb3JFYWNoKCh7IHN0YXJ0ICwgZW5kICB9KT0+e1xuICAgICAgICBlbmQgPSBfZmluZFNlZ21lbnRFbmQoc3RhcnQsIGVuZCwgbGluZVBvaW50cyk7XG4gICAgICAgIGNvbnN0IGZpcnN0ID0gbGluZVBvaW50c1tzdGFydF07XG4gICAgICAgIGNvbnN0IGxhc3QgPSBsaW5lUG9pbnRzW2VuZF07XG4gICAgICAgIGlmICh5ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBwb2ludHMucHVzaCh7XG4gICAgICAgICAgICAgICAgeDogZmlyc3QueCxcbiAgICAgICAgICAgICAgICB5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvaW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICB4OiBsYXN0LngsXG4gICAgICAgICAgICAgICAgeVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoeCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcG9pbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeTogZmlyc3QueVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwb2ludHMucHVzaCh7XG4gICAgICAgICAgICAgICAgeCxcbiAgICAgICAgICAgICAgICB5OiBsYXN0LnlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHBvaW50cztcbn1cbmZ1bmN0aW9uIF9maW5kU2VnbWVudEVuZChzdGFydCwgZW5kLCBwb2ludHMpIHtcbiAgICBmb3IoOyBlbmQgPiBzdGFydDsgZW5kLS0pe1xuICAgICAgICBjb25zdCBwb2ludCA9IHBvaW50c1tlbmRdO1xuICAgICAgICBpZiAoIWlzTmFOKHBvaW50LngpICYmICFpc05hTihwb2ludC55KSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGVuZDtcbn1cbmZ1bmN0aW9uIF9nZXRFZGdlKGEsIGIsIHByb3AsIGZuKSB7XG4gICAgaWYgKGEgJiYgYikge1xuICAgICAgICByZXR1cm4gZm4oYVtwcm9wXSwgYltwcm9wXSk7XG4gICAgfVxuICAgIHJldHVybiBhID8gYVtwcm9wXSA6IGIgPyBiW3Byb3BdIDogMDtcbn1cblxuZnVuY3Rpb24gX2NyZWF0ZUJvdW5kYXJ5TGluZShib3VuZGFyeSwgbGluZSkge1xuICAgIGxldCBwb2ludHMgPSBbXTtcbiAgICBsZXQgX2xvb3AgPSBmYWxzZTtcbiAgICBpZiAoaXNBcnJheShib3VuZGFyeSkpIHtcbiAgICAgICAgX2xvb3AgPSB0cnVlO1xuICAgICAgICBwb2ludHMgPSBib3VuZGFyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwb2ludHMgPSBfcG9pbnRzRnJvbVNlZ21lbnRzKGJvdW5kYXJ5LCBsaW5lKTtcbiAgICB9XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPyBuZXcgTGluZUVsZW1lbnQoe1xuICAgICAgICBwb2ludHMsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIHRlbnNpb246IDBcbiAgICAgICAgfSxcbiAgICAgICAgX2xvb3AsXG4gICAgICAgIF9mdWxsTG9vcDogX2xvb3BcbiAgICB9KSA6IG51bGw7XG59XG5mdW5jdGlvbiBfc2hvdWxkQXBwbHlGaWxsKHNvdXJjZSkge1xuICAgIHJldHVybiBzb3VyY2UgJiYgc291cmNlLmZpbGwgIT09IGZhbHNlO1xufVxuXG5mdW5jdGlvbiBfcmVzb2x2ZVRhcmdldChzb3VyY2VzLCBpbmRleCwgcHJvcGFnYXRlKSB7XG4gICAgY29uc3Qgc291cmNlID0gc291cmNlc1tpbmRleF07XG4gICAgbGV0IGZpbGwgPSBzb3VyY2UuZmlsbDtcbiAgICBjb25zdCB2aXNpdGVkID0gW1xuICAgICAgICBpbmRleFxuICAgIF07XG4gICAgbGV0IHRhcmdldDtcbiAgICBpZiAoIXByb3BhZ2F0ZSkge1xuICAgICAgICByZXR1cm4gZmlsbDtcbiAgICB9XG4gICAgd2hpbGUoZmlsbCAhPT0gZmFsc2UgJiYgdmlzaXRlZC5pbmRleE9mKGZpbGwpID09PSAtMSl7XG4gICAgICAgIGlmICghaXNOdW1iZXJGaW5pdGUoZmlsbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmaWxsO1xuICAgICAgICB9XG4gICAgICAgIHRhcmdldCA9IHNvdXJjZXNbZmlsbF07XG4gICAgICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRhcmdldC52aXNpYmxlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmlsbDtcbiAgICAgICAgfVxuICAgICAgICB2aXNpdGVkLnB1c2goZmlsbCk7XG4gICAgICAgIGZpbGwgPSB0YXJnZXQuZmlsbDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuIGZ1bmN0aW9uIF9kZWNvZGVGaWxsKGxpbmUsIGluZGV4LCBjb3VudCkge1xuICAgICBjb25zdCBmaWxsID0gcGFyc2VGaWxsT3B0aW9uKGxpbmUpO1xuICAgIGlmIChpc09iamVjdChmaWxsKSkge1xuICAgICAgICByZXR1cm4gaXNOYU4oZmlsbC52YWx1ZSkgPyBmYWxzZSA6IGZpbGw7XG4gICAgfVxuICAgIGxldCB0YXJnZXQgPSBwYXJzZUZsb2F0KGZpbGwpO1xuICAgIGlmIChpc051bWJlckZpbml0ZSh0YXJnZXQpICYmIE1hdGguZmxvb3IodGFyZ2V0KSA9PT0gdGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiBkZWNvZGVUYXJnZXRJbmRleChmaWxsWzBdLCBpbmRleCwgdGFyZ2V0LCBjb3VudCk7XG4gICAgfVxuICAgIHJldHVybiBbXG4gICAgICAgICdvcmlnaW4nLFxuICAgICAgICAnc3RhcnQnLFxuICAgICAgICAnZW5kJyxcbiAgICAgICAgJ3N0YWNrJyxcbiAgICAgICAgJ3NoYXBlJ1xuICAgIF0uaW5kZXhPZihmaWxsKSA+PSAwICYmIGZpbGw7XG59XG5mdW5jdGlvbiBkZWNvZGVUYXJnZXRJbmRleChmaXJzdENoLCBpbmRleCwgdGFyZ2V0LCBjb3VudCkge1xuICAgIGlmIChmaXJzdENoID09PSAnLScgfHwgZmlyc3RDaCA9PT0gJysnKSB7XG4gICAgICAgIHRhcmdldCA9IGluZGV4ICsgdGFyZ2V0O1xuICAgIH1cbiAgICBpZiAodGFyZ2V0ID09PSBpbmRleCB8fCB0YXJnZXQgPCAwIHx8IHRhcmdldCA+PSBjb3VudCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG59XG4gZnVuY3Rpb24gX2dldFRhcmdldFBpeGVsKGZpbGwsIHNjYWxlKSB7XG4gICAgbGV0IHBpeGVsID0gbnVsbDtcbiAgICBpZiAoZmlsbCA9PT0gJ3N0YXJ0Jykge1xuICAgICAgICBwaXhlbCA9IHNjYWxlLmJvdHRvbTtcbiAgICB9IGVsc2UgaWYgKGZpbGwgPT09ICdlbmQnKSB7XG4gICAgICAgIHBpeGVsID0gc2NhbGUudG9wO1xuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoZmlsbCkpIHtcbiAgICAgICAgcGl4ZWwgPSBzY2FsZS5nZXRQaXhlbEZvclZhbHVlKGZpbGwudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoc2NhbGUuZ2V0QmFzZVBpeGVsKSB7XG4gICAgICAgIHBpeGVsID0gc2NhbGUuZ2V0QmFzZVBpeGVsKCk7XG4gICAgfVxuICAgIHJldHVybiBwaXhlbDtcbn1cbiBmdW5jdGlvbiBfZ2V0VGFyZ2V0VmFsdWUoZmlsbCwgc2NhbGUsIHN0YXJ0VmFsdWUpIHtcbiAgICBsZXQgdmFsdWU7XG4gICAgaWYgKGZpbGwgPT09ICdzdGFydCcpIHtcbiAgICAgICAgdmFsdWUgPSBzdGFydFZhbHVlO1xuICAgIH0gZWxzZSBpZiAoZmlsbCA9PT0gJ2VuZCcpIHtcbiAgICAgICAgdmFsdWUgPSBzY2FsZS5vcHRpb25zLnJldmVyc2UgPyBzY2FsZS5taW4gOiBzY2FsZS5tYXg7XG4gICAgfSBlbHNlIGlmIChpc09iamVjdChmaWxsKSkge1xuICAgICAgICB2YWx1ZSA9IGZpbGwudmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWUgPSBzY2FsZS5nZXRCYXNlVmFsdWUoKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuIGZ1bmN0aW9uIHBhcnNlRmlsbE9wdGlvbihsaW5lKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IGxpbmUub3B0aW9ucztcbiAgICBjb25zdCBmaWxsT3B0aW9uID0gb3B0aW9ucy5maWxsO1xuICAgIGxldCBmaWxsID0gdmFsdWVPckRlZmF1bHQoZmlsbE9wdGlvbiAmJiBmaWxsT3B0aW9uLnRhcmdldCwgZmlsbE9wdGlvbik7XG4gICAgaWYgKGZpbGwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBmaWxsID0gISFvcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgICB9XG4gICAgaWYgKGZpbGwgPT09IGZhbHNlIHx8IGZpbGwgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoZmlsbCA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gJ29yaWdpbic7XG4gICAgfVxuICAgIHJldHVybiBmaWxsO1xufVxuXG5mdW5jdGlvbiBfYnVpbGRTdGFja0xpbmUoc291cmNlKSB7XG4gICAgY29uc3QgeyBzY2FsZSAsIGluZGV4ICwgbGluZSAgfSA9IHNvdXJjZTtcbiAgICBjb25zdCBwb2ludHMgPSBbXTtcbiAgICBjb25zdCBzZWdtZW50cyA9IGxpbmUuc2VnbWVudHM7XG4gICAgY29uc3Qgc291cmNlUG9pbnRzID0gbGluZS5wb2ludHM7XG4gICAgY29uc3QgbGluZXNCZWxvdyA9IGdldExpbmVzQmVsb3coc2NhbGUsIGluZGV4KTtcbiAgICBsaW5lc0JlbG93LnB1c2goX2NyZWF0ZUJvdW5kYXJ5TGluZSh7XG4gICAgICAgIHg6IG51bGwsXG4gICAgICAgIHk6IHNjYWxlLmJvdHRvbVxuICAgIH0sIGxpbmUpKTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspe1xuICAgICAgICBjb25zdCBzZWdtZW50ID0gc2VnbWVudHNbaV07XG4gICAgICAgIGZvcihsZXQgaiA9IHNlZ21lbnQuc3RhcnQ7IGogPD0gc2VnbWVudC5lbmQ7IGorKyl7XG4gICAgICAgICAgICBhZGRQb2ludHNCZWxvdyhwb2ludHMsIHNvdXJjZVBvaW50c1tqXSwgbGluZXNCZWxvdyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBMaW5lRWxlbWVudCh7XG4gICAgICAgIHBvaW50cyxcbiAgICAgICAgb3B0aW9uczoge31cbiAgICB9KTtcbn1cbiBmdW5jdGlvbiBnZXRMaW5lc0JlbG93KHNjYWxlLCBpbmRleCkge1xuICAgIGNvbnN0IGJlbG93ID0gW107XG4gICAgY29uc3QgbWV0YXMgPSBzY2FsZS5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygnbGluZScpO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBtZXRhcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IG1ldGEgPSBtZXRhc1tpXTtcbiAgICAgICAgaWYgKG1ldGEuaW5kZXggPT09IGluZGV4KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIW1ldGEuaGlkZGVuKSB7XG4gICAgICAgICAgICBiZWxvdy51bnNoaWZ0KG1ldGEuZGF0YXNldCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJlbG93O1xufVxuIGZ1bmN0aW9uIGFkZFBvaW50c0JlbG93KHBvaW50cywgc291cmNlUG9pbnQsIGxpbmVzQmVsb3cpIHtcbiAgICBjb25zdCBwb3N0cG9uZWQgPSBbXTtcbiAgICBmb3IobGV0IGogPSAwOyBqIDwgbGluZXNCZWxvdy5sZW5ndGg7IGorKyl7XG4gICAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc0JlbG93W2pdO1xuICAgICAgICBjb25zdCB7IGZpcnN0ICwgbGFzdCAsIHBvaW50ICB9ID0gZmluZFBvaW50KGxpbmUsIHNvdXJjZVBvaW50LCAneCcpO1xuICAgICAgICBpZiAoIXBvaW50IHx8IGZpcnN0ICYmIGxhc3QpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICAgICAgcG9zdHBvbmVkLnVuc2hpZnQocG9pbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9pbnRzLnB1c2gocG9pbnQpO1xuICAgICAgICAgICAgaWYgKCFsYXN0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcG9pbnRzLnB1c2goLi4ucG9zdHBvbmVkKTtcbn1cbiBmdW5jdGlvbiBmaW5kUG9pbnQobGluZSwgc291cmNlUG9pbnQsIHByb3BlcnR5KSB7XG4gICAgY29uc3QgcG9pbnQgPSBsaW5lLmludGVycG9sYXRlKHNvdXJjZVBvaW50LCBwcm9wZXJ0eSk7XG4gICAgaWYgKCFwb2ludCkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGNvbnN0IHBvaW50VmFsdWUgPSBwb2ludFtwcm9wZXJ0eV07XG4gICAgY29uc3Qgc2VnbWVudHMgPSBsaW5lLnNlZ21lbnRzO1xuICAgIGNvbnN0IGxpbmVQb2ludHMgPSBsaW5lLnBvaW50cztcbiAgICBsZXQgZmlyc3QgPSBmYWxzZTtcbiAgICBsZXQgbGFzdCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGNvbnN0IHNlZ21lbnQgPSBzZWdtZW50c1tpXTtcbiAgICAgICAgY29uc3QgZmlyc3RWYWx1ZSA9IGxpbmVQb2ludHNbc2VnbWVudC5zdGFydF1bcHJvcGVydHldO1xuICAgICAgICBjb25zdCBsYXN0VmFsdWUgPSBsaW5lUG9pbnRzW3NlZ21lbnQuZW5kXVtwcm9wZXJ0eV07XG4gICAgICAgIGlmIChfaXNCZXR3ZWVuKHBvaW50VmFsdWUsIGZpcnN0VmFsdWUsIGxhc3RWYWx1ZSkpIHtcbiAgICAgICAgICAgIGZpcnN0ID0gcG9pbnRWYWx1ZSA9PT0gZmlyc3RWYWx1ZTtcbiAgICAgICAgICAgIGxhc3QgPSBwb2ludFZhbHVlID09PSBsYXN0VmFsdWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBmaXJzdCxcbiAgICAgICAgbGFzdCxcbiAgICAgICAgcG9pbnRcbiAgICB9O1xufVxuXG5jbGFzcyBzaW1wbGVBcmMge1xuICAgIGNvbnN0cnVjdG9yKG9wdHMpe1xuICAgICAgICB0aGlzLnggPSBvcHRzLng7XG4gICAgICAgIHRoaXMueSA9IG9wdHMueTtcbiAgICAgICAgdGhpcy5yYWRpdXMgPSBvcHRzLnJhZGl1cztcbiAgICB9XG4gICAgcGF0aFNlZ21lbnQoY3R4LCBib3VuZHMsIG9wdHMpIHtcbiAgICAgICAgY29uc3QgeyB4ICwgeSAsIHJhZGl1cyAgfSA9IHRoaXM7XG4gICAgICAgIGJvdW5kcyA9IGJvdW5kcyB8fCB7XG4gICAgICAgICAgICBzdGFydDogMCxcbiAgICAgICAgICAgIGVuZDogVEFVXG4gICAgICAgIH07XG4gICAgICAgIGN0eC5hcmMoeCwgeSwgcmFkaXVzLCBib3VuZHMuZW5kLCBib3VuZHMuc3RhcnQsIHRydWUpO1xuICAgICAgICByZXR1cm4gIW9wdHMuYm91bmRzO1xuICAgIH1cbiAgICBpbnRlcnBvbGF0ZShwb2ludCkge1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgcmFkaXVzICB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgYW5nbGUgPSBwb2ludC5hbmdsZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IHggKyBNYXRoLmNvcyhhbmdsZSkgKiByYWRpdXMsXG4gICAgICAgICAgICB5OiB5ICsgTWF0aC5zaW4oYW5nbGUpICogcmFkaXVzLFxuICAgICAgICAgICAgYW5nbGVcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIF9nZXRUYXJnZXQoc291cmNlKSB7XG4gICAgY29uc3QgeyBjaGFydCAsIGZpbGwgLCBsaW5lICB9ID0gc291cmNlO1xuICAgIGlmIChpc051bWJlckZpbml0ZShmaWxsKSkge1xuICAgICAgICByZXR1cm4gZ2V0TGluZUJ5SW5kZXgoY2hhcnQsIGZpbGwpO1xuICAgIH1cbiAgICBpZiAoZmlsbCA9PT0gJ3N0YWNrJykge1xuICAgICAgICByZXR1cm4gX2J1aWxkU3RhY2tMaW5lKHNvdXJjZSk7XG4gICAgfVxuICAgIGlmIChmaWxsID09PSAnc2hhcGUnKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCBib3VuZGFyeSA9IGNvbXB1dGVCb3VuZGFyeShzb3VyY2UpO1xuICAgIGlmIChib3VuZGFyeSBpbnN0YW5jZW9mIHNpbXBsZUFyYykge1xuICAgICAgICByZXR1cm4gYm91bmRhcnk7XG4gICAgfVxuICAgIHJldHVybiBfY3JlYXRlQm91bmRhcnlMaW5lKGJvdW5kYXJ5LCBsaW5lKTtcbn1cbiBmdW5jdGlvbiBnZXRMaW5lQnlJbmRleChjaGFydCwgaW5kZXgpIHtcbiAgICBjb25zdCBtZXRhID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoaW5kZXgpO1xuICAgIGNvbnN0IHZpc2libGUgPSBtZXRhICYmIGNoYXJ0LmlzRGF0YXNldFZpc2libGUoaW5kZXgpO1xuICAgIHJldHVybiB2aXNpYmxlID8gbWV0YS5kYXRhc2V0IDogbnVsbDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVCb3VuZGFyeShzb3VyY2UpIHtcbiAgICBjb25zdCBzY2FsZSA9IHNvdXJjZS5zY2FsZSB8fCB7fTtcbiAgICBpZiAoc2NhbGUuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKSB7XG4gICAgICAgIHJldHVybiBjb21wdXRlQ2lyY3VsYXJCb3VuZGFyeShzb3VyY2UpO1xuICAgIH1cbiAgICByZXR1cm4gY29tcHV0ZUxpbmVhckJvdW5kYXJ5KHNvdXJjZSk7XG59XG5mdW5jdGlvbiBjb21wdXRlTGluZWFyQm91bmRhcnkoc291cmNlKSB7XG4gICAgY29uc3QgeyBzY2FsZSA9e30gLCBmaWxsICB9ID0gc291cmNlO1xuICAgIGNvbnN0IHBpeGVsID0gX2dldFRhcmdldFBpeGVsKGZpbGwsIHNjYWxlKTtcbiAgICBpZiAoaXNOdW1iZXJGaW5pdGUocGl4ZWwpKSB7XG4gICAgICAgIGNvbnN0IGhvcml6b250YWwgPSBzY2FsZS5pc0hvcml6b250YWwoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IGhvcml6b250YWwgPyBwaXhlbCA6IG51bGwsXG4gICAgICAgICAgICB5OiBob3Jpem9udGFsID8gbnVsbCA6IHBpeGVsXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gY29tcHV0ZUNpcmN1bGFyQm91bmRhcnkoc291cmNlKSB7XG4gICAgY29uc3QgeyBzY2FsZSAsIGZpbGwgIH0gPSBzb3VyY2U7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHNjYWxlLm9wdGlvbnM7XG4gICAgY29uc3QgbGVuZ3RoID0gc2NhbGUuZ2V0TGFiZWxzKCkubGVuZ3RoO1xuICAgIGNvbnN0IHN0YXJ0ID0gb3B0aW9ucy5yZXZlcnNlID8gc2NhbGUubWF4IDogc2NhbGUubWluO1xuICAgIGNvbnN0IHZhbHVlID0gX2dldFRhcmdldFZhbHVlKGZpbGwsIHNjYWxlLCBzdGFydCk7XG4gICAgY29uc3QgdGFyZ2V0ID0gW107XG4gICAgaWYgKG9wdGlvbnMuZ3JpZC5jaXJjdWxhcikge1xuICAgICAgICBjb25zdCBjZW50ZXIgPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUoMCwgc3RhcnQpO1xuICAgICAgICByZXR1cm4gbmV3IHNpbXBsZUFyYyh7XG4gICAgICAgICAgICB4OiBjZW50ZXIueCxcbiAgICAgICAgICAgIHk6IGNlbnRlci55LFxuICAgICAgICAgICAgcmFkaXVzOiBzY2FsZS5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh2YWx1ZSlcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSl7XG4gICAgICAgIHRhcmdldC5wdXNoKHNjYWxlLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZShpLCB2YWx1ZSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBfZHJhd2ZpbGwoY3R4LCBzb3VyY2UsIGFyZWEpIHtcbiAgICBjb25zdCB0YXJnZXQgPSBfZ2V0VGFyZ2V0KHNvdXJjZSk7XG4gICAgY29uc3QgeyBsaW5lICwgc2NhbGUgLCBheGlzICB9ID0gc291cmNlO1xuICAgIGNvbnN0IGxpbmVPcHRzID0gbGluZS5vcHRpb25zO1xuICAgIGNvbnN0IGZpbGxPcHRpb24gPSBsaW5lT3B0cy5maWxsO1xuICAgIGNvbnN0IGNvbG9yID0gbGluZU9wdHMuYmFja2dyb3VuZENvbG9yO1xuICAgIGNvbnN0IHsgYWJvdmUgPWNvbG9yICwgYmVsb3cgPWNvbG9yICB9ID0gZmlsbE9wdGlvbiB8fCB7fTtcbiAgICBpZiAodGFyZ2V0ICYmIGxpbmUucG9pbnRzLmxlbmd0aCkge1xuICAgICAgICBjbGlwQXJlYShjdHgsIGFyZWEpO1xuICAgICAgICBkb0ZpbGwoY3R4LCB7XG4gICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgYWJvdmUsXG4gICAgICAgICAgICBiZWxvdyxcbiAgICAgICAgICAgIGFyZWEsXG4gICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgIGF4aXNcbiAgICAgICAgfSk7XG4gICAgICAgIHVuY2xpcEFyZWEoY3R4KTtcbiAgICB9XG59XG5mdW5jdGlvbiBkb0ZpbGwoY3R4LCBjZmcpIHtcbiAgICBjb25zdCB7IGxpbmUgLCB0YXJnZXQgLCBhYm92ZSAsIGJlbG93ICwgYXJlYSAsIHNjYWxlICB9ID0gY2ZnO1xuICAgIGNvbnN0IHByb3BlcnR5ID0gbGluZS5fbG9vcCA/ICdhbmdsZScgOiBjZmcuYXhpcztcbiAgICBjdHguc2F2ZSgpO1xuICAgIGlmIChwcm9wZXJ0eSA9PT0gJ3gnICYmIGJlbG93ICE9PSBhYm92ZSkge1xuICAgICAgICBjbGlwVmVydGljYWwoY3R4LCB0YXJnZXQsIGFyZWEudG9wKTtcbiAgICAgICAgZmlsbChjdHgsIHtcbiAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICBjb2xvcjogYWJvdmUsXG4gICAgICAgICAgICBzY2FsZSxcbiAgICAgICAgICAgIHByb3BlcnR5XG4gICAgICAgIH0pO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICBjbGlwVmVydGljYWwoY3R4LCB0YXJnZXQsIGFyZWEuYm90dG9tKTtcbiAgICB9XG4gICAgZmlsbChjdHgsIHtcbiAgICAgICAgbGluZSxcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBjb2xvcjogYmVsb3csXG4gICAgICAgIHNjYWxlLFxuICAgICAgICBwcm9wZXJ0eVxuICAgIH0pO1xuICAgIGN0eC5yZXN0b3JlKCk7XG59XG5mdW5jdGlvbiBjbGlwVmVydGljYWwoY3R4LCB0YXJnZXQsIGNsaXBZKSB7XG4gICAgY29uc3QgeyBzZWdtZW50cyAsIHBvaW50cyAgfSA9IHRhcmdldDtcbiAgICBsZXQgZmlyc3QgPSB0cnVlO1xuICAgIGxldCBsaW5lTG9vcCA9IGZhbHNlO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpe1xuICAgICAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICB9ID0gc2VnbWVudDtcbiAgICAgICAgY29uc3QgZmlyc3RQb2ludCA9IHBvaW50c1tzdGFydF07XG4gICAgICAgIGNvbnN0IGxhc3RQb2ludCA9IHBvaW50c1tfZmluZFNlZ21lbnRFbmQoc3RhcnQsIGVuZCwgcG9pbnRzKV07XG4gICAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyhmaXJzdFBvaW50LngsIGZpcnN0UG9pbnQueSk7XG4gICAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhmaXJzdFBvaW50LngsIGNsaXBZKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oZmlyc3RQb2ludC54LCBmaXJzdFBvaW50LnkpO1xuICAgICAgICB9XG4gICAgICAgIGxpbmVMb29wID0gISF0YXJnZXQucGF0aFNlZ21lbnQoY3R4LCBzZWdtZW50LCB7XG4gICAgICAgICAgICBtb3ZlOiBsaW5lTG9vcFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGxpbmVMb29wKSB7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdHgubGluZVRvKGxhc3RQb2ludC54LCBjbGlwWSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY3R4LmxpbmVUbyh0YXJnZXQuZmlyc3QoKS54LCBjbGlwWSk7XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5jbGlwKCk7XG59XG5mdW5jdGlvbiBmaWxsKGN0eCwgY2ZnKSB7XG4gICAgY29uc3QgeyBsaW5lICwgdGFyZ2V0ICwgcHJvcGVydHkgLCBjb2xvciAsIHNjYWxlICB9ID0gY2ZnO1xuICAgIGNvbnN0IHNlZ21lbnRzID0gX3NlZ21lbnRzKGxpbmUsIHRhcmdldCwgcHJvcGVydHkpO1xuICAgIGZvciAoY29uc3QgeyBzb3VyY2U6IHNyYyAsIHRhcmdldDogdGd0ICwgc3RhcnQgLCBlbmQgIH0gb2Ygc2VnbWVudHMpe1xuICAgICAgICBjb25zdCB7IHN0eWxlOiB7IGJhY2tncm91bmRDb2xvciA9Y29sb3IgIH0gPSB7fSAgfSA9IHNyYztcbiAgICAgICAgY29uc3Qgbm90U2hhcGUgPSB0YXJnZXQgIT09IHRydWU7XG4gICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBiYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgIGNsaXBCb3VuZHMoY3R4LCBzY2FsZSwgbm90U2hhcGUgJiYgX2dldEJvdW5kcyhwcm9wZXJ0eSwgc3RhcnQsIGVuZCkpO1xuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGNvbnN0IGxpbmVMb29wID0gISFsaW5lLnBhdGhTZWdtZW50KGN0eCwgc3JjKTtcbiAgICAgICAgbGV0IGxvb3A7XG4gICAgICAgIGlmIChub3RTaGFwZSkge1xuICAgICAgICAgICAgaWYgKGxpbmVMb29wKSB7XG4gICAgICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnRlcnBvbGF0ZWRMaW5lVG8oY3R4LCB0YXJnZXQsIGVuZCwgcHJvcGVydHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0TG9vcCA9ICEhdGFyZ2V0LnBhdGhTZWdtZW50KGN0eCwgdGd0LCB7XG4gICAgICAgICAgICAgICAgbW92ZTogbGluZUxvb3AsXG4gICAgICAgICAgICAgICAgcmV2ZXJzZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBsb29wID0gbGluZUxvb3AgJiYgdGFyZ2V0TG9vcDtcbiAgICAgICAgICAgIGlmICghbG9vcCkge1xuICAgICAgICAgICAgICAgIGludGVycG9sYXRlZExpbmVUbyhjdHgsIHRhcmdldCwgc3RhcnQsIHByb3BlcnR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIGN0eC5maWxsKGxvb3AgPyAnZXZlbm9kZCcgOiAnbm9uemVybycpO1xuICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNsaXBCb3VuZHMoY3R4LCBzY2FsZSwgYm91bmRzKSB7XG4gICAgY29uc3QgeyB0b3AgLCBib3R0b20gIH0gPSBzY2FsZS5jaGFydC5jaGFydEFyZWE7XG4gICAgY29uc3QgeyBwcm9wZXJ0eSAsIHN0YXJ0ICwgZW5kICB9ID0gYm91bmRzIHx8IHt9O1xuICAgIGlmIChwcm9wZXJ0eSA9PT0gJ3gnKSB7XG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgY3R4LnJlY3Qoc3RhcnQsIHRvcCwgZW5kIC0gc3RhcnQsIGJvdHRvbSAtIHRvcCk7XG4gICAgICAgIGN0eC5jbGlwKCk7XG4gICAgfVxufVxuZnVuY3Rpb24gaW50ZXJwb2xhdGVkTGluZVRvKGN0eCwgdGFyZ2V0LCBwb2ludCwgcHJvcGVydHkpIHtcbiAgICBjb25zdCBpbnRlcnBvbGF0ZWRQb2ludCA9IHRhcmdldC5pbnRlcnBvbGF0ZShwb2ludCwgcHJvcGVydHkpO1xuICAgIGlmIChpbnRlcnBvbGF0ZWRQb2ludCkge1xuICAgICAgICBjdHgubGluZVRvKGludGVycG9sYXRlZFBvaW50LngsIGludGVycG9sYXRlZFBvaW50LnkpO1xuICAgIH1cbn1cblxudmFyIGluZGV4ID0ge1xuICAgIGlkOiAnZmlsbGVyJyxcbiAgICBhZnRlckRhdGFzZXRzVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgY291bnQgPSAoY2hhcnQuZGF0YS5kYXRhc2V0cyB8fCBbXSkubGVuZ3RoO1xuICAgICAgICBjb25zdCBzb3VyY2VzID0gW107XG4gICAgICAgIGxldCBtZXRhLCBpLCBsaW5lLCBzb3VyY2U7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyArK2kpe1xuICAgICAgICAgICAgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKGkpO1xuICAgICAgICAgICAgbGluZSA9IG1ldGEuZGF0YXNldDtcbiAgICAgICAgICAgIHNvdXJjZSA9IG51bGw7XG4gICAgICAgICAgICBpZiAobGluZSAmJiBsaW5lLm9wdGlvbnMgJiYgbGluZSBpbnN0YW5jZW9mIExpbmVFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgc291cmNlID0ge1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlOiBjaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpLFxuICAgICAgICAgICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogX2RlY29kZUZpbGwobGluZSwgaSwgY291bnQpLFxuICAgICAgICAgICAgICAgICAgICBjaGFydCxcbiAgICAgICAgICAgICAgICAgICAgYXhpczogbWV0YS5jb250cm9sbGVyLm9wdGlvbnMuaW5kZXhBeGlzLFxuICAgICAgICAgICAgICAgICAgICBzY2FsZTogbWV0YS52U2NhbGUsXG4gICAgICAgICAgICAgICAgICAgIGxpbmVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWV0YS4kZmlsbGVyID0gc291cmNlO1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7ICsraSl7XG4gICAgICAgICAgICBzb3VyY2UgPSBzb3VyY2VzW2ldO1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UgfHwgc291cmNlLmZpbGwgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzb3VyY2UuZmlsbCA9IF9yZXNvbHZlVGFyZ2V0KHNvdXJjZXMsIGksIG9wdGlvbnMucHJvcGFnYXRlKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmVmb3JlRHJhdyAoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGRyYXcgPSBvcHRpb25zLmRyYXdUaW1lID09PSAnYmVmb3JlRHJhdyc7XG4gICAgICAgIGNvbnN0IG1ldGFzZXRzID0gY2hhcnQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO1xuICAgICAgICBjb25zdCBhcmVhID0gY2hhcnQuY2hhcnRBcmVhO1xuICAgICAgICBmb3IobGV0IGkgPSBtZXRhc2V0cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSl7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2UgPSBtZXRhc2V0c1tpXS4kZmlsbGVyO1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNvdXJjZS5saW5lLnVwZGF0ZUNvbnRyb2xQb2ludHMoYXJlYSwgc291cmNlLmF4aXMpO1xuICAgICAgICAgICAgaWYgKGRyYXcgJiYgc291cmNlLmZpbGwpIHtcbiAgICAgICAgICAgICAgICBfZHJhd2ZpbGwoY2hhcnQuY3R4LCBzb3VyY2UsIGFyZWEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBiZWZvcmVEYXRhc2V0c0RyYXcgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucy5kcmF3VGltZSAhPT0gJ2JlZm9yZURhdGFzZXRzRHJhdycpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtZXRhc2V0cyA9IGNoYXJ0LmdldFNvcnRlZFZpc2libGVEYXRhc2V0TWV0YXMoKTtcbiAgICAgICAgZm9yKGxldCBpID0gbWV0YXNldHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpe1xuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gbWV0YXNldHNbaV0uJGZpbGxlcjtcbiAgICAgICAgICAgIGlmIChfc2hvdWxkQXBwbHlGaWxsKHNvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICBfZHJhd2ZpbGwoY2hhcnQuY3R4LCBzb3VyY2UsIGNoYXJ0LmNoYXJ0QXJlYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGJlZm9yZURhdGFzZXREcmF3IChjaGFydCwgYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBzb3VyY2UgPSBhcmdzLm1ldGEuJGZpbGxlcjtcbiAgICAgICAgaWYgKCFfc2hvdWxkQXBwbHlGaWxsKHNvdXJjZSkgfHwgb3B0aW9ucy5kcmF3VGltZSAhPT0gJ2JlZm9yZURhdGFzZXREcmF3Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIF9kcmF3ZmlsbChjaGFydC5jdHgsIHNvdXJjZSwgY2hhcnQuY2hhcnRBcmVhKTtcbiAgICB9LFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIHByb3BhZ2F0ZTogdHJ1ZSxcbiAgICAgICAgZHJhd1RpbWU6ICdiZWZvcmVEYXRhc2V0RHJhdydcbiAgICB9XG59O1xuXG5jb25zdCBnZXRCb3hTaXplID0gKGxhYmVsT3B0cywgZm9udFNpemUpPT57XG4gICAgbGV0IHsgYm94SGVpZ2h0ID1mb250U2l6ZSAsIGJveFdpZHRoID1mb250U2l6ZSAgfSA9IGxhYmVsT3B0cztcbiAgICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgYm94SGVpZ2h0ID0gTWF0aC5taW4oYm94SGVpZ2h0LCBmb250U2l6ZSk7XG4gICAgICAgIGJveFdpZHRoID0gbGFiZWxPcHRzLnBvaW50U3R5bGVXaWR0aCB8fCBNYXRoLm1pbihib3hXaWR0aCwgZm9udFNpemUpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBib3hXaWR0aCxcbiAgICAgICAgYm94SGVpZ2h0LFxuICAgICAgICBpdGVtSGVpZ2h0OiBNYXRoLm1heChmb250U2l6ZSwgYm94SGVpZ2h0KVxuICAgIH07XG59O1xuY29uc3QgaXRlbXNFcXVhbCA9IChhLCBiKT0+YSAhPT0gbnVsbCAmJiBiICE9PSBudWxsICYmIGEuZGF0YXNldEluZGV4ID09PSBiLmRhdGFzZXRJbmRleCAmJiBhLmluZGV4ID09PSBiLmluZGV4O1xuY2xhc3MgTGVnZW5kIGV4dGVuZHMgRWxlbWVudCB7XG4gY29uc3RydWN0b3IoY29uZmlnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5fYWRkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuIHRoaXMuX2hvdmVyZWRJdGVtID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3VnaG51dE1vZGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jaGFydCA9IGNvbmZpZy5jaGFydDtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gY29uZmlnLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuY3R4ID0gY29uZmlnLmN0eDtcbiAgICAgICAgdGhpcy5sZWdlbmRJdGVtcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jb2x1bW5TaXplcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5saW5lV2lkdGhzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm1heEhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5tYXhXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy50b3AgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYm90dG9tID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmxlZnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucmlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9tYXJnaW5zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5mdWxsU2l6ZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdXBkYXRlKG1heFdpZHRoLCBtYXhIZWlnaHQsIG1hcmdpbnMpIHtcbiAgICAgICAgdGhpcy5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgICAgICB0aGlzLm1heEhlaWdodCA9IG1heEhlaWdodDtcbiAgICAgICAgdGhpcy5fbWFyZ2lucyA9IG1hcmdpbnM7XG4gICAgICAgIHRoaXMuc2V0RGltZW5zaW9ucygpO1xuICAgICAgICB0aGlzLmJ1aWxkTGFiZWxzKCk7XG4gICAgICAgIHRoaXMuZml0KCk7XG4gICAgfVxuICAgIHNldERpbWVuc2lvbnMoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IHRoaXMuX21hcmdpbnMubGVmdDtcbiAgICAgICAgICAgIHRoaXMucmlnaHQgPSB0aGlzLndpZHRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLm1heEhlaWdodDtcbiAgICAgICAgICAgIHRoaXMudG9wID0gdGhpcy5fbWFyZ2lucy50b3A7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbSA9IHRoaXMuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuICAgIGJ1aWxkTGFiZWxzKCkge1xuICAgICAgICBjb25zdCBsYWJlbE9wdHMgPSB0aGlzLm9wdGlvbnMubGFiZWxzIHx8IHt9O1xuICAgICAgICBsZXQgbGVnZW5kSXRlbXMgPSBjYWxsYmFjayhsYWJlbE9wdHMuZ2VuZXJhdGVMYWJlbHMsIFtcbiAgICAgICAgICAgIHRoaXMuY2hhcnRcbiAgICAgICAgXSwgdGhpcykgfHwgW107XG4gICAgICAgIGlmIChsYWJlbE9wdHMuZmlsdGVyKSB7XG4gICAgICAgICAgICBsZWdlbmRJdGVtcyA9IGxlZ2VuZEl0ZW1zLmZpbHRlcigoaXRlbSk9PmxhYmVsT3B0cy5maWx0ZXIoaXRlbSwgdGhpcy5jaGFydC5kYXRhKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxhYmVsT3B0cy5zb3J0KSB7XG4gICAgICAgICAgICBsZWdlbmRJdGVtcyA9IGxlZ2VuZEl0ZW1zLnNvcnQoKGEsIGIpPT5sYWJlbE9wdHMuc29ydChhLCBiLCB0aGlzLmNoYXJ0LmRhdGEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJldmVyc2UpIHtcbiAgICAgICAgICAgIGxlZ2VuZEl0ZW1zLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxlZ2VuZEl0ZW1zID0gbGVnZW5kSXRlbXM7XG4gICAgfVxuICAgIGZpdCgpIHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zICwgY3R4ICB9ID0gdGhpcztcbiAgICAgICAgaWYgKCFvcHRpb25zLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB0aGlzLmhlaWdodCA9IDA7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGFiZWxPcHRzID0gb3B0aW9ucy5sYWJlbHM7XG4gICAgICAgIGNvbnN0IGxhYmVsRm9udCA9IHRvRm9udChsYWJlbE9wdHMuZm9udCk7XG4gICAgICAgIGNvbnN0IGZvbnRTaXplID0gbGFiZWxGb250LnNpemU7XG4gICAgICAgIGNvbnN0IHRpdGxlSGVpZ2h0ID0gdGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCk7XG4gICAgICAgIGNvbnN0IHsgYm94V2lkdGggLCBpdGVtSGVpZ2h0ICB9ID0gZ2V0Qm94U2l6ZShsYWJlbE9wdHMsIGZvbnRTaXplKTtcbiAgICAgICAgbGV0IHdpZHRoLCBoZWlnaHQ7XG4gICAgICAgIGN0eC5mb250ID0gbGFiZWxGb250LnN0cmluZztcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHdpZHRoID0gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuX2ZpdFJvd3ModGl0bGVIZWlnaHQsIGZvbnRTaXplLCBib3hXaWR0aCwgaXRlbUhlaWdodCkgKyAxMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMubWF4SGVpZ2h0O1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9maXRDb2xzKHRpdGxlSGVpZ2h0LCBsYWJlbEZvbnQsIGJveFdpZHRoLCBpdGVtSGVpZ2h0KSArIDEwO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud2lkdGggPSBNYXRoLm1pbih3aWR0aCwgb3B0aW9ucy5tYXhXaWR0aCB8fCB0aGlzLm1heFdpZHRoKTtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBNYXRoLm1pbihoZWlnaHQsIG9wdGlvbnMubWF4SGVpZ2h0IHx8IHRoaXMubWF4SGVpZ2h0KTtcbiAgICB9XG4gX2ZpdFJvd3ModGl0bGVIZWlnaHQsIGZvbnRTaXplLCBib3hXaWR0aCwgaXRlbUhlaWdodCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIG1heFdpZHRoICwgb3B0aW9uczogeyBsYWJlbHM6IHsgcGFkZGluZyAgfSAgfSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGhpdGJveGVzID0gdGhpcy5sZWdlbmRIaXRCb3hlcyA9IFtdO1xuICAgICAgICBjb25zdCBsaW5lV2lkdGhzID0gdGhpcy5saW5lV2lkdGhzID0gW1xuICAgICAgICAgICAgMFxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgICAgIGxldCB0b3RhbEhlaWdodCA9IHRpdGxlSGVpZ2h0O1xuICAgICAgICBjdHgudGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgIGxldCByb3cgPSAtMTtcbiAgICAgICAgbGV0IHRvcCA9IC1saW5lSGVpZ2h0O1xuICAgICAgICB0aGlzLmxlZ2VuZEl0ZW1zLmZvckVhY2goKGxlZ2VuZEl0ZW0sIGkpPT57XG4gICAgICAgICAgICBjb25zdCBpdGVtV2lkdGggPSBib3hXaWR0aCArIGZvbnRTaXplIC8gMiArIGN0eC5tZWFzdXJlVGV4dChsZWdlbmRJdGVtLnRleHQpLndpZHRoO1xuICAgICAgICAgICAgaWYgKGkgPT09IDAgfHwgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIDFdICsgaXRlbVdpZHRoICsgMiAqIHBhZGRpbmcgPiBtYXhXaWR0aCkge1xuICAgICAgICAgICAgICAgIHRvdGFsSGVpZ2h0ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIChpID4gMCA/IDAgOiAxKV0gPSAwO1xuICAgICAgICAgICAgICAgIHRvcCArPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgIHJvdysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGl0Ym94ZXNbaV0gPSB7XG4gICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICB0b3AsXG4gICAgICAgICAgICAgICAgcm93LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBpdGVtV2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpdGVtSGVpZ2h0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGluZVdpZHRoc1tsaW5lV2lkdGhzLmxlbmd0aCAtIDFdICs9IGl0ZW1XaWR0aCArIHBhZGRpbmc7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdG90YWxIZWlnaHQ7XG4gICAgfVxuICAgIF9maXRDb2xzKHRpdGxlSGVpZ2h0LCBsYWJlbEZvbnQsIGJveFdpZHRoLCBfaXRlbUhlaWdodCkge1xuICAgICAgICBjb25zdCB7IGN0eCAsIG1heEhlaWdodCAsIG9wdGlvbnM6IHsgbGFiZWxzOiB7IHBhZGRpbmcgIH0gIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBoaXRib3hlcyA9IHRoaXMubGVnZW5kSGl0Qm94ZXMgPSBbXTtcbiAgICAgICAgY29uc3QgY29sdW1uU2l6ZXMgPSB0aGlzLmNvbHVtblNpemVzID0gW107XG4gICAgICAgIGNvbnN0IGhlaWdodExpbWl0ID0gbWF4SGVpZ2h0IC0gdGl0bGVIZWlnaHQ7XG4gICAgICAgIGxldCB0b3RhbFdpZHRoID0gcGFkZGluZztcbiAgICAgICAgbGV0IGN1cnJlbnRDb2xXaWR0aCA9IDA7XG4gICAgICAgIGxldCBjdXJyZW50Q29sSGVpZ2h0ID0gMDtcbiAgICAgICAgbGV0IGxlZnQgPSAwO1xuICAgICAgICBsZXQgY29sID0gMDtcbiAgICAgICAgdGhpcy5sZWdlbmRJdGVtcy5mb3JFYWNoKChsZWdlbmRJdGVtLCBpKT0+e1xuICAgICAgICAgICAgY29uc3QgeyBpdGVtV2lkdGggLCBpdGVtSGVpZ2h0ICB9ID0gY2FsY3VsYXRlSXRlbVNpemUoYm94V2lkdGgsIGxhYmVsRm9udCwgY3R4LCBsZWdlbmRJdGVtLCBfaXRlbUhlaWdodCk7XG4gICAgICAgICAgICBpZiAoaSA+IDAgJiYgY3VycmVudENvbEhlaWdodCArIGl0ZW1IZWlnaHQgKyAyICogcGFkZGluZyA+IGhlaWdodExpbWl0KSB7XG4gICAgICAgICAgICAgICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGggKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogY3VycmVudENvbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGN1cnJlbnRDb2xIZWlnaHRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBsZWZ0ICs9IGN1cnJlbnRDb2xXaWR0aCArIHBhZGRpbmc7XG4gICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgY3VycmVudENvbFdpZHRoID0gY3VycmVudENvbEhlaWdodCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoaXRib3hlc1tpXSA9IHtcbiAgICAgICAgICAgICAgICBsZWZ0LFxuICAgICAgICAgICAgICAgIHRvcDogY3VycmVudENvbEhlaWdodCxcbiAgICAgICAgICAgICAgICBjb2wsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGl0ZW1XaWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGl0ZW1IZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjdXJyZW50Q29sV2lkdGggPSBNYXRoLm1heChjdXJyZW50Q29sV2lkdGgsIGl0ZW1XaWR0aCk7XG4gICAgICAgICAgICBjdXJyZW50Q29sSGVpZ2h0ICs9IGl0ZW1IZWlnaHQgKyBwYWRkaW5nO1xuICAgICAgICB9KTtcbiAgICAgICAgdG90YWxXaWR0aCArPSBjdXJyZW50Q29sV2lkdGg7XG4gICAgICAgIGNvbHVtblNpemVzLnB1c2goe1xuICAgICAgICAgICAgd2lkdGg6IGN1cnJlbnRDb2xXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogY3VycmVudENvbEhlaWdodFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRvdGFsV2lkdGg7XG4gICAgfVxuICAgIGFkanVzdEhpdEJveGVzKCkge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5kaXNwbGF5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGl0bGVIZWlnaHQgPSB0aGlzLl9jb21wdXRlVGl0bGVIZWlnaHQoKTtcbiAgICAgICAgY29uc3QgeyBsZWdlbmRIaXRCb3hlczogaGl0Ym94ZXMgLCBvcHRpb25zOiB7IGFsaWduICwgbGFiZWxzOiB7IHBhZGRpbmcgIH0gLCBydGwgIH0gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKHJ0bCwgdGhpcy5sZWZ0LCB0aGlzLndpZHRoKTtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIGxldCByb3cgPSAwO1xuICAgICAgICAgICAgbGV0IGxlZnQgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdGhpcy5sZWZ0ICsgcGFkZGluZywgdGhpcy5yaWdodCAtIHRoaXMubGluZVdpZHRoc1tyb3ddKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaGl0Ym94IG9mIGhpdGJveGVzKXtcbiAgICAgICAgICAgICAgICBpZiAocm93ICE9PSBoaXRib3gucm93KSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IGhpdGJveC5yb3c7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBfYWxpZ25TdGFydEVuZChhbGlnbiwgdGhpcy5sZWZ0ICsgcGFkZGluZywgdGhpcy5yaWdodCAtIHRoaXMubGluZVdpZHRoc1tyb3ddKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGl0Ym94LnRvcCArPSB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgICAgICAgICBoaXRib3gubGVmdCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bEhlbHBlci54KGxlZnQpLCBoaXRib3gud2lkdGgpO1xuICAgICAgICAgICAgICAgIGxlZnQgKz0gaGl0Ym94LndpZHRoICsgcGFkZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBjb2wgPSAwO1xuICAgICAgICAgICAgbGV0IHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSB0aGlzLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaGl0Ym94IG9mIGhpdGJveGVzKXtcbiAgICAgICAgICAgICAgICBpZiAoaGl0Ym94LmNvbCAhPT0gY29sKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbCA9IGhpdGJveC5jb2w7XG4gICAgICAgICAgICAgICAgICAgIHRvcCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSB0aGlzLmNvbHVtblNpemVzW2NvbF0uaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGl0Ym94LnRvcCA9IHRvcDtcbiAgICAgICAgICAgICAgICBoaXRib3gubGVmdCArPSB0aGlzLmxlZnQgKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGhpdGJveC5sZWZ0ID0gcnRsSGVscGVyLmxlZnRGb3JMdHIocnRsSGVscGVyLngoaGl0Ym94LmxlZnQpLCBoaXRib3gud2lkdGgpO1xuICAgICAgICAgICAgICAgIHRvcCArPSBoaXRib3guaGVpZ2h0ICsgcGFkZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpc0hvcml6b250YWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMucG9zaXRpb24gPT09ICd0b3AnIHx8IHRoaXMub3B0aW9ucy5wb3NpdGlvbiA9PT0gJ2JvdHRvbSc7XG4gICAgfVxuICAgIGRyYXcoKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGlzcGxheSkge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgICAgICBjbGlwQXJlYShjdHgsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5fZHJhdygpO1xuICAgICAgICAgICAgdW5jbGlwQXJlYShjdHgpO1xuICAgICAgICB9XG4gICAgfVxuIF9kcmF3KCkge1xuICAgICAgICBjb25zdCB7IG9wdGlvbnM6IG9wdHMgLCBjb2x1bW5TaXplcyAsIGxpbmVXaWR0aHMgLCBjdHggIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGFsaWduICwgbGFiZWxzOiBsYWJlbE9wdHMgIH0gPSBvcHRzO1xuICAgICAgICBjb25zdCBkZWZhdWx0Q29sb3IgPSBkZWZhdWx0cy5jb2xvcjtcbiAgICAgICAgY29uc3QgcnRsSGVscGVyID0gZ2V0UnRsQWRhcHRlcihvcHRzLnJ0bCwgdGhpcy5sZWZ0LCB0aGlzLndpZHRoKTtcbiAgICAgICAgY29uc3QgbGFiZWxGb250ID0gdG9Gb250KGxhYmVsT3B0cy5mb250KTtcbiAgICAgICAgY29uc3QgeyBwYWRkaW5nICB9ID0gbGFiZWxPcHRzO1xuICAgICAgICBjb25zdCBmb250U2l6ZSA9IGxhYmVsRm9udC5zaXplO1xuICAgICAgICBjb25zdCBoYWxmRm9udFNpemUgPSBmb250U2l6ZSAvIDI7XG4gICAgICAgIGxldCBjdXJzb3I7XG4gICAgICAgIHRoaXMuZHJhd1RpdGxlKCk7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKCdsZWZ0Jyk7XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IDAuNTtcbiAgICAgICAgY3R4LmZvbnQgPSBsYWJlbEZvbnQuc3RyaW5nO1xuICAgICAgICBjb25zdCB7IGJveFdpZHRoICwgYm94SGVpZ2h0ICwgaXRlbUhlaWdodCAgfSA9IGdldEJveFNpemUobGFiZWxPcHRzLCBmb250U2l6ZSk7XG4gICAgICAgIGNvbnN0IGRyYXdMZWdlbmRCb3ggPSBmdW5jdGlvbih4LCB5LCBsZWdlbmRJdGVtKSB7XG4gICAgICAgICAgICBpZiAoaXNOYU4oYm94V2lkdGgpIHx8IGJveFdpZHRoIDw9IDAgfHwgaXNOYU4oYm94SGVpZ2h0KSB8fCBib3hIZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZVdpZHRoLCAxKTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmZpbGxTdHlsZSwgZGVmYXVsdENvbG9yKTtcbiAgICAgICAgICAgIGN0eC5saW5lQ2FwID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lQ2FwLCAnYnV0dCcpO1xuICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gdmFsdWVPckRlZmF1bHQobGVnZW5kSXRlbS5saW5lRGFzaE9mZnNldCwgMCk7XG4gICAgICAgICAgICBjdHgubGluZUpvaW4gPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLmxpbmVKb2luLCAnbWl0ZXInKTtcbiAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSB2YWx1ZU9yRGVmYXVsdChsZWdlbmRJdGVtLnN0cm9rZVN0eWxlLCBkZWZhdWx0Q29sb3IpO1xuICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKHZhbHVlT3JEZWZhdWx0KGxlZ2VuZEl0ZW0ubGluZURhc2gsIFtdKSk7XG4gICAgICAgICAgICBpZiAobGFiZWxPcHRzLnVzZVBvaW50U3R5bGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkcmF3T3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3hIZWlnaHQgKiBNYXRoLlNRUlQyIC8gMixcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogbGVnZW5kSXRlbS5wb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgICAgICByb3RhdGlvbjogbGVnZW5kSXRlbS5yb3RhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgYm9yZGVyV2lkdGg6IGxpbmVXaWR0aFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY29uc3QgY2VudGVyWCA9IHJ0bEhlbHBlci54UGx1cyh4LCBib3hXaWR0aCAvIDIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlclkgPSB5ICsgaGFsZkZvbnRTaXplO1xuICAgICAgICAgICAgICAgIGRyYXdQb2ludExlZ2VuZChjdHgsIGRyYXdPcHRpb25zLCBjZW50ZXJYLCBjZW50ZXJZLCBsYWJlbE9wdHMucG9pbnRTdHlsZVdpZHRoICYmIGJveFdpZHRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeUJveFRvcCA9IHkgKyBNYXRoLm1heCgoZm9udFNpemUgLSBib3hIZWlnaHQpIC8gMiwgMCk7XG4gICAgICAgICAgICAgICAgY29uc3QgeEJveExlZnQgPSBydGxIZWxwZXIubGVmdEZvckx0cih4LCBib3hXaWR0aCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYm9yZGVyUmFkaXVzID0gdG9UUkJMQ29ybmVycyhsZWdlbmRJdGVtLmJvcmRlclJhZGl1cyk7XG4gICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QudmFsdWVzKGJvcmRlclJhZGl1cykuc29tZSgodik9PnYgIT09IDApKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHhCb3hMZWZ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogeUJveFRvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHc6IGJveFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgaDogYm94SGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3JkZXJSYWRpdXNcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4LnJlY3QoeEJveExlZnQsIHlCb3hUb3AsIGJveFdpZHRoLCBib3hIZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgICAgIGlmIChsaW5lV2lkdGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGZpbGxUZXh0ID0gZnVuY3Rpb24oeCwgeSwgbGVnZW5kSXRlbSkge1xuICAgICAgICAgICAgcmVuZGVyVGV4dChjdHgsIGxlZ2VuZEl0ZW0udGV4dCwgeCwgeSArIGl0ZW1IZWlnaHQgLyAyLCBsYWJlbEZvbnQsIHtcbiAgICAgICAgICAgICAgICBzdHJpa2V0aHJvdWdoOiBsZWdlbmRJdGVtLmhpZGRlbixcbiAgICAgICAgICAgICAgICB0ZXh0QWxpZ246IHJ0bEhlbHBlci50ZXh0QWxpZ24obGVnZW5kSXRlbS50ZXh0QWxpZ24pXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gdGhpcy5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgdGl0bGVIZWlnaHQgPSB0aGlzLl9jb21wdXRlVGl0bGVIZWlnaHQoKTtcbiAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY3Vyc29yID0ge1xuICAgICAgICAgICAgICAgIHg6IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLmxlZnQgKyBwYWRkaW5nLCB0aGlzLnJpZ2h0IC0gbGluZVdpZHRoc1swXSksXG4gICAgICAgICAgICAgICAgeTogdGhpcy50b3AgKyBwYWRkaW5nICsgdGl0bGVIZWlnaHQsXG4gICAgICAgICAgICAgICAgbGluZTogMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnNvciA9IHtcbiAgICAgICAgICAgICAgICB4OiB0aGlzLmxlZnQgKyBwYWRkaW5nLFxuICAgICAgICAgICAgICAgIHk6IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLnRvcCArIHRpdGxlSGVpZ2h0ICsgcGFkZGluZywgdGhpcy5ib3R0b20gLSBjb2x1bW5TaXplc1swXS5oZWlnaHQpLFxuICAgICAgICAgICAgICAgIGxpbmU6IDBcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uKHRoaXMuY3R4LCBvcHRzLnRleHREaXJlY3Rpb24pO1xuICAgICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gaXRlbUhlaWdodCArIHBhZGRpbmc7XG4gICAgICAgIHRoaXMubGVnZW5kSXRlbXMuZm9yRWFjaCgobGVnZW5kSXRlbSwgaSk9PntcbiAgICAgICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGxlZ2VuZEl0ZW0uZm9udENvbG9yO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGxlZ2VuZEl0ZW0uZm9udENvbG9yO1xuICAgICAgICAgICAgY29uc3QgdGV4dFdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KGxlZ2VuZEl0ZW0udGV4dCkud2lkdGg7XG4gICAgICAgICAgICBjb25zdCB0ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKGxlZ2VuZEl0ZW0udGV4dEFsaWduIHx8IChsZWdlbmRJdGVtLnRleHRBbGlnbiA9IGxhYmVsT3B0cy50ZXh0QWxpZ24pKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gYm94V2lkdGggKyBoYWxmRm9udFNpemUgKyB0ZXh0V2lkdGg7XG4gICAgICAgICAgICBsZXQgeCA9IGN1cnNvci54O1xuICAgICAgICAgICAgbGV0IHkgPSBjdXJzb3IueTtcbiAgICAgICAgICAgIHJ0bEhlbHBlci5zZXRXaWR0aCh0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA+IDAgJiYgeCArIHdpZHRoICsgcGFkZGluZyA+IHRoaXMucmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgeSA9IGN1cnNvci55ICs9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvci5saW5lKys7XG4gICAgICAgICAgICAgICAgICAgIHggPSBjdXJzb3IueCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0aGlzLmxlZnQgKyBwYWRkaW5nLCB0aGlzLnJpZ2h0IC0gbGluZVdpZHRoc1tjdXJzb3IubGluZV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaSA+IDAgJiYgeSArIGxpbmVIZWlnaHQgPiB0aGlzLmJvdHRvbSkge1xuICAgICAgICAgICAgICAgIHggPSBjdXJzb3IueCA9IHggKyBjb2x1bW5TaXplc1tjdXJzb3IubGluZV0ud2lkdGggKyBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIGN1cnNvci5saW5lKys7XG4gICAgICAgICAgICAgICAgeSA9IGN1cnNvci55ID0gX2FsaWduU3RhcnRFbmQoYWxpZ24sIHRoaXMudG9wICsgdGl0bGVIZWlnaHQgKyBwYWRkaW5nLCB0aGlzLmJvdHRvbSAtIGNvbHVtblNpemVzW2N1cnNvci5saW5lXS5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVhbFggPSBydGxIZWxwZXIueCh4KTtcbiAgICAgICAgICAgIGRyYXdMZWdlbmRCb3gocmVhbFgsIHksIGxlZ2VuZEl0ZW0pO1xuICAgICAgICAgICAgeCA9IF90ZXh0WCh0ZXh0QWxpZ24sIHggKyBib3hXaWR0aCArIGhhbGZGb250U2l6ZSwgaXNIb3Jpem9udGFsID8geCArIHdpZHRoIDogdGhpcy5yaWdodCwgb3B0cy5ydGwpO1xuICAgICAgICAgICAgZmlsbFRleHQocnRsSGVscGVyLngoeCksIHksIGxlZ2VuZEl0ZW0pO1xuICAgICAgICAgICAgaWYgKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGN1cnNvci54ICs9IHdpZHRoICsgcGFkZGluZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxlZ2VuZEl0ZW0udGV4dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmb250TGluZUhlaWdodCA9IGxhYmVsRm9udC5saW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGN1cnNvci55ICs9IGNhbGN1bGF0ZUxlZ2VuZEl0ZW1IZWlnaHQobGVnZW5kSXRlbSwgZm9udExpbmVIZWlnaHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdXJzb3IueSArPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmVzdG9yZVRleHREaXJlY3Rpb24odGhpcy5jdHgsIG9wdHMudGV4dERpcmVjdGlvbik7XG4gICAgfVxuIGRyYXdUaXRsZSgpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgdGl0bGVPcHRzID0gb3B0cy50aXRsZTtcbiAgICAgICAgY29uc3QgdGl0bGVGb250ID0gdG9Gb250KHRpdGxlT3B0cy5mb250KTtcbiAgICAgICAgY29uc3QgdGl0bGVQYWRkaW5nID0gdG9QYWRkaW5nKHRpdGxlT3B0cy5wYWRkaW5nKTtcbiAgICAgICAgaWYgKCF0aXRsZU9wdHMuZGlzcGxheSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJ0bEhlbHBlciA9IGdldFJ0bEFkYXB0ZXIob3B0cy5ydGwsIHRoaXMubGVmdCwgdGhpcy53aWR0aCk7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHRpdGxlT3B0cy5wb3NpdGlvbjtcbiAgICAgICAgY29uc3QgaGFsZkZvbnRTaXplID0gdGl0bGVGb250LnNpemUgLyAyO1xuICAgICAgICBjb25zdCB0b3BQYWRkaW5nUGx1c0hhbGZGb250U2l6ZSA9IHRpdGxlUGFkZGluZy50b3AgKyBoYWxmRm9udFNpemU7XG4gICAgICAgIGxldCB5O1xuICAgICAgICBsZXQgbGVmdCA9IHRoaXMubGVmdDtcbiAgICAgICAgbGV0IG1heFdpZHRoID0gdGhpcy53aWR0aDtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIG1heFdpZHRoID0gTWF0aC5tYXgoLi4udGhpcy5saW5lV2lkdGhzKTtcbiAgICAgICAgICAgIHkgPSB0aGlzLnRvcCArIHRvcFBhZGRpbmdQbHVzSGFsZkZvbnRTaXplO1xuICAgICAgICAgICAgbGVmdCA9IF9hbGlnblN0YXJ0RW5kKG9wdHMuYWxpZ24sIGxlZnQsIHRoaXMucmlnaHQgLSBtYXhXaWR0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBtYXhIZWlnaHQgPSB0aGlzLmNvbHVtblNpemVzLnJlZHVjZSgoYWNjLCBzaXplKT0+TWF0aC5tYXgoYWNjLCBzaXplLmhlaWdodCksIDApO1xuICAgICAgICAgICAgeSA9IHRvcFBhZGRpbmdQbHVzSGFsZkZvbnRTaXplICsgX2FsaWduU3RhcnRFbmQob3B0cy5hbGlnbiwgdGhpcy50b3AsIHRoaXMuYm90dG9tIC0gbWF4SGVpZ2h0IC0gb3B0cy5sYWJlbHMucGFkZGluZyAtIHRoaXMuX2NvbXB1dGVUaXRsZUhlaWdodCgpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB4ID0gX2FsaWduU3RhcnRFbmQocG9zaXRpb24sIGxlZnQsIGxlZnQgKyBtYXhXaWR0aCk7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKF90b0xlZnRSaWdodENlbnRlcihwb3NpdGlvbikpO1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSc7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IHRpdGxlT3B0cy5jb2xvcjtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IHRpdGxlT3B0cy5jb2xvcjtcbiAgICAgICAgY3R4LmZvbnQgPSB0aXRsZUZvbnQuc3RyaW5nO1xuICAgICAgICByZW5kZXJUZXh0KGN0eCwgdGl0bGVPcHRzLnRleHQsIHgsIHksIHRpdGxlRm9udCk7XG4gICAgfVxuIF9jb21wdXRlVGl0bGVIZWlnaHQoKSB7XG4gICAgICAgIGNvbnN0IHRpdGxlT3B0cyA9IHRoaXMub3B0aW9ucy50aXRsZTtcbiAgICAgICAgY29uc3QgdGl0bGVGb250ID0gdG9Gb250KHRpdGxlT3B0cy5mb250KTtcbiAgICAgICAgY29uc3QgdGl0bGVQYWRkaW5nID0gdG9QYWRkaW5nKHRpdGxlT3B0cy5wYWRkaW5nKTtcbiAgICAgICAgcmV0dXJuIHRpdGxlT3B0cy5kaXNwbGF5ID8gdGl0bGVGb250LmxpbmVIZWlnaHQgKyB0aXRsZVBhZGRpbmcuaGVpZ2h0IDogMDtcbiAgICB9XG4gX2dldExlZ2VuZEl0ZW1BdCh4LCB5KSB7XG4gICAgICAgIGxldCBpLCBoaXRCb3gsIGxoO1xuICAgICAgICBpZiAoX2lzQmV0d2Vlbih4LCB0aGlzLmxlZnQsIHRoaXMucmlnaHQpICYmIF9pc0JldHdlZW4oeSwgdGhpcy50b3AsIHRoaXMuYm90dG9tKSkge1xuICAgICAgICAgICAgbGggPSB0aGlzLmxlZ2VuZEhpdEJveGVzO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGgubGVuZ3RoOyArK2kpe1xuICAgICAgICAgICAgICAgIGhpdEJveCA9IGxoW2ldO1xuICAgICAgICAgICAgICAgIGlmIChfaXNCZXR3ZWVuKHgsIGhpdEJveC5sZWZ0LCBoaXRCb3gubGVmdCArIGhpdEJveC53aWR0aCkgJiYgX2lzQmV0d2Vlbih5LCBoaXRCb3gudG9wLCBoaXRCb3gudG9wICsgaGl0Qm94LmhlaWdodCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGVnZW5kSXRlbXNbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiBoYW5kbGVFdmVudChlKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmICghaXNMaXN0ZW5lZChlLnR5cGUsIG9wdHMpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaG92ZXJlZEl0ZW0gPSB0aGlzLl9nZXRMZWdlbmRJdGVtQXQoZS54LCBlLnkpO1xuICAgICAgICBpZiAoZS50eXBlID09PSAnbW91c2Vtb3ZlJyB8fCBlLnR5cGUgPT09ICdtb3VzZW91dCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzID0gdGhpcy5faG92ZXJlZEl0ZW07XG4gICAgICAgICAgICBjb25zdCBzYW1lSXRlbSA9IGl0ZW1zRXF1YWwocHJldmlvdXMsIGhvdmVyZWRJdGVtKTtcbiAgICAgICAgICAgIGlmIChwcmV2aW91cyAmJiAhc2FtZUl0ZW0pIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhvcHRzLm9uTGVhdmUsIFtcbiAgICAgICAgICAgICAgICAgICAgZSxcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXMsXG4gICAgICAgICAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgICAgICBdLCB0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2hvdmVyZWRJdGVtID0gaG92ZXJlZEl0ZW07XG4gICAgICAgICAgICBpZiAoaG92ZXJlZEl0ZW0gJiYgIXNhbWVJdGVtKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sob3B0cy5vbkhvdmVyLCBbXG4gICAgICAgICAgICAgICAgICAgIGUsXG4gICAgICAgICAgICAgICAgICAgIGhvdmVyZWRJdGVtLFxuICAgICAgICAgICAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaG92ZXJlZEl0ZW0pIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG9wdHMub25DbGljaywgW1xuICAgICAgICAgICAgICAgIGUsXG4gICAgICAgICAgICAgICAgaG92ZXJlZEl0ZW0sXG4gICAgICAgICAgICAgICAgdGhpc1xuICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBjYWxjdWxhdGVJdGVtU2l6ZShib3hXaWR0aCwgbGFiZWxGb250LCBjdHgsIGxlZ2VuZEl0ZW0sIF9pdGVtSGVpZ2h0KSB7XG4gICAgY29uc3QgaXRlbVdpZHRoID0gY2FsY3VsYXRlSXRlbVdpZHRoKGxlZ2VuZEl0ZW0sIGJveFdpZHRoLCBsYWJlbEZvbnQsIGN0eCk7XG4gICAgY29uc3QgaXRlbUhlaWdodCA9IGNhbGN1bGF0ZUl0ZW1IZWlnaHQoX2l0ZW1IZWlnaHQsIGxlZ2VuZEl0ZW0sIGxhYmVsRm9udC5saW5lSGVpZ2h0KTtcbiAgICByZXR1cm4ge1xuICAgICAgICBpdGVtV2lkdGgsXG4gICAgICAgIGl0ZW1IZWlnaHRcbiAgICB9O1xufVxuZnVuY3Rpb24gY2FsY3VsYXRlSXRlbVdpZHRoKGxlZ2VuZEl0ZW0sIGJveFdpZHRoLCBsYWJlbEZvbnQsIGN0eCkge1xuICAgIGxldCBsZWdlbmRJdGVtVGV4dCA9IGxlZ2VuZEl0ZW0udGV4dDtcbiAgICBpZiAobGVnZW5kSXRlbVRleHQgJiYgdHlwZW9mIGxlZ2VuZEl0ZW1UZXh0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICBsZWdlbmRJdGVtVGV4dCA9IGxlZ2VuZEl0ZW1UZXh0LnJlZHVjZSgoYSwgYik9PmEubGVuZ3RoID4gYi5sZW5ndGggPyBhIDogYik7XG4gICAgfVxuICAgIHJldHVybiBib3hXaWR0aCArIGxhYmVsRm9udC5zaXplIC8gMiArIGN0eC5tZWFzdXJlVGV4dChsZWdlbmRJdGVtVGV4dCkud2lkdGg7XG59XG5mdW5jdGlvbiBjYWxjdWxhdGVJdGVtSGVpZ2h0KF9pdGVtSGVpZ2h0LCBsZWdlbmRJdGVtLCBmb250TGluZUhlaWdodCkge1xuICAgIGxldCBpdGVtSGVpZ2h0ID0gX2l0ZW1IZWlnaHQ7XG4gICAgaWYgKHR5cGVvZiBsZWdlbmRJdGVtLnRleHQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGl0ZW1IZWlnaHQgPSBjYWxjdWxhdGVMZWdlbmRJdGVtSGVpZ2h0KGxlZ2VuZEl0ZW0sIGZvbnRMaW5lSGVpZ2h0KTtcbiAgICB9XG4gICAgcmV0dXJuIGl0ZW1IZWlnaHQ7XG59XG5mdW5jdGlvbiBjYWxjdWxhdGVMZWdlbmRJdGVtSGVpZ2h0KGxlZ2VuZEl0ZW0sIGZvbnRMaW5lSGVpZ2h0KSB7XG4gICAgY29uc3QgbGFiZWxIZWlnaHQgPSBsZWdlbmRJdGVtLnRleHQgPyBsZWdlbmRJdGVtLnRleHQubGVuZ3RoICsgMC41IDogMDtcbiAgICByZXR1cm4gZm9udExpbmVIZWlnaHQgKiBsYWJlbEhlaWdodDtcbn1cbmZ1bmN0aW9uIGlzTGlzdGVuZWQodHlwZSwgb3B0cykge1xuICAgIGlmICgodHlwZSA9PT0gJ21vdXNlbW92ZScgfHwgdHlwZSA9PT0gJ21vdXNlb3V0JykgJiYgKG9wdHMub25Ib3ZlciB8fCBvcHRzLm9uTGVhdmUpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAob3B0cy5vbkNsaWNrICYmICh0eXBlID09PSAnY2xpY2snIHx8IHR5cGUgPT09ICdtb3VzZXVwJykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbnZhciBwbHVnaW5fbGVnZW5kID0ge1xuICAgIGlkOiAnbGVnZW5kJyxcbiBfZWxlbWVudDogTGVnZW5kLFxuICAgIHN0YXJ0IChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbGVnZW5kID0gY2hhcnQubGVnZW5kID0gbmV3IExlZ2VuZCh7XG4gICAgICAgICAgICBjdHg6IGNoYXJ0LmN0eCxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICBjaGFydFxuICAgICAgICB9KTtcbiAgICAgICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIGxlZ2VuZCwgb3B0aW9ucyk7XG4gICAgICAgIGxheW91dHMuYWRkQm94KGNoYXJ0LCBsZWdlbmQpO1xuICAgIH0sXG4gICAgc3RvcCAoY2hhcnQpIHtcbiAgICAgICAgbGF5b3V0cy5yZW1vdmVCb3goY2hhcnQsIGNoYXJ0LmxlZ2VuZCk7XG4gICAgICAgIGRlbGV0ZSBjaGFydC5sZWdlbmQ7XG4gICAgfSxcbiAgICBiZWZvcmVVcGRhdGUgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBsZWdlbmQgPSBjaGFydC5sZWdlbmQ7XG4gICAgICAgIGxheW91dHMuY29uZmlndXJlKGNoYXJ0LCBsZWdlbmQsIG9wdGlvbnMpO1xuICAgICAgICBsZWdlbmQub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfSxcbiAgICBhZnRlclVwZGF0ZSAoY2hhcnQpIHtcbiAgICAgICAgY29uc3QgbGVnZW5kID0gY2hhcnQubGVnZW5kO1xuICAgICAgICBsZWdlbmQuYnVpbGRMYWJlbHMoKTtcbiAgICAgICAgbGVnZW5kLmFkanVzdEhpdEJveGVzKCk7XG4gICAgfSxcbiAgICBhZnRlckV2ZW50IChjaGFydCwgYXJncykge1xuICAgICAgICBpZiAoIWFyZ3MucmVwbGF5KSB7XG4gICAgICAgICAgICBjaGFydC5sZWdlbmQuaGFuZGxlRXZlbnQoYXJncy5ldmVudCk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgIHBvc2l0aW9uOiAndG9wJyxcbiAgICAgICAgYWxpZ246ICdjZW50ZXInLFxuICAgICAgICBmdWxsU2l6ZTogdHJ1ZSxcbiAgICAgICAgcmV2ZXJzZTogZmFsc2UsXG4gICAgICAgIHdlaWdodDogMTAwMCxcbiAgICAgICAgb25DbGljayAoZSwgbGVnZW5kSXRlbSwgbGVnZW5kKSB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IGxlZ2VuZEl0ZW0uZGF0YXNldEluZGV4O1xuICAgICAgICAgICAgY29uc3QgY2kgPSBsZWdlbmQuY2hhcnQ7XG4gICAgICAgICAgICBpZiAoY2kuaXNEYXRhc2V0VmlzaWJsZShpbmRleCkpIHtcbiAgICAgICAgICAgICAgICBjaS5oaWRlKGluZGV4KTtcbiAgICAgICAgICAgICAgICBsZWdlbmRJdGVtLmhpZGRlbiA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNpLnNob3coaW5kZXgpO1xuICAgICAgICAgICAgICAgIGxlZ2VuZEl0ZW0uaGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG9uSG92ZXI6IG51bGwsXG4gICAgICAgIG9uTGVhdmU6IG51bGwsXG4gICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgY29sb3I6IChjdHgpPT5jdHguY2hhcnQub3B0aW9ucy5jb2xvcixcbiAgICAgICAgICAgIGJveFdpZHRoOiA0MCxcbiAgICAgICAgICAgIHBhZGRpbmc6IDEwLFxuICAgICAgICAgICAgZ2VuZXJhdGVMYWJlbHMgKGNoYXJ0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YXNldHMgPSBjaGFydC5kYXRhLmRhdGFzZXRzO1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgbGFiZWxzOiB7IHVzZVBvaW50U3R5bGUgLCBwb2ludFN0eWxlICwgdGV4dEFsaWduICwgY29sb3IgLCB1c2VCb3JkZXJSYWRpdXMgLCBib3JkZXJSYWRpdXMgIH0gIH0gPSBjaGFydC5sZWdlbmQub3B0aW9ucztcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hhcnQuX2dldFNvcnRlZERhdGFzZXRNZXRhcygpLm1hcCgobWV0YSk9PntcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUodXNlUG9pbnRTdHlsZSA/IDAgOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRvUGFkZGluZyhzdHlsZS5ib3JkZXJXaWR0aCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBkYXRhc2V0c1ttZXRhLmluZGV4XS5sYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxTdHlsZTogc3R5bGUuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiBjb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpZGRlbjogIW1ldGEudmlzaWJsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVDYXA6IHN0eWxlLmJvcmRlckNhcFN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZURhc2g6IHN0eWxlLmJvcmRlckRhc2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lRGFzaE9mZnNldDogc3R5bGUuYm9yZGVyRGFzaE9mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVKb2luOiBzdHlsZS5ib3JkZXJKb2luU3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lV2lkdGg6IChib3JkZXJXaWR0aC53aWR0aCArIGJvcmRlcldpZHRoLmhlaWdodCkgLyA0LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlU3R5bGU6IHN0eWxlLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogcG9pbnRTdHlsZSB8fCBzdHlsZS5wb2ludFN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb246IHN0eWxlLnJvdGF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dEFsaWduOiB0ZXh0QWxpZ24gfHwgc3R5bGUudGV4dEFsaWduLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9yZGVyUmFkaXVzOiB1c2VCb3JkZXJSYWRpdXMgJiYgKGJvcmRlclJhZGl1cyB8fCBzdHlsZS5ib3JkZXJSYWRpdXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldEluZGV4OiBtZXRhLmluZGV4XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlOiB7XG4gICAgICAgICAgICBjb2xvcjogKGN0eCk9PmN0eC5jaGFydC5vcHRpb25zLmNvbG9yLFxuICAgICAgICAgICAgZGlzcGxheTogZmFsc2UsXG4gICAgICAgICAgICBwb3NpdGlvbjogJ2NlbnRlcicsXG4gICAgICAgICAgICB0ZXh0OiAnJ1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkZXNjcmlwdG9yczoge1xuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT4hbmFtZS5zdGFydHNXaXRoKCdvbicpLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgIF9zY3JpcHRhYmxlOiAobmFtZSk9PiFbXG4gICAgICAgICAgICAgICAgICAgICdnZW5lcmF0ZUxhYmVscycsXG4gICAgICAgICAgICAgICAgICAgICdmaWx0ZXInLFxuICAgICAgICAgICAgICAgICAgICAnc29ydCdcbiAgICAgICAgICAgICAgICBdLmluY2x1ZGVzKG5hbWUpXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5jbGFzcyBUaXRsZSBleHRlbmRzIEVsZW1lbnQge1xuIGNvbnN0cnVjdG9yKGNvbmZpZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuY2hhcnQgPSBjb25maWcuY2hhcnQ7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IGNvbmZpZy5vcHRpb25zO1xuICAgICAgICB0aGlzLmN0eCA9IGNvbmZpZy5jdHg7XG4gICAgICAgIHRoaXMuX3BhZGRpbmcgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMudG9wID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmJvdHRvbSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5sZWZ0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnJpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndpZHRoID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy53ZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuZnVsbFNpemUgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHVwZGF0ZShtYXhXaWR0aCwgbWF4SGVpZ2h0KSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIHRoaXMubGVmdCA9IDA7XG4gICAgICAgIHRoaXMudG9wID0gMDtcbiAgICAgICAgaWYgKCFvcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB0aGlzLmhlaWdodCA9IHRoaXMucmlnaHQgPSB0aGlzLmJvdHRvbSA9IDA7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMucmlnaHQgPSBtYXhXaWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLmJvdHRvbSA9IG1heEhlaWdodDtcbiAgICAgICAgY29uc3QgbGluZUNvdW50ID0gaXNBcnJheShvcHRzLnRleHQpID8gb3B0cy50ZXh0Lmxlbmd0aCA6IDE7XG4gICAgICAgIHRoaXMuX3BhZGRpbmcgPSB0b1BhZGRpbmcob3B0cy5wYWRkaW5nKTtcbiAgICAgICAgY29uc3QgdGV4dFNpemUgPSBsaW5lQ291bnQgKiB0b0ZvbnQob3B0cy5mb250KS5saW5lSGVpZ2h0ICsgdGhpcy5fcGFkZGluZy5oZWlnaHQ7XG4gICAgICAgIGlmICh0aGlzLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0aGlzLmhlaWdodCA9IHRleHRTaXplO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRleHRTaXplO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlzSG9yaXpvbnRhbCgpIHtcbiAgICAgICAgY29uc3QgcG9zID0gdGhpcy5vcHRpb25zLnBvc2l0aW9uO1xuICAgICAgICByZXR1cm4gcG9zID09PSAndG9wJyB8fCBwb3MgPT09ICdib3R0b20nO1xuICAgIH1cbiAgICBfZHJhd0FyZ3Mob2Zmc2V0KSB7XG4gICAgICAgIGNvbnN0IHsgdG9wICwgbGVmdCAsIGJvdHRvbSAsIHJpZ2h0ICwgb3B0aW9ucyAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGFsaWduID0gb3B0aW9ucy5hbGlnbjtcbiAgICAgICAgbGV0IHJvdGF0aW9uID0gMDtcbiAgICAgICAgbGV0IG1heFdpZHRoLCB0aXRsZVgsIHRpdGxlWTtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHRpdGxlWCA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBsZWZ0LCByaWdodCk7XG4gICAgICAgICAgICB0aXRsZVkgPSB0b3AgKyBvZmZzZXQ7XG4gICAgICAgICAgICBtYXhXaWR0aCA9IHJpZ2h0IC0gbGVmdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICB0aXRsZVggPSBsZWZ0ICsgb2Zmc2V0O1xuICAgICAgICAgICAgICAgIHRpdGxlWSA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCBib3R0b20sIHRvcCk7XG4gICAgICAgICAgICAgICAgcm90YXRpb24gPSBQSSAqIC0wLjU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpdGxlWCA9IHJpZ2h0IC0gb2Zmc2V0O1xuICAgICAgICAgICAgICAgIHRpdGxlWSA9IF9hbGlnblN0YXJ0RW5kKGFsaWduLCB0b3AsIGJvdHRvbSk7XG4gICAgICAgICAgICAgICAgcm90YXRpb24gPSBQSSAqIDAuNTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1heFdpZHRoID0gYm90dG9tIC0gdG9wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0aXRsZVgsXG4gICAgICAgICAgICB0aXRsZVksXG4gICAgICAgICAgICBtYXhXaWR0aCxcbiAgICAgICAgICAgIHJvdGF0aW9uXG4gICAgICAgIH07XG4gICAgfVxuICAgIGRyYXcoKSB7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAoIW9wdHMuZGlzcGxheSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZvbnRPcHRzID0gdG9Gb250KG9wdHMuZm9udCk7XG4gICAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSBmb250T3B0cy5saW5lSGVpZ2h0O1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBsaW5lSGVpZ2h0IC8gMiArIHRoaXMuX3BhZGRpbmcudG9wO1xuICAgICAgICBjb25zdCB7IHRpdGxlWCAsIHRpdGxlWSAsIG1heFdpZHRoICwgcm90YXRpb24gIH0gPSB0aGlzLl9kcmF3QXJncyhvZmZzZXQpO1xuICAgICAgICByZW5kZXJUZXh0KGN0eCwgb3B0cy50ZXh0LCAwLCAwLCBmb250T3B0cywge1xuICAgICAgICAgICAgY29sb3I6IG9wdHMuY29sb3IsXG4gICAgICAgICAgICBtYXhXaWR0aCxcbiAgICAgICAgICAgIHJvdGF0aW9uLFxuICAgICAgICAgICAgdGV4dEFsaWduOiBfdG9MZWZ0UmlnaHRDZW50ZXIob3B0cy5hbGlnbiksXG4gICAgICAgICAgICB0ZXh0QmFzZWxpbmU6ICdtaWRkbGUnLFxuICAgICAgICAgICAgdHJhbnNsYXRpb246IFtcbiAgICAgICAgICAgICAgICB0aXRsZVgsXG4gICAgICAgICAgICAgICAgdGl0bGVZXG4gICAgICAgICAgICBdXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNyZWF0ZVRpdGxlKGNoYXJ0LCB0aXRsZU9wdHMpIHtcbiAgICBjb25zdCB0aXRsZSA9IG5ldyBUaXRsZSh7XG4gICAgICAgIGN0eDogY2hhcnQuY3R4LFxuICAgICAgICBvcHRpb25zOiB0aXRsZU9wdHMsXG4gICAgICAgIGNoYXJ0XG4gICAgfSk7XG4gICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIHRpdGxlLCB0aXRsZU9wdHMpO1xuICAgIGxheW91dHMuYWRkQm94KGNoYXJ0LCB0aXRsZSk7XG4gICAgY2hhcnQudGl0bGVCbG9jayA9IHRpdGxlO1xufVxudmFyIHBsdWdpbl90aXRsZSA9IHtcbiAgICBpZDogJ3RpdGxlJyxcbiBfZWxlbWVudDogVGl0bGUsXG4gICAgc3RhcnQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBjcmVhdGVUaXRsZShjaGFydCwgb3B0aW9ucyk7XG4gICAgfSxcbiAgICBzdG9wIChjaGFydCkge1xuICAgICAgICBjb25zdCB0aXRsZUJsb2NrID0gY2hhcnQudGl0bGVCbG9jaztcbiAgICAgICAgbGF5b3V0cy5yZW1vdmVCb3goY2hhcnQsIHRpdGxlQmxvY2spO1xuICAgICAgICBkZWxldGUgY2hhcnQudGl0bGVCbG9jaztcbiAgICB9LFxuICAgIGJlZm9yZVVwZGF0ZSAoY2hhcnQsIF9hcmdzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHRpdGxlID0gY2hhcnQudGl0bGVCbG9jaztcbiAgICAgICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIHRpdGxlLCBvcHRpb25zKTtcbiAgICAgICAgdGl0bGUub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgICAgIGRpc3BsYXk6IGZhbHNlLFxuICAgICAgICBmb250OiB7XG4gICAgICAgICAgICB3ZWlnaHQ6ICdib2xkJ1xuICAgICAgICB9LFxuICAgICAgICBmdWxsU2l6ZTogdHJ1ZSxcbiAgICAgICAgcGFkZGluZzogMTAsXG4gICAgICAgIHBvc2l0aW9uOiAndG9wJyxcbiAgICAgICAgdGV4dDogJycsXG4gICAgICAgIHdlaWdodDogMjAwMFxuICAgIH0sXG4gICAgZGVmYXVsdFJvdXRlczoge1xuICAgICAgICBjb2xvcjogJ2NvbG9yJ1xuICAgIH0sXG4gICAgZGVzY3JpcHRvcnM6IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IHRydWUsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlXG4gICAgfVxufTtcblxuY29uc3QgbWFwID0gbmV3IFdlYWtNYXAoKTtcbnZhciBwbHVnaW5fc3VidGl0bGUgPSB7XG4gICAgaWQ6ICdzdWJ0aXRsZScsXG4gICAgc3RhcnQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB0aXRsZSA9IG5ldyBUaXRsZSh7XG4gICAgICAgICAgICBjdHg6IGNoYXJ0LmN0eCxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICBjaGFydFxuICAgICAgICB9KTtcbiAgICAgICAgbGF5b3V0cy5jb25maWd1cmUoY2hhcnQsIHRpdGxlLCBvcHRpb25zKTtcbiAgICAgICAgbGF5b3V0cy5hZGRCb3goY2hhcnQsIHRpdGxlKTtcbiAgICAgICAgbWFwLnNldChjaGFydCwgdGl0bGUpO1xuICAgIH0sXG4gICAgc3RvcCAoY2hhcnQpIHtcbiAgICAgICAgbGF5b3V0cy5yZW1vdmVCb3goY2hhcnQsIG1hcC5nZXQoY2hhcnQpKTtcbiAgICAgICAgbWFwLmRlbGV0ZShjaGFydCk7XG4gICAgfSxcbiAgICBiZWZvcmVVcGRhdGUgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB0aXRsZSA9IG1hcC5nZXQoY2hhcnQpO1xuICAgICAgICBsYXlvdXRzLmNvbmZpZ3VyZShjaGFydCwgdGl0bGUsIG9wdGlvbnMpO1xuICAgICAgICB0aXRsZS5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9LFxuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIGFsaWduOiAnY2VudGVyJyxcbiAgICAgICAgZGlzcGxheTogZmFsc2UsXG4gICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgIHdlaWdodDogJ25vcm1hbCdcbiAgICAgICAgfSxcbiAgICAgICAgZnVsbFNpemU6IHRydWUsXG4gICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgIHBvc2l0aW9uOiAndG9wJyxcbiAgICAgICAgdGV4dDogJycsXG4gICAgICAgIHdlaWdodDogMTUwMFxuICAgIH0sXG4gICAgZGVmYXVsdFJvdXRlczoge1xuICAgICAgICBjb2xvcjogJ2NvbG9yJ1xuICAgIH0sXG4gICAgZGVzY3JpcHRvcnM6IHtcbiAgICAgICAgX3NjcmlwdGFibGU6IHRydWUsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlXG4gICAgfVxufTtcblxuY29uc3QgcG9zaXRpb25lcnMgPSB7XG4gYXZlcmFnZSAoaXRlbXMpIHtcbiAgICAgICAgaWYgKCFpdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaSwgbGVuO1xuICAgICAgICBsZXQgeCA9IDA7XG4gICAgICAgIGxldCB5ID0gMDtcbiAgICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgICAgZm9yKGkgPSAwLCBsZW4gPSBpdGVtcy5sZW5ndGg7IGkgPCBsZW47ICsraSl7XG4gICAgICAgICAgICBjb25zdCBlbCA9IGl0ZW1zW2ldLmVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZWwgJiYgZWwuaGFzVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvcyA9IGVsLnRvb2x0aXBQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHggKz0gcG9zLng7XG4gICAgICAgICAgICAgICAgeSArPSBwb3MueTtcbiAgICAgICAgICAgICAgICArK2NvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiB4IC8gY291bnQsXG4gICAgICAgICAgICB5OiB5IC8gY291bnRcbiAgICAgICAgfTtcbiAgICB9LFxuIG5lYXJlc3QgKGl0ZW1zLCBldmVudFBvc2l0aW9uKSB7XG4gICAgICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHggPSBldmVudFBvc2l0aW9uLng7XG4gICAgICAgIGxldCB5ID0gZXZlbnRQb3NpdGlvbi55O1xuICAgICAgICBsZXQgbWluRGlzdGFuY2UgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgICAgIGxldCBpLCBsZW4sIG5lYXJlc3RFbGVtZW50O1xuICAgICAgICBmb3IoaSA9IDAsIGxlbiA9IGl0ZW1zLmxlbmd0aDsgaSA8IGxlbjsgKytpKXtcbiAgICAgICAgICAgIGNvbnN0IGVsID0gaXRlbXNbaV0uZWxlbWVudDtcbiAgICAgICAgICAgIGlmIChlbCAmJiBlbC5oYXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2VudGVyID0gZWwuZ2V0Q2VudGVyUG9pbnQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkID0gZGlzdGFuY2VCZXR3ZWVuUG9pbnRzKGV2ZW50UG9zaXRpb24sIGNlbnRlcik7XG4gICAgICAgICAgICAgICAgaWYgKGQgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSA9IGQ7XG4gICAgICAgICAgICAgICAgICAgIG5lYXJlc3RFbGVtZW50ID0gZWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZWFyZXN0RWxlbWVudCkge1xuICAgICAgICAgICAgY29uc3QgdHAgPSBuZWFyZXN0RWxlbWVudC50b29sdGlwUG9zaXRpb24oKTtcbiAgICAgICAgICAgIHggPSB0cC54O1xuICAgICAgICAgICAgeSA9IHRwLnk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5XG4gICAgICAgIH07XG4gICAgfVxufTtcbmZ1bmN0aW9uIHB1c2hPckNvbmNhdChiYXNlLCB0b1B1c2gpIHtcbiAgICBpZiAodG9QdXNoKSB7XG4gICAgICAgIGlmIChpc0FycmF5KHRvUHVzaCkpIHtcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGJhc2UsIHRvUHVzaCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiYXNlLnB1c2godG9QdXNoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmFzZTtcbn1cbiBmdW5jdGlvbiBzcGxpdE5ld2xpbmVzKHN0cikge1xuICAgIGlmICgodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgfHwgc3RyIGluc3RhbmNlb2YgU3RyaW5nKSAmJiBzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICByZXR1cm4gc3RyLnNwbGl0KCdcXG4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cjtcbn1cbiBmdW5jdGlvbiBjcmVhdGVUb29sdGlwSXRlbShjaGFydCwgaXRlbSkge1xuICAgIGNvbnN0IHsgZWxlbWVudCAsIGRhdGFzZXRJbmRleCAsIGluZGV4ICB9ID0gaXRlbTtcbiAgICBjb25zdCBjb250cm9sbGVyID0gY2hhcnQuZ2V0RGF0YXNldE1ldGEoZGF0YXNldEluZGV4KS5jb250cm9sbGVyO1xuICAgIGNvbnN0IHsgbGFiZWwgLCB2YWx1ZSAgfSA9IGNvbnRyb2xsZXIuZ2V0TGFiZWxBbmRWYWx1ZShpbmRleCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY2hhcnQsXG4gICAgICAgIGxhYmVsLFxuICAgICAgICBwYXJzZWQ6IGNvbnRyb2xsZXIuZ2V0UGFyc2VkKGluZGV4KSxcbiAgICAgICAgcmF3OiBjaGFydC5kYXRhLmRhdGFzZXRzW2RhdGFzZXRJbmRleF0uZGF0YVtpbmRleF0sXG4gICAgICAgIGZvcm1hdHRlZFZhbHVlOiB2YWx1ZSxcbiAgICAgICAgZGF0YXNldDogY29udHJvbGxlci5nZXREYXRhc2V0KCksXG4gICAgICAgIGRhdGFJbmRleDogaW5kZXgsXG4gICAgICAgIGRhdGFzZXRJbmRleCxcbiAgICAgICAgZWxlbWVudFxuICAgIH07XG59XG4gZnVuY3Rpb24gZ2V0VG9vbHRpcFNpemUodG9vbHRpcCwgb3B0aW9ucykge1xuICAgIGNvbnN0IGN0eCA9IHRvb2x0aXAuY2hhcnQuY3R4O1xuICAgIGNvbnN0IHsgYm9keSAsIGZvb3RlciAsIHRpdGxlICB9ID0gdG9vbHRpcDtcbiAgICBjb25zdCB7IGJveFdpZHRoICwgYm94SGVpZ2h0ICB9ID0gb3B0aW9ucztcbiAgICBjb25zdCBib2R5Rm9udCA9IHRvRm9udChvcHRpb25zLmJvZHlGb250KTtcbiAgICBjb25zdCB0aXRsZUZvbnQgPSB0b0ZvbnQob3B0aW9ucy50aXRsZUZvbnQpO1xuICAgIGNvbnN0IGZvb3RlckZvbnQgPSB0b0ZvbnQob3B0aW9ucy5mb290ZXJGb250KTtcbiAgICBjb25zdCB0aXRsZUxpbmVDb3VudCA9IHRpdGxlLmxlbmd0aDtcbiAgICBjb25zdCBmb290ZXJMaW5lQ291bnQgPSBmb290ZXIubGVuZ3RoO1xuICAgIGNvbnN0IGJvZHlMaW5lSXRlbUNvdW50ID0gYm9keS5sZW5ndGg7XG4gICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICAgIGxldCBoZWlnaHQgPSBwYWRkaW5nLmhlaWdodDtcbiAgICBsZXQgd2lkdGggPSAwO1xuICAgIGxldCBjb21iaW5lZEJvZHlMZW5ndGggPSBib2R5LnJlZHVjZSgoY291bnQsIGJvZHlJdGVtKT0+Y291bnQgKyBib2R5SXRlbS5iZWZvcmUubGVuZ3RoICsgYm9keUl0ZW0ubGluZXMubGVuZ3RoICsgYm9keUl0ZW0uYWZ0ZXIubGVuZ3RoLCAwKTtcbiAgICBjb21iaW5lZEJvZHlMZW5ndGggKz0gdG9vbHRpcC5iZWZvcmVCb2R5Lmxlbmd0aCArIHRvb2x0aXAuYWZ0ZXJCb2R5Lmxlbmd0aDtcbiAgICBpZiAodGl0bGVMaW5lQ291bnQpIHtcbiAgICAgICAgaGVpZ2h0ICs9IHRpdGxlTGluZUNvdW50ICogdGl0bGVGb250LmxpbmVIZWlnaHQgKyAodGl0bGVMaW5lQ291bnQgLSAxKSAqIG9wdGlvbnMudGl0bGVTcGFjaW5nICsgb3B0aW9ucy50aXRsZU1hcmdpbkJvdHRvbTtcbiAgICB9XG4gICAgaWYgKGNvbWJpbmVkQm9keUxlbmd0aCkge1xuICAgICAgICBjb25zdCBib2R5TGluZUhlaWdodCA9IG9wdGlvbnMuZGlzcGxheUNvbG9ycyA/IE1hdGgubWF4KGJveEhlaWdodCwgYm9keUZvbnQubGluZUhlaWdodCkgOiBib2R5Rm9udC5saW5lSGVpZ2h0O1xuICAgICAgICBoZWlnaHQgKz0gYm9keUxpbmVJdGVtQ291bnQgKiBib2R5TGluZUhlaWdodCArIChjb21iaW5lZEJvZHlMZW5ndGggLSBib2R5TGluZUl0ZW1Db3VudCkgKiBib2R5Rm9udC5saW5lSGVpZ2h0ICsgKGNvbWJpbmVkQm9keUxlbmd0aCAtIDEpICogb3B0aW9ucy5ib2R5U3BhY2luZztcbiAgICB9XG4gICAgaWYgKGZvb3RlckxpbmVDb3VudCkge1xuICAgICAgICBoZWlnaHQgKz0gb3B0aW9ucy5mb290ZXJNYXJnaW5Ub3AgKyBmb290ZXJMaW5lQ291bnQgKiBmb290ZXJGb250LmxpbmVIZWlnaHQgKyAoZm9vdGVyTGluZUNvdW50IC0gMSkgKiBvcHRpb25zLmZvb3RlclNwYWNpbmc7XG4gICAgfVxuICAgIGxldCB3aWR0aFBhZGRpbmcgPSAwO1xuICAgIGNvbnN0IG1heExpbmVXaWR0aCA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3R4Lm1lYXN1cmVUZXh0KGxpbmUpLndpZHRoICsgd2lkdGhQYWRkaW5nKTtcbiAgICB9O1xuICAgIGN0eC5zYXZlKCk7XG4gICAgY3R4LmZvbnQgPSB0aXRsZUZvbnQuc3RyaW5nO1xuICAgIGVhY2godG9vbHRpcC50aXRsZSwgbWF4TGluZVdpZHRoKTtcbiAgICBjdHguZm9udCA9IGJvZHlGb250LnN0cmluZztcbiAgICBlYWNoKHRvb2x0aXAuYmVmb3JlQm9keS5jb25jYXQodG9vbHRpcC5hZnRlckJvZHkpLCBtYXhMaW5lV2lkdGgpO1xuICAgIHdpZHRoUGFkZGluZyA9IG9wdGlvbnMuZGlzcGxheUNvbG9ycyA/IGJveFdpZHRoICsgMiArIG9wdGlvbnMuYm94UGFkZGluZyA6IDA7XG4gICAgZWFjaChib2R5LCAoYm9keUl0ZW0pPT57XG4gICAgICAgIGVhY2goYm9keUl0ZW0uYmVmb3JlLCBtYXhMaW5lV2lkdGgpO1xuICAgICAgICBlYWNoKGJvZHlJdGVtLmxpbmVzLCBtYXhMaW5lV2lkdGgpO1xuICAgICAgICBlYWNoKGJvZHlJdGVtLmFmdGVyLCBtYXhMaW5lV2lkdGgpO1xuICAgIH0pO1xuICAgIHdpZHRoUGFkZGluZyA9IDA7XG4gICAgY3R4LmZvbnQgPSBmb290ZXJGb250LnN0cmluZztcbiAgICBlYWNoKHRvb2x0aXAuZm9vdGVyLCBtYXhMaW5lV2lkdGgpO1xuICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgd2lkdGggKz0gcGFkZGluZy53aWR0aDtcbiAgICByZXR1cm4ge1xuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGRldGVybWluZVlBbGlnbihjaGFydCwgc2l6ZSkge1xuICAgIGNvbnN0IHsgeSAsIGhlaWdodCAgfSA9IHNpemU7XG4gICAgaWYgKHkgPCBoZWlnaHQgLyAyKSB7XG4gICAgICAgIHJldHVybiAndG9wJztcbiAgICB9IGVsc2UgaWYgKHkgPiBjaGFydC5oZWlnaHQgLSBoZWlnaHQgLyAyKSB7XG4gICAgICAgIHJldHVybiAnYm90dG9tJztcbiAgICB9XG4gICAgcmV0dXJuICdjZW50ZXInO1xufVxuZnVuY3Rpb24gZG9lc05vdEZpdFdpdGhBbGlnbih4QWxpZ24sIGNoYXJ0LCBvcHRpb25zLCBzaXplKSB7XG4gICAgY29uc3QgeyB4ICwgd2lkdGggIH0gPSBzaXplO1xuICAgIGNvbnN0IGNhcmV0ID0gb3B0aW9ucy5jYXJldFNpemUgKyBvcHRpb25zLmNhcmV0UGFkZGluZztcbiAgICBpZiAoeEFsaWduID09PSAnbGVmdCcgJiYgeCArIHdpZHRoICsgY2FyZXQgPiBjaGFydC53aWR0aCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHhBbGlnbiA9PT0gJ3JpZ2h0JyAmJiB4IC0gd2lkdGggLSBjYXJldCA8IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuZnVuY3Rpb24gZGV0ZXJtaW5lWEFsaWduKGNoYXJ0LCBvcHRpb25zLCBzaXplLCB5QWxpZ24pIHtcbiAgICBjb25zdCB7IHggLCB3aWR0aCAgfSA9IHNpemU7XG4gICAgY29uc3QgeyB3aWR0aDogY2hhcnRXaWR0aCAsIGNoYXJ0QXJlYTogeyBsZWZ0ICwgcmlnaHQgIH0gIH0gPSBjaGFydDtcbiAgICBsZXQgeEFsaWduID0gJ2NlbnRlcic7XG4gICAgaWYgKHlBbGlnbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgeEFsaWduID0geCA8PSAobGVmdCArIHJpZ2h0KSAvIDIgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIH0gZWxzZSBpZiAoeCA8PSB3aWR0aCAvIDIpIHtcbiAgICAgICAgeEFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSBpZiAoeCA+PSBjaGFydFdpZHRoIC0gd2lkdGggLyAyKSB7XG4gICAgICAgIHhBbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuICAgIGlmIChkb2VzTm90Rml0V2l0aEFsaWduKHhBbGlnbiwgY2hhcnQsIG9wdGlvbnMsIHNpemUpKSB7XG4gICAgICAgIHhBbGlnbiA9ICdjZW50ZXInO1xuICAgIH1cbiAgICByZXR1cm4geEFsaWduO1xufVxuIGZ1bmN0aW9uIGRldGVybWluZUFsaWdubWVudChjaGFydCwgb3B0aW9ucywgc2l6ZSkge1xuICAgIGNvbnN0IHlBbGlnbiA9IHNpemUueUFsaWduIHx8IG9wdGlvbnMueUFsaWduIHx8IGRldGVybWluZVlBbGlnbihjaGFydCwgc2l6ZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeEFsaWduOiBzaXplLnhBbGlnbiB8fCBvcHRpb25zLnhBbGlnbiB8fCBkZXRlcm1pbmVYQWxpZ24oY2hhcnQsIG9wdGlvbnMsIHNpemUsIHlBbGlnbiksXG4gICAgICAgIHlBbGlnblxuICAgIH07XG59XG5mdW5jdGlvbiBhbGlnblgoc2l6ZSwgeEFsaWduKSB7XG4gICAgbGV0IHsgeCAsIHdpZHRoICB9ID0gc2l6ZTtcbiAgICBpZiAoeEFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgIHggLT0gd2lkdGg7XG4gICAgfSBlbHNlIGlmICh4QWxpZ24gPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHggLT0gd2lkdGggLyAyO1xuICAgIH1cbiAgICByZXR1cm4geDtcbn1cbmZ1bmN0aW9uIGFsaWduWShzaXplLCB5QWxpZ24sIHBhZGRpbmdBbmRTaXplKSB7XG4gICAgbGV0IHsgeSAsIGhlaWdodCAgfSA9IHNpemU7XG4gICAgaWYgKHlBbGlnbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgeSArPSBwYWRkaW5nQW5kU2l6ZTtcbiAgICB9IGVsc2UgaWYgKHlBbGlnbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgeSAtPSBoZWlnaHQgKyBwYWRkaW5nQW5kU2l6ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB5IC09IGhlaWdodCAvIDI7XG4gICAgfVxuICAgIHJldHVybiB5O1xufVxuIGZ1bmN0aW9uIGdldEJhY2tncm91bmRQb2ludChvcHRpb25zLCBzaXplLCBhbGlnbm1lbnQsIGNoYXJ0KSB7XG4gICAgY29uc3QgeyBjYXJldFNpemUgLCBjYXJldFBhZGRpbmcgLCBjb3JuZXJSYWRpdXMgIH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IHsgeEFsaWduICwgeUFsaWduICB9ID0gYWxpZ25tZW50O1xuICAgIGNvbnN0IHBhZGRpbmdBbmRTaXplID0gY2FyZXRTaXplICsgY2FyZXRQYWRkaW5nO1xuICAgIGNvbnN0IHsgdG9wTGVmdCAsIHRvcFJpZ2h0ICwgYm90dG9tTGVmdCAsIGJvdHRvbVJpZ2h0ICB9ID0gdG9UUkJMQ29ybmVycyhjb3JuZXJSYWRpdXMpO1xuICAgIGxldCB4ID0gYWxpZ25YKHNpemUsIHhBbGlnbik7XG4gICAgY29uc3QgeSA9IGFsaWduWShzaXplLCB5QWxpZ24sIHBhZGRpbmdBbmRTaXplKTtcbiAgICBpZiAoeUFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICBpZiAoeEFsaWduID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIHggKz0gcGFkZGluZ0FuZFNpemU7XG4gICAgICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICB4IC09IHBhZGRpbmdBbmRTaXplO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmICh4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICB4IC09IE1hdGgubWF4KHRvcExlZnQsIGJvdHRvbUxlZnQpICsgY2FyZXRTaXplO1xuICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgIHggKz0gTWF0aC5tYXgodG9wUmlnaHQsIGJvdHRvbVJpZ2h0KSArIGNhcmV0U2l6ZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogX2xpbWl0VmFsdWUoeCwgMCwgY2hhcnQud2lkdGggLSBzaXplLndpZHRoKSxcbiAgICAgICAgeTogX2xpbWl0VmFsdWUoeSwgMCwgY2hhcnQuaGVpZ2h0IC0gc2l6ZS5oZWlnaHQpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldEFsaWduZWRYKHRvb2x0aXAsIGFsaWduLCBvcHRpb25zKSB7XG4gICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICAgIHJldHVybiBhbGlnbiA9PT0gJ2NlbnRlcicgPyB0b29sdGlwLnggKyB0b29sdGlwLndpZHRoIC8gMiA6IGFsaWduID09PSAncmlnaHQnID8gdG9vbHRpcC54ICsgdG9vbHRpcC53aWR0aCAtIHBhZGRpbmcucmlnaHQgOiB0b29sdGlwLnggKyBwYWRkaW5nLmxlZnQ7XG59XG4gZnVuY3Rpb24gZ2V0QmVmb3JlQWZ0ZXJCb2R5TGluZXMoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gcHVzaE9yQ29uY2F0KFtdLCBzcGxpdE5ld2xpbmVzKGNhbGxiYWNrKSk7XG59XG5mdW5jdGlvbiBjcmVhdGVUb29sdGlwQ29udGV4dChwYXJlbnQsIHRvb2x0aXAsIHRvb2x0aXBJdGVtcykge1xuICAgIHJldHVybiBjcmVhdGVDb250ZXh0KHBhcmVudCwge1xuICAgICAgICB0b29sdGlwLFxuICAgICAgICB0b29sdGlwSXRlbXMsXG4gICAgICAgIHR5cGU6ICd0b29sdGlwJ1xuICAgIH0pO1xufVxuZnVuY3Rpb24gb3ZlcnJpZGVDYWxsYmFja3MoY2FsbGJhY2tzLCBjb250ZXh0KSB7XG4gICAgY29uc3Qgb3ZlcnJpZGUgPSBjb250ZXh0ICYmIGNvbnRleHQuZGF0YXNldCAmJiBjb250ZXh0LmRhdGFzZXQudG9vbHRpcCAmJiBjb250ZXh0LmRhdGFzZXQudG9vbHRpcC5jYWxsYmFja3M7XG4gICAgcmV0dXJuIG92ZXJyaWRlID8gY2FsbGJhY2tzLm92ZXJyaWRlKG92ZXJyaWRlKSA6IGNhbGxiYWNrcztcbn1cbmNvbnN0IGRlZmF1bHRDYWxsYmFja3MgPSB7XG4gICAgYmVmb3JlVGl0bGU6IG5vb3AsXG4gICAgdGl0bGUgKHRvb2x0aXBJdGVtcykge1xuICAgICAgICBpZiAodG9vbHRpcEl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSB0b29sdGlwSXRlbXNbMF07XG4gICAgICAgICAgICBjb25zdCBsYWJlbHMgPSBpdGVtLmNoYXJ0LmRhdGEubGFiZWxzO1xuICAgICAgICAgICAgY29uc3QgbGFiZWxDb3VudCA9IGxhYmVscyA/IGxhYmVscy5sZW5ndGggOiAwO1xuICAgICAgICAgICAgaWYgKHRoaXMgJiYgdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5tb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXRlbS5kYXRhc2V0LmxhYmVsIHx8ICcnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpdGVtLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0ubGFiZWw7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhYmVsQ291bnQgPiAwICYmIGl0ZW0uZGF0YUluZGV4IDwgbGFiZWxDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJlbHNbaXRlbS5kYXRhSW5kZXhdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9LFxuICAgIGFmdGVyVGl0bGU6IG5vb3AsXG4gICAgYmVmb3JlQm9keTogbm9vcCxcbiAgICBiZWZvcmVMYWJlbDogbm9vcCxcbiAgICBsYWJlbCAodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgaWYgKHRoaXMgJiYgdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5tb2RlID09PSAnZGF0YXNldCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0b29sdGlwSXRlbS5sYWJlbCArICc6ICcgKyB0b29sdGlwSXRlbS5mb3JtYXR0ZWRWYWx1ZSB8fCB0b29sdGlwSXRlbS5mb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbGFiZWwgPSB0b29sdGlwSXRlbS5kYXRhc2V0LmxhYmVsIHx8ICcnO1xuICAgICAgICBpZiAobGFiZWwpIHtcbiAgICAgICAgICAgIGxhYmVsICs9ICc6ICc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdmFsdWUgPSB0b29sdGlwSXRlbS5mb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmKHZhbHVlKSkge1xuICAgICAgICAgICAgbGFiZWwgKz0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxhYmVsO1xuICAgIH0sXG4gICAgbGFiZWxDb2xvciAodG9vbHRpcEl0ZW0pIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRvb2x0aXBJdGVtLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRvb2x0aXBJdGVtLmRhdGFzZXRJbmRleCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBtZXRhLmNvbnRyb2xsZXIuZ2V0U3R5bGUodG9vbHRpcEl0ZW0uZGF0YUluZGV4KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJvcmRlckNvbG9yOiBvcHRpb25zLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBvcHRpb25zLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgIGJvcmRlcldpZHRoOiBvcHRpb25zLmJvcmRlcldpZHRoLFxuICAgICAgICAgICAgYm9yZGVyRGFzaDogb3B0aW9ucy5ib3JkZXJEYXNoLFxuICAgICAgICAgICAgYm9yZGVyRGFzaE9mZnNldDogb3B0aW9ucy5ib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgICAgICAgYm9yZGVyUmFkaXVzOiAwXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBsYWJlbFRleHRDb2xvciAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMuYm9keUNvbG9yO1xuICAgIH0sXG4gICAgbGFiZWxQb2ludFN0eWxlICh0b29sdGlwSXRlbSkge1xuICAgICAgICBjb25zdCBtZXRhID0gdG9vbHRpcEl0ZW0uY2hhcnQuZ2V0RGF0YXNldE1ldGEodG9vbHRpcEl0ZW0uZGF0YXNldEluZGV4KTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IG1ldGEuY29udHJvbGxlci5nZXRTdHlsZSh0b29sdGlwSXRlbS5kYXRhSW5kZXgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcG9pbnRTdHlsZTogb3B0aW9ucy5wb2ludFN0eWxlLFxuICAgICAgICAgICAgcm90YXRpb246IG9wdGlvbnMucm90YXRpb25cbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGFmdGVyTGFiZWw6IG5vb3AsXG4gICAgYWZ0ZXJCb2R5OiBub29wLFxuICAgIGJlZm9yZUZvb3Rlcjogbm9vcCxcbiAgICBmb290ZXI6IG5vb3AsXG4gICAgYWZ0ZXJGb290ZXI6IG5vb3Bcbn07XG4gZnVuY3Rpb24gaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soY2FsbGJhY2tzLCBuYW1lLCBjdHgsIGFyZykge1xuICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrc1tuYW1lXS5jYWxsKGN0eCwgYXJnKTtcbiAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRDYWxsYmFja3NbbmFtZV0uY2FsbChjdHgsIGFyZyk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5jbGFzcyBUb29sdGlwIGV4dGVuZHMgRWxlbWVudCB7XG4gc3RhdGljIHBvc2l0aW9uZXJzID0gcG9zaXRpb25lcnM7XG4gICAgY29uc3RydWN0b3IoY29uZmlnKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5vcGFjaXR5ID0gMDtcbiAgICAgICAgdGhpcy5fYWN0aXZlID0gW107XG4gICAgICAgIHRoaXMuX2V2ZW50UG9zaXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3NpemUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX2NhY2hlZEFuaW1hdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3Rvb2x0aXBJdGVtcyA9IFtdO1xuICAgICAgICB0aGlzLiRhbmltYXRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLiRjb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNoYXJ0ID0gY29uZmlnLmNoYXJ0O1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBjb25maWcub3B0aW9ucztcbiAgICAgICAgdGhpcy5kYXRhUG9pbnRzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnRpdGxlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmJlZm9yZUJvZHkgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYm9keSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5hZnRlckJvZHkgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuZm9vdGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnhBbGlnbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy55QWxpZ24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMueCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy55ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy53aWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jYXJldFggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuY2FyZXRZID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmxhYmVsQ29sb3JzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmxhYmVsUG9pbnRTdHlsZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMubGFiZWxUZXh0Q29sb3JzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpbml0aWFsaXplKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICAgICAgdGhpcy5fY2FjaGVkQW5pbWF0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy4kY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gX3Jlc29sdmVBbmltYXRpb25zKCkge1xuICAgICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLl9jYWNoZWRBbmltYXRpb25zO1xuICAgICAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKTtcbiAgICAgICAgY29uc3Qgb3B0cyA9IG9wdGlvbnMuZW5hYmxlZCAmJiBjaGFydC5vcHRpb25zLmFuaW1hdGlvbiAmJiBvcHRpb25zLmFuaW1hdGlvbnM7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBuZXcgQW5pbWF0aW9ucyh0aGlzLmNoYXJ0LCBvcHRzKTtcbiAgICAgICAgaWYgKG9wdHMuX2NhY2hlYWJsZSkge1xuICAgICAgICAgICAgdGhpcy5fY2FjaGVkQW5pbWF0aW9ucyA9IE9iamVjdC5mcmVlemUoYW5pbWF0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gICAgfVxuIGdldENvbnRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRjb250ZXh0IHx8ICh0aGlzLiRjb250ZXh0ID0gY3JlYXRlVG9vbHRpcENvbnRleHQodGhpcy5jaGFydC5nZXRDb250ZXh0KCksIHRoaXMsIHRoaXMuX3Rvb2x0aXBJdGVtcykpO1xuICAgIH1cbiAgICBnZXRUaXRsZShjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgY2FsbGJhY2tzICB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgYmVmb3JlVGl0bGUgPSBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhjYWxsYmFja3MsICdiZWZvcmVUaXRsZScsIHRoaXMsIGNvbnRleHQpO1xuICAgICAgICBjb25zdCB0aXRsZSA9IGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKGNhbGxiYWNrcywgJ3RpdGxlJywgdGhpcywgY29udGV4dCk7XG4gICAgICAgIGNvbnN0IGFmdGVyVGl0bGUgPSBpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhjYWxsYmFja3MsICdhZnRlclRpdGxlJywgdGhpcywgY29udGV4dCk7XG4gICAgICAgIGxldCBsaW5lcyA9IFtdO1xuICAgICAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhiZWZvcmVUaXRsZSkpO1xuICAgICAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyh0aXRsZSkpO1xuICAgICAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhhZnRlclRpdGxlKSk7XG4gICAgICAgIHJldHVybiBsaW5lcztcbiAgICB9XG4gICAgZ2V0QmVmb3JlQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJlZm9yZUFmdGVyQm9keUxpbmVzKGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKG9wdGlvbnMuY2FsbGJhY2tzLCAnYmVmb3JlQm9keScsIHRoaXMsIHRvb2x0aXBJdGVtcykpO1xuICAgIH1cbiAgICBnZXRCb2R5KHRvb2x0aXBJdGVtcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB7IGNhbGxiYWNrcyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGJvZHlJdGVtcyA9IFtdO1xuICAgICAgICBlYWNoKHRvb2x0aXBJdGVtcywgKGNvbnRleHQpPT57XG4gICAgICAgICAgICBjb25zdCBib2R5SXRlbSA9IHtcbiAgICAgICAgICAgICAgICBiZWZvcmU6IFtdLFxuICAgICAgICAgICAgICAgIGxpbmVzOiBbXSxcbiAgICAgICAgICAgICAgICBhZnRlcjogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzY29wZWQgPSBvdmVycmlkZUNhbGxiYWNrcyhjYWxsYmFja3MsIGNvbnRleHQpO1xuICAgICAgICAgICAgcHVzaE9yQ29uY2F0KGJvZHlJdGVtLmJlZm9yZSwgc3BsaXROZXdsaW5lcyhpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhzY29wZWQsICdiZWZvcmVMYWJlbCcsIHRoaXMsIGNvbnRleHQpKSk7XG4gICAgICAgICAgICBwdXNoT3JDb25jYXQoYm9keUl0ZW0ubGluZXMsIGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKHNjb3BlZCwgJ2xhYmVsJywgdGhpcywgY29udGV4dCkpO1xuICAgICAgICAgICAgcHVzaE9yQ29uY2F0KGJvZHlJdGVtLmFmdGVyLCBzcGxpdE5ld2xpbmVzKGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKHNjb3BlZCwgJ2FmdGVyTGFiZWwnLCB0aGlzLCBjb250ZXh0KSkpO1xuICAgICAgICAgICAgYm9keUl0ZW1zLnB1c2goYm9keUl0ZW0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGJvZHlJdGVtcztcbiAgICB9XG4gICAgZ2V0QWZ0ZXJCb2R5KHRvb2x0aXBJdGVtcywgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gZ2V0QmVmb3JlQWZ0ZXJCb2R5TGluZXMoaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2sob3B0aW9ucy5jYWxsYmFja3MsICdhZnRlckJvZHknLCB0aGlzLCB0b29sdGlwSXRlbXMpKTtcbiAgICB9XG4gICAgZ2V0Rm9vdGVyKHRvb2x0aXBJdGVtcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB7IGNhbGxiYWNrcyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGJlZm9yZUZvb3RlciA9IGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKGNhbGxiYWNrcywgJ2JlZm9yZUZvb3RlcicsIHRoaXMsIHRvb2x0aXBJdGVtcyk7XG4gICAgICAgIGNvbnN0IGZvb3RlciA9IGludm9rZUNhbGxiYWNrV2l0aEZhbGxiYWNrKGNhbGxiYWNrcywgJ2Zvb3RlcicsIHRoaXMsIHRvb2x0aXBJdGVtcyk7XG4gICAgICAgIGNvbnN0IGFmdGVyRm9vdGVyID0gaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soY2FsbGJhY2tzLCAnYWZ0ZXJGb290ZXInLCB0aGlzLCB0b29sdGlwSXRlbXMpO1xuICAgICAgICBsZXQgbGluZXMgPSBbXTtcbiAgICAgICAgbGluZXMgPSBwdXNoT3JDb25jYXQobGluZXMsIHNwbGl0TmV3bGluZXMoYmVmb3JlRm9vdGVyKSk7XG4gICAgICAgIGxpbmVzID0gcHVzaE9yQ29uY2F0KGxpbmVzLCBzcGxpdE5ld2xpbmVzKGZvb3RlcikpO1xuICAgICAgICBsaW5lcyA9IHB1c2hPckNvbmNhdChsaW5lcywgc3BsaXROZXdsaW5lcyhhZnRlckZvb3RlcikpO1xuICAgICAgICByZXR1cm4gbGluZXM7XG4gICAgfVxuIF9jcmVhdGVJdGVtcyhvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuX2FjdGl2ZTtcbiAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuY2hhcnQuZGF0YTtcbiAgICAgICAgY29uc3QgbGFiZWxDb2xvcnMgPSBbXTtcbiAgICAgICAgY29uc3QgbGFiZWxQb2ludFN0eWxlcyA9IFtdO1xuICAgICAgICBjb25zdCBsYWJlbFRleHRDb2xvcnMgPSBbXTtcbiAgICAgICAgbGV0IHRvb2x0aXBJdGVtcyA9IFtdO1xuICAgICAgICBsZXQgaSwgbGVuO1xuICAgICAgICBmb3IoaSA9IDAsIGxlbiA9IGFjdGl2ZS5sZW5ndGg7IGkgPCBsZW47ICsraSl7XG4gICAgICAgICAgICB0b29sdGlwSXRlbXMucHVzaChjcmVhdGVUb29sdGlwSXRlbSh0aGlzLmNoYXJ0LCBhY3RpdmVbaV0pKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5maWx0ZXIpIHtcbiAgICAgICAgICAgIHRvb2x0aXBJdGVtcyA9IHRvb2x0aXBJdGVtcy5maWx0ZXIoKGVsZW1lbnQsIGluZGV4LCBhcnJheSk9Pm9wdGlvbnMuZmlsdGVyKGVsZW1lbnQsIGluZGV4LCBhcnJheSwgZGF0YSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLml0ZW1Tb3J0KSB7XG4gICAgICAgICAgICB0b29sdGlwSXRlbXMgPSB0b29sdGlwSXRlbXMuc29ydCgoYSwgYik9Pm9wdGlvbnMuaXRlbVNvcnQoYSwgYiwgZGF0YSkpO1xuICAgICAgICB9XG4gICAgICAgIGVhY2godG9vbHRpcEl0ZW1zLCAoY29udGV4dCk9PntcbiAgICAgICAgICAgIGNvbnN0IHNjb3BlZCA9IG92ZXJyaWRlQ2FsbGJhY2tzKG9wdGlvbnMuY2FsbGJhY2tzLCBjb250ZXh0KTtcbiAgICAgICAgICAgIGxhYmVsQ29sb3JzLnB1c2goaW52b2tlQ2FsbGJhY2tXaXRoRmFsbGJhY2soc2NvcGVkLCAnbGFiZWxDb2xvcicsIHRoaXMsIGNvbnRleHQpKTtcbiAgICAgICAgICAgIGxhYmVsUG9pbnRTdHlsZXMucHVzaChpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhzY29wZWQsICdsYWJlbFBvaW50U3R5bGUnLCB0aGlzLCBjb250ZXh0KSk7XG4gICAgICAgICAgICBsYWJlbFRleHRDb2xvcnMucHVzaChpbnZva2VDYWxsYmFja1dpdGhGYWxsYmFjayhzY29wZWQsICdsYWJlbFRleHRDb2xvcicsIHRoaXMsIGNvbnRleHQpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubGFiZWxDb2xvcnMgPSBsYWJlbENvbG9ycztcbiAgICAgICAgdGhpcy5sYWJlbFBvaW50U3R5bGVzID0gbGFiZWxQb2ludFN0eWxlcztcbiAgICAgICAgdGhpcy5sYWJlbFRleHRDb2xvcnMgPSBsYWJlbFRleHRDb2xvcnM7XG4gICAgICAgIHRoaXMuZGF0YVBvaW50cyA9IHRvb2x0aXBJdGVtcztcbiAgICAgICAgcmV0dXJuIHRvb2x0aXBJdGVtcztcbiAgICB9XG4gICAgdXBkYXRlKGNoYW5nZWQsIHJlcGxheSkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLl9hY3RpdmU7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzO1xuICAgICAgICBsZXQgdG9vbHRpcEl0ZW1zID0gW107XG4gICAgICAgIGlmICghYWN0aXZlLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKHRoaXMub3BhY2l0eSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBwb3NpdGlvbmVyc1tvcHRpb25zLnBvc2l0aW9uXS5jYWxsKHRoaXMsIGFjdGl2ZSwgdGhpcy5fZXZlbnRQb3NpdGlvbik7XG4gICAgICAgICAgICB0b29sdGlwSXRlbXMgPSB0aGlzLl9jcmVhdGVJdGVtcyhvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMudGl0bGUgPSB0aGlzLmdldFRpdGxlKHRvb2x0aXBJdGVtcywgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmJlZm9yZUJvZHkgPSB0aGlzLmdldEJlZm9yZUJvZHkodG9vbHRpcEl0ZW1zLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuYm9keSA9IHRoaXMuZ2V0Qm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5hZnRlckJvZHkgPSB0aGlzLmdldEFmdGVyQm9keSh0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5mb290ZXIgPSB0aGlzLmdldEZvb3Rlcih0b29sdGlwSXRlbXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuX3NpemUgPSBnZXRUb29sdGlwU2l6ZSh0aGlzLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uQW5kU2l6ZSA9IE9iamVjdC5hc3NpZ24oe30sIHBvc2l0aW9uLCBzaXplKTtcbiAgICAgICAgICAgIGNvbnN0IGFsaWdubWVudCA9IGRldGVybWluZUFsaWdubWVudCh0aGlzLmNoYXJ0LCBvcHRpb25zLCBwb3NpdGlvbkFuZFNpemUpO1xuICAgICAgICAgICAgY29uc3QgYmFja2dyb3VuZFBvaW50ID0gZ2V0QmFja2dyb3VuZFBvaW50KG9wdGlvbnMsIHBvc2l0aW9uQW5kU2l6ZSwgYWxpZ25tZW50LCB0aGlzLmNoYXJ0KTtcbiAgICAgICAgICAgIHRoaXMueEFsaWduID0gYWxpZ25tZW50LnhBbGlnbjtcbiAgICAgICAgICAgIHRoaXMueUFsaWduID0gYWxpZ25tZW50LnlBbGlnbjtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgICAgICB4OiBiYWNrZ3JvdW5kUG9pbnQueCxcbiAgICAgICAgICAgICAgICB5OiBiYWNrZ3JvdW5kUG9pbnQueSxcbiAgICAgICAgICAgICAgICB3aWR0aDogc2l6ZS53aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHNpemUuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIGNhcmV0WDogcG9zaXRpb24ueCxcbiAgICAgICAgICAgICAgICBjYXJldFk6IHBvc2l0aW9uLnlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdG9vbHRpcEl0ZW1zID0gdG9vbHRpcEl0ZW1zO1xuICAgICAgICB0aGlzLiRjb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoKS51cGRhdGUodGhpcywgcHJvcGVydGllcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZWQgJiYgb3B0aW9ucy5leHRlcm5hbCkge1xuICAgICAgICAgICAgb3B0aW9ucy5leHRlcm5hbC5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICBjaGFydDogdGhpcy5jaGFydCxcbiAgICAgICAgICAgICAgICB0b29sdGlwOiB0aGlzLFxuICAgICAgICAgICAgICAgIHJlcGxheVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZHJhd0NhcmV0KHRvb2x0aXBQb2ludCwgY3R4LCBzaXplLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNhcmV0UG9zaXRpb24gPSB0aGlzLmdldENhcmV0UG9zaXRpb24odG9vbHRpcFBvaW50LCBzaXplLCBvcHRpb25zKTtcbiAgICAgICAgY3R4LmxpbmVUbyhjYXJldFBvc2l0aW9uLngxLCBjYXJldFBvc2l0aW9uLnkxKTtcbiAgICAgICAgY3R4LmxpbmVUbyhjYXJldFBvc2l0aW9uLngyLCBjYXJldFBvc2l0aW9uLnkyKTtcbiAgICAgICAgY3R4LmxpbmVUbyhjYXJldFBvc2l0aW9uLngzLCBjYXJldFBvc2l0aW9uLnkzKTtcbiAgICB9XG4gICAgZ2V0Q2FyZXRQb3NpdGlvbih0b29sdGlwUG9pbnQsIHNpemUsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyB4QWxpZ24gLCB5QWxpZ24gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IGNhcmV0U2l6ZSAsIGNvcm5lclJhZGl1cyAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHsgdG9wTGVmdCAsIHRvcFJpZ2h0ICwgYm90dG9tTGVmdCAsIGJvdHRvbVJpZ2h0ICB9ID0gdG9UUkJMQ29ybmVycyhjb3JuZXJSYWRpdXMpO1xuICAgICAgICBjb25zdCB7IHg6IHB0WCAsIHk6IHB0WSAgfSA9IHRvb2x0aXBQb2ludDtcbiAgICAgICAgY29uc3QgeyB3aWR0aCAsIGhlaWdodCAgfSA9IHNpemU7XG4gICAgICAgIGxldCB4MSwgeDIsIHgzLCB5MSwgeTIsIHkzO1xuICAgICAgICBpZiAoeUFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgeTIgPSBwdFkgKyBoZWlnaHQgLyAyO1xuICAgICAgICAgICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgeDEgPSBwdFg7XG4gICAgICAgICAgICAgICAgeDIgPSB4MSAtIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB5MSA9IHkyICsgY2FyZXRTaXplO1xuICAgICAgICAgICAgICAgIHkzID0geTIgLSBjYXJldFNpemU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHgxID0gcHRYICsgd2lkdGg7XG4gICAgICAgICAgICAgICAgeDIgPSB4MSArIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB5MSA9IHkyIC0gY2FyZXRTaXplO1xuICAgICAgICAgICAgICAgIHkzID0geTIgKyBjYXJldFNpemU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4MyA9IHgxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHhBbGlnbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgeDIgPSBwdFggKyBNYXRoLm1heCh0b3BMZWZ0LCBib3R0b21MZWZ0KSArIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoeEFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgICAgeDIgPSBwdFggKyB3aWR0aCAtIE1hdGgubWF4KHRvcFJpZ2h0LCBib3R0b21SaWdodCkgLSBjYXJldFNpemU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHgyID0gdGhpcy5jYXJldFg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeUFsaWduID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIHkxID0gcHRZO1xuICAgICAgICAgICAgICAgIHkyID0geTEgLSBjYXJldFNpemU7XG4gICAgICAgICAgICAgICAgeDEgPSB4MiAtIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgICAgICB4MyA9IHgyICsgY2FyZXRTaXplO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB5MSA9IHB0WSArIGhlaWdodDtcbiAgICAgICAgICAgICAgICB5MiA9IHkxICsgY2FyZXRTaXplO1xuICAgICAgICAgICAgICAgIHgxID0geDIgKyBjYXJldFNpemU7XG4gICAgICAgICAgICAgICAgeDMgPSB4MiAtIGNhcmV0U2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkzID0geTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHgxLFxuICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICB4MyxcbiAgICAgICAgICAgIHkxLFxuICAgICAgICAgICAgeTIsXG4gICAgICAgICAgICB5M1xuICAgICAgICB9O1xuICAgIH1cbiAgICBkcmF3VGl0bGUocHQsIGN0eCwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCB0aXRsZSA9IHRoaXMudGl0bGU7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IHRpdGxlLmxlbmd0aDtcbiAgICAgICAgbGV0IHRpdGxlRm9udCwgdGl0bGVTcGFjaW5nLCBpO1xuICAgICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKG9wdGlvbnMucnRsLCB0aGlzLngsIHRoaXMud2lkdGgpO1xuICAgICAgICAgICAgcHQueCA9IGdldEFsaWduZWRYKHRoaXMsIG9wdGlvbnMudGl0bGVBbGlnbiwgb3B0aW9ucyk7XG4gICAgICAgICAgICBjdHgudGV4dEFsaWduID0gcnRsSGVscGVyLnRleHRBbGlnbihvcHRpb25zLnRpdGxlQWxpZ24pO1xuICAgICAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICAgICAgdGl0bGVGb250ID0gdG9Gb250KG9wdGlvbnMudGl0bGVGb250KTtcbiAgICAgICAgICAgIHRpdGxlU3BhY2luZyA9IG9wdGlvbnMudGl0bGVTcGFjaW5nO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMudGl0bGVDb2xvcjtcbiAgICAgICAgICAgIGN0eC5mb250ID0gdGl0bGVGb250LnN0cmluZztcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbmd0aDsgKytpKXtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFRleHQodGl0bGVbaV0sIHJ0bEhlbHBlci54KHB0LngpLCBwdC55ICsgdGl0bGVGb250LmxpbmVIZWlnaHQgLyAyKTtcbiAgICAgICAgICAgICAgICBwdC55ICs9IHRpdGxlRm9udC5saW5lSGVpZ2h0ICsgdGl0bGVTcGFjaW5nO1xuICAgICAgICAgICAgICAgIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHB0LnkgKz0gb3B0aW9ucy50aXRsZU1hcmdpbkJvdHRvbSAtIHRpdGxlU3BhY2luZztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gX2RyYXdDb2xvckJveChjdHgsIHB0LCBpLCBydGxIZWxwZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbGFiZWxDb2xvciA9IHRoaXMubGFiZWxDb2xvcnNbaV07XG4gICAgICAgIGNvbnN0IGxhYmVsUG9pbnRTdHlsZSA9IHRoaXMubGFiZWxQb2ludFN0eWxlc1tpXTtcbiAgICAgICAgY29uc3QgeyBib3hIZWlnaHQgLCBib3hXaWR0aCAgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGJvZHlGb250ID0gdG9Gb250KG9wdGlvbnMuYm9keUZvbnQpO1xuICAgICAgICBjb25zdCBjb2xvclggPSBnZXRBbGlnbmVkWCh0aGlzLCAnbGVmdCcsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBydGxDb2xvclggPSBydGxIZWxwZXIueChjb2xvclgpO1xuICAgICAgICBjb25zdCB5T2ZmU2V0ID0gYm94SGVpZ2h0IDwgYm9keUZvbnQubGluZUhlaWdodCA/IChib2R5Rm9udC5saW5lSGVpZ2h0IC0gYm94SGVpZ2h0KSAvIDIgOiAwO1xuICAgICAgICBjb25zdCBjb2xvclkgPSBwdC55ICsgeU9mZlNldDtcbiAgICAgICAgaWYgKG9wdGlvbnMudXNlUG9pbnRTdHlsZSkge1xuICAgICAgICAgICAgY29uc3QgZHJhd09wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgcmFkaXVzOiBNYXRoLm1pbihib3hXaWR0aCwgYm94SGVpZ2h0KSAvIDIsXG4gICAgICAgICAgICAgICAgcG9pbnRTdHlsZTogbGFiZWxQb2ludFN0eWxlLnBvaW50U3R5bGUsXG4gICAgICAgICAgICAgICAgcm90YXRpb246IGxhYmVsUG9pbnRTdHlsZS5yb3RhdGlvbixcbiAgICAgICAgICAgICAgICBib3JkZXJXaWR0aDogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGNlbnRlclggPSBydGxIZWxwZXIubGVmdEZvckx0cihydGxDb2xvclgsIGJveFdpZHRoKSArIGJveFdpZHRoIC8gMjtcbiAgICAgICAgICAgIGNvbnN0IGNlbnRlclkgPSBjb2xvclkgKyBib3hIZWlnaHQgLyAyO1xuICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICAgICAgICBkcmF3UG9pbnQoY3R4LCBkcmF3T3B0aW9ucywgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBsYWJlbENvbG9yLmJvcmRlckNvbG9yO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGxhYmVsQ29sb3IuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICAgICAgZHJhd1BvaW50KGN0eCwgZHJhd09wdGlvbnMsIGNlbnRlclgsIGNlbnRlclkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3R4LmxpbmVXaWR0aCA9IGlzT2JqZWN0KGxhYmVsQ29sb3IuYm9yZGVyV2lkdGgpID8gTWF0aC5tYXgoLi4uT2JqZWN0LnZhbHVlcyhsYWJlbENvbG9yLmJvcmRlcldpZHRoKSkgOiBsYWJlbENvbG9yLmJvcmRlcldpZHRoIHx8IDE7XG4gICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBsYWJlbENvbG9yLmJvcmRlckNvbG9yO1xuICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKGxhYmVsQ29sb3IuYm9yZGVyRGFzaCB8fCBbXSk7XG4gICAgICAgICAgICBjdHgubGluZURhc2hPZmZzZXQgPSBsYWJlbENvbG9yLmJvcmRlckRhc2hPZmZzZXQgfHwgMDtcbiAgICAgICAgICAgIGNvbnN0IG91dGVyWCA9IHJ0bEhlbHBlci5sZWZ0Rm9yTHRyKHJ0bENvbG9yWCwgYm94V2lkdGgpO1xuICAgICAgICAgICAgY29uc3QgaW5uZXJYID0gcnRsSGVscGVyLmxlZnRGb3JMdHIocnRsSGVscGVyLnhQbHVzKHJ0bENvbG9yWCwgMSksIGJveFdpZHRoIC0gMik7XG4gICAgICAgICAgICBjb25zdCBib3JkZXJSYWRpdXMgPSB0b1RSQkxDb3JuZXJzKGxhYmVsQ29sb3IuYm9yZGVyUmFkaXVzKTtcbiAgICAgICAgICAgIGlmIChPYmplY3QudmFsdWVzKGJvcmRlclJhZGl1cykuc29tZSgodik9PnYgIT09IDApKSB7XG4gICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLm11bHRpS2V5QmFja2dyb3VuZDtcbiAgICAgICAgICAgICAgICBhZGRSb3VuZGVkUmVjdFBhdGgoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgIHg6IG91dGVyWCxcbiAgICAgICAgICAgICAgICAgICAgeTogY29sb3JZLFxuICAgICAgICAgICAgICAgICAgICB3OiBib3hXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaDogYm94SGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICByYWRpdXM6IGJvcmRlclJhZGl1c1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBsYWJlbENvbG9yLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgICAgICAgICAgYWRkUm91bmRlZFJlY3RQYXRoKGN0eCwge1xuICAgICAgICAgICAgICAgICAgICB4OiBpbm5lclgsXG4gICAgICAgICAgICAgICAgICAgIHk6IGNvbG9yWSArIDEsXG4gICAgICAgICAgICAgICAgICAgIHc6IGJveFdpZHRoIC0gMixcbiAgICAgICAgICAgICAgICAgICAgaDogYm94SGVpZ2h0IC0gMixcbiAgICAgICAgICAgICAgICAgICAgcmFkaXVzOiBib3JkZXJSYWRpdXNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5tdWx0aUtleUJhY2tncm91bmQ7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxSZWN0KG91dGVyWCwgY29sb3JZLCBib3hXaWR0aCwgYm94SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBjdHguc3Ryb2tlUmVjdChvdXRlclgsIGNvbG9yWSwgYm94V2lkdGgsIGJveEhlaWdodCk7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGxhYmVsQ29sb3IuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsUmVjdChpbm5lclgsIGNvbG9yWSArIDEsIGJveFdpZHRoIC0gMiwgYm94SGVpZ2h0IC0gMik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMubGFiZWxUZXh0Q29sb3JzW2ldO1xuICAgIH1cbiAgICBkcmF3Qm9keShwdCwgY3R4LCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgYm9keSAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHsgYm9keVNwYWNpbmcgLCBib2R5QWxpZ24gLCBkaXNwbGF5Q29sb3JzICwgYm94SGVpZ2h0ICwgYm94V2lkdGggLCBib3hQYWRkaW5nICB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgYm9keUZvbnQgPSB0b0ZvbnQob3B0aW9ucy5ib2R5Rm9udCk7XG4gICAgICAgIGxldCBib2R5TGluZUhlaWdodCA9IGJvZHlGb250LmxpbmVIZWlnaHQ7XG4gICAgICAgIGxldCB4TGluZVBhZGRpbmcgPSAwO1xuICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKG9wdGlvbnMucnRsLCB0aGlzLngsIHRoaXMud2lkdGgpO1xuICAgICAgICBjb25zdCBmaWxsTGluZU9mVGV4dCA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIGN0eC5maWxsVGV4dChsaW5lLCBydGxIZWxwZXIueChwdC54ICsgeExpbmVQYWRkaW5nKSwgcHQueSArIGJvZHlMaW5lSGVpZ2h0IC8gMik7XG4gICAgICAgICAgICBwdC55ICs9IGJvZHlMaW5lSGVpZ2h0ICsgYm9keVNwYWNpbmc7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGJvZHlBbGlnbkZvckNhbGN1bGF0aW9uID0gcnRsSGVscGVyLnRleHRBbGlnbihib2R5QWxpZ24pO1xuICAgICAgICBsZXQgYm9keUl0ZW0sIHRleHRDb2xvciwgbGluZXMsIGksIGosIGlsZW4sIGpsZW47XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSBib2R5QWxpZ247XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgY3R4LmZvbnQgPSBib2R5Rm9udC5zdHJpbmc7XG4gICAgICAgIHB0LnggPSBnZXRBbGlnbmVkWCh0aGlzLCBib2R5QWxpZ25Gb3JDYWxjdWxhdGlvbiwgb3B0aW9ucyk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmJvZHlDb2xvcjtcbiAgICAgICAgZWFjaCh0aGlzLmJlZm9yZUJvZHksIGZpbGxMaW5lT2ZUZXh0KTtcbiAgICAgICAgeExpbmVQYWRkaW5nID0gZGlzcGxheUNvbG9ycyAmJiBib2R5QWxpZ25Gb3JDYWxjdWxhdGlvbiAhPT0gJ3JpZ2h0JyA/IGJvZHlBbGlnbiA9PT0gJ2NlbnRlcicgPyBib3hXaWR0aCAvIDIgKyBib3hQYWRkaW5nIDogYm94V2lkdGggKyAyICsgYm94UGFkZGluZyA6IDA7XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGJvZHkubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIGJvZHlJdGVtID0gYm9keVtpXTtcbiAgICAgICAgICAgIHRleHRDb2xvciA9IHRoaXMubGFiZWxUZXh0Q29sb3JzW2ldO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IHRleHRDb2xvcjtcbiAgICAgICAgICAgIGVhY2goYm9keUl0ZW0uYmVmb3JlLCBmaWxsTGluZU9mVGV4dCk7XG4gICAgICAgICAgICBsaW5lcyA9IGJvZHlJdGVtLmxpbmVzO1xuICAgICAgICAgICAgaWYgKGRpc3BsYXlDb2xvcnMgJiYgbGluZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZHJhd0NvbG9yQm94KGN0eCwgcHQsIGksIHJ0bEhlbHBlciwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgYm9keUxpbmVIZWlnaHQgPSBNYXRoLm1heChib2R5Rm9udC5saW5lSGVpZ2h0LCBib3hIZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKGogPSAwLCBqbGVuID0gbGluZXMubGVuZ3RoOyBqIDwgamxlbjsgKytqKXtcbiAgICAgICAgICAgICAgICBmaWxsTGluZU9mVGV4dChsaW5lc1tqXSk7XG4gICAgICAgICAgICAgICAgYm9keUxpbmVIZWlnaHQgPSBib2R5Rm9udC5saW5lSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWFjaChib2R5SXRlbS5hZnRlciwgZmlsbExpbmVPZlRleHQpO1xuICAgICAgICB9XG4gICAgICAgIHhMaW5lUGFkZGluZyA9IDA7XG4gICAgICAgIGJvZHlMaW5lSGVpZ2h0ID0gYm9keUZvbnQubGluZUhlaWdodDtcbiAgICAgICAgZWFjaCh0aGlzLmFmdGVyQm9keSwgZmlsbExpbmVPZlRleHQpO1xuICAgICAgICBwdC55IC09IGJvZHlTcGFjaW5nO1xuICAgIH1cbiAgICBkcmF3Rm9vdGVyKHB0LCBjdHgsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgZm9vdGVyID0gdGhpcy5mb290ZXI7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IGZvb3Rlci5sZW5ndGg7XG4gICAgICAgIGxldCBmb290ZXJGb250LCBpO1xuICAgICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBydGxIZWxwZXIgPSBnZXRSdGxBZGFwdGVyKG9wdGlvbnMucnRsLCB0aGlzLngsIHRoaXMud2lkdGgpO1xuICAgICAgICAgICAgcHQueCA9IGdldEFsaWduZWRYKHRoaXMsIG9wdGlvbnMuZm9vdGVyQWxpZ24sIG9wdGlvbnMpO1xuICAgICAgICAgICAgcHQueSArPSBvcHRpb25zLmZvb3Rlck1hcmdpblRvcDtcbiAgICAgICAgICAgIGN0eC50ZXh0QWxpZ24gPSBydGxIZWxwZXIudGV4dEFsaWduKG9wdGlvbnMuZm9vdGVyQWxpZ24pO1xuICAgICAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICAgICAgZm9vdGVyRm9udCA9IHRvRm9udChvcHRpb25zLmZvb3RlckZvbnQpO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuZm9vdGVyQ29sb3I7XG4gICAgICAgICAgICBjdHguZm9udCA9IGZvb3RlckZvbnQuc3RyaW5nO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpe1xuICAgICAgICAgICAgICAgIGN0eC5maWxsVGV4dChmb290ZXJbaV0sIHJ0bEhlbHBlci54KHB0LngpLCBwdC55ICsgZm9vdGVyRm9udC5saW5lSGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgcHQueSArPSBmb290ZXJGb250LmxpbmVIZWlnaHQgKyBvcHRpb25zLmZvb3RlclNwYWNpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZHJhd0JhY2tncm91bmQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyB4QWxpZ24gLCB5QWxpZ24gIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IHggLCB5ICB9ID0gcHQ7XG4gICAgICAgIGNvbnN0IHsgd2lkdGggLCBoZWlnaHQgIH0gPSB0b29sdGlwU2l6ZTtcbiAgICAgICAgY29uc3QgeyB0b3BMZWZ0ICwgdG9wUmlnaHQgLCBib3R0b21MZWZ0ICwgYm90dG9tUmlnaHQgIH0gPSB0b1RSQkxDb3JuZXJzKG9wdGlvbnMuY29ybmVyUmFkaXVzKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBvcHRpb25zLmJvcmRlckNvbG9yO1xuICAgICAgICBjdHgubGluZVdpZHRoID0gb3B0aW9ucy5ib3JkZXJXaWR0aDtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHgubW92ZVRvKHggKyB0b3BMZWZ0LCB5KTtcbiAgICAgICAgaWYgKHlBbGlnbiA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NhcmV0KHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjdHgubGluZVRvKHggKyB3aWR0aCAtIHRvcFJpZ2h0LCB5KTtcbiAgICAgICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCArIHdpZHRoLCB5LCB4ICsgd2lkdGgsIHkgKyB0b3BSaWdodCk7XG4gICAgICAgIGlmICh5QWxpZ24gPT09ICdjZW50ZXInICYmIHhBbGlnbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2FyZXQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5saW5lVG8oeCArIHdpZHRoLCB5ICsgaGVpZ2h0IC0gYm90dG9tUmlnaHQpO1xuICAgICAgICBjdHgucXVhZHJhdGljQ3VydmVUbyh4ICsgd2lkdGgsIHkgKyBoZWlnaHQsIHggKyB3aWR0aCAtIGJvdHRvbVJpZ2h0LCB5ICsgaGVpZ2h0KTtcbiAgICAgICAgaWYgKHlBbGlnbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NhcmV0KHB0LCBjdHgsIHRvb2x0aXBTaXplLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjdHgubGluZVRvKHggKyBib3R0b21MZWZ0LCB5ICsgaGVpZ2h0KTtcbiAgICAgICAgY3R4LnF1YWRyYXRpY0N1cnZlVG8oeCwgeSArIGhlaWdodCwgeCwgeSArIGhlaWdodCAtIGJvdHRvbUxlZnQpO1xuICAgICAgICBpZiAoeUFsaWduID09PSAnY2VudGVyJyAmJiB4QWxpZ24gPT09ICdsZWZ0Jykge1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2FyZXQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGN0eC5saW5lVG8oeCwgeSArIHRvcExlZnQpO1xuICAgICAgICBjdHgucXVhZHJhdGljQ3VydmVUbyh4LCB5LCB4ICsgdG9wTGVmdCwgeSk7XG4gICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgY3R4LmZpbGwoKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuYm9yZGVyV2lkdGggPiAwKSB7XG4gICAgICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gX3VwZGF0ZUFuaW1hdGlvblRhcmdldChvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNoYXJ0ID0gdGhpcy5jaGFydDtcbiAgICAgICAgY29uc3QgYW5pbXMgPSB0aGlzLiRhbmltYXRpb25zO1xuICAgICAgICBjb25zdCBhbmltWCA9IGFuaW1zICYmIGFuaW1zLng7XG4gICAgICAgIGNvbnN0IGFuaW1ZID0gYW5pbXMgJiYgYW5pbXMueTtcbiAgICAgICAgaWYgKGFuaW1YIHx8IGFuaW1ZKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHBvc2l0aW9uZXJzW29wdGlvbnMucG9zaXRpb25dLmNhbGwodGhpcywgdGhpcy5fYWN0aXZlLCB0aGlzLl9ldmVudFBvc2l0aW9uKTtcbiAgICAgICAgICAgIGlmICghcG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzaXplID0gdGhpcy5fc2l6ZSA9IGdldFRvb2x0aXBTaXplKHRoaXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25BbmRTaXplID0gT2JqZWN0LmFzc2lnbih7fSwgcG9zaXRpb24sIHRoaXMuX3NpemUpO1xuICAgICAgICAgICAgY29uc3QgYWxpZ25tZW50ID0gZGV0ZXJtaW5lQWxpZ25tZW50KGNoYXJ0LCBvcHRpb25zLCBwb3NpdGlvbkFuZFNpemUpO1xuICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBnZXRCYWNrZ3JvdW5kUG9pbnQob3B0aW9ucywgcG9zaXRpb25BbmRTaXplLCBhbGlnbm1lbnQsIGNoYXJ0KTtcbiAgICAgICAgICAgIGlmIChhbmltWC5fdG8gIT09IHBvaW50LnggfHwgYW5pbVkuX3RvICE9PSBwb2ludC55KSB7XG4gICAgICAgICAgICAgICAgdGhpcy54QWxpZ24gPSBhbGlnbm1lbnQueEFsaWduO1xuICAgICAgICAgICAgICAgIHRoaXMueUFsaWduID0gYWxpZ25tZW50LnlBbGlnbjtcbiAgICAgICAgICAgICAgICB0aGlzLndpZHRoID0gc2l6ZS53aWR0aDtcbiAgICAgICAgICAgICAgICB0aGlzLmhlaWdodCA9IHNpemUuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRYID0gcG9zaXRpb24ueDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcmV0WSA9IHBvc2l0aW9uLnk7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoKS51cGRhdGUodGhpcywgcG9pbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuIF93aWxsUmVuZGVyKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLm9wYWNpdHk7XG4gICAgfVxuICAgIGRyYXcoY3R4KSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICAgIGxldCBvcGFjaXR5ID0gdGhpcy5vcGFjaXR5O1xuICAgICAgICBpZiAoIW9wYWNpdHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGVBbmltYXRpb25UYXJnZXQob3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IHRvb2x0aXBTaXplID0ge1xuICAgICAgICAgICAgd2lkdGg6IHRoaXMud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuaGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHB0ID0ge1xuICAgICAgICAgICAgeDogdGhpcy54LFxuICAgICAgICAgICAgeTogdGhpcy55XG4gICAgICAgIH07XG4gICAgICAgIG9wYWNpdHkgPSBNYXRoLmFicyhvcGFjaXR5KSA8IDFlLTMgPyAwIDogb3BhY2l0eTtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRpb25zLnBhZGRpbmcpO1xuICAgICAgICBjb25zdCBoYXNUb29sdGlwQ29udGVudCA9IHRoaXMudGl0bGUubGVuZ3RoIHx8IHRoaXMuYmVmb3JlQm9keS5sZW5ndGggfHwgdGhpcy5ib2R5Lmxlbmd0aCB8fCB0aGlzLmFmdGVyQm9keS5sZW5ndGggfHwgdGhpcy5mb290ZXIubGVuZ3RoO1xuICAgICAgICBpZiAob3B0aW9ucy5lbmFibGVkICYmIGhhc1Rvb2x0aXBDb250ZW50KSB7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY3R4Lmdsb2JhbEFscGhhID0gb3BhY2l0eTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0JhY2tncm91bmQocHQsIGN0eCwgdG9vbHRpcFNpemUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uKGN0eCwgb3B0aW9ucy50ZXh0RGlyZWN0aW9uKTtcbiAgICAgICAgICAgIHB0LnkgKz0gcGFkZGluZy50b3A7XG4gICAgICAgICAgICB0aGlzLmRyYXdUaXRsZShwdCwgY3R4LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0JvZHkocHQsIGN0eCwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmRyYXdGb290ZXIocHQsIGN0eCwgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXN0b3JlVGV4dERpcmVjdGlvbihjdHgsIG9wdGlvbnMudGV4dERpcmVjdGlvbik7XG4gICAgICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgICAgICB9XG4gICAgfVxuIGdldEFjdGl2ZUVsZW1lbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgIH1cbiBzZXRBY3RpdmVFbGVtZW50cyhhY3RpdmVFbGVtZW50cywgZXZlbnRQb3NpdGlvbikge1xuICAgICAgICBjb25zdCBsYXN0QWN0aXZlID0gdGhpcy5fYWN0aXZlO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSBhY3RpdmVFbGVtZW50cy5tYXAoKHsgZGF0YXNldEluZGV4ICwgaW5kZXggIH0pPT57XG4gICAgICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5jaGFydC5nZXREYXRhc2V0TWV0YShkYXRhc2V0SW5kZXgpO1xuICAgICAgICAgICAgaWYgKCFtZXRhKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBhIGRhdGFzZXQgYXQgaW5kZXggJyArIGRhdGFzZXRJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGRhdGFzZXRJbmRleCxcbiAgICAgICAgICAgICAgICBlbGVtZW50OiBtZXRhLmRhdGFbaW5kZXhdLFxuICAgICAgICAgICAgICAgIGluZGV4XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2hhbmdlZCA9ICFfZWxlbWVudHNFcXVhbChsYXN0QWN0aXZlLCBhY3RpdmUpO1xuICAgICAgICBjb25zdCBwb3NpdGlvbkNoYW5nZWQgPSB0aGlzLl9wb3NpdGlvbkNoYW5nZWQoYWN0aXZlLCBldmVudFBvc2l0aW9uKTtcbiAgICAgICAgaWYgKGNoYW5nZWQgfHwgcG9zaXRpb25DaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLl9hY3RpdmUgPSBhY3RpdmU7XG4gICAgICAgICAgICB0aGlzLl9ldmVudFBvc2l0aW9uID0gZXZlbnRQb3NpdGlvbjtcbiAgICAgICAgICAgIHRoaXMuX2lnbm9yZVJlcGxheUV2ZW50cyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSh0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbiBoYW5kbGVFdmVudChlLCByZXBsYXksIGluQ2hhcnRBcmVhID0gdHJ1ZSkge1xuICAgICAgICBpZiAocmVwbGF5ICYmIHRoaXMuX2lnbm9yZVJlcGxheUV2ZW50cykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lnbm9yZVJlcGxheUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBsYXN0QWN0aXZlID0gdGhpcy5fYWN0aXZlIHx8IFtdO1xuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLl9nZXRBY3RpdmVFbGVtZW50cyhlLCBsYXN0QWN0aXZlLCByZXBsYXksIGluQ2hhcnRBcmVhKTtcbiAgICAgICAgY29uc3QgcG9zaXRpb25DaGFuZ2VkID0gdGhpcy5fcG9zaXRpb25DaGFuZ2VkKGFjdGl2ZSwgZSk7XG4gICAgICAgIGNvbnN0IGNoYW5nZWQgPSByZXBsYXkgfHwgIV9lbGVtZW50c0VxdWFsKGFjdGl2ZSwgbGFzdEFjdGl2ZSkgfHwgcG9zaXRpb25DaGFuZ2VkO1xuICAgICAgICBpZiAoY2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5fYWN0aXZlID0gYWN0aXZlO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlZCB8fCBvcHRpb25zLmV4dGVybmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgeDogZS54LFxuICAgICAgICAgICAgICAgICAgICB5OiBlLnlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHRydWUsIHJlcGxheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNoYW5nZWQ7XG4gICAgfVxuIF9nZXRBY3RpdmVFbGVtZW50cyhlLCBsYXN0QWN0aXZlLCByZXBsYXksIGluQ2hhcnRBcmVhKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmIChlLnR5cGUgPT09ICdtb3VzZW91dCcpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWluQ2hhcnRBcmVhKSB7XG4gICAgICAgICAgICByZXR1cm4gbGFzdEFjdGl2ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhY3RpdmUgPSB0aGlzLmNoYXJ0LmdldEVsZW1lbnRzQXRFdmVudEZvck1vZGUoZSwgb3B0aW9ucy5tb2RlLCBvcHRpb25zLCByZXBsYXkpO1xuICAgICAgICBpZiAob3B0aW9ucy5yZXZlcnNlKSB7XG4gICAgICAgICAgICBhY3RpdmUucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3RpdmU7XG4gICAgfVxuIF9wb3NpdGlvbkNoYW5nZWQoYWN0aXZlLCBlKSB7XG4gICAgICAgIGNvbnN0IHsgY2FyZXRYICwgY2FyZXRZICwgb3B0aW9ucyAgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25lcnNbb3B0aW9ucy5wb3NpdGlvbl0uY2FsbCh0aGlzLCBhY3RpdmUsIGUpO1xuICAgICAgICByZXR1cm4gcG9zaXRpb24gIT09IGZhbHNlICYmIChjYXJldFggIT09IHBvc2l0aW9uLnggfHwgY2FyZXRZICE9PSBwb3NpdGlvbi55KTtcbiAgICB9XG59XG52YXIgcGx1Z2luX3Rvb2x0aXAgPSB7XG4gICAgaWQ6ICd0b29sdGlwJyxcbiAgICBfZWxlbWVudDogVG9vbHRpcCxcbiAgICBwb3NpdGlvbmVycyxcbiAgICBhZnRlckluaXQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucykge1xuICAgICAgICAgICAgY2hhcnQudG9vbHRpcCA9IG5ldyBUb29sdGlwKHtcbiAgICAgICAgICAgICAgICBjaGFydCxcbiAgICAgICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmVmb3JlVXBkYXRlIChjaGFydCwgX2FyZ3MsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGNoYXJ0LnRvb2x0aXApIHtcbiAgICAgICAgICAgIGNoYXJ0LnRvb2x0aXAuaW5pdGlhbGl6ZShvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVzZXQgKGNoYXJ0LCBfYXJncywgb3B0aW9ucykge1xuICAgICAgICBpZiAoY2hhcnQudG9vbHRpcCkge1xuICAgICAgICAgICAgY2hhcnQudG9vbHRpcC5pbml0aWFsaXplKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhZnRlckRyYXcgKGNoYXJ0KSB7XG4gICAgICAgIGNvbnN0IHRvb2x0aXAgPSBjaGFydC50b29sdGlwO1xuICAgICAgICBpZiAodG9vbHRpcCAmJiB0b29sdGlwLl93aWxsUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICAgICAgICAgICAgdG9vbHRpcFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChjaGFydC5ub3RpZnlQbHVnaW5zKCdiZWZvcmVUb29sdGlwRHJhdycsIHtcbiAgICAgICAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRvb2x0aXAuZHJhdyhjaGFydC5jdHgpO1xuICAgICAgICAgICAgY2hhcnQubm90aWZ5UGx1Z2lucygnYWZ0ZXJUb29sdGlwRHJhdycsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhZnRlckV2ZW50IChjaGFydCwgYXJncykge1xuICAgICAgICBpZiAoY2hhcnQudG9vbHRpcCkge1xuICAgICAgICAgICAgY29uc3QgdXNlRmluYWxQb3NpdGlvbiA9IGFyZ3MucmVwbGF5O1xuICAgICAgICAgICAgaWYgKGNoYXJ0LnRvb2x0aXAuaGFuZGxlRXZlbnQoYXJncy5ldmVudCwgdXNlRmluYWxQb3NpdGlvbiwgYXJncy5pbkNoYXJ0QXJlYSkpIHtcbiAgICAgICAgICAgICAgICBhcmdzLmNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICBleHRlcm5hbDogbnVsbCxcbiAgICAgICAgcG9zaXRpb246ICdhdmVyYWdlJyxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiAncmdiYSgwLDAsMCwwLjgpJyxcbiAgICAgICAgdGl0bGVDb2xvcjogJyNmZmYnLFxuICAgICAgICB0aXRsZUZvbnQ6IHtcbiAgICAgICAgICAgIHdlaWdodDogJ2JvbGQnXG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlU3BhY2luZzogMixcbiAgICAgICAgdGl0bGVNYXJnaW5Cb3R0b206IDYsXG4gICAgICAgIHRpdGxlQWxpZ246ICdsZWZ0JyxcbiAgICAgICAgYm9keUNvbG9yOiAnI2ZmZicsXG4gICAgICAgIGJvZHlTcGFjaW5nOiAyLFxuICAgICAgICBib2R5Rm9udDoge30sXG4gICAgICAgIGJvZHlBbGlnbjogJ2xlZnQnLFxuICAgICAgICBmb290ZXJDb2xvcjogJyNmZmYnLFxuICAgICAgICBmb290ZXJTcGFjaW5nOiAyLFxuICAgICAgICBmb290ZXJNYXJnaW5Ub3A6IDYsXG4gICAgICAgIGZvb3RlckZvbnQ6IHtcbiAgICAgICAgICAgIHdlaWdodDogJ2JvbGQnXG4gICAgICAgIH0sXG4gICAgICAgIGZvb3RlckFsaWduOiAnbGVmdCcsXG4gICAgICAgIHBhZGRpbmc6IDYsXG4gICAgICAgIGNhcmV0UGFkZGluZzogMixcbiAgICAgICAgY2FyZXRTaXplOiA1LFxuICAgICAgICBjb3JuZXJSYWRpdXM6IDYsXG4gICAgICAgIGJveEhlaWdodDogKGN0eCwgb3B0cyk9Pm9wdHMuYm9keUZvbnQuc2l6ZSxcbiAgICAgICAgYm94V2lkdGg6IChjdHgsIG9wdHMpPT5vcHRzLmJvZHlGb250LnNpemUsXG4gICAgICAgIG11bHRpS2V5QmFja2dyb3VuZDogJyNmZmYnLFxuICAgICAgICBkaXNwbGF5Q29sb3JzOiB0cnVlLFxuICAgICAgICBib3hQYWRkaW5nOiAwLFxuICAgICAgICBib3JkZXJDb2xvcjogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBib3JkZXJXaWR0aDogMCxcbiAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogNDAwLFxuICAgICAgICAgICAgZWFzaW5nOiAnZWFzZU91dFF1YXJ0J1xuICAgICAgICB9LFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgcHJvcGVydGllczogW1xuICAgICAgICAgICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAgICAgICAgICd5JyxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJyxcbiAgICAgICAgICAgICAgICAgICAgJ2hlaWdodCcsXG4gICAgICAgICAgICAgICAgICAgICdjYXJldFgnLFxuICAgICAgICAgICAgICAgICAgICAnY2FyZXRZJ1xuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICAgICAgZWFzaW5nOiAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogMjAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGxiYWNrczogZGVmYXVsdENhbGxiYWNrc1xuICAgIH0sXG4gICAgZGVmYXVsdFJvdXRlczoge1xuICAgICAgICBib2R5Rm9udDogJ2ZvbnQnLFxuICAgICAgICBmb290ZXJGb250OiAnZm9udCcsXG4gICAgICAgIHRpdGxlRm9udDogJ2ZvbnQnXG4gICAgfSxcbiAgICBkZXNjcmlwdG9yczoge1xuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnZmlsdGVyJyAmJiBuYW1lICE9PSAnaXRlbVNvcnQnICYmIG5hbWUgIT09ICdleHRlcm5hbCcsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlLFxuICAgICAgICBjYWxsYmFja3M6IHtcbiAgICAgICAgICAgIF9zY3JpcHRhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIF9pbmRleGFibGU6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgX2ZhbGxiYWNrOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICBhbmltYXRpb25zOiB7XG4gICAgICAgICAgICBfZmFsbGJhY2s6ICdhbmltYXRpb24nXG4gICAgICAgIH1cbiAgICB9LFxuICAgIGFkZGl0aW9uYWxPcHRpb25TY29wZXM6IFtcbiAgICAgICAgJ2ludGVyYWN0aW9uJ1xuICAgIF1cbn07XG5cbnZhciBwbHVnaW5zID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQ29sb3JzOiBwbHVnaW5fY29sb3JzLFxuRGVjaW1hdGlvbjogcGx1Z2luX2RlY2ltYXRpb24sXG5GaWxsZXI6IGluZGV4LFxuTGVnZW5kOiBwbHVnaW5fbGVnZW5kLFxuU3ViVGl0bGU6IHBsdWdpbl9zdWJ0aXRsZSxcblRpdGxlOiBwbHVnaW5fdGl0bGUsXG5Ub29sdGlwOiBwbHVnaW5fdG9vbHRpcFxufSk7XG5cbmNvbnN0IGFkZElmU3RyaW5nID0gKGxhYmVscywgcmF3LCBpbmRleCwgYWRkZWRMYWJlbHMpPT57XG4gICAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGluZGV4ID0gbGFiZWxzLnB1c2gocmF3KSAtIDE7XG4gICAgICAgIGFkZGVkTGFiZWxzLnVuc2hpZnQoe1xuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBsYWJlbDogcmF3XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoaXNOYU4ocmF3KSkge1xuICAgICAgICBpbmRleCA9IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBpbmRleDtcbn07XG5mdW5jdGlvbiBmaW5kT3JBZGRMYWJlbChsYWJlbHMsIHJhdywgaW5kZXgsIGFkZGVkTGFiZWxzKSB7XG4gICAgY29uc3QgZmlyc3QgPSBsYWJlbHMuaW5kZXhPZihyYXcpO1xuICAgIGlmIChmaXJzdCA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIGFkZElmU3RyaW5nKGxhYmVscywgcmF3LCBpbmRleCwgYWRkZWRMYWJlbHMpO1xuICAgIH1cbiAgICBjb25zdCBsYXN0ID0gbGFiZWxzLmxhc3RJbmRleE9mKHJhdyk7XG4gICAgcmV0dXJuIGZpcnN0ICE9PSBsYXN0ID8gaW5kZXggOiBmaXJzdDtcbn1cbmNvbnN0IHZhbGlkSW5kZXggPSAoaW5kZXgsIG1heCk9PmluZGV4ID09PSBudWxsID8gbnVsbCA6IF9saW1pdFZhbHVlKE1hdGgucm91bmQoaW5kZXgpLCAwLCBtYXgpO1xuZnVuY3Rpb24gX2dldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmdldExhYmVscygpO1xuICAgIGlmICh2YWx1ZSA+PSAwICYmIHZhbHVlIDwgbGFiZWxzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbGFiZWxzW3ZhbHVlXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuY2xhc3MgQ2F0ZWdvcnlTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgICBzdGF0aWMgaWQgPSAnY2F0ZWdvcnknO1xuIHN0YXRpYyBkZWZhdWx0cyA9IHtcbiAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgIGNhbGxiYWNrOiBfZ2V0TGFiZWxGb3JWYWx1ZVxuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcihjZmcpO1xuICAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdmFsdWVSYW5nZSA9IDA7XG4gICAgICAgIHRoaXMuX2FkZGVkTGFiZWxzID0gW107XG4gICAgfVxuICAgIGluaXQoc2NhbGVPcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFkZGVkID0gdGhpcy5fYWRkZWRMYWJlbHM7XG4gICAgICAgIGlmIChhZGRlZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuZ2V0TGFiZWxzKCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHsgaW5kZXggLCBsYWJlbCAgfSBvZiBhZGRlZCl7XG4gICAgICAgICAgICAgICAgaWYgKGxhYmVsc1tpbmRleF0gPT09IGxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhYmVscy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2FkZGVkTGFiZWxzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIuaW5pdChzY2FsZU9wdGlvbnMpO1xuICAgIH1cbiAgICBwYXJzZShyYXcsIGluZGV4KSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmKHJhdykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuZ2V0TGFiZWxzKCk7XG4gICAgICAgIGluZGV4ID0gaXNGaW5pdGUoaW5kZXgpICYmIGxhYmVsc1tpbmRleF0gPT09IHJhdyA/IGluZGV4IDogZmluZE9yQWRkTGFiZWwobGFiZWxzLCByYXcsIHZhbHVlT3JEZWZhdWx0KGluZGV4LCByYXcpLCB0aGlzLl9hZGRlZExhYmVscyk7XG4gICAgICAgIHJldHVybiB2YWxpZEluZGV4KGluZGV4LCBsYWJlbHMubGVuZ3RoIC0gMSk7XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IHsgbWluRGVmaW5lZCAsIG1heERlZmluZWQgIH0gPSB0aGlzLmdldFVzZXJCb3VuZHMoKTtcbiAgICAgICAgbGV0IHsgbWluICwgbWF4ICB9ID0gdGhpcy5nZXRNaW5NYXgodHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuYm91bmRzID09PSAndGlja3MnKSB7XG4gICAgICAgICAgICBpZiAoIW1pbkRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtYXhEZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gdGhpcy5nZXRMYWJlbHMoKS5sZW5ndGggLSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubWluID0gbWluO1xuICAgICAgICB0aGlzLm1heCA9IG1heDtcbiAgICB9XG4gICAgYnVpbGRUaWNrcygpIHtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW47XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLm9wdGlvbnMub2Zmc2V0O1xuICAgICAgICBjb25zdCB0aWNrcyA9IFtdO1xuICAgICAgICBsZXQgbGFiZWxzID0gdGhpcy5nZXRMYWJlbHMoKTtcbiAgICAgICAgbGFiZWxzID0gbWluID09PSAwICYmIG1heCA9PT0gbGFiZWxzLmxlbmd0aCAtIDEgPyBsYWJlbHMgOiBsYWJlbHMuc2xpY2UobWluLCBtYXggKyAxKTtcbiAgICAgICAgdGhpcy5fdmFsdWVSYW5nZSA9IE1hdGgubWF4KGxhYmVscy5sZW5ndGggLSAob2Zmc2V0ID8gMCA6IDEpLCAxKTtcbiAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHRoaXMubWluIC0gKG9mZnNldCA/IDAuNSA6IDApO1xuICAgICAgICBmb3IobGV0IHZhbHVlID0gbWluOyB2YWx1ZSA8PSBtYXg7IHZhbHVlKyspe1xuICAgICAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aWNrcztcbiAgICB9XG4gICAgZ2V0TGFiZWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gX2dldExhYmVsRm9yVmFsdWUuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgfVxuIGNvbmZpZ3VyZSgpIHtcbiAgICAgICAgc3VwZXIuY29uZmlndXJlKCk7XG4gICAgICAgIGlmICghdGhpcy5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgdGhpcy5fcmV2ZXJzZVBpeGVscyA9ICF0aGlzLl9yZXZlcnNlUGl4ZWxzO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldFBpeGVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5wYXJzZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gTmFOIDogdGhpcy5nZXRQaXhlbEZvckRlY2ltYWwoKHZhbHVlIC0gdGhpcy5fc3RhcnRWYWx1ZSkgLyB0aGlzLl92YWx1ZVJhbmdlKTtcbiAgICB9XG4gICAgZ2V0UGl4ZWxGb3JUaWNrKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHRpY2tzID0gdGhpcy50aWNrcztcbiAgICAgICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+IHRpY2tzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBpeGVsRm9yVmFsdWUodGlja3NbaW5kZXhdLnZhbHVlKTtcbiAgICB9XG4gICAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh0aGlzLl9zdGFydFZhbHVlICsgdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpICogdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxuICAgIGdldEJhc2VQaXhlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVUaWNrcyQxKGdlbmVyYXRpb25PcHRpb25zLCBkYXRhUmFuZ2UpIHtcbiAgICBjb25zdCB0aWNrcyA9IFtdO1xuICAgIGNvbnN0IE1JTl9TUEFDSU5HID0gMWUtMTQ7XG4gICAgY29uc3QgeyBib3VuZHMgLCBzdGVwICwgbWluICwgbWF4ICwgcHJlY2lzaW9uICwgY291bnQgLCBtYXhUaWNrcyAsIG1heERpZ2l0cyAsIGluY2x1ZGVCb3VuZHMgIH0gPSBnZW5lcmF0aW9uT3B0aW9ucztcbiAgICBjb25zdCB1bml0ID0gc3RlcCB8fCAxO1xuICAgIGNvbnN0IG1heFNwYWNlcyA9IG1heFRpY2tzIC0gMTtcbiAgICBjb25zdCB7IG1pbjogcm1pbiAsIG1heDogcm1heCAgfSA9IGRhdGFSYW5nZTtcbiAgICBjb25zdCBtaW5EZWZpbmVkID0gIWlzTnVsbE9yVW5kZWYobWluKTtcbiAgICBjb25zdCBtYXhEZWZpbmVkID0gIWlzTnVsbE9yVW5kZWYobWF4KTtcbiAgICBjb25zdCBjb3VudERlZmluZWQgPSAhaXNOdWxsT3JVbmRlZihjb3VudCk7XG4gICAgY29uc3QgbWluU3BhY2luZyA9IChybWF4IC0gcm1pbikgLyAobWF4RGlnaXRzICsgMSk7XG4gICAgbGV0IHNwYWNpbmcgPSBuaWNlTnVtKChybWF4IC0gcm1pbikgLyBtYXhTcGFjZXMgLyB1bml0KSAqIHVuaXQ7XG4gICAgbGV0IGZhY3RvciwgbmljZU1pbiwgbmljZU1heCwgbnVtU3BhY2VzO1xuICAgIGlmIChzcGFjaW5nIDwgTUlOX1NQQUNJTkcgJiYgIW1pbkRlZmluZWQgJiYgIW1heERlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogcm1pblxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogcm1heFxuICAgICAgICAgICAgfVxuICAgICAgICBdO1xuICAgIH1cbiAgICBudW1TcGFjZXMgPSBNYXRoLmNlaWwocm1heCAvIHNwYWNpbmcpIC0gTWF0aC5mbG9vcihybWluIC8gc3BhY2luZyk7XG4gICAgaWYgKG51bVNwYWNlcyA+IG1heFNwYWNlcykge1xuICAgICAgICBzcGFjaW5nID0gbmljZU51bShudW1TcGFjZXMgKiBzcGFjaW5nIC8gbWF4U3BhY2VzIC8gdW5pdCkgKiB1bml0O1xuICAgIH1cbiAgICBpZiAoIWlzTnVsbE9yVW5kZWYocHJlY2lzaW9uKSkge1xuICAgICAgICBmYWN0b3IgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKTtcbiAgICAgICAgc3BhY2luZyA9IE1hdGguY2VpbChzcGFjaW5nICogZmFjdG9yKSAvIGZhY3RvcjtcbiAgICB9XG4gICAgaWYgKGJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICBuaWNlTWluID0gTWF0aC5mbG9vcihybWluIC8gc3BhY2luZykgKiBzcGFjaW5nO1xuICAgICAgICBuaWNlTWF4ID0gTWF0aC5jZWlsKHJtYXggLyBzcGFjaW5nKSAqIHNwYWNpbmc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmljZU1pbiA9IHJtaW47XG4gICAgICAgIG5pY2VNYXggPSBybWF4O1xuICAgIH1cbiAgICBpZiAobWluRGVmaW5lZCAmJiBtYXhEZWZpbmVkICYmIHN0ZXAgJiYgYWxtb3N0V2hvbGUoKG1heCAtIG1pbikgLyBzdGVwLCBzcGFjaW5nIC8gMTAwMCkpIHtcbiAgICAgICAgbnVtU3BhY2VzID0gTWF0aC5yb3VuZChNYXRoLm1pbigobWF4IC0gbWluKSAvIHNwYWNpbmcsIG1heFRpY2tzKSk7XG4gICAgICAgIHNwYWNpbmcgPSAobWF4IC0gbWluKSAvIG51bVNwYWNlcztcbiAgICAgICAgbmljZU1pbiA9IG1pbjtcbiAgICAgICAgbmljZU1heCA9IG1heDtcbiAgICB9IGVsc2UgaWYgKGNvdW50RGVmaW5lZCkge1xuICAgICAgICBuaWNlTWluID0gbWluRGVmaW5lZCA/IG1pbiA6IG5pY2VNaW47XG4gICAgICAgIG5pY2VNYXggPSBtYXhEZWZpbmVkID8gbWF4IDogbmljZU1heDtcbiAgICAgICAgbnVtU3BhY2VzID0gY291bnQgLSAxO1xuICAgICAgICBzcGFjaW5nID0gKG5pY2VNYXggLSBuaWNlTWluKSAvIG51bVNwYWNlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBudW1TcGFjZXMgPSAobmljZU1heCAtIG5pY2VNaW4pIC8gc3BhY2luZztcbiAgICAgICAgaWYgKGFsbW9zdEVxdWFscyhudW1TcGFjZXMsIE1hdGgucm91bmQobnVtU3BhY2VzKSwgc3BhY2luZyAvIDEwMDApKSB7XG4gICAgICAgICAgICBudW1TcGFjZXMgPSBNYXRoLnJvdW5kKG51bVNwYWNlcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBudW1TcGFjZXMgPSBNYXRoLmNlaWwobnVtU3BhY2VzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBkZWNpbWFsUGxhY2VzID0gTWF0aC5tYXgoX2RlY2ltYWxQbGFjZXMoc3BhY2luZyksIF9kZWNpbWFsUGxhY2VzKG5pY2VNaW4pKTtcbiAgICBmYWN0b3IgPSBNYXRoLnBvdygxMCwgaXNOdWxsT3JVbmRlZihwcmVjaXNpb24pID8gZGVjaW1hbFBsYWNlcyA6IHByZWNpc2lvbik7XG4gICAgbmljZU1pbiA9IE1hdGgucm91bmQobmljZU1pbiAqIGZhY3RvcikgLyBmYWN0b3I7XG4gICAgbmljZU1heCA9IE1hdGgucm91bmQobmljZU1heCAqIGZhY3RvcikgLyBmYWN0b3I7XG4gICAgbGV0IGogPSAwO1xuICAgIGlmIChtaW5EZWZpbmVkKSB7XG4gICAgICAgIGlmIChpbmNsdWRlQm91bmRzICYmIG5pY2VNaW4gIT09IG1pbikge1xuICAgICAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICAgICAgdmFsdWU6IG1pblxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAobmljZU1pbiA8IG1pbikge1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhbG1vc3RFcXVhbHMoTWF0aC5yb3VuZCgobmljZU1pbiArIGogKiBzcGFjaW5nKSAqIGZhY3RvcikgLyBmYWN0b3IsIG1pbiwgcmVsYXRpdmVMYWJlbFNpemUobWluLCBtaW5TcGFjaW5nLCBnZW5lcmF0aW9uT3B0aW9ucykpKSB7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5pY2VNaW4gPCBtaW4pIHtcbiAgICAgICAgICAgIGorKztcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IoOyBqIDwgbnVtU3BhY2VzOyArK2ope1xuICAgICAgICBjb25zdCB0aWNrVmFsdWUgPSBNYXRoLnJvdW5kKChuaWNlTWluICsgaiAqIHNwYWNpbmcpICogZmFjdG9yKSAvIGZhY3RvcjtcbiAgICAgICAgaWYgKG1heERlZmluZWQgJiYgdGlja1ZhbHVlID4gbWF4KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgIHZhbHVlOiB0aWNrVmFsdWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChtYXhEZWZpbmVkICYmIGluY2x1ZGVCb3VuZHMgJiYgbmljZU1heCAhPT0gbWF4KSB7XG4gICAgICAgIGlmICh0aWNrcy5sZW5ndGggJiYgYWxtb3N0RXF1YWxzKHRpY2tzW3RpY2tzLmxlbmd0aCAtIDFdLnZhbHVlLCBtYXgsIHJlbGF0aXZlTGFiZWxTaXplKG1heCwgbWluU3BhY2luZywgZ2VuZXJhdGlvbk9wdGlvbnMpKSkge1xuICAgICAgICAgICAgdGlja3NbdGlja3MubGVuZ3RoIC0gMV0udmFsdWUgPSBtYXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogbWF4XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIW1heERlZmluZWQgfHwgbmljZU1heCA9PT0gbWF4KSB7XG4gICAgICAgIHRpY2tzLnB1c2goe1xuICAgICAgICAgICAgdmFsdWU6IG5pY2VNYXhcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aWNrcztcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlTGFiZWxTaXplKHZhbHVlLCBtaW5TcGFjaW5nLCB7IGhvcml6b250YWwgLCBtaW5Sb3RhdGlvbiAgfSkge1xuICAgIGNvbnN0IHJhZCA9IHRvUmFkaWFucyhtaW5Sb3RhdGlvbik7XG4gICAgY29uc3QgcmF0aW8gPSAoaG9yaXpvbnRhbCA/IE1hdGguc2luKHJhZCkgOiBNYXRoLmNvcyhyYWQpKSB8fCAwLjAwMTtcbiAgICBjb25zdCBsZW5ndGggPSAwLjc1ICogbWluU3BhY2luZyAqICgnJyArIHZhbHVlKS5sZW5ndGg7XG4gICAgcmV0dXJuIE1hdGgubWluKG1pblNwYWNpbmcgLyByYXRpbywgbGVuZ3RoKTtcbn1cbmNsYXNzIExpbmVhclNjYWxlQmFzZSBleHRlbmRzIFNjYWxlIHtcbiAgICBjb25zdHJ1Y3RvcihjZmcpe1xuICAgICAgICBzdXBlcihjZmcpO1xuICAgICAgICAgdGhpcy5zdGFydCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuZW5kID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5fc3RhcnRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuX2VuZFZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gMDtcbiAgICB9XG4gICAgcGFyc2UocmF3LCBpbmRleCkge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZihyYXcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHR5cGVvZiByYXcgPT09ICdudW1iZXInIHx8IHJhdyBpbnN0YW5jZW9mIE51bWJlcikgJiYgIWlzRmluaXRlKCtyYXcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gK3JhdztcbiAgICB9XG4gICAgaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpIHtcbiAgICAgICAgY29uc3QgeyBiZWdpbkF0WmVybyAgfSA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgeyBtaW5EZWZpbmVkICwgbWF4RGVmaW5lZCAgfSA9IHRoaXMuZ2V0VXNlckJvdW5kcygpO1xuICAgICAgICBsZXQgeyBtaW4gLCBtYXggIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBzZXRNaW4gPSAodik9Pm1pbiA9IG1pbkRlZmluZWQgPyBtaW4gOiB2O1xuICAgICAgICBjb25zdCBzZXRNYXggPSAodik9Pm1heCA9IG1heERlZmluZWQgPyBtYXggOiB2O1xuICAgICAgICBpZiAoYmVnaW5BdFplcm8pIHtcbiAgICAgICAgICAgIGNvbnN0IG1pblNpZ24gPSBzaWduKG1pbik7XG4gICAgICAgICAgICBjb25zdCBtYXhTaWduID0gc2lnbihtYXgpO1xuICAgICAgICAgICAgaWYgKG1pblNpZ24gPCAwICYmIG1heFNpZ24gPCAwKSB7XG4gICAgICAgICAgICAgICAgc2V0TWF4KDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtaW5TaWduID4gMCAmJiBtYXhTaWduID4gMCkge1xuICAgICAgICAgICAgICAgIHNldE1pbigwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobWluID09PSBtYXgpIHtcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSBtYXggPT09IDAgPyAxIDogTWF0aC5hYnMobWF4ICogMC4wNSk7XG4gICAgICAgICAgICBzZXRNYXgobWF4ICsgb2Zmc2V0KTtcbiAgICAgICAgICAgIGlmICghYmVnaW5BdFplcm8pIHtcbiAgICAgICAgICAgICAgICBzZXRNaW4obWluIC0gb2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pbiA9IG1pbjtcbiAgICAgICAgdGhpcy5tYXggPSBtYXg7XG4gICAgfVxuICAgIGdldFRpY2tMaW1pdCgpIHtcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSB0aGlzLm9wdGlvbnMudGlja3M7XG4gICAgICAgIGxldCB7IG1heFRpY2tzTGltaXQgLCBzdGVwU2l6ZSAgfSA9IHRpY2tPcHRzO1xuICAgICAgICBsZXQgbWF4VGlja3M7XG4gICAgICAgIGlmIChzdGVwU2l6ZSkge1xuICAgICAgICAgICAgbWF4VGlja3MgPSBNYXRoLmNlaWwodGhpcy5tYXggLyBzdGVwU2l6ZSkgLSBNYXRoLmZsb29yKHRoaXMubWluIC8gc3RlcFNpemUpICsgMTtcbiAgICAgICAgICAgIGlmIChtYXhUaWNrcyA+IDEwMDApIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYHNjYWxlcy4ke3RoaXMuaWR9LnRpY2tzLnN0ZXBTaXplOiAke3N0ZXBTaXplfSB3b3VsZCByZXN1bHQgZ2VuZXJhdGluZyB1cCB0byAke21heFRpY2tzfSB0aWNrcy4gTGltaXRpbmcgdG8gMTAwMC5gKTtcbiAgICAgICAgICAgICAgICBtYXhUaWNrcyA9IDEwMDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXhUaWNrcyA9IHRoaXMuY29tcHV0ZVRpY2tMaW1pdCgpO1xuICAgICAgICAgICAgbWF4VGlja3NMaW1pdCA9IG1heFRpY2tzTGltaXQgfHwgMTE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1heFRpY2tzTGltaXQpIHtcbiAgICAgICAgICAgIG1heFRpY2tzID0gTWF0aC5taW4obWF4VGlja3NMaW1pdCwgbWF4VGlja3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXhUaWNrcztcbiAgICB9XG4gY29tcHV0ZVRpY2tMaW1pdCgpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICB9XG4gICAgYnVpbGRUaWNrcygpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRzLnRpY2tzO1xuICAgICAgICBsZXQgbWF4VGlja3MgPSB0aGlzLmdldFRpY2tMaW1pdCgpO1xuICAgICAgICBtYXhUaWNrcyA9IE1hdGgubWF4KDIsIG1heFRpY2tzKTtcbiAgICAgICAgY29uc3QgbnVtZXJpY0dlbmVyYXRvck9wdGlvbnMgPSB7XG4gICAgICAgICAgICBtYXhUaWNrcyxcbiAgICAgICAgICAgIGJvdW5kczogb3B0cy5ib3VuZHMsXG4gICAgICAgICAgICBtaW46IG9wdHMubWluLFxuICAgICAgICAgICAgbWF4OiBvcHRzLm1heCxcbiAgICAgICAgICAgIHByZWNpc2lvbjogdGlja09wdHMucHJlY2lzaW9uLFxuICAgICAgICAgICAgc3RlcDogdGlja09wdHMuc3RlcFNpemUsXG4gICAgICAgICAgICBjb3VudDogdGlja09wdHMuY291bnQsXG4gICAgICAgICAgICBtYXhEaWdpdHM6IHRoaXMuX21heERpZ2l0cygpLFxuICAgICAgICAgICAgaG9yaXpvbnRhbDogdGhpcy5pc0hvcml6b250YWwoKSxcbiAgICAgICAgICAgIG1pblJvdGF0aW9uOiB0aWNrT3B0cy5taW5Sb3RhdGlvbiB8fCAwLFxuICAgICAgICAgICAgaW5jbHVkZUJvdW5kczogdGlja09wdHMuaW5jbHVkZUJvdW5kcyAhPT0gZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGF0YVJhbmdlID0gdGhpcy5fcmFuZ2UgfHwgdGhpcztcbiAgICAgICAgY29uc3QgdGlja3MgPSBnZW5lcmF0ZVRpY2tzJDEobnVtZXJpY0dlbmVyYXRvck9wdGlvbnMsIGRhdGFSYW5nZSk7XG4gICAgICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCB0aGlzLCAndmFsdWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5yZXZlcnNlKSB7XG4gICAgICAgICAgICB0aWNrcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0ID0gdGhpcy5tYXg7XG4gICAgICAgICAgICB0aGlzLmVuZCA9IHRoaXMubWluO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdGFydCA9IHRoaXMubWluO1xuICAgICAgICAgICAgdGhpcy5lbmQgPSB0aGlzLm1heDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGlja3M7XG4gICAgfVxuIGNvbmZpZ3VyZSgpIHtcbiAgICAgICAgY29uc3QgdGlja3MgPSB0aGlzLnRpY2tzO1xuICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLm1pbjtcbiAgICAgICAgbGV0IGVuZCA9IHRoaXMubWF4O1xuICAgICAgICBzdXBlci5jb25maWd1cmUoKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5vZmZzZXQgJiYgdGlja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSAoZW5kIC0gc3RhcnQpIC8gTWF0aC5tYXgodGlja3MubGVuZ3RoIC0gMSwgMSkgLyAyO1xuICAgICAgICAgICAgc3RhcnQgLT0gb2Zmc2V0O1xuICAgICAgICAgICAgZW5kICs9IG9mZnNldDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdGFydFZhbHVlID0gc3RhcnQ7XG4gICAgICAgIHRoaXMuX2VuZFZhbHVlID0gZW5kO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gZW5kIC0gc3RhcnQ7XG4gICAgfVxuICAgIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGZvcm1hdE51bWJlcih2YWx1ZSwgdGhpcy5jaGFydC5vcHRpb25zLmxvY2FsZSwgdGhpcy5vcHRpb25zLnRpY2tzLmZvcm1hdCk7XG4gICAgfVxufVxuXG5jbGFzcyBMaW5lYXJTY2FsZSBleHRlbmRzIExpbmVhclNjYWxlQmFzZSB7XG4gICAgc3RhdGljIGlkID0gJ2xpbmVhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICB0aWNrczoge1xuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubnVtZXJpY1xuICAgICAgICB9XG4gICAgfTtcbiAgICBkZXRlcm1pbmVEYXRhTGltaXRzKCkge1xuICAgICAgICBjb25zdCB7IG1pbiAsIG1heCAgfSA9IHRoaXMuZ2V0TWluTWF4KHRydWUpO1xuICAgICAgICB0aGlzLm1pbiA9IGlzTnVtYmVyRmluaXRlKG1pbikgPyBtaW4gOiAwO1xuICAgICAgICB0aGlzLm1heCA9IGlzTnVtYmVyRmluaXRlKG1heCkgPyBtYXggOiAxO1xuICAgICAgICB0aGlzLmhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKTtcbiAgICB9XG4gY29tcHV0ZVRpY2tMaW1pdCgpIHtcbiAgICAgICAgY29uc3QgaG9yaXpvbnRhbCA9IHRoaXMuaXNIb3Jpem9udGFsKCk7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IGhvcml6b250YWwgPyB0aGlzLndpZHRoIDogdGhpcy5oZWlnaHQ7XG4gICAgICAgIGNvbnN0IG1pblJvdGF0aW9uID0gdG9SYWRpYW5zKHRoaXMub3B0aW9ucy50aWNrcy5taW5Sb3RhdGlvbik7XG4gICAgICAgIGNvbnN0IHJhdGlvID0gKGhvcml6b250YWwgPyBNYXRoLnNpbihtaW5Sb3RhdGlvbikgOiBNYXRoLmNvcyhtaW5Sb3RhdGlvbikpIHx8IDAuMDAxO1xuICAgICAgICBjb25zdCB0aWNrRm9udCA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCk7XG4gICAgICAgIHJldHVybiBNYXRoLmNlaWwobGVuZ3RoIC8gTWF0aC5taW4oNDAsIHRpY2tGb250LmxpbmVIZWlnaHQgLyByYXRpbykpO1xuICAgIH1cbiAgICBnZXRQaXhlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbCA/IE5hTiA6IHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKCh2YWx1ZSAtIHRoaXMuX3N0YXJ0VmFsdWUpIC8gdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxuICAgIGdldFZhbHVlRm9yUGl4ZWwocGl4ZWwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXJ0VmFsdWUgKyB0aGlzLmdldERlY2ltYWxGb3JQaXhlbChwaXhlbCkgKiB0aGlzLl92YWx1ZVJhbmdlO1xuICAgIH1cbn1cblxuY29uc3QgbG9nMTBGbG9vciA9ICh2KT0+TWF0aC5mbG9vcihsb2cxMCh2KSk7XG5jb25zdCBjaGFuZ2VFeHBvbmVudCA9ICh2LCBtKT0+TWF0aC5wb3coMTAsIGxvZzEwRmxvb3IodikgKyBtKTtcbmZ1bmN0aW9uIGlzTWFqb3IodGlja1ZhbCkge1xuICAgIGNvbnN0IHJlbWFpbiA9IHRpY2tWYWwgLyBNYXRoLnBvdygxMCwgbG9nMTBGbG9vcih0aWNrVmFsKSk7XG4gICAgcmV0dXJuIHJlbWFpbiA9PT0gMTtcbn1cbmZ1bmN0aW9uIHN0ZXBzKG1pbiwgbWF4LCByYW5nZUV4cCkge1xuICAgIGNvbnN0IHJhbmdlU3RlcCA9IE1hdGgucG93KDEwLCByYW5nZUV4cCk7XG4gICAgY29uc3Qgc3RhcnQgPSBNYXRoLmZsb29yKG1pbiAvIHJhbmdlU3RlcCk7XG4gICAgY29uc3QgZW5kID0gTWF0aC5jZWlsKG1heCAvIHJhbmdlU3RlcCk7XG4gICAgcmV0dXJuIGVuZCAtIHN0YXJ0O1xufVxuZnVuY3Rpb24gc3RhcnRFeHAobWluLCBtYXgpIHtcbiAgICBjb25zdCByYW5nZSA9IG1heCAtIG1pbjtcbiAgICBsZXQgcmFuZ2VFeHAgPSBsb2cxMEZsb29yKHJhbmdlKTtcbiAgICB3aGlsZShzdGVwcyhtaW4sIG1heCwgcmFuZ2VFeHApID4gMTApe1xuICAgICAgICByYW5nZUV4cCsrO1xuICAgIH1cbiAgICB3aGlsZShzdGVwcyhtaW4sIG1heCwgcmFuZ2VFeHApIDwgMTApe1xuICAgICAgICByYW5nZUV4cC0tO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5taW4ocmFuZ2VFeHAsIGxvZzEwRmxvb3IobWluKSk7XG59XG4gZnVuY3Rpb24gZ2VuZXJhdGVUaWNrcyhnZW5lcmF0aW9uT3B0aW9ucywgeyBtaW4gLCBtYXggIH0pIHtcbiAgICBtaW4gPSBmaW5pdGVPckRlZmF1bHQoZ2VuZXJhdGlvbk9wdGlvbnMubWluLCBtaW4pO1xuICAgIGNvbnN0IHRpY2tzID0gW107XG4gICAgY29uc3QgbWluRXhwID0gbG9nMTBGbG9vcihtaW4pO1xuICAgIGxldCBleHAgPSBzdGFydEV4cChtaW4sIG1heCk7XG4gICAgbGV0IHByZWNpc2lvbiA9IGV4cCA8IDAgPyBNYXRoLnBvdygxMCwgTWF0aC5hYnMoZXhwKSkgOiAxO1xuICAgIGNvbnN0IHN0ZXBTaXplID0gTWF0aC5wb3coMTAsIGV4cCk7XG4gICAgY29uc3QgYmFzZSA9IG1pbkV4cCA+IGV4cCA/IE1hdGgucG93KDEwLCBtaW5FeHApIDogMDtcbiAgICBjb25zdCBzdGFydCA9IE1hdGgucm91bmQoKG1pbiAtIGJhc2UpICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbjtcbiAgICBjb25zdCBvZmZzZXQgPSBNYXRoLmZsb29yKChtaW4gLSBiYXNlKSAvIHN0ZXBTaXplIC8gMTApICogc3RlcFNpemUgKiAxMDtcbiAgICBsZXQgc2lnbmlmaWNhbmQgPSBNYXRoLmZsb29yKChzdGFydCAtIG9mZnNldCkgLyBNYXRoLnBvdygxMCwgZXhwKSk7XG4gICAgbGV0IHZhbHVlID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1pbiwgTWF0aC5yb3VuZCgoYmFzZSArIG9mZnNldCArIHNpZ25pZmljYW5kICogTWF0aC5wb3coMTAsIGV4cCkpICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbik7XG4gICAgd2hpbGUodmFsdWUgPCBtYXgpe1xuICAgICAgICB0aWNrcy5wdXNoKHtcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgbWFqb3I6IGlzTWFqb3IodmFsdWUpLFxuICAgICAgICAgICAgc2lnbmlmaWNhbmRcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChzaWduaWZpY2FuZCA+PSAxMCkge1xuICAgICAgICAgICAgc2lnbmlmaWNhbmQgPSBzaWduaWZpY2FuZCA8IDE1ID8gMTUgOiAyMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNpZ25pZmljYW5kKys7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNpZ25pZmljYW5kID49IDIwKSB7XG4gICAgICAgICAgICBleHArKztcbiAgICAgICAgICAgIHNpZ25pZmljYW5kID0gMjtcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IGV4cCA+PSAwID8gMSA6IHByZWNpc2lvbjtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9IE1hdGgucm91bmQoKGJhc2UgKyBvZmZzZXQgKyBzaWduaWZpY2FuZCAqIE1hdGgucG93KDEwLCBleHApKSAqIHByZWNpc2lvbikgLyBwcmVjaXNpb247XG4gICAgfVxuICAgIGNvbnN0IGxhc3RUaWNrID0gZmluaXRlT3JEZWZhdWx0KGdlbmVyYXRpb25PcHRpb25zLm1heCwgdmFsdWUpO1xuICAgIHRpY2tzLnB1c2goe1xuICAgICAgICB2YWx1ZTogbGFzdFRpY2ssXG4gICAgICAgIG1ham9yOiBpc01ham9yKGxhc3RUaWNrKSxcbiAgICAgICAgc2lnbmlmaWNhbmRcbiAgICB9KTtcbiAgICByZXR1cm4gdGlja3M7XG59XG5jbGFzcyBMb2dhcml0aG1pY1NjYWxlIGV4dGVuZHMgU2NhbGUge1xuICAgIHN0YXRpYyBpZCA9ICdsb2dhcml0aG1pYyc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICB0aWNrczoge1xuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubG9nYXJpdGhtaWMsXG4gICAgICAgICAgICBtYWpvcjoge1xuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoY2ZnKTtcbiAgICAgICAgIHRoaXMuc3RhcnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLmVuZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuX3N0YXJ0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3ZhbHVlUmFuZ2UgPSAwO1xuICAgIH1cbiAgICBwYXJzZShyYXcsIGluZGV4KSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gTGluZWFyU2NhbGVCYXNlLnByb3RvdHlwZS5wYXJzZS5hcHBseSh0aGlzLCBbXG4gICAgICAgICAgICByYXcsXG4gICAgICAgICAgICBpbmRleFxuICAgICAgICBdKTtcbiAgICAgICAgaWYgKHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLl96ZXJvID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzTnVtYmVyRmluaXRlKHZhbHVlKSAmJiB2YWx1ZSA+IDAgPyB2YWx1ZSA6IG51bGw7XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IHsgbWluICwgbWF4ICB9ID0gdGhpcy5nZXRNaW5NYXgodHJ1ZSk7XG4gICAgICAgIHRoaXMubWluID0gaXNOdW1iZXJGaW5pdGUobWluKSA/IE1hdGgubWF4KDAsIG1pbikgOiBudWxsO1xuICAgICAgICB0aGlzLm1heCA9IGlzTnVtYmVyRmluaXRlKG1heCkgPyBNYXRoLm1heCgwLCBtYXgpIDogbnVsbDtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5iZWdpbkF0WmVybykge1xuICAgICAgICAgICAgdGhpcy5femVybyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3plcm8gJiYgdGhpcy5taW4gIT09IHRoaXMuX3N1Z2dlc3RlZE1pbiAmJiAhaXNOdW1iZXJGaW5pdGUodGhpcy5fdXNlck1pbikpIHtcbiAgICAgICAgICAgIHRoaXMubWluID0gbWluID09PSBjaGFuZ2VFeHBvbmVudCh0aGlzLm1pbiwgMCkgPyBjaGFuZ2VFeHBvbmVudCh0aGlzLm1pbiwgLTEpIDogY2hhbmdlRXhwb25lbnQodGhpcy5taW4sIDApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICAgIH1cbiAgICBoYW5kbGVUaWNrUmFuZ2VPcHRpb25zKCkge1xuICAgICAgICBjb25zdCB7IG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gdGhpcy5nZXRVc2VyQm91bmRzKCk7XG4gICAgICAgIGxldCBtaW4gPSB0aGlzLm1pbjtcbiAgICAgICAgbGV0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBzZXRNaW4gPSAodik9Pm1pbiA9IG1pbkRlZmluZWQgPyBtaW4gOiB2O1xuICAgICAgICBjb25zdCBzZXRNYXggPSAodik9Pm1heCA9IG1heERlZmluZWQgPyBtYXggOiB2O1xuICAgICAgICBpZiAobWluID09PSBtYXgpIHtcbiAgICAgICAgICAgIGlmIChtaW4gPD0gMCkge1xuICAgICAgICAgICAgICAgIHNldE1pbigxKTtcbiAgICAgICAgICAgICAgICBzZXRNYXgoMTApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXRNaW4oY2hhbmdlRXhwb25lbnQobWluLCAtMSkpO1xuICAgICAgICAgICAgICAgIHNldE1heChjaGFuZ2VFeHBvbmVudChtYXgsICsxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1pbiA8PSAwKSB7XG4gICAgICAgICAgICBzZXRNaW4oY2hhbmdlRXhwb25lbnQobWF4LCAtMSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXggPD0gMCkge1xuICAgICAgICAgICAgc2V0TWF4KGNoYW5nZUV4cG9uZW50KG1pbiwgKzEpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pbiA9IG1pbjtcbiAgICAgICAgdGhpcy5tYXggPSBtYXg7XG4gICAgfVxuICAgIGJ1aWxkVGlja3MoKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGdlbmVyYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgbWluOiB0aGlzLl91c2VyTWluLFxuICAgICAgICAgICAgbWF4OiB0aGlzLl91c2VyTWF4XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHRpY2tzID0gZ2VuZXJhdGVUaWNrcyhnZW5lcmF0aW9uT3B0aW9ucywgdGhpcyk7XG4gICAgICAgIGlmIChvcHRzLmJvdW5kcyA9PT0gJ3RpY2tzJykge1xuICAgICAgICAgICAgX3NldE1pbkFuZE1heEJ5S2V5KHRpY2tzLCB0aGlzLCAndmFsdWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5yZXZlcnNlKSB7XG4gICAgICAgICAgICB0aWNrcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0ID0gdGhpcy5tYXg7XG4gICAgICAgICAgICB0aGlzLmVuZCA9IHRoaXMubWluO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdGFydCA9IHRoaXMubWluO1xuICAgICAgICAgICAgdGhpcy5lbmQgPSB0aGlzLm1heDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGlja3M7XG4gICAgfVxuIGdldExhYmVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyAnMCcgOiBmb3JtYXROdW1iZXIodmFsdWUsIHRoaXMuY2hhcnQub3B0aW9ucy5sb2NhbGUsIHRoaXMub3B0aW9ucy50aWNrcy5mb3JtYXQpO1xuICAgIH1cbiBjb25maWd1cmUoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5taW47XG4gICAgICAgIHN1cGVyLmNvbmZpZ3VyZSgpO1xuICAgICAgICB0aGlzLl9zdGFydFZhbHVlID0gbG9nMTAoc3RhcnQpO1xuICAgICAgICB0aGlzLl92YWx1ZVJhbmdlID0gbG9nMTAodGhpcy5tYXgpIC0gbG9nMTAoc3RhcnQpO1xuICAgIH1cbiAgICBnZXRQaXhlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWluO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKHZhbHVlID09PSB0aGlzLm1pbiA/IDAgOiAobG9nMTAodmFsdWUpIC0gdGhpcy5fc3RhcnRWYWx1ZSkgLyB0aGlzLl92YWx1ZVJhbmdlKTtcbiAgICB9XG4gICAgZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICBjb25zdCBkZWNpbWFsID0gdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpO1xuICAgICAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXJ0VmFsdWUgKyBkZWNpbWFsICogdGhpcy5fdmFsdWVSYW5nZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRUaWNrQmFja2Ryb3BIZWlnaHQob3B0cykge1xuICAgIGNvbnN0IHRpY2tPcHRzID0gb3B0cy50aWNrcztcbiAgICBpZiAodGlja09wdHMuZGlzcGxheSAmJiBvcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyh0aWNrT3B0cy5iYWNrZHJvcFBhZGRpbmcpO1xuICAgICAgICByZXR1cm4gdmFsdWVPckRlZmF1bHQodGlja09wdHMuZm9udCAmJiB0aWNrT3B0cy5mb250LnNpemUsIGRlZmF1bHRzLmZvbnQuc2l6ZSkgKyBwYWRkaW5nLmhlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5mdW5jdGlvbiBtZWFzdXJlTGFiZWxTaXplKGN0eCwgZm9udCwgbGFiZWwpIHtcbiAgICBsYWJlbCA9IGlzQXJyYXkobGFiZWwpID8gbGFiZWwgOiBbXG4gICAgICAgIGxhYmVsXG4gICAgXTtcbiAgICByZXR1cm4ge1xuICAgICAgICB3OiBfbG9uZ2VzdFRleHQoY3R4LCBmb250LnN0cmluZywgbGFiZWwpLFxuICAgICAgICBoOiBsYWJlbC5sZW5ndGggKiBmb250LmxpbmVIZWlnaHRcbiAgICB9O1xufVxuZnVuY3Rpb24gZGV0ZXJtaW5lTGltaXRzKGFuZ2xlLCBwb3MsIHNpemUsIG1pbiwgbWF4KSB7XG4gICAgaWYgKGFuZ2xlID09PSBtaW4gfHwgYW5nbGUgPT09IG1heCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IHBvcyAtIHNpemUgLyAyLFxuICAgICAgICAgICAgZW5kOiBwb3MgKyBzaXplIC8gMlxuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPCBtaW4gfHwgYW5nbGUgPiBtYXgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN0YXJ0OiBwb3MgLSBzaXplLFxuICAgICAgICAgICAgZW5kOiBwb3NcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHBvcyxcbiAgICAgICAgZW5kOiBwb3MgKyBzaXplXG4gICAgfTtcbn1cbiBmdW5jdGlvbiBmaXRXaXRoUG9pbnRMYWJlbHMoc2NhbGUpIHtcbiAgICBjb25zdCBvcmlnID0ge1xuICAgICAgICBsOiBzY2FsZS5sZWZ0ICsgc2NhbGUuX3BhZGRpbmcubGVmdCxcbiAgICAgICAgcjogc2NhbGUucmlnaHQgLSBzY2FsZS5fcGFkZGluZy5yaWdodCxcbiAgICAgICAgdDogc2NhbGUudG9wICsgc2NhbGUuX3BhZGRpbmcudG9wLFxuICAgICAgICBiOiBzY2FsZS5ib3R0b20gLSBzY2FsZS5fcGFkZGluZy5ib3R0b21cbiAgICB9O1xuICAgIGNvbnN0IGxpbWl0cyA9IE9iamVjdC5hc3NpZ24oe30sIG9yaWcpO1xuICAgIGNvbnN0IGxhYmVsU2l6ZXMgPSBbXTtcbiAgICBjb25zdCBwYWRkaW5nID0gW107XG4gICAgY29uc3QgdmFsdWVDb3VudCA9IHNjYWxlLl9wb2ludExhYmVscy5sZW5ndGg7XG4gICAgY29uc3QgcG9pbnRMYWJlbE9wdHMgPSBzY2FsZS5vcHRpb25zLnBvaW50TGFiZWxzO1xuICAgIGNvbnN0IGFkZGl0aW9uYWxBbmdsZSA9IHBvaW50TGFiZWxPcHRzLmNlbnRlclBvaW50TGFiZWxzID8gUEkgLyB2YWx1ZUNvdW50IDogMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdmFsdWVDb3VudDsgaSsrKXtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHBvaW50TGFiZWxPcHRzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgICAgICBwYWRkaW5nW2ldID0gb3B0cy5wYWRkaW5nO1xuICAgICAgICBjb25zdCBwb2ludFBvc2l0aW9uID0gc2NhbGUuZ2V0UG9pbnRQb3NpdGlvbihpLCBzY2FsZS5kcmF3aW5nQXJlYSArIHBhZGRpbmdbaV0sIGFkZGl0aW9uYWxBbmdsZSk7XG4gICAgICAgIGNvbnN0IHBsRm9udCA9IHRvRm9udChvcHRzLmZvbnQpO1xuICAgICAgICBjb25zdCB0ZXh0U2l6ZSA9IG1lYXN1cmVMYWJlbFNpemUoc2NhbGUuY3R4LCBwbEZvbnQsIHNjYWxlLl9wb2ludExhYmVsc1tpXSk7XG4gICAgICAgIGxhYmVsU2l6ZXNbaV0gPSB0ZXh0U2l6ZTtcbiAgICAgICAgY29uc3QgYW5nbGVSYWRpYW5zID0gX25vcm1hbGl6ZUFuZ2xlKHNjYWxlLmdldEluZGV4QW5nbGUoaSkgKyBhZGRpdGlvbmFsQW5nbGUpO1xuICAgICAgICBjb25zdCBhbmdsZSA9IE1hdGgucm91bmQodG9EZWdyZWVzKGFuZ2xlUmFkaWFucykpO1xuICAgICAgICBjb25zdCBoTGltaXRzID0gZGV0ZXJtaW5lTGltaXRzKGFuZ2xlLCBwb2ludFBvc2l0aW9uLngsIHRleHRTaXplLncsIDAsIDE4MCk7XG4gICAgICAgIGNvbnN0IHZMaW1pdHMgPSBkZXRlcm1pbmVMaW1pdHMoYW5nbGUsIHBvaW50UG9zaXRpb24ueSwgdGV4dFNpemUuaCwgOTAsIDI3MCk7XG4gICAgICAgIHVwZGF0ZUxpbWl0cyhsaW1pdHMsIG9yaWcsIGFuZ2xlUmFkaWFucywgaExpbWl0cywgdkxpbWl0cyk7XG4gICAgfVxuICAgIHNjYWxlLnNldENlbnRlclBvaW50KG9yaWcubCAtIGxpbWl0cy5sLCBsaW1pdHMuciAtIG9yaWcuciwgb3JpZy50IC0gbGltaXRzLnQsIGxpbWl0cy5iIC0gb3JpZy5iKTtcbiAgICBzY2FsZS5fcG9pbnRMYWJlbEl0ZW1zID0gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpO1xufVxuZnVuY3Rpb24gdXBkYXRlTGltaXRzKGxpbWl0cywgb3JpZywgYW5nbGUsIGhMaW1pdHMsIHZMaW1pdHMpIHtcbiAgICBjb25zdCBzaW4gPSBNYXRoLmFicyhNYXRoLnNpbihhbmdsZSkpO1xuICAgIGNvbnN0IGNvcyA9IE1hdGguYWJzKE1hdGguY29zKGFuZ2xlKSk7XG4gICAgbGV0IHggPSAwO1xuICAgIGxldCB5ID0gMDtcbiAgICBpZiAoaExpbWl0cy5zdGFydCA8IG9yaWcubCkge1xuICAgICAgICB4ID0gKG9yaWcubCAtIGhMaW1pdHMuc3RhcnQpIC8gc2luO1xuICAgICAgICBsaW1pdHMubCA9IE1hdGgubWluKGxpbWl0cy5sLCBvcmlnLmwgLSB4KTtcbiAgICB9IGVsc2UgaWYgKGhMaW1pdHMuZW5kID4gb3JpZy5yKSB7XG4gICAgICAgIHggPSAoaExpbWl0cy5lbmQgLSBvcmlnLnIpIC8gc2luO1xuICAgICAgICBsaW1pdHMuciA9IE1hdGgubWF4KGxpbWl0cy5yLCBvcmlnLnIgKyB4KTtcbiAgICB9XG4gICAgaWYgKHZMaW1pdHMuc3RhcnQgPCBvcmlnLnQpIHtcbiAgICAgICAgeSA9IChvcmlnLnQgLSB2TGltaXRzLnN0YXJ0KSAvIGNvcztcbiAgICAgICAgbGltaXRzLnQgPSBNYXRoLm1pbihsaW1pdHMudCwgb3JpZy50IC0geSk7XG4gICAgfSBlbHNlIGlmICh2TGltaXRzLmVuZCA+IG9yaWcuYikge1xuICAgICAgICB5ID0gKHZMaW1pdHMuZW5kIC0gb3JpZy5iKSAvIGNvcztcbiAgICAgICAgbGltaXRzLmIgPSBNYXRoLm1heChsaW1pdHMuYiwgb3JpZy5iICsgeSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY3JlYXRlUG9pbnRMYWJlbEl0ZW0oc2NhbGUsIGluZGV4LCBpdGVtT3B0cykge1xuICAgIGNvbnN0IG91dGVyRGlzdGFuY2UgPSBzY2FsZS5kcmF3aW5nQXJlYTtcbiAgICBjb25zdCB7IGV4dHJhICwgYWRkaXRpb25hbEFuZ2xlICwgcGFkZGluZyAsIHNpemUgIH0gPSBpdGVtT3B0cztcbiAgICBjb25zdCBwb2ludExhYmVsUG9zaXRpb24gPSBzY2FsZS5nZXRQb2ludFBvc2l0aW9uKGluZGV4LCBvdXRlckRpc3RhbmNlICsgZXh0cmEgKyBwYWRkaW5nLCBhZGRpdGlvbmFsQW5nbGUpO1xuICAgIGNvbnN0IGFuZ2xlID0gTWF0aC5yb3VuZCh0b0RlZ3JlZXMoX25vcm1hbGl6ZUFuZ2xlKHBvaW50TGFiZWxQb3NpdGlvbi5hbmdsZSArIEhBTEZfUEkpKSk7XG4gICAgY29uc3QgeSA9IHlGb3JBbmdsZShwb2ludExhYmVsUG9zaXRpb24ueSwgc2l6ZS5oLCBhbmdsZSk7XG4gICAgY29uc3QgdGV4dEFsaWduID0gZ2V0VGV4dEFsaWduRm9yQW5nbGUoYW5nbGUpO1xuICAgIGNvbnN0IGxlZnQgPSBsZWZ0Rm9yVGV4dEFsaWduKHBvaW50TGFiZWxQb3NpdGlvbi54LCBzaXplLncsIHRleHRBbGlnbik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgeDogcG9pbnRMYWJlbFBvc2l0aW9uLngsXG4gICAgICAgIHksXG4gICAgICAgIHRleHRBbGlnbixcbiAgICAgICAgbGVmdCxcbiAgICAgICAgdG9wOiB5LFxuICAgICAgICByaWdodDogbGVmdCArIHNpemUudyxcbiAgICAgICAgYm90dG9tOiB5ICsgc2l6ZS5oXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGlzTm90T3ZlcmxhcHBlZChpdGVtLCBhcmVhKSB7XG4gICAgaWYgKCFhcmVhKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCB7IGxlZnQgLCB0b3AgLCByaWdodCAsIGJvdHRvbSAgfSA9IGl0ZW07XG4gICAgY29uc3QgYXBleGVzSW5BcmVhID0gX2lzUG9pbnRJbkFyZWEoe1xuICAgICAgICB4OiBsZWZ0LFxuICAgICAgICB5OiB0b3BcbiAgICB9LCBhcmVhKSB8fCBfaXNQb2ludEluQXJlYSh7XG4gICAgICAgIHg6IGxlZnQsXG4gICAgICAgIHk6IGJvdHRvbVxuICAgIH0sIGFyZWEpIHx8IF9pc1BvaW50SW5BcmVhKHtcbiAgICAgICAgeDogcmlnaHQsXG4gICAgICAgIHk6IHRvcFxuICAgIH0sIGFyZWEpIHx8IF9pc1BvaW50SW5BcmVhKHtcbiAgICAgICAgeDogcmlnaHQsXG4gICAgICAgIHk6IGJvdHRvbVxuICAgIH0sIGFyZWEpO1xuICAgIHJldHVybiAhYXBleGVzSW5BcmVhO1xufVxuZnVuY3Rpb24gYnVpbGRQb2ludExhYmVsSXRlbXMoc2NhbGUsIGxhYmVsU2l6ZXMsIHBhZGRpbmcpIHtcbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IHZhbHVlQ291bnQgPSBzY2FsZS5fcG9pbnRMYWJlbHMubGVuZ3RoO1xuICAgIGNvbnN0IG9wdHMgPSBzY2FsZS5vcHRpb25zO1xuICAgIGNvbnN0IHsgY2VudGVyUG9pbnRMYWJlbHMgLCBkaXNwbGF5ICB9ID0gb3B0cy5wb2ludExhYmVscztcbiAgICBjb25zdCBpdGVtT3B0cyA9IHtcbiAgICAgICAgZXh0cmE6IGdldFRpY2tCYWNrZHJvcEhlaWdodChvcHRzKSAvIDIsXG4gICAgICAgIGFkZGl0aW9uYWxBbmdsZTogY2VudGVyUG9pbnRMYWJlbHMgPyBQSSAvIHZhbHVlQ291bnQgOiAwXG4gICAgfTtcbiAgICBsZXQgYXJlYTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdmFsdWVDb3VudDsgaSsrKXtcbiAgICAgICAgaXRlbU9wdHMucGFkZGluZyA9IHBhZGRpbmdbaV07XG4gICAgICAgIGl0ZW1PcHRzLnNpemUgPSBsYWJlbFNpemVzW2ldO1xuICAgICAgICBjb25zdCBpdGVtID0gY3JlYXRlUG9pbnRMYWJlbEl0ZW0oc2NhbGUsIGksIGl0ZW1PcHRzKTtcbiAgICAgICAgaXRlbXMucHVzaChpdGVtKTtcbiAgICAgICAgaWYgKGRpc3BsYXkgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgaXRlbS52aXNpYmxlID0gaXNOb3RPdmVybGFwcGVkKGl0ZW0sIGFyZWEpO1xuICAgICAgICAgICAgaWYgKGl0ZW0udmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIGFyZWEgPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbn1cbmZ1bmN0aW9uIGdldFRleHRBbGlnbkZvckFuZ2xlKGFuZ2xlKSB7XG4gICAgaWYgKGFuZ2xlID09PSAwIHx8IGFuZ2xlID09PSAxODApIHtcbiAgICAgICAgcmV0dXJuICdjZW50ZXInO1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPCAxODApIHtcbiAgICAgICAgcmV0dXJuICdsZWZ0JztcbiAgICB9XG4gICAgcmV0dXJuICdyaWdodCc7XG59XG5mdW5jdGlvbiBsZWZ0Rm9yVGV4dEFsaWduKHgsIHcsIGFsaWduKSB7XG4gICAgaWYgKGFsaWduID09PSAncmlnaHQnKSB7XG4gICAgICAgIHggLT0gdztcbiAgICB9IGVsc2UgaWYgKGFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICB4IC09IHcgLyAyO1xuICAgIH1cbiAgICByZXR1cm4geDtcbn1cbmZ1bmN0aW9uIHlGb3JBbmdsZSh5LCBoLCBhbmdsZSkge1xuICAgIGlmIChhbmdsZSA9PT0gOTAgfHwgYW5nbGUgPT09IDI3MCkge1xuICAgICAgICB5IC09IGggLyAyO1xuICAgIH0gZWxzZSBpZiAoYW5nbGUgPiAyNzAgfHwgYW5nbGUgPCA5MCkge1xuICAgICAgICB5IC09IGg7XG4gICAgfVxuICAgIHJldHVybiB5O1xufVxuZnVuY3Rpb24gZHJhd1BvaW50TGFiZWxCb3goY3R4LCBvcHRzLCBpdGVtKSB7XG4gICAgY29uc3QgeyBsZWZ0ICwgdG9wICwgcmlnaHQgLCBib3R0b20gIH0gPSBpdGVtO1xuICAgIGNvbnN0IHsgYmFja2Ryb3BDb2xvciAgfSA9IG9wdHM7XG4gICAgaWYgKCFpc051bGxPclVuZGVmKGJhY2tkcm9wQ29sb3IpKSB7XG4gICAgICAgIGNvbnN0IGJvcmRlclJhZGl1cyA9IHRvVFJCTENvcm5lcnMob3B0cy5ib3JkZXJSYWRpdXMpO1xuICAgICAgICBjb25zdCBwYWRkaW5nID0gdG9QYWRkaW5nKG9wdHMuYmFja2Ryb3BQYWRkaW5nKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJhY2tkcm9wQ29sb3I7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wTGVmdCA9IGxlZnQgLSBwYWRkaW5nLmxlZnQ7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wVG9wID0gdG9wIC0gcGFkZGluZy50b3A7XG4gICAgICAgIGNvbnN0IGJhY2tkcm9wV2lkdGggPSByaWdodCAtIGxlZnQgKyBwYWRkaW5nLndpZHRoO1xuICAgICAgICBjb25zdCBiYWNrZHJvcEhlaWdodCA9IGJvdHRvbSAtIHRvcCArIHBhZGRpbmcuaGVpZ2h0O1xuICAgICAgICBpZiAoT2JqZWN0LnZhbHVlcyhib3JkZXJSYWRpdXMpLnNvbWUoKHYpPT52ICE9PSAwKSkge1xuICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgYWRkUm91bmRlZFJlY3RQYXRoKGN0eCwge1xuICAgICAgICAgICAgICAgIHg6IGJhY2tkcm9wTGVmdCxcbiAgICAgICAgICAgICAgICB5OiBiYWNrZHJvcFRvcCxcbiAgICAgICAgICAgICAgICB3OiBiYWNrZHJvcFdpZHRoLFxuICAgICAgICAgICAgICAgIGg6IGJhY2tkcm9wSGVpZ2h0LFxuICAgICAgICAgICAgICAgIHJhZGl1czogYm9yZGVyUmFkaXVzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGN0eC5maWxsKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdHguZmlsbFJlY3QoYmFja2Ryb3BMZWZ0LCBiYWNrZHJvcFRvcCwgYmFja2Ryb3BXaWR0aCwgYmFja2Ryb3BIZWlnaHQpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gZHJhd1BvaW50TGFiZWxzKHNjYWxlLCBsYWJlbENvdW50KSB7XG4gICAgY29uc3QgeyBjdHggLCBvcHRpb25zOiB7IHBvaW50TGFiZWxzICB9ICB9ID0gc2NhbGU7XG4gICAgZm9yKGxldCBpID0gbGFiZWxDb3VudCAtIDE7IGkgPj0gMDsgaS0tKXtcbiAgICAgICAgY29uc3QgaXRlbSA9IHNjYWxlLl9wb2ludExhYmVsSXRlbXNbaV07XG4gICAgICAgIGlmICghaXRlbS52aXNpYmxlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcHRzQXRJbmRleCA9IHBvaW50TGFiZWxzLnNldENvbnRleHQoc2NhbGUuZ2V0UG9pbnRMYWJlbENvbnRleHQoaSkpO1xuICAgICAgICBkcmF3UG9pbnRMYWJlbEJveChjdHgsIG9wdHNBdEluZGV4LCBpdGVtKTtcbiAgICAgICAgY29uc3QgcGxGb250ID0gdG9Gb250KG9wdHNBdEluZGV4LmZvbnQpO1xuICAgICAgICBjb25zdCB7IHggLCB5ICwgdGV4dEFsaWduICB9ID0gaXRlbTtcbiAgICAgICAgcmVuZGVyVGV4dChjdHgsIHNjYWxlLl9wb2ludExhYmVsc1tpXSwgeCwgeSArIHBsRm9udC5saW5lSGVpZ2h0IC8gMiwgcGxGb250LCB7XG4gICAgICAgICAgICBjb2xvcjogb3B0c0F0SW5kZXguY29sb3IsXG4gICAgICAgICAgICB0ZXh0QWxpZ246IHRleHRBbGlnbixcbiAgICAgICAgICAgIHRleHRCYXNlbGluZTogJ21pZGRsZSdcbiAgICAgICAgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcGF0aFJhZGl1c0xpbmUoc2NhbGUsIHJhZGl1cywgY2lyY3VsYXIsIGxhYmVsQ291bnQpIHtcbiAgICBjb25zdCB7IGN0eCAgfSA9IHNjYWxlO1xuICAgIGlmIChjaXJjdWxhcikge1xuICAgICAgICBjdHguYXJjKHNjYWxlLnhDZW50ZXIsIHNjYWxlLnlDZW50ZXIsIHJhZGl1cywgMCwgVEFVKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb24oMCwgcmFkaXVzKTtcbiAgICAgICAgY3R4Lm1vdmVUbyhwb2ludFBvc2l0aW9uLngsIHBvaW50UG9zaXRpb24ueSk7XG4gICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBsYWJlbENvdW50OyBpKyspe1xuICAgICAgICAgICAgcG9pbnRQb3NpdGlvbiA9IHNjYWxlLmdldFBvaW50UG9zaXRpb24oaSwgcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8ocG9pbnRQb3NpdGlvbi54LCBwb2ludFBvc2l0aW9uLnkpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gZHJhd1JhZGl1c0xpbmUoc2NhbGUsIGdyaWRMaW5lT3B0cywgcmFkaXVzLCBsYWJlbENvdW50LCBib3JkZXJPcHRzKSB7XG4gICAgY29uc3QgY3R4ID0gc2NhbGUuY3R4O1xuICAgIGNvbnN0IGNpcmN1bGFyID0gZ3JpZExpbmVPcHRzLmNpcmN1bGFyO1xuICAgIGNvbnN0IHsgY29sb3IgLCBsaW5lV2lkdGggIH0gPSBncmlkTGluZU9wdHM7XG4gICAgaWYgKCFjaXJjdWxhciAmJiAhbGFiZWxDb3VudCB8fCAhY29sb3IgfHwgIWxpbmVXaWR0aCB8fCByYWRpdXMgPCAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjtcbiAgICBjdHgubGluZVdpZHRoID0gbGluZVdpZHRoO1xuICAgIGN0eC5zZXRMaW5lRGFzaChib3JkZXJPcHRzLmRhc2gpO1xuICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IGJvcmRlck9wdHMuZGFzaE9mZnNldDtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgcGF0aFJhZGl1c0xpbmUoc2NhbGUsIHJhZGl1cywgY2lyY3VsYXIsIGxhYmVsQ291bnQpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVBvaW50TGFiZWxDb250ZXh0KHBhcmVudCwgaW5kZXgsIGxhYmVsKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbnRleHQocGFyZW50LCB7XG4gICAgICAgIGxhYmVsLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgdHlwZTogJ3BvaW50TGFiZWwnXG4gICAgfSk7XG59XG5jbGFzcyBSYWRpYWxMaW5lYXJTY2FsZSBleHRlbmRzIExpbmVhclNjYWxlQmFzZSB7XG4gICAgc3RhdGljIGlkID0gJ3JhZGlhbExpbmVhcic7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICBhbmltYXRlOiB0cnVlLFxuICAgICAgICBwb3NpdGlvbjogJ2NoYXJ0QXJlYScsXG4gICAgICAgIGFuZ2xlTGluZXM6IHtcbiAgICAgICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgICAgICBsaW5lV2lkdGg6IDEsXG4gICAgICAgICAgICBib3JkZXJEYXNoOiBbXSxcbiAgICAgICAgICAgIGJvcmRlckRhc2hPZmZzZXQ6IDAuMFxuICAgICAgICB9LFxuICAgICAgICBncmlkOiB7XG4gICAgICAgICAgICBjaXJjdWxhcjogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgc3RhcnRBbmdsZTogMCxcbiAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgIHNob3dMYWJlbEJhY2tkcm9wOiB0cnVlLFxuICAgICAgICAgICAgY2FsbGJhY2s6IFRpY2tzLmZvcm1hdHRlcnMubnVtZXJpY1xuICAgICAgICB9LFxuICAgICAgICBwb2ludExhYmVsczoge1xuICAgICAgICAgICAgYmFja2Ryb3BDb2xvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgYmFja2Ryb3BQYWRkaW5nOiAyLFxuICAgICAgICAgICAgZGlzcGxheTogdHJ1ZSxcbiAgICAgICAgICAgIGZvbnQ6IHtcbiAgICAgICAgICAgICAgICBzaXplOiAxMFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbGxiYWNrIChsYWJlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJlbDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWRkaW5nOiA1LFxuICAgICAgICAgICAgY2VudGVyUG9pbnRMYWJlbHM6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9O1xuICAgIHN0YXRpYyBkZWZhdWx0Um91dGVzID0ge1xuICAgICAgICAnYW5nbGVMaW5lcy5jb2xvcic6ICdib3JkZXJDb2xvcicsXG4gICAgICAgICdwb2ludExhYmVscy5jb2xvcic6ICdjb2xvcicsXG4gICAgICAgICd0aWNrcy5jb2xvcic6ICdjb2xvcidcbiAgICB9O1xuICAgIHN0YXRpYyBkZXNjcmlwdG9ycyA9IHtcbiAgICAgICAgYW5nbGVMaW5lczoge1xuICAgICAgICAgICAgX2ZhbGxiYWNrOiAnZ3JpZCdcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoY2ZnKXtcbiAgICAgICAgc3VwZXIoY2ZnKTtcbiAgICAgICAgIHRoaXMueENlbnRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMueUNlbnRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgIHRoaXMuZHJhd2luZ0FyZWEgPSB1bmRlZmluZWQ7XG4gICAgICAgICB0aGlzLl9wb2ludExhYmVscyA9IFtdO1xuICAgICAgICB0aGlzLl9wb2ludExhYmVsSXRlbXMgPSBbXTtcbiAgICB9XG4gICAgc2V0RGltZW5zaW9ucygpIHtcbiAgICAgICAgY29uc3QgcGFkZGluZyA9IHRoaXMuX3BhZGRpbmcgPSB0b1BhZGRpbmcoZ2V0VGlja0JhY2tkcm9wSGVpZ2h0KHRoaXMub3B0aW9ucykgLyAyKTtcbiAgICAgICAgY29uc3QgdyA9IHRoaXMud2lkdGggPSB0aGlzLm1heFdpZHRoIC0gcGFkZGluZy53aWR0aDtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuaGVpZ2h0ID0gdGhpcy5tYXhIZWlnaHQgLSBwYWRkaW5nLmhlaWdodDtcbiAgICAgICAgdGhpcy54Q2VudGVyID0gTWF0aC5mbG9vcih0aGlzLmxlZnQgKyB3IC8gMiArIHBhZGRpbmcubGVmdCk7XG4gICAgICAgIHRoaXMueUNlbnRlciA9IE1hdGguZmxvb3IodGhpcy50b3AgKyBoIC8gMiArIHBhZGRpbmcudG9wKTtcbiAgICAgICAgdGhpcy5kcmF3aW5nQXJlYSA9IE1hdGguZmxvb3IoTWF0aC5taW4odywgaCkgLyAyKTtcbiAgICB9XG4gICAgZGV0ZXJtaW5lRGF0YUxpbWl0cygpIHtcbiAgICAgICAgY29uc3QgeyBtaW4gLCBtYXggIH0gPSB0aGlzLmdldE1pbk1heChmYWxzZSk7XG4gICAgICAgIHRoaXMubWluID0gaXNOdW1iZXJGaW5pdGUobWluKSAmJiAhaXNOYU4obWluKSA/IG1pbiA6IDA7XG4gICAgICAgIHRoaXMubWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6IDA7XG4gICAgICAgIHRoaXMuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpO1xuICAgIH1cbiBjb21wdXRlVGlja0xpbWl0KCkge1xuICAgICAgICByZXR1cm4gTWF0aC5jZWlsKHRoaXMuZHJhd2luZ0FyZWEgLyBnZXRUaWNrQmFja2Ryb3BIZWlnaHQodGhpcy5vcHRpb25zKSk7XG4gICAgfVxuICAgIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgICAgICBMaW5lYXJTY2FsZUJhc2UucHJvdG90eXBlLmdlbmVyYXRlVGlja0xhYmVscy5jYWxsKHRoaXMsIHRpY2tzKTtcbiAgICAgICAgdGhpcy5fcG9pbnRMYWJlbHMgPSB0aGlzLmdldExhYmVscygpLm1hcCgodmFsdWUsIGluZGV4KT0+e1xuICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBjYWxsYmFjayh0aGlzLm9wdGlvbnMucG9pbnRMYWJlbHMuY2FsbGJhY2ssIFtcbiAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICBpbmRleFxuICAgICAgICAgICAgXSwgdGhpcyk7XG4gICAgICAgICAgICByZXR1cm4gbGFiZWwgfHwgbGFiZWwgPT09IDAgPyBsYWJlbCA6ICcnO1xuICAgICAgICB9KS5maWx0ZXIoKHYsIGkpPT50aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpKTtcbiAgICB9XG4gICAgZml0KCkge1xuICAgICAgICBjb25zdCBvcHRzID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAob3B0cy5kaXNwbGF5ICYmIG9wdHMucG9pbnRMYWJlbHMuZGlzcGxheSkge1xuICAgICAgICAgICAgZml0V2l0aFBvaW50TGFiZWxzKHRoaXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRDZW50ZXJQb2ludCgwLCAwLCAwLCAwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXRDZW50ZXJQb2ludChsZWZ0TW92ZW1lbnQsIHJpZ2h0TW92ZW1lbnQsIHRvcE1vdmVtZW50LCBib3R0b21Nb3ZlbWVudCkge1xuICAgICAgICB0aGlzLnhDZW50ZXIgKz0gTWF0aC5mbG9vcigobGVmdE1vdmVtZW50IC0gcmlnaHRNb3ZlbWVudCkgLyAyKTtcbiAgICAgICAgdGhpcy55Q2VudGVyICs9IE1hdGguZmxvb3IoKHRvcE1vdmVtZW50IC0gYm90dG9tTW92ZW1lbnQpIC8gMik7XG4gICAgICAgIHRoaXMuZHJhd2luZ0FyZWEgLT0gTWF0aC5taW4odGhpcy5kcmF3aW5nQXJlYSAvIDIsIE1hdGgubWF4KGxlZnRNb3ZlbWVudCwgcmlnaHRNb3ZlbWVudCwgdG9wTW92ZW1lbnQsIGJvdHRvbU1vdmVtZW50KSk7XG4gICAgfVxuICAgIGdldEluZGV4QW5nbGUoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgYW5nbGVNdWx0aXBsaWVyID0gVEFVIC8gKHRoaXMuX3BvaW50TGFiZWxzLmxlbmd0aCB8fCAxKTtcbiAgICAgICAgY29uc3Qgc3RhcnRBbmdsZSA9IHRoaXMub3B0aW9ucy5zdGFydEFuZ2xlIHx8IDA7XG4gICAgICAgIHJldHVybiBfbm9ybWFsaXplQW5nbGUoaW5kZXggKiBhbmdsZU11bHRpcGxpZXIgKyB0b1JhZGlhbnMoc3RhcnRBbmdsZSkpO1xuICAgIH1cbiAgICBnZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2NhbGluZ0ZhY3RvciA9IHRoaXMuZHJhd2luZ0FyZWEgLyAodGhpcy5tYXggLSB0aGlzLm1pbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMucmV2ZXJzZSkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLm1heCAtIHZhbHVlKSAqIHNjYWxpbmdGYWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICh2YWx1ZSAtIHRoaXMubWluKSAqIHNjYWxpbmdGYWN0b3I7XG4gICAgfVxuICAgIGdldFZhbHVlRm9yRGlzdGFuY2VGcm9tQ2VudGVyKGRpc3RhbmNlKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmKGRpc3RhbmNlKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzY2FsZWREaXN0YW5jZSA9IGRpc3RhbmNlIC8gKHRoaXMuZHJhd2luZ0FyZWEgLyAodGhpcy5tYXggLSB0aGlzLm1pbikpO1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLnJldmVyc2UgPyB0aGlzLm1heCAtIHNjYWxlZERpc3RhbmNlIDogdGhpcy5taW4gKyBzY2FsZWREaXN0YW5jZTtcbiAgICB9XG4gICAgZ2V0UG9pbnRMYWJlbENvbnRleHQoaW5kZXgpIHtcbiAgICAgICAgY29uc3QgcG9pbnRMYWJlbHMgPSB0aGlzLl9wb2ludExhYmVscyB8fCBbXTtcbiAgICAgICAgaWYgKGluZGV4ID49IDAgJiYgaW5kZXggPCBwb2ludExhYmVscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50TGFiZWwgPSBwb2ludExhYmVsc1tpbmRleF07XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlUG9pbnRMYWJlbENvbnRleHQodGhpcy5nZXRDb250ZXh0KCksIGluZGV4LCBwb2ludExhYmVsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRQb2ludFBvc2l0aW9uKGluZGV4LCBkaXN0YW5jZUZyb21DZW50ZXIsIGFkZGl0aW9uYWxBbmdsZSA9IDApIHtcbiAgICAgICAgY29uc3QgYW5nbGUgPSB0aGlzLmdldEluZGV4QW5nbGUoaW5kZXgpIC0gSEFMRl9QSSArIGFkZGl0aW9uYWxBbmdsZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IE1hdGguY29zKGFuZ2xlKSAqIGRpc3RhbmNlRnJvbUNlbnRlciArIHRoaXMueENlbnRlcixcbiAgICAgICAgICAgIHk6IE1hdGguc2luKGFuZ2xlKSAqIGRpc3RhbmNlRnJvbUNlbnRlciArIHRoaXMueUNlbnRlcixcbiAgICAgICAgICAgIGFuZ2xlXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZShpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UG9pbnRQb3NpdGlvbihpbmRleCwgdGhpcy5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh2YWx1ZSkpO1xuICAgIH1cbiAgICBnZXRCYXNlUG9zaXRpb24oaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKGluZGV4IHx8IDAsIHRoaXMuZ2V0QmFzZVZhbHVlKCkpO1xuICAgIH1cbiAgICBnZXRQb2ludExhYmVsUG9zaXRpb24oaW5kZXgpIHtcbiAgICAgICAgY29uc3QgeyBsZWZ0ICwgdG9wICwgcmlnaHQgLCBib3R0b20gIH0gPSB0aGlzLl9wb2ludExhYmVsSXRlbXNbaW5kZXhdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVmdCxcbiAgICAgICAgICAgIHRvcCxcbiAgICAgICAgICAgIHJpZ2h0LFxuICAgICAgICAgICAgYm90dG9tXG4gICAgICAgIH07XG4gICAgfVxuIGRyYXdCYWNrZ3JvdW5kKCkge1xuICAgICAgICBjb25zdCB7IGJhY2tncm91bmRDb2xvciAsIGdyaWQ6IHsgY2lyY3VsYXIgIH0gIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmIChiYWNrZ3JvdW5kQ29sb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIHBhdGhSYWRpdXNMaW5lKHRoaXMsIHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy5fZW5kVmFsdWUpLCBjaXJjdWxhciwgdGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RoKTtcbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBiYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgICAgICBjdHguZmlsbCgpO1xuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuICAgIH1cbiBkcmF3R3JpZCgpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgICAgIGNvbnN0IG9wdHMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHsgYW5nbGVMaW5lcyAsIGdyaWQgLCBib3JkZXIgIH0gPSBvcHRzO1xuICAgICAgICBjb25zdCBsYWJlbENvdW50ID0gdGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RoO1xuICAgICAgICBsZXQgaSwgb2Zmc2V0LCBwb3NpdGlvbjtcbiAgICAgICAgaWYgKG9wdHMucG9pbnRMYWJlbHMuZGlzcGxheSkge1xuICAgICAgICAgICAgZHJhd1BvaW50TGFiZWxzKHRoaXMsIGxhYmVsQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChncmlkLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHRoaXMudGlja3MuZm9yRWFjaCgodGljaywgaW5kZXgpPT57XG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGljay52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldENvbnRleHQoaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvcHRzQXRJbmRleCA9IGdyaWQuc2V0Q29udGV4dChjb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXhCb3JkZXIgPSBib3JkZXIuc2V0Q29udGV4dChjb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgZHJhd1JhZGl1c0xpbmUodGhpcywgb3B0c0F0SW5kZXgsIG9mZnNldCwgbGFiZWxDb3VudCwgb3B0c0F0SW5kZXhCb3JkZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbmdsZUxpbmVzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIGN0eC5zYXZlKCk7XG4gICAgICAgICAgICBmb3IoaSA9IGxhYmVsQ291bnQgLSAxOyBpID49IDA7IGktLSl7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3B0c0F0SW5kZXggPSBhbmdsZUxpbmVzLnNldENvbnRleHQodGhpcy5nZXRQb2ludExhYmVsQ29udGV4dChpKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBjb2xvciAsIGxpbmVXaWR0aCAgfSA9IG9wdHNBdEluZGV4O1xuICAgICAgICAgICAgICAgIGlmICghbGluZVdpZHRoIHx8ICFjb2xvcikge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3R4LmxpbmVXaWR0aCA9IGxpbmVXaWR0aDtcbiAgICAgICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjtcbiAgICAgICAgICAgICAgICBjdHguc2V0TGluZURhc2gob3B0c0F0SW5kZXguYm9yZGVyRGFzaCk7XG4gICAgICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gb3B0c0F0SW5kZXguYm9yZGVyRGFzaE9mZnNldDtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSB0aGlzLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKG9wdHMudGlja3MucmV2ZXJzZSA/IHRoaXMubWluIDogdGhpcy5tYXgpO1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gdGhpcy5nZXRQb2ludFBvc2l0aW9uKGksIG9mZnNldCk7XG4gICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgICAgIGN0eC5tb3ZlVG8odGhpcy54Q2VudGVyLCB0aGlzLnlDZW50ZXIpO1xuICAgICAgICAgICAgICAgIGN0eC5saW5lVG8ocG9zaXRpb24ueCwgcG9zaXRpb24ueSk7XG4gICAgICAgICAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuICAgIH1cbiBkcmF3Qm9yZGVyKCkge31cbiBkcmF3TGFiZWxzKCkge1xuICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICAgICAgY29uc3Qgb3B0cyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRzLnRpY2tzO1xuICAgICAgICBpZiAoIXRpY2tPcHRzLmRpc3BsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGFydEFuZ2xlID0gdGhpcy5nZXRJbmRleEFuZ2xlKDApO1xuICAgICAgICBsZXQgb2Zmc2V0LCB3aWR0aDtcbiAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgY3R4LnRyYW5zbGF0ZSh0aGlzLnhDZW50ZXIsIHRoaXMueUNlbnRlcik7XG4gICAgICAgIGN0eC5yb3RhdGUoc3RhcnRBbmdsZSk7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICB0aGlzLnRpY2tzLmZvckVhY2goKHRpY2ssIGluZGV4KT0+e1xuICAgICAgICAgICAgaWYgKGluZGV4ID09PSAwICYmICFvcHRzLnJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvcHRzQXRJbmRleCA9IHRpY2tPcHRzLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KGluZGV4KSk7XG4gICAgICAgICAgICBjb25zdCB0aWNrRm9udCA9IHRvRm9udChvcHRzQXRJbmRleC5mb250KTtcbiAgICAgICAgICAgIG9mZnNldCA9IHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy50aWNrc1tpbmRleF0udmFsdWUpO1xuICAgICAgICAgICAgaWYgKG9wdHNBdEluZGV4LnNob3dMYWJlbEJhY2tkcm9wKSB7XG4gICAgICAgICAgICAgICAgY3R4LmZvbnQgPSB0aWNrRm9udC5zdHJpbmc7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBjdHgubWVhc3VyZVRleHQodGljay5sYWJlbCkud2lkdGg7XG4gICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdHNBdEluZGV4LmJhY2tkcm9wQ29sb3I7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFkZGluZyA9IHRvUGFkZGluZyhvcHRzQXRJbmRleC5iYWNrZHJvcFBhZGRpbmcpO1xuICAgICAgICAgICAgICAgIGN0eC5maWxsUmVjdCgtd2lkdGggLyAyIC0gcGFkZGluZy5sZWZ0LCAtb2Zmc2V0IC0gdGlja0ZvbnQuc2l6ZSAvIDIgLSBwYWRkaW5nLnRvcCwgd2lkdGggKyBwYWRkaW5nLndpZHRoLCB0aWNrRm9udC5zaXplICsgcGFkZGluZy5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVuZGVyVGV4dChjdHgsIHRpY2subGFiZWwsIDAsIC1vZmZzZXQsIHRpY2tGb250LCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IG9wdHNBdEluZGV4LmNvbG9yXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgfVxuIGRyYXdUaXRsZSgpIHt9XG59XG5cbmNvbnN0IElOVEVSVkFMUyA9IHtcbiAgICBtaWxsaXNlY29uZDoge1xuICAgICAgICBjb21tb246IHRydWUsXG4gICAgICAgIHNpemU6IDEsXG4gICAgICAgIHN0ZXBzOiAxMDAwXG4gICAgfSxcbiAgICBzZWNvbmQ6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiAxMDAwLFxuICAgICAgICBzdGVwczogNjBcbiAgICB9LFxuICAgIG1pbnV0ZToge1xuICAgICAgICBjb21tb246IHRydWUsXG4gICAgICAgIHNpemU6IDYwMDAwLFxuICAgICAgICBzdGVwczogNjBcbiAgICB9LFxuICAgIGhvdXI6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiAzNjAwMDAwLFxuICAgICAgICBzdGVwczogMjRcbiAgICB9LFxuICAgIGRheToge1xuICAgICAgICBjb21tb246IHRydWUsXG4gICAgICAgIHNpemU6IDg2NDAwMDAwLFxuICAgICAgICBzdGVwczogMzBcbiAgICB9LFxuICAgIHdlZWs6IHtcbiAgICAgICAgY29tbW9uOiBmYWxzZSxcbiAgICAgICAgc2l6ZTogNjA0ODAwMDAwLFxuICAgICAgICBzdGVwczogNFxuICAgIH0sXG4gICAgbW9udGg6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiAyLjYyOGU5LFxuICAgICAgICBzdGVwczogMTJcbiAgICB9LFxuICAgIHF1YXJ0ZXI6IHtcbiAgICAgICAgY29tbW9uOiBmYWxzZSxcbiAgICAgICAgc2l6ZTogNy44ODRlOSxcbiAgICAgICAgc3RlcHM6IDRcbiAgICB9LFxuICAgIHllYXI6IHtcbiAgICAgICAgY29tbW9uOiB0cnVlLFxuICAgICAgICBzaXplOiAzLjE1NGUxMFxuICAgIH1cbn07XG4gY29uc3QgVU5JVFMgPSAgLyogI19fUFVSRV9fICovIE9iamVjdC5rZXlzKElOVEVSVkFMUyk7XG4gZnVuY3Rpb24gc29ydGVyKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG4gZnVuY3Rpb24gcGFyc2Uoc2NhbGUsIGlucHV0KSB7XG4gICAgaWYgKGlzTnVsbE9yVW5kZWYoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBhZGFwdGVyID0gc2NhbGUuX2FkYXB0ZXI7XG4gICAgY29uc3QgeyBwYXJzZXIgLCByb3VuZCAsIGlzb1dlZWtkYXkgIH0gPSBzY2FsZS5fcGFyc2VPcHRzO1xuICAgIGxldCB2YWx1ZSA9IGlucHV0O1xuICAgIGlmICh0eXBlb2YgcGFyc2VyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHZhbHVlID0gcGFyc2VyKHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKCFpc051bWJlckZpbml0ZSh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSB0eXBlb2YgcGFyc2VyID09PSAnc3RyaW5nJyA/IGFkYXB0ZXIucGFyc2UodmFsdWUsICBwYXJzZXIpIDogYWRhcHRlci5wYXJzZSh2YWx1ZSk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHJvdW5kKSB7XG4gICAgICAgIHZhbHVlID0gcm91bmQgPT09ICd3ZWVrJyAmJiAoaXNOdW1iZXIoaXNvV2Vla2RheSkgfHwgaXNvV2Vla2RheSA9PT0gdHJ1ZSkgPyBhZGFwdGVyLnN0YXJ0T2YodmFsdWUsICdpc29XZWVrJywgaXNvV2Vla2RheSkgOiBhZGFwdGVyLnN0YXJ0T2YodmFsdWUsIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuICt2YWx1ZTtcbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVVbml0Rm9yQXV0b1RpY2tzKG1pblVuaXQsIG1pbiwgbWF4LCBjYXBhY2l0eSkge1xuICAgIGNvbnN0IGlsZW4gPSBVTklUUy5sZW5ndGg7XG4gICAgZm9yKGxldCBpID0gVU5JVFMuaW5kZXhPZihtaW5Vbml0KTsgaSA8IGlsZW4gLSAxOyArK2kpe1xuICAgICAgICBjb25zdCBpbnRlcnZhbCA9IElOVEVSVkFMU1tVTklUU1tpXV07XG4gICAgICAgIGNvbnN0IGZhY3RvciA9IGludGVydmFsLnN0ZXBzID8gaW50ZXJ2YWwuc3RlcHMgOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgICAgICAgaWYgKGludGVydmFsLmNvbW1vbiAmJiBNYXRoLmNlaWwoKG1heCAtIG1pbikgLyAoZmFjdG9yICogaW50ZXJ2YWwuc2l6ZSkpIDw9IGNhcGFjaXR5KSB7XG4gICAgICAgICAgICByZXR1cm4gVU5JVFNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFVOSVRTW2lsZW4gLSAxXTtcbn1cbiBmdW5jdGlvbiBkZXRlcm1pbmVVbml0Rm9yRm9ybWF0dGluZyhzY2FsZSwgbnVtVGlja3MsIG1pblVuaXQsIG1pbiwgbWF4KSB7XG4gICAgZm9yKGxldCBpID0gVU5JVFMubGVuZ3RoIC0gMTsgaSA+PSBVTklUUy5pbmRleE9mKG1pblVuaXQpOyBpLS0pe1xuICAgICAgICBjb25zdCB1bml0ID0gVU5JVFNbaV07XG4gICAgICAgIGlmIChJTlRFUlZBTFNbdW5pdF0uY29tbW9uICYmIHNjYWxlLl9hZGFwdGVyLmRpZmYobWF4LCBtaW4sIHVuaXQpID49IG51bVRpY2tzIC0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuaXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFVOSVRTW21pblVuaXQgPyBVTklUUy5pbmRleE9mKG1pblVuaXQpIDogMF07XG59XG4gZnVuY3Rpb24gZGV0ZXJtaW5lTWFqb3JVbml0KHVuaXQpIHtcbiAgICBmb3IobGV0IGkgPSBVTklUUy5pbmRleE9mKHVuaXQpICsgMSwgaWxlbiA9IFVOSVRTLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGlmIChJTlRFUlZBTFNbVU5JVFNbaV1dLmNvbW1vbikge1xuICAgICAgICAgICAgcmV0dXJuIFVOSVRTW2ldO1xuICAgICAgICB9XG4gICAgfVxufVxuIGZ1bmN0aW9uIGFkZFRpY2sodGlja3MsIHRpbWUsIHRpbWVzdGFtcHMpIHtcbiAgICBpZiAoIXRpbWVzdGFtcHMpIHtcbiAgICAgICAgdGlja3NbdGltZV0gPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAodGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgeyBsbyAsIGhpICB9ID0gX2xvb2t1cCh0aW1lc3RhbXBzLCB0aW1lKTtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wID0gdGltZXN0YW1wc1tsb10gPj0gdGltZSA/IHRpbWVzdGFtcHNbbG9dIDogdGltZXN0YW1wc1toaV07XG4gICAgICAgIHRpY2tzW3RpbWVzdGFtcF0gPSB0cnVlO1xuICAgIH1cbn1cbiBmdW5jdGlvbiBzZXRNYWpvclRpY2tzKHNjYWxlLCB0aWNrcywgbWFwLCBtYWpvclVuaXQpIHtcbiAgICBjb25zdCBhZGFwdGVyID0gc2NhbGUuX2FkYXB0ZXI7XG4gICAgY29uc3QgZmlyc3QgPSArYWRhcHRlci5zdGFydE9mKHRpY2tzWzBdLnZhbHVlLCBtYWpvclVuaXQpO1xuICAgIGNvbnN0IGxhc3QgPSB0aWNrc1t0aWNrcy5sZW5ndGggLSAxXS52YWx1ZTtcbiAgICBsZXQgbWFqb3IsIGluZGV4O1xuICAgIGZvcihtYWpvciA9IGZpcnN0OyBtYWpvciA8PSBsYXN0OyBtYWpvciA9ICthZGFwdGVyLmFkZChtYWpvciwgMSwgbWFqb3JVbml0KSl7XG4gICAgICAgIGluZGV4ID0gbWFwW21ham9yXTtcbiAgICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgICAgIHRpY2tzW2luZGV4XS5tYWpvciA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRpY2tzO1xufVxuIGZ1bmN0aW9uIHRpY2tzRnJvbVRpbWVzdGFtcHMoc2NhbGUsIHZhbHVlcywgbWFqb3JVbml0KSB7XG4gICAgY29uc3QgdGlja3MgPSBbXTtcbiAgICAgY29uc3QgbWFwID0ge307XG4gICAgY29uc3QgaWxlbiA9IHZhbHVlcy5sZW5ndGg7XG4gICAgbGV0IGksIHZhbHVlO1xuICAgIGZvcihpID0gMDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgICBtYXBbdmFsdWVdID0gaTtcbiAgICAgICAgdGlja3MucHVzaCh7XG4gICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgIG1ham9yOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGlsZW4gPT09IDAgfHwgIW1ham9yVW5pdCA/IHRpY2tzIDogc2V0TWFqb3JUaWNrcyhzY2FsZSwgdGlja3MsIG1hcCwgbWFqb3JVbml0KTtcbn1cbmNsYXNzIFRpbWVTY2FsZSBleHRlbmRzIFNjYWxlIHtcbiAgICBzdGF0aWMgaWQgPSAndGltZSc7XG4gc3RhdGljIGRlZmF1bHRzID0ge1xuIGJvdW5kczogJ2RhdGEnLFxuICAgICAgICBhZGFwdGVyczoge30sXG4gICAgICAgIHRpbWU6IHtcbiAgICAgICAgICAgIHBhcnNlcjogZmFsc2UsXG4gICAgICAgICAgICB1bml0OiBmYWxzZSxcbiAgICAgICAgICAgIHJvdW5kOiBmYWxzZSxcbiAgICAgICAgICAgIGlzb1dlZWtkYXk6IGZhbHNlLFxuICAgICAgICAgICAgbWluVW5pdDogJ21pbGxpc2Vjb25kJyxcbiAgICAgICAgICAgIGRpc3BsYXlGb3JtYXRzOiB7fVxuICAgICAgICB9LFxuICAgICAgICB0aWNrczoge1xuIHNvdXJjZTogJ2F1dG8nLFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZhbHNlLFxuICAgICAgICAgICAgbWFqb3I6IHtcbiAgICAgICAgICAgICAgICBlbmFibGVkOiBmYWxzZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiBjb25zdHJ1Y3Rvcihwcm9wcyl7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcbiAgICAgICAgIHRoaXMuX2NhY2hlID0ge1xuICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICBsYWJlbHM6IFtdLFxuICAgICAgICAgICAgYWxsOiBbXVxuICAgICAgICB9O1xuICAgICAgICAgdGhpcy5fdW5pdCA9ICdkYXknO1xuICAgICAgICAgdGhpcy5fbWFqb3JVbml0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9vZmZzZXRzID0ge307XG4gICAgICAgIHRoaXMuX25vcm1hbGl6ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fcGFyc2VPcHRzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpbml0KHNjYWxlT3B0cywgb3B0cyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBzY2FsZU9wdHMudGltZSB8fCAoc2NhbGVPcHRzLnRpbWUgPSB7fSk7XG4gICAgICAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5fYWRhcHRlciA9IG5ldyBhZGFwdGVycy5fZGF0ZShzY2FsZU9wdHMuYWRhcHRlcnMuZGF0ZSk7XG4gICAgICAgIGFkYXB0ZXIuaW5pdChvcHRzKTtcbiAgICAgICAgbWVyZ2VJZih0aW1lLmRpc3BsYXlGb3JtYXRzLCBhZGFwdGVyLmZvcm1hdHMoKSk7XG4gICAgICAgIHRoaXMuX3BhcnNlT3B0cyA9IHtcbiAgICAgICAgICAgIHBhcnNlcjogdGltZS5wYXJzZXIsXG4gICAgICAgICAgICByb3VuZDogdGltZS5yb3VuZCxcbiAgICAgICAgICAgIGlzb1dlZWtkYXk6IHRpbWUuaXNvV2Vla2RheVxuICAgICAgICB9O1xuICAgICAgICBzdXBlci5pbml0KHNjYWxlT3B0cyk7XG4gICAgICAgIHRoaXMuX25vcm1hbGl6ZWQgPSBvcHRzLm5vcm1hbGl6ZWQ7XG4gICAgfVxuIHBhcnNlKHJhdywgaW5kZXgpIHtcbiAgICAgICAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyc2UodGhpcywgcmF3KTtcbiAgICB9XG4gICAgYmVmb3JlTGF5b3V0KCkge1xuICAgICAgICBzdXBlci5iZWZvcmVMYXlvdXQoKTtcbiAgICAgICAgdGhpcy5fY2FjaGUgPSB7XG4gICAgICAgICAgICBkYXRhOiBbXSxcbiAgICAgICAgICAgIGxhYmVsczogW10sXG4gICAgICAgICAgICBhbGw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuICAgIGRldGVybWluZURhdGFMaW1pdHMoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLl9hZGFwdGVyO1xuICAgICAgICBjb25zdCB1bml0ID0gb3B0aW9ucy50aW1lLnVuaXQgfHwgJ2RheSc7XG4gICAgICAgIGxldCB7IG1pbiAsIG1heCAsIG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gdGhpcy5nZXRVc2VyQm91bmRzKCk7XG4gZnVuY3Rpb24gX2FwcGx5Qm91bmRzKGJvdW5kcykge1xuICAgICAgICAgICAgaWYgKCFtaW5EZWZpbmVkICYmICFpc05hTihib3VuZHMubWluKSkge1xuICAgICAgICAgICAgICAgIG1pbiA9IE1hdGgubWluKG1pbiwgYm91bmRzLm1pbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW1heERlZmluZWQgJiYgIWlzTmFOKGJvdW5kcy5tYXgpKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBib3VuZHMubWF4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIW1pbkRlZmluZWQgfHwgIW1heERlZmluZWQpIHtcbiAgICAgICAgICAgIF9hcHBseUJvdW5kcyh0aGlzLl9nZXRMYWJlbEJvdW5kcygpKTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmJvdW5kcyAhPT0gJ3RpY2tzJyB8fCBvcHRpb25zLnRpY2tzLnNvdXJjZSAhPT0gJ2xhYmVscycpIHtcbiAgICAgICAgICAgICAgICBfYXBwbHlCb3VuZHModGhpcy5nZXRNaW5NYXgoZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtaW4gPSBpc051bWJlckZpbml0ZShtaW4pICYmICFpc05hTihtaW4pID8gbWluIDogK2FkYXB0ZXIuc3RhcnRPZihEYXRlLm5vdygpLCB1bml0KTtcbiAgICAgICAgbWF4ID0gaXNOdW1iZXJGaW5pdGUobWF4KSAmJiAhaXNOYU4obWF4KSA/IG1heCA6ICthZGFwdGVyLmVuZE9mKERhdGUubm93KCksIHVuaXQpICsgMTtcbiAgICAgICAgdGhpcy5taW4gPSBNYXRoLm1pbihtaW4sIG1heCAtIDEpO1xuICAgICAgICB0aGlzLm1heCA9IE1hdGgubWF4KG1pbiArIDEsIG1heCk7XG4gICAgfVxuIF9nZXRMYWJlbEJvdW5kcygpIHtcbiAgICAgICAgY29uc3QgYXJyID0gdGhpcy5nZXRMYWJlbFRpbWVzdGFtcHMoKTtcbiAgICAgICAgbGV0IG1pbiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgbGV0IG1heCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTtcbiAgICAgICAgaWYgKGFyci5sZW5ndGgpIHtcbiAgICAgICAgICAgIG1pbiA9IGFyclswXTtcbiAgICAgICAgICAgIG1heCA9IGFyclthcnIubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbixcbiAgICAgICAgICAgIG1heFxuICAgICAgICB9O1xuICAgIH1cbiBidWlsZFRpY2tzKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IG9wdGlvbnMudGltZTtcbiAgICAgICAgY29uc3QgdGlja09wdHMgPSBvcHRpb25zLnRpY2tzO1xuICAgICAgICBjb25zdCB0aW1lc3RhbXBzID0gdGlja09wdHMuc291cmNlID09PSAnbGFiZWxzJyA/IHRoaXMuZ2V0TGFiZWxUaW1lc3RhbXBzKCkgOiB0aGlzLl9nZW5lcmF0ZSgpO1xuICAgICAgICBpZiAob3B0aW9ucy5ib3VuZHMgPT09ICd0aWNrcycgJiYgdGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMubWluID0gdGhpcy5fdXNlck1pbiB8fCB0aW1lc3RhbXBzWzBdO1xuICAgICAgICAgICAgdGhpcy5tYXggPSB0aGlzLl91c2VyTWF4IHx8IHRpbWVzdGFtcHNbdGltZXN0YW1wcy5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtaW4gPSB0aGlzLm1pbjtcbiAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5tYXg7XG4gICAgICAgIGNvbnN0IHRpY2tzID0gX2ZpbHRlckJldHdlZW4odGltZXN0YW1wcywgbWluLCBtYXgpO1xuICAgICAgICB0aGlzLl91bml0ID0gdGltZU9wdHMudW5pdCB8fCAodGlja09wdHMuYXV0b1NraXAgPyBkZXRlcm1pbmVVbml0Rm9yQXV0b1RpY2tzKHRpbWVPcHRzLm1pblVuaXQsIHRoaXMubWluLCB0aGlzLm1heCwgdGhpcy5fZ2V0TGFiZWxDYXBhY2l0eShtaW4pKSA6IGRldGVybWluZVVuaXRGb3JGb3JtYXR0aW5nKHRoaXMsIHRpY2tzLmxlbmd0aCwgdGltZU9wdHMubWluVW5pdCwgdGhpcy5taW4sIHRoaXMubWF4KSk7XG4gICAgICAgIHRoaXMuX21ham9yVW5pdCA9ICF0aWNrT3B0cy5tYWpvci5lbmFibGVkIHx8IHRoaXMuX3VuaXQgPT09ICd5ZWFyJyA/IHVuZGVmaW5lZCA6IGRldGVybWluZU1ham9yVW5pdCh0aGlzLl91bml0KTtcbiAgICAgICAgdGhpcy5pbml0T2Zmc2V0cyh0aW1lc3RhbXBzKTtcbiAgICAgICAgaWYgKG9wdGlvbnMucmV2ZXJzZSkge1xuICAgICAgICAgICAgdGlja3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aWNrc0Zyb21UaW1lc3RhbXBzKHRoaXMsIHRpY2tzLCB0aGlzLl9tYWpvclVuaXQpO1xuICAgIH1cbiAgICBhZnRlckF1dG9Ta2lwKCkge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm9mZnNldEFmdGVyQXV0b3NraXApIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdE9mZnNldHModGhpcy50aWNrcy5tYXAoKHRpY2spPT4rdGljay52YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfVxuIGluaXRPZmZzZXRzKHRpbWVzdGFtcHMgPSBbXSkge1xuICAgICAgICBsZXQgc3RhcnQgPSAwO1xuICAgICAgICBsZXQgZW5kID0gMDtcbiAgICAgICAgbGV0IGZpcnN0LCBsYXN0O1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm9mZnNldCAmJiB0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgZmlyc3QgPSB0aGlzLmdldERlY2ltYWxGb3JWYWx1ZSh0aW1lc3RhbXBzWzBdKTtcbiAgICAgICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gMSAtIGZpcnN0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdGFydCA9ICh0aGlzLmdldERlY2ltYWxGb3JWYWx1ZSh0aW1lc3RhbXBzWzFdKSAtIGZpcnN0KSAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0ID0gdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IGxhc3Q7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuZCA9IChsYXN0IC0gdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodGltZXN0YW1wc1t0aW1lc3RhbXBzLmxlbmd0aCAtIDJdKSkgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxpbWl0ID0gdGltZXN0YW1wcy5sZW5ndGggPCAzID8gMC41IDogMC4yNTtcbiAgICAgICAgc3RhcnQgPSBfbGltaXRWYWx1ZShzdGFydCwgMCwgbGltaXQpO1xuICAgICAgICBlbmQgPSBfbGltaXRWYWx1ZShlbmQsIDAsIGxpbWl0KTtcbiAgICAgICAgdGhpcy5fb2Zmc2V0cyA9IHtcbiAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgZW5kLFxuICAgICAgICAgICAgZmFjdG9yOiAxIC8gKHN0YXJ0ICsgMSArIGVuZClcbiAgICAgICAgfTtcbiAgICB9XG4gX2dlbmVyYXRlKCkge1xuICAgICAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5fYWRhcHRlcjtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW47XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4O1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IG9wdGlvbnMudGltZTtcbiAgICAgICAgY29uc3QgbWlub3IgPSB0aW1lT3B0cy51bml0IHx8IGRldGVybWluZVVuaXRGb3JBdXRvVGlja3ModGltZU9wdHMubWluVW5pdCwgbWluLCBtYXgsIHRoaXMuX2dldExhYmVsQ2FwYWNpdHkobWluKSk7XG4gICAgICAgIGNvbnN0IHN0ZXBTaXplID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy50aWNrcy5zdGVwU2l6ZSwgMSk7XG4gICAgICAgIGNvbnN0IHdlZWtkYXkgPSBtaW5vciA9PT0gJ3dlZWsnID8gdGltZU9wdHMuaXNvV2Vla2RheSA6IGZhbHNlO1xuICAgICAgICBjb25zdCBoYXNXZWVrZGF5ID0gaXNOdW1iZXIod2Vla2RheSkgfHwgd2Vla2RheSA9PT0gdHJ1ZTtcbiAgICAgICAgY29uc3QgdGlja3MgPSB7fTtcbiAgICAgICAgbGV0IGZpcnN0ID0gbWluO1xuICAgICAgICBsZXQgdGltZSwgY291bnQ7XG4gICAgICAgIGlmIChoYXNXZWVrZGF5KSB7XG4gICAgICAgICAgICBmaXJzdCA9ICthZGFwdGVyLnN0YXJ0T2YoZmlyc3QsICdpc29XZWVrJywgd2Vla2RheSk7XG4gICAgICAgIH1cbiAgICAgICAgZmlyc3QgPSArYWRhcHRlci5zdGFydE9mKGZpcnN0LCBoYXNXZWVrZGF5ID8gJ2RheScgOiBtaW5vcik7XG4gICAgICAgIGlmIChhZGFwdGVyLmRpZmYobWF4LCBtaW4sIG1pbm9yKSA+IDEwMDAwMCAqIHN0ZXBTaXplKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWluICsgJyBhbmQgJyArIG1heCArICcgYXJlIHRvbyBmYXIgYXBhcnQgd2l0aCBzdGVwU2l6ZSBvZiAnICsgc3RlcFNpemUgKyAnICcgKyBtaW5vcik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGltZXN0YW1wcyA9IG9wdGlvbnMudGlja3Muc291cmNlID09PSAnZGF0YScgJiYgdGhpcy5nZXREYXRhVGltZXN0YW1wcygpO1xuICAgICAgICBmb3IodGltZSA9IGZpcnN0LCBjb3VudCA9IDA7IHRpbWUgPCBtYXg7IHRpbWUgPSArYWRhcHRlci5hZGQodGltZSwgc3RlcFNpemUsIG1pbm9yKSwgY291bnQrKyl7XG4gICAgICAgICAgICBhZGRUaWNrKHRpY2tzLCB0aW1lLCB0aW1lc3RhbXBzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGltZSA9PT0gbWF4IHx8IG9wdGlvbnMuYm91bmRzID09PSAndGlja3MnIHx8IGNvdW50ID09PSAxKSB7XG4gICAgICAgICAgICBhZGRUaWNrKHRpY2tzLCB0aW1lLCB0aW1lc3RhbXBzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGlja3MpLnNvcnQoKGEsIGIpPT5hIC0gYikubWFwKCh4KT0+K3gpO1xuICAgIH1cbiBnZXRMYWJlbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLl9hZGFwdGVyO1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IHRoaXMub3B0aW9ucy50aW1lO1xuICAgICAgICBpZiAodGltZU9wdHMudG9vbHRpcEZvcm1hdCkge1xuICAgICAgICAgICAgcmV0dXJuIGFkYXB0ZXIuZm9ybWF0KHZhbHVlLCB0aW1lT3B0cy50b29sdGlwRm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWRhcHRlci5mb3JtYXQodmFsdWUsIHRpbWVPcHRzLmRpc3BsYXlGb3JtYXRzLmRhdGV0aW1lKTtcbiAgICB9XG4gZm9ybWF0KHZhbHVlLCBmb3JtYXQpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgZm9ybWF0cyA9IG9wdGlvbnMudGltZS5kaXNwbGF5Rm9ybWF0cztcbiAgICAgICAgY29uc3QgdW5pdCA9IHRoaXMuX3VuaXQ7XG4gICAgICAgIGNvbnN0IGZtdCA9IGZvcm1hdCB8fCBmb3JtYXRzW3VuaXRdO1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRhcHRlci5mb3JtYXQodmFsdWUsIGZtdCk7XG4gICAgfVxuIF90aWNrRm9ybWF0RnVuY3Rpb24odGltZSwgaW5kZXgsIHRpY2tzLCBmb3JtYXQpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgY29uc3QgZm9ybWF0dGVyID0gb3B0aW9ucy50aWNrcy5jYWxsYmFjaztcbiAgICAgICAgaWYgKGZvcm1hdHRlcikge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZvcm1hdHRlciwgW1xuICAgICAgICAgICAgICAgIHRpbWUsXG4gICAgICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICAgICAgdGlja3NcbiAgICAgICAgICAgIF0sIHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZvcm1hdHMgPSBvcHRpb25zLnRpbWUuZGlzcGxheUZvcm1hdHM7XG4gICAgICAgIGNvbnN0IHVuaXQgPSB0aGlzLl91bml0O1xuICAgICAgICBjb25zdCBtYWpvclVuaXQgPSB0aGlzLl9tYWpvclVuaXQ7XG4gICAgICAgIGNvbnN0IG1pbm9yRm9ybWF0ID0gdW5pdCAmJiBmb3JtYXRzW3VuaXRdO1xuICAgICAgICBjb25zdCBtYWpvckZvcm1hdCA9IG1ham9yVW5pdCAmJiBmb3JtYXRzW21ham9yVW5pdF07XG4gICAgICAgIGNvbnN0IHRpY2sgPSB0aWNrc1tpbmRleF07XG4gICAgICAgIGNvbnN0IG1ham9yID0gbWFqb3JVbml0ICYmIG1ham9yRm9ybWF0ICYmIHRpY2sgJiYgdGljay5tYWpvcjtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkYXB0ZXIuZm9ybWF0KHRpbWUsIGZvcm1hdCB8fCAobWFqb3IgPyBtYWpvckZvcm1hdCA6IG1pbm9yRm9ybWF0KSk7XG4gICAgfVxuIGdlbmVyYXRlVGlja0xhYmVscyh0aWNrcykge1xuICAgICAgICBsZXQgaSwgaWxlbiwgdGljaztcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gdGlja3MubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgICAgIHRpY2sgPSB0aWNrc1tpXTtcbiAgICAgICAgICAgIHRpY2subGFiZWwgPSB0aGlzLl90aWNrRm9ybWF0RnVuY3Rpb24odGljay52YWx1ZSwgaSwgdGlja3MpO1xuICAgICAgICB9XG4gICAgfVxuIGdldERlY2ltYWxGb3JWYWx1ZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgPyBOYU4gOiAodmFsdWUgLSB0aGlzLm1pbikgLyAodGhpcy5tYXggLSB0aGlzLm1pbik7XG4gICAgfVxuIGdldFBpeGVsRm9yVmFsdWUodmFsdWUpIHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0cyA9IHRoaXMuX29mZnNldHM7XG4gICAgICAgIGNvbnN0IHBvcyA9IHRoaXMuZ2V0RGVjaW1hbEZvclZhbHVlKHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKChvZmZzZXRzLnN0YXJ0ICsgcG9zKSAqIG9mZnNldHMuZmFjdG9yKTtcbiAgICB9XG4gZ2V0VmFsdWVGb3JQaXhlbChwaXhlbCkge1xuICAgICAgICBjb25zdCBvZmZzZXRzID0gdGhpcy5fb2Zmc2V0cztcbiAgICAgICAgY29uc3QgcG9zID0gdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpIC8gb2Zmc2V0cy5mYWN0b3IgLSBvZmZzZXRzLmVuZDtcbiAgICAgICAgcmV0dXJuIHRoaXMubWluICsgcG9zICogKHRoaXMubWF4IC0gdGhpcy5taW4pO1xuICAgIH1cbiBfZ2V0TGFiZWxTaXplKGxhYmVsKSB7XG4gICAgICAgIGNvbnN0IHRpY2tzT3B0cyA9IHRoaXMub3B0aW9ucy50aWNrcztcbiAgICAgICAgY29uc3QgdGlja0xhYmVsV2lkdGggPSB0aGlzLmN0eC5tZWFzdXJlVGV4dChsYWJlbCkud2lkdGg7XG4gICAgICAgIGNvbnN0IGFuZ2xlID0gdG9SYWRpYW5zKHRoaXMuaXNIb3Jpem9udGFsKCkgPyB0aWNrc09wdHMubWF4Um90YXRpb24gOiB0aWNrc09wdHMubWluUm90YXRpb24pO1xuICAgICAgICBjb25zdCBjb3NSb3RhdGlvbiA9IE1hdGguY29zKGFuZ2xlKTtcbiAgICAgICAgY29uc3Qgc2luUm90YXRpb24gPSBNYXRoLnNpbihhbmdsZSk7XG4gICAgICAgIGNvbnN0IHRpY2tGb250U2l6ZSA9IHRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCkuc2l6ZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHc6IHRpY2tMYWJlbFdpZHRoICogY29zUm90YXRpb24gKyB0aWNrRm9udFNpemUgKiBzaW5Sb3RhdGlvbixcbiAgICAgICAgICAgIGg6IHRpY2tMYWJlbFdpZHRoICogc2luUm90YXRpb24gKyB0aWNrRm9udFNpemUgKiBjb3NSb3RhdGlvblxuICAgICAgICB9O1xuICAgIH1cbiBfZ2V0TGFiZWxDYXBhY2l0eShleGFtcGxlVGltZSkge1xuICAgICAgICBjb25zdCB0aW1lT3B0cyA9IHRoaXMub3B0aW9ucy50aW1lO1xuICAgICAgICBjb25zdCBkaXNwbGF5Rm9ybWF0cyA9IHRpbWVPcHRzLmRpc3BsYXlGb3JtYXRzO1xuICAgICAgICBjb25zdCBmb3JtYXQgPSBkaXNwbGF5Rm9ybWF0c1t0aW1lT3B0cy51bml0XSB8fCBkaXNwbGF5Rm9ybWF0cy5taWxsaXNlY29uZDtcbiAgICAgICAgY29uc3QgZXhhbXBsZUxhYmVsID0gdGhpcy5fdGlja0Zvcm1hdEZ1bmN0aW9uKGV4YW1wbGVUaW1lLCAwLCB0aWNrc0Zyb21UaW1lc3RhbXBzKHRoaXMsIFtcbiAgICAgICAgICAgIGV4YW1wbGVUaW1lXG4gICAgICAgIF0sIHRoaXMuX21ham9yVW5pdCksIGZvcm1hdCk7XG4gICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLl9nZXRMYWJlbFNpemUoZXhhbXBsZUxhYmVsKTtcbiAgICAgICAgY29uc3QgY2FwYWNpdHkgPSBNYXRoLmZsb29yKHRoaXMuaXNIb3Jpem9udGFsKCkgPyB0aGlzLndpZHRoIC8gc2l6ZS53IDogdGhpcy5oZWlnaHQgLyBzaXplLmgpIC0gMTtcbiAgICAgICAgcmV0dXJuIGNhcGFjaXR5ID4gMCA/IGNhcGFjaXR5IDogMTtcbiAgICB9XG4gZ2V0RGF0YVRpbWVzdGFtcHMoKSB7XG4gICAgICAgIGxldCB0aW1lc3RhbXBzID0gdGhpcy5fY2FjaGUuZGF0YSB8fCBbXTtcbiAgICAgICAgbGV0IGksIGlsZW47XG4gICAgICAgIGlmICh0aW1lc3RhbXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRpbWVzdGFtcHM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbWV0YXMgPSB0aGlzLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCk7XG4gICAgICAgIGlmICh0aGlzLl9ub3JtYWxpemVkICYmIG1ldGFzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlLmRhdGEgPSBtZXRhc1swXS5jb250cm9sbGVyLmdldEFsbFBhcnNlZFZhbHVlcyh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBtZXRhcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdGltZXN0YW1wcyA9IHRpbWVzdGFtcHMuY29uY2F0KG1ldGFzW2ldLmNvbnRyb2xsZXIuZ2V0QWxsUGFyc2VkVmFsdWVzKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fY2FjaGUuZGF0YSA9IHRoaXMubm9ybWFsaXplKHRpbWVzdGFtcHMpO1xuICAgIH1cbiBnZXRMYWJlbFRpbWVzdGFtcHMoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcHMgPSB0aGlzLl9jYWNoZS5sYWJlbHMgfHwgW107XG4gICAgICAgIGxldCBpLCBpbGVuO1xuICAgICAgICBpZiAodGltZXN0YW1wcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aW1lc3RhbXBzO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuZ2V0TGFiZWxzKCk7XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGxhYmVscy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgdGltZXN0YW1wcy5wdXNoKHBhcnNlKHRoaXMsIGxhYmVsc1tpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5sYWJlbHMgPSB0aGlzLl9ub3JtYWxpemVkID8gdGltZXN0YW1wcyA6IHRoaXMubm9ybWFsaXplKHRpbWVzdGFtcHMpO1xuICAgIH1cbiBub3JtYWxpemUodmFsdWVzKSB7XG4gICAgICAgIHJldHVybiBfYXJyYXlVbmlxdWUodmFsdWVzLnNvcnQoc29ydGVyKSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpbnRlcnBvbGF0ZSh0YWJsZSwgdmFsLCByZXZlcnNlKSB7XG4gICAgbGV0IGxvID0gMDtcbiAgICBsZXQgaGkgPSB0YWJsZS5sZW5ndGggLSAxO1xuICAgIGxldCBwcmV2U291cmNlLCBuZXh0U291cmNlLCBwcmV2VGFyZ2V0LCBuZXh0VGFyZ2V0O1xuICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgIGlmICh2YWwgPj0gdGFibGVbbG9dLnBvcyAmJiB2YWwgPD0gdGFibGVbaGldLnBvcykge1xuICAgICAgICAgICAgKHsgbG8gLCBoaSAgfSA9IF9sb29rdXBCeUtleSh0YWJsZSwgJ3BvcycsIHZhbCkpO1xuICAgICAgICB9XG4gICAgICAgICh7IHBvczogcHJldlNvdXJjZSAsIHRpbWU6IHByZXZUYXJnZXQgIH0gPSB0YWJsZVtsb10pO1xuICAgICAgICAoeyBwb3M6IG5leHRTb3VyY2UgLCB0aW1lOiBuZXh0VGFyZ2V0ICB9ID0gdGFibGVbaGldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodmFsID49IHRhYmxlW2xvXS50aW1lICYmIHZhbCA8PSB0YWJsZVtoaV0udGltZSkge1xuICAgICAgICAgICAgKHsgbG8gLCBoaSAgfSA9IF9sb29rdXBCeUtleSh0YWJsZSwgJ3RpbWUnLCB2YWwpKTtcbiAgICAgICAgfVxuICAgICAgICAoeyB0aW1lOiBwcmV2U291cmNlICwgcG9zOiBwcmV2VGFyZ2V0ICB9ID0gdGFibGVbbG9dKTtcbiAgICAgICAgKHsgdGltZTogbmV4dFNvdXJjZSAsIHBvczogbmV4dFRhcmdldCAgfSA9IHRhYmxlW2hpXSk7XG4gICAgfVxuICAgIGNvbnN0IHNwYW4gPSBuZXh0U291cmNlIC0gcHJldlNvdXJjZTtcbiAgICByZXR1cm4gc3BhbiA/IHByZXZUYXJnZXQgKyAobmV4dFRhcmdldCAtIHByZXZUYXJnZXQpICogKHZhbCAtIHByZXZTb3VyY2UpIC8gc3BhbiA6IHByZXZUYXJnZXQ7XG59XG5jbGFzcyBUaW1lU2VyaWVzU2NhbGUgZXh0ZW5kcyBUaW1lU2NhbGUge1xuICAgIHN0YXRpYyBpZCA9ICd0aW1lc2VyaWVzJztcbiBzdGF0aWMgZGVmYXVsdHMgPSBUaW1lU2NhbGUuZGVmYXVsdHM7XG4gY29uc3RydWN0b3IocHJvcHMpe1xuICAgICAgICBzdXBlcihwcm9wcyk7XG4gICAgICAgICB0aGlzLl90YWJsZSA9IFtdO1xuICAgICAgICAgdGhpcy5fbWluUG9zID0gdW5kZWZpbmVkO1xuICAgICAgICAgdGhpcy5fdGFibGVSYW5nZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gaW5pdE9mZnNldHMoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcHMgPSB0aGlzLl9nZXRUaW1lc3RhbXBzRm9yVGFibGUoKTtcbiAgICAgICAgY29uc3QgdGFibGUgPSB0aGlzLl90YWJsZSA9IHRoaXMuYnVpbGRMb29rdXBUYWJsZSh0aW1lc3RhbXBzKTtcbiAgICAgICAgdGhpcy5fbWluUG9zID0gaW50ZXJwb2xhdGUodGFibGUsIHRoaXMubWluKTtcbiAgICAgICAgdGhpcy5fdGFibGVSYW5nZSA9IGludGVycG9sYXRlKHRhYmxlLCB0aGlzLm1heCkgLSB0aGlzLl9taW5Qb3M7XG4gICAgICAgIHN1cGVyLmluaXRPZmZzZXRzKHRpbWVzdGFtcHMpO1xuICAgIH1cbiBidWlsZExvb2t1cFRhYmxlKHRpbWVzdGFtcHMpIHtcbiAgICAgICAgY29uc3QgeyBtaW4gLCBtYXggIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgICAgICBjb25zdCB0YWJsZSA9IFtdO1xuICAgICAgICBsZXQgaSwgaWxlbiwgcHJldiwgY3VyciwgbmV4dDtcbiAgICAgICAgZm9yKGkgPSAwLCBpbGVuID0gdGltZXN0YW1wcy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgY3VyciA9IHRpbWVzdGFtcHNbaV07XG4gICAgICAgICAgICBpZiAoY3VyciA+PSBtaW4gJiYgY3VyciA8PSBtYXgpIHtcbiAgICAgICAgICAgICAgICBpdGVtcy5wdXNoKGN1cnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpdGVtcy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZTogbWluLFxuICAgICAgICAgICAgICAgICAgICBwb3M6IDBcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZTogbWF4LFxuICAgICAgICAgICAgICAgICAgICBwb3M6IDFcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IGl0ZW1zLmxlbmd0aDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBuZXh0ID0gaXRlbXNbaSArIDFdO1xuICAgICAgICAgICAgcHJldiA9IGl0ZW1zW2kgLSAxXTtcbiAgICAgICAgICAgIGN1cnIgPSBpdGVtc1tpXTtcbiAgICAgICAgICAgIGlmIChNYXRoLnJvdW5kKChuZXh0ICsgcHJldikgLyAyKSAhPT0gY3Vycikge1xuICAgICAgICAgICAgICAgIHRhYmxlLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB0aW1lOiBjdXJyLFxuICAgICAgICAgICAgICAgICAgICBwb3M6IGkgLyAoaWxlbiAtIDEpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRhYmxlO1xuICAgIH1cbiBfZ2V0VGltZXN0YW1wc0ZvclRhYmxlKCkge1xuICAgICAgICBsZXQgdGltZXN0YW1wcyA9IHRoaXMuX2NhY2hlLmFsbCB8fCBbXTtcbiAgICAgICAgaWYgKHRpbWVzdGFtcHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGltZXN0YW1wcztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5nZXREYXRhVGltZXN0YW1wcygpO1xuICAgICAgICBjb25zdCBsYWJlbCA9IHRoaXMuZ2V0TGFiZWxUaW1lc3RhbXBzKCk7XG4gICAgICAgIGlmIChkYXRhLmxlbmd0aCAmJiBsYWJlbC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRpbWVzdGFtcHMgPSB0aGlzLm5vcm1hbGl6ZShkYXRhLmNvbmNhdChsYWJlbCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGltZXN0YW1wcyA9IGRhdGEubGVuZ3RoID8gZGF0YSA6IGxhYmVsO1xuICAgICAgICB9XG4gICAgICAgIHRpbWVzdGFtcHMgPSB0aGlzLl9jYWNoZS5hbGwgPSB0aW1lc3RhbXBzO1xuICAgICAgICByZXR1cm4gdGltZXN0YW1wcztcbiAgICB9XG4gZ2V0RGVjaW1hbEZvclZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiAoaW50ZXJwb2xhdGUodGhpcy5fdGFibGUsIHZhbHVlKSAtIHRoaXMuX21pblBvcykgLyB0aGlzLl90YWJsZVJhbmdlO1xuICAgIH1cbiBnZXRWYWx1ZUZvclBpeGVsKHBpeGVsKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldHMgPSB0aGlzLl9vZmZzZXRzO1xuICAgICAgICBjb25zdCBkZWNpbWFsID0gdGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwocGl4ZWwpIC8gb2Zmc2V0cy5mYWN0b3IgLSBvZmZzZXRzLmVuZDtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlKHRoaXMuX3RhYmxlLCBkZWNpbWFsICogdGhpcy5fdGFibGVSYW5nZSArIHRoaXMuX21pblBvcywgdHJ1ZSk7XG4gICAgfVxufVxuXG52YXIgc2NhbGVzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuX19wcm90b19fOiBudWxsLFxuQ2F0ZWdvcnlTY2FsZTogQ2F0ZWdvcnlTY2FsZSxcbkxpbmVhclNjYWxlOiBMaW5lYXJTY2FsZSxcbkxvZ2FyaXRobWljU2NhbGU6IExvZ2FyaXRobWljU2NhbGUsXG5SYWRpYWxMaW5lYXJTY2FsZTogUmFkaWFsTGluZWFyU2NhbGUsXG5UaW1lU2NhbGU6IFRpbWVTY2FsZSxcblRpbWVTZXJpZXNTY2FsZTogVGltZVNlcmllc1NjYWxlXG59KTtcblxuY29uc3QgcmVnaXN0ZXJhYmxlcyA9IFtcbiAgICBjb250cm9sbGVycyxcbiAgICBlbGVtZW50cyxcbiAgICBwbHVnaW5zLFxuICAgIHNjYWxlc1xuXTtcblxuZXhwb3J0IHsgQW5pbWF0aW9uLCBBbmltYXRpb25zLCBBcmNFbGVtZW50LCBCYXJDb250cm9sbGVyLCBCYXJFbGVtZW50LCBCYXNlUGxhdGZvcm0sIEJhc2ljUGxhdGZvcm0sIEJ1YmJsZUNvbnRyb2xsZXIsIENhdGVnb3J5U2NhbGUsIENoYXJ0LCBwbHVnaW5fY29sb3JzIGFzIENvbG9ycywgRGF0YXNldENvbnRyb2xsZXIsIHBsdWdpbl9kZWNpbWF0aW9uIGFzIERlY2ltYXRpb24sIERvbVBsYXRmb3JtLCBEb3VnaG51dENvbnRyb2xsZXIsIEVsZW1lbnQsIGluZGV4IGFzIEZpbGxlciwgSW50ZXJhY3Rpb24sIHBsdWdpbl9sZWdlbmQgYXMgTGVnZW5kLCBMaW5lQ29udHJvbGxlciwgTGluZUVsZW1lbnQsIExpbmVhclNjYWxlLCBMb2dhcml0aG1pY1NjYWxlLCBQaWVDb250cm9sbGVyLCBQb2ludEVsZW1lbnQsIFBvbGFyQXJlYUNvbnRyb2xsZXIsIFJhZGFyQ29udHJvbGxlciwgUmFkaWFsTGluZWFyU2NhbGUsIFNjYWxlLCBTY2F0dGVyQ29udHJvbGxlciwgcGx1Z2luX3N1YnRpdGxlIGFzIFN1YlRpdGxlLCBUaWNrcywgVGltZVNjYWxlLCBUaW1lU2VyaWVzU2NhbGUsIHBsdWdpbl90aXRsZSBhcyBUaXRsZSwgcGx1Z2luX3Rvb2x0aXAgYXMgVG9vbHRpcCwgYWRhcHRlcnMgYXMgX2FkYXB0ZXJzLCBfZGV0ZWN0UGxhdGZvcm0sIGFuaW1hdG9yLCBjb250cm9sbGVycywgZGVmYXVsdHMsIGVsZW1lbnRzLCBsYXlvdXRzLCBwbHVnaW5zLCByZWdpc3RlcmFibGVzLCByZWdpc3RyeSwgc2NhbGVzIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jaGFydC5qcy5tYXBcbiIsIi8qIVxuICogQ2hhcnQuanMgdjQuMy4wXG4gKiBodHRwczovL3d3dy5jaGFydGpzLm9yZ1xuICogKGMpIDIwMjMgQ2hhcnQuanMgQ29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgQ29sb3IgfSBmcm9tICdAa3Vya2xlL2NvbG9yJztcblxuLyoqXG4gKiBAbmFtZXNwYWNlIENoYXJ0LmhlbHBlcnNcbiAqLyAvKipcbiAqIEFuIGVtcHR5IGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCBmb3Igb3B0aW9uYWwgY2FsbGJhY2suXG4gKi8gZnVuY3Rpb24gbm9vcCgpIHtcbi8qIG5vb3AgKi8gfVxuLyoqXG4gKiBSZXR1cm5zIGEgdW5pcXVlIGlkLCBzZXF1ZW50aWFsbHkgZ2VuZXJhdGVkIGZyb20gYSBnbG9iYWwgdmFyaWFibGUuXG4gKi8gY29uc3QgdWlkID0gKCgpPT57XG4gICAgbGV0IGlkID0gMDtcbiAgICByZXR1cm4gKCk9PmlkKys7XG59KSgpO1xuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYHZhbHVlYCBpcyBuZWl0aGVyIG51bGwgbm9yIHVuZGVmaW5lZCwgZWxzZSByZXR1cm5zIGZhbHNlLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIHRlc3QuXG4gKiBAc2luY2UgMi43LjBcbiAqLyBmdW5jdGlvbiBpc051bGxPclVuZGVmKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSBudWxsIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBgdmFsdWVgIGlzIGFuIGFycmF5IChpbmNsdWRpbmcgdHlwZWQgYXJyYXlzKSwgZWxzZSByZXR1cm5zIGZhbHNlLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIHRlc3QuXG4gKiBAZnVuY3Rpb25cbiAqLyBmdW5jdGlvbiBpc0FycmF5KHZhbHVlKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICAgIGlmICh0eXBlLnNsaWNlKDAsIDcpID09PSAnW29iamVjdCcgJiYgdHlwZS5zbGljZSgtNikgPT09ICdBcnJheV0nKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCAoZXhjbHVkaW5nIG51bGwpLCBlbHNlIHJldHVybnMgZmFsc2UuXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gdGVzdC5cbiAqIEBzaW5jZSAyLjcuMFxuICovIGZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IE9iamVjdF0nO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYHZhbHVlYCBpcyBhIGZpbml0ZSBudW1iZXIsIGVsc2UgcmV0dXJucyBmYWxzZVxuICogQHBhcmFtIHZhbHVlICAtIFRoZSB2YWx1ZSB0byB0ZXN0LlxuICovIGZ1bmN0aW9uIGlzTnVtYmVyRmluaXRlKHZhbHVlKSB7XG4gICAgcmV0dXJuICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHZhbHVlIGluc3RhbmNlb2YgTnVtYmVyKSAmJiBpc0Zpbml0ZSgrdmFsdWUpO1xufVxuLyoqXG4gKiBSZXR1cm5zIGB2YWx1ZWAgaWYgZmluaXRlLCBlbHNlIHJldHVybnMgYGRlZmF1bHRWYWx1ZWAuXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gcmV0dXJuIGlmIGRlZmluZWQuXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIC0gVGhlIHZhbHVlIHRvIHJldHVybiBpZiBgdmFsdWVgIGlzIG5vdCBmaW5pdGUuXG4gKi8gZnVuY3Rpb24gZmluaXRlT3JEZWZhdWx0KHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgICByZXR1cm4gaXNOdW1iZXJGaW5pdGUodmFsdWUpID8gdmFsdWUgOiBkZWZhdWx0VmFsdWU7XG59XG4vKipcbiAqIFJldHVybnMgYHZhbHVlYCBpZiBkZWZpbmVkLCBlbHNlIHJldHVybnMgYGRlZmF1bHRWYWx1ZWAuXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gcmV0dXJuIGlmIGRlZmluZWQuXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIC0gVGhlIHZhbHVlIHRvIHJldHVybiBpZiBgdmFsdWVgIGlzIHVuZGVmaW5lZC5cbiAqLyBmdW5jdGlvbiB2YWx1ZU9yRGVmYXVsdCh2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcgPyBkZWZhdWx0VmFsdWUgOiB2YWx1ZTtcbn1cbmNvbnN0IHRvUGVyY2VudGFnZSA9ICh2YWx1ZSwgZGltZW5zaW9uKT0+dHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5lbmRzV2l0aCgnJScpID8gcGFyc2VGbG9hdCh2YWx1ZSkgLyAxMDAgOiArdmFsdWUgLyBkaW1lbnNpb247XG5jb25zdCB0b0RpbWVuc2lvbiA9ICh2YWx1ZSwgZGltZW5zaW9uKT0+dHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5lbmRzV2l0aCgnJScpID8gcGFyc2VGbG9hdCh2YWx1ZSkgLyAxMDAgKiBkaW1lbnNpb24gOiArdmFsdWU7XG4vKipcbiAqIENhbGxzIGBmbmAgd2l0aCB0aGUgZ2l2ZW4gYGFyZ3NgIGluIHRoZSBzY29wZSBkZWZpbmVkIGJ5IGB0aGlzQXJnYCBhbmQgcmV0dXJucyB0aGVcbiAqIHZhbHVlIHJldHVybmVkIGJ5IGBmbmAuIElmIGBmbmAgaXMgbm90IGEgZnVuY3Rpb24sIHRoaXMgbWV0aG9kIHJldHVybnMgdW5kZWZpbmVkLlxuICogQHBhcmFtIGZuIC0gVGhlIGZ1bmN0aW9uIHRvIGNhbGwuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgd2l0aCB3aGljaCBgZm5gIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcGFyYW0gW3RoaXNBcmddIC0gVGhlIHZhbHVlIG9mIGB0aGlzYCBwcm92aWRlZCBmb3IgdGhlIGNhbGwgdG8gYGZuYC5cbiAqLyBmdW5jdGlvbiBjYWxsYmFjayhmbiwgYXJncywgdGhpc0FyZykge1xuICAgIGlmIChmbiAmJiB0eXBlb2YgZm4uY2FsbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgfVxufVxuZnVuY3Rpb24gZWFjaChsb29wYWJsZSwgZm4sIHRoaXNBcmcsIHJldmVyc2UpIHtcbiAgICBsZXQgaSwgbGVuLCBrZXlzO1xuICAgIGlmIChpc0FycmF5KGxvb3BhYmxlKSkge1xuICAgICAgICBsZW4gPSBsb29wYWJsZS5sZW5ndGg7XG4gICAgICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgICAgICBmb3IoaSA9IGxlbiAtIDE7IGkgPj0gMDsgaS0tKXtcbiAgICAgICAgICAgICAgICBmbi5jYWxsKHRoaXNBcmcsIGxvb3BhYmxlW2ldLCBpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKXtcbiAgICAgICAgICAgICAgICBmbi5jYWxsKHRoaXNBcmcsIGxvb3BhYmxlW2ldLCBpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QobG9vcGFibGUpKSB7XG4gICAgICAgIGtleXMgPSBPYmplY3Qua2V5cyhsb29wYWJsZSk7XG4gICAgICAgIGxlbiA9IGtleXMubGVuZ3RoO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKyl7XG4gICAgICAgICAgICBmbi5jYWxsKHRoaXNBcmcsIGxvb3BhYmxlW2tleXNbaV1dLCBrZXlzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBgYTBgIGFuZCBgYTFgIGFycmF5cyBoYXZlIHRoZSBzYW1lIGNvbnRlbnQsIGVsc2UgcmV0dXJucyBmYWxzZS5cbiAqIEBwYXJhbSBhMCAtIFRoZSBhcnJheSB0byBjb21wYXJlXG4gKiBAcGFyYW0gYTEgLSBUaGUgYXJyYXkgdG8gY29tcGFyZVxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfZWxlbWVudHNFcXVhbChhMCwgYTEpIHtcbiAgICBsZXQgaSwgaWxlbiwgdjAsIHYxO1xuICAgIGlmICghYTAgfHwgIWExIHx8IGEwLmxlbmd0aCAhPT0gYTEubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yKGkgPSAwLCBpbGVuID0gYTAubGVuZ3RoOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgdjAgPSBhMFtpXTtcbiAgICAgICAgdjEgPSBhMVtpXTtcbiAgICAgICAgaWYgKHYwLmRhdGFzZXRJbmRleCAhPT0gdjEuZGF0YXNldEluZGV4IHx8IHYwLmluZGV4ICE9PSB2MS5pbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuLyoqXG4gKiBSZXR1cm5zIGEgZGVlcCBjb3B5IG9mIGBzb3VyY2VgIHdpdGhvdXQga2VlcGluZyByZWZlcmVuY2VzIG9uIG9iamVjdHMgYW5kIGFycmF5cy5cbiAqIEBwYXJhbSBzb3VyY2UgLSBUaGUgdmFsdWUgdG8gY2xvbmUuXG4gKi8gZnVuY3Rpb24gY2xvbmUoc291cmNlKSB7XG4gICAgaWYgKGlzQXJyYXkoc291cmNlKSkge1xuICAgICAgICByZXR1cm4gc291cmNlLm1hcChjbG9uZSk7XG4gICAgfVxuICAgIGlmIChpc09iamVjdChzb3VyY2UpKSB7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuICAgICAgICBjb25zdCBrbGVuID0ga2V5cy5sZW5ndGg7XG4gICAgICAgIGxldCBrID0gMDtcbiAgICAgICAgZm9yKDsgayA8IGtsZW47ICsrayl7XG4gICAgICAgICAgICB0YXJnZXRba2V5c1trXV0gPSBjbG9uZShzb3VyY2Vba2V5c1trXV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfVxuICAgIHJldHVybiBzb3VyY2U7XG59XG5mdW5jdGlvbiBpc1ZhbGlkS2V5KGtleSkge1xuICAgIHJldHVybiBbXG4gICAgICAgICdfX3Byb3RvX18nLFxuICAgICAgICAncHJvdG90eXBlJyxcbiAgICAgICAgJ2NvbnN0cnVjdG9yJ1xuICAgIF0uaW5kZXhPZihrZXkpID09PSAtMTtcbn1cbi8qKlxuICogVGhlIGRlZmF1bHQgbWVyZ2VyIHdoZW4gQ2hhcnQuaGVscGVycy5tZXJnZSBpcyBjYWxsZWQgd2l0aG91dCBtZXJnZXIgb3B0aW9uLlxuICogTm90ZShTQik6IGFsc28gdXNlZCBieSBtZXJnZUNvbmZpZyBhbmQgbWVyZ2VTY2FsZUNvbmZpZyBhcyBmYWxsYmFjay5cbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX21lcmdlcihrZXksIHRhcmdldCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgaWYgKCFpc1ZhbGlkS2V5KGtleSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0dmFsID0gdGFyZ2V0W2tleV07XG4gICAgY29uc3Qgc3ZhbCA9IHNvdXJjZVtrZXldO1xuICAgIGlmIChpc09iamVjdCh0dmFsKSAmJiBpc09iamVjdChzdmFsKSkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVzZS1iZWZvcmUtZGVmaW5lXG4gICAgICAgIG1lcmdlKHR2YWwsIHN2YWwsIG9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRhcmdldFtrZXldID0gY2xvbmUoc3ZhbCk7XG4gICAgfVxufVxuZnVuY3Rpb24gbWVyZ2UodGFyZ2V0LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBzb3VyY2VzID0gaXNBcnJheShzb3VyY2UpID8gc291cmNlIDogW1xuICAgICAgICBzb3VyY2VcbiAgICBdO1xuICAgIGNvbnN0IGlsZW4gPSBzb3VyY2VzLmxlbmd0aDtcbiAgICBpZiAoIWlzT2JqZWN0KHRhcmdldCkpIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgY29uc3QgbWVyZ2VyID0gb3B0aW9ucy5tZXJnZXIgfHwgX21lcmdlcjtcbiAgICBsZXQgY3VycmVudDtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgaWxlbjsgKytpKXtcbiAgICAgICAgY3VycmVudCA9IHNvdXJjZXNbaV07XG4gICAgICAgIGlmICghaXNPYmplY3QoY3VycmVudCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhjdXJyZW50KTtcbiAgICAgICAgZm9yKGxldCBrID0gMCwga2xlbiA9IGtleXMubGVuZ3RoOyBrIDwga2xlbjsgKytrKXtcbiAgICAgICAgICAgIG1lcmdlcihrZXlzW2tdLCB0YXJnZXQsIGN1cnJlbnQsIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG59XG5mdW5jdGlvbiBtZXJnZUlmKHRhcmdldCwgc291cmNlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11c2UtYmVmb3JlLWRlZmluZVxuICAgIHJldHVybiBtZXJnZSh0YXJnZXQsIHNvdXJjZSwge1xuICAgICAgICBtZXJnZXI6IF9tZXJnZXJJZlxuICAgIH0pO1xufVxuLyoqXG4gKiBNZXJnZXMgc291cmNlW2tleV0gaW4gdGFyZ2V0W2tleV0gb25seSBpZiB0YXJnZXRba2V5XSBpcyB1bmRlZmluZWQuXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9tZXJnZXJJZihrZXksIHRhcmdldCwgc291cmNlKSB7XG4gICAgaWYgKCFpc1ZhbGlkS2V5KGtleSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0dmFsID0gdGFyZ2V0W2tleV07XG4gICAgY29uc3Qgc3ZhbCA9IHNvdXJjZVtrZXldO1xuICAgIGlmIChpc09iamVjdCh0dmFsKSAmJiBpc09iamVjdChzdmFsKSkge1xuICAgICAgICBtZXJnZUlmKHR2YWwsIHN2YWwpO1xuICAgIH0gZWxzZSBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIGtleSkpIHtcbiAgICAgICAgdGFyZ2V0W2tleV0gPSBjbG9uZShzdmFsKTtcbiAgICB9XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2RlcHJlY2F0ZWQoc2NvcGUsIHZhbHVlLCBwcmV2aW91cywgY3VycmVudCkge1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihzY29wZSArICc6IFwiJyArIHByZXZpb3VzICsgJ1wiIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgXCInICsgY3VycmVudCArICdcIiBpbnN0ZWFkJyk7XG4gICAgfVxufVxuLy8gcmVzb2x2ZU9iamVjdEtleSByZXNvbHZlciBjYWNoZVxuY29uc3Qga2V5UmVzb2x2ZXJzID0ge1xuICAgIC8vIENoYXJ0LmhlbHBlcnMuY29yZSByZXNvbHZlT2JqZWN0S2V5IHNob3VsZCByZXNvbHZlIGVtcHR5IGtleSB0byByb290IG9iamVjdFxuICAgICcnOiAodik9PnYsXG4gICAgLy8gZGVmYXVsdCByZXNvbHZlcnNcbiAgICB4OiAobyk9Pm8ueCxcbiAgICB5OiAobyk9Pm8ueVxufTtcbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfc3BsaXRLZXkoa2V5KSB7XG4gICAgY29uc3QgcGFydHMgPSBrZXkuc3BsaXQoJy4nKTtcbiAgICBjb25zdCBrZXlzID0gW107XG4gICAgbGV0IHRtcCA9ICcnO1xuICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXJ0cyl7XG4gICAgICAgIHRtcCArPSBwYXJ0O1xuICAgICAgICBpZiAodG1wLmVuZHNXaXRoKCdcXFxcJykpIHtcbiAgICAgICAgICAgIHRtcCA9IHRtcC5zbGljZSgwLCAtMSkgKyAnLic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBrZXlzLnB1c2godG1wKTtcbiAgICAgICAgICAgIHRtcCA9ICcnO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrZXlzO1xufVxuZnVuY3Rpb24gX2dldEtleVJlc29sdmVyKGtleSkge1xuICAgIGNvbnN0IGtleXMgPSBfc3BsaXRLZXkoa2V5KTtcbiAgICByZXR1cm4gKG9iaik9PntcbiAgICAgICAgZm9yIChjb25zdCBrIG9mIGtleXMpe1xuICAgICAgICAgICAgaWYgKGsgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvYmogPSBvYmogJiYgb2JqW2tdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3RLZXkob2JqLCBrZXkpIHtcbiAgICBjb25zdCByZXNvbHZlciA9IGtleVJlc29sdmVyc1trZXldIHx8IChrZXlSZXNvbHZlcnNba2V5XSA9IF9nZXRLZXlSZXNvbHZlcihrZXkpKTtcbiAgICByZXR1cm4gcmVzb2x2ZXIob2JqKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfY2FwaXRhbGl6ZShzdHIpIHtcbiAgICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xufVxuY29uc3QgZGVmaW5lZCA9ICh2YWx1ZSk9PnR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCc7XG5jb25zdCBpc0Z1bmN0aW9uID0gKHZhbHVlKT0+dHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nO1xuLy8gQWRhcHRlZCBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMxMTI4ODU1L2NvbXBhcmluZy1lY21hNi1zZXRzLWZvci1lcXVhbGl0eSMzMTEyOTM4NFxuY29uc3Qgc2V0c0VxdWFsID0gKGEsIGIpPT57XG4gICAgaWYgKGEuc2l6ZSAhPT0gYi5zaXplKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIGEpe1xuICAgICAgICBpZiAoIWIuaGFzKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59O1xuLyoqXG4gKiBAcGFyYW0gZSAtIFRoZSBldmVudFxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfaXNDbGlja0V2ZW50KGUpIHtcbiAgICByZXR1cm4gZS50eXBlID09PSAnbW91c2V1cCcgfHwgZS50eXBlID09PSAnY2xpY2snIHx8IGUudHlwZSA9PT0gJ2NvbnRleHRtZW51Jztcbn1cblxuLyoqXG4gKiBAYWxpYXMgQ2hhcnQuaGVscGVycy5tYXRoXG4gKiBAbmFtZXNwYWNlXG4gKi8gY29uc3QgUEkgPSBNYXRoLlBJO1xuY29uc3QgVEFVID0gMiAqIFBJO1xuY29uc3QgUElUQVUgPSBUQVUgKyBQSTtcbmNvbnN0IElORklOSVRZID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuY29uc3QgUkFEX1BFUl9ERUcgPSBQSSAvIDE4MDtcbmNvbnN0IEhBTEZfUEkgPSBQSSAvIDI7XG5jb25zdCBRVUFSVEVSX1BJID0gUEkgLyA0O1xuY29uc3QgVFdPX1RISVJEU19QSSA9IFBJICogMiAvIDM7XG5jb25zdCBsb2cxMCA9IE1hdGgubG9nMTA7XG5jb25zdCBzaWduID0gTWF0aC5zaWduO1xuZnVuY3Rpb24gYWxtb3N0RXF1YWxzKHgsIHksIGVwc2lsb24pIHtcbiAgICByZXR1cm4gTWF0aC5hYnMoeCAtIHkpIDwgZXBzaWxvbjtcbn1cbi8qKlxuICogSW1wbGVtZW50YXRpb24gb2YgdGhlIG5pY2UgbnVtYmVyIGFsZ29yaXRobSB1c2VkIGluIGRldGVybWluaW5nIHdoZXJlIGF4aXMgbGFiZWxzIHdpbGwgZ29cbiAqLyBmdW5jdGlvbiBuaWNlTnVtKHJhbmdlKSB7XG4gICAgY29uc3Qgcm91bmRlZFJhbmdlID0gTWF0aC5yb3VuZChyYW5nZSk7XG4gICAgcmFuZ2UgPSBhbG1vc3RFcXVhbHMocmFuZ2UsIHJvdW5kZWRSYW5nZSwgcmFuZ2UgLyAxMDAwKSA/IHJvdW5kZWRSYW5nZSA6IHJhbmdlO1xuICAgIGNvbnN0IG5pY2VSYW5nZSA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKGxvZzEwKHJhbmdlKSkpO1xuICAgIGNvbnN0IGZyYWN0aW9uID0gcmFuZ2UgLyBuaWNlUmFuZ2U7XG4gICAgY29uc3QgbmljZUZyYWN0aW9uID0gZnJhY3Rpb24gPD0gMSA/IDEgOiBmcmFjdGlvbiA8PSAyID8gMiA6IGZyYWN0aW9uIDw9IDUgPyA1IDogMTA7XG4gICAgcmV0dXJuIG5pY2VGcmFjdGlvbiAqIG5pY2VSYW5nZTtcbn1cbi8qKlxuICogUmV0dXJucyBhbiBhcnJheSBvZiBmYWN0b3JzIHNvcnRlZCBmcm9tIDEgdG8gc3FydCh2YWx1ZSlcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2ZhY3Rvcml6ZSh2YWx1ZSkge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IHNxcnQgPSBNYXRoLnNxcnQodmFsdWUpO1xuICAgIGxldCBpO1xuICAgIGZvcihpID0gMTsgaSA8IHNxcnQ7IGkrKyl7XG4gICAgICAgIGlmICh2YWx1ZSAlIGkgPT09IDApIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGkpO1xuICAgICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUgLyBpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoc3FydCA9PT0gKHNxcnQgfCAwKSkge1xuICAgICAgICByZXN1bHQucHVzaChzcXJ0KTtcbiAgICB9XG4gICAgcmVzdWx0LnNvcnQoKGEsIGIpPT5hIC0gYikucG9wKCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGlzTnVtYmVyKG4pIHtcbiAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xufVxuZnVuY3Rpb24gYWxtb3N0V2hvbGUoeCwgZXBzaWxvbikge1xuICAgIGNvbnN0IHJvdW5kZWQgPSBNYXRoLnJvdW5kKHgpO1xuICAgIHJldHVybiByb3VuZGVkIC0gZXBzaWxvbiA8PSB4ICYmIHJvdW5kZWQgKyBlcHNpbG9uID49IHg7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX3NldE1pbkFuZE1heEJ5S2V5KGFycmF5LCB0YXJnZXQsIHByb3BlcnR5KSB7XG4gICAgbGV0IGksIGlsZW4sIHZhbHVlO1xuICAgIGZvcihpID0gMCwgaWxlbiA9IGFycmF5Lmxlbmd0aDsgaSA8IGlsZW47IGkrKyl7XG4gICAgICAgIHZhbHVlID0gYXJyYXlbaV1bcHJvcGVydHldO1xuICAgICAgICBpZiAoIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgdGFyZ2V0Lm1pbiA9IE1hdGgubWluKHRhcmdldC5taW4sIHZhbHVlKTtcbiAgICAgICAgICAgIHRhcmdldC5tYXggPSBNYXRoLm1heCh0YXJnZXQubWF4LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiB0b1JhZGlhbnMoZGVncmVlcykge1xuICAgIHJldHVybiBkZWdyZWVzICogKFBJIC8gMTgwKTtcbn1cbmZ1bmN0aW9uIHRvRGVncmVlcyhyYWRpYW5zKSB7XG4gICAgcmV0dXJuIHJhZGlhbnMgKiAoMTgwIC8gUEkpO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXNcbiAqIGkuZS4gdGhlIG51bWJlciBvZiBkaWdpdHMgYWZ0ZXIgdGhlIGRlY2ltYWwgcG9pbnQsIG9mIHRoZSB2YWx1ZSBvZiB0aGlzIE51bWJlci5cbiAqIEBwYXJhbSB4IC0gQSBudW1iZXIuXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzLlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfZGVjaW1hbFBsYWNlcyh4KSB7XG4gICAgaWYgKCFpc051bWJlckZpbml0ZSh4KSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBlID0gMTtcbiAgICBsZXQgcCA9IDA7XG4gICAgd2hpbGUoTWF0aC5yb3VuZCh4ICogZSkgLyBlICE9PSB4KXtcbiAgICAgICAgZSAqPSAxMDtcbiAgICAgICAgcCsrO1xuICAgIH1cbiAgICByZXR1cm4gcDtcbn1cbi8vIEdldHMgdGhlIGFuZ2xlIGZyb20gdmVydGljYWwgdXByaWdodCB0byB0aGUgcG9pbnQgYWJvdXQgYSBjZW50cmUuXG5mdW5jdGlvbiBnZXRBbmdsZUZyb21Qb2ludChjZW50cmVQb2ludCwgYW5nbGVQb2ludCkge1xuICAgIGNvbnN0IGRpc3RhbmNlRnJvbVhDZW50ZXIgPSBhbmdsZVBvaW50LnggLSBjZW50cmVQb2ludC54O1xuICAgIGNvbnN0IGRpc3RhbmNlRnJvbVlDZW50ZXIgPSBhbmdsZVBvaW50LnkgLSBjZW50cmVQb2ludC55O1xuICAgIGNvbnN0IHJhZGlhbERpc3RhbmNlRnJvbUNlbnRlciA9IE1hdGguc3FydChkaXN0YW5jZUZyb21YQ2VudGVyICogZGlzdGFuY2VGcm9tWENlbnRlciArIGRpc3RhbmNlRnJvbVlDZW50ZXIgKiBkaXN0YW5jZUZyb21ZQ2VudGVyKTtcbiAgICBsZXQgYW5nbGUgPSBNYXRoLmF0YW4yKGRpc3RhbmNlRnJvbVlDZW50ZXIsIGRpc3RhbmNlRnJvbVhDZW50ZXIpO1xuICAgIGlmIChhbmdsZSA8IC0wLjUgKiBQSSkge1xuICAgICAgICBhbmdsZSArPSBUQVU7IC8vIG1ha2Ugc3VyZSB0aGUgcmV0dXJuZWQgYW5nbGUgaXMgaW4gdGhlIHJhbmdlIG9mICgtUEkvMiwgM1BJLzJdXG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGFuZ2xlLFxuICAgICAgICBkaXN0YW5jZTogcmFkaWFsRGlzdGFuY2VGcm9tQ2VudGVyXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGRpc3RhbmNlQmV0d2VlblBvaW50cyhwdDEsIHB0Mikge1xuICAgIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3cocHQyLnggLSBwdDEueCwgMikgKyBNYXRoLnBvdyhwdDIueSAtIHB0MS55LCAyKSk7XG59XG4vKipcbiAqIFNob3J0ZXN0IGRpc3RhbmNlIGJldHdlZW4gYW5nbGVzLCBpbiBlaXRoZXIgZGlyZWN0aW9uLlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYW5nbGVEaWZmKGEsIGIpIHtcbiAgICByZXR1cm4gKGEgLSBiICsgUElUQVUpICUgVEFVIC0gUEk7XG59XG4vKipcbiAqIE5vcm1hbGl6ZSBhbmdsZSB0byBiZSBiZXR3ZWVuIDAgYW5kIDIqUElcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX25vcm1hbGl6ZUFuZ2xlKGEpIHtcbiAgICByZXR1cm4gKGEgJSBUQVUgKyBUQVUpICUgVEFVO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9hbmdsZUJldHdlZW4oYW5nbGUsIHN0YXJ0LCBlbmQsIHNhbWVBbmdsZUlzRnVsbENpcmNsZSkge1xuICAgIGNvbnN0IGEgPSBfbm9ybWFsaXplQW5nbGUoYW5nbGUpO1xuICAgIGNvbnN0IHMgPSBfbm9ybWFsaXplQW5nbGUoc3RhcnQpO1xuICAgIGNvbnN0IGUgPSBfbm9ybWFsaXplQW5nbGUoZW5kKTtcbiAgICBjb25zdCBhbmdsZVRvU3RhcnQgPSBfbm9ybWFsaXplQW5nbGUocyAtIGEpO1xuICAgIGNvbnN0IGFuZ2xlVG9FbmQgPSBfbm9ybWFsaXplQW5nbGUoZSAtIGEpO1xuICAgIGNvbnN0IHN0YXJ0VG9BbmdsZSA9IF9ub3JtYWxpemVBbmdsZShhIC0gcyk7XG4gICAgY29uc3QgZW5kVG9BbmdsZSA9IF9ub3JtYWxpemVBbmdsZShhIC0gZSk7XG4gICAgcmV0dXJuIGEgPT09IHMgfHwgYSA9PT0gZSB8fCBzYW1lQW5nbGVJc0Z1bGxDaXJjbGUgJiYgcyA9PT0gZSB8fCBhbmdsZVRvU3RhcnQgPiBhbmdsZVRvRW5kICYmIHN0YXJ0VG9BbmdsZSA8IGVuZFRvQW5nbGU7XG59XG4vKipcbiAqIExpbWl0IGB2YWx1ZWAgYmV0d2VlbiBgbWluYCBhbmQgYG1heGBcbiAqIEBwYXJhbSB2YWx1ZVxuICogQHBhcmFtIG1pblxuICogQHBhcmFtIG1heFxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfbGltaXRWYWx1ZSh2YWx1ZSwgbWluLCBtYXgpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihtYXgsIHZhbHVlKSk7XG59XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfaW50MTZSYW5nZSh2YWx1ZSkge1xuICAgIHJldHVybiBfbGltaXRWYWx1ZSh2YWx1ZSwgLTMyNzY4LCAzMjc2Nyk7XG59XG4vKipcbiAqIEBwYXJhbSB2YWx1ZVxuICogQHBhcmFtIHN0YXJ0XG4gKiBAcGFyYW0gZW5kXG4gKiBAcGFyYW0gW2Vwc2lsb25dXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9pc0JldHdlZW4odmFsdWUsIHN0YXJ0LCBlbmQsIGVwc2lsb24gPSAxZS02KSB7XG4gICAgcmV0dXJuIHZhbHVlID49IE1hdGgubWluKHN0YXJ0LCBlbmQpIC0gZXBzaWxvbiAmJiB2YWx1ZSA8PSBNYXRoLm1heChzdGFydCwgZW5kKSArIGVwc2lsb247XG59XG5cbmZ1bmN0aW9uIF9sb29rdXAodGFibGUsIHZhbHVlLCBjbXApIHtcbiAgICBjbXAgPSBjbXAgfHwgKChpbmRleCk9PnRhYmxlW2luZGV4XSA8IHZhbHVlKTtcbiAgICBsZXQgaGkgPSB0YWJsZS5sZW5ndGggLSAxO1xuICAgIGxldCBsbyA9IDA7XG4gICAgbGV0IG1pZDtcbiAgICB3aGlsZShoaSAtIGxvID4gMSl7XG4gICAgICAgIG1pZCA9IGxvICsgaGkgPj4gMTtcbiAgICAgICAgaWYgKGNtcChtaWQpKSB7XG4gICAgICAgICAgICBsbyA9IG1pZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGxvLFxuICAgICAgICBoaVxuICAgIH07XG59XG4vKipcbiAqIEJpbmFyeSBzZWFyY2hcbiAqIEBwYXJhbSB0YWJsZSAtIHRoZSB0YWJsZSBzZWFyY2guIG11c3QgYmUgc29ydGVkIVxuICogQHBhcmFtIGtleSAtIHByb3BlcnR5IG5hbWUgZm9yIHRoZSB2YWx1ZSBpbiBlYWNoIGVudHJ5XG4gKiBAcGFyYW0gdmFsdWUgLSB2YWx1ZSB0byBmaW5kXG4gKiBAcGFyYW0gbGFzdCAtIGxvb2t1cCBsYXN0IGluZGV4XG4gKiBAcHJpdmF0ZVxuICovIGNvbnN0IF9sb29rdXBCeUtleSA9ICh0YWJsZSwga2V5LCB2YWx1ZSwgbGFzdCk9Pl9sb29rdXAodGFibGUsIHZhbHVlLCBsYXN0ID8gKGluZGV4KT0+e1xuICAgICAgICBjb25zdCB0aSA9IHRhYmxlW2luZGV4XVtrZXldO1xuICAgICAgICByZXR1cm4gdGkgPCB2YWx1ZSB8fCB0aSA9PT0gdmFsdWUgJiYgdGFibGVbaW5kZXggKyAxXVtrZXldID09PSB2YWx1ZTtcbiAgICB9IDogKGluZGV4KT0+dGFibGVbaW5kZXhdW2tleV0gPCB2YWx1ZSk7XG4vKipcbiAqIFJldmVyc2UgYmluYXJ5IHNlYXJjaFxuICogQHBhcmFtIHRhYmxlIC0gdGhlIHRhYmxlIHNlYXJjaC4gbXVzdCBiZSBzb3J0ZWQhXG4gKiBAcGFyYW0ga2V5IC0gcHJvcGVydHkgbmFtZSBmb3IgdGhlIHZhbHVlIGluIGVhY2ggZW50cnlcbiAqIEBwYXJhbSB2YWx1ZSAtIHZhbHVlIHRvIGZpbmRcbiAqIEBwcml2YXRlXG4gKi8gY29uc3QgX3Jsb29rdXBCeUtleSA9ICh0YWJsZSwga2V5LCB2YWx1ZSk9Pl9sb29rdXAodGFibGUsIHZhbHVlLCAoaW5kZXgpPT50YWJsZVtpbmRleF1ba2V5XSA+PSB2YWx1ZSk7XG4vKipcbiAqIFJldHVybiBzdWJzZXQgb2YgYHZhbHVlc2AgYmV0d2VlbiBgbWluYCBhbmQgYG1heGAgaW5jbHVzaXZlLlxuICogVmFsdWVzIGFyZSBhc3N1bWVkIHRvIGJlIGluIHNvcnRlZCBvcmRlci5cbiAqIEBwYXJhbSB2YWx1ZXMgLSBzb3J0ZWQgYXJyYXkgb2YgdmFsdWVzXG4gKiBAcGFyYW0gbWluIC0gbWluIHZhbHVlXG4gKiBAcGFyYW0gbWF4IC0gbWF4IHZhbHVlXG4gKi8gZnVuY3Rpb24gX2ZpbHRlckJldHdlZW4odmFsdWVzLCBtaW4sIG1heCkge1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGVuZCA9IHZhbHVlcy5sZW5ndGg7XG4gICAgd2hpbGUoc3RhcnQgPCBlbmQgJiYgdmFsdWVzW3N0YXJ0XSA8IG1pbil7XG4gICAgICAgIHN0YXJ0Kys7XG4gICAgfVxuICAgIHdoaWxlKGVuZCA+IHN0YXJ0ICYmIHZhbHVlc1tlbmQgLSAxXSA+IG1heCl7XG4gICAgICAgIGVuZC0tO1xuICAgIH1cbiAgICByZXR1cm4gc3RhcnQgPiAwIHx8IGVuZCA8IHZhbHVlcy5sZW5ndGggPyB2YWx1ZXMuc2xpY2Uoc3RhcnQsIGVuZCkgOiB2YWx1ZXM7XG59XG5jb25zdCBhcnJheUV2ZW50cyA9IFtcbiAgICAncHVzaCcsXG4gICAgJ3BvcCcsXG4gICAgJ3NoaWZ0JyxcbiAgICAnc3BsaWNlJyxcbiAgICAndW5zaGlmdCdcbl07XG5mdW5jdGlvbiBsaXN0ZW5BcnJheUV2ZW50cyhhcnJheSwgbGlzdGVuZXIpIHtcbiAgICBpZiAoYXJyYXkuX2NoYXJ0anMpIHtcbiAgICAgICAgYXJyYXkuX2NoYXJ0anMubGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcnJheSwgJ19jaGFydGpzJywge1xuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgbGlzdGVuZXJzOiBbXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJcbiAgICAgICAgICAgIF1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGFycmF5RXZlbnRzLmZvckVhY2goKGtleSk9PntcbiAgICAgICAgY29uc3QgbWV0aG9kID0gJ19vbkRhdGEnICsgX2NhcGl0YWxpemUoa2V5KTtcbiAgICAgICAgY29uc3QgYmFzZSA9IGFycmF5W2tleV07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcnJheSwga2V5LCB7XG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbHVlICguLi5hcmdzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzID0gYmFzZS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgICAgICBhcnJheS5fY2hhcnRqcy5saXN0ZW5lcnMuZm9yRWFjaCgob2JqZWN0KT0+e1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdFttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbbWV0aG9kXSguLi5hcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gdW5saXN0ZW5BcnJheUV2ZW50cyhhcnJheSwgbGlzdGVuZXIpIHtcbiAgICBjb25zdCBzdHViID0gYXJyYXkuX2NoYXJ0anM7XG4gICAgaWYgKCFzdHViKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGlzdGVuZXJzID0gc3R1Yi5saXN0ZW5lcnM7XG4gICAgY29uc3QgaW5kZXggPSBsaXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcik7XG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG4gICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXJyYXlFdmVudHMuZm9yRWFjaCgoa2V5KT0+e1xuICAgICAgICBkZWxldGUgYXJyYXlba2V5XTtcbiAgICB9KTtcbiAgICBkZWxldGUgYXJyYXkuX2NoYXJ0anM7XG59XG4vKipcbiAqIEBwYXJhbSBpdGVtc1xuICovIGZ1bmN0aW9uIF9hcnJheVVuaXF1ZShpdGVtcykge1xuICAgIGNvbnN0IHNldCA9IG5ldyBTZXQoaXRlbXMpO1xuICAgIGlmIChzZXQuc2l6ZSA9PT0gaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBpdGVtcztcbiAgICB9XG4gICAgcmV0dXJuIEFycmF5LmZyb20oc2V0KTtcbn1cblxuZnVuY3Rpb24gZm9udFN0cmluZyhwaXhlbFNpemUsIGZvbnRTdHlsZSwgZm9udEZhbWlseSkge1xuICAgIHJldHVybiBmb250U3R5bGUgKyAnICcgKyBwaXhlbFNpemUgKyAncHggJyArIGZvbnRGYW1pbHk7XG59XG4vKipcbiogUmVxdWVzdCBhbmltYXRpb24gcG9seWZpbGxcbiovIGNvbnN0IHJlcXVlc3RBbmltRnJhbWUgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWU7XG59KCk7XG4vKipcbiAqIFRocm90dGxlcyBjYWxsaW5nIGBmbmAgb25jZSBwZXIgYW5pbWF0aW9uIGZyYW1lXG4gKiBMYXRlc3QgYXJndW1lbnRzIGFyZSB1c2VkIG9uIHRoZSBhY3R1YWwgY2FsbFxuICovIGZ1bmN0aW9uIHRocm90dGxlZChmbiwgdGhpc0FyZykge1xuICAgIGxldCBhcmdzVG9Vc2UgPSBbXTtcbiAgICBsZXQgdGlja2luZyA9IGZhbHNlO1xuICAgIHJldHVybiBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgIC8vIFNhdmUgdGhlIGFyZ3MgZm9yIHVzZSBsYXRlclxuICAgICAgICBhcmdzVG9Vc2UgPSBhcmdzO1xuICAgICAgICBpZiAoIXRpY2tpbmcpIHtcbiAgICAgICAgICAgIHRpY2tpbmcgPSB0cnVlO1xuICAgICAgICAgICAgcmVxdWVzdEFuaW1GcmFtZS5jYWxsKHdpbmRvdywgKCk9PntcbiAgICAgICAgICAgICAgICB0aWNraW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm4uYXBwbHkodGhpc0FyZywgYXJnc1RvVXNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbn1cbi8qKlxuICogRGVib3VuY2VzIGNhbGxpbmcgYGZuYCBmb3IgYGRlbGF5YCBtc1xuICovIGZ1bmN0aW9uIGRlYm91bmNlKGZuLCBkZWxheSkge1xuICAgIGxldCB0aW1lb3V0O1xuICAgIHJldHVybiBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgIGlmIChkZWxheSkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoZm4sIGRlbGF5LCBhcmdzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkZWxheTtcbiAgICB9O1xufVxuLyoqXG4gKiBDb252ZXJ0cyAnc3RhcnQnIHRvICdsZWZ0JywgJ2VuZCcgdG8gJ3JpZ2h0JyBhbmQgb3RoZXJzIHRvICdjZW50ZXInXG4gKiBAcHJpdmF0ZVxuICovIGNvbnN0IF90b0xlZnRSaWdodENlbnRlciA9IChhbGlnbik9PmFsaWduID09PSAnc3RhcnQnID8gJ2xlZnQnIDogYWxpZ24gPT09ICdlbmQnID8gJ3JpZ2h0JyA6ICdjZW50ZXInO1xuLyoqXG4gKiBSZXR1cm5zIGBzdGFydGAsIGBlbmRgIG9yIGAoc3RhcnQgKyBlbmQpIC8gMmAgZGVwZW5kaW5nIG9uIGBhbGlnbmAuIERlZmF1bHRzIHRvIGBjZW50ZXJgXG4gKiBAcHJpdmF0ZVxuICovIGNvbnN0IF9hbGlnblN0YXJ0RW5kID0gKGFsaWduLCBzdGFydCwgZW5kKT0+YWxpZ24gPT09ICdzdGFydCcgPyBzdGFydCA6IGFsaWduID09PSAnZW5kJyA/IGVuZCA6IChzdGFydCArIGVuZCkgLyAyO1xuLyoqXG4gKiBSZXR1cm5zIGBsZWZ0YCwgYHJpZ2h0YCBvciBgKGxlZnQgKyByaWdodCkgLyAyYCBkZXBlbmRpbmcgb24gYGFsaWduYC4gRGVmYXVsdHMgdG8gYGxlZnRgXG4gKiBAcHJpdmF0ZVxuICovIGNvbnN0IF90ZXh0WCA9IChhbGlnbiwgbGVmdCwgcmlnaHQsIHJ0bCk9PntcbiAgICBjb25zdCBjaGVjayA9IHJ0bCA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgcmV0dXJuIGFsaWduID09PSBjaGVjayA/IHJpZ2h0IDogYWxpZ24gPT09ICdjZW50ZXInID8gKGxlZnQgKyByaWdodCkgLyAyIDogbGVmdDtcbn07XG4vKipcbiAqIFJldHVybiBzdGFydCBhbmQgY291bnQgb2YgdmlzaWJsZSBwb2ludHMuXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9nZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzKG1ldGEsIHBvaW50cywgYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgY29uc3QgcG9pbnRDb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgbGV0IHN0YXJ0ID0gMDtcbiAgICBsZXQgY291bnQgPSBwb2ludENvdW50O1xuICAgIGlmIChtZXRhLl9zb3J0ZWQpIHtcbiAgICAgICAgY29uc3QgeyBpU2NhbGUgLCBfcGFyc2VkICB9ID0gbWV0YTtcbiAgICAgICAgY29uc3QgYXhpcyA9IGlTY2FsZS5heGlzO1xuICAgICAgICBjb25zdCB7IG1pbiAsIG1heCAsIG1pbkRlZmluZWQgLCBtYXhEZWZpbmVkICB9ID0gaVNjYWxlLmdldFVzZXJCb3VuZHMoKTtcbiAgICAgICAgaWYgKG1pbkRlZmluZWQpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gX2xpbWl0VmFsdWUoTWF0aC5taW4oLy8gQHRzLWV4cGVjdC1lcnJvciBOZWVkIHRvIHR5cGUgX3BhcnNlZFxuICAgICAgICAgICAgX2xvb2t1cEJ5S2V5KF9wYXJzZWQsIGlTY2FsZS5heGlzLCBtaW4pLmxvLCAvLyBAdHMtZXhwZWN0LWVycm9yIE5lZWQgdG8gZml4IHR5cGVzIG9uIF9sb29rdXBCeUtleVxuICAgICAgICAgICAgYW5pbWF0aW9uc0Rpc2FibGVkID8gcG9pbnRDb3VudCA6IF9sb29rdXBCeUtleShwb2ludHMsIGF4aXMsIGlTY2FsZS5nZXRQaXhlbEZvclZhbHVlKG1pbikpLmxvKSwgMCwgcG9pbnRDb3VudCAtIDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXhEZWZpbmVkKSB7XG4gICAgICAgICAgICBjb3VudCA9IF9saW1pdFZhbHVlKE1hdGgubWF4KC8vIEB0cy1leHBlY3QtZXJyb3IgTmVlZCB0byB0eXBlIF9wYXJzZWRcbiAgICAgICAgICAgIF9sb29rdXBCeUtleShfcGFyc2VkLCBpU2NhbGUuYXhpcywgbWF4LCB0cnVlKS5oaSArIDEsIC8vIEB0cy1leHBlY3QtZXJyb3IgTmVlZCB0byBmaXggdHlwZXMgb24gX2xvb2t1cEJ5S2V5XG4gICAgICAgICAgICBhbmltYXRpb25zRGlzYWJsZWQgPyAwIDogX2xvb2t1cEJ5S2V5KHBvaW50cywgYXhpcywgaVNjYWxlLmdldFBpeGVsRm9yVmFsdWUobWF4KSwgdHJ1ZSkuaGkgKyAxKSwgc3RhcnQsIHBvaW50Q291bnQpIC0gc3RhcnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb3VudCA9IHBvaW50Q291bnQgLSBzdGFydDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydCxcbiAgICAgICAgY291bnRcbiAgICB9O1xufVxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIHNjYWxlIHJhbmdlcyBoYXZlIGNoYW5nZWQuXG4gKiBAcGFyYW0ge29iamVjdH0gbWV0YSAtIGRhdGFzZXQgbWV0YS5cbiAqIEByZXR1cm5zIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfc2NhbGVSYW5nZXNDaGFuZ2VkKG1ldGEpIHtcbiAgICBjb25zdCB7IHhTY2FsZSAsIHlTY2FsZSAsIF9zY2FsZVJhbmdlcyAgfSA9IG1ldGE7XG4gICAgY29uc3QgbmV3UmFuZ2VzID0ge1xuICAgICAgICB4bWluOiB4U2NhbGUubWluLFxuICAgICAgICB4bWF4OiB4U2NhbGUubWF4LFxuICAgICAgICB5bWluOiB5U2NhbGUubWluLFxuICAgICAgICB5bWF4OiB5U2NhbGUubWF4XG4gICAgfTtcbiAgICBpZiAoIV9zY2FsZVJhbmdlcykge1xuICAgICAgICBtZXRhLl9zY2FsZVJhbmdlcyA9IG5ld1JhbmdlcztcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IGNoYW5nZWQgPSBfc2NhbGVSYW5nZXMueG1pbiAhPT0geFNjYWxlLm1pbiB8fCBfc2NhbGVSYW5nZXMueG1heCAhPT0geFNjYWxlLm1heCB8fCBfc2NhbGVSYW5nZXMueW1pbiAhPT0geVNjYWxlLm1pbiB8fCBfc2NhbGVSYW5nZXMueW1heCAhPT0geVNjYWxlLm1heDtcbiAgICBPYmplY3QuYXNzaWduKF9zY2FsZVJhbmdlcywgbmV3UmFuZ2VzKTtcbiAgICByZXR1cm4gY2hhbmdlZDtcbn1cblxuY29uc3QgYXRFZGdlID0gKHQpPT50ID09PSAwIHx8IHQgPT09IDE7XG5jb25zdCBlbGFzdGljSW4gPSAodCwgcywgcCk9Pi0oTWF0aC5wb3coMiwgMTAgKiAodCAtPSAxKSkgKiBNYXRoLnNpbigodCAtIHMpICogVEFVIC8gcCkpO1xuY29uc3QgZWxhc3RpY091dCA9ICh0LCBzLCBwKT0+TWF0aC5wb3coMiwgLTEwICogdCkgKiBNYXRoLnNpbigodCAtIHMpICogVEFVIC8gcCkgKyAxO1xuLyoqXG4gKiBFYXNpbmcgZnVuY3Rpb25zIGFkYXB0ZWQgZnJvbSBSb2JlcnQgUGVubmVyJ3MgZWFzaW5nIGVxdWF0aW9ucy5cbiAqIEBuYW1lc3BhY2UgQ2hhcnQuaGVscGVycy5lYXNpbmcuZWZmZWN0c1xuICogQHNlZSBodHRwOi8vd3d3LnJvYmVydHBlbm5lci5jb20vZWFzaW5nL1xuICovIGNvbnN0IGVmZmVjdHMgPSB7XG4gICAgbGluZWFyOiAodCk9PnQsXG4gICAgZWFzZUluUXVhZDogKHQpPT50ICogdCxcbiAgICBlYXNlT3V0UXVhZDogKHQpPT4tdCAqICh0IC0gMiksXG4gICAgZWFzZUluT3V0UXVhZDogKHQpPT4odCAvPSAwLjUpIDwgMSA/IDAuNSAqIHQgKiB0IDogLTAuNSAqICgtLXQgKiAodCAtIDIpIC0gMSksXG4gICAgZWFzZUluQ3ViaWM6ICh0KT0+dCAqIHQgKiB0LFxuICAgIGVhc2VPdXRDdWJpYzogKHQpPT4odCAtPSAxKSAqIHQgKiB0ICsgMSxcbiAgICBlYXNlSW5PdXRDdWJpYzogKHQpPT4odCAvPSAwLjUpIDwgMSA/IDAuNSAqIHQgKiB0ICogdCA6IDAuNSAqICgodCAtPSAyKSAqIHQgKiB0ICsgMiksXG4gICAgZWFzZUluUXVhcnQ6ICh0KT0+dCAqIHQgKiB0ICogdCxcbiAgICBlYXNlT3V0UXVhcnQ6ICh0KT0+LSgodCAtPSAxKSAqIHQgKiB0ICogdCAtIDEpLFxuICAgIGVhc2VJbk91dFF1YXJ0OiAodCk9Pih0IC89IDAuNSkgPCAxID8gMC41ICogdCAqIHQgKiB0ICogdCA6IC0wLjUgKiAoKHQgLT0gMikgKiB0ICogdCAqIHQgLSAyKSxcbiAgICBlYXNlSW5RdWludDogKHQpPT50ICogdCAqIHQgKiB0ICogdCxcbiAgICBlYXNlT3V0UXVpbnQ6ICh0KT0+KHQgLT0gMSkgKiB0ICogdCAqIHQgKiB0ICsgMSxcbiAgICBlYXNlSW5PdXRRdWludDogKHQpPT4odCAvPSAwLjUpIDwgMSA/IDAuNSAqIHQgKiB0ICogdCAqIHQgKiB0IDogMC41ICogKCh0IC09IDIpICogdCAqIHQgKiB0ICogdCArIDIpLFxuICAgIGVhc2VJblNpbmU6ICh0KT0+LU1hdGguY29zKHQgKiBIQUxGX1BJKSArIDEsXG4gICAgZWFzZU91dFNpbmU6ICh0KT0+TWF0aC5zaW4odCAqIEhBTEZfUEkpLFxuICAgIGVhc2VJbk91dFNpbmU6ICh0KT0+LTAuNSAqIChNYXRoLmNvcyhQSSAqIHQpIC0gMSksXG4gICAgZWFzZUluRXhwbzogKHQpPT50ID09PSAwID8gMCA6IE1hdGgucG93KDIsIDEwICogKHQgLSAxKSksXG4gICAgZWFzZU91dEV4cG86ICh0KT0+dCA9PT0gMSA/IDEgOiAtTWF0aC5wb3coMiwgLTEwICogdCkgKyAxLFxuICAgIGVhc2VJbk91dEV4cG86ICh0KT0+YXRFZGdlKHQpID8gdCA6IHQgPCAwLjUgPyAwLjUgKiBNYXRoLnBvdygyLCAxMCAqICh0ICogMiAtIDEpKSA6IDAuNSAqICgtTWF0aC5wb3coMiwgLTEwICogKHQgKiAyIC0gMSkpICsgMiksXG4gICAgZWFzZUluQ2lyYzogKHQpPT50ID49IDEgPyB0IDogLShNYXRoLnNxcnQoMSAtIHQgKiB0KSAtIDEpLFxuICAgIGVhc2VPdXRDaXJjOiAodCk9Pk1hdGguc3FydCgxIC0gKHQgLT0gMSkgKiB0KSxcbiAgICBlYXNlSW5PdXRDaXJjOiAodCk9Pih0IC89IDAuNSkgPCAxID8gLTAuNSAqIChNYXRoLnNxcnQoMSAtIHQgKiB0KSAtIDEpIDogMC41ICogKE1hdGguc3FydCgxIC0gKHQgLT0gMikgKiB0KSArIDEpLFxuICAgIGVhc2VJbkVsYXN0aWM6ICh0KT0+YXRFZGdlKHQpID8gdCA6IGVsYXN0aWNJbih0LCAwLjA3NSwgMC4zKSxcbiAgICBlYXNlT3V0RWxhc3RpYzogKHQpPT5hdEVkZ2UodCkgPyB0IDogZWxhc3RpY091dCh0LCAwLjA3NSwgMC4zKSxcbiAgICBlYXNlSW5PdXRFbGFzdGljICh0KSB7XG4gICAgICAgIGNvbnN0IHMgPSAwLjExMjU7XG4gICAgICAgIGNvbnN0IHAgPSAwLjQ1O1xuICAgICAgICByZXR1cm4gYXRFZGdlKHQpID8gdCA6IHQgPCAwLjUgPyAwLjUgKiBlbGFzdGljSW4odCAqIDIsIHMsIHApIDogMC41ICsgMC41ICogZWxhc3RpY091dCh0ICogMiAtIDEsIHMsIHApO1xuICAgIH0sXG4gICAgZWFzZUluQmFjayAodCkge1xuICAgICAgICBjb25zdCBzID0gMS43MDE1ODtcbiAgICAgICAgcmV0dXJuIHQgKiB0ICogKChzICsgMSkgKiB0IC0gcyk7XG4gICAgfSxcbiAgICBlYXNlT3V0QmFjayAodCkge1xuICAgICAgICBjb25zdCBzID0gMS43MDE1ODtcbiAgICAgICAgcmV0dXJuICh0IC09IDEpICogdCAqICgocyArIDEpICogdCArIHMpICsgMTtcbiAgICB9LFxuICAgIGVhc2VJbk91dEJhY2sgKHQpIHtcbiAgICAgICAgbGV0IHMgPSAxLjcwMTU4O1xuICAgICAgICBpZiAoKHQgLz0gMC41KSA8IDEpIHtcbiAgICAgICAgICAgIHJldHVybiAwLjUgKiAodCAqIHQgKiAoKChzICo9IDEuNTI1KSArIDEpICogdCAtIHMpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMC41ICogKCh0IC09IDIpICogdCAqICgoKHMgKj0gMS41MjUpICsgMSkgKiB0ICsgcykgKyAyKTtcbiAgICB9LFxuICAgIGVhc2VJbkJvdW5jZTogKHQpPT4xIC0gZWZmZWN0cy5lYXNlT3V0Qm91bmNlKDEgLSB0KSxcbiAgICBlYXNlT3V0Qm91bmNlICh0KSB7XG4gICAgICAgIGNvbnN0IG0gPSA3LjU2MjU7XG4gICAgICAgIGNvbnN0IGQgPSAyLjc1O1xuICAgICAgICBpZiAodCA8IDEgLyBkKSB7XG4gICAgICAgICAgICByZXR1cm4gbSAqIHQgKiB0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0IDwgMiAvIGQpIHtcbiAgICAgICAgICAgIHJldHVybiBtICogKHQgLT0gMS41IC8gZCkgKiB0ICsgMC43NTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodCA8IDIuNSAvIGQpIHtcbiAgICAgICAgICAgIHJldHVybiBtICogKHQgLT0gMi4yNSAvIGQpICogdCArIDAuOTM3NTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbSAqICh0IC09IDIuNjI1IC8gZCkgKiB0ICsgMC45ODQzNzU7XG4gICAgfSxcbiAgICBlYXNlSW5PdXRCb3VuY2U6ICh0KT0+dCA8IDAuNSA/IGVmZmVjdHMuZWFzZUluQm91bmNlKHQgKiAyKSAqIDAuNSA6IGVmZmVjdHMuZWFzZU91dEJvdW5jZSh0ICogMiAtIDEpICogMC41ICsgMC41XG59O1xuXG5mdW5jdGlvbiBpc1BhdHRlcm5PckdyYWRpZW50KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgY29uc3QgdHlwZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHJldHVybiB0eXBlID09PSAnW29iamVjdCBDYW52YXNQYXR0ZXJuXScgfHwgdHlwZSA9PT0gJ1tvYmplY3QgQ2FudmFzR3JhZGllbnRdJztcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gY29sb3IodmFsdWUpIHtcbiAgICByZXR1cm4gaXNQYXR0ZXJuT3JHcmFkaWVudCh2YWx1ZSkgPyB2YWx1ZSA6IG5ldyBDb2xvcih2YWx1ZSk7XG59XG5mdW5jdGlvbiBnZXRIb3ZlckNvbG9yKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzUGF0dGVybk9yR3JhZGllbnQodmFsdWUpID8gdmFsdWUgOiBuZXcgQ29sb3IodmFsdWUpLnNhdHVyYXRlKDAuNSkuZGFya2VuKDAuMSkuaGV4U3RyaW5nKCk7XG59XG5cbmNvbnN0IG51bWJlcnMgPSBbXG4gICAgJ3gnLFxuICAgICd5JyxcbiAgICAnYm9yZGVyV2lkdGgnLFxuICAgICdyYWRpdXMnLFxuICAgICd0ZW5zaW9uJ1xuXTtcbmNvbnN0IGNvbG9ycyA9IFtcbiAgICAnY29sb3InLFxuICAgICdib3JkZXJDb2xvcicsXG4gICAgJ2JhY2tncm91bmRDb2xvcidcbl07XG5mdW5jdGlvbiBhcHBseUFuaW1hdGlvbnNEZWZhdWx0cyhkZWZhdWx0cykge1xuICAgIGRlZmF1bHRzLnNldCgnYW5pbWF0aW9uJywge1xuICAgICAgICBkZWxheTogdW5kZWZpbmVkLFxuICAgICAgICBkdXJhdGlvbjogMTAwMCxcbiAgICAgICAgZWFzaW5nOiAnZWFzZU91dFF1YXJ0JyxcbiAgICAgICAgZm46IHVuZGVmaW5lZCxcbiAgICAgICAgZnJvbTogdW5kZWZpbmVkLFxuICAgICAgICBsb29wOiB1bmRlZmluZWQsXG4gICAgICAgIHRvOiB1bmRlZmluZWQsXG4gICAgICAgIHR5cGU6IHVuZGVmaW5lZFxuICAgIH0pO1xuICAgIGRlZmF1bHRzLmRlc2NyaWJlKCdhbmltYXRpb24nLCB7XG4gICAgICAgIF9mYWxsYmFjazogZmFsc2UsXG4gICAgICAgIF9pbmRleGFibGU6IGZhbHNlLFxuICAgICAgICBfc2NyaXB0YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnb25Qcm9ncmVzcycgJiYgbmFtZSAhPT0gJ29uQ29tcGxldGUnICYmIG5hbWUgIT09ICdmbidcbiAgICB9KTtcbiAgICBkZWZhdWx0cy5zZXQoJ2FuaW1hdGlvbnMnLCB7XG4gICAgICAgIGNvbG9yczoge1xuICAgICAgICAgICAgdHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IGNvbG9yc1xuICAgICAgICB9LFxuICAgICAgICBudW1iZXJzOiB7XG4gICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IG51bWJlcnNcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGRlZmF1bHRzLmRlc2NyaWJlKCdhbmltYXRpb25zJywge1xuICAgICAgICBfZmFsbGJhY2s6ICdhbmltYXRpb24nXG4gICAgfSk7XG4gICAgZGVmYXVsdHMuc2V0KCd0cmFuc2l0aW9ucycsIHtcbiAgICAgICAgYWN0aXZlOiB7XG4gICAgICAgICAgICBhbmltYXRpb246IHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogNDAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlc2l6ZToge1xuICAgICAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2hvdzoge1xuICAgICAgICAgICAgYW5pbWF0aW9uczoge1xuICAgICAgICAgICAgICAgIGNvbG9yczoge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiAndHJhbnNwYXJlbnQnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb246IDBcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGhpZGU6IHtcbiAgICAgICAgICAgIGFuaW1hdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBjb2xvcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgdG86ICd0cmFuc3BhcmVudCdcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHZpc2libGU6IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgICAgICAgICBlYXNpbmc6ICdsaW5lYXInLFxuICAgICAgICAgICAgICAgICAgICBmbjogKHYpPT52IHwgMFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhcHBseUxheW91dHNEZWZhdWx0cyhkZWZhdWx0cykge1xuICAgIGRlZmF1bHRzLnNldCgnbGF5b3V0Jywge1xuICAgICAgICBhdXRvUGFkZGluZzogdHJ1ZSxcbiAgICAgICAgcGFkZGluZzoge1xuICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgcmlnaHQ6IDAsXG4gICAgICAgICAgICBib3R0b206IDAsXG4gICAgICAgICAgICBsZWZ0OiAwXG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuY29uc3QgaW50bENhY2hlID0gbmV3IE1hcCgpO1xuZnVuY3Rpb24gZ2V0TnVtYmVyRm9ybWF0KGxvY2FsZSwgb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gbG9jYWxlICsgSlNPTi5zdHJpbmdpZnkob3B0aW9ucyk7XG4gICAgbGV0IGZvcm1hdHRlciA9IGludGxDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmICghZm9ybWF0dGVyKSB7XG4gICAgICAgIGZvcm1hdHRlciA9IG5ldyBJbnRsLk51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpO1xuICAgICAgICBpbnRsQ2FjaGUuc2V0KGNhY2hlS2V5LCBmb3JtYXR0ZXIpO1xuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0dGVyO1xufVxuZnVuY3Rpb24gZm9ybWF0TnVtYmVyKG51bSwgbG9jYWxlLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGdldE51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpLmZvcm1hdChudW0pO1xufVxuXG5jb25zdCBmb3JtYXR0ZXJzID0ge1xuIHZhbHVlcyAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodmFsdWUpID8gIHZhbHVlIDogJycgKyB2YWx1ZTtcbiAgICB9LFxuIG51bWVyaWMgKHRpY2tWYWx1ZSwgaW5kZXgsIHRpY2tzKSB7XG4gICAgICAgIGlmICh0aWNrVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAnMCc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbG9jYWxlID0gdGhpcy5jaGFydC5vcHRpb25zLmxvY2FsZTtcbiAgICAgICAgbGV0IG5vdGF0aW9uO1xuICAgICAgICBsZXQgZGVsdGEgPSB0aWNrVmFsdWU7XG4gICAgICAgIGlmICh0aWNrcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBjb25zdCBtYXhUaWNrID0gTWF0aC5tYXgoTWF0aC5hYnModGlja3NbMF0udmFsdWUpLCBNYXRoLmFicyh0aWNrc1t0aWNrcy5sZW5ndGggLSAxXS52YWx1ZSkpO1xuICAgICAgICAgICAgaWYgKG1heFRpY2sgPCAxZS00IHx8IG1heFRpY2sgPiAxZSsxNSkge1xuICAgICAgICAgICAgICAgIG5vdGF0aW9uID0gJ3NjaWVudGlmaWMnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsdGEgPSBjYWxjdWxhdGVEZWx0YSh0aWNrVmFsdWUsIHRpY2tzKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsb2dEZWx0YSA9IGxvZzEwKE1hdGguYWJzKGRlbHRhKSk7XG4gICAgICAgIGNvbnN0IG51bURlY2ltYWwgPSBpc05hTihsb2dEZWx0YSkgPyAxIDogTWF0aC5tYXgoTWF0aC5taW4oLTEgKiBNYXRoLmZsb29yKGxvZ0RlbHRhKSwgMjApLCAwKTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIG5vdGF0aW9uLFxuICAgICAgICAgICAgbWluaW11bUZyYWN0aW9uRGlnaXRzOiBudW1EZWNpbWFsLFxuICAgICAgICAgICAgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBudW1EZWNpbWFsXG4gICAgICAgIH07XG4gICAgICAgIE9iamVjdC5hc3NpZ24ob3B0aW9ucywgdGhpcy5vcHRpb25zLnRpY2tzLmZvcm1hdCk7XG4gICAgICAgIHJldHVybiBmb3JtYXROdW1iZXIodGlja1ZhbHVlLCBsb2NhbGUsIG9wdGlvbnMpO1xuICAgIH0sXG4gbG9nYXJpdGhtaWMgKHRpY2tWYWx1ZSwgaW5kZXgsIHRpY2tzKSB7XG4gICAgICAgIGlmICh0aWNrVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAnMCc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVtYWluID0gdGlja3NbaW5kZXhdLnNpZ25pZmljYW5kIHx8IHRpY2tWYWx1ZSAvIE1hdGgucG93KDEwLCBNYXRoLmZsb29yKGxvZzEwKHRpY2tWYWx1ZSkpKTtcbiAgICAgICAgaWYgKFtcbiAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAyLFxuICAgICAgICAgICAgMyxcbiAgICAgICAgICAgIDUsXG4gICAgICAgICAgICAxMCxcbiAgICAgICAgICAgIDE1XG4gICAgICAgIF0uaW5jbHVkZXMocmVtYWluKSB8fCBpbmRleCA+IDAuOCAqIHRpY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlcnMubnVtZXJpYy5jYWxsKHRoaXMsIHRpY2tWYWx1ZSwgaW5kZXgsIHRpY2tzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxufTtcbmZ1bmN0aW9uIGNhbGN1bGF0ZURlbHRhKHRpY2tWYWx1ZSwgdGlja3MpIHtcbiAgICBsZXQgZGVsdGEgPSB0aWNrcy5sZW5ndGggPiAzID8gdGlja3NbMl0udmFsdWUgLSB0aWNrc1sxXS52YWx1ZSA6IHRpY2tzWzFdLnZhbHVlIC0gdGlja3NbMF0udmFsdWU7XG4gICAgaWYgKE1hdGguYWJzKGRlbHRhKSA+PSAxICYmIHRpY2tWYWx1ZSAhPT0gTWF0aC5mbG9vcih0aWNrVmFsdWUpKSB7XG4gICAgICAgIGRlbHRhID0gdGlja1ZhbHVlIC0gTWF0aC5mbG9vcih0aWNrVmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gZGVsdGE7XG59XG4gdmFyIFRpY2tzID0ge1xuICAgIGZvcm1hdHRlcnNcbn07XG5cbmZ1bmN0aW9uIGFwcGx5U2NhbGVEZWZhdWx0cyhkZWZhdWx0cykge1xuICAgIGRlZmF1bHRzLnNldCgnc2NhbGUnLCB7XG4gICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgIG9mZnNldDogZmFsc2UsXG4gICAgICAgIHJldmVyc2U6IGZhbHNlLFxuICAgICAgICBiZWdpbkF0WmVybzogZmFsc2UsXG4gYm91bmRzOiAndGlja3MnLFxuIGdyYWNlOiAwLFxuICAgICAgICBncmlkOiB7XG4gICAgICAgICAgICBkaXNwbGF5OiB0cnVlLFxuICAgICAgICAgICAgbGluZVdpZHRoOiAxLFxuICAgICAgICAgICAgZHJhd09uQ2hhcnRBcmVhOiB0cnVlLFxuICAgICAgICAgICAgZHJhd1RpY2tzOiB0cnVlLFxuICAgICAgICAgICAgdGlja0xlbmd0aDogOCxcbiAgICAgICAgICAgIHRpY2tXaWR0aDogKF9jdHgsIG9wdGlvbnMpPT5vcHRpb25zLmxpbmVXaWR0aCxcbiAgICAgICAgICAgIHRpY2tDb2xvcjogKF9jdHgsIG9wdGlvbnMpPT5vcHRpb25zLmNvbG9yLFxuICAgICAgICAgICAgb2Zmc2V0OiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICBib3JkZXI6IHtcbiAgICAgICAgICAgIGRpc3BsYXk6IHRydWUsXG4gICAgICAgICAgICBkYXNoOiBbXSxcbiAgICAgICAgICAgIGRhc2hPZmZzZXQ6IDAuMCxcbiAgICAgICAgICAgIHdpZHRoOiAxXG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlOiB7XG4gICAgICAgICAgICBkaXNwbGF5OiBmYWxzZSxcbiAgICAgICAgICAgIHRleHQ6ICcnLFxuICAgICAgICAgICAgcGFkZGluZzoge1xuICAgICAgICAgICAgICAgIHRvcDogNCxcbiAgICAgICAgICAgICAgICBib3R0b206IDRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdGlja3M6IHtcbiAgICAgICAgICAgIG1pblJvdGF0aW9uOiAwLFxuICAgICAgICAgICAgbWF4Um90YXRpb246IDUwLFxuICAgICAgICAgICAgbWlycm9yOiBmYWxzZSxcbiAgICAgICAgICAgIHRleHRTdHJva2VXaWR0aDogMCxcbiAgICAgICAgICAgIHRleHRTdHJva2VDb2xvcjogJycsXG4gICAgICAgICAgICBwYWRkaW5nOiAzLFxuICAgICAgICAgICAgZGlzcGxheTogdHJ1ZSxcbiAgICAgICAgICAgIGF1dG9Ta2lwOiB0cnVlLFxuICAgICAgICAgICAgYXV0b1NraXBQYWRkaW5nOiAzLFxuICAgICAgICAgICAgbGFiZWxPZmZzZXQ6IDAsXG4gICAgICAgICAgICBjYWxsYmFjazogVGlja3MuZm9ybWF0dGVycy52YWx1ZXMsXG4gICAgICAgICAgICBtaW5vcjoge30sXG4gICAgICAgICAgICBtYWpvcjoge30sXG4gICAgICAgICAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgICAgICAgICBjcm9zc0FsaWduOiAnbmVhcicsXG4gICAgICAgICAgICBzaG93TGFiZWxCYWNrZHJvcDogZmFsc2UsXG4gICAgICAgICAgICBiYWNrZHJvcENvbG9yOiAncmdiYSgyNTUsIDI1NSwgMjU1LCAwLjc1KScsXG4gICAgICAgICAgICBiYWNrZHJvcFBhZGRpbmc6IDJcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGRlZmF1bHRzLnJvdXRlKCdzY2FsZS50aWNrcycsICdjb2xvcicsICcnLCAnY29sb3InKTtcbiAgICBkZWZhdWx0cy5yb3V0ZSgnc2NhbGUuZ3JpZCcsICdjb2xvcicsICcnLCAnYm9yZGVyQ29sb3InKTtcbiAgICBkZWZhdWx0cy5yb3V0ZSgnc2NhbGUuYm9yZGVyJywgJ2NvbG9yJywgJycsICdib3JkZXJDb2xvcicpO1xuICAgIGRlZmF1bHRzLnJvdXRlKCdzY2FsZS50aXRsZScsICdjb2xvcicsICcnLCAnY29sb3InKTtcbiAgICBkZWZhdWx0cy5kZXNjcmliZSgnc2NhbGUnLCB7XG4gICAgICAgIF9mYWxsYmFjazogZmFsc2UsXG4gICAgICAgIF9zY3JpcHRhYmxlOiAobmFtZSk9PiFuYW1lLnN0YXJ0c1dpdGgoJ2JlZm9yZScpICYmICFuYW1lLnN0YXJ0c1dpdGgoJ2FmdGVyJykgJiYgbmFtZSAhPT0gJ2NhbGxiYWNrJyAmJiBuYW1lICE9PSAncGFyc2VyJyxcbiAgICAgICAgX2luZGV4YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnYm9yZGVyRGFzaCcgJiYgbmFtZSAhPT0gJ3RpY2tCb3JkZXJEYXNoJyAmJiBuYW1lICE9PSAnZGFzaCdcbiAgICB9KTtcbiAgICBkZWZhdWx0cy5kZXNjcmliZSgnc2NhbGVzJywge1xuICAgICAgICBfZmFsbGJhY2s6ICdzY2FsZSdcbiAgICB9KTtcbiAgICBkZWZhdWx0cy5kZXNjcmliZSgnc2NhbGUudGlja3MnLCB7XG4gICAgICAgIF9zY3JpcHRhYmxlOiAobmFtZSk9Pm5hbWUgIT09ICdiYWNrZHJvcFBhZGRpbmcnICYmIG5hbWUgIT09ICdjYWxsYmFjaycsXG4gICAgICAgIF9pbmRleGFibGU6IChuYW1lKT0+bmFtZSAhPT0gJ2JhY2tkcm9wUGFkZGluZydcbiAgICB9KTtcbn1cblxuY29uc3Qgb3ZlcnJpZGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbmNvbnN0IGRlc2NyaXB0b3JzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiBmdW5jdGlvbiBnZXRTY29wZSQxKG5vZGUsIGtleSkge1xuICAgIGlmICgha2V5KSB7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH1cbiAgICBjb25zdCBrZXlzID0ga2V5LnNwbGl0KCcuJyk7XG4gICAgZm9yKGxldCBpID0gMCwgbiA9IGtleXMubGVuZ3RoOyBpIDwgbjsgKytpKXtcbiAgICAgICAgY29uc3QgayA9IGtleXNbaV07XG4gICAgICAgIG5vZGUgPSBub2RlW2tdIHx8IChub2RlW2tdID0gT2JqZWN0LmNyZWF0ZShudWxsKSk7XG4gICAgfVxuICAgIHJldHVybiBub2RlO1xufVxuZnVuY3Rpb24gc2V0KHJvb3QsIHNjb3BlLCB2YWx1ZXMpIHtcbiAgICBpZiAodHlwZW9mIHNjb3BlID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gbWVyZ2UoZ2V0U2NvcGUkMShyb290LCBzY29wZSksIHZhbHVlcyk7XG4gICAgfVxuICAgIHJldHVybiBtZXJnZShnZXRTY29wZSQxKHJvb3QsICcnKSwgc2NvcGUpO1xufVxuIGNsYXNzIERlZmF1bHRzIHtcbiAgICBjb25zdHJ1Y3RvcihfZGVzY3JpcHRvcnMsIF9hcHBsaWVycyl7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9ICdyZ2JhKDAsMCwwLDAuMSknO1xuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gJ3JnYmEoMCwwLDAsMC4xKSc7XG4gICAgICAgIHRoaXMuY29sb3IgPSAnIzY2Nic7XG4gICAgICAgIHRoaXMuZGF0YXNldHMgPSB7fTtcbiAgICAgICAgdGhpcy5kZXZpY2VQaXhlbFJhdGlvID0gKGNvbnRleHQpPT5jb250ZXh0LmNoYXJ0LnBsYXRmb3JtLmdldERldmljZVBpeGVsUmF0aW8oKTtcbiAgICAgICAgdGhpcy5lbGVtZW50cyA9IHt9O1xuICAgICAgICB0aGlzLmV2ZW50cyA9IFtcbiAgICAgICAgICAgICdtb3VzZW1vdmUnLFxuICAgICAgICAgICAgJ21vdXNlb3V0JyxcbiAgICAgICAgICAgICdjbGljaycsXG4gICAgICAgICAgICAndG91Y2hzdGFydCcsXG4gICAgICAgICAgICAndG91Y2htb3ZlJ1xuICAgICAgICBdO1xuICAgICAgICB0aGlzLmZvbnQgPSB7XG4gICAgICAgICAgICBmYW1pbHk6IFwiJ0hlbHZldGljYSBOZXVlJywgJ0hlbHZldGljYScsICdBcmlhbCcsIHNhbnMtc2VyaWZcIixcbiAgICAgICAgICAgIHNpemU6IDEyLFxuICAgICAgICAgICAgc3R5bGU6ICdub3JtYWwnLFxuICAgICAgICAgICAgbGluZUhlaWdodDogMS4yLFxuICAgICAgICAgICAgd2VpZ2h0OiBudWxsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaG92ZXIgPSB7fTtcbiAgICAgICAgdGhpcy5ob3ZlckJhY2tncm91bmRDb2xvciA9IChjdHgsIG9wdGlvbnMpPT5nZXRIb3ZlckNvbG9yKG9wdGlvbnMuYmFja2dyb3VuZENvbG9yKTtcbiAgICAgICAgdGhpcy5ob3ZlckJvcmRlckNvbG9yID0gKGN0eCwgb3B0aW9ucyk9PmdldEhvdmVyQ29sb3Iob3B0aW9ucy5ib3JkZXJDb2xvcik7XG4gICAgICAgIHRoaXMuaG92ZXJDb2xvciA9IChjdHgsIG9wdGlvbnMpPT5nZXRIb3ZlckNvbG9yKG9wdGlvbnMuY29sb3IpO1xuICAgICAgICB0aGlzLmluZGV4QXhpcyA9ICd4JztcbiAgICAgICAgdGhpcy5pbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgIG1vZGU6ICduZWFyZXN0JyxcbiAgICAgICAgICAgIGludGVyc2VjdDogdHJ1ZSxcbiAgICAgICAgICAgIGluY2x1ZGVJbnZpc2libGU6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMubWFpbnRhaW5Bc3BlY3RSYXRpbyA9IHRydWU7XG4gICAgICAgIHRoaXMub25Ib3ZlciA9IG51bGw7XG4gICAgICAgIHRoaXMub25DbGljayA9IG51bGw7XG4gICAgICAgIHRoaXMucGFyc2luZyA9IHRydWU7XG4gICAgICAgIHRoaXMucGx1Z2lucyA9IHt9O1xuICAgICAgICB0aGlzLnJlc3BvbnNpdmUgPSB0cnVlO1xuICAgICAgICB0aGlzLnNjYWxlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnNjYWxlcyA9IHt9O1xuICAgICAgICB0aGlzLnNob3dMaW5lID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kcmF3QWN0aXZlRWxlbWVudHNPblRvcCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGVzY3JpYmUoX2Rlc2NyaXB0b3JzKTtcbiAgICAgICAgdGhpcy5hcHBseShfYXBwbGllcnMpO1xuICAgIH1cbiBzZXQoc2NvcGUsIHZhbHVlcykge1xuICAgICAgICByZXR1cm4gc2V0KHRoaXMsIHNjb3BlLCB2YWx1ZXMpO1xuICAgIH1cbiBnZXQoc2NvcGUpIHtcbiAgICAgICAgcmV0dXJuIGdldFNjb3BlJDEodGhpcywgc2NvcGUpO1xuICAgIH1cbiBkZXNjcmliZShzY29wZSwgdmFsdWVzKSB7XG4gICAgICAgIHJldHVybiBzZXQoZGVzY3JpcHRvcnMsIHNjb3BlLCB2YWx1ZXMpO1xuICAgIH1cbiAgICBvdmVycmlkZShzY29wZSwgdmFsdWVzKSB7XG4gICAgICAgIHJldHVybiBzZXQob3ZlcnJpZGVzLCBzY29wZSwgdmFsdWVzKTtcbiAgICB9XG4gcm91dGUoc2NvcGUsIG5hbWUsIHRhcmdldFNjb3BlLCB0YXJnZXROYW1lKSB7XG4gICAgICAgIGNvbnN0IHNjb3BlT2JqZWN0ID0gZ2V0U2NvcGUkMSh0aGlzLCBzY29wZSk7XG4gICAgICAgIGNvbnN0IHRhcmdldFNjb3BlT2JqZWN0ID0gZ2V0U2NvcGUkMSh0aGlzLCB0YXJnZXRTY29wZSk7XG4gICAgICAgIGNvbnN0IHByaXZhdGVOYW1lID0gJ18nICsgbmFtZTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoc2NvcGVPYmplY3QsIHtcbiAgICAgICAgICAgIFtwcml2YXRlTmFtZV06IHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogc2NvcGVPYmplY3RbbmFtZV0sXG4gICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBbbmFtZV06IHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGdldCAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsID0gdGhpc1twcml2YXRlTmFtZV07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IHRhcmdldFNjb3BlT2JqZWN0W3RhcmdldE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QobG9jYWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgdGFyZ2V0LCBsb2NhbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlT3JEZWZhdWx0KGxvY2FsLCB0YXJnZXQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0ICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzW3ByaXZhdGVOYW1lXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFwcGx5KGFwcGxpZXJzKSB7XG4gICAgICAgIGFwcGxpZXJzLmZvckVhY2goKGFwcGx5KT0+YXBwbHkodGhpcykpO1xuICAgIH1cbn1cbnZhciBkZWZhdWx0cyA9IC8qICNfX1BVUkVfXyAqLyBuZXcgRGVmYXVsdHMoe1xuICAgIF9zY3JpcHRhYmxlOiAobmFtZSk9PiFuYW1lLnN0YXJ0c1dpdGgoJ29uJyksXG4gICAgX2luZGV4YWJsZTogKG5hbWUpPT5uYW1lICE9PSAnZXZlbnRzJyxcbiAgICBob3Zlcjoge1xuICAgICAgICBfZmFsbGJhY2s6ICdpbnRlcmFjdGlvbidcbiAgICB9LFxuICAgIGludGVyYWN0aW9uOiB7XG4gICAgICAgIF9zY3JpcHRhYmxlOiBmYWxzZSxcbiAgICAgICAgX2luZGV4YWJsZTogZmFsc2VcbiAgICB9XG59LCBbXG4gICAgYXBwbHlBbmltYXRpb25zRGVmYXVsdHMsXG4gICAgYXBwbHlMYXlvdXRzRGVmYXVsdHMsXG4gICAgYXBwbHlTY2FsZURlZmF1bHRzXG5dKTtcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gZm9udCBvYmplY3QgaW50byBhIENTUyBmb250IHN0cmluZy5cbiAqIEBwYXJhbSBmb250IC0gQSBmb250IG9iamVjdC5cbiAqIEByZXR1cm4gVGhlIENTUyBmb250IHN0cmluZy4gU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy9mb250XG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIHRvRm9udFN0cmluZyhmb250KSB7XG4gICAgaWYgKCFmb250IHx8IGlzTnVsbE9yVW5kZWYoZm9udC5zaXplKSB8fCBpc051bGxPclVuZGVmKGZvbnQuZmFtaWx5KSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIChmb250LnN0eWxlID8gZm9udC5zdHlsZSArICcgJyA6ICcnKSArIChmb250LndlaWdodCA/IGZvbnQud2VpZ2h0ICsgJyAnIDogJycpICsgZm9udC5zaXplICsgJ3B4ICcgKyBmb250LmZhbWlseTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfbWVhc3VyZVRleHQoY3R4LCBkYXRhLCBnYywgbG9uZ2VzdCwgc3RyaW5nKSB7XG4gICAgbGV0IHRleHRXaWR0aCA9IGRhdGFbc3RyaW5nXTtcbiAgICBpZiAoIXRleHRXaWR0aCkge1xuICAgICAgICB0ZXh0V2lkdGggPSBkYXRhW3N0cmluZ10gPSBjdHgubWVhc3VyZVRleHQoc3RyaW5nKS53aWR0aDtcbiAgICAgICAgZ2MucHVzaChzdHJpbmcpO1xuICAgIH1cbiAgICBpZiAodGV4dFdpZHRoID4gbG9uZ2VzdCkge1xuICAgICAgICBsb25nZXN0ID0gdGV4dFdpZHRoO1xuICAgIH1cbiAgICByZXR1cm4gbG9uZ2VzdDtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gX2xvbmdlc3RUZXh0KGN0eCwgZm9udCwgYXJyYXlPZlRoaW5ncywgY2FjaGUpIHtcbiAgICBjYWNoZSA9IGNhY2hlIHx8IHt9O1xuICAgIGxldCBkYXRhID0gY2FjaGUuZGF0YSA9IGNhY2hlLmRhdGEgfHwge307XG4gICAgbGV0IGdjID0gY2FjaGUuZ2FyYmFnZUNvbGxlY3QgPSBjYWNoZS5nYXJiYWdlQ29sbGVjdCB8fCBbXTtcbiAgICBpZiAoY2FjaGUuZm9udCAhPT0gZm9udCkge1xuICAgICAgICBkYXRhID0gY2FjaGUuZGF0YSA9IHt9O1xuICAgICAgICBnYyA9IGNhY2hlLmdhcmJhZ2VDb2xsZWN0ID0gW107XG4gICAgICAgIGNhY2hlLmZvbnQgPSBmb250O1xuICAgIH1cbiAgICBjdHguc2F2ZSgpO1xuICAgIGN0eC5mb250ID0gZm9udDtcbiAgICBsZXQgbG9uZ2VzdCA9IDA7XG4gICAgY29uc3QgaWxlbiA9IGFycmF5T2ZUaGluZ3MubGVuZ3RoO1xuICAgIGxldCBpLCBqLCBqbGVuLCB0aGluZywgbmVzdGVkVGhpbmc7XG4gICAgZm9yKGkgPSAwOyBpIDwgaWxlbjsgaSsrKXtcbiAgICAgICAgdGhpbmcgPSBhcnJheU9mVGhpbmdzW2ldO1xuICAgICAgICAvLyBVbmRlZmluZWQgc3RyaW5ncyBhbmQgYXJyYXlzIHNob3VsZCBub3QgYmUgbWVhc3VyZWRcbiAgICAgICAgaWYgKHRoaW5nICE9PSB1bmRlZmluZWQgJiYgdGhpbmcgIT09IG51bGwgJiYgIWlzQXJyYXkodGhpbmcpKSB7XG4gICAgICAgICAgICBsb25nZXN0ID0gX21lYXN1cmVUZXh0KGN0eCwgZGF0YSwgZ2MsIGxvbmdlc3QsIHRoaW5nKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KHRoaW5nKSkge1xuICAgICAgICAgICAgLy8gaWYgaXQgaXMgYW4gYXJyYXkgbGV0cyBtZWFzdXJlIGVhY2ggZWxlbWVudFxuICAgICAgICAgICAgLy8gdG8gZG8gbWF5YmUgc2ltcGxpZnkgdGhpcyBmdW5jdGlvbiBhIGJpdCBzbyB3ZSBjYW4gZG8gdGhpcyBtb3JlIHJlY3Vyc2l2ZWx5P1xuICAgICAgICAgICAgZm9yKGogPSAwLCBqbGVuID0gdGhpbmcubGVuZ3RoOyBqIDwgamxlbjsgaisrKXtcbiAgICAgICAgICAgICAgICBuZXN0ZWRUaGluZyA9IHRoaW5nW2pdO1xuICAgICAgICAgICAgICAgIC8vIFVuZGVmaW5lZCBzdHJpbmdzIGFuZCBhcnJheXMgc2hvdWxkIG5vdCBiZSBtZWFzdXJlZFxuICAgICAgICAgICAgICAgIGlmIChuZXN0ZWRUaGluZyAhPT0gdW5kZWZpbmVkICYmIG5lc3RlZFRoaW5nICE9PSBudWxsICYmICFpc0FycmF5KG5lc3RlZFRoaW5nKSkge1xuICAgICAgICAgICAgICAgICAgICBsb25nZXN0ID0gX21lYXN1cmVUZXh0KGN0eCwgZGF0YSwgZ2MsIGxvbmdlc3QsIG5lc3RlZFRoaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgICBjb25zdCBnY0xlbiA9IGdjLmxlbmd0aCAvIDI7XG4gICAgaWYgKGdjTGVuID4gYXJyYXlPZlRoaW5ncy5sZW5ndGgpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZ2NMZW47IGkrKyl7XG4gICAgICAgICAgICBkZWxldGUgZGF0YVtnY1tpXV07XG4gICAgICAgIH1cbiAgICAgICAgZ2Muc3BsaWNlKDAsIGdjTGVuKTtcbiAgICB9XG4gICAgcmV0dXJuIGxvbmdlc3Q7XG59XG4vKipcbiAqIFJldHVybnMgdGhlIGFsaWduZWQgcGl4ZWwgdmFsdWUgdG8gYXZvaWQgYW50aS1hbGlhc2luZyBibHVyXG4gKiBAcGFyYW0gY2hhcnQgLSBUaGUgY2hhcnQgaW5zdGFuY2UuXG4gKiBAcGFyYW0gcGl4ZWwgLSBBIHBpeGVsIHZhbHVlLlxuICogQHBhcmFtIHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSBlbGVtZW50LlxuICogQHJldHVybnMgVGhlIGFsaWduZWQgcGl4ZWwgdmFsdWUuXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9hbGlnblBpeGVsKGNoYXJ0LCBwaXhlbCwgd2lkdGgpIHtcbiAgICBjb25zdCBkZXZpY2VQaXhlbFJhdGlvID0gY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW87XG4gICAgY29uc3QgaGFsZldpZHRoID0gd2lkdGggIT09IDAgPyBNYXRoLm1heCh3aWR0aCAvIDIsIDAuNSkgOiAwO1xuICAgIHJldHVybiBNYXRoLnJvdW5kKChwaXhlbCAtIGhhbGZXaWR0aCkgKiBkZXZpY2VQaXhlbFJhdGlvKSAvIGRldmljZVBpeGVsUmF0aW8gKyBoYWxmV2lkdGg7XG59XG4vKipcbiAqIENsZWFycyB0aGUgZW50aXJlIGNhbnZhcy5cbiAqLyBmdW5jdGlvbiBjbGVhckNhbnZhcyhjYW52YXMsIGN0eCkge1xuICAgIGN0eCA9IGN0eCB8fCBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHguc2F2ZSgpO1xuICAgIC8vIGNhbnZhcy53aWR0aCBhbmQgY2FudmFzLmhlaWdodCBkbyBub3QgY29uc2lkZXIgdGhlIGNhbnZhcyB0cmFuc2Zvcm0sXG4gICAgLy8gd2hpbGUgY2xlYXJSZWN0IGRvZXNcbiAgICBjdHgucmVzZXRUcmFuc2Zvcm0oKTtcbiAgICBjdHguY2xlYXJSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cbmZ1bmN0aW9uIGRyYXdQb2ludChjdHgsIG9wdGlvbnMsIHgsIHkpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVzZS1iZWZvcmUtZGVmaW5lXG4gICAgZHJhd1BvaW50TGVnZW5kKGN0eCwgb3B0aW9ucywgeCwgeSwgbnVsbCk7XG59XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gZHJhd1BvaW50TGVnZW5kKGN0eCwgb3B0aW9ucywgeCwgeSwgdykge1xuICAgIGxldCB0eXBlLCB4T2Zmc2V0LCB5T2Zmc2V0LCBzaXplLCBjb3JuZXJSYWRpdXMsIHdpZHRoLCB4T2Zmc2V0VywgeU9mZnNldFc7XG4gICAgY29uc3Qgc3R5bGUgPSBvcHRpb25zLnBvaW50U3R5bGU7XG4gICAgY29uc3Qgcm90YXRpb24gPSBvcHRpb25zLnJvdGF0aW9uO1xuICAgIGNvbnN0IHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzO1xuICAgIGxldCByYWQgPSAocm90YXRpb24gfHwgMCkgKiBSQURfUEVSX0RFRztcbiAgICBpZiAoc3R5bGUgJiYgdHlwZW9mIHN0eWxlID09PSAnb2JqZWN0Jykge1xuICAgICAgICB0eXBlID0gc3R5bGUudG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEhUTUxJbWFnZUVsZW1lbnRdJyB8fCB0eXBlID09PSAnW29iamVjdCBIVE1MQ2FudmFzRWxlbWVudF0nKSB7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZSh4LCB5KTtcbiAgICAgICAgICAgIGN0eC5yb3RhdGUocmFkKTtcbiAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2Uoc3R5bGUsIC1zdHlsZS53aWR0aCAvIDIsIC1zdHlsZS5oZWlnaHQgLyAyLCBzdHlsZS53aWR0aCwgc3R5bGUuaGVpZ2h0KTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzTmFOKHJhZGl1cykgfHwgcmFkaXVzIDw9IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgc3dpdGNoKHN0eWxlKXtcbiAgICAgICAgLy8gRGVmYXVsdCBpbmNsdWRlcyBjaXJjbGVcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGlmICh3KSB7XG4gICAgICAgICAgICAgICAgY3R4LmVsbGlwc2UoeCwgeSwgdyAvIDIsIHJhZGl1cywgMCwgMCwgVEFVKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3R4LmFyYyh4LCB5LCByYWRpdXMsIDAsIFRBVSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndHJpYW5nbGUnOlxuICAgICAgICAgICAgd2lkdGggPSB3ID8gdyAvIDIgOiByYWRpdXM7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHggKyBNYXRoLnNpbihyYWQpICogd2lkdGgsIHkgLSBNYXRoLmNvcyhyYWQpICogcmFkaXVzKTtcbiAgICAgICAgICAgIHJhZCArPSBUV09fVEhJUkRTX1BJO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgTWF0aC5zaW4ocmFkKSAqIHdpZHRoLCB5IC0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cyk7XG4gICAgICAgICAgICByYWQgKz0gVFdPX1RISVJEU19QSTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCArIE1hdGguc2luKHJhZCkgKiB3aWR0aCwgeSAtIE1hdGguY29zKHJhZCkgKiByYWRpdXMpO1xuICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3JlY3RSb3VuZGVkJzpcbiAgICAgICAgICAgIC8vIE5PVEU6IHRoZSByb3VuZGVkIHJlY3QgaW1wbGVtZW50YXRpb24gY2hhbmdlZCB0byB1c2UgYGFyY2AgaW5zdGVhZCBvZlxuICAgICAgICAgICAgLy8gYHF1YWRyYXRpY0N1cnZlVG9gIHNpbmNlIGl0IGdlbmVyYXRlcyBiZXR0ZXIgcmVzdWx0cyB3aGVuIHJlY3QgaXNcbiAgICAgICAgICAgIC8vIGFsbW9zdCBhIGNpcmNsZS4gMC41MTYgKGluc3RlYWQgb2YgMC41KSBwcm9kdWNlcyByZXN1bHRzIHdpdGggdmlzdWFsbHlcbiAgICAgICAgICAgIC8vIGNsb3NlciBwcm9wb3J0aW9uIHRvIHRoZSBwcmV2aW91cyBpbXBsIGFuZCBpdCBpcyBpbnNjcmliZWQgaW4gdGhlXG4gICAgICAgICAgICAvLyBjaXJjbGUgd2l0aCBgcmFkaXVzYC4gRm9yIG1vcmUgZGV0YWlscywgc2VlIHRoZSBmb2xsb3dpbmcgUFJzOlxuICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2NoYXJ0anMvQ2hhcnQuanMvaXNzdWVzLzU1OTdcbiAgICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL0NoYXJ0LmpzL2lzc3Vlcy81ODU4XG4gICAgICAgICAgICBjb3JuZXJSYWRpdXMgPSByYWRpdXMgKiAwLjUxNjtcbiAgICAgICAgICAgIHNpemUgPSByYWRpdXMgLSBjb3JuZXJSYWRpdXM7XG4gICAgICAgICAgICB4T2Zmc2V0ID0gTWF0aC5jb3MocmFkICsgUVVBUlRFUl9QSSkgKiBzaXplO1xuICAgICAgICAgICAgeE9mZnNldFcgPSBNYXRoLmNvcyhyYWQgKyBRVUFSVEVSX1BJKSAqICh3ID8gdyAvIDIgLSBjb3JuZXJSYWRpdXMgOiBzaXplKTtcbiAgICAgICAgICAgIHlPZmZzZXQgPSBNYXRoLnNpbihyYWQgKyBRVUFSVEVSX1BJKSAqIHNpemU7XG4gICAgICAgICAgICB5T2Zmc2V0VyA9IE1hdGguc2luKHJhZCArIFFVQVJURVJfUEkpICogKHcgPyB3IC8gMiAtIGNvcm5lclJhZGl1cyA6IHNpemUpO1xuICAgICAgICAgICAgY3R4LmFyYyh4IC0geE9mZnNldFcsIHkgLSB5T2Zmc2V0LCBjb3JuZXJSYWRpdXMsIHJhZCAtIFBJLCByYWQgLSBIQUxGX1BJKTtcbiAgICAgICAgICAgIGN0eC5hcmMoeCArIHlPZmZzZXRXLCB5IC0geE9mZnNldCwgY29ybmVyUmFkaXVzLCByYWQgLSBIQUxGX1BJLCByYWQpO1xuICAgICAgICAgICAgY3R4LmFyYyh4ICsgeE9mZnNldFcsIHkgKyB5T2Zmc2V0LCBjb3JuZXJSYWRpdXMsIHJhZCwgcmFkICsgSEFMRl9QSSk7XG4gICAgICAgICAgICBjdHguYXJjKHggLSB5T2Zmc2V0VywgeSArIHhPZmZzZXQsIGNvcm5lclJhZGl1cywgcmFkICsgSEFMRl9QSSwgcmFkICsgUEkpO1xuICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3JlY3QnOlxuICAgICAgICAgICAgaWYgKCFyb3RhdGlvbikge1xuICAgICAgICAgICAgICAgIHNpemUgPSBNYXRoLlNRUlQxXzIgKiByYWRpdXM7XG4gICAgICAgICAgICAgICAgd2lkdGggPSB3ID8gdyAvIDIgOiBzaXplO1xuICAgICAgICAgICAgICAgIGN0eC5yZWN0KHggLSB3aWR0aCwgeSAtIHNpemUsIDIgKiB3aWR0aCwgMiAqIHNpemUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmFkICs9IFFVQVJURVJfUEk7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8gY2FzZSAncmVjdFJvdCc6XG4gICAgICAgICAgICB4T2Zmc2V0VyA9IE1hdGguY29zKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIHhPZmZzZXQgPSBNYXRoLmNvcyhyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0VyA9IE1hdGguc2luKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCAtIHhPZmZzZXRXLCB5IC0geU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB5T2Zmc2V0VywgeSAtIHhPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldFcsIHkgKyB5T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCAtIHlPZmZzZXRXLCB5ICsgeE9mZnNldCk7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnY3Jvc3NSb3QnOlxuICAgICAgICAgICAgcmFkICs9IFFVQVJURVJfUEk7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8gY2FzZSAnY3Jvc3MnOlxuICAgICAgICAgICAgeE9mZnNldFcgPSBNYXRoLmNvcyhyYWQpICogKHcgPyB3IC8gMiA6IHJhZGl1cyk7XG4gICAgICAgICAgICB4T2Zmc2V0ID0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cztcbiAgICAgICAgICAgIHlPZmZzZXQgPSBNYXRoLnNpbihyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldFcgPSBNYXRoLnNpbihyYWQpICogKHcgPyB3IC8gMiA6IHJhZGl1cyk7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHggLSB4T2Zmc2V0VywgeSAtIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldFcsIHkgKyB5T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCArIHlPZmZzZXRXLCB5IC0geE9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggLSB5T2Zmc2V0VywgeSArIHhPZmZzZXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3N0YXInOlxuICAgICAgICAgICAgeE9mZnNldFcgPSBNYXRoLmNvcyhyYWQpICogKHcgPyB3IC8gMiA6IHJhZGl1cyk7XG4gICAgICAgICAgICB4T2Zmc2V0ID0gTWF0aC5jb3MocmFkKSAqIHJhZGl1cztcbiAgICAgICAgICAgIHlPZmZzZXQgPSBNYXRoLnNpbihyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldFcgPSBNYXRoLnNpbihyYWQpICogKHcgPyB3IC8gMiA6IHJhZGl1cyk7XG4gICAgICAgICAgICBjdHgubW92ZVRvKHggLSB4T2Zmc2V0VywgeSAtIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldFcsIHkgKyB5T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCArIHlPZmZzZXRXLCB5IC0geE9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggLSB5T2Zmc2V0VywgeSArIHhPZmZzZXQpO1xuICAgICAgICAgICAgcmFkICs9IFFVQVJURVJfUEk7XG4gICAgICAgICAgICB4T2Zmc2V0VyA9IE1hdGguY29zKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIHhPZmZzZXQgPSBNYXRoLmNvcyhyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgeU9mZnNldCA9IE1hdGguc2luKHJhZCkgKiByYWRpdXM7XG4gICAgICAgICAgICB5T2Zmc2V0VyA9IE1hdGguc2luKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKTtcbiAgICAgICAgICAgIGN0eC5tb3ZlVG8oeCAtIHhPZmZzZXRXLCB5IC0geU9mZnNldCk7XG4gICAgICAgICAgICBjdHgubGluZVRvKHggKyB4T2Zmc2V0VywgeSArIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4ICsgeU9mZnNldFcsIHkgLSB4T2Zmc2V0KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCAtIHlPZmZzZXRXLCB5ICsgeE9mZnNldCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbGluZSc6XG4gICAgICAgICAgICB4T2Zmc2V0ID0gdyA/IHcgLyAyIDogTWF0aC5jb3MocmFkKSAqIHJhZGl1cztcbiAgICAgICAgICAgIHlPZmZzZXQgPSBNYXRoLnNpbihyYWQpICogcmFkaXVzO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4IC0geE9mZnNldCwgeSAtIHlPZmZzZXQpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyh4ICsgeE9mZnNldCwgeSArIHlPZmZzZXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2Rhc2gnOlxuICAgICAgICAgICAgY3R4Lm1vdmVUbyh4LCB5KTtcbiAgICAgICAgICAgIGN0eC5saW5lVG8oeCArIE1hdGguY29zKHJhZCkgKiAodyA/IHcgLyAyIDogcmFkaXVzKSwgeSArIE1hdGguc2luKHJhZCkgKiByYWRpdXMpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgZmFsc2U6XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgY3R4LmZpbGwoKTtcbiAgICBpZiAob3B0aW9ucy5ib3JkZXJXaWR0aCA+IDApIHtcbiAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH1cbn1cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBwb2ludCBpcyBpbnNpZGUgdGhlIHJlY3RhbmdsZVxuICogQHBhcmFtIHBvaW50IC0gVGhlIHBvaW50IHRvIHRlc3RcbiAqIEBwYXJhbSBhcmVhIC0gVGhlIHJlY3RhbmdsZVxuICogQHBhcmFtIG1hcmdpbiAtIGFsbG93ZWQgbWFyZ2luXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9pc1BvaW50SW5BcmVhKHBvaW50LCBhcmVhLCBtYXJnaW4pIHtcbiAgICBtYXJnaW4gPSBtYXJnaW4gfHwgMC41OyAvLyBtYXJnaW4gLSBkZWZhdWx0IGlzIHRvIG1hdGNoIHJvdW5kZWQgZGVjaW1hbHNcbiAgICByZXR1cm4gIWFyZWEgfHwgcG9pbnQgJiYgcG9pbnQueCA+IGFyZWEubGVmdCAtIG1hcmdpbiAmJiBwb2ludC54IDwgYXJlYS5yaWdodCArIG1hcmdpbiAmJiBwb2ludC55ID4gYXJlYS50b3AgLSBtYXJnaW4gJiYgcG9pbnQueSA8IGFyZWEuYm90dG9tICsgbWFyZ2luO1xufVxuZnVuY3Rpb24gY2xpcEFyZWEoY3R4LCBhcmVhKSB7XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LnJlY3QoYXJlYS5sZWZ0LCBhcmVhLnRvcCwgYXJlYS5yaWdodCAtIGFyZWEubGVmdCwgYXJlYS5ib3R0b20gLSBhcmVhLnRvcCk7XG4gICAgY3R4LmNsaXAoKTtcbn1cbmZ1bmN0aW9uIHVuY2xpcEFyZWEoY3R4KSB7XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfc3RlcHBlZExpbmVUbyhjdHgsIHByZXZpb3VzLCB0YXJnZXQsIGZsaXAsIG1vZGUpIHtcbiAgICBpZiAoIXByZXZpb3VzKSB7XG4gICAgICAgIHJldHVybiBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG4gICAgfVxuICAgIGlmIChtb2RlID09PSAnbWlkZGxlJykge1xuICAgICAgICBjb25zdCBtaWRwb2ludCA9IChwcmV2aW91cy54ICsgdGFyZ2V0LngpIC8gMi4wO1xuICAgICAgICBjdHgubGluZVRvKG1pZHBvaW50LCBwcmV2aW91cy55KTtcbiAgICAgICAgY3R4LmxpbmVUbyhtaWRwb2ludCwgdGFyZ2V0LnkpO1xuICAgIH0gZWxzZSBpZiAobW9kZSA9PT0gJ2FmdGVyJyAhPT0gISFmbGlwKSB7XG4gICAgICAgIGN0eC5saW5lVG8ocHJldmlvdXMueCwgdGFyZ2V0LnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGN0eC5saW5lVG8odGFyZ2V0LngsIHByZXZpb3VzLnkpO1xuICAgIH1cbiAgICBjdHgubGluZVRvKHRhcmdldC54LCB0YXJnZXQueSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2JlemllckN1cnZlVG8oY3R4LCBwcmV2aW91cywgdGFyZ2V0LCBmbGlwKSB7XG4gICAgaWYgKCFwcmV2aW91cykge1xuICAgICAgICByZXR1cm4gY3R4LmxpbmVUbyh0YXJnZXQueCwgdGFyZ2V0LnkpO1xuICAgIH1cbiAgICBjdHguYmV6aWVyQ3VydmVUbyhmbGlwID8gcHJldmlvdXMuY3AxeCA6IHByZXZpb3VzLmNwMngsIGZsaXAgPyBwcmV2aW91cy5jcDF5IDogcHJldmlvdXMuY3AyeSwgZmxpcCA/IHRhcmdldC5jcDJ4IDogdGFyZ2V0LmNwMXgsIGZsaXAgPyB0YXJnZXQuY3AyeSA6IHRhcmdldC5jcDF5LCB0YXJnZXQueCwgdGFyZ2V0LnkpO1xufVxuZnVuY3Rpb24gc2V0UmVuZGVyT3B0cyhjdHgsIG9wdHMpIHtcbiAgICBpZiAob3B0cy50cmFuc2xhdGlvbikge1xuICAgICAgICBjdHgudHJhbnNsYXRlKG9wdHMudHJhbnNsYXRpb25bMF0sIG9wdHMudHJhbnNsYXRpb25bMV0pO1xuICAgIH1cbiAgICBpZiAoIWlzTnVsbE9yVW5kZWYob3B0cy5yb3RhdGlvbikpIHtcbiAgICAgICAgY3R4LnJvdGF0ZShvcHRzLnJvdGF0aW9uKTtcbiAgICB9XG4gICAgaWYgKG9wdHMuY29sb3IpIHtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IG9wdHMuY29sb3I7XG4gICAgfVxuICAgIGlmIChvcHRzLnRleHRBbGlnbikge1xuICAgICAgICBjdHgudGV4dEFsaWduID0gb3B0cy50ZXh0QWxpZ247XG4gICAgfVxuICAgIGlmIChvcHRzLnRleHRCYXNlbGluZSkge1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gb3B0cy50ZXh0QmFzZWxpbmU7XG4gICAgfVxufVxuZnVuY3Rpb24gZGVjb3JhdGVUZXh0KGN0eCwgeCwgeSwgbGluZSwgb3B0cykge1xuICAgIGlmIChvcHRzLnN0cmlrZXRocm91Z2ggfHwgb3B0cy51bmRlcmxpbmUpIHtcbiAgICAgICAgLyoqXG4gICAgICogTm93IHRoYXQgSUUxMSBzdXBwb3J0IGhhcyBiZWVuIGRyb3BwZWQsIHdlIGNhbiB1c2UgbW9yZVxuICAgICAqIG9mIHRoZSBUZXh0TWV0cmljcyBvYmplY3QuIFRoZSBhY3R1YWwgYm91bmRpbmcgYm94ZXNcbiAgICAgKiBhcmUgdW5mbGFnZ2VkIGluIENocm9tZSwgRmlyZWZveCwgRWRnZSwgYW5kIFNhZmFyaSBzbyB0aGV5XG4gICAgICogY2FuIGJlIHNhZmVseSB1c2VkLlxuICAgICAqIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvVGV4dE1ldHJpY3MjQnJvd3Nlcl9jb21wYXRpYmlsaXR5XG4gICAgICovIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQobGluZSk7XG4gICAgICAgIGNvbnN0IGxlZnQgPSB4IC0gbWV0cmljcy5hY3R1YWxCb3VuZGluZ0JveExlZnQ7XG4gICAgICAgIGNvbnN0IHJpZ2h0ID0geCArIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hSaWdodDtcbiAgICAgICAgY29uc3QgdG9wID0geSAtIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hBc2NlbnQ7XG4gICAgICAgIGNvbnN0IGJvdHRvbSA9IHkgKyBtZXRyaWNzLmFjdHVhbEJvdW5kaW5nQm94RGVzY2VudDtcbiAgICAgICAgY29uc3QgeURlY29yYXRpb24gPSBvcHRzLnN0cmlrZXRocm91Z2ggPyAodG9wICsgYm90dG9tKSAvIDIgOiBib3R0b207XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGN0eC5maWxsU3R5bGU7XG4gICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IG9wdHMuZGVjb3JhdGlvbldpZHRoIHx8IDI7XG4gICAgICAgIGN0eC5tb3ZlVG8obGVmdCwgeURlY29yYXRpb24pO1xuICAgICAgICBjdHgubGluZVRvKHJpZ2h0LCB5RGVjb3JhdGlvbik7XG4gICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkcmF3QmFja2Ryb3AoY3R4LCBvcHRzKSB7XG4gICAgY29uc3Qgb2xkQ29sb3IgPSBjdHguZmlsbFN0eWxlO1xuICAgIGN0eC5maWxsU3R5bGUgPSBvcHRzLmNvbG9yO1xuICAgIGN0eC5maWxsUmVjdChvcHRzLmxlZnQsIG9wdHMudG9wLCBvcHRzLndpZHRoLCBvcHRzLmhlaWdodCk7XG4gICAgY3R4LmZpbGxTdHlsZSA9IG9sZENvbG9yO1xufVxuLyoqXG4gKiBSZW5kZXIgdGV4dCBvbnRvIHRoZSBjYW52YXNcbiAqLyBmdW5jdGlvbiByZW5kZXJUZXh0KGN0eCwgdGV4dCwgeCwgeSwgZm9udCwgb3B0cyA9IHt9KSB7XG4gICAgY29uc3QgbGluZXMgPSBpc0FycmF5KHRleHQpID8gdGV4dCA6IFtcbiAgICAgICAgdGV4dFxuICAgIF07XG4gICAgY29uc3Qgc3Ryb2tlID0gb3B0cy5zdHJva2VXaWR0aCA+IDAgJiYgb3B0cy5zdHJva2VDb2xvciAhPT0gJyc7XG4gICAgbGV0IGksIGxpbmU7XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguZm9udCA9IGZvbnQuc3RyaW5nO1xuICAgIHNldFJlbmRlck9wdHMoY3R4LCBvcHRzKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSl7XG4gICAgICAgIGxpbmUgPSBsaW5lc1tpXTtcbiAgICAgICAgaWYgKG9wdHMuYmFja2Ryb3ApIHtcbiAgICAgICAgICAgIGRyYXdCYWNrZHJvcChjdHgsIG9wdHMuYmFja2Ryb3ApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdHJva2UpIHtcbiAgICAgICAgICAgIGlmIChvcHRzLnN0cm9rZUNvbG9yKSB7XG4gICAgICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gb3B0cy5zdHJva2VDb2xvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNOdWxsT3JVbmRlZihvcHRzLnN0cm9rZVdpZHRoKSkge1xuICAgICAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBvcHRzLnN0cm9rZVdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3R4LnN0cm9rZVRleHQobGluZSwgeCwgeSwgb3B0cy5tYXhXaWR0aCk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmZpbGxUZXh0KGxpbmUsIHgsIHksIG9wdHMubWF4V2lkdGgpO1xuICAgICAgICBkZWNvcmF0ZVRleHQoY3R4LCB4LCB5LCBsaW5lLCBvcHRzKTtcbiAgICAgICAgeSArPSBOdW1iZXIoZm9udC5saW5lSGVpZ2h0KTtcbiAgICB9XG4gICAgY3R4LnJlc3RvcmUoKTtcbn1cbi8qKlxuICogQWRkIGEgcGF0aCBvZiBhIHJlY3RhbmdsZSB3aXRoIHJvdW5kZWQgY29ybmVycyB0byB0aGUgY3VycmVudCBzdWItcGF0aFxuICogQHBhcmFtIGN0eCAtIENvbnRleHRcbiAqIEBwYXJhbSByZWN0IC0gQm91bmRpbmcgcmVjdFxuICovIGZ1bmN0aW9uIGFkZFJvdW5kZWRSZWN0UGF0aChjdHgsIHJlY3QpIHtcbiAgICBjb25zdCB7IHggLCB5ICwgdyAsIGggLCByYWRpdXMgIH0gPSByZWN0O1xuICAgIC8vIHRvcCBsZWZ0IGFyY1xuICAgIGN0eC5hcmMoeCArIHJhZGl1cy50b3BMZWZ0LCB5ICsgcmFkaXVzLnRvcExlZnQsIHJhZGl1cy50b3BMZWZ0LCAtSEFMRl9QSSwgUEksIHRydWUpO1xuICAgIC8vIGxpbmUgZnJvbSB0b3AgbGVmdCB0byBib3R0b20gbGVmdFxuICAgIGN0eC5saW5lVG8oeCwgeSArIGggLSByYWRpdXMuYm90dG9tTGVmdCk7XG4gICAgLy8gYm90dG9tIGxlZnQgYXJjXG4gICAgY3R4LmFyYyh4ICsgcmFkaXVzLmJvdHRvbUxlZnQsIHkgKyBoIC0gcmFkaXVzLmJvdHRvbUxlZnQsIHJhZGl1cy5ib3R0b21MZWZ0LCBQSSwgSEFMRl9QSSwgdHJ1ZSk7XG4gICAgLy8gbGluZSBmcm9tIGJvdHRvbSBsZWZ0IHRvIGJvdHRvbSByaWdodFxuICAgIGN0eC5saW5lVG8oeCArIHcgLSByYWRpdXMuYm90dG9tUmlnaHQsIHkgKyBoKTtcbiAgICAvLyBib3R0b20gcmlnaHQgYXJjXG4gICAgY3R4LmFyYyh4ICsgdyAtIHJhZGl1cy5ib3R0b21SaWdodCwgeSArIGggLSByYWRpdXMuYm90dG9tUmlnaHQsIHJhZGl1cy5ib3R0b21SaWdodCwgSEFMRl9QSSwgMCwgdHJ1ZSk7XG4gICAgLy8gbGluZSBmcm9tIGJvdHRvbSByaWdodCB0byB0b3AgcmlnaHRcbiAgICBjdHgubGluZVRvKHggKyB3LCB5ICsgcmFkaXVzLnRvcFJpZ2h0KTtcbiAgICAvLyB0b3AgcmlnaHQgYXJjXG4gICAgY3R4LmFyYyh4ICsgdyAtIHJhZGl1cy50b3BSaWdodCwgeSArIHJhZGl1cy50b3BSaWdodCwgcmFkaXVzLnRvcFJpZ2h0LCAwLCAtSEFMRl9QSSwgdHJ1ZSk7XG4gICAgLy8gbGluZSBmcm9tIHRvcCByaWdodCB0byB0b3AgbGVmdFxuICAgIGN0eC5saW5lVG8oeCArIHJhZGl1cy50b3BMZWZ0LCB5KTtcbn1cblxuY29uc3QgTElORV9IRUlHSFQgPSAvXihub3JtYWx8KFxcZCsoPzpcXC5cXGQrKT8pKHB4fGVtfCUpPykkLztcbmNvbnN0IEZPTlRfU1RZTEUgPSAvXihub3JtYWx8aXRhbGljfGluaXRpYWx8aW5oZXJpdHx1bnNldHwob2JsaXF1ZSggLT9bMC05XT9bMC05XWRlZyk/KSkkLztcbi8qKlxuICogQGFsaWFzIENoYXJ0LmhlbHBlcnMub3B0aW9uc1xuICogQG5hbWVzcGFjZVxuICovIC8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIGxpbmUgaGVpZ2h0IGB2YWx1ZWAgaW4gcGl4ZWxzIGZvciBhIHNwZWNpZmljIGZvbnQgYHNpemVgLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIGxpbmVIZWlnaHQgdG8gcGFyc2UgKGVnLiAxLjYsICcxNHB4JywgJzc1JScsICcxLjZlbScpLlxuICogQHBhcmFtIHNpemUgLSBUaGUgZm9udCBzaXplIChpbiBwaXhlbHMpIHVzZWQgdG8gcmVzb2x2ZSByZWxhdGl2ZSBgdmFsdWVgLlxuICogQHJldHVybnMgVGhlIGVmZmVjdGl2ZSBsaW5lIGhlaWdodCBpbiBwaXhlbHMgKHNpemUgKiAxLjIgaWYgdmFsdWUgaXMgaW52YWxpZCkuXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy9saW5lLWhlaWdodFxuICogQHNpbmNlIDIuNy4wXG4gKi8gZnVuY3Rpb24gdG9MaW5lSGVpZ2h0KHZhbHVlLCBzaXplKSB7XG4gICAgY29uc3QgbWF0Y2hlcyA9ICgnJyArIHZhbHVlKS5tYXRjaChMSU5FX0hFSUdIVCk7XG4gICAgaWYgKCFtYXRjaGVzIHx8IG1hdGNoZXNbMV0gPT09ICdub3JtYWwnKSB7XG4gICAgICAgIHJldHVybiBzaXplICogMS4yO1xuICAgIH1cbiAgICB2YWx1ZSA9ICttYXRjaGVzWzJdO1xuICAgIHN3aXRjaChtYXRjaGVzWzNdKXtcbiAgICAgICAgY2FzZSAncHgnOlxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICBjYXNlICclJzpcbiAgICAgICAgICAgIHZhbHVlIC89IDEwMDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZSAqIHZhbHVlO1xufVxuY29uc3QgbnVtYmVyT3JaZXJvID0gKHYpPT4rdiB8fCAwO1xuZnVuY3Rpb24gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIHByb3BzKSB7XG4gICAgY29uc3QgcmV0ID0ge307XG4gICAgY29uc3Qgb2JqUHJvcHMgPSBpc09iamVjdChwcm9wcyk7XG4gICAgY29uc3Qga2V5cyA9IG9ialByb3BzID8gT2JqZWN0LmtleXMocHJvcHMpIDogcHJvcHM7XG4gICAgY29uc3QgcmVhZCA9IGlzT2JqZWN0KHZhbHVlKSA/IG9ialByb3BzID8gKHByb3ApPT52YWx1ZU9yRGVmYXVsdCh2YWx1ZVtwcm9wXSwgdmFsdWVbcHJvcHNbcHJvcF1dKSA6IChwcm9wKT0+dmFsdWVbcHJvcF0gOiAoKT0+dmFsdWU7XG4gICAgZm9yIChjb25zdCBwcm9wIG9mIGtleXMpe1xuICAgICAgICByZXRbcHJvcF0gPSBudW1iZXJPclplcm8ocmVhZChwcm9wKSk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG59XG4vKipcbiAqIENvbnZlcnRzIHRoZSBnaXZlbiB2YWx1ZSBpbnRvIGEgVFJCTCBvYmplY3QuXG4gKiBAcGFyYW0gdmFsdWUgLSBJZiBhIG51bWJlciwgc2V0IHRoZSB2YWx1ZSB0byBhbGwgVFJCTCBjb21wb25lbnQsXG4gKiAgZWxzZSwgaWYgYW4gb2JqZWN0LCB1c2UgZGVmaW5lZCBwcm9wZXJ0aWVzIGFuZCBzZXRzIHVuZGVmaW5lZCBvbmVzIHRvIDAuXG4gKiAgeCAvIHkgYXJlIHNob3J0aGFuZHMgZm9yIHNhbWUgdmFsdWUgZm9yIGxlZnQvcmlnaHQgYW5kIHRvcC9ib3R0b20uXG4gKiBAcmV0dXJucyBUaGUgcGFkZGluZyB2YWx1ZXMgKHRvcCwgcmlnaHQsIGJvdHRvbSwgbGVmdClcbiAqIEBzaW5jZSAzLjAuMFxuICovIGZ1bmN0aW9uIHRvVFJCTCh2YWx1ZSkge1xuICAgIHJldHVybiBfcmVhZFZhbHVlVG9Qcm9wcyh2YWx1ZSwge1xuICAgICAgICB0b3A6ICd5JyxcbiAgICAgICAgcmlnaHQ6ICd4JyxcbiAgICAgICAgYm90dG9tOiAneScsXG4gICAgICAgIGxlZnQ6ICd4J1xuICAgIH0pO1xufVxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gdmFsdWUgaW50byBhIFRSQkwgY29ybmVycyBvYmplY3QgKHNpbWlsYXIgd2l0aCBjc3MgYm9yZGVyLXJhZGl1cykuXG4gKiBAcGFyYW0gdmFsdWUgLSBJZiBhIG51bWJlciwgc2V0IHRoZSB2YWx1ZSB0byBhbGwgVFJCTCBjb3JuZXIgY29tcG9uZW50cyxcbiAqICBlbHNlLCBpZiBhbiBvYmplY3QsIHVzZSBkZWZpbmVkIHByb3BlcnRpZXMgYW5kIHNldHMgdW5kZWZpbmVkIG9uZXMgdG8gMC5cbiAqIEByZXR1cm5zIFRoZSBUUkJMIGNvcm5lciB2YWx1ZXMgKHRvcExlZnQsIHRvcFJpZ2h0LCBib3R0b21MZWZ0LCBib3R0b21SaWdodClcbiAqIEBzaW5jZSAzLjAuMFxuICovIGZ1bmN0aW9uIHRvVFJCTENvcm5lcnModmFsdWUpIHtcbiAgICByZXR1cm4gX3JlYWRWYWx1ZVRvUHJvcHModmFsdWUsIFtcbiAgICAgICAgJ3RvcExlZnQnLFxuICAgICAgICAndG9wUmlnaHQnLFxuICAgICAgICAnYm90dG9tTGVmdCcsXG4gICAgICAgICdib3R0b21SaWdodCdcbiAgICBdKTtcbn1cbi8qKlxuICogQ29udmVydHMgdGhlIGdpdmVuIHZhbHVlIGludG8gYSBwYWRkaW5nIG9iamVjdCB3aXRoIHByZS1jb21wdXRlZCB3aWR0aC9oZWlnaHQuXG4gKiBAcGFyYW0gdmFsdWUgLSBJZiBhIG51bWJlciwgc2V0IHRoZSB2YWx1ZSB0byBhbGwgVFJCTCBjb21wb25lbnQsXG4gKiAgZWxzZSwgaWYgYW4gb2JqZWN0LCB1c2UgZGVmaW5lZCBwcm9wZXJ0aWVzIGFuZCBzZXRzIHVuZGVmaW5lZCBvbmVzIHRvIDAuXG4gKiAgeCAvIHkgYXJlIHNob3J0aGFuZHMgZm9yIHNhbWUgdmFsdWUgZm9yIGxlZnQvcmlnaHQgYW5kIHRvcC9ib3R0b20uXG4gKiBAcmV0dXJucyBUaGUgcGFkZGluZyB2YWx1ZXMgKHRvcCwgcmlnaHQsIGJvdHRvbSwgbGVmdCwgd2lkdGgsIGhlaWdodClcbiAqIEBzaW5jZSAyLjcuMFxuICovIGZ1bmN0aW9uIHRvUGFkZGluZyh2YWx1ZSkge1xuICAgIGNvbnN0IG9iaiA9IHRvVFJCTCh2YWx1ZSk7XG4gICAgb2JqLndpZHRoID0gb2JqLmxlZnQgKyBvYmoucmlnaHQ7XG4gICAgb2JqLmhlaWdodCA9IG9iai50b3AgKyBvYmouYm90dG9tO1xuICAgIHJldHVybiBvYmo7XG59XG4vKipcbiAqIFBhcnNlcyBmb250IG9wdGlvbnMgYW5kIHJldHVybnMgdGhlIGZvbnQgb2JqZWN0LlxuICogQHBhcmFtIG9wdGlvbnMgLSBBIG9iamVjdCB0aGF0IGNvbnRhaW5zIGZvbnQgb3B0aW9ucyB0byBiZSBwYXJzZWQuXG4gKiBAcGFyYW0gZmFsbGJhY2sgLSBBIG9iamVjdCB0aGF0IGNvbnRhaW5zIGZhbGxiYWNrIGZvbnQgb3B0aW9ucy5cbiAqIEByZXR1cm4gVGhlIGZvbnQgb2JqZWN0LlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiB0b0ZvbnQob3B0aW9ucywgZmFsbGJhY2spIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICBmYWxsYmFjayA9IGZhbGxiYWNrIHx8IGRlZmF1bHRzLmZvbnQ7XG4gICAgbGV0IHNpemUgPSB2YWx1ZU9yRGVmYXVsdChvcHRpb25zLnNpemUsIGZhbGxiYWNrLnNpemUpO1xuICAgIGlmICh0eXBlb2Ygc2l6ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc2l6ZSA9IHBhcnNlSW50KHNpemUsIDEwKTtcbiAgICB9XG4gICAgbGV0IHN0eWxlID0gdmFsdWVPckRlZmF1bHQob3B0aW9ucy5zdHlsZSwgZmFsbGJhY2suc3R5bGUpO1xuICAgIGlmIChzdHlsZSAmJiAhKCcnICsgc3R5bGUpLm1hdGNoKEZPTlRfU1RZTEUpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignSW52YWxpZCBmb250IHN0eWxlIHNwZWNpZmllZDogXCInICsgc3R5bGUgKyAnXCInKTtcbiAgICAgICAgc3R5bGUgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IGZvbnQgPSB7XG4gICAgICAgIGZhbWlseTogdmFsdWVPckRlZmF1bHQob3B0aW9ucy5mYW1pbHksIGZhbGxiYWNrLmZhbWlseSksXG4gICAgICAgIGxpbmVIZWlnaHQ6IHRvTGluZUhlaWdodCh2YWx1ZU9yRGVmYXVsdChvcHRpb25zLmxpbmVIZWlnaHQsIGZhbGxiYWNrLmxpbmVIZWlnaHQpLCBzaXplKSxcbiAgICAgICAgc2l6ZSxcbiAgICAgICAgc3R5bGUsXG4gICAgICAgIHdlaWdodDogdmFsdWVPckRlZmF1bHQob3B0aW9ucy53ZWlnaHQsIGZhbGxiYWNrLndlaWdodCksXG4gICAgICAgIHN0cmluZzogJydcbiAgICB9O1xuICAgIGZvbnQuc3RyaW5nID0gdG9Gb250U3RyaW5nKGZvbnQpO1xuICAgIHJldHVybiBmb250O1xufVxuLyoqXG4gKiBFdmFsdWF0ZXMgdGhlIGdpdmVuIGBpbnB1dHNgIHNlcXVlbnRpYWxseSBhbmQgcmV0dXJucyB0aGUgZmlyc3QgZGVmaW5lZCB2YWx1ZS5cbiAqIEBwYXJhbSBpbnB1dHMgLSBBbiBhcnJheSBvZiB2YWx1ZXMsIGZhbGxpbmcgYmFjayB0byB0aGUgbGFzdCB2YWx1ZS5cbiAqIEBwYXJhbSBjb250ZXh0IC0gSWYgZGVmaW5lZCBhbmQgdGhlIGN1cnJlbnQgdmFsdWUgaXMgYSBmdW5jdGlvbiwgdGhlIHZhbHVlXG4gKiBpcyBjYWxsZWQgd2l0aCBgY29udGV4dGAgYXMgZmlyc3QgYXJndW1lbnQgYW5kIHRoZSByZXN1bHQgYmVjb21lcyB0aGUgbmV3IGlucHV0LlxuICogQHBhcmFtIGluZGV4IC0gSWYgZGVmaW5lZCBhbmQgdGhlIGN1cnJlbnQgdmFsdWUgaXMgYW4gYXJyYXksIHRoZSB2YWx1ZVxuICogYXQgYGluZGV4YCBiZWNvbWUgdGhlIG5ldyBpbnB1dC5cbiAqIEBwYXJhbSBpbmZvIC0gb2JqZWN0IHRvIHJldHVybiBpbmZvcm1hdGlvbiBhYm91dCByZXNvbHV0aW9uIGluXG4gKiBAcGFyYW0gaW5mby5jYWNoZWFibGUgLSBXaWxsIGJlIHNldCB0byBgZmFsc2VgIGlmIG9wdGlvbiBpcyBub3QgY2FjaGVhYmxlLlxuICogQHNpbmNlIDIuNy4wXG4gKi8gZnVuY3Rpb24gcmVzb2x2ZShpbnB1dHMsIGNvbnRleHQsIGluZGV4LCBpbmZvKSB7XG4gICAgbGV0IGNhY2hlYWJsZSA9IHRydWU7XG4gICAgbGV0IGksIGlsZW4sIHZhbHVlO1xuICAgIGZvcihpID0gMCwgaWxlbiA9IGlucHV0cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICB2YWx1ZSA9IGlucHV0c1tpXTtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb250ZXh0ICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlKGNvbnRleHQpO1xuICAgICAgICAgICAgY2FjaGVhYmxlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluZGV4ICE9PSB1bmRlZmluZWQgJiYgaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWVbaW5kZXggJSB2YWx1ZS5sZW5ndGhdO1xuICAgICAgICAgICAgY2FjaGVhYmxlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmIChpbmZvICYmICFjYWNoZWFibGUpIHtcbiAgICAgICAgICAgICAgICBpbmZvLmNhY2hlYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxufVxuLyoqXG4gKiBAcGFyYW0gbWlubWF4XG4gKiBAcGFyYW0gZ3JhY2VcbiAqIEBwYXJhbSBiZWdpbkF0WmVyb1xuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYWRkR3JhY2UobWlubWF4LCBncmFjZSwgYmVnaW5BdFplcm8pIHtcbiAgICBjb25zdCB7IG1pbiAsIG1heCAgfSA9IG1pbm1heDtcbiAgICBjb25zdCBjaGFuZ2UgPSB0b0RpbWVuc2lvbihncmFjZSwgKG1heCAtIG1pbikgLyAyKTtcbiAgICBjb25zdCBrZWVwWmVybyA9ICh2YWx1ZSwgYWRkKT0+YmVnaW5BdFplcm8gJiYgdmFsdWUgPT09IDAgPyAwIDogdmFsdWUgKyBhZGQ7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWluOiBrZWVwWmVybyhtaW4sIC1NYXRoLmFicyhjaGFuZ2UpKSxcbiAgICAgICAgbWF4OiBrZWVwWmVybyhtYXgsIGNoYW5nZSlcbiAgICB9O1xufVxuZnVuY3Rpb24gY3JlYXRlQ29udGV4dChwYXJlbnRDb250ZXh0LCBjb250ZXh0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShwYXJlbnRDb250ZXh0KSwgY29udGV4dCk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIFByb3h5IGZvciByZXNvbHZpbmcgcmF3IHZhbHVlcyBmb3Igb3B0aW9ucy5cbiAqIEBwYXJhbSBzY29wZXMgLSBUaGUgb3B0aW9uIHNjb3BlcyB0byBsb29rIGZvciB2YWx1ZXMsIGluIHJlc29sdXRpb24gb3JkZXJcbiAqIEBwYXJhbSBwcmVmaXhlcyAtIFRoZSBwcmVmaXhlcyBmb3IgdmFsdWVzLCBpbiByZXNvbHV0aW9uIG9yZGVyLlxuICogQHBhcmFtIHJvb3RTY29wZXMgLSBUaGUgcm9vdCBvcHRpb24gc2NvcGVzXG4gKiBAcGFyYW0gZmFsbGJhY2sgLSBQYXJlbnQgc2NvcGVzIGZhbGxiYWNrXG4gKiBAcGFyYW0gZ2V0VGFyZ2V0IC0gY2FsbGJhY2sgZm9yIGdldHRpbmcgdGhlIHRhcmdldCBmb3IgY2hhbmdlZCB2YWx1ZXNcbiAqIEByZXR1cm5zIFByb3h5XG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9jcmVhdGVSZXNvbHZlcihzY29wZXMsIHByZWZpeGVzID0gW1xuICAgICcnXG5dLCByb290U2NvcGVzLCBmYWxsYmFjaywgZ2V0VGFyZ2V0ID0gKCk9PnNjb3Blc1swXSkge1xuICAgIGNvbnN0IGZpbmFsUm9vdFNjb3BlcyA9IHJvb3RTY29wZXMgfHwgc2NvcGVzO1xuICAgIGlmICh0eXBlb2YgZmFsbGJhY2sgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGZhbGxiYWNrID0gX3Jlc29sdmUoJ19mYWxsYmFjaycsIHNjb3Blcyk7XG4gICAgfVxuICAgIGNvbnN0IGNhY2hlID0ge1xuICAgICAgICBbU3ltYm9sLnRvU3RyaW5nVGFnXTogJ09iamVjdCcsXG4gICAgICAgIF9jYWNoZWFibGU6IHRydWUsXG4gICAgICAgIF9zY29wZXM6IHNjb3BlcyxcbiAgICAgICAgX3Jvb3RTY29wZXM6IGZpbmFsUm9vdFNjb3BlcyxcbiAgICAgICAgX2ZhbGxiYWNrOiBmYWxsYmFjayxcbiAgICAgICAgX2dldFRhcmdldDogZ2V0VGFyZ2V0LFxuICAgICAgICBvdmVycmlkZTogKHNjb3BlKT0+X2NyZWF0ZVJlc29sdmVyKFtcbiAgICAgICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgICAgICAuLi5zY29wZXNcbiAgICAgICAgICAgIF0sIHByZWZpeGVzLCBmaW5hbFJvb3RTY29wZXMsIGZhbGxiYWNrKVxuICAgIH07XG4gICAgcmV0dXJuIG5ldyBQcm94eShjYWNoZSwge1xuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIHRoZSBkZWxldGUgb3BlcmF0b3IuXG4gICAgICovIGRlbGV0ZVByb3BlcnR5ICh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0YXJnZXRbcHJvcF07IC8vIHJlbW92ZSBmcm9tIGNhY2hlXG4gICAgICAgICAgICBkZWxldGUgdGFyZ2V0Ll9rZXlzOyAvLyByZW1vdmUgY2FjaGVkIGtleXNcbiAgICAgICAgICAgIGRlbGV0ZSBzY29wZXNbMF1bcHJvcF07IC8vIHJlbW92ZSBmcm9tIHRvcCBsZXZlbCBzY29wZVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgZ2V0dGluZyBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICovIGdldCAodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICByZXR1cm4gX2NhY2hlZCh0YXJnZXQsIHByb3AsICgpPT5fcmVzb2x2ZVdpdGhQcmVmaXhlcyhwcm9wLCBwcmVmaXhlcywgc2NvcGVzLCB0YXJnZXQpKTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLlxuICAgICAqIEFsc28gdXNlZCBieSBPYmplY3QuaGFzT3duUHJvcGVydHkuXG4gICAgICovIGdldE93blByb3BlcnR5RGVzY3JpcHRvciAodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0Ll9zY29wZXNbMF0sIHByb3ApO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIE9iamVjdC5nZXRQcm90b3R5cGVPZi5cbiAgICAgKi8gZ2V0UHJvdG90eXBlT2YgKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0UHJvdG90eXBlT2Yoc2NvcGVzWzBdKTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciB0aGUgaW4gb3BlcmF0b3IuXG4gICAgICovIGhhcyAodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0S2V5c0Zyb21BbGxTY29wZXModGFyZ2V0KS5pbmNsdWRlcyhwcm9wKTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyBhbmQgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scy5cbiAgICAgKi8gb3duS2V5cyAodGFyZ2V0KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0S2V5c0Zyb21BbGxTY29wZXModGFyZ2V0KTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBzZXR0aW5nIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKi8gc2V0ICh0YXJnZXQsIHByb3AsIHZhbHVlKSB7XG4gICAgICAgICAgICBjb25zdCBzdG9yYWdlID0gdGFyZ2V0Ll9zdG9yYWdlIHx8ICh0YXJnZXQuX3N0b3JhZ2UgPSBnZXRUYXJnZXQoKSk7XG4gICAgICAgICAgICB0YXJnZXRbcHJvcF0gPSBzdG9yYWdlW3Byb3BdID0gdmFsdWU7IC8vIHNldCB0byB0b3AgbGV2ZWwgc2NvcGUgKyBjYWNoZVxuICAgICAgICAgICAgZGVsZXRlIHRhcmdldC5fa2V5czsgLy8gcmVtb3ZlIGNhY2hlZCBrZXlzXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLyoqXG4gKiBSZXR1cm5zIGFuIFByb3h5IGZvciByZXNvbHZpbmcgb3B0aW9uIHZhbHVlcyB3aXRoIGNvbnRleHQuXG4gKiBAcGFyYW0gcHJveHkgLSBUaGUgUHJveHkgcmV0dXJuZWQgYnkgYF9jcmVhdGVSZXNvbHZlcmBcbiAqIEBwYXJhbSBjb250ZXh0IC0gQ29udGV4dCBvYmplY3QgZm9yIHNjcmlwdGFibGUvaW5kZXhhYmxlIG9wdGlvbnNcbiAqIEBwYXJhbSBzdWJQcm94eSAtIFRoZSBwcm94eSBwcm92aWRlZCBmb3Igc2NyaXB0YWJsZSBvcHRpb25zXG4gKiBAcGFyYW0gZGVzY3JpcHRvckRlZmF1bHRzIC0gRGVmYXVsdHMgZm9yIGRlc2NyaXB0b3JzXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9hdHRhY2hDb250ZXh0KHByb3h5LCBjb250ZXh0LCBzdWJQcm94eSwgZGVzY3JpcHRvckRlZmF1bHRzKSB7XG4gICAgY29uc3QgY2FjaGUgPSB7XG4gICAgICAgIF9jYWNoZWFibGU6IGZhbHNlLFxuICAgICAgICBfcHJveHk6IHByb3h5LFxuICAgICAgICBfY29udGV4dDogY29udGV4dCxcbiAgICAgICAgX3N1YlByb3h5OiBzdWJQcm94eSxcbiAgICAgICAgX3N0YWNrOiBuZXcgU2V0KCksXG4gICAgICAgIF9kZXNjcmlwdG9yczogX2Rlc2NyaXB0b3JzKHByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpLFxuICAgICAgICBzZXRDb250ZXh0OiAoY3R4KT0+X2F0dGFjaENvbnRleHQocHJveHksIGN0eCwgc3ViUHJveHksIGRlc2NyaXB0b3JEZWZhdWx0cyksXG4gICAgICAgIG92ZXJyaWRlOiAoc2NvcGUpPT5fYXR0YWNoQ29udGV4dChwcm94eS5vdmVycmlkZShzY29wZSksIGNvbnRleHQsIHN1YlByb3h5LCBkZXNjcmlwdG9yRGVmYXVsdHMpXG4gICAgfTtcbiAgICByZXR1cm4gbmV3IFByb3h5KGNhY2hlLCB7XG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgdGhlIGRlbGV0ZSBvcGVyYXRvci5cbiAgICAgKi8gZGVsZXRlUHJvcGVydHkgKHRhcmdldCwgcHJvcCkge1xuICAgICAgICAgICAgZGVsZXRlIHRhcmdldFtwcm9wXTsgLy8gcmVtb3ZlIGZyb20gY2FjaGVcbiAgICAgICAgICAgIGRlbGV0ZSBwcm94eVtwcm9wXTsgLy8gcmVtb3ZlIGZyb20gcHJveHlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIGdldHRpbmcgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqLyBnZXQgKHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBfY2FjaGVkKHRhcmdldCwgcHJvcCwgKCk9Pl9yZXNvbHZlV2l0aENvbnRleHQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikpO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgKiBBIHRyYXAgZm9yIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IuXG4gICAgICogQWxzbyB1c2VkIGJ5IE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5cbiAgICAgKi8gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yICh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQuX2Rlc2NyaXB0b3JzLmFsbEtleXMgPyBSZWZsZWN0Lmhhcyhwcm94eSwgcHJvcCkgPyB7XG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgICAgIH0gOiB1bmRlZmluZWQgOiBSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm94eSwgcHJvcCk7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mLlxuICAgICAqLyBnZXRQcm90b3R5cGVPZiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXRQcm90b3R5cGVPZihwcm94eSk7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAqIEEgdHJhcCBmb3IgdGhlIGluIG9wZXJhdG9yLlxuICAgICAqLyBoYXMgKHRhcmdldCwgcHJvcCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlZmxlY3QuaGFzKHByb3h5LCBwcm9wKTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyBhbmQgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scy5cbiAgICAgKi8gb3duS2V5cyAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5vd25LZXlzKHByb3h5KTtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICogQSB0cmFwIGZvciBzZXR0aW5nIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKi8gc2V0ICh0YXJnZXQsIHByb3AsIHZhbHVlKSB7XG4gICAgICAgICAgICBwcm94eVtwcm9wXSA9IHZhbHVlOyAvLyBzZXQgdG8gcHJveHlcbiAgICAgICAgICAgIGRlbGV0ZSB0YXJnZXRbcHJvcF07IC8vIHJlbW92ZSBmcm9tIGNhY2hlXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9kZXNjcmlwdG9ycyhwcm94eSwgZGVmYXVsdHMgPSB7XG4gICAgc2NyaXB0YWJsZTogdHJ1ZSxcbiAgICBpbmRleGFibGU6IHRydWVcbn0pIHtcbiAgICBjb25zdCB7IF9zY3JpcHRhYmxlID1kZWZhdWx0cy5zY3JpcHRhYmxlICwgX2luZGV4YWJsZSA9ZGVmYXVsdHMuaW5kZXhhYmxlICwgX2FsbEtleXMgPWRlZmF1bHRzLmFsbEtleXMgIH0gPSBwcm94eTtcbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxLZXlzOiBfYWxsS2V5cyxcbiAgICAgICAgc2NyaXB0YWJsZTogX3NjcmlwdGFibGUsXG4gICAgICAgIGluZGV4YWJsZTogX2luZGV4YWJsZSxcbiAgICAgICAgaXNTY3JpcHRhYmxlOiBpc0Z1bmN0aW9uKF9zY3JpcHRhYmxlKSA/IF9zY3JpcHRhYmxlIDogKCk9Pl9zY3JpcHRhYmxlLFxuICAgICAgICBpc0luZGV4YWJsZTogaXNGdW5jdGlvbihfaW5kZXhhYmxlKSA/IF9pbmRleGFibGUgOiAoKT0+X2luZGV4YWJsZVxuICAgIH07XG59XG5jb25zdCByZWFkS2V5ID0gKHByZWZpeCwgbmFtZSk9PnByZWZpeCA/IHByZWZpeCArIF9jYXBpdGFsaXplKG5hbWUpIDogbmFtZTtcbmNvbnN0IG5lZWRzU3ViUmVzb2x2ZXIgPSAocHJvcCwgdmFsdWUpPT5pc09iamVjdCh2YWx1ZSkgJiYgcHJvcCAhPT0gJ2FkYXB0ZXJzJyAmJiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKSA9PT0gbnVsbCB8fCB2YWx1ZS5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0KTtcbmZ1bmN0aW9uIF9jYWNoZWQodGFyZ2V0LCBwcm9wLCByZXNvbHZlKSB7XG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIHByb3ApKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRbcHJvcF07XG4gICAgfVxuICAgIGNvbnN0IHZhbHVlID0gcmVzb2x2ZSgpO1xuICAgIC8vIGNhY2hlIHRoZSByZXNvbHZlZCB2YWx1ZVxuICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICAgIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIF9yZXNvbHZlV2l0aENvbnRleHQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikge1xuICAgIGNvbnN0IHsgX3Byb3h5ICwgX2NvbnRleHQgLCBfc3ViUHJveHkgLCBfZGVzY3JpcHRvcnM6IGRlc2NyaXB0b3JzICB9ID0gdGFyZ2V0O1xuICAgIGxldCB2YWx1ZSA9IF9wcm94eVtwcm9wXTsgLy8gcmVzb2x2ZSBmcm9tIHByb3h5XG4gICAgLy8gcmVzb2x2ZSB3aXRoIGNvbnRleHRcbiAgICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkgJiYgZGVzY3JpcHRvcnMuaXNTY3JpcHRhYmxlKHByb3ApKSB7XG4gICAgICAgIHZhbHVlID0gX3Jlc29sdmVTY3JpcHRhYmxlKHByb3AsIHZhbHVlLCB0YXJnZXQsIHJlY2VpdmVyKTtcbiAgICB9XG4gICAgaWYgKGlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCkge1xuICAgICAgICB2YWx1ZSA9IF9yZXNvbHZlQXJyYXkocHJvcCwgdmFsdWUsIHRhcmdldCwgZGVzY3JpcHRvcnMuaXNJbmRleGFibGUpO1xuICAgIH1cbiAgICBpZiAobmVlZHNTdWJSZXNvbHZlcihwcm9wLCB2YWx1ZSkpIHtcbiAgICAgICAgLy8gaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGFuIG9iamVjdCwgY3JlYXRlIGEgc3ViIHJlc29sdmVyIGZvciBpdFxuICAgICAgICB2YWx1ZSA9IF9hdHRhY2hDb250ZXh0KHZhbHVlLCBfY29udGV4dCwgX3N1YlByb3h5ICYmIF9zdWJQcm94eVtwcm9wXSwgZGVzY3JpcHRvcnMpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiBfcmVzb2x2ZVNjcmlwdGFibGUocHJvcCwgZ2V0VmFsdWUsIHRhcmdldCwgcmVjZWl2ZXIpIHtcbiAgICBjb25zdCB7IF9wcm94eSAsIF9jb250ZXh0ICwgX3N1YlByb3h5ICwgX3N0YWNrICB9ID0gdGFyZ2V0O1xuICAgIGlmIChfc3RhY2suaGFzKHByb3ApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVjdXJzaW9uIGRldGVjdGVkOiAnICsgQXJyYXkuZnJvbShfc3RhY2spLmpvaW4oJy0+JykgKyAnLT4nICsgcHJvcCk7XG4gICAgfVxuICAgIF9zdGFjay5hZGQocHJvcCk7XG4gICAgbGV0IHZhbHVlID0gZ2V0VmFsdWUoX2NvbnRleHQsIF9zdWJQcm94eSB8fCByZWNlaXZlcik7XG4gICAgX3N0YWNrLmRlbGV0ZShwcm9wKTtcbiAgICBpZiAobmVlZHNTdWJSZXNvbHZlcihwcm9wLCB2YWx1ZSkpIHtcbiAgICAgICAgLy8gV2hlbiBzY3JpcHRhYmxlIG9wdGlvbiByZXR1cm5zIGFuIG9iamVjdCwgY3JlYXRlIGEgcmVzb2x2ZXIgb24gdGhhdC5cbiAgICAgICAgdmFsdWUgPSBjcmVhdGVTdWJSZXNvbHZlcihfcHJveHkuX3Njb3BlcywgX3Byb3h5LCBwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIF9yZXNvbHZlQXJyYXkocHJvcCwgdmFsdWUsIHRhcmdldCwgaXNJbmRleGFibGUpIHtcbiAgICBjb25zdCB7IF9wcm94eSAsIF9jb250ZXh0ICwgX3N1YlByb3h5ICwgX2Rlc2NyaXB0b3JzOiBkZXNjcmlwdG9ycyAgfSA9IHRhcmdldDtcbiAgICBpZiAodHlwZW9mIF9jb250ZXh0LmluZGV4ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luZGV4YWJsZShwcm9wKSkge1xuICAgICAgICByZXR1cm4gdmFsdWVbX2NvbnRleHQuaW5kZXggJSB2YWx1ZS5sZW5ndGhdO1xuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QodmFsdWVbMF0pKSB7XG4gICAgICAgIC8vIEFycmF5IG9mIG9iamVjdHMsIHJldHVybiBhcnJheSBvciByZXNvbHZlcnNcbiAgICAgICAgY29uc3QgYXJyID0gdmFsdWU7XG4gICAgICAgIGNvbnN0IHNjb3BlcyA9IF9wcm94eS5fc2NvcGVzLmZpbHRlcigocyk9PnMgIT09IGFycik7XG4gICAgICAgIHZhbHVlID0gW107XG4gICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpe1xuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBjcmVhdGVTdWJSZXNvbHZlcihzY29wZXMsIF9wcm94eSwgcHJvcCwgaXRlbSk7XG4gICAgICAgICAgICB2YWx1ZS5wdXNoKF9hdHRhY2hDb250ZXh0KHJlc29sdmVyLCBfY29udGV4dCwgX3N1YlByb3h5ICYmIF9zdWJQcm94eVtwcm9wXSwgZGVzY3JpcHRvcnMpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiByZXNvbHZlRmFsbGJhY2soZmFsbGJhY2ssIHByb3AsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzRnVuY3Rpb24oZmFsbGJhY2spID8gZmFsbGJhY2socHJvcCwgdmFsdWUpIDogZmFsbGJhY2s7XG59XG5jb25zdCBnZXRTY29wZSA9IChrZXksIHBhcmVudCk9PmtleSA9PT0gdHJ1ZSA/IHBhcmVudCA6IHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnID8gcmVzb2x2ZU9iamVjdEtleShwYXJlbnQsIGtleSkgOiB1bmRlZmluZWQ7XG5mdW5jdGlvbiBhZGRTY29wZXMoc2V0LCBwYXJlbnRTY29wZXMsIGtleSwgcGFyZW50RmFsbGJhY2ssIHZhbHVlKSB7XG4gICAgZm9yIChjb25zdCBwYXJlbnQgb2YgcGFyZW50U2NvcGVzKXtcbiAgICAgICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZShrZXksIHBhcmVudCk7XG4gICAgICAgIGlmIChzY29wZSkge1xuICAgICAgICAgICAgc2V0LmFkZChzY29wZSk7XG4gICAgICAgICAgICBjb25zdCBmYWxsYmFjayA9IHJlc29sdmVGYWxsYmFjayhzY29wZS5fZmFsbGJhY2ssIGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmYWxsYmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgZmFsbGJhY2sgIT09IGtleSAmJiBmYWxsYmFjayAhPT0gcGFyZW50RmFsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIHJlYWNoIHRoZSBkZXNjcmlwdG9yIHRoYXQgZGVmaW5lcyBhIG5ldyBfZmFsbGJhY2ssIHJldHVybiB0aGF0LlxuICAgICAgICAgICAgICAgIC8vIFRoZSBmYWxsYmFjayB3aWxsIHJlc3VtZSB0byB0aGF0IG5ldyBzY29wZS5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2NvcGUgPT09IGZhbHNlICYmIHR5cGVvZiBwYXJlbnRGYWxsYmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYga2V5ICE9PSBwYXJlbnRGYWxsYmFjaykge1xuICAgICAgICAgICAgLy8gRmFsbGJhY2sgdG8gYGZhbHNlYCByZXN1bHRzIHRvIGBmYWxzZWAsIHdoZW4gZmFsbGluZyBiYWNrIHRvIGRpZmZlcmVudCBrZXkuXG4gICAgICAgICAgICAvLyBGb3IgZXhhbXBsZSBgaW50ZXJhY3Rpb25gIGZyb20gYGhvdmVyYCBvciBgcGx1Z2lucy50b29sdGlwYCBhbmQgYGFuaW1hdGlvbmAgZnJvbSBgYW5pbWF0aW9uc2BcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVN1YlJlc29sdmVyKHBhcmVudFNjb3BlcywgcmVzb2x2ZXIsIHByb3AsIHZhbHVlKSB7XG4gICAgY29uc3Qgcm9vdFNjb3BlcyA9IHJlc29sdmVyLl9yb290U2NvcGVzO1xuICAgIGNvbnN0IGZhbGxiYWNrID0gcmVzb2x2ZUZhbGxiYWNrKHJlc29sdmVyLl9mYWxsYmFjaywgcHJvcCwgdmFsdWUpO1xuICAgIGNvbnN0IGFsbFNjb3BlcyA9IFtcbiAgICAgICAgLi4ucGFyZW50U2NvcGVzLFxuICAgICAgICAuLi5yb290U2NvcGVzXG4gICAgXTtcbiAgICBjb25zdCBzZXQgPSBuZXcgU2V0KCk7XG4gICAgc2V0LmFkZCh2YWx1ZSk7XG4gICAgbGV0IGtleSA9IGFkZFNjb3Blc0Zyb21LZXkoc2V0LCBhbGxTY29wZXMsIHByb3AsIGZhbGxiYWNrIHx8IHByb3AsIHZhbHVlKTtcbiAgICBpZiAoa2V5ID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBmYWxsYmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgZmFsbGJhY2sgIT09IHByb3ApIHtcbiAgICAgICAga2V5ID0gYWRkU2NvcGVzRnJvbUtleShzZXQsIGFsbFNjb3BlcywgZmFsbGJhY2ssIGtleSwgdmFsdWUpO1xuICAgICAgICBpZiAoa2V5ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIF9jcmVhdGVSZXNvbHZlcihBcnJheS5mcm9tKHNldCksIFtcbiAgICAgICAgJydcbiAgICBdLCByb290U2NvcGVzLCBmYWxsYmFjaywgKCk9PnN1YkdldFRhcmdldChyZXNvbHZlciwgcHJvcCwgdmFsdWUpKTtcbn1cbmZ1bmN0aW9uIGFkZFNjb3Blc0Zyb21LZXkoc2V0LCBhbGxTY29wZXMsIGtleSwgZmFsbGJhY2ssIGl0ZW0pIHtcbiAgICB3aGlsZShrZXkpe1xuICAgICAgICBrZXkgPSBhZGRTY29wZXMoc2V0LCBhbGxTY29wZXMsIGtleSwgZmFsbGJhY2ssIGl0ZW0pO1xuICAgIH1cbiAgICByZXR1cm4ga2V5O1xufVxuZnVuY3Rpb24gc3ViR2V0VGFyZ2V0KHJlc29sdmVyLCBwcm9wLCB2YWx1ZSkge1xuICAgIGNvbnN0IHBhcmVudCA9IHJlc29sdmVyLl9nZXRUYXJnZXQoKTtcbiAgICBpZiAoIShwcm9wIGluIHBhcmVudCkpIHtcbiAgICAgICAgcGFyZW50W3Byb3BdID0ge307XG4gICAgfVxuICAgIGNvbnN0IHRhcmdldCA9IHBhcmVudFtwcm9wXTtcbiAgICBpZiAoaXNBcnJheSh0YXJnZXQpICYmIGlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAvLyBGb3IgYXJyYXkgb2Ygb2JqZWN0cywgdGhlIG9iamVjdCBpcyB1c2VkIHRvIHN0b3JlIHVwZGF0ZWQgdmFsdWVzXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldCB8fCB7fTtcbn1cbmZ1bmN0aW9uIF9yZXNvbHZlV2l0aFByZWZpeGVzKHByb3AsIHByZWZpeGVzLCBzY29wZXMsIHByb3h5KSB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGZvciAoY29uc3QgcHJlZml4IG9mIHByZWZpeGVzKXtcbiAgICAgICAgdmFsdWUgPSBfcmVzb2x2ZShyZWFkS2V5KHByZWZpeCwgcHJvcCksIHNjb3Blcyk7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gbmVlZHNTdWJSZXNvbHZlcihwcm9wLCB2YWx1ZSkgPyBjcmVhdGVTdWJSZXNvbHZlcihzY29wZXMsIHByb3h5LCBwcm9wLCB2YWx1ZSkgOiB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIF9yZXNvbHZlKGtleSwgc2NvcGVzKSB7XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiBzY29wZXMpe1xuICAgICAgICBpZiAoIXNjb3BlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWx1ZSA9IHNjb3BlW2tleV07XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBnZXRLZXlzRnJvbUFsbFNjb3Blcyh0YXJnZXQpIHtcbiAgICBsZXQga2V5cyA9IHRhcmdldC5fa2V5cztcbiAgICBpZiAoIWtleXMpIHtcbiAgICAgICAga2V5cyA9IHRhcmdldC5fa2V5cyA9IHJlc29sdmVLZXlzRnJvbUFsbFNjb3Blcyh0YXJnZXQuX3Njb3Blcyk7XG4gICAgfVxuICAgIHJldHVybiBrZXlzO1xufVxuZnVuY3Rpb24gcmVzb2x2ZUtleXNGcm9tQWxsU2NvcGVzKHNjb3Blcykge1xuICAgIGNvbnN0IHNldCA9IG5ldyBTZXQoKTtcbiAgICBmb3IgKGNvbnN0IHNjb3BlIG9mIHNjb3Blcyl7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHNjb3BlKS5maWx0ZXIoKGspPT4hay5zdGFydHNXaXRoKCdfJykpKXtcbiAgICAgICAgICAgIHNldC5hZGQoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gQXJyYXkuZnJvbShzZXQpO1xufVxuZnVuY3Rpb24gX3BhcnNlT2JqZWN0RGF0YVJhZGlhbFNjYWxlKG1ldGEsIGRhdGEsIHN0YXJ0LCBjb3VudCkge1xuICAgIGNvbnN0IHsgaVNjYWxlICB9ID0gbWV0YTtcbiAgICBjb25zdCB7IGtleSA9J3InICB9ID0gdGhpcy5fcGFyc2luZztcbiAgICBjb25zdCBwYXJzZWQgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgIGxldCBpLCBpbGVuLCBpbmRleCwgaXRlbTtcbiAgICBmb3IoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgIGluZGV4ID0gaSArIHN0YXJ0O1xuICAgICAgICBpdGVtID0gZGF0YVtpbmRleF07XG4gICAgICAgIHBhcnNlZFtpXSA9IHtcbiAgICAgICAgICAgIHI6IGlTY2FsZS5wYXJzZShyZXNvbHZlT2JqZWN0S2V5KGl0ZW0sIGtleSksIGluZGV4KVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xufVxuXG5jb25zdCBFUFNJTE9OID0gTnVtYmVyLkVQU0lMT04gfHwgMWUtMTQ7XG5jb25zdCBnZXRQb2ludCA9IChwb2ludHMsIGkpPT5pIDwgcG9pbnRzLmxlbmd0aCAmJiAhcG9pbnRzW2ldLnNraXAgJiYgcG9pbnRzW2ldO1xuY29uc3QgZ2V0VmFsdWVBeGlzID0gKGluZGV4QXhpcyk9PmluZGV4QXhpcyA9PT0gJ3gnID8gJ3knIDogJ3gnO1xuZnVuY3Rpb24gc3BsaW5lQ3VydmUoZmlyc3RQb2ludCwgbWlkZGxlUG9pbnQsIGFmdGVyUG9pbnQsIHQpIHtcbiAgICAvLyBQcm9wcyB0byBSb2IgU3BlbmNlciBhdCBzY2FsZWQgaW5ub3ZhdGlvbiBmb3IgaGlzIHBvc3Qgb24gc3BsaW5pbmcgYmV0d2VlbiBwb2ludHNcbiAgICAvLyBodHRwOi8vc2NhbGVkaW5ub3ZhdGlvbi5jb20vYW5hbHl0aWNzL3NwbGluZXMvYWJvdXRTcGxpbmVzLmh0bWxcbiAgICAvLyBUaGlzIGZ1bmN0aW9uIG11c3QgYWxzbyByZXNwZWN0IFwic2tpcHBlZFwiIHBvaW50c1xuICAgIGNvbnN0IHByZXZpb3VzID0gZmlyc3RQb2ludC5za2lwID8gbWlkZGxlUG9pbnQgOiBmaXJzdFBvaW50O1xuICAgIGNvbnN0IGN1cnJlbnQgPSBtaWRkbGVQb2ludDtcbiAgICBjb25zdCBuZXh0ID0gYWZ0ZXJQb2ludC5za2lwID8gbWlkZGxlUG9pbnQgOiBhZnRlclBvaW50O1xuICAgIGNvbnN0IGQwMSA9IGRpc3RhbmNlQmV0d2VlblBvaW50cyhjdXJyZW50LCBwcmV2aW91cyk7XG4gICAgY29uc3QgZDEyID0gZGlzdGFuY2VCZXR3ZWVuUG9pbnRzKG5leHQsIGN1cnJlbnQpO1xuICAgIGxldCBzMDEgPSBkMDEgLyAoZDAxICsgZDEyKTtcbiAgICBsZXQgczEyID0gZDEyIC8gKGQwMSArIGQxMik7XG4gICAgLy8gSWYgYWxsIHBvaW50cyBhcmUgdGhlIHNhbWUsIHMwMSAmIHMwMiB3aWxsIGJlIGluZlxuICAgIHMwMSA9IGlzTmFOKHMwMSkgPyAwIDogczAxO1xuICAgIHMxMiA9IGlzTmFOKHMxMikgPyAwIDogczEyO1xuICAgIGNvbnN0IGZhID0gdCAqIHMwMTsgLy8gc2NhbGluZyBmYWN0b3IgZm9yIHRyaWFuZ2xlIFRhXG4gICAgY29uc3QgZmIgPSB0ICogczEyO1xuICAgIHJldHVybiB7XG4gICAgICAgIHByZXZpb3VzOiB7XG4gICAgICAgICAgICB4OiBjdXJyZW50LnggLSBmYSAqIChuZXh0LnggLSBwcmV2aW91cy54KSxcbiAgICAgICAgICAgIHk6IGN1cnJlbnQueSAtIGZhICogKG5leHQueSAtIHByZXZpb3VzLnkpXG4gICAgICAgIH0sXG4gICAgICAgIG5leHQ6IHtcbiAgICAgICAgICAgIHg6IGN1cnJlbnQueCArIGZiICogKG5leHQueCAtIHByZXZpb3VzLngpLFxuICAgICAgICAgICAgeTogY3VycmVudC55ICsgZmIgKiAobmV4dC55IC0gcHJldmlvdXMueSlcbiAgICAgICAgfVxuICAgIH07XG59XG4vKipcbiAqIEFkanVzdCB0YW5nZW50cyB0byBlbnN1cmUgbW9ub3RvbmljIHByb3BlcnRpZXNcbiAqLyBmdW5jdGlvbiBtb25vdG9uZUFkanVzdChwb2ludHMsIGRlbHRhSywgbUspIHtcbiAgICBjb25zdCBwb2ludHNMZW4gPSBwb2ludHMubGVuZ3RoO1xuICAgIGxldCBhbHBoYUssIGJldGFLLCB0YXVLLCBzcXVhcmVkTWFnbml0dWRlLCBwb2ludEN1cnJlbnQ7XG4gICAgbGV0IHBvaW50QWZ0ZXIgPSBnZXRQb2ludChwb2ludHMsIDApO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwb2ludHNMZW4gLSAxOyArK2kpe1xuICAgICAgICBwb2ludEN1cnJlbnQgPSBwb2ludEFmdGVyO1xuICAgICAgICBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCBpICsgMSk7XG4gICAgICAgIGlmICghcG9pbnRDdXJyZW50IHx8ICFwb2ludEFmdGVyKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWxtb3N0RXF1YWxzKGRlbHRhS1tpXSwgMCwgRVBTSUxPTikpIHtcbiAgICAgICAgICAgIG1LW2ldID0gbUtbaSArIDFdID0gMDtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGFscGhhSyA9IG1LW2ldIC8gZGVsdGFLW2ldO1xuICAgICAgICBiZXRhSyA9IG1LW2kgKyAxXSAvIGRlbHRhS1tpXTtcbiAgICAgICAgc3F1YXJlZE1hZ25pdHVkZSA9IE1hdGgucG93KGFscGhhSywgMikgKyBNYXRoLnBvdyhiZXRhSywgMik7XG4gICAgICAgIGlmIChzcXVhcmVkTWFnbml0dWRlIDw9IDkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRhdUsgPSAzIC8gTWF0aC5zcXJ0KHNxdWFyZWRNYWduaXR1ZGUpO1xuICAgICAgICBtS1tpXSA9IGFscGhhSyAqIHRhdUsgKiBkZWx0YUtbaV07XG4gICAgICAgIG1LW2kgKyAxXSA9IGJldGFLICogdGF1SyAqIGRlbHRhS1tpXTtcbiAgICB9XG59XG5mdW5jdGlvbiBtb25vdG9uZUNvbXB1dGUocG9pbnRzLCBtSywgaW5kZXhBeGlzID0gJ3gnKSB7XG4gICAgY29uc3QgdmFsdWVBeGlzID0gZ2V0VmFsdWVBeGlzKGluZGV4QXhpcyk7XG4gICAgY29uc3QgcG9pbnRzTGVuID0gcG9pbnRzLmxlbmd0aDtcbiAgICBsZXQgZGVsdGEsIHBvaW50QmVmb3JlLCBwb2ludEN1cnJlbnQ7XG4gICAgbGV0IHBvaW50QWZ0ZXIgPSBnZXRQb2ludChwb2ludHMsIDApO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwb2ludHNMZW47ICsraSl7XG4gICAgICAgIHBvaW50QmVmb3JlID0gcG9pbnRDdXJyZW50O1xuICAgICAgICBwb2ludEN1cnJlbnQgPSBwb2ludEFmdGVyO1xuICAgICAgICBwb2ludEFmdGVyID0gZ2V0UG9pbnQocG9pbnRzLCBpICsgMSk7XG4gICAgICAgIGlmICghcG9pbnRDdXJyZW50KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpUGl4ZWwgPSBwb2ludEN1cnJlbnRbaW5kZXhBeGlzXTtcbiAgICAgICAgY29uc3QgdlBpeGVsID0gcG9pbnRDdXJyZW50W3ZhbHVlQXhpc107XG4gICAgICAgIGlmIChwb2ludEJlZm9yZSkge1xuICAgICAgICAgICAgZGVsdGEgPSAoaVBpeGVsIC0gcG9pbnRCZWZvcmVbaW5kZXhBeGlzXSkgLyAzO1xuICAgICAgICAgICAgcG9pbnRDdXJyZW50W2BjcDEke2luZGV4QXhpc31gXSA9IGlQaXhlbCAtIGRlbHRhO1xuICAgICAgICAgICAgcG9pbnRDdXJyZW50W2BjcDEke3ZhbHVlQXhpc31gXSA9IHZQaXhlbCAtIGRlbHRhICogbUtbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBvaW50QWZ0ZXIpIHtcbiAgICAgICAgICAgIGRlbHRhID0gKHBvaW50QWZ0ZXJbaW5kZXhBeGlzXSAtIGlQaXhlbCkgLyAzO1xuICAgICAgICAgICAgcG9pbnRDdXJyZW50W2BjcDIke2luZGV4QXhpc31gXSA9IGlQaXhlbCArIGRlbHRhO1xuICAgICAgICAgICAgcG9pbnRDdXJyZW50W2BjcDIke3ZhbHVlQXhpc31gXSA9IHZQaXhlbCArIGRlbHRhICogbUtbaV07XG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gY2FsY3VsYXRlcyBCw6l6aWVyIGNvbnRyb2wgcG9pbnRzIGluIGEgc2ltaWxhciB3YXkgdGhhbiB8c3BsaW5lQ3VydmV8LFxuICogYnV0IHByZXNlcnZlcyBtb25vdG9uaWNpdHkgb2YgdGhlIHByb3ZpZGVkIGRhdGEgYW5kIGVuc3VyZXMgbm8gbG9jYWwgZXh0cmVtdW1zIGFyZSBhZGRlZFxuICogYmV0d2VlbiB0aGUgZGF0YXNldCBkaXNjcmV0ZSBwb2ludHMgZHVlIHRvIHRoZSBpbnRlcnBvbGF0aW9uLlxuICogU2VlIDogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9ub3RvbmVfY3ViaWNfaW50ZXJwb2xhdGlvblxuICovIGZ1bmN0aW9uIHNwbGluZUN1cnZlTW9ub3RvbmUocG9pbnRzLCBpbmRleEF4aXMgPSAneCcpIHtcbiAgICBjb25zdCB2YWx1ZUF4aXMgPSBnZXRWYWx1ZUF4aXMoaW5kZXhBeGlzKTtcbiAgICBjb25zdCBwb2ludHNMZW4gPSBwb2ludHMubGVuZ3RoO1xuICAgIGNvbnN0IGRlbHRhSyA9IEFycmF5KHBvaW50c0xlbikuZmlsbCgwKTtcbiAgICBjb25zdCBtSyA9IEFycmF5KHBvaW50c0xlbik7XG4gICAgLy8gQ2FsY3VsYXRlIHNsb3BlcyAoZGVsdGFLKSBhbmQgaW5pdGlhbGl6ZSB0YW5nZW50cyAobUspXG4gICAgbGV0IGksIHBvaW50QmVmb3JlLCBwb2ludEN1cnJlbnQ7XG4gICAgbGV0IHBvaW50QWZ0ZXIgPSBnZXRQb2ludChwb2ludHMsIDApO1xuICAgIGZvcihpID0gMDsgaSA8IHBvaW50c0xlbjsgKytpKXtcbiAgICAgICAgcG9pbnRCZWZvcmUgPSBwb2ludEN1cnJlbnQ7XG4gICAgICAgIHBvaW50Q3VycmVudCA9IHBvaW50QWZ0ZXI7XG4gICAgICAgIHBvaW50QWZ0ZXIgPSBnZXRQb2ludChwb2ludHMsIGkgKyAxKTtcbiAgICAgICAgaWYgKCFwb2ludEN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb2ludEFmdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBzbG9wZURlbHRhID0gcG9pbnRBZnRlcltpbmRleEF4aXNdIC0gcG9pbnRDdXJyZW50W2luZGV4QXhpc107XG4gICAgICAgICAgICAvLyBJbiB0aGUgY2FzZSBvZiB0d28gcG9pbnRzIHRoYXQgYXBwZWFyIGF0IHRoZSBzYW1lIHggcGl4ZWwsIHNsb3BlRGVsdGFYIGlzIDBcbiAgICAgICAgICAgIGRlbHRhS1tpXSA9IHNsb3BlRGVsdGEgIT09IDAgPyAocG9pbnRBZnRlclt2YWx1ZUF4aXNdIC0gcG9pbnRDdXJyZW50W3ZhbHVlQXhpc10pIC8gc2xvcGVEZWx0YSA6IDA7XG4gICAgICAgIH1cbiAgICAgICAgbUtbaV0gPSAhcG9pbnRCZWZvcmUgPyBkZWx0YUtbaV0gOiAhcG9pbnRBZnRlciA/IGRlbHRhS1tpIC0gMV0gOiBzaWduKGRlbHRhS1tpIC0gMV0pICE9PSBzaWduKGRlbHRhS1tpXSkgPyAwIDogKGRlbHRhS1tpIC0gMV0gKyBkZWx0YUtbaV0pIC8gMjtcbiAgICB9XG4gICAgbW9ub3RvbmVBZGp1c3QocG9pbnRzLCBkZWx0YUssIG1LKTtcbiAgICBtb25vdG9uZUNvbXB1dGUocG9pbnRzLCBtSywgaW5kZXhBeGlzKTtcbn1cbmZ1bmN0aW9uIGNhcENvbnRyb2xQb2ludChwdCwgbWluLCBtYXgpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5taW4ocHQsIG1heCksIG1pbik7XG59XG5mdW5jdGlvbiBjYXBCZXppZXJQb2ludHMocG9pbnRzLCBhcmVhKSB7XG4gICAgbGV0IGksIGlsZW4sIHBvaW50LCBpbkFyZWEsIGluQXJlYVByZXY7XG4gICAgbGV0IGluQXJlYU5leHQgPSBfaXNQb2ludEluQXJlYShwb2ludHNbMF0sIGFyZWEpO1xuICAgIGZvcihpID0gMCwgaWxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICBpbkFyZWFQcmV2ID0gaW5BcmVhO1xuICAgICAgICBpbkFyZWEgPSBpbkFyZWFOZXh0O1xuICAgICAgICBpbkFyZWFOZXh0ID0gaSA8IGlsZW4gLSAxICYmIF9pc1BvaW50SW5BcmVhKHBvaW50c1tpICsgMV0sIGFyZWEpO1xuICAgICAgICBpZiAoIWluQXJlYSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgICAgIGlmIChpbkFyZWFQcmV2KSB7XG4gICAgICAgICAgICBwb2ludC5jcDF4ID0gY2FwQ29udHJvbFBvaW50KHBvaW50LmNwMXgsIGFyZWEubGVmdCwgYXJlYS5yaWdodCk7XG4gICAgICAgICAgICBwb2ludC5jcDF5ID0gY2FwQ29udHJvbFBvaW50KHBvaW50LmNwMXksIGFyZWEudG9wLCBhcmVhLmJvdHRvbSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluQXJlYU5leHQpIHtcbiAgICAgICAgICAgIHBvaW50LmNwMnggPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AyeCwgYXJlYS5sZWZ0LCBhcmVhLnJpZ2h0KTtcbiAgICAgICAgICAgIHBvaW50LmNwMnkgPSBjYXBDb250cm9sUG9pbnQocG9pbnQuY3AyeSwgYXJlYS50b3AsIGFyZWEuYm90dG9tKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfdXBkYXRlQmV6aWVyQ29udHJvbFBvaW50cyhwb2ludHMsIG9wdGlvbnMsIGFyZWEsIGxvb3AsIGluZGV4QXhpcykge1xuICAgIGxldCBpLCBpbGVuLCBwb2ludCwgY29udHJvbFBvaW50cztcbiAgICAvLyBPbmx5IGNvbnNpZGVyIHBvaW50cyB0aGF0IGFyZSBkcmF3biBpbiBjYXNlIHRoZSBzcGFuR2FwcyBvcHRpb24gaXMgdXNlZFxuICAgIGlmIChvcHRpb25zLnNwYW5HYXBzKSB7XG4gICAgICAgIHBvaW50cyA9IHBvaW50cy5maWx0ZXIoKHB0KT0+IXB0LnNraXApO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5jdWJpY0ludGVycG9sYXRpb25Nb2RlID09PSAnbW9ub3RvbmUnKSB7XG4gICAgICAgIHNwbGluZUN1cnZlTW9ub3RvbmUocG9pbnRzLCBpbmRleEF4aXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBwcmV2ID0gbG9vcCA/IHBvaW50c1twb2ludHMubGVuZ3RoIC0gMV0gOiBwb2ludHNbMF07XG4gICAgICAgIGZvcihpID0gMCwgaWxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBpbGVuOyArK2kpe1xuICAgICAgICAgICAgcG9pbnQgPSBwb2ludHNbaV07XG4gICAgICAgICAgICBjb250cm9sUG9pbnRzID0gc3BsaW5lQ3VydmUocHJldiwgcG9pbnQsIHBvaW50c1tNYXRoLm1pbihpICsgMSwgaWxlbiAtIChsb29wID8gMCA6IDEpKSAlIGlsZW5dLCBvcHRpb25zLnRlbnNpb24pO1xuICAgICAgICAgICAgcG9pbnQuY3AxeCA9IGNvbnRyb2xQb2ludHMucHJldmlvdXMueDtcbiAgICAgICAgICAgIHBvaW50LmNwMXkgPSBjb250cm9sUG9pbnRzLnByZXZpb3VzLnk7XG4gICAgICAgICAgICBwb2ludC5jcDJ4ID0gY29udHJvbFBvaW50cy5uZXh0Lng7XG4gICAgICAgICAgICBwb2ludC5jcDJ5ID0gY29udHJvbFBvaW50cy5uZXh0Lnk7XG4gICAgICAgICAgICBwcmV2ID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuY2FwQmV6aWVyUG9pbnRzKSB7XG4gICAgICAgIGNhcEJlemllclBvaW50cyhwb2ludHMsIGFyZWEpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBOb3RlOiB0eXBlZGVmcyBhcmUgYXV0by1leHBvcnRlZCwgc28gdXNlIGEgbWFkZS11cCBgZG9tYCBuYW1lc3BhY2Ugd2hlcmVcbiAqIG5lY2Vzc2FyeSB0byBhdm9pZCBkdXBsaWNhdGVzIHdpdGggYGV4cG9ydCAqIGZyb20gJy4vaGVscGVyc2A7IHNlZVxuICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9UeXBlU2NyaXB0L2lzc3Vlcy80NjAxMVxuICogQHR5cGVkZWYgeyBpbXBvcnQoJy4uL2NvcmUvY29yZS5jb250cm9sbGVyLmpzJykuZGVmYXVsdCB9IGRvbS5DaGFydFxuICogQHR5cGVkZWYgeyBpbXBvcnQoJy4uLy4uL3R5cGVzJykuQ2hhcnRFdmVudCB9IENoYXJ0RXZlbnRcbiAqLyAvKipcbiAqIEBwcml2YXRlXG4gKi8gZnVuY3Rpb24gX2lzRG9tU3VwcG9ydGVkKCkge1xuICAgIHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9nZXRQYXJlbnROb2RlKGRvbU5vZGUpIHtcbiAgICBsZXQgcGFyZW50ID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgIGlmIChwYXJlbnQgJiYgcGFyZW50LnRvU3RyaW5nKCkgPT09ICdbb2JqZWN0IFNoYWRvd1Jvb3RdJykge1xuICAgICAgICBwYXJlbnQgPSBwYXJlbnQuaG9zdDtcbiAgICB9XG4gICAgcmV0dXJuIHBhcmVudDtcbn1cbi8qKlxuICogY29udmVydCBtYXgtd2lkdGgvbWF4LWhlaWdodCB2YWx1ZXMgdGhhdCBtYXkgYmUgcGVyY2VudGFnZXMgaW50byBhIG51bWJlclxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBwYXJzZU1heFN0eWxlKHN0eWxlVmFsdWUsIG5vZGUsIHBhcmVudFByb3BlcnR5KSB7XG4gICAgbGV0IHZhbHVlSW5QaXhlbHM7XG4gICAgaWYgKHR5cGVvZiBzdHlsZVZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YWx1ZUluUGl4ZWxzID0gcGFyc2VJbnQoc3R5bGVWYWx1ZSwgMTApO1xuICAgICAgICBpZiAoc3R5bGVWYWx1ZS5pbmRleE9mKCclJykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBwZXJjZW50YWdlICogc2l6ZSBpbiBkaW1lbnNpb25cbiAgICAgICAgICAgIHZhbHVlSW5QaXhlbHMgPSB2YWx1ZUluUGl4ZWxzIC8gMTAwICogbm9kZS5wYXJlbnROb2RlW3BhcmVudFByb3BlcnR5XTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbHVlSW5QaXhlbHMgPSBzdHlsZVZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWVJblBpeGVscztcbn1cbmNvbnN0IGdldENvbXB1dGVkU3R5bGUgPSAoZWxlbWVudCk9PmVsZW1lbnQub3duZXJEb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQsIG51bGwpO1xuZnVuY3Rpb24gZ2V0U3R5bGUoZWwsIHByb3BlcnR5KSB7XG4gICAgcmV0dXJuIGdldENvbXB1dGVkU3R5bGUoZWwpLmdldFByb3BlcnR5VmFsdWUocHJvcGVydHkpO1xufVxuY29uc3QgcG9zaXRpb25zID0gW1xuICAgICd0b3AnLFxuICAgICdyaWdodCcsXG4gICAgJ2JvdHRvbScsXG4gICAgJ2xlZnQnXG5dO1xuZnVuY3Rpb24gZ2V0UG9zaXRpb25lZFN0eWxlKHN0eWxlcywgc3R5bGUsIHN1ZmZpeCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgIHN1ZmZpeCA9IHN1ZmZpeCA/ICctJyArIHN1ZmZpeCA6ICcnO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCA0OyBpKyspe1xuICAgICAgICBjb25zdCBwb3MgPSBwb3NpdGlvbnNbaV07XG4gICAgICAgIHJlc3VsdFtwb3NdID0gcGFyc2VGbG9hdChzdHlsZXNbc3R5bGUgKyAnLScgKyBwb3MgKyBzdWZmaXhdKSB8fCAwO1xuICAgIH1cbiAgICByZXN1bHQud2lkdGggPSByZXN1bHQubGVmdCArIHJlc3VsdC5yaWdodDtcbiAgICByZXN1bHQuaGVpZ2h0ID0gcmVzdWx0LnRvcCArIHJlc3VsdC5ib3R0b207XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmNvbnN0IHVzZU9mZnNldFBvcyA9ICh4LCB5LCB0YXJnZXQpPT4oeCA+IDAgfHwgeSA+IDApICYmICghdGFyZ2V0IHx8ICF0YXJnZXQuc2hhZG93Um9vdCk7XG4vKipcbiAqIEBwYXJhbSBlXG4gKiBAcGFyYW0gY2FudmFzXG4gKiBAcmV0dXJucyBDYW52YXMgcG9zaXRpb25cbiAqLyBmdW5jdGlvbiBnZXRDYW52YXNQb3NpdGlvbihlLCBjYW52YXMpIHtcbiAgICBjb25zdCB0b3VjaGVzID0gZS50b3VjaGVzO1xuICAgIGNvbnN0IHNvdXJjZSA9IHRvdWNoZXMgJiYgdG91Y2hlcy5sZW5ndGggPyB0b3VjaGVzWzBdIDogZTtcbiAgICBjb25zdCB7IG9mZnNldFggLCBvZmZzZXRZICB9ID0gc291cmNlO1xuICAgIGxldCBib3ggPSBmYWxzZTtcbiAgICBsZXQgeCwgeTtcbiAgICBpZiAodXNlT2Zmc2V0UG9zKG9mZnNldFgsIG9mZnNldFksIGUudGFyZ2V0KSkge1xuICAgICAgICB4ID0gb2Zmc2V0WDtcbiAgICAgICAgeSA9IG9mZnNldFk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmVjdCA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgeCA9IHNvdXJjZS5jbGllbnRYIC0gcmVjdC5sZWZ0O1xuICAgICAgICB5ID0gc291cmNlLmNsaWVudFkgLSByZWN0LnRvcDtcbiAgICAgICAgYm94ID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeCxcbiAgICAgICAgeSxcbiAgICAgICAgYm94XG4gICAgfTtcbn1cbi8qKlxuICogR2V0cyBhbiBldmVudCdzIHgsIHkgY29vcmRpbmF0ZXMsIHJlbGF0aXZlIHRvIHRoZSBjaGFydCBhcmVhXG4gKiBAcGFyYW0gZXZlbnRcbiAqIEBwYXJhbSBjaGFydFxuICogQHJldHVybnMgeCBhbmQgeSBjb29yZGluYXRlcyBvZiB0aGUgZXZlbnRcbiAqLyBmdW5jdGlvbiBnZXRSZWxhdGl2ZVBvc2l0aW9uKGV2ZW50LCBjaGFydCkge1xuICAgIGlmICgnbmF0aXZlJyBpbiBldmVudCkge1xuICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgfVxuICAgIGNvbnN0IHsgY2FudmFzICwgY3VycmVudERldmljZVBpeGVsUmF0aW8gIH0gPSBjaGFydDtcbiAgICBjb25zdCBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUoY2FudmFzKTtcbiAgICBjb25zdCBib3JkZXJCb3ggPSBzdHlsZS5ib3hTaXppbmcgPT09ICdib3JkZXItYm94JztcbiAgICBjb25zdCBwYWRkaW5ncyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ3BhZGRpbmcnKTtcbiAgICBjb25zdCBib3JkZXJzID0gZ2V0UG9zaXRpb25lZFN0eWxlKHN0eWxlLCAnYm9yZGVyJywgJ3dpZHRoJyk7XG4gICAgY29uc3QgeyB4ICwgeSAsIGJveCAgfSA9IGdldENhbnZhc1Bvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgIGNvbnN0IHhPZmZzZXQgPSBwYWRkaW5ncy5sZWZ0ICsgKGJveCAmJiBib3JkZXJzLmxlZnQpO1xuICAgIGNvbnN0IHlPZmZzZXQgPSBwYWRkaW5ncy50b3AgKyAoYm94ICYmIGJvcmRlcnMudG9wKTtcbiAgICBsZXQgeyB3aWR0aCAsIGhlaWdodCAgfSA9IGNoYXJ0O1xuICAgIGlmIChib3JkZXJCb3gpIHtcbiAgICAgICAgd2lkdGggLT0gcGFkZGluZ3Mud2lkdGggKyBib3JkZXJzLndpZHRoO1xuICAgICAgICBoZWlnaHQgLT0gcGFkZGluZ3MuaGVpZ2h0ICsgYm9yZGVycy5oZWlnaHQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHg6IE1hdGgucm91bmQoKHggLSB4T2Zmc2V0KSAvIHdpZHRoICogY2FudmFzLndpZHRoIC8gY3VycmVudERldmljZVBpeGVsUmF0aW8pLFxuICAgICAgICB5OiBNYXRoLnJvdW5kKCh5IC0geU9mZnNldCkgLyBoZWlnaHQgKiBjYW52YXMuaGVpZ2h0IC8gY3VycmVudERldmljZVBpeGVsUmF0aW8pXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldENvbnRhaW5lclNpemUoY2FudmFzLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgbGV0IG1heFdpZHRoLCBtYXhIZWlnaHQ7XG4gICAgaWYgKHdpZHRoID09PSB1bmRlZmluZWQgfHwgaGVpZ2h0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gX2dldFBhcmVudE5vZGUoY2FudmFzKTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgIHdpZHRoID0gY2FudmFzLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gY2FudmFzLmNsaWVudEhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IC8vIHRoaXMgaXMgdGhlIGJvcmRlciBib3ggb2YgdGhlIGNvbnRhaW5lclxuICAgICAgICAgICAgY29uc3QgY29udGFpbmVyU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNvbnRhaW5lcik7XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXJCb3JkZXIgPSBnZXRQb3NpdGlvbmVkU3R5bGUoY29udGFpbmVyU3R5bGUsICdib3JkZXInLCAnd2lkdGgnKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lclBhZGRpbmcgPSBnZXRQb3NpdGlvbmVkU3R5bGUoY29udGFpbmVyU3R5bGUsICdwYWRkaW5nJyk7XG4gICAgICAgICAgICB3aWR0aCA9IHJlY3Qud2lkdGggLSBjb250YWluZXJQYWRkaW5nLndpZHRoIC0gY29udGFpbmVyQm9yZGVyLndpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gcmVjdC5oZWlnaHQgLSBjb250YWluZXJQYWRkaW5nLmhlaWdodCAtIGNvbnRhaW5lckJvcmRlci5oZWlnaHQ7XG4gICAgICAgICAgICBtYXhXaWR0aCA9IHBhcnNlTWF4U3R5bGUoY29udGFpbmVyU3R5bGUubWF4V2lkdGgsIGNvbnRhaW5lciwgJ2NsaWVudFdpZHRoJyk7XG4gICAgICAgICAgICBtYXhIZWlnaHQgPSBwYXJzZU1heFN0eWxlKGNvbnRhaW5lclN0eWxlLm1heEhlaWdodCwgY29udGFpbmVyLCAnY2xpZW50SGVpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodCxcbiAgICAgICAgbWF4V2lkdGg6IG1heFdpZHRoIHx8IElORklOSVRZLFxuICAgICAgICBtYXhIZWlnaHQ6IG1heEhlaWdodCB8fCBJTkZJTklUWVxuICAgIH07XG59XG5jb25zdCByb3VuZDEgPSAodik9Pk1hdGgucm91bmQodiAqIDEwKSAvIDEwO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIGdldE1heGltdW1TaXplKGNhbnZhcywgYmJXaWR0aCwgYmJIZWlnaHQsIGFzcGVjdFJhdGlvKSB7XG4gICAgY29uc3Qgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNhbnZhcyk7XG4gICAgY29uc3QgbWFyZ2lucyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ21hcmdpbicpO1xuICAgIGNvbnN0IG1heFdpZHRoID0gcGFyc2VNYXhTdHlsZShzdHlsZS5tYXhXaWR0aCwgY2FudmFzLCAnY2xpZW50V2lkdGgnKSB8fCBJTkZJTklUWTtcbiAgICBjb25zdCBtYXhIZWlnaHQgPSBwYXJzZU1heFN0eWxlKHN0eWxlLm1heEhlaWdodCwgY2FudmFzLCAnY2xpZW50SGVpZ2h0JykgfHwgSU5GSU5JVFk7XG4gICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IGdldENvbnRhaW5lclNpemUoY2FudmFzLCBiYldpZHRoLCBiYkhlaWdodCk7XG4gICAgbGV0IHsgd2lkdGggLCBoZWlnaHQgIH0gPSBjb250YWluZXJTaXplO1xuICAgIGlmIChzdHlsZS5ib3hTaXppbmcgPT09ICdjb250ZW50LWJveCcpIHtcbiAgICAgICAgY29uc3QgYm9yZGVycyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ2JvcmRlcicsICd3aWR0aCcpO1xuICAgICAgICBjb25zdCBwYWRkaW5ncyA9IGdldFBvc2l0aW9uZWRTdHlsZShzdHlsZSwgJ3BhZGRpbmcnKTtcbiAgICAgICAgd2lkdGggLT0gcGFkZGluZ3Mud2lkdGggKyBib3JkZXJzLndpZHRoO1xuICAgICAgICBoZWlnaHQgLT0gcGFkZGluZ3MuaGVpZ2h0ICsgYm9yZGVycy5oZWlnaHQ7XG4gICAgfVxuICAgIHdpZHRoID0gTWF0aC5tYXgoMCwgd2lkdGggLSBtYXJnaW5zLndpZHRoKTtcbiAgICBoZWlnaHQgPSBNYXRoLm1heCgwLCBhc3BlY3RSYXRpbyA/IHdpZHRoIC8gYXNwZWN0UmF0aW8gOiBoZWlnaHQgLSBtYXJnaW5zLmhlaWdodCk7XG4gICAgd2lkdGggPSByb3VuZDEoTWF0aC5taW4od2lkdGgsIG1heFdpZHRoLCBjb250YWluZXJTaXplLm1heFdpZHRoKSk7XG4gICAgaGVpZ2h0ID0gcm91bmQxKE1hdGgubWluKGhlaWdodCwgbWF4SGVpZ2h0LCBjb250YWluZXJTaXplLm1heEhlaWdodCkpO1xuICAgIGlmICh3aWR0aCAmJiAhaGVpZ2h0KSB7XG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL0NoYXJ0LmpzL2lzc3Vlcy80NjU5XG4gICAgICAgIC8vIElmIHRoZSBjYW52YXMgaGFzIHdpZHRoLCBidXQgbm8gaGVpZ2h0LCBkZWZhdWx0IHRvIGFzcGVjdFJhdGlvIG9mIDIgKGNhbnZhcyBkZWZhdWx0KVxuICAgICAgICBoZWlnaHQgPSByb3VuZDEod2lkdGggLyAyKTtcbiAgICB9XG4gICAgY29uc3QgbWFpbnRhaW5IZWlnaHQgPSBiYldpZHRoICE9PSB1bmRlZmluZWQgfHwgYmJIZWlnaHQgIT09IHVuZGVmaW5lZDtcbiAgICBpZiAobWFpbnRhaW5IZWlnaHQgJiYgYXNwZWN0UmF0aW8gJiYgY29udGFpbmVyU2l6ZS5oZWlnaHQgJiYgaGVpZ2h0ID4gY29udGFpbmVyU2l6ZS5oZWlnaHQpIHtcbiAgICAgICAgaGVpZ2h0ID0gY29udGFpbmVyU2l6ZS5oZWlnaHQ7XG4gICAgICAgIHdpZHRoID0gcm91bmQxKE1hdGguZmxvb3IoaGVpZ2h0ICogYXNwZWN0UmF0aW8pKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodFxuICAgIH07XG59XG4vKipcbiAqIEBwYXJhbSBjaGFydFxuICogQHBhcmFtIGZvcmNlUmF0aW9cbiAqIEBwYXJhbSBmb3JjZVN0eWxlXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBjYW52YXMgY29udGV4dCBzaXplIG9yIHRyYW5zZm9ybWF0aW9uIGhhcyBjaGFuZ2VkLlxuICovIGZ1bmN0aW9uIHJldGluYVNjYWxlKGNoYXJ0LCBmb3JjZVJhdGlvLCBmb3JjZVN0eWxlKSB7XG4gICAgY29uc3QgcGl4ZWxSYXRpbyA9IGZvcmNlUmF0aW8gfHwgMTtcbiAgICBjb25zdCBkZXZpY2VIZWlnaHQgPSBNYXRoLmZsb29yKGNoYXJ0LmhlaWdodCAqIHBpeGVsUmF0aW8pO1xuICAgIGNvbnN0IGRldmljZVdpZHRoID0gTWF0aC5mbG9vcihjaGFydC53aWR0aCAqIHBpeGVsUmF0aW8pO1xuICAgIGNoYXJ0LmhlaWdodCA9IE1hdGguZmxvb3IoY2hhcnQuaGVpZ2h0KTtcbiAgICBjaGFydC53aWR0aCA9IE1hdGguZmxvb3IoY2hhcnQud2lkdGgpO1xuICAgIGNvbnN0IGNhbnZhcyA9IGNoYXJ0LmNhbnZhcztcbiAgICAvLyBJZiBubyBzdHlsZSBoYXMgYmVlbiBzZXQgb24gdGhlIGNhbnZhcywgdGhlIHJlbmRlciBzaXplIGlzIHVzZWQgYXMgZGlzcGxheSBzaXplLFxuICAgIC8vIG1ha2luZyB0aGUgY2hhcnQgdmlzdWFsbHkgYmlnZ2VyLCBzbyBsZXQncyBlbmZvcmNlIGl0IHRvIHRoZSBcImNvcnJlY3RcIiB2YWx1ZXMuXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFydGpzL0NoYXJ0LmpzL2lzc3Vlcy8zNTc1XG4gICAgaWYgKGNhbnZhcy5zdHlsZSAmJiAoZm9yY2VTdHlsZSB8fCAhY2FudmFzLnN0eWxlLmhlaWdodCAmJiAhY2FudmFzLnN0eWxlLndpZHRoKSkge1xuICAgICAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7Y2hhcnQuaGVpZ2h0fXB4YDtcbiAgICAgICAgY2FudmFzLnN0eWxlLndpZHRoID0gYCR7Y2hhcnQud2lkdGh9cHhgO1xuICAgIH1cbiAgICBpZiAoY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gIT09IHBpeGVsUmF0aW8gfHwgY2FudmFzLmhlaWdodCAhPT0gZGV2aWNlSGVpZ2h0IHx8IGNhbnZhcy53aWR0aCAhPT0gZGV2aWNlV2lkdGgpIHtcbiAgICAgICAgY2hhcnQuY3VycmVudERldmljZVBpeGVsUmF0aW8gPSBwaXhlbFJhdGlvO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gZGV2aWNlSGVpZ2h0O1xuICAgICAgICBjYW52YXMud2lkdGggPSBkZXZpY2VXaWR0aDtcbiAgICAgICAgY2hhcnQuY3R4LnNldFRyYW5zZm9ybShwaXhlbFJhdGlvLCAwLCAwLCBwaXhlbFJhdGlvLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogRGV0ZWN0cyBzdXBwb3J0IGZvciBvcHRpb25zIG9iamVjdCBhcmd1bWVudCBpbiBhZGRFdmVudExpc3RlbmVyLlxuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIjU2FmZWx5X2RldGVjdGluZ19vcHRpb25fc3VwcG9ydFxuICogQHByaXZhdGVcbiAqLyBjb25zdCBzdXBwb3J0c0V2ZW50TGlzdGVuZXJPcHRpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgbGV0IHBhc3NpdmVTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgZ2V0IHBhc3NpdmUgKCkge1xuICAgICAgICAgICAgICAgIHBhc3NpdmVTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBvcHRpb25zKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBvcHRpb25zKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgLy8gY29udGludWUgcmVnYXJkbGVzcyBvZiBlcnJvclxuICAgIH1cbiAgICByZXR1cm4gcGFzc2l2ZVN1cHBvcnRlZDtcbn0oKTtcbi8qKlxuICogVGhlIFwidXNlZFwiIHNpemUgaXMgdGhlIGZpbmFsIHZhbHVlIG9mIGEgZGltZW5zaW9uIHByb3BlcnR5IGFmdGVyIGFsbCBjYWxjdWxhdGlvbnMgaGF2ZVxuICogYmVlbiBwZXJmb3JtZWQuIFRoaXMgbWV0aG9kIHVzZXMgdGhlIGNvbXB1dGVkIHN0eWxlIG9mIGBlbGVtZW50YCBidXQgcmV0dXJucyB1bmRlZmluZWRcbiAqIGlmIHRoZSBjb21wdXRlZCBzdHlsZSBpcyBub3QgZXhwcmVzc2VkIGluIHBpeGVscy4gVGhhdCBjYW4gaGFwcGVuIGluIHNvbWUgY2FzZXMgd2hlcmVcbiAqIGBlbGVtZW50YCBoYXMgYSBzaXplIHJlbGF0aXZlIHRvIGl0cyBwYXJlbnQgYW5kIHRoaXMgbGFzdCBvbmUgaXMgbm90IHlldCBkaXNwbGF5ZWQsXG4gKiBmb3IgZXhhbXBsZSBiZWNhdXNlIG9mIGBkaXNwbGF5OiBub25lYCBvbiBhIHBhcmVudCBub2RlLlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1MvdXNlZF92YWx1ZVxuICogQHJldHVybnMgU2l6ZSBpbiBwaXhlbHMgb3IgdW5kZWZpbmVkIGlmIHVua25vd24uXG4gKi8gZnVuY3Rpb24gcmVhZFVzZWRTaXplKGVsZW1lbnQsIHByb3BlcnR5KSB7XG4gICAgY29uc3QgdmFsdWUgPSBnZXRTdHlsZShlbGVtZW50LCBwcm9wZXJ0eSk7XG4gICAgY29uc3QgbWF0Y2hlcyA9IHZhbHVlICYmIHZhbHVlLm1hdGNoKC9eKFxcZCspKFxcLlxcZCspP3B4JC8pO1xuICAgIHJldHVybiBtYXRjaGVzID8gK21hdGNoZXNbMV0gOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfcG9pbnRJbkxpbmUocDEsIHAyLCB0LCBtb2RlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogcDEueCArIHQgKiAocDIueCAtIHAxLngpLFxuICAgICAgICB5OiBwMS55ICsgdCAqIChwMi55IC0gcDEueSlcbiAgICB9O1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICovIGZ1bmN0aW9uIF9zdGVwcGVkSW50ZXJwb2xhdGlvbihwMSwgcDIsIHQsIG1vZGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBwMS54ICsgdCAqIChwMi54IC0gcDEueCksXG4gICAgICAgIHk6IG1vZGUgPT09ICdtaWRkbGUnID8gdCA8IDAuNSA/IHAxLnkgOiBwMi55IDogbW9kZSA9PT0gJ2FmdGVyJyA/IHQgPCAxID8gcDEueSA6IHAyLnkgOiB0ID4gMCA/IHAyLnkgOiBwMS55XG4gICAgfTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqLyBmdW5jdGlvbiBfYmV6aWVySW50ZXJwb2xhdGlvbihwMSwgcDIsIHQsIG1vZGUpIHtcbiAgICBjb25zdCBjcDEgPSB7XG4gICAgICAgIHg6IHAxLmNwMngsXG4gICAgICAgIHk6IHAxLmNwMnlcbiAgICB9O1xuICAgIGNvbnN0IGNwMiA9IHtcbiAgICAgICAgeDogcDIuY3AxeCxcbiAgICAgICAgeTogcDIuY3AxeVxuICAgIH07XG4gICAgY29uc3QgYSA9IF9wb2ludEluTGluZShwMSwgY3AxLCB0KTtcbiAgICBjb25zdCBiID0gX3BvaW50SW5MaW5lKGNwMSwgY3AyLCB0KTtcbiAgICBjb25zdCBjID0gX3BvaW50SW5MaW5lKGNwMiwgcDIsIHQpO1xuICAgIGNvbnN0IGQgPSBfcG9pbnRJbkxpbmUoYSwgYiwgdCk7XG4gICAgY29uc3QgZSA9IF9wb2ludEluTGluZShiLCBjLCB0KTtcbiAgICByZXR1cm4gX3BvaW50SW5MaW5lKGQsIGUsIHQpO1xufVxuXG5jb25zdCBnZXRSaWdodFRvTGVmdEFkYXB0ZXIgPSBmdW5jdGlvbihyZWN0WCwgd2lkdGgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4ICh4KSB7XG4gICAgICAgICAgICByZXR1cm4gcmVjdFggKyByZWN0WCArIHdpZHRoIC0geDtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0V2lkdGggKHcpIHtcbiAgICAgICAgICAgIHdpZHRoID0gdztcbiAgICAgICAgfSxcbiAgICAgICAgdGV4dEFsaWduIChhbGlnbikge1xuICAgICAgICAgICAgaWYgKGFsaWduID09PSAnY2VudGVyJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBhbGlnbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhbGlnbiA9PT0gJ3JpZ2h0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgICAgIH0sXG4gICAgICAgIHhQbHVzICh4LCB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHggLSB2YWx1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgbGVmdEZvckx0ciAoeCwgaXRlbVdpZHRoKSB7XG4gICAgICAgICAgICByZXR1cm4geCAtIGl0ZW1XaWR0aDtcbiAgICAgICAgfVxuICAgIH07XG59O1xuY29uc3QgZ2V0TGVmdFRvUmlnaHRBZGFwdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeCAoeCkge1xuICAgICAgICAgICAgcmV0dXJuIHg7XG4gICAgICAgIH0sXG4gICAgICAgIHNldFdpZHRoICh3KSB7fSxcbiAgICAgICAgdGV4dEFsaWduIChhbGlnbikge1xuICAgICAgICAgICAgcmV0dXJuIGFsaWduO1xuICAgICAgICB9LFxuICAgICAgICB4UGx1cyAoeCwgdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiB4ICsgdmFsdWU7XG4gICAgICAgIH0sXG4gICAgICAgIGxlZnRGb3JMdHIgKHgsIF9pdGVtV2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICB9XG4gICAgfTtcbn07XG5mdW5jdGlvbiBnZXRSdGxBZGFwdGVyKHJ0bCwgcmVjdFgsIHdpZHRoKSB7XG4gICAgcmV0dXJuIHJ0bCA/IGdldFJpZ2h0VG9MZWZ0QWRhcHRlcihyZWN0WCwgd2lkdGgpIDogZ2V0TGVmdFRvUmlnaHRBZGFwdGVyKCk7XG59XG5mdW5jdGlvbiBvdmVycmlkZVRleHREaXJlY3Rpb24oY3R4LCBkaXJlY3Rpb24pIHtcbiAgICBsZXQgc3R5bGUsIG9yaWdpbmFsO1xuICAgIGlmIChkaXJlY3Rpb24gPT09ICdsdHInIHx8IGRpcmVjdGlvbiA9PT0gJ3J0bCcpIHtcbiAgICAgICAgc3R5bGUgPSBjdHguY2FudmFzLnN0eWxlO1xuICAgICAgICBvcmlnaW5hbCA9IFtcbiAgICAgICAgICAgIHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2RpcmVjdGlvbicpLFxuICAgICAgICAgICAgc3R5bGUuZ2V0UHJvcGVydHlQcmlvcml0eSgnZGlyZWN0aW9uJylcbiAgICAgICAgXTtcbiAgICAgICAgc3R5bGUuc2V0UHJvcGVydHkoJ2RpcmVjdGlvbicsIGRpcmVjdGlvbiwgJ2ltcG9ydGFudCcpO1xuICAgICAgICBjdHgucHJldlRleHREaXJlY3Rpb24gPSBvcmlnaW5hbDtcbiAgICB9XG59XG5mdW5jdGlvbiByZXN0b3JlVGV4dERpcmVjdGlvbihjdHgsIG9yaWdpbmFsKSB7XG4gICAgaWYgKG9yaWdpbmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZGVsZXRlIGN0eC5wcmV2VGV4dERpcmVjdGlvbjtcbiAgICAgICAgY3R4LmNhbnZhcy5zdHlsZS5zZXRQcm9wZXJ0eSgnZGlyZWN0aW9uJywgb3JpZ2luYWxbMF0sIG9yaWdpbmFsWzFdKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHByb3BlcnR5Rm4ocHJvcGVydHkpIHtcbiAgICBpZiAocHJvcGVydHkgPT09ICdhbmdsZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJldHdlZW46IF9hbmdsZUJldHdlZW4sXG4gICAgICAgICAgICBjb21wYXJlOiBfYW5nbGVEaWZmLFxuICAgICAgICAgICAgbm9ybWFsaXplOiBfbm9ybWFsaXplQW5nbGVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYmV0d2VlbjogX2lzQmV0d2VlbixcbiAgICAgICAgY29tcGFyZTogKGEsIGIpPT5hIC0gYixcbiAgICAgICAgbm9ybWFsaXplOiAoeCk9PnhcbiAgICB9O1xufVxuZnVuY3Rpb24gbm9ybWFsaXplU2VnbWVudCh7IHN0YXJ0ICwgZW5kICwgY291bnQgLCBsb29wICwgc3R5bGUgIH0pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogc3RhcnQgJSBjb3VudCxcbiAgICAgICAgZW5kOiBlbmQgJSBjb3VudCxcbiAgICAgICAgbG9vcDogbG9vcCAmJiAoZW5kIC0gc3RhcnQgKyAxKSAlIGNvdW50ID09PSAwLFxuICAgICAgICBzdHlsZVxuICAgIH07XG59XG5mdW5jdGlvbiBnZXRTZWdtZW50KHNlZ21lbnQsIHBvaW50cywgYm91bmRzKSB7XG4gICAgY29uc3QgeyBwcm9wZXJ0eSAsIHN0YXJ0OiBzdGFydEJvdW5kICwgZW5kOiBlbmRCb3VuZCAgfSA9IGJvdW5kcztcbiAgICBjb25zdCB7IGJldHdlZW4gLCBub3JtYWxpemUgIH0gPSBwcm9wZXJ0eUZuKHByb3BlcnR5KTtcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgbGV0IHsgc3RhcnQgLCBlbmQgLCBsb29wICB9ID0gc2VnbWVudDtcbiAgICBsZXQgaSwgaWxlbjtcbiAgICBpZiAobG9vcCkge1xuICAgICAgICBzdGFydCArPSBjb3VudDtcbiAgICAgICAgZW5kICs9IGNvdW50O1xuICAgICAgICBmb3IoaSA9IDAsIGlsZW4gPSBjb3VudDsgaSA8IGlsZW47ICsraSl7XG4gICAgICAgICAgICBpZiAoIWJldHdlZW4obm9ybWFsaXplKHBvaW50c1tzdGFydCAlIGNvdW50XVtwcm9wZXJ0eV0pLCBzdGFydEJvdW5kLCBlbmRCb3VuZCkpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YXJ0LS07XG4gICAgICAgICAgICBlbmQtLTtcbiAgICAgICAgfVxuICAgICAgICBzdGFydCAlPSBjb3VudDtcbiAgICAgICAgZW5kICU9IGNvdW50O1xuICAgIH1cbiAgICBpZiAoZW5kIDwgc3RhcnQpIHtcbiAgICAgICAgZW5kICs9IGNvdW50O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydCxcbiAgICAgICAgZW5kLFxuICAgICAgICBsb29wLFxuICAgICAgICBzdHlsZTogc2VnbWVudC5zdHlsZVxuICAgIH07XG59XG4gZnVuY3Rpb24gX2JvdW5kU2VnbWVudChzZWdtZW50LCBwb2ludHMsIGJvdW5kcykge1xuICAgIGlmICghYm91bmRzKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBzZWdtZW50XG4gICAgICAgIF07XG4gICAgfVxuICAgIGNvbnN0IHsgcHJvcGVydHkgLCBzdGFydDogc3RhcnRCb3VuZCAsIGVuZDogZW5kQm91bmQgIH0gPSBib3VuZHM7XG4gICAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIGNvbnN0IHsgY29tcGFyZSAsIGJldHdlZW4gLCBub3JtYWxpemUgIH0gPSBwcm9wZXJ0eUZuKHByb3BlcnR5KTtcbiAgICBjb25zdCB7IHN0YXJ0ICwgZW5kICwgbG9vcCAsIHN0eWxlICB9ID0gZ2V0U2VnbWVudChzZWdtZW50LCBwb2ludHMsIGJvdW5kcyk7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgbGV0IGluc2lkZSA9IGZhbHNlO1xuICAgIGxldCBzdWJTdGFydCA9IG51bGw7XG4gICAgbGV0IHZhbHVlLCBwb2ludCwgcHJldlZhbHVlO1xuICAgIGNvbnN0IHN0YXJ0SXNCZWZvcmUgPSAoKT0+YmV0d2VlbihzdGFydEJvdW5kLCBwcmV2VmFsdWUsIHZhbHVlKSAmJiBjb21wYXJlKHN0YXJ0Qm91bmQsIHByZXZWYWx1ZSkgIT09IDA7XG4gICAgY29uc3QgZW5kSXNCZWZvcmUgPSAoKT0+Y29tcGFyZShlbmRCb3VuZCwgdmFsdWUpID09PSAwIHx8IGJldHdlZW4oZW5kQm91bmQsIHByZXZWYWx1ZSwgdmFsdWUpO1xuICAgIGNvbnN0IHNob3VsZFN0YXJ0ID0gKCk9Pmluc2lkZSB8fCBzdGFydElzQmVmb3JlKCk7XG4gICAgY29uc3Qgc2hvdWxkU3RvcCA9ICgpPT4haW5zaWRlIHx8IGVuZElzQmVmb3JlKCk7XG4gICAgZm9yKGxldCBpID0gc3RhcnQsIHByZXYgPSBzdGFydDsgaSA8PSBlbmQ7ICsraSl7XG4gICAgICAgIHBvaW50ID0gcG9pbnRzW2kgJSBjb3VudF07XG4gICAgICAgIGlmIChwb2ludC5za2lwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9IG5vcm1hbGl6ZShwb2ludFtwcm9wZXJ0eV0pO1xuICAgICAgICBpZiAodmFsdWUgPT09IHByZXZWYWx1ZSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5zaWRlID0gYmV0d2Vlbih2YWx1ZSwgc3RhcnRCb3VuZCwgZW5kQm91bmQpO1xuICAgICAgICBpZiAoc3ViU3RhcnQgPT09IG51bGwgJiYgc2hvdWxkU3RhcnQoKSkge1xuICAgICAgICAgICAgc3ViU3RhcnQgPSBjb21wYXJlKHZhbHVlLCBzdGFydEJvdW5kKSA9PT0gMCA/IGkgOiBwcmV2O1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdWJTdGFydCAhPT0gbnVsbCAmJiBzaG91bGRTdG9wKCkpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5vcm1hbGl6ZVNlZ21lbnQoe1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBzdWJTdGFydCxcbiAgICAgICAgICAgICAgICBlbmQ6IGksXG4gICAgICAgICAgICAgICAgbG9vcCxcbiAgICAgICAgICAgICAgICBjb3VudCxcbiAgICAgICAgICAgICAgICBzdHlsZVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgc3ViU3RhcnQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHByZXYgPSBpO1xuICAgICAgICBwcmV2VmFsdWUgPSB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKHN1YlN0YXJ0ICE9PSBudWxsKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKG5vcm1hbGl6ZVNlZ21lbnQoe1xuICAgICAgICAgICAgc3RhcnQ6IHN1YlN0YXJ0LFxuICAgICAgICAgICAgZW5kLFxuICAgICAgICAgICAgbG9vcCxcbiAgICAgICAgICAgIGNvdW50LFxuICAgICAgICAgICAgc3R5bGVcbiAgICAgICAgfSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIGZ1bmN0aW9uIF9ib3VuZFNlZ21lbnRzKGxpbmUsIGJvdW5kcykge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IHNlZ21lbnRzID0gbGluZS5zZWdtZW50cztcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspe1xuICAgICAgICBjb25zdCBzdWIgPSBfYm91bmRTZWdtZW50KHNlZ21lbnRzW2ldLCBsaW5lLnBvaW50cywgYm91bmRzKTtcbiAgICAgICAgaWYgKHN1Yi5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKC4uLnN1Yik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbiBmdW5jdGlvbiBmaW5kU3RhcnRBbmRFbmQocG9pbnRzLCBjb3VudCwgbG9vcCwgc3BhbkdhcHMpIHtcbiAgICBsZXQgc3RhcnQgPSAwO1xuICAgIGxldCBlbmQgPSBjb3VudCAtIDE7XG4gICAgaWYgKGxvb3AgJiYgIXNwYW5HYXBzKSB7XG4gICAgICAgIHdoaWxlKHN0YXJ0IDwgY291bnQgJiYgIXBvaW50c1tzdGFydF0uc2tpcCl7XG4gICAgICAgICAgICBzdGFydCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHdoaWxlKHN0YXJ0IDwgY291bnQgJiYgcG9pbnRzW3N0YXJ0XS5za2lwKXtcbiAgICAgICAgc3RhcnQrKztcbiAgICB9XG4gICAgc3RhcnQgJT0gY291bnQ7XG4gICAgaWYgKGxvb3ApIHtcbiAgICAgICAgZW5kICs9IHN0YXJ0O1xuICAgIH1cbiAgICB3aGlsZShlbmQgPiBzdGFydCAmJiBwb2ludHNbZW5kICUgY291bnRdLnNraXApe1xuICAgICAgICBlbmQtLTtcbiAgICB9XG4gICAgZW5kICU9IGNvdW50O1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBlbmRcbiAgICB9O1xufVxuIGZ1bmN0aW9uIHNvbGlkU2VnbWVudHMocG9pbnRzLCBzdGFydCwgbWF4LCBsb29wKSB7XG4gICAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBsYXN0ID0gc3RhcnQ7XG4gICAgbGV0IHByZXYgPSBwb2ludHNbc3RhcnRdO1xuICAgIGxldCBlbmQ7XG4gICAgZm9yKGVuZCA9IHN0YXJ0ICsgMTsgZW5kIDw9IG1heDsgKytlbmQpe1xuICAgICAgICBjb25zdCBjdXIgPSBwb2ludHNbZW5kICUgY291bnRdO1xuICAgICAgICBpZiAoY3VyLnNraXAgfHwgY3VyLnN0b3ApIHtcbiAgICAgICAgICAgIGlmICghcHJldi5za2lwKSB7XG4gICAgICAgICAgICAgICAgbG9vcCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHN0YXJ0ICUgY291bnQsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogKGVuZCAtIDEpICUgY291bnQsXG4gICAgICAgICAgICAgICAgICAgIGxvb3BcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzdGFydCA9IGxhc3QgPSBjdXIuc3RvcCA/IGVuZCA6IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsYXN0ID0gZW5kO1xuICAgICAgICAgICAgaWYgKHByZXYuc2tpcCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHByZXYgPSBjdXI7XG4gICAgfVxuICAgIGlmIChsYXN0ICE9PSBudWxsKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydCAlIGNvdW50LFxuICAgICAgICAgICAgZW5kOiBsYXN0ICUgY291bnQsXG4gICAgICAgICAgICBsb29wXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIGZ1bmN0aW9uIF9jb21wdXRlU2VnbWVudHMobGluZSwgc2VnbWVudE9wdGlvbnMpIHtcbiAgICBjb25zdCBwb2ludHMgPSBsaW5lLnBvaW50cztcbiAgICBjb25zdCBzcGFuR2FwcyA9IGxpbmUub3B0aW9ucy5zcGFuR2FwcztcbiAgICBjb25zdCBjb3VudCA9IHBvaW50cy5sZW5ndGg7XG4gICAgaWYgKCFjb3VudCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IGxvb3AgPSAhIWxpbmUuX2xvb3A7XG4gICAgY29uc3QgeyBzdGFydCAsIGVuZCAgfSA9IGZpbmRTdGFydEFuZEVuZChwb2ludHMsIGNvdW50LCBsb29wLCBzcGFuR2Fwcyk7XG4gICAgaWYgKHNwYW5HYXBzID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiBzcGxpdEJ5U3R5bGVzKGxpbmUsIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzdGFydCxcbiAgICAgICAgICAgICAgICBlbmQsXG4gICAgICAgICAgICAgICAgbG9vcFxuICAgICAgICAgICAgfVxuICAgICAgICBdLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKTtcbiAgICB9XG4gICAgY29uc3QgbWF4ID0gZW5kIDwgc3RhcnQgPyBlbmQgKyBjb3VudCA6IGVuZDtcbiAgICBjb25zdCBjb21wbGV0ZUxvb3AgPSAhIWxpbmUuX2Z1bGxMb29wICYmIHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gY291bnQgLSAxO1xuICAgIHJldHVybiBzcGxpdEJ5U3R5bGVzKGxpbmUsIHNvbGlkU2VnbWVudHMocG9pbnRzLCBzdGFydCwgbWF4LCBjb21wbGV0ZUxvb3ApLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKTtcbn1cbiBmdW5jdGlvbiBzcGxpdEJ5U3R5bGVzKGxpbmUsIHNlZ21lbnRzLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKSB7XG4gICAgaWYgKCFzZWdtZW50T3B0aW9ucyB8fCAhc2VnbWVudE9wdGlvbnMuc2V0Q29udGV4dCB8fCAhcG9pbnRzKSB7XG4gICAgICAgIHJldHVybiBzZWdtZW50cztcbiAgICB9XG4gICAgcmV0dXJuIGRvU3BsaXRCeVN0eWxlcyhsaW5lLCBzZWdtZW50cywgcG9pbnRzLCBzZWdtZW50T3B0aW9ucyk7XG59XG4gZnVuY3Rpb24gZG9TcGxpdEJ5U3R5bGVzKGxpbmUsIHNlZ21lbnRzLCBwb2ludHMsIHNlZ21lbnRPcHRpb25zKSB7XG4gICAgY29uc3QgY2hhcnRDb250ZXh0ID0gbGluZS5fY2hhcnQuZ2V0Q29udGV4dCgpO1xuICAgIGNvbnN0IGJhc2VTdHlsZSA9IHJlYWRTdHlsZShsaW5lLm9wdGlvbnMpO1xuICAgIGNvbnN0IHsgX2RhdGFzZXRJbmRleDogZGF0YXNldEluZGV4ICwgb3B0aW9uczogeyBzcGFuR2FwcyAgfSAgfSA9IGxpbmU7XG4gICAgY29uc3QgY291bnQgPSBwb2ludHMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBwcmV2U3R5bGUgPSBiYXNlU3R5bGU7XG4gICAgbGV0IHN0YXJ0ID0gc2VnbWVudHNbMF0uc3RhcnQ7XG4gICAgbGV0IGkgPSBzdGFydDtcbiAgICBmdW5jdGlvbiBhZGRTdHlsZShzLCBlLCBsLCBzdCkge1xuICAgICAgICBjb25zdCBkaXIgPSBzcGFuR2FwcyA/IC0xIDogMTtcbiAgICAgICAgaWYgKHMgPT09IGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzICs9IGNvdW50O1xuICAgICAgICB3aGlsZShwb2ludHNbcyAlIGNvdW50XS5za2lwKXtcbiAgICAgICAgICAgIHMgLT0gZGlyO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlKHBvaW50c1tlICUgY291bnRdLnNraXApe1xuICAgICAgICAgICAgZSArPSBkaXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMgJSBjb3VudCAhPT0gZSAlIGNvdW50KSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IHMgJSBjb3VudCxcbiAgICAgICAgICAgICAgICBlbmQ6IGUgJSBjb3VudCxcbiAgICAgICAgICAgICAgICBsb29wOiBsLFxuICAgICAgICAgICAgICAgIHN0eWxlOiBzdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcmV2U3R5bGUgPSBzdDtcbiAgICAgICAgICAgIHN0YXJ0ID0gZSAlIGNvdW50O1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzZWdtZW50cyl7XG4gICAgICAgIHN0YXJ0ID0gc3BhbkdhcHMgPyBzdGFydCA6IHNlZ21lbnQuc3RhcnQ7XG4gICAgICAgIGxldCBwcmV2ID0gcG9pbnRzW3N0YXJ0ICUgY291bnRdO1xuICAgICAgICBsZXQgc3R5bGU7XG4gICAgICAgIGZvcihpID0gc3RhcnQgKyAxOyBpIDw9IHNlZ21lbnQuZW5kOyBpKyspe1xuICAgICAgICAgICAgY29uc3QgcHQgPSBwb2ludHNbaSAlIGNvdW50XTtcbiAgICAgICAgICAgIHN0eWxlID0gcmVhZFN0eWxlKHNlZ21lbnRPcHRpb25zLnNldENvbnRleHQoY3JlYXRlQ29udGV4dChjaGFydENvbnRleHQsIHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnc2VnbWVudCcsXG4gICAgICAgICAgICAgICAgcDA6IHByZXYsXG4gICAgICAgICAgICAgICAgcDE6IHB0LFxuICAgICAgICAgICAgICAgIHAwRGF0YUluZGV4OiAoaSAtIDEpICUgY291bnQsXG4gICAgICAgICAgICAgICAgcDFEYXRhSW5kZXg6IGkgJSBjb3VudCxcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5kZXhcbiAgICAgICAgICAgIH0pKSk7XG4gICAgICAgICAgICBpZiAoc3R5bGVDaGFuZ2VkKHN0eWxlLCBwcmV2U3R5bGUpKSB7XG4gICAgICAgICAgICAgICAgYWRkU3R5bGUoc3RhcnQsIGkgLSAxLCBzZWdtZW50Lmxvb3AsIHByZXZTdHlsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2ID0gcHQ7XG4gICAgICAgICAgICBwcmV2U3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhcnQgPCBpIC0gMSkge1xuICAgICAgICAgICAgYWRkU3R5bGUoc3RhcnQsIGkgLSAxLCBzZWdtZW50Lmxvb3AsIHByZXZTdHlsZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIHJlYWRTdHlsZShvcHRpb25zKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBvcHRpb25zLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgYm9yZGVyQ2FwU3R5bGU6IG9wdGlvbnMuYm9yZGVyQ2FwU3R5bGUsXG4gICAgICAgIGJvcmRlckRhc2g6IG9wdGlvbnMuYm9yZGVyRGFzaCxcbiAgICAgICAgYm9yZGVyRGFzaE9mZnNldDogb3B0aW9ucy5ib3JkZXJEYXNoT2Zmc2V0LFxuICAgICAgICBib3JkZXJKb2luU3R5bGU6IG9wdGlvbnMuYm9yZGVySm9pblN0eWxlLFxuICAgICAgICBib3JkZXJXaWR0aDogb3B0aW9ucy5ib3JkZXJXaWR0aCxcbiAgICAgICAgYm9yZGVyQ29sb3I6IG9wdGlvbnMuYm9yZGVyQ29sb3JcbiAgICB9O1xufVxuZnVuY3Rpb24gc3R5bGVDaGFuZ2VkKHN0eWxlLCBwcmV2U3R5bGUpIHtcbiAgICBpZiAoIXByZXZTdHlsZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGNhY2hlID0gW107XG4gICAgY29uc3QgcmVwbGFjZXIgPSBmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmICghaXNQYXR0ZXJuT3JHcmFkaWVudCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNhY2hlLmluY2x1ZGVzKHZhbHVlKSkge1xuICAgICAgICAgICAgY2FjaGUucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhY2hlLmluZGV4T2YodmFsdWUpO1xuICAgIH07XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHN0eWxlLCByZXBsYWNlcikgIT09IEpTT04uc3RyaW5naWZ5KHByZXZTdHlsZSwgcmVwbGFjZXIpO1xufVxuXG5leHBvcnQgeyB1bmNsaXBBcmVhIGFzICQsIF9ybG9va3VwQnlLZXkgYXMgQSwgX2xvb2t1cEJ5S2V5IGFzIEIsIF9pc1BvaW50SW5BcmVhIGFzIEMsIGdldEFuZ2xlRnJvbVBvaW50IGFzIEQsIHRvUGFkZGluZyBhcyBFLCBlYWNoIGFzIEYsIGdldE1heGltdW1TaXplIGFzIEcsIEhBTEZfUEkgYXMgSCwgX2dldFBhcmVudE5vZGUgYXMgSSwgcmVhZFVzZWRTaXplIGFzIEosIHN1cHBvcnRzRXZlbnRMaXN0ZW5lck9wdGlvbnMgYXMgSywgdGhyb3R0bGVkIGFzIEwsIF9pc0RvbVN1cHBvcnRlZCBhcyBNLCBfZmFjdG9yaXplIGFzIE4sIGZpbml0ZU9yRGVmYXVsdCBhcyBPLCBQSSBhcyBQLCBjYWxsYmFjayBhcyBRLCBfYWRkR3JhY2UgYXMgUiwgX2xpbWl0VmFsdWUgYXMgUywgVEFVIGFzIFQsIHRvRGVncmVlcyBhcyBVLCBfbWVhc3VyZVRleHQgYXMgViwgX2ludDE2UmFuZ2UgYXMgVywgX2FsaWduUGl4ZWwgYXMgWCwgY2xpcEFyZWEgYXMgWSwgcmVuZGVyVGV4dCBhcyBaLCBfYXJyYXlVbmlxdWUgYXMgXywgcmVzb2x2ZSBhcyBhLCBmb250U3RyaW5nIGFzIGEkLCB0b0ZvbnQgYXMgYTAsIF90b0xlZnRSaWdodENlbnRlciBhcyBhMSwgX2FsaWduU3RhcnRFbmQgYXMgYTIsIG92ZXJyaWRlcyBhcyBhMywgbWVyZ2UgYXMgYTQsIF9jYXBpdGFsaXplIGFzIGE1LCBkZXNjcmlwdG9ycyBhcyBhNiwgaXNGdW5jdGlvbiBhcyBhNywgX2F0dGFjaENvbnRleHQgYXMgYTgsIF9jcmVhdGVSZXNvbHZlciBhcyBhOSwgb3ZlcnJpZGVUZXh0RGlyZWN0aW9uIGFzIGFBLCBfdGV4dFggYXMgYUIsIHJlc3RvcmVUZXh0RGlyZWN0aW9uIGFzIGFDLCBkcmF3UG9pbnRMZWdlbmQgYXMgYUQsIGRpc3RhbmNlQmV0d2VlblBvaW50cyBhcyBhRSwgbm9vcCBhcyBhRiwgX3NldE1pbkFuZE1heEJ5S2V5IGFzIGFHLCBuaWNlTnVtIGFzIGFILCBhbG1vc3RXaG9sZSBhcyBhSSwgYWxtb3N0RXF1YWxzIGFzIGFKLCBfZGVjaW1hbFBsYWNlcyBhcyBhSywgVGlja3MgYXMgYUwsIGxvZzEwIGFzIGFNLCBfbG9uZ2VzdFRleHQgYXMgYU4sIF9maWx0ZXJCZXR3ZWVuIGFzIGFPLCBfbG9va3VwIGFzIGFQLCBpc1BhdHRlcm5PckdyYWRpZW50IGFzIGFRLCBnZXRIb3ZlckNvbG9yIGFzIGFSLCBjbG9uZSBhcyBhUywgX21lcmdlciBhcyBhVCwgX21lcmdlcklmIGFzIGFVLCBfZGVwcmVjYXRlZCBhcyBhViwgX3NwbGl0S2V5IGFzIGFXLCB0b0ZvbnRTdHJpbmcgYXMgYVgsIHNwbGluZUN1cnZlIGFzIGFZLCBzcGxpbmVDdXJ2ZU1vbm90b25lIGFzIGFaLCBnZXRTdHlsZSBhcyBhXywgX2Rlc2NyaXB0b3JzIGFzIGFhLCBtZXJnZUlmIGFzIGFiLCB1aWQgYXMgYWMsIGRlYm91bmNlIGFzIGFkLCByZXRpbmFTY2FsZSBhcyBhZSwgY2xlYXJDYW52YXMgYXMgYWYsIHNldHNFcXVhbCBhcyBhZywgX2VsZW1lbnRzRXF1YWwgYXMgYWgsIF9pc0NsaWNrRXZlbnQgYXMgYWksIF9pc0JldHdlZW4gYXMgYWosIF9yZWFkVmFsdWVUb1Byb3BzIGFzIGFrLCBfdXBkYXRlQmV6aWVyQ29udHJvbFBvaW50cyBhcyBhbCwgX2NvbXB1dGVTZWdtZW50cyBhcyBhbSwgX2JvdW5kU2VnbWVudHMgYXMgYW4sIF9zdGVwcGVkSW50ZXJwb2xhdGlvbiBhcyBhbywgX2JlemllckludGVycG9sYXRpb24gYXMgYXAsIF9wb2ludEluTGluZSBhcyBhcSwgX3N0ZXBwZWRMaW5lVG8gYXMgYXIsIF9iZXppZXJDdXJ2ZVRvIGFzIGFzLCBkcmF3UG9pbnQgYXMgYXQsIGFkZFJvdW5kZWRSZWN0UGF0aCBhcyBhdSwgdG9UUkJMIGFzIGF2LCB0b1RSQkxDb3JuZXJzIGFzIGF3LCBfYm91bmRTZWdtZW50IGFzIGF4LCBfbm9ybWFsaXplQW5nbGUgYXMgYXksIGdldFJ0bEFkYXB0ZXIgYXMgYXosIGlzQXJyYXkgYXMgYiwgdG9MaW5lSGVpZ2h0IGFzIGIwLCBQSVRBVSBhcyBiMSwgSU5GSU5JVFkgYXMgYjIsIFJBRF9QRVJfREVHIGFzIGIzLCBRVUFSVEVSX1BJIGFzIGI0LCBUV09fVEhJUkRTX1BJIGFzIGI1LCBfYW5nbGVEaWZmIGFzIGI2LCBjb2xvciBhcyBjLCBkZWZhdWx0cyBhcyBkLCBlZmZlY3RzIGFzIGUsIHJlc29sdmVPYmplY3RLZXkgYXMgZiwgaXNOdW1iZXJGaW5pdGUgYXMgZywgZGVmaW5lZCBhcyBoLCBpc09iamVjdCBhcyBpLCBjcmVhdGVDb250ZXh0IGFzIGosIGlzTnVsbE9yVW5kZWYgYXMgaywgbGlzdGVuQXJyYXlFdmVudHMgYXMgbCwgdG9QZXJjZW50YWdlIGFzIG0sIHRvRGltZW5zaW9uIGFzIG4sIGZvcm1hdE51bWJlciBhcyBvLCBfYW5nbGVCZXR3ZWVuIGFzIHAsIF9nZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzIGFzIHEsIHJlcXVlc3RBbmltRnJhbWUgYXMgciwgc2lnbiBhcyBzLCB0b1JhZGlhbnMgYXMgdCwgdW5saXN0ZW5BcnJheUV2ZW50cyBhcyB1LCB2YWx1ZU9yRGVmYXVsdCBhcyB2LCBfc2NhbGVSYW5nZXNDaGFuZ2VkIGFzIHcsIGlzTnVtYmVyIGFzIHgsIF9wYXJzZU9iamVjdERhdGFSYWRpYWxTY2FsZSBhcyB5LCBnZXRSZWxhdGl2ZVBvc2l0aW9uIGFzIHogfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWhlbHBlcnMuc2VnbWVudC5qcy5tYXBcbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHsgQ2hhcnQgfSBmcm9tICdjaGFydC5qcyc7XG5pbXBvcnQgYW5ub3RhdGlvblBsdWdpbiBmcm9tICdjaGFydGpzLXBsdWdpbi1hbm5vdGF0aW9uJztcblxuXG4vLyBEZWZpbmUgY29sb3IgcmFuZ2VzIGZvciB0aGUgZGlmZmVyZW50IHZhbHVlIHJhbmdlc1xuY29uc3QgY29sb3JSYW5nZXMgPSB7XG5cdGdvb2Q6ICdyZ2JhKDE1NCwgMjA0LCA5MSwgMC4yKScsXG5cdG1vZGVyYXRlOiAncmdiYSgyNTUsIDIzNSwgNTksIDAuMiknLFxuXHR1bmhlYWx0aHlTZW5zaXRpdmU6ICdyZ2JhKDI1NSwgMTUyLCAwLCAwLjIpJyxcblx0dW5oZWFsdGh5OiAncmdiYSgyNTUsIDU5LCA1OSwgMC4yKScsXG5cdHZlcnlVbmhlYWx0aHk6ICdyZ2JhKDE0MywgNjMsIDE1MSwgMC4yKScsXG5cdGhhemFyZG91czogJ3JnYmEoMTI2LCAxMCwgMiwgMC4yKScsXG59O1xuXG4vLyBEZWZpbmUgdGhlIGFubm90YXRpb25zXG5jb25zdCBhbm5vdGF0aW9ucyA9IHtcblx0ZHJhd1RpbWU6ICdiZWZvcmVEYXRhc2V0c0RyYXcnLFxuXHRhbm5vdGF0aW9uczogW1xuXHRcdHtcblx0XHRcdHR5cGU6ICdib3gnLFxuXHRcdFx0eVNjYWxlSUQ6ICd5LWF4aXMtMCcsXG5cdFx0XHR5TWluOiAwLFxuXHRcdFx0eU1heDogMTIsXG5cdFx0XHRiYWNrZ3JvdW5kQ29sb3I6IGNvbG9yUmFuZ2VzLmdvb2QsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHR0eXBlOiAnYm94Jyxcblx0XHRcdHlTY2FsZUlEOiAneS1heGlzLTAnLFxuXHRcdFx0eU1pbjogMTIuMSxcblx0XHRcdHlNYXg6IDM1LjQsXG5cdFx0XHRiYWNrZ3JvdW5kQ29sb3I6IGNvbG9yUmFuZ2VzLm1vZGVyYXRlLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0dHlwZTogJ2JveCcsXG5cdFx0XHR5U2NhbGVJRDogJ3ktYXhpcy0wJyxcblx0XHRcdHlNaW46IDM1LjUsXG5cdFx0XHR5TWF4OiA1NS40LFxuXHRcdFx0YmFja2dyb3VuZENvbG9yOiBjb2xvclJhbmdlcy51bmhlYWx0aHlTZW5zaXRpdmUsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHR0eXBlOiAnYm94Jyxcblx0XHRcdHlTY2FsZUlEOiAneS1heGlzLTAnLFxuXHRcdFx0eU1pbjogNTUuNSxcblx0XHRcdHlNYXg6IDE1MC40LFxuXHRcdFx0YmFja2dyb3VuZENvbG9yOiBjb2xvclJhbmdlcy51bmhlYWx0aHksXG5cdFx0fSxcblx0XHR7XG5cdFx0XHR0eXBlOiAnYm94Jyxcblx0XHRcdHlTY2FsZUlEOiAneS1heGlzLTAnLFxuXHRcdFx0eU1pbjogMTUwLjUsXG5cdFx0XHR5TWF4OiAyNTAuNCxcblx0XHRcdGJhY2tncm91bmRDb2xvcjogY29sb3JSYW5nZXMudmVyeVVuaGVhbHRoeSxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHR5cGU6ICdib3gnLFxuXHRcdFx0eVNjYWxlSUQ6ICd5LWF4aXMtMCcsXG5cdFx0XHR5TWluOiAyNTAuNSxcblx0XHRcdHlNYXg6IDUwMC40LFxuXHRcdFx0YmFja2dyb3VuZENvbG9yOiBjb2xvclJhbmdlcy5oYXphcmRvdXMsXG5cdFx0fSxcblx0XSxcbn07XG5cblxuLy8gSW5pdGlhbGlzaWVyZSBkYXMgQ2hhcnQtT2JqZWt0XG52YXIgY3R4ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NoYXJ0JykuZ2V0Q29udGV4dCgnMmQnKTtcbnZhciBjaGFydCA9IG5ldyBDaGFydChjdHgsIHtcblx0Ly8gQXJ0IGRlcyBEaWFncmFtbXNcblx0dHlwZTogJ2xpbmUnLFxuXG5cdC8vIERhdGVuXG5cdGRhdGE6IHtcblx0XHRsYWJlbHM6IFtdLFxuXHRcdGRhdGFzZXRzOiBbe1xuXHRcdFx0bGFiZWw6ICdQTTIuNScsXG5cdFx0XHRkYXRhOiBbXSxcblx0XHRcdGJhY2tncm91bmRDb2xvcjogJ3JnYmEoMjU1LCA5OSwgMTMyLCAwLjIpJyxcblx0XHRcdGJvcmRlckNvbG9yOiAncmdiYSgyNTUsOTksMTMyLDEpJyxcblx0XHRcdGJvcmRlcldpZHRoOiAxLFxuXHRcdFx0cG9pbnRSYWRpdXM6IDAsXG5cdFx0XHRmaWxsOiBmYWxzZVxuXHRcdH0sIHtcblx0XHRcdGxhYmVsOiAnUE0xMCcsXG5cdFx0XHRkYXRhOiBbXSxcblx0XHRcdGJhY2tncm91bmRDb2xvcjogJ3JnYmEoNTQsIDE2MiwgMjM1LCAwLjIpJyxcblx0XHRcdGJvcmRlckNvbG9yOiAncmdiYSg1NCwgMTYyLCAyMzUsIDEpJyxcblx0XHRcdGJvcmRlcldpZHRoOiAxLFxuXHRcdFx0cG9pbnRSYWRpdXM6IDAsXG5cdFx0XHRmaWxsOiBmYWxzZVxuXHRcdH1dXG5cdH0sXG5cblx0Ly8gS29uZmlndXJhdGlvbnNvcHRpb25lblxuXHRvcHRpb25zOiB7XG5cdFx0bWFpbnRhaW5Bc3BlY3RSYXRpbzogZmFsc2UsXG5cdFx0cmVzcG9uc2l2ZTogdHJ1ZSxcblx0XHR0aXRsZToge1xuXHRcdFx0ZGlzcGxheTogdHJ1ZSxcblx0XHRcdHRleHQ6ICdGZWluc3RhdWJ3ZXJ0ZSdcblx0XHR9LFxuXHRcdHNjYWxlczoge1xuXHRcdFx0eDoge1xuXHRcdFx0XHQvKnR5cGU6ICd0aW1lJyxcblx0XHRcdFx0dGltZToge1xuXHRcdFx0XHRcdHVuaXQ6ICdob3VyJyxcblx0XHRcdFx0XHRkaXNwbGF5Rm9ybWF0czoge1xuXHRcdFx0XHRcdFx0aG91cjogJ01NTSBELCBoQSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sKi9cblx0XHRcdFx0ZGlzcGxheTogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdHk6IHtcblx0XHRcdFx0ZGlzcGxheTogdHJ1ZSxcblx0XHRcdFx0c2NhbGVMYWJlbDoge1xuXHRcdFx0XHRcdGRpc3BsYXk6IHRydWUsXG5cdFx0XHRcdFx0bGFiZWxTdHJpbmc6ICfCtWcvbcKzJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRiZWdpbkF0WmVybzogdHJ1ZSxcblx0XHRcdFx0c3VnZ2VzdGVkTWluOiAwLFxuXHRcdFx0XHRzdWdnZXN0ZWRNYXg6IDEwXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRwbHVnaW5zOiB7XG5cdFx0YW5ub3RhdGlvbjogYW5ub3RhdGlvbnNcblx0fSxcbn0pO1xuXG4vLyBGdW5rdGlvbiB6dW0gSGluenVmw7xnZW4gbmV1ZXIgRGF0ZW5wdW5rdGVcbmZ1bmN0aW9uIGFkZERhdGEodGltZSwgcG0yNSwgcG0xMCkge1xuXHQvLyBGw7xnZSBkaWUgbmV1ZW4gRGF0ZW5wdW5rdGUgaGluenVcblx0Y2hhcnQuZGF0YS5sYWJlbHMucHVzaCh0aW1lKTtcblx0Y2hhcnQuZGF0YS5kYXRhc2V0c1swXS5kYXRhLnB1c2gocG0yNSk7XG5cdGNoYXJ0LmRhdGEuZGF0YXNldHNbMV0uZGF0YS5wdXNoKHBtMTApO1xuXG5cdC8vIEJlZ3JlbnplIGRpZSBBbnphaGwgZGVyIERhdGVucHVua3RlIGF1ZiAxMDAgb2RlciBkaWUgbGV0enRlbiAxMiBTdHVuZGVuXG5cdHZhciBtYXhQb2ludHMgPSAxMDA7XG5cdHZhciBtYXhUaW1lID0gbmV3IERhdGUoKTtcblx0bWF4VGltZS5zZXRIb3VycyhtYXhUaW1lLmdldEhvdXJzKCkgLSAxMik7XG5cblx0d2hpbGUgKGNoYXJ0LmRhdGEubGFiZWxzLmxlbmd0aCA+IG1heFBvaW50cyB8fCAoY2hhcnQuZGF0YS5sYWJlbHMubGVuZ3RoID4gMCAmJiBuZXcgRGF0ZShjaGFydC5kYXRhLmxhYmVsc1swXSkgPCBtYXhUaW1lKSkge1xuXHRcdGNoYXJ0LmRhdGEubGFiZWxzLnNoaWZ0KCk7XG5cdFx0Y2hhcnQuZGF0YS5kYXRhc2V0c1swXS5kYXRhLnNoaWZ0KCk7XG5cdFx0Y2hhcnQuZGF0YS5kYXRhc2V0c1sxXS5kYXRhLnNoaWZ0KCk7XG5cdH1cblxuXHQvLyBBa3R1YWxpc2llcmUgZGFzIENoYXJ0XG5cdGNoYXJ0LnVwZGF0ZSgpO1xufVxuXG5cblxuc2V0SW50ZXJ2YWwoKCAgKSA9PiB7XG5cdGFkZERhdGEobmV3IERhdGUoKS50b0xvY2FsZVRpbWVTdHJpbmcoKSwgMStNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKjIpLCAzK01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDIpKTtcbn0sIDEwMDApIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..c261039 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,28 @@ +body { + font: 1.3em "Lucida Grande", Helvetica, Arial, sans-serif; + width: 100%; + overflow-x: hidden; +} + +a { + color: #00B7FF; +} + +canvas { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; +} + +h1 { + margin-bottom: -1%; +} + +#chart { + width: 100%; + overflow-x: hidden; +} + +#lastStatus { + font-size: 0.8em; +} \ No newline at end of file diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..0a6e090 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,64 @@ +const express = require('express'); +const router = express.Router(); +const PMEntry = require("../models/PMEntry"); +const Status = require("../models/Status"); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'PM2.5 & PM10' }); +}); + + + +router.get('/data/:timestamp', async (req,res) => { + let date = new Date(req.params.timestamp); + + try { + let entries = await PMEntry.find({ updatedAt: {$gt: req.params.timestamp} }); + res.json(entries); + } catch( e ) + { + console.error(e); + } + + +}); + + +router.post("/push", async(req, res) => { + console.log(req.body); + res.status(200); + res.send("ok"); + res.end(); + + let entry = new PMEntry(); + entry.pm10 = req.body.pm10; + entry.pm25 = req.body.pm25; + + if(entry.pm10 > 500 || entry.pm25 > 500 ) + return; + + await entry.save(); + +}); + + +router.get("/status", async(req,res) => { + let status = await Status.findOne({}).sort({createdAt: -1}); + res.json(status); +}); + +router.post("/status", async(req,res) => { + console.log(req.body); + + let status = new Status(); + status.error = req.body.error; + status.ip = req.body.ip; + status.sleeping = req.body.sleeping; + + await status.save(); + res.status(200); + res.end(); +}); + +module.exports = router; diff --git a/views/error.pug b/views/error.pug new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/views/error.pug @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/views/index.pug b/views/index.pug new file mode 100644 index 0000000..ad52c99 --- /dev/null +++ b/views/index.pug @@ -0,0 +1,7 @@ +extends layout + +block content + h1 PM2.5 [] & PM10 [] + p#lastStatus + div(style="width:100%; height:75vh;") + canvas#chart diff --git a/views/layout.pug b/views/layout.pug new file mode 100644 index 0000000..cbdf4d1 --- /dev/null +++ b/views/layout.pug @@ -0,0 +1,10 @@ +doctype html +html + head + title= title + link(rel='stylesheet', href='/stylesheets/style.css') + script(src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.0/chart.js") + script(src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.0.2/chartjs-plugin-annotation.js") + body + block content + script(src="/javascripts/main.js") diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..abd56d5 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,27 @@ +const path = require( "path" ); + +module.exports = { + mode: "development", + devtool: "inline-source-map", + entry: { + web: "./public/javascripts/main.js", + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + //exclude: /node_modules/, + }, + ], + }, + resolve: { + extensions: [".tsx", ".ts", ".js"], + }, + output: { + filename: "[name].bundle.js", + path: path.resolve( __dirname, "public/javascripts/" ), + }, +}; + + diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..94413be --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1773 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda" + integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@kurkle/color@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f" + integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw== + +"@types/babel-types@*", "@types/babel-types@^7.0.0": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.11.tgz#263b113fa396fac4373188d73225297fb86f19a9" + integrity sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A== + +"@types/babylon@^6.16.2": + version "6.16.6" + resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.6.tgz#a1e7e01567b26a5ebad321a74d10299189d8d932" + integrity sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w== + dependencies: + "@types/babel-types" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== + +"@types/json-schema@*", "@types/json-schema@^7.0.8": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/node@*": + version "20.1.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.1.4.tgz#83f148d2d1f5fe6add4c53358ba00d97fc4cdb71" + integrity sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q== + +"@types/webidl-conversions@*": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz#2b8e60e33906459219aa587e9d1a612ae994cfe7" + integrity sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog== + +"@types/whatwg-url@^8.2.1": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.2.tgz#749d5b3873e845897ada99be4448041d4cc39e63" + integrity sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA== + dependencies: + "@types/node" "*" + "@types/webidl-conversions" "*" + +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" + +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.0.tgz#b59b33377b1b896a9a7357cfc643b39c1524b1e6" + integrity sha512-K/vuv72vpfSEZoo5KIU0a2FsEoYdW0DUMtMpB5X3LlUwshetMZRZRxB7sCsVji/lFaSxtQQ3aM9O4eMolXkU9w== + +"@webpack-cli/info@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.1.tgz#eed745799c910d20081e06e5177c2b2569f166c0" + integrity sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA== + +"@webpack-cli/serve@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.4.tgz#3982ee6f8b42845437fc4d391e93ac5d9da52f0f" + integrity sha512-0xRgjgDLdz6G7+vvDLlaRpFatJaJ69uTalZLRSMX5B3VUrDmXcrVA3+6fXXQgmYz7bY9AAgs348XQdmtLsK41A== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-globals@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" + integrity sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw== + dependencies: + acorn "^4.0.4" + +acorn-import-assertions@^1.7.6: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw== + +acorn@^4.0.4, acorn@~4.0.2: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug== + +acorn@^8.5.0, acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg== + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +basic-auth@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + +body-parser@1.18.3: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + integrity sha512-YQyoqQG3sO8iCmf8+hyVpgHHOv0/hCEFiS4zTGUwTA1HjAFX66wRcNQrVCeJq9pgESMRvUAOvSil5MJlmccuKQ== + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + +browserslist@^4.14.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +bson@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/bson/-/bson-5.3.0.tgz#37b006df4cd91ed125cb686467c1dd6d4606b514" + integrity sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g== + +caniuse-lite@^1.0.30001449: + version "1.0.30001487" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz#d882d1a34d89c11aea53b8cdc791931bdab5fe1b" + integrity sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA== + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ== + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +character-parser@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" + integrity sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw== + dependencies: + is-regex "^1.0.3" + +chart.js@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.3.0.tgz#ac363030ab3fec572850d2d872956f32a46326a1" + integrity sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g== + dependencies: + "@kurkle/color" "^0.3.0" + +chartjs-plugin-annotation@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.0.0.tgz#3805f4ea16898e6fb0f72913c34b926d36ae2424" + integrity sha512-oQgFgtStHpkAyn/O/cBJ1i0AzZK+GJL9gHlbgd1C06WgwYMtxJp/eL+IuDBmr+xT47GWv1cKee9H4r/OWqBqbw== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +clean-css@^3.3.0: + version "3.4.28" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-3.4.28.tgz#bf1945e82fc808f55695e6ddeaec01400efd03ff" + integrity sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw== + dependencies: + commander "2.8.x" + source-map "0.4.x" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA== + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@2.8.x: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ== + dependencies: + graceful-readlink ">= 1.0.0" + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +constantinople@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" + integrity sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw== + dependencies: + "@types/babel-types" "^7.0.0" + "@types/babylon" "^6.16.2" + babel-types "^6.26.0" + babylon "^6.18.0" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-parser@~1.4.4: + version "1.4.6" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594" + integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA== + dependencies: + cookie "0.4.1" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw== + +cookie@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +core-js@^2.4.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.6.9, debug@~2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4.x: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg== + +doctypes@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" + integrity sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.284: + version "1.4.394" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.394.tgz#989abe104a40366755648876cde2cdeda9f31133" + integrity sha512-0IbC2cfr8w5LxTz+nmn2cJTGafsK9iauV2r5A5scfzyovqLrxuLoxOHE5OBobP3oVIggJT+0JfKnw9sm87c8Hw== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +enhanced-resolve@^5.14.0: + version "5.14.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz#0b6c676c8a3266c99fa281e4433a706f5c0c61c4" + integrity sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.2.1.tgz#ba303831f63e6a394983fde2f97ad77b22324527" + integrity sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +express@~4.16.1: + version "4.16.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.3" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.4" + qs "6.5.2" + range-parser "~1.2.0" + safe-buffer "5.1.2" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-intrinsic@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +iconv-lite@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-core-module@^2.11.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== + dependencies: + has "^1.0.3" + +is-expression@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" + integrity sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw== + dependencies: + acorn "~4.0.2" + object-assign "^4.0.1" + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-promise@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +is-regex@^1.0.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" + integrity sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g== + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +jstransformer@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" + integrity sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A== + dependencies: + is-promise "^2.0.0" + promise "^7.0.1" + +kareem@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" + integrity sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA== + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memory-pager@^1.0.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" + integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== + +mongodb-connection-string-url@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" + integrity sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ== + dependencies: + "@types/whatwg-url" "^8.2.1" + whatwg-url "^11.0.0" + +mongodb@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.3.0.tgz#9bef3ff35511a66fb7d9aafb7b06112787138db1" + integrity sha512-Wy/sbahguL8c3TXQWXmuBabiLD+iVmz+tOgQf+FwkCjhUIorqbAxRbbz00g4ZoN4sXIPwpAlTANMaGRjGGTikQ== + dependencies: + bson "^5.2.0" + mongodb-connection-string-url "^2.6.0" + socks "^2.7.1" + optionalDependencies: + saslprep "^1.0.3" + +mongoose@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-7.1.1.tgz#a0e17be54754dd8801cb3696585b949399550aa9" + integrity sha512-AIxaWwGY+td7QOMk4NgK6fbRuGovFyDzv65nU1uj1DsUh3lpjfP3iFYHSR+sUKrs7nbp19ksLlRXkmInBteSCA== + dependencies: + bson "^5.2.0" + kareem "2.5.1" + mongodb "5.3.0" + mpath "0.9.0" + mquery "5.0.0" + ms "2.1.3" + sift "16.0.1" + +morgan@~1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59" + integrity sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA== + dependencies: + basic-auth "~2.0.0" + debug "2.6.9" + depd "~1.1.2" + on-finished "~2.3.0" + on-headers "~1.0.1" + +mpath@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.9.0.tgz#0c122fe107846e31fc58c75b09c35514b3871904" + integrity sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew== + +mquery@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-5.0.0.tgz#a95be5dfc610b23862df34a47d3e5d60e110695d" + integrity sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg== + dependencies: + debug "4.x" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parseurl@~1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +promise@^7.0.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + +proxy-addr@~2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +pug-attrs@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.4.tgz#b2f44c439e4eb4ad5d4ef25cac20d18ad28cc336" + integrity sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ== + dependencies: + constantinople "^3.0.1" + js-stringify "^1.0.1" + pug-runtime "^2.0.5" + +pug-code-gen@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-1.1.1.tgz#1cf72744ef2a039eae6a3340caaa1105871258e8" + integrity sha512-UwZaJVhjhy2kYntLqXjSV1ae+K96ve6bG+N5bLFfA6yyGJTEkguct19MWDyUM9D8CDU3NNxVctUAh5McF19E6w== + dependencies: + constantinople "^3.0.1" + doctypes "^1.1.0" + js-stringify "^1.0.1" + pug-attrs "^2.0.2" + pug-error "^1.3.2" + pug-runtime "^2.0.3" + void-elements "^2.0.1" + with "^5.0.0" + +pug-error@^1.3.2, pug-error@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.3.tgz#f342fb008752d58034c185de03602dd9ffe15fa6" + integrity sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ== + +pug-filters@^2.1.1: + version "2.1.5" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.5.tgz#66bf6e80d97fbef829bab0aa35eddff33fc964f3" + integrity sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ== + dependencies: + clean-css "^3.3.0" + constantinople "^3.0.1" + jstransformer "1.0.0" + pug-error "^1.3.2" + pug-walk "^1.1.5" + resolve "^1.1.6" + uglify-js "^2.6.1" + +pug-lexer@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-3.1.0.tgz#fd087376d4a675b4f59f8fef422883434e9581a2" + integrity sha512-DxXOrmCIDVEwzN2ozZBK1t4QRTR6pLv5YkqM6dLdaSHnm+LJJRBngVn4IDMMBZQR9xUpxrRm9rffmku2OEqkJw== + dependencies: + character-parser "^2.1.1" + is-expression "^3.0.0" + pug-error "^1.3.2" + +pug-linker@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-2.0.3.tgz#b331ffa25737dde69c127b56c10ff17fae766dca" + integrity sha512-ZqKljvFUl1K5L4G5WABJ5FUYWOY0K2AXLmwj2QfM7nPCUcxfsmr05SikjgXGXVoIrygGzM/iWSsXwnkWId4AHw== + dependencies: + pug-error "^1.3.2" + pug-walk "^1.1.2" + +pug-load@^2.0.5: + version "2.0.12" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.12.tgz#d38c85eb85f6e2f704dea14dcca94144d35d3e7b" + integrity sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg== + dependencies: + object-assign "^4.1.0" + pug-walk "^1.1.8" + +pug-parser@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-2.0.2.tgz#53a680cfd05039dcb0c27d029094bc4a792689b0" + integrity sha512-PW8kKDLN07MbFljR/GaYHPBGW+64YldtFFZUEGltJ67RRzebI/DxZy4njlxacy9JeheosyVprZ9C5DIexG1D/Q== + dependencies: + pug-error "^1.3.2" + token-stream "0.0.1" + +pug-runtime@^2.0.3, pug-runtime@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.5.tgz#6da7976c36bf22f68e733c359240d8ae7a32953a" + integrity sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw== + +pug-strip-comments@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz#cc1b6de1f6e8f5931cf02ec66cdffd3f50eaf8a8" + integrity sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw== + dependencies: + pug-error "^1.3.3" + +pug-walk@^1.1.2, pug-walk@^1.1.5, pug-walk@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.8.tgz#b408f67f27912f8c21da2f45b7230c4bd2a5ea7a" + integrity sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA== + +pug@2.0.0-beta11: + version "2.0.0-beta11" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-beta11.tgz#15abe6af5004c7e2cf4613e4b27465c9546b5f01" + integrity sha512-iV0ibDCWLJGw8eEtBKAqbJZecOabQa6hpFeH+GCBzsAsCNSvpjo4wuHMPcmqtaZhxoO3ElbMePf8jkrM9TKulw== + dependencies: + pug-code-gen "^1.1.1" + pug-filters "^2.1.1" + pug-lexer "^3.0.0" + pug-linker "^2.0.2" + pug-load "^2.0.5" + pug-parser "^2.0.2" + pug-runtime "^2.0.3" + pug-strip-comments "^1.0.2" + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@~1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.1.6, resolve@^1.20.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg== + dependencies: + align-text "^0.1.1" + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saslprep@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" + integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== + dependencies: + sparse-bitfield "^3.0.3" + +schema-utils@^3.1.1, schema-utils@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" + integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +sift@16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.1.tgz#e9c2ccc72191585008cf3e36fc447b2d2633a053" + integrity sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@0.4.x: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A== + dependencies: + amdefine ">=0.0.4" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +sparse-bitfield@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" + integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== + dependencies: + memory-pager "^1.0.2" + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.7: + version "5.3.8" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.8.tgz#415e03d2508f7de63d59eca85c5d102838f06610" + integrity sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.8" + +terser@^5.16.8: + version "5.17.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.3.tgz#7f908f16b3cdf3f6c0f8338e6c1c674837f90d25" + integrity sha512-AudpAZKmZHkG9jueayypz4duuCFJMMNGRMwaPvQKWfxKedh8Z2x3OCoDqIIi1xx5+iwx1u6Au8XQcc9Lke65Yg== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + +token-stream@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" + integrity sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg== + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + +type-is@~1.6.16: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +uglify-js@^2.6.1: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w== + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +void-elements@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== + +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +webpack-cli@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.1.tgz#c211ac6d911e77c512978f7132f0d735d4a97ace" + integrity sha512-OLJwVMoXnXYH2ncNGU8gxVpUtm3ybvdioiTvHgUyBuyMLKiVvWy+QObzBsMtp5pH7qQoEuWgeEUQ/sU3ZJFzAw== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.0" + "@webpack-cli/info" "^2.0.1" + "@webpack-cli/serve" "^2.0.4" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.82.1: + version "5.82.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.82.1.tgz#8f38c78e53467556e8a89054ebd3ef6e9f67dbab" + integrity sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.14.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.2" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.7" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg== + +with@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" + integrity sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg== + dependencies: + acorn "^3.1.0" + acorn-globals "^3.0.0" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q== + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A== + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0"