import { DataPoint } from '../../../utils/dataTypes' ; import { YAnnotation } from './types' ; const enum BUFFER { STANDARD = 0.15 , SAME_VALUE = 0.5 } const orderOfMagnitude = ( n ) : number => { const o = Math . log10 ( Math . abs ( n ) ) ; return Math . ceil ( o ) ; } ; const roundedMagnitude = ( n ) => { const m = orderOfMagnitude ( n ) ; return n > 0 ? 10 ** m : - 1 * 10 ** m ; } ; const DEFAULT_ROUNDING_DIVISOR = 50 ; const roundedToNearest = ( rMag , n ) => ( roundUp ) => { const a = n / ( rMag / DEFAULT_ROUNDING_DIVISOR ) ; const b = rMag / DEFAULT_ROUNDING_DIVISOR ; return roundUp ? Math . ceil ( a ) * b : Math . floor ( a ) * b ; } ; const roundToOrderOfMagnitude = ( n , min ) : number => { if ( n === 0 ) { return 0 ; } const roundedY = roundedToNearest ( roundedMagnitude ( n ) , n ) ; return n < 0 ? roundedY ( min ) : roundedY ( ! min ) ; } ; export type YRange = { yMin : number ; yMax : number ; } ; export const DEFAULT_Y_RANGE = { yMax : 1000 , yMin : 1 , } ; const getBufferHeightByRange = ( yMin , yMax ) : number => { let bufferHeight = 0 ; if ( yMax === yMin ) { bufferHeight = yMax !== 0 ? Math . abs ( yMax * BUFFER . SAME_VALUE ) : BUFFER . SAME_VALUE ; } else { bufferHeight = ( yMax - yMin ) * BUFFER . STANDARD ; } return bufferHeight ; } ; const getYRangeWithBuffers = ( { yValues , startFromZero } ) : YRange => { if ( yValues . length === 0 ) { return DEFAULT_Y_RANGE ; } const dataRange = yValues . reduce ( ( yRange , currentY ) => ( { yMin : Math . min ( currentY , yRange . yMin ) , yMax : Math . max ( currentY , yRange . yMax ) , } ) , { yMin : Infinity , yMax : - Infinity , } ) ; const noNegativeValues = dataRange . yMin >= 0 ; const noPositiveValues = dataRange . yMax <= 0 ; const bufferHeight = getBufferHeightByRange ( dataRange . yMin , dataRange . yMax ) ; let yMax = dataRange . yMax + bufferHeight ; let yMin = dataRange . yMin - bufferHeight ; if ( dataRange . yMax !== 0 || dataRange . yMin !== 0 ) { if ( startFromZero && noNegativeValues ) { yMin = 0 ; } if ( startFromZero && noPositiveValues ) { yMax = 0 ; } } return { yMin : roundToOrderOfMagnitude ( yMin , true ) , yMax : roundToOrderOfMagnitude ( yMax , false ) , } ; } ; export const getYRange = ( { points , yAnnotations , startFromZero , } ) : YRange => { const yDataValues = points . map ( point => point . y as number ) ; const yAnnotationValues = yAnnotations . map ( yAnnotation => yAnnotation . value as number ) ; return getYRangeWithBuffers ( { yValues : [ ... yDataValues , ... yAnnotationValues ] , startFromZero } ) ; } ; export const currentYRange = ( ) => { let lastYRange = DEFAULT_Y_RANGE ; return ( { points , yAnnotations , startFromZero , } ) => { if ( points . length === 0 && yAnnotations . length === 0 ) { return lastYRange ; } lastYRange = getYRange ( { points , yAnnotations , startFromZero } ) ; return lastYRange ; } ; } ;