import { median , quantile , IEventListener } from '../internal' ; import { toolbar } from './annotations' ; import Column , { widthChanged , labelChanged , metaDataChanged , dirty , dirtyHeader , dirtyValues , rendererTypeChanged , groupRendererChanged , summaryRendererChanged , visibilityChanged , dirtyCaches , DEFAULT_COLOR , } from './Column' ; import type CompositeColumn from './CompositeColumn' ; import type { addColumn , filterChanged , moveColumn , removeColumn } from './CompositeColumn' ; import CompositeNumberColumn , { ICompositeNumberColumnDesc } from './CompositeNumberColumn' ; import type { IDataRow , ITypeFactory } from './interfaces' ; import { EAdvancedSortMethod } from './INumberColumn' ; import { integrateDefaults } from './internal' ; param label returns { { type : string , label : string } } export function createReduceDesc ( label = 'Reduce' ) { return { type : 'reduce' , label } ; } export interface IReduceDesc { readonly reduce ? : EAdvancedSortMethod ; } export declare type IReduceColumnDesc = IReduceDesc & ICompositeNumberColumnDesc ; asMemberOf event export declare function reduceChanged ( previous , current ) ; /**
 * combines multiple columns by using the maximal value
 */ @ toolbar ( 'reduce' ) export default class ReduceColumn extends CompositeNumberColumn { static readonly EVENT_REDUCE_CHANGED = 'reduceChanged' ; private reduce : EAdvancedSortMethod ; constructor ( id , desc ) { super ( id , integrateDefaults ( desc , { renderer : 'interleaving' , groupRenderer : 'interleaving' , summaryRenderer : 'interleaving' , } ) ) ; this . reduce = desc . reduce || EAdvancedSortMethod . max ; } get label ( ) { const l = super . getMetaData ( ) . label ; if ( l !== 'Reduce' ) { return l ; } return `${ this . reduce [ 0 ] . toUpperCase ( ) }${ this . reduce . slice ( 1 ) }(${ this . children . map ( ( d ) => d . label ) . join ( ', ' ) })` ; } getColor ( row ) { const c = this . _children ; if ( c . length === 0 || this . reduce === EAdvancedSortMethod . q1 || this . reduce === EAdvancedSortMethod . q3 || this . reduce === EAdvancedSortMethod . mean ) { return DEFAULT_COLOR ; } const v = this . compute ( row ) ; const selected = c . find ( ( c ) => c . getValue ( row ) === v ) ; return selected ? selected . getColor ( row ) : DEFAULT_COLOR ; } protected compute ( row ) { const vs = this . _children . map ( ( d ) => d . getValue ( row ) ) . filter ( ( d ) => ! Number . isNaN ( d ) ) ; if ( vs . length === 0 ) { return NaN ; } switch ( this . reduce ) { case EAdvancedSortMethod . mean : return vs . reduce ( ( a , b ) => a + b , 0 ) / vs . length ; case EAdvancedSortMethod . max : return vs . reduce ( ( a , b ) => Math . max ( a , b ) , Number . NEGATIVE_INFINITY ) ; case EAdvancedSortMethod . min : return vs . reduce ( ( a , b ) => Math . min ( a , b ) , Number . POSITIVE_INFINITY ) ; case EAdvancedSortMethod . median : return median ( vs ) ! ; case EAdvancedSortMethod . q1 : return quantile ( vs . sort ( ( a , b ) => a - b ) , 0.25 ) ! ; case EAdvancedSortMethod . q3 : return quantile ( vs . sort ( ( a , b ) => a - b ) , 0.75 ) ! ; } } protected createEventList ( ) { return super . createEventList ( ) . concat ( [ ReduceColumn . EVENT_REDUCE_CHANGED ] ) ; } on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) { return super . on ( type , listener ) ; } getReduce ( ) { return this . reduce ; } setReduce ( reduce ) { if ( this . reduce === reduce ) { return ; } this . fire ( [ ReduceColumn . EVENT_REDUCE_CHANGED , Column . EVENT_DIRTY_VALUES , Column . EVENT_DIRTY_CACHES , Column . EVENT_DIRTY ] , this . reduce , ( this . reduce = reduce ) ) ; } dump ( toDescRef ) { const r = super . dump ( toDescRef ) ; r . reduce = this . reduce ; return r ; } restore ( dump , factory ) { this . reduce = dump . reduce || this . reduce ; super . restore ( dump , factory ) ; } get canJustAddNumbers ( ) { return true ; } getExportValue ( row , format ) { if ( format === 'json' ) { return { value : this . getRawNumber ( row ) , children : this . children . map ( ( d ) => d . getExportValue ( row , format ) ) , } ; } return super . getExportValue ( row , format ) ; } }