import { Ident } from './Ident' ; import { IdentGenerator } from './IdentGenerator' ; import { Segment } from './Segment' ; /**
 * The identifier allocation strategy to use at a specified depth.
 */ enum LSEQStrategy { /**
     * Generate identifiers by adding a value to the previous digit.
     */ AddFromLeft = 1 , /**
     * Generate identifiers by subtracting a value to the next digit.
     */ SubtractFromRight = 2 } /**
 * An IdentGenerator that implements LSEQ to create identifiers.
 */ export class LSEQIdentGenerator implements IdentGenerator { startingWidth : number ; maxDistance : number ; strategies : LSEQStrategy [ ] ; first : Ident ; last : Ident ; param startingWidth param maxDistance returns constructor ( startingWidth = 4 , maxDistance = 10 ) { this . startingWidth = startingWidth ; this . maxDistance = maxDistance ; this . strategies = [ ] ; } inheritdoc getIdent ( name , time , before , after ) { if ( ! before ) before = this . getFirst ( name ) ; if ( ! after ) after = this . getLast ( name ) ; let distance = 0 ; let depth = - 1 ; let min = 0 ; let max = 0 ; while ( distance < 1 ) { depth ++ ; let left = before . get ( depth ) ; let right = after . get ( depth ) ; min = left ? left . digit : 0 ; max = right ? right . digit : this . getWidthAtDepth ( depth ) ; distance = max - min - 1 ; } let boundary = Math . min ( distance , this . maxDistance ) ; let delta = Math . floor ( Math . random ( ) * boundary ) + 1 ; let strategy = this . getStrategyAtDepth ( depth ) ; let path = [ ] ; for ( let i = 0 ; i < depth ; i ++ ) { path . push ( before . get ( i ) || Segment ( 0 , name ) ) ; } if ( strategy == LSEQStrategy . AddFromLeft ) { path . push ( Segment ( min + delta , name ) ) ; } else { path . push ( Segment ( max - delta , name ) ) ; } return new Ident ( time , path ) ; } param depth returns private getWidthAtDepth ( depth ) { let power = depth + this . startingWidth ; if ( power > 53 ) power = 53 ; return 2 ** power - 1 ; } param depth returns private getStrategyAtDepth ( depth ) { let strategy = this . strategies [ depth ] ; if ( ! strategy ) { let random = Math . floor ( Math . random ( ) * 2 ) + 1 ; strategy = this . strategies [ depth ] = < LSEQStrategy > random ; } return strategy ; } param name returns private getFirst ( name ) { if ( ! this . first ) this . first = new Ident ( 0 , [ Segment ( 0 , name ) ] ) ; return this . first ; } param name returns private getLast ( name ) { if ( ! this . last ) this . last = new Ident ( 0 , [ Segment ( this . getWidthAtDepth ( 0 ) , name ) ] ) ; return this . last ; } }