import { FileUtil } from "../core/file-util" ; export class SampleUtterances { public samples : { [ id ] : Array < string > ; } = { } ; public constructor ( ) { } public static fromFile ( file , callback ) { FileUtil . readFile ( file , function ( data ) { if ( data !== null ) { let sampleUtterances = new SampleUtterances ( ) ; try { sampleUtterances . parseFlatFile ( data . toString ( ) ) ; callback ( sampleUtterances ) ; } catch ( e ) { callback ( null , e . message ) ; } } else { let error = "File not found: " + file ; callback ( null , error ) ; } } ) ; } public static fromJSON ( sampleUtterancesJSON ) { let sampleUtterances = new SampleUtterances ( ) ; for ( let intent of Object . keys ( sampleUtterancesJSON ) ) { sampleUtterances . samples [ intent ] = sampleUtterancesJSON [ intent ] ; } return sampleUtterances ; } /**
     * To handle the case when what is said does not match any sample utterance
     */ public defaultUtterance ( ) { let firstIntent = Object . keys ( this . samples ) [ 0 ] ; return this . samples [ firstIntent ] [ 0 ] ; } param phraseString returns { UtteredIntent } public intentForUtterance ( phraseString ) { let phrase = new Phrase ( phraseString ) ; let matchedIntent = null ; for ( let intent of Object . keys ( this . samples ) ) { let samples = this . samples [ intent ] ; for ( let sample of samples ) { if ( phrase . matchesUtterance ( sample ) ) { matchedIntent = new UtteredIntent ( intent , phraseString , new Phrase ( sample ) ) ; break ; } } if ( matchedIntent !== null ) { break ; } } return matchedIntent ; } public hasIntent ( intent ) { return intent in this . samples ; } private parseFlatFile ( fileData ) { let lines = fileData . split ( "\n" ) ; for ( let line of lines ) { if ( line . trim ( ) . length === 0 ) { continue ; } let index = line . indexOf ( " " ) ; if ( index === - 1 ) { throw Error ( "Invalid sample utterance: " + line ) ; } let intent = line . substr ( 0 , index ) ; let sample = line . substr ( index ) . trim ( ) ; let intentSamples = [ ] ; if ( intent in this . samples ) { intentSamples = this . samples [ intent ] ; } else { this . samples [ intent ] = intentSamples ; } intentSamples . push ( sample ) ; } } } /**
 * Helper class for handling phrases - breaks out the slots within a phrase
 */ export class Phrase { public slots : Array < string > = [ ] ; public normalizedPhrase : string = null ; public constructor ( public phrase ) { this . normalizeSlots ( this . phrase ) ; } param utterance public normalizeSlots ( utterance ) { let slotlessUtterance = "" ; let index = 0 ; let done = false ; while ( ! done ) { let startSlotIndex = utterance . indexOf ( "{" , index ) ; if ( startSlotIndex !== - 1 ) { let endSlotIndex = utterance . indexOf ( "}" , startSlotIndex ) ; let slotValue = utterance . substr ( startSlotIndex + 1 , endSlotIndex - ( startSlotIndex + 1 ) ) ; this . slots . push ( slotValue ) ; slotlessUtterance += utterance . substr ( index , startSlotIndex - index + 1 ) + "}" ; index = endSlotIndex + 1 ; } else { slotlessUtterance += utterance . substr ( index ) ; done = true ; } } this . normalizedPhrase = slotlessUtterance ; } public matchesUtterance ( otherPhraseString ) { return this . matches ( new Phrase ( otherPhraseString ) ) ; } public matches ( otherPhrase ) { return this . normalizedPhrase . toLowerCase ( ) === otherPhrase . normalizedPhrase . toLowerCase ( ) ; } } /**
 * Object to hold tuple of intentName name, utterance, and the matched phrase
 *
 * Helpful for handling slots
 */ export class UtteredIntent { public constructor ( public intentName , public utterance , public matchedPhrase ) { } public slotCount ( ) { return this . matchedPhrase . slots . length ; } public slotName ( index ) { return this . matchedPhrase . slots [ index ] ; } public slotValue ( index ) { return new Phrase ( this . utterance ) . slots [ index ] ; } public toJSON ( ) { let json = { } ; for ( let i = 0 ; i < this . slotCount ( ) ; i ++ ) { json [ this . slotName ( i ) ] = this . slotValue ( i ) ; } return json ; } }