ngx-antv-f2
Version: 
Functional Antvis/F2 wrapper for Angular.
918 lines (893 loc) • 86.1 kB
JavaScript
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@antv/f2/lib/core'), require('@angular/common'), require('@antv/f2/lib/geom/'), require('@antv/f2/lib/coord/polar'), require('@antv/f2/lib/component/axis/circle'), require('@antv/f2/lib/geom/adjust/'), require('@antv/f2/lib/scale/time-cat'), require('@antv/f2/lib/plugin/tooltip'), require('@antv/f2/lib/plugin/legend'), require('@antv/f2/lib/component/guide'), require('@antv/f2/lib/plugin/guide'), require('@antv/f2/lib/animation/detail'), require('@antv/f2/lib/interaction/'), require('@antv/f2/lib/plugin/scroll-bar')) :
    typeof define === 'function' && define.amd ? define('ngx-antv-f2', ['exports', '@angular/core', '@antv/f2/lib/core', '@angular/common', '@antv/f2/lib/geom/', '@antv/f2/lib/coord/polar', '@antv/f2/lib/component/axis/circle', '@antv/f2/lib/geom/adjust/', '@antv/f2/lib/scale/time-cat', '@antv/f2/lib/plugin/tooltip', '@antv/f2/lib/plugin/legend', '@antv/f2/lib/component/guide', '@antv/f2/lib/plugin/guide', '@antv/f2/lib/animation/detail', '@antv/f2/lib/interaction/', '@antv/f2/lib/plugin/scroll-bar'], factory) :
    (factory((global['ngx-antv-f2'] = {}),global.ng.core,null,global.ng.common,null,null,null,null,null,null,null,null,null,null,null,null));
}(this, (function (exports,core,F2,common,Geom,CoordPolar,AxisCircle,Adjust,ScaleTimeCat,Tooltip,Legend,GuideComponent,GuidePlugin,Animation,Interaction,ScrollBar) { 'use strict';
    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation. All rights reserved.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
    this file except in compliance with the License. You may obtain a copy of the
    License at http://www.apache.org/licenses/LICENSE-2.0
    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
    MERCHANTABLITY OR NON-INFRINGEMENT.
    See the Apache Version 2.0 License for specific language governing permissions
    and limitations under the License.
    ***************************************************************************** */
    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m)
            return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
                ar.push(r.value);
        }
        catch (error) {
            e = { error: error };
        }
        finally {
            try {
                if (r && !r.done && (m = i["return"]))
                    m.call(i);
            }
            finally {
                if (e)
                    throw e.error;
            }
        }
        return ar;
    }
    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 配置坐标轴
     */
    var F2Axis = (function () {
        function F2Axis() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Axis.prototype.setChartAxis = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.disabled === true) {
                    chart.axis(false);
                }
                else {
                    chart.axis(this.option[0], this.option[1]);
                }
            };
        F2Axis.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-axis',
                        template: ''
                    },] },
        ];
        F2Axis.propDecorators = {
            disabled: [{ type: core.Input }],
            option: [{ type: core.Input }]
        };
        return F2Axis;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 装载数据
     */
    var F2Source = (function () {
        function F2Source() {
            this.dataChange = new core.EventEmitter();
        }
        /**
         * @param {?} changes
         * @return {?}
         */
        F2Source.prototype.ngOnChanges = /**
         * @param {?} changes
         * @return {?}
         */
            function (changes) {
                if (changes["data"]) {
                    this.dataChange.next(true);
                }
            };
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Source.prototype.setChartSource = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                chart.source(this.data, this.colDefs);
            };
        F2Source.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-source',
                        template: ''
                    },] },
        ];
        F2Source.propDecorators = {
            data: [{ type: core.Input }],
            colDefs: [{ type: core.Input }],
            dataChange: [{ type: core.Output }]
        };
        return F2Source;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description:
     */
    var F2Geometry = (function () {
        function F2Geometry() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Geometry.prototype.setChartGeometry = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                /** @type {?} */
                var geom;
                /** @type {?} */
                var geomType = this.type;
                if (geomType === 'point') {
                    geom = chart.point();
                }
                else if (geomType === 'path') {
                    geom = chart.path();
                }
                else if (geomType === 'line') {
                    geom = chart.line();
                }
                else if (geomType === 'area') {
                    geom = chart.area();
                }
                else if (geomType === 'interval') {
                    geom = chart.interval();
                }
                else if (geomType === 'polygon') {
                    geom = chart.polygon();
                }
                else if (geomType === 'schema') {
                    geom = chart.schema();
                }
                if (this.position) {
                    geom.position(this.position);
                }
                if (this.color) {
                    if (Array.isArray(this.color)) {
                        geom.color(this.color[0], this.color[1]);
                    }
                    else {
                        geom.color(this.color);
                    }
                }
                if (this.shape) {
                    geom.shape(this.shape);
                }
                if (this.size) {
                    geom.size(this.size);
                }
                if (this.adjust) {
                    geom.adjust(this.adjust);
                }
                if (this.style) {
                    geom.style(this.style);
                }
                if (this.animate !== undefined) {
                    geom.animate(this.animate);
                }
            };
        F2Geometry.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-geometry',
                        template: ''
                    },] },
        ];
        F2Geometry.propDecorators = {
            type: [{ type: core.Input }],
            config: [{ type: core.Input }],
            position: [{ type: core.Input }],
            color: [{ type: core.Input }],
            shape: [{ type: core.Input }],
            size: [{ type: core.Input }],
            adjust: [{ type: core.Input }],
            style: [{ type: core.Input }],
            animate: [{ type: core.Input }]
        };
        return F2Geometry;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 极坐标系
     */
    var F2CoordPolar = (function () {
        function F2CoordPolar() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2CoordPolar.prototype.setChartCoord = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.config) {
                    chart.coord('polar', this.config);
                }
                else {
                    chart.coord('polar');
                }
            };
        F2CoordPolar.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-coord-polar',
                        template: ''
                    },] },
        ];
        F2CoordPolar.propDecorators = {
            config: [{ type: core.Input }]
        };
        return F2CoordPolar;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 配置图例
     */
    var F2Legend = (function () {
        function F2Legend() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Legend.prototype.setChartLegend = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                chart.legend(this.config);
            };
        F2Legend.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-legend',
                        template: ''
                    },] },
        ];
        F2Legend.propDecorators = {
            config: [{ type: core.Input }]
        };
        return F2Legend;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 笛卡尔坐标系
     */
    var F2CoordRect = (function () {
        function F2CoordRect() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2CoordRect.prototype.setChartCoord = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.config) {
                    chart.coord('rect', this.config);
                }
                else {
                    chart.coord('rect');
                }
            };
        F2CoordRect.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-coord-rect',
                        template: ''
                    },] },
        ];
        F2CoordRect.propDecorators = {
            config: [{ type: core.Input }]
        };
        return F2CoordRect;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description:
     *  1.chart.tooltip(false);
     *  2.chart.tooltip({...});
     */
    var F2Tooltip = (function () {
        function F2Tooltip() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Tooltip.prototype.setChartTooltip = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.disabled === true) {
                    chart.tooltip(false);
                }
                else {
                    chart.tooltip(this.config);
                }
                return chart;
            };
        F2Tooltip.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-tooltip',
                        template: ''
                    },] },
        ];
        F2Tooltip.propDecorators = {
            disabled: [{ type: core.Input }],
            config: [{ type: core.Input }]
        };
        return F2Tooltip;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/17
     * \@Description: 绘制图表的辅助元素
     */
    var F2Guide = (function () {
        function F2Guide() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Guide.prototype.setChartGuide = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.type === 'line') {
                    chart.guide().line(this.config);
                }
                else if (this.type === 'text') {
                    chart.guide().text(this.config);
                }
                else if (this.type === 'point') {
                    chart.guide().point(this.config);
                }
                else if (this.type === 'tag') {
                    chart.guide().tag(this.config);
                }
                else if (this.type === 'rect') {
                    chart.guide().rect(this.config);
                }
                else if (this.type === 'html') {
                    chart.guide().html(this.config);
                }
                else if (this.type === 'arc') {
                    chart.guide().arc(this.config);
                }
                else if (this.type === 'regionFilter') {
                    chart.guide().regionFilter(this.config);
                }
            };
        F2Guide.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-guide',
                        template: ''
                    },] },
        ];
        F2Guide.propDecorators = {
            type: [{ type: core.Input }],
            config: [{ type: core.Input }]
        };
        return F2Guide;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/17
     * \@Description:
     */
    var F2Animate = (function () {
        function F2Animate() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Animate.prototype.setChartAnimate = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                if (this.disabled === true) {
                    chart.animate(false);
                }
                else {
                    chart.animate(this.config);
                }
            };
        F2Animate.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-animate',
                        template: ""
                    },] },
        ];
        F2Animate.propDecorators = {
            disabled: [{ type: core.Input }],
            config: [{ type: core.Input }]
        };
        return F2Animate;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/17
     * \@Description: 交互机制
     */
    var F2Interaction = (function () {
        function F2Interaction() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2Interaction.prototype.setChartInteraction = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                chart.interaction(this.option[0], this.option[1]);
            };
        F2Interaction.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-interaction',
                        template: ""
                    },] },
        ];
        F2Interaction.propDecorators = {
            option: [{ type: core.Input }]
        };
        return F2Interaction;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/17
     * \@Description:
     */
    var F2PieLabel = (function () {
        function F2PieLabel() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2PieLabel.prototype.setChartPieLabel = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                chart.pieLabel(this.config);
            };
        F2PieLabel.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-pie-label',
                        template: ''
                    },] },
        ];
        F2PieLabel.propDecorators = {
            config: [{ type: core.Input }]
        };
        return F2PieLabel;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/17
     * \@Description:
     */
    var F2ScrollBar = (function () {
        function F2ScrollBar() {
        }
        /**
         * @param {?} chart
         * @return {?}
         */
        F2ScrollBar.prototype.setChartScrollBar = /**
         * @param {?} chart
         * @return {?}
         */
            function (chart) {
                chart.scrollBar(this.config);
            };
        F2ScrollBar.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-scroll-bar',
                        template: ''
                    },] },
        ];
        F2ScrollBar.propDecorators = {
            config: [{ type: core.Input }]
        };
        return F2ScrollBar;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var F2Chart = (function () {
        function F2Chart() {
            this.config = {};
            /**
             * 自定义渲染事件
             */
            this.customRender = new core.EventEmitter();
        }
        /**
         * @param {?} event
         * @return {?}
         */
        F2Chart.prototype.onResize = /**
         * @param {?} event
         * @return {?}
         */
            function (event) {
                // this.render();
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.ngAfterViewInit = /**
         * @return {?}
         */
            function () {
                this.render();
                if (this.source) {
                    this.source.dataChange.subscribe(function (changes) {
                        console.log(changes);
                    });
                }
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.destroy();
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.render = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.chart = new F2.Chart(Object.assign({
                    el: this.canvas.nativeElement,
                    width: window.innerWidth,
                    height: window.innerWidth > window.innerHeight ? (window.innerHeight - 54) : window.innerWidth * 0.707,
                    pixelRatio: window.devicePixelRatio
                }, this.config));
                // 回传chart,自定义渲染
                if (this.preventRender === true) {
                    this.customRender.emit(this.chart);
                    return;
                }
                if (this.source && this.source.data) {
                    this.source.setChartSource(this.chart);
                }
                else {
                    return;
                }
                if (this.legend) {
                    this.legend.setChartLegend(this.chart);
                }
                // Coordinate
                if (this.coordRect) {
                    this.coordRect.setChartCoord(this.chart);
                }
                if (this.coordPolar) {
                    this.coordPolar.setChartCoord(this.chart);
                }
                // axis
                if (this.axisList && this.axisList.length > 0) {
                    this.axisList.forEach(function (axis) {
                        axis.setChartAxis(_this.chart);
                    });
                }
                // tooltip
                if (this.tooltip) {
                    this.tooltip.setChartTooltip(this.chart);
                }
                // geometry
                if (this.geometryList && this.geometryList.length > 0) {
                    this.geometryList.forEach(function (geometry) {
                        geometry.setChartGeometry(_this.chart);
                    });
                }
                // guide
                if (this.guide) {
                    this.guide.setChartGuide(this.chart);
                }
                // animate
                if (this.animate) {
                    this.animate.setChartAnimate(this.chart);
                }
                // pieLabel
                if (this.pieLabel) {
                    this.pieLabel.setChartPieLabel(this.chart);
                }
                // scrollBar
                if (this.scrollBar) {
                    this.scrollBar.setChartScrollBar(this.chart);
                }
                this.chart.render();
                // interaction
                if (this.interaction) {
                    this.interaction.setChartInteraction(this.chart);
                }
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.repaint = /**
         * @return {?}
         */
            function () {
                this.chart.repaint();
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.rerender = /**
         * @return {?}
         */
            function () {
                this.destroy();
                this.render();
            };
        /**
         * @return {?}
         */
        F2Chart.prototype.destroy = /**
         * @return {?}
         */
            function () {
                if (this.chart) {
                    this.chart.destroy();
                }
            };
        F2Chart.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-chart',
                        template: "\n    <div>\n      <canvas #canvas></canvas>\n    </div>\n    <ng-content></ng-content>\n  ",
                    },] },
        ];
        /** @nocollapse */
        F2Chart.ctorParameters = function () { return []; };
        F2Chart.propDecorators = {
            config: [{ type: core.Input }],
            preventRender: [{ type: core.Input }],
            customRender: [{ type: core.Output }],
            canvas: [{ type: core.ViewChild, args: ['canvas',] }],
            source: [{ type: core.ContentChild, args: [F2Source,] }],
            geometryList: [{ type: core.ContentChildren, args: [F2Geometry,] }],
            axisList: [{ type: core.ContentChildren, args: [F2Axis,] }],
            coordRect: [{ type: core.ContentChild, args: [F2CoordRect,] }],
            coordPolar: [{ type: core.ContentChild, args: [F2CoordPolar,] }],
            legend: [{ type: core.ContentChild, args: [F2Legend,] }],
            tooltip: [{ type: core.ContentChild, args: [F2Tooltip,] }],
            guide: [{ type: core.ContentChild, args: [F2Guide,] }],
            animate: [{ type: core.ContentChild, args: [F2Animate,] }],
            interaction: [{ type: core.ContentChild, args: [F2Interaction,] }],
            pieLabel: [{ type: core.ContentChild, args: [F2PieLabel,] }],
            scrollBar: [{ type: core.ContentChild, args: [F2ScrollBar,] }],
            onResize: [{ type: core.HostListener, args: ['window:resize', ['$event'],] }]
        };
        return F2Chart;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/13
     * \@Description: 为数据字段进行列定义
     */
    var F2Scale = (function () {
        function F2Scale() {
        }
        F2Scale.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-scale',
                        template: ""
                    },] },
        ];
        F2Scale.propDecorators = {
            field: [{ type: core.Input }],
            colDef: [{ type: core.Input }]
        };
        return F2Scale;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @author CK
     * \@date 2019/1/16
     * \@Description:
     */
    var F2GeomPoint = (function () {
        function F2GeomPoint() {
        }
        F2GeomPoint.decorators = [
            { type: core.Component, args: [{
                        selector: 'f2-geom-point',
                        template: ''
                    },] },
        ];
        F2GeomPoint.propDecorators = {
            config: [{ type: core.Input }],
            position: [{ type: core.Input }],
            color: [{ type: core.Input }],
            shape: [{ type: core.Input }],
            size: [{ type: core.Input }],
            adjust: [{ type: core.Input }],
            style: [{ type: core.Input }],
            animate: [{ type: core.Input }]
        };
        return F2GeomPoint;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    F2.Chart.plugins.register([
        Geom,
        CoordPolar,
        AxisCircle,
        Adjust,
        ScaleTimeCat,
        Animation,
        GuideComponent,
        GuidePlugin,
        Tooltip,
        Legend,
        Interaction,
        ScrollBar
    ]);
    /** @type {?} */
    var F2Component = [
        F2Chart,
        F2Source,
        F2Geometry,
        F2GeomPoint,
        F2Scale,
        F2CoordPolar,
        F2CoordRect,
        F2Legend,
        F2Axis,
        F2Tooltip,
        F2Guide,
        F2Animate,
        F2Interaction,
        F2PieLabel,
        F2ScrollBar,
    ];
    /**
     * // \@dynamic
     */
    var F2Module = (function () {
        function F2Module() {
        }
        F2Module.decorators = [
            { type: core.NgModule, args: [{
                        imports: [common.CommonModule],
                        declarations: __spread(F2Component),
                        exports: __spread(F2Component),
                    },] },
        ];
        return F2Module;
    }());
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    exports.F2Module = F2Module;
    exports.F2Axis = F2Axis;
    exports.F2Chart = F2Chart;
    exports.F2CoordPolar = F2CoordPolar;
    exports.F2CoordRect = F2CoordRect;
    exports.F2Geometry = F2Geometry;
    exports.F2Legend = F2Legend;
    exports.F2Scale = F2Scale;
    exports.F2Source = F2Source;
    exports.F2Tooltip = F2Tooltip;
    exports.F2GeomPoint = F2GeomPoint;
    exports.F2Guide = F2Guide;
    exports.F2Animate = F2Animate;
    exports.F2Interaction = F2Interaction;
    exports.F2PieLabel = F2PieLabel;
    exports.F2ScrollBar = F2ScrollBar;
    Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWFudHYtZjIudW1kLmpzLm1hcCIsInNvdXJjZXMiOltudWxsLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1heGlzLnRzIiwibmc6Ly9uZ3gtYW50di1mMi9saWIvYmFzaWMvZjItc291cmNlLnRzIiwibmc6Ly9uZ3gtYW50di1mMi9saWIvYmFzaWMvZjItZ2VvbWV0cnkudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1jb29yZC1wb2xhci50cyIsIm5nOi8vbmd4LWFudHYtZjIvbGliL2Jhc2ljL2YyLWxlZ2VuZC50cyIsIm5nOi8vbmd4LWFudHYtZjIvbGliL2Jhc2ljL2YyLWNvb3JkLXJlY3QudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi10b29sdGlwLnRzIiwibmc6Ly9uZ3gtYW50di1mMi9saWIvYmFzaWMvZjItZ3VpZGUudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1hbmltYXRlLnRzIiwibmc6Ly9uZ3gtYW50di1mMi9saWIvYmFzaWMvZjItaW50ZXJhY3Rpb24udHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1waWUtbGFiZWwudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1zY3JvbGwtYmFyLnRzIiwibmc6Ly9uZ3gtYW50di1mMi9saWIvYmFzaWMvZjItY2hhcnQudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi1zY2FsZS50cyIsIm5nOi8vbmd4LWFudHYtZjIvbGliL2Jhc2ljL2YyLWdlb20tcG9pbnQudHMiLCJuZzovL25neC1hbnR2LWYyL2xpYi9iYXNpYy9mMi5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2VcclxudGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGVcclxuTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcclxuXHJcblRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcclxuS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRFxyXG5XQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLFxyXG5NRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULlxyXG5cclxuU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXHJcbmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIGV4cG9ydHMpIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0U3Rhcihtb2QpIHtcclxuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XHJcbiAgICB2YXIgcmVzdWx0ID0ge307XHJcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgcmVzdWx0W2tdID0gbW9kW2tdO1xyXG4gICAgcmVzdWx0LmRlZmF1bHQgPSBtb2Q7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG4iLCJpbXBvcnQge0NvbXBvbmVudCwgSW5wdXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKipcbiAqIEBhdXRob3IgQ0tcbiAqIEBkYXRlIDIwMTkvMS8xM1xuICogQERlc2NyaXB0aW9uOiDDqcKFwo3Dp8K9wq7DpcKdwpDDpsKgwofDqMK9wrRcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZjItYXhpcycsXG4gIHRlbXBsYXRlOiAnJ1xufSlcbmV4cG9ydCBjbGFzcyBGMkF4aXMge1xuXG4gIC8qKlxuICAgKiBjaGFydC5heGlzKGZhbHNlKVxuICAgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW47XG5cblxuICAvKipcbiAgICogY2hhcnQuYXhpcyhmaWVsZCwgZmFsc2UpXG4gICAqIGNoYXJ0LmF4aXMoZmllbGQsIGNvbmZpZylcbiAgICovXG4gIEBJbnB1dCgpIG9wdGlvbjogW3N0cmluZywgb2JqZWN0XTtcblxuXG4gIHNldENoYXJ0QXhpcyhjaGFydDogYW55KSB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgPT09IHRydWUpIHtcbiAgICAgIGNoYXJ0LmF4aXMoZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjaGFydC5heGlzKHRoaXMub3B0aW9uWzBdLCB0aGlzLm9wdGlvblsxXSk7XG4gICAgfVxuICB9XG5cbn1cbiIsImltcG9ydCB7Q29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE91dHB1dCwgU2ltcGxlQ2hhbmdlc30gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qKlxuICogQGF1dGhvciBDS1xuICogQGRhdGUgMjAxOS8xLzEzXG4gKiBARGVzY3JpcHRpb246IMOowqPChcOowr3CvcOmwpXCsMOmwo3CrlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmMi1zb3VyY2UnLFxuICB0ZW1wbGF0ZTogJydcbn0pXG5leHBvcnQgY2xhc3MgRjJTb3VyY2UgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuXG4gIC8qKlxuICAgKiDDpcKPwq/DqMKnwobDpcKMwpbDpsKVwrDDpsKNwq5cbiAgICovXG4gIEBJbnB1dCgpIGRhdGE6IGFueVtdO1xuXG4gIC8qKlxuICAgKiDDpcKPwq/DqcKAwonDr8K8wozDpcKIwpfDpcKuwprDpMK5wonDqcKFwo3Dp8K9wq7Dr8K8wojDpcKQwoTDpMK4wqrDpcKtwpfDpsKuwrXDp8KawoTDpcK6wqbDqcKHwo/DqcKFwo3Dp8K9wq7Dr8K8wolcbiAgICovXG4gIEBJbnB1dCgpIGNvbERlZnM6IG9iamVjdDtcblxuICBAT3V0cHV0KCkgZGF0YUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlcy5kYXRhKSB7XG4gICAgICB0aGlzLmRhdGFDaGFuZ2UubmV4dCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICBzZXRDaGFydFNvdXJjZShjaGFydDogYW55KSB7XG4gICAgY2hhcnQuc291cmNlKHRoaXMuZGF0YSwgdGhpcy5jb2xEZWZzKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtDb21wb25lbnQsIElucHV0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqXG4gKiBAYXV0aG9yIENLXG4gKiBAZGF0ZSAyMDE5LzEvMTNcbiAqIEBEZXNjcmlwdGlvbjpcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZjItZ2VvbWV0cnknLFxuICB0ZW1wbGF0ZTogJydcbn0pXG5leHBvcnQgY2xhc3MgRjJHZW9tZXRyeSB7XG5cbiAgLyoqXG4gICAqIMOlwofCoMOkwr3ClcOnwrHCu8Olwp7Ci1xuICAgKlxuICAgKiAncG9pbnQnLCAncGF0aCcsICdsaW5lJywgJ2FyZWEnLCAnaW50ZXJ2YWwnLCAncG9seWdvbicsICdzY2hlbWEnLFxuICAgKi9cbiAgQElucHV0KCkgdHlwZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiB7XG4gICAqICAgZ2VuZXJhdGVQb2ludHM6IHtCb29sZWFufSxcbiAgICogICBzb3J0YWJsZToge0Jvb2xlYW59LFxuICAgKiAgIHN0YXJ0T25aZXJvOiB7Qm9vbGVhbn0sXG4gICAqICAgY29ubmVjdE51bGxzOiB7Qm9vbGVhbn1cbiAgICogIH1cbiAgICovXG4gIEBJbnB1dCgpIGNvbmZpZzogb2JqZWN0O1xuXG4gIC8qKlxuICAgKiDDpcKwwobDpsKVwrDDpsKNwq7DpcKAwrzDpsKYwqDDpcKwwoTDpcKIwrDDpcKbwr7DpcK9wqLDp8KawoTDpMK9wo3Dp8K9wq7DpMK4wopcbiAgICovXG4gIEBJbnB1dCgpIHBvc2l0aW9uOiBzdHJpbmcgfCBzdHJpbmdbXTtcblxuICAvKipcbiAgICogw6XCsMKGw6bClcKww6bCjcKuw6XCgMK8w6bCmMKgw6XCsMKEw6XCiMKww6XCm8K+w6XCvcKiw6fCmsKEw6nCosKcw6jCicKyw6TCuMKKXG4gICAqL1xuICBASW5wdXQoKSBjb2xvcjogc3RyaW5nIHwgW3N0cmluZywgc3RyaW5nIHwgYW55W10gfCBGdW5jdGlvbl07XG5cbiAgQElucHV0KCkgc2hhcGU6IGFueTtcblxuICBASW5wdXQoKSBzaXplOiBhbnk7XG5cbiAgQElucHV0KCkgYWRqdXN0OiBhbnk7XG5cbiAgQElucHV0KCkgc3R5bGU6IGFueTtcblxuICBASW5wdXQoKSBhbmltYXRlOiBhbnk7XG5cbiAgc2V0Q2hhcnRHZW9tZXRyeShjaGFydDogYW55KSB7XG4gICAgbGV0IGdlb207XG4gICAgY29uc3QgZ2VvbVR5cGUgPSB0aGlzLnR5cGU7XG4gICAgaWYgKGdlb21UeXBlID09PSAncG9pbnQnKSB7XG4gICAgICBnZW9tID0gY2hhcnQucG9pbnQoKTtcbiAgICB9IGVsc2UgaWYgKGdlb21UeXBlID09PSAncGF0aCcpIHtcbiAgICAgIGdlb20gPSBjaGFydC5wYXRoKCk7XG4gICAgfSBlbHNlIGlmIChnZW9tVHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICBnZW9tID0gY2hhcnQubGluZSgpO1xuICAgIH0gZWxzZSBpZiAoZ2VvbVR5cGUgPT09ICdhcmVhJykge1xuICAgICAgZ2VvbSA9IGNoYXJ0LmFyZWEoKTtcbiAgICB9IGVsc2UgaWYgKGdlb21UeXBlID09PSAnaW50ZXJ2YWwnKSB7XG4gICAgICBnZW9tID0gY2hhcnQuaW50ZXJ2YWwoKTtcbiAgICB9IGVsc2UgaWYgKGdlb21UeXBlID09PSAncG9seWdvbicpIHtcbiAgICAgIGdlb20gPSBjaGFydC5wb2x5Z29uKCk7XG4gICAgfSBlbHNlIGlmIChnZW9tVHlwZSA9PT0gJ3NjaGVtYScpIHtcbiAgICAgIGdlb20gPSBjaGFydC5zY2hlbWEoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucG9zaXRpb24pIHtcbiAgICAgIGdlb20ucG9zaXRpb24odGhpcy5wb3NpdGlvbik7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbG9yKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLmNvbG9yKSkge1xuICAgICAgICBnZW9tLmNvbG9yKHRoaXMuY29sb3JbMF0sIHRoaXMuY29sb3JbMV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZ2VvbS5jb2xvcih0aGlzLmNvbG9yKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRoaXMuc2hhcGUpIHtcbiAgICAgIGdlb20uc2hhcGUodGhpcy5zaGFwZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2l6ZSkge1xuICAgICAgZ2VvbS5zaXplKHRoaXMuc2l6ZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWRqdXN0KSB7XG4gICAgICBnZW9tLmFkanVzdCh0aGlzLmFkanVzdCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3R5bGUpIHtcbiAgICAgIGdlb20uc3R5bGUodGhpcy5zdHlsZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYW5pbWF0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBnZW9tLmFuaW1hdGUodGhpcy5hbmltYXRlKTtcbiAgICB9XG4gIH1cblxufVxuIiwiaW1wb3J0IHtDb21wb25lbnQsIElucHV0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBQb2xhckNvbmZpZyB7XG5cbiAgLyoqXG4gICAqIMOmwp7CgcOlwp3CkMOmwqDCh8OnwprChMOowrXCt8OlwqfCi8OowqfCksOlwrrCpsOvwrzCjMOlwrzCp8OlwrrCpsOlwojCtlxuICAgKi9cbiAgc3RhcnRBbmdsZT86IG51bWJlcjtcblxuICAvKipcbiAgICogw6bCnsKBw6XCncKQw6bCoMKHw6fCmsKEw6fCu8KTw6bCncKfw6jCp8KSw6XCusKmw6/CvMKMw6XCvMKnw6XCusKmw6XCiMK2XG4gICAqL1xuICBlbmRBbmdsZT86IG51bWJlcjtcblxuICAvKipcbiAgICogw6fCu8KYw6XCiMK2w6fCjsKvw6XCm8K+w6bCl8K2w6/CvMKMw6jCrsK+w6fCvcKuw6XChsKFw6nCg8Kow6fCqcK6w6XCv8KDw6XCjcKKw6XCvsKEw6/CvMKMw6fCm8K4w6XCr8K5w6XCgMK8w6/CvMKMMCDDqMKHwrMgMSDDqMKMwoPDpcKbwrRcbiAgICovXG4gIGlubmVyUmFkaXVzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiDDqMKuwr7Dp8K9wq7DpcKcwobDp8KawoTDpcKNworDpcK+woTDr8K8wozDp8KbwrjDpcKvwrnDpcKAwrzDr8K8wowwIMOowofCsyAxIMOowozCg8OlwpvCtFxuICAgKi9cbiAgcmFkaXVzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiDDpcKIwqTDpsKWwq3DpsKYwq/DpcKQwqbDpsKYwq/DpsKewoHDpcKdwpDDpsKgwofDr8K8wozDpsKewoHDpcKdwpDDpsKgwofDpMK4wovDpMK4wrogdHJ1ZVxuICAgKi9cbiAgaXNQb2xhcj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIMOmwpjCr8OlwpDCpsOlwo/CkcOnwpTCn8Oowr3CrMOnwr3CrsOvwrzCjHRydWUgw6jCocKow6fCpMK6w6XCj8KRw6fClMKfw6TCusKGw6jCvcKsw6fCvcKuXG4gICAqL1xuICB0cmFuc3Bvc2VkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogw6bCnsKBw6XCncKQw6bCoMKHw6fCmsKEw6XCnMKGw6XCv8KDw6bCicKAw6XCnMKow6fCmsKEw6fClMK7w6XCuMKDw6XCncKQw6bCoMKHXG4gICAqL1xuICBjZW50ZXI/OiBhbnk7XG5cbiAgLyoqXG4gICAqIMOmwp7CgcOlwp3CkMOmwqDCh8OnwprChMOlwo3CisOlwr7ChMOlwoDCvFxuICAgKi9cbiAgY2lyY2xlUmFkaXVzPzogbnVtYmVyO1xuXG59XG5cbi8qKlxuICogQGF1dGhvciBDS1xuICogQGRhdGUgMjAxOS8xLzEzXG4gKiBARGVzY3JpcHRpb246IMOmwp7CgcOlwp3CkMOmwqDCh8OnwrPCu1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmMi1jb29yZC1wb2xhcicsXG4gIHRlbXBsYXRlOiAnJ1xufSlcbmV4cG9ydCBjbGFzcyBGMkNvb3JkUG9sYXIge1xuXG4gIEBJbnB1dCgpIGNvbmZpZzogUG9sYXJDb25maWc7XG5cblxuICBzZXRDaGFydENvb3JkKGNoYXJ0OiBhbnkpIHtcbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIGNoYXJ0LmNvb3JkKCdwb2xhcicsIHRoaXMuY29uZmlnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2hhcnQuY29vcmQoJ3BvbGFyJyk7XG4gICAgfVxuICB9XG5cbn1cbiIsImltcG9ydCB7Q29tcG9uZW50LCBJbnB1dH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qKlxuICogQGF1dGhvciBDS1xuICogQGRhdGUgMjAxOS8xLzEzXG4gKiBARGVzY3JpcHRpb246IMOpwoXCjcOnwr3CrsOlwpvCvsOkwr7Ci1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmMi1sZWdlbmQnLFxuICB0ZW1wbGF0ZTogJydcbn0pXG5leHBvcnQgY2xhc3MgRjJMZWdlbmQge1xuXG4gIEBJbnB1dCgpIGNvbmZpZzogYm9vbGVhbiB8IG9iamVjdCB8IFtzdHJpbmcsIGFueV07XG5cblxuICBzZXRDaGFydExlZ2VuZChjaGFydDogYW55KSB7XG4gICAgY2hhcnQubGVnZW5kKHRoaXMuY29uZmlnKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtDb21wb25lbnQsIElucHV0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY3RDb25maWcge1xuICAvKipcbiAgICogw6XCncKQw6bCoMKHw6fCs8K7w6fCmsKEw6jCtcK3w6XCp8KLw6fCgsK5w6/CvMKMRjIgw6XCm8K+w6jCocKow6fCmsKEw6XCncKQw6bCoMKHw6fCs8K7w6XCjsKfw6fCgsK5w6TCvcKNw6TCusKOw6XCt8Kmw6TCuMKLw6jCp8KSXG4gICAqL1xuICBzdGFydD86IGFueTtcblxuICAvKipcbiAgICogw6XCncKQw6bCoMKHw6fCs8K7w6XCj8Kzw6TCuMKKw6jCp8KSw6fCmsKEw6fClMK7w6XCuMKDw6XCncKQw6bCoMKHXG4gICAqL1xuICBlbmQ/OiBhbnk7XG5cbiAgLyoqXG4gICAqIMOmwpjCr8OlwpDCpsOlwo/CkcOnwpTCn8Oowr3CrMOnwr3CrsOvwrzCjHRydWUgw6jCocKow6fCpMK6w6XCj8KRw6fClMKfw6TCusKGw6jCvcKsw6fCvcKuXG4gICAqL1xuICB0c