import { schemeCategory10 , schemeSet3 } from 'd3-scale-chromatic' ; import { OrderedSet } from '../internal' ; import Column , { DEFAULT_COLOR } from './Column' ; import { defaultGroup , ECompareValueType , IGroup , IGroupParent , IndicesArray , IOrderedGroup } from './interfaces' ; internal export function integrateDefaults < T > ( desc , defaults = { } ) { Object . keys ( defaults ) . forEach ( ( key ) => { const typed = key as keyof T ; if ( typeof desc [ typed ] === 'undefined' ) { ( desc as any ) [ typed ] = defaults [ typed ] ; } } ) ; return desc ; } internal export function patternFunction ( pattern , ... args ) { return new Function ( 'value' , ... args , `
  const escapedValue = encodeURIComponent(String(value));
  return \`${ pattern }\`;
 ` ) as any ; } internal export function joinGroups ( groups ) { if ( groups . length === 0 ) { return { ... defaultGroup } ; } if ( groups . length === 1 && ! groups [ 0 ] . parent ) { return { ... groups [ 0 ] } ; } const parents = [ ] ; for ( const group of groups ) { const gparents = [ ] ; let g = group ; while ( g . parent ) { gparents . unshift ( g . parent ) ; g = g . parent ; } parents . push ( ... gparents ) ; parents . push ( Object . assign ( { subGroups : [ ] } , group ) ) ; } parents . slice ( 1 ) . forEach ( ( g , i ) => { g . parent = parents [ i ] ; g . name = `${ parents [ i ] . name } ∩ ${ g . name }` ; g . color = g . color !== DEFAULT_COLOR ? g . color : g . parent . color ; parents [ i ] . subGroups = [ g ] ; } ) ; return parents [ parents . length - 1 ] ; } export function duplicateGroup < T extends IOrderedGroup | IGroupParent > ( group ) { const clone = Object . assign ( { } , group ) as T ; delete ( clone as IOrderedGroup ) . order ; if ( isGroupParent ( clone ) ) { clone . subGroups = [ ] ; } if ( clone . parent ) { clone . parent = duplicateGroup ( clone . parent ) ; clone . parent ! . subGroups . push ( clone ) ; } return clone ; } internal export function toGroupID ( group ) { return group . name ; } internal export function isOrderedGroup ( g ) { return ( g as IOrderedGroup ) . order != null ; } internal function isGroupParent ( g ) { return ( g as IGroupParent ) . subGroups != null ; } param groups export function unifyParents < T extends IOrderedGroup > ( groups ) { if ( groups . length <= 1 ) { return groups ; } const toPath = ( group ) => { const path = [ group ] ; let p = group . parent ; while ( p ) { path . unshift ( p ) ; p = p . parent ; } return path ; } ; const paths = groups . map ( toPath ) ; const isSame = ( a , b ) => { return b . name === a . name && b . parent === a . parent && isGroupParent ( b ) && b . subGroups . length > 0 ; } ; const removeDuplicates = ( level , i ) => { const real = [ ] ; while ( level . length > 0 ) { const node = level . shift ( ) ! ; if ( ! isGroupParent ( node ) || node . subGroups . length === 0 ) { real . push ( node ) ; continue ; } const root = { ... node } ; real . push ( root ) ; while ( level . length > 0 && isSame ( root , level [ 0 ] ! ) ) { root . subGroups . push ( ... ( level . shift ( ) ! as IGroupParent ) . subGroups ) ; } for ( const child of root . subGroups ) { ( child as IGroupParent | T ) . parent = root ; } root . subGroups = removeDuplicates ( root . subGroups as ( IGroupParent | T ) [ ] , i + 1 ) ; } return real ; } ; removeDuplicates ( paths . map ( ( p ) => p [ 0 ] ) , 0 ) ; return groups ; } internal export function groupRoots ( groups ) { const roots = new OrderedSet < IOrderedGroup | Readonly < IGroupParent > > ( ) ; for ( const group of groups ) { let root = group ; while ( root . parent ) { root = root . parent ; } roots . add ( root ) ; } return Array . from ( roots ) ; } param groups param f internal export function traverseGroupsDFS ( groups , f ) { const traverse = ( v ) => { if ( f ( v ) === false ) { return ; } if ( isGroupParent ( v ) ) { v . subGroups . forEach ( traverse ) ; } } ; const roots = groupRoots ( groups ) ; roots . forEach ( traverse ) ; } const colors = schemeCategory10 . concat ( schemeSet3 ) ; internal export const MAX_COLORS = colors . length ; internal export function colorPool ( ) { let act = 0 ; return ( ) => colors [ act ++ % colors . length ] ; } internal export function mapIndices < T > ( arr , callback ) { const r = [ ] ; for ( let i = 0 ; i < arr . length ; ++ i ) { r . push ( callback ( arr [ i ] , i ) ) ; } return r ; } internal export function everyIndices ( arr , callback ) { for ( let i = 0 ; i < arr . length ; ++ i ) { if ( ! callback ( arr [ i ] , i ) ) { return false ; } } return true ; } internal export function filterIndices ( arr , callback ) { const r = [ ] ; for ( let i = 0 ; i < arr . length ; ++ i ) { if ( callback ( arr [ i ] , i ) ) { r . push ( arr [ i ] ) ; } } return r ; } internal export function forEachIndices ( arr , callback ) { for ( let i = 0 ; i < arr . length ; ++ i ) { callback ( arr [ i ] , i ) ; } } internal export function chooseUIntByDataLength ( dataLength ? ) { if ( dataLength == null || ( typeof dataLength !== 'number' && ! Number . isNaN ( dataLength ) ) ) { return ECompareValueType . UINT32 ; } if ( dataLength <= 255 ) { return ECompareValueType . UINT8 ; } if ( dataLength <= 65535 ) { return ECompareValueType . UINT16 ; } return ECompareValueType . UINT32 ; } export function getAllToolbarActions ( col ) { const actions = new OrderedSet < string > ( ) ; let obj = col as any ; const toolbarIcon = Symbol . for ( 'toolbarIcon' ) ; do { const m = Reflect . getOwnMetadata ( toolbarIcon , obj . constructor ) as string [ ] ; if ( m ) { for ( const mi of m ) { actions . add ( mi ) ; } } obj = Object . getPrototypeOf ( obj ) ; } while ( obj ) ; return Array . from ( actions ) ; } export function getAllToolbarDialogAddons ( col , key ) { const actions = new OrderedSet < string > ( ) ; let obj = col as any ; const symbol = Symbol . for ( `toolbarDialogAddon${ key }` ) ; do { const m = Reflect . getOwnMetadata ( symbol , obj . constructor ) as string [ ] ; if ( m ) { for ( const mi of m ) { actions . add ( mi ) ; } } obj = Object . getPrototypeOf ( obj ) ; } while ( obj ) ; return Array . from ( actions ) ; }