import { TimeSerie, Options, yAxisOrientation } from './types'; import cloneDeep from 'lodash/cloneDeep'; import min from 'lodash/min'; import minBy from 'lodash/minBy'; import max from 'lodash/max'; import maxBy from 'lodash/maxBy'; const DEFAULT_AXIS_RANGE = [0, 1]; const DEFAULT_TRANSFORM = { x: 0, y: 0, k: 1 } // TODO: replace all getters with fields. Because getters will be recalculated on each call // TODO: remove duplicates in max/min values. // TODO: add scales // TODO: PodState can be divided in two classes, but it is hard now. export class PodState { private _xValueRange: [number, number]; private _yValueRange: [number, number]; private _y1ValueRange: [number, number] | undefined = undefined; // can be undefined, because y1 - is an optional param private _transform: { x: number, y: number, k: number } = cloneDeep(DEFAULT_TRANSFORM); constructor( protected series: T[], protected options: O, ) { this.initRanges(); } protected initRanges(): void { this._xValueRange = [this.minValueX, this.maxValueX]; this._yValueRange = [this.minValueY, this.maxValueY]; if(this.options.axis.y1.isActive) { this._y1ValueRange = [this.minValueY1, this.maxValueY1]; } } get xValueRange(): [number, number] | undefined { return this._xValueRange; } get yValueRange(): [number, number] | undefined { return this._yValueRange; } get y1ValueRange(): [number, number] | undefined { return this._y1ValueRange; } get transform(): { x?: number, y?: number, k?: number } { return this._transform; } set xValueRange(range: [number, number]) { this._xValueRange = range; } set yValueRange(range: [number, number]) { this._yValueRange = range; } set y1ValueRange(range: [number, number]) { this._y1ValueRange = range; } set transform(transform: { x?: number, y?: number, k?: number }) { this._transform.x = transform.x !== undefined ? transform.x : this._transform.x; this._transform.y = transform.y !== undefined ? transform.y : this._transform.y; this._transform.k = transform.k !== undefined ? transform.k : this._transform.k; } get minValueY(): number { if(this.isSeriesUnavailable) { return DEFAULT_AXIS_RANGE[0]; } if(this.options.axis.y !== undefined && this.options.axis.y.range !== undefined) { return min(this.options.axis.y.range); } const minValue = min( this.series .filter(serie => serie.visible !== false && this.filterSerieByYAxisOrientation(serie, yAxisOrientation.LEFT)) .map( serie => minBy(serie.datapoints, dp => dp[1])[1] ) ); return minValue; } get maxValueY(): number { if(this.isSeriesUnavailable) { return DEFAULT_AXIS_RANGE[1]; } if(this.options.axis.y !== undefined && this.options.axis.y.range !== undefined) { return max(this.options.axis.y.range); } const maxValue = max( this.series .filter(serie => serie.visible !== false && this.filterSerieByYAxisOrientation(serie, yAxisOrientation.LEFT)) .map( serie => maxBy(serie.datapoints, dp => dp[1])[1] ) ); return maxValue; } get minValueX(): number { if(this.isSeriesUnavailable) { return DEFAULT_AXIS_RANGE[0]; } if(this.options.axis.x !== undefined && this.options.axis.x.range !== undefined) { return min(this.options.axis.x.range); } const minValue = min( this.series .filter(serie => serie.visible !== false) .map( serie => minBy(serie.datapoints, dp => dp[0])[0] ) ); return minValue; } get maxValueX(): number { if(this.isSeriesUnavailable) { return DEFAULT_AXIS_RANGE[1]; } if(this.options.axis.x !== undefined && this.options.axis.x.range !== undefined) { return max(this.options.axis.x.range) } const maxValue = max( this.series .filter(serie => serie.visible !== false) .map( serie => maxBy(serie.datapoints, dp => dp[0])[0] ) ); return maxValue; } get minValueY1(): number { if(this.isSeriesUnavailable || this.options.axis.y1 === undefined || this.options.axis.y1.isActive === false) { return DEFAULT_AXIS_RANGE[0]; } if(this.options.axis.y1.range !== undefined) { return min(this.options.axis.y1.range); } const minValue = min( this.series .filter(serie => serie.visible !== false && this.filterSerieByYAxisOrientation(serie, yAxisOrientation.RIGHT)) .map( serie => minBy(serie.datapoints, dp => dp[1])[1] ) ); return minValue; } get maxValueY1(): number { if(this.isSeriesUnavailable || this.options.axis.y1 === undefined || this.options.axis.y1.isActive === false) { return DEFAULT_AXIS_RANGE[1]; } if(this.options.axis.y1 !== undefined && this.options.axis.y1.range !== undefined) { return max(this.options.axis.y1.range); } const maxValue = max( this.series .filter(serie => serie.visible !== false && this.filterSerieByYAxisOrientation(serie, yAxisOrientation.RIGHT)) .map( serie => maxBy(serie.datapoints, dp => dp[1])[1] ) ); return maxValue; } get isSeriesUnavailable(): boolean { return this.series === undefined || this.series.length === 0 || max(this.series.map(serie => serie.datapoints.length)) === 0; } protected filterSerieByYAxisOrientation(serie: T, orientation: yAxisOrientation): boolean { if(serie.yOrientation === undefined || serie.yOrientation === yAxisOrientation.BOTH) { return true; } return serie.yOrientation === orientation; } }