@senx/warpview
Version:
WarpView Elements
558 lines • 108 kB
JavaScript
/*
* Copyright 2021 SenX S.A.S.
*
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { Component, ElementRef, EventEmitter, HostListener, Input, NgZone, Output, Renderer2, ViewEncapsulation } from '@angular/core';
import { WarpViewComponent } from '../warp-view-component';
import { ChartLib } from '../../utils/chart-lib';
import moment from 'moment-timezone';
import { GTSLib } from '../../utils/gts.lib';
import { ColorLib } from '../../utils/color-lib';
import { SizeService } from '../../services/resize.service';
import { Logger } from '../../utils/logger';
import { ChartBounds } from '../../model/chartBounds';
import * as i0 from "@angular/core";
import * as i1 from "../../services/resize.service";
import * as i2 from "../warp-view-spinner/warp-view-spinner.component";
import * as i3 from "../../plotly/plotly.component";
import * as i4 from "@angular/common";
export class WarpViewAnnotationComponent extends WarpViewComponent {
constructor(el, renderer, sizeService, ngZone) {
super(el, renderer, sizeService, ngZone);
this.el = el;
this.renderer = renderer;
this.sizeService = sizeService;
this.ngZone = ngZone;
this.height = 0;
this.pointHover = new EventEmitter();
this.chartDraw = new EventEmitter();
this.boundsDidChange = new EventEmitter();
this.displayExpander = true;
this.layout = {
showlegend: false,
hovermode: 'closest',
xaxis: {
gridwidth: 1,
fixedrange: false,
autorange: false,
automargin: false,
showticklabels: true,
showgrid: false
},
autosize: false,
autoexpand: false,
yaxis: {
showticklabels: false,
fixedrange: true,
dtick: 1,
gridwidth: 1,
tick0: 0,
nticks: 1,
rangemode: 'tozero',
tickson: 'boundaries',
automargin: false,
autorange: false,
showline: false,
zeroline: true
},
margin: {
t: 2,
b: 50,
r: 10,
l: 10
},
};
this.marginLeft = 50;
this.expanded = false;
// tslint:disable-next-line:variable-name
this._type = 'annotation';
this.visibility = [];
this._standalone = true;
this.maxTick = Number.MIN_VALUE;
this.minTick = Number.MAX_VALUE;
this.visibleGtsId = [];
this.gtsId = [];
this.dataHashset = {};
this.lineHeight = 30;
this.chartBounds = new ChartBounds();
this.afterBoundsUpdate = false;
this.firstDraw = true;
this._autoResize = false;
this.LOG = new Logger(WarpViewAnnotationComponent, this._debug);
}
set type(type) {
this.LOG.debug(['type'], type);
this._type = type;
this.drawChart();
}
set hiddenData(hiddenData) {
const previousVisibility = JSON.stringify(this.visibility);
this.LOG.debug(['hiddenData', 'previousVisibility'], previousVisibility);
this._hiddenData = hiddenData;
this.visibility = [];
this.visibleGtsId.forEach(id => this.visibility.push(hiddenData.indexOf(id) < 0 && (id !== -1)));
this.LOG.debug(['hiddenData', 'hiddendygraphfullv'], this.visibility);
const newVisibility = JSON.stringify(this.visibility);
this.LOG.debug(['hiddenData', 'json'], previousVisibility, newVisibility);
if (previousVisibility !== newVisibility) {
const visible = [];
const hidden = [];
this.gtsId.forEach((id, i) => {
if (this._hiddenData.indexOf(id) > -1) {
hidden.push(i);
}
else {
visible.push(i);
}
});
if (visible.length > 0) {
this.graph.restyleChart({ visible: true }, visible);
}
if (hidden.length > 0) {
this.graph.restyleChart({ visible: false }, hidden);
}
this.LOG.debug(['hiddendygraphtrig', 'destroy'], 'redraw by visibility change');
}
}
set standalone(isStandalone) {
this.LOG.debug(['standalone'], isStandalone);
if (this._standalone !== isStandalone) {
this._standalone = isStandalone;
this.drawChart();
}
}
get standalone() {
return this._standalone;
}
handleKeyDown($event) {
if ($event.key === 'Control') {
this.trimmed = setInterval(() => {
if (!!this.toolTip.nativeElement.querySelector('#tooltip-body')) {
this.toolTip.nativeElement.querySelector('#tooltip-body').classList.add('full');
}
}, 100);
}
}
handleKeyup($event) {
this.LOG.debug(['document:keyup'], $event);
if ($event.key === 'Control') {
if (!!this.toolTip.nativeElement.querySelector('#tooltip-body')) {
if (this.trimmed) {
clearInterval(this.trimmed);
}
this.toolTip.nativeElement.querySelector('#tooltip-body').classList.remove('full');
}
}
}
update(options, refresh) {
this.drawChart(refresh);
}
updateBounds(min, max, marginLeft) {
this.LOG.debug(['updateBounds'], min, max, this._options);
this._options.bounds = this._options.bounds || {};
this._options.bounds.minDate = min;
this._options.bounds.maxDate = max;
this.layout.xaxis.autorange = false;
this.LOG.debug(['updateBounds'], GTSLib.toISOString(min, this.divider, this._options.timeZone), GTSLib.toISOString(max, this.divider, this._options.timeZone));
this.minTick = min;
this.maxTick = max;
if (this._options.timeMode && this._options.timeMode === 'timestamp') {
this.layout.xaxis.tick0 = min;
this.layout.xaxis.range = [min, max];
}
else {
this.layout.xaxis.tick0 = GTSLib.toISOString(min, this.divider, this._options.timeZone);
this.layout.xaxis.range = [
GTSLib.toISOString(min, this.divider, this._options.timeZone),
GTSLib.toISOString(max, this.divider, this._options.timeZone)
];
}
this.layout.margin.l = marginLeft;
this.marginLeft = marginLeft;
this.layout = { ...this.layout };
this.LOG.debug(['updateBounds'], { ...this.layout.xaxis.range });
this.afterBoundsUpdate = true;
}
drawChart(reparseNewData = false) {
this.loading = true;
this.layout.margin.l = !!this._standalone ? 10 : 50;
this.layout.margin.b = !!this._standalone ? 50 : 2;
this.height = this.lineHeight * (this.expanded ? this.gtsId.length : 1) + this.layout.margin.t + this.layout.margin.b;
this.LOG.debug(['drawChart', 'this.height'], this.height, this.expanded);
if (this.firstDraw && reparseNewData) {
this.expanded = !!this._options.expandAnnotation;
}
this.layout.height = this.height;
if (!this.initChart(this.el)) {
return;
}
this.el.nativeElement.style.display = 'block';
this.LOG.debug(['drawChart', 'this.plotlyData'], this.plotlyData);
this.LOG.debug(['drawChart', 'hiddenData'], this._hiddenData);
this.LOG.debug(['drawChart', 'this._options.bounds'], this._options.bounds, this._options.timeMode);
this.layout.yaxis.color = this.getGridColor(this.el.nativeElement);
this.layout.yaxis.gridcolor = this.getGridColor(this.el.nativeElement);
this.layout.yaxis.showline = !!this._standalone;
this.layout.yaxis.zerolinecolor = this.getGridColor(this.el.nativeElement);
this.layout.xaxis.color = this.getGridColor(this.el.nativeElement);
this.layout.xaxis.gridcolor = this.getGridColor(this.el.nativeElement);
this.layout.xaxis.autorange = !!this._standalone;
this.layout.xaxis.showticklabels = !!this._standalone;
this.displayExpander = (this.plotlyData.length > 1);
const count = this.plotlyData.filter(d => d.y.length > 0).length;
const calculatedHeight = this.lineHeight * (this.expanded ? count : 1) + this.layout.margin.t + this.layout.margin.b;
this.el.nativeElement.style.height = (calculatedHeight + 30) + 'px';
this.height = calculatedHeight;
this.layout.height = this.height;
this.LOG.debug(['drawChart', 'height'], this.lineHeight, this.height, count, calculatedHeight, this.expanded, this.layout.margin);
this.layout.yaxis.range = [0, this.expanded ? count : 1];
this.LOG.debug(['drawChart', 'this.layout'], this.layout, this.expanded);
if (this._options.timeMode && this._options.timeMode === 'timestamp') {
this.layout.xaxis.tick0 = this.minTick;
this.layout.xaxis.range = [this.minTick, this.maxTick];
this.layout.xaxis.type = 'linear';
}
else {
this.layout.xaxis.tick0 = GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone);
this.layout.xaxis.range = [
GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone),
GTSLib.toISOString(this.maxTick, this.divider, this._options.timeZone)
];
this.layout.xaxis.type = 'date';
}
this.plotlyConfig.scrollZoom = true;
this.layout.xaxis.showgrid = false;
setTimeout(() => {
this.plotlyConfig = { ...this.plotlyConfig };
this.layout = { ...this.layout };
this.firstDraw = false;
});
this.LOG.debug(['drawChart', 'this.plotlyConfig'], this.plotlyConfig, this.plotlyData, this.layout);
}
relayout(data) {
let change = false;
this.LOG.debug(['relayout', 'updateBounds'], data);
if (data['xaxis.range'] && data['xaxis.range'].length === 2) {
if (this.chartBounds.msmin !== data['xaxis.range'][0] || this.chartBounds.msmax !== data['xaxis.range'][1]) {
this.LOG.debug(['relayout', 'updateBounds', 'xaxis.range'], data['xaxis.range']);
change = true;
this.chartBounds.msmin = data['xaxis.range'][0];
this.chartBounds.msmax = data['xaxis.range'][1];
this.chartBounds.tsmin = GTSLib.toTimestamp(this.chartBounds.msmin, this.divider, this._options.timeZone);
this.chartBounds.tsmax = GTSLib.toTimestamp(this.chartBounds.msmax, this.divider, this._options.timeZone);
}
}
else if (data['xaxis.range[0]'] && data['xaxis.range[1]']) {
if (this.chartBounds.msmin !== data['xaxis.range[0]'] || this.chartBounds.msmax !== data['xaxis.range[1]']) {
this.LOG.debug(['relayout', 'updateBounds', 'xaxis.range[x]'], data['xaxis.range[0]'], data['xaxis.range[1]']);
change = true;
this.chartBounds.msmin = data['xaxis.range[0]'];
this.chartBounds.msmax = data['xaxis.range[1]'];
this.chartBounds.tsmin = GTSLib.toTimestamp(this.chartBounds.msmin, this.divider, this._options.timeZone);
this.chartBounds.tsmax = GTSLib.toTimestamp(this.chartBounds.msmax, this.divider, this._options.timeZone);
}
}
else if (data['xaxis.autorange']) {
if (this.chartBounds.tsmin !== this.minTick || this.chartBounds.tsmax !== this.maxTick) {
this.LOG.debug(['relayout', 'updateBounds', 'autorange'], data, this.minTick, this.maxTick);
change = true;
this.chartBounds.tsmin = this.minTick;
this.chartBounds.tsmax = this.maxTick;
}
}
if (change) {
this.LOG.debug(['relayout', 'updateBounds'], this.minTick, this.maxTick);
this.LOG.debug(['relayout', 'updateBounds'], this.chartBounds);
if (this._options.timeMode && this._options.timeMode === 'timestamp') {
this.emitNewBounds(this.chartBounds.msmin, this.chartBounds.msmax);
}
else {
this.emitNewBounds(this.chartBounds.tsmin, this.chartBounds.tsmax);
}
}
this.loading = false;
this.afterBoundsUpdate = false;
this.chartDraw.emit();
}
hover(data) {
this.LOG.debug(['hover'], data);
const tooltip = this.toolTip.nativeElement;
const color = data.points[0].fullData.marker.color;
this.pointHover.emit({
x: data.event.offsetX,
y: data.event.offsetY
});
let x = data.xvals[0];
if (!!data.points[0]) {
x = data.points[0].x;
}
const layout = this.el.nativeElement.getBoundingClientRect();
const count = this.plotlyData.filter(d => d.y.length > 0).length;
tooltip.style.opacity = '1';
tooltip.style.display = 'block';
tooltip.style.paddingLeft = (this._standalone ? 0 : 40) + 'px';
tooltip.style.top = (((this.expanded ? count - data.points[0].y : 0.5) * this.lineHeight) + this.layout.margin.t) + 'px';
tooltip.classList.remove('right', 'left');
tooltip.innerHTML = `<div class="tooltip-body trimmed" id="tooltip-body">
<span class="tooltip-date">${this._options.timeMode === 'timestamp'
? x
: (moment.utc(x).toISOString().replace('Z', this._options.timeZone === 'UTC' ? 'Z' : '') || '')}</span>
<i class="chip" style="background-color: ${color};border: 2px solid ${color};"></i> ${GTSLib.formatLabel(data.points[0].data.name)}: <span class="value">${data.points[0].text}</span>
</div>`;
if (data.event.offsetX > layout.width / 2) {
tooltip.classList.add('left');
}
else {
tooltip.classList.add('right');
}
tooltip.style.pointerEvents = 'none';
}
unhover() {
this.toolTip.nativeElement.style.display = 'none';
}
afterPlot(div) {
this.loading = false;
this.chartBounds.tsmin = this.minTick;
this.chartBounds.tsmax = this.maxTick;
this.LOG.debug(['afterPlot'], 'div', div);
this.chartDraw.emit(this.chartBounds);
if (this.afterBoundsUpdate || this._standalone) {
this.chartDraw.emit(this.chartBounds);
this.LOG.debug(['afterPlot'], 'chartBounds', this.chartBounds, div);
this.afterBoundsUpdate = false;
}
}
emitNewBounds(min, max) {
this.LOG.debug(['emitNewBounds'], min, max);
if (this._options.timeMode && this._options.timeMode === 'timestamp') {
this.boundsDidChange.emit({ bounds: { min, max }, source: 'annotation' });
}
else {
this.boundsDidChange.emit({
bounds: {
min: moment.tz(min, this._options.timeZone).valueOf(),
max: moment.tz(max, this._options.timeZone).valueOf()
},
source: 'annotation'
});
}
}
convert(data, firstDraw = false) {
this.loading = true;
this.noData = true;
const dataset = [];
let gtsList = GTSLib.flatDeep(GTSLib.flattenGtsIdArray(data.data, 0).res);
this.maxTick = Number.NEGATIVE_INFINITY;
this.minTick = Number.POSITIVE_INFINITY;
this.visibleGtsId = [];
this.gtsId = [];
const nonPlottable = gtsList.filter(g => g.v && GTSLib.isGtsToPlot(g));
gtsList = gtsList.filter(g => g.v && !GTSLib.isGtsToPlot(g));
let timestampMode = firstDraw;
if (firstDraw) {
const tsLimit = 100 * GTSLib.getDivider(this._options.timeUnit);
gtsList.forEach((gts) => {
const ticks = gts.v.map(t => t[0]);
const size = gts.v.length;
timestampMode = timestampMode && (ticks[0] > -tsLimit && ticks[0] < tsLimit);
timestampMode = timestampMode && (ticks[size - 1] > -tsLimit && ticks[size - 1] < tsLimit);
});
}
if (timestampMode || this._options.timeMode === 'timestamp') {
this.layout.xaxis.type = 'linear';
}
else {
this.layout.xaxis.type = 'date';
}
gtsList.forEach((gts, i) => {
if (gts.v) {
const size = gts.v.length;
const label = GTSLib.serializeGtsMetadata(gts);
const c = ColorLib.getColor(gts.id, this._options.scheme);
const color = ((data.params || [])[i] || { datasetColor: c }).datasetColor || c;
const series = {
type: 'scattergl',
mode: 'markers',
name: label,
x: [],
y: [],
text: [],
hoverinfo: 'none',
connectgaps: false,
visible: !(this._hiddenData.filter(h => h === gts.id).length > 0),
line: { color },
marker: {
symbol: 'line-ns-open',
color,
size: 20,
width: 5,
}
};
this.visibleGtsId.push(gts.id);
this.gtsId.push(gts.id);
if (timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp') {
this.layout.xaxis.type = 'linear';
}
else {
this.layout.xaxis.type = 'date';
}
const ticks = [];
series.text = [];
series.y = [];
if (size > 0) {
for (let v = 0; v < size; v++) {
const val = gts.v[v];
const t = val[0];
ticks.push(t);
series.text.push(val[val.length - 1]);
series.y.push((this.expanded ? i : 0) + 0.5);
this.minTick = (t < this.minTick) ? t : this.minTick;
this.maxTick = (t > this.maxTick) ? t : this.maxTick;
}
}
if (timestampMode || this._options.timeMode === 'timestamp') {
series.x = ticks;
}
else {
series.x = ticks.map(t => GTSLib.toISOString(t, this.divider, this._options.timeZone));
}
if (series.x.length > 0) {
dataset.push(series);
}
}
});
this.LOG.debug(['convert'], 'forEach value end', this.minTick, this.maxTick);
if (nonPlottable.length > 0) {
nonPlottable.forEach(g => {
g.v.forEach(value => {
const ts = value[0];
if (ts < this.minTick) {
this.minTick = ts;
}
if (ts > this.maxTick) {
this.maxTick = ts;
}
});
});
// if there is not any plottable data, we must add a fake one with id -1. This one will always be hidden.
if (0 === gtsList.length) {
if (!this.dataHashset[this.minTick]) {
this.dataHashset[this.minTick] = [0];
}
if (!this.dataHashset[this.maxTick]) {
this.dataHashset[this.maxTick] = [0];
}
this.visibility.push(false);
this.visibleGtsId.push(-1);
}
}
const x = { ...this.layout.xaxis, tick0: undefined, range: [] };
const pad = ChartLib.fraction2r(this.minTick, this.maxTick, 0.067);
if (timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp') {
x.tick0 = this.minTick - pad;
x.range = [x.tick0, this.maxTick + pad];
}
else {
x.tick0 = GTSLib.toISOString(this.minTick - pad, this.divider, this._options.timeZone);
x.range = [x.tick0, GTSLib.toISOString(this.maxTick + pad, this.divider, this._options.timeZone)];
}
this.layout.xaxis = x;
this.noData = dataset.length === 0;
const count = dataset.filter(d => d.y.length > 0).length;
this.layout.yaxis.range = [0, this.expanded ? count : 1];
this.LOG.debug(['convert end'], dataset, timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp');
return dataset;
}
toggle() {
this.LOG.debug(['this.expanded'], !!this.expanded);
this.expanded = !this.expanded;
this.drawChart(false);
}
setRealBounds(chartBounds) {
this.LOG.debug(['setRealBounds'], chartBounds, this._options.timeMode);
this.afterBoundsUpdate = true;
this.minTick = chartBounds.tsmin;
this.maxTick = chartBounds.tsmax;
this._options.bounds = this._options.bounds || {};
this._options.bounds.minDate = this.minTick;
this._options.bounds.maxDate = this.maxTick;
const x = {
tick0: undefined,
range: [],
};
if (this._options.showRangeSelector) {
x.rangeslider = {
bgcolor: 'transparent',
thickness: 40 / this.height
};
}
if (!!this._options.timeMode && this._options.timeMode === 'timestamp') {
x.tick0 = this.minTick / this.divider;
x.range = [this.minTick, this.maxTick];
}
else {
x.tick0 = GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone);
x.range = [
GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone),
GTSLib.toISOString(this.maxTick, this.divider, this._options.timeZone)
];
}
this.layout.xaxis = x;
this.layout = { ...this.layout };
}
resize(layout) {
//
}
}
WarpViewAnnotationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewAnnotationComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.SizeService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
WarpViewAnnotationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: WarpViewAnnotationComponent, selector: "warpview-annotation", inputs: { type: "type", hiddenData: "hiddenData", standalone: "standalone", height: "height" }, outputs: { pointHover: "pointHover", chartDraw: "chartDraw", boundsDidChange: "boundsDidChange" }, host: { listeners: { "keydown": "handleKeyDown($event)", "document:keydown": "handleKeyDown($event)", "keyup": "handleKeyup($event)", "document:keyup": "handleKeyup($event)" } }, usesInheritance: true, ngImport: i0, template: "<!--\n ~ Copyright 2021 SenX S.A.S.\n ~\n ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ http://www.apache.org/licenses/LICENSE-2.0\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n ~\n -->\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <button *ngIf=\"displayExpander && plotlyData && plotlyData.length > 1\" class=\"expander\" (click)=\"toggle()\"\n title=\"collapse/expand\">+/-\n </button>\n <div #toolTip class=\"wv-tooltip\"></div>\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <div *ngIf=\"!loading && !noData\" class=\"annotation-wrapper\">\n <div class=\"upperLine\" [ngStyle]=\"{left: standalone? '10px': marginLeft + 'px'}\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\" (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" className=\"chart\" (hover)=\"hover($event)\" (unhover)=\"unhover()\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n</div>\n", styles: [":root{--warp-view-chart-width: 100%;--warp-view-chart-height: 100%;--warp-view-datagrid-cell-padding: 5px;--warp-view-map-margin: 0;--warp-view-switch-height: 30px;--warp-view-switch-width: 100px;--warp-view-switch-radius: 18px;--warp-view-plot-chart-height: 100%;--warp-view-slider-pointer-size: 65px;--warp-view-resize-handle-height: 10px;--warp-view-tile-width: 100%;--warp-view-tile-height: 100%;--warp-view-font-color: #000000;--warp-view-bar-color: #dc3545;--warp-view-datagrid-odd-bg-color: #ffffff;--warp-view-datagrid-odd-color: #404040;--warp-view-datagrid-even-bg-color: #c0c0c0;--warp-view-datagrid-even-color: #000000;--warp-view-pagination-border-color: #c0c0c0;--warp-view-pagination-bg-color: #ffffff;--warp-view-pagination-active-bg-color: #4CAF50;--warp-view-pagination-active-color: #ffffff;--warp-view-pagination-active-border-color: #4CAF50;--warp-view-pagination-hover-bg-color: #c0c0c0;--warp-view-pagination-hover-color: #000000;--warp-view-pagination-hover-border-color: #c0c0c0;--warp-view-pagination-disabled-color: #c0c0c0;--warp-view-switch-inset-color: #c0c0c0;--warp-view-switch-inset-checked-color: #00cd00;--warp-view-switch-handle-color: radial-gradient(#ffffff 15%, #c0c0c0 100%);--warp-view-switch-handle-checked-color: radial-gradient(#ffffff 15%, #00cd00 100%);--warp-view-resize-handle-color: #c0c0c0;--warp-view-chart-legend-bg: #ffffff;--warp-view-chart-legend-color: #404040;--gts-classname-font-color: #004eff;--gts-labelname-font-color: #19A979;--gts-attrname-font-color: #ED4A7B;--gts-separator-font-color: #a0a0a0;--gts-labelvalue-font-color: #000000;--gts-attrvalue-font-color: #000000;--gts-stack-font-color: #000000;--gts-tree-expanded-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA7klEQVQ4T82TMW7CQBBF/0g+QOpINEkVCmpaLoBm5COk5QYoaeAY3MDSei2LGu4QKakiBA1tCpTK8kS2sLVe2xSh8XSrnf9m/s4s4c6gO/UYGEBEXlT1bK396bFGIjIJguA7iqJLkVNbYOZXItoQ0QHAzBhz9CCFeAVgCeAjy7Jpmqa/NUBEEgDzktqGuOKKO47j+KsGhGH4lOf5HsDIg5ycyqVYVd+steuGheLAzM9EtPMgW1VdVGWJ6N0YU1gpozVGH+K+gy/uBHR1crXUqNzbQXXhduJ69sd7cxOZ+UFVH5Mk+exb+YGt8n9+5h8up1sReYC0WAAAAABJRU5ErkJggg==);--gts-tree-collapsed-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0UlEQVQ4T6WTUW7CQAxEPQdozxYb9Qb94Aj9gQSoVCp6lMr21doDZFCQiFCU3YDY//d2PeOFPHnwJC+zAlVdA/jp+/6YmZ+1S0qCPxF5HUAAO3fvSpKS4ENEvm6gfUS0c5JiBma2Ibm/QiQPmbmdSqohquoA7GqSxRaapmkBjBkAeHP336t0UWBmHcnb+VcR4XcJpjDJLjPHkS4tleqZubmNiDHU6gumDQDYuvvh7hpV9V9EXgaA5Ka2jbMjmNk7yZOIfEfE8eFVfuSDLda4JDsD3FNdEckTC0YAAAAASUVORK5CYII=);--warp-view-popup-bg-color: #ffffff;--warp-view-popup-border-color: rgba(0, 0, 0, .2);--warp-view-popup-header-bg-color: #c0c0c0;--warp-view-popup-title-color: #404040;--warp-view-popup-close-color: #404040;--warp-view-popup-body-bg-color: #ffffff;--warp-view-popup-body-color: #000000;--warp-view-annotationtooltip-value-font-color: #004eff;--warp-view-annotationtooltip-font-color: #404040;--warp-view-spinner-color: #ff9900;--warp-view-tooltip-bg: #ffffff;--warp-view-tooltip-color: #000000;--warp-slider-connect-color: #ff9900;--warp-slider-handle-bg-color: #ffffff;--warp-slider-handle-color: #004eff;--warp-slider-handle-shadow: inset 0 0 1px #ffffff, inset 0 1px 7px #c0c0c0, 0 3px 6px -3px #a0a0a0}.noData{width:100%;text-align:center;color:var(--warp-view-chart-legend-color);position:relative}.js-plotly-plot .plotly .cursor-ew-resize{cursor:default!important}/*!\n * Copyright 2021 SenX S.A.S.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */.gts-classname{color:var(--gts-classname-font-color)}.gts-labelname{color:var(--gts-labelname-font-color)}.gts-attrname{color:var(--gts-attrname-font-color)}.gts-separator{color:var(--gts-separator-font-color)}.gts-labelvalue{color:var(--gts-labelvalue-font-color);font-style:italic}.gts-attrvalue{color:var(--gts-attrvalue-font-color);font-style:italic}:host{display:block}:host .expander{position:absolute;top:0;left:0;width:35px;z-index:9}:host #chartContainer{height:auto;position:relative;padding-top:30px}:host #chartContainer div.upperLine{position:absolute;top:0;left:0;height:0;border-bottom:1px solid var(--warp-view-chart-grid-color, #8e8e8e);right:10px}:host #chartContainer .annotation-wrapper{position:relative}:host .date{text-align:right;display:block;height:20px;vertical-align:middle;line-height:20px;position:absolute;top:0;left:40px}:host .chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .wv-tooltip{position:absolute;width:calc(100% - 50px);z-index:999;margin-left:10px;top:-1000px;font-size:10px}:host .wv-tooltip .tooltip-body{border:1px solid grey;border-radius:5px;background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;padding-left:10px;padding-right:10px;width:auto;max-width:100%;vertical-align:middle;line-height:10px;height:40px;overflow:visible;margin:1px}:host .wv-tooltip .tooltip-body .chip{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;cursor:pointer}:host .wv-tooltip .tooltip-body.trimmed{max-width:49%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body.full{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body .value{color:var(--warp-view-annotationtooltip-value-font-color)}:host .wv-tooltip .tooltip-body .tooltip-date{font-weight:700;text-align:left;display:block;width:100%;height:.8rem;padding-top:5px;padding-bottom:5px;vertical-align:middle;line-height:.8rem}:host .wv-tooltip .tooltip-body .round{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;margin-right:5px}:host .wv-tooltip.left .tooltip-body{text-align:left;float:left}:host .wv-tooltip.left .tooltip-body .tooltip-date{text-align:left}:host .wv-tooltip.right .tooltip-body{float:right}\n"], components: [{ type: i2.WarpViewSpinnerComponent, selector: "warpview-spinner", inputs: ["message"] }, { type: i3.PlotlyComponent, selector: "warpview-plotly", inputs: ["data", "layout", "config", "debug", "frames", "style", "divId", "revision", "className", "useResizeHandler", "updateOnLayoutChange", "updateOnDataChange", "updateOnlyWithRevision"], outputs: ["initialized", "update", "purge", "error", "afterExport", "afterPlot", "animated", "animatingFrame", "animationInterrupted", "autoSize", "beforeExport", "buttonClicked", "click", "plotly_click", "clickAnnotation", "deselect", "doubleClick", "framework", "hover", "legendClick", "legendDoubleClick", "relayout", "restyle", "redraw", "selected", "selecting", "sliderChange", "sliderEnd", "sliderStart", "transitioning", "transitionInterrupted", "unhover", "relayouting"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewAnnotationComponent, decorators: [{
type: Component,
args: [{ selector: 'warpview-annotation', encapsulation: ViewEncapsulation.ShadowDom, template: "<!--\n ~ Copyright 2021 SenX S.A.S.\n ~\n ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ http://www.apache.org/licenses/LICENSE-2.0\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n ~\n -->\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <button *ngIf=\"displayExpander && plotlyData && plotlyData.length > 1\" class=\"expander\" (click)=\"toggle()\"\n title=\"collapse/expand\">+/-\n </button>\n <div #toolTip class=\"wv-tooltip\"></div>\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <div *ngIf=\"!loading && !noData\" class=\"annotation-wrapper\">\n <div class=\"upperLine\" [ngStyle]=\"{left: standalone? '10px': marginLeft + 'px'}\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\" (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" className=\"chart\" (hover)=\"hover($event)\" (unhover)=\"unhover()\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n</div>\n", styles: [":root{--warp-view-chart-width: 100%;--warp-view-chart-height: 100%;--warp-view-datagrid-cell-padding: 5px;--warp-view-map-margin: 0;--warp-view-switch-height: 30px;--warp-view-switch-width: 100px;--warp-view-switch-radius: 18px;--warp-view-plot-chart-height: 100%;--warp-view-slider-pointer-size: 65px;--warp-view-resize-handle-height: 10px;--warp-view-tile-width: 100%;--warp-view-tile-height: 100%;--warp-view-font-color: #000000;--warp-view-bar-color: #dc3545;--warp-view-datagrid-odd-bg-color: #ffffff;--warp-view-datagrid-odd-color: #404040;--warp-view-datagrid-even-bg-color: #c0c0c0;--warp-view-datagrid-even-color: #000000;--warp-view-pagination-border-color: #c0c0c0;--warp-view-pagination-bg-color: #ffffff;--warp-view-pagination-active-bg-color: #4CAF50;--warp-view-pagination-active-color: #ffffff;--warp-view-pagination-active-border-color: #4CAF50;--warp-view-pagination-hover-bg-color: #c0c0c0;--warp-view-pagination-hover-color: #000000;--warp-view-pagination-hover-border-color: #c0c0c0;--warp-view-pagination-disabled-color: #c0c0c0;--warp-view-switch-inset-color: #c0c0c0;--warp-view-switch-inset-checked-color: #00cd00;--warp-view-switch-handle-color: radial-gradient(#ffffff 15%, #c0c0c0 100%);--warp-view-switch-handle-checked-color: radial-gradient(#ffffff 15%, #00cd00 100%);--warp-view-resize-handle-color: #c0c0c0;--warp-view-chart-legend-bg: #ffffff;--warp-view-chart-legend-color: #404040;--gts-classname-font-color: #004eff;--gts-labelname-font-color: #19A979;--gts-attrname-font-color: #ED4A7B;--gts-separator-font-color: #a0a0a0;--gts-labelvalue-font-color: #000000;--gts-attrvalue-font-color: #000000;--gts-stack-font-color: #000000;--gts-tree-expanded-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA7klEQVQ4T82TMW7CQBBF/0g+QOpINEkVCmpaLoBm5COk5QYoaeAY3MDSei2LGu4QKakiBA1tCpTK8kS2sLVe2xSh8XSrnf9m/s4s4c6gO/UYGEBEXlT1bK396bFGIjIJguA7iqJLkVNbYOZXItoQ0QHAzBhz9CCFeAVgCeAjy7Jpmqa/NUBEEgDzktqGuOKKO47j+KsGhGH4lOf5HsDIg5ycyqVYVd+steuGheLAzM9EtPMgW1VdVGWJ6N0YU1gpozVGH+K+gy/uBHR1crXUqNzbQXXhduJ69sd7cxOZ+UFVH5Mk+exb+YGt8n9+5h8up1sReYC0WAAAAABJRU5ErkJggg==);--gts-tree-collapsed-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0UlEQVQ4T6WTUW7CQAxEPQdozxYb9Qb94Aj9gQSoVCp6lMr21doDZFCQiFCU3YDY//d2PeOFPHnwJC+zAlVdA/jp+/6YmZ+1S0qCPxF5HUAAO3fvSpKS4ENEvm6gfUS0c5JiBma2Ibm/QiQPmbmdSqohquoA7GqSxRaapmkBjBkAeHP336t0UWBmHcnb+VcR4XcJpjDJLjPHkS4tleqZubmNiDHU6gumDQDYuvvh7hpV9V9EXgaA5Ka2jbMjmNk7yZOIfEfE8eFVfuSDLda4JDsD3FNdEckTC0YAAAAASUVORK5CYII=);--warp-view-popup-bg-color: #ffffff;--warp-view-popup-border-color: rgba(0, 0, 0, .2);--warp-view-popup-header-bg-color: #c0c0c0;--warp-view-popup-title-color: #404040;--warp-view-popup-close-color: #404040;--warp-view-popup-body-bg-color: #ffffff;--warp-view-popup-body-color: #000000;--warp-view-annotationtooltip-value-font-color: #004eff;--warp-view-annotationtooltip-font-color: #404040;--warp-view-spinner-color: #ff9900;--warp-view-tooltip-bg: #ffffff;--warp-view-tooltip-color: #000000;--warp-slider-connect-color: #ff9900;--warp-slider-handle-bg-color: #ffffff;--warp-slider-handle-color: #004eff;--warp-slider-handle-shadow: inset 0 0 1px #ffffff, inset 0 1px 7px #c0c0c0, 0 3px 6px -3px #a0a0a0}.noData{width:100%;text-align:center;color:var(--warp-view-chart-legend-color);position:relative}.js-plotly-plot .plotly .cursor-ew-resize{cursor:default!important}/*!\n * Copyright 2021 SenX S.A.S.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */.gts-classname{color:var(--gts-classname-font-color)}.gts-labelname{color:var(--gts-labelname-font-color)}.gts-attrname{color:var(--gts-attrname-font-color)}.gts-separator{color:var(--gts-separator-font-color)}.gts-labelvalue{color:var(--gts-labelvalue-font-color);font-style:italic}.gts-attrvalue{color:var(--gts-attrvalue-font-color);font-style:italic}:host{display:block}:host .expander{position:absolute;top:0;left:0;width:35px;z-index:9}:host #chartContainer{height:auto;position:relative;padding-top:30px}:host #chartContainer div.upperLine{position:absolute;top:0;left:0;height:0;border-bottom:1px solid var(--warp-view-chart-grid-color, #8e8e8e);right:10px}:host #chartContainer .annotation-wrapper{position:relative}:host .date{text-align:right;display:block;height:20px;vertical-align:middle;line-height:20px;position:absolute;top:0;left:40px}:host .chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .wv-tooltip{position:absolute;width:calc(100% - 50px);z-index:999;margin-left:10px;top:-1000px;font-size:10px}:host .wv-tooltip .tooltip-body{border:1px solid grey;border-radius:5px;background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;padding-left:10px;padding-right:10px;width:auto;max-width:100%;vertical-align:middle;line-height:10px;height:40px;overflow:visible;margin:1px}:host .wv-tooltip .tooltip-body .chip{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;cursor:pointer}:host .wv-tooltip .tooltip-body.trimmed{max-width:49%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body.full{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body .value{color:var(--warp-view-annotationtooltip-value-font-color)}:host .wv-tooltip .tooltip-body .tooltip-date{font-weight:700;text-align:left;display:block;width:100%;height:.8rem;padding-top:5px;padding-bottom:5px;vertical-align:middle;line-height:.8rem}:host .wv-tooltip .tooltip-body .round{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;margin-right:5px}:host .wv-tooltip.left .tooltip-body{text-align:left;float:left}:host .wv-tooltip.left .tooltip-body .tooltip-date{text-align:left}:host .wv-tooltip.right .tooltip-body{float:right}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.SizeService }, { type: i0.NgZone }]; }, propDecorators: { type: [{
type: Input,
args: ['type']
}], hiddenData: [{
type: Input,
args: ['hiddenData']
}], standalone: [{
type: Input,
args: ['standalone']
}], height: [{
type: Input,
args: ['height']
}], pointHover: [{
type: Output,
args: ['pointHover']
}], chartDraw: [{
type: Output,
args: ['chartDraw']
}], boundsDidChange: [{
type: Output,
args: ['boundsDidChange']
}], handleKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}, {
type: HostListener,
args: ['document:keydown', ['$event']]
}], handleKeyup: [{
type: HostListener,
args: ['keyup', ['$event']]
}, {
type: HostListener,
args: ['document:keyup', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FycC12aWV3LWFubm90YXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvd2FycHZpZXctbmcvc3JjL2xpYi9lbGVtZW50cy93YXJwLXZpZXctYW5ub3RhdGlvbi93YXJwLXZpZXctYW5ub3RhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy93YXJwdmlldy1uZy9zcmMvbGliL2VsZW1lbnRzL3dhcnAtdmlldy1hbm5vdGF0aW9uL3dhcnAtdmlldy1hbm5vdGF0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3JJLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQyxPQUFPLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUVyQyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFFM0MsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUMxRCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLHlCQUF5QixDQUFDOzs7Ozs7QUFTcEQsTUFBTSxPQUFPLDJCQUE0QixTQUFRLGlCQUFpQjtJQXdEaEUsWUFDUyxFQUFjLEVBQ2QsUUFBbUIsRUFDbkIsV0FBd0IsRUFDeEIsTUFBYztRQUVyQixLQUFLLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFMbEMsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUNkLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQVZOLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFFTixlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUN0QyxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUM5QixvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFhckUsb0JBQWUsR0FBRyxJQUFJLENBQUM7UUFDdkIsV0FBTSxHQUFpQjtZQUNyQixVQUFVLEVBQUUsS0FBSztZQUNqQixTQUFTLEVBQUUsU0FBUztZQUNwQixLQUFLLEVBQUU7Z0JBQ0wsU0FBUyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLEtBQUs7Z0JBQ2pCLFNBQVMsRUFBRSxLQUFLO2dCQUNoQixVQUFVLEVBQUUsS0FBSztnQkFDakIsY0FBYyxFQUFFLElBQUk7Z0JBQ3BCLFFBQVEsRUFBRSxLQUFLO2FBQ2hCO1lBQ0QsUUFBUSxFQUFFLEtBQUs7WUFDZixVQUFVLEVBQUUsS0FBSztZQUNqQixLQUFLLEVBQUU7Z0JBQ0wsY0FBYyxFQUFFLEtBQUs7Z0JBQ3JCLFVBQVUsRUFBRSxJQUFJO2dCQUNoQixLQUFLLEVBQUUsQ0FBQztnQkFDUixTQUFTLEVBQUUsQ0FBQztnQkFDWixLQUFLLEVBQUUsQ0FBQztnQkFDUixNQUFNLEVBQUUsQ0FBQztnQkFDVCxTQUFTLEVBQUUsUUFBUTtnQkFDbkIsT0FBTyxFQUFFLFlBQVk7Z0JBQ3JCLFVBQVUsRUFBRSxLQUFLO2dCQUNqQixTQUFTLEVBQUUsS0FBSztnQkFDaEIsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsUUFBUSxFQUFFLElBQUk7YUFDZjtZQUNELE1BQU0sRUFBRTtnQkFDTixDQUFDLEVBQUUsQ0FBQztnQkFDSixDQUFDLEVBQUUsRUFBRTtnQkFDTCxDQUFDLEVBQUUsRUFBRTtnQkFDTCxDQUFDLEVBQUUsRUFBRTthQUNOO1NBQ0YsQ0FBQztRQUNGLGVBQVUsR0FBRyxFQUFFLENBQUM7UUFDaEIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQix5Q0FBeUM7UUFDL0IsVUFBSyxHQUFHLFlBQVksQ0FBQztRQUN2QixlQUFVLEdBQWMsRUFBRSxDQUFDO1FBQzNCLGdCQUFXLEdBQUcsSUFBSSxDQUFDO1FBRW5CLFlBQU8sR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQzNCLFlBQU8sR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQzNCLGlCQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLFVBQUssR0FBRyxFQUFFLENBQUM7UUFDWCxnQkFBVyxHQUFHLEVBQUUsQ0FBQztRQUNqQixlQUFVLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLGdCQUFXLEdBQWdCLElBQUksV0FBVyxFQUFFLENBQUM7UUFDN0Msc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1FBQzFCLGNBQVMsR0FBRyxJQUFJLENBQUM7UUF0RHZCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxNQUFNLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUEvREQsSUFBbUIsSUFBSSxDQUFDLElBQVk7UUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztRQUNsQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELElBQXlCLFVBQVUsQ0FBQyxVQUFvQjtRQUN0RCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLG9CQUFvQixDQUFDLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQztRQUM5QixJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3RFLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxFQUFFLGtCQUFrQixFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzFFLElBQUksa0JBQWtCLEtBQUssYUFBYSxFQUFFO1lBQ3hDLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNuQixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUM7WUFDbEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7b0JBQ3JDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2hCO3FCQUFNO29CQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2pCO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxFQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQzthQUNuRDtZQUNELElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3JCLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2FBQ25EO1lBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxtQkFBbUIsRUFBRSxTQUFTLENBQUMsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1NBQ2pGO0lBQ0gsQ0FBQztJQUVELElBQXlCLFVBQVUsQ0FBQyxZQUFxQjtRQUN2RCxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzdDLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxZQUFZLEVBQUU7WUFDckMsSUFBSSxDQUFDLFdBQVcsR0FBRyxZQUFZLENBQUM7WUFDaEMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1NBQ2xCO0lBQ0gsQ0FBQztJQUVELElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBMEVELGFBQWEsQ0FBQyxNQUFxQjtRQUNqQyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEtBQUssU0FBUyxFQUFFO1lBQzVCLElBQUksQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDOUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxFQUFFO29CQUMvRCxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDakY7WUFDSCxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDVDtJQUNILENBQUM7SUFJRCxXQUFXLENBQUMsTUFBcUI7UUFDL0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzNDLElBQUksTUFBTSxDQUFDLEdBQUcsS0FBSyxTQUFTLEVBQUU7WUFDNUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxFQUFFO2dCQUMvRCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ2hCLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQzdCO2dCQUNELElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQ3BGO1NBQ0Y7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLE9BQWMsRUFBRSxPQUFnQjtRQUNyQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFFRCxZQUFZLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxVQUFVO1FBQy9CLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsY0FBYyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsUUFBUSx