import { Bot } from './Bot' ; import { BotObjectsContext } from './BotObjectsContext' ; import { calculateBotValue } from './BotCalculations' ; import { zip , sortBy } from 'lodash' ; param calc param tags param defaults export function buildLookupTable ( calc , tags , defaults = null ) { return new BotLookupTable ( calc , tags , defaults ) ; } /**
 * Defines a lookup table for a group of bots.
 * Lookup tables help performance by calculating lists of bots which have the same values for
 * a given set of tags. This makes subsequent queries for the same set of tags effectively a O(1) operation instead of a O(N) operation.
 *
 * Building the table is O(N) because all the bots need to be scanned to build the table.
 */ export class BotLookupTable { private _map : Map < string , Bot [ ] > ; private _tags : string [ ] ; constructor ( calc , tags , defaults ) { this . _map = new Map ( ) ; this . _tags = sortBy ( tags ) ; for ( let bot of calc . objects ) { const val = calculateTagValueKey ( calc , bot , tags , defaults ) ; if ( val !== null ) { this . _saveBot ( val , bot ) ; } } } param values query ( values ) { return this . _map . get ( valuesToKey ( values ) ) || [ ] ; } toString ( ) { return `BotLookupTable[${ this . _tags . join ( ',' ) }]` ; } private _saveBot ( key , bot ) { let list = this . _map . get ( key ) ; if ( ! list ) { list = [ ] ; this . _map . set ( key , list ) ; } list . push ( bot ) ; } } param calc param bot param tags param defaults function calculateTagValueKey ( calc , bot , tags , defaults ) { let values = [ ] ; if ( ! defaults ) { defaults = new Array ( tags . length ) ; } for ( let [ tag , def ] of zip ( tags , defaults ) ) { let val = calculateBotValue ( calc , bot , tag ) ; if ( typeof val === 'undefined' ) { val = def ; } if ( typeof val === 'undefined' ) { return null ; } values . push ( val ) ; } return valuesToKey ( values ) ; } export function valuesToKey ( values ) { return values . join ( ':' ) ; }