import { LinearRegressionResult , Trend , TrendResult } from './types' ; import { getVisibleData } from '../dataFilters' ; import { getDataPoints } from '../../../../utils/getDataPoints' ; import { DataStream , Timestamp , ViewPortConfig } from '../../../../utils/dataTypes' ; import { TREND_TYPE } from '../../../../utils/dataConstants' ; param data const linearRegression = ( data ) : LinearRegressionResult | null => { const dataPoints = data . data ; const len = dataPoints . length ; if ( len === 0 ) { return null ; } const startDate = dataPoints [ 0 ] . x ; let sumX = 0 ; let sumY = 0 ; let sumXX = 0 ; let sumXY = 0 ; for ( let i = 0 ; i < len ; i += 1 ) { const { x , y } = dataPoints [ i ] ; const time = x - startDate ; sumX += time ; sumY += y ; sumXX += time * time ; sumXY += time * y ; } const run = len * sumXX - sumX * sumX ; const rise = len * sumXY - sumX * sumY ; const gradient = run === 0 ? 0 : rise / run ; const intercept = sumY / len - ( gradient * sumX ) / len ; return { type : TREND_TYPE . LINEAR , dataStreamId : data . id , equation : { gradient , intercept } , startDate : new Date ( startDate ) , } ; } ; param data param trendType export const computeTrendResult = ( dataStream , trendType ) : TrendResult | null => { switch ( trendType ) { case TREND_TYPE . LINEAR : return linearRegression ( dataStream ) ; default : console . error ( `Unable to compute trend result for trend type '${ trendType }'.` ) ; return null ; } } ; /**
 * Computes trend results for all requested trends using the data in the provided viewport (including boundary points).
 */ export const getAllTrendResults = ( viewport , dataStreams , trends ) : TrendResult [ ] => { const trendResults = [ ] ; dataStreams . forEach ( stream => { const { id } = stream ; const dataPoints = getDataPoints ( stream , stream . resolution ) ; const dataInViewport = getVisibleData ( dataPoints , viewport ) ; if ( dataInViewport . length >= 2 ) { trends . filter ( ( { dataStreamId } ) => id === dataStreamId ) . forEach ( ( { type , color } ) => { const trendResult = computeTrendResult ( { ... stream , data : dataInViewport } , type ) ; if ( trendResult ) { trendResults . push ( { ... trendResult , color } ) ; } } ) ; } } ) ; return trendResults ; } ; /**
 * Calculates the value of the given trend result at the requested date.
 */ export const getTrendValue = ( trendResult , timestamp ) : number => { switch ( trendResult . type ) { case TREND_TYPE . LINEAR : return ( ( timestamp - trendResult . startDate . getTime ( ) ) * trendResult . equation . gradient + trendResult . equation . intercept ) ; default : throw new Error ( `Cannot compute trend value for trend of type '${ trendResult . type }' on data stream ${ trendResult . dataStreamId }.` ) ; } } ;