import { bisector } from 'd3-array' ; import { DataPoint , MinimalViewPortConfig , Primitive } from '../../../utils/dataTypes' ; import { isMinimalStaticViewport } from '../../../utils/predicates' ; import { parseDuration } from '../../../utils/time' ; export const pointBisector = bisector ( ( p ) => p . x ) ; /**
 * Get Visible Data
 *
 * Returns the data points which are required for the chart to correctly render.
 * This assumes linear interpolation between points
 * TODO: Support other interpolation methods
 *
 * NOTE: It's possible to have data not in the viewport which is required for the chart to render
 * it's fully visualization correctly. For Instance, even if a point isn't visible in the viewport, it may
 * be used within interpolation to calculate a path between the points which is within the viewport.
 *
 * Different interpolation methods need larger amount of context around the viewport to correctly render
 * the chart visualization.
 */ export const getVisibleData = < T extends Primitive > ( data , viewport , includeBoundaryPoints = true ) : DataPoint < T > [ ] => { const start = isMinimalStaticViewport ( viewport ) ? new Date ( viewport . start ) : new Date ( Date . now ( ) - parseDuration ( viewport . duration ) ) ; const end = isMinimalStaticViewport ( viewport ) ? new Date ( viewport . end ) : new Date ( ) ; if ( data . length === 0 ) { return [ ] ; } if ( start . getTime ( ) > data [ data . length - 1 ] . x ) { return [ ] ; } if ( end . getTime ( ) < data [ 0 ] . x ) { return [ ] ; } const startIndex = Math . max ( pointBisector . left ( data , start ) - ( includeBoundaryPoints ? 1 : 0 ) , 0 ) ; const endIndex = Math . min ( pointBisector . right ( data , end ) - ( includeBoundaryPoints ? 0 : 1 ) , data . length - 1 ) ; return data . slice ( startIndex , endIndex + 1 ) ; } ; /**
 * Returns all data before or at the given date.
 *
 * Assumes data is ordered chronologically.
 */ export const getDataBeforeDate = < T extends Primitive > ( data , date ) : DataPoint < T > [ ] => { if ( data . length === 0 ) { return [ ] ; } if ( date . getTime ( ) < data [ 0 ] . x ) { return [ ] ; } const endIndex = Math . min ( pointBisector . right ( data , date ) - 1 , data . length - 1 ) ; return data . slice ( 0 , endIndex + 1 ) ; } ;