'use strict' ; import { StateResolver } from "./StateResolver" ; import { HappeningType , HelpfulAction , search } from 'pddl-workspace' ; export class MessageParser { private lastStateOrder = - 1 ; private stateIdToOrder = new Map < string , number > ( ) ; constructor ( private readonly search , private readonly stateIdPattern ) { } clear ( ) { this . stateIdToOrder . clear ( ) ; this . lastStateOrder = - 1 ; } parseStateId ( origId ) { let assignedStateId ; if ( this . stateIdPattern ) { this . stateIdPattern . lastIndex = 0 ; let match ; if ( match = origId . match ( this . stateIdPattern ) ) { assignedStateId = parseInt ( match [ 1 ] ) ; } else { console . log ( "State ID does not conform to the pattern. Assigning own ID." ) ; assignedStateId = ++ this . lastStateOrder ; } } else { assignedStateId = ++ this . lastStateOrder ; } this . stateIdToOrder . set ( origId , assignedStateId ) ; return assignedStateId ; } parseInitialState ( state ) { const assignedStateId = this . parseStateId ( state . id ) ; this . stateIdToOrder . set ( state . id , assignedStateId ) ; return new search . SearchState ( assignedStateId , state . id , state . g , state . earliestTime , [ ] , state . landmarks ) ; } parseState ( state ) { let assignedStateId = this . stateIdToOrder . get ( state . id ) ; if ( assignedStateId === undefined ) { assignedStateId = this . parseStateId ( state . id ) ; } const parentId = this . stateIdToOrder . get ( state . parentId ) ; const planHead = state . planHead . map ( ( h ) => this . parseSearchHappening ( h , false ) ) ; const actionName = state . appliedAction ? this . createActionName ( this . parseSearchHappening ( state . appliedAction , false ) ) : undefined ; return new search . SearchState ( assignedStateId , state . id , state . g , state . earliestTime , planHead , state . landmarks , parentId , actionName ) ; } createActionName ( lastHappening ) { let actionName = lastHappening . actionName ; if ( lastHappening . shotCounter > 0 ) { actionName += `[${ lastHappening . shotCounter }]` ; } switch ( lastHappening . kind ) { case HappeningType . START : actionName += '├' ; break ; case HappeningType . END : actionName += ' ┤' ; break ; } if ( lastHappening . iterations > 1 ) { actionName += ` ${ lastHappening . iterations }x` ; } return actionName ; } parseEvaluatedState ( state ) { const assignedStateId = this . stateIdToOrder . get ( state . id ) ; if ( assignedStateId === undefined ) { throw new Error ( `State with id ${ state . id } is unknown` ) ; } const stateFound = this . search . getState ( assignedStateId ) ; if ( ! stateFound ) { throw new Error ( `State with id ${ state . id } not found.` ) ; } if ( ! state . hasOwnProperty ( 'h' ) ) { return stateFound . setDeadEnd ( ) ; } else { const relaxedPlan = state . relaxedPlan . map ( ( h ) => this . parseSearchHappening ( h , true ) ) ; const helpfulActions = state . helpfulActions . map ( ( a ) => this . parseHelpfulAction ( a ) ) ; return stateFound . evaluate ( state . h , state . totalMakespan , helpfulActions , relaxedPlan ) ; } } parseSearchHappening ( happening , isRelaxed ) { return { actionName : happening . actionName , earliestTime : happening . earliestTime , shotCounter : happening . shotCounter , iterations : happening . iterations , kind : this . parseHappeningType ( happening . kind ) , isRelaxed : isRelaxed } ; } parseHelpfulAction ( action ) { return { actionName : action . actionName , kind : this . parseHappeningType ( action . kind ) } ; } parseHappeningType ( happeningTypeAsString ) { switch ( happeningTypeAsString ) { case HappeningType [ HappeningType . END ] : return HappeningType . END ; case HappeningType [ HappeningType . INSTANTANEOUS ] : return HappeningType . INSTANTANEOUS ; case HappeningType [ HappeningType . START ] : return HappeningType . START ; case HappeningType [ HappeningType . TIMED ] : return HappeningType . TIMED ; default : throw new Error ( "Unexpected happening type: " + happeningTypeAsString ) ; } } }