import { QueryConfig } from '../../config' ; import { SpecQueryModel } from '../../model' ; import { fieldDef as fieldDefShorthand } from '../../query/shorthand' ; import { EncodingQuery , isFieldQuery , isAutoCountQuery } from '../../query/encoding' ; import { Dict , extend , forEach , keys , contains } from '../../util' ; import { Schema } from '../../schema' ; import { FeatureScore } from '../ranking' ; import { BIN_Q , TIMEUNIT_T , TIMEUNIT_O , Q , N , O , T , ExtendedType , getExtendedType , K } from './type' ; import { Scorer } from './base' ; import { Channel } from 'vega-lite/build/src/channel' ; export const TERRIBLE = - 10 ; /**
 * Effectiveness score for relationship between
 * Field Type (with Bin and TimeUnit) and Channel Score (Cleveland / Mackinlay based)
 */ export class TypeChannelScorer extends Scorer { constructor ( ) { super ( 'TypeChannel' ) ; } protected initScore ( ) { const SCORE = { } as Dict < number > ; const CONTINUOUS_TYPE_CHANNEL_SCORE = { x : 0 , y : 0 , size : - 0.575 , color : - 0.725 , text : - 2 , opacity : - 3 , shape : TERRIBLE , row : TERRIBLE , column : TERRIBLE , detail : 2 * TERRIBLE , } ; [ Q , T , TIMEUNIT_T ] . forEach ( ( type ) => { keys ( CONTINUOUS_TYPE_CHANNEL_SCORE ) . forEach ( ( channel ) => { SCORE [ this . featurize ( type , channel ) ] = CONTINUOUS_TYPE_CHANNEL_SCORE [ channel ] ; } ) ; } ) ; const ORDERED_TYPE_CHANNEL_SCORE = extend ( { } , CONTINUOUS_TYPE_CHANNEL_SCORE , { row : - 0.75 , column : - 0.75 , shape : - 3.1 , text : - 3.2 , detail : - 4 , } ) ; [ BIN_Q , TIMEUNIT_O , O ] . forEach ( ( type ) => { keys ( ORDERED_TYPE_CHANNEL_SCORE ) . forEach ( ( channel ) => { SCORE [ this . featurize ( type , channel ) ] = ORDERED_TYPE_CHANNEL_SCORE [ channel ] ; } ) ; } ) ; const NOMINAL_TYPE_CHANNEL_SCORE = { x : 0 , y : 0 , color : - 0.6 , shape : - 0.65 , row : - 0.7 , column : - 0.7 , text : - 0.8 , detail : - 2 , size : - 3 , opacity : - 3.1 , } ; keys ( NOMINAL_TYPE_CHANNEL_SCORE ) . forEach ( ( channel ) => { SCORE [ this . featurize ( N , channel ) ] = NOMINAL_TYPE_CHANNEL_SCORE [ channel ] ; SCORE [ this . featurize ( K , channel ) ] = contains ( [ 'x' , 'y' , 'detail' ] , channel ) ? - 1 : NOMINAL_TYPE_CHANNEL_SCORE [ channel ] - 2 ; } ) ; return SCORE ; } public featurize ( type , channel ) { return `${ type }_${ channel }` ; } public getScore ( specM , schema , opt ) { const encodingQueryByField = specM . getEncodings ( ) . reduce ( ( m , encQ ) => { if ( isFieldQuery ( encQ ) || isAutoCountQuery ( encQ ) ) { const fieldKey = fieldDefShorthand ( encQ ) ; ( m [ fieldKey ] = m [ fieldKey ] || [ ] ) . push ( encQ ) ; } return m ; } , { } ) ; const features = [ ] ; forEach ( encodingQueryByField , ( encQs ) => { const bestFieldFeature = encQs . reduce ( ( best , encQ ) => { if ( isFieldQuery ( encQ ) || isAutoCountQuery ( encQ ) ) { const type = getExtendedType ( encQ ) ; const feature = this . featurize ( type , encQ . channel as Channel ) ; const featureScore = this . getFeatureScore ( feature ) ; if ( best === null || featureScore . score > best . score ) { return featureScore ; } } return best ; } , null ) ; features . push ( bestFieldFeature ) ; } ) ; return features ; } }